=== 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.11.3 - 2026-10-13 =
* **Fix: The Selected Font Was Overridden by Some Themes.** The font chosen in Settings was applied only to the outer box of each widget, and the text inside picked it up from there. Any theme or page builder that sets its own font on headings or buttons, such as a heading font chosen in the theme's Customizer, took priority, so on those sites the location name, the "Show forecast" button and the alert window used the theme's font instead. Whether the font worked depended on each site's theme settings, even between sites running the same theme. The selected font is now applied to every element of both widgets and their alert windows, so it is used whatever theme is active.
* **Fix: The Header Widget's Alert Window Ignored the Selected Font.** The alert window is moved to the end of the page when it opens, outside the widget, so it always showed the theme's font. It now uses the plugin font like the rest of the widget.
* **Fix: Forecast Tabs Wrapped Onto Extra Rows on Tablets and Narrow Layouts.** The eight forecast category tabs kept to one swipeable row only on phones. On wider screens, and wherever the widget sat in a narrow column, they broke onto two or three rows, often leaving the AQI tab alone on the last one. The tabs now stay on one row at every width and can be swiped or scrolled when they do not all fit. Where they all fit, nothing changes. On computers with a mouse, a slim scrollbar in the widget's colors appears under the tabs whenever some are out of view, so they can be reached without a trackpad or touch screen. Touch screens keep the clean look with no scrollbar.
* **Fix: Widget Styles No Longer Change the Rest of the Site.** The widget stylesheet included a reset that removed the margins and padding from every element on the page and set the font of the whole page, so pages showing a widget could look different from the rest of the site. These rules now apply only inside the widgets.

= 2.11.1 - 2026-10-12 =
* **Fix: Current Conditions Could Be Over an Hour Old.** The current temperature, condition and condition animation come from the hourly forecast, which was treated as up to date for a full hour. Combined with the hourly background refresh, the widgets could show conditions from one to two hours earlier, so the animation might show rain after it had cleared. The hourly forecast, and the current conditions that come with it, are now refreshed every 15 minutes, in line with how often current conditions are updated at the source. The 7-day forecast keeps its one-hour refresh, since it changes far less often, and severe weather alerts keep their 15-minute refresh.
* **Fix: The Dashboard Weather Card Never Refreshed on Its Own.** The current weather shown on the getting started and review cards in the dashboard only read what the widgets had already saved, so on a site with few visitors it could keep showing an old condition and animation until a page cache purge cleared the saved data. Viewing the dashboard now queues a background refresh when the saved reading is out of date, without slowing the dashboard down.
* **Change: Background Refresh Runs Every 15 Minutes.** The scheduled job that keeps weather data ready for visitors now runs every 15 minutes instead of hourly, and only requests data that has actually gone out of date, so the 7-day forecast is not downloaded more often than before. Existing sites switch to the new schedule automatically after updating.
* **Tip:** Scheduled refreshes rely on WP-Cron, which WordPress normally runs only when someone visits the site. On sites with little traffic, setting up a real server cron job that calls wp-cron.php every 5 to 15 minutes keeps the weather current. Most hosts offer this in their control panel.

= 2.11.0 - 2026-10-10 =
* **Changed (Admin): New Getting Started Notice.** The plain "set your location" warning is replaced by a getting started card in the same style as the review prompt. It walks through the three steps: set a location, add the weather to your site, and choose light or dark mode, a font and an optional WeatherAPI key. The left panel shows the current weather at your saved location over the matching condition animation, so you can see the widget artwork before placing it. The placement step matches your theme: block themes, which have no Widgets screen, are pointed to the Global Weather Pro blocks and the Site Editor. Both shortcodes have a one-click Copy button, and dismissing the notice no longer reloads the page.
* **Changed (Admin): The Getting Started Notice Retires on Its Own.** It goes away 7 days after activation once a location is saved, and stays until then if no location has been set, since the widgets cannot show local weather without one. It is not shown on the plugin's own settings screen. Anyone who dismissed the old "set your location" warning will not see it.
* **Changed (Admin): Review Prompt Matches the New Card.** The condition animation now fills the left side of the review prompt, with the current weather at your location over it when it is available. The review prompt also waits until the getting started notice has gone, so the two never appear together.
* **Developer:** Add `define( 'GWPRO_FORCE_ONBOARDING_NOTICE', true );` or `define( 'GWPRO_FORCE_REVIEW_NOTICE', true );` to wp-config.php to preview either notice immediately. Remove the line when done.

= 2.10.0 - 2026-10-09 =
* **Change: Weather Animations Are Now Videos.** The AI condition animations in the header widget now play as short, muted, looping videos instead of animated WebP images. They play more smoothly, use less battery on phones, and can run longer for the same download size. No action is needed after updating.
* **Improvement: Larger, Widescreen Weather Animations.** The condition animation in the header widget is now shown in a rounded 16:9 frame beside the temperature instead of a small square icon: 192 x 108 pixels on desktop and 224 x 126 on tablets. On phones it becomes a banner across the top of the summary card. On tablets, the animation, temperature and unit toggle now sit side by side instead of being stacked.
* **New: Gradual Switch to Video.** Condition videos are being added a few at a time. Until a condition has one, the header widget keeps showing its existing animated image in the same frame (or a still image where one is provided), so every condition always has artwork. Animated images also have the pause button, and start paused for visitors who have asked their device for reduced motion. Each new video appears automatically once it is included in an update.
* **Improvement: Animations Load Only When Needed.** The condition video is not downloaded until the header widget is close to being scrolled into view, and it pauses while scrolled out of view. Until it plays, a still image of the same condition is shown.
* **Improvement: Reduced Motion and Data Saver.** Visitors who have asked their device for reduced motion, or turned on a data saver, see the still image, and the video is downloaded only if they press play.
* **Improvement: Pause Button Works Everywhere.** Pausing the weather animation now pauses the video itself, so it also works when the plugin's files are served from a CDN. Previously, the pause button was hidden in that case. If the browser declines to start the video by itself (for example, in iOS Low Power Mode), the button switches to play so the visitor can start it.
* **Change: Review Notice.** The review prompt in the dashboard now shows the clear-sky condition video, with a pause button. Admins who have asked their device for reduced motion see a still image instead.

= 2.9.2 - 2026-10-03 =
* **Change: Plugin Renamed to "Global Weather Pro: Weather Widget for WP."** The plugin's display name previously ended in "for WordPress." WordPress.org does not allow the word "WordPress" in a plugin's display name or permalink, as it is a trademark of the WordPress Foundation, so the name now uses the permitted abbreviation "WP" instead. Only the name has changed. The plugin's address on WordPress.org, its folder name, settings, widgets, blocks, shortcodes, and saved data are all unaffected, and no action is needed after updating.

= 2.9.0 - 2026-10-03 =
* **New: Use Your Own WeatherAPI Key (Optional).** Site owners can now enter their own WeatherAPI.com key under Settings > Global Weather Pro. With a key, forecasts and severe weather alerts are requested from WeatherAPI directly by your own server instead of through the Global Weather Pro service. Without one, nothing changes: the plugin keeps working with no key at all. The key is used only in server-side requests and is never included in the page or sent to visitors' browsers.
* **New: Key Check on Save.** A newly entered key is tested with WeatherAPI before it is saved. If WeatherAPI rejects it, the previous setting is kept and the settings screen says why, for example a mistyped key, a used-up monthly quota, or a disabled key. If WeatherAPI cannot be reached at that moment, the key is saved unchecked.
* **New: Key Problems Are Reported in Settings.** If WeatherAPI later starts refusing the key, for example after the monthly quota runs out, the settings screen shows a warning explaining the problem. The warning clears itself once requests succeed again.
* **New: Keep the Key Out of the Database.** Defining `GWPRO_WEATHERAPI_KEY` in wp-config.php supplies the key without storing it in the database. The constant takes precedence over the settings field, and the field is replaced with a note while it is set.
* **Change: Switching Data Sources Takes Effect Immediately.** Adding, changing or removing the key refreshes the cached forecasts straight away from the new source. The stored place name is kept, since it does not depend on where the forecast comes from.
* **Change: Forecasts Are Requested by Coordinates When Available.** With your own key, the plugin sends WeatherAPI the coordinates found by the place name lookup rather than the location text, so landmarks and campuses that WeatherAPI cannot match by name still return the right forecast.
* **Fix: The 7-Day Strip Showed Empty Columns When Fewer Days Were Available.** The strip always drew seven columns, so a forecast with fewer days, such as the 3 days included with a free WeatherAPI key, showed the missing days as columns reading "undefined" with no icon. It now shows only the days the forecast contains.
* **Change: Settings Page Version Badge.** The version shown on the settings page is now read from the plugin itself rather than typed in separately, so it can no longer fall out of date.

= 2.8.6 - 2026-10-03 =
* **Fix: A Slow Location Lookup Could Blank the Entire Widget.** Turning the configured location into a place name was a separate request made while the page was being generated, and if it failed, the whole widget showed "Could not load weather data." even though the forecast itself had loaded. The lookup now happens once, when the location is saved in Settings, and the result is stored permanently instead of in a cache that can expire or be cleared. Page loads no longer make a lookup request at all. If a stored result is not yet available, the widget shows the place name included with the forecast and retries the lookup in the background, so a lookup failure can no longer stop the forecast from displaying.
* **Fix: The First Location Saved on a New Site Was Not Fetched in Advance.** Saving a location for the very first time creates the setting rather than updating it, and only updates triggered the immediate cache refresh. The first visitor after setup therefore paid for every request. Both cases now refresh the cache straight away.
* **Change: Background Requests Allow More Time.** Scheduled refreshes and the lookup made when the location is saved now wait up to 20 seconds for the weather data service instead of 5, since no visitor is waiting on them. Requests made during a page load keep the short timeout. The new 'gwpro_background_request_timeout' filter adjusts the longer limit.
* **New: Settings Warning When the Lookup Fails.** If the place name lookup does not respond when the location is saved, the settings screen now says so and explains that the widget will use the forecast's place name until the lookup succeeds.

= 2.8.5 - 2026-10-03 =
* **Fix: A Temporary Weather Service Failure Could Be Saved by Page Caching Plugins.** The widgets receive their weather data inside the page itself, so a page caching plugin saves whatever state the data was in when the page was generated. If the weather data service was briefly unreachable at that moment, the cached copy of the page kept showing "Could not load weather data." to every visitor until the cache expired, long after the service had recovered. Because different pages were cached at different times, the error appeared to come and go at random. Pages generated while weather data is unavailable are now marked as not cacheable for WP Super Cache, W3 Total Cache, WP Rocket, LiteSpeed Cache and other plugins that honor the standard WordPress signal, so the next visit after the service recovers shows the forecast again.
* **Developer: Weather Data Failures Are Now Logged.** When a request to the weather data service failed, the reason was discarded, leaving site owners with a generic message and no way of telling a timeout from a server error or an unexpected response. With `WP_DEBUG_LOG` enabled, each failure is now written to 'wp-content/debug.log' with the endpoint, the location, and the cause, including the HTTP status code and the start of the response where there is one. Nothing is logged when debug logging is off.
* **Developer: Clearer Browser Console Messages.** Both widgets printed the same console message whether the server had reported a weather data error or the weather data never reached the browser at all. They now print a distinct message for each case: the first points to the debug log, and the second points to a script optimization or caching plugin that may be delaying or reordering the plugin's inline scripts.

= 2.8.0 - 2026-09-24 =
* **Accessibility: Weather Alerts Can Now Be Opened From the Keyboard.** The alert icon and the close button were plain elements labelled as buttons, so they could not be reached with the Tab key or activated with Enter or Space. They are now real buttons, and the alert list opens in a native modal dialog that holds keyboard focus, closes with Escape or a click outside it, and returns focus to the alert icon afterward. The icon also tells screen reader users how many alerts are active. Previously, clicking the alert icon in one widget also opened the alert window of the other widget when both were on the same page; each widget now opens only its own.
* **Accessibility: Forecast Tabs Follow the Standard Tab Pattern.** The Temperature, Rain Chance, Wind and other forecast tabs now respond to the arrow keys, Home and End. Screen readers are told which tab is selected, and each forecast panel is linked to its tab. Switching tabs in the 7-day strip no longer resets the hourly strip.
* **Accessibility: Pause Control for the Condition Animation.** The animated condition image loops indefinitely, and WCAG 2.2.2 requires a way to stop moving content that runs longer than five seconds. A small pause and play button now sits on the image, and the animation starts paused for visitors whose device is set to reduce motion.
* **Accessibility: Screen Readers No Longer Read the Whole Widget Aloud on Load.** The widget containers were marked as live regions, so a screen reader read every figure in the widget at once when the page loaded. That marking has been removed. Labels that screen readers ignored or that hid the visible text were replaced with real text. Temperatures now announce their unit, the UV reading announces its number as well as its risk level, and hourly and daily forecast icons describe the condition instead of being skipped.
* **Accessibility: Sidebar Unit Toggle Is Now a Pair of Buttons.** The F and C controls were links that went nowhere, and the selected unit was shown only by a text color that fell below the WCAG AA contrast minimum. They are now buttons that tell screen readers which unit is selected, have a larger touch target, and mark the selected unit with an outline as well as color. Muted text in the light sidebar theme was darkened to meet the 4.5:1 contrast ratio.
* **Change: Redesigned Review Prompt.** The review request is now a card in the style of the block editor, with a condition animation, follows the admin color scheme, and works on narrow screens. Choosing an option no longer reloads the page, and the close button now remembers the choice; previously the notice came back on the next page load.
* **Fix: The Widget No Longer Appears Unstyled for a Moment.** The light and dark widget stylesheets and the alert stylesheet were added by the widget scripts after the page had loaded, so the widget briefly appeared without its styling on every visit. WordPress now loads them with the rest of the page's styles. On block themes, and on classic themes when the widget sits in a sidebar or in the page's own content, they load in the page head before anything is drawn. A block's own light or dark setting is respected.
* **New: Alignment, Spacing and HTML Anchor Settings for the Blocks.** The Header block can be set to wide or full width, and the Sidebar block can be aligned left, center or right with text wrapping around it. Both blocks now have margin and padding controls and an HTML anchor field, like core blocks.
* **New: The Widgets Can Be Translated.** Labels, tab names, button text, UV and air quality levels, alert text and status messages were written in English inside the widget scripts. They now go through the plugin's text domain, so they can be translated on translate.wordpress.org. Weekday names and clock times now follow the site's language setting, so a German site shows "Do, 19:05" rather than "Thu, 7:05 PM". Weather condition descriptions still come from the weather data service in English.
* **Change: Widget Text Can Be Selected and Copied.** Text selection was turned off for the whole header widget. It is now turned off only on the tab and toggle buttons, where a double click would otherwise highlight the label.

= 2.7.15 - 2026-09-16 =
* **Fix: The Block Never Appeared in the Block Inserter.** The block registration code looked for its block definition, editor script, and editor stylesheet in a folder that was not included in the plugin package. WordPress skips a block whose definition file is missing without reporting any error, so searching the inserter returned nothing, and the block described in the 2.7.14 documentation could not actually be added to a page. The block definitions and editor script now ship with the plugin.
* **Fix: Blocks in Block Theme Templates Loaded Without Their Weather Data.** Block themes build templates and template parts before the page head is output, which is earlier than the point where the widget scripts were registered. Weather data attached to a script that is not yet registered is discarded without warning, so the widget script loaded with no data and stopped with a "gwpro is not defined" error, and the widget stylesheet was skipped on the same pages. The scripts and styles are now registered before any widget, shortcode, or block renders, and the widget scripts fall back to their built-in error message instead of stopping if the data is ever missing.
* **Change: Separate Header and Sidebar Blocks.** The single "Weather Widget" block with a layout setting has been replaced by two blocks, "Global Weather Pro Header" and "Global Weather Pro Sidebar," named to match the classic widgets. Both appear when the inserter is searched for "weather widget," "weather," "forecast," or "Global Weather Pro," and both keep the per-block location and color theme overrides in the block settings sidebar.
* **Change: Each Block Can Be Placed Once Per Page.** The widgets rely on fixed element IDs, so two copies of the same block on one page would interfere with each other. The editor now prevents a second copy from being inserted. A header block and a sidebar block can still share the same page.
* **Change: Editor Placeholder Instead of a Blank Preview.** The weather display is assembled in the visitor's browser, a step the editor does not perform, so a live preview inside the editor would render empty. The editor now shows a labeled placeholder summarizing the block's location and theme settings, and the live weather appears on the published page.
* **Documentation: Block Instructions Updated.** The description, installation steps, and FAQ now refer to the two blocks by name. If a page or template shows a notice that it contains an unsupported block, that content was saved with the earlier "Weather Widget" block. Remove it and insert the Global Weather Pro Header or Sidebar block in its place.

= 2.7.14 - 2026-09-12 =
* **Documentation: The Weather Widget Block Is Now Documented.** The plugin has registered a server-rendered "Weather Widget" block for the block editor and Full Site Editing templates since 2.7.0, but no part of the readme ever mentioned it. The installation instructions and the first FAQ entry both directed site owners to "Appearance" > "Widgets," a screen that does not exist on a block theme, so anyone running a modern theme was told to follow steps they could not follow and had no way of discovering the block that would have worked. Blocks are now listed alongside widgets and shortcodes everywhere placement is described, with a note that block themes have no classic Widgets screen.
* **Documentation: Per-Block Location and Theme Overrides Are Now Documented.** Each block instance can override the site-wide location and color theme, which is what makes it possible to show weather for different cities on different pages. This capability was present but undocumented, so in practice no one knew to use it.
* **Documentation: Plugin Headers Completed.** Added the missing "Requires PHP" header to readme.txt, and added "Plugin URI", "Author URI", "Text Domain", "Domain Path", "Requires at least", and "Requires PHP" to the main plugin file. The text domain in particular was being passed to "wp_set_script_translations()" for the block editor script without ever being declared, which is the header WordPress uses to locate translation files.
* **Fix: Description Rendered Incorrectly on the Plugin Directory Page.** The opening paragraph of the Description began with a bold marker that was never closed, so the plugin's single most prominent block of copy rendered either entirely bold or with the markers visible as literal characters.
* **Fix: Removed a Changelog Entry for a Release That Does Not Exist.** An entry labeled 8.9.8 sat at the top of the changelog, above 2.7.11, describing a stable tag change to a version number the plugin has never had. It was the first thing anyone opening the Changelog tab would read.

= 2.7.11 - 2026-09-10 =
* **Fix: Header Widget Rendered Wider Than the Space It Was Given.** The card was set to the full width of its container and then given a margin on all four sides. A margin sits outside the measured box rather than within it, so the card was always about thirty-two pixels wider than the area it had to fit into, and the surplus was either clipped at the right edge or pushed out as a horizontal scrollbar on the page. The card also carried a minimum width equal to its container, which meant it could not give ground inside a narrow column, a flexible layout, or a page builder that expected its contents to adapt. Horizontal margin has been removed and the minimum width lifted, so the widget now fills exactly the width it is allotted and shrinks with it. Vertical spacing above and below the card is unchanged.
* **Fix: The Hourly and 7-Day Control Did Not Look Like a Control.** The two halves of the forecast switch were never shown together: whichever view was on screen had its own button hidden, leaving a single button carrying the name of the view the visitor was not currently looking at. Read cold by someone arriving at the page, a lone button reading "Hourly" above a seven-day forecast is far more easily taken for a caption describing the panel than for an invitation to change it, and there was nothing else to suggest otherwise. Both halves are now always on screen as a pair, with the active view filled in the widget's accent color and the alternative left plain, so the control reads as a choice between two options and shows at a glance which one is in effect.
* **Fix: Temperature Unit Buttons Were Not Recognizable as Buttons.** The Fahrenheit and Celsius controls were distinguished from one another only by a small difference in text color, applied from a script after the widget had already been drawn. They also declared no background or border of their own, so browsers fell back to the default grey system button styling, which matched neither theme and read as leftover page furniture rather than as part of the widget. The pair is now styled as a single segmented control with the selected unit filled in the accent color, and the selected state is set as the widget is built instead of on first interaction.
* **Fix: The Severe Weather Alert Icon Was Covered by the Forecast Buttons.** At tablet and desktop widths the alert icon and the forecast toggle were both pinned to the bottom-right corner of the card at fixed offsets that placed them in overlapping positions, and because the toggle is drawn later it sat on top. On a widget showing an active severe weather alert, the one element most worth seeing could therefore be obscured by a view switch. Both elements now sit in the card's normal flow, where the layout keeps them apart on its own rather than relying on measurements that only held at one particular card height. The equivalent correction was made for phone widths in 2.7.6; this extends it to every screen size.
* **Fix: Forecast Controls Announced the Wrong State to Screen Readers.** The forecast toggle's accessible descriptions were reversed, so the button that showed the seven-day forecast announced itself as switching to the hourly view and the hourly button announced the opposite. Its pressed state was likewise set the wrong way round when the widget was built and was never updated afterwards, so assistive technology was told the same view was selected no matter which the visitor had chosen. Both the descriptions and the pressed state are now correct at every step and are kept in step with what is on screen, and the same state now drives the visible highlighting as well, so the two cannot fall out of agreement again.

= 2.7.9 - 2026-08-26 =
* **Fix: Sidebar Measurement Labels Were Too Cramped to Fit.** The six measurements below the current conditions were laid out as a wrapping row in which each item was allotted a minimum of eighty pixels. That is roughly the width of the word "Precipitation" on its own, so the longest labels had no room left over and pushed past the edge of their column, and because items in that kind of row cannot shrink below the width of their own text, the result got worse rather than better as the sidebar narrowed. The measurements are now arranged in a two-column grid in which each cell is given half the width of the widget and is allowed to shrink, so every label fits whole with space to spare. The trailing colons have been dropped as part of the change: in a grid the column alignment already separates the label from its reading, and a colon left over from the old inline layout only added width without adding meaning.
* **Fix: Severe Weather Alert Text Was Centred in the Sidebar.** The sidebar widget centres its own contents, and the alert modal is built inside that container, so the alert wording inherited the centring from its surroundings. The alert stylesheet had never set an alignment of its own to stop it, which left multi-sentence warnings reading as a stack of centred fragments rather than as prose. Alert text is now aligned to the start of the line, which is the left edge on a left-to-right site and the right edge on a right-to-left one.

= 2.7.8 - 2026-08-26 =
* **Fix: Air Quality Labels Were Cut Off in the Forecast Strip.** The AQI badge in the header widget's hourly and 7-day strips inherited the widget's full text size, but the forecast columns are a fixed width. Longer tier names therefore ran past the edge of their column and were trimmed with an ellipsis after roughly seven characters, so "Unhealthy" and "Hazardous" arrived as fragments and the color was doing all the work. The badge now renders at a smaller size scaled to the column, with padding that scales with it, so every tier name fits whole at desktop and phone widths and in all 18 available fonts, including the wider monospace and display faces. The "--" shown where no reading is available was given the same treatment, so it no longer sits noticeably larger than the badges around it.
* **Change: "Very Unhealthy" Is Now Labeled "Severe".** EPA tier 5 was the one label too long to fit a forecast column at a readable size; shrinking the text far enough to accommodate it would have made every badge, including the short ones, harder to read. It is now shortened on the badge itself, following the same approach already used for tier 3 ("Unhealthy for Sensitive Groups" appears as "Sensitive"). The full description remains in the badge's hover tooltip and is still announced in full to screen readers, so no information is lost.

= 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.
