Files
AR-VMS-Seaman/docs/mockups/runtime_mimic_fuel.html
T
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

549 lines
25 KiB
HTML
Raw 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.
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>VMS-Sailor · Mímico Combustible</title>
<link rel="icon" type="image/svg+xml" href="../brand/favicon.svg">
<link rel="stylesheet" href="_tokens.css">
<style>
body { overflow: hidden; }
.rt {
display: grid;
grid-template-rows: 56px 1fr 32px;
grid-template-columns: 240px 1fr 320px;
grid-template-areas:
"topbar topbar topbar"
"sidebar canvas inspector"
"ticker ticker ticker";
height: 100vh;
}
.topbar {
grid-area: topbar;
display: flex; align-items: center; gap: var(--s-5);
padding: 0 var(--s-5);
background: var(--c-midnight);
border-bottom: 1px solid var(--c-steel);
}
.breadcrumb {
display: flex; align-items: center; gap: var(--s-3);
font-size: 13px;
color: var(--c-fog);
}
.breadcrumb img { height: 28px; }
.breadcrumb strong { color: var(--c-foam); font-family: var(--f-display); font-size: 16px; }
.breadcrumb .sep { opacity: 0.5; }
.breadcrumb .system { color: var(--c-cyan); font-weight: 600; }
.topbar .top-spacer { flex: 1; }
.topbar .actions { display: flex; gap: var(--s-2); align-items: center; }
.sidebar {
grid-area: sidebar;
background: var(--c-midnight);
border-right: 1px solid var(--c-steel);
padding: var(--s-4) 0;
overflow-y: auto;
}
.sb-title { font-size: 10px; font-weight: 700; letter-spacing: 2px;
color: var(--c-fog); text-transform: uppercase;
padding: var(--s-4) var(--s-4) var(--s-2); }
.nav-item {
display: flex; align-items: center; gap: var(--s-2);
padding: 10px 16px;
color: var(--c-sand); font-size: 13px;
cursor: pointer; transition: background 120ms;
}
.nav-item:hover { background: var(--c-steel); }
.nav-item.active {
background: linear-gradient(90deg, rgba(0,217,255,0.12), transparent);
color: var(--c-foam);
box-shadow: inset 2px 0 0 var(--c-cyan);
}
/* Canvas mimic */
.canvas {
grid-area: canvas;
position: relative;
background:
radial-gradient(circle at 30% 20%, rgba(0,217,255,0.04), transparent 60%),
var(--c-abyss);
overflow: hidden;
}
.canvas-bg-grid {
position: absolute; inset: 0;
background-image:
linear-gradient(rgba(91,192,235,0.04) 1px, transparent 1px),
linear-gradient(90deg, rgba(91,192,235,0.04) 1px, transparent 1px);
background-size: 24px 24px;
}
.mimic-header {
position: absolute;
top: var(--s-4); left: var(--s-5);
z-index: 3;
}
.mimic-header h2 {
margin: 0;
font-family: var(--f-display);
font-size: 26px;
font-weight: 600;
color: var(--c-foam);
}
.mimic-header .sub {
font-size: 12px;
color: var(--c-fog);
letter-spacing: 1px;
}
.canvas-actions {
position: absolute;
top: var(--s-4); right: var(--s-5);
display: flex; gap: var(--s-2);
z-index: 3;
}
.legend {
position: absolute;
bottom: var(--s-5); left: var(--s-5);
padding: var(--s-3) var(--s-4);
background: var(--g-glass);
border: 1px solid rgba(255,255,255,0.08);
backdrop-filter: blur(12px);
border-radius: var(--r-3);
display: flex; gap: var(--s-5);
font-size: 11px;
color: var(--c-fog);
z-index: 3;
}
.legend .swatch {
display: inline-block; width: 10px; height: 10px;
border-radius: 2px;
margin-right: 6px;
vertical-align: middle;
}
.mimic-svg {
position: absolute;
inset: 80px 0 60px 0;
width: 100%; height: calc(100% - 140px);
}
.inspector {
grid-area: inspector;
background: var(--c-midnight);
border-left: 1px solid var(--c-steel);
padding: var(--s-5);
overflow-y: auto;
}
.insp-tag {
font-family: var(--f-mono);
font-size: 14px;
color: var(--c-cyan);
font-weight: 600;
margin-bottom: 2px;
}
.insp-name {
font-family: var(--f-display);
font-size: 22px;
font-weight: 600;
color: var(--c-foam);
margin: 0 0 var(--s-3);
}
.insp-value {
font-family: var(--f-mono);
font-size: 56px;
font-weight: 600;
color: var(--c-foam);
letter-spacing: -2px;
line-height: 1;
}
.insp-value .unit { font-size: 18px; color: var(--c-fog); margin-left: 6px; font-weight: 400; }
.insp-trend {
margin-top: var(--s-3);
height: 60px;
width: 100%;
}
.insp-row {
display: grid;
grid-template-columns: 110px 1fr;
gap: var(--s-3);
padding: var(--s-2) 0;
font-size: 13px;
border-bottom: 1px solid var(--c-steel);
}
.insp-row:last-child { border-bottom: none; }
.insp-row .k { color: var(--c-fog); }
.insp-row .v { font-family: var(--f-mono); color: var(--c-foam); }
.alarm-section {
margin-top: var(--s-4);
padding: var(--s-3);
background: rgba(255,176,32,0.06);
border: 1px solid rgba(255,176,32,0.25);
border-radius: var(--r-2);
}
.alarm-section .ttl { font-size: 11px; letter-spacing: 1.5px; color: var(--c-warn); font-weight: 700; text-transform: uppercase; }
/* Flow animations */
@keyframes flowDash { to { stroke-dashoffset: -40; } }
.flow { stroke-dasharray: 8 8; animation: flowDash 1.6s linear infinite; }
.flow.fast { animation-duration: 0.8s; }
@keyframes pumpSpin { from { transform: rotate(0deg); } to { transform: rotate(360deg); } }
.pump-rotor { animation: pumpSpin 0.7s linear infinite; transform-origin: center; transform-box: fill-box; }
.ticker {
grid-area: ticker;
display: flex; align-items: center; gap: var(--s-5);
padding: 0 var(--s-5);
background: var(--c-midnight);
border-top: 1px solid var(--c-steel);
font-family: var(--f-mono);
font-size: 11px;
color: var(--c-fog);
}
.ticker .sep { color: var(--c-iron); }
.ticker .pulse {
width: 8px; height: 8px;
border-radius: 50%;
background: var(--c-ok);
box-shadow: 0 0 12px rgba(0,224,138,0.7);
animation: heartbeat 2s ease-in-out infinite;
}
@keyframes heartbeat {
0%, 100% { transform: scale(1); opacity: 1; }
50% { transform: scale(1.4); opacity: 0.6; }
}
.tk-spacer { flex: 1; }
.ic { width: 16px; height: 16px; stroke: currentColor; fill: none; stroke-width: 2; }
</style>
</head>
<body>
<div class="app-root rt">
<header class="topbar">
<div class="breadcrumb">
<img src="../brand/logo-mark.svg" alt="">
<strong>M/Y Aurora</strong>
<span class="sep">/</span>
<span>Mímicos</span>
<span class="sep">/</span>
<span class="system">Combustible</span>
</div>
<span class="top-spacer"></span>
<span class="chip"><span class="dot ok"></span> 6 tags · 4 OK · 1 watch · 0 alarmas</span>
<span class="chip">Autoridad: <strong style="color:var(--c-cyan);margin-left:4px;">MÁQUINAS</strong></span>
<div class="actions">
<button class="btn-icon" title="Pausa updates"><svg class="ic" viewBox="0 0 24 24"><rect x="6" y="4" width="4" height="16"/><rect x="14" y="4" width="4" height="16"/></svg></button>
<button class="btn btn-secondary">Trends</button>
</div>
</header>
<aside class="sidebar">
<div class="sb-title">Sistemas</div>
<div class="nav-item">⚙ Máquina principal</div>
<div class="nav-item">⚡ Generación</div>
<div class="nav-item active">⛽ Combustible</div>
<div class="nav-item">💧 Refrigeración FW</div>
<div class="nav-item">🌊 Refrigeración SW</div>
<div class="nav-item">🛁 Sentinas</div>
<div class="nav-item">💨 Aire arranque</div>
<div class="nav-item">🌬 HVAC</div>
<div class="nav-item">💡 Iluminación</div>
<div class="sb-title">Combustible</div>
<div class="nav-item">📋 Resumen sistema</div>
<div class="nav-item">🔄 Transferencia tanques</div>
<div class="nav-item">🧪 Calidad y filtros</div>
<div class="nav-item">📊 Consumo histórico</div>
</aside>
<main class="canvas">
<div class="canvas-bg-grid"></div>
<div class="mimic-header">
<h2>Sistema de combustible</h2>
<div class="sub">2 tanques estructurales · 2 motores principales · 1 genset · Diesel marino MDO</div>
</div>
<div class="canvas-actions">
<button class="btn-icon" title="Centrar"><svg class="ic" viewBox="0 0 24 24"><circle cx="12" cy="12" r="3"/><path d="M12 3v3M12 18v3M3 12h3M18 12h3"/></svg></button>
<button class="btn-icon" title="Imprimir P&ID"><svg class="ic" viewBox="0 0 24 24"><polyline points="6 9 6 2 18 2 18 9"/><path d="M6 18H4a2 2 0 0 1-2-2v-5a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2v5a2 2 0 0 1-2 2h-2"/><rect x="6" y="14" width="12" height="8"/></svg></button>
<button class="btn btn-secondary">Calidad de filtros</button>
</div>
<svg class="mimic-svg" viewBox="0 0 1100 680" preserveAspectRatio="xMidYMid meet" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient id="tank" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#0A1A2E"/>
<stop offset="100%" stop-color="#1A2B42"/>
</linearGradient>
<linearGradient id="fuelFill" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#1B7FB5"/>
<stop offset="100%" stop-color="#00D9FF"/>
</linearGradient>
<linearGradient id="fuelFill2" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#1B7FB5"/>
<stop offset="100%" stop-color="#00D9FF"/>
</linearGradient>
<radialGradient id="pumpGlow" cx="50%" cy="50%" r="50%">
<stop offset="0%" stop-color="rgba(0,217,255,0.5)"/>
<stop offset="100%" stop-color="transparent"/>
</radialGradient>
</defs>
<!-- ============ TITLE LABELS ============ -->
<g font-family="JetBrains Mono" font-size="10" fill="#7C8B9F" letter-spacing="1">
<text x="40" y="40">P&amp;ID · FUEL</text>
<text x="40" y="56">Rev 1.0 · Sprint 0</text>
</g>
<!-- ============ TANKS ============ -->
<!-- Tank 1 -->
<g transform="translate(80,140)">
<rect x="0" y="0" width="180" height="280" rx="10" fill="url(#tank)" stroke="#2C3E5C" stroke-width="2"/>
<rect x="6" y="68" width="168" height="206" rx="6" fill="url(#fuelFill)" opacity="0.85"/>
<rect x="6" y="64" width="168" height="8" fill="#00D9FF" opacity="0.4" filter="blur(2px)"/>
<text x="90" y="-12" text-anchor="middle" font-family="JetBrains Mono" font-size="13" font-weight="700" fill="#E6EAF0">TANK_FUEL_1</text>
<text x="90" y="320" text-anchor="middle" font-family="Inter" font-size="11" fill="#7C8B9F">Capacidad 3500 L</text>
<!-- Level meter on tank side -->
<line x1="-12" y1="0" x2="-12" y2="280" stroke="#7C8B9F" stroke-width="1"/>
<g font-family="JetBrains Mono" font-size="9" fill="#7C8B9F" text-anchor="end">
<line x1="-18" y1="0" x2="-12" y2="0"/><text x="-22" y="4">100%</text>
<line x1="-18" y1="70" x2="-12" y2="70"/><text x="-22" y="74">75%</text>
<line x1="-18" y1="140" x2="-12" y2="140"/><text x="-22" y="144">50%</text>
<line x1="-18" y1="210" x2="-12" y2="210"/><text x="-22" y="214">25%</text>
<line x1="-18" y1="280" x2="-12" y2="280"/><text x="-22" y="284">0%</text>
</g>
<!-- Level value -->
<g transform="translate(90,150)">
<rect x="-50" y="-26" width="100" height="52" rx="8" fill="rgba(4,17,31,0.85)" stroke="#00D9FF" stroke-width="1.5"/>
<text text-anchor="middle" y="0" font-family="JetBrains Mono" font-size="24" font-weight="700" fill="#F2F5F9">78%</text>
<text text-anchor="middle" y="18" font-family="Inter" font-size="10" fill="#7C8B9F">2,730 L</text>
</g>
</g>
<!-- Tank 2 -->
<g transform="translate(300,140)">
<rect x="0" y="0" width="180" height="280" rx="10" fill="url(#tank)" stroke="#2C3E5C" stroke-width="2"/>
<rect x="6" y="105" width="168" height="169" rx="6" fill="url(#fuelFill2)" opacity="0.85"/>
<rect x="6" y="101" width="168" height="8" fill="#00D9FF" opacity="0.4" filter="blur(2px)"/>
<text x="90" y="-12" text-anchor="middle" font-family="JetBrains Mono" font-size="13" font-weight="700" fill="#E6EAF0">TANK_FUEL_2</text>
<text x="90" y="320" text-anchor="middle" font-family="Inter" font-size="11" fill="#7C8B9F">Capacidad 3500 L</text>
<g transform="translate(90,170)">
<rect x="-50" y="-26" width="100" height="52" rx="8" fill="rgba(4,17,31,0.85)" stroke="#00D9FF" stroke-width="1.5"/>
<text text-anchor="middle" y="0" font-family="JetBrains Mono" font-size="24" font-weight="700" fill="#F2F5F9">64%</text>
<text text-anchor="middle" y="18" font-family="Inter" font-size="10" fill="#7C8B9F">2,240 L</text>
</g>
</g>
<!-- ============ PIPES from tanks ============ -->
<g stroke="#00D9FF" stroke-width="2.5" fill="none">
<!-- Tank 1 outlet to manifold -->
<path d="M 260 380 L 280 380 L 280 480 L 540 480" class="flow"/>
<!-- Tank 2 outlet to manifold -->
<path d="M 480 380 L 480 470 L 540 470" class="flow"/>
</g>
<!-- ============ VALVES ============ -->
<!-- Valve T1 outlet -->
<g transform="translate(260,380)">
<path d="M 0 -8 L 16 0 L 0 8 L -16 0 Z" fill="#00E08A" stroke="#04111F" stroke-width="1.5"/>
<line x1="0" y1="-10" x2="0" y2="-18" stroke="#7C8B9F" stroke-width="2"/>
<circle cx="0" cy="-22" r="4" fill="#00E08A"/>
<text x="0" y="22" text-anchor="middle" font-family="JetBrains Mono" font-size="9" fill="#7C8B9F">V_T1_OUT</text>
</g>
<!-- Valve T2 outlet -->
<g transform="translate(480,380)">
<path d="M 0 -8 L 16 0 L 0 8 L -16 0 Z" fill="#00E08A" stroke="#04111F" stroke-width="1.5"/>
<line x1="0" y1="-10" x2="0" y2="-18" stroke="#7C8B9F" stroke-width="2"/>
<circle cx="0" cy="-22" r="4" fill="#00E08A"/>
<text x="0" y="22" text-anchor="middle" font-family="JetBrains Mono" font-size="9" fill="#7C8B9F">V_T2_OUT</text>
</g>
<!-- ============ FILTER ============ -->
<g transform="translate(540,460)">
<rect x="0" y="0" width="50" height="40" rx="4" fill="#1A2B42" stroke="#00D9FF" stroke-width="2"/>
<line x1="0" y1="10" x2="50" y2="10" stroke="#7C8B9F"/>
<line x1="0" y1="20" x2="50" y2="20" stroke="#7C8B9F"/>
<line x1="0" y1="30" x2="50" y2="30" stroke="#7C8B9F"/>
<text x="25" y="55" text-anchor="middle" font-family="JetBrains Mono" font-size="9" fill="#7C8B9F">FILTER 30µm</text>
<text x="25" y="-6" text-anchor="middle" font-family="JetBrains Mono" font-size="8" fill="#00E08A">Δp 0.4 bar</text>
</g>
<!-- ============ MAIN PUMP ============ -->
<g transform="translate(660,480)">
<circle cx="0" cy="0" r="32" fill="url(#pumpGlow)" />
<circle cx="0" cy="0" r="24" fill="#1A2B42" stroke="#00D9FF" stroke-width="2.5"/>
<g class="pump-rotor">
<path d="M -16 0 L 16 0 M 0 -16 L 0 16" stroke="#00D9FF" stroke-width="3" stroke-linecap="round"/>
<circle r="4" fill="#00D9FF"/>
</g>
<text x="0" y="48" text-anchor="middle" font-family="JetBrains Mono" font-size="10" font-weight="700" fill="#F2F5F9">PUMP_MAIN</text>
<text x="0" y="62" text-anchor="middle" font-family="JetBrains Mono" font-size="9" fill="#00E08A">RUNNING · 2.8 bar</text>
</g>
<!-- Pipe pump to manifold up -->
<g stroke="#00D9FF" stroke-width="2.5" fill="none">
<path d="M 590 480 L 630 480" class="flow fast"/>
<path d="M 692 480 L 720 480 L 720 220" class="flow fast"/>
</g>
<!-- ============ MANIFOLD to engines (top) ============ -->
<g stroke="#00D9FF" stroke-width="2.5" fill="none">
<line x1="720" y1="220" x2="980" y2="220" class="flow"/>
<!-- Branch to ME_PORT -->
<line x1="780" y1="220" x2="780" y2="160" class="flow"/>
<!-- Branch to ME_STBD -->
<line x1="860" y1="220" x2="860" y2="160" class="flow"/>
<!-- Branch to GEN_1 -->
<line x1="940" y1="220" x2="940" y2="320" class="flow"/>
</g>
<!-- ============ ENGINES (consumers) ============ -->
<g transform="translate(720,80)">
<rect x="0" y="0" width="120" height="60" rx="8" fill="#0A1A2E" stroke="#00E08A" stroke-width="2"/>
<text x="60" y="22" text-anchor="middle" font-family="JetBrains Mono" font-size="13" font-weight="700" fill="#F2F5F9">ME_PORT</text>
<text x="60" y="40" text-anchor="middle" font-family="JetBrains Mono" font-size="10" fill="#00E08A">1,520 rpm · 62%</text>
<text x="60" y="54" text-anchor="middle" font-family="Inter" font-size="9" fill="#7C8B9F">Consumo 14.2 L/h</text>
</g>
<g transform="translate(800,80)">
<rect x="0" y="0" width="120" height="60" rx="8" fill="#0A1A2E" stroke="#00E08A" stroke-width="2"/>
<text x="60" y="22" text-anchor="middle" font-family="JetBrains Mono" font-size="13" font-weight="700" fill="#F2F5F9">ME_STBD</text>
<text x="60" y="40" text-anchor="middle" font-family="JetBrains Mono" font-size="10" fill="#00E08A">1,498 rpm · 58%</text>
<text x="60" y="54" text-anchor="middle" font-family="Inter" font-size="9" fill="#7C8B9F">Consumo 13.4 L/h</text>
</g>
<g transform="translate(880,340)">
<rect x="0" y="0" width="120" height="60" rx="8" fill="#0A1A2E" stroke="#FFB020" stroke-width="2"/>
<text x="60" y="22" text-anchor="middle" font-family="JetBrains Mono" font-size="13" font-weight="700" fill="#F2F5F9">GEN_1</text>
<text x="60" y="40" text-anchor="middle" font-family="JetBrains Mono" font-size="10" fill="#FFB020">1,800 rpm · 88%</text>
<text x="60" y="54" text-anchor="middle" font-family="Inter" font-size="9" fill="#7C8B9F">Consumo 16.3 L/h</text>
</g>
<!-- Engine box labels (inlet valves) -->
<g transform="translate(780,160)">
<circle r="6" fill="#00E08A" stroke="#04111F" stroke-width="1.5"/>
</g>
<g transform="translate(860,160)">
<circle r="6" fill="#00E08A" stroke="#04111F" stroke-width="1.5"/>
</g>
<g transform="translate(940,320)">
<circle r="6" fill="#00E08A" stroke="#04111F" stroke-width="1.5"/>
</g>
<!-- ============ DAY TANK ============ -->
<g transform="translate(560,320)">
<rect x="0" y="0" width="80" height="100" rx="6" fill="url(#tank)" stroke="#2C3E5C" stroke-width="2"/>
<rect x="4" y="36" width="72" height="62" rx="3" fill="url(#fuelFill)" opacity="0.85"/>
<rect x="4" y="34" width="72" height="6" fill="#00D9FF" opacity="0.4" filter="blur(1.5px)"/>
<text x="40" y="-8" text-anchor="middle" font-family="JetBrains Mono" font-size="11" font-weight="700" fill="#E6EAF0">DAY TANK</text>
<text x="40" y="118" text-anchor="middle" font-family="JetBrains Mono" font-size="11" fill="#F2F5F9">64%</text>
</g>
<!-- ============ RETURN LINE ============ -->
<g stroke="#5BC0EB" stroke-width="1.8" fill="none" stroke-dasharray="3 3" opacity="0.7">
<path d="M 720 110 L 1040 110 L 1040 510 L 280 510 L 280 410"/>
</g>
<text x="900" y="105" font-family="JetBrains Mono" font-size="9" fill="#5BC0EB">RETURN LINE</text>
<!-- ============ PRESSURE GAUGE ============ -->
<g transform="translate(660,420)">
<circle r="22" fill="#0A1A2E" stroke="#00D9FF" stroke-width="2"/>
<text text-anchor="middle" y="-4" font-family="JetBrains Mono" font-size="11" font-weight="700" fill="#F2F5F9">2.8</text>
<text text-anchor="middle" y="10" font-family="JetBrains Mono" font-size="9" fill="#7C8B9F">bar</text>
<path d="M 0 0 L 12 -8" stroke="#00D9FF" stroke-width="2" stroke-linecap="round"/>
</g>
<!-- ============ FUEL CONSUMPTION SUMMARY ============ -->
<g transform="translate(40,520)">
<rect x="0" y="0" width="280" height="120" rx="10" fill="rgba(4,17,31,0.7)" stroke="#1A2B42" stroke-width="1.5"/>
<text x="16" y="22" font-family="Inter" font-size="10" font-weight="700" fill="#7C8B9F" letter-spacing="1.5">CONSUMO TOTAL ÚLTIMA HORA</text>
<text x="16" y="64" font-family="JetBrains Mono" font-size="36" font-weight="700" fill="#F2F5F9">43.9 <tspan font-size="14" fill="#7C8B9F">L/h</tspan></text>
<line x1="16" y1="78" x2="264" y2="78" stroke="#1A2B42"/>
<g font-family="JetBrains Mono" font-size="10" fill="#7C8B9F">
<text x="16" y="98">ME_PORT 14.2</text>
<text x="100" y="98">ME_STBD 13.4</text>
<text x="186" y="98">GEN_1 16.3</text>
</g>
<text x="16" y="112" font-family="Inter" font-size="10" fill="#00E08A">Autonomía a régimen: 113 h</text>
</g>
<!-- Pulsing alarm marker (info) on filter pressure approaching limit -->
<g transform="translate(570,440)">
<circle r="12" fill="rgba(91,192,235,0.18)" stroke="#5BC0EB" stroke-width="1.5">
<animate attributeName="r" values="10;14;10" dur="2s" repeatCount="indefinite"/>
<animate attributeName="opacity" values="1;0.4;1" dur="2s" repeatCount="indefinite"/>
</circle>
<text text-anchor="middle" y="3" font-family="Inter" font-size="9" font-weight="700" fill="#5BC0EB">i</text>
</g>
</svg>
<div class="legend">
<span><span class="swatch" style="background: #00E08A;"></span> Válvula abierta</span>
<span><span class="swatch" style="background: #FF8030;"></span> Válvula cerrada</span>
<span><span class="swatch" style="background: #00D9FF;"></span> Flujo activo</span>
<span><span class="swatch" style="background: transparent; border: 1px dashed #5BC0EB;"></span> Retorno</span>
<span><span class="swatch" style="background: rgba(91,192,235,0.3); border: 1px solid #5BC0EB;"></span> Info / watch</span>
</div>
</main>
<aside class="inspector">
<div class="insp-tag">TANK_FUEL_1.LEVEL</div>
<h3 class="insp-name">Nivel tanque combustible 1</h3>
<div class="insp-value">78<span class="unit">%</span></div>
<svg class="insp-trend" viewBox="0 0 280 60" preserveAspectRatio="none">
<defs>
<linearGradient id="tArea" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="rgba(0,217,255,0.45)"/>
<stop offset="100%" stop-color="rgba(0,217,255,0)"/>
</linearGradient>
</defs>
<path d="M 0 30 L 30 28 L 60 33 L 90 26 L 120 24 L 150 22 L 180 19 L 210 14 L 240 13 L 280 12 L 280 60 L 0 60 Z" fill="url(#tArea)"/>
<path d="M 0 30 L 30 28 L 60 33 L 90 26 L 120 24 L 150 22 L 180 19 L 210 14 L 240 13 L 280 12" stroke="#00D9FF" stroke-width="2" fill="none"/>
<circle cx="280" cy="12" r="4" fill="#00D9FF"/>
</svg>
<div style="display: flex; justify-content: space-between; font-family: var(--f-mono); font-size: 10px; color: var(--c-fog); margin-top: 4px;">
<span>-6h</span><span>-3h</span><span>now</span>
</div>
<div style="margin-top: var(--s-5);">
<div class="insp-row"><span class="k">Volumen</span><span class="v">2,730 L</span></div>
<div class="insp-row"><span class="k">Capacidad</span><span class="v">3,500 L</span></div>
<div class="insp-row"><span class="k">Range normal</span><span class="v">10 100%</span></div>
<div class="insp-row"><span class="k">Calidad</span><span class="v" style="color:var(--c-ok)">GOOD</span></div>
<div class="insp-row"><span class="k">Última lectura</span><span class="v">42 ms</span></div>
<div class="insp-row"><span class="k">Protocolo</span><span class="v">MODBUS_RTU</span></div>
<div class="insp-row"><span class="k">Tarjeta</span><span class="v">card_004 / AI3</span></div>
<div class="insp-row"><span class="k">Filtro</span><span class="v">MOVING_AVG · 8</span></div>
<div class="insp-row"><span class="k">Historizando</span><span class="v" style="color:var(--c-ok)">SÍ · 1s</span></div>
</div>
<div class="alarm-section">
<div class="ttl">2 alarmas configuradas</div>
<div style="margin-top: 8px; font-size: 12px; font-family: var(--f-mono); color: var(--c-sand);">
<div>LOW &lt; 15% <span style="color:var(--c-warn)">LOW</span></div>
<div>LOW_LOW &lt; 5% <span style="color:var(--c-emergency)">EMERGENCY</span></div>
</div>
</div>
<div style="margin-top: var(--s-5);">
<button class="btn btn-secondary" style="width: 100%;">Abrir trend completo</button>
</div>
</aside>
<footer class="ticker">
<span class="pulse"></span>
<span>WebSocket LIVE</span>
<span class="sep">|</span>
<span>187 tags activos</span>
<span class="sep">|</span>
<span>2 alarmas</span>
<span class="tk-spacer"></span>
<span>v0.1.0.dev0 · Sprint 0</span>
</footer>
</div>
</body>
</html>