Files
Armen Rohalov 2a62415f0c ui_design v2: redesign of all 5 pages
ui_design v2: tactical-ops redesign of all 5 pages

Two parallel takes on visual polish for flights, annotations, dataset
explorer, admin, and settings.

- v2/plugin/ — self-contained HTML produced via the frontend-design
  plugin, adheres to v2/plugin/_design_system.md..
- v2/stitch/ — Google Stitch MCP exports against the same design
  system.

IA from the original wireframes in _docs/ui_design/ is preserved
verbatim — this pass is visual only.
2026-05-16 20:09:16 +03:00

896 lines
45 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>AZAION // FLIGHTS — Tactical Ops</title>
<script src="https://cdn.tailwindcss.com"></script>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=IBM+Plex+Sans:wght@400;500;600&family=JetBrains+Mono:wght@400;500;600;700&display=swap" rel="stylesheet">
<style>
:root {
--surface-0: #0A0D10;
--surface-1: #13171C;
--surface-2: #1A1F26;
--surface-input: #0A0D10;
--border-hair: #252B34;
--border-raised: #3B4451;
--text-primary: #E8ECF1;
--text-secondary:#9AA4B2;
--text-muted: #5B6573;
--accent-amber: #FF9D3D;
--accent-cyan: #36D6C5;
--accent-red: #FF4756;
--accent-green: #3DDC84;
--accent-blue: #4E9EFF;
}
html, body {
background: var(--surface-0);
color: var(--text-primary);
}
body {
font-family: 'IBM Plex Sans', system-ui, sans-serif;
font-size: 13px;
line-height: 1.5;
-webkit-font-smoothing: antialiased;
}
.mono { font-family: 'JetBrains Mono', ui-monospace, monospace; font-variant-numeric: tabular-nums; }
.num { font-variant-numeric: tabular-nums; font-family: 'JetBrains Mono', ui-monospace, monospace; }
.micro {
font-family: 'JetBrains Mono', ui-monospace, monospace;
font-size: 10px;
line-height: 1.4;
letter-spacing: 0.12em;
text-transform: uppercase;
color: var(--text-secondary);
}
.section-head {
font-family: 'JetBrains Mono', ui-monospace, monospace;
font-size: 11px;
line-height: 1.2;
letter-spacing: 0.14em;
text-transform: uppercase;
color: var(--accent-amber);
}
/* Corner brackets */
.bracket { position: relative; }
.bracket::before, .bracket::after,
.bracket > .br::before, .bracket > .br::after {
content: ''; position: absolute; width: 8px; height: 8px;
border-color: var(--accent-amber); border-style: solid; border-width: 0;
pointer-events: none;
}
.bracket::before { top: -1px; left: -1px; border-top-width: 1px; border-left-width: 1px; }
.bracket::after { top: -1px; right: -1px; border-top-width: 1px; border-right-width: 1px; }
.bracket > .br::before { bottom: -1px; left: -1px; border-bottom-width: 1px; border-left-width: 1px; }
.bracket > .br::after { bottom: -1px; right: -1px; border-bottom-width: 1px; border-right-width: 1px; }
.bracket-cyan::before, .bracket-cyan::after,
.bracket-cyan > .br::before, .bracket-cyan > .br::after { border-color: var(--accent-cyan); }
.bracket-red::before, .bracket-red::after,
.bracket-red > .br::before, .bracket-red > .br::after { border-color: var(--accent-red); }
.hair { border-color: var(--border-hair); }
.panel { background: var(--surface-1); border: 1px solid var(--border-hair); }
/* Buttons */
.btn-primary {
background: var(--accent-amber); color: #0A0D10; border: 1px solid var(--accent-amber);
padding: 6px 14px; font-family: 'JetBrains Mono', monospace; font-size: 11px;
letter-spacing: 0.08em; text-transform: uppercase; font-weight: 600;
transition: filter .12s;
}
.btn-primary:hover { filter: brightness(1.08); }
.btn-secondary {
background: transparent; color: var(--accent-amber); border: 1px solid var(--accent-amber);
padding: 6px 14px; font-family: 'JetBrains Mono', monospace; font-size: 11px;
letter-spacing: 0.08em; text-transform: uppercase;
}
.btn-secondary:hover { background: rgba(255,157,61,0.12); }
.btn-ghost {
background: transparent; color: var(--text-secondary); border: 1px solid var(--border-hair);
padding: 6px 14px; font-family: 'JetBrains Mono', monospace; font-size: 11px;
letter-spacing: 0.08em; text-transform: uppercase;
}
.btn-ghost:hover { color: var(--text-primary); border-color: var(--border-raised); }
.btn-danger {
background: var(--accent-red); color: #0A0D10; border: 1px solid var(--accent-red);
padding: 6px 14px; font-family: 'JetBrains Mono', monospace; font-size: 11px;
letter-spacing: 0.08em; text-transform: uppercase; font-weight: 600;
}
.btn-cyan {
background: transparent; color: var(--accent-cyan); border: 1px solid var(--accent-cyan);
padding: 6px 14px; font-family: 'JetBrains Mono', monospace; font-size: 11px;
letter-spacing: 0.08em; text-transform: uppercase;
}
.btn-cyan:hover { background: rgba(54,214,197,0.10); }
/* Inputs */
.ipt {
background: var(--surface-input); border: 1px solid var(--border-hair);
border-radius: 2px; padding: 6px 10px; height: 32px;
font-family: 'IBM Plex Sans', sans-serif; font-size: 12px;
color: var(--text-primary); width: 100%;
}
.ipt:focus { outline: none; border-color: var(--accent-amber); box-shadow: 0 0 0 1px var(--accent-amber); }
.ipt::placeholder { color: var(--text-muted); }
.ipt-num { font-variant-numeric: tabular-nums; font-family: 'JetBrains Mono', monospace; }
select.ipt { appearance: none; background-image:
linear-gradient(45deg, transparent 50%, var(--text-secondary) 50%),
linear-gradient(135deg, var(--text-secondary) 50%, transparent 50%);
background-position: calc(100% - 14px) 14px, calc(100% - 9px) 14px;
background-size: 5px 5px, 5px 5px; background-repeat: no-repeat; padding-right: 26px; }
input[type="date"].ipt { color-scheme: dark; }
/* Pill / status */
.pill {
display: inline-flex; align-items: center; gap: 6px;
padding: 2px 8px; border-radius: 2px; border: 1px solid currentColor;
font-family: 'JetBrains Mono', monospace; font-size: 10px;
letter-spacing: 0.12em; text-transform: uppercase;
background: transparent;
}
.pill .dot { width: 6px; height: 6px; border-radius: 9999px; background: currentColor; flex-shrink: 0; }
.pill-green { color: var(--accent-green); }
.pill-cyan { color: var(--accent-cyan); }
.pill-red { color: var(--accent-red); }
.pill-amber { color: var(--accent-amber); }
.pill-muted { color: var(--text-secondary); border-color: var(--border-hair); }
@keyframes pulse { 0%,100% { opacity: 1 } 50% { opacity: .35 } }
.pulse { animation: pulse 1.6s ease-in-out infinite; }
/* Header live-dot — glow-ring animation, matches other plugin pages */
.live-dot {
width: 6px; height: 6px; border-radius: 999px;
background: var(--accent-cyan);
box-shadow: 0 0 0 0 rgba(54,214,197,0.5);
animation: liveDotPulse 1.6s ease-in-out infinite;
display: inline-block;
flex: none;
}
@keyframes liveDotPulse {
0%,100% { box-shadow: 0 0 0 0 rgba(54,214,197,0.5); }
50% { box-shadow: 0 0 0 6px rgba(54,214,197,0); }
}
/* Draw-mode selector buttons */
.dmode {
display: inline-flex; align-items: center; justify-content: center; gap: 6px;
height: 32px; padding: 0 8px;
font-family: 'JetBrains Mono', monospace;
font-size: 10px; font-weight: 600;
letter-spacing: 0.10em; text-transform: uppercase;
border: 1px solid; border-radius: 2px;
background: transparent;
cursor: pointer;
transition: background-color .12s, color .12s, box-shadow .12s;
white-space: nowrap;
}
.dmode:hover { background-color: rgba(255,255,255,0.04); }
.dmode-sq { width: 32px; height: 32px; padding: 0; }
.dmode-amber { color: var(--accent-amber); border-color: var(--accent-amber); }
.dmode-amber.active { background-color: rgba(255,157,61,0.20); box-shadow: inset 0 0 0 1px var(--accent-amber); }
.dmode-green { color: var(--accent-green); border-color: var(--accent-green); }
.dmode-green.active { background-color: rgba(61,220,132,0.18); box-shadow: inset 0 0 0 1px var(--accent-green); }
.dmode-red { color: var(--accent-red); border-color: var(--accent-red); }
.dmode-red.active { background-color: rgba(255,71,86,0.18); box-shadow: inset 0 0 0 1px var(--accent-red); }
/* Params panel collapse */
.params-panel { width: 290px; transition: width .18s ease; }
.params-panel.collapsed { width: 44px; }
.params-panel.collapsed .panel-body { display: none; }
.params-panel:not(.collapsed) .collapsed-rail { display: none; }
.collapsed-rail {
display: flex; flex-direction: column; align-items: center; gap: 8px;
padding: 10px 6px;
}
.rail-btn {
width: 32px; height: 32px;
display: inline-flex; align-items: center; justify-content: center;
border: 1px solid var(--border-hair); border-radius: 2px;
background: var(--surface-0); color: var(--text-secondary);
cursor: pointer; transition: color .12s, border-color .12s, background-color .12s;
font-family: 'JetBrains Mono', monospace; font-size: 12px;
}
.rail-btn:hover { color: var(--text-primary); border-color: var(--border-raised); background: var(--surface-2); }
.collapse-btn {
display: inline-flex; align-items: center; justify-content: center;
width: 26px; height: 26px;
border: 1px solid var(--border-hair); border-radius: 2px;
background: var(--surface-1); color: var(--text-secondary);
cursor: pointer; transition: color .12s, border-color .12s;
font-family: 'JetBrains Mono', monospace; font-size: 12px;
}
.collapse-btn:hover { color: var(--accent-amber); border-color: var(--accent-amber); }
/* Tab nav */
.tab {
display: inline-flex; align-items: center;
height: 48px; padding: 0 14px;
font: 500 12px/1 'JetBrains Mono', monospace;
letter-spacing: 0.10em; text-transform: uppercase;
color: var(--text-secondary);
border-bottom: 2px solid transparent;
cursor: pointer;
}
.tab:hover { color: var(--text-primary); }
.tab.active { color: var(--text-primary); border-bottom-color: var(--accent-amber); font-weight: 500; }
/* Icon buttons in header */
.ibtn {
display: inline-flex; align-items: center; justify-content: center;
width: 28px; height: 28px;
border: 1px solid var(--border-hair); border-radius: 2px;
color: var(--text-secondary); background: transparent;
transition: color .12s, border-color .12s, background-color .12s;
cursor: pointer;
}
.ibtn:hover { color: var(--text-primary); border-color: var(--border-raised); background: var(--surface-2); }
.ibtn.active { color: var(--accent-amber); border-color: var(--accent-amber); background: rgba(255,157,61,0.08); }
.ibtn.danger:hover { color: var(--accent-red); border-color: var(--accent-red); background: rgba(255,71,86,0.08); }
/* Flight list row */
.fl-row {
display: flex; align-items: center; gap: 8px;
height: 28px; padding: 0 12px;
border-bottom: 1px solid var(--border-hair);
cursor: pointer;
font-family: 'JetBrains Mono', monospace; font-size: 12px;
color: var(--text-primary);
}
.fl-row:hover { background: var(--surface-2); }
.fl-row.active { background: var(--surface-2); position: relative; }
.fl-row.active::before {
content: ''; position: absolute; left: 0; top: 0; bottom: 0; width: 2px;
background: var(--accent-amber);
}
.fl-row .fid { color: var(--accent-amber); }
.fl-row .meta { margin-left: auto; font-size: 10px; color: var(--text-muted); letter-spacing: 0.08em; }
/* Waypoint row */
.wp-row {
display: flex; align-items: center; gap: 10px;
height: 30px; padding: 0 4px;
border-bottom: 1px solid var(--border-hair);
font-size: 12px; color: var(--text-primary);
}
.wp-row:last-child { border-bottom: none; }
.wp-row .wp-id {
font-family: 'JetBrains Mono', monospace; font-size: 11px;
color: var(--text-secondary); width: 28px;
font-variant-numeric: tabular-nums;
}
.wp-row .wp-marker { width: 10px; height: 10px; flex-shrink: 0; }
.wp-row .wp-tag {
margin-left: auto; font-family: 'JetBrains Mono', monospace;
font-size: 9px; letter-spacing: 0.1em; text-transform: uppercase;
color: var(--text-muted); border: 1px solid var(--border-hair);
padding: 1px 5px; border-radius: 2px;
}
/* Map background grid */
.map-grid {
background-color: #0F1318;
background-image:
linear-gradient(rgba(255,255,255,0.03) 1px, transparent 1px),
linear-gradient(90deg, rgba(255,255,255,0.03) 1px, transparent 1px),
radial-gradient(ellipse at 30% 40%, rgba(54,214,197,0.04), transparent 60%),
radial-gradient(ellipse at 80% 70%, rgba(255,157,61,0.03), transparent 65%);
background-size: 60px 60px, 60px 60px, 100% 100%, 100% 100%;
}
/* GPS-Denied accent state */
.gps-active-frame {
border: 2px solid var(--accent-red) !important;
box-shadow: inset 0 0 0 1px rgba(255,71,86,0.12);
}
.gps-active-frame.bracket::before, .gps-active-frame.bracket::after,
.gps-active-frame.bracket > .br::before, .gps-active-frame.bracket > .br::after {
border-color: var(--accent-red);
}
/* Scrollbar */
::-webkit-scrollbar { width: 8px; height: 8px; }
::-webkit-scrollbar-track { background: var(--surface-0); }
::-webkit-scrollbar-thumb { background: var(--border-hair); border-radius: 0; }
::-webkit-scrollbar-thumb:hover { background: var(--border-raised); }
/* Map waypoint markers (svg-styled overlays) */
.wp-marker-map {
position: absolute; transform: translate(-50%, -50%);
pointer-events: auto;
}
.wp-square { width: 12px; height: 12px; background: #0A0D10; border: 1.5px solid var(--accent-cyan); }
.wp-square.corrected { border-color: var(--accent-cyan); background: rgba(54,214,197,0.15); }
.wp-diamond { width: 14px; height: 14px; background: var(--accent-green); border: 1.5px solid #0A0D10; transform: translate(-50%,-50%) rotate(45deg); box-shadow: 0 0 0 1px var(--accent-green); }
.wp-octagon {
width: 16px; height: 16px; background: var(--accent-red);
clip-path: polygon(30% 0, 70% 0, 100% 30%, 100% 70%, 70% 100%, 30% 100%, 0 70%, 0 30%);
}
.crosshair-x, .crosshair-y {
position: absolute; background: rgba(255,255,255,0.06); pointer-events: none;
}
.crosshair-x { left: 0; right: 0; height: 1px; top: 50%; }
.crosshair-y { top: 0; bottom: 0; width: 1px; left: 50%; }
.map-axis-label {
position: absolute; font-family: 'JetBrains Mono', monospace; font-size: 9px;
color: var(--text-muted); letter-spacing: 0.1em; text-transform: uppercase;
}
details > summary { list-style: none; cursor: pointer; }
details > summary::-webkit-details-marker { display: none; }
</style>
</head>
<body class="h-screen flex flex-col overflow-hidden">
<!-- ========================= GLOBAL HEADER ========================= -->
<header class="h-12 flex items-center px-4 gap-3 border-b" style="border-color: var(--border-hair); background: var(--surface-1);">
<span class="mono font-bold" style="color: var(--accent-amber); letter-spacing: 0.2em; font-size: 14px;">AZAION</span>
<span class="micro" style="color: var(--text-muted);">//</span>
<button class="inline-flex items-center gap-2 mono" style="height: 28px; padding: 0 10px; background: var(--surface-1); border: 1px solid var(--accent-amber); border-radius: 2px; font-size: 11px; letter-spacing: 0.10em;">
<span class="live-dot"></span>
<span style="color: var(--text-primary);">FL-03</span>
<span style="color: var(--text-secondary); font-size: 10px;"></span>
</button>
<nav class="flex items-center self-stretch ml-3">
<a href="flights.html" class="tab active">Flights</a>
<a href="annotations.html" class="tab">Annotations</a>
<a href="dataset_explorer.html" class="tab">Dataset</a>
<a href="admin.html" class="tab">Admin</a>
</nav>
<div class="ml-auto flex items-center gap-2" style="font: 500 10px/1.4 'JetBrains Mono', monospace; letter-spacing: 0.12em; text-transform: uppercase;">
<span class="live-dot"></span>
<span style="color: var(--accent-cyan);">LINK</span>
<span style="color: var(--border-raised);">|</span>
<span style="color: var(--text-secondary); text-transform: none; letter-spacing: 0;">user@azaion.com</span>
<span style="color: var(--border-raised); margin: 0 4px;">|</span>
<a href="settings.html" class="ibtn" title="Settings">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6"><path d="M12 15a3 3 0 100-6 3 3 0 000 6z"/><path d="M19.4 15a1.65 1.65 0 00.33 1.82l.06.06a2 2 0 11-2.83 2.83l-.06-.06a1.65 1.65 0 00-1.82-.33 1.65 1.65 0 00-1 1.51V21a2 2 0 11-4 0v-.09a1.65 1.65 0 00-1-1.51 1.65 1.65 0 00-1.82.33l-.06.06a2 2 0 11-2.83-2.83l.06-.06a1.65 1.65 0 00.33-1.82 1.65 1.65 0 00-1.51-1H3a2 2 0 110-4h.09a1.65 1.65 0 001.51-1 1.65 1.65 0 00-.33-1.82l-.06-.06a2 2 0 112.83-2.83l.06.06a1.65 1.65 0 001.82.33H9a1.65 1.65 0 001-1.51V3a2 2 0 114 0v.09a1.65 1.65 0 001 1.51 1.65 1.65 0 001.82-.33l.06-.06a2 2 0 112.83 2.83l-.06.06a1.65 1.65 0 00-.33 1.82V9a1.65 1.65 0 001.51 1H21a2 2 0 110 4h-.09a1.65 1.65 0 00-1.51 1z"/></svg>
</a>
<a href="#" class="ibtn danger" title="Sign out">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6"><path d="M9 21H5a2 2 0 01-2-2V5a2 2 0 012-2h4"/><polyline points="16 17 21 12 16 7"/><line x1="21" y1="12" x2="9" y2="12"/></svg>
</a>
</div>
</header>
<!-- ========================= MAIN ROW ========================= -->
<div class="flex flex-1 overflow-hidden">
<!-- =========================================================== -->
<!-- FLIGHT LIST SIDEBAR (~200px) -->
<!-- =========================================================== -->
<aside class="w-[210px] shrink-0 flex flex-col border-r hair" style="background: var(--surface-1);">
<div class="px-3 py-2.5 flex items-center justify-between border-b hair">
<span class="section-head">Flight Roster</span>
<span class="micro num" style="color: var(--text-muted);">04</span>
</div>
<!-- Filter -->
<div class="px-3 py-2 border-b hair">
<div class="relative">
<input class="ipt h-7 text-[11px] pl-7 mono" placeholder="SEARCH FLIGHTS" style="letter-spacing:0.08em;">
<svg class="absolute left-2 top-1/2 -translate-y-1/2" width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="color: var(--text-muted);"><circle cx="11" cy="11" r="7"/><line x1="21" y1="21" x2="16.65" y2="16.65"/></svg>
</div>
</div>
<!-- Flight list -->
<div class="flex-1 overflow-y-auto">
<div class="fl-row active">
<span class="fid">FL02</span>
<span style="color: var(--accent-amber);" title="Pinned"></span>
<span class="meta num">05/12</span>
</div>
<div class="fl-row">
<span class="fid">FL01</span>
<span class="meta num">05/09</span>
</div>
<div class="fl-row">
<span class="fid">FL03</span>
<span class="meta num">05/08</span>
</div>
<div class="fl-row">
<span class="fid">FL04</span>
<span class="meta num">05/03</span>
</div>
<div class="fl-row">
<span class="fid" style="color: var(--text-muted);">FL05</span>
<span class="micro" style="color: var(--text-muted);">DRAFT</span>
<span class="meta num">04/28</span>
</div>
</div>
<!-- Create -->
<div class="p-3 border-t hair">
<button class="btn-primary w-full flex items-center justify-center gap-2">
<svg width="10" height="10" viewBox="0 0 10 10"><path d="M5 1 V9 M1 5 H9" stroke="currentColor" stroke-width="1.5"/></svg>
Create New
</button>
</div>
<!-- Telemetry card -->
<div class="m-3 mt-0 bracket panel p-3" style="padding:12px;">
<div class="flex items-center justify-between mb-2">
<span class="micro" style="color: var(--accent-amber);">// Telemetry</span>
</div>
<label class="micro block mb-1">Date</label>
<input type="date" value="2025-03-01" class="ipt ipt-num text-[12px]">
<span class="br"></span>
</div>
</aside>
<!-- =========================================================== -->
<!-- PARAMS / GPS-DENIED PANEL (~280px) — both modes visible -->
<!-- =========================================================== -->
<aside id="paramsPanel" class="params-panel shrink-0 overflow-y-auto border-r hair" style="background: var(--surface-1);">
<!-- Collapsed rail (visible only when .collapsed) -->
<div class="collapsed-rail">
<button class="rail-btn" onclick="toggleParams()" title="Expand parameters">»</button>
<span class="block w-6 h-px" style="background: var(--border-hair);"></span>
<button class="dmode dmode-sq dmode-amber active" title="Points">
<svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="6" cy="6" r="1.6" fill="currentColor"/><circle cx="18" cy="6" r="1.6" fill="currentColor"/><circle cx="12" cy="14" r="1.6" fill="currentColor"/><circle cx="6" cy="20" r="1.6" fill="currentColor"/><circle cx="18" cy="20" r="1.6" fill="currentColor"/></svg>
</button>
<button class="dmode dmode-sq dmode-green" title="Work Area">
<svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polygon points="4 7 12 3 20 7 20 17 12 21 4 17"/></svg>
</button>
<button class="dmode dmode-sq dmode-red" title="No-Go Zone">
<svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="9"/><line x1="5.6" y1="5.6" x2="18.4" y2="18.4"/></svg>
</button>
</div>
<!-- Expanded body -->
<div class="panel-body">
<!-- Mode toggle bar -->
<div class="flex items-stretch border-b hair" style="background: var(--surface-0);">
<button id="tabFP" onclick="setMode('fp')" class="flex-1 py-2.5 mono text-[10px] uppercase tracking-[0.14em] border-b-2 transition"
style="color: var(--text-primary); border-color: var(--accent-amber); background: var(--surface-1);">
Flight Params
</button>
<button id="tabGPS" onclick="setMode('gps')" class="flex-1 py-2.5 mono text-[10px] uppercase tracking-[0.14em] border-b-2 transition"
style="color: var(--text-secondary); border-color: transparent;">
GPS-Denied
</button>
<button class="collapse-btn shrink-0 mx-1 self-center" onclick="toggleParams()" title="Collapse">«</button>
</div>
<!-- ============== FLIGHT PARAMETERS ============== -->
<section id="flightParams" class="p-4 space-y-5">
<!-- Draw-mode selector -->
<div>
<div class="flex items-center justify-between mb-1.5">
<span class="micro" style="color: var(--accent-amber);">// Draw Mode</span>
<span class="micro num" style="color: var(--text-muted);">click map to plot</span>
</div>
<div class="grid grid-cols-3 gap-2">
<button class="dmode dmode-amber active" data-mode="points">
<svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="6" cy="6" r="1.6" fill="currentColor"/><circle cx="18" cy="6" r="1.6" fill="currentColor"/><circle cx="12" cy="14" r="1.6" fill="currentColor"/><circle cx="6" cy="20" r="1.6" fill="currentColor"/><circle cx="18" cy="20" r="1.6" fill="currentColor"/><path d="M6 6l6 8 6-8M6 20l6-6 6 6" opacity="0.45"/></svg>
<span>Points</span>
</button>
<button class="dmode dmode-green" data-mode="work">
<svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polygon points="4 7 12 3 20 7 20 17 12 21 4 17"/></svg>
<span>Work Area</span>
</button>
<button class="dmode dmode-red" data-mode="nogo">
<svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="9"/><line x1="5.6" y1="5.6" x2="18.4" y2="18.4"/></svg>
<span>No-Go Zone</span>
</button>
</div>
</div>
<header class="flex items-center justify-between">
<h2 class="section-head">Mission Config</h2>
<span class="pill pill-amber"><span class="dot"></span>FL02</span>
</header>
<div class="bracket panel p-3 space-y-3">
<div>
<label class="micro block mb-1.5">Aircraft</label>
<select class="ipt">
<option>DJI Mavic 3 Enterprise</option>
<option>DJI Matrice 350 RTK</option>
<option>Autel EVO Max 4T</option>
</select>
</div>
<div class="grid grid-cols-2 gap-2">
<div>
<label class="micro block mb-1.5">Default Height</label>
<div class="relative">
<input type="number" value="100" class="ipt ipt-num pr-9">
<span class="absolute right-2.5 top-1/2 -translate-y-1/2 micro" style="color: var(--text-muted);">M</span>
</div>
</div>
<div>
<label class="micro block mb-1.5">Focal Length</label>
<div class="relative">
<input type="number" value="24" class="ipt ipt-num pr-10">
<span class="absolute right-2.5 top-1/2 -translate-y-1/2 micro" style="color: var(--text-muted);">MM</span>
</div>
</div>
</div>
<div>
<label class="micro block mb-1.5">Comm Address / Port</label>
<input type="text" value="192.168.1.42:8080" class="ipt ipt-num">
</div>
<span class="br"></span>
</div>
<!-- Waypoints -->
<div class="bracket panel p-3">
<header class="flex items-center justify-between mb-2.5">
<span class="section-head">Waypoints</span>
<span class="micro num" style="color: var(--text-muted);">06 PTS</span>
</header>
<div class="space-y-0">
<div class="wp-row">
<span class="wp-id">00</span>
<span class="wp-marker" style="background: var(--accent-green); transform: rotate(45deg);"></span>
<span class="mono text-[11px]">START</span>
<span class="wp-tag" style="color: var(--accent-green); border-color: var(--accent-green);">ORIGIN</span>
</div>
<div class="wp-row">
<span class="wp-id">01</span>
<span class="wp-marker" style="background: transparent; border: 1.5px solid var(--accent-cyan);"></span>
<span class="mono text-[11px]">Point 1</span>
<span class="wp-tag">TRACK</span>
</div>
<div class="wp-row">
<span class="wp-id">02</span>
<span class="wp-marker" style="background: transparent; border: 1.5px solid var(--accent-cyan);"></span>
<span class="mono text-[11px]">Point 2</span>
<span class="wp-tag" style="color: var(--accent-red); border-color: var(--accent-red);">MIL-VEH</span>
</div>
<div class="wp-row">
<span class="wp-id">03</span>
<span class="wp-marker" style="background: transparent; border: 1.5px solid var(--accent-cyan);"></span>
<span class="mono text-[11px]">Point 3</span>
</div>
<div class="wp-row">
<span class="wp-id">04</span>
<span class="wp-marker" style="background: transparent; border: 1.5px solid var(--accent-cyan);"></span>
<span class="mono text-[11px]">Point 4</span>
<span class="wp-tag">CONFIRM</span>
</div>
<div class="wp-row">
<span class="wp-id">FN</span>
<span class="wp-marker" style="background: var(--accent-red); clip-path: polygon(30% 0, 70% 0, 100% 30%, 100% 70%, 70% 100%, 30% 100%, 0 70%, 0 30%);"></span>
<span class="mono text-[11px]">FINISH</span>
<span class="wp-tag" style="color: var(--accent-red); border-color: var(--accent-red);">TARGET</span>
</div>
</div>
<span class="br"></span>
</div>
<div class="grid grid-cols-2 gap-2">
<button onclick="setMode('gps')" class="btn-secondary" style="color: var(--accent-red); border-color: var(--accent-red);">GPS-Denied</button>
<button class="btn-cyan">Upload</button>
</div>
</section>
<!-- ============== GPS-DENIED MODE ============== -->
<section id="gpsDenied" class="p-4 space-y-5 hidden">
<header class="flex items-center justify-between">
<h2 class="section-head" style="color: var(--accent-red);">GPS-Denied // Active</h2>
<span class="pill pill-red"><span class="dot pulse"></span>GPS-DENIED ACTIVE</span>
</header>
<!-- Frame with red accent -->
<div id="gpsFrame" class="bracket bracket-red panel gps-active-frame p-3">
<header class="flex items-center justify-between mb-3">
<span class="section-head" style="color: var(--accent-red);">// Orthophoto Upload</span>
<span class="micro num" style="color: var(--text-muted);">03 / 12</span>
</header>
<div class="space-y-1.5">
<div class="flex items-center gap-2.5 border hair px-2.5 py-2" style="background: var(--surface-0);">
<span class="w-6 h-6 flex items-center justify-center shrink-0 mono text-[10px]" style="background: var(--accent-cyan); color: #0A0D10; font-weight: 700;">P1</span>
<span class="mono text-[11px] flex-1 truncate">ortho_001.jpg</span>
<span class="num text-[10px]" style="color: var(--text-secondary);">48.8566, 2.3522</span>
</div>
<div class="flex items-center gap-2.5 border hair px-2.5 py-2" style="background: var(--surface-0);">
<span class="w-6 h-6 flex items-center justify-center shrink-0 mono text-[10px]" style="background: var(--accent-cyan); color: #0A0D10; font-weight: 700;">P2</span>
<span class="mono text-[11px] flex-1 truncate">ortho_002.jpg</span>
<span class="num text-[10px]" style="color: var(--text-secondary);">48.8612, 2.3601</span>
</div>
<div class="flex items-center gap-2.5 border hair px-2.5 py-2" style="background: var(--surface-0);">
<span class="w-6 h-6 flex items-center justify-center shrink-0 mono text-[10px]" style="background: var(--accent-cyan); color: #0A0D10; font-weight: 700;">P3</span>
<span class="mono text-[11px] flex-1 truncate">ortho_003.jpg</span>
<span class="num text-[10px]" style="color: var(--text-secondary);">48.8703, 2.3754</span>
</div>
</div>
<button class="w-full mt-2.5 py-2 mono text-[10px] uppercase tracking-[0.12em] border border-dashed flex items-center justify-center gap-2"
style="border-color: var(--border-raised); color: var(--text-secondary); background: transparent;">
<svg width="10" height="10" viewBox="0 0 10 10"><path d="M5 1 V9 M1 5 H9" stroke="currentColor" stroke-width="1.4"/></svg>
Upload Photos
</button>
<span class="br"></span>
</div>
<!-- Live GPS readout -->
<div class="bracket panel p-3">
<header class="flex items-center justify-between mb-2.5">
<span class="section-head">// Live GPS</span>
<span class="pill pill-green"><span class="dot pulse"></span>CONNECTED</span>
</header>
<div class="space-y-1.5 text-[12px]">
<div class="flex items-center justify-between py-1 border-b hair">
<span class="micro">Status</span>
<span class="mono" style="color: var(--accent-green);">CONNECTED · STREAMING</span>
</div>
<div class="flex items-center justify-between py-1 border-b hair">
<span class="micro">Latitude</span>
<span class="num">48.85660° N</span>
</div>
<div class="flex items-center justify-between py-1 border-b hair">
<span class="micro">Longitude</span>
<span class="num">02.35220° E</span>
</div>
<div class="flex items-center justify-between py-1 border-b hair">
<span class="micro">Satellites</span>
<span class="num" style="color: var(--accent-cyan);">12 / 14</span>
</div>
<div class="flex items-center justify-between py-1">
<span class="micro">Drift</span>
<span class="num" style="color: var(--accent-amber);">±2.4 M</span>
</div>
</div>
<span class="br"></span>
</div>
<!-- GPS Correction -->
<div class="bracket panel p-3">
<header class="flex items-center justify-between mb-2.5">
<span class="section-head">// GPS Correction</span>
</header>
<div class="space-y-2.5">
<div>
<label class="micro block mb-1.5">Waypoint #</label>
<input type="number" value="03" class="ipt ipt-num">
</div>
<div>
<label class="micro block mb-1.5">Corrected GPS</label>
<input type="text" value="48.86120, 2.36011" class="ipt ipt-num">
</div>
<button class="btn-primary w-full">Apply Correction</button>
</div>
<span class="br"></span>
</div>
<button onclick="setMode('fp')" class="btn-ghost w-full"> Back to Flight Params</button>
</section>
</div><!-- /.panel-body -->
</aside>
<!-- =========================================================== -->
<!-- MAP VIEW -->
<!-- =========================================================== -->
<main class="flex-1 relative overflow-hidden map-grid">
<!-- crosshairs -->
<div class="crosshair-x"></div>
<div class="crosshair-y"></div>
<!-- axis labels -->
<div class="map-axis-label" style="top: 8px; left: 12px;">SECTOR 04-K // ZOOM 17</div>
<div class="map-axis-label" style="top: 8px; left: 50%; transform: translateX(-50%);">— TARGET CORRIDOR —</div>
<div class="map-axis-label" style="bottom: 8px; left: 12px;">N 48.8566 // E 02.3522</div>
<div class="map-axis-label" style="bottom: 8px; right: 12px;">GRID 60M · WGS-84</div>
<!-- Compass rosette top-left -->
<div class="absolute top-12 left-4 w-20 h-20 flex items-center justify-center border hair bracket panel"
style="background: rgba(19,23,28,0.6); backdrop-filter: blur(2px);">
<svg width="60" height="60" viewBox="-30 -30 60 60" style="color: var(--accent-amber);">
<circle r="24" fill="none" stroke="currentColor" stroke-opacity="0.3" stroke-width="0.7"/>
<circle r="20" fill="none" stroke="currentColor" stroke-opacity="0.2" stroke-width="0.5"/>
<line x1="0" y1="-26" x2="0" y2="-20" stroke="currentColor" stroke-width="1.5"/>
<line x1="0" y1="20" x2="0" y2="26" stroke="currentColor" stroke-opacity="0.4" stroke-width="0.8"/>
<line x1="-26" y1="0" x2="-20" y2="0" stroke="currentColor" stroke-opacity="0.4" stroke-width="0.8"/>
<line x1="20" y1="0" x2="26" y2="0" stroke="currentColor" stroke-opacity="0.4" stroke-width="0.8"/>
<text x="0" y="-12" text-anchor="middle" font-family="JetBrains Mono" font-size="7" fill="currentColor" font-weight="700">N</text>
<polygon points="0,-16 -3,-8 0,-10 3,-8" fill="currentColor"/>
</svg>
<span class="br"></span>
</div>
<!-- SVG paths overlay -->
<svg class="absolute inset-0 w-full h-full" viewBox="0 0 800 600" preserveAspectRatio="none">
<defs>
<marker id="arrowCyan" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="6" markerHeight="6" orient="auto">
<path d="M0,0 L10,5 L0,10 z" fill="#36D6C5"/>
</marker>
</defs>
<!-- Original (planned) path — red dashed -->
<polyline points="150,450 250,350 350,280 450,320 550,250 650,200"
fill="none" stroke="#FF4756" stroke-width="1.5"
stroke-dasharray="5 4" opacity="0.85"/>
<!-- Corrected (live) path — cyan solid -->
<polyline points="150,460 255,358 360,290 455,328 555,260 650,210"
fill="none" stroke="#36D6C5" stroke-width="2"
marker-end="url(#arrowCyan)"/>
<!-- Correction ties (thin perpendicular linkers between original/corrected) -->
<g stroke="#36D6C5" stroke-width="0.6" stroke-dasharray="2 2" opacity="0.4">
<line x1="250" y1="350" x2="255" y2="358"/>
<line x1="350" y1="280" x2="360" y2="290"/>
<line x1="450" y1="320" x2="455" y2="328"/>
<line x1="550" y1="250" x2="555" y2="260"/>
</g>
</svg>
<!-- Waypoint markers on map -->
<!-- Start: diamond (green) -->
<div class="wp-marker-map" style="left:18.75%; top:75%;">
<div class="wp-diamond"></div>
<span class="absolute top-3 left-3 mono text-[9px] num" style="color: var(--accent-green); letter-spacing: 0.1em;">WP-00 · START</span>
</div>
<!-- Intermediate: square handles -->
<div class="wp-marker-map" style="left:31.25%; top:58.3%;">
<div class="wp-square"></div>
<span class="absolute top-3 left-3 mono text-[9px] num" style="color: var(--accent-cyan);">WP-01</span>
</div>
<div class="wp-marker-map" style="left:43.75%; top:46.7%;">
<div class="wp-square"></div>
<span class="absolute top-3 left-3 mono text-[9px] num" style="color: var(--accent-cyan);">WP-02</span>
</div>
<div class="wp-marker-map" style="left:56.25%; top:53.3%;">
<div class="wp-square"></div>
<span class="absolute top-3 left-3 mono text-[9px] num" style="color: var(--accent-cyan);">WP-03</span>
<span class="absolute -top-4 -left-1 mono text-[8px]" style="color: var(--accent-amber); letter-spacing: 0.1em;">CORRECTED</span>
</div>
<div class="wp-marker-map" style="left:68.75%; top:41.7%;">
<div class="wp-square"></div>
<span class="absolute top-3 left-3 mono text-[9px] num" style="color: var(--accent-cyan);">WP-04</span>
</div>
<!-- Finish: octagon (red) -->
<div class="wp-marker-map" style="left:81.25%; top:33.3%;">
<div class="wp-octagon"></div>
<span class="absolute top-3.5 left-3.5 mono text-[9px] num" style="color: var(--accent-red); letter-spacing: 0.1em;">WP-FN · TARGET</span>
</div>
<!-- ============ MAP HUD: TOP-RIGHT STATUS ============ -->
<div class="absolute top-4 right-4 w-[240px] bracket panel p-3" style="background: rgba(19,23,28,0.92); backdrop-filter: blur(4px);">
<header class="flex items-center justify-between mb-2.5 pb-2 border-b hair">
<span class="flex items-center gap-2 mono text-[10px]" style="color: var(--accent-cyan); letter-spacing: 0.14em;">
<span class="w-1.5 h-1.5 rounded-full pulse" style="background: var(--accent-cyan);"></span>
LIVE · CONNECTED
</span>
<span class="micro num" style="color: var(--text-muted);">FL02</span>
</header>
<div class="space-y-1">
<div class="flex items-center justify-between">
<span class="micro">Sat</span>
<span class="num text-[12px]" style="color: var(--accent-green);">12 / 14</span>
</div>
<div class="flex items-center justify-between">
<span class="micro">Lat</span>
<span class="num text-[12px]">48.85660° N</span>
</div>
<div class="flex items-center justify-between">
<span class="micro">Lon</span>
<span class="num text-[12px]">02.35220° E</span>
</div>
<div class="flex items-center justify-between">
<span class="micro">Alt</span>
<span class="num text-[12px]">320 M / AGL</span>
</div>
<div class="flex items-center justify-between">
<span class="micro">Hdg</span>
<span class="num text-[12px]" style="color: var(--accent-amber);">047° NE</span>
</div>
<div class="flex items-center justify-between">
<span class="micro">Spd</span>
<span class="num text-[12px]">11.4 M/S</span>
</div>
<div class="flex items-center justify-between pt-1.5 mt-1.5 border-t hair">
<span class="micro">Link</span>
<span class="num text-[11px]" style="color: var(--accent-green);">RSSI -52 DBM</span>
</div>
</div>
<span class="br"></span>
</div>
<!-- ============ MAP HUD: LEGEND BOTTOM-LEFT ============ -->
<div class="absolute bottom-12 left-4 w-[200px] bracket panel p-3" style="background: rgba(19,23,28,0.92);">
<header class="mb-2 pb-1.5 border-b hair">
<span class="section-head">// Map Legend</span>
</header>
<div class="space-y-1.5 text-[11px]">
<div class="flex items-center gap-2.5">
<svg width="22" height="6"><line x1="0" y1="3" x2="22" y2="3" stroke="#FF4756" stroke-width="1.5" stroke-dasharray="3 3"/></svg>
<span class="mono uppercase text-[10px]" style="letter-spacing: 0.1em;">Planned · Original</span>
</div>
<div class="flex items-center gap-2.5">
<svg width="22" height="6"><line x1="0" y1="3" x2="22" y2="3" stroke="#36D6C5" stroke-width="2"/></svg>
<span class="mono uppercase text-[10px]" style="letter-spacing: 0.1em;">Corrected · Live</span>
</div>
<div class="flex items-center gap-2.5 pt-1.5 border-t hair">
<div style="width:10px; height:10px; background: var(--accent-green); transform: rotate(45deg);"></div>
<span class="mono uppercase text-[10px]" style="letter-spacing: 0.1em;">Origin / Start</span>
</div>
<div class="flex items-center gap-2.5">
<div style="width:10px; height:10px; background: transparent; border: 1.5px solid var(--accent-cyan);"></div>
<span class="mono uppercase text-[10px]" style="letter-spacing: 0.1em;">Waypoint</span>
</div>
<div class="flex items-center gap-2.5">
<div style="width:11px; height:11px; background: var(--accent-red); clip-path: polygon(30% 0, 70% 0, 100% 30%, 100% 70%, 70% 100%, 30% 100%, 0 70%, 0 30%);"></div>
<span class="mono uppercase text-[10px]" style="letter-spacing: 0.1em;">Target / Finish</span>
</div>
</div>
<span class="br"></span>
</div>
<!-- ============ MAP TOOLBAR: RIGHT EDGE ============ -->
<div class="absolute top-1/2 right-4 -translate-y-1/2 flex flex-col gap-1.5">
<button class="w-8 h-8 flex items-center justify-center border hair panel mono text-[11px]" title="Zoom in" style="color: var(--text-primary);">+</button>
<button class="w-8 h-8 flex items-center justify-center border hair panel mono text-[11px]" title="Zoom out" style="color: var(--text-primary);"></button>
<div class="w-8 h-px" style="background: var(--border-hair);"></div>
<button class="w-8 h-8 flex items-center justify-center border hair panel" title="Recenter" style="color: var(--accent-amber);">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6"><circle cx="12" cy="12" r="3"/><circle cx="12" cy="12" r="8"/><line x1="12" y1="2" x2="12" y2="4"/><line x1="12" y1="20" x2="12" y2="22"/><line x1="2" y1="12" x2="4" y2="12"/><line x1="20" y1="12" x2="22" y2="12"/></svg>
</button>
<button class="w-8 h-8 flex items-center justify-center border hair panel" title="Layers" style="color: var(--text-secondary);">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6"><polygon points="12 2 2 7 12 12 22 7 12 2"/><polyline points="2 17 12 22 22 17"/><polyline points="2 12 12 17 22 12"/></svg>
</button>
</div>
<!-- ============ BOTTOM STATUS STRIP ============ -->
<div class="absolute bottom-0 left-0 right-0 h-7 flex items-center px-3 gap-4 border-t hair"
style="background: var(--surface-1);">
<span class="pill pill-green"><span class="dot pulse"></span>TELEMETRY · LIVE</span>
<span class="micro" style="color: var(--text-muted);">SSE</span>
<span class="micro num" style="color: var(--text-secondary);">FRAME 12,847 / 18,400</span>
<span class="micro" style="color: var(--text-muted);">·</span>
<span class="micro num" style="color: var(--text-secondary);">LAT 48.85660 N · LON 02.35220 E</span>
<span class="ml-auto micro num" style="color: var(--text-muted);">LAST PING +0.42S</span>
</div>
</main>
</div>
<script>
function setMode(mode) {
const fp = document.getElementById('flightParams');
const gps = document.getElementById('gpsDenied');
const tabFP = document.getElementById('tabFP');
const tabGPS = document.getElementById('tabGPS');
if (mode === 'gps') {
fp.classList.add('hidden');
gps.classList.remove('hidden');
tabFP.style.color = 'var(--text-secondary)';
tabFP.style.borderColor = 'transparent';
tabFP.style.background = 'transparent';
tabGPS.style.color = 'var(--text-primary)';
tabGPS.style.borderColor = 'var(--accent-red)';
tabGPS.style.background = 'var(--surface-1)';
} else {
gps.classList.add('hidden');
fp.classList.remove('hidden');
tabGPS.style.color = 'var(--text-secondary)';
tabGPS.style.borderColor = 'transparent';
tabGPS.style.background = 'transparent';
tabFP.style.color = 'var(--text-primary)';
tabFP.style.borderColor = 'var(--accent-amber)';
tabFP.style.background = 'var(--surface-1)';
}
}
function toggleParams() {
document.getElementById('paramsPanel').classList.toggle('collapsed');
}
</script>
</body>
</html>