# Design System — Rebelocity Club
> Versión: v02 · Última actualización: 2026-07-02
> Referencia de diseño y desarrollo para cualquier persona que trabaje en este producto.
> Para flujos de usuario y comportamientos de cada vista, ver `SPEC-FLUJOS-RCH.md`.
---
## Índice
1. [Fundamentos de marca](#1-fundamentos-de-marca)
2. [Tokens de color](#2-tokens-de-color)
3. [Tipografía](#3-tipografía)
4. [Espaciado, radios y layout](#4-espaciado-radios-y-layout)
5. [Componentes base](#5-componentes-base)
6. [Componentes de directorio](#6-componentes-de-directorio)
7. [Componentes de mensajería](#7-componentes-de-mensajería)
8. [Componentes de panel admin](#8-componentes-de-panel-admin)
9. [UI condicional](#9-ui-condicional)
10. [Iconografía](#10-iconografía)
11. [Vistas completadas y pendientes](#11-vistas-completadas-y-pendientes)
12. [Convenciones de naming](#12-convenciones-de-naming)
---
## 1. Fundamentos de marca
- **Nombre del producto**: Rebelocity Club
- **Idioma**: Español (México)
- **Logo**: archivo `logo-rch-blanco.png` (versión blanca para fondos oscuros)
- **Wordmark CSS** (cuando no hay imagen): `REBEL` en `--accent` rojo + `OCITY` en blanco/gris según fondo
- **Temas**: el sistema soporta **Dark** (default en vistas autenticadas) y **Light** (alternativa). Se implementan con CSS custom properties en `:root` y `body.light`.
---
## 2. Tokens de color
### Dark theme (`:root`)
```css
:root {
/* Fondos */
--bg: #07090F; /* fondo base de página */
--bg2: #0D1117; /* nav, hero, superficies elevadas */
--bg3: #141922; /* fondos de input dentro de panels */
--card: #111620; /* tarjetas, secciones de formulario */
--card2: #161C2A; /* tarjetas secundarias, toggles apagados */
/* Bordes */
--border: rgba(255,255,255,0.07);
--border2: rgba(255,255,255,0.13);
/* Colores de marca */
--accent: #E2261C; /* rojo marca — logo, alertas, énfasis */
--accent2: #E8554D; /* rojo gradiente */
/* Colores semánticos */
--blue: #4A80D6; /* azul adaptado dark (mayor contraste sobre oscuro) */
--blue2: #3A6BC4; /* hover del azul en dark */
--green: #10B981; /* éxito, estados positivos */
--gold: #F5B842; /* puntos, logros, relay */
--red: #EF4444; /* errores, acciones destructivas */
/* Texto */
--text: #F0F4FF; /* texto principal */
--text2: #8B96B0; /* texto secundario */
--text3: #5A6480; /* placeholder, metadatos terciarios */
/* Tipografías */
--fh: 'Montserrat', sans-serif;
--fb: 'Inter', sans-serif;
}
```
### Light theme (`body.light`)
```css
body.light {
--bg: #F4F6FA;
--bg2: #FFFFFF;
--bg3: #EDF0F7;
--card: #FFFFFF;
--card2: #EEF1F6;
--border: rgba(0,0,0,0.07);
--border2: rgba(0,0,0,0.12);
--accent: #E2261C; /* igual en ambos temas */
--accent2: #E8554D;
--blue: #234E9C; /* azul exacto de marca */
--blue2: #1A3F82;
--green: #059669;
--gold: #D97706;
--red: #DC2626;
--text: #0E1525;
--text2: #4A5570;
--text3: #8B96B0;
}
```
### Tabla semántica de uso de color
| Token | Dark | Light | Uso correcto |
|---|---|---|---|
| `--blue` | `#4A80D6` | `#234E9C` | CTAs primarios, tabs activos, chips seleccionados, toggles on, links |
| `--accent` | `#E2261C` | `#E2261C` | Logo, alertas críticas, énfasis de marca. **Nunca en botones de acción genérica** |
| `--green` | `#10B981` | `#059669` | Aceptar, éxito, estado activo/positivo, barra de chat abierto |
| `--gold` | `#F5B842` | `#D97706` | Puntos de lealtad, nivel, relay, porcentaje de perfil |
| `--red` | `#EF4444` | `#DC2626` | Errores de validación, botones de rechazo, créditos negativos |
> ⚠️ **Regla clave:** el rojo (`--accent`) identifica la marca. Los botones de acción destructiva o de rechazo usan `--red` (`#EF4444`), no `--accent`.
---
## 3. Tipografía
### Familias
```css
--fh: 'Montserrat', sans-serif; /* headings, nombre en hero, badges de nivel */
--fb: 'Inter', sans-serif; /* body, inputs, botones, labels */
```
### Import de Google Fonts (incluir en todas las vistas)
```html
```
### Escala tipográfica
| Elemento | Familia | Tamaño | Peso | Detalle |
|---|---|---|---|---|
| Hero name / nombre principal | Montserrat | 22px | 900 | `letter-spacing: -.3px` |
| Título de panel | Montserrat | 13–16px | 800 | uppercase, `letter-spacing: .03em` |
| Nav logo (texto) | Montserrat | 18px | 900 | `letter-spacing: -.4px` |
| Section heading (`h2`) | Montserrat | 14px | 700 | — |
| Puntos grandes | Montserrat | 28–32px | 900 | Tarjeta de membresía |
| Tab label | Inter | 14px | 600 | — |
| Body / inputs | Inter | 14px | 400 | — |
| Botones | Inter | 12–13px | 600–700 | — |
| Chips | Inter | 10–13px | 600 | Según tamaño del chip |
| Labels de campo | Inter | 11px | 700 | uppercase, `letter-spacing: .06em` |
| Hints / captions | Inter | 11–12px | 400 | `color: --text2` o `--text3` |
| Metadatos de tarjeta | Inter | 11–12px | 400–600 | `color: --text2` |
| Badges / etiquetas | Inter | 9–11px | 700 | uppercase |
---
## 4. Espaciado, radios y layout
### Radios de borde
```css
--r: 12px; /* tarjetas principales, secciones de formulario, modales */
--r2: 8px; /* inputs, botones, chips de filtro, cards de directorio */
--r3: 6px; /* elementos pequeños, badges */
```
Los botones redondeados del tipo "pill" (chips, badges de puntos) usan `border-radius: 100px`.
### Layout de página principal (perfil / vistas con sidebar)
```css
.page-body {
max-width: 1100px;
margin: 0 auto;
padding: 32px;
display: grid;
grid-template-columns: 1fr 290px;
gap: 28px;
align-items: start;
}
```
### Alturas fijas
| Elemento | Altura | Posición |
|---|---|---|
| Nav global | 54px | `position: sticky; top: 0; z-index: 100` |
| Tabs de sección (perfil) | ~44px | `position: sticky; top: 54px; z-index: 99` |
| Panel lateral de mensajería | 100% viewport - 48px | `position: fixed; top: 48px; right: 0; bottom: 0` |
| Save bar | ~52px | `position: fixed; bottom: 0; left: 0; right: 0; z-index: 200` |
### Sidebar
- Ancho: `290px`
- `position: sticky; top: 120px`
### Panel lateral de mensajería
- Ancho: `420px`
- `position: fixed; right: 0; top: 48px; bottom: 0`
- Borde izquierdo: `1px solid var(--border)`
- Sombra: `box-shadow: -8px 0 32px rgba(0,0,0,.4)`
### Grillas de formulario
```css
.fg { display: flex; flex-direction: column; gap: 6px; } /* campo simple */
.fg2 { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; } /* 2 columnas */
.fg3 { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 14px; } /* 3 columnas */
.fg.full { grid-column: 1 / -1; } /* span completo dentro de grid */
```
---
## 5. Componentes base
### 5.1 Botones
Todos los botones usan `font-family: var(--fb)` y `cursor: pointer`. El `border-radius` por defecto es `var(--r2)` (8px) salvo que se indique lo contrario.
#### Primario (CTA principal)
Color azul, texto blanco. Acción principal de la vista.
```css
.btn-primary {
padding: 9px 22px;
border-radius: var(--r2);
border: none;
background: var(--blue);
color: #fff;
font-size: 13px;
font-weight: 700;
transition: background .15s;
}
.btn-primary:hover { background: var(--blue2); }
```
#### Secundario / outline
Borde `--border2`, fondo transparente. Para acciones secundarias como "Guardar borrador" o "← Anterior".
```css
.btn-outline {
padding: 9px 20px;
border-radius: var(--r2);
border: 1px solid var(--border2);
background: transparent;
color: var(--text2);
font-size: 13px;
font-weight: 600;
}
.btn-outline:hover { border-color: var(--blue); color: var(--blue); }
```
#### Ghost / descartar
Para "Descartar cambios" o acciones de bajo impacto.
```css
.btn-ghost {
padding: 9px 18px;
border-radius: var(--r2);
border: 1px solid var(--border2);
background: transparent;
color: var(--text2);
font-size: 13px;
font-weight: 600;
}
.btn-ghost:hover { color: var(--text); border-color: var(--text2); }
```
#### Aceptar (verde)
Para acciones de aceptación: "Aceptar solicitud", "Abrir chat".
```css
.btn-accept {
padding: 10px;
border-radius: 10px;
border: none;
background: var(--green);
color: #fff;
font-size: 13px;
font-weight: 700;
display: flex;
align-items: center;
justify-content: center;
gap: 6px;
}
.btn-accept:hover { background: #0DA271; }
```
#### Rechazar (rojo borde)
Para acciones de rechazo. Usa borde y fondo semitransparente rojo, **no fondo sólido**.
```css
.btn-decline {
padding: 10px;
border-radius: 10px;
border: 1px solid rgba(239,68,68,.35);
background: rgba(239,68,68,.08);
color: var(--red);
font-size: 13px;
font-weight: 700;
}
.btn-decline:hover { background: rgba(239,68,68,.15); }
```
#### Full (ancho completo, azul)
```css
.btn-full {
flex: 1;
padding: 10px;
border-radius: 10px;
border: none;
background: var(--blue);
color: #fff;
font-size: 13px;
font-weight: 700;
}
.btn-full:hover { background: var(--blue2); }
```
#### Botón de acción en modal del directorio
```css
.btn-msg-modal {
width: 100%;
padding: 11px 20px;
border-radius: var(--r2);
border: none;
background: var(--blue);
color: #fff;
font-size: 13px;
font-weight: 700;
display: flex;
align-items: center;
justify-content: center;
gap: 6px;
}
```
> ❌ **Regla:** el rojo (`--accent`) nunca se usa como fondo de botón de acción. Solo para logo y alertas. Los botones de rechazo usan borde rojo semitransparente, no relleno.
---
### 5.2 Inputs, selects y textareas
```css
input[type="text"],
input[type="date"],
input[type="email"],
input[type="tel"],
select,
textarea {
background: var(--bg2);
border: 1px solid var(--border2);
border-radius: var(--r2);
padding: 10px 13px;
color: var(--text);
font-family: var(--fb);
font-size: 14px;
width: 100%;
outline: none;
transition: border-color .15s;
}
input:focus,
select:focus,
textarea:focus {
border-color: var(--blue);
box-shadow: 0 0 0 3px rgba(74,128,214,.12);
}
input::placeholder,
textarea::placeholder { color: var(--text3); }
input[readonly] {
color: var(--text2);
cursor: default;
}
input[readonly]:focus {
border-color: var(--border2);
box-shadow: none;
}
textarea {
resize: vertical;
min-height: 90px;
line-height: 1.55;
}
select {
appearance: none;
background-image: url("data:image/svg+xml,..."); /* chevron gris */
background-repeat: no-repeat;
background-position: right 11px center;
padding-right: 32px;
}
```
#### Labels de campo
```css
label.fl {
font-size: 11px;
font-weight: 700;
color: var(--text2);
text-transform: uppercase;
letter-spacing: .06em;
display: flex;
align-items: center;
gap: 5px;
}
label.fl .req { color: var(--blue); } /* asterisco de campo requerido */
label.fl .opt {
color: var(--text3);
font-weight: 400;
text-transform: none;
letter-spacing: 0;
font-size: 11px;
}
```
#### Hints debajo del campo
```css
.f-hint {
font-size: 11px;
color: var(--text3);
margin-top: 3px;
line-height: 1.5;
}
```
#### Contador de caracteres
```css
.char-count {
font-size: 11px;
color: var(--text3);
text-align: right;
margin-top: 3px;
}
```
---
### 5.3 Chips (selectores interactivos)
Los chips son elementos pill-shaped que el usuario puede seleccionar para indicar disciplinas, nivel, objetivos, etc.
```css
.chip {
padding: 7px 15px;
border-radius: 100px;
border: 1.5px solid var(--border2);
background: transparent;
font-family: var(--fb);
font-size: 13px;
font-weight: 600;
color: var(--text2);
cursor: pointer;
transition: all .15s;
display: flex;
align-items: center;
gap: 5px;
}
.chip:hover {
color: var(--text);
border-color: var(--text2);
background: rgba(255,255,255,.04);
}
/* Activo — azul (disciplinas, objetivos, rol, especialidad) */
.chip.on {
background: rgba(74,128,214,.12);
border-color: var(--blue);
color: var(--blue);
}
/* Activo — verde (solo para chips de nivel) */
.chip.nivel.on {
background: rgba(16,185,129,.10);
border-color: rgba(16,185,129,.50);
color: var(--green);
}
```
**Tipos de selección:**
- **Multi-select** (`toggleChip`): varios chips pueden estar activos simultáneamente. Ej: Disciplinas, Objetivos.
- **Single-select** (`toggleNivel`, `toggleSingle`): solo uno activo a la vez. Ej: Nivel, Tipo de relay.
- **Rol** (`toggleRol`): single-select con lógica de negocio adicional (muestra/oculta bloques condicionales).
---
### 5.4 Toggles (switch)
Estructura HTML y CSS estándar:
```html
```
```css
.tog-row {
display: flex;
align-items: center;
justify-content: space-between;
padding: 12px 14px;
background: var(--bg2);
border: 1px solid var(--border2);
border-radius: var(--r2);
}
.tog-sw { position: relative; width: 42px; height: 23px; }
.tog-sl {
position: absolute;
inset: 0;
background: var(--card2);
border: 1px solid var(--border2);
border-radius: 100px;
transition: .2s;
}
.tog-sl::before {
content: '';
position: absolute;
width: 17px; height: 17px;
left: 2px; top: 50%;
transform: translateY(-50%);
background: var(--text2);
border-radius: 50%;
transition: .2s;
}
.tog-sw input:checked + .tog-sl {
background: var(--blue);
border-color: var(--blue);
}
.tog-sw input:checked + .tog-sl::before {
transform: translateX(19px) translateY(-50%);
background: #fff;
}
```
**Variante destacada** (toggle de alto impacto como "Acepto nuevos atletas"):
```css
.tog-row.destacado {
background: rgba(74,128,214,.07);
border-color: rgba(74,128,214,.25);
}
```
---
### 5.5 Secciones de formulario (fsec)
Contenedor estándar para agrupar campos relacionados.
```html
person
Título de la sección
Descripción breve
```
```css
.fsec {
background: var(--card);
border: 1px solid var(--border);
border-radius: var(--r);
overflow: hidden;
margin-bottom: 20px;
}
.fsec-hd {
padding: 16px 20px;
border-bottom: 1px solid var(--border);
display: flex;
align-items: center;
gap: 10px;
}
.fsec-hd h2 { font-family: var(--fh); font-size: 14px; font-weight: 700; flex: 1; }
.fsec-hd p { font-size: 12px; color: var(--text2); margin-top: 1px; }
.fsec-body { padding: 20px; display: flex; flex-direction: column; gap: 16px; }
```
**Variante con acento** (plan de membresía activo):
```css
.fsec.plan-activo { border-top: 3px solid var(--blue); }
```
---
### 5.6 Tabs de sección (perfil)
```css
.ptab {
padding: 13px 20px;
font-size: 14px;
font-weight: 600;
color: var(--text2);
cursor: pointer;
border-bottom: 2px solid transparent;
transition: all .15s;
margin-bottom: -1px;
}
.ptab:hover { color: var(--text); }
.ptab.on { color: var(--blue); border-bottom-color: var(--blue); }
```
---
### 5.7 Save Bar
Barra fija en la parte inferior. Visible solo en el tab Perfil del usuario.
```css
.save-bar {
position: fixed;
bottom: 0; left: 0; right: 0;
z-index: 200;
background: var(--card);
border-top: 1px solid var(--border2);
padding: 12px 32px;
display: flex;
justify-content: space-between;
align-items: center;
}
```
Contiene: mensaje informativo a la izquierda + botones "Descartar" (ghost) y "Guardar cambios" (primario azul) a la derecha.
---
### 5.8 Nav global
```css
.nav {
background: var(--bg2);
border-bottom: 1px solid var(--border);
height: 54px;
display: flex;
align-items: center;
padding: 0 32px;
position: sticky;
top: 0;
z-index: 100;
}
```
- **Logo**: imagen `logo-rch-blanco.png`, altura 28px
- **Links de sección**: `padding: 6px 13px; border-radius: 6px; font-size: 13px; font-weight: 500; color: rgba(255,255,255,.5)`. Hover: `color: #fff; background: rgba(255,255,255,.07)`
- **Chip de puntos**: `border-radius: 100px; padding: 5px 13px; font-size: 13px; font-weight: 600`
- **Avatar**: `33px × 33px`, circular, gradiente `var(--accent) → var(--accent2)`, iniciales en blanco, borde `2px solid var(--accent)`
---
### 5.9 Footer (solo páginas públicas)
El footer siempre usa fondo oscuro fijo `#0B0F1A`, independientemente del tema de la página.
```css
.site-footer { background: #0B0F1A; }
.ft-nav a:hover { color: #5B8FDE; background: rgba(74,128,214,.1); }
.ft-social-icons a:hover { border-color: #5B8FDE; background: rgba(74,128,214,.12); }
```
El color de hover en footer es `#5B8FDE` (azul más claro) para garantizar contraste sobre el fondo muy oscuro.
**Regla:** El footer **no aparece** en vistas autenticadas (Perfil, Sherpa IA, Membresía, Mensajería, Panel admin de club).
---
### 5.10 Barras de progreso
```css
/* Barra base */
.progress-bar {
height: 5–6px;
background: var(--border);
border-radius: 100px;
overflow: hidden;
}
/* Nivel / azul (progreso al siguiente nivel) */
.lp-fill { background: linear-gradient(90deg, var(--blue), #67e8f9); }
/* Puntos de lealtad */
.pp-fill { background: linear-gradient(90deg, #1A3B80, var(--blue)); }
/* Perfil completado */
.comp-fill { background: linear-gradient(90deg, var(--gold), #fde68a); }
/* Uso de plan — semáforo */
.ur-fill.ok { background: var(--green); } /* < 70% */
.ur-fill.warn { background: var(--gold); } /* 70–90% */
.ur-fill.crit { background: var(--red); } /* > 90% */
```
---
### 5.11 Tarjeta de membresía (sidebar)
```css
.mem-card {
background: linear-gradient(135deg, #141C2A 0%, #1A2438 60%, #0F1520 100%);
border: 1px solid var(--border2);
border-radius: var(--r);
padding: 22px;
min-height: 160px;
position: relative;
overflow: hidden;
}
/* Círculos decorativos con ::before y ::after */
```
---
### 5.12 Íconos de Material Symbols
```html
```
```css
.ms {
font-family: 'Material Symbols Rounded';
font-variation-settings: 'FILL' 1, 'wght' 400, 'GRAD' 0, 'opsz' 24;
font-size: 20px;
line-height: 1;
display: inline-block;
vertical-align: middle;
user-select: none;
}
.ms.sm { font-size: 16px; }
.ms.xs { font-size: 14px; }
.ms.xxs { font-size: 12px; }
```
Siempre se usa la variante `Rounded` con `FILL: 1` (ícono relleno). Para cambiar tamaño, usar las clases `.sm`, `.xs`, `.xxs`.
---
## 6. Componentes de directorio
### 6.1 Tabs del directorio
Similares a los tabs de perfil pero sin la línea sticky de la segunda fila. Ubicados en el header de la página.
```css
.dtab {
padding: 10px 20px;
font-size: 14px;
font-weight: 600;
color: var(--text2);
cursor: pointer;
border-bottom: 2px solid transparent;
transition: all .15s;
margin-bottom: -1px;
}
.dtab:hover { color: var(--text); }
.dtab.on { color: var(--blue); border-bottom-color: var(--blue); }
```
---
### 6.2 Barra de filtros
Zona fija debajo del header con dos filas: búsqueda + sort, y filtros de disciplina + filtros secundarios.
#### Input de búsqueda
```css
.search-wrap {
position: relative;
flex: 1;
}
.search-wrap input {
width: 100%;
padding: 8px 12px 8px 34px; /* espacio para el ícono */
border-radius: var(--r2);
background: var(--bg3);
border: 1px solid var(--border2);
color: var(--text);
font-size: 13px;
}
.search-icon { position: absolute; left: 10px; top: 50%; transform: translateY(-50%); color: var(--text3); }
```
#### Botón de sort
```css
.sort-btn {
padding: 7px 14px;
border-radius: var(--r2);
border: 1px solid var(--border2);
background: var(--bg3);
color: var(--text2);
font-size: 12px;
font-weight: 600;
cursor: pointer;
white-space: nowrap;
}
.sort-btn:hover { border-color: var(--blue); color: var(--blue); }
```
#### Dropdown de disciplina
Botón que abre un panel flotante con opciones (Todos / Triatlón / Running / Ciclismo / Natación / Multi-sport). La opción seleccionada muestra un `✓` y el botón muestra el label activo.
```css
.disc-btn {
padding: 7px 12px;
border-radius: var(--r2);
border: 1px solid var(--border2);
background: var(--bg3);
color: var(--text2);
font-size: 12px;
font-weight: 600;
cursor: pointer;
display: flex;
align-items: center;
gap: 6px;
}
.disc-btn.active { border-color: var(--blue); color: var(--blue); }
.disc-panel {
position: absolute;
top: calc(100% + 6px);
left: 0;
background: var(--bg2);
border: 1px solid var(--border2);
border-radius: var(--r);
padding: 6px;
min-width: 200px;
z-index: 50;
box-shadow: 0 8px 24px rgba(0,0,0,.3);
}
```
#### Selects secundarios de filtro
```css
.fselect {
padding: 7px 28px 7px 10px;
border-radius: var(--r2);
border: 1px solid var(--border2);
background: var(--bg3);
color: var(--text2);
font-size: 12px;
font-weight: 600;
cursor: pointer;
appearance: none;
}
.fselect:focus { border-color: var(--blue); color: var(--text); }
```
#### Chip de filtro activo
Para filtros booleanos como "Busco equipo":
```css
.fchip {
padding: 7px 13px;
border-radius: 100px;
border: 1px solid var(--border2);
background: transparent;
color: var(--text2);
font-size: 12px;
font-weight: 600;
cursor: pointer;
transition: all .15s;
white-space: nowrap;
}
.fchip.on {
background: rgba(74,128,214,.12);
border-color: var(--blue);
color: var(--blue);
}
```
---
### 6.3 Tarjetas del directorio (cards)
Cada tarjeta representa un atleta, coach o club.
```css
.mcard {
background: var(--bg2);
border: 1px solid var(--border);
border-radius: var(--r);
padding: 20px;
cursor: pointer;
transition: border-color .15s, box-shadow .15s;
}
.mcard:hover {
border-color: var(--border2);
box-shadow: 0 4px 16px rgba(0,0,0,.25);
}
```
**Badge "Busco equipo"** (dorado, solo en tarjetas de atletas con relay activo):
```css
.relay-badge {
padding: 2px 8px;
border-radius: 100px;
background: rgba(245,184,66,.12);
border: 1px solid rgba(245,184,66,.3);
color: var(--gold);
font-size: 10px;
font-weight: 700;
}
```
---
### 6.4 Modal de detalle
Se activa al hacer clic en una tarjeta del directorio.
```css
.modal-backdrop {
position: fixed;
inset: 0;
background: rgba(7,9,15,.75);
display: flex;
align-items: center;
justify-content: center;
z-index: 1000;
padding: 24px;
}
.modal {
background: var(--bg2);
border: 1px solid var(--border2);
border-radius: var(--r);
width: 100%;
max-width: 580px;
max-height: 90vh;
overflow-y: auto;
box-shadow: 0 20px 60px rgba(0,0,0,.5);
}
.modal-body {
padding: 28px;
display: flex;
gap: 24px;
align-items: flex-start;
}
.modal-footer {
padding: 0 28px 24px;
}
.modal-close {
position: absolute;
top: 16px; right: 16px;
width: 32px; height: 32px;
border-radius: 50%;
border: 1px solid var(--border2);
background: transparent;
color: var(--text2);
cursor: pointer;
}
```
**Formas de cerrar el modal:**
- Botón "✕" en la esquina
- Clic en el backdrop fuera del modal (`onclick="closeModalOutside(event)"`)
---
## 7. Componentes de mensajería
Aplica a los cuatro flujos de mensajería (contactar coach, coach recibe, contactar club, admin club recibe).
### 7.1 Panel lateral
Contenedor principal que se superpone sobre la vista de fondo.
```css
.msg-panel {
position: fixed;
top: 48px; right: 0; bottom: 0;
width: 420px;
background: var(--bg2);
border-left: 1px solid var(--border);
display: flex;
flex-direction: column;
overflow: hidden;
box-shadow: -8px 0 32px rgba(0,0,0,.4);
}
```
#### Overlay sobre el fondo
```css
.panel-overlay {
position: fixed;
inset: 48px 0 0 0;
background: rgba(7,9,15,.5);
pointer-events: none;
}
```
El fondo de directorio o inbox se desenfoca con:
```css
.admin-bg { filter: blur(2px) brightness(.45); }
```
---
### 7.2 Header del panel
```css
.panel-hd {
padding: 18px 20px 14px;
border-bottom: 1px solid var(--border);
display: flex;
align-items: flex-start;
gap: 12px;
flex-shrink: 0;
}
.panel-hd-avatar {
width: 38px; height: 38px;
border-radius: 50%;
font-family: var(--fh);
font-size: 12px;
font-weight: 800;
display: flex;
align-items: center;
justify-content: center;
color: #fff;
}
.panel-hd-title {
font-family: var(--fh);
font-size: 13px;
font-weight: 800;
color: var(--text);
text-transform: uppercase;
letter-spacing: .03em;
}
.panel-hd-sub { font-size: 11px; color: var(--text2); margin-top: 2px; }
```
**Badge "NUEVA"** (solicitudes entrantes):
```css
.new-badge {
padding: 1px 7px;
border-radius: 100px;
background: rgba(74,128,214,.15);
border: 1px solid rgba(74,128,214,.3);
color: var(--blue);
font-size: 10px;
font-weight: 700;
}
```
---
### 7.3 Dots de progreso (step wizard)
Barra de progreso visual para los pasos del flujo.
```css
.step-dots {
display: flex;
gap: 6px;
align-items: center;
padding: 10px 20px 0;
flex-shrink: 0;
}
.sdot {
width: 20px; height: 4px;
border-radius: 2px;
background: var(--border2);
transition: background .2s, width .2s;
}
.sdot.on { background: var(--blue); width: 28px; } /* paso actual */
.sdot.done { background: var(--green); } /* paso completado */
.step-num {
font-size: 10px;
color: var(--text3);
font-weight: 600;
margin-left: 6px;
}
```
**Regla:** En el flujo de rechazo, el dot del paso que no existe (ej. paso 3 de chat cuando se rechaza) se oculta. El label dice "2 / 2" en lugar de "2 / 3".
---
### 7.4 Tarjetas de contexto (atleta / coach / club)
Dentro del panel, muestran información del perfil de la otra persona.
```css
.athlete-ctx {
background: var(--bg3);
border: 1px solid var(--border);
border-radius: 10px;
padding: 14px;
display: flex;
gap: 12px;
align-items: flex-start;
}
.athlete-ctx-avatar {
width: 42px; height: 42px;
border-radius: 50%;
font-family: var(--fh);
font-size: 13px;
font-weight: 800;
display: flex;
align-items: center;
justify-content: center;
color: #fff;
}
.athlete-ctx-name { font-size: 13px; font-weight: 700; color: var(--text); margin-bottom: 2px; }
.athlete-ctx-meta { font-size: 11px; color: var(--text2); line-height: 1.5; }
.athlete-ctx-chips { display: flex; gap: 6px; flex-wrap: wrap; margin-top: 6px; }
.athlete-ctx-chip {
padding: 2px 8px;
border-radius: 100px;
background: var(--bg);
border: 1px solid var(--border2);
color: var(--text2);
font-size: 10px;
font-weight: 600;
}
```
**Regla de datos:** La tarjeta de contexto solo muestra campos que existen en el formulario de perfil. Ver sección 9 de `SPEC-FLUJOS-RCH.md`.
---
### 7.5 Caja de mensaje entrante
Muestra el mensaje escrito por el atleta o que llega al admin.
```css
.incoming-msg-box {
background: var(--bg3);
border: 1px solid var(--border);
border-radius: 12px;
border-top-left-radius: 4px;
padding: 14px;
}
.incoming-msg-label {
font-size: 10px;
font-weight: 700;
color: var(--text3);
text-transform: uppercase;
letter-spacing: .07em;
margin-bottom: 8px;
display: flex;
align-items: center;
gap: 5px;
}
.incoming-msg-text { font-size: 13px; color: var(--text); line-height: 1.7; }
.incoming-msg-time { margin-top: 8px; font-size: 10px; color: var(--text3); }
```
---
### 7.6 Pantalla de confirmación centrada
Usada en el paso 2 de todos los flujos para confirmar que la acción fue ejecutada.
```css
.confirm-center {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
text-align: center;
gap: 12px;
padding: 32px 24px;
}
/* Ícono éxito (verde) */
.confirm-icon {
width: 72px; height: 72px;
border-radius: 50%;
background: rgba(16,185,129,.15);
border: 2px solid var(--green);
display: flex;
align-items: center;
justify-content: center;
}
/* Ícono rechazo (rojo) */
.declined-icon {
width: 72px; height: 72px;
border-radius: 50%;
background: rgba(239,68,68,.10);
border: 2px solid rgba(239,68,68,.35);
display: flex;
align-items: center;
justify-content: center;
}
.confirm-title { font-family: var(--fh); font-size: 16px; font-weight: 800; color: var(--text); }
.confirm-body { font-size: 13px; color: var(--text2); line-height: 1.6; max-width: 290px; }
```
---
### 7.7 Chat
#### Barra de estado del chat
```css
.chat-status-bar {
padding: 8px 20px;
background: rgba(16,185,129,.08);
border-bottom: 1px solid rgba(16,185,129,.2);
display: flex;
align-items: center;
gap: 8px;
flex-shrink: 0;
}
.chat-status-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--green); }
.chat-status-text { font-size: 11px; color: var(--green); font-weight: 600; }
```
#### Burbujas de chat
```css
.msg-bubble-wrap { display: flex; flex-direction: column; gap: 4px; }
.msg-bubble-wrap.me { align-items: flex-end; }
.msg-bubble-wrap.them { align-items: flex-start; }
.bubble-meta { font-size: 10px; color: var(--text3); display: flex; align-items: center; gap: 5px; }
.msg-bubble {
max-width: 88%;
padding: 10px 14px;
border-radius: 16px;
font-size: 13px;
line-height: 1.6;
color: var(--text);
}
.msg-bubble.me { background: var(--blue); color: #fff; border-bottom-right-radius: 4px; }
.msg-bubble.them { background: var(--bg3); border: 1px solid var(--border); border-bottom-left-radius: 4px; }
.msg-status { font-size: 10px; color: rgba(255,255,255,.6); text-align: right; margin-top: 2px; }
```
#### Separador de fecha
```css
.section-label {
font-size: 10px;
color: var(--text3);
text-transform: uppercase;
letter-spacing: .08em;
font-weight: 700;
text-align: center;
position: relative;
}
.section-label::before,
.section-label::after {
content: '';
position: absolute;
top: 50%; height: 1px;
background: var(--border);
width: 28%;
}
.section-label::before { left: 0; }
.section-label::after { right: 0; }
```
#### Nota de sistema dentro del chat
```css
.sys-note {
text-align: center;
padding: 8px 16px;
font-size: 11px;
color: var(--green);
font-weight: 600;
}
```
#### Barra de input del chat
```css
.chat-input-bar {
padding: 12px 20px;
border-top: 1px solid var(--border);
display: flex;
gap: 8px;
align-items: center;
flex-shrink: 0;
}
.chat-input {
flex: 1;
padding: 9px 14px;
border-radius: 100px;
background: var(--bg3);
border: 1px solid var(--border2);
color: var(--text);
font-family: var(--fb);
font-size: 13px;
outline: none;
transition: border-color .15s;
}
.chat-input:focus { border-color: var(--blue); }
.chat-input::placeholder { color: var(--text3); }
.send-btn {
width: 36px; height: 36px;
border-radius: 50%;
background: var(--blue);
border: none;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
transition: background .15s;
}
.send-btn:hover { background: var(--blue2); }
```
---
### 7.8 Toggle de simulación (mockup)
Controles en la barra superior del mockup para simular la respuesta de la otra parte (Acepta / Rechaza). Solo existe en los mockups de presentación, no en producción.
```css
.resp-toggle { display: none; align-items: center; gap: 6px; }
.rbtn {
padding: 4px 10px;
border-radius: 6px;
border: 1px solid var(--border2);
background: transparent;
color: var(--text2);
font-size: 11px;
cursor: pointer;
transition: all .15s;
}
.rbtn.on.rechaza { background: var(--red); border-color: var(--red); color: #fff; }
.rbtn.on.acepta { background: var(--green); border-color: var(--green); color: #fff; }
```
**Cuándo aparece el toggle:**
- Coach (POV Ángeles): desde paso 3 (en espera)
- Coach (POV Javier): desde paso 1 (al recibir solicitud)
- Club (POV Ángeles): no aplica (el atleta no controla la respuesta)
- Club Admin (POV Laura): desde paso 1
---
### 7.9 Tip / nota informativa dentro del panel
```css
.admin-tip {
font-size: 11px;
color: var(--text3);
line-height: 1.6;
padding: 10px 12px;
background: var(--bg3);
border-radius: 8px;
border-left: 2px solid var(--border2);
display: flex;
gap: 8px;
align-items: flex-start;
}
```
---
### 7.10 Footer del panel
Área de botones fija en la parte inferior del panel lateral.
```css
.panel-footer {
padding: 14px 20px;
border-top: 1px solid var(--border);
display: flex;
gap: 8px;
flex-shrink: 0;
}
```
Puede contener combinaciones de: `btn-decline` (flex:1) + `btn-accept` (flex:2), o `btn-outline` + `btn-full` en partes iguales.
---
## 8. Componentes de panel admin
Aplica a la vista del administrador del club (`MOCKUP-RCH-Mensajes-ClubAdmin-v01.html`).
### 8.1 Sidebar del panel admin
```css
.admin-sidebar {
width: 240px;
flex-shrink: 0;
background: var(--bg2);
border-right: 1px solid var(--border);
padding: 16px 0;
}
.admin-section {
padding: 10px 16px 6px;
font-size: 10px;
font-weight: 700;
color: var(--text3);
text-transform: uppercase;
letter-spacing: .08em;
}
.admin-row {
padding: 9px 16px;
display: flex;
align-items: center;
gap: 8px;
border-left: 2px solid transparent;
cursor: pointer;
}
.admin-row.on {
background: rgba(74,128,214,.08);
border-left-color: var(--blue);
}
.admin-row-name { font-size: 12px; font-weight: 600; color: var(--text2); }
.admin-row-badge {
margin-left: auto;
padding: 1px 6px;
border-radius: 100px;
background: var(--blue);
color: #fff;
font-size: 9px;
font-weight: 700;
}
```
---
### 8.2 Items de lista (inbox del admin)
```css
.admin-list-item {
background: var(--bg2);
border: 1px solid var(--border);
border-radius: 10px;
padding: 14px;
margin-bottom: 10px;
display: flex;
gap: 10px;
align-items: flex-start;
}
/* Ítem seleccionado / activo */
.admin-list-item.active {
border-color: var(--blue);
box-shadow: 0 0 0 2px rgba(74,128,214,.2);
}
.unread-dot {
width: 8px; height: 8px;
border-radius: 50%;
background: var(--blue);
flex-shrink: 0;
margin-top: 4px;
}
```
---
## 9. UI condicional
Comportamientos que dependen del estado del usuario o de la interacción actual.
| Condición | Comportamiento |
|---|---|
| Rol = Coach | Muestra bloque Coach (toggle "Acepto nuevos atletas" + Especialidad). Oculta toggle "Busco coach". Activa tab "Mi club". |
| Rol ≠ Coach | Muestra toggle "Busco coach". Oculta bloque Coach y tab "Mi club". |
| Toggle relay activo | Muestra bloque relay (Disciplina, Tipo, Carrera). |
| Tab activo ≠ Perfil | Oculta save bar fija. |
| Flujo mensajería: modo rechaza | Oculta paso 3 (chat). Dots muestran "2 / 2". Botón "Siguiente →" deshabilitado en paso 2. |
| Flujo mensajería: modo acepta | Habilita paso 3. Dots muestran "2 / 3" y "3 / 3". |
| Admin panel — solicitud nueva | Muestra badge azul "1" en "Solicitudes" en la sidebar. |
| Perfil: coach acepta nuevos atletas | Toggle activo → aparece en el directorio de coaches. |
**Clases CSS de visibilidad condicional** (flujos de mensajería):
```css
.only-acepta { display: none !important; }
.only-rechaza { display: none !important; }
body.resp-acepta .only-acepta { display: flex !important; }
body.resp-rechaza .only-rechaza { display: flex !important; }
```
---
## 10. Iconografía
Se usa **Material Symbols Rounded** exclusivamente. Todos los íconos se muestran en variante rellena (`FILL: 1`).
### Íconos más usados en el sistema
| Ícono | Nombre MS | Contexto de uso |
|---|---|---|
| ⚡ | `bolt` | Puntos de lealtad |
| 🏊 | `pool` | Natación |
| 🚴 | `directions_bike` | Ciclismo |
| 🏃 | `directions_run` | Running |
| 📍 | `location_on` | Ciudad/ubicación |
| 🏅 | `military_tech` | Rol atleta, logros |
| ✉️ | `mail` | Mensajes, solicitudes |
| 💬 | `forum` | Chat, conversaciones |
| ✓ | `check` | Completado, éxito |
| ✕ | `close` | Cerrar, rechazar |
| ℹ️ | `info` | Tip / nota informativa |
| ⏰ | `schedule` | Timestamp |
| 📤 | `send` | Enviar mensaje |
| 👤 | `person` | Información personal |
| 🖊 | `edit_note` | Historia / bio |
| ➕ | `person_add` | Agregar miembro |
| 👥 | `groups` | Club, miembros |
---
## 11. Vistas completadas y pendientes
### Completadas ✅
| Archivo | Descripción | Estado |
|---|---|---|
| `MOCKUP-RCH-Perfil-v01.html` | Perfil de atleta — tema dark | ✅ Validado |
| `MOCKUP-RCH-Perfil-v01-light.html` | Perfil de atleta — tema light | ✅ Validado |
| `MOCKUP-RCH-Footer-v01.html` | Footer standalone (dark/light/móvil) | ✅ Validado |
| `MOCKUP-RCH-Eventos-v01.html` | Alta de evento (admin) + detalle (atleta) + directorio | ✅ Completado |
| `MOCKUP-RCH-Directorio-v01.html` | Directorio: atletas, coaches y clubs con filtros y modal | ✅ Validado |
| `MOCKUP-RCH-Mensajes-Coach-v01.html` | Flujo mensajería — POV atleta contactando coach (4 pasos) | ✅ Validado |
| `MOCKUP-RCH-Mensajes-Javier-v01.html` | Flujo mensajería — POV coach recibiendo solicitud (3 pasos) | ✅ Validado |
| `MOCKUP-RCH-Mensajes-Club-v01.html` | Flujo mensajería — POV atleta contactando club (3 pasos) | ✅ Validado |
| `MOCKUP-RCH-Mensajes-ClubAdmin-v01.html` | Flujo mensajería — POV admin del club recibiendo mensaje (3/2 pasos) | ✅ Validado |
### Pendientes de diseñar
| Sección | Descripción |
|---|---|
| Inbox del atleta | Vista de todas las conversaciones activas y solicitudes del atleta |
| Directorio de eventos | Listado completo de eventos con filtros |
| Foros | Listado de hilos, detalle de hilo, modal de creación |
| Clasificados | Listado, detalle, publicar anuncio |
| Home / Landing pública | Página de entrada para visitantes no registrados |
| Onboarding | Flujo de registro e introducción para nuevos usuarios |
| Notificaciones | Centro de notificaciones del usuario |
---
## 12. Convenciones de naming
### Archivos de mockup
```
MOCKUP-RCH-[Sección]-v[N].html
MOCKUP-RCH-[Sección]-v[N]-light.html
Ejemplos:
MOCKUP-RCH-Directorio-v01.html
MOCKUP-RCH-Foros-v01.html
MOCKUP-RCH-Home-v01.html
```
### Clases CSS
- Componentes de layout: `.page-body`, `.sidebar`, `.panel-body`
- Secciones de formulario: `.fsec`, `.fsec-hd`, `.fsec-body`
- Grillas: `.fg`, `.fg2`, `.fg3`
- Chips: `.chip`, `.chip.on`, `.chip.nivel`
- Botones: `.btn-primary`, `.btn-outline`, `.btn-ghost`, `.btn-accept`, `.btn-decline`, `.btn-full`
- Tabs: `.ptab` (perfil), `.dtab` (directorio)
- Mensajería: `.msg-panel`, `.panel-hd`, `.panel-body`, `.panel-footer`, `.sdot`, `.msg-bubble`
### Variables CSS
Usar siempre `var(--token)` en lugar de valores hardcodeados. La única excepción es el fondo del footer (`#0B0F1A`) y colores de gradiente específicos documentados en este archivo.
---
*Para actualizar este documento: agregar nuevas secciones en la sección correspondiente, actualizar la tabla de vistas en la sección 11, y bumpejar el número de versión y la fecha en el encabezado.*