{% extends "base.html" %} {% block title %}ADS-B — SignalOps{% endblock %} {% block extra_style %} /* ── Map ── */ #adsb-map { width:100%; height:100%; min-height:100% } .map-card { height:100% !important } /* ── Left panel ── */ .mode-item { display:flex; align-items:center; gap:8px; padding:7px 10px; border-radius:6px; cursor:pointer; font-family:'Rajdhani',sans-serif; font-size:13px; font-weight:600; letter-spacing:0.5px; color:var(--td); border:1px solid transparent; transition:all 0.18s; user-select:none; } .mode-item:hover { color:var(--t); background:rgba(138, 122, 184,0.08) } .mode-item.active { color:var(--pl); background:rgba(138, 122, 184,0.12); border-color:rgba(138, 122, 184,0.25) } .mode-dot { width:7px; height:7px; border-radius:50%; background:var(--tm); flex-shrink:0; transition:background 0.18s } .mode-item.active .mode-dot { background:var(--pl); box-shadow:0 0 6px var(--pl) } .mode-sub { padding:4px 10px 8px 25px; display:none } .mode-sub.open { display:block } .lp-hdr { font-size:9px; letter-spacing:2px; color:var(--tm); padding:10px 10px 4px; text-transform:uppercase } .lp-sep { height:1px; background:var(--b); margin:6px 0 } .toggle-row { display:flex; gap:4px; padding:0 6px } .tgl-btn { flex:1; padding:5px 4px; border-radius:4px; font-family:'Rajdhani',sans-serif; font-size:10px; font-weight:700; letter-spacing:0.5px; cursor:pointer; border:1px solid rgba(255,255,255,0.08); background:transparent; color:var(--tm); transition:all 0.18s; } .tgl-btn.active { background:rgba(138, 122, 184,0.15); color:var(--pl); border-color:rgba(138, 122, 184,0.3) } .tgl-btn:hover:not(.active) { color:var(--t) } /* ── Callsign label ── */ .cs-label { background:rgba(10, 10, 14,0.82); border:1px solid rgba(255,255,255,0.1); border-radius:3px; padding:1px 5px; font-family:'JetBrains Mono',monospace; font-size:9px; white-space:nowrap; pointer-events:none; color:#E2E2EC; } .cs-label.mil { border-color:rgba(255,149,0,0.5); color:#FF9500 } .cs-label.emg { border-color:rgba(199, 123, 123,0.5); color:#C77B7B } /* ── Military flagged ── */ .flagged-row td { background:rgba(199, 123, 123,0.05)!important } .flag-tag { display:inline-block; padding:1px 5px; border-radius:3px; font-size:9px; font-family:'Rajdhani',sans-serif; font-weight:700; letter-spacing:1px; background:rgba(255,149,0,0.12); color:#FF9500; border:1px solid rgba(255,149,0,0.3) } /* ── Dark Ops theme ── */ body.theme-darkops { background:#000 } body.theme-darkops .topnav { opacity:0.12; transition:opacity 0.3s; background:rgba(0,0,0,0.98) } body.theme-darkops .topnav:hover { opacity:1 } body.theme-darkops .card { background:#050505; border-color:rgba(116, 176, 149,0.12) } body.theme-darkops #darkops-overlay { display:block } /* ── Misc ── */ .ac-row { cursor:pointer; transition:background 0.15s } .ac-row:hover td { background:rgba(138, 122, 184,0.08)!important } .ac-row.selected td { background:rgba(138, 122, 184,0.14)!important } .squawk-emergency { animation:sq-flash 1s infinite } @keyframes sq-flash { 0%,100%{background:rgba(199, 123, 123,0.1)} 50%{background:rgba(199, 123, 123,0.25)} } .squawk-pill { display:inline-block; padding:2px 7px; border-radius:4px; font-family:'JetBrains Mono',monospace; font-size:10px; font-weight:600; background:rgba(255,255,255,0.05); color:var(--td) } .squawk-7500 { background:rgba(199, 123, 123,0.2)!important; color:#C77B7B!important; border:1px solid rgba(199, 123, 123,0.4) } .squawk-7600 { background:rgba(201, 161, 90,0.2)!important; color:#C9A15A!important; border:1px solid rgba(201, 161, 90,0.4) } .squawk-7700 { background:rgba(255,107,38,0.2)!important; color:#FF6B26!important; border:1px solid rgba(255,107,38,0.4) } .alt-bar { height:3px; border-radius:2px; margin-top:3px; background:rgba(255,255,255,0.05) } .alt-fill { height:4px; border-radius:2px } #emergency-banner { display:none; background:rgba(199, 123, 123,0.1); border:1px solid rgba(199, 123, 123,0.4); border-radius:8px; padding:12px 16px; margin-bottom:10px; animation:sq-flash 1.5s infinite } .detail-panel { background:var(--s); border:1px solid rgba(138, 122, 184,0.3); border-radius:8px; padding:16px; display:none; margin-top:12px } .detail-grid { display:grid; grid-template-columns:auto 1fr; gap:5px 12px; font-size:11px; align-items:baseline } .detail-grid .dk { color:var(--tm); letter-spacing:1px; font-size:10px; text-transform:uppercase; white-space:nowrap } .detail-grid .dv { color:var(--t); font-weight:600; word-break:break-word } .detail-section-hdr { font-size:9px; color:var(--tm); letter-spacing:2.5px; margin-bottom:10px; text-transform:uppercase; font-family:'Rajdhani',sans-serif; font-weight:700; padding-bottom:4px; border-bottom:1px solid rgba(138, 122, 184,0.15) } /* Status value color accents */ .dv-warn { color:#C9A15A !important } .dv-danger { color:#C77B7B !important } .dv-ok { color:#74B095 !important } .dv-info { color:#7C9BC9 !important } .dv-mono { font-family:'JetBrains Mono',monospace; font-size:10.5px } .dv-small { font-size:10px; color:var(--td) !important; font-weight:500 } /* Tiny trend arrow for climb/descent */ .trend-up::before { content:'▲ '; color:#74B095 } .trend-down::before { content:'▼ '; color:#7C9BC9 } .trend-level::before{ content:'◆ '; color:var(--td) } /* Phase badge colors */ .phase-taxi { background:rgba(156,163,175,0.15); color:#9CA3AF; border:1px solid rgba(156,163,175,0.3) } .phase-climb { background:rgba(116, 176, 149,0.15); color:#74B095; border:1px solid rgba(116, 176, 149,0.3) } .phase-cruise { background:rgba(96,165,250,0.15); color:#7C9BC9; border:1px solid rgba(96,165,250,0.3) } .phase-descent { background:rgba(180, 168, 214,0.15); color:#B4A8D6; border:1px solid rgba(180, 168, 214,0.3) } .phase-approach { background:rgba(201, 161, 90,0.15); color:#C9A15A; border:1px solid rgba(201, 161, 90,0.3) } .phase-ground { background:rgba(107,114,128,0.15); color:#6B7280; border:1px solid rgba(107,114,128,0.3) } .stat-box { background:var(--s); border:1px solid var(--b); border-radius:8px; padding:10px 14px; text-align:center } .stat-box .val { font-family:'Rajdhani',sans-serif; font-size:24px; font-weight:700; line-height:1 } .stat-box .lbl { font-size:9px; letter-spacing:2px; color:var(--tm); margin-top:3px; text-transform:uppercase } .refresh-ring { width:16px; height:16px; border-radius:50%; border:2px solid rgba(138, 122, 184,0.2); border-top-color:var(--p); animation:spin 1s linear infinite; display:inline-block; vertical-align:middle } .threat-row { display:flex; align-items:center; gap:8px; margin-bottom:6px; font-size:10px } .threat-lbl { color:var(--tm); width:110px; flex-shrink:0 } .threat-track { flex:1; height:4px; background:rgba(255,255,255,0.06); border-radius:2px } .threat-fill { height:4px; border-radius:2px; transition:width 0.4s } .threat-val { color:var(--t); font-weight:700; width:30px; text-align:right; flex-shrink:0 } #detail-photo { width:100%; height:110px; object-fit:cover; border-radius:6px; background:rgba(255,255,255,0.03); border:1px solid var(--b); display:none; margin-bottom:10px } #detail-photo-wrap { margin-bottom:10px; display:none } #darkops-overlay { display:none; position:absolute; bottom:16px; left:16px; z-index:600; background:rgba(0,0,0,0.85); border:1px solid rgba(116, 176, 149,0.35); border-radius:6px; padding:12px 14px; font-size:10px; pointer-events:none; min-width:160px } /* ═══ MAP STYLE TOGGLE (base + overlay) ═══ */ #map-style-toggle{ position:absolute; bottom:14px;left:14px; background:rgba(11, 11, 15,0.92); backdrop-filter:blur(14px) saturate(1.2); -webkit-backdrop-filter:blur(14px) saturate(1.2); border:1px solid rgba(138, 122, 184,0.28); border-radius:10px; padding:4px; z-index:500; display:flex;flex-direction:column;gap:2px; box-shadow:0 10px 30px rgba(0,0,0,0.55), inset 0 1px 0 rgba(255,255,255,0.04); font-family:'Rajdhani',sans-serif; } #map-style-toggle .mst-row{display:flex;gap:1px;padding:2px} #map-style-toggle .mst-sep{ height:1px;margin:1px 8px; background:linear-gradient(to right, transparent, rgba(138, 122, 184,0.25), transparent); } #map-style-toggle button{ background:transparent;border:none; color:var(--td); font-family:'Rajdhani',sans-serif;font-size:10px;font-weight:700; letter-spacing:1.2px; padding:6px 10px;border-radius:6px; cursor:pointer;transition:all 0.18s ease; display:inline-flex;align-items:center;gap:5px; position:relative; } #map-style-toggle button svg{ width:13px;height:13px;flex-shrink:0; stroke:currentColor;fill:none; stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round; opacity:0.85;transition:opacity 0.15s, transform 0.2s; } #map-style-toggle button:hover{color:var(--t);background:rgba(138, 122, 184,0.08)} #map-style-toggle button:hover svg{opacity:1;transform:scale(1.08)} #map-style-toggle .mst-base button.active{ color:#C3B8E2; background:linear-gradient(180deg, rgba(138, 122, 184,0.25), rgba(138, 122, 184,0.12)); box-shadow:inset 0 0 0 1px rgba(180, 168, 214,0.4), 0 0 12px rgba(138, 122, 184,0.2); } #map-style-toggle .mst-base button.active svg{opacity:1} #map-style-toggle .mst-overlay button.active{ color:#FCD34D; background:linear-gradient(180deg, rgba(201, 161, 90,0.2), rgba(201, 161, 90,0.08)); box-shadow:inset 0 0 0 1px rgba(201, 161, 90,0.45), 0 0 10px rgba(201, 161, 90,0.18); } #map-style-toggle .mst-overlay button.active svg{opacity:1} /* Attribution control styling */ .leaflet-control-attribution{ background:rgba(8,11,9,0.7) !important; color:var(--tm) !important; font-size:9px !important; padding:2px 6px !important; border-radius:4px 0 0 0 !important; } .leaflet-control-attribution a{color:var(--td) !important} /* ═══ MAP HUD OVERLAY (live map-derived values) ═══ */ #drone-hud{ position:absolute;inset:0;pointer-events:none;z-index:450; display:none; font-family:'JetBrains Mono',monospace;color:#4ADE80; text-shadow:0 0 4px rgba(74,222,128,0.6); } #drone-hud.active{display:block} #drone-hud::before{ content:'';position:absolute;inset:0; background: radial-gradient(ellipse at center, transparent 35%, rgba(0,0,0,0.35) 100%), linear-gradient(rgba(74,222,128,0.04) 1px, transparent 1px), linear-gradient(90deg, rgba(74,222,128,0.04) 1px, transparent 1px); background-size:100% 100%, 40px 40px, 40px 40px; pointer-events:none; } /* Artificial horizon line across the whole view */ #drone-hud::after{ content:'';position:absolute; left:80px;right:80px;top:50%;height:1px; background:linear-gradient(to right, transparent, rgba(74,222,128,0.4) 15%, rgba(74,222,128,0.4) 85%, transparent); pointer-events:none; } #drone-hud .dh-cross{ position:absolute;top:50%;left:50%; width:80px;height:80px; transform:translate(-50%,-50%); } #drone-hud .dh-cross::before, #drone-hud .dh-cross::after{ content:'';position:absolute;background:#4ADE80; box-shadow:0 0 6px rgba(74,222,128,0.8); } #drone-hud .dh-cross::before{left:50%;top:0;bottom:0;width:1px;transform:translateX(-0.5px)} #drone-hud .dh-cross::after{top:50%;left:0;right:0;height:1px;transform:translateY(-0.5px)} #drone-hud .dh-cross .dh-dot{ position:absolute;top:50%;left:50%;width:10px;height:10px; border:1px solid #4ADE80;border-radius:50%; transform:translate(-50%,-50%); } /* Pitch ladder marks either side of crosshair */ #drone-hud .dh-pitch{ position:absolute;top:50%;left:50%; transform:translate(-50%,-50%); width:260px;height:1px;pointer-events:none; } #drone-hud .dh-pitch::before, #drone-hud .dh-pitch::after{ content:'';position:absolute;top:-30px;width:30px;height:1px; background:#4ADE80;box-shadow:0 0 4px rgba(74,222,128,0.6); } #drone-hud .dh-pitch::before{left:20px} #drone-hud .dh-pitch::after{right:20px} #drone-hud .dh-corner{ position:absolute;width:28px;height:28px; border-color:#4ADE80;border-style:solid; } #drone-hud .dh-tl{top:16px;left:16px;border-width:2px 0 0 2px} #drone-hud .dh-tr{top:16px;right:16px;border-width:2px 2px 0 0} #drone-hud .dh-bl{bottom:16px;left:16px;border-width:0 0 2px 2px} #drone-hud .dh-br{bottom:16px;right:16px;border-width:0 2px 2px 0} #drone-hud .dh-telemetry{ position:absolute;top:20px;left:56px; font-size:10px;letter-spacing:1.5px;line-height:1.7; } #drone-hud .dh-telemetry .k{color:rgba(74,222,128,0.5);margin-right:6px} #drone-hud .dh-telemetry .v{color:#4ADE80;font-weight:700} #drone-hud .dh-status{ position:absolute;top:20px;right:56px;text-align:right; font-size:10px;letter-spacing:2px; } #drone-hud .dh-status .rec{ display:inline-block;width:8px;height:8px;border-radius:50%; background:#F87171;margin-right:6px; animation:dh-blink 1s infinite; box-shadow:0 0 8px rgba(248,113,113,0.8); } @keyframes dh-blink{0%,50%{opacity:1}51%,100%{opacity:0.2}} #drone-hud .dh-altbar{ position:absolute;right:24px;top:50%;transform:translateY(-50%); width:4px;height:180px;background:rgba(74,222,128,0.15);border-radius:2px; } #drone-hud .dh-altbar::before{ content:'';position:absolute;left:-1px;right:-1px;bottom:0; height:var(--dh-zoom-pct,60%);background:linear-gradient(to top, #4ADE80, rgba(74,222,128,0.3)); border-radius:2px;box-shadow:0 0 6px rgba(74,222,128,0.6); } #drone-hud .dh-footer{ position:absolute;bottom:20px;left:56px;right:56px; display:flex;justify-content:space-between;font-size:9px; letter-spacing:2px;color:rgba(74,222,128,0.7); } /* ═══ MGRS GRID LABEL ═══ */ .mgrs-lbl{ background:rgba(11, 11, 15,0.85); color:#C9A15A; font-family:'JetBrains Mono',monospace; font-size:9px;font-weight:700; padding:1px 4px;border:1px solid rgba(201, 161, 90,0.3); border-radius:2px;letter-spacing:0.5px; white-space:nowrap;pointer-events:none; } /* Cockpit-mode subtle map desaturation for immersion */ .adsb-map-cockpit{filter:contrast(1.15) saturate(0.75) brightness(0.9)} /* ═══ RESPONSIVE — map toolbar + HUD (desktop >900px unchanged) ═══ */ @media (max-width:900px){ #map-style-toggle{left:8px;bottom:8px;max-width:calc(100% - 16px)} #map-style-toggle .mst-row{flex-wrap:wrap} #map-style-toggle button{min-height:36px;padding:6px 9px} #drone-hud .dh-corner{width:20px;height:20px} #drone-hud .dh-tl{top:10px;left:10px} #drone-hud .dh-tr{top:10px;right:10px} #drone-hud .dh-bl{bottom:10px;left:10px} #drone-hud .dh-br{bottom:10px;right:10px} #drone-hud .dh-telemetry{top:14px;left:54px;font-size:9px;letter-spacing:0.5px;line-height:1.6} #drone-hud .dh-status{top:14px;right:38px;font-size:9px;letter-spacing:0.5px} #drone-hud .dh-altbar{right:14px;height:110px} #drone-hud .dh-footer{top:96px;bottom:auto;left:54px;right:38px;font-size:8px;letter-spacing:0.5px;gap:8px;flex-wrap:wrap} .leaflet-popup-content{max-width:calc(100vw - 80px)} } @media (max-width:600px){ /* icon-only map toolbar on phones (labels stay in title tooltips) */ #map-style-toggle button{font-size:0;gap:0;min-width:36px;justify-content:center;padding:6px} #map-style-toggle button svg{width:16px;height:16px} } /* ═══ RESPONSIVE — page layout ═══ */ @media (max-width:900px){ #drone-hud .dh-pitch{width:180px} #drone-hud::after{left:40px;right:40px} .adsb-head{flex-wrap:wrap;gap:10px} .adsb-head > div:last-child{flex-wrap:wrap} .adsb-ctl-row{flex-wrap:wrap} .adsb-ctl-row > div{flex:1 1 100%;min-width:0} .adsb-coords{width:100%} .adsb-coords input{flex:1;width:auto !important;min-width:0} #radius-slider{width:100% !important} #type-filter{width:100% !important} .adsb-ctl-row .btn{min-height:40px;flex:1} .adsb-coords .btn{flex:0 0 auto;min-width:44px} .adsb-map-card{margin-bottom:0} #stats-row{grid-template-columns:repeat(3,1fr) !important} #main-layout{grid-template-columns:minmax(0,1fr) !important;height:auto !important;min-height:0 !important} .adsb-map-card,.map-card{order:0;height:60vh !important;min-height:360px} .adsb-left{order:1;max-height:none} .adsb-right{order:2;overflow:visible !important} .adsb-right #ac-list{max-height:420px} .mode-item{min-height:38px} .tgl-btn{min-height:34px} .dp-grid3,.dp-grid2{grid-template-columns:1fr !important} .dp-head{flex-wrap:wrap} #detail-panel a.btn,#detail-panel button.btn{min-height:36px;display:inline-flex;align-items:center} } @media (max-width:600px){ #stats-row{grid-template-columns:repeat(2,1fr) !important} .stat-box{padding:8px 10px} .stat-box .val{font-size:20px} .detail-panel{padding:12px} #detail-title{font-size:16px !important} } {% endblock %} {% block content %}
ADS-B Aircraft Intelligence
Emergency squawk detected
Center coordinates
Radius: 100 km
Filter
Map mode
Live Tracking
Heatmap
Time window
Military
Callsign filter
RCH Nato QID Jake Magma Reach
Airport Focus
Visual
Dark Ops
Overlays
LAT—
LON—
View w—
View h—
--:--:--Z
—
—
Squawk codes
7500Hijacking
7600Radio Failure
7700Emergency
1200VFR
7777Military Intercept
Nearby aircraft
Scan to populate
aircraft photo
Identification
Flight data
Threat breakdown
Navigation
Telemetry & signal
Operational assessment
FlightRadar24 → ADSBexchange → FlightAware → PlaneFinder → JetPhotos →
Full aircraft table
NO DATA — SCAN AN AREA
{% endblock %} {% block scripts %} {% endblock %}