# Sistema de Tipografia Fluida Viceversable — Reglas y Arquitectura

> **Valores y tokens -> `design-tokens.json`** (fuente unica de verdad, seccion `typography`)
> Este documento define las **reglas de uso**.
> **Guia visual -> `guia-tipografia.html`** (cada estilo renderizado con ejemplos)

---

## Principios

1. **Tipografia fluida con clamp()** — cada tamano se interpola entre piso (movil) y techo (desktop). Sin breakpoints, sin saltos.
2. **Escala modular Major Third (1.250)** — S_n = Base x 1.250^n. 8 niveles, de small (n=-2) a display (n=5). Sin tamanos arbitrarios.
3. **Piso y techo** — Piso: viewport 320px, base 16px. Techo: viewport 1240px, base 18px.
4. **2 familias, roles claros** — Instrument Serif (editorial: Display, H1-H3) + Geist (funcional: H4-H6, body, UI).
5. **Line-height por contexto** — display 1.05, headings 1.15, subheadings 1.3, body 1.55.
6. **45-75 caracteres por linea** — contener con max-width: 38rem.
7. **Contraste WCAG 4.5:1 minimo** — prohibido gris claro en texto importante.
8. **Sin emojis en la identidad visual** — no se usan en navegacion, titulos, CTAs, badges, estados, dashboards, apps, webs ni documentos de marca. Si hace falta apoyo visual, se usa iconografia del sistema o SVG.

---

## Familias tipograficas

| Token CSS | Familia | Pesos | Uso |
|-----------|---------|-------|-----|
| `--font-body` | Geist | 300, 400, 500, 600, 700 | H4-H6, body, UI, labels, navegacion |
| `--font-display` | Instrument Serif | 400 regular, 400 italic | Display, H1-H3, wordmark |

**Google Fonts:**
```
https://fonts.googleapis.com/css2?family=Geist:wght@300;400;500;600;700&family=Instrument+Serif:ital@0;1&display=swap
```

**Geist** soporta peso 300 — se usa para lectura principal (body) y elementos de navegacion inactivos.
**Instrument Serif** no tiene variantes de peso — solo regular (400) e italic.

---

## Escala fluida

| Token | clamp() | Piso -> Techo | Nivel | Familia |
|-------|---------|---------------|-------|---------|
| `--text-small` | clamp(0.64rem, 0.612rem + 0.139vw, 0.72rem) | 10px -> 12px | n=-2 | Geist |
| `--text-h6` | clamp(0.8rem, 0.765rem + 0.174vw, 0.9rem) | 13px -> 14px | n=-1 | Geist |
| `--text-body` | clamp(1rem, 0.957rem + 0.217vw, 1.125rem) | 16px -> 18px | n=0 (base) | Geist |
| `--text-h5` | = var(--text-body) | 16px -> 18px | n=0 | Geist |
| `--text-h4` | clamp(1.25rem, 1.196rem + 0.272vw, 1.406rem) | 20px -> 23px | n=1 | Geist |
| `--text-h3` | clamp(1.563rem, 1.495rem + 0.340vw, 1.758rem) | 25px -> 28px | n=2 | Instrument |
| `--text-h2` | clamp(1.953rem, 1.868rem + 0.425vw, 2.197rem) | 31px -> 35px | n=3 | Instrument |
| `--text-h1` | clamp(2.441rem, 2.335rem + 0.531vw, 2.747rem) | 39px -> 44px | n=4 | Instrument |
| `--text-display` | clamp(3.052rem, 2.919rem + 0.663vw, 3.433rem) | 49px -> 55px | n=5 | Instrument |

---

## Roles semanticos

### Display — Greeting
- Familia: `font-display` (Instrument Serif), **italic fijo**
- Tamano: `--text-display`
- Peso: `--fw-regular`
- Line-height: `--lh-display` (1.05)
- Letter-spacing: `--ls-display` (-0.03em)
- Uso: saludo principal, hero editorial, titulo unico por vista

### Display — KPI
- Familia: `font-display` (Instrument Serif), regular
- Tamano: `--text-display`
- Peso: `--fw-regular`
- Line-height: `--lh-display` (1.05)
- Letter-spacing: `--ls-kpi` (0.05em)
- Uso: numeros hero en cards KPI

### H1
- Familia: `font-display` (Instrument Serif), regular
- Tamano: `--text-h1`
- Peso: `--fw-regular`
- Line-height: `--lh-heading` (1.15)
- Letter-spacing: `--ls-heading` (-0.02em)
- Uso: titulo principal de pagina

### H2
- Familia: `font-display` (Instrument Serif), regular
- Tamano: `--text-h2`
- Peso: `--fw-regular`
- Line-height: `--lh-heading` (1.15)
- Letter-spacing: `--ls-heading` (-0.02em)
- Uso: divide bloques de contenido

### H3
- Familia: `font-display` (Instrument Serif), regular
- Tamano: `--text-h3`
- Peso: `--fw-regular`
- Line-height: `--lh-heading` (1.15)
- Uso: subsecciones

### H4
- Familia: `font-body` (Geist)
- Tamano: `--text-h4`
- Peso: `--fw-semibold` (600)
- Line-height: `--lh-subhead` (1.3)
- Uso: titulos de cards

### H5
- Familia: `font-body` (Geist)
- Tamano: `--text-h5` (= `--text-body`)
- Peso: `--fw-semibold` (600)
- Line-height: `--lh-subhead` (1.3)
- Uso: agrupadores internos

### H6
- Familia: `font-body` (Geist)
- Tamano: `--text-h6`
- Peso: `--fw-semibold` (600)
- Line-height: `--lh-subhead` (1.3)
- Uso: labels funcionales, nav items

### Overline
- Familia: `font-body` (Geist)
- Tamano: `--text-small`
- Peso: `--fw-bold` (700)
- Transformacion: uppercase
- Letter-spacing: `--ls-overline` (0.25em)
- Color: `rgba(18,15,32,0.45)`
- Uso: encabezados de tabla (th), etiquetas de seccion

### Body
- Familia: `font-body` (Geist)
- Tamano: `--text-body`
- Peso: `--fw-light` (300) principal / `--fw-regular` (400) secundario
- Line-height: `--lh-body` (1.55)
- Max-width: 38rem
- Uso: parrafos, descripciones, contenido principal

### Small / Caption
- Familia: `font-body` (Geist)
- Tamano: `--text-small`
- Peso: `--fw-light` (300)
- Color: `rgba(18,15,32,0.45)`
- Uso: metadata, timestamps, hints, notas al pie

### Badge
- Familia: `font-body` (Geist)
- Tamano: `--text-small`
- Peso: `--fw-semibold` (600)
- Transformacion: uppercase
- Letter-spacing: `--ls-badge` (0.03em)
- Uso: chips de fase (Explore/Create/Activate), status badges

### KPI Label
- Familia: `font-body` (Geist)
- Tamano: `--text-small`
- Peso: `--fw-semibold` (600)
- Transformacion: uppercase
- Letter-spacing: `--ls-badge` (0.03em)
- Color: `rgba(18,15,32,0.45)`
- Uso: descriptores debajo de numeros KPI

### Nav
- Familia: `font-body` (Geist)
- Tamano: `--text-h6`
- Peso: `--fw-light` (300) / `--fw-medium` (500) activo
- Uso: items de navegacion

### Wordmark
- Familia: `font-display` (Instrument Serif), **italic fijo**
- Tamano: `--text-h3`
- Peso: `--fw-regular`
- Uso: logo tipografico en sidebar de app

---

## Clase utilitaria: .text-serif-italic

Cambia cualquier elemento a Instrument Serif italic sin afectar el peso heredado.

```css
.text-serif-italic {
  font-family: var(--font-display);
  font-style: italic;
}
```

Uso: mezclar la voz editorial dentro de texto funcional en la misma linea.
Ejemplo: "La marca que *cuenta historias* gana"

---

## Variable --font-style-serif

Controla el font-style por defecto de Instrument Serif en H1-H3 y KPI.
Valor default: `normal`. Display y Wordmark ignoran esta variable (siempre italic).

---

## Tokens de pesos

| Token | Valor | Uso |
|-------|-------|-----|
| `--fw-light` | 300 | Geist body principal, nav inactivo |
| `--fw-regular` | 400 | Geist body secundario, Instrument Serif |
| `--fw-medium` | 500 | Geist nav activo |
| `--fw-semibold` | 600 | Geist H4-H6, badges, KPI labels |
| `--fw-bold` | 700 | Geist overline |

---

## Tokens de line-height

| Token | Valor | Uso |
|-------|-------|-----|
| `--lh-display` | 1.05 | Display — puro impacto visual |
| `--lh-heading` | 1.15 | H1-H3 (Instrument Serif) |
| `--lh-subhead` | 1.3 | H4-H6 (Geist) |
| `--lh-body` | 1.55 | Body, small, UI |

---

## Tokens de letter-spacing

| Token | Valor | Uso |
|-------|-------|-----|
| `--ls-display` | -0.03em | Display |
| `--ls-heading` | -0.02em | H1, H2 |
| `--ls-badge` | 0.03em | Badges, KPI labels |
| `--ls-kpi` | 0.05em | Numeros hero KPI |
| `--ls-overline` | 0.25em | Overline (th, labels de seccion) |
| `--ls-overline-compact` | 0.06em | Overline en espacios reducidos (ej: tags inline) |

---

## Reglas generales

- **Instrument Serif solo en Display, H1-H3 y Wordmark** — no se usa en UI funcional.
- **Display siempre italic** — es el tono editorial, no se cambia.
- **Wordmark siempre italic** — consistencia con el logo.
- **Overline no se usa en badges** — los badges tienen `--ls-badge` (0.03em), no `--ls-overline`.
- **Geist peso 300 para lectura** — body principal y nav inactivo usan light.

---

## Equivalencia Swift (Voiceverse)

| CSS (piso) | Swift pt | Rol | Nota |
|------------|----------|-----|------|
| 10px | 11pt | small | Geist Regular — VVTextSize.small(10) + sizeOffset(1) |
| 13px | 13pt | h6 | Geist SemiBold — VVTextSize.h6(12) + sizeOffset(1) |
| 16px | 15pt | body | Geist Light — VVTextSize.body(14) + sizeOffset(1) |
| 20px | 19pt | h4 | Geist SemiBold — VVTextSize.h4(18) + sizeOffset(1) |
| 25px | 22pt | h3 | Instrument Serif — sin sizeOffset |
| 31px | 28pt | h2 | Instrument Serif — sin sizeOffset |
| 39px | 34pt | h1 | Instrument Serif — sin sizeOffset |
| 49px | 44pt | display | Instrument Serif — sin sizeOffset |

**Regla macOS:** Los valores son una adaptacion deliberada para app de panel (menu bar). Geist recibe un offset global de +1pt via `sizeOffset`. Instrument Serif no recibe offset porque sus tamanos grandes ya son apropiados para macOS. Esta escala es intencional y no debe alinearse mecanicamente con el piso web.
