Files

780 lines
26 KiB
HTML
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.
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>VMS-Sailor Runtime · M/Y Aurora · Overview</title>
<link rel="icon" type="image/svg+xml" href="../brand/favicon.svg">
<link rel="stylesheet" href="_tokens.css">
<style>
body { overflow-x: hidden; }
.rt {
display: grid;
grid-template-rows: 64px 1fr 36px;
grid-template-columns: 240px 1fr;
grid-template-areas:
"topbar topbar"
"sidebar main"
"ticker ticker";
height: 100vh;
}
/* Topbar */
.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);
}
.vessel-id {
display: flex; align-items: center; gap: var(--s-3);
}
.vessel-id img { height: 32px; }
.vessel-id h1 {
margin: 0;
font-family: var(--f-display);
font-size: 18px;
font-weight: 600;
color: var(--c-foam);
line-height: 1;
}
.vessel-id .sub {
font-size: 11px;
color: var(--c-fog);
letter-spacing: 1.5px;
text-transform: uppercase;
}
.status-pill {
display: flex; align-items: center; gap: var(--s-2);
padding: 6px 14px;
background: rgba(0,224,138,0.12);
border: 1px solid rgba(0,224,138,0.4);
border-radius: var(--r-pill);
font-size: 12px;
font-weight: 600;
color: var(--c-ok);
letter-spacing: 0.5px;
}
.top-spacer { flex: 1; }
.top-meta {
display: flex; gap: var(--s-5); align-items: center;
font-family: var(--f-mono);
font-size: 12px;
color: var(--c-fog);
}
.top-meta strong { color: var(--c-sand); }
.alarm-chip {
display: flex; align-items: center; gap: var(--s-2);
padding: 6px 14px;
background: rgba(255,176,32,0.10);
border: 1px solid rgba(255,176,32,0.4);
border-radius: var(--r-pill);
font-size: 12px;
color: var(--c-warn);
font-weight: 700;
}
.user-chip {
display: flex; align-items: center; gap: var(--s-2);
padding: 6px 12px 6px 6px;
background: var(--c-steel);
border-radius: var(--r-pill);
font-size: 12px;
}
.avatar {
width: 26px; height: 26px;
border-radius: 50%;
background: var(--g-cyan);
color: #04111F;
display: flex; align-items: center; justify-content: center;
font-weight: 700;
font-size: 12px;
}
/* Sidebar */
.sidebar {
grid-area: sidebar;
background: var(--c-midnight);
border-right: 1px solid var(--c-steel);
overflow-y: auto;
padding: var(--s-4) 0;
}
.sb-section { padding: var(--s-4) var(--s-3); }
.sb-title {
font-size: 10px; font-weight: 700; letter-spacing: 2px;
color: var(--c-fog); text-transform: uppercase;
margin-bottom: var(--s-2); padding-left: var(--s-2);
}
.nav-item {
display: flex; align-items: center; gap: var(--s-3);
padding: 10px 12px;
border-radius: var(--r-2);
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);
}
.nav-item .ic { color: var(--c-fog); }
.nav-item.active .ic { color: var(--c-cyan); }
.nav-item .count {
margin-left: auto;
font-family: var(--f-mono);
font-size: 11px;
color: var(--c-fog);
}
.nav-item .alarm-badge {
margin-left: auto;
padding: 2px 8px;
background: var(--c-emergency);
color: white;
border-radius: var(--r-pill);
font-size: 10px;
font-weight: 700;
}
/* Main */
.main {
grid-area: main;
padding: var(--s-5);
overflow-y: auto;
background: var(--g-deep-sea);
}
.page-title {
display: flex; align-items: center; justify-content: space-between;
margin-bottom: var(--s-5);
}
.page-title h2 {
margin: 0;
font-family: var(--f-display);
font-size: 28px;
font-weight: 600;
color: var(--c-foam);
}
.page-title .sub {
color: var(--c-fog); font-size: 13px; margin-top: 4px;
}
.clock {
font-family: var(--f-mono);
font-size: 32px;
color: var(--c-foam);
letter-spacing: 1px;
text-align: right;
}
.clock .date {
font-size: 12px; color: var(--c-fog);
letter-spacing: 2px;
}
/* Grid de cards */
.grid {
display: grid;
grid-template-columns: repeat(12, 1fr);
gap: var(--s-5);
}
.col-3 { grid-column: span 3; }
.col-4 { grid-column: span 4; }
.col-6 { grid-column: span 6; }
.col-8 { grid-column: span 8; }
.col-12 { grid-column: span 12; }
.stat {
background: var(--c-midnight);
border: 1px solid var(--c-steel);
border-radius: var(--r-3);
padding: var(--s-5);
box-shadow: var(--e-2);
position: relative;
overflow: hidden;
}
.stat::before {
content: ""; position: absolute;
top: 0; left: 0; right: 0; height: 2px;
background: var(--c-iron);
}
.stat.accent-cyan::before { background: var(--g-cyan); }
.stat.accent-ok::before { background: var(--g-ok); }
.stat.accent-warn::before { background: var(--g-warn); }
.stat-header {
display: flex; justify-content: space-between; align-items: flex-start;
margin-bottom: var(--s-3);
}
.stat-label {
font-size: 11px; font-weight: 600; letter-spacing: 1.5px;
color: var(--c-fog); text-transform: uppercase;
}
.stat-value {
font-family: var(--f-mono);
font-size: 44px;
font-weight: 600;
color: var(--c-foam);
line-height: 1;
letter-spacing: -1px;
}
.stat-unit {
font-size: 16px;
color: var(--c-fog);
font-weight: 400;
margin-left: 4px;
}
.stat-trend {
display: flex; align-items: center; gap: 4px;
font-size: 12px;
font-family: var(--f-mono);
color: var(--c-fog);
margin-top: var(--s-2);
}
.stat-trend.up { color: var(--c-ok); }
.stat-trend.down { color: var(--c-warn); }
/* Engines card */
.engine-row {
display: grid;
grid-template-columns: 60px 1fr 110px;
gap: var(--s-4);
align-items: center;
padding: var(--s-3) 0;
border-bottom: 1px solid var(--c-steel);
}
.engine-row:last-child { border-bottom: none; }
.engine-label {
font-family: var(--f-mono);
font-size: 13px;
font-weight: 600;
color: var(--c-foam);
}
.engine-state {
display: inline-block;
padding: 2px 8px;
background: rgba(0,224,138,0.12);
color: var(--c-ok);
border-radius: var(--r-pill);
font-size: 10px;
font-weight: 700;
letter-spacing: 0.5px;
margin-top: 2px;
}
.gauge-bar {
position: relative;
height: 8px;
background: var(--c-steel);
border-radius: var(--r-pill);
overflow: hidden;
}
.gauge-fill {
position: absolute;
inset: 0 auto 0 0;
background: var(--g-cyan);
border-radius: var(--r-pill);
box-shadow: 0 0 12px rgba(0,217,255,0.4);
}
.gauge-fill.warn { background: var(--g-warn); box-shadow: 0 0 12px rgba(255,176,32,0.4); }
.engine-meta {
display: flex; gap: var(--s-3);
font-size: 11px;
color: var(--c-fog);
margin-top: 4px;
font-family: var(--f-mono);
}
.engine-meta strong { color: var(--c-sand); }
.engine-rpm {
font-family: var(--f-mono);
font-size: 22px;
font-weight: 600;
color: var(--c-foam);
text-align: right;
}
.engine-rpm small { color: var(--c-fog); font-size: 11px; display: block; font-weight: 400; }
/* Roll/pitch */
.horizon {
width: 100%;
aspect-ratio: 1;
max-width: 280px;
margin: 0 auto;
position: relative;
}
.horizon-readout {
display: flex; justify-content: space-around;
margin-top: var(--s-4);
font-family: var(--f-mono);
}
.ro-block { text-align: center; }
.ro-block .lbl { color: var(--c-fog); font-size: 10px; letter-spacing: 2px; text-transform: uppercase; }
.ro-block .val { font-size: 26px; color: var(--c-foam); font-weight: 600; }
/* Recent alarms list */
.alarm-row {
display: grid;
grid-template-columns: 90px 1fr auto;
gap: var(--s-3);
padding: var(--s-3);
border-radius: var(--r-2);
align-items: center;
transition: background 120ms;
cursor: pointer;
}
.alarm-row:hover { background: var(--c-steel); }
.alarm-time {
font-family: var(--f-mono);
font-size: 11px;
color: var(--c-fog);
}
.alarm-msg {
font-size: 13px;
color: var(--c-sand);
}
.alarm-msg strong { color: var(--c-foam); }
.alarm-msg .src {
font-family: var(--f-mono);
font-size: 11px;
color: var(--c-cyan);
margin-right: 6px;
}
/* Tanks */
.tank {
display: flex; flex-direction: column; align-items: center;
gap: var(--s-2);
}
.tank-shell {
position: relative;
width: 70px;
height: 120px;
border: 2px solid var(--c-iron);
border-radius: 8px 8px 4px 4px;
overflow: hidden;
background: var(--c-abyss);
}
.tank-fill {
position: absolute;
left: 0; right: 0; bottom: 0;
background: linear-gradient(180deg, #1B7FB5 0%, #00D9FF 100%);
}
/* Surface highlight per fill color via currentColor on the fill */
.tank-fill { color: rgba(0,217,255,0.55); }
.tank-fill.warn { background: linear-gradient(180deg, #C0760F 0%, #FFB020 100%); color: rgba(255,176,32,0.55); }
.tank-fill.water { background: linear-gradient(180deg, #007F4E 0%, #00E08A 100%); color: rgba(0,224,138,0.55); }
.tank-fill.black { background: linear-gradient(180deg, #5A6B7F 0%, #94A3B8 100%); color: rgba(148,162,177,0.55); }
.tank-fill::before {
content: ""; position: absolute;
top: 0; left: 0; right: 0; height: 4px;
background: currentColor;
box-shadow: 0 0 6px currentColor;
pointer-events: none;
}
.tank-label { font-family: var(--f-mono); font-size: 11px; color: var(--c-fog); }
.tank-pct {
font-family: var(--f-mono);
font-size: 16px;
color: var(--c-foam);
font-weight: 600;
}
.tank-row {
display: flex; gap: var(--s-5); justify-content: space-around;
align-items: flex-end;
}
/* Ticker */
.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-width: 2; stroke: currentColor; fill: none; }
</style>
</head>
<body>
<div class="app-root rt">
<header class="topbar">
<div class="vessel-id">
<img src="../brand/logo-mark.svg" alt="">
<div>
<h1>M/Y Aurora</h1>
<div class="sub">Sunseeker 76 · 23.4 m</div>
</div>
</div>
<span class="status-pill">
<span class="dot ok"></span> Normal · todo en rango
</span>
<span class="top-spacer"></span>
<span class="alarm-chip">
<svg class="ic" viewBox="0 0 24 24"><path d="M12 9v4M12 17h.01"/><path d="M10.29 3.86 1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z"/></svg>
2 alarmas activas
</span>
<span class="chip">
<span class="dot cyan"></span>
Autoridad: <strong style="color:var(--c-cyan)">PUENTE</strong>
</span>
<span class="user-chip">
<span class="avatar">A</span>
Álvaro · <span style="color:var(--c-fog)">Admin</span>
</span>
</header>
<aside class="sidebar">
<div class="sb-section">
<div class="sb-title">Vistas</div>
<div class="nav-item active">
<svg class="ic" viewBox="0 0 24 24"><rect x="3" y="3" width="7" height="7"/><rect x="14" y="3" width="7" height="7"/><rect x="14" y="14" width="7" height="7"/><rect x="3" y="14" width="7" height="7"/></svg>
Overview
</div>
<div class="nav-item">
<svg class="ic" viewBox="0 0 24 24"><circle cx="12" cy="12" r="9"/><path d="M12 3v18M3 12h18"/></svg>
Mímicos
</div>
<div class="nav-item">
<svg class="ic" viewBox="0 0 24 24"><path d="M10.29 3.86 1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z"/><path d="M12 9v4M12 17h.01"/></svg>
Alarmas
<span class="alarm-badge">2</span>
</div>
<div class="nav-item">
<svg class="ic" viewBox="0 0 24 24"><polyline points="3 17 9 11 13 15 21 7"/></svg>
Trends
</div>
<div class="nav-item">
<svg class="ic" viewBox="0 0 24 24"><circle cx="12" cy="12" r="9"/><polyline points="12 6 12 12 15 14"/></svg>
Log Book
</div>
<div class="nav-item">
<svg class="ic" viewBox="0 0 24 24"><path d="M6 3v18M18 3v18"/><circle cx="12" cy="12" r="3"/></svg>
Trim & Maniobra
</div>
</div>
<div class="sb-section">
<div class="sb-title">Sistemas</div>
<div class="nav-item"><svg class="ic" viewBox="0 0 24 24"><circle cx="12" cy="12" r="3"/><path d="M5 12h2M17 12h2M12 5v2M12 17v2"/></svg> Máquina principal</div>
<div class="nav-item"><svg class="ic" viewBox="0 0 24 24"><path d="M13 2L3 14h7v8l10-12h-7V2z"/></svg> Generación eléctrica</div>
<div class="nav-item"><svg class="ic" viewBox="0 0 24 24"><path d="M12 2v10l4 4M22 12a10 10 0 1 1-20 0 10 10 0 0 1 20 0z"/></svg> Combustible</div>
<div class="nav-item"><svg class="ic" viewBox="0 0 24 24"><path d="M6 8c0-4 6-6 6-6s6 2 6 6v3a6 6 0 0 1-12 0V8z"/></svg> Refrigeración</div>
<div class="nav-item"><svg class="ic" viewBox="0 0 24 24"><circle cx="12" cy="12" r="9"/><polyline points="12 6 12 12 8 14"/></svg> Sentinas</div>
<div class="nav-item"><svg class="ic" viewBox="0 0 24 24"><path d="M3 12h6l3-9 3 18 3-9h3"/></svg> HVAC</div>
<div class="nav-item"><svg class="ic" viewBox="0 0 24 24"><path d="M12 2v6M12 16v6M2 12h6M16 12h6M5 5l4 4M15 15l4 4M5 19l4-4M15 9l4-4"/></svg> Iluminación</div>
</div>
<div class="sb-section">
<div class="sb-title">Soporte</div>
<div class="nav-item">
<svg class="ic" viewBox="0 0 24 24"><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/></svg>
Auditoría VPN
</div>
</div>
</aside>
<main class="main">
<div class="page-title">
<div>
<h2>Estado general del buque</h2>
<div class="sub">Última actualización: hace 1.2 s · Sin desconexiones</div>
</div>
<div class="clock">
<div>03:42:18</div>
<div class="date">2026-05-17 · UTC-04</div>
</div>
</div>
<div class="grid">
<!-- 4 stats -->
<div class="stat col-3 accent-cyan">
<div class="stat-header">
<span class="stat-label">Combustible</span>
<span class="dot ok"></span>
</div>
<div class="stat-value">2,840<span class="stat-unit">L</span></div>
<div class="stat-trend down">▼ 18 L/h consumo medio</div>
</div>
<div class="stat col-3 accent-ok">
<div class="stat-header">
<span class="stat-label">Generación</span>
<span class="dot ok"></span>
</div>
<div class="stat-value">28.4<span class="stat-unit">kW</span></div>
<div class="stat-trend">GEN_1 · 55% carga</div>
</div>
<div class="stat col-3 accent-ok">
<div class="stat-header">
<span class="stat-label">Baterías</span>
<span class="dot ok"></span>
</div>
<div class="stat-value">27.8<span class="stat-unit">V</span></div>
<div class="stat-trend up">▲ Cargando 12 A</div>
</div>
<div class="stat col-3 accent-warn">
<div class="stat-header">
<span class="stat-label">Sentinas</span>
<span class="dot warn"></span>
</div>
<div class="stat-value">12<span class="stat-unit">%</span></div>
<div class="stat-trend down">BILGE_MID en watch</div>
</div>
<!-- Motores -->
<div class="card col-8">
<div class="stat-header">
<span class="stat-label">Máquina principal · 2× MTU 12V 2000 M96</span>
<a href="#" style="font-size:12px">Ver mímico →</a>
</div>
<div style="margin-top: var(--s-4);">
<div class="engine-row">
<div>
<div class="engine-label">ME_PORT</div>
<span class="engine-state">RUNNING</span>
</div>
<div>
<div class="gauge-bar"><div class="gauge-fill" style="width: 62%;"></div></div>
<div class="engine-meta">
<span>Aceite <strong>4.8 bar</strong></span>
<span>Coolant <strong>82°C</strong></span>
<span>Carga <strong>62%</strong></span>
<span>Horas <strong>1,284</strong></span>
</div>
</div>
<div class="engine-rpm">1,520 <small>rpm</small></div>
</div>
<div class="engine-row">
<div>
<div class="engine-label">ME_STBD</div>
<span class="engine-state">RUNNING</span>
</div>
<div>
<div class="gauge-bar"><div class="gauge-fill" style="width: 58%;"></div></div>
<div class="engine-meta">
<span>Aceite <strong>4.9 bar</strong></span>
<span>Coolant <strong>81°C</strong></span>
<span>Carga <strong>58%</strong></span>
<span>Horas <strong>1,287</strong></span>
</div>
</div>
<div class="engine-rpm">1,498 <small>rpm</small></div>
</div>
<div class="engine-row">
<div>
<div class="engine-label">GEN_1</div>
<span class="engine-state">RUNNING</span>
</div>
<div>
<div class="gauge-bar"><div class="gauge-fill warn" style="width: 88%;"></div></div>
<div class="engine-meta">
<span>L1 <strong>231 V</strong></span>
<span>Coolant <strong>89°C</strong></span>
<span>Carga <strong>88%</strong></span>
<span>Horas <strong>3,418</strong></span>
</div>
</div>
<div class="engine-rpm">1,800 <small>rpm</small></div>
</div>
</div>
</div>
<!-- Roll/pitch -->
<div class="card col-4">
<div class="stat-header">
<span class="stat-label">Actitud (NMEA 2000 · PGN 127257)</span>
<span class="badge badge-ok">SAFE</span>
</div>
<div class="horizon">
<svg viewBox="0 0 200 200" xmlns="http://www.w3.org/2000/svg" style="width:100%;">
<defs>
<linearGradient id="sky" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#3A6BA8"/>
<stop offset="100%" stop-color="#1B3E6E"/>
</linearGradient>
<linearGradient id="sea" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stop-color="#0A1A2E"/>
<stop offset="100%" stop-color="#04111F"/>
</linearGradient>
<clipPath id="circleClip">
<circle cx="100" cy="100" r="86"/>
</clipPath>
</defs>
<circle cx="100" cy="100" r="92" fill="none" stroke="#1A2B42" stroke-width="2"/>
<g clip-path="url(#circleClip)">
<g transform="rotate(-4 100 100)">
<rect x="0" y="0" width="200" height="100" fill="url(#sky)"/>
<rect x="0" y="100" width="200" height="100" fill="url(#sea)"/>
<line x1="0" y1="100" x2="200" y2="100" stroke="#00D9FF" stroke-width="1.5" opacity="0.7"/>
<g font-family="JetBrains Mono" font-size="9" fill="#E6EAF0">
<line x1="80" y1="80" x2="120" y2="80" stroke="#E6EAF0" stroke-width="1" opacity="0.6"/>
<text x="125" y="84">10°</text>
<line x1="80" y1="120" x2="120" y2="120" stroke="#E6EAF0" stroke-width="1" opacity="0.6"/>
<text x="125" y="124">10°</text>
</g>
</g>
</g>
<!-- Center cross -->
<g stroke="#00D9FF" stroke-width="2" fill="none">
<line x1="80" y1="100" x2="95" y2="100"/>
<line x1="105" y1="100" x2="120" y2="100"/>
<circle cx="100" cy="100" r="3" fill="#00D9FF"/>
</g>
<!-- Tick scale top -->
<g stroke="#7C8B9F" stroke-width="1">
<line x1="100" y1="8" x2="100" y2="16"/>
<line x1="50" y1="22" x2="56" y2="29" opacity="0.5"/>
<line x1="150" y1="22" x2="144" y2="29" opacity="0.5"/>
</g>
</svg>
</div>
<div class="horizon-readout">
<div class="ro-block">
<div class="lbl">Roll</div>
<div class="val">-4.1°</div>
</div>
<div class="ro-block">
<div class="lbl">Pitch</div>
<div class="val">+1.8°</div>
</div>
</div>
<div style="margin-top: var(--s-4); padding-top: var(--s-3); border-top: 1px solid var(--c-steel); font-size: 11px; color: var(--c-fog); display:flex; justify-content: space-between; font-family: var(--f-mono);">
<span>Envelope ±10°</span>
<span>L3 trigger 18°</span>
</div>
</div>
<!-- Tanques -->
<div class="card col-6">
<div class="stat-header">
<span class="stat-label">Tanques estructurales</span>
<a href="#" style="font-size:12px">Detalle →</a>
</div>
<div class="tank-row" style="margin-top: var(--s-4);">
<div class="tank">
<div class="tank-shell">
<div class="tank-fill" style="height: 78%;"></div>
</div>
<div class="tank-pct">78%</div>
<div class="tank-label">FUEL 1</div>
</div>
<div class="tank">
<div class="tank-shell">
<div class="tank-fill" style="height: 64%;"></div>
</div>
<div class="tank-pct">64%</div>
<div class="tank-label">FUEL 2</div>
</div>
<div class="tank">
<div class="tank-shell">
<div class="tank-fill water" style="height: 91%;"></div>
</div>
<div class="tank-pct">91%</div>
<div class="tank-label">WATER</div>
</div>
<div class="tank">
<div class="tank-shell">
<div class="tank-fill warn" style="height: 12%;"></div>
</div>
<div class="tank-pct" style="color: var(--c-warn);">12%</div>
<div class="tank-label">BILGE</div>
</div>
<div class="tank">
<div class="tank-shell">
<div class="tank-fill black" style="height: 28%;"></div>
</div>
<div class="tank-pct">28%</div>
<div class="tank-label">BLACK</div>
</div>
</div>
</div>
<!-- Alarmas recientes -->
<div class="card col-6">
<div class="stat-header">
<span class="stat-label">Alarmas recientes</span>
<a href="#" style="font-size:12px">Ver todas (2) →</a>
</div>
<div style="margin-top: var(--s-3);">
<div class="alarm-row">
<span class="alarm-time">03:38:42</span>
<div class="alarm-msg">
<span class="src">GEN_1.COOLANT_TEMP</span>
<strong>89°C</strong> alta — aproximando límite 92°C
</div>
<span class="badge badge-low">LOW</span>
</div>
<div class="alarm-row">
<span class="alarm-time">03:31:17</span>
<div class="alarm-msg">
<span class="src">BILGE_MID.LEVEL</span>
Nivel <strong>12%</strong> — verificar bomba
</div>
<span class="badge badge-info">INFO</span>
</div>
<div class="alarm-row" style="opacity: 0.5;">
<span class="alarm-time">03:12:04</span>
<div class="alarm-msg">
<span class="src">ME_PORT.OIL_TEMP</span>
Recuperado a <strong>88°C</strong> · resolved
</div>
<span class="badge badge-muted">CLEARED</span>
</div>
<div class="alarm-row" style="opacity: 0.5;">
<span class="alarm-time">02:58:30</span>
<div class="alarm-msg">
<span class="src">SHORE_POWER.STATUS</span>
Transferencia a gen — desconexión muelle
</div>
<span class="badge badge-muted">CLEARED</span>
</div>
</div>
</div>
</div>
</main>
<footer class="ticker">
<span class="pulse"></span>
<span>WebSocket <strong style="color:var(--c-sand)">LIVE</strong></span>
<span class="sep">|</span>
<span>Latencia <strong style="color:var(--c-sand)">42 ms</strong></span>
<span class="sep">|</span>
<span>Driver Modbus RTU <strong style="color:var(--c-ok)">OK</strong></span>
<span class="sep">|</span>
<span>Driver NMEA 2000 <strong style="color:var(--c-ok)">OK</strong></span>
<span class="sep">|</span>
<span>Tags activos <strong style="color:var(--c-sand)">187</strong></span>
<span class="tk-spacer"></span>
<span><span class="dot cyan"></span> VPN soporte <strong>INACTIVA</strong></span>
<span class="sep">|</span>
<span>Telemetría <strong style="color:var(--c-ok)">activa</strong> (visible)</span>
<span class="sep">|</span>
<span>v0.1.0.dev0</span>
</footer>
</div>
</body>
</html>