/* AegisSight Monitor - Product Page v2 */ (function () { 'use strict'; /* ==================== NAVBAR ==================== */ var navbar = document.getElementById('navbar'); window.addEventListener('scroll', function () { navbar.classList.toggle('scrolled', window.scrollY > 10); }); /* ==================== MOBILE MENU ==================== */ var toggle = document.querySelector('.mobile-menu-toggle'); var menu = document.getElementById('mobile-menu'); var overlay = document.getElementById('mobile-overlay'); function closeMenu() { toggle.classList.remove('active'); menu.classList.remove('open'); overlay.classList.remove('open'); toggle.setAttribute('aria-expanded', 'false'); } toggle.addEventListener('click', function () { var isOpen = menu.classList.contains('open'); if (isOpen) { closeMenu(); } else { toggle.classList.add('active'); menu.classList.add('open'); overlay.classList.add('open'); toggle.setAttribute('aria-expanded', 'true'); } }); overlay.addEventListener('click', closeMenu); menu.querySelectorAll('a').forEach(function (l) { l.addEventListener('click', closeMenu); }); /* ==================== SMOOTH SCROLL ==================== */ document.querySelectorAll('a[href^="#"]').forEach(function (link) { link.addEventListener('click', function (e) { var t = document.querySelector(this.getAttribute('href')); if (t) { e.preventDefault(); t.scrollIntoView({ behavior: 'smooth' }); } }); }); /* ==================== HERO VIDEOS ==================== */ var videos = document.querySelectorAll('.hero-video'); var currentVideo = 0; var ROTATION_INTERVAL = 12000; var rotationTimer; function switchVideo() { videos[currentVideo].classList.remove('active'); currentVideo = (currentVideo + 1) % videos.length; var next = videos[currentVideo]; next.currentTime = 0; next.play().catch(function () {}); next.classList.add('active'); } function startRotation() { rotationTimer = setInterval(switchVideo, ROTATION_INTERVAL); } // Pause when tab hidden document.addEventListener('visibilitychange', function () { if (document.hidden) { clearInterval(rotationTimer); videos.forEach(function (v) { v.pause(); }); } else { videos.forEach(function (v) { if (v.classList.contains('active')) v.play().catch(function () {}); }); startRotation(); } }); if (videos.length > 1) startRotation(); /* ==================== SIMPLE MARKDOWN ==================== */ function mdToText(md) { if (!md) return ''; // Remove ## headers and bold markers, keep text return md .replace(/^## .+$/gm, '') .replace(/^### .+$/gm, '') .replace(/\*\*(.+?)\*\*/g, '$1') .replace(/\[(\d+[a-z]?)\]/g, '') .replace(/\n{3,}/g, '\n\n') .trim() .split('\n\n') .filter(function (p) { return p.trim().length > 0; }) .map(function (p) { return '
' + p.trim().replace(/\n/g, ' ') + '
'; }) .join(''); } /* ==================== LIVE DATA ==================== */ function timeAgo(dateStr) { var diffMin = Math.floor((Date.now() - new Date(dateStr).getTime()) / 60000); if (diffMin < 1) return 'Gerade eben aktualisiert'; if (diffMin < 60) return 'Aktualisiert vor ' + diffMin + ' Min.'; var diffH = Math.floor(diffMin / 60); if (diffH < 24) return 'Aktualisiert vor ' + diffH + ' Std.'; var diffD = Math.floor(diffH / 24); return 'Aktualisiert vor ' + diffD + (diffD === 1 ? ' Tag' : ' Tagen'); } var liveData = null; function loadLiveData() { fetch('/lagen/iran-konflikt/data/current.json?t=' + Date.now()) .then(function (r) { if (!r.ok) throw new Error(r.status); return r.json(); }) .then(function (data) { liveData = data; var inc = data.incident || {}; var lag = data.current_lagebild || {}; // Stats var ea = document.getElementById('stat-articles'); var es = document.getElementById('stat-sources'); var ef = document.getElementById('stat-factchecks'); var eu = document.getElementById('demo-updated'); if (ea) ea.textContent = inc.article_count || 0; if (es) es.textContent = inc.source_count || 0; if (ef) ef.textContent = inc.factcheck_count || 0; if (eu && lag.updated_at) eu.textContent = timeAgo(lag.updated_at); // Excerpt var excerptEl = document.getElementById('excerpt-text'); var toggleBtn = document.getElementById('excerpt-toggle'); if (excerptEl && lag.summary_markdown) { var html = mdToText(lag.summary_markdown); excerptEl.innerHTML = html; toggleBtn.style.display = 'inline-block'; toggleBtn.addEventListener('click', function () { var expanded = excerptEl.classList.toggle('expanded'); this.textContent = expanded ? 'Weniger anzeigen' : 'Weiterlesen'; }); } // Map if (data.locations && data.locations.length > 0) { initMap(data.locations, data.category_labels || {}); } }) .catch(function () { var eu = document.getElementById('demo-updated'); if (eu) eu.textContent = 'Daten derzeit nicht verfügbar'; }); } /* ==================== LEAFLET MAP ==================== */ function initMap(locations, categoryLabels) { var mapEl = document.getElementById('map-container'); if (!mapEl || typeof L === 'undefined') return; var map = L.map(mapEl, { center: [33.0, 48.0], zoom: 5, zoomControl: true, scrollWheelZoom: false }); L.tileLayer('https://tile.openstreetmap.de/{z}/{x}/{y}.png', { attribution: '© OpenStreetMap', maxZoom: 18 }).addTo(map); var catColors = { primary: '#E74C3C', secondary: '#F39C12', tertiary: '#3498DB', mentioned: '#95A5A6' }; var bounds = []; locations.forEach(function (loc) { if (!loc.lat || !loc.lon) return; var cat = loc.category || 'mentioned'; var color = catColors[cat] || catColors.mentioned; var catClass = 'cat-' + cat; var icon = L.divIcon({ className: 'pulse-marker ' + catClass, iconSize: [12, 12], iconAnchor: [6, 6] }); var marker = L.marker([loc.lat, loc.lon], { icon: icon }).addTo(map); var label = categoryLabels[cat] || cat; marker.bindPopup('' + loc.name + '