@sailingrotevista/rotevista-dash 2.0.11 → 2.0.13
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 +103 -3
- package/index.html +13 -1
- package/package.json +1 -1
- package/style.css +274 -92
package/app.js
CHANGED
|
@@ -333,7 +333,48 @@ function toggleFocusMode(type, element) {
|
|
|
333
333
|
el.addEventListener('pointerleave', () => clearTimeout(pressTimer));
|
|
334
334
|
});
|
|
335
335
|
|
|
336
|
-
|
|
336
|
+
// ==========================================================================
|
|
337
|
+
// GESTIONE HOTSPOT: Click (Fullscreen) e Long Press (Night Mode)
|
|
338
|
+
// ==========================================================================
|
|
339
|
+
if (ui.hotspot) {
|
|
340
|
+
let pressTimer;
|
|
341
|
+
const HOLD_DURATION = 1000; // 1 secondo di pressione per attivare Night Mode
|
|
342
|
+
|
|
343
|
+
ui.hotspot.addEventListener('pointerdown', (e) => {
|
|
344
|
+
// Avvia il timer al tocco
|
|
345
|
+
pressTimer = setTimeout(() => {
|
|
346
|
+
document.body.classList.toggle('night-mode');
|
|
347
|
+
// Feedback visivo immediato al cambio modalità
|
|
348
|
+
ui.hotspot.style.opacity = "0.5";
|
|
349
|
+
setTimeout(() => ui.hotspot.style.opacity = "1", 200);
|
|
350
|
+
pressTimer = null; // Reset per evitare che il click scatti dopo
|
|
351
|
+
}, HOLD_DURATION);
|
|
352
|
+
});
|
|
353
|
+
|
|
354
|
+
ui.hotspot.addEventListener('pointerup', (e) => {
|
|
355
|
+
if (pressTimer) {
|
|
356
|
+
clearTimeout(pressTimer);
|
|
357
|
+
pressTimer = null;
|
|
358
|
+
// Se arriviamo qui, è stato un click rapido -> Fullscreen
|
|
359
|
+
const doc = document.documentElement;
|
|
360
|
+
const isF = document.fullscreenElement || document.webkitFullscreenElement;
|
|
361
|
+
if (!isF) {
|
|
362
|
+
if (doc.requestFullscreen) doc.requestFullscreen();
|
|
363
|
+
else if (doc.webkitRequestFullscreen) doc.webkitRequestFullscreen();
|
|
364
|
+
} else {
|
|
365
|
+
if (document.exitFullscreen) document.exitFullscreen();
|
|
366
|
+
else if (document.webkitExitFullscreen) document.webkitExitFullscreen();
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
});
|
|
370
|
+
|
|
371
|
+
ui.hotspot.addEventListener('pointerleave', () => {
|
|
372
|
+
if (pressTimer) {
|
|
373
|
+
clearTimeout(pressTimer);
|
|
374
|
+
pressTimer = null;
|
|
375
|
+
}
|
|
376
|
+
});
|
|
377
|
+
}
|
|
337
378
|
(function genTicks() { const c = document.getElementById('ticks'); if (c) { for (let i = 0; i < 360; i += 10) { const l = document.createElementNS("http://www.w3.org/2000/svg", "line"); const m = i % 30 === 0; l.setAttribute("x1", "200"); l.setAttribute("y1", "40"); l.setAttribute("x2", "200"); l.setAttribute("y2", (m ? 60 : 50)); l.setAttribute("stroke", m ? "#fff" : "#666"); l.setAttribute("stroke-width", m ? "2" : "1"); l.setAttribute("transform", `rotate(${i}, 200, 200)`); c.appendChild(l); } } })();
|
|
338
379
|
|
|
339
380
|
async function init() { await fetchServerConfig(); startDisplayLoop(); connect(); }
|
|
@@ -341,7 +382,66 @@ window.addEventListener('load', init);
|
|
|
341
382
|
function checkDepthAlarm(m) { ui.depth.classList.remove('alarm-warning', 'alarm-danger'); if (m < CONFIG.alarms.depthDanger) { ui.depth.classList.add('alarm-danger'); playBingBing(); } else if (m < CONFIG.alarms.depthWarning) ui.depth.classList.add('alarm-warning'); }
|
|
342
383
|
function playBingBing() { if (!audioCtx) return; const n = Date.now(); if (n - lastAlarmTime < 3000) return; lastAlarmTime = n; function b(f, s) { const o = audioCtx.createOscillator(); const g = audioCtx.createGain(); o.connect(g); g.connect(audioCtx.destination); o.frequency.value = f; g.gain.setValueAtTime(0.1, s); g.gain.exponentialRampToValueAtTime(0.01, s + 0.4); o.start(s); o.stop(s + 0.5); } b(880, audioCtx.currentTime); b(880, audioCtx.currentTime + 0.6); }
|
|
343
384
|
|
|
344
|
-
// Simulatore
|
|
385
|
+
// Simulatore su Depth (3 click rapidi)
|
|
345
386
|
ui.depth.closest('.data-box').addEventListener('click', (function() {
|
|
346
|
-
let dC = 0, lC = 0;
|
|
387
|
+
let dC = 0, lC = 0;
|
|
388
|
+
return function() {
|
|
389
|
+
const n = Date.now();
|
|
390
|
+
if (n - lC < 500) dC++; else dC = 1;
|
|
391
|
+
lC = n;
|
|
392
|
+
if (dC === 3) {
|
|
393
|
+
simulationMode = !simulationMode;
|
|
394
|
+
if (simulationMode) {
|
|
395
|
+
if (socket) socket.close();
|
|
396
|
+
startDynamicSimulation(); // Chiama la nuova funzione
|
|
397
|
+
} else {
|
|
398
|
+
location.reload();
|
|
399
|
+
}
|
|
400
|
+
dC = 0;
|
|
401
|
+
}
|
|
402
|
+
};
|
|
347
403
|
})());
|
|
404
|
+
|
|
405
|
+
// ==========================================================================
|
|
406
|
+
// 9. MOTORE SIMULAZIONE DINAMICA
|
|
407
|
+
// ==========================================================================
|
|
408
|
+
function startDynamicSimulation() {
|
|
409
|
+
ui.status.innerText = "SIM ATTIVO";
|
|
410
|
+
|
|
411
|
+
// Parametri base iniziali
|
|
412
|
+
let baseTws = 60, baseDepth = 12, baseHdg = 45;
|
|
413
|
+
|
|
414
|
+
simInterval = setInterval(() => {
|
|
415
|
+
// T rappresenta il progresso nel ciclo di 10 minuti (da 0 a 1)
|
|
416
|
+
const t = (Date.now() % 600000) / 600000;
|
|
417
|
+
const radT = t * 2 * Math.PI;
|
|
418
|
+
|
|
419
|
+
// Oscillazioni fluide (Sinusoidali)
|
|
420
|
+
const tws = baseTws + Math.sin(radT) * 5; // Oscilla +- 5 kts
|
|
421
|
+
const depth = baseDepth + Math.sin(radT) * 3; // Oscilla +- 3 m
|
|
422
|
+
const twa = 40 + Math.sin(radT * 2) * 10; // Oscilla angolo +- 10°
|
|
423
|
+
|
|
424
|
+
// Calcoli Vettoriali (Nautica)
|
|
425
|
+
const stw = Math.min(tws * 0.7, 8); // Velocità barca legata al vento
|
|
426
|
+
const twaRad = degToRad(twa);
|
|
427
|
+
|
|
428
|
+
// AWS = radq(stw² + tws² + 2*stw*tws*cos(twa))
|
|
429
|
+
const aws = Math.sqrt(Math.pow(stw, 2) + Math.pow(tws, 2) + 2 * stw * tws * Math.cos(twaRad));
|
|
430
|
+
// AWA = atan2(tws*sin(twa), stw + tws*cos(twa))
|
|
431
|
+
const awa = radToDeg(Math.atan2(tws * Math.sin(twaRad), stw + tws * Math.cos(twaRad)));
|
|
432
|
+
|
|
433
|
+
// Calcolo Leeway (Scarroccio): più forte il vento, più scarroccia
|
|
434
|
+
const leeway = (tws > 5) ? Math.sin(twaRad) * (tws * 0.2) : 0;
|
|
435
|
+
|
|
436
|
+
// Invio dati al sistema
|
|
437
|
+
processIncomingData("environment.wind.speedTrue", ktsToMs(tws));
|
|
438
|
+
processIncomingData("environment.wind.angleTrueWater", degToRad(twa));
|
|
439
|
+
processIncomingData("environment.wind.speedApparent", ktsToMs(aws));
|
|
440
|
+
processIncomingData("environment.wind.angleApparent", degToRad(awa));
|
|
441
|
+
processIncomingData("environment.depth.belowTransducer", depth);
|
|
442
|
+
processIncomingData("navigation.headingTrue", degToRad(baseHdg));
|
|
443
|
+
processIncomingData("navigation.speedThroughWater", ktsToMs(stw));
|
|
444
|
+
processIncomingData("navigation.courseOverGroundTrue", degToRad(baseHdg + leeway));
|
|
445
|
+
}, 1000);
|
|
446
|
+
}
|
|
447
|
+
|
package/index.html
CHANGED
|
@@ -89,6 +89,8 @@
|
|
|
89
89
|
<!-- ViewBox ottimizzato per ingrandire il diametro (Zoom in) -->
|
|
90
90
|
<svg id="wind-gauge" viewBox="35 38 330 395" preserveAspectRatio="xMidYMid meet">
|
|
91
91
|
<defs>
|
|
92
|
+
<!-- Maschera per tagliare la barca esattamente sul bordo del cerchio r=50 -->
|
|
93
|
+
<clipPath id="boat-clip"><circle cx="200" cy="200" r="50" /></clipPath>
|
|
92
94
|
<!-- Gradienti e Maschere per i settori del vento -->
|
|
93
95
|
<linearGradient id="axiom-grad" x1="0%" y1="0%" x2="0%" y2="100%">
|
|
94
96
|
<stop offset="0%" style="stop-color:#ffffff;stop-opacity:1" />
|
|
@@ -101,6 +103,12 @@
|
|
|
101
103
|
<stop offset="75%" style="stop-color:#ff8800;stop-opacity:1" />
|
|
102
104
|
<stop offset="100%" style="stop-color:#ff0000;stop-opacity:1" />
|
|
103
105
|
</linearGradient>
|
|
106
|
+
<!-- Gradiente Leeway per la Night Mode (Rosso cupo al centro, Rosso vivo ai lati) -->
|
|
107
|
+
<linearGradient id="leeway-night-grad" x1="0%" y1="0%" x2="100%" y2="0%">
|
|
108
|
+
<stop offset="0%" style="stop-color:#ff0000;stop-opacity:1" /> <!-- Estremo SX: Rosso vivo -->
|
|
109
|
+
<stop offset="50%" style="stop-color:#330000;stop-opacity:1" /> <!-- Centro: Rosso cupo -->
|
|
110
|
+
<stop offset="100%" style="stop-color:#ff0000;stop-opacity:1" /> <!-- Estremo DX: Rosso vivo -->
|
|
111
|
+
</linearGradient>
|
|
104
112
|
<clipPath id="leeway-clip">
|
|
105
113
|
<rect id="leeway-mask-rect" x="125" y="0" width="0" height="12" rx="2" />
|
|
106
114
|
</clipPath>
|
|
@@ -150,7 +158,11 @@
|
|
|
150
158
|
<circle id="fullscreen-hotspot" cx="200" cy="200" r="55" fill="#181818" stroke="#333" stroke-width="1" filter="url(#center-glow)" cursor="pointer" />
|
|
151
159
|
|
|
152
160
|
<!-- Icona Barca Centrale (Spinta Y+5 per centratura visiva perfetta) -->
|
|
153
|
-
<path id="boat-icon" d="M200,150 Q165,185 170,250 Q165,190 200,173 Q235,190 230,250 Q235,185 200,150 Z"
|
|
161
|
+
<path id="boat-icon" d="M200,150 Q165,185 170,250 Q165,190 200,173 Q235,190 230,250 Q235,185 200,150 Z"
|
|
162
|
+
fill="url(#axiom-grad)"
|
|
163
|
+
transform="translate(0, 5)"
|
|
164
|
+
clip-path="url(#boat-clip)"
|
|
165
|
+
style="pointer-events: none;" />
|
|
154
166
|
|
|
155
167
|
<!-- Display Centrale Numerico: Vento Apparente -->
|
|
156
168
|
<g id="aws-display-group" transform="translate(200, 265)">
|
package/package.json
CHANGED
package/style.css
CHANGED
|
@@ -5,9 +5,12 @@ body {
|
|
|
5
5
|
background-color: #000;
|
|
6
6
|
color: #fff;
|
|
7
7
|
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Arial, sans-serif;
|
|
8
|
-
margin: 0;
|
|
9
|
-
|
|
8
|
+
margin: 0;
|
|
9
|
+
padding: 0;
|
|
10
|
+
height: 100vh;
|
|
11
|
+
width: 100vw;
|
|
10
12
|
overflow: hidden;
|
|
13
|
+
/* BLOCCO TOTALE GESTI DI SISTEMA: Fondamentale per il Long Press su mobile */
|
|
11
14
|
-webkit-touch-callout: none;
|
|
12
15
|
-webkit-user-select: none;
|
|
13
16
|
user-select: none;
|
|
@@ -16,30 +19,60 @@ body {
|
|
|
16
19
|
|
|
17
20
|
.main-container {
|
|
18
21
|
display: grid;
|
|
19
|
-
width: 100%;
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
22
|
+
width: 100%;
|
|
23
|
+
height: 100%;
|
|
24
|
+
padding: 5px;
|
|
25
|
+
box-sizing: border-box;
|
|
26
|
+
gap: 8px; /* Spazio costante tra tutti i blocchi della dashboard */
|
|
27
|
+
|
|
28
|
+
/*
|
|
29
|
+
LAYOUT LIQUIDO:
|
|
30
|
+
I lati hanno un minimo vitale (180px) per proteggere i testi.
|
|
31
|
+
Il centro (auto) si adatta millimetricamente al diametro dell'SVG.
|
|
32
|
+
*/
|
|
33
|
+
grid-template-columns: minmax(180px, 1fr) minmax(auto, 3fr) minmax(180px, 1fr);
|
|
23
34
|
grid-template-rows: 100%;
|
|
24
35
|
transition: all 0.5s cubic-bezier(0.4, 0, 0.2, 1);
|
|
25
36
|
justify-content: stretch;
|
|
26
37
|
}
|
|
27
38
|
|
|
28
|
-
/* Espansione colonne per schermi larghi (16:10) */
|
|
39
|
+
/* Espansione colonne per schermi molto larghi (es. 16:10 / 16:9) */
|
|
29
40
|
@media (min-aspect-ratio: 1.5) {
|
|
30
41
|
.main-container {
|
|
31
|
-
/* Aumentiamo il gap e il minimo vitale per schermi enormi */
|
|
32
42
|
grid-template-columns: minmax(200px, 1fr) auto minmax(200px, 1fr);
|
|
33
43
|
gap: 15px;
|
|
34
44
|
}
|
|
35
45
|
}
|
|
46
|
+
|
|
36
47
|
/* ==========================================================================
|
|
37
48
|
2. PANNELLI E DATA-BOX
|
|
38
49
|
========================================================================== */
|
|
39
|
-
.side-panel {
|
|
50
|
+
.side-panel {
|
|
51
|
+
display: flex;
|
|
52
|
+
flex-direction: column;
|
|
53
|
+
background: rgba(255, 255, 255, 0.03);
|
|
54
|
+
border-radius: 12px;
|
|
55
|
+
height: 100%;
|
|
56
|
+
overflow: hidden;
|
|
57
|
+
}
|
|
58
|
+
|
|
40
59
|
.left-panel { grid-column: 1; }
|
|
41
|
-
|
|
42
|
-
.
|
|
60
|
+
|
|
61
|
+
.center-panel {
|
|
62
|
+
grid-column: 2;
|
|
63
|
+
display: flex;
|
|
64
|
+
flex-direction: column;
|
|
65
|
+
align-items: center;
|
|
66
|
+
justify-content: center;
|
|
67
|
+
height: 100%;
|
|
68
|
+
overflow: hidden;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
.right-panel {
|
|
72
|
+
grid-column: 3;
|
|
73
|
+
align-items: flex-end;
|
|
74
|
+
text-align: right;
|
|
75
|
+
}
|
|
43
76
|
|
|
44
77
|
.data-box {
|
|
45
78
|
position: relative;
|
|
@@ -47,54 +80,41 @@ body {
|
|
|
47
80
|
padding: 8px 12px;
|
|
48
81
|
display: flex;
|
|
49
82
|
flex-direction: column;
|
|
50
|
-
width: 100%;
|
|
51
|
-
|
|
83
|
+
width: 100%;
|
|
84
|
+
box-sizing: border-box;
|
|
85
|
+
container-type: size; /* Rende il box misurabile per l'unità cqh */
|
|
52
86
|
flex: 1;
|
|
53
87
|
overflow: hidden;
|
|
54
|
-
-webkit-touch-callout: none;
|
|
55
|
-
-webkit-user-select: none;
|
|
56
|
-
user-select: none;
|
|
57
|
-
touch-action: none;
|
|
58
88
|
}
|
|
59
89
|
|
|
60
|
-
/*
|
|
61
|
-
.data-box:nth-child(1), .data-box:nth-child(2) { height: 25vh; }
|
|
62
|
-
.data-box:nth-child(3), .data-box:nth-child(4), .data-box:nth-child(5) { height: 16.666vh; }
|
|
63
|
-
|
|
64
|
-
/* Allineamento Speculare Box */
|
|
90
|
+
/* Allineamento Speculare: SX a sinistra, DX a destra del box */
|
|
65
91
|
.left-panel .data-box { align-items: flex-start; text-align: left; }
|
|
66
92
|
.right-panel .data-box { align-items: flex-end; text-align: right; }
|
|
67
93
|
|
|
94
|
+
/* Altezze Proporzionali: 25% dell'altezza per i grafici, 16.6% per i MEAN/TACK */
|
|
95
|
+
.data-box:nth-child(1), .data-box:nth-child(2) { height: 25vh; }
|
|
96
|
+
.data-box:nth-child(3), .data-box:nth-child(4), .data-box:nth-child(5) { height: 16.666vh; }
|
|
97
|
+
|
|
68
98
|
/* ==========================================================================
|
|
69
99
|
3. TACTICAL FOCUS MODE (AUTO-EXPANDING SPLIT)
|
|
70
100
|
========================================================================== */
|
|
71
101
|
|
|
72
|
-
/*
|
|
102
|
+
/* Nasconde le colonne non focalizzate */
|
|
73
103
|
.focus-active .side-panel:not(.has-focus) { display: none !important; }
|
|
74
|
-
.focus-active .side-panel.has-focus {
|
|
75
|
-
min-width: 400px !important;
|
|
76
|
-
}
|
|
77
104
|
|
|
105
|
+
/* Protezione larghezza minima per il grafico focalizzato */
|
|
106
|
+
.focus-active .side-panel.has-focus { min-width: 400px !important; }
|
|
78
107
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
LOGICA POSIZIONE E LARGHEZZA:
|
|
82
|
-
Il Vento prende solo la larghezza del suo cerchio (auto).
|
|
83
|
-
Il Box focalizzato si prende TUTTO il resto dello schermo (1fr).
|
|
84
|
-
*/
|
|
85
|
-
.focus-active.focus-side-left {
|
|
86
|
-
grid-template-columns: 1fr auto !important; /* Dati SX giganti, Vento DX compatto */
|
|
87
|
-
}
|
|
108
|
+
/* Logica di espansione: il box scelto prende tutto il resto dello spazio (1fr) */
|
|
109
|
+
.focus-active.focus-side-left { grid-template-columns: 1fr auto !important; }
|
|
88
110
|
.focus-active.focus-side-left .side-panel.has-focus { grid-column: 1 !important; }
|
|
89
111
|
.focus-active.focus-side-left .center-panel { grid-column: 2 !important; justify-content: flex-start; }
|
|
90
112
|
|
|
91
|
-
.focus-active.focus-side-right {
|
|
92
|
-
grid-template-columns: auto 1fr !important; /* Vento SX compatto, Dati DX giganti */
|
|
93
|
-
}
|
|
113
|
+
.focus-active.focus-side-right { grid-template-columns: auto 1fr !important; }
|
|
94
114
|
.focus-active.focus-side-right .center-panel { grid-column: 1 !important; justify-content: flex-start; }
|
|
95
115
|
.focus-active.focus-side-right .side-panel.has-focus { grid-column: 2 !important; }
|
|
96
116
|
|
|
97
|
-
/*
|
|
117
|
+
/* Styling del box in Focus Mode */
|
|
98
118
|
.focus-active .has-focus .data-box:not(.is-focused) { display: none !important; }
|
|
99
119
|
.focus-active .has-focus .data-box.is-focused {
|
|
100
120
|
height: 100vh !important;
|
|
@@ -103,13 +123,13 @@ body {
|
|
|
103
123
|
padding: 20px;
|
|
104
124
|
}
|
|
105
125
|
|
|
106
|
-
/* Tipografia
|
|
126
|
+
/* Tipografia massiccia in Focus Mode */
|
|
107
127
|
.focus-active .is-focused .value { font-size: clamp(4rem, 25cqh, 4rem) !important; margin-top: 15px; }
|
|
108
128
|
.focus-active .is-focused .scale-labels { font-size: 32px !important; min-width: 40px !important; line-height: 1.2; }
|
|
109
129
|
.focus-active .is-focused .label-row .label { font-size: 2rem !important; }
|
|
110
130
|
.focus-active .is-focused .label-row .unit { font-size: 2rem !important; }
|
|
111
131
|
|
|
112
|
-
/* Ingrandimento
|
|
132
|
+
/* Ingrandimento etichette Hercules in Focus */
|
|
113
133
|
.focus-active .is-focused.box-hercules .unit::before,
|
|
114
134
|
.focus-active .is-focused.box-hercules .unit::after,
|
|
115
135
|
.focus-active .is-focused.box-hercules .label::before,
|
|
@@ -121,46 +141,51 @@ body {
|
|
|
121
141
|
.focus-active .is-focused .sparkline path { stroke-width: 1px !important; }
|
|
122
142
|
|
|
123
143
|
/* ==========================================================================
|
|
124
|
-
4. TIPOGRAFIA
|
|
144
|
+
4. TIPOGRAFIA DINAMICA (ELASTICA CQH)
|
|
125
145
|
========================================================================== */
|
|
126
146
|
.label-row { display: flex; justify-content: space-between; align-items: baseline; margin-bottom: 2px; width: 100%; }
|
|
127
147
|
|
|
128
|
-
/* SX
|
|
148
|
+
/* Simmetria Titoli/Unità: SX [Label...Unit], DX [Unit...Label] */
|
|
129
149
|
.left-panel .label-row { justify-content: space-between; flex-direction: row; }
|
|
130
|
-
|
|
131
|
-
/* DX: [Unità] ... [Titolo] */
|
|
132
150
|
.right-panel .label-row { justify-content: space-between; flex-direction: row; }
|
|
133
151
|
|
|
134
|
-
/*
|
|
152
|
+
/* Forza i titoli MEAN (senza unità) a destra nella colonna DX */
|
|
135
153
|
.right-panel .label-row .label:only-child { margin-left: auto; }
|
|
136
154
|
|
|
137
155
|
.label { color: #666; font-size: 0.65rem; font-weight: bold; text-transform: uppercase; }
|
|
138
156
|
.unit { color: #888; font-size: 0.6rem; font-weight: bold; }
|
|
139
|
-
.value { color: #fff; font-size: clamp(1.2rem, 22cqh, 3rem); font-weight: 600; line-height: 0.9; letter-spacing: -1px; padding-bottom: 5px; }
|
|
140
157
|
|
|
141
|
-
|
|
158
|
+
/* Numero standard (22% altezza box per non coprire il grafico) */
|
|
159
|
+
.value {
|
|
160
|
+
color: #fff;
|
|
161
|
+
font-size: clamp(1.2rem, 22cqh, 3rem);
|
|
162
|
+
font-weight: 600;
|
|
163
|
+
line-height: 0.9;
|
|
164
|
+
letter-spacing: -1px;
|
|
165
|
+
padding-bottom: 5px;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/* Centratura verticale automatica per i box senza grafico */
|
|
169
|
+
.value-large, .dual-value-container, .value-with-compass {
|
|
170
|
+
margin-top: auto;
|
|
171
|
+
margin-bottom: auto;
|
|
172
|
+
}
|
|
173
|
+
|
|
142
174
|
.value-large { font-size: clamp(1.5rem, 35cqh, 4.5rem); line-height: 0.85; }
|
|
143
175
|
|
|
144
|
-
/* TACK Layout */
|
|
176
|
+
/* TACK Layout (Mure opposte) */
|
|
145
177
|
.dual-value-container { display: flex; justify-content: space-between; width: 100%; }
|
|
146
178
|
.dual-value-col { display: flex; flex-direction: column; width: 48%; }
|
|
147
179
|
.dual-label { color: #666; font-size: 0.55rem; font-weight: bold; text-transform: uppercase; margin-bottom: 2px; }
|
|
148
180
|
.value.dual-val { font-size: clamp(1rem, 22cqh, 2rem); padding-bottom: 0; line-height: 0.9; }
|
|
149
181
|
|
|
150
182
|
/* ==========================================================================
|
|
151
|
-
BUSSOLA TWD
|
|
183
|
+
5. BUSSOLA TWD DINAMICA
|
|
152
184
|
========================================================================== */
|
|
153
|
-
.value-with-compass {
|
|
154
|
-
display: flex;
|
|
155
|
-
flex: 1;
|
|
156
|
-
justify-content: space-between;
|
|
157
|
-
align-items: center;
|
|
158
|
-
width: 100%;
|
|
159
|
-
gap: 5px;
|
|
160
|
-
}
|
|
185
|
+
.value-with-compass { display: flex; justify-content: space-between; align-items: center; width: 100%; gap: 5px; }
|
|
161
186
|
|
|
162
187
|
.mini-compass {
|
|
163
|
-
/*
|
|
188
|
+
/* Forma circolare protetta: 80% dell'altezza o 42% della larghezza */
|
|
164
189
|
width: min(80cqh, 42cqw);
|
|
165
190
|
height: min(80cqh, 42cqw);
|
|
166
191
|
aspect-ratio: 1 / 1;
|
|
@@ -173,15 +198,12 @@ body {
|
|
|
173
198
|
}
|
|
174
199
|
|
|
175
200
|
.value-with-compass .value-large {
|
|
176
|
-
margin: 0;
|
|
177
|
-
|
|
178
|
-
text-align: right;
|
|
179
|
-
font-size: clamp(1rem, 38cqh, 4rem);
|
|
180
|
-
white-space: nowrap;
|
|
201
|
+
margin: 0; flex: 1; text-align: right;
|
|
202
|
+
font-size: clamp(1rem, 38cqh, 4rem); white-space: nowrap;
|
|
181
203
|
}
|
|
182
204
|
|
|
183
205
|
/* ==========================================================================
|
|
184
|
-
|
|
206
|
+
6. GRAFICI E SCALE (SIMMETRIA INTERNA)
|
|
185
207
|
========================================================================== */
|
|
186
208
|
.graph-wrapper {
|
|
187
209
|
position: relative; width: 100%; flex-grow: 1; min-height: 0; margin-top: 4px;
|
|
@@ -189,84 +211,244 @@ body {
|
|
|
189
211
|
border-radius: 4px; gap: 2px;
|
|
190
212
|
}
|
|
191
213
|
|
|
192
|
-
/* Spostamento verso il centro */
|
|
214
|
+
/* Spostamento verso il centro per eliminare spazi neri morti */
|
|
193
215
|
.left-panel .graph-wrapper { margin-right: -6px; }
|
|
194
216
|
.right-panel .graph-wrapper { margin-left: -6px; }
|
|
195
217
|
|
|
196
218
|
.sparkline { flex-grow: 1; height: 100%; background: transparent !important; display: block; }
|
|
197
219
|
.sparkline path, .sparkline line { stroke-width: 1px !important; transition: all 0.3s ease; }
|
|
198
220
|
|
|
199
|
-
.scale-labels {
|
|
221
|
+
.scale-labels {
|
|
222
|
+
display: flex; flex-direction: column; justify-content: space-between;
|
|
223
|
+
font-size: 10px; color: #777; font-weight: bold; min-width: 18px;
|
|
224
|
+
height: 100%; line-height: 1; padding: 2px 0;
|
|
225
|
+
}
|
|
200
226
|
|
|
201
|
-
/* Simmetria
|
|
227
|
+
/* Simmetria: le scale numeriche "guardano" sempre il quadrante centrale */
|
|
202
228
|
.left-panel .scale-labels { order: 2; text-align: left; padding-left: 4px; border-left: 1px solid rgba(255,255,255,0.08); }
|
|
203
229
|
.left-panel .sparkline { order: 1; }
|
|
204
230
|
.right-panel .scale-labels { order: 1; text-align: right; padding-right: 4px; border-right: 1px solid rgba(255,255,255,0.08); }
|
|
205
231
|
.right-panel .sparkline { order: 2; }
|
|
206
232
|
|
|
233
|
+
/* Colori semantici per i grafici */
|
|
207
234
|
#stw-graph { stroke: #2ecc71; fill: rgba(46, 204, 113, 0.12); }
|
|
208
235
|
#sog-graph { stroke: #f39c12; fill: rgba(243, 156, 18, 0.12); }
|
|
209
236
|
#depth-graph { stroke: #3498db; fill: rgba(52, 152, 219, 0.12); }
|
|
210
237
|
#tws-graph { stroke: #ffffff; fill: rgba(255, 255, 255, 0.08); }
|
|
211
238
|
|
|
212
239
|
/* ==========================================================================
|
|
213
|
-
|
|
240
|
+
7. HERCULES MODE (ZOOM E VISUALS)
|
|
214
241
|
========================================================================== */
|
|
215
242
|
.line-hercules { filter: drop-shadow(0 0 5px #ff0000); stroke-width: 1.8px !important; }
|
|
216
243
|
.box-hercules { background: rgba(255, 0, 0, 0.08) !important; }
|
|
244
|
+
.box-hercules .scale-labels { color: #ff8888; }
|
|
217
245
|
|
|
218
|
-
/*
|
|
219
|
-
.focus-active .is-focused.box-hercules .unit::before,
|
|
220
|
-
.focus-active .is-focused.box-hercules .unit::after,
|
|
221
|
-
.focus-active .is-focused.box-hercules .label::before {
|
|
222
|
-
font-size: 16px !important; /* Raddoppiato in Focus */
|
|
223
|
-
letter-spacing: 2px;
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
/* Stile base Hercules */
|
|
246
|
+
/* Etichetta Hercules dinamica accanto alle unità */
|
|
227
247
|
.box-hercules .unit::before, .box-hercules .unit::after,
|
|
228
248
|
.box-hercules .label::before {
|
|
229
249
|
font-size: 7px; color: #ff4444; font-weight: 900; letter-spacing: 1px; text-transform: uppercase;
|
|
230
250
|
}
|
|
231
|
-
|
|
232
|
-
/* Simmetria Hercules SX: "STW [HERCULES kts]" */
|
|
233
251
|
.left-panel .box-hercules .unit::before { content: "HERCULES "; }
|
|
234
|
-
|
|
235
|
-
/* Simmetria Hercules DX: "[m HERCULES] DEPTH" */
|
|
236
252
|
.right-panel .box-hercules .unit::after { content: " HERCULES"; }
|
|
237
|
-
|
|
238
|
-
/* Eccezione: Box MEAN colonna DX (Senza unità) -> "[HERCULES TWA]" */
|
|
239
|
-
.right-panel .box-hercules .label:only-child::before { content: "HERCULES "; }
|
|
253
|
+
.right-panel .box-hercules .label:only-child::after { content: " HERCULES"; }
|
|
240
254
|
|
|
241
255
|
/* ==========================================================================
|
|
242
|
-
|
|
256
|
+
8. STATI E ANIMAZIONI
|
|
243
257
|
========================================================================== */
|
|
244
258
|
#status { position: absolute; top: 5px; right: 15px; font-size: 0.5rem; text-transform: uppercase; z-index: 1000; }
|
|
245
259
|
.online { color: #2ecc71; opacity: 0.5; }
|
|
246
260
|
.offline { color: #e74c3c; font-weight: bold; }
|
|
247
|
-
|
|
261
|
+
|
|
262
|
+
/* Animazioni fluide per gli elementi rotanti (0.8s) */
|
|
263
|
+
#awa-pointer, #twa-pointer, #track-pointer, #twd-arrow, #twd-boat-wrap {
|
|
264
|
+
transition: all 0.8s cubic-bezier(0.4, 0, 0.2, 1);
|
|
265
|
+
}
|
|
266
|
+
|
|
248
267
|
#leeway-mask-rect { transition: none; }
|
|
249
268
|
.alarm-warning { color: #f1c40f !important; }
|
|
250
269
|
.alarm-danger { color: #e74c3c !important; font-weight: 900; animation: blink-unstable 1s infinite; }
|
|
270
|
+
|
|
251
271
|
@keyframes blink-unstable { 0% { opacity: 1; } 50% { opacity: 0.3; } 100% { opacity: 1; } }
|
|
252
272
|
.unstable-data { animation: blink-unstable 1.5s infinite ease-in-out; color: #f39c12 !important; }
|
|
273
|
+
|
|
253
274
|
#wind-gauge { width: 100%; height: 100%; max-height: 100%; object-fit: contain; }
|
|
254
275
|
|
|
255
276
|
/* ==========================================================================
|
|
256
|
-
|
|
277
|
+
9. RESPONSIVE (PORTRAIT MODE - IPHONE/TABLET)
|
|
257
278
|
========================================================================== */
|
|
258
279
|
@media (max-aspect-ratio: 0.9 / 1) {
|
|
259
|
-
.main-container {
|
|
280
|
+
.main-container {
|
|
281
|
+
grid-template-columns: 1fr 1fr !important;
|
|
282
|
+
grid-template-rows: 45vh calc(55vh - 8px) !important;
|
|
283
|
+
}
|
|
284
|
+
|
|
260
285
|
.center-panel { grid-row: 1 !important; grid-column: 1 / span 2 !important; padding: 5px 0; }
|
|
261
286
|
.left-panel { grid-row: 2 !important; grid-column: 1 !important; }
|
|
262
287
|
.right-panel { grid-row: 2 !important; grid-column: 2 !important; }
|
|
263
288
|
|
|
289
|
+
/* Focus Mode Verticale: Impilamento Flex sopra/sotto */
|
|
264
290
|
.main-container.focus-active { display: flex !important; flex-direction: column !important; }
|
|
265
291
|
.focus-active .center-panel { flex: 0 0 45vh !important; width: 100% !important; }
|
|
266
|
-
.focus-active .side-panel.has-focus { flex: 0 0 55vh !important; width: 100% !important; display: flex !important; }
|
|
292
|
+
.focus-active .side-panel.has-focus { flex: 0 0 calc(55vh - 8px) !important; width: 100% !important; display: flex !important; }
|
|
293
|
+
|
|
294
|
+
/* Altezze box Portrait dinamiche (per evitare overflow) */
|
|
295
|
+
.data-box { height: auto !important; flex: 1 !important; }
|
|
296
|
+
.data-box:nth-child(1), .data-box:nth-child(2) { flex: 1.5 !important; }
|
|
267
297
|
|
|
268
|
-
.data-box:nth-child(1), .data-box:nth-child(2) { height: 13.5vh; }
|
|
269
|
-
.data-box:nth-child(3), .data-box:nth-child(4), .data-box:nth-child(5) { height: 9.3vh; }
|
|
270
298
|
.value-large { font-size: clamp(1.2rem, 35cqh, 2.5rem); margin: auto 0; }
|
|
271
299
|
.value.dual-val { font-size: clamp(0.9rem, 30cqh, 1.4rem); }
|
|
300
|
+
|
|
301
|
+
/* Protezione bussola per box bassi (Portrait) */
|
|
302
|
+
.mini-compass {
|
|
303
|
+
width: min(70cqh, 40cqw) !important;
|
|
304
|
+
height: min(70cqh, 40cqw) !important;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
.right-panel .label-row .label:only-child { margin-left: auto !important; }
|
|
308
|
+
.box-hercules .unit::before, .box-hercules .unit::after { font-size: 6px !important; }
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
/* ==========================================================================
|
|
312
|
+
10. NIGHT MODE (RED ON BLACK - TACTICAL)
|
|
313
|
+
========================================================================== */
|
|
314
|
+
body.night-mode {
|
|
315
|
+
background-color: #000 !important;
|
|
316
|
+
color: #ff0000 !important;
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
/* --- Pannelli e Box --- */
|
|
320
|
+
.night-mode .side-panel {
|
|
321
|
+
background: rgba(20, 0, 0, 0.4);
|
|
322
|
+
border: 1px solid #330000;
|
|
323
|
+
}
|
|
324
|
+
.night-mode .data-box {
|
|
325
|
+
border-bottom-color: #260000;
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
/* --- Tipografia Secondaria (Titoli, Unità, TACK Labels) --- */
|
|
329
|
+
.night-mode .label,
|
|
330
|
+
.night-mode .unit,
|
|
331
|
+
.night-mode .dual-label {
|
|
332
|
+
color: #800000 !important; /* Rosso cupo per non affaticare la vista */
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
/* --- Valori Numerici --- */
|
|
336
|
+
.night-mode .value,
|
|
337
|
+
.night-mode .value-large {
|
|
338
|
+
color: #ff3333 !important;
|
|
339
|
+
text-shadow: 0 0 8px rgba(255, 0, 0, 0.4); /* Bagliore per profondità */
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
/* --- Grafici Sparkline (Solo Linea, No Riempimento) --- */
|
|
343
|
+
.night-mode .graph-wrapper {
|
|
344
|
+
background: rgba(30, 0, 0, 0.3) !important;
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
/* Nasconde l'area di riempimento sotto la linea */
|
|
348
|
+
.night-mode .sparkline path:first-of-type {
|
|
349
|
+
display: none !important;
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
/* Rende la linea del tracciato molto più visibile */
|
|
353
|
+
.night-mode .sparkline path {
|
|
354
|
+
fill: none !important;
|
|
355
|
+
stroke: #ff3333 !important;
|
|
356
|
+
stroke-width: 1.8px !important;
|
|
357
|
+
opacity: 1 !important;
|
|
358
|
+
filter: drop-shadow(0 0 2px rgba(255, 0, 0, 0.4));
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
/* Griglie interne (Orizzontali e Verticali) uniformi */
|
|
362
|
+
.night-mode .sparkline line {
|
|
363
|
+
stroke: #4d0000 !important;
|
|
364
|
+
stroke-width: 0.7px !important;
|
|
365
|
+
opacity: 1 !important;
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
/* Forza i segmenti colorati del TWS alla stessa luminosità della linea */
|
|
369
|
+
.night-mode #tws-graph line:not([stroke*="rgba"]) {
|
|
370
|
+
stroke: #ff3333 !important;
|
|
371
|
+
stroke-width: 1.8px !important;
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
/* Numeri delle scale a lato dei grafici */
|
|
375
|
+
.night-mode .scale-labels {
|
|
376
|
+
color: #660000 !important;
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
/* --- Hercules Mode in Night Mode --- */
|
|
380
|
+
.night-mode .box-hercules {
|
|
381
|
+
background: rgba(60, 0, 0, 0.2) !important;
|
|
382
|
+
}
|
|
383
|
+
.night-mode .line-hercules {
|
|
384
|
+
filter: drop-shadow(0 0 6px #ff0000) !important;
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
/* Scritta Hercules in alto (Colore personalizzato #f60000) */
|
|
388
|
+
.night-mode .box-hercules .unit::before,
|
|
389
|
+
.night-mode .box-hercules .unit::after,
|
|
390
|
+
.night-mode .box-hercules .label::before,
|
|
391
|
+
.night-mode .box-hercules .label::after {
|
|
392
|
+
color: #f60000 !important;
|
|
393
|
+
font-weight: 700;
|
|
394
|
+
opacity: 0.9;
|
|
395
|
+
letter-spacing: 1px;
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
/* --- Strumento Centrale (Wind Gauge) --- */
|
|
399
|
+
.night-mode #wind-gauge circle { stroke: #330000; }
|
|
400
|
+
.night-mode #ticks line { stroke: #4d0000 !important; }
|
|
401
|
+
.night-mode #tick-labels { fill: #800000 !important; }
|
|
402
|
+
.night-mode #boat-icon { fill: #330000 !important; opacity: 0.6; }
|
|
403
|
+
.night-mode #aws-val-svg { fill: #ff3333 !important; }
|
|
404
|
+
|
|
405
|
+
/* Settori Vento (Distinguibili per stile, non per colore) */
|
|
406
|
+
.night-mode #wind-gauge path[stroke="#ff0000"] { stroke: #660000 !important; opacity: 0.8; } /* Sx Solid */
|
|
407
|
+
.night-mode #wind-gauge path[stroke="#00ff00"] {
|
|
408
|
+
stroke: #660000 !important;
|
|
409
|
+
stroke-dasharray: 4, 3; /* Dx Dashed */
|
|
410
|
+
opacity: 0.8;
|
|
411
|
+
}
|
|
412
|
+
.night-mode #wind-gauge path[stroke="#ff8800"] { stroke: #330000 !important; stroke-width: 8; } /* Poppa Dark */
|
|
413
|
+
|
|
414
|
+
/* Lancette Wind Gauge */
|
|
415
|
+
.night-mode #awa-pointer path { fill: #ff0000; stroke: #000; }
|
|
416
|
+
.night-mode #twa-pointer path { fill: #800000; stroke: #000; }
|
|
417
|
+
.night-mode #track-pointer path { fill: #ff0000; stroke: #fff; stroke-width: 0.5; }
|
|
418
|
+
|
|
419
|
+
/* --- Blocco Leeway (Scarroccio) --- */
|
|
420
|
+
.night-mode rect[fill="url(#leeway-grad)"] { fill: url(#leeway-night-grad) !important; }
|
|
421
|
+
.night-mode #leeway-val { fill: #ff3333 !important; }
|
|
422
|
+
.night-mode g[stroke="#555"] line { stroke: #4d0000 !important; }
|
|
423
|
+
.night-mode g[fill="#555"] text { fill: #660000 !important; }
|
|
424
|
+
.night-mode rect[fill="#222"] { fill: #0a0000 !important; stroke: #200000; }
|
|
425
|
+
|
|
426
|
+
/* --- Bussola TWD --- */
|
|
427
|
+
.night-mode .mini-compass { border-color: #330000; background: #000; }
|
|
428
|
+
.night-mode .mini-compass text { fill: #800000 !important; }
|
|
429
|
+
.night-mode #twd-arrow path { fill: #ff0000 !important; stroke: #000 !important; }
|
|
430
|
+
.night-mode #twd-boat-wrap path { fill: #ff0000 !important; opacity: 0.15; }
|
|
431
|
+
|
|
432
|
+
.night-mode #center-glow feDropShadow {
|
|
433
|
+
flood-color: #ff0000 !important;
|
|
434
|
+
flood-opacity: 0.6 !important;
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
.night-mode #aws-display-group text {
|
|
438
|
+
fill: #ff3333 !important;
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
/* --- Modifica: Miglioramento visibilità TWD in Night Mode --- */
|
|
442
|
+
.night-mode #twd-arrow #twd-wind-chevron {
|
|
443
|
+
stroke: #ff3333 !important; /* Rosso più brillante */
|
|
444
|
+
stroke-width: 3px !important; /* Più spesso */
|
|
445
|
+
opacity: 1 !important; /* Piena opacità */
|
|
446
|
+
filter: drop-shadow(0 0 4px #ff0000); /* Effetto neon per staccarsi dallo sfondo */
|
|
447
|
+
transform-origin: center; /* Forza il centro corretto */
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
/* Assicuriamoci che anche la punta della barca sia visibile */
|
|
451
|
+
.night-mode #twd-boat-wrap path {
|
|
452
|
+
fill: #ff3333 !important;
|
|
453
|
+
opacity: 0.4 !important;
|
|
272
454
|
}
|