Sprint 0 completo del producto VMS-Sailor (Vessel Management System integrado para buques 30-40m). Brief de referencia en VMS_Sailor_v2_Parte_*.md (intacto). Core (vmssailor.core, 95.17% coverage, 99 tests verde): - ShipCoord: sistema naval x_pp/y_cl/z_bl frozen - Vessel, Deck, Bulkhead - Equipment, EquipmentModel, Sensor, EquipmentSpec - Tag, AlarmConfig, TagBinding, Scaling - CardInstance, Bus, Topology con validacion 21 puntos I/O AR-NMEA-IO-v1.0 - Alarm, PermissiveRule, Condition - Project agregado raiz con validacion cross-entity - Persistencia portable .vmsproj (SQLite) con roundtrip verificable Biblioteca curada seed (vmssailor.library): - systems_catalog.json completo (catalogo maestro Parte 1 sec 7) - 2 vessels: Sunseeker 76, Ferretti 850 - 2 motores: MTU 12V 2000 M96, Volvo D13-900 - 1 genset: Northern Lights M65C13 - yacht_motor_planeo.yaml (reglas heuristicas) - TODO marcado data_source=seed_estimate - requiere validacion datasheets Tools: - vms-validate-library: CLI valida biblioteca completa - vms-generate-test-project: CLI demo + verificacion roundtrip persistencia Design System + 8 mockups HTML estaticos: - docs/design_system.md (paleta Deep Ocean, gradientes, typography, motion) - docs/brand/ (logo + variantes SVG) - docs/mockups/splash, studio_main, runtime_overview, runtime_mimic_fuel (P&ID animado), runtime_alarms, runtime_trim (panel estrella con horizonte artificial), mobile_overview, mobile_trim - docs/mockups/index.html (galeria) Firmware (Sprint 12+ implementacion): - firmware/ar_nmea_io_v1/src/config/pinout.h con macros GPIO Decisiones autonomas documentadas en docs/decisions_sprint0.md. Stack: Python 3.11 + uv + Pydantic v2 + SQLite stdlib + hatchling + pytest 9 + ruff + mypy. Sin PySide6, FastAPI, Flutter ni firmware funcional (entran en sprints siguientes). Criterio de aceptacion Sprint 0: cumplido. - uv sync: OK - pytest: 99/99 verde - cov vmssailor.core: 95.17% (objetivo >=80%) - ruff: clean - vms-validate-library: OK - vms-generate-test-project: INTEGRIDAD OK Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
14 KiB
VMS-Sailor — Design System
Sistema visual completo del producto. Aplica a Studio (PySide6), Runtime cliente desktop (PySide6) y Mobile (Flutter). Los mockups HTML en
docs/mockups/son la referencia visual canónica para los sprints de UI (Sprint 1, 6, 11).
1. Filosofía visual
"Deep ocean meets technical precision."
VMS-Sailor opera 24/7 en cabinas de mando del puente y de la sala de máquinas. La identidad visual debe transmitir:
- Confianza profesional — esto no es un toy. Es un sistema crítico que mueve toneladas y combustible bajo presión.
- Calma de mar profundo — la paleta default es oscura para no fatigar al operador en turnos largos de noche.
- Claridad inequívoca — colores de alarma estandarizados (cerca de las prácticas IMO), tipografía técnica para valores.
- Personalidad — sin ser un producto enterprise gris. Detalles de marca (compás, casco, glow cyan) le dan alma de "navegante".
No es: ni industrial-feo (PLC años 90), ni consumer-juguete (apps fintech), ni nave-espacial fantasioso (sci-fi).
Sí es: Lufthansa cockpit ↔ Tesla Roadster cabin ↔ B&G Vulcan plotter.
2. Paleta — VMS Ocean
Modo oscuro (default)
| Token | Hex | Uso |
|---|---|---|
--c-abyss |
#04111F |
Background base del app, casi negro navy |
--c-midnight |
#0A1A2E |
Cards, paneles |
--c-steel |
#1A2B42 |
Bordes, divisores, hover background |
--c-iron |
#2C3E5C |
Bordes activos, foreground muted |
--c-fog |
#7C8B9F |
Texto secundario, iconos inactivos |
--c-sand |
#E6EAF0 |
Texto primario sobre dark |
--c-foam |
#F2F5F9 |
Texto alta jerarquía, headlines |
--c-cyan |
#00D9FF |
Accent primario — marca, links, actividad |
--c-cyan-deep |
#1B7FB5 |
Cyan profundo para gradientes |
--c-horizon |
#5BC0EB |
Accent secundario, gauges |
Estado / semántico
| Token | Hex | Uso |
|---|---|---|
--c-ok |
#00E08A |
Estados OK, valores en rango |
--c-info |
#5BC0EB |
Alarma INFO |
--c-warn |
#FFB020 |
Alarma LOW + WARNING (ámbar IMO) |
--c-high |
#FF8030 |
Alarma HIGH (naranja escalada) |
--c-emergency |
#FF3B47 |
Alarma EMERGENCY (rojo SOS) |
--c-emergency-deep |
#A11220 |
Reset emergencia hover/active |
Modo claro (alternativo "outdoor")
Sólo para uso bajo sol fuerte en cubierta. Mismos accent colors, fondos invertidos.
| Token | Hex | Uso |
|---|---|---|
--c-foam-light |
#FFFFFF |
Background base |
--c-sand-light |
#F2F5F9 |
Cards |
--c-iron-light |
#D1D8E0 |
Bordes |
--c-abyss-light |
#04111F |
Texto primario |
--c-fog-light |
#5A6B7F |
Texto secundario |
3. Gradientes
| Token | CSS | Uso |
|---|---|---|
--g-deep-sea |
linear-gradient(135deg, #04111F 0%, #0A1A2E 60%, #1A2B42 100%) |
Background app |
--g-horizon |
linear-gradient(180deg, #04111F 0%, #1B3E6E 60%, #3A6BA8 90%, #5BC0EB 100%) |
Hero, splash |
--g-cyan-glow |
radial-gradient(circle at 50% 50%, rgba(0,217,255,0.4) 0%, transparent 70%) |
Aura tras logo |
--g-glass |
linear-gradient(135deg, rgba(255,255,255,0.06), rgba(255,255,255,0.02)) |
Glassmorphism cards |
--g-glass-edge |
linear-gradient(135deg, rgba(255,255,255,0.18), rgba(255,255,255,0.02)) |
Borde 1px de glass |
--g-emergency |
linear-gradient(135deg, #FF3B47, #A11220) |
Botón emergency |
--g-cyan |
linear-gradient(135deg, #00D9FF 0%, #5BC0EB 50%, #1B7FB5 100%) |
Logo, accent fill |
4. Tipografía
Familia
| Rol | Familia | Fallback |
|---|---|---|
| Display (H1, splash, branding) | Space Grotesk | Inter, system-ui, sans-serif |
| UI / cuerpo | Inter | system-ui, -apple-system, "Segoe UI", Roboto, sans-serif |
| Valores numéricos / mono | JetBrains Mono | "Cascadia Mono", Consolas, "Courier New", monospace |
Escalas (modo dark, sobre --c-abyss)
| Token | Size | Line-height | Weight | Letter-spacing | Color |
|---|---|---|---|---|---|
--t-display-xl |
56px | 1.05 | 700 | -1.5px | --c-foam |
--t-display-lg |
40px | 1.1 | 700 | -1.0px | --c-foam |
--t-h1 |
32px | 1.2 | 600 | -0.5px | --c-foam |
--t-h2 |
24px | 1.25 | 600 | -0.3px | --c-foam |
--t-h3 |
18px | 1.35 | 600 | -0.2px | --c-sand |
--t-body-lg |
16px | 1.5 | 400 | 0 | --c-sand |
--t-body |
14px | 1.5 | 400 | 0 | --c-sand |
--t-caption |
12px | 1.4 | 500 | 0.4px | --c-fog |
--t-overline |
11px | 1.2 | 600 | 2.4px (uppercase) | --c-fog |
--t-value-xl |
48px | 1.0 | 600 | -1.5px | --c-foam (mono) |
--t-value-lg |
28px | 1.0 | 500 | -0.5px | --c-foam (mono) |
--t-value |
16px | 1.0 | 500 | 0 | --c-sand (mono) |
Tono y estilo del copy
- Español por defecto (regla de oro #13)
- Verbos en imperativo para botones: "Acuse recibo", "Reset emergencia"
- Sin exclamaciones. Esto es industrial, no Black Friday
- Valores con unidad SI siempre adyacente:
87.2 bar,1450 rpm - Timestamps en ISO local:
2026-05-17 03:42:18
5. Espaciado
Sistema base de 4px. Tokens:
| Token | px | Uso típico |
|---|---|---|
--s-0 |
0 | reset |
--s-1 |
4 | gap interno mínimo |
--s-2 |
8 | padding small |
--s-3 |
12 | gap cards |
--s-4 |
16 | padding default |
--s-5 |
24 | sección |
--s-6 |
32 | bloques |
--s-7 |
48 | hero |
--s-8 |
64 | grandes layouts |
--s-9 |
96 | splash |
6. Border-radius
| Token | px | Uso |
|---|---|---|
--r-1 |
4 | inputs, chips small |
--r-2 |
8 | botones default |
--r-3 |
12 | cards |
--r-4 |
16 | paneles grandes |
--r-5 |
24 | hero, modals |
--r-pill |
9999 | badges, switches |
7. Sombras y elevación
5 niveles de elevación + 2 efectos especiales:
| Token | CSS |
|---|---|
--e-1 |
0 1px 3px rgba(0,0,0,0.32) |
--e-2 |
0 4px 12px rgba(0,0,0,0.40) |
--e-3 |
0 8px 24px rgba(0,0,0,0.50) |
--e-4 |
0 16px 48px rgba(0,0,0,0.60) |
--e-5 (modal) |
0 32px 80px rgba(0,0,0,0.70) |
--glow-cyan |
0 0 24px rgba(0,217,255,0.45) |
--glow-warn |
0 0 24px rgba(255,176,32,0.45) |
--glow-emergency |
0 0 32px rgba(255,59,71,0.55) |
--inner-stroke |
inset 0 0 0 1px rgba(255,255,255,0.06) |
8. Glassmorphism
Para paneles superpuestos (notificaciones, dropdowns, modales sobre mímicos):
background: var(--g-glass);
border: 1px solid rgba(255,255,255,0.08);
backdrop-filter: blur(16px) saturate(1.4);
box-shadow: var(--e-3), var(--inner-stroke);
Uso prudente. No abusar — los mímicos críticos deben ser sólidos para lecturabilidad.
9. Iconografía
- Estilo: 2px stroke, esquinas redondeadas (1px radius), 24×24px canvas base
- Familia base: Lucide / Phosphor (libres). Custom para símbolos navales (válvulas ISO 14617, motor, bomba, intercambiador, etc.)
- Color:
currentColorpara que herede del contexto - Inactivos: opacity 0.5
10. Componentes clave
Botones
| Variante | Background | Border | Color | Sombra |
|---|---|---|---|---|
| Primary | --g-cyan |
none | #04111F |
--glow-cyan |
| Secondary | transparent | 1px solid --c-iron |
--c-sand |
none |
| Ghost | transparent | none | --c-cyan |
none |
| Danger | --g-emergency |
none | --c-foam |
--glow-emergency |
| Disabled | --c-steel |
none | --c-fog |
none |
Padding: 12px 20px default. Min-width 96px. Border-radius --r-2.
Cards / Paneles
background: var(--c-midnight);
border: 1px solid var(--c-steel);
border-radius: var(--r-3);
padding: var(--s-5);
box-shadow: var(--e-2);
Badges de prioridad de alarma
| Prioridad | Background | Color | Border |
|---|---|---|---|
| EMERGENCY | #FF3B47 |
#FFFFFF |
inset 0 0 0 1px #FF8090 |
| HIGH | #FF8030 |
#04111F |
inset 0 0 0 1px #FFA060 |
| LOW | #FFB020 |
#04111F |
inset 0 0 0 1px #FFCB60 |
| INFO | #5BC0EB |
#04111F |
inset 0 0 0 1px #8DDBF2 |
Forma pill (border-radius: --r-pill), uppercase, letter-spacing 0.5px,
padding 4px 10px.
Gauges (visión general)
- Bar gauge horizontal: ancho variable, alto 8-12px, fondo
--c-steel, fill con--g-cyano color de estado - Arc gauge: 220° arc, stroke 8px, valor central en
--t-value-xlmono - Donut: 100% completo, fill por segmentos con colores semánticos
Indicador Roll/Pitch (Trim panel)
- Pantalla negra circular con grilla de horizonte
- Línea de horizonte animada que rota según roll
- Marcas cada 5°, números cada 10°
- Bandas de color: -8°a +8° (
--c-ok), 8°-12° (--c-warn), 12°-18° (--c-high), >18° (--c-emergency) - Glow del color de estado activo
11. Motion principles
| Acción | Duration | Easing |
|---|---|---|
| Hover/focus | 120ms | cubic-bezier(0.4, 0, 0.2, 1) |
| Entrada de elemento | 240ms | cubic-bezier(0.0, 0, 0.2, 1) (ease-out) |
| Salida | 200ms | cubic-bezier(0.4, 0, 1, 1) (ease-in) |
| Modal | 280ms | cubic-bezier(0.4, 0, 0.2, 1) |
| Alarma crítica entry | 320ms | cubic-bezier(0.34, 1.56, 0.64, 1) (bounce sutil) |
| Roll/pitch indicator | live | damped, sin animation (refresh ≤100ms) |
| Pulse de alarma activa | 1200ms | ease-in-out infinite |
Sin animaciones decorativas en valores críticos. El RPM no "se anima" de 1200 a 1450 — salta. La animación introduce delay perceptivo.
12. Layout patterns
Studio shell (Sprint 1)
┌────────────────────────────────────────────────────────────┐
│ topbar: logo · proyecto activo · acciones │ 48px
├──────────┬─────────────────────────────────────┬───────────┤
│ sidebar │ │ inspector │
│ (sistemas)│ canvas central │ (props) │
│ 256px │ (silueta + mímico) │ 320px │
│ │ │ │
├──────────┴─────────────────────────────────────┴───────────┤
│ statusbar: cobertura tests · version · sprint │ 32px
└────────────────────────────────────────────────────────────┘
Runtime cliente (Sprint 6)
┌────────────────────────────────────────────────────────────┐
│ vessel name · status · alarms badge · authority · user │ 56px
├──────────┬─────────────────────────────────────────────────┤
│ system │ │
│ sidebar │ active view: overview | mimic | alarms | │
│ 240px │ trends | trim | logbook | audit │
│ │ │
├──────────┴─────────────────────────────────────────────────┤
│ ticker alarmas · hora · VPN status │ 32px
└────────────────────────────────────────────────────────────┘
Mobile (Sprint 11)
- Bottom tab nav: Overview · Mímicos · Alarmas · Trim · Más
- Top bar mínima con nombre del buque y alarma count
- Single-column layout, swipe gestures
13. Accesibilidad
- Contraste mínimo WCAG AA (4.5:1 texto, 3:1 large). El amber sobre navy lo cumple.
- Touch targets móviles: 44×44pt iOS / 48×48dp Android mínimo
- Estados de focus visibles: outline 2px
--c-cyan+ offset 2px - Color nunca como único indicador — siempre acompañado por ícono o texto
14. Don't list
- ❌ Sin "neon glow" excesivo — sólo en logo y elementos de marca
- ❌ Sin emojis en UI — son ambiguos visualmente para alarmas
- ❌ Sin animaciones decorativas en valores críticos
- ❌ Sin gradientes en texto pequeño (lecturabilidad pobre)
- ❌ Sin fuentes serif — no encaja con el carácter técnico
- ❌ Sin scrollbars custom invasivos — respetar plataforma
- ❌ Sin tooltips obligatorios para entender la UI — diseña explícito
15. Mockups de referencia
| Archivo | Descripción |
|---|---|
docs/mockups/splash.html |
Pantalla de bienvenida con logo + tagline |
docs/mockups/studio_main.html |
Studio (Sprint 1) — wizard + canvas |
docs/mockups/runtime_overview.html |
Dashboard del buque (Sprint 6) |
docs/mockups/runtime_mimic_fuel.html |
Mímico sistema combustible |
docs/mockups/runtime_alarms.html |
Panel de alarmas |
docs/mockups/runtime_trim.html |
Trim & Maniobra (panel destacado) |
docs/mockups/mobile_overview.html |
App móvil overview |
docs/mockups/mobile_trim.html |
App móvil trim |
Todos son HTML+CSS estáticos. Abrir directamente en navegador.
16. Brand assets (docs/brand/)
| Archivo | Uso |
|---|---|
logo.svg |
Horizontal completo (320×80), color |
logo-mark.svg |
Solo compass mark (96×96), color |
logo-mono.svg |
Horizontal monocromático (currentColor) |
favicon.svg |
Cuadrado 64×64 con fondo navy |
Versión 1.0 — Sprint 0. Cambios mayores requieren acuerdo explícito de Álvaro (es la base visual de todo el producto).