Sistema de diseño · Higinio Sosa
Celeste Clásica
Sistema de marca light-first, sereno y confiable, para todos los productos de software de Higinio Sosa: web apps, dashboards, landing pages y móvil. La elegancia viene del orden y el aire, no de la decoración.
Claridad primero
El contenido siempre por encima de la decoración.
Calma visual
Superficies claras, whitespace generoso, contraste solo donde importa.
Un acento a la vez
El azul acero guía la acción; nunca compite consigo mismo.
Consistencia sobre novedad
Mismos tokens en todos los productos; cero valores mágicos.
Movimiento con propósito
La animación explica — aparece, cambia, desaparece — nunca decora sola.
Regla de oro
Los componentes consumen solo tokens semánticos (--surface, --accent, --link…), nunca hex directos. El cambio de tema es un atributo, no un refactor.
Fundamentos
Voz y contenido
Una consultora seria pero cálida — "banca privada boutique", no "startup ruidosa".
| Regla | Sí | No |
|---|---|---|
| Idioma: español LatAm neutro, de "tú" | Guarda tus cambios | Guarde usted los cambios |
| Sentence case en todo | Eliminar cuenta | Eliminar Cuenta / ELIMINAR |
| Botones imperativos de 1–3 palabras | Guardar | Guardando los cambios ahora |
| Errores accionables | El correo no tiene un formato válido. Revísalo. | Error |
| Sin exclamaciones ni emoji | Cuenta creada | ¡Cuenta creada! 🎉 |
| Voz en segunda persona | Tus proyectos | Nuestros proyectos para ti |
Fundamentos
Colores
Un solo acento — azul acero #7192ba — sobre neutrales grisáceo-azulados derivados de la tinta #31343e. Haz clic en cualquier muestra para copiar su variable.
Primario — Azul acero
Neutrales — Gris azulado
Semánticos — ramp de 3 tonos
Cada estado tiene el sólido (-500), el fondo suave (-100) y el tono de texto AA sobre ese fondo (-text).
Aliases semánticos
Los componentes consumen solo esta capa — así el theme switch es un cambio de atributo.
| Alias | Valor (light) | Rol |
|---|
Regla AA del acento
primary-500 sobre blanco da ~3:1 — válido solo para componentes UI (rellenos, bordes, focus). Para texto (links, botones ghost) usa --link = primary-700 (~6:1). primary-300 jamás como texto.
Proporción 60-30-10
Un solo botón primario visible por pantalla; el resto secundarios o ghost. Fondos siempre planos: sin gradientes, texturas ni patrones. El acento pierde poder si supera el 10 %.
Fundamentos
Tipografía
Tres familias con roles estrictos. Escala 1.25 (tercera mayor) desde 16 px.
Fraunces
Display 600–700 · solo h1–h2, cifras hero y marketing. Nunca UI ni párrafos.
Public Sans
Body/UI 400–600 · párrafos, botones, formularios, h3–h6. Todo lo demás.
IBM Plex Mono
Mono 400–500 · datos numéricos, código, IDs, montos en tablas.
Escala
Tracking: -0.02em en display ≥31px · 0 en body · +0.04em en labels uppercase. Longitud de línea máx. 65ch. Números en tablas con tabular-nums. Mínimo absoluto 12 px.
Fundamentos
Espaciado
Escala base 4 px — cero valores mágicos. El número del token = px ÷ 4.
Aliases de uso
| Alias | Valor | Uso |
|---|---|---|
| --card-padding | 24px | Padding de tarjetas (16px en móvil) |
| --section-gap | 64px | Separación entre secciones |
| --form-gap | 20px | Gap entre campos de formulario |
| --button-padding-md | 12px 20px | Botón md (sm: 8px 14px) |
| --control-height-* | 36 / 44 / 52 | Alturas de controles sm / md / lg |
| --gutter | 24px | Gutter del grid de 12 columnas (16px móvil) |
Fundamentos
Radios y sombras
Sombras frías teñidas con la tinta rgba(49,52,62,…), nunca negro puro. Máximo 3 niveles de elevación visibles por pantalla.
Radios
Sombras
Borde por defecto 1px solid var(--border). Focus ring global de teclado: 2px var(--primary-500) con offset 2px vía :focus-visible — el click de ratón no lo dispara. Único uso de transparencia: overlay de modal y ring de focus. No hay blur ni glassmorphism en Celeste Clásica.
Fundamentos
Iconografía
Set sustituto: Lucide — trazo 1.5–2 px, esquinas redondeadas, geométrico. Si existe un set propio de marca, reemplazar.
- Los iconos se insertan inline como SVG para heredar currentColor.
- Tamaños: 14 px inline con texto pequeño · 16–18 px inputs y chevrons · 20 px botones y toolbars · 40 px empty states (en primary-300 decorativo).
- Sin emoji; sin Unicode-como-icono (excepto el / tipográfico de breadcrumbs).
Biblioteca
Componentes
Los 25 componentes del sistema, renderizados en vivo con las clases del framework celeste-clasica.css. Cada bloque incluye su código de uso.
Botones
Alturas 36 / 44 / 52 px · radius md · peso 600 · un solo primario visible por pantalla. Ghost usa --link (AA), no primary-500.
Ver código
<button class="btn btn--primary">Guardar cambios</button>
<button class="btn btn--secondary">Cancelar</button>
<button class="btn btn--ghost">Ver detalles</button>
<button class="btn btn--danger">Eliminar cuenta</button>
<!-- Tamaños: btn--sm · (md por defecto) · btn--lg -->
<button class="btn btn--primary btn--lg">Grande</button>
IconButton
Botón cuadrado solo-icono para toolbars y chrome. Default ghost. Siempre con aria-label.
Ver código
<button class="icon-btn icon-btn--ghost" aria-label="Buscar">
<svg>…icono 18px…</svg>
</button>
<!-- Variantes: --ghost (default) · --secondary · --primary
Tamaños: --sm 32px · (md 40px) · --lg 48px -->
Spinner
Trazo 2.5, rotación 0.8 s linear. Si la carga dura <300 ms, no mostrar spinner. Blanco dentro de botones primarios.
Ver código
<svg class="spinner" viewBox="0 0 24 24" fill="none">
<circle cx="12" cy="12" r="9" stroke="currentColor" stroke-width="2.5"/>
<path d="M21 12a9 9 0 0 0-9-9" stroke="currentColor"
stroke-width="2.5" stroke-linecap="round"/>
</svg>
Input
Altura 44 px · label siempre visible (nunca placeholder como label) · focus con borde --accent + ring.
Ver código
<div class="field">
<label class="field__label" for="correo">Correo electrónico</label>
<input class="input" id="correo" type="email" placeholder="tu@correo.com">
<span class="field__help">Nunca compartiremos tu correo.</span>
</div>
<!-- Estados: input--error (+ .field__error) · input--success · disabled
Icono leading: envolver en .input-icon -->
Textarea
Min-height 96 px · resize: vertical · contador opcional alineado a la derecha.
Ver código
<div class="field">
<label class="field__label" for="desc">Descripción</label>
<textarea class="textarea" id="desc" maxlength="200"></textarea>
<span class="textarea-counter">0 / 200</span>
</div>
Select
Trigger igual que input + chevron 16 px que rota al abrir. Menú con shadow-lg y opción seleccionada en --accent-soft.
Ver código
<div class="select-wrap">
<select class="select">
<option>Ciudad de México (GMT-6)</option>
<option>Bogotá (GMT-5)</option>
</select>
</div>
SegmentedControl
2–4 opciones mutuamente excluyentes. Indicador blanco con shadow-xs. Para más de 4 opciones, usar Select.
Ver código
<div class="segmented" role="radiogroup" aria-label="Vista">
<input type="radio" name="vista" id="lista" checked><label for="lista">Lista</label>
<input type="radio" name="vista" id="tablero"><label for="tablero">Tablero</label>
</div>
<!-- Compacto: añadir segmented--sm -->
Slider
Track 6 px con porción rellena en --accent · thumb blanco 18 px con borde de acento que escala 1.15 al presionar.
Ver código
<div class="slider-row">
<span class="slider-label">Límite de gasto</span>
<span class="slider-value">$ 350</span>
</div>
<input class="slider" type="range" min="0" max="1000" value="350">
<!-- JS: actualizar --slider-fill = ((v-min)/(max-min))*100 + '%' -->
Checkbox y Radio
20 px · borde 2 px · check que se dibuja con ease-spring · label clicable con gap 10 px.
Ver código
<label class="checkbox">
<input type="checkbox" checked>
<span class="checkbox__box">
<svg viewBox="0 0 24 24"><path d="M20 6 9 17l-5-5"/></svg>
</span>
Recibir novedades
</label>
<label class="radio">
<input type="radio" name="plan" checked>
<span class="radio__dot"></span>
Plan mensual
</label>
Switch
Track 44×24 px · thumb 20 px que desliza 20 px en 200 ms ease-spring.
Ver código
<label class="switch">
<input type="checkbox" checked>
<span class="switch__track"></span>
Notificaciones
</label>
Badge y Tag
Fondo suave semántico (*-100) + texto --*-text (AA garantizado). Estado nunca solo con color: color + icono + texto.
Ver código
<span class="badge badge--success">
<svg>…icono…</svg>Activo
</span>
<!-- Tonos: (neutral) · --success · --warning · --danger · --info -->
<span class="tag">diseño
<button class="tag__close" aria-label="Quitar etiqueta">
<svg>…x…</svg>
</button>
</span>
Avatar
Fallback automático a iniciales sobre chip primary-100. Dot de presencia: 28 % del diámetro con anillo de superficie.
Ver código
<span class="avatar avatar--lg">
<span class="avatar__initials">HS</span>
<i class="avatar__dot avatar__dot--online"></i>
</span>
<!-- Tamaños: --sm 28 · (md 36) · --lg 48 · --xl 64
Presencia: --online · --busy · --away · (offline) -->
Divider
Regla hairline 1 px --border · variante con label centrado (patrón "o continúa con") · vertical para flex.
Ver código
<hr class="divider">
<div class="divider--label" role="separator">o continúa con</div>
<span class="divider--vertical" role="separator"></span>
Accordion
Altura animada con grid-template-rows 0fr→1fr (sin reflow) · chevron rota 180° · aria-expanded.
Ver código
<div class="accordion">
<div class="accordion__item is-open">
<button class="accordion__header" aria-expanded="true">
Pregunta <svg>…chevron…</svg>
</button>
<div class="accordion__panel"><div>
<div class="accordion__content">Respuesta</div>
</div></div>
</div>
</div>
<!-- JS: alternar .is-open en .accordion__item + aria-expanded -->
Tooltip
Delay 400 ms · fade + translateY(4→0) · máx. 1 línea; si necesita más, usar popover. Pasa el cursor por los botones.
Ver código
<button class="btn btn--secondary" data-tooltip="Duplica el proyecto">
Duplicar
</button>
<!-- Solo CSS: atributo data-tooltip. Fondo se invierte en dark. -->
Alert
Banner inline y persistente (vs Toast, transitorio). Icono *-500 + texto --*-text sobre fondo *-100. role="status".
Nueva versión disponible
La versión 2.4 incluye exportación a PDF. Actualiza cuando quieras.
Pago confirmado
El recibo se envió a tu correo.
Tu plan expira en 5 días
Renueva antes del 12 de julio para no perder acceso.
No se pudo guardar el formulario
Revisa los campos marcados en rojo e inténtalo de nuevo.
Ver código
<div class="alert alert--warning" role="status">
<svg>…icono…</svg>
<div>
<p class="alert__title">Tu plan expira en 5 días</p>
<p class="alert__body">Renueva antes del 12 de julio.</p>
</div>
<button class="alert__close" aria-label="Cerrar aviso">…x…</button>
</div>
<!-- Tonos: --info · --success · --warning · --danger -->
Toast
Top-right (desktop) · 360 px · borde izquierdo 3 px semántico · auto-dismiss 5 s pausable con hover · máx. 3 apilados.
Ver código
<div class="toast-stack">
<div class="toast toast--success">
<svg>…icono…</svg>
<div>
<p class="toast__title">Cambios guardados</p>
<p class="toast__body">El proyecto se actualizó.</p>
</div>
<button class="icon-btn icon-btn--ghost icon-btn--sm" aria-label="Cerrar">…x…</button>
</div>
</div>
Progress y ProgressRing
Solo progreso determinado — para carga indeterminada usar Skeleton. Width / dashoffset animan 250 ms.
Ver código
<div class="progress-row">
<span class="progress-label">Almacenamiento</span>
<span class="progress-value">68%</span>
</div>
<div class="progress">
<div class="progress__bar" style="width:68%"
role="progressbar" aria-valuenow="68"
aria-valuemin="0" aria-valuemax="100"></div>
</div>
<!-- Tonos de barra: (accent) · --success · --warning · --danger -->
Modal
Overlay --overlay · panel 480 px (confirmación) o 640 px (formulario) · fade + scale(0.96→1) · Esc y click en overlay cierran.
Ver código
<div class="modal" id="miModal" role="dialog" aria-modal="true" aria-labelledby="miModalTitulo">
<div class="modal__overlay" data-modal-close></div>
<div class="modal__panel">
<div class="modal__header">
<h4 class="modal__title" id="miModalTitulo">¿Eliminar proyecto?</h4>
<button class="icon-btn icon-btn--ghost" data-modal-close aria-label="Cerrar">…x…</button>
</div>
<p>Esta acción no se puede deshacer.</p>
<div class="modal__footer">
<button class="btn btn--secondary" data-modal-close>Cancelar</button>
<button class="btn btn--danger">Eliminar</button>
</div>
</div>
</div>
<!-- Panel ancho: modal__panel--lg (640px) -->
Tabla
Header uppercase +0.04em · filas 52 px · numéricos a la derecha con tabular-nums · seleccionada en --accent-soft.
Ver código
<table class="table">
<thead><tr><th>Cliente</th><th class="num">Monto</th></tr></thead>
<tbody>
<tr><td>Constructora Delta</td><td class="num">$ 48,200.00</td></tr>
<tr class="is-selected"><td>Grupo Andrade</td><td class="num">$ 9,850.00</td></tr>
</tbody>
</table>
Stat
KPI único, componer dentro de Card. Valor en mono text-3xl · delta con flecha en tonos --*-text · count-up al entrar en viewport.
Ver código
<div class="card">
<div class="stat">
<span class="stat__label"><svg>…</svg>Ingresos del mes</span>
<div class="stat__row">
<span class="stat__value">$ 128,400</span>
<span class="stat__delta stat__delta--up"><svg>…</svg>+12.4%</span>
</div>
</div>
</div>
<!-- Delta: --up (success-text) · --down (danger-text) · neutro (text-muted) -->
Pagination
1-indexado, bajo una tabla · trunca con elipsis a partir de 7 páginas · página activa como chip sólido con aria-current="page".
Ver código
<ul class="pagination" aria-label="Paginación">
<li><button class="pagination__btn" aria-label="Anterior">…‹…</button></li>
<li><button class="pagination__btn">1</button></li>
<li><span class="pagination__ellipsis">…</span></li>
<li><button class="pagination__btn is-active" aria-current="page">5</button></li>
<li><button class="pagination__btn">6</button></li>
<li><button class="pagination__btn" aria-label="Siguiente">…›…</button></li>
</ul>
Skeleton y EmptyState
Shimmer 1.4 s en loop, radius igual al contenido que reemplaza. Un estado vacío siempre invita a actuar.
Aún no tienes proyectos
Crea tu primer proyecto para empezar a organizar tu trabajo.
Ver código
<div class="skeleton" style="height:10px;width:85%"></div>
<div class="skeleton skeleton--circle" style="width:40px;height:40px"></div>
<div class="empty-state">
<svg>…icono 40px…</svg>
<p class="empty-state__title">Aún no tienes proyectos</p>
<p class="empty-state__desc">Crea tu primer proyecto para empezar.</p>
<button class="btn btn--primary">Crear proyecto</button>
</div>
Card, Link y Code
Tarjeta con padding 24 px y shadow-sm; la interactiva sube 2 px al hover. Link con subrayado que crece. Code inline en mono.
Tarjeta estática
Contenido en reposo con borde --border y shadow-sm.
Tarjeta interactiva
Pasa el cursor: sube 2 px con shadow-md. Consulta la guía de motion.
Ver código
<div class="card">…</div>
<div class="card card--interactive">…</div>
<a class="link" href="#">Enlace con subrayado animado</a>
<span class="code">--accent</span>
Sistema
Motion
Solo transform y opacity. La salida siempre ~20 % más corta que la entrada. Distancias de 4–8 px: nada "vuela" por la pantalla.
| Token | Valor | Uso |
|---|---|---|
| --duration-instant | 100ms | Press, toggle |
| --duration-fast | 150ms | Hover, focus, color |
| --duration-base | 200ms | Dropdowns, tooltips, switches |
| --duration-slow | 250ms | Modales, toasts |
| --duration-page | 320ms | Transiciones de página |
Easings (pasa el cursor)
- Stagger en listas: 30 ms por ítem, máximo 6 ítems.
- Si la carga dura <300 ms, no mostrar spinner (evita parpadeo).
- prefers-reduced-motion colapsa toda animación a 0.01 ms.
Sistema
Accesibilidad
WCAG AA mínimo: 4.5:1 texto normal, 3:1 texto grande y componentes UI. Touch targets de 44×44 px. Estado nunca comunicado solo con color.
| Combinación | Contraste | Veredicto |
|---|---|---|
| neutral-800 sobre blanco | ≈ 10.4:1 | AAA |
| Blanco sobre primary-500 | ≈ 3.4:1 | Solo texto ≥18px o UI |
| --link (primary-700) sobre blanco | ≈ 6:1 | AA texto normal |
| primary-300 sobre blanco | ≈ 1.8:1 | Nunca como texto |
| Tonos --*-text sobre *-100 | ≥ 4.5:1 | AA garantizado |
- Focus visible siempre: ring global de teclado vía :focus-visible con especificidad cero (:where()).
- IconButton siempre con aria-label · Progress con role="progressbar" · Alert con role="status" · Pagination con aria-current="page".
- Labels de formulario siempre visibles — el placeholder nunca sustituye al label.
Sistema
Tokens y descarga
El sistema completo vive en dist/celeste-clasica/: celeste-clasica.css (framework completo), tokens.css (solo variables), tailwind.css (@theme para Tailwind v4) y tokens.json (W3C DTCG 2025.10, interoperable con Figma / Tokens Studio / Style Dictionary).
Variables CSS
:root {
/* Primario */
--primary-50: #f2f6fa; --primary-100: #dfe9f2; --primary-200: #c3d5e6;
--primary-300: #a0c0d4; --primary-400: #87a8c7; --primary-500: #7192ba;
--primary-600: #5d7ba3; --primary-700: #4d6588; --primary-800: #40536e;
--primary-900: #31343e;
/* Neutrales */
--neutral-0: #ffffff; --neutral-50: #f7f8fa; --neutral-100: #eef0f3;
--neutral-200: #dcdfe5; --neutral-300: #b8bdc7; --neutral-400: #8a8f9c;
--neutral-500: #666b78; --neutral-600: #4d5160; --neutral-700: #3d414e;
--neutral-800: #31343e; --neutral-900: #22242b;
/* Semánticos (ramp de 3) */
--success-500: #3d9970; --success-100: #e2f3ec; --success-text: #2b6e50;
--warning-500: #c9922e; --warning-100: #faf1de; --warning-text: #8a651c;
--danger-500: #c04d4d; --danger-100: #f9e7e7; --danger-text: #8f3232;
--info-500: #7192ba; --info-100: #dfe9f2; --info-text: #4d6588;
/* Aliases (los componentes consumen SOLO esto) */
--bg: var(--neutral-50); --surface: var(--neutral-0); --surface-alt: var(--neutral-100);
--border: var(--neutral-200); --border-strong: var(--neutral-300);
--text-primary: var(--neutral-800); --text-secondary: var(--neutral-600);
--text-muted: var(--neutral-500); --text-disabled: var(--neutral-400);
--text-on-primary: #ffffff; --text-on-primary-solid: var(--primary-700);
--accent: var(--primary-500); --accent-hover: var(--primary-600);
--accent-active: var(--primary-700); --accent-soft: var(--primary-50);
--accent-soft-strong: var(--primary-100); --link: var(--primary-700);
/* Tipografía */
--font-display: "Fraunces", Georgia, serif;
--font-body: "Public Sans", system-ui, -apple-system, sans-serif;
--font-mono: "IBM Plex Mono", ui-monospace, monospace;
--text-xs: .75rem; --text-sm: .875rem; --text-base: 1rem; --text-lg: 1.125rem;
--text-xl: 1.25rem; --text-2xl: 1.5625rem; --text-3xl: 1.9375rem;
--text-4xl: 2.4375rem; --text-5xl: 3.0625rem;
--tracking-display: -0.02em; --tracking-label: 0.04em; --measure: 65ch;
/* Espaciado (base 4px) */
--space-1: 4px; --space-2: 8px; --space-3: 12px; --space-4: 16px;
--space-5: 20px; --space-6: 24px; --space-8: 32px; --space-10: 40px;
--space-12: 48px; --space-16: 64px; --space-20: 80px; --space-24: 96px;
--control-height-sm: 36px; --control-height-md: 44px; --control-height-lg: 52px;
/* Radios y sombras */
--radius-sm: 6px; --radius-md: 10px; --radius-lg: 14px;
--radius-xl: 20px; --radius-full: 9999px;
--shadow-xs: 0 1px 2px rgba(49,52,62,.06);
--shadow-sm: 0 1px 3px rgba(49,52,62,.08), 0 1px 2px rgba(49,52,62,.05);
--shadow-md: 0 4px 8px rgba(49,52,62,.09), 0 2px 4px rgba(49,52,62,.05);
--shadow-lg: 0 12px 24px rgba(49,52,62,.12), 0 4px 8px rgba(49,52,62,.06);
--shadow-xl: 0 24px 48px rgba(49,52,62,.16);
--ring: 0 0 0 3px rgba(113,146,186,.25);
/* Motion */
--duration-instant: 100ms; --duration-fast: 150ms; --duration-base: 200ms;
--duration-slow: 250ms; --duration-page: 320ms;
--ease-out: cubic-bezier(0.2, 0, 0, 1);
--ease-in: cubic-bezier(0.4, 0, 1, 1);
--ease-spring: cubic-bezier(0.34, 1.4, 0.64, 1);
}
Tailwind CSS v4 — bloque @theme
@import "tailwindcss";
@theme {
/* Colores → genera bg-primary-500, text-neutral-800, border-primary-200… */
--color-primary-50: #f2f6fa; --color-primary-100: #dfe9f2;
--color-primary-200: #c3d5e6; --color-primary-300: #a0c0d4;
--color-primary-400: #87a8c7; --color-primary-500: #7192ba;
--color-primary-600: #5d7ba3; --color-primary-700: #4d6588;
--color-primary-800: #40536e; --color-primary-900: #31343e;
--color-neutral-50: #f7f8fa; --color-neutral-100: #eef0f3;
--color-neutral-200: #dcdfe5; --color-neutral-300: #b8bdc7;
--color-neutral-400: #8a8f9c; --color-neutral-500: #666b78;
--color-neutral-600: #4d5160; --color-neutral-700: #3d414e;
--color-neutral-800: #31343e; --color-neutral-900: #22242b;
--color-success: #3d9970; --color-success-soft: #e2f3ec; --color-success-strong: #2b6e50;
--color-warning: #c9922e; --color-warning-soft: #faf1de; --color-warning-strong: #8a651c;
--color-danger: #c04d4d; --color-danger-soft: #f9e7e7; --color-danger-strong: #8f3232;
--color-info: #7192ba; --color-info-soft: #dfe9f2; --color-info-strong: #4d6588;
/* Tipografía → font-display, font-body, font-mono */
--font-display: "Fraunces", Georgia, serif;
--font-body: "Public Sans", system-ui, sans-serif;
--font-mono: "IBM Plex Mono", ui-monospace, monospace;
/* Radios → rounded-sm/md/lg/xl */
--radius-sm: 6px; --radius-md: 10px; --radius-lg: 14px; --radius-xl: 20px;
/* Sombras → shadow-xs…shadow-xl (teñidas de tinta) */
--shadow-xs: 0 1px 2px rgba(49,52,62,.06);
--shadow-sm: 0 1px 3px rgba(49,52,62,.08), 0 1px 2px rgba(49,52,62,.05);
--shadow-md: 0 4px 8px rgba(49,52,62,.09), 0 2px 4px rgba(49,52,62,.05);
--shadow-lg: 0 12px 24px rgba(49,52,62,.12), 0 4px 8px rgba(49,52,62,.06);
--shadow-xl: 0 24px 48px rgba(49,52,62,.16);
/* Easings → ease-out-cc, ease-in-cc, ease-spring */
--ease-out-cc: cubic-bezier(0.2, 0, 0, 1);
--ease-in-cc: cubic-bezier(0.4, 0, 1, 1);
--ease-spring: cubic-bezier(0.34, 1.4, 0.64, 1);
}
Cómo consumirlo en un proyecto nuevo
1) Copia dist/celeste-clasica/celeste-clasica.css (o solo tokens.css) e impórtalo antes de tus estilos, o pega el bloque @theme en tu CSS de Tailwind v4. 2) Aplica .celeste-reset al body. 3) Consume solo aliases semánticos. 4) Alterna data-theme en <html> para light/dark.