Jedes Windvorranggebiet kann jetzt 1–n text_fragment-Einträge als
Stellungnahme-Kriterien referenzieren. Das Panel lädt diese lazy beim
Öffnen und zeigt sie als aufklappbare Accordion-Sektion.
Außerdem: alle hardcodierten Strings im Karten-Block (Panel, Map,
Block) durch t()-Aufrufe ersetzt; 7 neue Translation-Keys ergänzt.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- /api/vorranggebiete.geojson + .kml endpoints (filter via ?id=W-XX)
- Download-Buttons in WindAreaPanel pro selektiertes Gebiet
- Hover-Tooltip auf Polygon zeigt Fläche, geplante Anlagen, Höhe, Gemeinden
- Favicon + apple-touch-icon dynamisch aus data.logoUrl (CMS-Logo)
- alte windrad-PNGs in static/favicons/ entfernt
- WindkarteBlock list-fetch: _limit statt limit (RustyCMS-Param)
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Green gradient header, white card with shadow, left-border accent on open
accordion items, hover-visible copy button in summary row, lighter dividers.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Neuer CMS-Block `wind_map` — platzierbar auf jeder Seite per Row-Content.
Fetcht wind_area-Einträge + GeoJSON-Asset client-side, rendert Leaflet-Karte
(CartoDB Light) mit farbcodierten Polygonen nach Planungsstatus. Klick auf
Gebiet öffnet Slide-in-Panel mit Kenndaten, Gemeinden, Stellungnahme-Link
und Puffer-Ringen (200/600/1000 m via Turf). Erweiterbar für 2. Entwurf 2026.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- /api/kalender.ics SSR route: ICS feed of all calendar items (webcal-subscribable, Cache 1h)
- buildICSFeed() / downloadICSFeed() for multi-event ICS export
- googleCalUrl() deep-link pre-fills Google Calendar create form
- Web Share API per event (navigator.share on mobile, clipboard fallback on desktop)
— "Kopiert\!" toast per event for 2s after clipboard write
- Actions bar (subscribe + bulk export) only rendered after onMount
— Apple platforms: webcal:// link opens Calendar.app natively
— All others: direct ICS download via <a download>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Calendar widget stays stacked (calendar above events list)
- Grid widens to max-w-2xl with fixed h-10 cells (no aspect-square height growth)
- Gap between cells: 0.5 → 1.5
- Button system extracted to shared btn-* utility classes in app.css
- Replaced Google Calendar link + Google Maps with OSM
- Removed google icon from iconify subset
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace direct post.isEvent/eventDate/eventLocation reads with
getPostEventInfo() helper that derives info from the resolved
calendarItem reference. Loaders now resolve "calendarItem" and request
that field instead of legacy flat properties.
Also regenerate iconify mdi subset (map-marker-outline, download,
google, calendar-search, refresh).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
RustyCMS /api/transform decodes only the first frame of animated formats,
which silently kills GIF animation when markdown HTML images get rewritten
to /api/transform URLs. Skip the transform for `.gif` URLs so the original
asset URL flows through and animation survives.
Also picks up an arrow-right entry in the iconify mdi subset generated
during a UI build.
- Palette: gray/zinc/slate/neutral → stein, red → fire, amber → erde,
sky → himmel, green → wald
- Footer: replaced raw rgb with stein tokens
- Radius: unified to rounded-xs across cards, buttons, inputs, pagination
- Buttons: .btn-primary/.btn-secondary now font-medium; added secondary
- Card hover: -translate-y-0.5 + shadow + wald-300 border
- Header active link: wald border-bottom + wald-700 text
- Mobile nav: bigger touch targets + wald active accent
- Pagination: prev/next text labels + wald-500 active state with
separated shape/color classes to avoid Tailwind conflicts
- Lead paragraph: scoped .markdown > p:first-child for top-level
MarkdownBlock only via [data-block-type="markdown"]
- Section dividers: subtle wald-200 gradient between content rows
- Global focus-visible ring (wald-500)
- Inline hex → palette tokens (Badge amber, Tag custom-color contrast)
- Font weights snapped to design system (300/400/500/600/700)
- transition-all → transition-colors where only color changes
- Removed em-dashes from user-visible templates
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Audit at 22:15 MESZ flagged the conventional sum (lignite + hard coal
+ gas + nuclear) as 19.1 GW in the widget vs 15.65 GW in reality. The
breakdown showed the gap was Energy-Charts' `Fossil gas` (6.9 GW)
which bundles natural gas + GuD + similar, while SMARD's `Erdgas`
filter 4069 (3.8 GW) tracks just natural gas the way the widget label
implies. SMARD is the canonical German grid feed; switching the
primary source resolves the discrepancy directly.
- New `lib/smard.ts` fetches the 11 relevant filter IDs in parallel:
conventional (1223/4070/4069/1224), wind (4067/1225), solar (1226),
hydro (1228), biomass (4066), other-conventional + pumped storage
(1227/4071, surfaced separately), load (410). Two-step protocol
(index.json → archive.json) handled inside; output is MW (MWh × 4)
aligned to one common slot timestamp so every value on screen comes
from the same point in time.
- Aggregator route uses SMARD for production + load, Energy-Charts
only for cross-border saldo + day-ahead prices (where SMARD has no
convenient single-call endpoint). `dataSource: "smard" |
"energy-charts"` flag travels in the response so the widget can
attribute the numbers and fall back gracefully when SMARD is down.
- StrommixBlock gets a "Werte prüfen" disclosure that lists every
component (wind onshore + offshore, solar, the four conventional
buckets, biomass, hydro, load) with its MW value and the slot
timestamp + data source. Fact-check users can verify the addition
themselves now without asking.
Verified live: SMARD @ 21:00 UTC = lignite 8484 + hard coal 3480 +
gas 3811 + nuclear 0 = 15.78 GW conventional. Matches the user's
ground-truth 15.65 GW within sampling noise.
The previous setup loaded the full @iconify-json/mdi collection (7000+
icons, 2.95 MB) just to render the ~30 icons we actually use, producing a
2.99 MB client chunk.
generate-icons.mjs scans src/ for static `icon="mdi:..."` references,
extracts a minimal IconifyJSON containing only those icons (plus an
EXTRA_ICONS list for dynamic CMS-driven names) from
@iconify-json/mdi/icons.json, and writes it to a generated subset file.
iconify-offline.ts now registers that subset instead of the full pack.
build/client: 5.6 MB -> 1.6 MB (-71%)
build/server: 5.3 MB -> 2.4 MB (-55%)
largest client chunk: 2.99 MB -> 127 KB (-96%)
iconify subset: 2.95 MB -> 15.5 KB (-99.5%)
Hooked into predev/prebuild so the subset stays fresh; missing icons
fall back to the iconify API at runtime.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>