=== Global Weather Pro: Weather Widget for WordPress ===

== Archived Changelog Entries ==

This file contains older changelog entries so the plugin's readme.txt stays a
reasonable size. For recent releases, see the Changelog section of readme.txt.

= 2.7.7 - 2026-08-25 =
* **Security: Text From the Weather Service Is Now Escaped Before Display.** Both widgets build their markup as a single template string and insert it with innerHTML, which meant any text arriving from the data service was interpreted as markup rather than treated as text. Severe weather alert titles and descriptions are the clearest case: they are third-party content the site owner never writes or reviews, and they are the one field long enough to conceal markup. Every upstream value written into the widgets is now escaped on the way in, covering alert titles and descriptions, the geocoded place name, the current condition wording (including where it appears as an image description), the last-updated time, and the day names and times in the forecast strips. There is no indication that any such content was ever served; this removes the possibility rather than addressing an observed problem.
* **Security: Forecast Icon Addresses Are Validated Before Use.** Weather condition icon addresses supplied by the data service were written directly into an image tag. They are now accepted only if they are a well-formed absolute http or https address. Anything using another scheme, or containing a quote, a space, or an angle bracket that could break out of the attribute, is discarded instead of rendered.
* **Fix: A Missing Forecast Icon No Longer Caused the Page to Be Downloaded Twice.** When an icon address was absent, the hourly and 7-day strips still rendered an image tag with an empty address. Browsers resolve an empty image address by re-requesting the current page and attempting to read the HTML as image data, so every visitor paid for a second download of the page. The attribute is now omitted entirely when there is no usable address.

= 2.7.6 - 2026-08-24 =
* **New: Header Widget Now Displays on Phones.** The header widget was previously removed altogether on mobile devices, so the animated weather conditions were never seen by mobile visitors. It now renders at every screen size. Below 600px it reflows into a single-column card and opens collapsed, showing the location, the animated condition, the current temperature and the condition description, with a "Show details & forecast" control revealing the full parameter readout and both forecast strips. Tablet and desktop layouts are unchanged.
* **Fix: 7-Day Forecast No Longer Overflowed Narrow Screens.** Unlike the hourly strip, the 7-day strip had no scroll container, so its seven fixed-width columns forced the entire page to scroll sideways on a phone. It now scrolls horizontally within the widget.
* **Change: Time Shown in the Widget Is Now the Forecast Location's, Not the Visitor's.** The time displayed beside "Last Updated" in the header widget, and beneath the location in the sidebar widget, was taken from the visitor's own device clock. A visitor two time zones away from the configured location saw their own wall time presented as the widget's, and because that value is regenerated on every page load it always appeared current no matter how old the underlying weather data was. Both widgets now show the current local time at the forecast location, derived from its IANA time zone. Note that this is the location's clock rather than the moment the forecast was retrieved; weather data is served from a cache with a one-hour freshness window, so the figures shown can be up to an hour old.
* **Fix: Overlapping Controls on Narrow Screens.** The forecast toggle buttons and the severe weather alert icon are positioned against the widget's bottom-right corner at desktop widths, which placed them on top of the forecast content on a phone. Both now sit in the normal flow below 600px, with the alert icon raised above the forecast so it is visible without expanding the card.
* **Fix: JavaScript Error on Mobile Pages Without the Header Widget.** The removed mobile check read a style property from the widget container without first confirming it existed, throwing a TypeError on any mobile page that did not include the header widget.
* **Enhancement: Larger Touch Targets.** Forecast category tabs are now a single swipeable row with 44px touch targets on phones rather than wrapping into four rows of small buttons.

= 2.7.2 - 2026-08-19 =
**Action Required: Re-Download Self-Hosted Fonts.** Self-hosted fonts now survive plugin updates. If you had self-hosted your fonts, click "Download & Self-Host All Fonts" once more under Settings > Global Weather Pro, this is the last time it will be needed.
* **Fix: Self-Hosted Fonts No Longer Lost on Plugin Updates.** Downloaded font files were being stored inside the plugin's own folder, which WordPress deletes and recreates every time a plugin updates. Self-hosted fonts were therefore wiped by each update, and the site quietly resumed loading them from Google's servers, silently undoing a privacy choice the site owner had deliberately made. Fonts are now stored in the WordPress uploads directory, which survives updates, so a font downloaded once stays downloaded.
* **Enhancement: Migration of Existing Self-Hosted Fonts.** On the first admin page load after updating, any font files still present in the old location are moved to the new one and their stylesheets repointed automatically. In most cases the previous update has already removed them, in which case the fonts simply need downloading once more.
* **Enhancement: Font Directory Protection.** The self-hosted fonts directory is now created with an index file so its contents cannot be listed by browsing to it directly.
* **Fix: Font Files Removed on Uninstall.** Self-hosted font files were left behind permanently when the plugin was deleted. They are now removed along with the plugin's settings.

= 2.7.1 - 2026-08-19 =
* **Fix: No More Default Location.** A fresh install with no configured location was showing real weather for a hard-coded town in New Mexico, which looked like a malfunction to anyone who had just activated the plugin. The widgets now render a neutral "Set a location to see weather." message until a location is saved, and the plugin makes no outbound API requests at all while unconfigured.
* **Fix: Sidebar Widget Failed Silently.** When weather data could not be loaded, the sidebar widget's message was being written to an element that does not exist, so visitors saw an empty space instead of an explanation. The message now renders correctly.
* **Enhancement: Themed Status Messages.** The "set a location" and "could not load weather data" messages now use a stylesheet class instead of inline styling, so they inherit the widget's configured font and theme colors rather than appearing as unstyled text.

= 2.7.0 - 2026-08-18 =
* **Performance: Eliminated Render Blocking Weather Requests.** The widgets previously fetched alerts, hourly, daily, and geocode data from the weather service synchronously while the page was being generated, adding latency to every page load and, on a slow upstream, potentially stalling it for several seconds. Weather data is now served from cache using a stale-while-revalidate model: a cached copy is returned immediately and refreshed in the background via WP-Cron, so page rendering no longer waits on the network except on a completely cold cache (which now uses a shorter timeout).
* **Performance: Conditional Asset Loading.** The widget stylesheet and its Google Font were being enqueued on every page of the site regardless of whether a widget appeared. They now load only on pages that actually display a widget, shortcode, or block.
* **Performance: Reduced Outbound API Traffic.** The severe weather alerts cache lifetime was raised from 1 minute to 15 minutes, and geocode results (which do not change for a fixed location) are now cached for a week. Data for both widgets on a single page is also fetched once per request rather than twice.
* **New: Background Cache Warming.** An hourly scheduled task refreshes weather data for the saved location, so visitors are no longer the ones who trigger a cold fetch. Changing the location in settings refreshes the cache immediately within the admin request.
* **Reliability: Graceful Degradation on API Failure.** A failed request is now briefly remembered so the plugin does not retry a struggling service on every page view, and an alerts-only failure no longer blanks the entire forecast — the widget shows the forecast with no active alerts instead.
* **Developer: New Filters.** Added 'gwpro_api_base_url', 'gwpro_request_timeout', and 'gwpro_failure_backoff' filters so site owners can point the plugin at a proxy or tune request behavior without editing plugin files.

= 2.6.4 - 2026-08-15 =
* **New: Expanded FAQ.** Added three FAQ entries covering how artificial intelligence is used in the plugin, whether the AI-generated animations are self-hosted, and how severe weather alerts are delivered. The AI entries state plainly that artificial intelligence produces the animations only, all forecasts, air quality readings, and alerts come from WeatherAPI and are neither AI-generated nor AI-predicted.
* **Fix: FAQ Question Formatting.** FAQ questions were previously wrapped in single asterisks, which rendered them as italic body text rather than headings. They now use the readme heading syntax, so each question renders as a proper bold heading with its own anchor link on the plugin directory listing.

= 2.6.3 - 2026-08-15 =
* **Enhancement: SEO & Discoverability Improvements.** Rewrote the plugin's short description to lead with the terms site owners actually search for, weather forecasts, severe weather alerts, AI-generated animations, and weather widgets, while staying within WordPress.org's 150 character limit.
* **Enhancement: Search Optimization.** Refined the WordPress.org plugin tags to add `ai`, placing Global Weather Pro in the AI plugin browse listing alongside its existing weather widget, weather alerts, weather forecast, and geolocation tags.
* **Documentation: Corrected Weather Condition Count.** The Description previously cited two different and outdated figures for the number of supported weather conditions. Both now correctly read 60+, matching WeatherAPI's current condition code list (1000–1282), each with its own bundled AI-generated animation.

= 2.6.0 - 2026-07-27 =
* **New: Expanded Font Library (18 Typefaces).** The Font Family setting now offers 18 professional Google Fonts (up from 4), organized into Sans-Serif, Serif, Monospace, and Display categories in a clean grouped select. All font data is centralized in a single source of truth, and the previous 4 fonts keep their exact values, so existing installs migrate with zero changes.
* **New: Download & Self-Host All Fonts.** A one-click tool on the settings page downloads every font family's files directly to your own server, so visitor browsers never contact Google Fonts, ideal for site owners who prefer not to link their site to Google's Font API. Each font is saved with its own license file (Apache-2.0 for Roboto and Roboto Mono, SIL OFL-1.1 for all others; both permit self-hosting). Fonts not yet downloaded automatically fall back to Google's CDN, and a status line on the settings page shows how many families are self-hosted.
* **New: Font-Independent Layout System.** Choosing a wide serif or monospace font no longer shifts the widget layout. Forecast strip columns are now fixed-width with graceful truncation, temperatures and times use fixed-width (tabular) numerals in every typeface, x-heights are optically normalized so all fonts render at a consistent visual size, and tab and toggle buttons never wrap, the widget geometry stays identical no matter which font is selected.
* **Enhancement: Smarter Location Display.** Long location names (e.g. full street addresses) now wrap onto short lines inside a capped-width box instead of pushing the current-conditions data columns out of position. The location heading's box is measured and fitted to its widest rendered line at runtime, so the weather parameters sit flush beside the visible text in every font, and data columns are now rigid so values like precipitation amounts can never break onto two lines.
* **Enhancement: Hardened Font Setting.** The font setting is now validated against the whitelist of available fonts on save and on load, falling back safely to the default for any unrecognized value.
* **Fix: Font Category Headers in Dark Mode.** The new Sans-Serif / Serif / Monospace / Display group headers in the settings dropdown are explicitly styled for readable contrast against the dark admin theme.
* **Documentation: Third-Party Disclosures.** The Google Fonts entry under Third-Party Services now accurately describes when Google is (and is not) contacted, lists both endpoints visitor browsers may access, and discloses that the self-host download runs server-side. A new "Third-Party Fonts & Licenses" section documents every bundled-on-download font license.

= 2.5.0 - 2026-07-25 =
* **New: Air Quality Index (AQI) Forecast Tab.** Added a new "AQI" tab as the last tab in the header widget's forecast strip. In hourly mode it displays the hour-by-hour air quality forecast, and in 7-day mode it displays the daily air quality forecast, so visitors can plan outdoor activities with air quality in mind.
* **New: Color-Coded EPA Air Quality Tiers.** AQI values are based on the US EPA Air Quality Index (1–6) and displayed as color-coded badges matching the official EPA scale: Good (green – minimal or no risk), Moderate (yellow – acceptable for most people), Unhealthy for Sensitive Groups (orange – sensitive people should take precautions), Unhealthy (red – health effects become more likely for everyone), Very Unhealthy (purple – health alert), and Hazardous (maroon – emergency conditions). Badge text color automatically adjusts between black and white for readable contrast against each background.
* **Enhancement: AQI Accessibility.** Each AQI badge includes a descriptive `title` tooltip and `aria-label` (e.g. "AQI 3 – Unhealthy for Sensitive Groups") so both the numeric index and the full risk description are available on hover and announced to screen readers.
* **Enhancement: Air Quality Data via WeatherAPI.** Air quality data is sourced from WeatherAPI's `air_quality` feed (US EPA index) and delivered through the Global Weather Pro service like all other weather data—no API keys or additional setup required. Hours or days without available air quality data gracefully display "--" instead of an empty value.
* **Fix: Unreadable Dropdown Options on the Settings Page.** Resolved an issue where the option lists of the Appearance and Font dropdowns on the settings page could render with dark text on a dark background, making them unreadable. The settings page now declares a dark `color-scheme` so native dropdown popups render with correct dark-mode colors, and option elements are explicitly styled with light text on the dark surface for browsers that honor per-option styling.

= 2.4.19 - 2026-07-18 =
* **Fix: WordPress admin users may have experienced a short-term bug in the last commit of the weather widget, specifically in the header widget, where the weather condition images were static. The latest version has fixed the issue. ** Thank you for your patience.

= 2.4.9 - 2026-07-08 =
* **Fix: Added custom weather condition image mappings for all supported WeatherAPI weather conditions. **

= 2.4.8 - 2026-07-08 =
* **Fix: Missing weather condition image for Smoky Haze ** Added a dedicated weather condition image mapping for the Smoky Haze condition to ensure the correct condition image is displayed.

= 2.4.6 - 2026-07-01 =
* **Fix: Hourly Forecast Now Starts at the Current Hour.** The header widget's hourly forecast previously always began at 12:00 AM of the current day. It now correctly starts at the current hour and spans a full 24 hours (e.g. 1:00 PM today through 12:00 PM the next day), matching the description of a true, rolling hour-by-hour forecast.
* **Fix: Corrected Hourly Time/Data Alignment.** Resolved an issue where the hourly temperatures and conditions did not match their displayed times. The starting hour was being derived from WeatherAPI's cached `last_updated` timestamp, which can be up to an hour stale, causing the forecast values to appear shifted relative to their labels.
* **Enhancement: Time-Zone-Accurate "Current Hour" Detection.** The widget now determines the location's current hour from the live browser clock projected into the location's IANA time zone (`tz_id`) via `Intl.DateTimeFormat`, making it immune to server-side cache staleness and the viewer's own time zone. The cached location time is retained only as a fallback.

= 2.4.4 - 2026-06-30 =
* **Fix: UV Index Display in Header Widget.** Resolved an issue where the "UV Index" field in the header widget rendered empty. The '#uv-div-span' element now correctly populates with the current UV risk level.
* **Fix: Correct UV Data Source.** The header widget now reads the UV value from the current conditions in the forecast response (`minutelyDataImperial`) rather than the daily forecast, so the displayed UV reflects the current hour instead of a full-day summary.
* **Enhancement: Standardized UV Color Coding.** The UV Index badge is now color-coded to the official EPA/WHO UV Index risk scale using standardized hex values: Low 0–2 (#299501 green), Moderate 3–5 (#F7E400 yellow), High 6–7 (#F85900 orange), Very High 8–10 (#D8001D red), and Extreme 11+ (#6B49C8 purple). Text color automatically adjusts between black and white for readable contrast against each background.
* **Enhancement: UV Accessibility.** Added a descriptive `title` tooltip and `aria-label` to the UV Index badge (e.g. "UV 7 – high") so both the numeric value and risk level are announced to screen readers.
* **Enhancement: Robust UV Parsing.** The raw UV value is now coerced to a number and rounded before bucketing, and gracefully falls back to "--" when no valid reading is available.
