GEOINT-Modus: Experimentelle taktische Kartenansicht mit Echtzeit-Datenlayern

Neuer experimenteller GEOINT-Modus per Checkbox auf der Karten-Kachel:
- Satellitenbilder (Esri World Imagery) statt OSM-Strassenkarte
- Echtzeit-Flugverkehr (airplanes.live via Backend-Proxy, 15s Refresh)
- Erdbeben-Layer (USGS M2.5+, pulsierende Kreise nach Magnitude)
- GDELT Nachrichten (geokodierte Echtzeit-News, Cluster-Darstellung)
- Heatmap-Visualisierung der Artikel-Standorte (Leaflet.heat)
- Timeline-Slider fuer zeitliche Filterung der Artikel-Marker
- Koordinatenanzeige (Lat/Lon unter Mauszeiger)
- Distanzmessung (Klick-zu-Klick mit km-Anzeige)
- Taktisches Styling (dunkle Tonung, gruene Akzente, Scanlines)

Neue Dateien: geoint.js, geoint.css, routers/geoint.py
Inspiriert von WorldView/Gods Eye Konzept, komplett eigenentwickelt.
Dieser Commit ist enthalten in:
Claude Dev
2026-03-24 09:29:19 +01:00
Ursprung fdbffa7e00
Commit b2be1358ab
6 geänderte Dateien mit 1030 neuen und 1 gelöschten Zeilen

308
src/static/css/geoint.css Normale Datei
Datei anzeigen

@@ -0,0 +1,308 @@
/* =====================================================================
GEOINT-Modus: Taktische Kartenansicht mit Echtzeit-Datenlayern
===================================================================== */
/* --- Toggle-Checkbox im Card-Header --- */
.geoint-toggle {
display: inline-flex;
align-items: center;
gap: 5px;
cursor: pointer;
user-select: none;
margin-right: 8px;
}
.geoint-toggle input[type="checkbox"] {
accent-color: #00ff88;
width: 13px;
height: 13px;
cursor: pointer;
}
.geoint-toggle-label {
font-family: var(--font-mono, 'Courier New', monospace);
font-size: 10px;
font-weight: 700;
letter-spacing: 1.5px;
text-transform: uppercase;
color: var(--text-secondary);
transition: color 0.2s;
}
.geoint-toggle input:checked + .geoint-toggle-label {
color: #00ff88;
text-shadow: 0 0 6px rgba(0, 255, 136, 0.4);
}
/* --- Taktisches Styling (aktiv) --- */
.geoint-active .leaflet-tile-pane {
filter: brightness(0.88) contrast(1.08) saturate(0.85);
transition: filter 0.4s ease;
}
.geoint-active::after {
content: '';
position: absolute;
inset: 0;
pointer-events: none;
z-index: 800;
background: repeating-linear-gradient(
0deg,
transparent,
transparent 3px,
rgba(0, 255, 100, 0.012) 3px,
rgba(0, 255, 100, 0.012) 6px
);
}
.geoint-active .map-empty { display: none !important; }
/* Gruener Akzent am Card-Header wenn aktiv */
.map-card.geoint-card-active .card-header {
border-bottom: 2px solid rgba(0, 255, 136, 0.25);
}
/* --- Sub-Layer Control Panel --- */
.geoint-sub-control {
background: rgba(11, 17, 33, 0.92);
border: 1px solid rgba(0, 255, 136, 0.2);
border-radius: 6px;
padding: 10px 12px;
min-width: 170px;
backdrop-filter: blur(8px);
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.4);
}
.geoint-sub-control h4 {
font-family: var(--font-mono, 'Courier New', monospace);
font-size: 9px;
font-weight: 700;
letter-spacing: 2px;
text-transform: uppercase;
color: #00ff88;
margin: 0 0 8px 0;
padding-bottom: 6px;
border-bottom: 1px solid rgba(0, 255, 136, 0.15);
}
.geoint-sub-item {
display: flex;
align-items: center;
gap: 6px;
padding: 3px 0;
}
.geoint-sub-item input[type="checkbox"] {
accent-color: #00ff88;
width: 12px;
height: 12px;
cursor: pointer;
flex-shrink: 0;
}
.geoint-sub-item label {
font-family: var(--font-mono, 'Courier New', monospace);
font-size: 11px;
color: rgba(255, 255, 255, 0.8);
cursor: pointer;
white-space: nowrap;
}
.geoint-sub-item label .geoint-dot {
display: inline-block;
width: 7px;
height: 7px;
border-radius: 50%;
margin-right: 4px;
vertical-align: middle;
}
.geoint-dot-flights { background: #00ff88; }
.geoint-dot-quakes { background: #ff4444; }
.geoint-dot-gdelt { background: #44aaff; }
.geoint-dot-heatmap { background: #ff8800; }
.geoint-dot-coords { background: #aaaaaa; }
.geoint-dot-distance { background: #ffdd00; }
.geoint-sub-separator {
height: 1px;
background: rgba(0, 255, 136, 0.1);
margin: 5px 0;
}
/* --- Flugzeug-Icons --- */
.geoint-aircraft {
display: flex;
align-items: center;
justify-content: center;
transition: filter 0.15s;
}
.geoint-aircraft:hover {
filter: drop-shadow(0 0 6px #00ff88);
}
.geoint-aircraft svg {
width: 14px;
height: 14px;
}
/* --- Erdbeben Puls-Animation --- */
.geoint-quake-marker {
animation: geoint-pulse 2.5s ease-in-out infinite;
}
@keyframes geoint-pulse {
0%, 100% { opacity: 0.7; }
50% { opacity: 1; }
}
/* --- GDELT Nachrichtenmarker --- */
.geoint-gdelt-icon {
display: flex;
align-items: center;
justify-content: center;
width: 18px;
height: 18px;
background: rgba(68, 170, 255, 0.85);
border: 1.5px solid rgba(68, 170, 255, 1);
border-radius: 50%;
font-size: 10px;
color: #fff;
font-weight: 700;
box-shadow: 0 0 4px rgba(68, 170, 255, 0.5);
}
/* --- Koordinatenanzeige --- */
.geoint-coord-display {
background: rgba(11, 17, 33, 0.88);
border: 1px solid rgba(0, 255, 136, 0.2);
border-radius: 4px;
padding: 4px 8px;
font-family: var(--font-mono, 'Courier New', monospace);
font-size: 11px;
color: #00ff88;
letter-spacing: 0.5px;
white-space: nowrap;
backdrop-filter: blur(4px);
}
/* --- Distanzmessung --- */
.geoint-distance-label {
background: rgba(11, 17, 33, 0.9);
border: 1px solid rgba(255, 221, 0, 0.3);
border-radius: 3px;
padding: 2px 6px;
font-family: var(--font-mono, 'Courier New', monospace);
font-size: 10px;
color: #ffdd00;
white-space: nowrap;
}
/* --- Timeline-Slider --- */
.geoint-timeline {
display: none;
padding: 6px 12px 8px;
background: rgba(11, 17, 33, 0.6);
border-top: 1px solid rgba(0, 255, 136, 0.1);
}
.geoint-active .geoint-timeline {
display: flex;
align-items: center;
gap: 10px;
}
.geoint-timeline input[type="range"] {
flex: 1;
height: 4px;
-webkit-appearance: none;
appearance: none;
background: rgba(255, 255, 255, 0.12);
border-radius: 2px;
outline: none;
cursor: pointer;
}
.geoint-timeline input[type="range"]::-webkit-slider-thumb {
-webkit-appearance: none;
width: 14px;
height: 14px;
background: #00ff88;
border-radius: 50%;
border: 2px solid rgba(11, 17, 33, 0.8);
cursor: pointer;
box-shadow: 0 0 6px rgba(0, 255, 136, 0.5);
}
.geoint-timeline input[type="range"]::-moz-range-thumb {
width: 14px;
height: 14px;
background: #00ff88;
border-radius: 50%;
border: 2px solid rgba(11, 17, 33, 0.8);
cursor: pointer;
}
.geoint-timeline-label {
font-family: var(--font-mono, 'Courier New', monospace);
font-size: 10px;
color: #00ff88;
min-width: 90px;
text-align: center;
}
.geoint-timeline-btn {
background: none;
border: 1px solid rgba(0, 255, 136, 0.3);
border-radius: 3px;
color: #00ff88;
font-size: 11px;
padding: 2px 6px;
cursor: pointer;
font-family: var(--font-mono, 'Courier New', monospace);
}
.geoint-timeline-btn:hover {
background: rgba(0, 255, 136, 0.1);
}
/* --- Popup-Styling fuer GEOINT-Layer --- */
.geoint-popup {
font-family: var(--font-mono, 'Courier New', monospace);
font-size: 11px;
line-height: 1.5;
color: #e0e0e0;
}
.geoint-popup strong {
color: #00ff88;
}
.geoint-popup .geoint-popup-row {
display: flex;
gap: 8px;
}
.geoint-popup .geoint-popup-key {
color: rgba(255, 255, 255, 0.5);
min-width: 40px;
}
/* --- Light Theme Overrides --- */
[data-theme="light"] .geoint-sub-control {
background: rgba(240, 243, 248, 0.95);
border-color: rgba(0, 160, 80, 0.25);
}
[data-theme="light"] .geoint-sub-control h4 {
color: #008844;
}
[data-theme="light"] .geoint-sub-item label {
color: rgba(0, 0, 0, 0.75);
}
[data-theme="light"] .geoint-coord-display {
background: rgba(240, 243, 248, 0.92);
color: #006633;
border-color: rgba(0, 160, 80, 0.25);
}
[data-theme="light"] .geoint-timeline {
background: rgba(240, 243, 248, 0.7);
border-top-color: rgba(0, 160, 80, 0.15);
}
[data-theme="light"] .geoint-timeline input[type="range"]::-webkit-slider-thumb {
background: #008844;
}
[data-theme="light"] .geoint-timeline-label {
color: #006633;
}
[data-theme="light"] .geoint-toggle input:checked + .geoint-toggle-label {
color: #008844;
text-shadow: none;
}
[data-theme="light"] .geoint-active .leaflet-tile-pane {
filter: brightness(0.95) contrast(1.05) saturate(0.9);
}
[data-theme="light"] .geoint-active::after {
background: repeating-linear-gradient(
0deg,
transparent,
transparent 3px,
rgba(0, 100, 50, 0.008) 3px,
rgba(0, 100, 50, 0.008) 6px
);
}