== Changelog ==

Older release notes for Turbo Search for WooCommerce (Free). See readme.txt
for the current and immediately previous release.

= 1.11.24 =
* Housekeeping: refreshed both WordPress.org listing screenshots — the previous pair was taken on two different stores in two different currencies; both are now the same live store, showing the live search dropdown with real results and the Recent Searches feature.

= 1.11.23 =
* Housekeeping: corrected a changelog entry misattributed to the wrong version heading in this file, introduced by the previous release. No functional change.

= 1.11.22 =
* Fix: the "Last successful index: X ago" line on the Turbo Search settings page never updated after a rebuild finished — it only ever reflected whatever it said on the last full page load, so it could sit at "23 seconds ago" indefinitely until the admin manually refreshed. The rebuild-progress check (which already polls every couple of seconds while a rebuild runs) now refreshes this line the moment the rebuild completes.

= 1.11.21 =
* Fix: on a store using a currency-switcher plugin, this edition's REST search endpoint and its MU fast-path companion could compute different cache keys for the same, identical (unconverted) result — the REST path derived currency from a WooCommerce function switcher plugins commonly redirect to the shopper's selection, while the MU path already correctly used the store's raw configured default. This didn't affect what shoppers saw (both paths always serve the store default), but it silently defeated the MU fast path for switcher sessions and fragmented the cache into one redundant copy per selected currency. Both paths now derive currency the same way.

= 1.11.20 =
* Fix: on a store using a currency-switcher plugin, this edition's search dropdown could show a price with the shopper's currently-selected currency symbol while the number itself was still in the store's real default currency (this edition never converts prices — that's a Pro feature). Caused by reading the currency symbol through a WooCommerce function that switcher plugins commonly redirect to the shopper's selection; now reads the store's actually-configured default currency directly, so the symbol shown always matches the amount.

= 1.11.19 =
* Added: an "Upgrade to Pro" link on this plugin's own row on the Installed Plugins screen, next to Settings/Deactivate — links out to the Pro product page. Hidden automatically if Pro is already active on the site.

= 1.11.18 =
* Housekeeping: updated this edition's internal references to the Pro edition (used to detect whether Pro is active, e.g. to avoid both editions running at once) to match the Pro edition's own upcoming rename to "OzuLabs Turbo Search for WooCommerce Pro". No effect on sites not running Pro.

= 1.11.17 =
* Housekeeping: simplified how this plugin keeps its MU companion file current. It previously tracked "is the file up to date" with a separate stored flag, checked once per version; three separate bugs across the last two releases came from that flag drifting out of sync with the actual file on disk. The plugin now just checks the real file directly on every admin page load instead — cheap, and impossible to drift. Also extended the existing "MU file needs attention" admin notice to cover a file that exists but is outdated, not just one that's missing entirely.

= 1.11.16 =
* Fix: if this plugin's MU companion file already existed but was outdated (an interrupted previous update, a permissions issue), and replacing it failed, that failure was recorded as a success — so nothing ever retried, and the site kept running the outdated copy indefinitely with no visible warning. A replacement is now only recorded as done once the file on disk is actually confirmed to match; otherwise the next admin visit tries again.

= 1.11.15 =
* Housekeeping: trimmed this section back down to the current and immediately previous release (see changelog.txt for older ones) — it had drifted to six entries over the last several releases. Added an automated check that now fails the build if this section holds more than two releases, so this can't silently drift again.

= 1.11.14 =
* Fix: 1.11.13's protection against installing this plugin's MU companion file alongside a leftover copy from an old intermediate build only covered normal updates — activating the plugin fresh on a site with that leftover copy still present could install a second, conflicting copy and make every page fail to load. The same protection now applies everywhere this file gets installed, including activation.
* Housekeeping: reworded a historical changelog entry (1.11.10) that described a specific real-world symptom more definitively than was actually verified at the time.

= 1.11.13 =
* Fix: a site updating through an old intermediate build could end up with two copies of this plugin's MU companion file installed at once, which made every page on the site fail to load. Removing the old copy no longer depends on a one-time migration step that may have already run; the new copy is never installed unless the old one is confirmed gone first.
* Housekeeping: removed the remaining Pro-only multi-currency detection code from this edition's MU companion file — it never had any effect here (this edition always prices in your store's own currency), but it shouldn't have shipped in this edition's files at all.
* Housekeeping: the Settings tab's shortcode example now shows [otsw_search], matching the Documentation tab and the plugin's own primary tag.

= 1.11.12 =
* Housekeeping: removed the remaining backend plumbing for typo-corrected search queries — a Pro-only feature this edition never actually produced results for. The always-empty property, the cache wrapper it used, and the response header it triggered are gone; 1.11.10's changelog entry described the frontend half of this removal, this finishes the backend half.
* Housekeeping: renamed the remaining internal HTML/CSS/JavaScript identifiers (previously a 3-letter prefix) to the plugin's distinctive prefix, for compliance with WordPress.org's plugin identifier guidelines. This is an internal rename with no effect on how the plugin looks or behaves; a custom theme/CSS snippet that specifically targeted the plugin's old class names would need updating to the new ones.
* Added: [otsw_search] is now the primary search-form shortcode. The existing [turbo_search] shortcode keeps working exactly as before.

= 1.11.11 =
* Fix: on some mobile browsers, the search dropdown's recent-searches and suggestion rows could render with a much larger font than specified, making those rows look oversized. Caused by the browser's automatic text-size boosting, which is now explicitly disabled for the dropdown so its sizing always renders as designed.

= 1.11.10 =
* Renamed: this plugin is now "OzuLabs Turbo Search for WooCommerce" (slug: ozulabs-turbo-search-for-woocommerce). If you're updating from an earlier version, existing settings and your search index carry over automatically.
* Fix: removed code that read a shopper's selected currency and could apply its symbol to search-result prices without converting the underlying amount. This edition doesn't convert currency, so it now always shows the store's own currency and symbol together, matching what this readme has always said.
* Fix: when a search hit an internal rate limit, the resulting incomplete result could get cached and served to every other shopper searching the same term for up to 24 hours. That kind of result is no longer cached.
* Fix: a background indexing request could briefly block outbound connections needed by unrelated plugins or payment/webhook calls running in the same batch. That block is now scoped to only this plugin's own indexing work.
* Housekeeping: removed several inactive, Pro-only code paths that had no effect in this Free edition (ranking by recent sales, synonym matching, corrected-query and category-suggestion UI).
* Housekeeping: internal identifiers were renamed for WordPress.org compliance. Sites updating from an earlier version have their settings migrated automatically and their search index rebuilt once, in the background.

= 1.11.9 =
* Fix: on longer result lists (more common on mobile, where the dropdown has less vertical space to work with), rows near the bottom of the visible area could be squeezed shorter than their own title/price/excerpt content, causing that content to visually spill into the row below it instead of the dropdown scrolling as intended. 1.11.8's fix addressed a different, real-but-unrelated rendering issue and did not fix this one.

= 1.11.8 =
* Fix: on some mobile browsers (iOS Safari in particular), scrolling the search results dropdown could visibly tear or overlap the text of adjacent rows mid-scroll. The dropdown now scrolls on its own GPU-accelerated layer, which eliminates the artifact.

= 1.11.7 =
* Removed: the optional "Occasional Announcements" feature (an off-by-default check for a promotional notice from OzuLabs) has been removed entirely. This edition now makes no outbound network requests of any kind.

= 1.11.6 =
* Housekeeping: escaped a product ID in an internal error-log message flagged by the official WordPress Plugin Check tool (no user-facing behavior change — this text is never shown to shoppers).

= 1.11.5 =
* Housekeeping: the installed plugin version now shows on every tab of the Turbo Search settings page, next to the support contact info.

= 1.11.4 =
* Fix: on a Multisite network, deleting the plugin with "Delete data on uninstall" enabled could still remove a shopper-facing admin notice's dismissed state, or the small companion file another site depends on, even when a still-active Pro or Free edition on a DIFFERENT site in the network needed them — the previous fix only checked the site being uninstalled. Both are now protected network-wide during uninstall.

= 1.11.3 =
* Fix: on the Settings page, hovering the help icon next to "Occasional Announcements" (and potentially other fields) could show its tooltip text cut off on the left, since the tooltip was centered on the icon instead of anchored to it. It now opens to the right of the icon, where there's always room.

= 1.11.2 =
* Fix: on a Multisite network, deactivating or removing this Free edition on one site could delete the small companion file another site's Free or Pro edition still depends on for fast-path search caching, because the check only ever looked at the CURRENT site's own active plugins. The file is now also automatically restored the next time any admin page loads on a site that still has it installed, rather than only when that site's own stored version number happened to change.
* Fix: deleting the plugin with "Delete data on uninstall" enabled removed a shopper-facing admin notice's dismissed state even when a still-active Pro edition on the same site depended on it, because that specific cleanup step wasn't covered by the existing Pro-safety check used everywhere else in uninstall. It's now protected the same way.

= 1.11.1 =
* Fix: if a product's search update couldn't be scheduled at all — both the normal background queue and its own retry safety-net were rejected in the same moment, a rare double failure — the update could previously be lost until that product was saved again or a full rebuild ran. It's now remembered and automatically resubmitted by the plugin's existing daily maintenance task.

= 1.11.0 =
* Security: on a server that hosts more than one WordPress site with APCu enabled (common on shared hosting, and on any Multisite network), two different sites could occasionally see each other's cached search results — product titles, prices, links, images — if their settings and search term happened to match, because the shared search-result cache was not kept separate per site. Same fix applied to the per-visitor search rate limit, which could previously also be shared across sites on the same server. Both are now kept strictly separate per site.
* Change: the optional "check for announcements" feature (an occasional dismissible notice on the Settings page) is now off by default and only ever contacts OzuLabs' server after an administrator turns it on. Turning it off again immediately stops further checks and clears any notice already shown.
* Fix: on a Multisite network, deleting the plugin with "Delete data on uninstall" enabled removed every site's search data based only on whichever site's own copy of that setting WordPress happened to check — even a site that had explicitly left the setting off. Each site's own choice is now respected individually.
* Fix: switching from this Free edition to Pro on the same site could break Pro's fast-path search caching, because deactivating or removing Free unconditionally deleted a small companion file both editions share. It's now left in place whenever the same site still has another active edition that needs it.
* Fix: deactivating or uninstalling the plugin could leave a small number of background scheduling tasks behind — retries for an in-progress rebuild or a single product's search update/removal that hadn't finished yet. These are now always cleared, the same way other background tasks already were.
* Housekeeping: documented that "Recent Searches" (on by default) stores a shopper's own past searches only in their own browser, never on the server — see the FAQ.

= 1.10.2 =
* Fix: if a product could not be removed from search after several quick retries (a removed, hidden, or password-protected product), it previously stayed in the index indefinitely unless something else happened to touch that exact product again. It's now retried automatically in the background until it succeeds.
* Fix: a product successfully removed, hidden, or password-protected could still appear in an existing cached search result for up to 5 minutes, since cache refresh for that case waited on the same short delay used for ordinary product edits. Removal now refreshes the cache immediately.
* Fix: if the background signal that refreshes search's cache failed to schedule, stale results could persist for up to 24 hours unless an unrelated product happened to be saved afterward. It's now refreshed immediately in that case instead of depending on later activity.
* Fix: two narrower background-job scheduling gaps (a single product's update retry, and its removal retry, both occasionally not getting rescheduled) are now verified the same way other scheduling in this plugin already is.

= 1.10.1 =
* Fix: a temporary database error while a background rebuild was reading the product list could look identical to "finished reading the whole catalog", causing the rebuild to finish early and publish an index missing every product after that point. The read is now verified and retried the same way other rebuild steps already were.
* Fix: if the database failed to prepare a clean staging area before a rebuild started, or failed the final switch to the newly built index, the rebuild could silently proceed (in the first case) or report success while still serving the old index (in the second). Both are now verified, retried, and — if they keep failing — reported with a specific, actionable error instead of a false success or a silent skip.
* Fix: a product removed, hidden, or password-protected on your store could occasionally remain findable through search if the database briefly failed to remove it from the index. Removal is now retried automatically.
* Fix: a handful of narrower background-job scheduling gaps (a rejected retry-of-a-retry during a rebuild, a single product's update occasionally not reaching the index, a cache-refresh signal occasionally not going out) are now verified and retried the same way the main rebuild scheduling already was.
* Fix: on a temporary search error, the live search dropdown could keep showing that same incomplete result to a shopper for the rest of their visit instead of trying again, because the browser's own short-term cache didn't know the result was incomplete.

= 1.10.0 =
* Improvement: exact-title, "starts with", and "contains as a phrase" ranking boosts now recognize a product title as a match even when it contains punctuation the search box normalizes away — for example searching "t shirt" now gets full ranking credit against a product titled "T-Shirt", the same credit it already got against a title with no punctuation. Triggers a one-time background rebuild.
* Fix: a product with variations (size, color, etc.) could show stale variation SKUs, price range, or stock status in search results after editing a variation directly — WooCommerce fires separate events for variation changes that this plugin wasn't listening for. Creating, editing, changing stock on, deleting, or restoring a variation now refreshes its parent product's search entry.
* Fix: restoring a trashed product (or one of its variations) from the Trash could leave it unsearchable until an unrelated edit or a full rebuild, because WordPress's restore action doesn't go through the same code path as a normal save.
* Fix: a temporary database hiccup during a search (a brief lock wait, a mid-upgrade schema mismatch) could be cached as "no products found" for up to 24 hours, since a failed query and a genuine empty result looked identical internally. A failed query is no longer cached either way.
* Fix: if the background rebuild's job queue rejected a batch partway through a large catalog (the same rare timing issue 1.9.1 fixed for the very first batch), the rebuild could stall indefinitely with no automatic recovery. Every batch is now verified and retried the same way.
* Hardening: if one or more products fail to write into a rebuilt index, the rebuild now still completes with everything else that worked and shows a specific, actionable notice — instead of either silently reporting success or (for a batch where every product failed) leaving the previous, working index in place.

= 1.9.1 =
* Fix: on some hosts, the one-time index rebuild that runs automatically right after an update could silently fail to start — the background job queue wasn't ready yet at that exact moment, so the request to schedule the rebuild was dropped with no error, leaving the admin dashboard showing "Indexing..." indefinitely. This is now detected and retried automatically; if it still can't be scheduled after several attempts, a clear error is now shown on the Turbo Search settings page instead of an indefinite spinner.

= 1.9.0 =
* Improvement: search ranking now narrows to a bounded set of FULLTEXT candidates before applying the full relevance formula, instead of scoring every row a broad query matches. Reduces database work for common single-word searches on large catalogs without changing top-result ranking.
* Improvement: the title matching used in ranking is now precomputed once when a product is indexed instead of being recalculated on every search request.
* Fix: changing the "Number of results" or "Show out-of-stock products" setting could keep showing search results computed under the previous setting for up to 24 hours, because neither setting was part of the search result cache key. Both now refresh cached results immediately.
* Fix: a search term that happened to be a prefix of a product's SKU (for example "ABC1" against a SKU of "ABC10") could return only SKU matches and hide a genuine, stronger match on a completely different product's title or description. Only an exact SKU match now takes priority this way — a mere prefix match no longer suppresses a real result.
* Fix: a handful of words MySQL/MariaDB's default full-text configuration treats as noise (com, de, en, la, und, www) were missing from this plugin's own list of ignored words, which could make an otherwise ordinary multi-word search (for example "cafe de") return nothing.
* Hardening: activation now detects if the required InnoDB database storage engine is unavailable and shows a clear, specific error instead of a confusing raw database error. This plugin has always required InnoDB; virtually every MySQL/MariaDB host has it available by default.

= 1.8.1 =
* Fix: 1.8.0's one-batch-per-check rebuild driver released the batch it claimed only on the success path — if processing that batch failed for any reason, the claim was never released, leaving it stuck until Action Scheduler's own timeout (several minutes) eventually force-released it. It's now always released, success or failure.
* Fix: `[turbo_search_button]` (1.7.0's alias for `[turbo_search]`) always reported itself to WordPress as `turbo_search` for the purpose of the `shortcode_atts_{tag}` customization filter, regardless of which tag a shopper's page actually used — so a site trying to hook `shortcode_atts_turbo_search_button` specifically to customize the alias was silently never called. Each tag now reports itself correctly.

= 1.8.0 =
* Feature: the index rebuild status check now advances the rebuild itself, one step at a time, instead of only watching it — so a rebuild keeps moving even on a host where background scheduling (WP-Cron) is slow to pick up new work. Bounded to exactly one step per check: confirmed live in the Pro edition that an unbounded version of this (processing everything due, not just one step) could drain an entire 2000-product rebuild in a single check, making the progress bar sit at 0% and then jump straight to 100% instead of climbing smoothly.

= 1.7.0 =
* Improvement: `[turbo_search_button]` — the Pro edition's shortcode tag — now also works here, rendering the same search widget as this edition's own `[turbo_search]`. A site's shortcode keeps working either way if it ever switches between editions.

= 1.6.4 =
* Fix: activating this Free edition while Pro was already active silently failed with no explanation — WordPress (including `wp plugin activate`) reported the activation as successful, and the plugin then simply showed as inactive again on the next page load. Confirmed live: the warning notice for this case was real code, but could never actually render, because WordPress redirects immediately after processing an activation request, before any admin notice is ever painted on that request — and by the following page load Free had already been deactivated, so its own code wasn't loaded again to show the notice a second time either. Activating now fails immediately with a clear, visible message explaining that Pro is already active.

= 1.6.3 =
* Change: raised the tested-compatible WooCommerce version from 9.4 to 10.8, the version actually verified live (installed, activated, indexed a real catalog, and passed WordPress's official Plugin Check tool with zero findings) rather than bumped on assumption.

= 1.6.2 =
* Housekeeping: the 1.6.1 release commit that was actually tagged and published was missing its own changelog entries for 1.6.0 and 1.6.1 (a lineage mismatch between the published tag and the corrected source — fixed here by publishing the correction as its own version rather than altering the already-published 1.6.1 tag). No runtime behavior changed since 1.6.1.

= 1.6.1 =
* Fix: the MU cache-bypass fast path (which serves a cached search result before WordPress finishes booting) ignored the Rate Limiting settings on the Settings tab and always enforced a fixed 60 requests/minute, so a cached and an uncached search from the same visitor were governed by two different effective limits. Both paths now read the same configured value.
* Fix: on a site with both editions installed and only one actually active, the same fast path could pick whichever edition merely had a folder present (favoring Pro) instead of the one WordPress had active — for example, running Pro's currency-conversion logic against a request the active Free edition would have served in the store's default currency. It now checks WordPress's own active-plugin state and serves the real REST route instead whenever that can't be resolved to exactly one edition.
* Fix: "Delete All Plugin Data Now" no longer flushes the entire WordPress object cache — that could drop WooCommerce's and other plugins' cached data too on a large store. It now relies on this plugin's own option cleanup, which already invalidates its own cache entries correctly.
* Fix: activating, deactivating, or uninstalling network-wide on a Multisite install stopped processing after the first 1,000 sites. It now pages through every site regardless of network size.
* Housekeeping: the bundled translation template (languages/turbo-search-for-woocommerce.pot) was regenerated — it had been stale since 1.3.0 and was missing several newer strings.

= 1.6.0 =
* Change: removed the free edition's 100-product indexing limit — it now indexes the entire published catalog, with no cap. Existing per-store data is unaffected; the removed cap only stopped new products beyond the 100th from ever being indexed.
* Fix: the coding-standards lint gate (composer lint) failed with 36 findings — an array-formatting issue and one SQL query that built a table name by string interpolation instead of a prepared placeholder. Both are fixed; no query behavior changed.
* Change: the Settings and App Data tabs no longer show several separate disabled Pro-only fields (Search Merchandising, Quick Add to Cart, Search Synonyms, Ranking Weights, Export/Import Settings) or a large promotional card above the working settings. A single compact "Turbo Search Pro" card now appears once, below the complete set of free settings.
* Change: the optional promotional notice's link is now restricted to OzuLabs' own domains and rejects tracking parameters, so a compromised or repurposed endpoint could not point shoppers anywhere else.
* Housekeeping: moved older changelog history out of readme.txt into a separate changelog.txt file.

= 1.5.1 =
* Fix: 1.5.0's new rate-limit table wasn't actually created on an in-place upgrade (only on a brand-new install) — the schema-version marker that triggers table creation on update wasn't bumped alongside it. Caught before it caused any visible problem (the plugin fails open — allows every request — when this table is missing, exactly to avoid blocking search traffic over an internal gap like this), but the atomic rate limiting from 1.5.0 wasn't actually active on any site that upgraded rather than installed fresh until now.

= 1.5.0 =
* Improvement: search abuse protection is now self-contained instead of leaning on your server's configuration. Previously, the per-visitor request limit was only exact on a host with the APCu extension — without it, two requests arriving at the same instant could both slip through the check before either was recorded, letting roughly double the intended rate through under real concurrent load (confirmed directly: 15 genuinely simultaneous requests with no coordination at all). It's now enforced exactly either way, with no extension or external cache required.
* Feature: a second, much stricter limit specifically for searches that find nothing and fall through every fallback the plugin tries (broadened matching) — the most expensive kind of request, and the shape a scripted flood of random search terms would use to run up load without ever repeating a query the result cache could serve cheaply. A normal shopper never notices it; it only engages once a search would already have come back empty.
* Improvement: both limits — the general one and the new stricter one — are configurable on the Settings tab (New: Rate Limiting), rather than fixed in code.

= 1.4.1 =
* Fix: 1.4.0's "one word missing from the catalog still finds the rest" relaxation had a gap — it only covered queries with at least one longer, FULLTEXT-eligible word. A query made entirely of short words (each under 4 characters) skipped that entirely, so it could still come back empty even when products matching either word plainly existed — confirmed live: "egg mix" returned nothing despite an egg product and a "mix" product both being in the catalog. A matching fallback now covers this case too.

= 1.4.0 =
* Fix: a search containing an ordinary connecting word returned nothing at all. Every word in a query has to match, so "for", "with", "the" and the like had to appear in a product's own title or SKU — confirmed live on a real store, where "bacon" found a product and "bacon for", "bacon with" and "the bacon" each found none. Those words are now dropped from a multi-word search (short, genuinely selective terms like "LG", "HP" or "3M" are kept, and a search made up entirely of such words still searches for them).
* Fix: a search whose FULLTEXT pass found only one or two products stopped there instead of filling the rest of the dropdown. Prefix matches now top up a partial result set the way the substring pass already did, so a search asking for 6 results no longer shows 1 when 5 more genuinely matched. The stronger FULLTEXT matches keep their positions at the top.
* Improvement: searches that skip the FULLTEXT index (queries made up of short words, like "lg tv") previously had no relevance ranking at all — they were ordered by total sales, then alphabetically. Each word now scores against the product title, so a product matching more of what was typed ranks above one matching less, with popularity only breaking the ties that remain.
* Improvement: a multi-word search where one word matches nothing in the catalog no longer comes back empty. As a last resort — and only when the alternative is an empty dropdown — the search re-runs allowing any of the words to match, ranked so that products matching more of the query come first.

= 1.3.1 =
* Improvement: the divider line between result rows is a bit more visible.

= 1.3.0 =
* Improvement: Recent Searches (the last few searches offered again on an empty search box) is now configurable on the Settings tab — turn it off entirely, or change how many are remembered (1–10, default 5, same as before). Previously always on with a fixed count of 5.

= 1.2.4 =
* Change: the Settings tab now shows a disabled Quick Add to Cart field with an upsell to Turbo Search Pro, matching the existing pattern for other Pro-only fields.

= 1.2.3 =
* Fix: the 1.2.1 title-prefix fix wasn't enough on its own — confirmed live on a real store. The "title contains query as a phrase" boost had the identical raw-character flaw (searching "dog" still credited "Dogo African Choker Necklace" via a plain '%dog%' substring match), which was enough to tie it with genuine "... dog ..." titles and hand the win to an unrelated total_sales/alphabetical tiebreak. The phrase boost now requires "dog" to appear as a genuine whole word too, the same as the prefix boost already did.
* Fix: the result dropdown's width was set to exactly match the search box it's attached to, with no minimum — a theme with a compact header search box (a couple hundred px) forced an equally cramped, hard-to-read dropdown. Now has a sensible minimum width, capped so it can never overflow past the edge of the screen.

= 1.2.2 =
* Fix: result titles in the dropdown were forced onto a single line and cut off with "…" as soon as they ran out of room — on a narrow mobile screen this could leave a title reading as just its first word or two, hard to scan and easy to mistake for a shorter, differently-named product. Titles now wrap onto 2 lines.

= 1.2.1 =
* Fix: the "title starts with query" ranking boost matched on raw characters, not whole words — so searching "dog" could rank an unrelated product like "Dogo African Choker Necklace" above genuine dog collars, since "Dogo" also starts with the letters "d-o-g". The boost now requires the match end at a word boundary (the query alone, or the query followed by a space), so a short word that happens to prefix a longer, different word no longer gets an unearned edge over products that actually contain that word.

= 1.2.0 =
* Feature: recent searches — the last 5 searches are remembered per browser and offered again when the search box is focused, with a one-click "Clear."
* Improvement: exact title/SKU matches and title-prefix matches now get a stronger built-in ranking boost.
* Improvement: the search dropdown shows a "Searching products…" state immediately instead of staying blank while a request is in flight, and a clear "Search is temporarily unavailable — please try again" message if the request fails.
* Improvement: the no-results message now includes a helpful hint ("Try another spelling or a shorter search.").
* Change: the Settings tab now shows a disabled Search Merchandising field with an upsell to Turbo Search Pro, matching the existing pattern for other Pro-only fields.

= 1.1.2 =
* Feature: the App Data tab and the Settings tab's Pro summary now mention Export/Import Settings, a Pro-only feature for moving configuration between sites as a JSON file — matches the disabled-stub-plus-upsell-copy pattern already used for other Pro-only fields.

= 1.0.5 =
* Change: "Delete Data on Uninstall" and the "Delete All Plugin Data Now" danger-zone action moved off the Settings tab into their own new "App Data" tab (parity fix — this shipped for the Pro edition in 1.3.40/1.3.41 but was missed here).
* Feature: the Settings tab now shows what Pro adds — an "Unlock More With Turbo Search Pro" summary, plus a disabled Search Synonyms field and a Ranking Weights explainer, each linking to ozulabs.com.

= 1.0.4 =
* Change: Turbo Search now has its own top-level admin menu item instead of living under Settings, so it's visible directly in the main sidebar.

= 1.0.3 =
* Feature: the Settings page can now show an occasional dismissible promo/announcement banner, sourced from ozupay.com and configured centrally — no plugin update needed to change it. Dismissing it is permanent per admin; editing the banner's content automatically re-shows it once, even to admins who dismissed an earlier version.

= 1.0.2 =
* Fix: removed the Plugin Name header from the companion MU cache-bypass file
  to prevent WordPress from listing it as a separate plugin or generating
  incorrect activation links during install.

= 1.0.1 =
* Fix: running the Free and Pro editions simultaneously on the same site is now
  blocked — activating Free while Pro is already active shows a clear "Plugin
  Conflict" error instead of silently double-registering the REST route, daily
  GC cron, and search index tables.
* Fix: garbage-collection cron no longer references the analytics log table
  (`wcs_search_log`), which this edition never creates; the prune block was
  unreachable dead code inherited during the initial port.

= 1.0.0 =
* Initial WordPress.org release — the free core edition of Turbo Search for WooCommerce. Live product search using native MySQL/MariaDB FULLTEXT indexing, background indexing via Action Scheduler, live index sync on product save/delete/stock change, multi-layer result caching (object cache / APCu / transients), search across title/SKU/content/categories, and full WooCommerce Multisite support.
