Every feature, fix, and upgrade since the first commit —
/teachers/ and /lehrkraefte/ list all 42 tours by school subject. Every tour page now carries a printable worksheet (a task per station, quiz questions, answer key) and a QR code that opens the tour on student devicesgeopulseworld.com/#today/de/touren/… with the German texts, properly paired with the English pages for search engines (hreflang), plus structured data for learning resources, breadcrumbs and FAQs. New pages are reported to Bing and other IndexNow engines automatically/#tour=coldwar waited for the map's load event a second time, but that event only ever fires once. The tour now starts as soon as the data is ready and the visitor has entered — which is also what the 42 tour landing pages link tolayers=earthquakes,fires ticked the boxes, but live layers that load a moment later were created hidden. They are switched on once they existdata/fireballs.json; the same workflow renews the camera index monthly@3 before. Share links only accept known languages and tour ids, and a malformed link can no longer switch sharing offdefer, and tours_loader.js picks up the tour texts when the browser goes idle. Click a tour before that finishes and the click is caught, the texts fetched, and the click replayed — no error, just a short wait/tours/coldwar/) with its stations, description and structured data, plus a sitemap.xml and a robots.txt. Until now a search for "Cold War map" could find nothing here, because there was only ever one URL to find/main.js while the page asked for /main.js?v=2.7. Those never match, so the entire pre-cache sat unused and offline only ever worked by accident. The list is versioned now, the four files it was missing are in it, and a reload without a connection serves the appog:image pointed at a relative path, which most platforms do not resolve. Shared links were arriving blankimg-src and skips any partner camera whose image host isn't allowed, naming the missing host, instead of shipping dead markersscripts/build-camera-index.mjs condenses 3 MB of raw catalogues into a 662 KB index (143 KB gzipped) that loads lazily: never fetched unless the layer is switched on or someone searcheslayer-legend existed twice; every legend write landed in the undocumented copy while the documented one stayed emptyprotected variable to safeText in sentence splitter (JS reserved word caused syntax error)speechSynthesis.cancel() calls now route through stopNarration() to properly clear the sentence queue} in buildWebcamPopup() caused silent syntax error preventing all JS execution.setPopup() pattern for reliable click interaction. Telemetry updates on each open