v1.0
Mulligan Design System

Diseñar con intención.
Construir con consistencia.

Un sistema de diseño estructurado para Tradeit TCG. Basado en Atomic Design, inspirado en Carbon, pensado para una plataforma de marketplace profesional de coleccionables digitales.

5
Ramps de color
40+
Componentes
2
Modos (L/D)
v1.0
Versión actual
Acceso rápido
¿Nuevo en Mulligan?
Comienza por entender los principios que guían cada decisión de diseño en Tradeit TCG.
Documentación

Primeros pasos

Mulligan es el lenguaje visual de Tradeit TCG. Este documento es la fuente de verdad para diseñadores y desarrolladores.

Instalación de fuentes

Agregar las fuentes IBM Plex via Google Fonts en el <head> de tu documento:

<link rel="preconnect" href="https://fonts.googleapis.com">
<link href="https://fonts.googleapis.com/css2?family=IBM+Plex+Sans:wght@300;400;500&family=IBM+Plex+Mono:wght@400;500&display=swap" rel="stylesheet">

Variables CSS base

Copiar estos tokens en tu archivo CSS global. Son la base de todos los componentes del sistema:

:root {
  /* Color — Blue (primario) */
  --blue-60: #1A6FB5;
  --blue-80: #0D4A80;
  --blue-10: #EBF2FB;

  /* Semánticos light mode */
  --color-bg-primary:     #FFFFFF;
  --color-bg-secondary:   #F0EFEC;
  --color-text-primary:   #131210;
  --color-text-secondary: #5C5A56;
  --color-border:         #D6D4CE;
  --color-interactive:    #1A6FB5;
  --color-success:        #2DA67E;
  --color-warning:        #E69A20;
  --color-danger:         #D94646;

  /* Tipografía */
  --font: 'IBM Plex Sans', system-ui, sans-serif;
  --mono: 'IBM Plex Mono', monospace;

  /* Espaciado base 4px */
  --sp-1: 4px;   --sp-2: 8px;   --sp-3: 12px;
  --sp-4: 16px;  --sp-6: 24px;  --sp-8: 32px;

  /* Border radius */
  --r-sm: 4px;  --r-md: 8px;  --r-lg: 12px;  --r-xl: 16px;
}
Nunca hardcodear colores hexadecimales en componentes. Siempre usar variables CSS semánticas para garantizar compatibilidad con dark mode.
Fundamentos

Principios de diseño

Cinco principios guían cada decisión visual en Mulligan. Ante cualquier duda de diseño, volver a estos principios.

01
Confianza primero
Cada decisión visual debe transmitir seguridad y profesionalismo. El usuario opera con activos de valor. Si algo se ve informal o impreciso, no pertenece a la plataforma.
02
Densidad inteligente
Mostrar múltiples atributos de una carta sin saturar. Jerarquía visual clara. La información debe estar disponible sin ser abrumadora.
03
Coherencia sistémica
Los mismos tokens, componentes y patrones funcionan en web y app. Sin excepciones. Un componente diseñado una sola vez debe funcionar en todos los contextos.
04
Accesibilidad base
Contraste mínimo AA (4.5:1 texto, 3:1 UI). Focus rings visibles. Semántica HTML correcta. La accesibilidad no es un añadido posterior, es un requisito base.
05
Flat & estructurado
Sin gradientes decorativos. Elevación comunicada con bordes y opacidad, no con sombras profundas. La estructura surge de la organización del contenido, no de efectos visuales.
Fundamentos

Paleta de colores

5 ramps semánticos de 6 stops cada uno. Cada color tiene un uso específico y no debe intercambiarse arbitrariamente.

Blue — Primario interactivo

10
20
40
60
80
100
TokenHexUso
blue-10#EBF2FBFondos hover, backgrounds de badges info
blue-40#6AAAD8Íconos secundarios, estados intermedios, dark mode interactive
blue-60#1A6FB5Color primario de acción. Botones, links, focus rings
blue-80#0D4A80Hover de botón primario, texto sobre blue-10

Gray — Neutro estructural

0
10
20
40
60
80
100

Ramps semánticos

Teal — Éxito
10
40
60
Amber — Warning
10
40
60
Red — Danger
10
40
60

Tokens semánticos

Light Mode

--color-bg-primary
#FFFFFF
--color-bg-secondary
#F0EFEC
--color-text-primary
#131210
--color-text-secondary
#5C5A56
--color-interactive
#1A6FB5
--color-success
#2DA67E
--color-warning
#E69A20
--color-danger
#D94646
Fundamentos

Tipografía

Escala modular con ratio 1.25. IBM Plex Sans para UI, IBM Plex Mono exclusivo para precios y datos numéricos.

NombreSizeWeightLine-heightUso
Display48px3001.1Heroes, landing page
Heading 132px300–4001.2Título de página principal
Heading 224px5001.3Sección principal, panel header
Heading 320px5001.4Nombre de carta en ficha
Body16px4001.6Texto de párrafo
Body Small14px4001.6Descripciones, helpers
Label12px5001.4Etiquetas uppercase (ls: 0.08em)
Caption11px4001.4Timestamps, metadatos
Price14–28px4001.2Precios en IBM Plex Mono

Muestras

Tradeit TCG Display
Heading 1 — Mercado de cartas
Heading 2 — Resultados de búsqueda
Heading 3 — Charizard ex SIR
Body — Carta en estado Near Mint, primera edición, idioma inglés. Set Scarlet & Violet 151.
Body Small — Edición: Scarlet & Violet · Rareza: Special Illustration Rare
Label — Precio promedio · Variación 30d
$ 48.500 CLP
USD 52.40 · TRM 950
El peso 500 es el máximo permitido en todo el sistema. Nunca usar 600 ni 700. La jerarquía se logra con tamaño y color, no con negrita excesiva.
Fundamentos

Espaciado

Sistema base 4px. Todos los valores de espaciado son múltiplos de 4 para garantizar consistencia matemática en toda la plataforma.

sp-1
4px
sp-2
8px
sp-3
12px
sp-4
16px
sp-5
20px
sp-6
24px
sp-8
32px
sp-10
40px
sp-12
48px
sp-16
64px
TokenpxremUso típico
space-14px0.25remGap interno mínimo
space-28px0.5remGap entre ícono y texto
space-312px0.75remPadding en badges, chips
space-416px1remPadding en inputs, gap en rows
space-624px1.5remPadding de cards estándar
space-832px2remSeparación entre secciones
space-1040px2.5remMargin entre bloques principales
space-1248px3remPadding de secciones en web
space-1664px4remSeparadores de página
Fundamentos

Grid y Layout

Sistema de grilla de 12 columnas para web y 4 columnas para app. Máximo de contenido: 1280px.

Breakpoints Web

BreakpointWidthColumnasGutterMargin
sm< 640px412px16px
md640–1024px816px24px
lg1024–1280px1216px32px
xl> 1280px1224pxauto (max 1440px)

Breakpoints App (Mobile)

BreakpointWidthColumnasGutterMargin
Mobile320–390px412px16px
Mobile L390–428px416px16px
Tablet428–768px816px24px
Fundamentos

Elevación

4 niveles de elevación. La profundidad se comunica principalmente con bordes, no con sombras dramáticas.

Elevation 0
Solo border
Elevation 1
Cards
Elevation 2
Dropdowns
Elevation 3
Modales
Fundamentos

Motion

Animaciones funcionales, no decorativas. Cada tipo tiene una duración y easing específicos calibrados para transmitir la sensación correcta de peso y respuesta. Siempre respetar prefers-reduced-motion.

TipoDuraciónEasingUso
Micro100msease-outHover states, toggles, scale en active
Short150msease-outTooltips, badges, chips activos
Medium200msease-in-outDropdowns, notificaciones, color de fondo
Long300msease-in-outModales overlay, drawers, sidebars
Chart400msease-outAnimación inicial del gráfico de precio
Skeleton1400ms ∞ease-in-outLoading shimmer en cards y contenido
Page Entry500mseaseEntrada de página, staggered reveals

Micro — 100ms ease-out

100ms Hover & Active state

La respuesta más rápida del sistema. El usuario siente feedback inmediato en cada interacción táctil o de cursor. Aplica a botones (color + scale en active), toggles y checkboxes.

Listing activo

transition: background-color 100ms ease-out, transform 100ms ease-out;

✓ Hacer

Aplicar escala sutil scale(0.97) en el estado :active de los botones. Da sensación física de "presión" sin retardar la interacción.

✗ Evitar

No superar 100ms en respuestas de hover. Por encima de ese umbral la UI se siente lenta y el usuario pierde la sensación de control directo.

Short — 150ms ease-out

150ms Tooltip & Badge appear

Para elementos que aparecen como respuesta directa a una acción del usuario: tooltips, badges de éxito tras una acción, chips que se activan. Suficientemente rápido para no interrumpir, suficientemente visible para orientar.

Professional Sports Authenticator · Grado máximo
✓ Pago confirmado

transition: opacity 150ms ease-out, transform 150ms ease-out;

✓ Hacer

Los tooltips deben aparecer con un pequeño desplazamiento vertical (4px → 0) además del fade. Esto da dirección al movimiento e indica de dónde viene el elemento.

✗ Evitar

No animar la desaparición de tooltips. Deben ocultarse inmediatamente al quitar el cursor para no bloquear visualmente el contenido subyacente.

Medium — 200ms ease-in-out

200ms Dropdown & Notificación

Para elementos que se despliegan o aparecen desde un contexto ya visible: dropdowns de filtro, notificaciones inline que se insertan en el flujo, transiciones de color de fondo en estados de carga.

Listing publicado
Charizard ex SIR ya está visible en la plataforma.

animation: dropIn / notifSlide 200ms ease-in-out both;

✓ Hacer

El ease-in-out en 200ms da la sensación de que el elemento tiene masa pero no peso. Ideal para overlays pequeños que no bloquean el flujo principal de trabajo.

✗ Evitar

No reutilizar la animación de dropdown para notificaciones toast globales. Los toasts deben deslizarse desde el borde de la pantalla, no aparecer desde un punto fijo.

Long — 300ms ease-in-out

300ms Modal & Drawer

Para transiciones de pantalla completa o que cubren una porción significativa del viewport. El modal combina fade del overlay con scale + translateY del contenido. El drawer desliza desde el borde con transform.

Filtros

Modal: scale(.96)+translateY(12px) → scale(1) · 300ms ease-in-out
Drawer: translateX(-100%) → translateX(0) · 300ms ease-in-out

✓ Hacer

El overlay del modal debe animarse de forma independiente al contenedor: el overlay aparece primero (opacity), y el modal aparece 20–30ms después con scale+translateY para dar sensación de capas.

✗ Evitar

No usar animaciones largas (>300ms) en interacciones repetitivas. Si el usuario abre y cierra el mismo modal varias veces, 400ms+ se vuelve frustrante muy rápido.

Chart — 400ms ease-out

400ms Gráfico de precio histórico

Animación de entrada del gráfico de precio. La línea se dibuja de izquierda a derecha usando stroke-dashoffset, seguida del área sombreada con un fade. El usuario percibe el tiempo como una narrativa: "el precio fue así con el tiempo".

Precio promedio — 9M
$48.500 ↑ 12.4%
9M 1M 3M 12M

stroke-dasharray:400; stroke-dashoffset: 400 → 0 · 400ms ease-out
Área fill: opacity 0 → 1 · 400ms ease-out · delay 200ms

✓ Hacer

Al cambiar el periodo (1M → 3M → 9M), volver a disparar la animación. Le recuerda al usuario que los datos cambiaron y que la nueva línea representa un nuevo rango temporal.

✗ Evitar

No animar el gráfico si ya fue visible y el usuario hace scroll hacia arriba. La animación solo se dispara una vez en la entrada inicial de la ficha de carta.

Skeleton — 1400ms ∞ ease-in-out

1400ms ∞ Loading shimmer

El skeleton loader reemplaza el contenido durante la carga. El shimmer viaja de izquierda a derecha simulando un reflejo de luz. Debe preservar exactamente la forma del contenido real para evitar el "layout shift" al cargar.

background: linear-gradient(90deg, bg-secondary 25%, bg-page 50%, bg-secondary 75%);
background-size: 1200px; animation: shimmer 1.4s ease-in-out infinite;

✓ Hacer

El skeleton debe tener exactamente las mismas dimensiones que el contenido real. La transición de skeleton a contenido debe ser instantánea (sin fade) para minimizar el layout shift percibido.

✗ Evitar

No mostrar skeleton por más de 3 segundos sin mostrar un estado de error. Si los datos no cargan, reemplazar el skeleton con un empty state que permita al usuario reintentar.

Page Entry — 500ms staggered

500ms Staggered reveal de página

Al entrar a una nueva página, los elementos principales aparecen en secuencia con un delay escalonado (stagger) de 80ms entre cada uno. Crea una sensación de "construcción" progresiva sin parecer lenta. Máximo 4 elementos en stagger.

Charizard ex
SV 151 SIR NM
$48.500 ↑ 12%

@keyframes fadeUp: opacity 0→1, translateY 14px→0 · 500ms ease
nth-child(1): delay 0ms · nth-child(2): 80ms · nth-child(3): 160ms · nth-child(4): 240ms

✓ Hacer

Limitar el stagger a máximo 4 elementos con delay máximo de 240ms total. Si hay más elementos, animar solo los primeros 4 y mostrar el resto sin animación para que la página no tarde en ser usable.

✗ Evitar

No aplicar stagger a listas de items dinámicos (resultados de búsqueda). El stagger en grillas de muchos items se ve errático. Usar solo en elementos estructurales de la página como hero, titulo, badges y precio.

Código de referencia

@media (prefers-reduced-motion: no-preference) {

  /* Micro — hover + active */
  .btn { transition: background-color 100ms ease-out, transform 100ms ease-out; }
  .btn:active { transform: scale(0.97); }

  /* Short — tooltip */
  .tooltip { opacity:0; transform:translateY(4px);
    transition: opacity 150ms ease-out, transform 150ms ease-out; }
  .tooltip-trigger:hover .tooltip { opacity:1; transform:translateY(0); }

  /* Medium — dropdown */
  @keyframes dropIn {
    from { opacity:0; transform:translateY(-6px); }
    to   { opacity:1; transform:translateY(0); }
  }
  .dropdown { animation: dropIn 200ms ease-in-out both; }

  /* Long — modal */
  @keyframes modalIn {
    from { opacity:0; transform:scale(.96) translateY(12px); }
    to   { opacity:1; transform:scale(1) translateY(0); }
  }
  .modal { animation: modalIn 300ms ease-in-out both; }

  /* Chart — path draw */
  @keyframes chartDraw {
    from { stroke-dashoffset: 400; }
    to   { stroke-dashoffset: 0; }
  }
  .chart-line { stroke-dasharray:400; animation: chartDraw 400ms ease-out; }

  /* Skeleton shimmer */
  @keyframes shimmer {
    0%   { background-position:-600px 0; }
    100% { background-position: 600px 0; }
  }
  .skeleton {
    background: linear-gradient(90deg,
      var(--bg-secondary) 25%, var(--bg-page) 50%, var(--bg-secondary) 75%);
    background-size:1200px;
    animation: shimmer 1.4s ease-in-out infinite;
  }

  /* Staggered page entry */
  @keyframes fadeUp {
    from { opacity:0; transform:translateY(14px); }
    to   { opacity:1; transform:translateY(0); }
  }
  .stagger > *:nth-child(1) { animation: fadeUp 500ms ease both 0ms; }
  .stagger > *:nth-child(2) { animation: fadeUp 500ms ease both 80ms; }
  .stagger > *:nth-child(3) { animation: fadeUp 500ms ease both 160ms; }
  .stagger > *:nth-child(4) { animation: fadeUp 500ms ease both 240ms; }
}
Fundamentos

Íconos

Sistema de íconos basado en Phosphor Icons. Trazo consistente de 1.8px, 4 tamaños estándar.

TamañoUso
16pxInline en texto, badges, labels
20pxControles de UI, inputs con ícono
24pxBotones con ícono, navegación
32pxIlustrativos, empty states

Íconos del sistema

ContextoÍcono (Phosphor)
BúsquedaMagnifyingGlass
FiltrosFunnel
ComprarShoppingCart
Vender / ListingTag
WishlistHeart
NotificacionesBell
PerfilUser
VerificadoSealCheck
Precio ↑TrendUp
Precio ↓TrendDown
EnvíoPackage
GradingCertificate
Componentes — Atomic Design

Átomos

Las unidades más pequeñas del sistema. Cada átomo es funcional por sí mismo y es la base de moléculas y organismos.

Buttons

Variantes
Tamaños
✓ Hacer

Usar Primary solo para la acción más importante de la pantalla. Un máximo de un botón Primary visible por vista.

✗ Evitar

No usar múltiples botones Primary en paralelo. No usar Danger para acciones reversibles.

✓ Hacer

Botones de acción destructiva (eliminar listing, cancelar orden) usan variante Danger precedida de confirmación modal.

✗ Evitar

No deshabilitar botones sin explicar por qué. Usar helper text o tooltip que indique la condición bloqueante.

Badges

Near Mint Verificado Sellado En disputa PSA 10 Borrador
✓ Hacer

Usar el sistema de color semántico: azul para info/condición, teal para éxito/verificado, amber para advertencia, rojo para error. El badge oscuro sólido es exclusivo para grading certificado (PSA, CGC).

✗ Evitar

No usar más de 2 badges simultáneos en un mismo contexto de card. No inventar colores fuera del sistema para nuevos estados.

Chips / Filtros

✓ Hacer

Los chips de tipo de producto son mutuamente excluyentes. Siempre hay exactamente uno activo. Usar para filtros rápidos con máximo 5 opciones visibles.

✗ Evitar

No usar chips para acciones. Los chips son exclusivamente para filtrado y selección de estado. Las acciones van en botones.

Inputs

Búsqueda por nombre exacto
Ingresa un valor numérico
✓ Hacer

Validar on blur (cuando el usuario sale del campo). Mostrar el error de forma inline debajo del campo afectado, con color rojo y descripción del problema.

✗ Evitar

No validar on keypress (bloquea mientras el usuario escribe). No mostrar todos los errores de un formulario al hacer submit sin marcar cada campo individualmente.

✓ Hacer

Los campos de precio siempre deben incluir la unidad (CLP, USD) en el label o placeholder. El helper text muestra la referencia de mercado como orientación.

✗ Evitar

No usar placeholder como sustituto del label. El placeholder desaparece al escribir y no debe contener información crítica para completar el campo.

Card de carta

Charizard ex
SIR
Charizard ex
SV — Scarlet & Violet 151
$48.500
↑ 12%
Mewtwo ex
PSA 9
Mewtwo ex
SV 151 · Graduado
$185.000
↑ 28%
Pikachu ex
UR
Pikachu ex
SV — Paldea Evolved
$22.000
↓ 3%
✓ Hacer

Truncar nombre y set con ellipsis cuando excedan el ancho. La card mantiene siempre la misma altura: el precio y la tendencia deben ser siempre visibles.

✗ Evitar

No omitir la tendencia de precio. Es un dato crítico para el usuario inversionista. Si no hay datos suficientes, mostrar "–" en lugar de ocultar el espacio.

✓ Hacer

Las cartas graduadas usan badge oscuro sólido (PSA/CGC + grado). El fondo de la imagen usa amber para diferenciar visualmente el tipo de producto.

✗ Evitar

No usar imágenes redondas para el arte de la carta. Siempre rectángulo con border-radius 6px para respetar las proporciones reales de las cartas físicas.

Componentes — Atomic Design

Moléculas

Grupos de átomos que funcionan juntos como una unidad con responsabilidad única. Las moléculas combinan átomos simples (labels, inputs, botones, badges) para resolver un problema específico de interfaz, de la misma forma en que los átomos se combinan en química para formar algo con propiedades nuevas.

Notificaciones inline

Alertas contextuales dentro del flujo de contenido. Compuestas por borde lateral semántico (3px), fondo tonal y bloque de texto con título + descripción. Cuatro variantes semánticas fijas: info, éxito, advertencia y error.

Variantes
Verificación pendiente
Tu cuenta vendedor está en revisión. Puede tardar hasta 48 horas.
Pago confirmado
La compra de Pikachu ex fue procesada correctamente.
Precio fuera de rango
Tu listing está 40% por encima del precio promedio de mercado.
Listing rechazado
Las fotos no cumplen la resolución mínima requerida.
Tokens aplicados

Info: border-left: 3px blue-60 · fondo blue-10 · título blue-80

Success: border-left: 3px teal-40 · fondo teal-10 · título teal-60

Warning: border-left: 3px amber-40 · fondo amber-10 · título amber-60

Error: border-left: 3px red-40 · fondo red-10 · título red-60

✓ Hacer

Las notificaciones inline son estáticas. El usuario las descarta manualmente. Usar en el contexto donde ocurre el evento: formulario con errores, resultado de acción o alerta de sistema persistente.

✗ Evitar

No apilar más de 2 notificaciones inline en la misma vista. No usar la variante error para comunicar estados informativos: cada variante tiene un significado semántico fijo e inamovible.

Display de precio

Componente de datos financieros. Combina label categórico (uppercase 11px 500), valor principal en IBM Plex Mono y tendencia con flecha + porcentaje + período. Tres tamaños según el contexto de uso.

Variantes de contenido
Precio promedio CLP
$ 48.500
↑ 12.4% · 30 días
Ref. TCGPlayer USD
$ 52.40
Referencia · NM
Mínimo activo
$ 39.000
↓ 3.1% · 7 días
Tamaños
Label
$48.500
↑ 12%
Compact — cards
Label
$48.500
↑ 12.4% · 30d
Default — ficha
Label
$48.500
↑ 12.4% · 30 días
Hero — dashboard
✓ Hacer

Precio siempre en IBM Plex Mono para alineación de dígitos. Label en uppercase 11px. Tendencia con flecha + porcentaje + período explícito. La moneda (CLP/USD) siempre visible.

✗ Evitar

No mezclar CLP y USD en el mismo componente sin indicar cuál es precio local y cuál es referencia. No omitir la moneda pensando que el usuario la recordará del contexto.

Tabs

Navegación entre vistas del mismo contenido agrupado por categoría. Altura de ítem 36px, indicador activo border-bottom 2px en interactive con margin-bottom -1px para solapar el borde del contenedor. Dos variantes: estándar (línea) y contenida (switcher).

Variante estándar
Single Cards
Sellados
Graduados
Mis listings
Contenido de la tab activa...
Variante contenida (switcher)
Web
App
✓ Hacer

Las tabs son navegación entre categorías. El cambio no requiere confirmación: siempre una activa. La variante switcher es solo para exactamente 2 opciones excluyentes (Web/App, Light/Dark, Lista/Grilla).

✗ Evitar

No usar tabs para pasos de un proceso secuencial: usar stepper. No exceder 5 tabs en la misma barra. No ocultar tabs según el rol sin señalarlo: mostrar la tab deshabilitada en su lugar.

Breadcrumb

Ruta de navegación jerárquica. Compuesto por ítems separados por "/" donde los ítems previos son links en color interactivo y el ítem actual es texto secundario no clickeable. Si hay más de 4 niveles, el centro se colapsa con "…".

Variantes de profundidad
Inicio / Buscar / Charizard ex
Inicio / Mi panel / Mis listings / Editar listing
Inicio / / Historial / Orden #4821
✓ Hacer

El ítem actual en text-secondary sin cursor pointer. Si hay más de 4 niveles, colapsar el medio con "…" clickeable que muestra la ruta completa en tooltip. El separador "/" siempre en text-muted.

✗ Evitar

No mostrar breadcrumb en home ni en páginas de primer nivel. El nombre de la página actual en el H1 debe ser idéntico al ítem del breadcrumb: no usar títulos distintos entre ambos.

Form Field

Unidad fundamental de cualquier formulario. Composición vertical fija: label (12px 500) → input/select (40px) → helper text (11px). Cuatro estados: default, success (border teal), error (border rojo), disabled (opacidad 0.4, no editable).

Estados
Búsqueda por nombre exacto
✓ Email válido
✕ Ingresa un valor numérico
Campo no disponible
Select
✓ Hacer

Validar on blur (al salir del campo). El helper text en error describe el problema específico, no un mensaje genérico. El campo de precio incluye la unidad (CLP/USD) en el label.

✗ Evitar

No validar on keypress: interrumpe al usuario mientras escribe. No usar placeholder como sustituto del label: desaparece al escribir. Nunca mostrar todos los errores solo al hacer submit.

Star Rating

Valoración de vendedor. Compuesto por estrellas en amber-40, promedio numérico (1 decimal) y conteo de reseñas. Dos modos: solo lectura (perfiles y listas) e interactivo (flujo post-compra). Con menos de 5 reseñas muestra "Nuevo vendedor".

Solo lectura
★★★★★ 4.9 (142 reseñas)
★★★★ 4.1 (28)
Nuevo vendedor
Interactivo (post-compra)
¿Cómo fue tu experiencia con este vendedor?
3 de 5 — Neutral
✓ Hacer

Con menos de 5 reseñas, mostrar "Nuevo vendedor" en lugar del promedio numérico para no distorsionar la percepción de confianza del usuario comprador con muestras estadísticamente insignificantes.

✗ Evitar

No mostrar el componente interactivo en el perfil público del vendedor: solo aparece en el flujo post-compra. No permitir que el mismo usuario valore dos veces al mismo vendedor en la misma transacción.

Progress Bar

Indicador de avance para procesos con valor cuantificable. Track de 4px en bg-secondary, fill en color semántico con border-radius 2px. Siempre acompañado de label de contexto y valor numérico visible. No usar para carga indeterminada.

Variantes semánticas
Verificación KYC75%
Ventas completadas40 / 50
Subiendo fotos3 / 6 archivos
Verificación fallidaReintentar →
✓ Hacer

Mostrar siempre el valor numérico (porcentaje o fracción x/total) junto a la barra. El color del fill refleja el estado semántico: azul neutro, teal éxito, amber en progreso, rojo error.

✗ Evitar

No usar para carga indeterminada (sin tiempo definido). Para eso usar skeleton loader o spinner. La progress bar siempre implica un valor conocido y finito de avance que el sistema puede calcular.

Avatar

Representación visual del usuario. Círculo con iniciales (2 caracteres) sobre fondo tonal. Tres tamaños: Sm 28px para topbar y listas, Md 40px para paneles y cards, Lg 56px para páginas de perfil. Puede incluir un dot indicador de estado en la esquina inferior derecha.

Tamaños y variantes
MC
Sm · 28px
JR
Md · 40px
TP
Lg · 56px
AB
Con indicador
Sin foto
✓ Hacer

Usar las 2 primeras letras del username. Asignar el color de fondo de forma determinista basada en el username (hash del string → índice de ramp) para que el mismo usuario siempre tenga el mismo color.

✗ Evitar

No usar avatares cuadrados o rectangulares. No mostrar avatares sin fallback: si la imagen de perfil no carga, siempre mostrar el círculo con iniciales. No usar emoji como avatar en ningún contexto.

Componentes — Atomic Design

Organismos

Secciones completas de la UI compuestas por moléculas y átomos. Cada organismo es independiente, tiene su propio propósito y puede existir en múltiples páginas.

Top Navigation Bar

Presente en todas las páginas web. Altura fija 48px, position fixed, z-index 100. Compuesta por logo, search central y acciones de usuario a la derecha.

Iniciar sesión
Registrarse
MC
✓ Hacer

La barra de navegación debe ser siempre sticky (position: fixed). El logo siempre enlaza al home. En estado autenticado, el avatar reemplaza los botones de auth.

✗ Evitar

No agregar más de 2 acciones secundarias en el topbar. No ocultar el topbar en scroll en desktop: solo es aceptable en mobile y solo al hacer scroll hacia abajo.

Search & Filter Bar

Barra secundaria debajo del nav, sticky independiente. Concentra todos los controles de búsqueda: input, selects de edición, chips de tipo de producto y CTA.

Single Card Sellado Graduado
✓ Hacer

Los chips de tipo de producto son mutuamente excluyentes. El botón de búsqueda siempre al extremo derecho. En mobile, colapsar selects y chips en un botón "Filtros" que abre un bottom sheet.

✗ Evitar

No aplicar la búsqueda automáticamente con debounce en este contexto: el usuario puede estar ingresando un nombre complejo. Requiere acción explícita (Enter o botón).

Grid de resultados

Grilla de 4 columnas en desktop con sidebar de filtros a la izquierda. Máximo 24 cards por página. Incluye header con conteo de resultados y control de ordenamiento.

Filtros
Condición
Near Mint
Lightly Played
Damaged
Idioma
EN
JP
48 resultados
Charizard ex
$48.500↑12%
Mewtwo ex PSA
$185.000↑28%
Pikachu ex
$22.000↓3%
Gardevoir ex
$31.000↑5%
✓ Hacer

Mostrar siempre el conteo de resultados en el header de la grilla. Al aplicar un filtro, hacer scroll al inicio del contenido. Usar skeleton loaders durante la carga, no spinners.

✗ Evitar

No resetear los filtros al cambiar de página de paginación. Los filtros aplicados persisten durante toda la sesión de búsqueda del usuario.

Ficha de carta + Dashboard de precios

Vista de detalle completa. Columna principal con datos oficiales (Pokémon TCG API), gráfico histórico con controles de periodo, y columna lateral con CTA de compra y datos del vendedor.

Charizard ex · SIR · 182/165
Charizard ex
SV 151 SIR NM
Promedio CLP
$48.500
↑ 12.4% · 30d
Ref. TCGPlayer
$52.40 USD
TRM $950
1M 3M 9M 12M
Listings activos (4)
Charizard ex · NM
trader_mcl · ★ 4.9
$42.000
Charizard ex · LP
cards_store · ★ 4.7
$38.000
✓ Hacer

Los datos de imagen, nombre, número y rareza provienen exclusivamente de la Pokémon TCG API (source of truth). El vendedor no puede editar estos campos en su listing.

✗ Evitar

No mostrar el gráfico de precio si hay menos de 3 transacciones en el periodo seleccionado. Mostrar mensaje "Datos insuficientes · mostrando referencia TCGPlayer" en su lugar.

✓ Hacer

Los listings se ordenan por precio ascendente por defecto. El comprador siempre ve primero la mejor oferta disponible para la condición que filtró.

✗ Evitar

No mezclar condiciones en el mismo listado sin diferenciación visual clara. Un listing NM y uno LP del mismo vendedor deben tener sus badges de condición prominentes.

Panel de Usuario (Vendedor)

Dashboard del vendedor con resumen de métricas, listado de órdenes recientes y acceso rápido a gestión de listings. Mismo patrón para el panel comprador con métricas adaptadas.

MC
trader_mcl
Vendedor verificado · Santiago, RM
★ 4.9 · Verificado
Total recaudado
$842.500
↑ neto comisiones
Ventas completas
142
96.4% completitud
Listings activos
23
4 borradores
Órdenes recientes
Charizard ex SIR
poke_fan_1 · Hace 2 h
$42.000
Pago confirmado
Pikachu ex UR · NM
colect_scl · Hace 1 día
$22.000
Entregado
Mewtwo ex · ETB Sellado
invest_tcg · Hace 3 días
$95.000
En camino
✓ Hacer

Las métricas del panel (total recaudado, completitud) se calculan solo sobre transacciones con estado "Entregado". Las órdenes canceladas no cuentan en el promedio positivo de reputación.

✗ Evitar

No mostrar el total bruto sin deducir comisiones. El vendedor debe ver siempre el monto neto que realmente recibirá para planificar su negocio correctamente.

✓ Hacer

El color del dot de estado debe coincidir exactamente con el color del badge de estado. Redundancia visual intencional para usuarios con daltonismo.

✗ Evitar

No paginar las órdenes recientes en el resumen del panel. Mostrar las últimas 5 con un link "Ver todas" que lleva a la vista completa de seguimiento.

Modal

Overlay centrado con fondo semitransparente. 3 tamaños: sm (480px), md (640px), lg (800px). Siempre con header, body y footer de acciones. En mobile se convierte en bottom sheet.

Confirmar compra
Charizard ex SIR · NM
Vendedor: trader_mcl · ★ 4.9
$42.000 CLP
Al confirmar, los fondos quedan retenidos en escrow hasta que confirmes la recepción de la carta.
✓ Hacer

En modales de confirmación de compra o acciones destructivas, la acción primaria siempre a la derecha. Incluir un resumen del objeto afectado dentro del modal para que el usuario no tenga que recordarlo.

✗ Evitar

No apilar modales. Un modal que abre otro modal confunde al usuario sobre cómo volver atrás. Si se necesita flujo de pasos, usar un stepper dentro de un solo modal.

Bottom Navigation (App)

Barra de navegación fija al fondo en mobile. 4 tabs: Inicio, Buscar, Mis compras/ventas y Perfil. Siempre visible, no se oculta en scroll.

Contenido de la pantalla
Inicio
Buscar
Mis compras
Perfil
✓ Hacer

Mantener exactamente 4 tabs. La tab activa resalta con color interactivo en ícono y label. Touch target de cada tab: mínimo 44×44px incluyendo safe area inferior en iOS.

✗ Evitar

No ocultar el bottom nav durante el scroll. No usar badges de notificación en más de 2 tabs simultáneamente, genera ruido visual que desenfoca la atención del usuario.

Empty State

Estado vacío para búsquedas sin resultado, wishlist vacía o panel sin actividad. Siempre incluye ícono neutral, título descriptivo, descripción orientativa y CTA cuando corresponde.

Sin resultados para "Blastoise ex"
No encontramos cartas con ese nombre. Intenta con un nombre parcial o ajusta los filtros de edición y condición.
✓ Hacer

El empty state debe explicar por qué no hay contenido y ofrecer una acción concreta para resolverlo. El ícono debe ser neutral y relacionado con el contexto (búsqueda, carrito, perfil).

✗ Evitar

No mostrar un empty state genérico "Sin resultados" sin contexto. No incluir CTA de acción destructiva en un empty state (nunca "Eliminar todo" como solución a una lista vacía).

Componentes — Atomic Design

Templates

Layouts de página completos que orquestan los organismos en estructuras coherentes. Los templates definen la composición espacial de cada pantalla, sin contenido real: son el esqueleto sobre el que se construyen las páginas.

Template: Búsqueda y Resultados

Layout de 2 columnas: sidebar de filtros (240px) + grilla de resultados (flex 1). Top nav y filter bar son sticky independientes. Paginación centrada al final del contenido.

✓ Hacer

El sidebar de filtros es sticky dentro del scroll de contenido (no del page). Al aplicar un filtro, el conteo de resultados se actualiza inmediatamente. El template mantiene el sidebar visible incluso si hay pocos resultados.

✗ Evitar

No colapsar el sidebar automáticamente en pantallas intermedias (1024px). En ese rango, reducir el sidebar a 180px pero mantenerlo visible. Ocultarlo completamente solo bajo 768px.

✓ Hacer

En mobile (app), el template se transforma: sidebar desaparece, chips de filtro en scroll horizontal, grilla pasa a 2 columnas, paginación pasa a "cargar más" (infinite scroll opcional).

✗ Evitar

No mostrar un estado vacío en el área de grilla si los filtros aplicados son la causa. Acompañar siempre el empty state con el botón "Limpiar filtros" como CTA principal.

Template: Ficha de Carta (Detalle)

Layout de 2 columnas: columna principal 8/12 con imagen oficial, datos del set, gráfico histórico y listings. Columna lateral 4/12 sticky con CTA de compra e info del vendedor.

✓ Hacer

La columna lateral (CTA de compra + vendedor) es sticky dentro del scroll de la columna principal. El usuario puede hacer scroll por los listings sin perder de vista el botón de compra.

✗ Evitar

No duplicar el CTA de compra en la columna principal. Solo existe en la columna lateral para mantener la jerarquía visual clara y evitar confusión sobre cuál acción ejecutar.

✓ Hacer

En mobile, el template colapsa a una sola columna con el CTA de compra fijo en la barra inferior (position: sticky, bottom: 0 + safe area). Todos los datos se apilan verticalmente en ese orden: imagen → precios → gráfico → listings.

✗ Evitar

No permitir que el gráfico de precio ocupe más del 30% del viewport sin scroll. En desktop es suficiente con 120px de alto. El gráfico es contexto, no el foco principal de la pantalla.

Template: Panel de Usuario

Layout con sidebar de navegación interna (220px) + área de contenido. La navegación del panel es secundaria y no reemplaza el topbar principal. En mobile usa bottom tab navigation.

✓ Hacer

El sidebar de navegación del panel es persistente: todas las sub-secciones (Resumen, Compras, Listings, Valoraciones, Configuración) son accesibles en todo momento sin salir del panel.

✗ Evitar

No mezclar la navegación del panel con la navegación global del topbar. Son contextos independientes. El topbar navega a secciones globales; el sidebar del panel navega dentro del área personal.

✓ Hacer

El estado activo del sidebar del panel usa border-left de 2px en color interactivo + fondo blue-10, igual que el sidebar de documentación. Coherencia sistémica entre superficies de navegación.

✗ Evitar

No esconder datos financieros (total recaudado, total gastado) detrás de un click adicional. Las métricas principales están en el resumen al entrar al panel, siempre visibles de inmediato.

Template: Autenticación

Layout minimalista sin topbar principal. Card centrada horizontal y verticalmente sobre un fondo de página. Máximo 480px de ancho. Misma estructura para registro, login y recuperación de contraseña.

✓ Hacer

La card de autenticación tiene siempre el logo arriba, el formulario al centro y el link alternativo (¿Ya tienes cuenta? / ¿Olvidaste tu contraseña?) al fondo. El orden no varía entre login y registro.

✗ Evitar

No mostrar el topbar global en páginas de autenticación. Quita toda distracción y enfoca al usuario en la tarea. Solo el logo dentro de la card como punto de identidad de marca.

✓ Hacer

Validar inline field por field (on blur). Si el formulario es de registro y tiene múltiples pasos (datos → verificación), usar un stepper dentro de la misma card, no pantallas separadas.

✗ Evitar

No redirigir automáticamente al usuario tras el login sin confirmación visual. Mostrar brevemente "Sesión iniciada" antes de la redirección para confirmar que la acción fue exitosa.

Patrones

Light Mode

El modo claro es el modo por defecto de Mulligan. Está basado en una escala de grises cálidos derivada del ramp Gray, con superficies blancas y fondos de página ligeramente tintados. La elevación se comunica con sombras sutiles y diferencias de borde, nunca con colores de fondo saturados.

Implementación

Los tokens de Light Mode son los valores por defecto definidos en :root. No requieren clase adicional: cualquier componente que use las variables CSS semánticas renderiza automáticamente en light mode cuando el usuario no ha seleccionado dark mode y el sistema operativo no lo solicita.

/* Tokens por defecto en :root — Light Mode */
:root {
  --bg-page:      #F8F8F6;  /* gray-0: fondo de página */
  --bg-primary:   #FFFFFF;  /* blanco puro: cards, inputs, nav */
  --bg-secondary: #F0EFEC;  /* gray-10: hover, filter bar, tags */
  --text-primary:   #131210; /* gray-100: texto principal */
  --text-secondary: #5C5A56; /* gray-60: labels, descripciones */
  --text-muted:     #9B9892; /* gray-40: metadatos, placeholders */
  --border:    #D6D4CE;      /* gray-20: borders por defecto */
  --border-em: #B2B0AB;      /* gray-30: borders énfasis/hover */
  --interactive: #1A6FB5;   /* blue-60: botones, links, focus */
  --success:  #2DA67E;      /* teal-40 */
  --warning:  #E69A20;      /* amber-40 */
  --danger:   #D94646;      /* red-40 */
}

/* El modo claro es el default: no requiere clase especial */
/* Solo el dark mode necesita la clase .dark en <html> */

Paleta de fondos — capas de elevación

En light mode la elevación se comunica con sombras progresivamente más pronunciadas y con diferencias de 1px en los bordes. Las capas van desde el fondo de página (más oscuro dentro de la escala clara) hasta los overlays flotantes (con shadow prominente).

bg-page — Fondo de página #F8F8F6 · gray-0
bg-secondary — Filter bar, hover, tags #F0EFEC · gray-10
bg-primary — Cards, modales, inputs, nav #FFFFFF
Elevation 2 — Dropdowns, tooltips shadow: 0 4px 16px rgba(0,0,0,.08)
Elevation 3 — Modales, drawers shadow: 0 8px 32px rgba(0,0,0,.12)
border — Separadores por defecto #D6D4CE · gray-20

Tokens semánticos — Light Mode completo

TokenValor LightRampUso
--bg-page#F8F8F6gray-0Fondo de página. Ligeramente tintado para reducir fatiga vs. blanco puro.
--bg-primary#FFFFFFCards, inputs, topbar, modales. La superficie "elevada" principal.
--bg-secondary#F0EFECgray-10Filter bar, hover states, tags, fondos de skeleton.
--text-primary#131210gray-100Cuerpo de texto, títulos, precios. Máximo contraste.
--text-secondary#5C5A56gray-60Labels uppercase, descripciones secundarias, metadatos.
--text-muted#9B9892gray-40Placeholders, timestamps, texto deshabilitado.
--border#D6D4CEgray-20Todos los bordes por defecto. 0.5px–1px.
--border-em#B2B0ABgray-30Bordes en hover, énfasis, separadores visibles.
--interactive#1A6FB5blue-60Botones primarios, links, focus rings, active tabs.
--success#2DA67Eteal-40Confirmaciones, precios al alza, vendedor verificado.
--warning#E69A20amber-40Advertencias, precios inusuales, grading highlight.
--danger#D94646red-40Errores, acciones destructivas, precios a la baja.

Escala tipográfica en Light Mode

En light mode el texto primario #131210 sobre fondo blanco logra un ratio de contraste de 17.5:1, muy por encima del mínimo AA (4.5:1). El texto secundario #5C5A56 sobre blanco alcanza 7.1:1. Todos los pares del sistema cumplen WCAG AA como mínimo.

Heading 1 — 32px 300
color: #131210 · ratio 17.5:1 ✓ AAA
Body regular — 16px 400. Texto de párrafo, descripciones de listing y contenido de ficha de carta.
color: #131210 · ratio 17.5:1 ✓ AAA
Body small — 14px 400. Metadatos, helper text, set names, descripción del vendor.
color: #5C5A56 · ratio 7.1:1 ✓ AA
Label · 12px · 500 · Uppercase
color: #9B9892 · ratio 3.5:1 ✓ AA (texto grande)
$ 48.500 ↑ 12.4%
IBM Plex Mono · color: #131210

Vista previa de componentes en Light Mode

Todos los componentes del sistema en su estado de luz: navegación, cards de carta, notificaciones, formulario y botones. Las superficies blancas se elevan sobre el fondo gris mediante bordes y sombras mínimas.

M
Mulligan Design System
Buscar carta...
Registrarse
MC
SIR
Charizard ex
SV · 151
$48.500 ↑12%
NM
PSA 9
Mewtwo ex
SV 151 · Graduado
$185.000 ↑28%
Verificación pendiente
Tu cuenta está en revisión.
Pago confirmado
Compra procesada correctamente.
Confirmar
Cancelar
Nombre de la carta
Charizard ex
Near Mint Verificado Sellado PSA 10 En disputa

Elevación — escala completa

Cuatro niveles de elevación en light mode. El nivel 0 usa solo borde como separador visual. Los niveles 1–3 agregan box-shadow progresiva para comunicar profundidad y separación del fondo de página.

Elevation 0
Solo border
Cards planas, inputs
Elevation 1
Shadow suave
Cards en grid
Elevation 2
Shadow media
Dropdowns, tooltips
Elevation 3
Shadow profunda
Modales, drawers
✓ Hacer

Usar blue-60 (#1A6FB5) como color interactivo en light mode. Este valor cumple contraste AA (4.5:1) sobre blanco y sobre bg-page. Cumple además contraste 3:1 para elementos de UI (bordes de inputs, íconos).

✗ Evitar

No usar blanco puro (#FFFFFF) como fondo de página. El sistema usa #F8F8F6 (gray-0) para reducir la fatiga visual y dar contexto de profundidad a las cards blancas que se elevan sobre él.

✓ Hacer

La elevación en light mode usa box-shadow progresiva. Nivel 0 = solo border, Nivel 1 = shadow 6% opacidad, Nivel 2 = shadow 8%, Nivel 3 = shadow 12%. Las sombras siempre en negro con opacidad, nunca en color.

✗ Evitar

No usar colores de fondo saturados para diferenciar superficies en light mode (ej. fondo azul claro para el nav). La jerarquía visual se construye con la escala gray, no con tonos de color. Los colores son para semántica, no para estructura.

✓ Hacer

Los focus rings en light mode usan box-shadow: 0 0 0 2px rgba(26,111,181,.2). El anillo es semitransparente para que se vea bien tanto sobre fondo blanco como sobre bg-secondary gris.

✗ Evitar

No hardcodear colores hexadecimales en componentes aunque estés en light mode. Si lo haces, el dark mode dejará de funcionar en ese componente. Siempre usar var(--token-semantico) sin excepción.

Patrones

Dark Mode

Estrategia completa de modo oscuro basada en tokens semánticos CSS. El dark mode no es una inversión de colores: es un sistema de capas donde los fondos más oscuros están abajo y los más claros emergen hacia el usuario.

Implementación

El sistema usa variables CSS que cambian según una clase en el elemento raíz. Esto permite que cada componente se adapte automáticamente sin CSS adicional, siempre que use variables semánticas y nunca valores hexadecimales directos.

/* 1. Detectar preferencia del sistema */
@media (prefers-color-scheme: dark) {
  :root { --bg-page: #131210; --bg-primary: #1E1D1A; /* ... */ }
}

/* 2. Clase para toggle manual del usuario */
.dark {
  --bg-page:    #131210;
  --bg-primary: #1E1D1A;
  --bg-secondary: #252421;
  --text-primary: #F0EFEC;
  --text-secondary: #9B9892;
  --text-muted: #5C5A56;
  --border: #2E2D2A;
  --border-em: #3D3C38;
  --interactive: #6AAAD8; /* blue-40, más legible sobre oscuro */
}

/* 3. Toggle en JavaScript */
document.documentElement.classList.toggle('dark');
localStorage.setItem('theme', isDark ? 'dark' : 'light');

Paleta de fondos — capas de elevación

En dark mode la elevación se comunica con fondos progresivamente más claros (no con sombras). Las capas van desde el fondo de página (más oscuro) hasta los overlays (más claros).

bg-page — Fondo de página #131210 · gray-100
bg-primary — Cards, inputs, nav #1E1D1A
bg-secondary — Hover, tag bg #252421
border — Separadores #2E2D2A · gray-80

Tokens semánticos — comparación Light / Dark

TokenLight ModeDark ModeNota
--bg-page#F8F8F6#131210Fondo de página base
--bg-primary#FFFFFF#1E1D1ACards, modales, inputs
--bg-secondary#F0EFEC#252421Hover, filter bar, tags
--text-primary#131210#F0EFECTexto principal — inversión
--text-secondary#5C5A56#9B9892Labels, descripciones
--border#D6D4CE#2E2D2ABorders por defecto
--interactive#1A6FB5 (blue-60)#6AAAD8 (blue-40)Más claro para contraste sobre oscuro
--success#2DA67E#2DA67ESin cambio (ya legible)
--warning#E69A20#E69A20Sin cambio
--danger#D94646#D94646Sin cambio

Vista previa de componentes en Dark Mode

M
Mulligan Design System
Charizard ex
SV · 151
$48.500 ↑12%
Verificación pendiente
Tu cuenta está en revisión.
Pago confirmado
Compra procesada correctamente.
Comprar
Cancelar
✓ Hacer

Usar blue-40 (#6AAAD8) como color interactivo en dark mode. El blue-60 (#1A6FB5) no cumple contraste AA sobre fondos oscuros. Guardar la preferencia del usuario en localStorage para que persista entre sesiones.

✗ Evitar

No usar fondo negro puro (#000000) en dark mode. El sistema usa gray-100 (#131210) como base: aporta calidez y reduce la fatiga visual en sesiones largas. No invertir imágenes de cartas: tienen colores propios.

✓ Hacer

La elevación en dark mode se comunica con fondos progresivamente más claros (bg-page → bg-primary → bg-secondary), no con sombras. Las sombras se reducen al 50% de opacidad respecto a light mode.

✗ Evitar

No hardcodear ningún color hexadecimal en componentes. Siempre usar var(--nombre-token). Un solo hex hardcodeado puede romper el dark mode de un componente entero silenciosamente.

Patrones

Responsive

Adaptaciones sistemáticas del mismo componente según el contexto de uso. El 80% del tráfico de Tradeit TCG ocurre en mobile (eventos y torneos): la app es el producto principal, la web es el complemento de escritorio.

Estrategia Mobile-First

Diseñar desde el layout más restrictivo (320px) hacia el más amplio (1440px). En cada breakpoint, se añaden elementos que el espacio adicional permite, no se quitan elementos del diseño de escritorio.

BreakpointRangoColsGutterMargin
xs320–390px412px16px
sm390–640px416px16px
md640–1024px816px24px
lg1024–1280px1216px32px
xl>1280px1224pxauto (max 1440px)

Adaptaciones por componente

ComponenteWeb (lg+)App (xs/sm)Cambio clave
Top NavLogo + search central + auth buttonsLogo + título + 2 íconos de acciónSearch → pantalla dedicada
NavegaciónSidebar vertical 220px permanenteBottom tab bar 4 items + safe areaDe vertical a horizontal fijo en fondo
FiltrosBarra horizontal sticky inlineBotón "Filtros" → bottom sheet fullDe inline a modal contextual
Grid de cartas4–6 columnas con sidebar2 columnas sin sidebarSidebar de filtros desaparece
Ficha de carta2 col: contenido (8/12) + CTA (4/12)1 col vertical + CTA sticky en bottomCTA migra a barra inferior fija
Panel usuarioSidebar nav 220px + contenidoStack vertical sin sidebarNavegación se fusiona en bottom tabs
ModalOverlay centrado (max 640px)Bottom sheet full width (90vh)Overlay → slide desde abajo
TablasFull width con columnas visiblesScroll horizontal o card viewPriorizar columnas críticas

Bottom sheet (Mobile)

Sustituto mobile de los modales centrados y los paneles de filtro. Desliza desde el borde inferior. Siempre incluye handle de arrastre, soporte para drag-to-dismiss y cierre al tocar el overlay.

Contenido de la pantalla
Filtros
Single Card Sellado Graduado
✓ Hacer

Los bottom sheets tienen siempre un handle visible (36×4px centrado), soportan drag-to-dismiss y cierran al tocar el overlay. Usar max-height: 90vh para que nunca cubran la pantalla completa sin intención.

✗ Evitar

No usar modales centrados en pantallas menores de 640px. No hacer scroll horizontal en ningún breakpoint excepto en tablas con contenedor controlado. El scroll lateral en toda la página es un error crítico de layout.

✓ Hacer

Touch targets mínimos de 44×44px en todos los elementos interactivos de la app. El espaciado entre elementos táctiles debe ser de al menos 8px para evitar activaciones accidentales durante el uso en movimiento.

✗ Evitar

No ocultar contenido importante detrás de más de un tap en mobile. Si el usuario necesita la información para decidir si compra, debe estar visible sin interacción adicional. Priorizar sobre mostrar más items en la grilla.

Patrones

Accesibilidad

WCAG AA por defecto en todos los componentes. La accesibilidad no es un requisito adicional: es una restricción de diseño que mejora la experiencia para todos los usuarios, incluyendo los que usan la plataforma en condiciones de baja atención o alta velocidad.

Contraste de color

Todos los pares texto/fondo del sistema cumplen el ratio mínimo de contraste WCAG AA. Los colores interactivos cumplen también el ratio mínimo para elementos de UI (3:1).

Texto primario sobre oscuro 14.7:1
Texto primario sobre blanco 17.5:1
Texto info sobre bg info 5.8:1 ✓ AA
Texto éxito sobre bg éxito 4.9:1 ✓ AA

Focus ring

Todos los elementos interactivos muestran un anillo de foco visible cuando se navega con teclado. Nunca usar outline: none sin un reemplazo equivalente.

box-shadow: 0 0 0 2px rgba(26,111,181, 0.3);

Checklist de accesibilidad

ReglaImplementaciónNivel
Contraste de textoMínimo 4.5:1 para texto normal, 3:1 para texto grande (+18px o +14px bold)AA
Contraste de UIMínimo 3:1 para bordes de inputs y íconos interactivos sin textoAA
Focus visiblebox-shadow: 0 0 0 2px rgba(var(--interactive), 0.3). Nunca outline:none sin reemplazoAA
Semántica HTMLAcciones → <button>, navegación → <a>, formularios → <label for=""> asociados. No usar <div> para interaccionesA
Alt textCartas: alt="Charizard ex — Scarlet & Violet 151 — Special Illustration Rare". Imágenes decorativas: alt=""A
ARIA labelsaria-label en íconos sin texto. role="status" aria-live="polite" en precios que se actualizan dinámicamenteAA
Orden de focoEl orden de tabulación debe seguir el flujo visual de lectura. No usar tabindex positivo: genera jerarquías confusasA
Reducción de movimientoTodas las animaciones envueltas en @media (prefers-reduced-motion: no-preference)AAA
Touch targetsMínimo 44×44px en app. Espaciado mínimo de 8px entre elementos táctilesAA (2.5.5)
Texto escalableNo usar user-scalable=no. Diseñar para que el zoom hasta 200% no rompa el layoutAA
Doble codificaciónNunca comunicar estado solo con color. Siempre acompañar con ícono, texto o patrón adicional para usuarios con daltonismoA
Errores de formularioAsociar mensaje de error con el campo mediante aria-describedby. No depender solo del color rojo para indicar el errorAA
✓ Hacer

Usar doble codificación para estados semánticos: color + ícono o color + texto. Un usuario con daltonismo no puede distinguir entre una notificación de éxito y de error solo por el color del borde.

✗ Evitar

No usar outline: none en elementos interactivos sin un focus ring equivalente. Los usuarios de teclado y lectores de pantalla necesitan saber en todo momento qué elemento está enfocado.

✓ Hacer

Los precios que se actualizan en tiempo real deben tener role="status" o aria-live="polite" para que los lectores de pantalla anuncien el cambio sin interrumpir la lectura del contexto actual.

✗ Evitar

No deshabilitar el zoom con user-scalable=no. Los usuarios con baja visión necesitan poder ampliar hasta 200% sin que el layout se rompa. Diseñar con zoom en mente desde el inicio.

Patrones

Contenido

Guías de redacción, jerarquía informativa y estándares de etiquetado para toda la plataforma. El contenido es parte del diseño: el tono, la precisión y la consistencia del texto determinan si el usuario confía en la plataforma o no.

Voz y tono

Mulligan usa una voz directa, técnica y sin artificios. La plataforma habla con coleccionistas que conocen el vocabulario del mercado: no hace falta simplificar en exceso. La confianza se gana con precisión, no con informalidad forzada.

AtributoDescripciónEjemplo
DirectoFrases cortas. Sin rodeos. El usuario actúa, la UI confirma."Pago confirmado" no "¡Tu pago fue procesado exitosamente!"
TécnicoUsar el vocabulario del coleccionista: NM, LP, PSA, BGS, set, listing, escrow."Listing en estado Near Mint" no "Producto en muy buen estado"
HonestoLos errores explican la causa real, no mensajes genéricos."Precio mínimo permitido: $500 CLP" no "Valor inválido"
NeutroSin entusiasmo artificial. Sin "¡Excelente elección!" ni emojis en mensajes de sistema."Carta agregada a wishlist" no "¡Añadida a tu colección de favoritos! 🎉"

Condición de carta — código de color y texto

El estándar de condición es el más crítico del sistema. Un error aquí genera disputas entre compradores y vendedores. La condición siempre se muestra como badge visual + texto corto estandarizado. Nunca se usa solo el color sin la abreviación.

Sistema completo
Condición
Badge
Tokens
Descripción para vendedor
Mint (M)
M
teal-10 / teal-60
Perfecta. Sin uso. Recién sacada del sobre.
Near Mint (NM)
NM
blue-10 / blue-80
Casi perfecta. Puede tener leves marcas de mazo.
Lightly Played (LP)
LP
amber-10 / amber-60
Ligeramente usada. Marcas visibles de cerca.
Moderately Played (MP)
MP
amber-10 / amber-80
Marcas claras de uso en bordes y superficie.
Heavily Played (HP)
HP
red-10 / red-60
Desgaste muy visible. Solo para juego casual.
Damaged (D)
D
red-10 / red-80
Doblada, rasgada o con daño estructural.
Graduado PSA/CGC
PSA 10
gray-100 / gray-10
Certificada por empresa + grado numérico 1–10.

Textos de interfaz — estándares

Labels de acción
✓ Usar

"Publicar listing" · "Confirmar compra" · "Ver oferta" · "Agregar a wishlist" · "Editar" · "Pausar"

✗ Evitar

"Click aquí" · "Enviar" · "OK" · "Continuar" · "Siguiente" (sin contexto) · "Procesar"

Mensajes de error
✓ Usar

"Precio mínimo: $500 CLP" · "El nombre no puede estar vacío" · "Foto demasiado pequeña: mínimo 400×560px"

✗ Evitar

"Valor inválido" · "Error en el campo" · "Algo salió mal, intenta de nuevo" · "Error 422"

Estados vacíos
Sin resultados
No encontramos cartas con ese nombre. Intenta con un nombre parcial o cambia los filtros.
Wishlist vacía
Agrega cartas a tu wishlist para hacer seguimiento de precios y disponibilidad.

Numeración y moneda

DatoFormato correctoFormato incorrecto
Precio CLP$48.500 CLP$48500 / CLP 48.500 / 48.500 pesos
Precio USD$52.40 USDUSD 52.4 / US$52.40 / 52,40 USD
Porcentaje↑ 12.4%+12.4% / 12,4%
Número de carta182/165182 de 165 / #182
Grado PSAPSA 10 / CGC 9.5PSA-10 / 10 PSA / Grado 10
Fecha de ordenHace 2 horas · Hace 3 días2026-04-15 14:32 / 15/04/2026
✓ Hacer

El badge de condición siempre visible en la card de resultado sin hover. Es información crítica de compra: el usuario decide si hace clic o no según la condición visible. Siempre badge + abreviación, nunca solo color.

✗ Evitar

No inventar condiciones fuera del estándar internacional (M, NM, LP, MP, HP, D). Si el vendedor quiere aclarar algo específico sobre el estado, lo hace en el campo de descripción libre del listing.

✓ Hacer

Los textos de error deben describir la causa y, cuando sea posible, la solución. "Foto demasiado pequeña: mínimo 400×560px" es más útil que "Archivo no válido". El usuario actúa; la UI explica.

✗ Evitar

No usar tono entusiasta en mensajes de sistema: "¡Excelente!" "¡Listo!" "¡Genial!". Mulligan es una plataforma de transacciones de valor: la confianza se construye con precisión, no con exclamaciones.

Documentación

Changelog

Historial de versiones del sistema de diseño.

v1.0
Lanzamiento inicial — 2026
Definición completa del sistema: 5 ramps de color, escala tipográfica, espaciado base-4, grid 12/4 columnas, catálogo de componentes por nivel Atomic Design, soporte Light/Dark Mode, guías de accesibilidad y condición de carta.