diff --git a/README.md b/README.md index 65ad291..2c861ae 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@
## Screenshot -
+
---
@@ -44,7 +44,7 @@ Open `http://localhost:5050` in your browser. See [Installation](#installation)
git clone https://github.com/smittix/intercept.git
cd intercept
uv venv --python 3.11.12 # Or your Python version
-.venv\Scripts\activate
+source .venv/bin/activate
uv sync
# Run (sudo recommended for full functionality)
diff --git a/static/css/adsb_dashboard.css b/static/css/adsb_dashboard.css
new file mode 100644
index 0000000..8c1189c
--- /dev/null
+++ b/static/css/adsb_dashboard.css
@@ -0,0 +1,643 @@
+* {
+ margin: 0;
+ padding: 0;
+ box-sizing: border-box;
+}
+
+:root {
+ --bg-dark: #0a0a0f;
+ --bg-panel: #0d1117;
+ --bg-card: #161b22;
+ --border-glow: #00ff88;
+ --text-primary: #e6edf3;
+ --text-secondary: #8b949e;
+ --accent-green: #00ff88;
+ --accent-cyan: #00d4ff;
+ --accent-orange: #ff9500;
+ --accent-red: #ff4444;
+ --accent-yellow: #ffcc00;
+ --grid-line: rgba(0, 255, 136, 0.1);
+ --radar-cyan: #00ffff;
+ --radar-bg: #1a1a2e;
+}
+
+body {
+ font-family: 'Rajdhani', sans-serif;
+ background: var(--bg-dark);
+ color: var(--text-primary);
+ min-height: 100vh;
+ overflow-x: hidden;
+}
+
+/* Animated radar sweep background */
+.radar-bg {
+ position: fixed;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ background-image:
+ linear-gradient(var(--grid-line) 1px, transparent 1px),
+ linear-gradient(90deg, var(--grid-line) 1px, transparent 1px);
+ background-size: 50px 50px;
+ pointer-events: none;
+ z-index: 0;
+}
+
+/* Scan line effect */
+.scanline {
+ position: fixed;
+ top: 0;
+ left: 0;
+ right: 0;
+ height: 4px;
+ background: linear-gradient(90deg, transparent, var(--accent-green), transparent);
+ animation: scan 4s linear infinite;
+ pointer-events: none;
+ z-index: 1000;
+ opacity: 0.5;
+}
+
+@keyframes scan {
+ 0% {
+ top: -4px;
+ }
+
+ 100% {
+ top: 100vh;
+ }
+}
+
+/* Header */
+.header {
+ position: relative;
+ z-index: 10;
+ padding: 12px 20px;
+ background: linear-gradient(180deg, rgba(0, 255, 136, 0.1) 0%, transparent 100%);
+ border-bottom: 1px solid rgba(0, 255, 136, 0.3);
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+}
+
+.logo {
+ font-family: 'Orbitron', monospace;
+ font-size: 24px;
+ font-weight: 900;
+ letter-spacing: 4px;
+ color: var(--accent-green);
+ text-shadow: 0 0 20px var(--accent-green), 0 0 40px var(--accent-green);
+}
+
+.logo span {
+ color: var(--text-secondary);
+ font-weight: 400;
+ font-size: 14px;
+ margin-left: 15px;
+ letter-spacing: 2px;
+}
+
+.status-bar {
+ display: flex;
+ gap: 20px;
+ align-items: center;
+ font-family: 'JetBrains Mono', monospace;
+ font-size: 11px;
+}
+
+.status-item {
+ display: flex;
+ align-items: center;
+ gap: 6px;
+}
+
+.status-dot {
+ width: 8px;
+ height: 8px;
+ border-radius: 50%;
+ background: var(--accent-green);
+ box-shadow: 0 0 10px var(--accent-green);
+ animation: pulse 2s ease-in-out infinite;
+}
+
+.status-dot.inactive {
+ background: var(--accent-red);
+ box-shadow: 0 0 10px var(--accent-red);
+}
+
+@keyframes pulse {
+
+ 0%,
+ 100% {
+ opacity: 1;
+ }
+
+ 50% {
+ opacity: 0.5;
+ }
+}
+
+/* Stats badges in header */
+.stats-badges {
+ display: flex;
+ gap: 12px;
+}
+
+.stat-badge {
+ background: rgba(0, 255, 136, 0.1);
+ border: 1px solid rgba(0, 255, 136, 0.3);
+ border-radius: 4px;
+ padding: 4px 10px;
+ font-family: 'JetBrains Mono', monospace;
+ font-size: 11px;
+}
+
+.stat-badge .value {
+ color: var(--accent-green);
+ font-weight: 600;
+}
+
+.stat-badge .label {
+ color: var(--text-secondary);
+ margin-left: 4px;
+}
+
+.datetime {
+ font-family: 'Orbitron', monospace;
+ font-size: 12px;
+ color: var(--accent-green);
+}
+
+.back-link {
+ color: var(--accent-green);
+ text-decoration: none;
+ font-size: 11px;
+ padding: 4px 10px;
+ border: 1px solid var(--accent-green);
+ border-radius: 4px;
+}
+
+/* Main dashboard grid */
+.dashboard {
+ position: relative;
+ z-index: 10;
+ display: grid;
+ grid-template-columns: 1fr 340px;
+ grid-template-rows: 1fr auto;
+ gap: 0;
+ height: calc(100vh - 60px);
+ min-height: 500px;
+}
+
+/* Panels */
+.panel {
+ background: var(--bg-panel);
+ border: 1px solid rgba(0, 255, 136, 0.2);
+ overflow: hidden;
+ position: relative;
+}
+
+.panel::before {
+ content: '';
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ height: 2px;
+ background: linear-gradient(90deg, transparent, var(--accent-green), transparent);
+}
+
+.panel-header {
+ padding: 10px 15px;
+ background: rgba(0, 255, 136, 0.05);
+ border-bottom: 1px solid rgba(0, 255, 136, 0.1);
+ font-family: 'Orbitron', monospace;
+ font-size: 11px;
+ font-weight: 500;
+ letter-spacing: 2px;
+ text-transform: uppercase;
+ color: var(--accent-green);
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+}
+
+.panel-indicator {
+ width: 6px;
+ height: 6px;
+ background: var(--accent-green);
+ border-radius: 50%;
+ animation: blink 1s ease-in-out infinite;
+}
+
+@keyframes blink {
+
+ 0%,
+ 100% {
+ opacity: 1;
+ }
+
+ 50% {
+ opacity: 0.3;
+ }
+}
+
+@keyframes slideDown {
+ from {
+ opacity: 0;
+ transform: translateX(-50%) translateY(-20px);
+ }
+
+ to {
+ opacity: 1;
+ transform: translateX(-50%) translateY(0);
+ }
+}
+
+/* Main display container (map + radar scope) */
+.main-display {
+ grid-column: 1;
+ grid-row: 1;
+ position: relative;
+}
+
+.display-container {
+ position: relative;
+ width: 100%;
+ height: 100%;
+}
+
+#radarMap {
+ width: 100%;
+ height: 100%;
+ display: block;
+}
+
+#radarScope {
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ display: none;
+ background: var(--radar-bg);
+}
+
+#radarScope.active {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+}
+
+#radarCanvas {
+ max-width: 100%;
+ max-height: 100%;
+}
+
+/* Right sidebar */
+.sidebar {
+ grid-column: 2;
+ grid-row: 1;
+ display: flex;
+ flex-direction: column;
+ border-left: 1px solid rgba(0, 255, 136, 0.2);
+ overflow: hidden;
+}
+
+/* View toggle */
+.view-toggle {
+ display: flex;
+ padding: 10px;
+ gap: 8px;
+ background: var(--bg-panel);
+ border-bottom: 1px solid rgba(0, 255, 136, 0.2);
+}
+
+.view-btn {
+ flex: 1;
+ padding: 10px;
+ border: 1px solid rgba(0, 255, 136, 0.3);
+ background: transparent;
+ color: var(--text-secondary);
+ font-family: 'Orbitron', monospace;
+ font-size: 11px;
+ font-weight: 600;
+ text-transform: uppercase;
+ letter-spacing: 2px;
+ border-radius: 4px;
+ cursor: pointer;
+ transition: all 0.2s ease;
+}
+
+.view-btn:hover {
+ border-color: var(--accent-green);
+ color: var(--accent-green);
+}
+
+.view-btn.active {
+ background: var(--accent-green);
+ border-color: var(--accent-green);
+ color: var(--bg-dark);
+}
+
+/* Selected aircraft panel */
+.selected-aircraft {
+ flex-shrink: 0;
+ max-height: 280px;
+ overflow-y: auto;
+}
+
+.selected-info {
+ padding: 12px;
+}
+
+.selected-callsign {
+ font-family: 'Orbitron', monospace;
+ font-size: 20px;
+ font-weight: 700;
+ color: var(--accent-green);
+ text-shadow: 0 0 15px var(--accent-green);
+ text-align: center;
+ margin-bottom: 12px;
+}
+
+.telemetry-grid {
+ display: grid;
+ grid-template-columns: repeat(2, 1fr);
+ gap: 6px;
+}
+
+.telemetry-item {
+ background: rgba(0, 0, 0, 0.3);
+ border-radius: 4px;
+ padding: 8px;
+ border-left: 2px solid var(--accent-green);
+}
+
+.telemetry-label {
+ font-size: 9px;
+ text-transform: uppercase;
+ letter-spacing: 1px;
+ color: var(--text-secondary);
+ margin-bottom: 2px;
+}
+
+.telemetry-value {
+ font-family: 'JetBrains Mono', monospace;
+ font-size: 12px;
+ color: var(--accent-cyan);
+}
+
+/* Aircraft list */
+.aircraft-list {
+ flex: 1;
+ min-height: 0;
+ display: flex;
+ flex-direction: column;
+}
+
+.aircraft-list-content {
+ flex: 1;
+ overflow-y: auto;
+ padding: 8px;
+}
+
+.aircraft-item {
+ background: rgba(0, 0, 0, 0.3);
+ border: 1px solid rgba(0, 255, 136, 0.15);
+ border-radius: 4px;
+ padding: 8px 10px;
+ margin-bottom: 6px;
+ cursor: pointer;
+ transition: all 0.2s ease;
+}
+
+.aircraft-item:hover {
+ border-color: var(--accent-green);
+ background: rgba(0, 255, 136, 0.05);
+}
+
+.aircraft-item.selected {
+ border-color: var(--accent-green);
+ box-shadow: 0 0 15px rgba(0, 255, 136, 0.2);
+ background: rgba(0, 255, 136, 0.1);
+}
+
+.aircraft-header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ margin-bottom: 4px;
+}
+
+.aircraft-callsign {
+ font-family: 'Orbitron', monospace;
+ font-size: 12px;
+ font-weight: 600;
+ color: var(--accent-green);
+}
+
+.aircraft-icao {
+ font-family: 'JetBrains Mono', monospace;
+ font-size: 9px;
+ color: var(--text-secondary);
+ background: rgba(0, 255, 136, 0.1);
+ padding: 2px 5px;
+ border-radius: 3px;
+}
+
+.aircraft-details {
+ display: grid;
+ grid-template-columns: repeat(3, 1fr);
+ gap: 6px;
+ font-size: 10px;
+}
+
+.aircraft-detail {
+ text-align: center;
+}
+
+.aircraft-detail-value {
+ font-family: 'JetBrains Mono', monospace;
+ color: var(--accent-cyan);
+ font-size: 11px;
+}
+
+.aircraft-detail-label {
+ color: var(--text-secondary);
+ font-size: 8px;
+ text-transform: uppercase;
+}
+
+/* Bottom controls bar */
+.controls-bar {
+ grid-column: 1 / -1;
+ grid-row: 2;
+ display: flex;
+ align-items: center;
+ gap: 20px;
+ padding: 10px 20px;
+ background: var(--bg-panel);
+ border-top: 1px solid rgba(0, 255, 136, 0.3);
+}
+
+.control-group {
+ display: flex;
+ align-items: center;
+ gap: 8px;
+}
+
+.control-group label {
+ display: flex;
+ align-items: center;
+ gap: 6px;
+ cursor: pointer;
+ font-size: 11px;
+ color: var(--text-primary);
+}
+
+.control-group input[type="checkbox"] {
+ accent-color: var(--accent-green);
+}
+
+.control-group select {
+ padding: 6px 10px;
+ background: rgba(0, 0, 0, 0.3);
+ border: 1px solid rgba(0, 255, 136, 0.3);
+ border-radius: 4px;
+ color: var(--accent-green);
+ font-family: 'JetBrains Mono', monospace;
+ font-size: 11px;
+}
+
+.control-group input[type="text"] {
+ width: 80px;
+ padding: 6px 8px;
+ background: rgba(0, 0, 0, 0.3);
+ border: 1px solid rgba(0, 255, 136, 0.3);
+ border-radius: 4px;
+ color: var(--accent-green);
+ font-family: 'JetBrains Mono', monospace;
+ font-size: 11px;
+}
+
+.control-label {
+ font-size: 10px;
+ text-transform: uppercase;
+ letter-spacing: 1px;
+ color: var(--text-secondary);
+}
+
+/* Start/stop button */
+.start-btn {
+ padding: 8px 20px;
+ border: 1px solid var(--accent-green);
+ background: rgba(0, 255, 136, 0.1);
+ color: var(--accent-green);
+ font-family: 'Orbitron', monospace;
+ font-size: 11px;
+ font-weight: 600;
+ text-transform: uppercase;
+ letter-spacing: 2px;
+ border-radius: 4px;
+ cursor: pointer;
+ transition: all 0.2s ease;
+ margin-left: auto;
+}
+
+.start-btn:hover {
+ background: var(--accent-green);
+ color: var(--bg-dark);
+ box-shadow: 0 0 20px rgba(0, 255, 136, 0.3);
+}
+
+.start-btn.active {
+ background: var(--accent-red);
+ border-color: var(--accent-red);
+ color: #fff;
+}
+
+.start-btn.active:hover {
+ box-shadow: 0 0 20px rgba(255, 68, 68, 0.3);
+}
+
+/* GPS button */
+.gps-btn {
+ padding: 6px 10px;
+ background: rgba(0, 255, 136, 0.2);
+ border: 1px solid rgba(0, 255, 136, 0.3);
+ border-radius: 4px;
+ color: var(--accent-green);
+ font-family: 'JetBrains Mono', monospace;
+ font-size: 10px;
+ cursor: pointer;
+}
+
+/* Leaflet overrides */
+.leaflet-container {
+ background: var(--bg-dark) !important;
+}
+
+.leaflet-control-zoom a {
+ background: var(--bg-panel) !important;
+ color: var(--accent-green) !important;
+ border-color: rgba(0, 255, 136, 0.3) !important;
+}
+
+.leaflet-control-attribution {
+ background: rgba(0, 0, 0, 0.7) !important;
+ color: var(--text-secondary) !important;
+ font-size: 9px !important;
+}
+
+/* Custom scrollbar */
+::-webkit-scrollbar {
+ width: 6px;
+}
+
+::-webkit-scrollbar-track {
+ background: var(--bg-dark);
+}
+
+::-webkit-scrollbar-thumb {
+ background: var(--accent-green);
+ border-radius: 3px;
+}
+
+/* No aircraft message */
+.no-aircraft {
+ text-align: center;
+ padding: 30px 15px;
+ color: var(--text-secondary);
+}
+
+.no-aircraft-icon {
+ font-size: 36px;
+ margin-bottom: 10px;
+ opacity: 0.5;
+}
+
+/* Responsive */
+@media (max-width: 1000px) {
+ .dashboard {
+ grid-template-columns: 1fr;
+ grid-template-rows: 1fr auto auto;
+ }
+
+ .main-display {
+ min-height: 400px;
+ }
+
+ .sidebar {
+ grid-column: 1;
+ grid-row: 2;
+ border-left: none;
+ border-top: 1px solid rgba(0, 255, 136, 0.2);
+ max-height: 300px;
+ }
+
+ .controls-bar {
+ grid-row: 3;
+ flex-wrap: wrap;
+ }
+}
\ No newline at end of file
diff --git a/static/css/index.css b/static/css/index.css
new file mode 100644
index 0000000..7c3b903
--- /dev/null
+++ b/static/css/index.css
@@ -0,0 +1,2987 @@
+@import url('https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;700&family=Orbitron:wght@400;500;600;700;800;900&family=Rajdhani:wght@400;500;600;700&display=swap');
+
+* {
+ box-sizing: border-box;
+ margin: 0;
+ padding: 0;
+}
+
+:root {
+ --bg-primary: #000000;
+ --bg-secondary: #0a0a0a;
+ --bg-tertiary: #111111;
+ --bg-card: #0d0d0d;
+ --accent-cyan: #00d4ff;
+ --accent-cyan-dim: #00d4ff40;
+ --accent-green: #00ff88;
+ --accent-red: #ff3366;
+ --accent-orange: #ff8800;
+ --text-primary: #ffffff;
+ --text-secondary: #888888;
+ --text-dim: #444444;
+ --border-color: #1a1a1a;
+ --border-glow: #00d4ff33;
+}
+
+[data-theme="light"] {
+ --bg-primary: #f5f5f5;
+ --bg-secondary: #e8e8e8;
+ --bg-tertiary: #dddddd;
+ --bg-card: #ffffff;
+ --accent-cyan: #0088aa;
+ --accent-cyan-dim: #0088aa40;
+ --accent-green: #00aa55;
+ --accent-red: #cc2244;
+ --accent-orange: #cc6600;
+ --text-primary: #111111;
+ --text-secondary: #555555;
+ --text-dim: #999999;
+ --border-color: #cccccc;
+ --border-glow: #0088aa33;
+}
+
+[data-theme="light"] body {
+ background-image:
+ radial-gradient(ellipse at top, #d0e8f0 0%, transparent 50%),
+ radial-gradient(ellipse at bottom, #f0f0f0 0%, var(--bg-primary) 100%);
+}
+
+[data-theme="light"] .leaflet-tile-pane {
+ filter: none;
+}
+
+body {
+ font-family: 'Rajdhani', 'Segoe UI', sans-serif;
+ background: var(--bg-primary);
+ color: var(--text-primary);
+ min-height: 100vh;
+ background-image:
+ radial-gradient(ellipse at top, #001a2c 0%, transparent 50%),
+ radial-gradient(ellipse at bottom, #0a0a0a 0%, var(--bg-primary) 100%);
+}
+
+.container {
+ max-width: 1400px;
+ margin: 0 auto;
+ padding: 20px;
+}
+
+header {
+ background: linear-gradient(180deg, var(--bg-secondary) 0%, transparent 100%);
+ padding: 30px 20px;
+ text-align: center;
+ border-bottom: 1px solid var(--border-color);
+ margin-bottom: 25px;
+ position: relative;
+}
+
+header::after {
+ content: '';
+ position: absolute;
+ bottom: -1px;
+ left: 50%;
+ transform: translateX(-50%);
+ width: 200px;
+ height: 1px;
+ background: linear-gradient(90deg, transparent, var(--accent-cyan), transparent);
+}
+
+header h1 {
+ color: var(--text-primary);
+ font-size: 2.5em;
+ font-weight: 700;
+ letter-spacing: 8px;
+ text-transform: uppercase;
+ margin-bottom: 8px;
+ text-shadow: 0 0 30px var(--accent-cyan-dim);
+}
+
+header p {
+ color: var(--text-secondary);
+ font-size: 14px;
+ letter-spacing: 3px;
+ text-transform: uppercase;
+}
+
+/* New header stat badges */
+.header-stats {
+ display: flex;
+ justify-content: center;
+ gap: 15px;
+ margin-top: 15px;
+ flex-wrap: wrap;
+}
+
+.stat-badge {
+ display: flex;
+ align-items: center;
+ gap: 8px;
+ padding: 8px 16px;
+ background: linear-gradient(135deg, rgba(0, 212, 255, 0.1), rgba(0, 0, 0, 0.3));
+ border: 1px solid var(--border-color);
+ border-radius: 6px;
+ font-family: 'JetBrains Mono', monospace;
+ transition: all 0.2s ease;
+}
+
+.stat-badge:hover {
+ border-color: var(--accent-cyan);
+ box-shadow: 0 0 15px var(--accent-cyan-dim);
+}
+
+.stat-badge .badge-value {
+ font-size: 18px;
+ font-weight: 700;
+ color: var(--accent-cyan);
+ text-shadow: 0 0 10px var(--accent-cyan-dim);
+}
+
+.stat-badge .badge-value.highlight {
+ color: var(--accent-green);
+ text-shadow: 0 0 10px rgba(0, 255, 136, 0.4);
+}
+
+.stat-badge .badge-value.warning {
+ color: var(--accent-orange);
+ text-shadow: 0 0 10px rgba(255, 136, 0, 0.4);
+}
+
+.stat-badge .badge-value.alert {
+ color: var(--accent-red);
+ text-shadow: 0 0 10px rgba(255, 51, 102, 0.4);
+}
+
+.stat-badge .badge-label {
+ font-size: 10px;
+ color: var(--text-secondary);
+ text-transform: uppercase;
+ letter-spacing: 1px;
+}
+
+.stat-badge .badge-icon {
+ font-size: 16px;
+}
+
+.header-stats-group {
+ display: none;
+}
+
+.header-stats-group.active {
+ display: flex;
+ gap: 12px;
+ flex-wrap: wrap;
+ justify-content: center;
+}
+
+/* UTC Clock in header */
+.header-clock {
+ position: absolute;
+ top: 20px;
+ left: 20px;
+ font-family: 'JetBrains Mono', monospace;
+ font-size: 12px;
+ color: var(--text-secondary);
+ display: flex;
+ align-items: center;
+ gap: 8px;
+}
+
+.header-clock .utc-time {
+ color: var(--accent-cyan);
+ font-weight: 600;
+}
+
+.header-clock .utc-label {
+ font-size: 9px;
+ color: var(--text-dim);
+ text-transform: uppercase;
+ letter-spacing: 1px;
+}
+
+/* Active mode indicator */
+.active-mode-indicator {
+ display: inline-flex;
+ align-items: center;
+ gap: 6px;
+ padding: 4px 12px;
+ background: var(--accent-cyan);
+ color: var(--bg-primary);
+ border-radius: 4px;
+ font-size: 10px;
+ font-weight: 600;
+ text-transform: uppercase;
+ letter-spacing: 1px;
+ margin-left: 10px;
+}
+
+.active-mode-indicator .pulse-dot {
+ width: 6px;
+ height: 6px;
+ background: var(--bg-primary);
+ border-radius: 50%;
+ animation: pulse-glow 2s infinite;
+}
+
+.help-btn {
+ position: absolute;
+ top: 20px;
+ right: 20px;
+ width: 32px;
+ height: 32px;
+ border-radius: 50%;
+ background: var(--bg-primary);
+ border: 1px solid var(--border-color);
+ color: var(--text-secondary);
+ font-size: 16px;
+ font-weight: bold;
+ cursor: pointer;
+ transition: all 0.2s ease;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ z-index: 100;
+}
+
+.help-btn:hover {
+ border-color: var(--accent-cyan);
+ color: var(--accent-cyan);
+ box-shadow: 0 0 15px var(--accent-cyan-dim);
+}
+
+.theme-toggle {
+ position: absolute;
+ top: 20px;
+ right: 60px;
+ width: 32px;
+ height: 32px;
+ border-radius: 50%;
+ background: var(--bg-primary);
+ border: 1px solid var(--border-color);
+ color: var(--text-secondary);
+ font-size: 16px;
+ cursor: pointer;
+ transition: all 0.2s ease;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ z-index: 100;
+}
+
+.theme-toggle:hover {
+ border-color: var(--accent-cyan);
+ color: var(--accent-cyan);
+ box-shadow: 0 0 15px var(--accent-cyan-dim);
+}
+
+.theme-toggle .icon-sun,
+.theme-toggle .icon-moon {
+ position: absolute;
+ transition: opacity 0.2s, transform 0.2s;
+}
+
+.theme-toggle .icon-sun {
+ opacity: 0;
+ transform: rotate(-90deg);
+}
+
+.theme-toggle .icon-moon {
+ opacity: 1;
+ transform: rotate(0deg);
+}
+
+[data-theme="light"] .theme-toggle .icon-sun {
+ opacity: 1;
+ transform: rotate(0deg);
+}
+
+[data-theme="light"] .theme-toggle .icon-moon {
+ opacity: 0;
+ transform: rotate(90deg);
+}
+
+.help-modal {
+ display: none;
+ position: fixed;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ background: rgba(0, 0, 0, 0.85);
+ z-index: 10000;
+ overflow-y: auto;
+ padding: 40px 20px;
+}
+
+.help-modal.active {
+ display: block;
+}
+
+.help-content {
+ max-width: 800px;
+ margin: 0 auto;
+ background: var(--bg-card);
+ border: 1px solid var(--border-color);
+ border-radius: 8px;
+ padding: 30px;
+ position: relative;
+}
+
+.help-content h2 {
+ color: var(--accent-cyan);
+ margin-bottom: 20px;
+ font-size: 24px;
+ letter-spacing: 2px;
+}
+
+.help-content h3 {
+ color: var(--text-primary);
+ margin: 25px 0 15px 0;
+ font-size: 14px;
+ text-transform: uppercase;
+ letter-spacing: 1px;
+ border-bottom: 1px solid var(--border-color);
+ padding-bottom: 8px;
+}
+
+.help-close {
+ position: absolute;
+ top: 15px;
+ right: 15px;
+ background: none;
+ border: none;
+ color: var(--text-dim);
+ font-size: 24px;
+ cursor: pointer;
+ transition: color 0.2s;
+}
+
+.help-close:hover {
+ color: var(--accent-red);
+}
+
+.icon-grid {
+ display: grid;
+ grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
+ gap: 12px;
+ margin: 15px 0;
+}
+
+.icon-item {
+ display: flex;
+ align-items: center;
+ gap: 10px;
+ padding: 10px;
+ background: var(--bg-primary);
+ border: 1px solid var(--border-color);
+ border-radius: 4px;
+ font-size: 12px;
+}
+
+.icon-item .icon {
+ font-size: 18px;
+ width: 30px;
+ text-align: center;
+}
+
+.icon-item .desc {
+ color: var(--text-secondary);
+}
+
+.tip-list {
+ list-style: none;
+ padding: 0;
+ margin: 15px 0;
+}
+
+.tip-list li {
+ padding: 8px 0;
+ padding-left: 20px;
+ position: relative;
+ color: var(--text-secondary);
+ font-size: 13px;
+ border-bottom: 1px solid var(--border-color);
+}
+
+.tip-list li:last-child {
+ border-bottom: none;
+}
+
+.tip-list li::before {
+ content: '›';
+ position: absolute;
+ left: 0;
+ color: var(--accent-cyan);
+ font-weight: bold;
+}
+
+.help-tabs {
+ display: flex;
+ gap: 0;
+ margin-bottom: 20px;
+ border: 1px solid var(--border-color);
+ border-radius: 4px;
+ overflow: hidden;
+}
+
+.help-tab {
+ flex: 1;
+ padding: 10px;
+ background: var(--bg-primary);
+ border: none;
+ color: var(--text-secondary);
+ cursor: pointer;
+ font-size: 11px;
+ text-transform: uppercase;
+ letter-spacing: 1px;
+ transition: all 0.2s;
+}
+
+.help-tab:not(:last-child) {
+ border-right: 1px solid var(--border-color);
+}
+
+.help-tab:hover {
+ background: var(--bg-secondary);
+}
+
+.help-tab.active {
+ background: var(--accent-cyan);
+ color: var(--bg-primary);
+}
+
+.help-section {
+ display: none;
+}
+
+.help-section.active {
+ display: block;
+}
+
+.logo {
+ margin-bottom: 15px;
+ animation: logo-pulse 3s ease-in-out infinite;
+}
+
+.logo svg {
+ filter: drop-shadow(0 0 10px var(--accent-cyan-dim));
+}
+
+@keyframes logo-pulse {
+
+ 0%,
+ 100% {
+ filter: drop-shadow(0 0 5px var(--accent-cyan-dim));
+ }
+
+ 50% {
+ filter: drop-shadow(0 0 20px var(--accent-cyan));
+ }
+}
+
+.main-content {
+ display: grid;
+ grid-template-columns: 340px 1fr;
+ gap: 25px;
+}
+
+@media (max-width: 900px) {
+ .main-content {
+ grid-template-columns: 1fr;
+ }
+}
+
+.sidebar {
+ background: linear-gradient(180deg, var(--bg-card) 0%, var(--bg-primary) 100%);
+ border: 1px solid var(--border-color);
+ padding: 20px;
+ position: relative;
+ border-radius: 8px;
+}
+
+.sidebar::before {
+ content: '';
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ height: 2px;
+ background: linear-gradient(90deg, var(--accent-cyan), transparent);
+ border-radius: 8px 8px 0 0;
+}
+
+.section {
+ margin-bottom: 20px;
+ background: linear-gradient(135deg, rgba(0, 212, 255, 0.03), rgba(0, 0, 0, 0.2));
+ border: 1px solid var(--border-color);
+ border-radius: 6px;
+ padding: 12px;
+ position: relative;
+}
+
+.section h3 {
+ color: var(--accent-cyan);
+ margin-bottom: 12px;
+ padding-bottom: 8px;
+ border-bottom: 1px solid var(--border-color);
+ font-size: 11px;
+ font-weight: 600;
+ text-transform: uppercase;
+ letter-spacing: 2px;
+ display: flex;
+ align-items: center;
+ gap: 8px;
+ cursor: pointer;
+ user-select: none;
+ font-family: 'Orbitron', 'Rajdhani', sans-serif;
+}
+
+.section h3::before {
+ content: '';
+ width: 6px;
+ height: 6px;
+ background: var(--accent-cyan);
+ border-radius: 50%;
+ box-shadow: 0 0 8px var(--accent-cyan);
+ flex-shrink: 0;
+}
+
+.section h3::after {
+ content: '▼';
+ font-size: 8px;
+ color: var(--text-dim);
+ transition: transform 0.2s ease;
+ margin-left: auto;
+ font-family: sans-serif;
+}
+
+.section.collapsed h3::after {
+ transform: rotate(-90deg);
+}
+
+.section.collapsed>*:not(h3) {
+ display: none !important;
+}
+
+.section h3:hover {
+ color: var(--text-primary);
+}
+
+.section h3:hover::before {
+ background: var(--accent-green);
+ box-shadow: 0 0 12px var(--accent-green);
+}
+
+.form-group {
+ margin-bottom: 12px;
+}
+
+.form-group label {
+ display: block;
+ margin-bottom: 4px;
+ color: var(--text-secondary);
+ font-size: 10px;
+ text-transform: uppercase;
+ letter-spacing: 1px;
+}
+
+.form-group input,
+.form-group select {
+ width: 100%;
+ padding: 10px 12px;
+ background: var(--bg-primary);
+ border: 1px solid var(--border-color);
+ color: var(--text-primary);
+ font-family: 'JetBrains Mono', monospace;
+ font-size: 13px;
+ transition: all 0.2s ease;
+}
+
+.form-group input:focus,
+.form-group select:focus {
+ outline: none;
+ border-color: var(--accent-cyan);
+ box-shadow: 0 0 15px var(--accent-cyan-dim), inset 0 0 15px var(--accent-cyan-dim);
+}
+
+.checkbox-group {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 12px;
+}
+
+.checkbox-group label {
+ display: flex;
+ align-items: center;
+ gap: 8px;
+ color: var(--text-secondary);
+ font-size: 12px;
+ cursor: pointer;
+ padding: 8px 12px;
+ background: var(--bg-primary);
+ border: 1px solid var(--border-color);
+ transition: all 0.2s ease;
+}
+
+.checkbox-group label:hover {
+ border-color: var(--accent-cyan);
+}
+
+.checkbox-group input[type="checkbox"] {
+ width: auto;
+ accent-color: var(--accent-cyan);
+}
+
+.preset-buttons {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 6px;
+}
+
+.preset-btn {
+ padding: 8px 14px;
+ background: var(--bg-primary);
+ border: 1px solid var(--border-color);
+ color: var(--text-secondary);
+ cursor: pointer;
+ font-family: 'JetBrains Mono', monospace;
+ font-size: 11px;
+ text-transform: uppercase;
+ letter-spacing: 1px;
+ transition: all 0.2s ease;
+ border-radius: 3px;
+}
+
+.preset-btn:hover {
+ background: var(--accent-cyan);
+ color: var(--bg-primary);
+ border-color: var(--accent-cyan);
+ box-shadow: 0 0 20px var(--accent-cyan-dim);
+}
+
+.run-btn {
+ width: 100%;
+ padding: 14px;
+ background: transparent;
+ border: 2px solid var(--accent-green);
+ color: var(--accent-green);
+ font-family: 'Rajdhani', sans-serif;
+ font-size: 13px;
+ font-weight: 700;
+ text-transform: uppercase;
+ letter-spacing: 3px;
+ cursor: pointer;
+ transition: all 0.3s ease;
+ margin-top: 12px;
+ position: relative;
+ overflow: hidden;
+ border-radius: 4px;
+}
+
+.run-btn::before {
+ content: '';
+ position: absolute;
+ top: 0;
+ left: -100%;
+ width: 100%;
+ height: 100%;
+ background: linear-gradient(90deg, transparent, var(--accent-green), transparent);
+ opacity: 0.3;
+ transition: left 0.5s ease;
+}
+
+.run-btn:hover {
+ background: var(--accent-green);
+ color: var(--bg-primary);
+ box-shadow: 0 0 30px rgba(0, 255, 136, 0.4);
+}
+
+.run-btn:hover::before {
+ left: 100%;
+}
+
+.stop-btn {
+ width: 100%;
+ padding: 16px;
+ background: transparent;
+ border: 2px solid var(--accent-red);
+ color: var(--accent-red);
+ font-family: 'Rajdhani', sans-serif;
+ font-size: 14px;
+ font-weight: 700;
+ text-transform: uppercase;
+ letter-spacing: 4px;
+ cursor: pointer;
+ transition: all 0.3s ease;
+ margin-top: 15px;
+}
+
+.stop-btn:hover {
+ background: var(--accent-red);
+ color: var(--bg-primary);
+ box-shadow: 0 0 30px rgba(255, 51, 102, 0.4);
+}
+
+.output-panel {
+ background: linear-gradient(180deg, var(--bg-card) 0%, var(--bg-primary) 100%);
+ border: 1px solid var(--border-color);
+ display: flex;
+ flex-direction: column;
+ position: relative;
+ border-radius: 8px;
+ overflow: hidden;
+}
+
+.output-panel::before {
+ content: '';
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ height: 2px;
+ background: linear-gradient(90deg, transparent, var(--accent-cyan), transparent);
+ border-radius: 8px 8px 0 0;
+}
+
+.output-header {
+ padding: 15px 20px;
+ background: linear-gradient(135deg, rgba(0, 212, 255, 0.05), rgba(0, 0, 0, 0.3));
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ border-bottom: 1px solid var(--border-color);
+}
+
+.output-header h3 {
+ color: var(--text-primary);
+ font-size: 12px;
+ font-weight: 600;
+ text-transform: uppercase;
+ letter-spacing: 3px;
+ font-family: 'Orbitron', 'Rajdhani', sans-serif;
+ display: flex;
+ align-items: center;
+ gap: 10px;
+}
+
+.output-header h3::before {
+ content: '';
+ width: 8px;
+ height: 8px;
+ background: var(--accent-cyan);
+ border-radius: 50%;
+ box-shadow: 0 0 10px var(--accent-cyan);
+}
+
+.stats {
+ display: flex;
+ gap: 12px;
+ font-size: 10px;
+ color: var(--text-secondary);
+ font-family: 'JetBrains Mono', monospace;
+}
+
+.stats>div {
+ display: flex;
+ align-items: center;
+ gap: 4px;
+ padding: 4px 8px;
+ background: var(--bg-primary);
+ border: 1px solid var(--border-color);
+ border-radius: 3px;
+}
+
+.stats>div:hover {
+ border-color: var(--accent-cyan);
+}
+
+.stats span {
+ color: var(--accent-cyan);
+ font-weight: 600;
+}
+
+.output-content {
+ flex: 1;
+ padding: 15px;
+ overflow-y: auto;
+ font-family: 'JetBrains Mono', monospace;
+ font-size: 12px;
+ background: var(--bg-primary);
+ margin: 15px;
+ border: 1px solid var(--border-color);
+ min-height: 500px;
+ max-height: 600px;
+}
+
+.output-content::-webkit-scrollbar {
+ width: 6px;
+}
+
+.output-content::-webkit-scrollbar-track {
+ background: var(--bg-primary);
+}
+
+.output-content::-webkit-scrollbar-thumb {
+ background: var(--border-color);
+}
+
+.output-content::-webkit-scrollbar-thumb:hover {
+ background: var(--accent-cyan);
+}
+
+.message {
+ padding: 15px;
+ margin-bottom: 10px;
+ border: 1px solid var(--border-color);
+ border-left: 3px solid var(--accent-cyan);
+ background: var(--bg-secondary);
+ position: relative;
+ transition: all 0.2s ease;
+}
+
+.message:hover {
+ border-left-color: var(--accent-cyan);
+ box-shadow: 0 0 20px var(--accent-cyan-dim);
+}
+
+.message.pocsag {
+ border-left-color: var(--accent-cyan);
+}
+
+.message.flex {
+ border-left-color: var(--accent-orange);
+}
+
+.message .header {
+ display: flex;
+ justify-content: space-between;
+ margin-bottom: 8px;
+ font-size: 10px;
+ color: var(--text-dim);
+ text-transform: uppercase;
+ letter-spacing: 1px;
+}
+
+.message .protocol {
+ color: var(--accent-cyan);
+ font-weight: 600;
+}
+
+.message.pocsag .protocol {
+ color: var(--accent-cyan);
+}
+
+.message.flex .protocol {
+ color: var(--accent-orange);
+}
+
+.message .address {
+ color: var(--accent-green);
+ font-family: 'JetBrains Mono', monospace;
+ font-size: 11px;
+ margin-bottom: 8px;
+}
+
+.message .content {
+ color: var(--text-primary);
+ word-wrap: break-word;
+ font-size: 13px;
+ line-height: 1.5;
+}
+
+.message .content.numeric {
+ font-family: 'JetBrains Mono', monospace;
+ font-size: 15px;
+ letter-spacing: 2px;
+ color: var(--accent-cyan);
+}
+
+.status-bar {
+ padding: 12px 20px;
+ background: linear-gradient(180deg, var(--bg-secondary) 0%, var(--bg-primary) 100%);
+ border-top: 1px solid var(--border-color);
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ font-size: 11px;
+ gap: 15px;
+ flex-wrap: wrap;
+}
+
+.status-indicator {
+ display: flex;
+ align-items: center;
+ gap: 10px;
+ text-transform: uppercase;
+ letter-spacing: 2px;
+ padding: 6px 12px;
+ background: rgba(0, 0, 0, 0.3);
+ border-radius: 4px;
+ border: 1px solid var(--border-color);
+}
+
+.status-controls {
+ display: flex;
+ align-items: center;
+ gap: 6px;
+ flex-wrap: wrap;
+}
+
+.control-group {
+ display: flex;
+ align-items: center;
+ gap: 6px;
+ padding: 4px 10px;
+ background: rgba(0, 0, 0, 0.2);
+ border-radius: 4px;
+ border: 1px solid var(--border-color);
+}
+
+.control-group-label {
+ font-size: 9px;
+ color: var(--text-dim);
+ text-transform: uppercase;
+ letter-spacing: 1px;
+ margin-right: 4px;
+}
+
+.status-dot {
+ width: 8px;
+ height: 8px;
+ background: var(--text-dim);
+ position: relative;
+}
+
+.status-dot.running {
+ background: var(--accent-green);
+ box-shadow: 0 0 10px var(--accent-green);
+ animation: pulse-glow 2s infinite;
+}
+
+@keyframes pulse-glow {
+
+ 0%,
+ 100% {
+ opacity: 1;
+ box-shadow: 0 0 10px var(--accent-green);
+ }
+
+ 50% {
+ opacity: 0.7;
+ box-shadow: 0 0 20px var(--accent-green), 0 0 30px var(--accent-green);
+ }
+}
+
+@keyframes pulse {
+
+ 0%,
+ 100% {
+ opacity: 1;
+ }
+
+ 50% {
+ opacity: 0.3;
+ }
+}
+
+.clear-btn {
+ padding: 8px 16px;
+ background: transparent;
+ border: 1px solid var(--border-color);
+ color: var(--text-secondary);
+ cursor: pointer;
+ font-size: 10px;
+ text-transform: uppercase;
+ letter-spacing: 2px;
+ transition: all 0.2s ease;
+}
+
+.clear-btn:hover {
+ border-color: var(--accent-cyan);
+ color: var(--accent-cyan);
+}
+
+.tool-status {
+ font-size: 10px;
+ padding: 4px 10px;
+ margin-left: 8px;
+ text-transform: uppercase;
+ letter-spacing: 1px;
+ font-weight: 600;
+}
+
+.tool-status.ok {
+ background: transparent;
+ border: 1px solid var(--accent-green);
+ color: var(--accent-green);
+}
+
+.tool-status.missing {
+ background: transparent;
+ border: 1px solid var(--accent-red);
+ color: var(--accent-red);
+}
+
+.info-text {
+ font-size: 10px;
+ color: var(--text-dim);
+ margin-top: 8px;
+ text-transform: uppercase;
+ letter-spacing: 1px;
+}
+
+.header-controls {
+ display: flex;
+ align-items: center;
+ gap: 20px;
+}
+
+.signal-meter {
+ display: flex;
+ align-items: flex-end;
+ gap: 2px;
+ height: 20px;
+ padding: 0 10px;
+}
+
+.signal-bar {
+ width: 4px;
+ background: var(--border-color);
+ transition: all 0.1s ease;
+}
+
+.signal-bar:nth-child(1) {
+ height: 4px;
+}
+
+.signal-bar:nth-child(2) {
+ height: 8px;
+}
+
+.signal-bar:nth-child(3) {
+ height: 12px;
+}
+
+.signal-bar:nth-child(4) {
+ height: 16px;
+}
+
+.signal-bar:nth-child(5) {
+ height: 20px;
+}
+
+.signal-bar.active {
+ background: var(--accent-cyan);
+ box-shadow: 0 0 8px var(--accent-cyan);
+}
+
+.waterfall-container {
+ padding: 0 15px;
+ margin-bottom: 10px;
+}
+
+#waterfallCanvas {
+ width: 100%;
+ height: 60px;
+ background: var(--bg-primary);
+ border: 1px solid var(--border-color);
+ transition: box-shadow 0.3s ease;
+}
+
+#waterfallCanvas.active {
+ box-shadow: 0 0 15px var(--accent-cyan-dim);
+ border-color: var(--accent-cyan);
+}
+
+.status-controls {
+ display: flex;
+ gap: 8px;
+ align-items: center;
+}
+
+.control-btn {
+ padding: 6px 12px;
+ background: transparent;
+ border: 1px solid var(--border-color);
+ color: var(--text-secondary);
+ cursor: pointer;
+ font-size: 10px;
+ text-transform: uppercase;
+ letter-spacing: 1px;
+ transition: all 0.2s ease;
+ font-family: 'Rajdhani', sans-serif;
+}
+
+.control-btn:hover {
+ border-color: var(--accent-cyan);
+ color: var(--accent-cyan);
+}
+
+.control-btn.active {
+ border-color: var(--accent-green);
+ color: var(--accent-green);
+}
+
+.control-btn.muted {
+ border-color: var(--accent-red);
+ color: var(--accent-red);
+}
+
+/* Signal Strength Graph */
+.signal-graph-panel {
+ background: var(--bg-card);
+ border: 1px solid var(--border-color);
+ border-radius: 4px;
+ padding: 12px;
+ margin-top: 10px;
+}
+
+.signal-graph-header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ margin-bottom: 10px;
+}
+
+.signal-graph-header h4 {
+ color: var(--accent-cyan);
+ font-size: 11px;
+ text-transform: uppercase;
+ letter-spacing: 1px;
+ margin: 0;
+}
+
+.signal-graph-device {
+ font-size: 10px;
+ color: var(--text-secondary);
+ font-family: 'JetBrains Mono', monospace;
+}
+
+#signalGraph {
+ width: 100%;
+ height: 80px;
+ background: var(--bg-primary);
+ border: 1px solid var(--border-color);
+ border-radius: 3px;
+}
+
+/* Network Relationship Graph */
+.network-graph-container {
+ background: var(--bg-card);
+ border: 1px solid var(--border-color);
+ border-radius: 4px;
+ padding: 12px;
+ margin-top: 10px;
+}
+
+.network-graph-container h4 {
+ color: var(--accent-cyan);
+ font-size: 11px;
+ text-transform: uppercase;
+ letter-spacing: 1px;
+ margin: 0 0 10px 0;
+}
+
+#networkGraph {
+ width: 100%;
+ height: 200px;
+ background: var(--bg-primary);
+ border: 1px solid var(--border-color);
+ border-radius: 3px;
+}
+
+.network-graph-legend {
+ display: flex;
+ gap: 15px;
+ margin-top: 8px;
+ font-size: 10px;
+}
+
+.legend-item {
+ display: flex;
+ align-items: center;
+ gap: 5px;
+ color: var(--text-secondary);
+}
+
+.legend-dot {
+ width: 10px;
+ height: 10px;
+ border-radius: 50%;
+}
+
+.legend-dot.ap {
+ background: var(--accent-cyan);
+}
+
+.legend-dot.client {
+ background: var(--accent-green);
+}
+
+.legend-dot.drone {
+ background: var(--accent-orange);
+}
+
+/* Channel Recommendation */
+.channel-recommendation {
+ background: var(--bg-card);
+ border: 1px solid var(--accent-green);
+ border-radius: 4px;
+ padding: 10px;
+ margin-top: 10px;
+}
+
+.channel-recommendation h4 {
+ color: var(--accent-green);
+ font-size: 11px;
+ text-transform: uppercase;
+ letter-spacing: 1px;
+ margin: 0 0 8px 0;
+}
+
+.channel-recommendation .rec-text {
+ font-size: 12px;
+ color: var(--text-secondary);
+}
+
+.channel-recommendation .rec-channel {
+ font-size: 18px;
+ font-weight: bold;
+ color: var(--accent-green);
+}
+
+/* Device Correlation */
+.correlation-badge {
+ display: inline-block;
+ padding: 2px 6px;
+ background: var(--accent-orange);
+ color: var(--bg-primary);
+ font-size: 9px;
+ border-radius: 3px;
+ margin-left: 5px;
+ font-weight: bold;
+}
+
+/* Hidden SSID reveal */
+.hidden-ssid-revealed {
+ color: var(--accent-orange);
+ font-style: italic;
+}
+
+/* Mode tabs - grouped layout */
+.mode-tabs-container {
+ margin-bottom: 15px;
+}
+
+.tab-group {
+ margin-bottom: 8px;
+}
+
+.tab-group-label {
+ font-size: 9px;
+ color: var(--text-secondary);
+ text-transform: uppercase;
+ letter-spacing: 2px;
+ margin-bottom: 4px;
+ padding-left: 4px;
+ font-family: 'Rajdhani', sans-serif;
+}
+
+.mode-tabs {
+ display: flex;
+ gap: 0;
+ border: 1px solid var(--border-color);
+ border-radius: 4px;
+ overflow: hidden;
+}
+
+.mode-tab {
+ flex: 1;
+ padding: 10px 8px;
+ background: var(--bg-primary);
+ border: none;
+ color: var(--text-secondary);
+ cursor: pointer;
+ font-family: 'Rajdhani', sans-serif;
+ font-size: 10px;
+ font-weight: 600;
+ text-transform: uppercase;
+ letter-spacing: 1px;
+ transition: all 0.2s ease;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ gap: 4px;
+}
+
+.mode-tab .tab-icon {
+ font-size: 16px;
+}
+
+.mode-tab:not(:last-child) {
+ border-right: 1px solid var(--border-color);
+}
+
+.mode-tab:hover {
+ background: var(--bg-secondary);
+ color: var(--text-primary);
+}
+
+.mode-tab.active {
+ background: var(--accent-cyan);
+ color: var(--bg-primary);
+}
+
+.mode-content {
+ display: none;
+}
+
+.mode-content.active {
+ display: block;
+}
+
+/* Aircraft (ADS-B) Styles */
+.aircraft-card {
+ padding: 12px;
+ margin-bottom: 8px;
+ border: 1px solid var(--border-color);
+ border-left: 3px solid var(--accent-cyan);
+ background: var(--bg-secondary);
+ display: grid;
+ grid-template-columns: auto 1fr auto;
+ gap: 12px;
+ align-items: center;
+}
+
+.aircraft-icon {
+ font-size: 28px;
+ transform: rotate(var(--heading, 0deg));
+ transition: transform 0.3s ease;
+}
+
+.aircraft-info {
+ display: grid;
+ grid-template-columns: repeat(auto-fit, minmax(100px, 1fr));
+ gap: 8px;
+}
+
+.aircraft-callsign {
+ color: var(--accent-cyan);
+ font-weight: 600;
+ font-size: 14px;
+}
+
+.aircraft-data {
+ font-size: 11px;
+ color: var(--text-secondary);
+}
+
+.aircraft-data span {
+ color: var(--text-primary);
+}
+
+/* Aircraft Map Display - Leaflet */
+.aircraft-map-container {
+ position: relative;
+ width: 100%;
+ height: 400px;
+ background: #0a0a0a;
+ border: 1px solid var(--accent-cyan);
+ border-radius: 4px;
+ overflow: hidden;
+ box-shadow: 0 0 20px rgba(0, 212, 255, 0.2);
+}
+
+#aircraftMap {
+ width: 100%;
+ height: 100%;
+ background: #0a0a0a;
+}
+
+/* Dark theme for Leaflet */
+.leaflet-container {
+ background: #0a0a0a;
+ font-family: 'JetBrains Mono', monospace;
+}
+
+.leaflet-tile-pane {
+ filter: invert(1) hue-rotate(180deg) brightness(0.8) contrast(1.2);
+}
+
+.leaflet-control-zoom {
+ margin-top: 45px !important;
+}
+
+.leaflet-control-zoom a {
+ background: var(--bg-card) !important;
+ color: var(--accent-cyan) !important;
+ border-color: var(--border-color) !important;
+}
+
+.leaflet-control-zoom a:hover {
+ background: var(--bg-tertiary) !important;
+}
+
+.leaflet-control-attribution {
+ background: rgba(0, 0, 0, 0.7) !important;
+ color: #666 !important;
+ font-size: 9px !important;
+}
+
+.leaflet-control-attribution a {
+ color: #888 !important;
+}
+
+.map-header {
+ position: absolute;
+ top: 8px;
+ left: 10px;
+ right: 10px;
+ display: flex;
+ justify-content: space-between;
+ z-index: 1000;
+ font-family: 'JetBrains Mono', monospace;
+ font-size: 11px;
+ color: var(--accent-cyan);
+ text-shadow: 0 0 5px var(--accent-cyan);
+ background: rgba(0, 0, 0, 0.6);
+ padding: 4px 8px;
+ border-radius: 3px;
+}
+
+.map-footer {
+ position: absolute;
+ bottom: 8px;
+ left: 10px;
+ right: 10px;
+ display: flex;
+ justify-content: space-between;
+ z-index: 1000;
+ font-family: 'JetBrains Mono', monospace;
+ font-size: 10px;
+ color: var(--accent-cyan);
+ text-shadow: 0 0 5px var(--accent-cyan);
+ background: rgba(0, 0, 0, 0.6);
+ padding: 4px 8px;
+ border-radius: 3px;
+}
+
+/* Aircraft marker styles */
+.aircraft-marker {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+}
+
+.aircraft-marker svg {
+ filter: drop-shadow(0 0 4px currentColor);
+}
+
+.aircraft-popup {
+ font-family: 'JetBrains Mono', monospace;
+ font-size: 11px;
+}
+
+.aircraft-popup .callsign {
+ color: var(--accent-cyan);
+ font-weight: bold;
+ font-size: 13px;
+}
+
+.aircraft-popup .data-row {
+ display: flex;
+ justify-content: space-between;
+ margin: 3px 0;
+}
+
+.aircraft-popup .label {
+ color: #888;
+}
+
+.aircraft-popup .value {
+ color: #fff;
+}
+
+.leaflet-popup-content-wrapper {
+ background: var(--bg-card) !important;
+ border: 1px solid var(--border-color) !important;
+ border-radius: 4px !important;
+}
+
+.leaflet-popup-tip {
+ background: var(--bg-card) !important;
+ border: 1px solid var(--border-color) !important;
+}
+
+.leaflet-popup-content {
+ color: var(--text-primary) !important;
+ margin: 10px !important;
+}
+
+.leaflet-tooltip.aircraft-tooltip {
+ background: rgba(0, 0, 0, 0.8) !important;
+ border: 1px solid var(--accent-cyan) !important;
+ color: var(--accent-cyan) !important;
+ font-family: 'JetBrains Mono', monospace !important;
+ font-size: 10px !important;
+ padding: 2px 6px !important;
+ border-radius: 2px !important;
+}
+
+.leaflet-tooltip.aircraft-tooltip::before {
+ border-right-color: var(--accent-cyan) !important;
+}
+
+/* Satellite Mode Styles */
+.satellite-section {
+ margin-bottom: 20px;
+}
+
+.satellite-tabs {
+ display: flex;
+ gap: 4px;
+ margin-bottom: 15px;
+}
+
+.satellite-tab {
+ padding: 8px 16px;
+ background: var(--bg-secondary);
+ border: 1px solid var(--border-color);
+ border-radius: 4px;
+ color: var(--text-secondary);
+ cursor: pointer;
+ font-family: 'Rajdhani', sans-serif;
+ font-size: 11px;
+ text-transform: uppercase;
+ transition: all 0.2s ease;
+}
+
+.satellite-tab:hover {
+ border-color: var(--accent-cyan);
+ color: var(--text-primary);
+}
+
+.satellite-tab.active {
+ background: var(--accent-cyan);
+ border-color: var(--accent-cyan);
+ color: var(--bg-primary);
+}
+
+.satellite-content {
+ display: none;
+}
+
+.satellite-content.active {
+ display: block;
+}
+
+/* Satellite Pass Predictor - Cool UI */
+.pass-predictor {
+ display: grid;
+ grid-template-columns: 1fr 1fr;
+ grid-template-rows: auto auto;
+ gap: 15px;
+}
+
+@media (max-width: 1100px) {
+ .pass-predictor {
+ grid-template-columns: 1fr;
+ }
+}
+
+.polar-plot-container {
+ position: relative;
+ background: var(--bg-secondary);
+ border: 1px solid var(--border-color);
+ border-radius: 8px;
+ padding: 15px;
+ min-height: 320px;
+}
+
+.ground-track-cell {
+ background: var(--bg-secondary);
+ border: 1px solid var(--border-color);
+ border-radius: 8px;
+ padding: 15px;
+ min-height: 320px;
+ display: flex;
+ flex-direction: column;
+}
+
+.ground-track-cell #groundTrackMap {
+ flex: 1;
+ min-height: 200px;
+}
+
+.countdown-cell {
+ background: var(--bg-secondary);
+ border: 1px solid var(--border-color);
+ border-radius: 8px;
+ padding: 15px;
+}
+
+.countdown-cell .satellite-countdown {
+ margin: 0;
+ padding: 0;
+ border: none;
+ background: none;
+}
+
+.pass-list-cell {
+ background: var(--bg-secondary);
+ border: 1px solid var(--border-color);
+ border-radius: 8px;
+ padding: 15px;
+ max-height: 350px;
+ overflow-y: auto;
+}
+
+.polar-plot-header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ margin-bottom: 10px;
+}
+
+.polar-plot-title {
+ color: var(--accent-cyan);
+ font-size: 12px;
+ text-transform: uppercase;
+ letter-spacing: 1px;
+}
+
+.popout-btn {
+ padding: 4px 10px;
+ background: transparent;
+ border: 1px solid var(--accent-cyan);
+ border-radius: 3px;
+ color: var(--accent-cyan);
+ font-size: 10px;
+ cursor: pointer;
+ transition: all 0.2s ease;
+}
+
+.popout-btn:hover {
+ background: var(--accent-cyan);
+ color: var(--bg-primary);
+}
+
+.polar-plot {
+ position: relative;
+ width: 100%;
+ padding-bottom: 100%;
+}
+
+.polar-plot canvas {
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+}
+
+.pass-list-container {
+ background: var(--bg-secondary);
+ border: 1px solid var(--border-color);
+ border-radius: 8px;
+ padding: 15px;
+ max-height: 450px;
+ overflow-y: auto;
+}
+
+.pass-list-header {
+ color: var(--accent-cyan);
+ font-size: 12px;
+ text-transform: uppercase;
+ letter-spacing: 1px;
+ margin-bottom: 10px;
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+}
+
+/* Satellite Countdown Block */
+.satellite-countdown {
+ background: linear-gradient(135deg, var(--bg-tertiary) 0%, var(--bg-secondary) 100%);
+ border: 1px solid var(--accent-cyan);
+ border-radius: 8px;
+ padding: 15px;
+ margin-bottom: 15px;
+ box-shadow: 0 0 20px rgba(0, 212, 255, 0.1);
+}
+
+.countdown-satellite-name {
+ color: var(--accent-cyan);
+ font-size: 14px;
+ font-weight: 600;
+ text-transform: uppercase;
+ letter-spacing: 2px;
+ text-align: center;
+ margin-bottom: 12px;
+ text-shadow: 0 0 10px var(--accent-cyan-dim);
+}
+
+.countdown-grid {
+ display: grid;
+ grid-template-columns: repeat(3, 1fr);
+ gap: 10px;
+ margin-bottom: 10px;
+}
+
+.countdown-block {
+ background: var(--bg-primary);
+ border: 1px solid var(--border-color);
+ border-radius: 6px;
+ padding: 10px;
+ text-align: center;
+}
+
+.countdown-label {
+ color: var(--text-dim);
+ font-size: 9px;
+ text-transform: uppercase;
+ letter-spacing: 1px;
+ margin-bottom: 5px;
+}
+
+.countdown-value {
+ color: var(--accent-cyan);
+ font-size: 22px;
+ font-weight: 700;
+ font-family: 'JetBrains Mono', monospace;
+ text-shadow: 0 0 15px var(--accent-cyan-dim);
+ line-height: 1.2;
+}
+
+.countdown-value.active {
+ color: var(--accent-green);
+ text-shadow: 0 0 15px rgba(0, 255, 136, 0.4);
+ animation: countdown-pulse 1s ease-in-out infinite;
+}
+
+@keyframes countdown-pulse {
+
+ 0%,
+ 100% {
+ opacity: 1;
+ }
+
+ 50% {
+ opacity: 0.7;
+ }
+}
+
+.countdown-sublabel {
+ color: var(--text-secondary);
+ font-size: 9px;
+ margin-top: 4px;
+}
+
+.countdown-status {
+ text-align: center;
+ font-size: 10px;
+ color: var(--text-dim);
+ padding-top: 8px;
+ border-top: 1px solid var(--border-color);
+}
+
+.countdown-status.visible {
+ color: var(--accent-green);
+}
+
+.countdown-status.upcoming {
+ color: var(--accent-orange);
+}
+
+.location-input {
+ display: flex;
+ gap: 8px;
+ margin-bottom: 15px;
+}
+
+.location-input input {
+ flex: 1;
+ padding: 8px;
+ background: var(--bg-primary);
+ border: 1px solid var(--border-color);
+ border-radius: 3px;
+ color: var(--text-primary);
+ font-size: 12px;
+}
+
+.pass-card {
+ padding: 12px;
+ margin-bottom: 8px;
+ background: var(--bg-primary);
+ border: 1px solid var(--border-color);
+ border-radius: 4px;
+ cursor: pointer;
+ transition: all 0.2s ease;
+}
+
+.pass-card:hover {
+ border-color: var(--accent-cyan);
+}
+
+.pass-card.active {
+ border-color: var(--accent-cyan);
+ box-shadow: 0 0 10px rgba(0, 255, 255, 0.2);
+}
+
+.pass-satellite {
+ color: var(--accent-cyan);
+ font-weight: 600;
+ margin-bottom: 4px;
+}
+
+.pass-time {
+ color: var(--text-primary);
+ font-size: 13px;
+ margin-bottom: 4px;
+}
+
+.pass-details {
+ display: flex;
+ gap: 15px;
+ font-size: 11px;
+ color: var(--text-secondary);
+}
+
+.pass-details span {
+ color: var(--text-primary);
+}
+
+.pass-quality {
+ display: inline-block;
+ padding: 2px 8px;
+ border-radius: 10px;
+ font-size: 10px;
+ font-weight: 600;
+}
+
+.pass-quality.excellent {
+ background: rgba(0, 255, 0, 0.2);
+ color: var(--accent-green);
+}
+
+.pass-quality.good {
+ background: rgba(0, 255, 255, 0.2);
+ color: var(--accent-cyan);
+}
+
+.pass-quality.fair {
+ background: rgba(255, 102, 0, 0.2);
+ color: var(--accent-orange);
+}
+
+/* Satellite List Styles */
+.satellite-list {
+ max-height: 200px;
+ overflow-y: auto;
+ background: var(--bg-primary);
+ border: 1px solid var(--border-color);
+ border-radius: 4px;
+ padding: 8px;
+}
+
+.sat-item {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ padding: 6px 8px;
+ margin-bottom: 4px;
+ background: var(--bg-secondary);
+ border-radius: 3px;
+ font-size: 12px;
+}
+
+.sat-item:last-child {
+ margin-bottom: 0;
+}
+
+.sat-item label {
+ display: flex;
+ align-items: center;
+ gap: 8px;
+ cursor: pointer;
+ flex: 1;
+}
+
+.sat-item input[type="checkbox"] {
+ margin: 0;
+}
+
+.sat-item .sat-name {
+ color: var(--text-primary);
+}
+
+.sat-item .sat-norad {
+ color: var(--text-secondary);
+ font-size: 10px;
+}
+
+.sat-item .sat-remove {
+ background: none;
+ border: none;
+ color: var(--accent-red);
+ cursor: pointer;
+ font-size: 14px;
+ padding: 2px 6px;
+ opacity: 0.6;
+}
+
+.sat-item .sat-remove:hover {
+ opacity: 1;
+}
+
+.sat-item.builtin .sat-remove {
+ display: none;
+}
+
+/* Satellite Add Modal */
+.sat-modal {
+ position: fixed;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ background: rgba(0, 0, 0, 0.8);
+ display: none;
+ justify-content: center;
+ align-items: center;
+ z-index: 10000;
+}
+
+.sat-modal.active {
+ display: flex;
+}
+
+.sat-modal-content {
+ background: var(--bg-secondary);
+ border: 1px solid var(--accent-cyan);
+ border-radius: 8px;
+ padding: 20px;
+ width: 90%;
+ max-width: 500px;
+ max-height: 80vh;
+ overflow-y: auto;
+}
+
+.sat-modal-header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ margin-bottom: 15px;
+ padding-bottom: 10px;
+ border-bottom: 1px solid var(--border-color);
+}
+
+.sat-modal-header h3 {
+ color: var(--accent-cyan);
+ margin: 0;
+}
+
+.sat-modal-close {
+ background: none;
+ border: none;
+ color: var(--text-secondary);
+ font-size: 24px;
+ cursor: pointer;
+}
+
+.sat-modal-close:hover {
+ color: var(--text-primary);
+}
+
+.sat-modal-tabs {
+ display: flex;
+ gap: 10px;
+ margin-bottom: 15px;
+}
+
+.sat-modal-tab {
+ flex: 1;
+ padding: 8px;
+ background: var(--bg-primary);
+ border: 1px solid var(--border-color);
+ border-radius: 4px;
+ color: var(--text-secondary);
+ cursor: pointer;
+ font-size: 12px;
+}
+
+.sat-modal-tab.active {
+ border-color: var(--accent-cyan);
+ color: var(--accent-cyan);
+}
+
+.sat-modal-section {
+ display: none;
+}
+
+.sat-modal-section.active {
+ display: block;
+}
+
+.tle-textarea {
+ width: 100%;
+ height: 120px;
+ background: var(--bg-primary);
+ border: 1px solid var(--border-color);
+ border-radius: 4px;
+ color: var(--text-primary);
+ font-family: monospace;
+ font-size: 11px;
+ padding: 10px;
+ resize: vertical;
+}
+
+.celestrak-categories {
+ display: grid;
+ grid-template-columns: repeat(2, 1fr);
+ gap: 8px;
+ max-height: 200px;
+ overflow-y: auto;
+}
+
+.celestrak-cat {
+ padding: 8px 12px;
+ background: var(--bg-primary);
+ border: 1px solid var(--border-color);
+ border-radius: 4px;
+ color: var(--text-secondary);
+ cursor: pointer;
+ font-size: 11px;
+ text-align: center;
+}
+
+.celestrak-cat:hover {
+ border-color: var(--accent-cyan);
+ color: var(--accent-cyan);
+}
+
+/* Iridium Burst Styles */
+.iridium-warning {
+ padding: 12px;
+ margin-bottom: 15px;
+ background: rgba(255, 102, 0, 0.1);
+ border: 1px solid var(--accent-orange);
+ border-radius: 4px;
+ color: var(--accent-orange);
+ font-size: 12px;
+}
+
+.iridium-warning strong {
+ display: block;
+ margin-bottom: 4px;
+}
+
+.burst-card {
+ padding: 10px;
+ margin-bottom: 6px;
+ background: var(--bg-secondary);
+ border: 1px solid var(--border-color);
+ border-left: 3px solid #9370DB;
+ font-family: monospace;
+ font-size: 11px;
+}
+
+.burst-time {
+ color: var(--text-secondary);
+}
+
+.burst-freq {
+ color: #9370DB;
+ font-weight: 600;
+}
+
+.burst-data {
+ color: var(--text-primary);
+ word-break: break-all;
+}
+
+/* Popout window styles */
+.popout-container {
+ position: fixed;
+ top: 0;
+ left: 0;
+ width: 100vw;
+ height: 100vh;
+ background: var(--bg-primary);
+ z-index: 10000;
+ display: none;
+}
+
+.popout-container.active {
+ display: block;
+}
+
+.popout-header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 15px 20px;
+ background: var(--bg-secondary);
+ border-bottom: 1px solid var(--border-color);
+}
+
+.popout-title {
+ color: var(--accent-cyan);
+ font-size: 18px;
+ font-weight: 600;
+}
+
+.popout-close {
+ padding: 8px 16px;
+ background: transparent;
+ border: 1px solid var(--accent-red);
+ border-radius: 3px;
+ color: var(--accent-red);
+ cursor: pointer;
+}
+
+.popout-body {
+ padding: 20px;
+ height: calc(100vh - 70px);
+ overflow: auto;
+}
+
+/* Sensor card styling */
+.sensor-card {
+ padding: 15px;
+ margin-bottom: 10px;
+ border: 1px solid var(--border-color);
+ border-left: 3px solid var(--accent-green);
+ background: var(--bg-secondary);
+}
+
+.sensor-card .device-name {
+ color: var(--accent-green);
+ font-weight: 600;
+ font-size: 13px;
+ margin-bottom: 8px;
+}
+
+.sensor-card .sensor-data {
+ display: grid;
+ grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
+ gap: 8px;
+}
+
+.sensor-card .data-item {
+ background: var(--bg-primary);
+ padding: 8px 10px;
+ border: 1px solid var(--border-color);
+}
+
+.sensor-card .data-label {
+ font-size: 9px;
+ color: var(--text-dim);
+ text-transform: uppercase;
+ letter-spacing: 1px;
+}
+
+.sensor-card .data-value {
+ font-family: 'JetBrains Mono', monospace;
+ font-size: 14px;
+ color: var(--accent-cyan);
+}
+
+/* Recon Dashboard - Prominent Device Intelligence */
+.recon-panel {
+ background: var(--bg-card);
+ border: 1px solid var(--border-color);
+ margin: 15px;
+ margin-bottom: 10px;
+ position: relative;
+}
+
+.recon-panel::before {
+ content: '';
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ height: 2px;
+ background: linear-gradient(90deg, var(--accent-orange), var(--accent-cyan), transparent);
+}
+
+.recon-panel.collapsed .recon-content {
+ display: none;
+}
+
+.recon-header {
+ padding: 12px 15px;
+ background: var(--bg-secondary);
+ border-bottom: 1px solid var(--border-color);
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+}
+
+.recon-header h4 {
+ color: var(--accent-orange);
+ font-size: 11px;
+ font-weight: 600;
+ text-transform: uppercase;
+ letter-spacing: 2px;
+ margin: 0;
+}
+
+.recon-stats {
+ display: flex;
+ gap: 15px;
+ font-size: 10px;
+ font-family: 'JetBrains Mono', monospace;
+}
+
+.recon-stats span {
+ color: var(--accent-cyan);
+}
+
+.recon-content {
+ max-height: 300px;
+ overflow-y: auto;
+}
+
+.device-row {
+ display: grid;
+ grid-template-columns: 1fr auto auto auto;
+ gap: 10px;
+ padding: 10px 15px;
+ border-bottom: 1px solid var(--border-color);
+ font-size: 11px;
+ align-items: center;
+ transition: background 0.2s ease;
+}
+
+.device-row:hover {
+ background: var(--bg-secondary);
+}
+
+.device-row.anomaly {
+ border-left: 3px solid var(--accent-red);
+ background: rgba(255, 51, 102, 0.05);
+}
+
+.device-row.new-device {
+ border-left: 3px solid var(--accent-green);
+ background: rgba(0, 255, 136, 0.05);
+}
+
+.device-info {
+ display: flex;
+ flex-direction: column;
+ gap: 2px;
+}
+
+.device-name-row {
+ color: var(--text-primary);
+ font-weight: 500;
+}
+
+.device-id {
+ color: var(--text-dim);
+ font-family: 'JetBrains Mono', monospace;
+ font-size: 10px;
+}
+
+.device-meta {
+ text-align: right;
+ color: var(--text-secondary);
+ font-family: 'JetBrains Mono', monospace;
+}
+
+.device-meta.encrypted {
+ color: var(--accent-green);
+}
+
+.device-meta.plaintext {
+ color: var(--accent-red);
+}
+
+.transmission-bar {
+ width: 60px;
+ height: 4px;
+ background: var(--border-color);
+ position: relative;
+}
+
+.transmission-bar-fill {
+ height: 100%;
+ background: var(--accent-cyan);
+ transition: width 0.3s ease;
+}
+
+.badge {
+ display: inline-block;
+ padding: 2px 6px;
+ font-size: 9px;
+ text-transform: uppercase;
+ letter-spacing: 1px;
+ border: 1px solid;
+}
+
+.badge.proto-pocsag {
+ border-color: var(--accent-cyan);
+ color: var(--accent-cyan);
+}
+
+.badge.proto-flex {
+ border-color: var(--accent-orange);
+ color: var(--accent-orange);
+}
+
+.badge.proto-433 {
+ border-color: var(--accent-green);
+ color: var(--accent-green);
+}
+
+.badge.proto-unknown {
+ border-color: var(--text-dim);
+ color: var(--text-dim);
+}
+
+.recon-toggle {
+ padding: 4px 8px;
+ background: transparent;
+ border: 1px solid var(--border-color);
+ color: var(--text-secondary);
+ cursor: pointer;
+ font-size: 9px;
+ text-transform: uppercase;
+ letter-spacing: 1px;
+}
+
+.recon-toggle:hover {
+ border-color: var(--accent-orange);
+ color: var(--accent-orange);
+}
+
+.recon-toggle.active {
+ border-color: var(--accent-orange);
+ color: var(--accent-orange);
+ background: rgba(255, 136, 0, 0.1);
+}
+
+.hex-dump {
+ font-family: 'JetBrains Mono', monospace;
+ font-size: 10px;
+ color: var(--text-dim);
+ background: var(--bg-primary);
+ padding: 8px;
+ margin-top: 8px;
+ border: 1px solid var(--border-color);
+ word-break: break-all;
+}
+
+.timeline-dot {
+ width: 8px;
+ height: 8px;
+ border-radius: 50%;
+ background: var(--accent-cyan);
+ display: inline-block;
+ margin-right: 5px;
+}
+
+.timeline-dot.recent {
+ background: var(--accent-green);
+}
+
+.timeline-dot.stale {
+ background: var(--accent-orange);
+}
+
+.timeline-dot.old {
+ background: var(--text-dim);
+}
+
+/* WiFi Visualizations */
+.wifi-visuals {
+ display: grid;
+ grid-template-columns: 1fr 1fr;
+ gap: 10px;
+ padding: 15px;
+ background: var(--bg-secondary);
+ margin: 0 15px 10px 15px;
+ border: 1px solid var(--border-color);
+}
+
+@media (max-width: 1200px) {
+ .wifi-visuals {
+ grid-template-columns: 1fr;
+ }
+}
+
+.wifi-visual-panel {
+ background: var(--bg-primary);
+ border: 1px solid var(--border-color);
+ padding: 10px;
+ position: relative;
+}
+
+.wifi-visual-panel h5 {
+ color: var(--accent-cyan);
+ font-size: 10px;
+ text-transform: uppercase;
+ letter-spacing: 1px;
+ margin-bottom: 10px;
+ padding-bottom: 5px;
+ border-bottom: 1px solid var(--border-color);
+}
+
+/* Radar Display */
+.radar-container {
+ position: relative;
+ width: 150px;
+ height: 150px;
+ margin: 0 auto;
+}
+
+#radarCanvas,
+#btRadarCanvas {
+ width: 100%;
+ height: 100%;
+ border-radius: 50%;
+ background: radial-gradient(circle, #001515 0%, #000a0a 100%);
+ border: 1px solid var(--accent-cyan-dim);
+}
+
+#btRadarCanvas {
+ background: radial-gradient(circle, #150015 0%, #0a000a 100%);
+ border: 1px solid rgba(138, 43, 226, 0.3);
+}
+
+/* Channel Graph */
+.channel-graph {
+ display: flex;
+ align-items: flex-end;
+ justify-content: space-around;
+ height: 60px;
+ padding: 5px 0;
+ border-bottom: 1px solid var(--border-color);
+}
+
+.channel-bar-wrapper {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ flex: 1;
+}
+
+.channel-bar {
+ width: 80%;
+ background: var(--border-color);
+ min-height: 2px;
+ transition: height 0.3s ease, background 0.3s ease;
+}
+
+.channel-bar.active {
+ background: var(--accent-cyan);
+ box-shadow: 0 0 5px var(--accent-cyan);
+}
+
+.channel-bar.congested {
+ background: var(--accent-orange);
+}
+
+.channel-bar.very-congested {
+ background: var(--accent-red);
+}
+
+.channel-label {
+ font-size: 8px;
+ color: #fff;
+ margin-top: 3px;
+}
+
+/* Security Donut */
+.security-container {
+ display: flex;
+ align-items: center;
+ gap: 15px;
+}
+
+.security-donut {
+ width: 80px;
+ height: 80px;
+ flex-shrink: 0;
+}
+
+#securityCanvas {
+ width: 100%;
+ height: 100%;
+}
+
+.security-legend {
+ display: flex;
+ flex-direction: column;
+ gap: 4px;
+ font-size: 10px;
+ font-family: 'JetBrains Mono', monospace;
+}
+
+.security-legend-item {
+ display: flex;
+ align-items: center;
+ gap: 6px;
+}
+
+.security-legend-dot {
+ width: 10px;
+ height: 10px;
+ border-radius: 2px;
+}
+
+.security-legend-dot.wpa3 {
+ background: var(--accent-green);
+}
+
+.security-legend-dot.wpa2 {
+ background: var(--accent-orange);
+}
+
+.security-legend-dot.wep {
+ background: var(--accent-red);
+}
+
+.security-legend-dot.open {
+ background: var(--accent-cyan);
+}
+
+/* Signal Strength Meter */
+.signal-strength-display {
+ text-align: center;
+ padding: 5px;
+}
+
+.target-ssid {
+ font-size: 11px;
+ color: var(--text-secondary);
+ margin-bottom: 5px;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
+
+.signal-value {
+ font-family: 'JetBrains Mono', monospace;
+ font-size: 28px;
+ color: var(--accent-cyan);
+ text-shadow: 0 0 10px var(--accent-cyan-dim);
+}
+
+.signal-value.weak {
+ color: var(--accent-red);
+ text-shadow: 0 0 10px rgba(255, 51, 102, 0.4);
+}
+
+.signal-value.medium {
+ color: var(--accent-orange);
+ text-shadow: 0 0 10px rgba(255, 136, 0, 0.4);
+}
+
+.signal-value.strong {
+ color: var(--accent-green);
+ text-shadow: 0 0 10px rgba(0, 255, 136, 0.4);
+}
+
+.signal-bars-large {
+ display: flex;
+ justify-content: center;
+ align-items: flex-end;
+ gap: 3px;
+ height: 30px;
+ margin-top: 8px;
+}
+
+.signal-bar-large {
+ width: 8px;
+ background: var(--border-color);
+ transition: all 0.2s ease;
+}
+
+.signal-bar-large.active {
+ box-shadow: 0 0 5px currentColor;
+}
+
+.signal-bar-large.weak {
+ background: var(--accent-red);
+}
+
+.signal-bar-large.medium {
+ background: var(--accent-orange);
+}
+
+.signal-bar-large.strong {
+ background: var(--accent-green);
+}
+
+.signal-bar-large:nth-child(1) {
+ height: 20%;
+}
+
+.signal-bar-large:nth-child(2) {
+ height: 40%;
+}
+
+.signal-bar-large:nth-child(3) {
+ height: 60%;
+}
+
+.signal-bar-large:nth-child(4) {
+ height: 80%;
+}
+
+.signal-bar-large:nth-child(5) {
+ height: 100%;
+}
+
+/* Scanline effect overlay */
+body::before {
+ content: '';
+ position: fixed;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ pointer-events: none;
+ background: repeating-linear-gradient(0deg,
+ rgba(0, 0, 0, 0.03),
+ rgba(0, 0, 0, 0.03) 1px,
+ transparent 1px,
+ transparent 2px);
+ z-index: 1000;
+}
+
+/* Disclaimer Modal */
+.disclaimer-overlay {
+ position: fixed;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ background: rgba(0, 0, 0, 0.95);
+ z-index: 9999;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+}
+
+.disclaimer-modal {
+ background: var(--bg-card);
+ border: 1px solid var(--accent-cyan);
+ max-width: 550px;
+ padding: 30px;
+ text-align: center;
+ box-shadow: 0 0 50px rgba(0, 212, 255, 0.3);
+}
+
+.disclaimer-modal h2 {
+ color: var(--accent-red);
+ font-size: 1.5em;
+ margin-bottom: 20px;
+ letter-spacing: 3px;
+}
+
+.disclaimer-modal .warning-icon {
+ font-size: 48px;
+ margin-bottom: 15px;
+}
+
+.disclaimer-modal p {
+ color: var(--text-secondary);
+ font-size: 13px;
+ line-height: 1.8;
+ margin-bottom: 15px;
+ text-align: left;
+}
+
+.disclaimer-modal ul {
+ text-align: left;
+ color: var(--text-secondary);
+ font-size: 12px;
+ margin: 15px 0;
+ padding-left: 20px;
+}
+
+.disclaimer-modal ul li {
+ margin-bottom: 8px;
+}
+
+.disclaimer-modal .accept-btn {
+ background: var(--accent-cyan);
+ color: #000;
+ border: none;
+ padding: 12px 40px;
+ font-family: 'Rajdhani', sans-serif;
+ font-size: 14px;
+ font-weight: 600;
+ letter-spacing: 2px;
+ cursor: pointer;
+ margin-top: 20px;
+ transition: all 0.3s ease;
+}
+
+.disclaimer-modal .accept-btn:hover {
+ background: #fff;
+ box-shadow: 0 0 20px rgba(0, 212, 255, 0.5);
+}
+
+.disclaimer-hidden {
+ display: none !important;
+}
+
+/* Ground Track Map */
+#groundTrackMap {
+ height: 240px;
+ border-radius: 6px;
+ margin-top: 10px;
+}
+
+.ground-track-header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ margin-bottom: 5px;
+}
+
+.ground-track-title {
+ font-size: 14px;
+ font-weight: 600;
+ color: var(--accent-cyan);
+}
+
+.sat-position-indicator {
+ position: absolute;
+ width: 12px;
+ height: 12px;
+ background: #ff0;
+ border: 2px solid #000;
+ border-radius: 50%;
+ transform: translate(-50%, -50%);
+ z-index: 100;
+ animation: pulse-sat 1s infinite;
+}
+
+@keyframes pulse-sat {
+
+ 0%,
+ 100% {
+ box-shadow: 0 0 0 0 rgba(255, 255, 0, 0.7);
+ }
+
+ 50% {
+ box-shadow: 0 0 0 8px rgba(255, 255, 0, 0);
+ }
+}
+
+/* Beacon Flood Alert */
+.beacon-flood-alert {
+ background: linear-gradient(135deg, rgba(255, 0, 0, 0.2), rgba(255, 100, 0, 0.2));
+ border: 1px solid #ff4444;
+ border-radius: 6px;
+ padding: 10px;
+ margin: 10px 0;
+ animation: beacon-flash 0.5s infinite alternate;
+}
+
+@keyframes beacon-flash {
+ from {
+ opacity: 0.8;
+ }
+
+ to {
+ opacity: 1;
+ }
+}
+
+/* WPS Indicator */
+.wps-enabled {
+ background: #ff6600;
+ color: #000;
+ padding: 2px 6px;
+ border-radius: 3px;
+ font-size: 9px;
+ font-weight: bold;
+ margin-left: 5px;
+}
+
+/* PMKID Capture */
+.pmkid-btn {
+ background: linear-gradient(135deg, #9933ff, #6600cc);
+ color: #fff;
+}
+
+.pmkid-btn:hover {
+ background: linear-gradient(135deg, #aa44ff, #7700dd);
+}
+
+/* Find My Detection */
+.findmy-device {
+ border-left: 3px solid #007aff;
+ background: rgba(0, 122, 255, 0.1);
+}
+
+.findmy-badge {
+ background: linear-gradient(135deg, #007aff, #5856d6);
+ color: #fff;
+ padding: 2px 8px;
+ border-radius: 10px;
+ font-size: 10px;
+ font-weight: bold;
+}
+
+/* Tracker Following Alert */
+.tracker-following-alert {
+ background: linear-gradient(135deg, rgba(255, 0, 0, 0.3), rgba(255, 50, 50, 0.2));
+ border: 2px solid #ff0000;
+ border-radius: 8px;
+ padding: 15px;
+ margin: 10px 0;
+ animation: tracker-pulse 1s infinite;
+}
+
+@keyframes tracker-pulse {
+
+ 0%,
+ 100% {
+ border-color: #ff0000;
+ }
+
+ 50% {
+ border-color: #ff6666;
+ }
+}
+
+.tracker-following-alert h4 {
+ color: #ff4444;
+ margin: 0 0 10px 0;
+ display: flex;
+ align-items: center;
+ gap: 8px;
+}
+
+/* Flight Path Trails */
+.flight-trail {
+ stroke-dasharray: 5, 5;
+ fill: none;
+}
+
+/* Squawk Alerts */
+.squawk-emergency {
+ background: #ff0000 !important;
+ animation: squawk-flash 0.3s infinite alternate;
+}
+
+.squawk-hijack {
+ background: #ff0000 !important;
+}
+
+.squawk-radio-fail {
+ background: #ff6600 !important;
+}
+
+.squawk-mayday {
+ background: #ff0000 !important;
+}
+
+@keyframes squawk-flash {
+ from {
+ opacity: 0.7;
+ }
+
+ to {
+ opacity: 1;
+ }
+}
+
+.squawk-alert-banner {
+ position: fixed;
+ top: 60px;
+ left: 50%;
+ transform: translateX(-50%);
+ background: #ff0000;
+ color: #fff;
+ padding: 15px 30px;
+ border-radius: 8px;
+ font-weight: bold;
+ z-index: 9999;
+ animation: squawk-banner-flash 0.5s infinite alternate;
+}
+
+@keyframes squawk-banner-flash {
+ from {
+ background: #ff0000;
+ }
+
+ to {
+ background: #cc0000;
+ }
+}
+
+@keyframes slideDown {
+ from {
+ opacity: 0;
+ transform: translateX(-50%) translateY(-20px);
+ }
+
+ to {
+ opacity: 1;
+ transform: translateX(-50%) translateY(0);
+ }
+}
+
+@keyframes fadeOut {
+ from {
+ opacity: 1;
+ }
+
+ to {
+ opacity: 0;
+ }
+}
+
+/* Military Aircraft */
+.military-aircraft {
+ border-left: 3px solid #556b2f;
+ background: rgba(85, 107, 47, 0.2);
+}
+
+.military-badge {
+ background: #556b2f;
+ color: #fff;
+ padding: 2px 6px;
+ border-radius: 3px;
+ font-size: 9px;
+ font-weight: bold;
+}
+
+/* Map Clustering */
+.marker-cluster {
+ background: rgba(0, 212, 255, 0.6);
+ border-radius: 50%;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ font-weight: bold;
+ color: #000;
+ border: 2px solid var(--accent-cyan);
+}
+
+.marker-cluster-small {
+ width: 30px;
+ height: 30px;
+ font-size: 12px;
+}
+
+.marker-cluster-medium {
+ width: 40px;
+ height: 40px;
+ font-size: 14px;
+}
+
+.marker-cluster-large {
+ width: 50px;
+ height: 50px;
+ font-size: 16px;
+}
\ No newline at end of file
diff --git a/static/css/satellite_dashboard.css b/static/css/satellite_dashboard.css
new file mode 100644
index 0000000..be6cc7d
--- /dev/null
+++ b/static/css/satellite_dashboard.css
@@ -0,0 +1,687 @@
+* {
+ margin: 0;
+ padding: 0;
+ box-sizing: border-box;
+}
+
+:root {
+ --bg-dark: #0a0a0f;
+ --bg-panel: #0d1117;
+ --bg-card: #161b22;
+ --border-glow: #00d4ff;
+ --text-primary: #e6edf3;
+ --text-secondary: #8b949e;
+ --accent-cyan: #00d4ff;
+ --accent-green: #00ff88;
+ --accent-orange: #ff9500;
+ --accent-red: #ff4444;
+ --accent-purple: #a855f7;
+ --grid-line: rgba(0, 212, 255, 0.1);
+}
+
+body {
+ font-family: 'Rajdhani', sans-serif;
+ background: var(--bg-dark);
+ color: var(--text-primary);
+ min-height: 100vh;
+ overflow-x: hidden;
+}
+
+/* Animated grid background */
+.grid-bg {
+ position: fixed;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ background-image:
+ linear-gradient(var(--grid-line) 1px, transparent 1px),
+ linear-gradient(90deg, var(--grid-line) 1px, transparent 1px);
+ background-size: 50px 50px;
+ animation: gridMove 20s linear infinite;
+ pointer-events: none;
+ z-index: 0;
+}
+
+@keyframes gridMove {
+ 0% {
+ transform: translate(0, 0);
+ }
+
+ 100% {
+ transform: translate(50px, 50px);
+ }
+}
+
+/* Scan line effect */
+.scanline {
+ position: fixed;
+ top: 0;
+ left: 0;
+ right: 0;
+ height: 4px;
+ background: linear-gradient(90deg, transparent, var(--accent-cyan), transparent);
+ animation: scan 3s linear infinite;
+ pointer-events: none;
+ z-index: 1000;
+ opacity: 0.5;
+}
+
+@keyframes scan {
+ 0% {
+ top: -4px;
+ }
+
+ 100% {
+ top: 100vh;
+ }
+}
+
+/* Header */
+.header {
+ position: relative;
+ z-index: 10;
+ padding: 12px 20px;
+ background: linear-gradient(180deg, rgba(0, 212, 255, 0.1) 0%, transparent 100%);
+ border-bottom: 1px solid rgba(0, 212, 255, 0.3);
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+}
+
+.logo {
+ font-family: 'Orbitron', monospace;
+ font-size: 24px;
+ font-weight: 900;
+ letter-spacing: 4px;
+ color: var(--accent-cyan);
+ text-shadow: 0 0 20px var(--accent-cyan), 0 0 40px var(--accent-cyan);
+}
+
+.logo span {
+ color: var(--text-secondary);
+ font-weight: 400;
+ font-size: 14px;
+ margin-left: 15px;
+ letter-spacing: 2px;
+}
+
+/* Stats badges in header */
+.stats-badges {
+ display: flex;
+ gap: 12px;
+}
+
+.stat-badge {
+ background: rgba(0, 212, 255, 0.1);
+ border: 1px solid rgba(0, 212, 255, 0.3);
+ border-radius: 4px;
+ padding: 4px 10px;
+ font-family: 'JetBrains Mono', monospace;
+ font-size: 11px;
+}
+
+.stat-badge .value {
+ color: var(--accent-cyan);
+ font-weight: 600;
+}
+
+.stat-badge .value.highlight {
+ color: var(--accent-green);
+}
+
+.stat-badge .label {
+ color: var(--text-secondary);
+ margin-left: 4px;
+}
+
+.status-bar {
+ display: flex;
+ gap: 20px;
+ align-items: center;
+ font-family: 'JetBrains Mono', monospace;
+ font-size: 11px;
+}
+
+.status-item {
+ display: flex;
+ align-items: center;
+ gap: 6px;
+}
+
+.status-dot {
+ width: 8px;
+ height: 8px;
+ border-radius: 50%;
+ background: var(--accent-green);
+ box-shadow: 0 0 10px var(--accent-green);
+ animation: pulse 2s ease-in-out infinite;
+}
+
+@keyframes pulse {
+
+ 0%,
+ 100% {
+ opacity: 1;
+ }
+
+ 50% {
+ opacity: 0.5;
+ }
+}
+
+.datetime {
+ font-family: 'Orbitron', monospace;
+ font-size: 12px;
+ color: var(--accent-cyan);
+}
+
+.back-link {
+ color: var(--accent-cyan);
+ text-decoration: none;
+ font-size: 11px;
+ padding: 4px 10px;
+ border: 1px solid var(--accent-cyan);
+ border-radius: 4px;
+}
+
+/* Main dashboard grid */
+.dashboard {
+ position: relative;
+ z-index: 10;
+ display: grid;
+ grid-template-columns: 1fr 1fr 340px;
+ grid-template-rows: 1fr auto;
+ gap: 0;
+ height: calc(100vh - 60px);
+ min-height: 500px;
+}
+
+/* Panels */
+.panel {
+ background: var(--bg-panel);
+ border: 1px solid rgba(0, 212, 255, 0.2);
+ overflow: hidden;
+ position: relative;
+}
+
+.panel::before {
+ content: '';
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ height: 2px;
+ background: linear-gradient(90deg, transparent, var(--accent-cyan), transparent);
+}
+
+.panel-header {
+ padding: 10px 15px;
+ background: rgba(0, 212, 255, 0.05);
+ border-bottom: 1px solid rgba(0, 212, 255, 0.1);
+ font-family: 'Orbitron', monospace;
+ font-size: 11px;
+ font-weight: 500;
+ letter-spacing: 2px;
+ text-transform: uppercase;
+ color: var(--accent-cyan);
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+}
+
+.panel-indicator {
+ width: 6px;
+ height: 6px;
+ background: var(--accent-green);
+ border-radius: 50%;
+ animation: blink 1s ease-in-out infinite;
+}
+
+@keyframes blink {
+
+ 0%,
+ 100% {
+ opacity: 1;
+ }
+
+ 50% {
+ opacity: 0.3;
+ }
+}
+
+.panel-content {
+ padding: 12px;
+ height: calc(100% - 40px);
+ overflow-y: auto;
+}
+
+/* Polar plot */
+.polar-container {
+ grid-column: 1;
+ grid-row: 1;
+}
+
+#polarPlot {
+ width: 100%;
+ height: 100%;
+ min-height: 300px;
+}
+
+/* Ground track map */
+.map-container {
+ grid-column: 2;
+ grid-row: 1;
+}
+
+#groundMap {
+ width: 100%;
+ height: 100%;
+ min-height: 300px;
+}
+
+/* Right sidebar */
+.sidebar {
+ grid-column: 3;
+ grid-row: 1;
+ display: flex;
+ flex-direction: column;
+ border-left: 1px solid rgba(0, 212, 255, 0.2);
+ overflow: hidden;
+}
+
+/* Satellite selector at top of sidebar */
+.satellite-selector {
+ display: flex;
+ align-items: center;
+ gap: 10px;
+ padding: 10px;
+ background: var(--bg-panel);
+ border-bottom: 1px solid rgba(0, 212, 255, 0.2);
+}
+
+.satellite-selector label {
+ font-family: 'Orbitron', monospace;
+ font-size: 10px;
+ font-weight: 500;
+ letter-spacing: 2px;
+ color: var(--text-secondary);
+}
+
+.satellite-selector select {
+ flex: 1;
+ background: rgba(0, 212, 255, 0.1);
+ border: 1px solid var(--accent-cyan);
+ border-radius: 4px;
+ padding: 8px 12px;
+ color: var(--accent-cyan);
+ font-family: 'Orbitron', monospace;
+ font-size: 11px;
+ font-weight: 600;
+ cursor: pointer;
+}
+
+.satellite-selector select:focus {
+ outline: none;
+ box-shadow: 0 0 15px rgba(0, 212, 255, 0.3);
+}
+
+/* Countdown panel */
+.countdown-panel {
+ flex-shrink: 0;
+ background: linear-gradient(135deg, rgba(0, 212, 255, 0.1) 0%, rgba(0, 255, 136, 0.05) 100%);
+}
+
+.countdown-display {
+ text-align: center;
+ padding: 15px 10px;
+}
+
+.next-pass-label {
+ font-size: 10px;
+ text-transform: uppercase;
+ letter-spacing: 2px;
+ color: var(--text-secondary);
+ margin-bottom: 4px;
+}
+
+.satellite-name {
+ font-family: 'Orbitron', monospace;
+ font-size: 16px;
+ font-weight: 700;
+ color: var(--accent-cyan);
+ text-shadow: 0 0 15px var(--accent-cyan);
+ margin-bottom: 12px;
+}
+
+.countdown-grid {
+ display: grid;
+ grid-template-columns: repeat(4, 1fr);
+ gap: 6px;
+}
+
+.countdown-block {
+ background: rgba(0, 0, 0, 0.3);
+ border: 1px solid rgba(0, 212, 255, 0.2);
+ border-radius: 4px;
+ padding: 8px 4px;
+ text-align: center;
+}
+
+.countdown-value {
+ font-family: 'Orbitron', monospace;
+ font-size: 22px;
+ font-weight: 700;
+ color: var(--accent-cyan);
+ text-shadow: 0 0 10px var(--accent-cyan);
+ line-height: 1;
+}
+
+.countdown-value.active {
+ color: var(--accent-green);
+ text-shadow: 0 0 15px var(--accent-green);
+ animation: countPulse 1s ease-in-out infinite;
+}
+
+@keyframes countPulse {
+
+ 0%,
+ 100% {
+ opacity: 1;
+ transform: scale(1);
+ }
+
+ 50% {
+ opacity: 0.8;
+ transform: scale(1.05);
+ }
+}
+
+.countdown-label {
+ font-size: 9px;
+ text-transform: uppercase;
+ letter-spacing: 1px;
+ color: var(--text-secondary);
+ margin-top: 4px;
+}
+
+/* Telemetry panel */
+.telemetry-panel {
+ flex-shrink: 0;
+}
+
+.telemetry-rows {
+ display: grid;
+ grid-template-columns: 1fr 1fr;
+ gap: 6px;
+}
+
+.telemetry-item {
+ background: rgba(0, 0, 0, 0.3);
+ border-radius: 4px;
+ padding: 8px;
+ border-left: 2px solid var(--accent-cyan);
+}
+
+.telemetry-label {
+ font-size: 9px;
+ text-transform: uppercase;
+ letter-spacing: 1px;
+ color: var(--text-secondary);
+ margin-bottom: 2px;
+}
+
+.telemetry-value {
+ font-family: 'JetBrains Mono', monospace;
+ font-size: 12px;
+ color: var(--accent-cyan);
+}
+
+/* Pass list */
+.pass-list {
+ flex: 1;
+ min-height: 0;
+ display: flex;
+ flex-direction: column;
+}
+
+.pass-list-content {
+ flex: 1;
+ overflow-y: auto;
+ padding: 0;
+}
+
+.pass-item {
+ background: rgba(0, 0, 0, 0.3);
+ border: 1px solid rgba(0, 212, 255, 0.15);
+ border-radius: 4px;
+ padding: 8px 10px;
+ margin-bottom: 6px;
+ cursor: pointer;
+ transition: all 0.2s ease;
+}
+
+.pass-item:hover {
+ border-color: var(--accent-cyan);
+ background: rgba(0, 212, 255, 0.05);
+}
+
+.pass-item.active {
+ border-color: var(--accent-cyan);
+ box-shadow: 0 0 15px rgba(0, 212, 255, 0.2);
+ background: rgba(0, 212, 255, 0.1);
+}
+
+.pass-item-header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ margin-bottom: 4px;
+}
+
+.pass-sat-name {
+ font-family: 'Orbitron', monospace;
+ font-size: 11px;
+ font-weight: 600;
+ color: var(--accent-cyan);
+}
+
+.pass-quality {
+ font-size: 8px;
+ padding: 2px 5px;
+ border-radius: 3px;
+ text-transform: uppercase;
+ letter-spacing: 1px;
+ font-weight: 600;
+}
+
+.pass-quality.excellent {
+ background: rgba(0, 255, 136, 0.2);
+ color: var(--accent-green);
+}
+
+.pass-quality.good {
+ background: rgba(0, 212, 255, 0.2);
+ color: var(--accent-cyan);
+}
+
+.pass-quality.fair {
+ background: rgba(255, 149, 0, 0.2);
+ color: var(--accent-orange);
+}
+
+.pass-item-details {
+ display: flex;
+ justify-content: space-between;
+ font-size: 10px;
+ color: var(--text-secondary);
+}
+
+.pass-time {
+ font-family: 'JetBrains Mono', monospace;
+}
+
+/* Bottom controls bar */
+.controls-bar {
+ grid-column: 1 / -1;
+ grid-row: 2;
+ display: flex;
+ align-items: center;
+ gap: 20px;
+ padding: 10px 20px;
+ background: var(--bg-panel);
+ border-top: 1px solid rgba(0, 212, 255, 0.3);
+}
+
+.control-group {
+ display: flex;
+ align-items: center;
+ gap: 8px;
+}
+
+.control-label {
+ font-size: 10px;
+ text-transform: uppercase;
+ letter-spacing: 1px;
+ color: var(--text-secondary);
+}
+
+.control-group input[type="text"],
+.control-group input[type="number"] {
+ width: 90px;
+ padding: 6px 8px;
+ background: rgba(0, 0, 0, 0.3);
+ border: 1px solid rgba(0, 212, 255, 0.3);
+ border-radius: 4px;
+ color: var(--accent-cyan);
+ font-family: 'JetBrains Mono', monospace;
+ font-size: 11px;
+}
+
+.control-group input:focus {
+ outline: none;
+ border-color: var(--accent-cyan);
+ box-shadow: 0 0 10px rgba(0, 212, 255, 0.2);
+}
+
+.btn {
+ padding: 8px 16px;
+ border: 1px solid var(--accent-cyan);
+ background: rgba(0, 212, 255, 0.1);
+ color: var(--accent-cyan);
+ font-family: 'Orbitron', monospace;
+ font-size: 11px;
+ font-weight: 600;
+ text-transform: uppercase;
+ letter-spacing: 1px;
+ border-radius: 4px;
+ cursor: pointer;
+ transition: all 0.2s ease;
+}
+
+.btn:hover {
+ background: var(--accent-cyan);
+ color: var(--bg-dark);
+ box-shadow: 0 0 20px rgba(0, 212, 255, 0.3);
+}
+
+.btn.primary {
+ background: var(--accent-cyan);
+ color: var(--bg-dark);
+ margin-left: auto;
+}
+
+.btn.primary:hover {
+ box-shadow: 0 0 25px rgba(0, 212, 255, 0.5);
+}
+
+/* Leaflet dark theme overrides */
+.leaflet-container {
+ background: var(--bg-dark) !important;
+}
+
+.leaflet-control-zoom a {
+ background: var(--bg-panel) !important;
+ color: var(--accent-cyan) !important;
+ border-color: rgba(0, 212, 255, 0.3) !important;
+}
+
+.leaflet-control-attribution {
+ background: rgba(0, 0, 0, 0.7) !important;
+ color: var(--text-secondary) !important;
+ font-size: 9px !important;
+}
+
+/* Custom scrollbar */
+::-webkit-scrollbar {
+ width: 6px;
+}
+
+::-webkit-scrollbar-track {
+ background: var(--bg-dark);
+}
+
+::-webkit-scrollbar-thumb {
+ background: var(--accent-cyan);
+ border-radius: 3px;
+}
+
+/* Responsive */
+@media (max-width: 1200px) {
+ .dashboard {
+ grid-template-columns: 1fr 1fr;
+ grid-template-rows: 1fr auto auto;
+ }
+
+ .polar-container {
+ grid-column: 1;
+ grid-row: 1;
+ }
+
+ .map-container {
+ grid-column: 2;
+ grid-row: 1;
+ }
+
+ .sidebar {
+ grid-column: 1 / 3;
+ grid-row: 2;
+ flex-direction: row;
+ border-left: none;
+ border-top: 1px solid rgba(0, 212, 255, 0.2);
+ max-height: 250px;
+ }
+
+ .sidebar>* {
+ flex: 1;
+ min-width: 200px;
+ }
+
+ .controls-bar {
+ grid-row: 3;
+ flex-wrap: wrap;
+ }
+}
+
+@media (max-width: 800px) {
+ .dashboard {
+ grid-template-columns: 1fr;
+ grid-template-rows: auto auto auto auto;
+ }
+
+ .polar-container,
+ .map-container {
+ grid-column: 1;
+ min-height: 300px;
+ }
+
+ .sidebar {
+ grid-column: 1;
+ flex-direction: column;
+ max-height: none;
+ }
+
+ .controls-bar {
+ grid-row: 4;
+ }
+}
\ No newline at end of file
diff --git a/screenshot.png b/static/images/screenshots/screenshot.png
similarity index 100%
rename from screenshot.png
rename to static/images/screenshots/screenshot.png
diff --git a/screenshot2.png b/static/images/screenshots/screenshot2.png
similarity index 100%
rename from screenshot2.png
rename to static/images/screenshots/screenshot2.png
diff --git a/templates/adsb_dashboard.html b/templates/adsb_dashboard.html
index 31fcb61..19aca15 100644
--- a/templates/adsb_dashboard.html
+++ b/templates/adsb_dashboard.html
@@ -7,622 +7,7 @@
-
+
diff --git a/templates/index.html b/templates/index.html
index 39c9538..d9218c5 100644
--- a/templates/index.html
+++ b/templates/index.html
@@ -12,2844 +12,7 @@
-
+
diff --git a/templates/satellite_dashboard.html b/templates/satellite_dashboard.html
index 60ed6a7..e228978 100644
--- a/templates/satellite_dashboard.html
+++ b/templates/satellite_dashboard.html
@@ -7,636 +7,7 @@
-
+