Fix: Logo-Hintergrund, Scroll-Reveal-Bug, Timeline-Dropdown, UI-Cleanup

- Logo: Blau-grauer Hintergrund für Lesbarkeit auf dunkler Navbar
- Scroll-Reveal Fix: Cards in hidden tabs sofort revealed, nur sichtbare via Observer
- Tab-Wechsel: Reveal-Trigger für Cards im neu aktiven Panel
- Timeline-Dropdown: Aufklappbare Uhrzeiten pro Tag, neuester Tag standardmäßig offen
- Entfernt: FC-Quick-Stats im Hero, Powered-by Badge, CTA-Powered-Text
- CSS: Timeline-Dropdown Styles, unused hero-fc/powered-by Styles entfernt

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Dieser Commit ist enthalten in:
Claude Code
2026-03-07 14:35:50 +01:00
Ursprung 500f6129f1
Commit 23b6a7036d
3 geänderte Dateien mit 174 neuen und 104 gelöschten Zeilen

Datei anzeigen

@@ -1,6 +1,6 @@
/**
* AegisSight Lagebild Page - Dark Theme Design Refresh
* Count-Up, Timeline, Scroll-Reveal, Smooth-Scroll, Favicons
* Count-Up, Timeline mit Dropdown, Scroll-Reveal, Smooth-Scroll, Favicons
*/
/** Feste Zeitzone fuer alle Anzeigen — NIEMALS aendern. */
@@ -11,6 +11,7 @@ var Lagebild = {
allSnapshots: {},
currentView: null,
map: null,
timelineGroups: null,
/* ===== Inline SVG Icons ===== */
icons: {
@@ -18,9 +19,6 @@ var Lagebild = {
fileText: '<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/><line x1="16" y1="13" x2="8" y2="13"/><line x1="16" y1="17" x2="8" y2="17"/></svg>',
globe: '<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><line x1="2" y1="12" x2="22" y2="12"/><path d="M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z"/></svg>',
shieldCheck: '<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/><polyline points="9 12 11 14 15 10"/></svg>',
checkCircle: '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"/><polyline points="22 4 12 14.01 9 11.01"/></svg>',
helpCircle: '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><path d="M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3"/><line x1="12" y1="17" x2="12.01" y2="17"/></svg>',
xCircle: '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><line x1="15" y1="9" x2="9" y2="15"/><line x1="9" y1="9" x2="15" y2="15"/></svg>',
externalLink: '<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"/><polyline points="15 3 21 3 21 9"/><line x1="10" y1="14" x2="21" y2="3"/></svg>'
},
@@ -70,23 +68,6 @@ var Lagebild = {
statsHtml += this.statCard(this.icons.shieldCheck, '<span class="count-up" data-target="' + d.incident.factcheck_count + '">0</span>', 'Faktenchecks');
document.getElementById('hero-stats').innerHTML = statsHtml;
// FC Quick Stats
var checks = d.fact_checks || [];
var stats = { confirmed: 0, unconfirmed: 0, contradicted: 0, developing: 0, established: 0, disputed: 0 };
for (var k = 0; k < checks.length; k++) {
var st = checks[k].status || 'developing';
if (stats[st] !== undefined) stats[st]++;
}
var confirmed = stats.confirmed + stats.established;
var open = stats.unconfirmed + stats.developing;
var contradicted = stats.contradicted + stats.disputed;
var fcHtml = '';
fcHtml += '<span class="fc-quick-badge success">' + this.icons.checkCircle + ' <span class="count-up" data-target="' + confirmed + '">0</span>&nbsp;Bestätigt</span>';
fcHtml += '<span class="fc-quick-badge warning">' + this.icons.helpCircle + ' <span class="count-up" data-target="' + open + '">0</span>&nbsp;Offen</span>';
fcHtml += '<span class="fc-quick-badge error">' + this.icons.xCircle + ' <span class="count-up" data-target="' + contradicted + '">0</span>&nbsp;Widerlegt</span>';
document.getElementById('hero-fc-stats').innerHTML = fcHtml;
// Start count-up animations
var self = this;
requestAnimationFrame(function() {
@@ -149,6 +130,7 @@ var Lagebild = {
});
}
this.timelineGroups = groups;
var dates = Object.keys(groups).sort();
var strip = document.getElementById('timeline-strip');
var h = '';
@@ -190,7 +172,7 @@ var Lagebild = {
}, 150);
}
// Click handler
// Click handler for day buttons
var self = this;
strip.addEventListener('click', function(e) {
var btn = e.target.closest('.timeline-day');
@@ -200,7 +182,13 @@ var Lagebild = {
for (var k = 0; k < allDays.length; k++) allDays[k].classList.remove('active');
btn.classList.add('active');
var dateKey = btn.getAttribute('data-date');
var snapId = btn.getAttribute('data-snapshot-id');
// Show dropdown for this day
self.showTimelineDropdown(dateKey, snapId);
// Load latest snapshot
if (snapId === 'current') {
self.currentView = {
summary: self.data.current_lagebild.summary_markdown,
@@ -214,6 +202,67 @@ var Lagebild = {
self.loadSnapshot(parseInt(snapId));
}
});
// Click handler for dropdown snapshot items (delegated, set up once)
var dropdown = document.getElementById('timeline-dropdown');
dropdown.addEventListener('click', function(e) {
var item = e.target.closest('.timeline-snap-item');
if (!item) return;
var items = dropdown.querySelectorAll('.timeline-snap-item');
for (var k = 0; k < items.length; k++) items[k].classList.remove('active');
item.classList.add('active');
var snapId = item.getAttribute('data-snapshot-id');
if (snapId === 'current') {
self.currentView = {
summary: self.data.current_lagebild.summary_markdown,
sources_json: self.data.current_lagebild.sources_json,
updated_at: self.data.current_lagebild.updated_at || self.data.generated_at,
articles: self.data.articles,
fact_checks: self.data.fact_checks
};
self.renderCurrentView();
} else {
self.loadSnapshot(parseInt(snapId));
}
});
// Show dropdown for newest day by default
var newestDate = dates[dates.length - 1];
if (newestDate && groups[newestDate].length > 1) {
this.showTimelineDropdown(newestDate, groups[newestDate][0].id);
}
},
showTimelineDropdown: function(dateKey, activeSnapId) {
var dropdown = document.getElementById('timeline-dropdown');
var snaps = this.timelineGroups[dateKey];
if (!snaps || snaps.length <= 1) {
dropdown.classList.remove('open');
dropdown.innerHTML = '';
return;
}
var d = new Date(dateKey + 'T12:00:00Z');
var dateLabel = d.toLocaleDateString('de-DE', { day: 'numeric', month: 'long', year: 'numeric', timeZone: 'UTC' });
var h = '<div class="timeline-dropdown-header">' + dateLabel + ' &mdash; ' + snaps.length + ' Updates</div>';
h += '<div class="timeline-snap-list">';
for (var i = 0; i < snaps.length; i++) {
var snap = snaps[i];
var isActive = (String(snap.id) === String(activeSnapId));
h += '<button class="timeline-snap-item' + (isActive ? ' active' : '') + '"';
h += ' data-snapshot-id="' + snap.id + '">';
h += '<span class="timeline-snap-time">' + this.fmtTimeOnly(snap.created_at) + ' Uhr</span>';
h += '<span class="timeline-snap-meta">' + snap.article_count + ' Artikel, ' + snap.fact_check_count + ' FC</span>';
h += '</button>';
}
h += '</div>';
dropdown.innerHTML = h;
dropdown.classList.add('open');
},
toDateKey: function(iso) {
@@ -410,9 +459,12 @@ var Lagebild = {
legend.addTo(this.map);
// Dark popup styling
var style = document.createElement('style');
style.textContent = '.lagebild-page .leaflet-popup-content-wrapper{background:#151D2E;color:#E8ECF4;border:1px solid #1E2D45;border-radius:4px;box-shadow:0 4px 16px rgba(0,0,0,0.4);}.lagebild-page .leaflet-popup-tip{background:#151D2E;}';
document.head.appendChild(style);
if (!document.getElementById('leaflet-dark-style')) {
var style = document.createElement('style');
style.id = 'leaflet-dark-style';
style.textContent = '.lagebild-page .leaflet-popup-content-wrapper{background:#151D2E;color:#E8ECF4;border:1px solid #1E2D45;border-radius:4px;box-shadow:0 4px 16px rgba(0,0,0,0.4);}.lagebild-page .leaflet-popup-tip{background:#151D2E;}';
document.head.appendChild(style);
}
setTimeout(function() { if (Lagebild.map) Lagebild.map.invalidateSize(); }, 300);
},
@@ -493,7 +545,15 @@ var Lagebild = {
this.classList.add('active');
var panels = document.querySelectorAll('.tab-panel');
for (var j = 0; j < panels.length; j++) panels[j].classList.remove('active');
document.getElementById('panel-' + tab).classList.add('active');
var activePanel = document.getElementById('panel-' + tab);
activePanel.classList.add('active');
// Trigger reveal for cards in newly active panel
var revealCards = activePanel.querySelectorAll('.reveal:not(.revealed)');
for (var k = 0; k < revealCards.length; k++) {
revealCards[k].classList.add('revealed');
}
if (tab === 'karte') self.renderMap();
});
}
@@ -535,7 +595,6 @@ var Lagebild = {
initScrollReveal: function() {
var cards = document.querySelectorAll('.content-card, .lagebild-cta');
if (!('IntersectionObserver' in window)) {
// Fallback: show all immediately
for (var i = 0; i < cards.length; i++) cards[i].classList.add('revealed');
return;
}
@@ -550,7 +609,13 @@ var Lagebild = {
for (var i = 0; i < cards.length; i++) {
cards[i].classList.add('reveal');
observer.observe(cards[i]);
// Immediately reveal cards in the active (visible) tab panel
var panel = cards[i].closest('.tab-panel');
if (!panel || panel.classList.contains('active')) {
cards[i].classList.add('revealed');
} else {
observer.observe(cards[i]);
}
}
},
@@ -634,6 +699,15 @@ var Lagebild = {
} catch(e) { return iso; }
},
fmtTimeOnly: function(iso) {
if (!iso) return '';
try {
var d = new Date(this.toUTC(iso));
if (isNaN(d.getTime())) return iso;
return d.toLocaleTimeString('de-DE', { hour: '2-digit', minute: '2-digit', timeZone: TIMEZONE });
} catch(e) { return iso; }
},
fmtShort: function(iso) {
if (!iso) return '';
try { return new Date(this.toUTC(iso)).toLocaleDateString('de-DE', { day: 'numeric', month: 'short', hour: '2-digit', minute: '2-digit', timeZone: TIMEZONE }); }