Las referencias.
El bar. Los productos contra los que este sistema se mide, con la contribución específica de cada uno.
Color.
Todos los colores se definen en OKLCH para uniformidad perceptual entre temas. El acento es un solo color — terracota — usado con disciplina: máximo tres elementos por viewport.
Modo claro
Modo oscuro
Los swatches de abajo aplican .theme-dark localmente, así puedes verlos en su valor oscuro sin cambiar el tema de la página.
Superficies y elevación.
El sistema de superficies es la identidad visual primaria. La profundidad viene del contraste entre --bg y --bg-raised, no de sombras.
Sombras (solo modo producto, superficies flotantes)
Tipografía.
Dos tipografías. Geist Sans para todo: UI, marketing, contenido. Geist Mono para numéricos, código y contenido técnico. La jerarquía se construye con peso, tamaño y tracking.
Tipo display
Escala de tipos
Pesos
Mono
Espaciado.
Unidad base de 4 píxeles. Los componentes referencian tokens nombrados, nunca valores crudos. Las superficies de producto premium son más densas que las editoriales — el whitespace es para momentos.
Radios.
Cinco valores. No hay --radius-none — todo en este sistema tiene al menos un radio sutil. Ángulos rectos leen utilitario.
Movimiento.
Snap-tight. Linear es la referencia. Cada interacción se completa antes de que termines de pensarla.
| Duración | Valor |
|---|---|
| --dur-instant | 60ms |
| --dur-quick | 100ms |
| --dur-base | 180ms |
| --dur-snap | 240ms |
| --dur-smooth | 400ms |
| --dur-ambient | 800ms |
Microinteracciones.
Los detalles que separan «bien diseñado» de «se siente premium». Focus rings, selección, scrollbars, skeletons.
Selecciona este texto. El color del fondo usa --accent-pale y el ink usa --accent.
Scroll dentro de esta caja para ver el scrollbar custom — fino, color --rule, redondeado.
Línea de relleno · 1
Línea de relleno · 2
Línea de relleno · 3
Línea de relleno · 4
Línea de relleno · 5
Línea de relleno · 6
Final de la caja.
Iconografía.
Lucide a 1.5px de stroke. 20px standalone es el default; 16px y 24px para inline y prominent. Color heredado, nunca como única señal de interacción.
Componentes.
Marcados como Implementado cuando viven en el código que renderiza esta página, o como Boceto cuando solo está documentado su contrato visual.
Foundation
Button
ImplementadoPrimary, secondary, ghost, destructive. Tamaños xs / sm / md / lg.
IconButton
ImplementadoBotón icon-only con aria-label requerido. Tamaños xs / sm / md.
Input + Label
ImplementadoBorder completo, focus shifts to --accent, focus ring aparece.
Badge
ImplementadoPill con tracking ancho. Variantes neutral, accent, success, warning, danger.
Sheet · Dialog
ImplementadoBottom-sheet en móvil, modal centrado en desktop. Backdrop con blur. Usa la primitiva Dialog de @base-ui.
Toast · Menu
ImplementadoSuperficies flotantes con --bg-overlay, --shadow-md, microinteractions cuidadas. ToastProvider cuelga del layout de Vera.
Switch · SegmentedControl
ImplementadoToggle binario y toggle 2–4 opciones. Usados en LocationEditor, BlockTimeSheet, ReminderTypeToggle.
Kbd
ImplementadoIndicador de tecla. Geist Mono, --bg-sunken, --rule border.
Producto · superficie de reserva
ServiceCard
ImplementadoNombre, duración · precio, descripción, chevron afford. Hover lifts border to --rule-strong.
DateStrip · SlotList · BookingForm · ConfirmationCard
ImplementadoComponentes del flujo de reserva. Selected state invierte color al --accent. Conflict-checks contra el slot tomado en localStorage.
WhatsAppPreview
ImplementadoLa pieza central del portafolio. Marco de iPhone con notch, status bar, header verde de WhatsApp, burbuja con tail squareada y double-check azul.
WhatsAppDraftPreview
ImplementadoVariante en modo composición — sin burbuja entrante, composer editable abajo, botones para copiar o abrir en wa.me.
Producto · superficie de doctora
AppointmentRow
ImplementadoFila de cita expandible inline. Tiempo en mono accent, paciente, servicio, badge de duración. Expanded revela teléfono, email, nota, y acciones efímeras.
WeekCalendar
ImplementadoGrid de 7 columnas × medias horas. Booking blocks absolute-positioned con barra izquierda --accent. Bloqueados con hatch diagonal. Out-of-hours --bg-sunken.
AvailabilityGrid
ImplementadoEditor variant del calendario semanal — un botón por celda. Drag-to-paint con pointer-events unificados (mouse + touch). touch-action:none impide scroll de página durante el drag.
NextSlotPill
ImplementadoIndicador persistente: «Próxima disponibilidad jueves a las 11:00». Recomputa al hidratar incluyendo las reservas locales del visitante.
CommandPalette · Kbd
Implementado⌘K en cualquier ruta /panel/*. Filtro instantáneo, navegación con ↑↓, Enter ejecuta. Acciones: ir a hoy/semana/horarios, ver página pública, cambiar tema, limpiar datos.
Producto · onboarding
OnboardingShell · OnboardingProgress
ImplementadoWrapper de seis pasos. Wordmark + barra de progreso + bottom action bar fixed en móvil, static en desktop. Sheet de confirmación al intentar salir.
FloatingLabelInput · SpecialtyAutocombobox · SlugPreview
ImplementadoInputs estilo Stripe / Material 3 — la label flota arriba al focus o cuando hay valor. Slug se autogenera del nombre con un check de disponible debounced 400 ms.
EmbeddedProfilePreview
Implementadoiframe con el perfil público real, dentro de un marco con fade gradient abajo. Cierra el círculo del onboarding mostrando lo que la doctora acaba de configurar.
Marketing & meta
MarketingHero · FeatureBlock
ImplementadoCompuestos de marketing. Densidad comfortable, hero scale clamp(48–80px).
ModePicker
Implementado«Como paciente / Como doctora» — dos cards lado a lado en desktop, apiladas en móvil.
ThemeToggle
ImplementadoCiclo light → dark → auto. Persiste a localStorage. Sin FOUC gracias al script inline.
Patrones.
Composiciones consistentes entre superficies.
Header de página
┌──────────────────────────────────────┐
│ Vera Sobre Sistema ☼ Reservar │ ← transparente arriba
└──────────────────────────────────────┘
↓ scroll > 40px
┌──────────────────────────────────────┐
│ Vera Sobre Sistema ☼ Reservar │ ← bg/0.8 + blur
└──────────────────────────────────────┘Sticky on scroll. Transparente arriba; aplica --bg/0.8 + backdrop-blur después de 40px. Border-bottom aparece simultáneamente.
Sheet / Modal
Móvil: Desktop: ┌────────────┐ ┌──────────────────┐ │ │ │ ┌──────┐ │ │ │ │ │ modal│ │ │ │ │ └──────┘ │ │ ━━━━━━━━━━ │ ← handle │ │ │ ▼ Sheet ▼ │ │ │ └────────────┘ └──────────────────┘
Móvil < 768px: bottom-sheet con drag handle, 90vh máx, drag-to-dismiss. Desktop ≥ 768px: modal centrado, max-w varía sm/md/lg.
Densidad
compact: --row-height-base: 40px · --field-height-base: 36px comfortable: --row-height-base: 48px · --field-height-base: 44px
Compact por defecto en superficies de producto. .density-comfortable se aplica al hero del landing, al onboarding y a la pantalla de celebración.
Accesibilidad.
Baseline no negociable. Verificado independientemente para ambos temas.
- Focus rings visibles en todos los elementos interactivos
- Contraste mínimo AA contra la superficie correspondiente; AAA para --ink sobre --bg
- Tap targets mínimo 44×44px en touch
- HTML semántico — <button>, <nav>, <main>
- Skip-to-content link en todas las plantillas de página
- Las etiquetas de formulario nunca se reemplazan por placeholders solos
- aria-label en todos los botones icon-only
- aria-live="polite" en regiones de toast
- Focus trap en sheets, dialogs, drawers — retorna foco al trigger al desmontar
- ESC cierra todos los overlays
- prefers-reduced-motion respetado en todo el sistema
- El color nunca es la única señal — siempre acompañado de texto o icono
- Ambos temas cumplen mínimos de contraste de manera independiente
Lo que el sistema no es.
La lista corta de elecciones que romperían el sistema. Cada vez que el producto crece, la primera pregunta es: ¿estamos a punto de hacer una de estas?
- 01No introducir tipografías adicionales — dos es el techo.
- 02No agregar gradientes — los productos premium los ganan, no los toman.
- 03No usar iconos sin etiqueta en flujos de producto.
- 04No usar serif en cualquier lugar del producto.
- 05No usar itálica en display — lee editorial.
- 06No introducir azul, verde o morado como colores primarios.
- 07No usar emoji en copy de producto.
- 08No replicar componentes de davhera.com — construir fresco dentro del scope.
- 09No usar negro puro o blanco puro (excepto --bg-raised en modo claro).
- 10No shipear solo modo claro — ambos son de primera clase.
- 11No usar sombras en cards en modo claro — el contraste de superficie es suficiente.
- 12No usar ease-in-out del navegador — usa los easings nombrados.
- 13No escribir copy de marketing en estilo ensayo.
- 14No agregar overlays de grano, drop caps, pull quotes — toda decoración editorial.