=== Spelhubben Weather ===
Contributors: spelhubben
Tags: weather, forecast, widget, shortcode, blocks
Requires at least: 6.8
Tested up to: 7.0
Requires PHP: 7.4
Stable tag: 2.1.2
Donate link: https://www.paypal.com/donate/?hosted_button_id=CV74CEXY5XEAU

License: GPLv3 or later
License URI: https://www.gnu.org/licenses/gpl-3.0.html

Weather widget, Gutenberg block and shortcode with hourly forecasts, smart local maps and multi-provider forecasts.

== License ==

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.

Full license text is included in the `LICENSE` file in the plugin root.

== Feedback & Bug Reports ==
Feedback and bug reports can be posted here: https://github.com/K3NT4/spelhubben-weather/issues
For common questions see the FAQ: https://github.com/K3NT4/spelhubben-weather/blob/main/Docs/FAQ.md
For Roadmap: https://github.com/users/K3NT4/projects/2

Weather widget & block with optional map and daily forecast. Can combine Open-Meteo, SMHI, Yr/MET, MET Norway Nowcast, FMI, OpenWeatherMap, and WeatherAPI.com data.

== Description ==
This plugin displays current weather and an optional forecast. It can aggregate data from free global weather providers (Open-Meteo, SMHI, Yr/MET Norway, MET Norway Nowcast, FMI, OpenWeatherMap, and WeatherAPI.com) and compute a simple consensus. Works worldwide with excellent coverage in Europe and beyond.

== Changelog ==

= 2.1.2 =
- Improved: WordPress 7.0 compatibility by moving the Gutenberg block and legacy block registration to Block API v3.
- Fixed: Block editor previews now load Spelhubben Weather content assets inside the iframed editor.
- Improved: Plugin metadata and asset versions now target WordPress 7.0 while keeping the minimum requirements at WordPress 6.8 and PHP 7.4.

= 2.1.0 =
- Added: Central provider registry shared by settings, renderer, shortcode/block/widget surfaces, diagnostics and documentation.
- Added: Real MET Norway Nowcast 2.0 current-weather provider with explicit `ok`, `missing_key`, `no_coverage`, `request_failed`, and `no_data` diagnostics.
- Added: Compact hourly forecast via Open-Meteo using `hourly="1"` and `hours="3-24"` (default `24`).
- Changed: Removed the external Leaflet CDN fallback. Map scripts and vendor assets are now local-only.
- Changed: OpenWeatherMap and WeatherAPI are disabled by default on fresh installs until API keys are configured.
- Added: Smart map foundation with OpenLayers, Leaflet legacy mode, static fallback, `map_engine`, and map diagnostics in Performance.
- Improved: Shortcode, Gutenberg block and widget parity for hourly forecast, tides, presets and map engine attributes.
- Fixed: Admin settings layout no longer overlaps on wider forms, and bundled textdomain/script translations load consistently from `/languages`.
- Improved: Hourly forecast time labels now use a locale-aware compact format, e.g. `13:00` for Swedish/Norwegian sites and `1:00 PM` for US English.
- Improved: CI now separates PHP lint, regression tests, asset-sync checks and release checks.

= 2.0.4 =
- Added: Admin settings for OpenWeatherMap and WeatherAPI keys, and runtime calls now send the correct key/query parameters.
- Fixed: Provider docs, settings text, and shortcode guidance now match the actual 7-provider matrix and API-key requirements.
- Fixed: `map_height` is clamped in the renderer too, so shortcode/block/widget overrides consistently honor the documented 120px minimum.
- Fixed: Shortcodes admin/provider docs were unified and the Quick Builder now uses the same provider list as the shortcode reference.
- Fixed: Shortcodes admin layout was rebalanced so the examples column stays readable and the Quick Builder wraps more cleanly.
- Improved: Provider order is normalized in cache keys for better cache hit rates.
- Improved: Added reproducible asset-build and release-check scripts; refreshed `assets/map.min.js` and added `assets/style.min.css`.
- Improved: Privacy/consent documentation clarified for optional Leaflet/OpenStreetMap map fallback behavior.

= 2.0.3 =
- Fixed: Added default `units` and `yr_contact` options to remove undefined index notices on new installs.
- Fixed: Widget now initializes options before render so `wind_unit` fallback is safe and notice-free.
- Fixed: Admin attribution checker now uses the localized AJAX nonce (no more `nonce is not defined` error).
- Fixed: Rebuilt `assets/map.min.js` from the source to eliminate the stray syntax error and keep parity with `map.js`.

= 2.0.2 =
- Urgent Fix: Ensure `assets/vendor` is included in distribution packages (adjusted `.distignore` rules). This prevents missing Leaflet vendor files after packaging/deploy.
- Fixed: Plugin version constant and admin asset versioning made consistent with the release.
- Documentation: Updated packaging notes and deploy recommendations.

= 2.0.1 =
- Fixed: Minor asset/enqueue edge-case causing Leaflet/map to fail loading on some paginated or special views where `$post` is not available.
- Fixed: Plugin version constant and admin asset versioning updated to reflect release `2.0.1`.
- Improved: Documentation updates and metadata cleaned up for the new release.


**Features**
- **Shortcode** `[spelhubben_weather]`, **Gutenberg block**, and **classic widget**
- **7 Weather Providers:** Open-Meteo, SMHI, Yr (MET Norway), MET Norway Nowcast, FMI, OpenWeatherMap, WeatherAPI.com — enable any combination
- **Icon Themes:** Classic, Modern Flat, Modern Gradient, Modern 2026, Modern 3D (selectable in admin settings)
- **Multiple Layouts:** `inline`, `compact`, `card`, `detailed`
- **Daily Forecast:** 3–10 days customizable
- **Provider Comparison:** Side-by-side data from all enabled providers
- **Smart Map:** OpenLayers by default, Leaflet legacy mode, static fallback and OpenStreetMap attribution (ODbL)
- **Hourly Forecast:** compact 3–24 hour timeline powered by Open-Meteo with locale-aware time labels
- **Wind direction display:** Rotated arrow with cardinal labels (optional via `show=wind_dir`)
- **Local Icons:** SVG icons (no CDN dependency), responsive scaling
- **Performance:** 6-30x faster settings page, lazy-loaded plugin showcase, optimized caching
- **Fully GDPR Compliant:** No cookies, no tracking, no personal data collection
- **Translation-Ready:** English base strings, Swedish and Norwegian Bokmål translations included

*Not affiliated with Open-Meteo, SMHI, Yr/MET Norway, MET Norway Nowcast, FMI, OpenLayers, Leaflet, or OpenStreetMap. Names are used for descriptive purposes only. Map data © OpenStreetMap contributors (ODbL).*

== Installation ==
1. Upload/activate the plugin.
2. Go to **Settings → Spelhubben Weather** and set defaults (place, shown fields, layout, providers, cache time, units/format).
3. Add weather to your site in any of these ways:

= Block (Gutenberg) =
- Edit a page/post → click **Add block** → search for **“Spelhubben Weather”**.
- Optional: override defaults in the block sidebar (place/lat,lon, layout, map, forecast).

= Shortcode =
- Insert `[spelhubben_weather]` anywhere shortcodes are supported.
- Examples:
  - Basic: `[spelhubben_weather]`
  - Compact with map & animation: `[spelhubben_weather place="Gothenburg" layout="compact" map="1" animate="1"]`
  - Inline no map: `[spelhubben_weather lat="57.7089" lon="11.9746" layout="inline" map="0" show="temp,icon"]`
  - Detailed + daily forecast (5 days) + provider mix: `[spelhubben_weather place="Umeå" layout="detailed" forecast="daily" days="5" providers="smhi,yr,openmeteo,fmi"]`
  - With wind direction: `[spelhubben_weather place="Stockholm" show="temp,wind,wind_dir,icon" layout="compact" animate="1"]`
  - Compact hourly forecast: `[spelhubben_weather hourly="1" hours="24" layout="compact"]`
  - OpenLayers map engine: `[spelhubben_weather map="1" map_engine="openlayers"]`
  - Dashboard preset: `[spelhubben_weather preset="dashboard" hourly="1" map="1"]`

= Classic Widget =
- Go to **Appearance → Widgets** → add **Spelhubben Weather**.
- Configure per-widget options (title, place or lat/lon, fields, layout, map, forecast, days, CSS class).

== Frequently Asked Questions ==

= Where does the data come from? =
From public APIs such as Open-Meteo, SMHI, Yr/MET Norway, MET Norway Nowcast, **FMI** (Finnish Meteorological Institute), OpenWeatherMap, and WeatherAPI.com. You choose providers under **Settings → Spelhubben Weather** or per block/shortcode/widget via the `providers` attribute.

= Do I need an API key? =
Usually no. Open-Meteo, SMHI, Yr/MET Norway, MET Norway Nowcast, and FMI do not require keys. OpenWeatherMap and WeatherAPI.com do require API keys, and for Yr/MET Norway it’s recommended to include contact info (email/URL) in **Settings → Spelhubben Weather → Yr contact/UA** so your User-Agent is compliant.

= Block, shortcode or widget — what’s the difference? =
All three render the same UI. Use the **block** in the block editor, the **shortcode** in classic content areas, and the **widget** in sidebars (Appearance → Widgets). Each lets you override global defaults.

= How do place and coordinates work? =

= Tide (experimental) =

If you're testing experimental tide support:

- **Enabling:** Turn on `Tides` in Settings → Spelhubben Weather and select a provider (WorldTides, NOAA or Custom endpoint). WorldTides typically requires an API key.
- **Shortcode:** Use `extras="tides"` or `tides="1"` to show tide events, e.g. `[spelhubben_weather place="Gothenburg" extras="tides"]`.
- **Providers:** WorldTides (global, commercial), NOAA Tides & Currents (US only), or supply a custom endpoint that returns JSON with `events`/`extremes`/`data` arrays (items should include `time`, and optionally `type` and `height`).
- **Troubleshooting:** Use `tests/tide_test.php` to validate provider responses and caching. Ensure provider settings and API key are correct; tide results are cached according to the configured TTL.

If `lat` and `lon` are provided they take precedence. Otherwise the plugin geocodes the `place` string (e.g. `place="Umeå"`). Set a global default place in settings.

= What fields can I show/hide? =
Use `show="temp,wind,icon"` (comma separated). Defaults are set in settings. Add `wind_dir` to show wind direction arrow and label.

= How do layouts work? =
Choose `layout="inline|compact|card|detailed"`. “Detailed” supports the multi-day forecast row.
= Can I see individual provider data (for comparison)? =
Yes! Use `comparison="1"` to show all enabled providers' data side-by-side. Useful for debugging or comparing which providers are available in your location.
Example: `[spelhubben_weather place="Stockholm" comparison="1" providers="openmeteo,smhi,yr,fmi,openweathermap,weatherapi"]`

= What icon themes are available? =
The plugin offers multiple themes: **Classic** (traditional), **Modern Flat** (clean, minimalist), **Modern Gradient** (contemporary with subtle gradients), **Modern 2026** (duotone/stroke modern style), and **Modern 3D** (subtle gradients + drop-shadows). Choose in **Settings → Spelhubben Weather → Icon style**. All themes include icons for sun, partly-cloudy (including alternate), cloud, fog, rain, sleet, snow, storm/thunder, and hail where applicable.

= How do I enable the map and set its size? =
`map="1"` shows a smart OpenStreetMap-powered map. By default `map_engine="auto"` tries OpenLayers first, then Leaflet legacy, then a static fallback with coordinates and an OSM link. You can force `map_engine="openlayers|leaflet|static"`. Control height with `map_height="240"` (px). Global defaults exist in settings.

= How do I get an hourly forecast? =
Set `hourly="1"` and optionally `hours="3–24"`. Example: `hourly="1" hours="24"`. Hour labels follow the active site locale, such as 24-hour time for Swedish/Norwegian sites.

= How do I enable animations? =
`animate="1"` adds subtle UI animation. Global default is in settings. The renderer also accepts `true`, `yes`, or `on` as truthy values for convenience.

= How do I get a daily forecast? =
Set `forecast="daily"` and `days="3–10"`. Example: `forecast="daily" days="5"`.

= How do I use moon phase? =
Use `extras="moon"` to show moon phase in the weather meta area. Use `extras="moon_daily"` together with `forecast="daily"` to show moon information in the daily forecast. Example: `[spelhubben_weather extras="moon"]`.

= Can I mix providers and get a consensus? =
Yes. Set `providers="smhi,yr,openmeteo,fmi"` (order doesn’t matter). The plugin calculates a simple consensus across available providers for the displayed fields.

= Units & format? =
Pick a preset with `units="metric|metric_kmh|imperial"`. You can override parts via `temp_unit="C|F"`, `wind_unit="ms|kmh|mph"`, `precip_unit="mm|in"`, and `date_format` for forecast labels. All have global defaults in settings (**Units & format** section).

= Caching — how long is data stored? =
Responses are cached with WordPress transients. Change TTL (minutes) in settings. Clear via the **Clear cache** button on the Performance page (Settings → Performance) or by changing attributes (which creates a new cache key).

= Does it work without JavaScript? =
Yes, rendering is server-side. Interactive maps require JS, but the map area can fall back to a static status with coordinates and an OpenStreetMap link.

= Translations? =
The plugin is fully translatable. **Included translations:** **Swedish (sv_SE), Norwegian Bokmål (nb_NO)**. Strings are also available on translate.wordpress.org. Bundled translation files live in `/languages` and include `.pot`, `.po`, `.mo`, `.l10n.php`, and block editor JSON files.

= GDPR / privacy? =
The plugin does not set cookies by itself. If you enable the map, OpenStreetMap tiles are requested client-side by the local OpenLayers/Leaflet runtime. Mention OSM in your privacy notice if needed.

= Troubleshooting tips =
- Nothing shows: check that at least one provider is selected in settings.
- Wrong location: provide exact `lat`/`lon` or a more specific `place` (e.g. “Uddevalla, SE”).
- Map not visible: ensure `map="1"` and that your theme/container is wide/tall enough; increase `map_height`.
- Rate limiting: reduce refreshes or increase cache TTL.
== Translations ==

The plugin is **fully translatable** and includes built-in translations for **Swedish (sv_SE)** and **Norwegian Bokmål (nb_NO)**.

=== How to translate the plugin ===

**Option 1: Contribute to translate.wordpress.org (recommended)**
- Visit [translate.wordpress.org](https://translate.wordpress.org/projects/wp-plugins/spelhubben-weather/)
- Select your language and add translations via the browser interface
- Your translations will automatically be included in future releases

**Option 2: Local translation files**
If you need to add or modify translations locally:

1. **Generate or update the POT file** (translation template):
   ```
   wp i18n make-pot . languages/spelhubben-weather.pot --slug=spelhubben-weather
   ```

2. **Create a PO file for your language** (e.g., `spelhubben-weather-de_DE.po`):
   - Copy the `.pot` file and rename to match your locale (e.g., `de_DE`)
   - Use a translation tool like [Poedit](https://poedit.net/) or a text editor
   - Translate all strings in the PO file
   - Save the file as `spelhubben-weather-de_DE.po`

3. **Generate the MO file** (compiled binary format):
   ```
   msgfmt spelhubben-weather-de_DE.po -o spelhubben-weather-de_DE.mo
   ```

4. **Place files in the plugin**:
   - Store both `.po` and `.mo` files in `/languages/`
   - If you bundle translations with the plugin, also keep generated `.l10n.php` files and block editor JSON files in sync with the PO/MO files.

5. **Activate your translation**:
   - Change your WordPress language to match the locale code (Settings → General → Site Language)
   - The plugin will automatically load the translated strings

**Translation file structure**:
```
languages/
  spelhubben-weather.pot          (template for all translations)
  spelhubben-weather-sv_SE.po    (Swedish source text)
  spelhubben-weather-sv_SE.mo    (Swedish compiled)
  spelhubben-weather-sv_SE.l10n.php
  spelhubben-weather-nb_NO.po    (Norwegian source text)
  spelhubben-weather-nb_NO.mo    (Norwegian compiled)
  spelhubben-weather-nb_NO.l10n.php
```

**What gets translated**:
- All frontend strings (shortcode output, widget labels, weather descriptions, WMO codes)
- Admin settings and UI labels
- JavaScript strings (expand/collapse, status messages)
- Error messages and notices

**Best practices**:
- Use context clues in the POT file (`msgctxt`) to distinguish similar phrases
- Test your translation in WordPress to ensure formatting and plurals work correctly
- Check that translated UI aligns properly in your language (RTL vs LTR)

== Screenshots ==
1. Frontend examples: inline, compact, card, detailed, with optional map.
2. Frontend example: New look and wind direction
3. Settings page: defaults, providers, cache, units & format.
4. Alerts page: active warnings and smart recommendations for extreme conditions.
5. Shortcodes page: searchable examples, copy buttons, and admin live preview.
6. Performance page: cache statistics, API usage and "Clear cache" action.

== Older Changelog ==

= 2.0.0 =
* FIX: Leaflet map now loads correctly on paginated, archive and guest pages where the global `$post` may be unavailable. Asset loader now scans the main query for shortcodes/blocks and enqueues Leaflet assets accordingly.
* CHANGE: Bumped version to 2.0.0.

= 1.9.9 =
* FIX: Leaflet/map is now displayed correctly even for guests and special pages where $post is not set (fallback to get_queried_object()).

- = 1.9.8 =
- **Fixed:** Fixed an issue where the Leaflet map could fail to load on live/optimized sites due to script handle conflicts with themes or other plugins.
- **Improved:** Renamed Leaflet asset handles to unique, plugin-specific names to prevent collisions and ensure correct dependency resolution.
- **Improved:** Removed forced defer handling for Leaflet/map scripts to avoid broken load order when caching/optimization plugins are active.
- **Improved:** Improved map initialization logic to prevent infinite retry loops and reduce console spam when Leaflet isn’t available.
- **Improved:** Kept Leaflet/map assets conditionally loaded only on pages where the widget/block/shortcode is actually rendered.

- = 1.9.7 =
- **Experimental:** Tide support added for testing — opt-in feature. Adds support for WorldTides (API key), NOAA (US-only), and a configurable custom endpoint. Shortcode support via `extras="tides"` or `tides="1"`. Admin visibility can be toggled while rolling out to selected users. Responses are cached; configure TTL in Settings.

- = 1.9.5 =
- **New:** Moon phase support via `extras="moon"` and daily moon information via `extras="moon_daily"`.

- = 1.9.4 =
- **Fixed:** Wind direction cardinal calculation and arrow rotation; ensured text-domain i18n call fixed for VC integration; asset sanitization workaround for wind arrow rotation (data-deg + frontend JS).

- = 1.9.3 =
- **New:** `wind_unit` override in Block inspector, Widget settings and Shortcodes Quick Builder.
- **Improved:** `metric_knt` preset for metric display with knots.
- **Fixed:** Wind direction arrow rotation corrected to match compass degrees.
- **Fixed:** Shortcode `wind_unit` reliably overrides resolved units and renderer emits `data-svv-wind-unit` for debugging.
- **Fixed:** Alert threshold comparisons now converted into display units to avoid false alerts.
- **Fixed:** PHP parse error in admin page resolved.
- **Changed:** Plugin version bumped to 1.9.3; readme stable tag updated.
- = 1.9.2 =
- **New:** Shortcode/Block/Widget `theme` attribute — `theme="auto|light|dark"` to force UI theme per instance (default `auto`).
- **New:** Quick Builder theme selector in admin Shortcodes page; example shortcode added.
- **Improved:** Renderer emits `data-svv-theme` and `svv-theme-<value>` class for easier CSS targeting.
- **Improved:** Frontend CSS and map styling — darker Leaflet tiles in dark theme and darker alert box styles for better contrast.
- **Changed:** Admin JS updated to include `theme` when generating shortcodes; docs updated across readmes.

- = 1.9.0 =
- **New:** Weather Alerts system with smart recommendations for extreme conditions
- **New:** Storm Warning alert for wind speeds exceeding 24.5 m/s
- **New:** Settings Export & Import feature for easy configuration management
- **New:** Performance Dashboard to track API usage, cache efficiency, and response times
- **New:** Full Dark Mode support for all frontend and admin interfaces
- **New:** 3 Gutenberg Block Patterns (Compact, Detailed, Forecast)
- **New:** Alert toggles for Blocks, Widgets, and Shortcodes
- **New:** Wind direction display (`wind_dir`) — rotated arrow + cardinal labels (optional via `show=wind_dir`)
- **New:** Shortcode Quick Builder in admin **Shortcodes** page with selectable options, one-click copy and live preview
 - **New:** Rotating Tips panel on the Settings page with contextual admin tips (Shortcodes, Alerts, Performance)
 - **New:** Compact action buttons in the Tips panel for quick access to Shortcodes, Alerts and Performance
 - **New:** "Reset to defaults" button on the Settings page (nonce-protected) to restore plugin defaults
 - **Improved:** Tips text is translation-ready, rotates more slowly for readability (15s), and uses `aria-live` for accessibility
- **Improved:** `animate` attribute parsing is more tolerant (accepts `1`, `true`, `yes`, `on`)
- **Improved:** Full English translation and i18n readiness (English is now the base language)
- **Improved:** Refined alert thresholds based on meteorological standards

= 1.8.6 =
- **Fixed:** Map not rendering in widgets due to missing Leaflet asset detection
- **Fixed:** Block name mismatch (`spelhubben/weather` → `spelhubben-weather/spelhubben-weather`) preventing proper asset enqueuing
- **Improved:** Enhanced Leaflet initialization with better timing and error handling in `map.js`
- **Improved:** Added widget detection in asset loading logic using `is_active_widget()`
- **Improved:** Added fallback height (`height: 240px;`) to `.svv-map` CSS class for better Leaflet container sizing
- **Improved:** Better error reporting and retry logic in map initialization with Leaflet availability checks

= 1.8.5 =
- **Performance:** Conditional Leaflet asset loading — only loads when shortcode or Gutenberg block is present on the page.
- **Fix:** Added `.htaccess` files to prevent WordPress rewrite rules from interfering with static assets.
- **Fix:** Ensure correct MIME types for CSS and JS files to prevent browser strict MIME checking warnings.
- **UX:** Eliminates unnecessary 404 errors on pages without weather widget.

= 1.8.4 =
- **Maintenance:** Added centralized configuration constants file (`includes/constants.php`) for improved code maintainability and reduced magic numbers.
- **Performance:** Settings page now loads 6-30x faster with lazy-loaded WP.org plugin showcase via AJAX.
- **Fix:** Fixed memory leaks from uncleanup event listeners in admin interface with proper cleanup handlers.
- **Fix:** Fixed WMO weather code duplication—fog (codes 45, 48) now displays correctly instead of showing cloud icon.
- **Fix:** Fixed geocoding cache to include API language, ensuring proper locale-specific results for multi-language sites.
- **Fix:** Fixed widget null-safety with null-coalesce operators to prevent PHP Notices.
- **Fix:** Standardized API error handling with consistent response validation across all providers.
- **Fix:** Fixed syntax error in WP.org plugin showcase API call (missing closing parenthesis).
- **Compliance:** Verified full WordPress Consent API and GDPR compliance—no cookies, no tracking, no personal data collection.
- **Code Quality:** Debounce timeout optimized (400ms → 600ms) reducing AJAX traffic by 50% during live preview.
- **Documentation:** Comprehensive audit and testing guides included for developers.

= 1.8.3 =
- Version bump for production release.

= 1.8.2 =
- **Fix:** WordPress naming convention compliance – all global functions and variables now use proper `sv_vader_` prefix.
- **Fix:** Corrected asset paths for Leaflet library (vendor directory structure).
- **Tech:** Code review and standards compliance (no breaking changes).
- Tested up to: WordPress 6.9

= 1.8.1 =
- **New:** 3 selectable icon themes: **Classic**, **Modern Flat**, and **Modern Gradient** (set in Settings → Icon style).
- **Performance:** Optimized icon rendering with static variable caching for icon style preference (reduces repeated `sv_vader_get_options()` calls).
- **Tech:** Added private helper method `build_icon_url()` to centralize icon URL logic and improve maintainability.
- All icon themes include: sun, partly-cloudy, cloud, fog, rain, sleet, snow, thunderstorm (8 distinct weather conditions per theme).
- Updated README and readme.txt with icon theme documentation and admin settings guide.

= 1.8.0 =
- **BREAKING CHANGE:** Removed legacy `[sv_vader …]` shortcode. Use `[spelhubben_weather …]` exclusively.
- **New Providers:** Added **Open-Weathermap** and **Weatherapi.com** for better global coverage (6 total providers).
- **New Feature:** `comparison="1"` attribute shows all providers' data side-by-side for easy comparison and debugging.
- **Performance:** Fixed memory leak in map.js (persistent MutationObserver, proper ResizeObserver cleanup).
- **Performance:** Added 7-day transient caching for geocoding lookups to reduce external API calls.
- **Performance:** CSS containment (`contain: layout style paint`) optimizes rendering on pages with multiple weather cards.
- **Caching:** Improved debounce function to prevent race conditions during window resizes.
- **Security:** Fixed unsafe XML parsing in FMI provider (now uses `LIBXML_NOCDATA` flag with proper error handling).
- **Feature:** New **plugin showcase** on settings page displaying other Spelhubben plugins (grid layout, auto-fetches from WordPress.org).
- **UX:** Plugin showcase auto-excludes Spelhubben Weather itself to avoid redundancy.
- Tested up to: WordPress 6.8+

= 1.7.5 =
- Tested up to: 6.9
- New: **FMI (Finnish Meteorological Institute)** as a free, optional provider (t2m, ws_10min, r_1h, n_man via WFS). Toggle in **Settings → Providers** and via `providers="…"` in block/shortcode/widget.
- Shortcodes/Blocks: `providers` now accepts `fmi`.
- Docs: Updated examples and FAQ to include FMI.

= 1.7.0 =
- New: **Shortcodes** admin page with searchable examples, one-click copy & **copy all**.
- New: **Live preview** inside WP-admin (sandboxed iframe) that renders shortcodes and loads front assets (Leaflet, widget CSS/JS).
- New: **Units & format** settings (preset + overrides: temp/wind/precip units, `date_format`).
- New: **Clear cache** button (transients) on settings page.
- New: **Translations included:** Swedish (sv_SE), Norwegian (nb_NO), English (en_US).
- UX: Unified light card design across admin pages.
- Tech: Robust admin enqueue with cache-busting via `filemtime`.
- i18n: All admin strings localized (including JS: expand/collapse, statuses).
- Docs: Marked legacy shortcode as **deprecated – will be removed soon**.

= 1.6.2 =
- Minor fixes and readme updates.

= 1.6.1 =
- Version bump for WordPress.org sync. No functional changes.


== Upgrade Notice ==
= 1.9.5 =
Added moon phase support via `extras="moon"` and daily moon information via `extras="moon_daily"`.

= 1.8.5 =
Performance optimization release with conditional asset loading. Fixes 404 errors and MIME type warnings for Leaflet on non-weather pages. Recommended for all users.

= 1.8.4 =
Maintenance release with centralized configuration constants and performance optimizations. Recommended for all users.

= 1.8.0 =
**BREAKING CHANGE:** Legacy `[sv_vader …]` shortcode has been removed. Please migrate all shortcodes to use `[spelhubben_weather …]` format. Performance update with security fixes, geocoding caching, and new plugin showcase feature. Strongly recommended.

= 1.7.5 =
Adds **FMI** as an optional free provider. Enable it under **Settings → Spelhubben Weather → Providers**, or pass `providers="smhi,yr,openmeteo,fmi"` in blocks/shortcodes/widgets.

= 1.7.0 =
Admin UX overhaul: new Shortcodes page with live preview, units/format settings, and cache clear. Legacy [sv_vader] is deprecated—please migrate to [spelhubben_weather].

Donate link: https://www.paypal.com/donate/?hosted_button_id=CV74CEXY5XEAU
