1<!doctype html> 2<html lang="de"> 3<head> 4 <meta charset="utf-8"> 5 <meta name="viewport" content="width=device-width,initial-scale=1,viewport-fit=cover"> 6 <title>Meteozentrale App: Wetter, Warnungen & Regenradar</title> 7 <meta name="description" content="Wetter für Ihren Ort: aktuelle Warnungen, Regenradar, Pollen und 14-Tage-Trend. Meteozentrale-App kostenlos im Browser öffnen und Ihren Wetterort speichern."> 8 <meta name="theme-color" content="#07111f"> 9 <meta name="robots" content="index,follow,max-image-preview:large,max-snippet:-1,max-video-preview:-1"> 10 <meta name="application-name" content="Meteozentrale App"> 11 <meta name="mobile-web-app-capable" content="yes"> 12 <meta name="apple-mobile-web-app-capable" content="yes"> 13 <meta name="apple-mobile-web-app-title" content="Meteozentrale App"> 14 <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent"> 15 <meta property="og:type" content="website"> 16 <meta property="og:locale" content="de_DE"> 17 <meta property="og:site_name" content="Meteozentrale"> 18 <meta property="og:title" content="Meteozentrale App: Wetter, Warnungen & Regenradar"> 19 <meta property="og:description" content="Wetter für Ihren Ort: aktuelle Warnungen, Regenradar, Pollen und 14-Tage-Trend. Meteozentrale-App kostenlos im Browser öffnen und Ihren Wetterort speichern."> 20 <meta property="og:url" content="https://meteozentrale.de/app/"> 21 <meta property="og:image" content="https://meteozentrale.de/assets/pwa/screenshot-app-home.png"> 22 <meta property="og:image:width" content="1280"> 23 <meta property="og:image:height" content="720"> 24 <meta property="og:image:alt" content="Meteozentrale App Wetter-Cockpit mit Live-Lage und Warnsignalen"> 25 <meta name="twitter:card" content="summary_large_image"> 26 <meta name="twitter:title" content="Meteozentrale App: Wetter, Warnungen & Regenradar"> 27 <meta name="twitter:description" content="Wetter für Ihren Ort: aktuelle Warnungen, Regenradar, Pollen und 14-Tage-Trend. Meteozentrale-App kostenlos im Browser öffnen und Ihren Wetterort speichern."> 28 <meta name="twitter:image" content="https://meteozentrale.de/assets/pwa/screenshot-app-home.png"> 29 <link rel="canonical" href="https://meteozentrale.de/app/"> 30 <link rel="alternate" type="text/plain" title="KI-Kurzprofil der Meteozentrale App" href="/llms.txt"> 31 <link rel="manifest" href="/manifest.webmanifest"> 32 <link rel="apple-touch-icon" href="/assets/pwa/icons/meteozentrale-app-apple-180.png"> 33 <link rel="stylesheet" href="/assets/pwa/app-v51.css?v=51.3.0"> 34
34<script type="application/ld+json"> 35{ 36 "@context": "https://schema.org", 37 "@graph": [ 38 { 39 "@type": "Organization", 40 "@id": "https://meteozentrale.de/#organization", 41 "name": "Meteozentrale", 42 "url": "https://meteozentrale.de/", 43 "logo": { 44 "@type": "ImageObject", 45 "url": "https://meteozentrale.de/assets/pwa/icons/meteozentrale-app-512.png", 46 "width": 512, 47 "height": 512 48 } 49 }, 50 { 51 "@type": "WebSite", 52 "@id": "https://meteozentrale.de/#website", 53 "name": "Meteozentrale.de", 54 "url": "https://meteozentrale.de/", 55 "inLanguage": "de-DE", 56 "publisher": { 57 "@id": "https://meteozentrale.de/#organization" 58 }, 59 "potentialAction": { 60 "@type": "SearchAction", 61 "target": "https://meteozentrale.de/?s={search_term_string}", 62 "query-input": "required name=search_term_string" 63 } 64 }, 65 { 66 "@type": "WebPage", 67 "@id": "https://meteozentrale.de/app/#webpage", 68 "url": "https://meteozentrale.de/app/", 69 "name": "Meteozentrale App: Wetter, Warnungen & Regenradar", 70 "description": "Wetter für Ihren Ort: aktuelle Warnungen, Regenradar, Pollen und 14-Tage-Trend. Meteozentrale-App kostenlos im Browser öffnen und Ihren Wetterort speichern.", 71 "isPartOf": { 72 "@id": "https://meteozentrale.de/#website" 73 }, 74 "primaryImageOfPage": { 75 "@id": "https://meteozentrale.de/app/#primaryimage" 76 }, 77 "mainEntity": { 78 "@id": "https://meteozentrale.de/app/#webapp" 79 }, 80 "dateModified": "2026-10-02T19:50:47+02:00", 81 "inLanguage": "de-DE" 82 }, 83 { 84 "@type": "ImageObject", 85 "@id": "https://meteozentrale.de/app/#primaryimage", 86 "url": "https://meteozentrale.de/assets/pwa/screenshot-app-home.png", 87 "width": 1280, 88 "height": 720, 89 "caption": "Meteozentrale App Wetter-Cockpit mit Live-Lage, Warnsignalen und Ortswetter." 90 }, 91 { 92 "@type": [ 93 "WebApplication", 94 "SoftwareApplication" 95 ], 96 "@id": "https://meteozentrale.de/app/#webapp", 97 "name": "Meteozentrale App", 98 "alternateName": [ 99 "Meteozentrale PWA", 100 "Meteozentrale Mein Wetter" 101 ], 102 "url": "https://meteozentrale.de/app/", 103 "installUrl": "https://meteozentrale.de/app/", 104 "description": "Wetter für Ihren Ort: aktuelle Warnungen, Regenradar, Pollen und 14-Tage-Trend. Meteozentrale-App kostenlos im Browser öffnen und Ihren Wetterort speichern.", 105 "image": "https://meteozentrale.de/assets/pwa/screenshot-app-home.png", 106 "thumbnailUrl": "https://meteozentrale.de/assets/pwa/icons/meteozentrale-app-512.png", 107 "applicationCategory": "LifestyleApplication", 108 "applicationSubCategory": "WeatherApplication", 109 "operatingSystem": "Android, iOS, Windows, macOS, Linux", 110 "browserRequirements": "Moderner Browser mit JavaScript, LocalStorage, Web-App-Manifest und optionalem Standortzugriff.", 111 "softwareVersion": "81.8", 112 "isAccessibleForFree": true, 113 "inLanguage": "de-DE", 114 "publisher": { 115 "@id": "https://meteozentrale.de/#organization" 116 }, 117 "provider": { 118 "@id": "https://meteozentrale.de/#organization" 119 }, 120 "offers": { 121 "@type": "Offer", 122 "price": "0", 123 "priceCurrency": "EUR", 124 "availability": "https://schema.org/InStock", 125 "url": "https://meteozentrale.de/app/" 126 }, 127 "featureList": [ 128 "Installierbare Progressive Web App ohne Play-Store-Pflicht", 129 "Gespeicherter Wetter-Ort mit direkten Meteozentrale-Modulen", 130 "Live-Lage mit Datenstand, Warnsignalen und regionalem Warnzentrum", 131 "SkyGuard Stormtracker mit konservativem Radar-/Ortsabgleich ohne Zelltrajektorien- oder Ankunftsgarantie", 132 "72-Stunden-Pollenprognose und mehrstufiger Live-Daten-Fallback mit klar gekennzeichneter Reserve",
133 "MOSMIX-Wahrscheinlichkeiten, Dauerregen, Schnee, Glätte, Frost und regionale Warnzentrum-Karte", 134 "Optionaler Agrarblick mit modellierter Bodenfeuchte, Wasserbilanz, Spritzfenster und witterungsbedingter Befahrbarkeit", 135 "Optionale Push-Nachrichten und datensparsame Analytics mit Consent" 136 ], 137 "screenshot": [ 138 { 139 "@type": "ImageObject", 140 "url": "https://meteozentrale.de/assets/pwa/screenshot-app-home.png", 141 "width": 1280, 142 "height": 720 143 } 144 ], 145 "audience": { 146 "@type": "Audience", 147 "audienceType": "Menschen, Landwirtschaft, Kommunen, Einsatzplanung und Wetterinteressierte in Deutschland" 148 }, 149 "about": [ 150 { 151 "@type": "Thing", 152 "name": "Wetterwarnung" 153 }, 154 { 155 "@type": "Thing", 156 "name": "Unwetter" 157 }, 158 { 159 "@type": "Thing", 160 "name": "Regenradar" 161 }, 162 { 163 "@type": "Thing", 164 "name": "Agrarwetter" 165 }, 166 { 167 "@type": "Thing", 168 "name": "Progressive Web App" 169 } 170 ] 171 } 172 ] 173} </script>
173 174
174<script> 175 window.mzLoadWebpushr = function(){ 176 if (window.MZ_WEBPUSHR_LOAD_PROMISE) return window.MZ_WEBPUSHR_LOAD_PROMISE; 177 window.MZ_WEBPUSHR_LOAD_PROMISE = new Promise(function(resolve, reject){ 178 window.webpushr = window.webpushr || function(){ (window.webpushr.q = window.webpushr.q || []).push(arguments); }; 179 window.webpushr('setup', {'key':'BHaKHu4UT8Uuju1yAHj_XONQiF1yPVFcW1kigczkHkaRwbR-hJsaZNaCBivfBwcaQTLtPZdo24cA0PiLDFhcuVg'}); 180 var js = document.createElement('script'); 181 js.id = 'webpushr-jssdk'; 182 js.async = true; 183 js.src = 'https://cdn.webpushr.com/app.min.js'; 184 js.onload = function(){ window.MZ_WEBPUSHR_READY = true; resolve(true); }; 185 js.onerror = function(){ reject(new Error('Push-Dienst konnte nicht geladen werden.')); }; 186 document.head.appendChild(js); 187 }); 188 return window.MZ_WEBPUSHR_LOAD_PROMISE; 189 }; 190 </script>
190 191
191<script> 192 window.MZ_ANALYTICS_ID = "G-1MMGHXXRHP"; 193 window.MZ_APP_VERSION = 'v81.8-bericht-interaktion'; 194 window.dataLayer = window.dataLayer || []; 195 function gtag(){ window.dataLayer.push(arguments); } 196 197 (function(){ 198 var storedConsent = null; 199 try { storedConsent = localStorage.getItem('mz_analytics_consent_v1'); } catch(e) {} 200 var analyticsConsent = storedConsent === 'granted' ? 'granted' : 'denied'; 201 202 gtag('consent', 'default', { 203 'analytics_storage': analyticsConsent, 204 'ad_storage': 'denied', 205 'ad_user_data': 'denied', 206 'ad_personalization': 'denied', 207 'wait_for_update': 500 208 }); 209 gtag('js', new Date()); 210 gtag('config', window.MZ_ANALYTICS_ID, { 211 'send_page_view': false, 212 'page_title': "Meteozentrale App: Wetter, Warnungen & Regenradar", 213 'page_path': location.pathname + location.search, 214 'page_location': location.href, 215 'app_version': window.MZ_APP_VERSION, 216 'transport_type': 'beacon' 217 }); 218 })(); 219 </script>
vendor: 66 bytes, lines 219-220
219 220 <script async src="https://www.googletagmanager.com/gtag/js?id=
220G-1MMGHXXRHP
vendor: 14 bytes, lines 220-221
220"></script> 221
221<style> 222 .mz-analytics-consent{position:fixed;left:max(12px,env(safe-area-inset-left));right:max(12px,env(safe-area-inset-right));bottom:max(12px,env(safe-area-inset-bottom));z-index:99999;display:none;gap:12px;align-items:center;justify-content:space-between;border:1px solid rgba(148,163,184,.28);background:linear-gradient(180deg,rgba(15,23,42,.97),rgba(2,6,23,.97));box-shadow:0 18px 55px rgba(0,0,0,.45);border-radius:22px;padding:14px;color:#e5f7ff;font-family:Inter,system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif}.mz-analytics-consent.is-visible{display:flex}.mz-analytics-consent strong{display:block;margin-bottom:3px}.mz-analytics-consent span{display:block;color:#b6c5d8;font-size:13px;line-height:1.45}.mz-analytics-consent .mz-ac-actions{display:flex;gap:8px;flex:0 0 auto}.mz-analytics-consent button{border:1px solid rgba(148,163,184,.28);border-radius:999px;padding:10px 13px;font-weight:900;cursor:pointer}.mz-analytics-consent [data-analytics-accept]{background:#22d3ee;color:#04111d;border-color:transparent}.mz-analytics-consent [data-analytics-decline]{background:rgba(255,255,255,.06);color:#e5f7ff}prompticon3,promptpopup,#webpushr-notification-card-wrapper{display:none!important}@media(max-width:640px){.mz-analytics-consent{align-items:stretch;flex-direction:column;bottom:calc(78px + env(safe-area-inset-bottom))}.mz-analytics-consent .mz-ac-actions{display:grid;grid-template-columns:1fr 1fr}.mz-analytics-consent button{width:100%;min-height:44px}} 223 .quick-place-panel-v19{grid-template-columns:minmax(0,1fr)}.quick-place-panel-v19 .quick-actions{grid-template-columns:repeat(4,minmax(0,1fr));width:100%}.quick-place-panel-v19 .quick-actions a{min-width:0;white-space:normal}.quick-place-panel-v19 p{max-width:72ch}@media(max-width:700px){.quick-place-panel-v19 .quick-actions{grid-template-columns:repeat(2,minmax(0,1fr))}} 224 .mz-community-invite{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:12px 16px;margin:0 0 16px;border:1px solid rgba(34,211,238,.35);border-radius:14px;background:rgba(8,80,101,.28);font-size:14px}.mz-community-invite span{color:#d0dfeb}.mz-community-invite a{display:inline-flex;align-items:center;min-height:36px;color:#67e8f9;font-weight:800;text-decoration:none}.mz-community-invite a:focus-visible{outline:3px solid #fbbf24;outline-offset:3px} 225 .mz-community-panel{display:flex;align-items:center;justify-content:space-between;gap:24px;margin:0 0 20px;padding:24px;border:1px solid rgba(34,211,238,.42);border-radius:24px;background:linear-gradient(120deg,rgba(8,80,101,.48),rgba(15,23,42,.95));color:#e5f7ff} 226 .mz-community-copy{min-width:0;max-width:720px}.mz-community-copy h2{margin:8px 0;font-size:clamp(21px,3vw,28px);line-height:1.2}.mz-community-copy p{margin:0 0 10px;color:#d0dfeb;line-height:1.55}.mz-community-copy small{color:#aebfd0} 227 .mz-community-actions{display:flex;flex-direction:column;gap:10px;flex:0 0 auto}.mz-community-actions a{display:flex;align-items:center;justify-content:center;gap:8px;min-height:46px;padding:12px 16px;border:1px solid rgba(148,163,184,.35);border-radius:14px;color:#e5f7ff;text-decoration:none;font-weight:700;text-align:center}.mz-community-actions .mz-community-primary{background:#22d3ee;border-color:#22d3ee;color:#04111d}.quick-actions a.mz-community-quick{border-color:#22d3ee;color:#a5f3fc}.mz-community-actions a:focus-visible,.mz-community-quick:focus-visible{outline:3px solid #fbbf24;outline-offset:3px} 228 @media(max-width:760px){.mz-community-panel{align-items:stretch;flex-direction:column;gap:16px;padding:20px}.mz-community-actions{width:100%}} 229 </style> 230 <!-- Wetterberichte: isolierte WordPress-Leseansicht, 2026-09-08 --> 231 <link rel="stylesheet" href="/app/mz-articles-v2.css?v=20260908-2"> 232<style> 233 234/* Report views and likes. */ 235.mz-report-engagement{margin:22px 0;padding:16px;border:1px solid #355169;border-radius:16px;background:linear-gradient(135deg,#101f2e,#0d1824);box-shadow:0 12px 28px rgba(0,0,0,.18)} 236.mz-report-engagement-actions{display:flex;align-items:stretch;gap:12px;flex-wrap:wrap} 237.mz-report-view-stat,.mz-report-like{display:inline-flex;align-items:center;justify-content:center;gap:8px;min-height:46px;padding:10px 14px;border-radius:13px;font-size:15px;font-weight:750} 238.mz-report-view-stat{border:1px solid #3b5268;background:#132536;color:#d9e8f4} 239.mz-report-view-stat strong,.mz-report-like strong{font-variant-numeric:tabular-nums;font-size:16px} 240.mz-report-engagement-icon{font-size:18px;line-height:1} 241.mz-report-like{border:1px solid #735064;background:#291b28;color:#ffe7f0;cursor:pointer;transition:background .18s ease,border-color .18s ease,transform .18s ease} 242.mz-report-like:hover{border-color:#f472a7;background:#3a2032;transform:translateY(-1px)} 243.mz-report-like.is-liked,.mz-report-like[aria-pressed="true"]{border-color:#fb7185;background:#5b2035;color:#fff} 244.mz-report-like-heart{font-size:21px;line-height:1;color:#fb7185}.mz-report-like.is-liked .mz-report-like-heart{color:#fff} 245.mz-report-engagement-status{margin:10px 2px 0!important;color:#9fb4c5!important;font-size:12px!important;line-height:1.45!important} 246.mz-report-engagement-status[data-tone="success"]{color:#86efac!important}.mz-report-engagement-status[data-tone="error"]{color:#fda4af!important} 247@media(max-width:600px){.mz-report-engagement{padding:14px}.mz-report-engagement-actions{display:grid;grid-template-columns:1fr 1fr}.mz-report-view-stat,.mz-report-like{min-width:0;padding:10px 8px;font-size:13px}} 248 249</style> 250</head> 251<body> 252 <div class="mz-analytics-consent" data-analytics-consent role="dialog" aria-live="polite" aria-label="Analyse-Einstellungen"> 253 <div> 254 <strong>App besser machen?</strong>
255 <span>Mit deiner Zustimmung messen wir anonymisierte Nutzung: welche Module geöffnet werden, ob die Lagekarte hilft und wo die App verbessert werden muss. GPS-Koordinaten werden nicht an Analytics gesendet.</span> 256 </div> 257 <div class="mz-ac-actions"> 258 <button type="button" data-analytics-decline>Nein</button> 259 <button type="button" data-analytics-accept>Einverstanden</button> 260 </div> 261 </div> 262 <div class="mz-app" id="app-start" data-place-root> 263 <header class="app-top"> 264 <a class="brand" href="/app/" aria-label="Meteozentrale App Startseite"> 265 <span class="brand-dot" aria-hidden="true"></span> 266 <span><span class="brand-title">Meteozentrale</span><br><span class="brand-sub">Mein Wetter</span></span> 267 </a> 268 <div class="top-actions"> 269 <button class="install-btn" type="button" data-install-app>Installieren</button> 270 <button class="view-settings-btn" type="button" data-view-settings-open aria-haspopup="dialog">Einstellungen</button> 271 <a class="pill website-link" href="/">Zur Website</a> 272 </div> 273 </header> 274 275 <nav class="app-bottom-nav" aria-label="Hauptnavigation"> 276 <a href="#app-start"><span aria-hidden="true">â</span><b>Start</b></a> 277 <a data-module="meteoz" data-needs-place href="/meteo/meteoz.php"><span aria-hidden="true">â </span><b>Warnungen</b></a> 278 <a data-module="forecast5" data-needs-place href="/meteo/5tage.php"><span aria-hidden="true">â¦</span><b>5 Tage</b></a> 279 <a data-module="meteogram" data-needs-place href="/meteo/meteogram.php"><span aria-hidden="true">ð</span><b>14 Tage</b></a> 280 <button type="button" data-main-menu-open><span aria-hidden="true">â·</span><b>Menü</b></button> 281 </nav> 282 283 <div class="browser-notice" data-browser-notice hidden> 284 <strong>Bitte im normalen Browser oeffnen</strong> 285 <span>Facebook, Instagram und manche Messenger blockieren GPS, Push und App-Installation. Oeffne diesen Link in Safari, Chrome oder dem Huawei-Browser.</span> 286 <a data-browser-url href="/app/">App-Link</a> 287 </div> 288 289 <div class="mz-community-invite mz-weather-content"><span><span aria-hidden="true">ð·</span> Dein Wetter zählt</span><a data-community-entry="kopf" href="/wettermelder/#mitmachen">Jetzt melden â</a></div> 290 291 <section class="start-grid-v19" aria-label="Persönliches Wetter und Warnungen"> 292 <section class="live-start-v11 live-start-v18 live-start-v19" data-live-root data-live-version="19" data-live-state="empty" aria-label="Live-Lage für gespeicherten Ort"> 293 <article class="live-main"> 294 <div class="live-kicker-row"> 295 <span class="eyebrow live-eyebrow">Dein Wetter</span> 296 <span class="live-updated" data-live-updated>Ort speichern, dann laden wir den ersten Blick.</span> 297 </div> 298 <div class="live-topline"> 299 <span class="live-badge" data-live-level>Warnstatus</span> 300 <span class="live-place-pill">für <strong data-place-name>deinen Ort</strong></span> 301 </div> 302 <div class="platinum-status" data-platinum-status data-platinum-level="empty"> 303 <div class="platinum-main"> 304 <span class="platinum-kicker" data-platinum-kicker>Warnstatus</span> 305 <strong data-platinum-title>Speichere deinen Ort für den persönlichen Wetterblick.</strong> 306 <p data-platinum-copy>Danach siehst du sofort, ob die Lage grün bleibt oder ob Wetter, Umwelt oder Mobilität wirklich wichtig werden.</p> 307 </div> 308 <div class="platinum-metrics" aria-label="Kurzstatus"> 309 <span><b data-platinum-signal>wartet</b><small>Status</small></span> 310 <span><b data-platinum-window>nach Ort</b><small>Zeitfenster</small></span> 311 <span><b data-platinum-update>--</b><small>Stand</small></span> 312 </div> 313 <div class="platinum-actions"> 314 <a data-platinum-primary data-module="hours24" data-needs-place href="/meteo/24stunden.php">Ortswetter</a> 315 <a data-platinum-secondary data-module="skyguard" data-needs-place href="/meteo/">SkyGuard</a> 316 </div> 317 </div> 318 <div class="live-radar-note" data-live-radar-note hidden>
319 <span>Regenradar</span> 320 <strong data-live-radar-note-text>Der Sofortblick wird geladen</strong> 321 </div> 322 <div class="focus-headline" data-focus-headline> 323 <span>Lageblick</span> 324 <strong>Was heute wirklich wichtig ist</strong> 325 </div> 326 <div class="signal-board" data-signal-board aria-label="Parameterstatus"> 327 <a class="signal-card is-empty" data-signal-card="warning" data-module="meteoz" data-needs-place href="/meteo/meteoz.php"> 328 <span>â ï¸ Warnung</span><strong data-signal-state="warning">wartet</strong><small data-signal-detail="warning">Ort speichern</small> 329 </a> 330 <a class="signal-card is-empty" data-signal-card="thunder" data-module="meteoz" data-needs-place href="/meteo/meteoz.php"> 331 <span>âï¸ Gewitter</span><strong data-signal-state="thunder">wartet</strong><small data-signal-detail="thunder">Ort speichern</small> 332 </a> 333 <a class="signal-card is-empty" data-signal-card="rain" data-module="niederschlag" data-needs-place href="/niederschlag/"> 334 <span>ð§ï¸ Regen</span><strong data-signal-state="rain">wartet</strong><small data-signal-detail="rain">Ort speichern</small> 335 </a> 336 <a class="signal-card is-empty" data-signal-card="rain_radar" data-module="niederschlag" data-needs-place href="/niederschlag/"> 337 <span>ð¡ Regenradar</span><strong data-signal-state="rain_radar">wartet</strong><small data-signal-detail="rain_radar">Ort speichern</small> 338 </a> 339 <a class="signal-card is-empty" data-signal-card="flash_flood" data-module="niederschlag" data-needs-place href="/niederschlag/"> 340 <span>ð Sturzflut</span><strong data-signal-state="flash_flood">wartet</strong><small data-signal-detail="flash_flood">Ort speichern</small> 341 </a> 342 <a class="signal-card is-empty" data-signal-card="continuous_rain" data-module="niederschlag" data-needs-place href="/niederschlag/"> 343 <span>â Dauerregen</span><strong data-signal-state="continuous_rain">wartet</strong><small data-signal-detail="continuous_rain">Ort speichern</small> 344 </a> 345 <a class="signal-card is-empty" data-signal-card="wind" data-module="sturm" data-needs-place href="/sturmwarnung/"> 346 <span>ðªï¸ Wind</span><strong data-signal-state="wind">wartet</strong><small data-signal-detail="wind">Ort speichern</small> 347 </a> 348 <a class="signal-card is-empty" data-signal-card="heat" data-module="meteoz" data-needs-place href="/meteo/meteoz.php"> 349 <span>ð¡ï¸ Wärme</span><strong data-signal-state="heat">wartet</strong><small data-signal-detail="heat">Ort speichern</small> 350 </a> 351 <a class="signal-card is-empty" data-signal-card="snow" data-module="hours24" data-needs-place href="/meteo/24stunden.php"> 352 <span>âï¸ Schnee</span><strong data-signal-state="snow">wartet</strong><small data-signal-detail="snow">Ort speichern</small> 353 </a> 354 <a class="signal-card is-empty" data-signal-card="ice" data-module="meteoz" data-needs-place href="/meteo/meteoz.php"> 355 <span>ð§ Glätte</span><strong data-signal-state="ice">wartet</strong><small data-signal-detail="ice">Ort speichern</small> 356 </a> 357 <a class="signal-card is-empty" data-signal-card="frost" data-module="hours24" data-needs-place href="/meteo/24stunden.php"> 358 <span>𥶠Frost</span><strong data-signal-state="frost">wartet</strong><small data-signal-detail="frost">Ort speichern</small> 359 </a> 360 </div> 361 <button type="button" class="signal-toggle" data-signal-toggle aria-expanded="false">Weitere Wetterdetails anzeigen</button> 362 <div class="live-sources" data-live-sources hidden> 363 <span>Regenradar:</span> 364 <a data-live-radar-source href="https://morgenwirdes.de/" target="_blank" rel="noopener noreferrer">Morgenwirdes.de</a>
365 <span>Datenquelle: Deutscher Wetterdienst</span> 366 </div> 367 <div class="live-reasons" data-live-reasons></div> 368 <div class="live-actions"> 369 <a class="live-primary-link" data-live-primary data-module="hours24" data-needs-place href="/meteo/24stunden.php">Tagesverlauf öffnen</a> 370 <a class="live-secondary-link" data-module="skyguard" data-needs-place href="/meteo/">SkyGuard live</a> 371 <a class="live-secondary-link" data-module="meteoz" data-needs-place href="/meteo/meteoz.php">Unwetter-Index</a> 372 </div> 373 </article> 374 <aside class="live-side"> 375 <div class="live-kpi live-current"> 376 <span>Jetzt</span> 377 <strong data-live-temp>â</strong> 378 <small data-live-weather>Live-Wetter wird geladen</small> 379 </div> 380 <div class="live-kpi"> 381 <span>Regen</span> 382 <strong data-live-rain>â</strong> 383 <small data-live-rain-sub>nächste Stunden</small> 384 </div> 385 <div class="live-kpi"> 386 <span>Wind</span> 387 <strong data-live-gust>â</strong> 388 <small data-live-gust-sub>Windspitzen</small> 389 </div> 390 <div class="live-kpi"> 391 <span>Warnungen</span> 392 <strong data-live-warning>â</strong> 393 <small data-live-warning-sub>Radar/Warnlage prüfen</small> 394 </div> 395 </aside> 396 <article class="live-report" aria-label="Textlicher Lagebericht"> 397 <div class="live-report-head"><span>Textlicher Lagebericht</span><small>für <strong data-place-name>deinen Ort</strong></small></div> 398 <h2 data-live-headline>Noch keine Live-Lage geladen.</h2> 399 <p data-live-summary>Speichere einen Ort oder nutze GPS. Danach erscheint hier eine verständliche Zusammenfassung der aktuellen und kommenden Wetterlage.</p> 400 </article> 401 <div class="live-timeline" data-live-timeline aria-label="Nächste sechs Stunden"></div> 402 </section> 403 404 <aside class="place-card place-card-v19" id="mein-ort" data-place-search aria-label="Mein gespeicherter Wetterort"> 405 <div class="place-status"><span class="pulse-dot"></span><span>Mein Wetter-Ort</span></div> 406 <h2 data-place-name>Noch kein Ort gespeichert</h2> 407 <p data-place-sub>Speichere einen Ort oder nutze GPS. Danach öffnen sich alle Wetterwerkzeuge direkt für diesen Ort.</p> 408 <form class="place-form" data-place-form> 409 <input name="ort" autocomplete="postal-code address-level2" placeholder="Ort oder PLZ, z. B. Büdingen, 63654 oder Köln" aria-label="Ort oder PLZ speichern"> 410 <button type="submit" data-place-submit>Ort speichern</button> 411 </form> 412 <div class="place-results" data-place-results hidden></div> 413 <div class="place-actions"> 414 <button type="button" data-place-gps>GPS nutzen</button> 415 <button type="button" data-place-manager-open>Orte verwalten <span data-place-count-badge>0</span></button> 416 </div> 417 <p class="location-message" data-location-message hidden></p> 418 <div class="privacy-note">Speicherung erfolgt lokal auf diesem Gerät â mit zusätzlicher lokaler Sicherung, damit dein Ort nach einem Neustart erhalten bleibt. Nur wenn du CellWarn-Push für ausgewählte Orte aktivierst, werden deren Koordinaten zusätzlich auf Meteozentrale gespeichert.</div> 419 </aside> 420 </section> 421 422 <section class="mz-community-panel mz-weather-content" aria-labelledby="mz-community-title" id="app-wettermelder"> 423 <div class="mz-community-copy"> 424 <span class="eyebrow small">Wettermelder · Gemeinsam das Wetter beobachten</span> 425 <h2 id="mz-community-title">Wie ist das Wetter gerade bei dir?</h2> 426 <p>Sonne, Regen oder ein besonderer Himmel? Teile deine Beobachtung mit der Community. Auch eine kurze Meldung ohne Foto hilft.</p> 427 <small>Entdecke freigegebene Meldungen und Fotos aus den letzten 24 Stunden.</small> 428 </div> 429 <div class="mz-community-actions"> 430 <a class="mz-community-primary" data-community-entry="start_melden" href="/wettermelder/#mitmachen"><span aria-hidden="true">ð·</span> Jetzt Wetter melden</a> 431 <a data-community-entry="start_ansehen" href="/wettermelder/">Meldungen & Fotos ansehen â</a> 432 </div> 433 </section> 434 435 <section class="quick-place-panel quick-place-panel-v19" aria-label="Schnellzugriff"> 436 <div>
437 <span class="eyebrow small">Schnellzugriff</span> 438 <h2>Was möchtest du wissen?</h2> 439 <p>Die wichtigsten Bereiche bleiben schnell erreichbar. Die App hebt zusätzlich automatisch hervor, was für deinen Ort gerade wirklich zählt.</p> 440 </div> 441 <div class="quick-actions" data-priority-actions> 442 <a class="mz-community-quick" data-community-entry="schnellzugriff" href="/wettermelder/#mitmachen"><span aria-hidden="true">ð·</span> Wetter melden</a> 443 <a data-module="meteoz" data-needs-place href="/meteo/meteoz.php"><span aria-hidden="true">â </span> Warnungen</a> 444 <a data-module="niederschlag" data-needs-place href="/niederschlag/"><span aria-hidden="true">â</span> Radar & Regen</a> 445 <a data-module="forecast5" data-needs-place href="/meteo/5tage.php"><span aria-hidden="true">â¦</span> 5 Tage</a> 446 <a data-module="meteogram" data-needs-place href="/meteo/meteogram.php"><span aria-hidden="true">ð</span> 14 Tage</a> 447 <a href="#regionale-lage" data-security-panel-open><span aria-hidden="true">â</span>
447 Karte</a> 448 <a href="#app-alltagsblick"><span aria-hidden="true">â</span> Alltag</a> 449 <a href="#app-agrarblick" data-agro-open aria-controls="app-agrarblick" aria-expanded="false"><span aria-hidden="true">ð±</span> Agrar</a> 450 </div> 451 </section> 452 453 <section class="agro-panel" id="app-agrarblick" data-agro-root data-agro-state="empty" data-agro-level="0" hidden aria-label="Agrarwetter für den gespeicherten Ort" aria-live="polite"> 454 <div class="agro-head"> 455 <div> 456 <span class="eyebrow small agro-eyebrow">Agrarblick</span> 457 <h2>Was ist auf dem Feld wirklich wichtig?</h2> 458 </div> 459 <div class="agro-head-actions"> 460 <small data-agro-place>nach Ort</small> 461 <button type="button" class="agro-close" data-agro-close aria-label="Agrarblick schlieÃen">SchlieÃen</button> 462 </div> 463 </div> 464 <div class="agro-focus"> 465 <div class="agro-focus-copy"> 466 <span data-agro-kicker>Landwirtschaftliche Entscheidungshilfe</span> 467 <h3 data-agro-headline>Ort speichern, dann bewertet die App das nächste Arbeitsfenster.</h3> 468 <p data-agro-summary>Du siehst zuerst nur die wichtigste Aussage. Bodenmodell, Wasserbilanz und Wetterdetails bleiben darunter einklappbar.</p> 469 </div> 470 <div class="agro-confidence"> 471 <span>Einordnung</span> 472 <strong data-agro-confidence>wartet auf Ort</strong> 473 <small>Modellwerte ersetzen keine Schlagkontrolle.</small> 474 </div> 475 </div> 476 <div class="agro-decisions" aria-label="Agrar-Entscheidungen"> 477 <article data-agro-card="spray"> 478 <span>Pflanzenschutz</span> 479 <strong data-agro-spray-status>â</strong> 480 <small data-agro-spray-detail>Wetterfenster nach Ortswahl</small> 481 </article> 482 <article data-agro-card="traffic"> 483 <span>Befahren</span> 484 <strong data-agro-traffic-status>â</strong> 485 <small data-agro-traffic-detail>Witterungsrisiko nach Ortswahl</small> 486 </article> 487 <article data-agro-card="water"> 488 <span>Wasserbilanz 24h</span> 489 <strong data-agro-water-status>â</strong> 490 <small data-agro-water-detail>Niederschlag minus Referenzverdunstung</small> 491 </article> 492 </div> 493 <button type="button" class="agro-details-toggle" data-agro-details-toggle aria-expanded="false">Boden & Wasser ansehen</button> 494 <div class="agro-details" data-agro-details hidden> 495 <article> 496 <span>Oberboden 3â9 cm</span> 497 <strong data-agro-soil-surface>â</strong> 498 <small data-agro-soil-surface-detail>standortnaher Modellwert</small> 499 </article> 500 <article> 501 <span>Boden 9â81 cm</span> 502 <strong data-agro-soil-root>â</strong> 503 <small data-agro-soil-root-detail>nicht kulturspezifisch</small> 504 </article> 505 <article> 506 <span>Bodentemperatur 6 cm</span> 507 <strong data-agro-soil-temp>â</strong> 508 <small>für Aussaat und Entwicklung</small> 509 </article> 510 <article> 511 <span>Referenzverdunstung</span> 512 <strong data-agro-et0>â</strong> 513 <small>ETâ der nächsten 24 Stunden</small> 514 </article> 515 </div> 516 <p class="agro-disclaimer" data-agro-disclaimer>Bodenfeuchte und Befahrbarkeit sind Modellorientierungen ohne Schlag-, Bodenart- oder Sensorkalibrierung. Vor-Ort-Prüfung und Produktauflagen gehen immer vor.</p> 517 <p class="agro-source">Wetter- und Bodenmodell über <a href="https://open-meteo.com/" target="_blank" rel="noopener noreferrer">Open-Meteo</a>.</p> 518 </section> 519 520 521 <section class="security-map-panel" id="regionale-lage" data-security-map-root data-radius="50" aria-label="Regionale Lagekarte"> 522 <div class="security-map-head"> 523 <div> 524 <span class="eyebrow small">Warnzentrum im Umkreis</span> 525 <h2>Welche Warnlage gilt rund um <span data-place-name>deinen Ort</span>?</h2> 526 <p data-security-summary>Speichere einen Ort. Danach zeigt die App nur relevante Meldungen aus deiner Umgebung: Bevölkerungsschutz, Hochwasser, Polizei, Wetter ab Orange, Luftqualität und Bahn.</p> 527 </div> 528 <button type="button" class="section-toggle map-panel-toggle" data-security-panel-toggle aria-expanded="false">Karte anzeigen</button> 529 </div> 530 <div class="security-map-body" data-security-panel-body hidden> 531 <div class="security-map-actions"> 532 <button type="button" data-security-radius="25">25 km</button> 533 <button type="button" data-security-radius="50" aria-pressed="true">50 km</button> 534 <button type="button" data-security-radius="100">100 km</button> 535 <button type="button" data-security-details-toggle aria-expanded="false">Meldungsdetails</button> 536 <button type="button" data-security-districts aria-pressed="false">Landkreise</button> 537 <a data-security-open data-module="warnzentrum" data-needs-place href="/warnzentrum/">
537Regionales Warnzentrum öffnen</a> 538 </div> 539 </div> 540 <div class="security-map-shell"> 541 <div class="security-map" data-security-map aria-label="Karte für Bund, Hochwasser, Polizei, Wetter und optionale Landkreise"></div> 542 <div class="security-map-overlay" data-security-empty> 543 <strong>Ort speichern, Karte startet automatisch.</strong> 544 <span>Die App zeigt dann deinen Ort, den Umkreis, relevante Meldungen und optional die Landkreise zur Orientierung.</span> 545 </div> 546 </div> 547 <div class="security-map-legend" aria-label="Kartenlegende"> 548 <span class="cat-civil">â Bund / Bevölkerungsschutz</span> 549 <span class="cat-flood">â Hochwasser</span> 550 <span class="cat-police">â Polizei</span> 551 <span class="cat-weather">â Wetter</span> 552 <span class="cat-air">â Luftqualität</span> 553 <span class="cat-rail">â Bahn</span> 554 <span class="cat-home">â gespeicherter Ort</span> 555 </div> 556 <div class="security-map-list" data-security-list data-security-details hidden> 557 <article class="security-map-card is-empty"> 558 <strong>Noch kein Ort gespeichert</strong> 559 <span>Danach wird die Karte direkt im App-Index sichtbar mit deinem regionalen Kartenausschnitt geladen.</span> 560 </article> 561 </div> 562 </div> 563 </section> 564 565 <section class="saved-panel saved-panel-v31"> 566 <div class="section-head compact"> 567 <div><span class="eyebrow small">Ortsauswahl</span><h2><span data-place-name>Noch kein Ort gespeichert</span></h2><p><span data-place-count>0 Orte gespeichert</span> · Zuhause, Arbeit, Familie oder Urlaub bleiben schnell erreichbar.</p></div> 568 <button type="button" class="section-toggle" data-place-manager-open>Ort wechseln oder verwalten</button> 569 </div> 570 </section> 571 572 <div class="section-head module-head-v37" id="weitere-dienste" data-service-head> 573 <div> 574 <span class="eyebrow small">Live-Dienste</span> 575 <h2>Jetzt sinnvolle Dienste</h2> 576 <p data-service-headline>Die App sortiert die wichtigsten Bereiche nach deiner aktuellen Lage. Kein Katalog, sondern der nächste sinnvolle Klick.</p> 577 </div> 578 <button type="button" class="section-toggle service-toggle" data-modules-toggle aria-expanded="false">Alle Dienste kompakt</button> 579 </div> 580 581 <section class="grid module-grid-v31 service-grid-v37" data-module-grid aria-label="Meteozentrale App Module"> 582 <a class="tile service-tile sky" data-module="skyguard" data-needs-place href="/app/"> 583 <span class="tag">SkyGuard</span> 584 <div class="service-tile-main"> 585 <div class="icon" aria-hidden="true">ð¡ï¸</div> 586 <div class="service-tile-copy"> 587 <h3>Radar & Gewitter</h3> 588 <p>Radarzellen, Blitze und Warnflächen mit konservativem Radar-/Ortsabgleich. Keine Zelltrajektorien- oder Ankunftsgarantie.</p> 589 </div> 590 </div> 591 <div class="service-live-row"> 592 <small class="module-status" data-module-status>Status nach Ort</small> 593 <small class="module-place" data-module-place>Ort wählen</small> </div> 594 <small class="module-reason" data-module-reason>Live-Einordnung folgt nach Ortswahl.</small> 595 </a> 596 <a class="tile service-tile " data-module="hours24" data-needs-place href="/app/"> 597 <span class="tag">Heute</span> 598 <div class="service-tile-main"> 599 <div class="icon" aria-hidden="true">ð</div> 600 <div class="service-tile-copy"> 601 <h3>Wetter heute</h3> 602 <p>Der verständliche Stundenverlauf mit Temperatur, Regen und Wind.</p> 603 </div> 604 </div> 605 <div class="service-live-row"> 606 <small class="module-status" data-module-status>Status nach Ort</small> 607 <small class="module-place" data-module-place>Ort wählen</small> </div> 608 <small class="module-reason" data-module-reason>Live-Einordnung folgt nach Ortswahl.</small> 609 </a> 610 <a class="tile service-tile " data-module="forecast5" data-needs-place href="/app/">
611 <span class="tag">5 Tage</span> 612 <div class="service-tile-main"> 613 <div class="icon" aria-hidden="true">ðï¸</div> 614 <div class="service-tile-copy"> 615 <h3>5-Tage-Prognose</h3> 616 <p>Tagestrend, Temperatur, Niederschlag und Wind für die kommenden fünf Tage.</p> 617 </div> 618 </div> 619 <div class="service-live-row"> 620 <small class="module-status" data-module-status>Status nach Ort</small> 621 <small class="module-place" data-module-place>Ort wählen</small> </div> 622 <small class="module-reason" data-module-reason>Live-Einordnung folgt nach Ortswahl.</small> 623 </a> 624 <a class="tile service-tile " data-module="meteogram" data-needs-place href="/app/"> 625 <span class="tag">Ausblick</span> 626 <div class="service-tile-main"> 627 <div class="icon" aria-hidden="true">ð</div> 628 <div class="service-tile-copy"> 629 <h3>14-Tage-Trend</h3> 630 <p>Wie sich das Wetter in den kommenden zwei Wochen entwickelt.</p> 631 </div> 632 </div> 633 <div class="service-live-row"> 634 <small class="module-status" data-module-status>Status nach Ort</small> 635 <small class="module-place" data-module-place>Ort wählen</small> </div> 636 <small class="module-reason" data-module-reason>Live-Einordnung folgt nach Ortswahl.</small> 637 </a> 638 <a class="tile service-tile " data-module="niederschlag" data-needs-place href="/app/"> 639 <span class="tag">Radar</span> 640 <div class="service-tile-main"> 641 <div class="icon" aria-hidden="true">ð§ï¸</div> 642 <div class="service-tile-copy"> 643 <h3>Radar & Regen</h3> 644 <p>Regenradar, Starkregen, Dauerregen und Regensummen.</p> 645 </div> 646 </div> 647 <div class="service-live-row"> 648 <small class="module-status" data-module-status>Status nach Ort</small> 649 <small class="module-place" data-module-place>Ort wählen</small> </div> 650 <small class="module-reason" data-module-reason>Live-Einordnung folgt nach Ortswahl.</small> 651 </a> 652 <a class="tile service-tile " data-module="sturm" data-needs-place href="/app/"> 653 <span class="tag">Wind</span> 654 <div class="service-tile-main"> 655 <div class="icon" aria-hidden="true">ðªï¸</div> 656 <div class="service-tile-copy"> 657 <h3>Wind & Sturm</h3> 658 <p>Böen, Windspitzen und mögliche Sturmwarnungen.</p> 659 </div> 660 </div> 661 <div class="service-live-row"> 662 <small class="module-status" data-module-status>Status nach Ort</small> 663 <small class="module-place" data-module-place>Ort wählen</small> </div> 664 <small class="module-reason" data-module-reason>Live-Einordnung folgt nach Ortswahl.</small> 665 </a> 666 <a class="tile service-tile " data-module="meteoz" data-needs-place href="/app/"> 667 <span class="tag">Warnung</span> 668 <div class="service-tile-main"> 669 <div class="icon" aria-hidden="true">â ï¸</div> 670 <div class="service-tile-copy"> 671 <h3>Warnungen</h3> 672 <p>Amtliche Warnungen und eine verständliche Einschätzung der Wettergefahren.</p> 673 </div> 674 </div> 675 <div class="service-live-row"> 676 <small class="module-status" data-module-status>Status nach Ort</small> 677 <small class="module-place" data-module-place>Ort wählen</small> </div> 678 <small class="module-reason" data-module-reason>Live-Einordnung folgt nach Ortswahl.</small> 679 </a> 680 <a class="tile service-tile " data-module="models" href="/app/"> 681 <span class="tag">Profi</span> 682 <div class="service-tile-main"> 683 <div class="icon" aria-hidden="true">ð°ï¸</div> 684 <div class="service-tile-copy"> 685 <h3>Karten</h3> 686 <p>
686Modellkarten und vertiefende Daten für Wetterinteressierte.</p> 687 </div> 688 </div> 689 <div class="service-live-row"> 690 <small class="module-status" data-module-status>Status nach Ort</small> 691 </div> 692 <small class="module-reason" data-module-reason>Live-Einordnung folgt nach Ortswahl.</small> 693 </a> 694 <a class="tile service-tile warnhub" data-module="warnzentrum" data-needs-place href="/app/"> 695 <span class="tag">Umgebung</span> 696 <div class="service-tile-main"> 697 <div class="icon" aria-hidden="true">📡</div> 698 <div class="service-tile-copy"> 699 <h3>Warnzentrum</h3> 700 <p>Nur relevante Meldungen: Bevölkerungsschutz, Hochwasser, Polizei, Wetter ab Orange, Luftqualität und Bahnlage.</p> 701 </div> 702 </div> 703 <div class="service-live-row"> 704 <small class="module-status" data-module-status>Status nach Ort</small> 705 <small class="module-place" data-module-place>Ort wählen</small> </div> 706 <small class="module-reason" data-module-reason>Live-Einordnung folgt nach Ortswahl.</small> 707 </a> 708 </section> 709 710 <section class="wide-panel probability-panel probability-panel-v31" id="wahrscheinlichkeiten" data-probability-root aria-label="Wahrscheinlichkeitsblick"> 711 <article class="panel probability-card"> 712 <div class="probability-head"> 713 <div> 714 <span class="eyebrow small">Für Wetterinteressierte</span> 715 <h3>Modelle & Wahrscheinlichkeiten</h3> 716 </div> 717 <div class="probability-summary-actions"><p data-probability-summary>Vertiefende Modelldaten â nur wenn du genauer einsteigen möchtest.</p><button type="button" class="section-toggle" data-probability-toggle aria-expanded="false">Fachdaten anzeigen</button></div> 718 </div> 719 <div class="probability-grid" data-probability-grid hidden></div> 720 <div class="probability-source" data-probability-details hidden> 721 <span>MOSMIX-Wahrscheinlichkeiten über</span> 722 <a href="https://morgenwirdes.de/" target="_blank" rel="noopener noreferrer">Morgenwirdes.de</a> 723 <span>Datenquelle: Deutscher Wetterdienst</span> 724 </div> 725 </article> 726 </section> 727 728 <div class="app-dialog" data-main-menu hidden role="dialog" aria-modal="true" aria-labelledby="main-menu-title"> 729 <div class="app-dialog-backdrop" data-dialog-close></div> 730 <section class="app-dialog-card main-menu-card"> 731 <div class="app-dialog-head"><div><span class="eyebrow small">Meteozentrale</span><h2 id="main-menu-title">Alle Bereiche</h2></div><button type="button" data-dialog-close aria-label="SchlieÃen">Ã</button></div> 732 <p>Wähle direkt, was du wissen möchtest. Fachbegriffe stehen nur noch als Zusatz dabei.</p> 733 <button type="button" class="menu-place-action" data-place-manager-open><span>â</span><strong><b data-place-name>Ort auswählen</b><small>Ort suchen, GPS verwenden oder gespeicherte Orte wechseln</small></strong></button> 734 <nav class="main-menu-grid" aria-label="Alle Wetterbereiche"> 735 <a data-menu-link href="/wettermelder/"><span>ð·</span><strong>Wettermelder<small>Wetter melden · Fotos · Community-Karte</small></strong></a> 736 <a data-menu-link data-module="meteoz" data-needs-place href="/meteo/meteoz.php"><span>â ï¸</span><strong>Warnungen<small>Gefahren verständlich erklärt</small></strong></a> 737 <a data-menu-link data-module="hours24" data-needs-place href="/meteo/24stunden.php"><span>ð</span><strong>Wetter heute<small>Stündliche Vorhersage</small></strong></a> 738 <a data-menu-link data-module="forecast5" data-needs-place href="/meteo/5tage.php"><span>ðï¸</span><strong>5-Tage-Prognose<small>Der kompakte Tagestrend</small></strong></a> 739 <a data-menu-link data-module="niederschlag" data-needs-place href="/niederschlag/"><span>ð§ï¸</span><strong>Radar & Regen<small>Regen, Starkregen, Dauerregen</small></strong></a> 740 <a data-menu-link data-module="meteogram" data-needs-place href="/meteo/meteogram.php"><span>ð</span><strong>14-Tage-Trend<small>Der weitere Ausblick</small></strong></a> 741 <a data-menu-link data-module="skyguard" data-needs-place href="/meteo/"><span>âï¸</span><strong>Gewitter & Blitze<small>SkyGuard Stormtracker</small></strong></a> 742 <a data-menu-link data-module="sturm" data-needs-place href="/sturmwarnung/"><span>ðªï¸</span><strong>Wind & Sturm<small>Böen und Sturmgefahr</small></strong></a> 743 <a data-menu-link data-module="warnzentrum" data-needs-place href="/warnzentrum/"><span>ð¡</span><strong>Warnzentrum<small>Bund, Hochwasser, Polizei, Wetter ab Orange</small></strong></a> 744 <a data-menu-link href="#app-alltagsblick"><span>âï¸</span><strong>Alltagsblick<small>Temperaturtrend, Luftdruck, Wäsche und Luft</small></strong></a> 745 <a data-menu-link data-agro-open aria-controls="app-agrarblick" aria-expanded="false" href="#app-agrarblick"><span>ð±</span><strong>Agrarblick<small>Boden, Spritzfenster und Befahrbarkeit</small></strong></a>
746 <a data-menu-link href="#regionale-lage" data-security-panel-open><span>ðºï¸</span><strong>Karte<small>Meldungen in deiner Umgebung</small></strong></a> 747 <a data-menu-link data-module="models" href="/app/"><span>ð°ï¸</span><strong>Modelle & Fachdaten<small>Für Wetterinteressierte</small></strong></a> 748 </nav> 749 <button type="button" class="menu-settings-action" data-menu-settings-open>App, Push und Ansicht einstellen</button> 750 </section> 751 </div> 752 753 <div class="app-dialog" data-place-manager hidden role="dialog" aria-modal="true" aria-labelledby="place-manager-title"> 754 <div class="app-dialog-backdrop" data-dialog-close></div> 755 <section class="app-dialog-card place-manager-card"> 756 <div class="app-dialog-head"><div><span class="eyebrow small">Ort & GPS</span><h2 id="place-manager-title">Welches Wetter möchtest du sehen?</h2></div><button type="button" data-dialog-close aria-label="SchlieÃen">Ã</button></div> 757 <div class="dialog-place-search" data-place-search> 758 <h3>Anderen Ort suchen</h3> 759 <p>Gib einen Ortsnamen oder eine Postleitzahl ein.</p> 760 <form class="place-form" data-place-form> 761 <input name="ort" autocomplete="postal-code address-level2" placeholder="Ort oder PLZ, z. B. Köln oder 63654" aria-label="Anderen Ort suchen"> 762 <button type="submit" data-place-submit>Suchen</button> 763 </form> 764 <div class="place-results" data-place-results hidden></div> 765 <div class="dialog-location-divider"><span>oder</span></div> 766 <button type="button" class="dialog-gps-button" data-place-gps><span>â</span><strong>Meinen aktuellen Standort verwenden</strong></button> 767 <p class="location-message" data-location-message hidden></p> 768 <small class="dialog-privacy">Die Standortfreigabe erfolgt über deinen Browser. Orte werden nur auf diesem Gerät gespeichert.</small> 769 </div> 770 <div class="dialog-saved-head"><h3>Gespeicherte Orte</h3><span data-place-count>0 Orte gespeichert</span></div> 771 <p class="dialog-saved-help">Tippe auf einen Ort, um ihn sofort als Hauptort zu verwenden.</p> 772 <div class="saved-list saved-list-dialog" data-place-list></div> 773 <div class="dialog-actions"><button type="button" data-place-clear>Aktiven Hauptort entfernen</button></div> 774 </section> 775 </div> 776 777 <div class="app-dialog" data-install-guide hidden role="dialog" aria-modal="true" aria-labelledby="install-guide-title"> 778 <div class="app-dialog-backdrop" data-dialog-close></div> 779 <section class="app-dialog-card install-guide-card"> 780 <div class="app-dialog-head"><div><span class="eyebrow small">iPhone und iPad</span><h2 id="install-guide-title">Meteozentrale zum Home-Bildschirm</h2></div><button type="button" data-dialog-close aria-label="SchlieÃen">Ã</button></div> 781 <ol class="install-guide-steps"> 782 <li><span>1</span><div><strong>In Safari öffnen</strong><p>Falls du aus Facebook, Instagram oder einem Messenger kommst, öffne diese Seite zuerst in Safari.</p></div></li> 783 <li><span>2</span><div><strong>Teilen antippen</strong><p>Tippe in der Safari-Leiste auf das Teilen-Symbol.</p></div></li> 784 <li><span>3</span><div><strong>Zum Home-Bildschirm</strong><p>Wähle âZum Home-Bildschirmâ und bestätige anschlieÃend mit âHinzufügenâ.</p></div></li> 785 </ol> 786 <p class="install-guide-note">Danach startet die Meteozentrale wie eine App direkt vom Home-Bildschirm.</p> 787 </section> 788 </div> 789 790 <div class="app-dialog" data-view-settings hidden role="dialog" aria-modal="true" aria-labelledby="view-settings-title"> 791 <div class="app-dialog-backdrop" data-dialog-close></div> 792 <section class="app-dialog-card view-settings-card"> 793 <div class="app-dialog-head"><div><span class="eyebrow small">Einstellungen</span><h2 id="view-settings-title">Deine Startseite</h2></div><button type="button" data-dialog-close aria-label="SchlieÃen">Ã</button></div> 794 <p>Warnstatus, Farbwechsel und Vorhersage bleiben übersichtlich. Zusätzliche Fachbereiche kannst du hier ein- oder ausblenden.</p> 795 <div class="settings-action"><span><strong>Relevante Push-Warnungen</strong><small>Persönliche Warnungen werden über die exakte amtliche DWD-Warnzelle zugestellt. Profilregistrierung und tatsächliche Geräte-Zustellung werden getrennt geprüft.</small><small id="mz-push-inline-status" style="display:block;margin-top:6px;color:#93c5fd">Push-Status wird geprüft â¦</small></span><div style="display:flex;flex-wrap:wrap;gap:8px;justify-content:flex-end"><button class="push-btn" id="webpushr-subscription-button" type="button" data-push-settings>Pushs aktivieren</button><button class="push-btn" id="mz-webpushr-unsubscribe" type="button" data-push-disable style="background:#ef4444;color:#fff;border:1px solid rgba(239,68,68,.35)">Pushs abbestellen</button></div></div> 796 <div class="settings-action settings-storage-action"><span><strong>Ortsspeicher auf diesem Gerät</strong><small>Dein Hauptort wird lokal gespeichert und zusätzlich lokal gesichert. Das hilft besonders nach Neustart der App.</small><small data-storage-status style="display:block;margin-top:6px;color:#93c5fd">Ortsspeicher wird geprüft â¦</small></span><button class="push-btn" type="button" data-place-storage-check>Speicher prüfen</button></div> 797 <div class="settings-action app-info-action"><span><strong>App-Info · Version 81.8</strong><small>Neu: Aufrufe und Likes direkt in den Wetterberichten. Wetterberichte findest du weiterhin im eigenen Reiter. Artikel-Push ist noch in Vorbereitung.</small><small>Persönliche Wetterwarnungen trennen jetzt Profilregistrierung, echten Geräte-Test und nachvollziehbaren Versandstatus.</small><small>Live-Wetter: Open-Meteo/DWD-Modelle · Pollen und Luft: CAMS Europe über Open-Meteo · Browser-Ersatz und lokale Reserve werden sichtbar gekennzeichnet; Warnungen, Radar und SkyGuard müssen dabei separat live geprüft werden. Der Radar-/Ortsabgleich garantiert weder Zelltrajektorien noch eine Ankunft am Ort.</small></span><a class="pill" href="/app/?mz_refresh=81.8" aria-label="Meteozentrale App Version 81.8 neu laden">Nach Update neu laden</a></div> 798 <label class="view-option"><input type="checkbox" data-view-preference="probabilities" checked><span><strong>Wahrscheinlichkeitsblick</strong><small>MOSMIX-Bereich am Seitenende anzeigen</small></span></label> 799 <label class="view-option"><input type="checkbox" data-view-preference="allTools"><span><strong>Alle Wetterdienste kompakt</strong><small>Statt der wichtigsten Live-Dienste die gesamte Dienstliste kompakt anzeigen</small></span></label> 800 <label class="view-option"><input type="checkbox" data-view-preference="mapDetails"><span><strong>Meldungsdetails zur Karte</strong><small>Zusätzliche Meldungen unter der aufgeklappten Karte zeigen</small></span></label> 801 <div class="settings-action settings-agro-action"><span><strong>Agrarblick bei Bedarf</strong><small>Bodenmodell, Wasserbilanz, Spritzfenster und Befahrbarkeit werden nur für die aktuelle Ansicht geöffnet.</small></span><button type="button" class="push-btn" data-agro-open aria-controls="app-agrarblick" aria-expanded="false">Agrarblick öffnen</button></div> 802 </section> 803 </div> 804 805 <p class="footer">© 2026 Meteozentrale · App-Version 81.8 · Stand 02.10.2026, 19:50 · Ort, GPS, Warnstatus, 5-Tage-Prognose, 14-Tage-Meteogramm, optionaler Agrarblick, Pollen, konservativer SkyGuard-Radar-/Ortsabgleich, Lagebericht und alle Wetterdienste verständlich erreichbar; keine Zelltrajektorien- oder Ankunftsgarantie.</p> 806 </div> 807
807<script src="/assets/pwa/mz-location-core.js?v=20" defer></script>
807 808
808<script src="/assets/pwa/app-v51.js?v=51.3.1" defer></script>
808 809
809<script src="/app/mz-push-preferences.js?v=73.0" defer></script>
809 810
810<script src="/app/mz-cellwarn-optin.js?v=20260928-2" defer></script>
810 811 812
812<script> 813 (function(){ 814 'use strict'; 815 var STATUS_ID = 'mz-push-inline-status'; 816 var UNSUB_BTN_ID = 'mz-webpushr-unsubscribe'; 817 var SUB_BTN_ID = 'webpushr-subscription-button'; 818 var USER_OFF_KEY = 'mz_push_user_unsubscribed_v1'; 819 820 function $(id){ return document.getElementById(id); } 821 function setStatus(text, tone){ 822 var el = $(STATUS_ID); 823 if (!el) return; 824 el.textContent = text; 825 el.style.color = tone === 'ok' ? '#86efac' : tone === 'warn' ? '#fbbf24' : tone === 'bad' ? '#fca5a5' : '#93c5fd'; 826 } 827 function permissionState(){ 828 try { return ('Notification' in window) ? Notification.permission : 'unsupported'; } 829 catch(e){ return 'unknown'; } 830 } 831 async function getPushSubscriptions(){ 832 var out = []; 833 try { 834 if (!('serviceWorker' in navigator)) return out; 835 var regs = await navigator.serviceWorker.getRegistrations(); 836 for (var i = 0; i < regs.length; i++) { 837 var reg = regs[i]; 838 if (!reg || !reg.pushManager) continue; 839 var sub = await reg.pushManager.getSubscription(); 840 if (sub) out.push({reg: reg, sub: sub}); 841 } 842 } catch(e) {} 843 return out; 844 } 845 function cleanupWebpushrLocalTraces(){
846 try { 847 Object.keys(localStorage).forEach(function(k){ 848 if (String(k).toLowerCase().indexOf('webpushr') !== -1) localStorage.removeItem(k); 849 }); 850 localStorage.setItem(USER_OFF_KEY, '1'); 851 } catch(e) {} 852 try { 853 Object.keys(sessionStorage).forEach(function(k){ 854 if (String(k).toLowerCase().indexOf('webpushr') !== -1) sessionStorage.removeItem(k); 855 }); 856 } catch(e) {} 857 ['_webpushrId','_webpushr_f_id','_webpushr_first_optin'].forEach(function(name){ 858 try { 859 document.cookie = name + '=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/;'; 860 document.cookie = name + '=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/; domain=.meteozentrale.de;'; 861 } catch(e) {} 862 }); 863 } 864 async function refreshPushStatus(){ 865 var perm = permissionState(); 866 var subs = await getPushSubscriptions(); 867 if (perm === 'denied') { 868 setStatus('Push ist im Browser blockiert. Bitte in den Browser-Einstellungen wieder erlauben.', 'bad'); 869 } else if (subs.length > 0) { 870 try { localStorage.setItem(USER_OFF_KEY, '0'); } catch(e) {} 871 setStatus('Die Browser-Subscription ist aktiv. Die tatsächliche Zustellung kannst du unten mit dem persönlichen Test-Push prüfen.', 'ok'); 872 } else if (perm === 'granted') { 873 setStatus('Browser erlaubt Push, aber aktuell ist keine aktive Push-Subscription vorhanden. Bei Bedarf Pushs erneut aktivieren.', 'warn'); 874 } else { 875 setStatus('Pushs sind noch nicht aktiv. Tippe auf âPushs aktivierenâ und erlaube Benachrichtigungen.', 'warn'); 876 } 877 } 878 async function unsubscribePush(){ 879 var ok = window.confirm( 880 'Pushs auf diesem Gerät wirklich abbestellen?\n\n' + 881 'Du erhältst dann keine Meteozentrale-Pushs mehr, kannst sie aber jederzeit wieder aktivieren.' 882 ); 883 if (!ok) return; 884 setStatus('Pushs werden abbestellt â¦', 'warn'); 885 var count = 0; 886 var profileDisabled = false; 887 var cellwarnDisabled = false; 888 try { 889 if (window.MZWarnProfile && typeof window.MZWarnProfile.disable === 'function') { 890 profileDisabled = await window.MZWarnProfile.disable(); 891 } 892 } catch(e) {} 893 try { 894 if (window.MZCellWarn && typeof window.MZCellWarn.disable === 'function') { 895 cellwarnDisabled = await window.MZCellWarn.disable(); 896 } 897 } catch(e) {} 898 try { 899 var subs = await getPushSubscriptions(); 900 for (var i = 0; i < subs.length; i++) { 901 try { 902 var done = await subs[i].sub.unsubscribe(); 903 if (done) count++; 904 } catch(e) {} 905 } 906 } catch(e) {} 907 cleanupWebpushrLocalTraces(); 908 if (count > 0 && profileDisabled && cellwarnDisabled) setStatus('Pushs, Warnprofil und CellWarn wurden auf diesem Gerät vollständig deaktiviert.', 'ok'); 909 else if (count > 0) setStatus('Browser-Push wurde abbestellt. Die Deaktivierung des Serverprofils konnte nicht bestätigt werden.', 'warn'); 910 else setStatus('Keine aktive Push-Subscription gefunden. Pushs sind auf diesem Gerät nicht aktiv.', 'ok'); 911 setTimeout(refreshPushStatus, 800); 912 setTimeout(refreshPushStatus, 2500); 913 } 914 function bind(){ 915 var off = $(UNSUB_BTN_ID); 916 if (off) off.addEventListener('click', unsubscribePush); 917 var sub = $(SUB_BTN_ID); 918 if (sub) sub.addEventListener('click', function(e){ 919 try { localStorage.setItem(USER_OFF_KEY, '0'); } catch(e) {} 920 if (!window.MZ_WEBPUSHR_READY && typeof window.mzLoadWebpushr === 'function') { 921 e.preventDefault(); 922 e.stopImmediatePropagation(); 923 setStatus('Push-Dienst wird geladen â¦', 'warn'); 924 window.mzLoadWebpushr().then(function(){ 925 setStatus('Push-Anmeldung wird geöffnet. Bitte Benachrichtigungen erlauben, falls der Browser fragt.', 'warn'); 926 setTimeout(function(){ sub.click(); }, 250); 927 }).catch(function(){ setStatus('Push-Dienst ist gerade nicht erreichbar. Bitte später erneut versuchen.', 'bad'); }); 928 return; 929 } 930 setStatus('Push-Anmeldung wird geöffnet. Bitte Benachrichtigungen erlauben, falls der Browser fragt.', 'warn'); 931 setTimeout(refreshPushStatus, 3500); 932 setTimeout(refreshPushStatus, 8000); 933 }, true); 934 window.addEventListener('focus', refreshPushStatus); 935 document.addEventListener('visibilitychange', function(){ if (document.visibilityState === 'visible') refreshPushStatus(); }); 936 refreshPushStatus(); 937 } 938 if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', bind); else bind(); 939 })(); 940 </script>
940 941
941<script> 942 (function(){ 943 'use strict'; 944 var GA_ID = window.MZ_ANALYTICS_ID || 'G-1MMGHXXRHP'; 945 var APP_VERSION = window.MZ_APP_VERSION || 'v81.2-app-quality-hotfix'; 946 var CONSENT_KEY = 'mz_analytics_consent_v1'; 947 var pageViewSent = false; 948 var placeLoadedSent = false; 949 950 function storageGet(key){ try { return localStorage.getItem(key); } catch(e){ return null; } } 951 function storageSet(key, value){ try { localStorage.setItem(key, value); } catch(e){} } 952 function hasConsent(){ return storageGet(CONSENT_KEY) === 'granted'; } 953 function isStandalone(){ return (window.matchMedia && window.matchMedia('(display-mode: standalone)').matches) || window.navigator.standalone === true; } 954 function clean(value, max){ return String(value || '').replace(/\s+/g, ' ').trim().slice(0, max || 90); } 955 function capabilityParams(){ 956 return { 957 manifest_link: document.querySelector('link[rel="manifest"]') ? 'yes' : 'no', 958 service_worker_supported: 'serviceWorker' in navigator ? 'yes' : 'no', 959 push_supported: 'PushManager' in window ? 'yes' : 'no', 960 notification_supported: 'Notification' in window ? 'yes' : 'no', 961 standalone: isStandalone() ? 'yes' : 'no', 962 canonical_url: clean(document.querySelector('link[rel="canonical"]') ? document.querySelector('link[rel="canonical"]').href : '', 160) 963 }; 964 } 965 function currentPlace(){ 966 try { 967 if (window.MZLocationCore && typeof window.MZLocationCore.primary === 'function') return window.MZLocationCore.primary(); 968 } catch(e) {} 969 try { return JSON.parse(localStorage.getItem('mz_app_primary_place_v1') || 'null'); } catch(e){ return null; } 970 } 971 function placeParams(){ 972 var p = currentPlace() || {}; 973 var has = !!(p && (p.name || p.display_name || p.slug)); 974 return { 975 has_place: has ? 'yes' : 'no', 976 place_name: has ? clean(p.name || String(p.display_name || '').split(',')[0], 60) : '', 977 place_state: clean(p.admin1 || '', 50), 978 place_country: clean(p.country_code || p.countryCode || '', 8), 979 place_source: clean(p.source || '', 40) 980 }; 981 } 982 function send(eventName, params){ 983 if (!hasConsent() || typeof window.gtag !== 'function') return; 984 var payload = Object.assign({ 985 app_area: 'pwa_app_index', 986 app_version: APP_VERSION, 987 app_mode: isStandalone() ? 'standalone' : 'browser', 988 app_kind: 'progressive_web_app', 989 app_install_channel: 'web_install', 990 app_schema: 'software_application_web_application' 991 }, placeParams(), params || {}); 992 delete payload.latitude; 993 delete payload.longitude; 994 delete payload.lat; 995 delete payload.lon; 996 window.gtag('event', eventName, payload); 997 } 998 function sendPageView(reason){ 999 if (!hasConsent() || pageViewSent || typeof window.gtag !== 'function') return; 1000 pageViewSent = true; 1001 window.gtag('event', 'page_view', Object.assign({ 1002 page_title: document.title, 1003 page_location: location.href, 1004 page_path: location.pathname + location.search, 1005 page_referrer: document.referrer || '', 1006 app_area: 'pwa_app_index', 1007 app_version: APP_VERSION, 1008 app_mode: isStandalone() ? 'standalone' : 'browser', 1009 app_kind: 'progressive_web_app', 1010 app_install_channel: 'web_install', 1011 app_schema: 'software_application_web_application', 1012 view_reason: reason || 'load' 1013 }, placeParams())); 1014 send('app_open', {open_reason: reason || 'load'}); 1015 send('app_capabilities', Object.assign({capability_reason: reason || 'load'}, capabilityParams())); 1016 } 1017 function updateConsent(value){ 1018 storageSet(CONSENT_KEY, value); 1019 if (typeof window.gtag === 'function') { 1020 window.gtag('consent', 'update', { 1021 'analytics_storage': value === 'granted' ? 'granted' : 'denied', 1022 'ad_storage': 'denied', 1023 'ad_user_data': 'denied', 1024 'ad_personalization': 'denied' 1025 }); 1026 } 1027 var banner = document.querySelector('[data-analytics-consent]'); 1028 if (banner) banner.classList.remove('is-visible'); 1029 if (value === 'granted') { 1030 sendPageView('consent_granted'); 1031 send('analytics_consent_accept'); 1032 } 1033 } 1034 function initConsentBanner(){ 1035 var stored = storageGet(CONSENT_KEY); 1036 var banner = document.querySelector('[data-analytics-consent]'); 1037 if (!stored && banner) banner.classList.add('is-visible'); 1038 if (stored === 'granted') sendPageView('stored_consent'); 1039 document.addEventListener('click', function(e){ 1040 if (e.target.closest('[data-analytics-accept]')) updateConsent('granted'); 1041 if (e.target.closest('[data-analytics-decline]')) updateConsent('denied'); 1042 }); 1043 } 1044 function closestText(el){ 1045 if (!el) return ''; 1046 var h = el.querySelector('h1,h2,h3,strong,.tag'); 1047 return clean((h && h.textContent) || el.textContent || '', 80); 1048 } 1049 function bindEvents(){ 1050 document.addEventListener('submit', function(e){ 1051 if (e.target && e.target.matches('[data-place-form]')) { 1052 var input = e.target.querySelector('input[name="ort"]'); 1053 send('place_search_submit', {search_length: input && input.value ? String(input.value).trim().length : 0}); 1054 } 1055 }, true); 1056 document.addEventListener('click', function(e){ 1057 var radius = e.target.closest('[data-security-radius]'); 1058 if (radius) send('security_radius_change', {radius_km: clean(radius.getAttribute('data-security-radius'), 8)}); 1059 1060 if (e.target.closest('[data-place-gps]')) send('gps_click'); 1061 if (e.target.closest('[data-place-refresh]')) send('place_links_refresh'); 1062 if (e.target.closest('[data-place-clear]')) send('place_clear'); 1063 if (e.target.closest('[data-install-app]')) send('install_button_click'); 1064 if (e.target.closest('[data-push-settings],#webpushr-subscription-button')) send('push_button_click'); 1065 if (e.target.closest('[data-push-disable],#mz-webpushr-unsubscribe')) send('push_disable_click'); 1066 if (e.target.closest('[data-security-open]')) send('regional_warnzentrum_open', {entry: 'security_map_button'}); 1067 1068 var communityEl = e.target.closest('[data-community-entry]'); 1069 if (communityEl) send('wettermelder_open', {entry: clean(communityEl.getAttribute('data-community-entry'), 40)}); 1070 1071 var moduleEl = e.target.closest('[data-module]'); 1072 if (moduleEl) { 1073 send('module_open', { 1074 module_name: clean(moduleEl.getAttribute('data-module'), 40), 1075 module_label: closestText(moduleEl), 1076 needs_place: moduleEl.hasAttribute('data-needs-place') ? 'yes' : 'no', 1077 target_url: clean(moduleEl.getAttribute('href') || '',
1077160) 1078 }); 1079 } 1080 }, true); 1081 window.addEventListener('beforeinstallprompt', function(){ send('pwa_install_prompt_available'); }); 1082 window.addEventListener('appinstalled', function(){ send('pwa_installed'); }); 1083 window.addEventListener('mz-place-updated', function(ev){ 1084 var p = ev && ev.detail && ev.detail.place; 1085 send('place_saved', { 1086 place_name: p ? clean(p.name || '', 60) : '', 1087 place_state: p ? clean(p.admin1 || '', 50) : '', 1088 place_source: p ? clean(p.source || '', 40) : 'unknown' 1089 }); 1090 }); 1091 document.addEventListener('visibilitychange', function(){ 1092 if (document.visibilityState === 'visible') send('app_visible'); 1093 }); 1094 } 1095 function watchPlaceLoaded(){ 1096 setTimeout(function(){ 1097 var p = currentPlace(); 1098 if (p && !placeLoadedSent) { 1099 placeLoadedSent = true; 1100 send('place_loaded', {place_source: clean(p.source || '', 40)}); 1101 } 1102 }, 1600); 1103 } 1104 initConsentBanner(); 1105 bindEvents(); 1106 watchPlaceLoaded(); 1107 window.MZAnalytics = {track: send, pageView: sendPageView, setConsent: updateConsent}; 1108 })(); 1109 </script>
vendor: 1 bytes, line 1109
1109
1110<script> 1111/* Report views and likes for the Meteozentrale PWA. Uses the existing WordPress counters. */ 1112(() => { 1113 'use strict'; 1114 1115 const CONFIG_URL = '/app/index.php'; 1116 const VIEW_DELAY_MS = 10000; 1117 const VIEW_KEY_PREFIX = 'mz_app_report_view_v1_'; 1118 const numberFormat = new Intl.NumberFormat('de-DE'); 1119 1120 let activePostId = 0; 1121 let viewInterval = 0; 1122 let configPromise = null; 1123 let configTime = 0; 1124 const viewed = new Set(); 1125 1126 function element(tag, className, text) { 1127 const node = document.createElement(tag); 1128 if (className) node.className = className; 1129 if (text !== undefined) node.textContent = text; 1130 return node; 1131 } 1132 1133 function getConfig() { 1134 if (Date.now() - configTime > 300000) configPromise = null; 1135 if (!configPromise) { 1136 configTime = Date.now(); 1137 configPromise = fetch(CONFIG_URL, { 1138 method: 'POST', 1139 body: new URLSearchParams({mz_article_config: '1'}), 1140 credentials: 'same-origin', 1141 cache: 'no-store', 1142 headers: {'Accept': 'application/json'} 1143 }) 1144 .then(response => { 1145 if (!response.ok) throw new Error('interaction_config_unavailable'); 1146 return response.json(); 1147 }) 1148 .then(config => { 1149 if (!config?.success || !config?.ajaxUrl || !config?.viewNonce || !config?.reactionNonce) { 1150 throw new Error('interaction_config_invalid'); 1151 } 1152 return config; 1153 }) 1154 .catch(error => { 1155 configPromise = null; 1156 throw error; 1157 }); 1158 } 1159 return configPromise; 1160 } 1161 1162 async function ajax(config, payload) { 1163 const response = await fetch(config.ajaxUrl, { 1164 method: 'POST', 1165 credentials: 'same-origin', 1166 cache: 'no-store', 1167 headers: { 1168 'Accept': 'application/json', 1169 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8' 1170 }, 1171 body: new URLSearchParams(payload).toString() 1172 }); 1173 const result = await response.json().catch(() => null); 1174 if (!response.ok || !result?.success) throw new Error('interaction_request_failed'); 1175 return result.data || {}; 1176 } 1177 1178 function wasViewed(postId) { 1179 if (viewed.has(postId)) return true; 1180 try { return sessionStorage.getItem(VIEW_KEY_PREFIX + postId) === '1'; } 1181 catch { return false; } 1182 } 1183 1184 function rememberView(postId) { 1185 viewed.add(postId); 1186 try { sessionStorage.setItem(VIEW_KEY_PREFIX + postId, '1'); } 1187 catch {} 1188 } 1189 1190 function setViewCount(card, stats) { 1191 const count = card.querySelector('[data-report-views-count]'); 1192 const stat = card.querySelector('[data-report-views]'); 1193 if (!count || !stat) return; 1194 count.textContent = numberFormat.format(Math.max(0, Number(stats?.total) || 0)); 1195 stat.title = `${numberFormat.format(Math.max(0, Number(stats?.today) || 0))} heute`; 1196 } 1197 1198 function setLikeState(card, stats) { 1199 const button = card.querySelector('[data-report-like]'); 1200 const count = card.querySelector('[data-report-likes-count]'); 1201 if (!button || !count) return; 1202 const liked = stats?.user_reaction === 'like'; 1203 const likes = Math.max(0, Number(stats?.counts?.like) || 0); 1204 button.setAttribute('aria-pressed', liked ? 'true' : 'false'); 1205 button.classList.toggle('is-liked', liked); 1206 count.textContent = numberFormat.format(likes); 1207 button.setAttribute('aria-label', `${liked ? 'Bericht gefällt dir' : 'Bericht gefällt mir'} · ${numberFormat.format(likes)} Likes`); 1208 } 1209 1210 function setStatus(card, text, tone = '') { 1211 const status = card.querySelector('[data-report-interaction-status]'); 1212 if (!status) return; 1213 status.textContent = text; 1214 status.dataset.tone = tone; 1215 } 1216 1217 async function loadStats(postId, card) { 1218 try { 1219 const config = await getConfig(); 1220 if (activePostId !== postId || !card.isConnected) return; 1221 const [views, reactions] = await Promise.allSettled([ 1222 ajax(config, { 1223 action: 'mz_trendometer_views_stats', 1224 nonce: config.viewNonce, 1225 id: String(postId) 1226 }), 1227 ajax(config, { 1228 action: 'mz_article_reactions_stats', 1229 nonce: config.reactionNonce, 1230 post_id: String(postId) 1231 }) 1232 ]); 1233 if (activePostId !== postId || !card.isConnected) return; 1234 if (views.status === 'fulfilled') setViewCount(card, views.value); 1235 if (reactions.status === 'fulfilled') setLikeState(card, reactions.value); 1236 if (views.status === 'rejected' && reactions.status === 'rejected') { 1237 setStatus(card, 'Aufrufe und Likes sind gerade nicht verfügbar.', 'error'); 1238 } 1239 } catch { 1240 if (activePostId === postId && card.isConnected) { 1241 setStatus(card, 'Aufrufe und Likes sind gerade nicht verfügbar.', 'error'); 1242 } 1243 } 1244 } 1245 1246 async function trackView(postId, card) { 1247 if (wasViewed(postId) || activePostId !== postId || !card.isConnected) return; 1248 rememberView(postId); 1249 try { 1250 const config = await getConfig(); 1251 const stats = await ajax(config, { 1252 action: 'mz_trendometer_track', 1253 nonce: config.viewNonce, 1254 type: 'post', 1255 id: String(postId) 1256 }); 1257 if (activePostId === postId && card.isConnected) setViewCount(card, stats); 1258 window.MZAnalytics?.track?.('report_view_counted', {post_id: postId}); 1259 } catch { 1260 // An uncertain response may already have been counted; do not duplicate it. 1261 } 1262 } 1263 1264 function scheduleView(postId, card) { 1265 clearInterval(viewInterval); 1266 if (wasViewed(postId)) return; 1267 let visibleTime = 0; 1268 let lastTick = performance.now(); 1269 viewInterval = window.setInterval(() => { 1270 const now = performance.now(); 1271 if (activePostId !== postId || !card.isConnected || card.closest('[hidden]')) { 1272 clearInterval(viewInterval); 1273 return; 1274 } 1275 if (document.visibilityState === 'visible') visibleTime += Math.min(now - lastTick, 600); 1276 lastTick = now; 1277 if (visibleTime >= VIEW_DELAY_MS) { 1278 clearInterval(viewInterval); 1279 trackView(postId, card); 1280 } 1281 }, 500); 1282 } 1283 1284 async function likeReport(postId, card) { 1285 const button = card.querySelector('[data-report-like]'); 1286 if (!button || button.disabled) return; 1287 if (button.getAttribute('aria-pressed') === 'true') { 1288 setStatus(card, 'Dein Like ist bereits gespeichert.', 'success'); 1289 return; 1290 } 1291 button.disabled = true; 1292 setStatus(card, 'Like wird gespeichert â¦'); 1293 try { 1294 const config = await getConfig(); 1295 const stats = await ajax(config, { 1296 action: 'mz_article_react', 1297 nonce: config.reactionNonce, 1298 post_id: String(postId), 1299 reaction: 'like' 1300 }); 1301 if (activePostId !== postId || !card.isConnected) return; 1302 setLikeState(card, stats); 1303 setStatus(card, stats.message || 'Danke! Dein Like ist gespeichert.', 'success'); 1304 window.MZAnalytics?.track?.('report_like', {post_id: postId}); 1305 } catch { 1306 if (activePostId === postId && card.isConnected) { 1307 setStatus(card, 'Der Like konnte gerade nicht gespeichert werden.', 'error'); 1308 } 1309 } finally { 1310 if (button.isConnected) button.disabled = false;
1311 } 1312 } 1313 1314 function createCard(postId) { 1315 const card = element('section', 'mz-report-engagement'); 1316 card.setAttribute('aria-label', 'Aufrufe und Like'); 1317 1318 const views = element('div', 'mz-report-view-stat'); 1319 views.dataset.reportViews = ''; 1320 views.append( 1321 element('span', 'mz-report-engagement-icon', 'ð'), 1322 element('strong', '', 'â'), 1323 element('span', '', 'Aufrufe') 1324 ); 1325 views.querySelector('strong').dataset.reportViewsCount = ''; 1326 1327 const like = element('button', 'mz-report-like'); 1328 like.type = 'button'; 1329 like.dataset.reportLike = ''; 1330 like.setAttribute('aria-pressed', 'false'); 1331 like.setAttribute('aria-label', 'Bericht gefällt mir'); 1332 like.append( 1333 element('span', 'mz-report-like-heart', 'â¥'), 1334 element('span', '', 'Gefällt mir'), 1335 element('strong', '', 'â') 1336 ); 1337 like.querySelector('strong').dataset.reportLikesCount = ''; 1338 like.addEventListener('click', () => likeReport(postId, card)); 1339 1340 const status = element('p', 'mz-report-engagement-status', 'Aufrufe und Likes aus App und Website.'); 1341 status.dataset.reportInteractionStatus = ''; 1342 status.setAttribute('role', 'status'); 1343 1344 const actions = element('div', 'mz-report-engagement-actions'); 1345 actions.append(views, like); 1346 card.append(actions, status); 1347 return card; 1348 } 1349 1350 window.addEventListener('mz:article-read', event => { 1351 const postId = Number(event.detail?.id); 1352 if (!Number.isSafeInteger(postId) || postId < 1) return; 1353 const reader = document.querySelector('.mz-report-reader'); 1354 const body = reader?.querySelector('.mz-report-body'); 1355 if (!reader || !body) return; 1356 1357 activePostId = postId; 1358 clearInterval(viewInterval); 1359 reader.querySelector('.mz-report-engagement')?.remove(); 1360 const card = createCard(postId); 1361 body.insertAdjacentElement('beforebegin', card); 1362 loadStats(postId, card); 1363 scheduleView(postId, card); 1364 }); 1365 1366 window.addEventListener('pagehide', () => clearInterval(viewInterval), {once: true}); 1367})(); 1368 1369</script>
1369 1370
1370<script src="/app/mz-articles-v2.js?v=20260908-2" defer></script>
1370 1371
1371<script src="/app/mz-article-preferences-v1.js?v=20260908-2" defer></script>
vendor: 1 bytes, line 1371
1371
1372<script type="module" src="https://static.cloudflareinsights.com/beacon.min.js/v31edd6df95cf4e85bb4c19e7a9bdbcba1788362987495" integrity="sha512-iIg7k2xntmwu6/uSb5tpc/hySgZc4eoL31yB29W6tJFo2akwjPWcEqnCEdJvGexCL0KEQwVYv5BlowfhVz26hg==" data-cf-beacon='{"version":"2024.11.0","token":"63195a54b95243a9afd8e8f18b56fb7b","r":1,"spa":2}' crossorigin="anonymous"></script>
1372 1373</body> 1374</html>
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.