@sailingrotevista/rotevista-dash 6.0.8 → 6.0.11

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/app.js CHANGED
@@ -115,6 +115,15 @@ function getShortestRotation(curr, target) {
115
115
  return curr + diff;
116
116
  }
117
117
 
118
+ /**
119
+ * Scrive il testo nel DOM solo se il valore è realmente cambiato (Evita layout reflow inutili)
120
+ */
121
+ function safeSetText(el, text) {
122
+ if (el && el.innerText !== text) {
123
+ el.innerText = text;
124
+ }
125
+ }
126
+
118
127
  /**
119
128
  * Inserimento sicuro nel buffer con trigonometria precaricata e pruning automatico
120
129
  */
@@ -614,7 +623,7 @@ function startDisplayLoop() {
614
623
 
615
624
  // --- AGGIORNAMENTO VELOCITÀ SULL'ACQUA (STW) ---
616
625
  if (store.raw["navigation.speedThroughWater"] !== undefined) {
617
- ui.stw.innerText = stwKts.toFixed(1);
626
+ safeSetText(ui.stw, stwKts.toFixed(1));
618
627
  ui.stw.style.color = ""; // Neutro
619
628
  manageHistory('stw', stwKts);
620
629
  }
@@ -627,11 +636,11 @@ function startDisplayLoop() {
627
636
 
628
637
  const labelSogVmg = document.getElementById('sog-vmg-label');
629
638
  if (displayModeSog === 'VMG') {
630
- ui.sog.innerText = vmgVal.toFixed(1);
639
+ safeSetText(ui.sog, vmgVal.toFixed(1));
631
640
  ui.sog.style.setProperty('color', '#00b8d4', 'important'); // Cyan
632
641
  if (labelSogVmg) labelSogVmg.textContent = 'VMG';
633
642
  } else {
634
- ui.sog.innerText = sogKts.toFixed(1);
643
+ safeSetText(ui.sog, sogKts.toFixed(1));
635
644
  if (labelSogVmg) labelSogVmg.textContent = 'SOG';
636
645
 
637
646
  if (isNavigating) {
@@ -650,7 +659,7 @@ function startDisplayLoop() {
650
659
 
651
660
  // --- AGGIORNAMENTO PROFONDITÀ (DEPTH) ---
652
661
  if (store.raw["environment.depth.belowTransducer"] !== undefined) {
653
- ui.depth.innerText = store.raw["environment.depth.belowTransducer"].toFixed(1);
662
+ safeSetText(ui.depth, store.raw["environment.depth.belowTransducer"].toFixed(1));
654
663
  checkDepthAlarm(store.raw["environment.depth.belowTransducer"]);
655
664
  manageHistory('depth', store.raw["environment.depth.belowTransducer"]);
656
665
  }
@@ -666,7 +675,7 @@ function startDisplayLoop() {
666
675
  const labelWind = document.getElementById('tws-aws-label');
667
676
  const currentWind = (displayModeTws === 'AWS') ? awsVal : twsVal;
668
677
 
669
- ui.tws.innerText = currentWind.toFixed(1);
678
+ safeSetText(ui.tws, currentWind.toFixed(1));
670
679
  if (labelWind) labelWind.textContent = displayModeTws;
671
680
 
672
681
  if (currentWind >= CONFIG.graphs.reef2) {
@@ -684,7 +693,7 @@ function startDisplayLoop() {
684
693
  }
685
694
 
686
695
  if (store.raw["environment.wind.speedApparent"] !== undefined) {
687
- ui.awsSvg.textContent = awsVal.toFixed(1);
696
+ safeSetText(ui.awsSvg, awsVal.toFixed(1));
688
697
  }
689
698
 
690
699
  // --- PUNTATORI ANALOGICI ---
@@ -702,9 +711,8 @@ function startDisplayLoop() {
702
711
  updateLeewayDisplay(Math.max(-20, Math.min(20, smoothedLeeway)));
703
712
  }
704
713
 
705
- // --- HEAVY TIER (2s) E SLOW TIER (3s) ---
706
- if (lastAvgUIUpdate++ % 2 === 0) {
707
- ['stw', 'sog', 'depth', 'tws'].forEach(refreshGraph);
714
+ // --- SLOW TIER (Salvataggio stato ogni 10 secondi) ---
715
+ if (lastAvgUIUpdate++ % 10 === 0) {
708
716
  saveDashboardState();
709
717
  }
710
718
 
@@ -949,6 +957,10 @@ function manageHistory(type, value) {
949
957
 
950
958
  // --- 7. STORAGE STORICO ---
951
959
  store.histories[type].push({ val: finalValue, time: now });
960
+
961
+ // --- TRIGGER STRATEGIA 1 (EVENT-DRIVEN) ---
962
+ // Ridisegnamo lo strumento SOLO nell'esatto istante in cui viene generato un nuovo punto storico!
963
+ refreshGraph(type);
952
964
 
953
965
  // --- 8. PRUNING DINAMICO ---
954
966
  const maxViewportMinutes = historyMinutes * 2;
@@ -958,9 +970,8 @@ function manageHistory(type, value) {
958
970
  store.histories[type].shift();
959
971
  }
960
972
 
961
- // Reset per il prossimo bucket
973
+ // Reset per il prossimo bucket (sincronizzato)
962
974
  store.graphTempBuf[type] = [];
963
- // Spostiamo il timer esattamente al confine del secchiello assoluto appena concluso
964
975
  store.lastUpdates[type] = Math.floor(now / bucketIntervalMs) * bucketIntervalMs;
965
976
  }
966
977
 
@@ -1018,30 +1029,36 @@ function calculateScale(type, data, mode) {
1018
1029
  return { min: 0, max: Math.max(s.stdMax, Math.ceil(maxHistorico / s.step) * s.step) };
1019
1030
  }
1020
1031
 
1021
- // --- 1.2 HERCULES PROFONDITÀ (0 IN BASSO, SNAP SUL MAX SENZA PADDING) ---
1032
+ // --- 1.2 HERCULES PROFONDITÀ (BASE 0 IN ACQUE BASSE, FLUTTUANTE AL LARGO) ---
1022
1033
  if (mode === 'hercules') {
1023
1034
  const roundStep = s.hercSpan; // Passo di griglia selezionato dall'utente
1035
+ const shallowThreshold = Math.max(s.stdMax, 10); // Es. 20m
1024
1036
 
1025
1037
  let targetMin = 0;
1038
+ // Se siamo in acque profonde, lasciamo che il minimo fluttui per mostrare i micro-dettagli
1039
+ if (localMin > shallowThreshold) {
1040
+ targetMin = Math.max(0, Math.floor(localMin / roundStep) * roundStep);
1041
+ }
1042
+
1026
1043
  let targetMax = Math.ceil(localMax / roundStep) * roundStep;
1027
1044
 
1028
- // Impediamo una scala inferiore a 4 metri per sicurezza visiva
1029
- const absoluteMinSpan = 4;
1030
- if (targetMax < absoluteMinSpan) {
1031
- targetMax = absoluteMinSpan;
1045
+ // Impediamo uno span inferiore a 4 metri per evitare grafici piatti
1046
+ if (targetMax - targetMin < 4) {
1047
+ targetMax = targetMin + 4;
1032
1048
  }
1033
1049
 
1034
- // Regola asimmetrica per il MAX (Espansione istantanea, contrazione a 2 minuti)
1035
- if (currentVal > currentScale.max) {
1036
- currentScale.max = targetMax;
1050
+ // Regola asimmetrica per il MIN e il MAX (Espansione istantanea, contrazione a 2 minuti)
1051
+ if (currentVal < currentScale.min || currentVal > currentScale.max) {
1052
+ currentScale.min = Math.min(currentScale.min, targetMin);
1053
+ currentScale.max = Math.max(currentScale.max, targetMax);
1037
1054
  } else {
1038
- const allStableInTarget = recentVals.every(val => val <= targetMax);
1055
+ const allStableInTarget = recentVals.every(val => val >= targetMin && val <= targetMax);
1039
1056
  if (allStableInTarget) {
1057
+ currentScale.min = targetMin;
1040
1058
  currentScale.max = targetMax;
1041
1059
  }
1042
1060
  }
1043
1061
 
1044
- currentScale.min = 0;
1045
1062
  return { min: currentScale.min, max: currentScale.max };
1046
1063
  }
1047
1064
  }
@@ -1100,10 +1117,21 @@ function updateScaleLabels(t, min, max) {
1100
1117
  }
1101
1118
 
1102
1119
  /**
1103
- * refreshGraph: Recupero dati, switch AWS/TWS e passaggio a motore grafico.
1120
+ * refreshGraph: Recupero dati, switch AWS/TWS/VMG e passaggio a motore grafico.
1121
+ * Redirige e protegge i canali secondari (AWS/VMG) evitando ridisegni inutili.
1104
1122
  */
1105
1123
  function refreshGraph(t) {
1106
- const boxType = (t === 'vmg') ? 'sog' : t;
1124
+ // Redirezione di sicurezza dei canali secondari (AWS / VMG) verso i contenitori principali
1125
+ if (t === 'aws') {
1126
+ if (displayModeTws !== 'AWS') return; // Se non stiamo visualizzando AWS a schermo, ignora il rinfresco
1127
+ t = 'tws';
1128
+ }
1129
+ if (t === 'vmg') {
1130
+ if (displayModeSog !== 'VMG') return; // Se non stiamo visualizzando VMG a schermo, ignora il rinfresco
1131
+ t = 'sog';
1132
+ }
1133
+
1134
+ const boxType = t;
1107
1135
  let rawData;
1108
1136
 
1109
1137
  if (t === 'tws' && displayModeTws === 'AWS') {
@@ -1128,6 +1156,7 @@ function refreshGraph(t) {
1128
1156
  /**
1129
1157
  * drawGraph: Motore SVG con Timeline Reale e Gestione GAP
1130
1158
  * Risolve i conflitti di orologio (Clock Drift) tra Cerbo GX e Tablet.
1159
+ * Integra la reattività dello spessore della curva in modalità Dual Screen (Focus).
1131
1160
  */
1132
1161
  function drawGraph(d, id, min, max, isTws, isHercules) {
1133
1162
  const svg = document.getElementById(id);
@@ -1142,6 +1171,10 @@ function drawGraph(d, id, min, max, isTws, isHercules) {
1142
1171
  const latestPoint = d[d.length - 1];
1143
1172
  const now = latestPoint ? latestPoint.time : Date.now();
1144
1173
 
1174
+ // --- RILEVAMENTO DINAMICO DUAL SCREEN BLINDATO ---
1175
+ const box = svg.closest('.data-box');
1176
+ const isFocused = isFocusActive && box && box.classList.contains('is-focused');
1177
+
1145
1178
  const visibleMinutes = CONFIG.graphs.historyMinutes * (isNavigating ? 1 : 2);
1146
1179
  const viewportMs = visibleMinutes * 60000;
1147
1180
  const viewportStart = now - viewportMs;
@@ -1153,15 +1186,20 @@ function drawGraph(d, id, min, max, isTws, isHercules) {
1153
1186
  const colDepth = "#0088cc", colStw = "#00C851", colSog = "#ffbb33", colVmg = "#00b8d4";
1154
1187
 
1155
1188
  const getColorProps = (val) => {
1156
- let color = colTws, opacity = "0.15", stroke = "1";
1189
+ // Se siamo in Dual Screen (focus), aumentiamo lo spessore base della curva di un filino (da 1.6 a 2.2)
1190
+ const baseStroke = isFocused ? "4.2" : "1.6";
1191
+ const alertStroke = isFocused ? "4.8" : "2.2";
1192
+ const warnStroke = isFocused ? "4.4" : "1.8";
1193
+
1194
+ let color = colTws, opacity = "0.15", stroke = baseStroke;
1157
1195
  if (isTws) {
1158
1196
  const baseWind = (displayModeTws === 'AWS') ? colAws : colTws;
1159
- if (val >= CONFIG.graphs.reef2) { color = colDanger; opacity = "0.55"; stroke = "1.2"; }
1160
- else if (val >= CONFIG.graphs.reef1) { color = colWarning; opacity = "0.45"; stroke = "1"; }
1197
+ if (val >= CONFIG.graphs.reef2) { color = colDanger; opacity = "0.55"; stroke = alertStroke; }
1198
+ else if (val >= CONFIG.graphs.reef1) { color = colWarning; opacity = "0.45"; stroke = warnStroke; }
1161
1199
  else color = baseWind;
1162
1200
  } else if (isDepth) {
1163
- if (val < CONFIG.alarms.depthDanger) { color = colDanger; opacity = "0.55"; stroke = "1.2"; }
1164
- else if (val < CONFIG.alarms.depthWarning) { color = colWarning; opacity = "0.45"; stroke = "1"; }
1201
+ if (val < CONFIG.alarms.depthDanger) { color = colDanger; opacity = "0.55"; stroke = alertStroke; }
1202
+ else if (val < CONFIG.alarms.depthWarning) { color = colWarning; opacity = "0.45"; stroke = warnStroke; }
1165
1203
  else color = colDepth;
1166
1204
  } else {
1167
1205
  if (id === 'stw-graph') color = colStw;
@@ -1171,14 +1209,37 @@ function drawGraph(d, id, min, max, isTws, isHercules) {
1171
1209
  };
1172
1210
 
1173
1211
  let grids = "";
1174
- // Tracciamo 3 linee simmetriche al 25%, 50% (centrale) e 75%.
1175
- // La linea al 50% passerà sempre in modo matematicamente esatto dietro il valore medio stampato.
1176
- [0.25, 0.5, 0.75].forEach(p => grids += `<line x1="0" y1="${h-(p*h)}" x2="${w}" y2="${h-(p*h)}" stroke="rgba(0,0,0,0.12)" stroke-width="0.5" />`);
1212
+ // --- GRIGLIE ORIZZONTALI (Spessore fisso a 0.5px, non deformabile) ---
1213
+ [0.25, 0.5, 0.75].forEach(p => grids += `<line x1="0" y1="${h-(p*h)}" x2="${w}" y2="${h-(p*h)}" stroke="rgba(0,0,0,0.12)" stroke-width="0.5" vector-effect="non-scaling-stroke" />`);
1177
1214
 
1215
+ // --- GRIGLIE VERTICALI (Spessore fisso a 0.4px, non deformabile) ---
1178
1216
  const gridInterval = (visibleMinutes <= 15) ? 1 : 5;
1179
1217
  for (let m = gridInterval; m < visibleMinutes; m += gridInterval) {
1180
1218
  const x = w - ((m / visibleMinutes) * w);
1181
- grids += `<line x1="${x}" y1="0" x2="${x}" y2="${h}" stroke="rgba(0,0,0,0.08)" stroke-width="0.5" />`;
1219
+ grids += `<line x1="${x}" y1="0" x2="${x}" y2="${h}" stroke="rgba(0,0,0,0.08)" stroke-width="0.4" vector-effect="non-scaling-stroke" />`;
1220
+ }
1221
+
1222
+ // --- DISEGNO LINEE DI SICUREZZA ALLARME PROFONDITÀ (DANGER & WARNING) ---
1223
+ if (isDepth) {
1224
+ const dangerVal = CONFIG.alarms.depthDanger; // Es. 2.5m
1225
+ const warningVal = CONFIG.alarms.depthWarning; // Es. 3.5m
1226
+ const marginX = 4; // Margine per non toccare i bordi esterni
1227
+
1228
+ // Spessore dinamico per gli allarmi: 4.8px in Dual Screen, 1.8px nella griglia normale
1229
+ const alarmStrokeWidth = isFocused ? "4.8" : "1.8";
1230
+
1231
+ // Linea Rossa Viva (Spessore dinamico, con il tuo tratteggio alternato personalizzato)
1232
+ if (dangerVal >= min && dangerVal <= max) {
1233
+ const p = (dangerVal - min) / range;
1234
+ const y = h - (p * h);
1235
+ grids += `<line x1="${marginX}" y1="${y}" x2="${w - marginX}" y2="${y}" stroke="rgba(255, 59, 48, 0.95)" stroke-width="${alarmStrokeWidth}" stroke-dasharray="12, 6, 2, 6" vector-effect="non-scaling-stroke" />`;
1236
+ }
1237
+ // Linea Giallo Oro Viva (Spessore dinamico, con il tuo tratteggio alternato personalizzato)
1238
+ if (warningVal >= min && warningVal <= max) {
1239
+ const p = (warningVal - min) / range;
1240
+ const y = h - (p * h);
1241
+ grids += `<line x1="${marginX}" y1="${y}" x2="${w - marginX}" y2="${y}" stroke="rgba(255, 204, 0, 0.95)" stroke-width="${alarmStrokeWidth}" stroke-dasharray="6 , 2, 6, 12" vector-effect="non-scaling-stroke" />`;
1242
+ }
1182
1243
  }
1183
1244
 
1184
1245
  let gradientStops = "", lines = "", areaPath = "";
@@ -1208,7 +1269,8 @@ function drawGraph(d, id, min, max, isTws, isHercules) {
1208
1269
  started = false;
1209
1270
  }
1210
1271
  } else {
1211
- lines += `<line x1="${x1}" y1="${y1}" x2="${x2}" y2="${y2}" style="stroke:${props.color}; stroke-width:${props.stroke}; stroke-linecap:round; shape-rendering:geometricPrecision;" />`;
1272
+ // Curva del grafico: spessore reattivo al focus e protezione da deformazione (non-scaling)
1273
+ lines += `<line x1="${x1}" y1="${y1}" x2="${x2}" y2="${y2}" style="stroke:${props.color}; stroke-width:${props.stroke}; stroke-linecap:round; shape-rendering:geometricPrecision;" vector-effect="non-scaling-stroke" />`;
1212
1274
  if (!started) {
1213
1275
  areaPath += `M ${Math.max(0, x1)} ${h} L ${Math.max(0, x1)} ${y1} `;
1214
1276
  started = true;
@@ -1235,8 +1297,20 @@ function toggleFocusMode(type, element) {
1235
1297
  const container = document.querySelector('.main-container');
1236
1298
  const isLeft = ['stw', 'sog', 'hdg', 'cog', 'tack'].includes(type);
1237
1299
  isFocusActive = !isFocusActive;
1238
- if (isFocusActive) { container.classList.add('focus-active', isLeft ? 'focus-side-left' : 'focus-side-right'); element.classList.add('is-focused'); }
1239
- else { container.classList.remove('focus-active', 'focus-side-left', 'focus-side-right'); document.querySelectorAll('.data-box').forEach(b => b.classList.remove('is-focused')); }
1300
+ if (isFocusActive) {
1301
+ container.classList.add('focus-active', isLeft ? 'focus-side-left' : 'focus-side-right');
1302
+ element.classList.add('is-focused');
1303
+ } else {
1304
+ container.classList.remove('focus-active', 'focus-side-left', 'focus-side-right');
1305
+ document.querySelectorAll('.data-box').forEach(b => b.classList.remove('is-focused'));
1306
+ }
1307
+
1308
+ // --- FORZATURA REDRAW IMMEDIATO DUAL SCREEN ---
1309
+ // Quando entriamo o usciamo dal Focus, ridisegnamo subito lo strumento
1310
+ // interessato per applicare istantaneamente il cambio di spessore della linea!
1311
+ if (['stw', 'sog', 'tws', 'depth'].includes(type)) {
1312
+ refreshGraph(type);
1313
+ }
1240
1314
  }
1241
1315
 
1242
1316
  ['stw', 'sog', 'tws', 'depth'].forEach(type => {
@@ -1275,8 +1349,10 @@ function toggleFocusMode(type, element) {
1275
1349
  } else if (!isFocusActive) {
1276
1350
  if (type === 'sog') {
1277
1351
  displayModeSog = (displayModeSog === 'SOG') ? 'VMG' : 'SOG';
1352
+ refreshGraph('sog'); // --- FORZA RINFRESCO ISTANTANEO AL CAMBIO SOG/VMG ---
1278
1353
  } else if (type === 'tws') {
1279
1354
  displayModeTws = (displayModeTws === 'TWS') ? 'AWS' : 'TWS';
1355
+ refreshGraph('tws'); // --- FORZA RINFRESCO ISTANTANEO AL CAMBIO TWS/AWS ---
1280
1356
  }
1281
1357
  el.style.backgroundColor = "rgba(0, 0, 0, 0.05)";
1282
1358
  setTimeout(() => el.style.backgroundColor = "", 150);
@@ -1404,22 +1480,45 @@ async function init() {
1404
1480
  // RICONNESSIONE RAPIDA AL RISVEGLIO (VISIBILITY WATCHDOG)
1405
1481
  // ==========================================================================
1406
1482
 
1407
- // Quando sblocchi l'iPad o riapri il browser, forziamo la chiusura del vecchio
1408
- // WebSocket orfano. Questo farà scattare immediatamente connect() e la sincronizzazione.
1483
+ // Quando sblocchi l'iPad o riapri la scheda, sincronizziamo in modo intelligente
1409
1484
  document.addEventListener('visibilitychange', () => {
1410
1485
  if (document.visibilityState === 'visible') {
1411
- console.log("⏰ Schermo sbloccato: forzatura riconnessione rapida.");
1412
- if (socket) {
1413
- try {
1414
- socket.close(); // Fa scattare onclose -> connect() -> onopen -> fetchServerHistory()
1415
- } catch (e) {
1486
+ // 1. Se la connessione è già attiva e sana, scarichiamo solo lo storico senza disconnetterci
1487
+ if (socket && socket.readyState === WebSocket.OPEN) {
1488
+ console.log("⏰ Schermo sbloccato: connessione attiva, sincronizzazione dello storico.");
1489
+ fetchServerHistory().then(() => {
1490
+ ['stw', 'sog', 'depth', 'tws'].forEach(refreshGraph);
1491
+ }).catch(err => {});
1492
+ }
1493
+ // 2. Se la connessione è persa o morta, forzatura riconnessione rapida
1494
+ else {
1495
+ console.log("⏰ Schermo sbloccato: connessione assente, forzatura riconnessione rapida.");
1496
+ if (socket) {
1497
+ try {
1498
+ socket.close();
1499
+ } catch (e) {
1500
+ connect();
1501
+ }
1502
+ } else {
1416
1503
  connect();
1417
1504
  }
1418
- } else {
1419
- connect();
1420
1505
  }
1421
1506
  }
1422
1507
  });
1508
+
1509
+ // Rileva se il dispositivo è andato in sospensione misurando il ritardo dei secondi
1510
+ let lastHeartbeat = Date.now();
1511
+ setInterval(() => {
1512
+ const now = Date.now();
1513
+ const diff = now - lastHeartbeat;
1514
+ lastHeartbeat = now;
1515
+
1516
+ // Se passano più di 6 secondi tra un ciclo e l'altro (invece di 1 secondo),
1517
+ // significa che il PC era in sospensione. Avviamo il risveglio.
1518
+ if (diff > 6000) {
1519
+ handleWakeUp();
1520
+ }
1521
+ }, 1000);
1423
1522
  }
1424
1523
 
1425
1524
 
package/icons/dash.png ADDED
Binary file
package/index.html CHANGED
@@ -1,14 +1,21 @@
1
1
  <!DOCTYPE html>
2
2
  <html lang="it">
3
- <head>
4
- <meta charset="UTF-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
6
- <meta name="apple-mobile-web-app-capable" content="yes">
7
- <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
8
- <link rel="manifest" href="manifest.json">
9
- <title>Sailing Dashboard Pro</title>
10
- <link rel="stylesheet" href="style.css">
11
- </head>
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
6
+ <meta name="apple-mobile-web-app-capable" content="yes">
7
+ <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
8
+ <link rel="manifest" href="manifest.json">
9
+
10
+ <!-- Icona standard per la scheda del browser (Favicon) -->
11
+ <link rel="icon" type="image/png" href="icons/dash.png">
12
+
13
+ <!-- Icona per Bookmark e schermata Home su Apple iPad, iPhone e Mac -->
14
+ <link rel="apple-touch-icon" href="icons/dash.png">
15
+
16
+ <title>Sailing Dashboard Pro</title>
17
+ <link rel="stylesheet" href="style.css">
18
+ </head>
12
19
  <body>
13
20
 
14
21
  <div class="main-container">
package/manifest.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "name": "Signal K Wind Dashboard",
4
4
  "icons": [
5
5
  {
6
- "src": "https://cdn-icons-png.flaticon.com/512/959/959711.png",
6
+ "src": "./icons/dash.png",
7
7
  "type": "image/png",
8
8
  "sizes": "512x512"
9
9
  }
@@ -14,4 +14,4 @@
14
14
  "scope": "./",
15
15
  "theme_color": "#000000",
16
16
  "orientation": "landscape"
17
- }
17
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sailingrotevista/rotevista-dash",
3
- "version": "6.0.8",
3
+ "version": "6.0.11",
4
4
  "description": "Wind Dashboard with navigation and course aids",
5
5
  "main": "index.js",
6
6
  "publishConfig": {
package/style.css CHANGED
@@ -175,8 +175,7 @@ body.night-mode .alarm-danger {
175
175
 
176
176
  .focus-active .is-focused .sparkline path,
177
177
  .focus-active .is-focused .sparkline line {
178
- stroke-width: 1.5px !important; /* Un briciolo più spessa per la stabilità visiva su schermi grandi */
179
- }
178
+ }
180
179
 
181
180
  .focus-active.focus-side-left {
182
181
  grid-template-columns: 3fr 2fr !important;
@@ -415,7 +414,6 @@ body.night-mode .alarm-danger {
415
414
  rect[fill="#222"] { fill: #eee !important; }
416
415
  #leeway-val { color: #000 !important; }
417
416
 
418
- #awa-pointer, #twa-pointer, #track-pointer, #twd-arrow, #twd-boat-wrap { transition: all 0.8s cubic-bezier(0.4, 0, 0.2, 1); }
419
417
  #wind-gauge { width: 100%; height: 100%; max-height: 100%; object-fit: contain; }
420
418
 
421
419
  /* ==========================================================================