signalk-mareas-ihm 2.2.1 → 2.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,265 +1,319 @@
1
- # Changelog
2
-
3
- ## [2.2.1] - 2026-06-20
4
-
5
- ### English
6
-
7
- **Documentation & UI**
8
- - Instructions modal rewritten as a proper user manual: safety notice, 16 sections covering setup, anchoring manoeuvre, swing-circle geometry (blue/red rings), real sensors, AIS proximity watch, shelter, grounding alarm, multi-device audio, FAQ.
9
- - New "Recommended onboard hardware" section listing what each user typically needs: Raspberry Pi, USB self-amplified speaker (essential for audible alarms), GPS, depth sounder, anemometer, AIS receiver, IMU.
10
- - Modal typography +2 px for easier reading at arm's length in cockpit conditions.
11
- - AIS module renamed "anti-collision" "proximity watch" (no CPA/TCPA yet honesty matters in safety tooling).
12
-
13
- **Bug fixes**
14
- - Map no longer auto-recenters on the boat after a temporary GPS loss. If you dragged the map to look elsewhere, that decision is now respected even if the GPS blinks.
15
-
16
- **App Store & registry**
17
- - Screenshots converted to JPEG ≤1778 px wide, each <500 KB, per Signal K App Store spec. Tarball size dropped from 6.1 MB to 2.9 MB.
18
- - Plugin test suite added using Node's built-in `node:test` (no new devDependencies). Covers Signal K plugin contract, screenshot manifest integrity, files[] correctness and entrypoint import. Runs with `npm test`.
19
-
20
- ### Español
21
-
22
- **Documentación y UI**
23
- - Modal de instrucciones reescrito como manual profesional: aviso de seguridad, 16 secciones con configuración, maniobra de fondeo, geometría de los círculos azul y rojo, sensores reales, vigilancia AIS de proximidad, abrigo, alarma de varada, audio multidispositivo, FAQ.
24
- - Nueva sección "Hardware recomendado a bordo" con lo que necesita cada usuario: Raspberry Pi, altavoz USB autoamplificado (imprescindible para que las alarmas se oigan), GPS, sonda, anemómetro, receptor AIS, IMU.
25
- - Tipografía del modal +2 px para leer cómodamente a un metro bajo la luz del sol.
26
- - Módulo AIS renombrado "anti-colisión" → "vigilancia de proximidad" (no hay CPA/TCPA todavía — la honestidad importa en herramientas de seguridad).
27
-
28
- **Corrección de bugs**
29
- - El mapa ya no se auto-centra en el barco tras perder el GPS un instante. Si arrastraste el mapa para mirar otra zona, esa decisión se respeta aunque el GPS parpadee.
30
-
31
- **App Store y registro**
32
- - Capturas convertidas a JPEG ≤1778 px ancho, cada una <500 KB, según la especificación del App Store de Signal K. Tamaño del paquete bajado de 6.1 MB a 2.9 MB.
33
- - Añadida suite de tests del plugin usando `node:test` nativo de Node (sin nuevas dependencias). Cubre contrato del plugin Signal K, integridad del manifiesto de screenshots, corrección de files[] y carga del entrypoint. Se ejecuta con `npm test`.
34
-
35
- ## [2.2.0] - 2026-06-20
36
-
37
- Rediseño del sistema AIS, cache persistente entre sesiones, auto-desarme inteligente al motorizar, panel AIS más usable, capturas para el App Store de Signal K.
38
-
39
- ### Novedades
40
-
41
- **Sistema AIS Los barcos vecinos ya no se "olvidan"**
42
- - El plugin guarda en disco los datos de cada barco AIS visto en los últimos 3 días: nombre, eslora, manga, tipo, callsign, IMO. Al reiniciar el plugin o abrir el visor desde cero, los nombres y datos ya están ahí sin esperar a que cada barco vuelva a emitir su paquete de identificación (que tarda hasta 6 min).
43
- - Si un barco se queda sin recepción AIS por unos minutos, sigue visible en pantalla con una X discreta indicando "datos estimados".
44
- - Banner azul claro en el popup cuando el target es estimado: "Datos estimados, mostrando última posición conocida".
45
-
46
- **Sistema AIS — Lista y filtros nuevos**
47
- - Slider de radio configurable de 0.5 a 50 km para decidir qué barcos ves en el mapa y en la lista. Se recuerda al recargar.
48
- - Ordena la lista por distancia, nombre, favoritos primero, MMSI o tipo de barco.
49
- - Casilla de filtro de texto para buscar por nombre o MMSI con mensaje "Sin resultados" cuando no hay coincidencias.
50
- - Marca AIS como favorito con una ★ amarilla — se sincroniza entre todos tus dispositivos.
51
- - Botón 🔍 vesselfinder en cada barco abre vesselfinder en una nueva pestaña con la info completa del barco (IMO + MMSI).
52
- - Iconos en la lista ahora distinguen velero, motora, carguero, tanker, pasaje, pesca... a primera vista.
53
-
54
- **Sistema AIS — Alarma más fiable**
55
- - Cuando haces ACK a un target y este vuelve a moverse hacia ti, la alarma vuelve a sonar (antes se quedaba muda).
56
- - El ACK caduca a los 15 min para forzar una nueva evaluación si el barco sigue siendo peligro.
57
- - Eliminado el bucle "alarma se abre y cierra sola" por fluctuaciones de velocidad pequeñas.
58
- - La velocidad de acercamiento ya no arrastra valores antiguos cuando ambos barcos están parados.
59
- - Actualización de tráfico AIS más rápida — el rastro de un barco que se mueve aparece a los pocos segundos en vez de medio minuto.
60
-
61
- **Sistema AIS — Visor**
62
- - Click en un barco el mapa lo centra, lo sigue automáticamente y aparece su distancia al lado del aro azul de identificación.
63
- - La selección se queda activa aunque cierres el popup. Una X en el aro azul te permite deseleccionar cuando quieras.
64
- - El rastro del barco seleccionado se ve siempre destacado (más grueso y opaco), aunque esté lejos.
65
-
66
- **Salida a motor sin alarma de garreo**
67
- - Cuando sales del fondeo a motor sin acordarte de "levar" en la app, ahora el plugin detecta que llevas más de 30 segundos por encima de 3 nudos y desarma la vigilancia automáticamente. Antes saltaba la sirena de garreo y despertaba al patrón sin motivo.
68
-
69
- **Previsión de abrigo (rosa de sectores)**
70
- - Restaurado el algoritmo de detección que tenías en versiones anteriores y funcionaba bien. Los cambios intermedios daban falsos positivos en costas irregulares (caso Moaña). Ahora vuelve a marcar correctamente qué sectores tienen costa o espigón cerca y cuáles están expuestos al mar abierto.
71
- - El icono del barco dentro de la rosa ya no aparece partido a veces.
72
-
73
- **Historial de olas**
74
- - Resolución triplicada: una barra cada 5 minutos en vez de cada 15.
75
- - Las barras "Ahora" están a la izquierda y el pasado se extiende a la derecha (más intuitivo).
76
- - Si hay muchas barras hay scroll horizontal con barras más anchas.
77
- - Escala vertical autoescalable de 0 a 2 m con líneas guía claras a ambos lados.
78
-
79
- **Ventanas y modales mejorados**
80
- - Los modales informativos (Escala de exposición, Cómo se calcula la protección, Historial de olas con leyenda y tabla) ahora ocupan casi toda la pantalla con textos cómodos de leer a un metro de distancia bajo la luz del sol.
81
- - El header de cada modal lleva botón "‹ Atrás" grande y bien visible.
82
-
83
- **App Store de Signal K**
84
- - Capturas de pantalla añadidas al paquete — visibles en el App Store de Signal K tras la instalación. La principal es el visor de fondeo en uso real.
85
-
86
- ### Mejoras de uso (UX)
87
-
88
- - **Versátil en cualquier pantalla**: del móvil al monitor del puente, el visor reordena y reescala todo para que los controles siempre se puedan tocar cómodamente con el dedo, y los textos sean legibles a la distancia desde la que se usa el dispositivo.
89
- - Quitado el tooltip molesto "Container ship top view" que salía al pasar el ratón sobre los AIS Class A.
90
- - El faldón del popup AIS muestra el icono específico del tipo de barco (⛵ velero, 📦 carga, 🛢️ tanque, 🛳️ pasaje, etc.) en vez del genérico.
91
-
92
- ### Correcciones
93
-
94
- - Resumen del abrigo ("Abrigado: ninguna de las próximas 12 h…") ahora respeta el idioma del visor en lugar de salir en español cuando la UI está en inglés.
95
- - El nombre de un barco AIS ya no se pierde si reaparece en el visor sin haber recibido nuevo paquete de identificación.
96
- - El foco del mapa ya no oscila entre el barco propio y un AIS seleccionado.
97
- - Al pulsar la X del aro de un AIS, ya no salta accidentalmente la alarma del siguiente barco en zona.
98
- - El panel "AIS en zona" mantiene fija arriba la cabecera (radio, ordenar, filtro) y solo se mueve la lista al hacer scroll.
99
- - La rueda del ratón scrollea la lista correctamente desde cualquier parte del panel.
100
- - Los cambios de pantalla se reflejan al instante tras actualizar el plugin (antes el navegador podía mostrar versión cacheada).
101
-
102
- ---
103
-
104
- ## [2.1.11] - 2026-06-13 (pendiente publicación)
105
-
106
- ### Nuevas funciones
107
- - **NOAA ENC (EE.UU.)** como capa seleccionable. Servicio WMS Maritime Chart Service del NOAA ENCOnline (`gis.charttools.noaa.gov/.../exts/MaritimeChartService/WMSServer`). Gratis, sin API key. Capas 1-6 activas (naturales+puerto, sondas+corrientes, lecho+obstáculos+pipes, rutas tráfico, áreas especiales, boyas+balizas+faros+radar). Cobertura: aguas costeras EE.UU. (Atlántico, Pacífico, Golfo, Grandes Lagos, Alaska, Hawai, Caribe). Opacidad por defecto 60%. ID interno: `noaa`.
108
-
109
- ### Cartas no incluidas (notas)
110
- - **CHS Canadá**: investigada y descartada por ahora. El endpoint NONNA (`nonna-geoserver.api.gc.ca`) está caído/movido. El portal oficial `data.chs-shc.ca` requiere login y no expone WMS público. No hay servicio público sin auth equivalente al de NOAA para Canadá. Se reactivará cuando aparezca alternativa.
111
-
112
- ### Documentación
113
- - README: corregido "garreo" "anchor drag" en la sección de audio inglés (línea 82). Era una fuga del término español dentro del párrafo EN.
114
-
115
- ## [2.1.10] - 2026-06-10
116
-
117
- ### Fixes
118
- - **Alarma meteo activa sin estar fondeado** (feedback Pablo G. Nascimento). `_checkWeatherAlarm` no comprobaba `anch`; quien tuviese el switch ON recibía avisos amarrado al pantalán o navegando. Añadido guard: si no está fondeado, la alarma se fuerza a `false` y el chequeo retorna inmediatamente. La rosa del visor y el historial IMU siguen activos para info general — solo se suprime el aviso/voz/banner.
119
- - **Rosa de abrigo en marinas con escolleras**: el query Overpass solo buscaba `way["natural"="coastline"]`. En marinas (e.g. Vigo Marina Davila 42.242,-8.724) los espigones están etiquetados como `man_made=breakwater`, `man_made=pier` o `man_made=groyne`, no como costa natural. El cálculo daba "F · 10% protección" para una marina con escolleras gigantes. Ahora el query incluye los tres tipos `man_made` y los trata como obstáculos sólidos en el ray-casting. `ALGORITHM_VERSION` bumpeada a `v76` para invalidar cachés viejas.
120
-
121
- ### Documentación
122
- - Nota: las lecturas de olas (intensidad/período/dirección) del IMU son **siempre activas** mientras el plugin corre — son info general útil tanto fondeado como navegando. Los **avisos** (alarma meteo) solo disparan en fondeo. El visor sigue mostrando todos los datos.
123
-
124
- ## [2.1.5] - 2026-06-03
125
-
126
- ### Fixes
127
- - **CRÍTICO: "Cannot set headers after they are sent"** en `/navtiles/:z/:x/:y.png`. El handler hacía `tileResp.pipe(res)` y si la conexión upstream caía mid-stream el `tileReq.on('error')` callback intentaba `res.status(502).send()` cuando los headers ya estaban enviados. Fix: helper `sendFallback()` que comprueba `res.headersSent` antes de enviar; si headers ya fueron enviados, sólo `res.end()` para cerrar el socket limpio. También guard antes de `pipe()` por si `res.headersSent` ya es true al entrar (idempotencia).
128
- - **Bottom bar Sonda**: el botón solo abría el popup sin llamar `fetchSondaData()` — quedaba con "Cargando..." si no se había abierto antes desde el menú. Ahora ambos paths fetchan.
129
- - **Quality donut mismatch** (visor shelter): el donut del bottom bar usaba un mapa hardcoded `{A:100, B:80, C:60, ...}` que no coincidía con el % real de `_shelterCache.assessment.scorePercent`. Ahora lee el valor real del cache; fallback al mapa si no hay cache aún.
130
-
131
- ### Nuevas funciones
132
- - **Alarma "Mala condición climática"** en panel de alarmas: nuevo selector con switch. Cuando activado, comprueba cada 5 min las próximas 6h del shelter cache buscando viento > 25 kt u ola > 1.5 m, y dispara `setAlarmActive('weather', true)`. Estado persistido en localStorage.
133
-
134
- ### Traducciones
135
- - **Wave history popup** (`#wave-hist-info-pop`): título "Historial de olas leyenda y detalle" / "Wave history — legend & details", subtitle, badges Calma/Rizada/Moderada/Agitada/Fuerte → Calm/Rippled/Moderate/Rough/Strong, headers tabla Inicio/Intensidad/Período/Altura/RMS → Start/Intensity/Period/Height/RMS, badge ACTUAL → CURRENT, mensaje "No hay datos todavía...". Ampliado de 620px → 900px y 88vh → 92vh.
136
- - **Tooltips left bar**: m-ham (Menú/Menu), m-cartas audio toggle, m-snooze, m-fav, m-lb-curvas, m-lb-mareas, m-kip, m-fb — todos con `data-i18n-title`.
137
-
138
- ## [2.1.4] - 2026-06-03
139
-
140
- ### Traducciones (i18n)
141
- - **Panel meteo AHORA** (left card): labels VIENTO/RACHA/AIRE/MAR ahora bilingües (WIND/GUST/AIR/SEA en EN).
142
- - **Filas tabla meteo**: Aire, Presión, Lluvia, T. Mar, Ola, Período, Dir ola todas con T() (Air/Pressure/Rain/Sea T./Wave/Period/Wave dir).
143
- - **Resumen meteo** botón colapsable bilingüe.
144
- - **Shelter NOW box**: badges "Veleta" "Vane", "Sensor" igual ambos; labels racha/aire/agua gust/air/water.
145
- - **Eje gráfico presión**: "ahora" → "now".
146
- - **Labels flotantes visor mapa**: "Viento" → "Wind", "Olas" → "Waves", "Mar en calma" → "Calm sea".
147
-
148
- ### UI consistente
149
- - **Estilo unificado del back button** y título de cabecera en TODOS los modales:
150
- - `.m-back-btn` / `.m-modal-title` classes utility.
151
- - Back: rgba(255,178,63,.15) bg + 1px border var(--org) + color var(--org) + 18px font + 48px min-height + radius 12px.
152
- - Title: 28px (antes 38px en m-modal-hdr) coherente con Anchor Calculation, Shelter, Weather Forecast.
153
- - `m-modal-hdr .m-back` actualizado a las mismas dimensiones que la clase utility (sin min-width:110px, sin height fija 56px).
154
- - `m-close-spacer` reducido de 110px 80px para compensar el botón más estrecho.
155
-
156
- ### Infra i18n
157
- - `applyLang()` ahora procesa también `data-i18n-title` (atributos title de tooltips) y `data-i18n-placeholder` (placeholders de inputs).
158
-
159
- ## [2.1.3] - 2026-06-03
160
-
161
- ### Traducciones
162
- - Tooltips title="..." del bottom bar (velocidad/viento/sonda/cadena/distancia/presión/abrigo/calidad) y sidebar derecha (anchor/centrar/info/AIS/cartas/abrigo/alarmas/fondeo).
163
- - Intensidades de ola en la rosa abrigo: Cal/Riz/Mod/Agi/Fue → Calm/Rip/Mod/Rou/Str.
164
- - Modal "Guardar fondeo favorito": título, hint, placeholder, botones Cancelar/Guardar.
165
- - Selector modelo meteo "Mejor (automático)" → "Best (automatic)".
166
- - Spinner "Cargando…" → "Loading…" en popups Sonda y Meteo.
167
-
168
- ## [2.1.2] - 2026-06-03
169
-
170
- ### NPM metadata
171
- - **Descripción ampliada** del paquete (antes hablaba solo de mareas; ahora menciona anchor watch, AIS, shelter, weather, depth, charts).
172
- - **~70 keywords en inglés** orientados a búsqueda internacional: anchor-watch, ais-alarm, shelter-forecast, weather-forecast, swing-radius, bathymetry, chartplotter, mbtiles, marine-safety, voice-alarm, etc.
173
-
174
- ## [2.1.1] - 2026-06-02
175
-
176
- ### Fixes críticos (alarmas y audio)
177
- - **State machine de alarmas robusta**: detector de loops huérfanos en `setAlarmActive` — si los timers fueron matados externamente (ACK manual, snooze, cancel-silence cross-device) pero `_activeAlarms[kind]=true` persiste, ahora se re-arman correctamente. Antes el plugin quedaba "atascado" sin sonar nunca más.
178
- - **30s grace para AIS** antes del primer aviso de voz: modal aparece instant, 30s silencio para reaccionar, luego beep + voz.
179
- - **ACK/snooze/un-mute = re-arme instantáneo** vía flag `_alarmInstantRearm[kind]` — sin esperar 30s adicionales.
180
- - **Cortar voz al instante**: arquitectura per-kind (cancel tokens `_voiceCancelTokens`, arrays `_activeVoiceSources` y `_activeVoiceAudios`). HTMLAudio fallback se aborta con `removeAttribute('src')+load()`.
181
- - **Voz garreo INSTANT** (antes esperaba 30s erróneamente porque `_ALARM_VOICE_PRE_DELAY_MS` era global). Default ahora 0, AIS pasa 30000 explícitamente.
182
- - **Mute 60s window respetado** incluso por SSE del backend: cuando el usuario muta, `_userMuteUntilMs = Date.now()+60s`; durante esa ventana ni garreo crítico ni el push SSE pueden auto-reactivar.
183
- - **Vibración fallback** (`navigator.vibrate`) + banner rojo "🔇 Audio bloqueado TOCA aquí" + visibilitychange resume del AudioContext.
184
- - **Snooze auto-cancela al levar ancla** (POST `/cancel-silence`).
185
- - **Snooze sólo aplica si AIS está activo** (no permite snooze durante garreo solo).
186
-
187
- ### UI / UX
188
- - **Shelter modal portrait fullscreen REAL** — fix del bug `dvw/dvh` × `zoom: var(--ui-scale)` (gracias Gemini): cambio de unidades `100dvw/100dvh` → `100%/100%` para que se cancelen con el factor zoom del overlay.
189
- - **Chip numérico de opacidad** encima del thumb del slider: bold 900, font 14px, sombra, oculto durante drag, oculto cuando capa desactivada.
190
- - **Defaults opacidad** capas: Sat=100, Batimetría=13, IHM=13 (preferencia del usuario).
191
- - **"SonarChart" → "Batimetría"** (cero referencias comerciales). Variable `_navTokenCache` → `_chTokenCache`, comentarios sanitizados en `src/index.ts`.
192
- - **Triángulos toggle** sidebars apuntan correctamente al borde donde se esconden.
193
- - **AIS confirm popup** sin truncar título — popups de confirmación corta excluidos del `_mInjectModalHeader` que cortaba con `white-space:nowrap`.
194
- - Curvas y Mareas solo en left bar (eliminados duplicados sidebar derecha).
195
- - TidesView centrado fix (`baseW=825, baseH=890` corregidos).
196
-
197
- ### i18n
198
- - Info modal completo (Estado, Fondeado/Anchored, etc.).
199
- - Menú principal (8 items).
200
- - Bottom bar (Velocidad/Speed, etc.).
201
- - AIS popup (Acercamiento/Closing, Ancla est./Est. anchor).
202
- - Shelter (Detección automática, Escala Exposición, Protección, score popup completo, hist olas).
203
- - Botón ancla Echar/Drop, Levar/Lift.
204
- - Back buttons del modal-hdr Atrás / ‹ Back.
205
-
206
- ## [2.0.0] - 2026-05-22
207
-
208
- Salto generacional. Lo que era un plugin de mareas pasa a ser un **visor completo de fondeo** con previsión de abrigo, medición de olas en tiempo real y alarmas en barco y móvil.
209
-
210
- ### Nuevo
211
-
212
- **Fondeo seguro**
213
- - Detección automática de garreo con radio predictivo según la marea.
214
- - Cálculo de cadena recomendada con dos métodos (tradicional y Vicente).
215
- - Alarmas configurables: garreo, varada, AIS por proximidad.
216
- - Track de aproximación al fondeo con gradiente de tiempo.
217
-
218
- **Previsión de abrigo**
219
- - Rosa de 16 sectores con detección automática del abrigo según la costa (OpenStreetMap).
220
- - Grado A-F y porcentaje de protección combinando viento y olas.
221
- - Strip de 12 h con previsión hora a hora.
222
- - Resumen "AHORA / PREDICCIÓN" con datos en tiempo real.
223
-
224
- **Medición de olas en fondeo**
225
- - Dirección, período y altura de ola medidas a bordo (sensores de actitud y aceleración).
226
- - Historial de las últimas 24 h.
227
- - El grado de abrigo se ajusta cuando la ola real supera la prevista.
228
-
229
- **Sensores en tiempo real**
230
- - Lectura directa de viento (veleta del barco), temperatura del aire y del agua, presión atmosférica.
231
- - Etiquetas "Veleta" y "Sensor" para distinguir datos reales de previsión.
232
- - Fallback automático a Open-Meteo si un sensor falla.
233
-
234
- **Cartas náuticas integradas**
235
- - Servidor MBTiles incluido para cargar tus propias cartas en el visor.
236
-
237
- **Audio mejorado**
238
- - Voces pregrabadas (OGG) por idioma más naturales que el sintetizador.
239
- - Detección automática de la salida de audio del Raspberry Pi.
240
- - Alarmas distintas por evento (AIS, garreo, varada).
241
- - Soporte fiable en móvil (incluso con la pestaña en segundo plano).
242
-
243
- **Mareas IHM**
244
- - Lista completa actualizada (70 estaciones reales de IHM España).
245
- - Visor del coeficiente y tendencia (subiendo/bajando) en barra superior.
246
-
247
- ### Mejoras
248
-
249
- - Compass cardinal en español (N/NE/E/SE/S/SO/O/NO).
250
- - Sonda inteligente: cuando se congela o da lecturas absurdas, el visor lo detecta y deja de mostrar valores inventados.
251
- - Estabilidad mejorada en conexiones débiles (4G/Tailscale).
252
- - Tolerancia a errores de la API de mareas (no se cuelga con respuestas inesperadas).
253
-
254
- ### Corregido
255
-
256
- - Identificadores de estación incorrectos que provocaban errores constantes cuando el plugin arrancaba sin GPS.
257
- - El visor mostraba "Sonda mínima esperada" obsoleta cuando el sensor de sonda se quedaba congelado.
258
- - Solapamiento de etiquetas en la rosa cuando viento y oleaje coincidían en dirección.
259
- - Memoria del navegador a las pocas horas con la capa de viento activa.
260
-
261
- ---
262
-
263
- ## [1.3.1] - Versiones anteriores
264
-
265
- Plugin de mareas IHM España con previsión meteo Open-Meteo y barra de estado superior.
1
+ # Changelog
2
+
3
+ ## [2.3.0] - 2026-06-22
4
+
5
+ ### English
6
+
7
+ **Safety hardening (refactor Rev475-487)**
8
+
9
+ - **Grounding FSM** with four orthogonal dimensions exposed at `state.grounding`: `physics` (data + clearance), `config` (alarm settings), `notification` (active/snoozed/inactive/latched), `safetyLatch` (persistent across restart). Plus legacy paths (`groundingAlarm`, `groundingStatus`, `groundingDetail`) preserved for backward compatibility.
10
+ - **Grounding snooze** added: `POST /api/anchor-watch/silence-alarm {kind:"grounding", minutes:N}` silences the grounding siren for N minutes. The visor snooze button (😴) now silences AIS *and* grounding (anchor-drag still untouched — safety critical). Cancel with `kind:"all"`.
11
+ - **Visual risk indicator**: anchor icon (sidebar button + map marker) glows red and pulses when physical grounding risk is detected, independent of whether the alarm is enabled or silenced. Bottom-bar SONDA cell shows "⚠ RIESGO DE VARADA" in red.
12
+ - **Disconnect banner**: when the visor stops receiving state for >15s (WiFi lost, plugin down, SK stopped, Pi off), a red banner appears warning "DATA UNRELIABLE — check WiFi, plugin or boat link before making decisions". Auto-reload on backend restart (detected via `serverInstanceId` change).
13
+ - **GPS freshness exposed** as `state.gpsAgeMs`. `boatPosition: null` when fresh GPS is unavailable (avoids stale-position leakage).
14
+ - **Single-flight lock** for `drop`/`lift`/`toggle` anchor commands (10s recovery). Concurrent calls return 409.
15
+ - **Persistent safety latch**: if the depth sounder freezes or disappears while grounding is monitored, the latch holds the alarm even across plugin restarts until the user explicitly clears it.
16
+ - **Schema version 2** + `serverInstanceId` to detect cached frontend / backend restart and force reload.
17
+ - **Input validation**: POST endpoints now reject invalid types (`enabled:"yes"`, `draft:"text"`, out-of-range numbers) with 400 instead of silent coercion.
18
+ - **Robust draft reader** handling all `design.draft` shapes (number, `{value}`, `{value:{maximum}}`).
19
+ - **Validated position** with 60s timestamp window for SSE consumers.
20
+ - **Defensive deep-clone** of state payload to avoid mutation leaks.
21
+ - **Cache migration** for legacy `groundingRisk` snapshots.
22
+ - Integration test suite (`tests/grounding_v475.test.js`, `depth_v476.test.js`, `fsm_v477.test.js`, `sync_v478.test.js`) — 37 tests.
23
+
24
+ QA validated in-water on Tunatunes during a real grounding-risk event (Vigo, 2026-06-22), including snooze, glow indicators, bottom-bar display, and connection-loss banner triggered by laptop WiFi cut.
25
+
26
+ ### Español
27
+
28
+ **Refuerzo de seguridad (refactor Rev475-487)**
29
+
30
+ - **FSM de varada** con cuatro dimensiones ortogonales expuestas en `state.grounding`: `physics` (datos + holgura), `config` (configuración de alarma), `notification` (active/snoozed/inactive/latched), `safetyLatch` (persistente entre reinicios). Más los paths legacy (`groundingAlarm`, `groundingStatus`, `groundingDetail`) preservados por compatibilidad.
31
+ - **Snooze de varada** añadido: `POST /api/anchor-watch/silence-alarm {kind:"grounding", minutes:N}` silencia la sirena de varada N minutos. El botón snooze del visor (😴) ahora silencia AIS *y* varada (garreo intocable — safety crítico). Cancelar con `kind:"all"`.
32
+ - **Indicador visual de riesgo**: el icono ancla (botón sidebar + marker del mapa) brilla en rojo pulsante cuando se detecta riesgo físico de varada, independientemente de si la alarma está activada o silenciada. La celda SONDA del bottom-bar muestra "⚠ RIESGO DE VARADA" en rojo.
33
+ - **Banner de desconexión**: cuando el visor lleva >15s sin recibir state (WiFi caído, plugin parado, SK parado, Pi apagado), aparece un banner rojo: "DATOS NO FIABLES — verifica WiFi, plugin o conexión con el barco antes de tomar decisiones". Auto-recarga al reiniciar backend (detectado vía cambio de `serverInstanceId`).
34
+ - **Edad del GPS expuesta** en `state.gpsAgeMs`. `boatPosition: null` cuando no hay fix fresco (evita filtrar posiciones obsoletas).
35
+ - **Lock single-flight** para comandos `drop`/`lift`/`toggle` (recovery 10s). Llamadas concurrentes devuelven 409.
36
+ - **Safety latch persistente**: si la sonda se congela o desaparece mientras vigilamos varada, el latch mantiene la alarma incluso entre reinicios del plugin hasta que el usuario la limpie explícitamente.
37
+ - **Schema versión 2** + `serverInstanceId` para detectar frontend cacheado / backend reiniciado y forzar reload.
38
+ - **Validación de inputs**: los endpoints POST ahora rechazan tipos inválidos (`enabled:"yes"`, `draft:"texto"`, números fuera de rango) con 400 en lugar de coerción silenciosa.
39
+ - **Lector de calado robusto** que maneja todos los shapes de `design.draft` (número, `{value}`, `{value:{maximum}}`).
40
+ - **Posición validada** con ventana timestamp 60s para consumidores SSE.
41
+ - **Deep-clone defensivo** del payload de state para evitar fugas de mutación.
42
+ - **Migración de cache** para snapshots legacy de `groundingRisk`.
43
+ - Suite de tests de integración (`tests/grounding_v475.test.js`, `depth_v476.test.js`, `fsm_v477.test.js`, `sync_v478.test.js`) 37 tests.
44
+
45
+ QA validado en agua a bordo del Tunatunes durante un evento real de riesgo de varada (Vigo, 2026-06-22), incluyendo snooze, indicadores de glow, bottom-bar y banner de pérdida de conexión disparado al cortar el WiFi del portátil.
46
+
47
+ ## [2.2.2] - 2026-06-20
48
+
49
+ ### English
50
+
51
+ - **Fix:** `tests/` directory now included in the published npm tarball via `files[]`. In 2.2.1 the `npm test` script was declared but the test files themselves were excluded, so the Signal K Plugin Registry could not detect any tests and showed the "no plugin-level tests provided" warning. This release ships the suite inside the package so `npm test` runs from the installed tarball.
52
+
53
+ ### Español
54
+
55
+ - **Corrección:** el directorio `tests/` ahora va dentro del tarball npm publicado (añadido a `files[]`). En 2.2.1 declaramos el script `npm test` pero los archivos de test no viajaban en el paquete, así que el Signal K Plugin Registry no detectaba ninguno y mostraba el aviso "no plugin-level tests provided". Esta versión incluye la suite dentro del paquete para que `npm test` se ejecute desde el tarball instalado.
56
+
57
+ ## [2.2.1] - 2026-06-20
58
+
59
+ ### English
60
+
61
+ **Documentation & UI**
62
+ - Instructions modal rewritten as a proper user manual: safety notice, 16 sections covering setup, anchoring manoeuvre, swing-circle geometry (blue/red rings), real sensors, AIS proximity watch, shelter, grounding alarm, multi-device audio, FAQ.
63
+ - New "Recommended onboard hardware" section listing what each user typically needs: Raspberry Pi, USB self-amplified speaker (essential for audible alarms), GPS, depth sounder, anemometer, AIS receiver, IMU.
64
+ - Modal typography +2 px for easier reading at arm's length in cockpit conditions.
65
+ - AIS module renamed "anti-collision" → "proximity watch" (no CPA/TCPA yet — honesty matters in safety tooling).
66
+
67
+ **Bug fixes**
68
+ - Map no longer auto-recenters on the boat after a temporary GPS loss. If you dragged the map to look elsewhere, that decision is now respected even if the GPS blinks.
69
+
70
+ **App Store & registry**
71
+ - Screenshots converted to JPEG ≤1778 px wide, each <500 KB, per Signal K App Store spec. Tarball size dropped from 6.1 MB to 2.9 MB.
72
+ - Plugin test suite added using Node's built-in `node:test` (no new devDependencies). Covers Signal K plugin contract, screenshot manifest integrity, files[] correctness and entrypoint import. Runs with `npm test`.
73
+
74
+ ### Español
75
+
76
+ **Documentación y UI**
77
+ - Modal de instrucciones reescrito como manual profesional: aviso de seguridad, 16 secciones con configuración, maniobra de fondeo, geometría de los círculos azul y rojo, sensores reales, vigilancia AIS de proximidad, abrigo, alarma de varada, audio multidispositivo, FAQ.
78
+ - Nueva sección "Hardware recomendado a bordo" con lo que necesita cada usuario: Raspberry Pi, altavoz USB autoamplificado (imprescindible para que las alarmas se oigan), GPS, sonda, anemómetro, receptor AIS, IMU.
79
+ - Tipografía del modal +2 px para leer cómodamente a un metro bajo la luz del sol.
80
+ - Módulo AIS renombrado "anti-colisión" "vigilancia de proximidad" (no hay CPA/TCPA todavía la honestidad importa en herramientas de seguridad).
81
+
82
+ **Corrección de bugs**
83
+ - El mapa ya no se auto-centra en el barco tras perder el GPS un instante. Si arrastraste el mapa para mirar otra zona, esa decisión se respeta aunque el GPS parpadee.
84
+
85
+ **App Store y registro**
86
+ - Capturas convertidas a JPEG ≤1778 px ancho, cada una <500 KB, según la especificación del App Store de Signal K. Tamaño del paquete bajado de 6.1 MB a 2.9 MB.
87
+ - Añadida suite de tests del plugin usando `node:test` nativo de Node (sin nuevas dependencias). Cubre contrato del plugin Signal K, integridad del manifiesto de screenshots, corrección de files[] y carga del entrypoint. Se ejecuta con `npm test`.
88
+
89
+ ## [2.2.0] - 2026-06-20
90
+
91
+ Rediseño del sistema AIS, cache persistente entre sesiones, auto-desarme inteligente al motorizar, panel AIS más usable, capturas para el App Store de Signal K.
92
+
93
+ ### Novedades
94
+
95
+ **Sistema AIS Los barcos vecinos ya no se "olvidan"**
96
+ - El plugin guarda en disco los datos de cada barco AIS visto en los últimos 3 días: nombre, eslora, manga, tipo, callsign, IMO. Al reiniciar el plugin o abrir el visor desde cero, los nombres y datos ya están ahí sin esperar a que cada barco vuelva a emitir su paquete de identificación (que tarda hasta 6 min).
97
+ - Si un barco se queda sin recepción AIS por unos minutos, sigue visible en pantalla con una X discreta indicando "datos estimados".
98
+ - Banner azul claro en el popup cuando el target es estimado: "Datos estimados, mostrando última posición conocida".
99
+
100
+ **Sistema AIS Lista y filtros nuevos**
101
+ - Slider de radio configurable de 0.5 a 50 km para decidir qué barcos ves en el mapa y en la lista. Se recuerda al recargar.
102
+ - Ordena la lista por distancia, nombre, favoritos primero, MMSI o tipo de barco.
103
+ - Casilla de filtro de texto para buscar por nombre o MMSI con mensaje "Sin resultados" cuando no hay coincidencias.
104
+ - Marca AIS como favorito con una ★ amarilla — se sincroniza entre todos tus dispositivos.
105
+ - Botón 🔍 vesselfinder en cada barco — abre vesselfinder en una nueva pestaña con la info completa del barco (IMO + MMSI).
106
+ - Iconos en la lista ahora distinguen velero, motora, carguero, tanker, pasaje, pesca... a primera vista.
107
+
108
+ **Sistema AIS — Alarma más fiable**
109
+ - Cuando haces ACK a un target y este vuelve a moverse hacia ti, la alarma vuelve a sonar (antes se quedaba muda).
110
+ - El ACK caduca a los 15 min para forzar una nueva evaluación si el barco sigue siendo peligro.
111
+ - Eliminado el bucle "alarma se abre y cierra sola" por fluctuaciones de velocidad pequeñas.
112
+ - La velocidad de acercamiento ya no arrastra valores antiguos cuando ambos barcos están parados.
113
+ - Actualización de tráfico AIS más rápida el rastro de un barco que se mueve aparece a los pocos segundos en vez de medio minuto.
114
+
115
+ **Sistema AIS Visor**
116
+ - Click en un barco → el mapa lo centra, lo sigue automáticamente y aparece su distancia al lado del aro azul de identificación.
117
+ - La selección se queda activa aunque cierres el popup. Una X en el aro azul te permite deseleccionar cuando quieras.
118
+ - El rastro del barco seleccionado se ve siempre destacado (más grueso y opaco), aunque esté lejos.
119
+
120
+ **Salida a motor sin alarma de garreo**
121
+ - Cuando sales del fondeo a motor sin acordarte de "levar" en la app, ahora el plugin detecta que llevas más de 30 segundos por encima de 3 nudos y desarma la vigilancia automáticamente. Antes saltaba la sirena de garreo y despertaba al patrón sin motivo.
122
+
123
+ **Previsión de abrigo (rosa de sectores)**
124
+ - Restaurado el algoritmo de detección que tenías en versiones anteriores y funcionaba bien. Los cambios intermedios daban falsos positivos en costas irregulares (caso Moaña). Ahora vuelve a marcar correctamente qué sectores tienen costa o espigón cerca y cuáles están expuestos al mar abierto.
125
+ - El icono del barco dentro de la rosa ya no aparece partido a veces.
126
+
127
+ **Historial de olas**
128
+ - Resolución triplicada: una barra cada 5 minutos en vez de cada 15.
129
+ - Las barras "Ahora" están a la izquierda y el pasado se extiende a la derecha (más intuitivo).
130
+ - Si hay muchas barras hay scroll horizontal con barras más anchas.
131
+ - Escala vertical autoescalable de 0 a 2 m con líneas guía claras a ambos lados.
132
+
133
+ **Ventanas y modales mejorados**
134
+ - Los modales informativos (Escala de exposición, Cómo se calcula la protección, Historial de olas con leyenda y tabla) ahora ocupan casi toda la pantalla con textos cómodos de leer a un metro de distancia bajo la luz del sol.
135
+ - El header de cada modal lleva botón " Atrás" grande y bien visible.
136
+
137
+ **App Store de Signal K**
138
+ - Capturas de pantalla añadidas al paquete — visibles en el App Store de Signal K tras la instalación. La principal es el visor de fondeo en uso real.
139
+
140
+ ### Mejoras de uso (UX)
141
+
142
+ - **Versátil en cualquier pantalla**: del móvil al monitor del puente, el visor reordena y reescala todo para que los controles siempre se puedan tocar cómodamente con el dedo, y los textos sean legibles a la distancia desde la que se usa el dispositivo.
143
+ - Quitado el tooltip molesto "Container ship top view" que salía al pasar el ratón sobre los AIS Class A.
144
+ - El faldón del popup AIS muestra el icono específico del tipo de barco (⛵ velero, 📦 carga, 🛢️ tanque, 🛳️ pasaje, etc.) en vez del genérico.
145
+
146
+ ### Correcciones
147
+
148
+ - Resumen del abrigo ("Abrigado: ninguna de las próximas 12 h…") ahora respeta el idioma del visor en lugar de salir en español cuando la UI está en inglés.
149
+ - El nombre de un barco AIS ya no se pierde si reaparece en el visor sin haber recibido nuevo paquete de identificación.
150
+ - El foco del mapa ya no oscila entre el barco propio y un AIS seleccionado.
151
+ - Al pulsar la X del aro de un AIS, ya no salta accidentalmente la alarma del siguiente barco en zona.
152
+ - El panel "AIS en zona" mantiene fija arriba la cabecera (radio, ordenar, filtro) y solo se mueve la lista al hacer scroll.
153
+ - La rueda del ratón scrollea la lista correctamente desde cualquier parte del panel.
154
+ - Los cambios de pantalla se reflejan al instante tras actualizar el plugin (antes el navegador podía mostrar versión cacheada).
155
+
156
+ ---
157
+
158
+ ## [2.1.11] - 2026-06-13 (pendiente publicación)
159
+
160
+ ### Nuevas funciones
161
+ - **NOAA ENC (EE.UU.)** como capa seleccionable. Servicio WMS Maritime Chart Service del NOAA ENCOnline (`gis.charttools.noaa.gov/.../exts/MaritimeChartService/WMSServer`). Gratis, sin API key. Capas 1-6 activas (naturales+puerto, sondas+corrientes, lecho+obstáculos+pipes, rutas tráfico, áreas especiales, boyas+balizas+faros+radar). Cobertura: aguas costeras EE.UU. (Atlántico, Pacífico, Golfo, Grandes Lagos, Alaska, Hawai, Caribe). Opacidad por defecto 60%. ID interno: `noaa`.
162
+
163
+ ### Cartas no incluidas (notas)
164
+ - **CHS Canadá**: investigada y descartada por ahora. El endpoint NONNA (`nonna-geoserver.api.gc.ca`) está caído/movido. El portal oficial `data.chs-shc.ca` requiere login y no expone WMS público. No hay servicio público sin auth equivalente al de NOAA para Canadá. Se reactivará cuando aparezca alternativa.
165
+
166
+ ### Documentación
167
+ - README: corregido "garreo" → "anchor drag" en la sección de audio inglés (línea 82). Era una fuga del término español dentro del párrafo EN.
168
+
169
+ ## [2.1.10] - 2026-06-10
170
+
171
+ ### Fixes
172
+ - **Alarma meteo activa sin estar fondeado** (feedback Pablo G. Nascimento). `_checkWeatherAlarm` no comprobaba `anch`; quien tuviese el switch ON recibía avisos amarrado al pantalán o navegando. Añadido guard: si no está fondeado, la alarma se fuerza a `false` y el chequeo retorna inmediatamente. La rosa del visor y el historial IMU siguen activos para info general — solo se suprime el aviso/voz/banner.
173
+ - **Rosa de abrigo en marinas con escolleras**: el query Overpass solo buscaba `way["natural"="coastline"]`. En marinas (e.g. Vigo Marina Davila 42.242,-8.724) los espigones están etiquetados como `man_made=breakwater`, `man_made=pier` o `man_made=groyne`, no como costa natural. El cálculo daba "F · 10% protección" para una marina con escolleras gigantes. Ahora el query incluye los tres tipos `man_made` y los trata como obstáculos sólidos en el ray-casting. `ALGORITHM_VERSION` bumpeada a `v76` para invalidar cachés viejas.
174
+
175
+ ### Documentación
176
+ - Nota: las lecturas de olas (intensidad/período/dirección) del IMU son **siempre activas** mientras el plugin corre — son info general útil tanto fondeado como navegando. Los **avisos** (alarma meteo) solo disparan en fondeo. El visor sigue mostrando todos los datos.
177
+
178
+ ## [2.1.5] - 2026-06-03
179
+
180
+ ### Fixes
181
+ - **CRÍTICO: "Cannot set headers after they are sent"** en `/navtiles/:z/:x/:y.png`. El handler hacía `tileResp.pipe(res)` y si la conexión upstream caía mid-stream el `tileReq.on('error')` callback intentaba `res.status(502).send()` cuando los headers ya estaban enviados. Fix: helper `sendFallback()` que comprueba `res.headersSent` antes de enviar; si headers ya fueron enviados, sólo `res.end()` para cerrar el socket limpio. También guard antes de `pipe()` por si `res.headersSent` ya es true al entrar (idempotencia).
182
+ - **Bottom bar Sonda**: el botón solo abría el popup sin llamar `fetchSondaData()` quedaba con "Cargando..." si no se había abierto antes desde el menú. Ahora ambos paths fetchan.
183
+ - **Quality donut mismatch** (visor ↔ shelter): el donut del bottom bar usaba un mapa hardcoded `{A:100, B:80, C:60, ...}` que no coincidía con el % real de `_shelterCache.assessment.scorePercent`. Ahora lee el valor real del cache; fallback al mapa si no hay cache aún.
184
+
185
+ ### Nuevas funciones
186
+ - **Alarma "Mala condición climática"** en panel de alarmas: nuevo selector con switch. Cuando activado, comprueba cada 5 min las próximas 6h del shelter cache buscando viento > 25 kt u ola > 1.5 m, y dispara `setAlarmActive('weather', true)`. Estado persistido en localStorage.
187
+
188
+ ### Traducciones
189
+ - **Wave history popup** (`#wave-hist-info-pop`): título "Historial de olas leyenda y detalle" / "Wave history — legend & details", subtitle, badges Calma/Rizada/Moderada/Agitada/Fuerte → Calm/Rippled/Moderate/Rough/Strong, headers tabla Inicio/Intensidad/Período/Altura/RMS → Start/Intensity/Period/Height/RMS, badge ACTUAL → CURRENT, mensaje "No hay datos todavía...". Ampliado de 620px → 900px y 88vh → 92vh.
190
+ - **Tooltips left bar**: m-ham (Menú/Menu), m-cartas audio toggle, m-snooze, m-fav, m-lb-curvas, m-lb-mareas, m-kip, m-fb — todos con `data-i18n-title`.
191
+
192
+ ## [2.1.4] - 2026-06-03
193
+
194
+ ### Traducciones (i18n)
195
+ - **Panel meteo AHORA** (left card): labels VIENTO/RACHA/AIRE/MAR ahora bilingües (WIND/GUST/AIR/SEA en EN).
196
+ - **Filas tabla meteo**: Aire, Presión, Lluvia, T. Mar, Ola, Período, Dir ola → todas con T() (Air/Pressure/Rain/Sea T./Wave/Period/Wave dir).
197
+ - **Resumen meteo** botón colapsable → bilingüe.
198
+ - **Shelter NOW box**: badges "Veleta" → "Vane", "Sensor" igual ambos; labels racha/aire/agua → gust/air/water.
199
+ - **Eje gráfico presión**: "ahora" → "now".
200
+ - **Labels flotantes visor mapa**: "Viento" → "Wind", "Olas" → "Waves", "Mar en calma" → "Calm sea".
201
+
202
+ ### UI consistente
203
+ - **Estilo unificado del back button** y título de cabecera en TODOS los modales:
204
+ - `.m-back-btn` / `.m-modal-title` classes utility.
205
+ - Back: rgba(255,178,63,.15) bg + 1px border var(--org) + color var(--org) + 18px font + 48px min-height + radius 12px.
206
+ - Title: 28px (antes 38px en m-modal-hdr) — coherente con Anchor Calculation, Shelter, Weather Forecast.
207
+ - `m-modal-hdr .m-back` actualizado a las mismas dimensiones que la clase utility (sin min-width:110px, sin height fija 56px).
208
+ - `m-close-spacer` reducido de 110px 80px para compensar el botón más estrecho.
209
+
210
+ ### Infra i18n
211
+ - `applyLang()` ahora procesa también `data-i18n-title` (atributos title de tooltips) y `data-i18n-placeholder` (placeholders de inputs).
212
+
213
+ ## [2.1.3] - 2026-06-03
214
+
215
+ ### Traducciones
216
+ - Tooltips title="..." del bottom bar (velocidad/viento/sonda/cadena/distancia/presión/abrigo/calidad) y sidebar derecha (anchor/centrar/info/AIS/cartas/abrigo/alarmas/fondeo).
217
+ - Intensidades de ola en la rosa abrigo: Cal/Riz/Mod/Agi/Fue → Calm/Rip/Mod/Rou/Str.
218
+ - Modal "Guardar fondeo favorito": título, hint, placeholder, botones Cancelar/Guardar.
219
+ - Selector modelo meteo "Mejor (automático)" "Best (automatic)".
220
+ - Spinner "Cargando…" "Loading…" en popups Sonda y Meteo.
221
+
222
+ ## [2.1.2] - 2026-06-03
223
+
224
+ ### NPM metadata
225
+ - **Descripción ampliada** del paquete (antes hablaba solo de mareas; ahora menciona anchor watch, AIS, shelter, weather, depth, charts).
226
+ - **~70 keywords en inglés** orientados a búsqueda internacional: anchor-watch, ais-alarm, shelter-forecast, weather-forecast, swing-radius, bathymetry, chartplotter, mbtiles, marine-safety, voice-alarm, etc.
227
+
228
+ ## [2.1.1] - 2026-06-02
229
+
230
+ ### Fixes críticos (alarmas y audio)
231
+ - **State machine de alarmas robusta**: detector de loops huérfanos en `setAlarmActive` — si los timers fueron matados externamente (ACK manual, snooze, cancel-silence cross-device) pero `_activeAlarms[kind]=true` persiste, ahora se re-arman correctamente. Antes el plugin quedaba "atascado" sin sonar nunca más.
232
+ - **30s grace para AIS** antes del primer aviso de voz: modal aparece instant, 30s silencio para reaccionar, luego beep + voz.
233
+ - **ACK/snooze/un-mute = re-arme instantáneo** vía flag `_alarmInstantRearm[kind]` — sin esperar 30s adicionales.
234
+ - **Cortar voz al instante**: arquitectura per-kind (cancel tokens `_voiceCancelTokens`, arrays `_activeVoiceSources` y `_activeVoiceAudios`). HTMLAudio fallback se aborta con `removeAttribute('src')+load()`.
235
+ - **Voz garreo INSTANT** (antes esperaba 30s erróneamente porque `_ALARM_VOICE_PRE_DELAY_MS` era global). Default ahora 0, AIS pasa 30000 explícitamente.
236
+ - **Mute 60s window respetado** incluso por SSE del backend: cuando el usuario muta, `_userMuteUntilMs = Date.now()+60s`; durante esa ventana ni garreo crítico ni el push SSE pueden auto-reactivar.
237
+ - **Vibración fallback** (`navigator.vibrate`) + banner rojo "🔇 Audio bloqueado — TOCA aquí" + visibilitychange resume del AudioContext.
238
+ - **Snooze auto-cancela al levar ancla** (POST `/cancel-silence`).
239
+ - **Snooze sólo aplica si AIS está activo** (no permite snooze durante garreo solo).
240
+
241
+ ### UI / UX
242
+ - **Shelter modal portrait fullscreen REAL** — fix del bug `dvw/dvh` × `zoom: var(--ui-scale)` (gracias Gemini): cambio de unidades `100dvw/100dvh` → `100%/100%` para que se cancelen con el factor zoom del overlay.
243
+ - **Chip numérico de opacidad** encima del thumb del slider: bold 900, font 14px, sombra, oculto durante drag, oculto cuando capa desactivada.
244
+ - **Defaults opacidad** capas: Sat=100, Batimetría=13, IHM=13 (preferencia del usuario).
245
+ - **"SonarChart" "Batimetría"** (cero referencias comerciales). Variable `_navTokenCache` → `_chTokenCache`, comentarios sanitizados en `src/index.ts`.
246
+ - **Triángulos toggle** sidebars apuntan correctamente al borde donde se esconden.
247
+ - **AIS confirm popup** sin truncar título — popups de confirmación corta excluidos del `_mInjectModalHeader` que cortaba con `white-space:nowrap`.
248
+ - Curvas y Mareas solo en left bar (eliminados duplicados sidebar derecha).
249
+ - TidesView centrado fix (`baseW=825, baseH=890` corregidos).
250
+
251
+ ### i18n
252
+ - Info modal completo (Estado, Fondeado/Anchored, etc.).
253
+ - Menú principal (8 items).
254
+ - Bottom bar (Velocidad/Speed, etc.).
255
+ - AIS popup (Acercamiento/Closing, Ancla est./Est. anchor).
256
+ - Shelter (Detección automática, Escala Exposición, Protección, score popup completo, hist olas).
257
+ - Botón ancla Echar/Drop, Levar/Lift.
258
+ - Back buttons del modal-hdr Atrás / Back.
259
+
260
+ ## [2.0.0] - 2026-05-22
261
+
262
+ Salto generacional. Lo que era un plugin de mareas pasa a ser un **visor completo de fondeo** con previsión de abrigo, medición de olas en tiempo real y alarmas en barco y móvil.
263
+
264
+ ### Nuevo
265
+
266
+ **Fondeo seguro**
267
+ - Detección automática de garreo con radio predictivo según la marea.
268
+ - Cálculo de cadena recomendada con dos métodos (tradicional y Vicente).
269
+ - Alarmas configurables: garreo, varada, AIS por proximidad.
270
+ - Track de aproximación al fondeo con gradiente de tiempo.
271
+
272
+ **Previsión de abrigo**
273
+ - Rosa de 16 sectores con detección automática del abrigo según la costa (OpenStreetMap).
274
+ - Grado A-F y porcentaje de protección combinando viento y olas.
275
+ - Strip de 12 h con previsión hora a hora.
276
+ - Resumen "AHORA / PREDICCIÓN" con datos en tiempo real.
277
+
278
+ **Medición de olas en fondeo**
279
+ - Dirección, período y altura de ola medidas a bordo (sensores de actitud y aceleración).
280
+ - Historial de las últimas 24 h.
281
+ - El grado de abrigo se ajusta cuando la ola real supera la prevista.
282
+
283
+ **Sensores en tiempo real**
284
+ - Lectura directa de viento (veleta del barco), temperatura del aire y del agua, presión atmosférica.
285
+ - Etiquetas "Veleta" y "Sensor" para distinguir datos reales de previsión.
286
+ - Fallback automático a Open-Meteo si un sensor falla.
287
+
288
+ **Cartas náuticas integradas**
289
+ - Servidor MBTiles incluido para cargar tus propias cartas en el visor.
290
+
291
+ **Audio mejorado**
292
+ - Voces pregrabadas (OGG) por idioma — más naturales que el sintetizador.
293
+ - Detección automática de la salida de audio del Raspberry Pi.
294
+ - Alarmas distintas por evento (AIS, garreo, varada).
295
+ - Soporte fiable en móvil (incluso con la pestaña en segundo plano).
296
+
297
+ **Mareas IHM**
298
+ - Lista completa actualizada (70 estaciones reales de IHM España).
299
+ - Visor del coeficiente y tendencia (subiendo/bajando) en barra superior.
300
+
301
+ ### Mejoras
302
+
303
+ - Compass cardinal en español (N/NE/E/SE/S/SO/O/NO).
304
+ - Sonda inteligente: cuando se congela o da lecturas absurdas, el visor lo detecta y deja de mostrar valores inventados.
305
+ - Estabilidad mejorada en conexiones débiles (4G/Tailscale).
306
+ - Tolerancia a errores de la API de mareas (no se cuelga con respuestas inesperadas).
307
+
308
+ ### Corregido
309
+
310
+ - Identificadores de estación incorrectos que provocaban errores constantes cuando el plugin arrancaba sin GPS.
311
+ - El visor mostraba "Sonda mínima esperada" obsoleta cuando el sensor de sonda se quedaba congelado.
312
+ - Solapamiento de etiquetas en la rosa cuando viento y oleaje coincidían en dirección.
313
+ - Memoria del navegador a las pocas horas con la capa de viento activa.
314
+
315
+ ---
316
+
317
+ ## [1.3.1] - Versiones anteriores
318
+
319
+ Plugin de mareas IHM España con previsión meteo Open-Meteo y barra de estado superior.