signalk-mareas-ihm 2.1.3 → 2.1.4

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.
@@ -1,7 +1,7 @@
1
1
  {
2
- "version": "2.1.3",
3
- "timestamp": "20260609-0150",
2
+ "version": "2.1.4",
3
+ "timestamp": "20260609-0204",
4
4
  "gitHash": null,
5
5
  "gitDirty": true,
6
- "builtAt": "2026-06-08T23:50:21.804Z"
6
+ "builtAt": "2026-06-09T00:04:55.082Z"
7
7
  }
package/dist/index.js CHANGED
@@ -49,7 +49,7 @@ function isPositionValue(v) {
49
49
  // timestamp + git hash so we can verify exactly which build is running on the Pi
50
50
  // without ambiguity. ("¿Qué versión tengo deployada?" → /api/paths or landing.)
51
51
  const PLUGIN_VERSION = esmRequire("../package.json").version;
52
- const PLUGIN_REVISION = "Rev314";
52
+ const PLUGIN_REVISION = "Rev315";
53
53
  let _buildInfo = null;
54
54
  try {
55
55
  _buildInfo = esmRequire("./build-info.json");
package/dist/mobile.html CHANGED
@@ -755,6 +755,33 @@ body.mobile-ui #m-bottom-bar .m-bb-grade .ic{font-size:10px}
755
755
  body.mobile-ui #m-bottom-bar .m-bb-grade #m-bb-grade{width:28px!important;height:28px!important;font-size:18px!important}
756
756
  body.mobile-ui #m-bottom-bar #m-bb-pres-svg{width:50px!important;height:18px!important}
757
757
 
758
+ /* Rev315: estilos UNIFICADOS de back-button y título en TODAS las ventanas.
759
+ Estas clases utility se pueden aplicar a cualquier botón/título de un modal
760
+ para forzar la misma apariencia visual en todo el plugin. Color principal
761
+ var(--org) naranja, peso 900, tamaño 22px back y 28px título. */
762
+ .m-back-btn{
763
+ background:rgba(255,178,63,.15)!important;
764
+ border:1px solid var(--org)!important;
765
+ color:var(--org)!important;
766
+ font-size:18px!important;
767
+ font-weight:800!important;
768
+ padding:12px 18px!important;
769
+ border-radius:12px!important;
770
+ cursor:pointer!important;
771
+ min-height:48px!important;
772
+ display:inline-flex!important;align-items:center!important;gap:4px!important;
773
+ letter-spacing:-.2px!important;
774
+ }
775
+ .m-back-btn:active{opacity:.6!important;transform:scale(.95)!important}
776
+ .m-modal-title{
777
+ font-size:28px!important;
778
+ font-weight:900!important;
779
+ color:#fff!important;
780
+ letter-spacing:-.3px!important;
781
+ text-align:center!important;
782
+ margin:0!important;
783
+ }
784
+
758
785
  /* === MODALES fullscreen Rev173: contenido MUCHO más grande, sin pinch, sin scroll horizontal === */
759
786
  body.mobile-ui .popup-overlay{
760
787
  align-items:stretch!important;justify-content:stretch!important;
@@ -790,19 +817,24 @@ body.mobile-ui .m-modal-hdr{
790
817
  display:flex;align-items:center;justify-content:space-between;
791
818
  padding:0 12px;
792
819
  }
820
+ /* Rev315: m-back UNIFICADO (alineado con clase utility .m-back-btn). Ya no
821
+ necesita min-width:110px ni height fija — es más compacto y consistente
822
+ con todos los demás botones Back del proyecto (Anchor Calculation, etc). */
793
823
  body.mobile-ui .m-modal-hdr .m-back{
794
824
  background:rgba(255,178,63,.15);border:1px solid var(--org);color:var(--org);
795
- font-size:22px;font-weight:800;cursor:pointer;padding:14px 20px;
796
- display:flex;align-items:center;gap:6px;min-width:110px;height:56px;
797
- border-radius:12px;
825
+ font-size:18px;font-weight:800;cursor:pointer;padding:12px 18px;
826
+ display:flex;align-items:center;gap:4px;min-height:48px;
827
+ border-radius:12px;letter-spacing:-.2px;
798
828
  }
799
829
  body.mobile-ui .m-modal-hdr .m-back:active{opacity:.6;transform:scale(.95)}
830
+ /* Rev315: título UNIFICADO 28px (antes 38px). Coherente con la clase
831
+ utility .m-modal-title y con todos los modales del proyecto. */
800
832
  body.mobile-ui .m-modal-hdr .m-title{
801
- flex:1;text-align:center;font-size:38px;font-weight:900;color:#fff;
833
+ flex:1;text-align:center;font-size:28px;font-weight:900;color:#fff;
802
834
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
803
- padding:0 8px;letter-spacing:-.4px;
835
+ padding:0 8px;letter-spacing:-.3px;
804
836
  }
805
- body.mobile-ui .m-modal-hdr .m-close-spacer{min-width:110px}
837
+ body.mobile-ui .m-modal-hdr .m-close-spacer{min-width:80px}
806
838
 
807
839
  /* === Tipografía GIGANTE dentro de modales (legibilidad marítima de sol) ===
808
840
  Rev183: subimos todo +2-4 px más. El usuario insiste en que todavía
@@ -2023,6 +2055,29 @@ var _i18n={
2023
2055
  sb_abrigo_tip:{es:'Previsión abrigo',en:'Shelter forecast'},
2024
2056
  sb_alarmas_tip:{es:'Panel de alarmas',en:'Alarms panel'},
2025
2057
  sb_fondeo_tip:{es:'Cálculo fondeo',en:'Anchorage calculator'},
2058
+ /* Rev315: meteo panel AHORA + row labels */
2059
+ met_viento:{es:'VIENTO',en:'WIND'},
2060
+ met_aire:{es:'AIRE',en:'AIR'},
2061
+ met_mar:{es:'MAR',en:'SEA'},
2062
+ met_resumen:{es:'Resumen',en:'Summary'},
2063
+ met_row_aire:{es:'Aire',en:'Air'},
2064
+ met_row_presion:{es:'Presión',en:'Pressure'},
2065
+ met_row_lluvia:{es:'Lluvia',en:'Rain'},
2066
+ met_row_tmar:{es:'T. Mar',en:'Sea T.'},
2067
+ met_row_ola:{es:'Ola',en:'Wave'},
2068
+ met_row_periodo:{es:'Período',en:'Period'},
2069
+ met_row_dirola:{es:'Dir ola',en:'Wave dir'},
2070
+ /* Rev315: shelter NOW box */
2071
+ sh_veleta:{es:'Veleta',en:'Vane'},
2072
+ sh_sensor:{es:'Sensor',en:'Sensor'},
2073
+ sh_racha:{es:'racha',en:'gust'},
2074
+ sh_aire:{es:'aire',en:'air'},
2075
+ sh_agua:{es:'agua',en:'water'},
2076
+ m_ahora_low:{es:'ahora',en:'now'},
2077
+ /* Rev315: labels flotantes visor (mapa) */
2078
+ m_viento:{es:'Viento',en:'Wind'},
2079
+ m_olas:{es:'Olas',en:'Waves'},
2080
+ m_mar_calma:{es:'Mar en calma',en:'Calm sea'},
2026
2081
  /* Rev313: modal guardar favorito */
2027
2082
  fav_guardar_title:{es:'❤ Guardar fondeo favorito',en:'❤ Save favourite anchorage'},
2028
2083
  fav_guardar_hint:{es:'Nombre del favorito (vacío = nombre automático por geolocalización):',en:'Favourite name (empty = auto name by geolocation):'},
@@ -5324,8 +5379,11 @@ function _shelterRenderPopup(){
5324
5379
  temperaturas. Sin sensor → forecast Open-Meteo (sin badge).
5325
5380
  _BADGE_VELETA y _BADGE_SENSOR son verdes (#3aa856), mismo tono que
5326
5381
  el badge "IMU" pre-existente para coherencia visual. */
5327
- var _BADGE_VELETA=' <span style="color:#3aa856;font-size:11px;font-weight:800;margin-left:4px">Veleta</span>';
5328
- var _BADGE_SENSOR=' <span style="color:#3aa856;font-size:10px;font-weight:800;margin-left:3px">Sensor</span>';
5382
+ /* Rev315: badges Veleta/Sensor i18n. */
5383
+ var _badgeVeletaTxt=(typeof T==='function')?T('sh_veleta','Veleta'):'Veleta';
5384
+ var _badgeSensorTxt=(typeof T==='function')?T('sh_sensor','Sensor'):'Sensor';
5385
+ var _BADGE_VELETA=' <span style="color:#3aa856;font-size:11px;font-weight:800;margin-left:4px">'+_badgeVeletaTxt+'</span>';
5386
+ var _BADGE_SENSOR=' <span style="color:#3aa856;font-size:10px;font-weight:800;margin-left:3px">'+_badgeSensorTxt+'</span>';
5329
5387
  var _useSensorWind=isNow&&_boatWind;
5330
5388
  var _useSensorEnv=isNow&&_envSensors;
5331
5389
  var stWindKt,stDirDeg,windBadge;
@@ -5481,7 +5539,7 @@ function _shelterRenderPopup(){
5481
5539
  var axis=
5482
5540
  '<text x="'+x_24h.toFixed(1)+'" y="'+(H-6)+'" text-anchor="start" fill="rgba(255,255,255,.78)" font-size="13" font-weight="700">-24 h</text>'+
5483
5541
  '<text x="'+x_12h.toFixed(1)+'" y="'+(H-6)+'" text-anchor="middle" fill="rgba(255,255,255,.65)" font-size="13" font-weight="700">-12 h</text>'+
5484
- '<text x="'+nowX.toFixed(1)+'" y="'+(H-6)+'" text-anchor="middle" fill="#ffeb3b" font-size="13" font-weight="900">ahora</text>'+
5542
+ '<text x="'+nowX.toFixed(1)+'" y="'+(H-6)+'" text-anchor="middle" fill="#ffeb3b" font-size="13" font-weight="900">'+((typeof T==='function')?T('m_ahora_low','ahora'):'ahora')+'</text>'+
5485
5543
  '<text x="'+x_max.toFixed(1)+'" y="'+(H-6)+'" text-anchor="end" fill="rgba(255,235,59,.85)" font-size="13" font-weight="800">+'+maxFutureH+' h</text>'+
5486
5544
  '<text x="2" y="'+(padTop+10)+'" text-anchor="start" fill="rgba(255,255,255,.6)" font-size="11" font-weight="700">'+Math.round(pMax)+'</text>'+
5487
5545
  '<text x="2" y="'+(H-padBot-2)+'" text-anchor="start" fill="rgba(255,255,255,.6)" font-size="11" font-weight="700">'+Math.round(pMin)+'</text>';
@@ -5525,11 +5583,13 @@ function _shelterRenderPopup(){
5525
5583
  /* Rev128: reorden infobox — wind, gust, wave, TEMPS, pressure-num, sparkline.
5526
5584
  La sparkline queda al final para visual cleanliness (es el elemento más
5527
5585
  alto y rompía si quedaba en medio). */
5586
+ /* Rev315: labels i18n (racha/aire/agua). */
5587
+ var _ts=function(k,fb){ return (typeof T==='function')?T(k,fb):fb; };
5528
5588
  statusBody.innerHTML=
5529
5589
  '<div>🌬 <b style="font-size:24px">'+Math.round(stWindKt)+' kt</b> <span style="color:#9ad">'+stDir+'</span>'+windBadge+'</div>'+
5530
- '<div>💨 racha <b style="font-size:21px">'+Math.round(stGustKt)+' kt</b>'+gustBadge+'</div>'+
5590
+ '<div>💨 '+_ts('sh_racha','racha')+' <b style="font-size:21px">'+Math.round(stGustKt)+' kt</b>'+gustBadge+'</div>'+
5531
5591
  '<div>'+waveLine+'</div>'+
5532
- '<div>🌡 aire <b style="font-size:20px">'+tempA+'</b>'+tempABadge+' &nbsp;&nbsp; 🌊 agua <b style="font-size:20px">'+tempW+'</b>'+tempWBadge+'</div>'+
5592
+ '<div>🌡 '+_ts('sh_aire','aire')+' <b style="font-size:20px">'+tempA+'</b>'+tempABadge+' &nbsp;&nbsp; 🌊 '+_ts('sh_agua','agua')+' <b style="font-size:20px">'+tempW+'</b>'+tempWBadge+'</div>'+
5533
5593
  pressureNumLine+
5534
5594
  sparkRow;
5535
5595
  /* Botón AHORA: resaltado si NO hay hora seleccionada */
@@ -5896,7 +5956,7 @@ function _wxMapMarkerUpdate(){
5896
5956
  if(_wDeg!==null){
5897
5957
  var wEdge=geoEdge(pos.lat,pos.lng,alarmR,_wDeg);
5898
5958
  var wDirTxt=_wxC16?_wxC16(_wDeg):'';
5899
- var wLabel='Viento '+(wDirTxt?wDirTxt+' ':'')+Math.round(_wKt)+' kt';
5959
+ var wLabel=((typeof T==='function')?T('m_viento','Viento'):'Viento')+' '+(wDirTxt?wDirTxt+' ':'')+Math.round(_wKt)+' kt';
5900
5960
  var html=_wxMarkerHtml('#ffeb3b',wLabel,_wDeg,'wind',_labOffW);
5901
5961
  var icon=L.divIcon({html:html,iconSize:[1,1],iconAnchor:[0,0],className:'wx-map-marker'});
5902
5962
  if(_wxMapMarkers.wind){_wxMapMarkers.wind.setIcon(icon);_wxMapMarkers.wind.setLatLng(wEdge);_wxMapMarkers.wind.setZIndexOffset(300);if(!map.hasLayer(_wxMapMarkers.wind))_wxMapMarkers.wind.addTo(map);}
@@ -5910,13 +5970,12 @@ function _wxMapMarkerUpdate(){
5910
5970
  var oEdge=geoEdge(pos.lat,pos.lng,alarmR,_vDirEff);
5911
5971
  var oDirTxt=_wxC16?_wxC16(_vDirEff):'';
5912
5972
  var oLabel;
5973
+ /* Rev315: labels "Olas" y "Mar en calma" i18n. */
5974
+ var _tw=function(k,fb){ return (typeof T==='function')?T(k,fb):fb; };
5913
5975
  if(_boatWave){
5914
- /* Rev128: si la ola es despreciable (intensidad calma), no marear con
5915
- direcciones y períodos cortos sin sentido — decir simplemente
5916
- "Mar en calma". Si hay movimiento medible, mostrar altura+dir+período. */
5917
5976
  var _vbCalm=(_boatWave.intensity==='calma')&&(typeof _boatWave.heightSigM!=='number'||_boatWave.heightSigM<0.05);
5918
5977
  if(_vbCalm){
5919
- oLabel='Mar en calma';
5978
+ oLabel=_tw('m_mar_calma','Mar en calma');
5920
5979
  }else{
5921
5980
  var _vbPer=(typeof _boatWave.periodSec==='number'&&_boatWave.periodSec>0)?Math.round(_boatWave.periodSec)+'s':'';
5922
5981
  var _vbMain;
@@ -5925,10 +5984,10 @@ function _wxMapMarkerUpdate(){
5925
5984
  }else{
5926
5985
  _vbMain=(_boatWave.intensity||'').charAt(0).toUpperCase()+(_boatWave.intensity||'').slice(1);
5927
5986
  }
5928
- oLabel='Olas '+(oDirTxt?oDirTxt+' ':'')+_vbMain+(_vbPer?' · '+_vbPer:'');
5987
+ oLabel=_tw('m_olas','Olas')+' '+(oDirTxt?oDirTxt+' ':'')+_vbMain+(_vbPer?' · '+_vbPer:'');
5929
5988
  }
5930
5989
  }else{
5931
- oLabel='Olas '+(oDirTxt?oDirTxt+' ':'')+h.waveHeightM.toFixed(1).replace('.',',')+' m'+(h.wavePeriodSec>0?' · '+Math.round(h.wavePeriodSec)+' s':'');
5990
+ oLabel=_tw('m_olas','Olas')+' '+(oDirTxt?oDirTxt+' ':'')+h.waveHeightM.toFixed(1).replace('.',',')+' m'+(h.wavePeriodSec>0?' · '+Math.round(h.wavePeriodSec)+' s':'');
5932
5991
  }
5933
5992
  var oHtml=_wxMarkerHtml('#4dd0ff',oLabel,_vDirEff,'wave',_labOffV);
5934
5993
  var oIcon=L.divIcon({html:oHtml,iconSize:[1,1],iconAnchor:[0,0],className:'wx-map-marker'});
@@ -9033,12 +9092,14 @@ function m_renderMeteoWindy(d, seaD){
9033
9092
  var nowColW = (nowWindKt!=null) ? wColor(nowWindKt) : '#fff';
9034
9093
  var nowColG = (nowGustKt!=null) ? wColor(nowGustKt) : '#fff';
9035
9094
  /* Rev238: panel AHORA — sin iconos en labels (limpio). */
9095
+ /* Rev315: AHORA panel — labels i18n. */
9096
+ var _tn = function(k,fb){ return (typeof T==='function')?T(k,fb):fb; };
9036
9097
  var nowPanelHtml =
9037
9098
  '<div style="display:flex;flex-direction:column;height:100%;background:var(--bg);border:3px solid var(--org);box-sizing:border-box">' +
9038
- '<div style="background:var(--org);color:#000;font-size:22px;font-weight:900;text-align:center;padding:4px 4px;letter-spacing:2px;line-height:1">AHORA</div>' +
9099
+ '<div style="background:var(--org);color:#000;font-size:22px;font-weight:900;text-align:center;padding:4px 4px;letter-spacing:2px;line-height:1">'+_tn('m_ahora','AHORA')+'</div>' +
9039
9100
  '<div style="display:grid;grid-template-columns:1fr 1fr;grid-template-rows:1fr 1fr;flex:1;gap:0;color:#fff;text-align:center">' +
9040
9101
  '<div style="border-right:1px solid rgba(255,255,255,.4);border-bottom:1px solid rgba(255,255,255,.4);padding:4px 4px;display:flex;flex-direction:column;justify-content:center">' +
9041
- '<div style="font-size:16px;color:var(--org);font-weight:700;letter-spacing:1px;line-height:1">VIENTO'+srcBadge(srcWind)+'</div>' +
9102
+ '<div style="font-size:16px;color:var(--org);font-weight:700;letter-spacing:1px;line-height:1">'+_tn('met_viento','VIENTO').toUpperCase()+srcBadge(srcWind)+'</div>' +
9042
9103
  '<div style="font-size:32px;font-weight:900;color:#fff;line-height:1.05;display:flex;align-items:center;justify-content:center;gap:4px">'+
9043
9104
  '<span>'+fmtKt(nowWindKt)+'</span>'+
9044
9105
  '<span style="font-size:14px;color:#9aa;font-weight:700">kt</span>'+
@@ -9046,15 +9107,15 @@ function m_renderMeteoWindy(d, seaD){
9046
9107
  '</div>' +
9047
9108
  '</div>' +
9048
9109
  '<div style="border-bottom:1px solid rgba(255,255,255,.4);padding:4px 4px;display:flex;flex-direction:column;justify-content:center">' +
9049
- '<div style="font-size:16px;color:var(--org);font-weight:700;letter-spacing:1px;line-height:1">RACHA'+srcBadge(srcGust)+'</div>' +
9110
+ '<div style="font-size:16px;color:var(--org);font-weight:700;letter-spacing:1px;line-height:1">'+_tn('met_racha','RACHA').toUpperCase()+srcBadge(srcGust)+'</div>' +
9050
9111
  '<div style="font-size:32px;font-weight:900;color:#fff;line-height:1.05">'+fmtKt(nowGustKt)+'<span style="font-size:14px;color:#9aa;font-weight:700"> kt</span></div>' +
9051
9112
  '</div>' +
9052
9113
  '<div style="border-right:1px solid rgba(255,255,255,.4);padding:4px 4px;display:flex;flex-direction:column;justify-content:center">' +
9053
- '<div style="font-size:16px;color:var(--org);font-weight:700;letter-spacing:1px;line-height:1">AIRE'+srcBadge(srcAir)+'</div>' +
9114
+ '<div style="font-size:16px;color:var(--org);font-weight:700;letter-spacing:1px;line-height:1">'+_tn('met_aire','AIRE').toUpperCase()+srcBadge(srcAir)+'</div>' +
9054
9115
  '<div style="font-size:32px;font-weight:900;color:#fff;line-height:1.05">'+fmtT(nowTAir)+'</div>' +
9055
9116
  '</div>' +
9056
9117
  '<div style="padding:4px 4px;display:flex;flex-direction:column;justify-content:center">' +
9057
- '<div style="font-size:16px;color:var(--org);font-weight:700;letter-spacing:1px;line-height:1">MAR'+srcBadge(srcSea)+'</div>' +
9118
+ '<div style="font-size:16px;color:var(--org);font-weight:700;letter-spacing:1px;line-height:1">'+_tn('met_mar','MAR').toUpperCase()+srcBadge(srcSea)+'</div>' +
9058
9119
  '<div style="font-size:32px;font-weight:900;color:#fff;line-height:1.05">'+fmtT(nowTSea)+'</div>' +
9059
9120
  '</div>' +
9060
9121
  '</div>' +
@@ -9203,32 +9264,27 @@ function m_renderMeteoWindy(d, seaD){
9203
9264
  if (kn == null) return '–';
9204
9265
  return '<span style="color:'+wColor(kn)+';font-size:32px">'+kn.toFixed(0)+'</span>';
9205
9266
  });
9206
- /* Aire */
9207
- if (h.temperature_2m) rows += rowMetric('Aire','🌡️','#ffb23f','°C',
9267
+ /* Rev315: row labels i18n. */
9268
+ var _tr=function(k,fb){ return (typeof T==='function')?T(k,fb):fb; };
9269
+ if (h.temperature_2m) rows += rowMetric(_tr('met_row_aire','Aire'),'🌡️','#ffb23f','°C',
9208
9270
  function(col){ return getVal(h.temperature_2m, col); },
9209
9271
  function(v){ return v==null?'–':'<span style="font-size:30px">'+v.toFixed(0)+'°</span>'; });
9210
- /* Presión */
9211
- if (h.pressure_msl || h.surface_pressure) rows += rowMetric('Presión','🔵','#9ad','mbar',
9272
+ if (h.pressure_msl || h.surface_pressure) rows += rowMetric(_tr('met_row_presion','Presión'),'🔵','#9ad','mbar',
9212
9273
  function(col){ return getVal(h.pressure_msl || h.surface_pressure, col); },
9213
9274
  function(v){ return v==null?'–':'<span style="font-size:26px">'+Math.round(v)+'</span>'; });
9214
- /* Lluvia */
9215
- if (h.precipitation || h.rain) rows += rowMetric('Lluvia','💧','#4dd0ff','mm',
9275
+ if (h.precipitation || h.rain) rows += rowMetric(_tr('met_row_lluvia','Lluvia'),'💧','#4dd0ff','mm',
9216
9276
  function(col){ return getVal(h.precipitation || h.rain, col); },
9217
9277
  function(v){ return (v==null||v===0)?'–':'<span style="font-size:28px">'+v.toFixed(1)+'</span>'; });
9218
- /* T. Mar */
9219
- if (seaH.sea_surface_temperature) rows += rowMetric('T. Mar','🐟','#4dd0ff','°C',
9278
+ if (seaH.sea_surface_temperature) rows += rowMetric(_tr('met_row_tmar','T. Mar'),'🐟','#4dd0ff','°C',
9220
9279
  function(col){ return getSeaVal(seaH.sea_surface_temperature, col); },
9221
9280
  function(v){ return v==null?'–':'<span style="font-size:30px">'+v.toFixed(0)+'°</span>'; });
9222
- /* Ola altura */
9223
- if (seaH.wave_height) rows += rowMetric('Ola','🌊','#4dd0ff','m',
9281
+ if (seaH.wave_height) rows += rowMetric(_tr('met_row_ola','Ola'),'🌊','#4dd0ff','m',
9224
9282
  function(col){ return getSeaVal(seaH.wave_height, col); },
9225
9283
  function(v){ return v==null?'–':'<span style="font-size:30px">'+v.toFixed(1)+'</span>'; });
9226
- /* Período */
9227
- if (seaH.wave_period) rows += rowMetric('Período','⏱️','#9ad','s',
9284
+ if (seaH.wave_period) rows += rowMetric(_tr('met_row_periodo','Período'),'⏱️','#9ad','s',
9228
9285
  function(col){ return getSeaVal(seaH.wave_period, col); },
9229
9286
  function(v){ return v==null?'–':'<span style="font-size:28px">'+Math.round(v)+'</span>'; });
9230
- /* Dir ola número de grados + flecha rotada pequeña (Rev228). */
9231
- if (seaH.wave_direction) rows += rowMetric('Dir ola','🧭','#4dd0ff','°',
9287
+ if (seaH.wave_direction) rows += rowMetric(_tr('met_row_dirola','Dir ola'),'🧭','#4dd0ff','°',
9232
9288
  function(col){ return getSeaVal(seaH.wave_direction, col); },
9233
9289
  function(v){
9234
9290
  if (v == null) return '–';
@@ -9338,7 +9394,7 @@ function m_renderMeteoWindy(d, seaD){
9338
9394
  try { collapsed = localStorage.getItem('m-met-summary-collapsed') === '1'; } catch(_){}
9339
9395
  return '<div id="m-met-summary" class="' + (collapsed ? 'collapsed' : '') + '" style="background:rgba(20,40,60,.7);border-top:2px solid var(--org);color:#dde;flex-shrink:0">' +
9340
9396
  '<button id="m-met-summary-toggle" onclick="m_toggleMeteoSummary()" style="display:flex;align-items:center;justify-content:space-between;width:100%;background:none;border:none;color:var(--org);font-size:28px;font-weight:900;padding:18px 24px;cursor:pointer;text-align:left">' +
9341
- '<span>📰 Resumen</span>' +
9397
+ '<span>📰 '+((typeof T==='function')?T('met_resumen','Resumen'):'Resumen')+'</span>' +
9342
9398
  '<span id="m-met-summary-chev" style="font-size:24px">' + (collapsed ? '▼' : '▲') + '</span>' +
9343
9399
  '</button>' +
9344
9400
  '<div id="m-met-summary-body" style="padding:0 24px 18px;font-size:24px;line-height:1.55;' + (collapsed ? 'display:none' : '') + '">' +
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "signalk-mareas-ihm",
3
- "version": "2.1.3",
3
+ "version": "2.1.4",
4
4
  "description": "Complete SignalK anchor watch & marine safety webapp. Voice alarms for anchor drag, AIS collision risk and grounding. Shelter / anchorage forecast (wind exposure + wave history). Weather forecast (Open-Meteo). Depth & scope calculator. Multi-source nautical charts (Esri Satellite, IHM ENC S-52, bathymetry, MBTiles offline, OpenStreetMap, OpenSeaMap). Favourite anchorages. Multi-device real-time sync (SSE). Includes official IHM Spain tide predictions. Mobile-first UI in ES/EN.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",