feat(ui): redesign Marine Pro Dark — bottom nav + dark navy + Inter v1.7.0
Some checks are pending
Build Android (APK + AAB) / build-android (push) Waiting to run
Some checks are pending
Build Android (APK + AAB) / build-android (push) Waiting to run
Reskin completo baseado em pesquisa de Navionics/Windy/PredictWind/Garmin ActiveCaptain. Mata o feel "magazine editorial vintage" e adota padrões mobile-app modernos. Mudanças visuais (CSS overlay v3 sem alterar HTML/JS de business): - Paleta dark navy (#0d2538) + cyan accent (#06b6d4) + reservado red pra alarme - Inter (sans-serif) substitui Fraunces (italic editorial) - Tabular nums em todas as métricas (lat/lon/depth/speed) - Cards modernos: border-radius 14px + shadows sutis + bg dark - Header 50% mais compacto (sem compass mark, avatar maior + accent cyan) - FAB reposicionado acima da bottom nav, gradient cyan - Modais: bottom sheet no mobile com top corners rounded - Form fields dark com focus glow cyan - Buttons com border-radius modernos, primary = cyan filled Novos componentes: - Bottom navigation: 5 tabs com line icons (Início/Travessias/Pendências/ Zonas/Mais), backdrop-filter blur, badge vermelho em pendências overdue - Safety status bar (sticky abaixo do header): GPS dot + Anchor watch + Bateria. Pulsa amarelo se warn, vermelho se danger - switchPanel() unifica top tabs (legacy) + bottom nav Service worker bumped pra invalidar cache antigo automaticamente. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
b57ba0da37
commit
c7994167be
6 changed files with 945 additions and 9 deletions
|
|
@ -15,7 +15,7 @@
|
||||||
<title>Diário de Bordo</title>
|
<title>Diário de Bordo</title>
|
||||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||||
<link href="https://fonts.googleapis.com/css2?family=Fraunces:ital,opsz,wght,SOFT@0,9..144,400..700,0..100;1,9..144,400..700,0..100&family=Manrope:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500;600&display=swap" rel="stylesheet">
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500;600;700&display=swap" rel="stylesheet">
|
||||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.9.4/leaflet.min.css">
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.9.4/leaflet.min.css">
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.9.4/leaflet.min.js"></script>
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.9.4/leaflet.min.js"></script>
|
||||||
<link rel="icon" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cg stroke='%230e2a3d' stroke-width='1' fill='none'%3E%3Ccircle cx='12' cy='12' r='10'/%3E%3Cpath d='M12 2 L13.5 12 L12 22 L10.5 12 Z' fill='%230e2a3d'/%3E%3Cpath d='M2 12 L12 13.5 L22 12 L12 10.5 Z' fill='%23a07832'/%3E%3C/g%3E%3C/svg%3E">
|
<link rel="icon" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cg stroke='%230e2a3d' stroke-width='1' fill='none'%3E%3Ccircle cx='12' cy='12' r='10'/%3E%3Cpath d='M12 2 L13.5 12 L12 22 L10.5 12 Z' fill='%230e2a3d'/%3E%3Cpath d='M2 12 L12 13.5 L22 12 L12 10.5 Z' fill='%23a07832'/%3E%3C/g%3E%3C/svg%3E">
|
||||||
|
|
@ -1405,6 +1405,393 @@ header{
|
||||||
|
|
||||||
/* ── TOOLBAR refinada ── */
|
/* ── TOOLBAR refinada ── */
|
||||||
.toolbar{gap:10px; margin-bottom:18px}
|
.toolbar{gap:10px; margin-bottom:18px}
|
||||||
|
|
||||||
|
/* ════════════════════════════════════════════════════════════════════
|
||||||
|
v3 — "MARINE PRO DARK" REDESIGN (override completo)
|
||||||
|
Bottom nav · Inter + Mono · Dark navy + cyan · Cards modernos
|
||||||
|
════════════════════════════════════════════════════════════════════ */
|
||||||
|
:root{
|
||||||
|
/* Tipografia — sem Fraunces editorial */
|
||||||
|
--f-display:'Inter',-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;
|
||||||
|
--f-body:'Inter',-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;
|
||||||
|
--f-mono:'JetBrains Mono','SF Mono','Consolas',monospace;
|
||||||
|
/* Paleta marine pro dark */
|
||||||
|
--m-bg:#0d2538; /* deep navy (canvas) */
|
||||||
|
--m-bg-2:#0f2a40; /* surface 1 */
|
||||||
|
--m-bg-3:#163a55; /* surface 2 (cards) */
|
||||||
|
--m-bg-4:#1d4a6b; /* surface elevated */
|
||||||
|
--m-border:rgba(255,255,255,.08);
|
||||||
|
--m-border-strong:rgba(255,255,255,.18);
|
||||||
|
--m-text:#e8f1f8; /* primary text */
|
||||||
|
--m-text-mid:#b3c5d6; /* secondary */
|
||||||
|
--m-text-soft:#7d97ad; /* tertiary */
|
||||||
|
--m-accent:#06b6d4; /* cyan accent */
|
||||||
|
--m-accent-2:#22d3ee; /* cyan brighter */
|
||||||
|
--m-accent-glow:rgba(6,182,212,.20);
|
||||||
|
--m-ok:#10b981; /* anchored / safe */
|
||||||
|
--m-warn:#f59e0b; /* drift / soon */
|
||||||
|
--m-danger:#ef4444; /* alarm */
|
||||||
|
--m-info:#3b82f6; /* info */
|
||||||
|
/* Spacing scale */
|
||||||
|
--sp-1:4px;--sp-2:8px;--sp-3:12px;--sp-4:16px;--sp-5:24px;--sp-6:32px;--sp-7:48px;
|
||||||
|
/* Radius */
|
||||||
|
--m-r-sm:6px;--m-r-md:10px;--m-r-lg:14px;--m-r-xl:20px;--m-r-pill:9999px;
|
||||||
|
/* Shadows (subtle, marine) */
|
||||||
|
--m-sh-1:0 1px 2px rgba(0,0,0,.32);
|
||||||
|
--m-sh-2:0 2px 6px rgba(0,0,0,.28),0 1px 2px rgba(0,0,0,.24);
|
||||||
|
--m-sh-3:0 8px 20px rgba(0,0,0,.32),0 2px 6px rgba(0,0,0,.24);
|
||||||
|
}
|
||||||
|
|
||||||
|
html,body{
|
||||||
|
background:var(--m-bg);
|
||||||
|
color:var(--m-text);
|
||||||
|
font-family:var(--f-body);
|
||||||
|
font-feature-settings:'cv11','ss03';
|
||||||
|
font-size:15px;line-height:1.5;
|
||||||
|
}
|
||||||
|
body{
|
||||||
|
background-image:
|
||||||
|
radial-gradient(ellipse 800px 600px at top right,rgba(34,211,238,.04) 0%,transparent 70%),
|
||||||
|
radial-gradient(ellipse 700px 500px at bottom left,rgba(6,182,212,.03) 0%,transparent 70%),
|
||||||
|
linear-gradient(180deg,#0a1f30 0%,#0d2538 100%);
|
||||||
|
background-attachment:fixed;
|
||||||
|
padding-bottom:calc(76px + env(safe-area-inset-bottom));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Mata o italic editorial em TUDO */
|
||||||
|
.boat-name,.entry-title,.empty-title,.modal-head h3,
|
||||||
|
.entry-notes,.field textarea,.export-card-title,
|
||||||
|
.export-card-text,.field-hint,h1,h2,h3,h4,h5,
|
||||||
|
.gps-card,.anchor-card,.fleet-name,.welcome-tagline{
|
||||||
|
font-family:var(--f-body)!important;
|
||||||
|
font-style:normal!important;
|
||||||
|
font-variation-settings:normal!important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ── HEADER COMPACTO ── */
|
||||||
|
header{
|
||||||
|
background:linear-gradient(180deg,var(--m-bg-2) 0%,var(--m-bg) 100%);
|
||||||
|
border-bottom:1px solid var(--m-border);
|
||||||
|
padding:max(10px,env(safe-area-inset-top)) 14px 10px;
|
||||||
|
box-shadow:var(--m-sh-1);
|
||||||
|
}
|
||||||
|
.header-row{gap:10px;max-width:760px}
|
||||||
|
.compass-mark{display:none} /* compact: avatar é suficiente */
|
||||||
|
.boat-tagline{
|
||||||
|
font-family:var(--f-mono);font-size:9px;color:var(--m-accent);
|
||||||
|
letter-spacing:.18em;opacity:.85;margin-bottom:1px;
|
||||||
|
}
|
||||||
|
.boat-name,.boat-selector{
|
||||||
|
font-family:var(--f-body)!important;font-style:normal!important;
|
||||||
|
font-size:17px!important;font-weight:600;letter-spacing:-.01em;
|
||||||
|
color:var(--m-text)!important;line-height:1.2;
|
||||||
|
}
|
||||||
|
.boat-meta{
|
||||||
|
font-family:var(--f-body);font-size:11px;color:var(--m-text-soft);
|
||||||
|
text-transform:none;letter-spacing:0;
|
||||||
|
}
|
||||||
|
.boat-edit-btn{display:none}
|
||||||
|
.boat-header-avatar{
|
||||||
|
width:38px;height:38px;border:2px solid var(--m-accent);
|
||||||
|
background:var(--m-bg-3);color:var(--m-accent);
|
||||||
|
box-shadow:0 0 0 3px var(--m-accent-glow);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ── SAFETY STATUS BAR (logo abaixo do header) ── */
|
||||||
|
.safety-bar{
|
||||||
|
display:flex;justify-content:space-between;align-items:center;
|
||||||
|
background:var(--m-bg-2);border-bottom:1px solid var(--m-border);
|
||||||
|
padding:6px 14px;font-family:var(--f-mono);font-size:10.5px;
|
||||||
|
color:var(--m-text-mid);letter-spacing:.04em;
|
||||||
|
position:sticky;top:0;z-index:39;
|
||||||
|
}
|
||||||
|
.safety-bar-item{display:inline-flex;align-items:center;gap:5px}
|
||||||
|
.safety-bar-dot{width:7px;height:7px;border-radius:50%;background:var(--m-text-soft)}
|
||||||
|
.safety-bar-dot.ok{background:var(--m-ok);box-shadow:0 0 6px var(--m-ok)}
|
||||||
|
.safety-bar-dot.warn{background:var(--m-warn);box-shadow:0 0 6px var(--m-warn);animation:pulseDot 1.5s infinite}
|
||||||
|
.safety-bar-dot.danger{background:var(--m-danger);box-shadow:0 0 8px var(--m-danger);animation:pulseDot .8s infinite}
|
||||||
|
@keyframes pulseDot{50%{opacity:.4}}
|
||||||
|
|
||||||
|
/* ── TOP TABS REMOVIDAS (substituídas pela bottom nav) ── */
|
||||||
|
.tabs{display:none!important}
|
||||||
|
|
||||||
|
/* ── CONTAINER ── */
|
||||||
|
.container{padding:14px 12px 20px;max-width:760px}
|
||||||
|
.panel{padding:0;background:transparent}
|
||||||
|
|
||||||
|
/* ── CARDS DARK MODERNOS ── */
|
||||||
|
.export-card,.gps-card,.anchor-card,.empty,.contact-card{
|
||||||
|
background:var(--m-bg-3);
|
||||||
|
border:1px solid var(--m-border);
|
||||||
|
border-radius:var(--m-r-lg);
|
||||||
|
box-shadow:var(--m-sh-2);
|
||||||
|
padding:16px;margin-bottom:12px;
|
||||||
|
color:var(--m-text);
|
||||||
|
}
|
||||||
|
.export-card-title{
|
||||||
|
color:var(--m-text)!important;font-weight:600;font-size:15px;
|
||||||
|
letter-spacing:-.005em;margin-bottom:6px;
|
||||||
|
}
|
||||||
|
.export-card-text{
|
||||||
|
color:var(--m-text-mid)!important;font-size:13px;line-height:1.5;
|
||||||
|
}
|
||||||
|
.gps-card,.anchor-card{
|
||||||
|
background:linear-gradient(165deg,var(--m-bg-3),var(--m-bg-2));
|
||||||
|
border:1px solid var(--m-border-strong);
|
||||||
|
}
|
||||||
|
.gps-card.idle{
|
||||||
|
background:var(--m-bg-3);
|
||||||
|
color:var(--m-text);
|
||||||
|
}
|
||||||
|
.gps-stats{gap:14px}
|
||||||
|
.gps-stat-value,.t-stat-value{
|
||||||
|
color:var(--m-accent)!important;
|
||||||
|
font-family:var(--f-mono);font-weight:700;
|
||||||
|
font-variant-numeric:tabular-nums;
|
||||||
|
}
|
||||||
|
.gps-stat-label,.t-stat-label{
|
||||||
|
color:var(--m-text-soft)!important;
|
||||||
|
font-size:9.5px;letter-spacing:.14em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.entry{
|
||||||
|
background:var(--m-bg-3);
|
||||||
|
border:1px solid var(--m-border);
|
||||||
|
border-left:3px solid var(--m-accent);
|
||||||
|
border-radius:var(--m-r-md);
|
||||||
|
box-shadow:var(--m-sh-1);
|
||||||
|
padding:14px;margin-bottom:10px;
|
||||||
|
color:var(--m-text);
|
||||||
|
}
|
||||||
|
.entry-title{color:var(--m-text)!important;font-weight:600;font-size:15px}
|
||||||
|
.entry-meta{color:var(--m-text-mid)}
|
||||||
|
.entry.maint{border-left-color:var(--m-warn)}
|
||||||
|
.entry.pending{border-left-color:var(--m-warn)}
|
||||||
|
.entry.pending.overdue{border-left-color:var(--m-danger)}
|
||||||
|
.entry.pending.done{border-left-color:var(--m-ok);opacity:.7}
|
||||||
|
.entry-grid dt{color:var(--m-text-soft)}
|
||||||
|
.entry-grid dd{color:var(--m-text)}
|
||||||
|
.entry-notes{
|
||||||
|
background:var(--m-bg-2)!important;border-left-color:var(--m-accent)!important;
|
||||||
|
color:var(--m-text-mid)!important;border-radius:var(--m-r-sm);
|
||||||
|
font-style:normal!important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ── STATS DASHBOARD ── */
|
||||||
|
.stats{gap:8px}
|
||||||
|
.stat{
|
||||||
|
background:var(--m-bg-3);
|
||||||
|
border:1px solid var(--m-border);
|
||||||
|
border-radius:var(--m-r-md);
|
||||||
|
padding:14px 12px;
|
||||||
|
position:relative;overflow:hidden;
|
||||||
|
}
|
||||||
|
.stat::before{
|
||||||
|
content:'';position:absolute;top:0;left:0;right:0;height:2px;
|
||||||
|
background:linear-gradient(90deg,var(--m-accent),var(--m-accent-2));
|
||||||
|
opacity:.7;
|
||||||
|
}
|
||||||
|
.stat-value{
|
||||||
|
color:var(--m-accent)!important;
|
||||||
|
font-family:var(--f-mono);font-weight:700;
|
||||||
|
font-variant-numeric:tabular-nums;
|
||||||
|
font-size:24px;
|
||||||
|
}
|
||||||
|
.stat-label{
|
||||||
|
color:var(--m-text-soft)!important;
|
||||||
|
font-size:9.5px;letter-spacing:.14em;
|
||||||
|
}
|
||||||
|
.stat-sub{color:var(--m-text-mid)!important;font-style:normal!important;font-size:11px}
|
||||||
|
|
||||||
|
/* ── BUTTONS ── */
|
||||||
|
.btn{
|
||||||
|
background:var(--m-bg-3);border:1px solid var(--m-border-strong);
|
||||||
|
color:var(--m-text);font-family:var(--f-body);
|
||||||
|
font-size:14px;font-weight:500;
|
||||||
|
border-radius:var(--m-r-md);
|
||||||
|
min-height:44px;padding:11px 18px;
|
||||||
|
text-transform:none;letter-spacing:0;
|
||||||
|
transition:all .15s;
|
||||||
|
}
|
||||||
|
.btn:hover{background:var(--m-bg-4);border-color:var(--m-accent)}
|
||||||
|
.btn-primary,.btn-brass{
|
||||||
|
background:var(--m-accent);color:#001a25;border-color:var(--m-accent);
|
||||||
|
font-weight:600;
|
||||||
|
}
|
||||||
|
.btn-primary:hover,.btn-brass:hover{background:var(--m-accent-2);color:#001a25;border-color:var(--m-accent-2)}
|
||||||
|
.btn-danger{background:transparent;color:var(--m-danger);border-color:var(--m-danger)}
|
||||||
|
.btn-danger:hover{background:rgba(239,68,68,.1);color:var(--m-danger)}
|
||||||
|
.btn-block{width:100%}
|
||||||
|
.btn-sm{min-height:34px;padding:7px 14px;font-size:12.5px}
|
||||||
|
.btn-big{min-height:54px;padding:14px 22px;font-size:15px;font-weight:600}
|
||||||
|
|
||||||
|
/* ── FAB acima da bottom nav ── */
|
||||||
|
.fab{
|
||||||
|
bottom:calc(86px + env(safe-area-inset-bottom))!important;
|
||||||
|
right:18px!important;
|
||||||
|
background:linear-gradient(135deg,var(--m-accent),var(--m-accent-2))!important;
|
||||||
|
color:#001a25!important;
|
||||||
|
width:56px!important;height:56px!important;
|
||||||
|
box-shadow:0 6px 20px var(--m-accent-glow),0 2px 8px rgba(0,0,0,.5)!important;
|
||||||
|
}
|
||||||
|
.fab:hover{transform:scale(1.06) translateY(-2px)!important}
|
||||||
|
.fab svg{stroke:#001a25!important}
|
||||||
|
|
||||||
|
/* ── BOTTOM NAVIGATION ── */
|
||||||
|
.bottom-nav{
|
||||||
|
position:fixed;bottom:0;left:0;right:0;z-index:48;
|
||||||
|
background:var(--m-bg-2);
|
||||||
|
border-top:1px solid var(--m-border);
|
||||||
|
padding:6px 0 max(6px,env(safe-area-inset-bottom));
|
||||||
|
display:flex;justify-content:space-around;align-items:stretch;
|
||||||
|
backdrop-filter:blur(18px);
|
||||||
|
-webkit-backdrop-filter:blur(18px);
|
||||||
|
background:rgba(15,42,64,.92);
|
||||||
|
}
|
||||||
|
.bn-item{
|
||||||
|
flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;
|
||||||
|
gap:3px;padding:6px 4px;
|
||||||
|
background:none;border:none;cursor:pointer;
|
||||||
|
color:var(--m-text-soft);
|
||||||
|
font-family:var(--f-body);font-size:10px;font-weight:500;
|
||||||
|
transition:color .15s;
|
||||||
|
min-height:54px;
|
||||||
|
}
|
||||||
|
.bn-item:hover{color:var(--m-text-mid)}
|
||||||
|
.bn-item.active{color:var(--m-accent)}
|
||||||
|
.bn-item svg{width:22px;height:22px;stroke-width:2;transition:stroke-width .15s}
|
||||||
|
.bn-item.active svg{stroke-width:2.4}
|
||||||
|
.bn-badge{
|
||||||
|
position:absolute;top:4px;right:50%;transform:translate(14px,0);
|
||||||
|
background:var(--m-danger);color:#fff;
|
||||||
|
font-family:var(--f-mono);font-size:9px;font-weight:700;
|
||||||
|
min-width:16px;height:16px;border-radius:8px;
|
||||||
|
display:flex;align-items:center;justify-content:center;padding:0 4px;
|
||||||
|
}
|
||||||
|
.bn-item{position:relative}
|
||||||
|
|
||||||
|
/* ── MODAIS dark ── */
|
||||||
|
.modal{
|
||||||
|
background:var(--m-bg-3);
|
||||||
|
color:var(--m-text);
|
||||||
|
border:1px solid var(--m-border-strong);
|
||||||
|
border-radius:var(--m-r-xl) var(--m-r-xl) 0 0;
|
||||||
|
border-top:1px solid var(--m-border-strong);
|
||||||
|
}
|
||||||
|
@media(min-width:600px){
|
||||||
|
.modal{border-radius:var(--m-r-xl);}
|
||||||
|
}
|
||||||
|
.modal-head{border-bottom:1px solid var(--m-border)}
|
||||||
|
.modal-head h3{color:var(--m-text);font-style:normal;font-weight:600;font-size:17px}
|
||||||
|
.modal-foot{border-top:1px solid var(--m-border);background:var(--m-bg-2)}
|
||||||
|
.modal-backdrop{background:rgba(0,0,0,.7);backdrop-filter:blur(6px)}
|
||||||
|
.icon-btn{color:var(--m-text-mid);background:transparent;border:none}
|
||||||
|
.icon-btn:hover{color:var(--m-text);background:var(--m-bg-2)}
|
||||||
|
|
||||||
|
/* ── FORM FIELDS dark ── */
|
||||||
|
.field-label{color:var(--m-text-soft);font-size:10px;letter-spacing:.12em;font-weight:600;text-transform:uppercase}
|
||||||
|
.field input,.field textarea,.field select{
|
||||||
|
background:var(--m-bg-2)!important;
|
||||||
|
border:1px solid var(--m-border-strong)!important;
|
||||||
|
color:var(--m-text)!important;
|
||||||
|
border-radius:var(--m-r-sm);
|
||||||
|
font-family:var(--f-body);font-style:normal!important;
|
||||||
|
font-size:15px;padding:11px 13px;
|
||||||
|
}
|
||||||
|
.field input:focus,.field textarea:focus,.field select:focus{
|
||||||
|
outline:none!important;
|
||||||
|
border-color:var(--m-accent)!important;
|
||||||
|
box-shadow:0 0 0 3px var(--m-accent-glow)!important;
|
||||||
|
background:var(--m-bg-3)!important;
|
||||||
|
}
|
||||||
|
.field-hint{color:var(--m-text-soft);font-style:normal!important}
|
||||||
|
|
||||||
|
/* ── SECTION HEADERS / TOOLBARS ── */
|
||||||
|
.section-header h2{color:var(--m-text-soft);text-transform:uppercase;letter-spacing:.12em;font-size:10.5px}
|
||||||
|
.toolbar{margin-bottom:14px}
|
||||||
|
|
||||||
|
/* ── EMPTY STATES ── */
|
||||||
|
.empty{text-align:center;padding:32px 20px;color:var(--m-text-soft)}
|
||||||
|
.empty-title{color:var(--m-text);font-weight:600;font-size:16px;font-style:normal!important}
|
||||||
|
.empty-text{color:var(--m-text-soft);font-size:13.5px;line-height:1.55}
|
||||||
|
|
||||||
|
/* ── SYNC INDICATOR ── */
|
||||||
|
.sync-indicator{font-size:10px;margin-left:5px}
|
||||||
|
|
||||||
|
/* ── WELCOME SCREEN dark ── */
|
||||||
|
.welcome-screen{background:linear-gradient(135deg,var(--m-bg) 0%,var(--m-bg-2) 50%,#06151f 100%)}
|
||||||
|
.welcome-card{
|
||||||
|
background:var(--m-bg-3);
|
||||||
|
border:1px solid var(--m-border-strong);
|
||||||
|
border-radius:var(--m-r-xl);
|
||||||
|
box-shadow:var(--m-sh-3);
|
||||||
|
color:var(--m-text);
|
||||||
|
}
|
||||||
|
.welcome-title{color:var(--m-text);font-style:normal;font-weight:700;font-size:24px}
|
||||||
|
.welcome-tagline{color:var(--m-text-mid);font-style:normal;font-size:14px}
|
||||||
|
.welcome-btn{
|
||||||
|
background:var(--m-bg-2);border:1px solid var(--m-border-strong);
|
||||||
|
color:var(--m-text);border-radius:var(--m-r-md);
|
||||||
|
font-family:var(--f-body);font-weight:500;
|
||||||
|
}
|
||||||
|
.welcome-btn:hover{background:var(--m-bg-4);border-color:var(--m-accent)}
|
||||||
|
.welcome-btn-google{background:#fff;color:#3c4043;border-color:#dadce0}
|
||||||
|
.welcome-btn-google:hover{background:#f1f3f4;color:#3c4043;border-color:#dadce0}
|
||||||
|
.welcome-btn-primary{background:var(--m-accent);color:#001a25;border-color:var(--m-accent)}
|
||||||
|
.welcome-btn-primary:hover{background:var(--m-accent-2);color:#001a25;border-color:var(--m-accent-2)}
|
||||||
|
.welcome-btn-text{color:var(--m-text-soft);background:transparent;border:none}
|
||||||
|
.welcome-tab{color:var(--m-text-soft);text-transform:uppercase;letter-spacing:.12em}
|
||||||
|
.welcome-tab.active{color:var(--m-accent);border-bottom-color:var(--m-accent)}
|
||||||
|
|
||||||
|
/* ── FLEET & ANCHOR CALC dark ── */
|
||||||
|
.fleet-item{background:var(--m-bg-2);border:1px solid var(--m-border)}
|
||||||
|
.fleet-item:hover{background:var(--m-bg-4);border-color:var(--m-accent)}
|
||||||
|
.fleet-item.active{border-left:3px solid var(--m-accent);background:var(--m-bg-4)}
|
||||||
|
.fleet-name{color:var(--m-text);font-style:normal;font-weight:600;font-size:15px}
|
||||||
|
.fleet-meta{color:var(--m-text-soft);text-transform:uppercase;letter-spacing:.06em}
|
||||||
|
.fleet-active-badge{background:var(--m-accent);color:#001a25;font-weight:700}
|
||||||
|
.fleet-edit-icon{background:transparent;border:1px solid var(--m-border-strong);color:var(--m-text-mid)}
|
||||||
|
.fleet-units-toggle{border:1px solid var(--m-border-strong);background:var(--m-bg-2)}
|
||||||
|
.fleet-units-toggle button{background:transparent;color:var(--m-text-mid)}
|
||||||
|
.fleet-units-toggle button.active{background:var(--m-accent);color:#001a25}
|
||||||
|
|
||||||
|
.anchor-calc{background:var(--m-bg-2);border:1px solid var(--m-border);border-left:3px solid var(--m-accent)}
|
||||||
|
.anchor-calc-head{color:var(--m-accent);font-weight:600}
|
||||||
|
.anchor-calc-stat{background:var(--m-bg-3);border:1px solid var(--m-border)}
|
||||||
|
.anchor-calc-stat-label{color:var(--m-text-soft)}
|
||||||
|
.anchor-calc-stat-value{color:var(--m-text);font-style:normal;font-weight:700;font-family:var(--f-mono);font-variant-numeric:tabular-nums}
|
||||||
|
.anchor-calc-stat-value.ok{color:var(--m-ok)}
|
||||||
|
.anchor-calc-stat-value.warn{color:var(--m-warn)}
|
||||||
|
.anchor-calc-stat-value.danger{color:var(--m-danger)}
|
||||||
|
.anchor-calc-advice{background:rgba(6,182,212,.08);border-left-color:var(--m-accent);color:var(--m-text-mid);font-style:normal}
|
||||||
|
|
||||||
|
/* ── BADGES & TAGS ── */
|
||||||
|
.badge{background:var(--m-danger);color:#fff;font-family:var(--f-mono);font-weight:700}
|
||||||
|
.pax-tag{background:var(--m-bg-3);border:1px solid var(--m-border);color:var(--m-text);border-radius:var(--m-r-pill)}
|
||||||
|
|
||||||
|
/* ── ALERTS ── */
|
||||||
|
.alert-overdue,.alert-danger{background:rgba(239,68,68,.08);border-left:3px solid var(--m-danger);color:var(--m-text)}
|
||||||
|
.alert-soon,.alert-warn{background:rgba(245,158,11,.08);border-left:3px solid var(--m-warn);color:var(--m-text)}
|
||||||
|
.alert-info{background:rgba(59,130,246,.08);border-left:3px solid var(--m-info);color:var(--m-text)}
|
||||||
|
|
||||||
|
/* ── TOAST ── */
|
||||||
|
.toast{
|
||||||
|
background:var(--m-bg-3);color:var(--m-text);
|
||||||
|
border:1px solid var(--m-border-strong);
|
||||||
|
border-radius:var(--m-r-md);
|
||||||
|
box-shadow:var(--m-sh-3);
|
||||||
|
font-family:var(--f-body);font-style:normal;font-weight:500;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ── pax/checklist/tags ajustes ── */
|
||||||
|
.checklist-card{background:var(--m-bg-3);border:1px solid var(--m-border);border-radius:var(--m-r-md);color:var(--m-text)}
|
||||||
|
.weather-widget{background:var(--m-bg-3)!important;border:1px solid var(--m-border)!important;color:var(--m-text)!important;border-radius:var(--m-r-md)}
|
||||||
|
|
||||||
|
/* ── SCROLLBAR thin estilo iOS ── */
|
||||||
|
::-webkit-scrollbar{width:6px;height:6px}
|
||||||
|
::-webkit-scrollbar-thumb{background:var(--m-border-strong);border-radius:3px}
|
||||||
|
::-webkit-scrollbar-track{background:transparent}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|
@ -1450,6 +1837,13 @@ header{
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
|
<!-- Safety status bar (sempre visível, marine pro) -->
|
||||||
|
<div class="safety-bar" id="safety-bar">
|
||||||
|
<span class="safety-bar-item"><span class="safety-bar-dot" id="sb-gps-dot"></span><span id="sb-gps">GPS aguardando</span></span>
|
||||||
|
<span class="safety-bar-item" id="sb-anchor-wrap" style="display:none"><span class="safety-bar-dot ok" id="sb-anchor-dot"></span><span id="sb-anchor">Fundeado</span></span>
|
||||||
|
<span class="safety-bar-item"><span id="sb-battery">—</span></span>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="container">
|
<div class="container">
|
||||||
|
|
||||||
<div class="tabs" role="tablist">
|
<div class="tabs" role="tablist">
|
||||||
|
|
@ -1951,6 +2345,31 @@ Hora: {HORA}</textarea>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<button class="fab" id="fab" onclick="quickAdd()" title="Adicionar"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M12 5v14M5 12h14"/></svg></button>
|
<button class="fab" id="fab" onclick="quickAdd()" title="Adicionar"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M12 5v14M5 12h14"/></svg></button>
|
||||||
|
|
||||||
|
<!-- Bottom Navigation (substitui top tabs) -->
|
||||||
|
<nav class="bottom-nav" id="bottom-nav">
|
||||||
|
<button class="bn-item active" data-panel="overview" onclick="switchPanel('overview')" aria-label="Início">
|
||||||
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"><path d="M3 12l9-9 9 9"/><path d="M5 10v10h14V10"/><path d="M9 20v-6h6v6"/></svg>
|
||||||
|
<span>Início</span>
|
||||||
|
</button>
|
||||||
|
<button class="bn-item" data-panel="trips" onclick="switchPanel('trips')" aria-label="Travessias">
|
||||||
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"><path d="M2 17.5L12 22l10-4.5"/><path d="M2 12.5L12 17l10-4.5"/><path d="M12 2L2 7l10 5 10-5z"/></svg>
|
||||||
|
<span>Travessias</span>
|
||||||
|
</button>
|
||||||
|
<button class="bn-item" data-panel="pending" onclick="switchPanel('pending')" aria-label="Pendências">
|
||||||
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><path d="M12 6v6l4 2"/></svg>
|
||||||
|
<span>Pendências</span>
|
||||||
|
<span class="bn-badge" id="bn-badge-pending" style="display:none">0</span>
|
||||||
|
</button>
|
||||||
|
<button class="bn-item" data-panel="zones" onclick="switchPanel('zones')" aria-label="Zonas">
|
||||||
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"><path d="M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z"/><circle cx="12" cy="10" r="3"/></svg>
|
||||||
|
<span>Zonas</span>
|
||||||
|
</button>
|
||||||
|
<button class="bn-item" data-panel="export" onclick="switchPanel('export')" aria-label="Mais">
|
||||||
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"><circle cx="5" cy="12" r="1.5"/><circle cx="12" cy="12" r="1.5"/><circle cx="19" cy="12" r="1.5"/></svg>
|
||||||
|
<span>Mais</span>
|
||||||
|
</button>
|
||||||
|
</nav>
|
||||||
<!-- Fleet Manager Modal -->
|
<!-- Fleet Manager Modal -->
|
||||||
<div class="modal-backdrop" id="fleet-modal" onclick="if(event.target===this)closeModal('fleet-modal')">
|
<div class="modal-backdrop" id="fleet-modal" onclick="if(event.target===this)closeModal('fleet-modal')">
|
||||||
<div class="modal" style="max-width:520px">
|
<div class="modal" style="max-width:520px">
|
||||||
|
|
@ -2727,7 +3146,56 @@ function syncUnitsToggle(){
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
document.querySelectorAll('.tab').forEach(t=>{t.addEventListener('click',()=>{document.querySelectorAll('.tab').forEach(x=>x.classList.remove('active'));document.querySelectorAll('.panel').forEach(x=>x.classList.remove('active'));t.classList.add('active');document.getElementById('panel-'+t.dataset.panel).classList.add('active');document.getElementById('fab').style.display=['trips','maintenance','pending','zones'].includes(t.dataset.panel)?'flex':'none';if(t.dataset.panel==='export'){updateStorageInfo();bindCloudInputs();renderCloudStatus();renderShareList();bindWeatherInputs();renderAuthBox();refreshGoogleStatus()}if(t.dataset.panel==='pending'&&_gcalConnected&&Date.now()-_gcalLastPullAt>GCAL_PULL_INTERVAL_MS)googlePullNow();if(t.dataset.panel==='zones')renderZones();window.scrollTo(0,0)})});
|
function switchPanel(name){
|
||||||
|
document.querySelectorAll('.tab').forEach(x=>x.classList.toggle('active',x.dataset.panel===name));
|
||||||
|
document.querySelectorAll('.bn-item').forEach(x=>x.classList.toggle('active',x.dataset.panel===name));
|
||||||
|
document.querySelectorAll('.panel').forEach(x=>x.classList.remove('active'));
|
||||||
|
const p=document.getElementById('panel-'+name);
|
||||||
|
if(p)p.classList.add('active');
|
||||||
|
// FAB visível em panels que têm "criar item"
|
||||||
|
document.getElementById('fab').style.display=['trips','maintenance','pending','zones','overview'].includes(name)?'flex':'none';
|
||||||
|
if(name==='export'){updateStorageInfo();bindCloudInputs();renderCloudStatus();renderShareList();bindWeatherInputs();renderAuthBox();refreshGoogleStatus()}
|
||||||
|
if(name==='pending'&&_gcalConnected&&Date.now()-_gcalLastPullAt>GCAL_PULL_INTERVAL_MS)googlePullNow();
|
||||||
|
if(name==='zones')renderZones();
|
||||||
|
window.scrollTo(0,0);
|
||||||
|
}
|
||||||
|
// Compat: top tabs (escondidos via CSS mas mantém handlers caso re-exibidos)
|
||||||
|
document.querySelectorAll('.tab').forEach(t=>{t.addEventListener('click',()=>switchPanel(t.dataset.panel))});
|
||||||
|
|
||||||
|
// Safety bar: atualiza bateria, GPS, anchor a cada 10s
|
||||||
|
function updateSafetyBar(){
|
||||||
|
const bat=document.getElementById('battery-indicator');
|
||||||
|
const sbBat=document.getElementById('sb-battery');
|
||||||
|
if(sbBat&&bat){sbBat.textContent=bat.textContent.trim()||'—'}
|
||||||
|
const sbGps=document.getElementById('sb-gps');
|
||||||
|
const sbGpsDot=document.getElementById('sb-gps-dot');
|
||||||
|
if(sbGps&&sbGpsDot){
|
||||||
|
if(tracking?.active||(typeof lastGpsPos!=='undefined'&&lastGpsPos)){
|
||||||
|
sbGps.textContent='GPS ativo';sbGpsDot.className='safety-bar-dot ok';
|
||||||
|
}else{
|
||||||
|
sbGps.textContent='GPS aguardando';sbGpsDot.className='safety-bar-dot';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const sbAnchorWrap=document.getElementById('sb-anchor-wrap');
|
||||||
|
const sbAnchorDot=document.getElementById('sb-anchor-dot');
|
||||||
|
const sbAnchor=document.getElementById('sb-anchor');
|
||||||
|
if(sbAnchorWrap&&anchorWatch){
|
||||||
|
if(anchorWatch.active){
|
||||||
|
sbAnchorWrap.style.display='inline-flex';
|
||||||
|
const breach=anchorWatch.currentDist>anchorWatch.radius;
|
||||||
|
sbAnchorDot.className='safety-bar-dot '+(breach?'danger':'ok');
|
||||||
|
sbAnchor.textContent=breach?'⚠ DERIVANDO!':`Fundeado · raio ${Math.round(anchorWatch.currentDist||0)}/${anchorWatch.radius}m`;
|
||||||
|
}else{
|
||||||
|
sbAnchorWrap.style.display='none';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Bottom nav badge pendências
|
||||||
|
const overdue=(state.pending||[]).filter(p=>!p.done&&p.dueDate&&p.dueDate<new Date().toISOString().slice(0,10)).length;
|
||||||
|
const bnBadge=document.getElementById('bn-badge-pending');
|
||||||
|
if(bnBadge){bnBadge.style.display=overdue>0?'flex':'none';bnBadge.textContent=overdue}
|
||||||
|
}
|
||||||
|
setInterval(updateSafetyBar,5000);
|
||||||
|
setTimeout(updateSafetyBar,1500);
|
||||||
function quickAdd(){const a=document.querySelector('.tab.active').dataset.panel;if(a==='maintenance')openMaintModal();else if(a==='pending')openPendingModal();else if(a==='zones')openZoneEditor();else openTripModal()}
|
function quickAdd(){const a=document.querySelector('.tab.active').dataset.panel;if(a==='maintenance')openMaintModal();else if(a==='pending')openPendingModal();else if(a==='zones')openZoneEditor();else openTripModal()}
|
||||||
function openModal(id){document.getElementById(id).classList.add('show')}
|
function openModal(id){document.getElementById(id).classList.add('show')}
|
||||||
function closeModal(id){document.getElementById(id).classList.remove('show')}
|
function closeModal(id){document.getElementById(id).classList.remove('show')}
|
||||||
|
|
|
||||||
|
|
@ -7,8 +7,8 @@ android {
|
||||||
applicationId "br.com.pontualtech.shivao"
|
applicationId "br.com.pontualtech.shivao"
|
||||||
minSdkVersion rootProject.ext.minSdkVersion
|
minSdkVersion rootProject.ext.minSdkVersion
|
||||||
targetSdkVersion rootProject.ext.targetSdkVersion
|
targetSdkVersion rootProject.ext.targetSdkVersion
|
||||||
versionCode 9
|
versionCode 10
|
||||||
versionName "1.6.2"
|
versionName "1.7.0"
|
||||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||||
aaptOptions {
|
aaptOptions {
|
||||||
// Files and dirs to omit from the packaged assets dir, modified to accommodate modern web apps.
|
// Files and dirs to omit from the packaged assets dir, modified to accommodate modern web apps.
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "shivao-mobile",
|
"name": "shivao-mobile",
|
||||||
"version": "1.6.2",
|
"version": "1.7.0",
|
||||||
"description": "Shivao app nativo (Capacitor wrapper Android/iOS)",
|
"description": "Shivao app nativo (Capacitor wrapper Android/iOS)",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@
|
||||||
<title>Diário de Bordo</title>
|
<title>Diário de Bordo</title>
|
||||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||||
<link href="https://fonts.googleapis.com/css2?family=Fraunces:ital,opsz,wght,SOFT@0,9..144,400..700,0..100;1,9..144,400..700,0..100&family=Manrope:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500;600&display=swap" rel="stylesheet">
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500;600;700&display=swap" rel="stylesheet">
|
||||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.9.4/leaflet.min.css">
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.9.4/leaflet.min.css">
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.9.4/leaflet.min.js"></script>
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.9.4/leaflet.min.js"></script>
|
||||||
<link rel="icon" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cg stroke='%230e2a3d' stroke-width='1' fill='none'%3E%3Ccircle cx='12' cy='12' r='10'/%3E%3Cpath d='M12 2 L13.5 12 L12 22 L10.5 12 Z' fill='%230e2a3d'/%3E%3Cpath d='M2 12 L12 13.5 L22 12 L12 10.5 Z' fill='%23a07832'/%3E%3C/g%3E%3C/svg%3E">
|
<link rel="icon" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cg stroke='%230e2a3d' stroke-width='1' fill='none'%3E%3Ccircle cx='12' cy='12' r='10'/%3E%3Cpath d='M12 2 L13.5 12 L12 22 L10.5 12 Z' fill='%230e2a3d'/%3E%3Cpath d='M2 12 L12 13.5 L22 12 L12 10.5 Z' fill='%23a07832'/%3E%3C/g%3E%3C/svg%3E">
|
||||||
|
|
@ -1405,6 +1405,393 @@ header{
|
||||||
|
|
||||||
/* ── TOOLBAR refinada ── */
|
/* ── TOOLBAR refinada ── */
|
||||||
.toolbar{gap:10px; margin-bottom:18px}
|
.toolbar{gap:10px; margin-bottom:18px}
|
||||||
|
|
||||||
|
/* ════════════════════════════════════════════════════════════════════
|
||||||
|
v3 — "MARINE PRO DARK" REDESIGN (override completo)
|
||||||
|
Bottom nav · Inter + Mono · Dark navy + cyan · Cards modernos
|
||||||
|
════════════════════════════════════════════════════════════════════ */
|
||||||
|
:root{
|
||||||
|
/* Tipografia — sem Fraunces editorial */
|
||||||
|
--f-display:'Inter',-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;
|
||||||
|
--f-body:'Inter',-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;
|
||||||
|
--f-mono:'JetBrains Mono','SF Mono','Consolas',monospace;
|
||||||
|
/* Paleta marine pro dark */
|
||||||
|
--m-bg:#0d2538; /* deep navy (canvas) */
|
||||||
|
--m-bg-2:#0f2a40; /* surface 1 */
|
||||||
|
--m-bg-3:#163a55; /* surface 2 (cards) */
|
||||||
|
--m-bg-4:#1d4a6b; /* surface elevated */
|
||||||
|
--m-border:rgba(255,255,255,.08);
|
||||||
|
--m-border-strong:rgba(255,255,255,.18);
|
||||||
|
--m-text:#e8f1f8; /* primary text */
|
||||||
|
--m-text-mid:#b3c5d6; /* secondary */
|
||||||
|
--m-text-soft:#7d97ad; /* tertiary */
|
||||||
|
--m-accent:#06b6d4; /* cyan accent */
|
||||||
|
--m-accent-2:#22d3ee; /* cyan brighter */
|
||||||
|
--m-accent-glow:rgba(6,182,212,.20);
|
||||||
|
--m-ok:#10b981; /* anchored / safe */
|
||||||
|
--m-warn:#f59e0b; /* drift / soon */
|
||||||
|
--m-danger:#ef4444; /* alarm */
|
||||||
|
--m-info:#3b82f6; /* info */
|
||||||
|
/* Spacing scale */
|
||||||
|
--sp-1:4px;--sp-2:8px;--sp-3:12px;--sp-4:16px;--sp-5:24px;--sp-6:32px;--sp-7:48px;
|
||||||
|
/* Radius */
|
||||||
|
--m-r-sm:6px;--m-r-md:10px;--m-r-lg:14px;--m-r-xl:20px;--m-r-pill:9999px;
|
||||||
|
/* Shadows (subtle, marine) */
|
||||||
|
--m-sh-1:0 1px 2px rgba(0,0,0,.32);
|
||||||
|
--m-sh-2:0 2px 6px rgba(0,0,0,.28),0 1px 2px rgba(0,0,0,.24);
|
||||||
|
--m-sh-3:0 8px 20px rgba(0,0,0,.32),0 2px 6px rgba(0,0,0,.24);
|
||||||
|
}
|
||||||
|
|
||||||
|
html,body{
|
||||||
|
background:var(--m-bg);
|
||||||
|
color:var(--m-text);
|
||||||
|
font-family:var(--f-body);
|
||||||
|
font-feature-settings:'cv11','ss03';
|
||||||
|
font-size:15px;line-height:1.5;
|
||||||
|
}
|
||||||
|
body{
|
||||||
|
background-image:
|
||||||
|
radial-gradient(ellipse 800px 600px at top right,rgba(34,211,238,.04) 0%,transparent 70%),
|
||||||
|
radial-gradient(ellipse 700px 500px at bottom left,rgba(6,182,212,.03) 0%,transparent 70%),
|
||||||
|
linear-gradient(180deg,#0a1f30 0%,#0d2538 100%);
|
||||||
|
background-attachment:fixed;
|
||||||
|
padding-bottom:calc(76px + env(safe-area-inset-bottom));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Mata o italic editorial em TUDO */
|
||||||
|
.boat-name,.entry-title,.empty-title,.modal-head h3,
|
||||||
|
.entry-notes,.field textarea,.export-card-title,
|
||||||
|
.export-card-text,.field-hint,h1,h2,h3,h4,h5,
|
||||||
|
.gps-card,.anchor-card,.fleet-name,.welcome-tagline{
|
||||||
|
font-family:var(--f-body)!important;
|
||||||
|
font-style:normal!important;
|
||||||
|
font-variation-settings:normal!important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ── HEADER COMPACTO ── */
|
||||||
|
header{
|
||||||
|
background:linear-gradient(180deg,var(--m-bg-2) 0%,var(--m-bg) 100%);
|
||||||
|
border-bottom:1px solid var(--m-border);
|
||||||
|
padding:max(10px,env(safe-area-inset-top)) 14px 10px;
|
||||||
|
box-shadow:var(--m-sh-1);
|
||||||
|
}
|
||||||
|
.header-row{gap:10px;max-width:760px}
|
||||||
|
.compass-mark{display:none} /* compact: avatar é suficiente */
|
||||||
|
.boat-tagline{
|
||||||
|
font-family:var(--f-mono);font-size:9px;color:var(--m-accent);
|
||||||
|
letter-spacing:.18em;opacity:.85;margin-bottom:1px;
|
||||||
|
}
|
||||||
|
.boat-name,.boat-selector{
|
||||||
|
font-family:var(--f-body)!important;font-style:normal!important;
|
||||||
|
font-size:17px!important;font-weight:600;letter-spacing:-.01em;
|
||||||
|
color:var(--m-text)!important;line-height:1.2;
|
||||||
|
}
|
||||||
|
.boat-meta{
|
||||||
|
font-family:var(--f-body);font-size:11px;color:var(--m-text-soft);
|
||||||
|
text-transform:none;letter-spacing:0;
|
||||||
|
}
|
||||||
|
.boat-edit-btn{display:none}
|
||||||
|
.boat-header-avatar{
|
||||||
|
width:38px;height:38px;border:2px solid var(--m-accent);
|
||||||
|
background:var(--m-bg-3);color:var(--m-accent);
|
||||||
|
box-shadow:0 0 0 3px var(--m-accent-glow);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ── SAFETY STATUS BAR (logo abaixo do header) ── */
|
||||||
|
.safety-bar{
|
||||||
|
display:flex;justify-content:space-between;align-items:center;
|
||||||
|
background:var(--m-bg-2);border-bottom:1px solid var(--m-border);
|
||||||
|
padding:6px 14px;font-family:var(--f-mono);font-size:10.5px;
|
||||||
|
color:var(--m-text-mid);letter-spacing:.04em;
|
||||||
|
position:sticky;top:0;z-index:39;
|
||||||
|
}
|
||||||
|
.safety-bar-item{display:inline-flex;align-items:center;gap:5px}
|
||||||
|
.safety-bar-dot{width:7px;height:7px;border-radius:50%;background:var(--m-text-soft)}
|
||||||
|
.safety-bar-dot.ok{background:var(--m-ok);box-shadow:0 0 6px var(--m-ok)}
|
||||||
|
.safety-bar-dot.warn{background:var(--m-warn);box-shadow:0 0 6px var(--m-warn);animation:pulseDot 1.5s infinite}
|
||||||
|
.safety-bar-dot.danger{background:var(--m-danger);box-shadow:0 0 8px var(--m-danger);animation:pulseDot .8s infinite}
|
||||||
|
@keyframes pulseDot{50%{opacity:.4}}
|
||||||
|
|
||||||
|
/* ── TOP TABS REMOVIDAS (substituídas pela bottom nav) ── */
|
||||||
|
.tabs{display:none!important}
|
||||||
|
|
||||||
|
/* ── CONTAINER ── */
|
||||||
|
.container{padding:14px 12px 20px;max-width:760px}
|
||||||
|
.panel{padding:0;background:transparent}
|
||||||
|
|
||||||
|
/* ── CARDS DARK MODERNOS ── */
|
||||||
|
.export-card,.gps-card,.anchor-card,.empty,.contact-card{
|
||||||
|
background:var(--m-bg-3);
|
||||||
|
border:1px solid var(--m-border);
|
||||||
|
border-radius:var(--m-r-lg);
|
||||||
|
box-shadow:var(--m-sh-2);
|
||||||
|
padding:16px;margin-bottom:12px;
|
||||||
|
color:var(--m-text);
|
||||||
|
}
|
||||||
|
.export-card-title{
|
||||||
|
color:var(--m-text)!important;font-weight:600;font-size:15px;
|
||||||
|
letter-spacing:-.005em;margin-bottom:6px;
|
||||||
|
}
|
||||||
|
.export-card-text{
|
||||||
|
color:var(--m-text-mid)!important;font-size:13px;line-height:1.5;
|
||||||
|
}
|
||||||
|
.gps-card,.anchor-card{
|
||||||
|
background:linear-gradient(165deg,var(--m-bg-3),var(--m-bg-2));
|
||||||
|
border:1px solid var(--m-border-strong);
|
||||||
|
}
|
||||||
|
.gps-card.idle{
|
||||||
|
background:var(--m-bg-3);
|
||||||
|
color:var(--m-text);
|
||||||
|
}
|
||||||
|
.gps-stats{gap:14px}
|
||||||
|
.gps-stat-value,.t-stat-value{
|
||||||
|
color:var(--m-accent)!important;
|
||||||
|
font-family:var(--f-mono);font-weight:700;
|
||||||
|
font-variant-numeric:tabular-nums;
|
||||||
|
}
|
||||||
|
.gps-stat-label,.t-stat-label{
|
||||||
|
color:var(--m-text-soft)!important;
|
||||||
|
font-size:9.5px;letter-spacing:.14em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.entry{
|
||||||
|
background:var(--m-bg-3);
|
||||||
|
border:1px solid var(--m-border);
|
||||||
|
border-left:3px solid var(--m-accent);
|
||||||
|
border-radius:var(--m-r-md);
|
||||||
|
box-shadow:var(--m-sh-1);
|
||||||
|
padding:14px;margin-bottom:10px;
|
||||||
|
color:var(--m-text);
|
||||||
|
}
|
||||||
|
.entry-title{color:var(--m-text)!important;font-weight:600;font-size:15px}
|
||||||
|
.entry-meta{color:var(--m-text-mid)}
|
||||||
|
.entry.maint{border-left-color:var(--m-warn)}
|
||||||
|
.entry.pending{border-left-color:var(--m-warn)}
|
||||||
|
.entry.pending.overdue{border-left-color:var(--m-danger)}
|
||||||
|
.entry.pending.done{border-left-color:var(--m-ok);opacity:.7}
|
||||||
|
.entry-grid dt{color:var(--m-text-soft)}
|
||||||
|
.entry-grid dd{color:var(--m-text)}
|
||||||
|
.entry-notes{
|
||||||
|
background:var(--m-bg-2)!important;border-left-color:var(--m-accent)!important;
|
||||||
|
color:var(--m-text-mid)!important;border-radius:var(--m-r-sm);
|
||||||
|
font-style:normal!important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ── STATS DASHBOARD ── */
|
||||||
|
.stats{gap:8px}
|
||||||
|
.stat{
|
||||||
|
background:var(--m-bg-3);
|
||||||
|
border:1px solid var(--m-border);
|
||||||
|
border-radius:var(--m-r-md);
|
||||||
|
padding:14px 12px;
|
||||||
|
position:relative;overflow:hidden;
|
||||||
|
}
|
||||||
|
.stat::before{
|
||||||
|
content:'';position:absolute;top:0;left:0;right:0;height:2px;
|
||||||
|
background:linear-gradient(90deg,var(--m-accent),var(--m-accent-2));
|
||||||
|
opacity:.7;
|
||||||
|
}
|
||||||
|
.stat-value{
|
||||||
|
color:var(--m-accent)!important;
|
||||||
|
font-family:var(--f-mono);font-weight:700;
|
||||||
|
font-variant-numeric:tabular-nums;
|
||||||
|
font-size:24px;
|
||||||
|
}
|
||||||
|
.stat-label{
|
||||||
|
color:var(--m-text-soft)!important;
|
||||||
|
font-size:9.5px;letter-spacing:.14em;
|
||||||
|
}
|
||||||
|
.stat-sub{color:var(--m-text-mid)!important;font-style:normal!important;font-size:11px}
|
||||||
|
|
||||||
|
/* ── BUTTONS ── */
|
||||||
|
.btn{
|
||||||
|
background:var(--m-bg-3);border:1px solid var(--m-border-strong);
|
||||||
|
color:var(--m-text);font-family:var(--f-body);
|
||||||
|
font-size:14px;font-weight:500;
|
||||||
|
border-radius:var(--m-r-md);
|
||||||
|
min-height:44px;padding:11px 18px;
|
||||||
|
text-transform:none;letter-spacing:0;
|
||||||
|
transition:all .15s;
|
||||||
|
}
|
||||||
|
.btn:hover{background:var(--m-bg-4);border-color:var(--m-accent)}
|
||||||
|
.btn-primary,.btn-brass{
|
||||||
|
background:var(--m-accent);color:#001a25;border-color:var(--m-accent);
|
||||||
|
font-weight:600;
|
||||||
|
}
|
||||||
|
.btn-primary:hover,.btn-brass:hover{background:var(--m-accent-2);color:#001a25;border-color:var(--m-accent-2)}
|
||||||
|
.btn-danger{background:transparent;color:var(--m-danger);border-color:var(--m-danger)}
|
||||||
|
.btn-danger:hover{background:rgba(239,68,68,.1);color:var(--m-danger)}
|
||||||
|
.btn-block{width:100%}
|
||||||
|
.btn-sm{min-height:34px;padding:7px 14px;font-size:12.5px}
|
||||||
|
.btn-big{min-height:54px;padding:14px 22px;font-size:15px;font-weight:600}
|
||||||
|
|
||||||
|
/* ── FAB acima da bottom nav ── */
|
||||||
|
.fab{
|
||||||
|
bottom:calc(86px + env(safe-area-inset-bottom))!important;
|
||||||
|
right:18px!important;
|
||||||
|
background:linear-gradient(135deg,var(--m-accent),var(--m-accent-2))!important;
|
||||||
|
color:#001a25!important;
|
||||||
|
width:56px!important;height:56px!important;
|
||||||
|
box-shadow:0 6px 20px var(--m-accent-glow),0 2px 8px rgba(0,0,0,.5)!important;
|
||||||
|
}
|
||||||
|
.fab:hover{transform:scale(1.06) translateY(-2px)!important}
|
||||||
|
.fab svg{stroke:#001a25!important}
|
||||||
|
|
||||||
|
/* ── BOTTOM NAVIGATION ── */
|
||||||
|
.bottom-nav{
|
||||||
|
position:fixed;bottom:0;left:0;right:0;z-index:48;
|
||||||
|
background:var(--m-bg-2);
|
||||||
|
border-top:1px solid var(--m-border);
|
||||||
|
padding:6px 0 max(6px,env(safe-area-inset-bottom));
|
||||||
|
display:flex;justify-content:space-around;align-items:stretch;
|
||||||
|
backdrop-filter:blur(18px);
|
||||||
|
-webkit-backdrop-filter:blur(18px);
|
||||||
|
background:rgba(15,42,64,.92);
|
||||||
|
}
|
||||||
|
.bn-item{
|
||||||
|
flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;
|
||||||
|
gap:3px;padding:6px 4px;
|
||||||
|
background:none;border:none;cursor:pointer;
|
||||||
|
color:var(--m-text-soft);
|
||||||
|
font-family:var(--f-body);font-size:10px;font-weight:500;
|
||||||
|
transition:color .15s;
|
||||||
|
min-height:54px;
|
||||||
|
}
|
||||||
|
.bn-item:hover{color:var(--m-text-mid)}
|
||||||
|
.bn-item.active{color:var(--m-accent)}
|
||||||
|
.bn-item svg{width:22px;height:22px;stroke-width:2;transition:stroke-width .15s}
|
||||||
|
.bn-item.active svg{stroke-width:2.4}
|
||||||
|
.bn-badge{
|
||||||
|
position:absolute;top:4px;right:50%;transform:translate(14px,0);
|
||||||
|
background:var(--m-danger);color:#fff;
|
||||||
|
font-family:var(--f-mono);font-size:9px;font-weight:700;
|
||||||
|
min-width:16px;height:16px;border-radius:8px;
|
||||||
|
display:flex;align-items:center;justify-content:center;padding:0 4px;
|
||||||
|
}
|
||||||
|
.bn-item{position:relative}
|
||||||
|
|
||||||
|
/* ── MODAIS dark ── */
|
||||||
|
.modal{
|
||||||
|
background:var(--m-bg-3);
|
||||||
|
color:var(--m-text);
|
||||||
|
border:1px solid var(--m-border-strong);
|
||||||
|
border-radius:var(--m-r-xl) var(--m-r-xl) 0 0;
|
||||||
|
border-top:1px solid var(--m-border-strong);
|
||||||
|
}
|
||||||
|
@media(min-width:600px){
|
||||||
|
.modal{border-radius:var(--m-r-xl);}
|
||||||
|
}
|
||||||
|
.modal-head{border-bottom:1px solid var(--m-border)}
|
||||||
|
.modal-head h3{color:var(--m-text);font-style:normal;font-weight:600;font-size:17px}
|
||||||
|
.modal-foot{border-top:1px solid var(--m-border);background:var(--m-bg-2)}
|
||||||
|
.modal-backdrop{background:rgba(0,0,0,.7);backdrop-filter:blur(6px)}
|
||||||
|
.icon-btn{color:var(--m-text-mid);background:transparent;border:none}
|
||||||
|
.icon-btn:hover{color:var(--m-text);background:var(--m-bg-2)}
|
||||||
|
|
||||||
|
/* ── FORM FIELDS dark ── */
|
||||||
|
.field-label{color:var(--m-text-soft);font-size:10px;letter-spacing:.12em;font-weight:600;text-transform:uppercase}
|
||||||
|
.field input,.field textarea,.field select{
|
||||||
|
background:var(--m-bg-2)!important;
|
||||||
|
border:1px solid var(--m-border-strong)!important;
|
||||||
|
color:var(--m-text)!important;
|
||||||
|
border-radius:var(--m-r-sm);
|
||||||
|
font-family:var(--f-body);font-style:normal!important;
|
||||||
|
font-size:15px;padding:11px 13px;
|
||||||
|
}
|
||||||
|
.field input:focus,.field textarea:focus,.field select:focus{
|
||||||
|
outline:none!important;
|
||||||
|
border-color:var(--m-accent)!important;
|
||||||
|
box-shadow:0 0 0 3px var(--m-accent-glow)!important;
|
||||||
|
background:var(--m-bg-3)!important;
|
||||||
|
}
|
||||||
|
.field-hint{color:var(--m-text-soft);font-style:normal!important}
|
||||||
|
|
||||||
|
/* ── SECTION HEADERS / TOOLBARS ── */
|
||||||
|
.section-header h2{color:var(--m-text-soft);text-transform:uppercase;letter-spacing:.12em;font-size:10.5px}
|
||||||
|
.toolbar{margin-bottom:14px}
|
||||||
|
|
||||||
|
/* ── EMPTY STATES ── */
|
||||||
|
.empty{text-align:center;padding:32px 20px;color:var(--m-text-soft)}
|
||||||
|
.empty-title{color:var(--m-text);font-weight:600;font-size:16px;font-style:normal!important}
|
||||||
|
.empty-text{color:var(--m-text-soft);font-size:13.5px;line-height:1.55}
|
||||||
|
|
||||||
|
/* ── SYNC INDICATOR ── */
|
||||||
|
.sync-indicator{font-size:10px;margin-left:5px}
|
||||||
|
|
||||||
|
/* ── WELCOME SCREEN dark ── */
|
||||||
|
.welcome-screen{background:linear-gradient(135deg,var(--m-bg) 0%,var(--m-bg-2) 50%,#06151f 100%)}
|
||||||
|
.welcome-card{
|
||||||
|
background:var(--m-bg-3);
|
||||||
|
border:1px solid var(--m-border-strong);
|
||||||
|
border-radius:var(--m-r-xl);
|
||||||
|
box-shadow:var(--m-sh-3);
|
||||||
|
color:var(--m-text);
|
||||||
|
}
|
||||||
|
.welcome-title{color:var(--m-text);font-style:normal;font-weight:700;font-size:24px}
|
||||||
|
.welcome-tagline{color:var(--m-text-mid);font-style:normal;font-size:14px}
|
||||||
|
.welcome-btn{
|
||||||
|
background:var(--m-bg-2);border:1px solid var(--m-border-strong);
|
||||||
|
color:var(--m-text);border-radius:var(--m-r-md);
|
||||||
|
font-family:var(--f-body);font-weight:500;
|
||||||
|
}
|
||||||
|
.welcome-btn:hover{background:var(--m-bg-4);border-color:var(--m-accent)}
|
||||||
|
.welcome-btn-google{background:#fff;color:#3c4043;border-color:#dadce0}
|
||||||
|
.welcome-btn-google:hover{background:#f1f3f4;color:#3c4043;border-color:#dadce0}
|
||||||
|
.welcome-btn-primary{background:var(--m-accent);color:#001a25;border-color:var(--m-accent)}
|
||||||
|
.welcome-btn-primary:hover{background:var(--m-accent-2);color:#001a25;border-color:var(--m-accent-2)}
|
||||||
|
.welcome-btn-text{color:var(--m-text-soft);background:transparent;border:none}
|
||||||
|
.welcome-tab{color:var(--m-text-soft);text-transform:uppercase;letter-spacing:.12em}
|
||||||
|
.welcome-tab.active{color:var(--m-accent);border-bottom-color:var(--m-accent)}
|
||||||
|
|
||||||
|
/* ── FLEET & ANCHOR CALC dark ── */
|
||||||
|
.fleet-item{background:var(--m-bg-2);border:1px solid var(--m-border)}
|
||||||
|
.fleet-item:hover{background:var(--m-bg-4);border-color:var(--m-accent)}
|
||||||
|
.fleet-item.active{border-left:3px solid var(--m-accent);background:var(--m-bg-4)}
|
||||||
|
.fleet-name{color:var(--m-text);font-style:normal;font-weight:600;font-size:15px}
|
||||||
|
.fleet-meta{color:var(--m-text-soft);text-transform:uppercase;letter-spacing:.06em}
|
||||||
|
.fleet-active-badge{background:var(--m-accent);color:#001a25;font-weight:700}
|
||||||
|
.fleet-edit-icon{background:transparent;border:1px solid var(--m-border-strong);color:var(--m-text-mid)}
|
||||||
|
.fleet-units-toggle{border:1px solid var(--m-border-strong);background:var(--m-bg-2)}
|
||||||
|
.fleet-units-toggle button{background:transparent;color:var(--m-text-mid)}
|
||||||
|
.fleet-units-toggle button.active{background:var(--m-accent);color:#001a25}
|
||||||
|
|
||||||
|
.anchor-calc{background:var(--m-bg-2);border:1px solid var(--m-border);border-left:3px solid var(--m-accent)}
|
||||||
|
.anchor-calc-head{color:var(--m-accent);font-weight:600}
|
||||||
|
.anchor-calc-stat{background:var(--m-bg-3);border:1px solid var(--m-border)}
|
||||||
|
.anchor-calc-stat-label{color:var(--m-text-soft)}
|
||||||
|
.anchor-calc-stat-value{color:var(--m-text);font-style:normal;font-weight:700;font-family:var(--f-mono);font-variant-numeric:tabular-nums}
|
||||||
|
.anchor-calc-stat-value.ok{color:var(--m-ok)}
|
||||||
|
.anchor-calc-stat-value.warn{color:var(--m-warn)}
|
||||||
|
.anchor-calc-stat-value.danger{color:var(--m-danger)}
|
||||||
|
.anchor-calc-advice{background:rgba(6,182,212,.08);border-left-color:var(--m-accent);color:var(--m-text-mid);font-style:normal}
|
||||||
|
|
||||||
|
/* ── BADGES & TAGS ── */
|
||||||
|
.badge{background:var(--m-danger);color:#fff;font-family:var(--f-mono);font-weight:700}
|
||||||
|
.pax-tag{background:var(--m-bg-3);border:1px solid var(--m-border);color:var(--m-text);border-radius:var(--m-r-pill)}
|
||||||
|
|
||||||
|
/* ── ALERTS ── */
|
||||||
|
.alert-overdue,.alert-danger{background:rgba(239,68,68,.08);border-left:3px solid var(--m-danger);color:var(--m-text)}
|
||||||
|
.alert-soon,.alert-warn{background:rgba(245,158,11,.08);border-left:3px solid var(--m-warn);color:var(--m-text)}
|
||||||
|
.alert-info{background:rgba(59,130,246,.08);border-left:3px solid var(--m-info);color:var(--m-text)}
|
||||||
|
|
||||||
|
/* ── TOAST ── */
|
||||||
|
.toast{
|
||||||
|
background:var(--m-bg-3);color:var(--m-text);
|
||||||
|
border:1px solid var(--m-border-strong);
|
||||||
|
border-radius:var(--m-r-md);
|
||||||
|
box-shadow:var(--m-sh-3);
|
||||||
|
font-family:var(--f-body);font-style:normal;font-weight:500;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ── pax/checklist/tags ajustes ── */
|
||||||
|
.checklist-card{background:var(--m-bg-3);border:1px solid var(--m-border);border-radius:var(--m-r-md);color:var(--m-text)}
|
||||||
|
.weather-widget{background:var(--m-bg-3)!important;border:1px solid var(--m-border)!important;color:var(--m-text)!important;border-radius:var(--m-r-md)}
|
||||||
|
|
||||||
|
/* ── SCROLLBAR thin estilo iOS ── */
|
||||||
|
::-webkit-scrollbar{width:6px;height:6px}
|
||||||
|
::-webkit-scrollbar-thumb{background:var(--m-border-strong);border-radius:3px}
|
||||||
|
::-webkit-scrollbar-track{background:transparent}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|
@ -1450,6 +1837,13 @@ header{
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
|
<!-- Safety status bar (sempre visível, marine pro) -->
|
||||||
|
<div class="safety-bar" id="safety-bar">
|
||||||
|
<span class="safety-bar-item"><span class="safety-bar-dot" id="sb-gps-dot"></span><span id="sb-gps">GPS aguardando</span></span>
|
||||||
|
<span class="safety-bar-item" id="sb-anchor-wrap" style="display:none"><span class="safety-bar-dot ok" id="sb-anchor-dot"></span><span id="sb-anchor">Fundeado</span></span>
|
||||||
|
<span class="safety-bar-item"><span id="sb-battery">—</span></span>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="container">
|
<div class="container">
|
||||||
|
|
||||||
<div class="tabs" role="tablist">
|
<div class="tabs" role="tablist">
|
||||||
|
|
@ -1951,6 +2345,31 @@ Hora: {HORA}</textarea>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<button class="fab" id="fab" onclick="quickAdd()" title="Adicionar"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M12 5v14M5 12h14"/></svg></button>
|
<button class="fab" id="fab" onclick="quickAdd()" title="Adicionar"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M12 5v14M5 12h14"/></svg></button>
|
||||||
|
|
||||||
|
<!-- Bottom Navigation (substitui top tabs) -->
|
||||||
|
<nav class="bottom-nav" id="bottom-nav">
|
||||||
|
<button class="bn-item active" data-panel="overview" onclick="switchPanel('overview')" aria-label="Início">
|
||||||
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"><path d="M3 12l9-9 9 9"/><path d="M5 10v10h14V10"/><path d="M9 20v-6h6v6"/></svg>
|
||||||
|
<span>Início</span>
|
||||||
|
</button>
|
||||||
|
<button class="bn-item" data-panel="trips" onclick="switchPanel('trips')" aria-label="Travessias">
|
||||||
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"><path d="M2 17.5L12 22l10-4.5"/><path d="M2 12.5L12 17l10-4.5"/><path d="M12 2L2 7l10 5 10-5z"/></svg>
|
||||||
|
<span>Travessias</span>
|
||||||
|
</button>
|
||||||
|
<button class="bn-item" data-panel="pending" onclick="switchPanel('pending')" aria-label="Pendências">
|
||||||
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><path d="M12 6v6l4 2"/></svg>
|
||||||
|
<span>Pendências</span>
|
||||||
|
<span class="bn-badge" id="bn-badge-pending" style="display:none">0</span>
|
||||||
|
</button>
|
||||||
|
<button class="bn-item" data-panel="zones" onclick="switchPanel('zones')" aria-label="Zonas">
|
||||||
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"><path d="M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z"/><circle cx="12" cy="10" r="3"/></svg>
|
||||||
|
<span>Zonas</span>
|
||||||
|
</button>
|
||||||
|
<button class="bn-item" data-panel="export" onclick="switchPanel('export')" aria-label="Mais">
|
||||||
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"><circle cx="5" cy="12" r="1.5"/><circle cx="12" cy="12" r="1.5"/><circle cx="19" cy="12" r="1.5"/></svg>
|
||||||
|
<span>Mais</span>
|
||||||
|
</button>
|
||||||
|
</nav>
|
||||||
<!-- Fleet Manager Modal -->
|
<!-- Fleet Manager Modal -->
|
||||||
<div class="modal-backdrop" id="fleet-modal" onclick="if(event.target===this)closeModal('fleet-modal')">
|
<div class="modal-backdrop" id="fleet-modal" onclick="if(event.target===this)closeModal('fleet-modal')">
|
||||||
<div class="modal" style="max-width:520px">
|
<div class="modal" style="max-width:520px">
|
||||||
|
|
@ -2727,7 +3146,56 @@ function syncUnitsToggle(){
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
document.querySelectorAll('.tab').forEach(t=>{t.addEventListener('click',()=>{document.querySelectorAll('.tab').forEach(x=>x.classList.remove('active'));document.querySelectorAll('.panel').forEach(x=>x.classList.remove('active'));t.classList.add('active');document.getElementById('panel-'+t.dataset.panel).classList.add('active');document.getElementById('fab').style.display=['trips','maintenance','pending','zones'].includes(t.dataset.panel)?'flex':'none';if(t.dataset.panel==='export'){updateStorageInfo();bindCloudInputs();renderCloudStatus();renderShareList();bindWeatherInputs();renderAuthBox();refreshGoogleStatus()}if(t.dataset.panel==='pending'&&_gcalConnected&&Date.now()-_gcalLastPullAt>GCAL_PULL_INTERVAL_MS)googlePullNow();if(t.dataset.panel==='zones')renderZones();window.scrollTo(0,0)})});
|
function switchPanel(name){
|
||||||
|
document.querySelectorAll('.tab').forEach(x=>x.classList.toggle('active',x.dataset.panel===name));
|
||||||
|
document.querySelectorAll('.bn-item').forEach(x=>x.classList.toggle('active',x.dataset.panel===name));
|
||||||
|
document.querySelectorAll('.panel').forEach(x=>x.classList.remove('active'));
|
||||||
|
const p=document.getElementById('panel-'+name);
|
||||||
|
if(p)p.classList.add('active');
|
||||||
|
// FAB visível em panels que têm "criar item"
|
||||||
|
document.getElementById('fab').style.display=['trips','maintenance','pending','zones','overview'].includes(name)?'flex':'none';
|
||||||
|
if(name==='export'){updateStorageInfo();bindCloudInputs();renderCloudStatus();renderShareList();bindWeatherInputs();renderAuthBox();refreshGoogleStatus()}
|
||||||
|
if(name==='pending'&&_gcalConnected&&Date.now()-_gcalLastPullAt>GCAL_PULL_INTERVAL_MS)googlePullNow();
|
||||||
|
if(name==='zones')renderZones();
|
||||||
|
window.scrollTo(0,0);
|
||||||
|
}
|
||||||
|
// Compat: top tabs (escondidos via CSS mas mantém handlers caso re-exibidos)
|
||||||
|
document.querySelectorAll('.tab').forEach(t=>{t.addEventListener('click',()=>switchPanel(t.dataset.panel))});
|
||||||
|
|
||||||
|
// Safety bar: atualiza bateria, GPS, anchor a cada 10s
|
||||||
|
function updateSafetyBar(){
|
||||||
|
const bat=document.getElementById('battery-indicator');
|
||||||
|
const sbBat=document.getElementById('sb-battery');
|
||||||
|
if(sbBat&&bat){sbBat.textContent=bat.textContent.trim()||'—'}
|
||||||
|
const sbGps=document.getElementById('sb-gps');
|
||||||
|
const sbGpsDot=document.getElementById('sb-gps-dot');
|
||||||
|
if(sbGps&&sbGpsDot){
|
||||||
|
if(tracking?.active||(typeof lastGpsPos!=='undefined'&&lastGpsPos)){
|
||||||
|
sbGps.textContent='GPS ativo';sbGpsDot.className='safety-bar-dot ok';
|
||||||
|
}else{
|
||||||
|
sbGps.textContent='GPS aguardando';sbGpsDot.className='safety-bar-dot';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const sbAnchorWrap=document.getElementById('sb-anchor-wrap');
|
||||||
|
const sbAnchorDot=document.getElementById('sb-anchor-dot');
|
||||||
|
const sbAnchor=document.getElementById('sb-anchor');
|
||||||
|
if(sbAnchorWrap&&anchorWatch){
|
||||||
|
if(anchorWatch.active){
|
||||||
|
sbAnchorWrap.style.display='inline-flex';
|
||||||
|
const breach=anchorWatch.currentDist>anchorWatch.radius;
|
||||||
|
sbAnchorDot.className='safety-bar-dot '+(breach?'danger':'ok');
|
||||||
|
sbAnchor.textContent=breach?'⚠ DERIVANDO!':`Fundeado · raio ${Math.round(anchorWatch.currentDist||0)}/${anchorWatch.radius}m`;
|
||||||
|
}else{
|
||||||
|
sbAnchorWrap.style.display='none';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Bottom nav badge pendências
|
||||||
|
const overdue=(state.pending||[]).filter(p=>!p.done&&p.dueDate&&p.dueDate<new Date().toISOString().slice(0,10)).length;
|
||||||
|
const bnBadge=document.getElementById('bn-badge-pending');
|
||||||
|
if(bnBadge){bnBadge.style.display=overdue>0?'flex':'none';bnBadge.textContent=overdue}
|
||||||
|
}
|
||||||
|
setInterval(updateSafetyBar,5000);
|
||||||
|
setTimeout(updateSafetyBar,1500);
|
||||||
function quickAdd(){const a=document.querySelector('.tab.active').dataset.panel;if(a==='maintenance')openMaintModal();else if(a==='pending')openPendingModal();else if(a==='zones')openZoneEditor();else openTripModal()}
|
function quickAdd(){const a=document.querySelector('.tab.active').dataset.panel;if(a==='maintenance')openMaintModal();else if(a==='pending')openPendingModal();else if(a==='zones')openZoneEditor();else openTripModal()}
|
||||||
function openModal(id){document.getElementById(id).classList.add('show')}
|
function openModal(id){document.getElementById(id).classList.add('show')}
|
||||||
function closeModal(id){document.getElementById(id).classList.remove('show')}
|
function closeModal(id){document.getElementById(id).classList.remove('show')}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
// Shivao Service Worker — offline real
|
// Shivao Service Worker — offline real
|
||||||
// Estratégia: shell precachado, tiles cache-first, windy network-first, /api passa direto.
|
// Estratégia: shell precachado, tiles cache-first, windy network-first, /api passa direto.
|
||||||
// Versão usada nos cache names — bumpa essa string pra invalidar caches antigos em deploys.
|
// Versão usada nos cache names — bumpa essa string pra invalidar caches antigos em deploys.
|
||||||
const VERSION = 'shivao-v1.6.0';
|
const VERSION = 'shivao-v1.7.0';
|
||||||
const SHELL_CACHE = `shivao-shell-${VERSION}`;
|
const SHELL_CACHE = `shivao-shell-${VERSION}`;
|
||||||
const TILES_CACHE = 'shivao-tiles-v1'; // separado pra não invalidar tiles em update do shell
|
const TILES_CACHE = 'shivao-tiles-v1'; // separado pra não invalidar tiles em update do shell
|
||||||
const WINDY_CACHE = `shivao-windy-${VERSION}`;
|
const WINDY_CACHE = `shivao-windy-${VERSION}`;
|
||||||
|
|
|
||||||
|
|
@ -347,7 +347,7 @@ app.get('/.well-known/assetlinks.json', (req, res) => {
|
||||||
});
|
});
|
||||||
|
|
||||||
// Atalho: /apk redireciona pra última APK release no Forgejo
|
// Atalho: /apk redireciona pra última APK release no Forgejo
|
||||||
const LATEST_APK_URL = 'https://git.pontualtech.work/karlao/shivao-projeto/releases/download/v1.6.2/Shivao-v1.6.2.apk';
|
const LATEST_APK_URL = 'https://git.pontualtech.work/karlao/shivao-projeto/releases/download/v1.7.0/Shivao-v1.7.0.apk';
|
||||||
app.get('/apk', (req, res) => res.redirect(302, LATEST_APK_URL));
|
app.get('/apk', (req, res) => res.redirect(302, LATEST_APK_URL));
|
||||||
|
|
||||||
// Página A4 imprimível com QR Code + instruções (cola no barco/marina)
|
// Página A4 imprimível com QR Code + instruções (cola no barco/marina)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue