Files
alro65 deb04c9315 sprint-0: fundaciones VMS-Sailor
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>
2026-05-17 07:26:06 -04:00

370 lines
14 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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:
1. **Confianza profesional** — esto no es un toy. Es un sistema crítico
que mueve toneladas y combustible bajo presión.
2. **Calma de mar profundo** — la paleta default es oscura para no
fatigar al operador en turnos largos de noche.
3. **Claridad inequívoca** — colores de alarma estandarizados (cerca de
las prácticas IMO), tipografía técnica para valores.
4. **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):
```css
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**: `currentColor` para 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
```css
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-cyan` o color de estado
- Arc gauge: 220° arc, stroke 8px, valor central en `--t-value-xl` mono
- 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).