La identidad visual de Centik se basa en cuatro principios:
- Claridad: La informacion financiera debe ser inmediatamente comprensible. Cada dato tiene un proposito visual claro — color, peso o posicion que comunica si algo es positivo, negativo o neutro sin necesidad de leer etiquetas.
- Calma: Las finanzas generan ansiedad. La interfaz debe transmitir control y orden. Fondos oscuros, espaciado generoso, transiciones suaves. Nada parpadea, nada grita.
- Densidad controlada: Un dashboard financiero necesita mostrar muchos datos. La solucion no es esconder informacion sino organizarla en jerarquias claras con agrupacion visual consistente.
- Minimalismo retro-futurista: Estetica Nothing OS x Bloomberg Terminal x Dieter Rams — calmo, confiado, preciso, ligeramente jugueton en los detalles. OLED negro puro y acento chartreuse como identidad visual central. Sin formas redondeadas excesivas ni UI burbujeante.
--color-bg: #000000 → Negro OLED, fondo principal de la app
--color-surface: #0A0A0A → Fondo secundario, sidebar, secciones principales
--color-surface-elevated: #141414 → Cards, contenedores, elementos elevados
--color-surface-hover: #1A1A1A → Estado hover en superficies interactivas
--color-border-divider: #222222 → Bordes, separadores, divisores
--color-dot-matrix: #1E1E1E → Textura dot-matrix (usar al 40% de opacidad)
--color-text-primary: #E8E8E8 → Texto principal, titulos, montos
--color-text-secondary: #999999 → Labels, descripciones, texto de soporte
--color-text-tertiary: #666666 → Placeholders, metadata, texto silenciado
--color-text-disabled: #444444 → Estado deshabilitado
--color-accent: #CCFF00 → Accion principal, links, elementos interactivos (chartreuse)
--color-accent-hover: #B8E600 → Hover del acento
--color-accent-subtle: rgba(204, 255, 0, 0.12) → Fondos de badges/tags con acento
--color-positive: #00E676 → Ingresos, ahorro, tendencia positiva
--color-positive-subtle: rgba(0, 230, 118, 0.12) → Fondo sutil para contextos positivos
--color-negative: #FF3333 → Gastos, deuda, tendencia negativa
--color-negative-subtle: rgba(255, 51, 51, 0.12) → Fondo sutil para contextos negativos
--color-warning: #FF9100 → Alertas, presupuesto cerca del limite
--color-warning-subtle: rgba(255, 145, 0, 0.12) → Fondo sutil para warnings
--color-info: #448AFF → Informacion neutral
--color-info-subtle: rgba(68, 138, 255, 0.12) → Fondo sutil para info
Cada categoria tiene un color desaturado asignado que se usa consistentemente en graficas, iconos y badges. Los colores son versiones silenciadas de la paleta original para armonizar con la estetica monocromatica del sistema.
Comida: #C88A5A → Naranja silenciado (de #fb923c)
Servicios: #7A9EC4 → Azul silenciado (de #60a5fa)
Entretenimiento: #9B89C4 → Purpura silenciado (de #a78bfa)
Suscripciones: #C48AA3 → Rosa silenciado (de #f472b6)
Transporte: #C4A84E → Amarillo silenciado (de #fbbf24)
Otros: #8A9099 → Gris silenciado (de #94a3b8)
Contenedores de icono: El color de categoria silenciado al 12% de opacidad como fondo, color solido para el icono.
Acento de categoria principal: En vistas de presupuesto y dashboard, la card de la categoria con mayor gasto recibe un borde izquierdo sutil en chartreuse (--color-accent).
El color nunca es decorativo. Cada uso de color comunica algo:
- Verde (
--color-positive) aparece exclusivamente donde hay dinero que entra o crece - Rojo (
--color-negative) aparece exclusivamente donde hay dinero que sale o se debe - Chartreuse (
--color-accent) es la accion: botones primarios, links, elementos clicables - Naranja (
--color-warning) es la precaucion: estas cerca de un limite - Los colores de categoria solo aparecen en contextos de categorias (graficas, badges, iconos)
Nunca usar rojo para un boton de accion a menos que sea destructivo (eliminar). Nunca usar verde para decorar si no implica dinero positivo.
Restricciones visuales:
- Sin gradientes (excepto oscuro-a-mas-oscuro muy sutil en fondos)
- Sin formas redondeadas tipo blob ni UI burbujeante
- Ratios de contraste accesibles WCAG 2.1 AA obligatorios
Ratios de contraste verificados:
#E8E8E8sobre#000000= 17.4:1 (supera AAA)#CCFF00sobre#000000= 14.4:1 (supera AAA)#999999sobre#000000= 5.8:1 (supera AA)#666666sobre#000000= 3.7:1 (solo para texto decorativo/terciario, no para contenido esencial)
La jerarquia visual se comunica exclusivamente a traves de cambios de fondo (background-shift). Sin bordes decorativos visibles en cards. Sin sombras.
Nivel 0: --color-bg (#000000) → Fondo de pagina
Nivel 1: --color-surface (#0A0A0A) → Sidebar, secciones principales
Nivel 2: --color-surface-elevated (#141414) → Cards, contenedores, modales
Hover: --color-surface-hover (#1A1A1A) → Superficies interactivas al pasar el cursor
Los anillos de foco usan un outline solido con --color-accent. Sin sombra glow, sin resplandor.
:focus-visible {
outline: 2px solid var(--color-accent);
outline-offset: 2px;
}Los siguientes tokens de sombra han sido eliminados del sistema de diseno:
--shadow-sm(eliminado)--shadow-md(eliminado)--shadow-lg(eliminado)--shadow-glow(eliminado)
La profundidad se comunica unicamente a traves de la diferencia de luminosidad entre niveles de fondo. Cada nivel es ligeramente mas claro que el anterior, creando una jerarquia visual sutil y elegante.
El sistema usa dos familias complementarias:
--font-sans: 'Satoshi', system-ui, -apple-system, sans-serif
--font-mono: 'IBM Plex Mono', 'Fira Code', monospace
- Satoshi — Sans-serif geometrica para titulos, cuerpo de texto y etiquetas. Reemplaza DM Sans. Se carga via
next/font(local o Google Fonts). - IBM Plex Mono — Monoespaciada para TODOS los numeros financieros en toda la app: tablas, listas, cards, inputs, KPIs, badges. Reemplaza JetBrains Mono. Se carga via
next/font/googleonext/font/local.
| Nivel | Tamano | Fuente | Peso | Uso |
|---|---|---|---|---|
| Display | 36px / 40px | Satoshi Bold | 700 | Numeros hero en KPIs, totales del dashboard. Maximo 1-2 por pagina. |
| Heading | 20px / 28px | Satoshi Semibold | 600 | Titulos de pagina, headers de seccion, titulos de cards. |
| Body | 14px / 20px | Satoshi Regular/Medium | 400 o 500 | Texto principal, descripciones, contenido de tablas. |
| Label | 12px / 16px | Satoshi Medium | 500 | Etiquetas de formulario, headers de columnas, categorias de metadata. Uppercase, letter-spacing +2px, --color-text-secondary. |
| Meta | 11px / 14px | Satoshi Regular | 400 | Timestamps, IDs, informacion auxiliar. --color-text-tertiary. |
Todos los numeros financieros usan IBM Plex Mono con las siguientes reglas:
- Peso: 600 (Semibold) o 700 (Bold) segun contexto
- Alineacion: Siempre
font-variant-numeric: tabular-numspara alineacion en columnas - Signo de peso: El "$" se muestra a un tamano menor y en
--color-text-tertiary(silenciado). En un monto Display de 36px, el "$" se renderiza a ~24px y silenciado - Colores segun contexto:
- Montos positivos:
--color-positive - Montos negativos:
--color-negative - Montos neutros:
--color-text-primary(#E8E8E8)
- Montos positivos:
Las etiquetas, headers de columna y subtitulos de seccion siguen un estilo consistente:
text-transform: uppercase
letter-spacing: +2px (equivalente a tracking-widest)
Nivel: Label (12px) o Meta (11px)
Color: --color-text-secondary o --color-text-tertiary
Se usa para: etiquetas de formulario, headers de columna en tablas, subtitulos de seccion, texto de badges.
- Las etiquetas y descripciones siempre tienen menos peso visual que el valor que describen
- No usar ALL CAPS en texto de cuerpo — solo para el nivel Label/metadata (maximo 3 palabras)
- Line-height minimo de 1.4 para bloques de texto legible
- Nunca mezclar Satoshi y IBM Plex Mono en la misma linea de texto (excepto cuando un monto aparece inline en una oracion)
Base de 4px con ajustes para la estetica Glyph Finance:
| Token | Valor | Uso |
|---|---|---|
| 1 | 4px | Espaciado inline minimo |
| 2 | 8px | Gap icono-a-texto, padding interno de badges |
| 3 | 12px | Gap entre elementos en listas compactas, gap de grid entre cards |
| 4 | 16px | Margenes de pagina (mobile), gap titulo de seccion a contenido |
| 5 | 20px | Padding interno de cards (estandar) |
| 6 | 24px | Padding interno de cards (generoso, para KPI cards), separacion de secciones dentro de cards |
| 8 | 32px | Separacion entre cards o secciones de pagina |
| Contexto | Valor |
|---|---|
| Cards: padding interno | 20px (estandar), 24px (KPI cards generosas) |
| Grid de cards: gap | 12px |
| Margenes de pagina | 16px (mobile), 24px (desktop) |
| Celdas de tabla | 12px vertical, 16px horizontal |
| Gap vertical en formularios | 14px |
| Padding de modales | 24px |
--radius-sm: 8px → Tags, elementos pequenos, contenedores de icono
--radius-md: 12px → Inputs, tooltips, contenedores medios
--radius-lg: 16px → Cards
--radius-xl: 24px → Modales
--radius-full: 9999px → Elementos circulares, badges tipo pill
Todos los radios han aumentado respecto al sistema anterior. Los botones usan --radius-full (9999px, capsulas completas), badges usan --radius-full (pill), inputs 12px, cards 16px (mas redondeadas), modales 24px (significativamente mas redondeadas). El efecto general es una interfaz moderna sin llegar a ser burbujeante.
Lucide React exclusivamente. No emojis, no SVGs custom, no icon fonts.
14px → Dentro de badges, acciones secundarias en tablas, chevrons
16px → Botones, inputs con icono, items de lista
18px → Navegacion sidebar, headers de card
20px → Headers de seccion
24px → KPI cards, estados vacios
32px → Estados vacios grandes (empty states)
Las categorias almacenan el nombre del icono como string en la BD. Crear un componente DynamicIcon que resuelva el icono de Lucide por nombre:
// Mapeo estatico para tree-shaking
import { Utensils, Zap, Clapperboard, Smartphone, Car, Package, Briefcase, Laptop } from 'lucide-react'
const iconMap: Record<string, LucideIcon> = {
utensils: Utensils,
zap: Zap,
clapperboard: Clapperboard,
smartphone: Smartphone,
car: Car,
package: Package,
briefcase: Briefcase,
laptop: Laptop,
}No usar import dinamico de toda la libreria — impacta el bundle size.
Los iconos de categoria se muestran dentro de un contenedor con border-radius que usa el color de la categoria al 12% de opacidad como fondo y el color solido para el icono:
Fondo: {categoryColor} al 12% opacidad
Icono: {categoryColor} (color solido)
Tamano contenedor: 36px x 36px (listas), 40px x 40px (cards)
Border-radius: 12px
Variantes:
| Variante | Fondo | Texto | Borde | Uso |
|---|---|---|---|---|
| Primary | --color-accent (#CCFF00) |
#000000 (negro puro) |
none | Accion principal (Guardar, Registrar) |
| Secondary | transparent |
--color-text-secondary |
1px --color-border-divider |
Accion secundaria (Cancelar, Filtrar) |
| Danger | --color-negative (#FF3333) |
#FFFFFF (blanco) |
none | Acciones destructivas (Eliminar) |
| Ghost | transparent |
--color-text-secondary |
none | Acciones terciarias, links en tablas |
| Toggle (active) | --color-accent (#CCFF00) |
#000000 (negro puro) |
none | Expense/Income toggle, periodo activo |
| Toggle (inactive) | transparent |
--color-text-secondary |
none | Toggle no seleccionado |
Tamanos:
| Tamano | Padding | Font Size | Min Height |
|---|---|---|---|
| sm | 6px 12px | 12px | 32px |
| md | 10px 18px | 14px | 40px |
| lg | 12px 24px | 16px | 48px |
Forma: Todos los botones usan border-radius: --radius-full (9999px) — forma capsule/pill verdadera, no rectangulo redondeado.
Interaccion: transition: all 200ms, font-weight 600, gap 6px icono-a-texto. Estado de presion: transform: scale(0.98) para sensacion de switch tactil. Focus: 2px --color-accent outline segun spec de focus ring.
Toggle pills: Variante nueva para selectores binarios o multi-opcion (Expense/Income, Week/Month/Year). Estado activo: fondo chartreuse con texto negro. Estado inactivo: ghost/transparente con texto secundario. Agrupar toggles en fila con gap de 4px.
Estilo: Underline-only para TODOS los inputs en todos los formularios. Solo borde inferior, sin caja/rectangulo completo.
Estructura:
- Fondo: transparente. Sin fill de
--color-surface. La linea se asienta directamente sobre la superficie donde esta el formulario. - Borde inferior: 1px
--color-border-divider(#222222) en estado default. - Texto:
--color-text-primary(#E8E8E8). Font-size 14px nivel Body. - Padding: 10px 0 (padding vertical, sin padding horizontal ya que no hay caja).
Floating labels:
- La label comienza como texto placeholder sobre la linea en
--color-text-tertiary. - En focus o cuando tiene contenido: la label flota hacia arriba sobre el input, transiciona a estilo Label (12px, uppercase, letter-spacing +2px,
--color-text-secondary). - Transicion: 200ms ease para la animacion de flotacion.
Estado focus:
- La linea inferior transiciona de
--color-border-dividera--color-accent(#CCFF00, chartreuse). - Transicion: 200ms ease.
- Focus ring: outline estandar de 2px
--color-accentsegun spec global de focus ring.
Estado error:
- Color de linea inferior:
--color-negative(#FF3333). - Mensaje de error debajo del input en nivel Meta (11px,
--color-negative).
Inputs de montos:
- Prefijo "$" mostrado en
--color-text-tertiarya un tamano ligeramente menor, posicionado al inicio de la linea. El prefijo es estatico (no flota). Digitos del monto en IBM Plex Mono.
Inputs de porcentaje:
- Sufijo "%" mostrado en
--color-text-tertiary, posicionado al final de la linea. Sufijo estatico.
Inputs de select/dropdown:
- Mismo estilo de underline. Icono chevron (16px,
--color-text-tertiary) al extremo derecho de la linea.
Superficie: --color-surface-elevated (#141414) sobre --color-bg (#000000). Sin bordes visibles, sin sombra. La elevacion se comunica unicamente por el contraste de fondo.
Border-radius: --radius-lg (16px).
Padding: 20px estandar, 24px para KPI/hero cards.
Cards interactivas: cursor-pointer, hover a --color-surface-hover.
Cards apiladas (stacked): Separador de 1px --color-border-divider (#222222) entre cards adyacentes para legibilidad de listas. Esta es una concesion pragmatica — la regla de "sin lineas" es aspiracional pero la legibilidad de listas requiere separadores sutiles.
Cards de scroll horizontal: Cards oscuras pequenas en fila para categorias — icono + nombre uppercase + monto monoespaciado. Fondo --color-surface-elevated, sin borde.
Hero/balance cards: Pueden incluir patron de textura dot-matrix como acento visual (detallado en Phase 14).
Desktop:
- Overlay:
rgba(0, 0, 0, 0.7)conbackdrop-filter: blur(4px) - Container:
--color-surface-elevated, sin borde decorativo, border-radius--radius-xl, padding 28px - Max-width: 480px para formularios, 640px para vistas amplias
- Max-height: 85vh con overflow-y auto
- Animacion de entrada: fade in + scale desde 0.95 (200ms ease-out)
- Boton de cerrar (X) siempre en la esquina superior derecha
Mobile (bottom sheet):
- Se desliza hacia arriba desde la parte inferior de la pantalla.
- Altura: 85% de la altura de pantalla (
85vh). - Overlay:
rgba(0, 0, 0, 0.7)conbackdrop-filter: blur(4px). - Container:
--color-surface-elevated, sin borde, border-radius--radius-xl(24px) solo en esquinas superiores (esquinas inferiores cuadradas, al ras del borde de pantalla). - Padding: 24px.
- Handle indicator: 4px de alto, 40px de ancho,
--color-border-dividercentrado en la parte superior con 12px de margen superior.
Header row:
- Fondo:
--color-bg(#000000). - Estilo de texto: nivel Label (12px, uppercase, letter-spacing +2px, font-weight 500).
- Color de texto:
--color-text-secondary.
Body rows:
- Sin fondos alternados entre filas. Todas las filas en la misma superficie.
- Borde inferior: 1px
--color-border-divider(#222222) como separador en cada fila. - Estado hover: fondo
--color-surface-hover(#1A1A1A).
Formato de celdas:
- Montos: alineados a la derecha,
font-variant-numeric: tabular-nums, IBM Plex Mono. - Texto: alineado a la izquierda, Satoshi.
- Padding: 12px vertical, 16px horizontal.
Variante compacta (para mobile o datos densos):
- Padding: 8px vertical, 12px horizontal.
- Font-size: 12px para celdas del body.
Forma: Pill-shaped, border-radius: --radius-full (9999px). Consistente con la forma pill de los botones.
Tamano:
- Padding: 2px 8px.
- Font-size: 11px, font-weight 600, uppercase.
Variantes semanticas (fondo sutil + texto solido):
| Variante | Fondo | Texto | Uso |
|---|---|---|---|
| Accent | --color-accent-subtle |
--color-accent |
Links "VER TODO", elementos destacados |
| Positive | --color-positive-subtle |
--color-positive |
Tags de ingreso, tendencia positiva |
| Negative | --color-negative-subtle |
--color-negative |
Tags de gasto, tendencia negativa |
| Warning | --color-warning-subtle |
--color-warning |
Alertas, presupuesto cerca del limite |
| Info | --color-info-subtle |
--color-info |
Informacion neutral, periodos |
| Neutral | rgba(232, 232, 232, 0.08) |
--color-text-secondary |
Categorias, etiquetas genericas |
Patron "VER TODO": Usar variante Accent con flecha derecha. Texto en chartreuse, uppercase, nivel Meta. Ejemplo: VER TODO -> como badge pill que actua como link.
Reemplaza TODAS las barras de progreso continuas/suaves en la app. Cada indicador de porcentaje (progreso de presupuesto, utilizacion de credito, avance de deuda) usa este estilo segmentado tipo battery-bar.
Estructura:
- Contenedor: Fondo a color semantico al 12% de opacidad. Altura: 6px (variante compacta) o 8px (variante detallada). Ancho completo del padre.
- Segmentos: Siempre exactamente 10 segmentos rectangulares. Cada segmento = 10% del total. 2px gaps entre segmentos. Los segmentos son rectangulos planos (sin border-radius).
- Direccion de llenado: Izquierda a derecha.
Sistema de colores semaforo (traffic-light):
Aplicado por segmento segun la posicion en el rango de llenado:
--color-accent(#CCFF00, chartreuse) para segmentos que representan < 80% de llenado--color-warning(#FF9100, naranja) para segmentos que representan 80-99% de llenado--color-negative(#FF3333, rojo) para segmentos que representan 100%+ de llenado
Comportamiento de overflow (100%+): Los 10 segmentos se llenan con --color-negative (rojo). Se muestra el exceso como texto a la derecha de la barra: "+15%" en --color-negative a nivel Meta (11px). Esto hace inmediatamente claro que el presupuesto/limite ha sido excedido sin necesidad de un indicador separado.
Ejemplos:
- 45% presupuesto gastado: 4 segmentos chartreuse llenos, 1 medio lleno chartreuse, 5 vacios
- 85% presupuesto gastado: 8 segmentos chartreuse, luego el 9no segmento en naranja (cruzando umbral del 80%), 1 vacio
- 110% sobre presupuesto: 10 segmentos en rojo + texto "+10%"
Nota: Los segmentos parcialmente llenos muestran ancho parcial dentro del espacio del segmento. El gap entre segmentos siempre se mantiene.
CSS conceptual del contenedor:
display: flex;
gap: 2px;
align-items: center;
background: {color-semantico al 12% opacidad};
padding: 2px;CSS conceptual de segmento individual:
flex: 1;
height: 100%;
background: {color basado en posicion en sistema semaforo};
border-radius: 0; /* rectangulos planos */
transition: background-color 300ms ease;Contenedor: Fondo --color-surface-elevated. Padding 20px. Border-radius --radius-lg.
Line/Area charts:
- Stroke width: 1.5px (reducido de 2px para sensacion minimal).
- Dot endpoints: puntos solidos de 4px en cada data point. Mismo color que el stroke de la linea.
- Area fill: gradiente desde color de stroke al 10-15% de opacidad en la parte superior a 0% en la inferior. Sutil, no dominante.
- No grid lines. Eliminar todas las referencias a CartesianGrid.
- Axis labels: minimos. X-axis muestra solo etiquetas de fecha de inicio y fin para series temporales. Sin etiquetas en Y-axis. Valores visibles solo en hover/tooltip.
- Axis ticks:
--color-text-tertiary, 11px, nivel Meta. - Axis lines: ocultas.
Bar charts:
- Barras rectangulares, sin border-radius (tops planos). Relleno geometrico limpio.
- Ancho de barra: mas delgado que default — aproximadamente 60% del espacio disponible para mostrar gaps entre barras.
- Sin outlines ni strokes en barras.
Donut charts:
- Anillo mas delgado (innerRadius ~70% de outerRadius) para sensacion minimal.
- Sin labels dentro del donut. Texto central para total/resumen si es necesario.
Estrategia de color:
- Graficas de serie unica:
--color-accent(#CCFF00, chartreuse). - Graficas multi-serie: usar colores de categoria de la paleta desaturada.
- Ingreso vs gasto:
--color-positivepara ingreso,--color-negativepara gasto.
Tooltips:
- Tooltip flotante estilo card. Fondo:
--color-surface-elevated. Sin borde (elevacion via background-shift). Border-radius:--radius-md. Font-size: 12px nivel Body. - Montos en tooltip usan IBM Plex Mono (display financiero monoespaciado).
Las seis firmas visuales que diferencian a Glyph Finance de cualquier tema oscuro generico. Inspiradas en la interfaz glyph de Nothing OS, la estetica de impresion dot-matrix y la precision de terminales financieras clasicas. Un desarrollador que lea esta seccion entiende los elementos de identidad sin necesidad de buscar en otras secciones del documento — cada firma incluye su especificacion completa o una referencia directa a donde esta documentada.
Textura sutil de puntos en cuadricula que se aplica como fondo en cards premium. Inspirada en papel de impresion dot-matrix y la estetica retro-futurista de Nothing OS.
Contextos de uso: Hero cards EXCLUSIVAMENTE — card de balance del dashboard y card de comparacion de analytics. NO se aplica a todas las cards elevadas, NO a headers de seccion. Es un indicador premium, no un patron universal.
Especificacion de cuadricula:
- Patron: cuadricula de 8x8 pixeles con puntos pequenos
- Color de punto:
--color-dot-matrix(#1E1E1E) al 40% de opacidad - Cobertura: superficie completa de la card como textura de fondo
- Efecto: "Un susurro, no un grito" — textura apenas visible que recompensa la inspeccion cercana
Implementacion CSS (listo para copiar):
Enfoque 1 — SVG background-image (preferido):
.dot-matrix-bg {
background-image: url("data:image/svg+xml,%3Csvg width='8' height='8' xmlns='http://www.w3.org/2000/svg'%3E%3Ccircle cx='4' cy='4' r='0.75' fill='%231E1E1E' fill-opacity='0.4'/%3E%3C/svg%3E");
background-repeat: repeat;
background-size: 8px 8px;
}Enfoque 2 — CSS radial-gradient (fallback):
.dot-matrix-bg {
background-image: radial-gradient(circle, rgba(30, 30, 30, 0.4) 0.75px, transparent 0.75px);
background-size: 8px 8px;
}Nota de composicion: La textura dot-matrix se superpone SOBRE el fondo --color-surface-elevated de la card. Aplicar via pseudo-elemento (::before con position: absolute; inset: 0; pointer-events: none) o como capa adicional de background para que no interfiera con el contenido de la card.
Barra de progreso segmentada con 10 segmentos rectangulares separados por gaps de 2px. Colores semaforo: chartreuse (--color-accent) por debajo del 80%, naranja (--color-warning) entre 80-99%, rojo (--color-negative) al 100% o mas. Indicador visual para progreso de presupuesto, utilizacion de credito y avance de pago de deuda.
Uso: Presupuestos, utilizacion de credito, progreso de pago de deudas.
Especificacion completa en Componentes Base > Progress Bars (Battery-Bar).
Todos los numeros financieros usan IBM Plex Mono (--font-mono) con signo de peso silenciado a menor tamano en --color-text-tertiary y digitos codificados por color segun direccion: positivos en --color-positive, negativos en --color-negative, neutros en --color-text-primary.
Regla de layout: Signo "$" alineado a la izquierda y silenciado en --color-text-tertiary. Digitos alineados a la derecha en --color-text-primary. Siempre font-variant-numeric: tabular-nums para alineacion en columnas.
Especificacion completa en Tipografia > Numeros Financieros.
Estetica de iconos inspirada en pixel-art 8x8 — simples, geometricos, instantaneamente reconocibles a tamanos pequenos. Los iconos deben sentirse como si pertenecieran a la interfaz glyph de Nothing Phone, no a una app generica.
Libreria: Lucide React (sin set de iconos custom). La estetica pixel-art se logra a traves de la seleccion de iconos y parametros de renderizado, no con una fuente custom.
Guia de seleccion de iconos:
- Preferir iconos geometricos y angulares sobre organicos/curvos
- Preferir variantes de trazo delgado (thin-stroke) sobre variantes llenas (filled)
- Preferir iconos con lineas rectas y angulos rectos cuando esten disponibles
- Ejemplos "on-brand" de Lucide:
Utensils(geometrico),Zap(angular),Briefcase(rectangular),Car(silueta simple) - Evitar: iconos con curvas excesivas, detalle ornamentado o formas organicas
Reglas de renderizado:
stroke-width: 1.5(mas delgado que el default de Lucide de 2, sensacion mas precisa)shape-rendering: crispEdgesen el elemento SVG para renderizado alineado a pixeles sin suavizado anti-aliasing- Color del icono: color de categoria (solido) de la paleta desaturada
Contenedor (ya especificado en Iconografia):
- Fondo: color de categoria al 12% de opacidad
- Tamano: 36x36px (listas), 40x40px (cards)
- Border-radius: 12px
- Referencia cruzada: especificacion de contenedor en Iconografia > Contenedores de Icono
Indicador LED pequeno que comunica estado "activo" o "en vivo" sin texto. Inspirado en los indicadores LED de la interfaz glyph de Nothing Phone.
Estrategia de colocacion:
- Indicador de periodo actual en el selector de periodo — un dot junto al periodo activo senala "este es el periodo en vivo"
- Item de navegacion activo en la barra de tabs inferior — un dot debajo del icono activo reemplaza etiquetas de texto
- KPI cards mostrando datos en tiempo real o actualizados recientemente — un dot cerca del valor senala frescura de datos
Usar con moderacion. Maximo 2-3 dots visibles en cualquier pantalla. El uso excesivo diluye la senal.
Especificacion visual:
- Tamano: 4px circulo solido
- Color:
--color-accent(#CCFF00, chartreuse) - Sin glow, sin sombra, sin ring — solo el dot (consistente con la filosofia de elevacion sin sombras)
Animacion: Pulso continuo sutil. El dot respira lentamente — nunca frenetico, nunca llamando la atencion. Comunica "vivo" no "urgente."
Implementacion CSS (listo para copiar):
@keyframes status-pulse {
0%, 100% {
opacity: 1;
transform: scale(1);
}
50% {
opacity: 0.5;
transform: scale(0.85);
}
}
.status-dot {
width: 4px;
height: 4px;
border-radius: 50%;
background-color: var(--color-accent);
animation: status-pulse 2.5s ease-in-out infinite;
}Duracion: Ciclo de 2.5s — lo suficientemente lento para sentirse calmo, lo suficientemente rapido para ser notado.
Efecto de revelacion por scanlines que hace que los datos aparezcan como si fueran renderizados por una impresora dot-matrix o un escaneo CRT. Se usa cuando datos nuevos aparecen en pantalla — KPIs actualizandose, graficas re-renderizandose, datos frescos de transacciones cargando.
Descripcion visual: El elemento se renderiza de arriba hacia abajo en scanlines horizontales. El contenido aparece en franjas horizontales delgadas de arriba hacia abajo, como si fuera impreso linea por linea. El efecto debe sentirse mecanico, preciso y retro — como un cabezal de impresora moviendose sobre el papel.
Contextos de activacion:
- Valores de KPI cards actualizandose despues de un refresh de datos
- Graficas re-renderizandose despues de un cambio de periodo
- Nueva transaccion apareciendo en una lista
- Carga inicial de pagina (primer pintado de componentes con muchos datos)
NO usar para: transiciones de navegacion, apertura/cierre de modales, interacciones de botones, estados hover.
Timing:
- Duracion: 400-600ms (default 500ms)
- Funcion de timing:
steps(12, end)— progresion escalonada para sensacion mecanica, NO easing suave - 12 pasos = 12 scanlines a traves de la altura del elemento
Implementacion CSS (listo para copiar):
Enfoque: CSS clip-path con animacion escalonada para revelar contenido en franjas horizontales.
@keyframes scanline-reveal {
0% {
clip-path: inset(0 0 100% 0);
}
100% {
clip-path: inset(0 0 0% 0);
}
}
.pixel-dissolve {
animation: scanline-reveal 500ms steps(12, end) forwards;
}
/* Variante para refresh de datos (elemento ya visible, re-trigger) */
.pixel-dissolve-refresh {
animation: none;
}
.pixel-dissolve-refresh.updating {
animation: scanline-reveal 500ms steps(12, end) forwards;
}Composabilidad: La animacion se aplica al elemento completo. Para KPI cards, aplicar al contenedor del valor. Para graficas, aplicar al wrapper de la grafica. Para items de lista, aplicar a elementos individuales de fila.
Movimiento reducido: Respetar prefers-reduced-motion. Cuando se prefiere movimiento reducido, omitir la animacion completamente — el contenido aparece inmediatamente.
@media (prefers-reduced-motion: reduce) {
.pixel-dissolve,
.pixel-dissolve-refresh.updating {
animation: none;
clip-path: none;
}
}$1,234.56 → Monto estandar
-$1,234.56 → Monto negativo (prefijo -, en rojo)
+$1,234.56 → Monto positivo explicito (prefijo +, en verde, solo en transacciones)
$0.00 → Zero, mostrar como "—" en tablas, "$0.00" en inputs
En KPI cards donde el espacio es limitado y el monto supera 6 digitos, abreviar:
$1,234,567.89 → $1.23M
$123,456.78 → $123.4K (solo si el espacio lo requiere)
Siempre mostrar el monto completo en tooltip al hacer hover.
20.5% → Formato estandar
0.0% → Zero
-5.2% → Negativo (en rojo)
1 abr → En listas de transacciones (dia + mes abreviado)
1 abr 2026 → En listas cuando hay transacciones de multiples anos
Abril 2026 → Titulos de periodo
01/04/2026 → Inputs de fecha
Tailwind v4 usa configuracion CSS-first via bloques @theme. Este bloque contiene todos los tokens del sistema de diseno Glyph Finance, listo para copiar en src/app/globals.css.
@theme {
/* Fondos */
--color-bg: #000000;
--color-surface: #0A0A0A;
--color-surface-elevated: #141414;
--color-surface-hover: #1A1A1A;
/* Bordes */
--color-border-divider: #222222;
/* Textura */
--color-dot-matrix: #1E1E1E;
/* Texto */
--color-text-primary: #E8E8E8;
--color-text-secondary: #999999;
--color-text-tertiary: #666666;
--color-text-disabled: #444444;
/* Acento */
--color-accent: #CCFF00;
--color-accent-hover: #B8E600;
--color-accent-subtle: rgba(204, 255, 0, 0.12);
/* Semanticos */
--color-positive: #00E676;
--color-positive-subtle: rgba(0, 230, 118, 0.12);
--color-negative: #FF3333;
--color-negative-subtle: rgba(255, 51, 51, 0.12);
--color-warning: #FF9100;
--color-warning-subtle: rgba(255, 145, 0, 0.12);
--color-info: #448AFF;
--color-info-subtle: rgba(68, 138, 255, 0.12);
/* Categorias (desaturadas) */
--color-cat-food: #C88A5A;
--color-cat-services: #7A9EC4;
--color-cat-entertainment: #9B89C4;
--color-cat-subscriptions: #C48AA3;
--color-cat-transport: #C4A84E;
--color-cat-other: #8A9099;
/* Tipografia */
--font-mono: 'IBM Plex Mono', 'Fira Code', monospace;
/* Radios */
--radius-sm: 8px;
--radius-md: 12px;
--radius-lg: 16px;
--radius-xl: 24px;
}@theme inline {
--font-sans: var(--font-satoshi);
}El bloque @theme inline es necesario para inyectar la variable CSS generada por next/font. Satoshi se carga via next/font/google o next/font/local en el layout raiz, lo que genera una variable CSS --font-satoshi. El @theme inline conecta esa variable con el token --font-sans de Tailwind.
Los siguientes estilos se aplican en globals.css fuera de los bloques @theme:
:focus-visible {
outline: 2px solid var(--color-accent, #CCFF00);
outline-offset: 2px;
border-radius: inherit;
}
body {
background-color: var(--color-bg);
color: var(--color-text-primary);
}- CSS-first: Este enfoque reemplaza el antiguo
tailwind.config.tscon JavaScript. En Tailwind v4, toda la configuracion vive en CSS. - Sin sombras en @theme: No existen tokens de sombra. La elevacion es puramente cambio de fondo (background-shift).
- Colores de categoria: Los valores hex son las versiones desaturadas. Para fondos de contenedores de icono, usar el color de categoria al 15% de opacidad en codigo de componente (e.g.,
rgba(200, 138, 90, 0.15)para Comida). - Fuente sans: Se define en
@theme inline(no en el bloque principal) porque depende de la variable CSS inyectada pornext/fonten runtime.