diff --git a/VERSION b/VERSION index 08e9158..64e9c64 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1217 \ No newline at end of file +1219 \ No newline at end of file diff --git a/backend/static/css/components.css b/backend/static/css/components.css index 77b70ec..87dea9c 100644 --- a/backend/static/css/components.css +++ b/backend/static/css/components.css @@ -3053,17 +3053,18 @@ html.modal-open { .map-legend::-webkit-scrollbar { display: none; } /* Regenradar-Zeitleiste (RainViewer: ~2h Vergangenheit + ~30min Nowcast, Play/Pause + Slider) */ -/* Optik wie die Status-Pill darunter (hell/cremefarben, Blur, Border), direkt darüber gesetzt. */ +/* Optik + Maße wie die Status-Pill darunter: gleiche linke Kante (var(--space-3)); die Breite wird + per JS an die Pill angeglichen (gleiche rechte Kante). Höhe wie die Pill. */ .map-radar-timeline { position: absolute; left: var(--space-3); - right: 88px; /* Platz für die Ecken-FABs (Speed-Dial / Zurück) rechts */ - bottom: calc(var(--space-3) + 40px); /* unmittelbar über der Status-Pill */ + width: min(320px, calc(100% - 100px)); /* Fallback; JS setzt = Pill-Breite */ + bottom: calc(var(--space-3) + 34px); /* unmittelbar über der Status-Pill */ z-index: 900; display: flex; align-items:center; - gap: 8px; - padding: 4px 12px 4px 5px; + gap: 7px; + padding: 3px 12px 3px 4px; border-radius: var(--radius-full); background: rgba(255, 255, 255, 0.88); backdrop-filter: blur(4px); @@ -3071,6 +3072,7 @@ html.modal-open { border: 1px solid var(--c-border-light); color: var(--c-text); pointer-events: auto; + box-sizing: border-box; } :root[data-theme="dark"] .map-radar-timeline { background: rgba(24, 20, 16, 0.92); @@ -3078,19 +3080,20 @@ html.modal-open { } .rdr-play { flex-shrink: 0; - width: 30px; height: 30px; + width: 24px; height: 24px; border: none; border-radius: 50%; background: var(--c-surface-2); color: var(--c-text); cursor: pointer; display: flex; align-items: center; justify-content: center; } +.rdr-play svg { width: 14px; height: 14px; } .rdr-play:active { background: var(--c-border); } .rdr-slider { flex: 1; min-width: 0; height: 4px; accent-color: var(--c-primary); cursor: pointer; } .rdr-time { flex-shrink: 0; font-size: 11px; font-weight: 600; font-variant-numeric: tabular-nums; - min-width: 78px; text-align: right; color: var(--c-text-secondary); + min-width: 74px; text-align: right; color: var(--c-text-secondary); } .rdr-time.is-forecast { color: var(--c-primary); } /* Nowcast/Vorhersage-Frames hervorgehoben */ diff --git a/backend/static/index.html b/backend/static/index.html index 60bf077..1770205 100644 --- a/backend/static/index.html +++ b/backend/static/index.html @@ -86,14 +86,14 @@ Ban Yaro - + - - - - - + + + + + @@ -617,11 +617,11 @@ - - - - - + + + + + @@ -631,7 +631,7 @@ - + diff --git a/backend/static/js/app.js b/backend/static/js/app.js index 1433eb5..6d91f3c 100644 --- a/backend/static/js/app.js +++ b/backend/static/js/app.js @@ -3,7 +3,7 @@ Router, State-Management, Navigation, Initialisierung. ============================================================ */ -const APP_VER = '1217'; // ← bei jedem Deploy mit Frontend-Änderungen erhöhen +const APP_VER = '1219'; // ← bei jedem Deploy mit Frontend-Änderungen erhöhen const APP_VERSION = '1.6.0'; // ← semantische Version, wird bei make release gesetzt window.APP_VER = APP_VER; // global verfügbar für andere Module (z.B. offline-indicator) window.APP_VERSION = APP_VERSION; diff --git a/backend/static/js/pages/map.js b/backend/static/js/pages/map.js index 29bff06..568f5d3 100644 --- a/backend/static/js/pages/map.js +++ b/backend/static/js/pages/map.js @@ -621,12 +621,16 @@ window.Page_map = (() => { document.getElementById('central-map')?.appendChild(el); el.querySelector('#rdr-play').addEventListener('click', _toggleRadarPlay); el.querySelector('#rdr-slider').addEventListener('input', e => { + const idx = parseInt(e.target.value, 10); // ZUERST lesen: _radarPause() setzt slider.value zurück _radarPause(); - _showRadarFrame(parseInt(e.target.value, 10)); + _showRadarFrame(idx); }); } else { el.querySelector('#rdr-slider').max = _radarFrames.length - 1; } + // Breite an die Status-Pill angleichen → gleiche linke + rechte Kante. + const pill = document.querySelector('.map-statusbar'); + if (pill && pill.offsetWidth > 60) el.style.width = pill.offsetWidth + 'px'; _updateRadarTimelineUI(); } diff --git a/backend/static/landing.html b/backend/static/landing.html index 0b01da6..9eef0c0 100644 --- a/backend/static/landing.html +++ b/backend/static/landing.html @@ -4,7 +4,7 @@ - + Ban Yaro — Die Hunde-App für Deutschland, Österreich & Schweiz diff --git a/backend/static/sw.js b/backend/static/sw.js index 1affc8c..b3e17b8 100644 --- a/backend/static/sw.js +++ b/backend/static/sw.js @@ -4,7 +4,7 @@ ============================================================ */ // ← EINZIGE Stelle für die Version — STATIC_ASSETS und CACHE_VERSION leiten sich ab -const VER = '1217'; +const VER = '1219'; const CACHE_VERSION = `by-v${VER}`; const CACHE_STATIC = `${CACHE_VERSION}-static`; const CACHE_TILES = 'ban-yaro-tiles-v1'; // bleibt über SW-Updates erhalten diff --git a/docs/DWD_RAIN_FORECAST_PLAN.md b/docs/DWD_RAIN_FORECAST_PLAN.md new file mode 100644 index 0000000..4c84e5d --- /dev/null +++ b/docs/DWD_RAIN_FORECAST_PLAN.md @@ -0,0 +1,56 @@ +# DWD Regen-Vorhersage (Radar-Nowcast) — Scoping-Plan + +**Status:** gescoppt + Datenformat verifiziert (2026-06-05). Umsetzung offen. +**Ziel:** Verlässliche, längere Regen-**Vorhersage** als animiertes Karten-Overlay (bis +2 h) statt RainViewers +unzuverlässigem 30-Min-Nowcast (der oft leer ist). Self-hosted wie die Basemap — passt zur Tile-Server-Philosophie. + +## Quelle: DWD RV (Composite RV) — kostenlos, kein API-Key +- `https://opendata.dwd.de/weather/radar/composite/rv/DE1200_RV.tar.bz2` +- **Alle 5 Min** publiziert. Jedes Archiv = ein Vorhersage-Lauf mit **25 Frames** `_000`…`_120` + (**0 bis +120 Min**, 5-Min-Schritte), je ~2,5 MB unkomprimiert (~1 MB als .tar.bz2). +- **Format (verifiziert):** RADOLAN-Binär. 194-Byte-ASCII-Header bis `ETX (0x03)`, dann **1200×1100 uint16 + little-endian** (= 2.640.000 Byte). Header-Felder: `PR E-02` (0,01 mm), `INT 5` (5-Min-Summe), + `GP1200x1100`, `VV` (Lead-Time). **Wert = `raw & 0x0FFF` × 0,01 mm/5min; `raw & 0x2000` = kein Daten.** + → Decode trivial, **kein wradlib nötig** (PoC: 1,32 Mio Zellen geparst, Regen korrekt erkannt). +- **Gitter/Projektion:** DE1200 (1 km), polar-stereografisch, fest georeferenziert (Eckkoordinaten dokumentiert; + wradlib `get_radolan_grid` ODER GDAL mit dem bekannten RADOLAN-PROJ-String). +- **Abdeckung:** Deutschland + Randbereiche (reicht etwas nach AT/CH/Nachbarn, aber DE-zentriert). + Voll-AT/CH bräuchte ACG/MeteoSwiss → out of scope. + +## Pipeline (Server-seitig, Cron alle 5 Min — analog zum OSM-POI-Job) +1. **Fetch** neueste `DE1200_RV