{% 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 %}