=== Simple Subscriptions ===
Contributors: freedomtelephony
Tags: subscriptions, recurring billing, stripe, memberships
Requires at least: 6.2
Tested up to: 7.0
Requires PHP: 7.4
Stable tag: 1.31.0
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

Standalone subscriptions and recurring billing for WordPress, with Stripe checkout, customer portals, notifications and reporting.

== Description ==

Simple Subscriptions gives you subscription products, checkout, and a customer portal without requiring WooCommerce. Stripe Billing handles the recurring-charge math (proration, retries, coupons); this plugin owns the WordPress-side product model, checkout experience, and admin tooling.

Simple Subscriptions includes standalone plan pages, checkout, direct Stripe integration, webhooks, vouchers, customer records, portal actions, notifications, retries, reports and audit logging. Test the complete customer journey in staging mode before enabling live payments.

== Required agreement and external services ==

The plugin is a commercial product operated by Freedom Telephony Ltd. An administrator must positively agree to the Terms and Conditions and privacy information once during initial setup before the plugin can be used. Routine plugin and terms updates do not invalidate that acceptance or interrupt live subscription services. The agreement is available at https://simple-subscriptions.com/terms.

After agreement, the plugin communicates securely with simple-subscriptions.com to register the installation, retrieve and enforce the applicable licence and subscriber capacity, manage paid capacity changes, and send daily operational heartbeats. Registration sends the site URL, WordPress administrator email address, business name and plugin version. Heartbeats send the current-mode subscriber count, gross paid revenue total, currency and plugin version. These communications are required for the commercial licence and capacity service.

The plugin also communicates with Stripe when the administrator configures Stripe keys or when customers use checkout, billing and portal functions. Stripe processes payment and billing information under the site owner's Stripe agreement. Optional SMS functionality communicates with BulkSMS or Twilio only when the administrator selects and configures that provider.

== Privacy ==

The plugin stores customer and subscription information in the WordPress database and provides WordPress personal-data export and erasure integrations. Site owners remain responsible for publishing an appropriate privacy notice and establishing a lawful basis for processing customer information. The setup agreement covers the plugin's own commercial licence service and data transmissions to simple-subscriptions.com.

== Installation ==

1. Upload the complete production plugin ZIP through Plugins → Add New → Upload Plugin.
2. Activate Simple Subscriptions. A dedicated agreement screen opens immediately.
3. Read the linked Terms and Conditions and privacy information. Either positively tick the agreement and continue, or deactivate and delete the plugin. No licensing registration or heartbeat is sent before acceptance, and routine updates will not require acceptance again.
4. After acceptance, complete the separate setup wizard with your business details and Stripe test keys, then test the full customer journey before enabling verified live mode.

== Changelog ==

= 1.45.2 =
* Changed: the plugin now appears as "Simple Subscriptions Pro" on the WordPress Plugins page, so Pro and Lite are unmistakable at a glance.

= 1.45.1 =
* Improved: opening Account & Upgrade now refreshes the licence automatically when the cached copy is more than fifteen minutes old — so an upgrade or complimentary grant made on the licensing service is live by the time you look, without pressing Refresh or waiting for the daily check.

= 1.45.0 =
* Changed: free trials and pricing badges now require an active licence, in line with every other Pro feature. When the licence is inactive the plan-editor fields show locked chips, new saves do not store trial or badge values, and the checkout neither applies a trial nor advertises one — so a customer can never be promised a trial that will not be honoured.

= 1.44.0 =
* New: revoked licences are now handled distinctly from simply-unlicensed ones. A revoked site shows a prominent banner on every plugin screen, and the Account page replaces the purchase button with a "contact support@simple-subscriptions.com to request reinstatement" panel — a revoked user cannot re-purchase from within the plugin (checkout is also blocked server-side). Genuinely lapsed/free sites keep the normal Get Pro button.
* New: the plan limit is now obvious — the Plans screen shows a clear locked banner explaining new plans need Pro, and the Create button is removed while revoked.
* Changed: per-subscription payment time and change-renewal-date now appear as visible "Pro feature — contact support" locked chips on the subscription page (rather than disappearing), and both save handlers refuse.

= 1.43.0 =
* New: plan limit enforced when unlicensed — existing plans keep working, but no new plans can be created (the New Plan editor redirects, and a direct save is blocked). Matches the free tier's one-plan ceiling.
* Fixed: the email and SMS template editor is now genuinely locked when unlicensed — inputs are disabled, the Save button is replaced with a "Reactivate Pro" prompt, and saves are refused server-side. Existing templates keep sending.
* Fixed: the padlock on locked Reports/Vouchers menu items rendered as stray characters on some servers; now a clean lock icon.
* Improved: locked Pro pages now show a polished, reassuring upsell screen (what the feature does, that nothing is broken, and how to reactivate) instead of a red error.

= 1.42.0 =
* Changed: when a licence is inactive, Pro features are now shown-but-locked rather than hidden. Reports and Vouchers stay in both the WordPress menu and the in-page tabs, marked with a gold padlock, and open a clear "Pro feature — contact support@simple-subscriptions.com to reactivate" page. Existing subscriptions, payments and the customer portal keep working throughout. Underneath, the features remain fully disabled (no SMS, no retries, no template edits, no voucher creation).

= 1.41.1 =
* Fixed: the in-page tab bar (separate from the WordPress menu) still exposed the Vouchers tab when unlicensed — now removed. The email-template editor on the Notifications page is now locked when unlicensed: it shows a clear Pro banner and refuses to save changes, while existing templates keep sending.

= 1.41.0 =
* New: deep licence enforcement at the source. Without an active licence, SMS is never sent, the multi-card retry engine is withheld, and the payment-time, voucher and SMS-template save handlers all refuse — so a Pro feature cannot function regardless of which screen invokes it. All messages point to support@simple-subscriptions.com.
* New: a build-and-gate diagnostic on the Account page (plugin version and the live licence-gate values) so a stale install or licence mismatch is immediately visible.

= 1.40.3 =
* Fixed: an unlicensed or revoked site now presents exactly the free (Lite) feature set, enforced through one central gate rather than per-screen. Reports, Vouchers and the marketing tools disappear from the menu; the voucher post type is not registered; the voucher field and coupons are removed from checkout; SMS, the payments recovery card, per-subscription payment time, change-renewal-date and early renewal are all withheld. Everything returns the instant the licence activates.

= 1.40.2 =
* Fixed: licence enforcement now covers the full Pro surface. Without an active licence the Reports and Vouchers menus disappear, the payments recovery card does not render, the per-subscription payment time and change-renewal-date controls are hidden and their handlers refuse, and early renewal declines with a clear message. Everything returns the moment the licence activates.

= 1.40.1 =
* New: licence connection diagnostics on the Account page — the stored key prefix, exactly what the licensing service last answered, and a loud red line when a licence check fails (including the reason), so a stale cached plan can never masquerade as the hub's answer.
* New: "Reset connection" — forgets the local key and licence and re-registers, healing an orphaned or rotated key in one click.

= 1.40.0 =
* Changed: positive licence activation. Pro features now require a licence the hub has confirmed (purchased or granted). A copied zip installs and registers but runs at the free feature level from the start — no updates, no Pro features, and it appears in the hub flagged as unpaid. Paying customers are protected in every failure direction: hub outages keep them active via the sealed cached licence, and lapsed renewals keep features while pausing updates.
* New: an activation notice on the plugin's screens while unlicensed, with "Check licence now" and the purchase button.

= 1.39.1 =
* Improved: lapsed-licence messaging matches the graceful policy — features stay on, updates pause. A failing renewal card gets its own recoverable message ("Fix payment") instead of being told the licence expired, and the Account page shows "Pro — licence expired" rather than mislabelling a paid customer as Free.

= 1.39.0 =
* Changed: the product is now live-only. The test/staging mode toggle, test key fields and the demo playground are removed from customer builds (developers can restore them with the SSUBS_ALLOW_TEST_MODE constant).
* New: licensing connection diagnostics — the Account page now shows exactly why a connection attempt failed, and the button becomes "Connect now" to retry immediately instead of waiting for the hourly background attempt.

= 1.38.2 =
* Fixed: saving a payment time now moves the STRIPE billing point too (the notice confirms it) — previously only the local record moved, so the charge time on card-billed subscriptions did not actually change.
* Fixed: Started / Last payment / Next renewal now display in site-local time everywhere; they previously showed raw UTC, an hour off during BST.

= 1.38.1 =
* Fixed: Stripe webhooks are now acknowledged instantly and processed after the response (with a cron fallback and five-minute sweeper) — slow email transports can no longer make Stripe count deliveries as failed.
* Fixed: sparse Stripe events can no longer blank a subscription's renewal date.
* Fixed: the subscription detail page now shows success and error notices, so a failed save is never silent.
* New: licence hardening — hub URL pinned, cached licence sealed against tampering, and a revoked licence (fraud/chargeback, set from the hub) drops the install to the Lite feature set: payments, renewals and the portal keep working; SMS, vouchers, reports, multi-card retry and per-subscription payment times switch off until the revocation is lifted.


= 1.38.0 =
* New: per-subscription payment time — pick the local time of day renewals are attempted for any subscription, right on its record. Defaults to 08:00 (or your site setting); saving re-pins the current renewal to the new time without moving the date.
* New: setup wizard redesigned — same questions in the same order, now a beautiful branded flow with progress, trust signals (Stripe-secured, no card required, ~5 minutes) and save-as-you-go reassurance.
* Fixed: last remaining subscriber-spaces meter and "Not permitted" early-renewal label (both removed in 1.37.1 — update if you still see them).


= 1.37.1 =
* New: Payments today card — three views on the Subscriptions screen: Failed & due today, Paid today, and Failed for 1+ days (newest first). Retry individual customers or in bulk from any failed view; recovered rows sweep green, show "→ Active" and glide into Paid today, while declines shake and stay put.
* New: every next-payment date is pinned to your payment time (08:00 by default) — on signup, renewal, reactivation, resume and retry, wherever the date comes from.
* Changed: early renewal is now always available (up to 12 per rolling 24 hours) — no customer opt-in toggle; the portal is simpler for it.
* Changed: reports rail (income today/week/month, sign-ups, plan mix) moved from Subscriptions to the Dashboard, with duplicate stat cards removed.
* Changed: subscription list slimmed — customer name only, renewal date without the time.
* Fixed: Account & Upgrade no longer shows subscriber-space meters anywhere, and upgrading is available in test and live mode alike.
* Fixed: portal messages after reactivation no longer lose their spaces (double URL-encoding).


= 1.37.0 =
* New: Reports — nine ready-made reports (revenue, growth, churn, failed & recovered, plan performance, upcoming renewals, customer list, refunds, VAT summary) plus a custom report builder with saved templates. Every report exports to CSV or a print-ready PDF page.
* New: multi-card payment recovery — retries try every saved card in turn, safest first, stopping at the first success. Hard limits: 2 attempts per card and 4 per customer per day; capped cards are skipped automatically.
* New: Subscriptions screen rebuilt — search by name, email, phone, address or postcode; status tabs (Active, On-hold, Cancelling, Cancelled, Paused); failed-payments recovery card with Due-today / Older views; live stats rail with income today, this week and this month against the previous period.
* New: customer portal redesigned — renewal countdown ring, payment history, clearer manage actions and a friendlier look on every device.
* Changed: Customers screen is now a fast find-and-manage list; all per-subscription actions live on the customer record.
* Changed: subscriber capacity limits removed everywhere — every plan now supports unlimited subscribers.
* Changed: dashboard shows this month's revenue and leads with your numbers.
* Fixed: Account & Upgrade no longer claims a 10-subscriber limit on the free plan.


= 1.36.2 =
* New: Subscriptions screen reorganised into age-based views — All / Active, Today's failed payments, On-hold over 1 day, Today's successful payments, Paused and Cancelled. Failed payments are grouped by how long they have been failing, since that decides the right action.
* New: Bulk payment retry rebuilt around a per-customer daily cap (2/day). Retry a hand-picked selection, everyone who failed today, or every on-hold customer; anyone already at their daily limit is skipped automatically. A warning appears before retrying any card that has already been tried today.
* New: Live recovery — when a retried payment succeeds the row moves out of the failed list and the on-page recovered totals update immediately.
* New: Auto-cancel for stuck on-hold subscriptions (off by default). After a configurable number of days on-hold (minimum 14), each subscription is checked against Stripe and only cancelled if Stripe also shows it as no longer paying; if Stripe recovered it, it is reactivated instead. Optional final email to the customer.
* New: Bookmarkable subscription detail page bringing the subscription, its customer, invoices, history and all its actions onto one screen. This is now the single place subscription actions live.
* New: Editable customer records — name, email, mobile, landline, full postal address and internal notes. Adds a dedicated landline field (the mobile is kept for SMS).
* New: SMS template manager (appears once an SMS provider is configured) — create and edit reusable text messages with a merge-tag legend, then send them to a customer from their record in one click.
* Improvement: The standalone On-Hold page now lives inside Subscriptions; old links redirect there.

= 1.36.1 =
* The audit log is now paginated — 50 entries per page with Previous/Next navigation and a running "Showing X–Y of Z" count — so sites with thousands of logged events load instantly instead of trying to render the entire history at once. Filters and searches carry across pages, and a customer's detail screen links straight to their full filtered log.

= 1.36.0 =
* Cancelled subscriptions now show exactly one action: "Take payment and reactivate". It charges the full renewal amount to the saved card on Stripe, reactivates the subscription, restarts billing from today, and emails both the customer and the admin. If the customer is still inside a period they already paid for, no payment is taken. The meaningless "Cancel at period end", "Pause" and "Mark on-hold" buttons no longer appear on cancelled rows.
* Early renewals now run on the customer's terms. A new toggle in the customer portal — "Allow early renewal payments" — must be switched on before the admin can renew a plan early, and at most 12 early renewals can be taken per subscription in any rolling 24 hours: enough to pay a monthly plan a full year in advance, and no more. The admin button shows the running count (e.g. 3/12) and locks itself when permission is missing or the limit is reached.
* Early renewal scheduling confirmed and documented: each early payment moves the next renewal exactly one billing period past the previous renewal date, pinned to the payment time setting (08:00 by default), so twelve early payments land the renewal a clean year out at 8am.
* New: Emergency mode and the Stripe data check. When the plugin detects that this database and Stripe disagree — the classic sign of a site restored from a backup — it switches on emergency mode: a banner on every plugin screen, and payment actions on affected subscriptions stay blocked. The new Stripe data check (Operations → Stripe data check) compares every subscription against Stripe, lists each difference in plain English side by side, and asks you to choose: update this site with Stripe's data, or leave your data as it is. Nothing changes until you choose, and the check itself never charges anyone.
* The "Blocked to prevent a double charge" message now tells you what to do about it, pointing straight at the Stripe data check instead of leaving you stranded.
* The audit log now reads like a logbook, not a debug dump: actors are named people ("Ella Fraser (customer)", "Alexander (admin)", "Stripe (webhook)", "Automated process"), actions are plain English ("Signed in to the customer portal", "Took payment and reactivated", "Early renewal payment taken"), and the technical action key moved into the details view. Portal sign-ins, cancellations, reactivations, consent changes and every emergency-mode decision are all recorded.



= 1.31.0 =
* FIXED: setting up the Stripe connection created a brand new webhook endpoint every single time, instead of replacing the one it made last time. Stripe allows 16 per account, so repeated setup attempts silently used them all up and then failed with "You have reached the maximum of 16 live webhook endpoints" — an error that gave no hint of the cause. The plugin now removes any endpoint pointing at this site before registering a fresh one. Endpoints belonging to other sites, or created by hand, are never touched.
* If the account is genuinely full of other sites' endpoints, the error now explains what a webhook endpoint is, that old ones are safe to remove, and where to remove them.

= 1.30.1 =
* Added the GPLv2 licence text. The plugin has always carried a GPL header but shipped no licence file, which WordPress.org would have picked up.

= 1.30.0 =
* FIXED: asking for a sign-in link looked like the page had simply reloaded. The confirmation was a small notice above a form that stayed exactly where it was, so nothing appeared to change and people pressed the button again. Sending a link now replaces the form with a "Check your inbox" screen, with "send another" and password login as separate choices.

= 1.29.0 =
* Payment retries are now capped at one automated run and one manual attempt per day, as intended. The manual limit was 2; it is now 1.
* The automated retry queue is hard-capped to one run per calendar day. It previously had only a concurrency lock, which is released the moment a run finishes - so an external cron calling wp-cron.php repeatedly could put a second round of charges through the same declined cards on the same day. Stripe treats that as excessive retries and it is your account at risk.
* readme: corrected the Stable tag (was 1.9.4 while the plugin was 1.28.0 - WordPress.org serves whatever Stable tag names) and the Contributors field (now a wordpress.org username).

= 1.28.0 =
* Receipts now read like receipts. The payment appears once, in the order people expect - subtotal, VAT, total paid - instead of the same figure turning up three times as "Amount", "Plan cost" and "Total paid".
* "Plan cost" is gone from receipts. It is a price ("£24.99 per month"), not an amount, so a customer paying £0.00 on a voucher saw a price they had not paid sitting next to one they had.
* The total now always appears, even when you do not charge VAT. Previously the whole block was skipped without VAT, which would have left a receipt that never said what was paid.
* No VAT line on a £0.00 order - a free order has no tax to declare.
* Existing receipt templates are updated in place on upgrade, so any wording you have written survives.

= 1.27.0 =
* FIXED: reactivating a subscription sent FOUR emails for one action - the customer got "your subscription is active again" and "your plan has changed" (it had not), and you got a copy of each, one of them titled "Renewal event". Now it sends one.
* FIXED: any event the admin mapping did not recognise was emailed to you as a "Renewal event". A plan change, an expiry, anything new - all announced as a renewal that never happened. Unrecognised events now send nothing rather than something untrue, and two new admin messages ("Plan changed", "Subscription ended") cover the two real cases.
* FIXED: cancellation emails said "access remains active until the end date shown below" while showing no date - introduced in 1.26.0 when the misleading renewal date was removed. The same stored date means two different things: for an active subscription it is when you will be charged, for one set to cancel it is when access runs out. They are now separate rows - "Next renewal" and "Access until" - and a fully cancelled subscription shows neither.
* Renewal reminders, trial warnings and sign-in links no longer send you a copy. You do not need one of every nudge.
* REMOVED: the "login code" text template. Nothing has ever sent it - magic sign-in links replaced it - so it sat in the list looking editable and functional while being neither.

= 1.26.0 =
* Emails now only mention things that actually apply. Any detail row left empty is removed, so "Voucher: None", "Add-ons: None" and "Discount applied: £0.00" no longer appear on emails to people who used none of them. This works on templates you have edited yourself - a blank value simply means "say nothing".
* Vouchers and discounts now appear only on messages about a sale (sign-up, welcome, receipts). A cancellation email no longer recites the voucher someone used months ago.
* FIXED: cancellation and "subscription ended" emails showed a "Next renewal" date. Telling somebody their subscription is cancelled and then giving them a renewal date reads as "we are going to charge you anyway".
* FIXED (money): {amount} fell back to the plan's list price when nobody said what had been charged. A customer on a 100%% voucher received a receipt for £24.99 having paid nothing, and receipts showed "£24.99 / month" - a price, not an amount. It now shows only what was actually taken, and shows nothing if that is not known.
* Subjects tidy themselves up, so a message whose amount is unknown no longer arrives titled "New sign-up - Jane Smith - ".
* "No address saved" no longer appears on customer emails.

= 1.25.0 =
* FIXED PROPERLY: the "Mode: LIVE" row really is removed from notification emails now. The 1.23.0 attempt could never have worked - it looked for one exact string, but any template opened in the visual editor comes back reformatted, so the match failed silently and the upgrade was marked as done regardless. Matching is now on the row itself, tolerant of whitespace, attributes and case, under a new database version so it actually runs. {mode} also resolves to nothing now, so nothing can print LIVE at a customer again.
* NEW: text messages that cannot send now say so. If a text template is switched on but no provider is connected, the message was skipped in complete silence - nothing sent, nothing failed, no way to find out. The card now reads "Cannot send" and explains why.
* The Messages tab is much quieter: the wall of merge-tag text is gone (the editor has clickable tags), renewal reminders are tucked into a collapsible panel that shows their state at a glance, and each message now says WHEN it sends rather than repeating who it goes to.
* "Reset all messages to defaults" moved from the top of the page to the bottom, behind a disclosure. It overwrites everything you have written, so it should not be the first button you meet.

= 1.24.0 =
* Notifications is now split into tabs: Messages, Testing, and Delivery log. The tester and the full template list on one page had become a wall.
* The Testing tab shows a small dot until you have confirmed your emails actually arrive, so the reminder is present without being a banner.
* Removed the per-template "Send test" row. The Testing tab does the same job better, and two ways to do one thing was half the clutter.

= 1.23.0 =
* NEW: VAT / sales tax (Settings). Choose whether you charge no tax, your prices already include tax (the usual UK/EU choice), or tax is added on top at checkout. Set your rate, its name and your VAT number.
* Stripe calculates the tax, shows it at checkout and puts it on its own invoices. This plugin only reports the figures Stripe used, so a receipt can never disagree with what was actually charged.
* NEW: {tax_breakdown} merge tag - prints subtotal, tax rate, tax amount, total and your VAT number on receipts, and prints nothing at all if you do not charge tax.
* Receipts record the tax that was charged at the time of sale, so changing your rate later does not rewrite old receipts.
* REMOVED: the "Mode: LIVE" row from notification emails. The plugin has been live-only since 1.7.0, so it printed the word LIVE on every email and told nobody anything. Existing templates are cleaned up on upgrade without touching any wording you have written yourself.

= 1.22.0 =
* FIXED (likely the big one): WordPress has never set the "envelope sender" on outgoing mail - a bug open in WordPress core since 2012 (Trac #22837). Receivers check SPF against the envelope sender, not the From address, so the check ran against your web host's domain instead of yours. It could pass and still not ALIGN with your From address, and unaligned SPF is not authentication. Since February 2024 Gmail discards unauthenticated mail silently - no bounce, not even spam. The plugin now sets it, which costs nothing and needs no DNS change.
* NEW: built-in DKIM signing (Email Delivery -> Sign your emails). The plugin can generate its own signing key and sign your emails itself, with no SMTP service, no other plugin and no monthly bill - just one DNS record. A host's own DKIM cannot do this, because that key lives on their mail server and can only sign mail sent through it, not mail sent by WordPress.
* Signing only switches on once the DNS record is verified as published. A signature nobody can check is worse than no signature at all.
* The private key is stored encrypted, like the Stripe keys, and never leaves the site.

= 1.21.1 =
* Removed the alarming "your customers are probably not receiving these emails" warning. It was a guess dressed up as a diagnosis - it fired whenever a site used PHP mail and had emailed anyone outside its own domain, which describes plenty of perfectly healthy sites - and its advice to install a separate SMTP plugin was out of date the moment SMTP became built in. The tester answers the same question with evidence instead.
* Notifications now shows one calm line explaining why testing is worth doing once, rather than two stacked banners.
* Warnings about delivery now appear only after YOU report that emails are not arriving, not because the plugin guessed.

= 1.21.0 =
* NEW: Email Delivery screen. Shows how mail currently leaves your site, who it comes from, and when it was last attempted - none of which you could see before. The provider settings stay hidden until you actually choose to send through a provider, and picking Brevo, Mailgun, Postmark, SendGrid or SES fills in the host, port and encryption for you. Defaults to WordPress's built-in mail; nothing to set up.
* NEW: email tester on the Notifications screen. Send any or all of your customer emails to a test address, through the real sending code, with sample data. Results appear per message.
* The tester warns if you test with an address on your own domain. That is the one test guaranteed to pass while your customers receive nothing, because mail to your own domain is delivered inside your own server and never checked - which is exactly how this went unnoticed.
* The plugin cannot know whether an email was delivered, only that it was accepted, so the tester asks you and records your answer. Notifications and Email Delivery both say "Not verified" until you confirm mail actually arrives.
* If an SMTP plugin (WP Mail SMTP, FluentSMTP, Post SMTP, Easy WP SMTP) is active, Email Delivery stands down and says so rather than fighting it.
* FIXED: a sign-in link for an address that also owns an administrator account was refused - correctly, since an emailed link must never unlock an admin account - but reported as "expired or already used". It now explains the real reason and points to the password login, instead of sending you round in circles requesting links that would all be refused.

= 1.20.1 =
* NEW: "Emails come from" name and address settings, the same control WooCommerce exposes. This is the single biggest factor in whether customers receive your emails, and until now the plugin decided it for you and never told you what it had chosen.
* The settings screen shows the address currently in use, and warns clearly if it is not on your website's domain - the case where mail is almost always rejected or spam-filtered.
* The default deliberately differs from WooCommerce's: Woo defaults to the WordPress admin email, which on many sites is a personal Gmail, and sending as gmail.com from a web host fails authentication outright. Simple Subscriptions picks a real mailbox on your own domain and never silently sends as an off-domain address.

= 1.20.0 =
* NEW: SMTP is now built in (Settings -> Email delivery). Enter the details from a sending service and the plugin sends through it directly - no separate SMTP plugin needed. The password is stored encrypted, like the Stripe keys. If you already run an SMTP plugin it still wins; the two do not fight.
* FIXED (deliverability): emails were sent from "wordpress@yourdomain", a mailbox that usually does not exist, which receivers increasingly reject. When your business email is on the same domain as the site it is now used as the sender instead. When it is on a different domain (a support inbox at Google or Microsoft, say) the old behaviour is kept deliberately, because sending as a domain this server is not authorised for fails outright.

= 1.19.1 =
* NEW: the plugin now detects the single most common cause of "customers never get any email" - WordPress sending through PHP's built-in mail function instead of a real SMTP service - and warns about it on the Notifications and Delivery Log screens, with the fix.
* The delivery log no longer implies "Sent" means delivered. It means the mail server accepted it; anything after that is out of the plugin's hands.

= 1.19.0 =
* NEW: Delivery log (Notifications -> "See what was actually sent"). The plugin has recorded every send attempt since day one - who it went to, which message, and whether it was sent, refused or suppressed - and there has never been a screen to look at it. That is why "customers receive no emails" has been so hard to pin down: the evidence existed and was invisible.
* The log calls out the exact pattern of admin mail working while customer mail never sends, because that rules your mail server out.
* NEW: "Send test" on every email template. Runs the real sending code to any address you like and tells you whether the mail server accepted it - no need to buy a subscription to test.

= 1.18.1 =
* FIXED: admin "Cancel now" followed by a customer reactivation created a SECOND Stripe subscription alongside the original. "Cancel now" pauses the Stripe subscription rather than deleting it, but the reactivation code treated the local "cancelled" status as proof it was gone. Whether to resume or replace is now decided by asking Stripe.
* FIXED: a replacement subscription was built from the plan's list price with no coupon, so reactivating silently dropped the customer's voucher and started charging them full price. Replacements now inherit the voucher, from Stripe if it is still there and from the recorded voucher code if not.

= 1.18.0 =
* FIXED (reporting): new-signup emails announced every sale at the plan's list price and always said "Voucher: None", even when a voucher had taken the payment to £0. The voucher a customer used was read from Stripe only to bump a redemption counter and then thrown away - nothing was ever stored - so no email, report or support screen could tell a discounted sale from a full-price one. Subscriptions now record the voucher used, the amount actually taken and the discount applied.
* New-signup emails now lead with the amount actually taken, name the voucher, show the discount, and still show the list price separately as "Plan cost".
* FIXED (money): reactivating a subscription from the customer portal charged the customer immediately, even when they had already paid for the period they were in. Cancelling does not claw back the period you bought, so reactivating inside it now takes no payment and keeps the existing renewal date.
* FIXED (money): off-cycle charges (reactivation, retries) were built by hand from the plan price and did NOT inherit the coupon on the subscription, so anyone holding a voucher was billed the full list price. The customer's discount is now carried onto the invoice.
* FIXED (money): removed a hardcoded 2499 (£24.99) fallback left over from the removed demo subsystem. A subscription with a missing plan link would charge a real card that invented amount. It now refuses to charge at all.
* FIXED: reactivation sent no notification to anyone - there were no templates for it. Customers now get "Subscription restarted", and you get your own copy.
* FIXED: customer emails that could not be sent failed silently. Missing template, disabled template, missing address and mail-server rejection are now each recorded in the audit log with the reason.

= 1.17.1 =
* Notification templates are now named in plain English. The customer welcome email was labelled "Welcome Magic Link" - an internal name that made it very hard to find, or even to tell whether a welcome email existed at all. Every template now has a real name.
* Each notification now says WHEN it sends, not just who it goes to. The welcome email, for example, now reads "The first email your customer receives, sent as soon as their payment succeeds."
* Recipients now read "To the customer" / "To you" rather than "Customer" / "Admin".

= 1.17.0 =
* FIXED (billing): "Stops after N renewals" did not stop anything. The choice was written into Stripe metadata and never acted on, so a fixed-length subscription renewed forever. The end date is now scheduled on the Stripe subscription itself. Existing fixed-length subscriptions created before this release are NOT retro-fitted - check any live ones in Stripe.
* FIXED (billing): the end-date calculation overflowed on month-ends. A subscription starting 31 January drifted three days past its final boundary, which let Stripe issue one extra invoice. Period maths now clamps the way Stripe does (31 Jan -> 28 Feb -> 31 Mar).
* FIXED (customers): the "welcome magic link" was not a magic link. Customers were created with a random password that was never sent to them, then emailed a link to a portal demanding a login they could not pass - making self-service cancellation unreachable. Welcome emails now contain a genuine one-time sign-in link.
* NEW: "Email me a sign-in link" on the customer portal, so customers can always get back in without a password.
* SECURITY: welcome emails are no longer BCC'd to the business inbox. They now carry a sign-in token, and copying that to the merchant would share a working key to the customer's account (and any link scanner in that inbox would consume it first). The owner still receives the separate new-signup notification.
* SECURITY: sign-in tokens are stripped from the notification log before it is written, so a live credential is never stored in the database.
* Sign-in links are single-use, expire after 7 days, are stored only as a hash, and will never sign in an administrator or editor account.

= 1.16.0 =
* Vouchers and Notifications are now two separate menu entries. They had nothing to do with each other but shared a "Vouchers and Notifications" landing page whose only job was to offer two buttons - a click in the way of both. Old links still work and land on Vouchers.
* Rebuilt the email notification editor around a live preview. The preview now sits beside the editor, shown by default, and updates as you type - no more editing raw HTML blind and hoping.
* Email bodies can now be edited visually, with formatting buttons instead of hand-written HTML. Click "HTML" for the raw source whenever you want it.
* Merge tags are now clickable chips that insert at the cursor, rather than a list of names to memorise and type by hand. "more..." reveals the full set.
* The preview is rendered by the same code that builds the real email, so it cannot drift from what actually gets sent.
* Text message templates now show a live preview and a character/segment count.

= 1.15.2 =
* Fixed: cancelling the capacity upgrade checkout showed "Thanks! Your payment went through and your extra subscriber spaces are active." No payment was taken and no capacity was granted - the message was simply wrong. The plugin now confirms a real capacity increase before saying anything went through, and reports honestly when it cannot see a payment.
* Fixed: the "Add New" button and heading disappeared from the Plans list. The v1.15.0 editor styling was scoped to the whole post type, so it leaked onto the list screen.
* Admin payment retries are now capped at 2 per subscription per day. After the first retry, and again in the confirmation prompt, the plugin warns that retrying a declined card again the same day risks Stripe treating it as excessive retries - a breach of their terms. At the limit the button shows as spent rather than erroring. Automatic retries are unaffected.
* Voucher codes are easier to reach: the product's Vouchers section now has a proper button through to the voucher manager.

= 1.15.1 =
* Fixed: choosing a main product image appeared to do nothing. The upload worked, but the new editor's empty-state styling kept the image permanently hidden.
* Fixed: "Stop after a set number of renewals" gave you nowhere to say how many. The rebuilt pricing row had lost the class the renewal logic keys off, so the count field never appeared. One-off payments correctly hide renewal options again too.
* Fixed: the live preview was squashed into the panel width and showed the WordPress admin bar. It now renders the page at a real desktop width and scales it down, with the admin bar suppressed inside the frame.
* Fixed: the first pricing option now opens expanded, so "More options" is reachable without expanding the row first.
* Vouchers are easier to find: the section is now called "Vouchers & checkout options" and links straight through to the Vouchers page where the codes are managed.
* Every section except Name & pricing is now marked "optional", because a name and a price genuinely is all you need.

= 1.15.0 =
* Rebuilt the product editor as a single page. The seven drag-handled meta boxes are gone: everything is now one scrolling page with a progress checklist down the side, so the order to fill things in is obvious and nothing is hidden behind a tab.
* Product name is now the first field of the first card, clearly labelled, instead of an unlabelled heading.
* Sections collapse to a summary of their own contents ("The Monthly Coffee Club - 2 options, from GBP 24.00"), so a collapsed section is a receipt rather than a hiding place.
* New products open with the first section expanded and a "Next:" prompt; existing products open fully expanded with no prompts. Next never blocks - nothing is gated.
* The status flips to "Ready to go live" as soon as there is a name and a price, because that alone is sellable.
* Replaced the 76-option emoji dropdown for "What's included" icons with a searchable, grouped grid showing the actual Lucide icons that get rendered. The old menu previewed emoji that never appeared on the page.
* "What's included" now starts empty with a single Add item button. The enable checkbox is gone - adding a card is the intent, so presence is what shows the section.
* Added a live preview panel showing the real product page in an iframe, refreshed shortly after you stop typing.
* Pricing options now show essentials only (name, billing frequency, price), with badge, free trial, setup fee and length folded behind "More options".
* Pricing options now show how many people are subscribed to them.
* An option with subscribers can no longer be removed. It offers "Stop offering" instead, which hides it from the product page while existing subscriptions carry on billing exactly as before. Removing such an option previously left those subscriptions silently falling back to monthly billing.
* Merged the separate product image and gallery boxes into one Images & description section.
* Replaced the WordPress Publish box with a plain status control ("Not live yet" / "Ready to go live" / "Live").

= 1.14.0 =
* Vouchers: you can now choose how long a repeating discount lasts. The "Applies to" dropdown offers their first payment only, every payment, or their first 2-12, 18, 24, 36, 48 or 60 months.
* Vouchers: the chosen length is stored and sent to Stripe, replacing the old hidden 12-month assumption.
* Vouchers: the live preview describes repeating discounts too, e.g. "they pay £15.00 a month for their first 6 months, then £20.00 a month after that."
* Vouchers: existing repeating vouchers are recorded as 12 months on upgrade, exactly matching the length they were already given, and now display as "First 12 months".

= 1.13.0 =
* Vouchers: rewritten for clarity. A "How vouchers work" panel explains the three steps, and every field now says what it actually does.
* Vouchers: a live "What the customer gets" preview shows the real effect as you type, e.g. "On a £20.00 a month plan: they pay £15.00 on their first payment, then £20.00 a month after that."
* Vouchers: "Duration" is now "Applies to", with plain choices — their first payment only, or every payment while subscribed.
* Vouchers: removed the "Repeating" option. It was silently hardcoded to 12 months with no way to change it. Existing repeating vouchers keep working and are shown as "First 12 months (legacy)".
* Vouchers: "Show at checkout" renamed to "Active — customers can redeem this code". It was never only about visibility: switching it off stops the code working entirely.
* Vouchers: the Amount field now shows whether it wants a currency amount or a percentage, and says so.
* Vouchers: blank "Total uses allowed" now states that it means unlimited, and the expiry field states that it works to the end of the chosen day.
* Vouchers: the list now shows uses (e.g. "12 / 50"), the expiry date and a clear status (Active, Off, Expired, Used up).
* Vouchers: deleting a voucher now also deactivates its Stripe promotion code and deletes the Stripe coupon, instead of leaving them orphaned. Customers who already redeemed a voucher keep their discount, which is explained on the page.
* Fixed: "Choose one billing option before continuing to checkout." was appearing on the product page. It is screen-reader help text that became visible when its styling was removed in 1.10.0. It is hidden again and still read out by screen readers.
* Fixed: restored a form spacing reset on the product page that could let a theme open a gap inside the purchase panel.

= 1.12.0 =
* Checkout redesigned: a calm, official two-column layout with the form on the left and the plan summary on the right, stacking to a single column on mobile (summary first, so the price is visible before the form).
* Premium, consistent form fields with clear labels, focus rings and a styled consent checkbox. Fixed the cramped spacing and run-together label text of the old version.
* Replaced the emoji trust row with small, clean line icons. No oversized padlock, and "Powered by Stripe" is text only.
* Plan summary is easier to read: plan name, pricing option, large price, renewal terms, and any setup fee or add-ons on their own clearly disclosed rows.
* "Change selection" is now a proper link.
* The checkout follows the plan's chosen colours, so the product page and checkout match. Defaults are a light grey page, white cards and a blue button.
* Removed superseded checkout CSS that was overriding the new design.

= 1.11.0 =
* Removed the Tools section. It was already hidden on live sites (its demo checkout would have run against the live Stripe account), but links to it remained and led to a "not allowed to access this page" error.
* Moved "Reset Stripe connection" onto the Settings page, and it now confirms when it has run (previously it redirected silently to a hidden page).
* Removed the demo checkout/portal subsystem entirely. It auto-created two PUBLISHED pages on every site which, on a live-only plugin, were publicly reachable and could launch a real Stripe Checkout with real cards.
* On upgrade, those auto-created demo pages are moved to Trash and their options and access tokens are cleaned up. Pages that were edited or repurposed are left untouched.
* Fixed the admin plan preview placeholder, which lost its styling when the superseded theme CSS was removed in 1.10.0. It now uses the standard placeholder and follows the plan's chosen colours.

= 1.10.0 =
* Complete product page redesign: single unified theme with merchant-picked colours.
* New "Page colours" section on the plan edit screen: background and accent colour pickers with live preview. Different products can use different palettes.
* Automatic contrast: text, cards and button colours derive from the chosen background and accent, guaranteeing readable pages on any palette (light or dark).
* Purchase panel redesigned: brand pill, title, live price, plan selector, add-ons, button and trust row in one card.
* Live "Total today" price: the headline updates with the selected plan plus any chosen add-ons (e.g. "£36.00 today, then £24.00 per month").
* Per-tier badges: optional editable badge text (e.g. "Best value") per pricing option in the plan editor.
* Pricing options redesigned: radio-left cards with stacked price, accent selection state and badge support.
* What's included icons upgraded from emoji to crisp Lucide line icons (bundled, MIT).
* Mobile: purchase card now appears first so the product name and price are visible immediately.
* Checkout and demo pages now follow the plan's colours.
* Theme gallery removed; superseded theme CSS layers stripped from the stylesheet.
* Removed merchant-facing copy from the customer-facing trust bar.

= 1.9.4 =
* Change: The setup wizard's Stripe step now uses the same single "Save & verify Stripe" button — it checks the connection and sets up the webhook in one click, showing both results. (Matches the main settings page.)

= 1.9.3 =
* Change: One-step Stripe verification. The separate "check connection" and "create webhook" buttons are now a single "Save & verify Stripe" button that saves your keys, checks the connection and sets up the webhook together, showing both results at once.

= 1.9.2 =
* New: Dashboard setup checklist. Shows what still needs doing before you can take payments — green for done, red for required, orange for optional — each with a link straight to the fix. Disappears once everything is complete. (The wizard already shows step progress.)

= 1.9.1 =
* Change: Updated the Reactivate explanation in the Customers action key to clarify that the admin button does not take a payment (use Retry payment), while customer self-reactivation from the portal charges that day.

= 1.9.0 =
* New: Customer self-reactivation now takes payment. When a customer reactivates their own cancelled subscription from the portal, they are charged that day and their billing cycle restarts from today (next renewal one period from now). If the payment fails, the subscription stays cancelled. Works for both soft-cancelled and fully cancelled/expired subscriptions.
* Unchanged: Admin reactivation still does not charge — collect payment with Retry payment as before.
* Change: Removed the Reports tab (its figures now live on the Dashboard).

= 1.8.2 =
* Change: Failed-payment recovery now shows on the Dashboard as simple cards (Recovered payments, Outstanding, Recovery rate), alongside the other headline stats. Removed the separate windowed section from the Reports page.

= 1.8.1 =
* New: Failed-payment recovery stats on the Reports page — money recovered vs still outstanding, recovery rate and payment counts, across This week / This month / This year / All time.
* Renewal reminders: relabelled the send-time field, made the lead-time options square checkboxes, defaulted everything to off, and the lead-time options now grey out until reminders are switched on.

= 1.8.0 =
* New: Renewal reminder emails. Turn on automatic reminders before a subscription renews, choose one or more lead times (24h up to 7 days before), and set the send time of day. Reminders use the editable "Your subscription renews soon" template and are sent to customers only. Configure under Notifications.

= 1.7.4 =
* New: The Stripe webhook is now created automatically when you save your live keys on the Settings page — no need to click "Create webhook" separately. If it can't be created automatically, your keys still save and a notice points you to the manual button. (The setup wizard already created it for you; this covers the Settings path too.)

= 1.7.3 =
* Change: New installs no longer create demo/sample data (demo customer, subscription, invoice and sample plan). Sites start empty.
* New: The Customers page now shows a "key" explaining each customer action (Pause, Cancel, Retry, etc.) with a "?" you can hover or tap for a plain-English description — so you can see what each action does without a demo record.

= 1.7.2 =
* New: When a Settings status card needs action (orange), it now shows a "Set this up" link that jumps straight to the relevant section.

= 1.7.1 =
* New: The Customers list now shows subscription action buttons (Pause, Cancel, Retry, etc.) inline for each subscription, stacked per customer — no need to open each customer first.
* New: The four status cards on Settings now show a green background when complete and orange when action is needed (e.g. SMS not set up).
* Change: SMS provider default label simplified to "None".
* Tidy: Removed remaining test/staging wording now that the plugin is live-only.

= 1.7.0 =
* Major change: Test mode has been removed. Simple Subscriptions now operates in Live mode only. The setup wizard asks for your live Stripe keys, and the mode toggle has been removed from settings. Every subscription created is a real charge. A clear "LIVE MODE" notice is shown on the plugin's screens.
* The setup wizard's Stripe step now asks directly for your live publishable and secret keys, with a link straight to your Stripe API keys page.

= 1.6.5 =
* Fix: "Authenticate with Stripe" no longer causes a critical error. The Stripe Connect authorize page (connect.stripe.com) was being blocked by a redirect helper meant only for checkout/billing pages; it now redirects correctly.
* Fix: The setup wizard now pre-selects Live mode by default (matching the recommendation), instead of defaulting to Test.

= 1.6.4 =
* Fix: "Authenticate with Stripe" in the setup wizard no longer shows "Sorry, you are not allowed to do that." The wizard now uses the same secure link as the settings page.
* Change: The setup wizard now recommends starting in Live mode (for those who just want to get started), with Test mode offered as the try-first alternative.
* New: Simple Subscriptions admin screens are now kept clean of unrelated third-party notices and upsells from other plugins. Only Simple Subscriptions' own notices show on its pages; every other admin page is left untouched.

= 1.6.3 =
* Fix: The "Delete all data on uninstall" checkbox (and other settings after the Stripe section) now saves correctly. A nested form for the Stripe connect/disconnect buttons was closing the settings form early, orphaning the fields below it. The buttons are now links, so the settings form stays intact.
* Change: Removed the "Recent tokenised demo portals" section from Tools.

= 1.6.2 =
* Fix: "Disconnect from Stripe" now reliably shows as disconnected. The connected badge is driven by the saved connection status only, so disconnect always takes effect.
* Fix: Uninstall cleanup now also removes OAuth refresh tokens and the new capacity-alert trackers when "Delete all data on uninstall" is enabled.
* New: Tools now has a "Reset connection (for testing)" button that clears all Stripe keys, connected status, OAuth tokens and licensing state WITHOUT touching subscribers, invoices, plans or customers — giving a clean slate to re-test the connect flow.

= 1.6.1 =
* Improve: "Authenticate with Stripe" is now the primary option in BOTH the setup wizard and the settings page. Manual key entry still works but is tucked into a collapsible "Enter keys manually instead" section.
* Improve: The wizard's Stripe step shows a connected badge and lets you continue once your account is authenticated.

= 1.6.0 =
* New: "Authenticate with Stripe" — connect your Stripe account in one click instead of copying publishable and secret keys. Uses secure OAuth brokered by simple-subscriptions.com; your account stays entirely your own and payments go directly to you. Manual key entry is still available.
* New: Per-mode connected status with a one-click Disconnect. Test and live are authenticated separately.

= 1.5.0 =
* Security: The demo checkout and demo portal tools are now completely disabled in live mode — hidden from the menu and refused if reached directly — so a demo can never run against your live Stripe account. Preview your real checkout via your product page instead.
* Improve: Subscriber-limit warning emails (and the first-subscriber congratulations email) now arrive immediately when a customer subscribes, rather than waiting for the next daily sync.
* Improve: Capacity warnings are strictly live-only; a test or demo signup never triggers a limit warning.

= 1.4.9 =
* New: A one-time congratulations email is sent when your first LIVE subscriber signs up (test and demo signups never trigger it).
* New: When a customer is turned away at checkout because you are at your subscriber limit, you now receive an upgrade-prompt email (throttled to at most once per hour).
* Improve: The capacity banner now appears from the halfway point on the free plan (5 of 10) and states clearly that new signups stop at the limit, so you always have warning before customers are blocked.
* Improve: The message shown to a would-be customer when a site is at capacity no longer mentions any limit. It shows a neutral "technical issue" notice and the seller's own support email (and phone, if set) so the customer can get help.

= 1.4.8 =
* Hub heartbeats now report LIVE customers and LIVE revenue only. Test, demo and staging signups never leave the site, so the hub's Subscriber Management screen only ever shows real customers. The heartbeat also reports the site's current mode so the hub can display staging status.

= 1.4.7 =
* Restored the shared ssubs_stripe_api_request() helper that the Simple Subscriptions Hub (master) plugin depends on for capacity billing. It was lost in an earlier rebuild, causing "Call to undefined function" on hub cancel/upgrade actions when this plugin runs on the hub site. Includes Stripe-safe boolean encoding and idempotency key support.

= 1.4.6 =
* When the hub reports a missing Stripe subscription during a capacity change (typically a leftover test/sandbox purchase), the Account & Upgrade page now explains the cause and the recovery steps instead of showing only the raw error.

= 1.4.5 =
* Fixed the critical error when clicking Update capacity: all Account & Upgrade actions (upgrade, change capacity, cancel, refresh) are now wrapped in error guards, so any unexpected failure — including hub-side errors — shows a readable notice on the account page instead of a crash. Attempting a capacity action in staging mode now also returns a friendly notice rather than a dead-end screen.
* Product pages are now polished for mobile and tablet: full-width thumb-friendly subscribe button, stacked customer fields with 16px inputs (no iOS zoom), tidy square gallery grids, comfortable pricing-option and add-on tap targets, scaled typography, and small-phone refinements. Applies across all themes.
* The Simple Subscriptions admin menu now stays expanded on every plugin screen, including plan editor, plan list and hidden detail pages.
* Admin styles and scripts now load on all plugin screens, including the Plans list table.

= 1.4.4 =
* Mode banners are no longer shown inside the setup wizard, and the staging banner now uses a light amber style with dark, readable text.
* Fixed Back and Skip buttons appearing on every wizard step (WordPress button styles were overriding the hidden attribute); business name and email can no longer be skipped.
* Added a direct link to the Stripe API keys dashboard page on the wizard's Stripe step, switching between test and live automatically.
* Currency selection now defaults to British Pound (GBP).
* SMS setup: removed the "Skip for now" radio option (the Skip button handles skipping), added a Save button directly after the password field that verifies the BulkSMS or Twilio credentials with the provider, and blocked progressing until credentials verify or the step is skipped. The optional test-message box appears beneath once verified.
* Theme Gallery previews now display demo imagery for every theme instead of empty placeholders, and the preview's top navigation shows your site name and your site's assigned menu.
* Fixed the Plan title field overlapping the Billing type column in the plan editor's Pricing Options section.
* The Account & Upgrade capacity purchase area is disabled in staging/test mode (with a clear explanation) and enforced server-side; upgrades are live-mode only.

= 1.4.3 =
* Bundled the Stripe PHP SDK in the plugin package, removing the "production package containing vendor/autoload.php" warnings.
* Rebuilt the setup wizard as a guided step-by-step flow with a progress bar: business name, customer service email, optional telephone and address, currency, optional SMS, mode choice, then Stripe.
* SMS setup now defaults to BulkSMS and shows only the three fields needed for the chosen provider (BulkSMS or Twilio), with a live "Send test message" button.
* The wizard's Stripe step verifies both the connection and the webhook for the chosen mode; live mode is only enabled once both live checks pass.
* Added a prominent LIVE MODE warning banner across all Simple Subscriptions admin screens while live payments are active.
* Simplified the first-run agreement screen to a brief terms, privacy and operational-data paragraph.

= 1.4.2 =
* Replaced the consent card inside the setup wizard with a dedicated first-run agreement screen shown immediately after activation.
* Until a decision is made, WordPress administration redirects to the focused agreement screen, which offers only “Agree and continue” or “Deactivate and delete plugin”.
* Moved all business, Stripe, display and SMS configuration to the setup wizard shown after acceptance.
* Restricted the missing Stripe SDK warning to Stripe configuration areas instead of displaying it throughout Simple Subscriptions.
* Made the decline option perform a clean uninstall, removing activation-created tables, roles and helper pages before deleting the plugin files.

= 1.4.1 =
* Changed legal acceptance to a one-time installation decision. Routine plugin or terms updates no longer invalidate an existing acceptance or disable checkout, webhooks, portals, retries or subscription management.
* Preserved the first acceptance timestamp, accepting administrator, terms URL and legal version as an audit record instead of overwriting them whenever setup is saved.
* Updated the setup wizard to show the original acceptance details without presenting or requiring the checkbox again.

= 1.4.0 =
* Added a mandatory, unticked legal agreement in the setup wizard. The plugin remains locked until an administrator positively agrees to the Terms and Conditions and privacy information.
* Deferred hub registration, licence checks and heartbeats until legal agreement has been recorded.
* Added prominent disclosure of the data sent to simple-subscriptions.com and retained the commercial subscriber-capacity licensing model.
* Updated product metadata, author details, tested WordPress version and release documentation.
* Improved output escaping, request validation, SQL preparation and translation placeholder handling throughout the plugin.
* Removed development-only documentation from the production package.

= 0.5.9 =
* Fixed theme backgrounds and header colours not applying on the standalone signup page (CSS variables were read on ancestor elements where they were undefined).
* Fixed unreadable checkout text caused by a CSS variable cycle, and hardened checkout headings, labels and inputs against site-theme style conflicts.
* Improved input placeholder and test-card hint contrast on dark themes.

= 0.5.8 =
* Gave every signup theme (Blank, Tech, Fashion, Beauty, Calm, Sea, Elegant, Futuristic) a distinct, polished identity: the standalone landing now uses each theme's own background wash, header, title typography, accent button, cards and FAQ instead of a single hardcoded palette.
* Fixed the subscribe button and product-page accents ignoring the selected theme, and improved contrast/navigation legibility on the dark Tech and Futuristic themes.
* Redesigned the live and demo checkout with a modern two-column order-summary layout, themed inputs with focus states, a secure-payment reassurance row, a clearer demo/test-mode badge and a Stripe test-card hint.
* Themed the demo confirmation screen to match the chosen palette and removed a dead theme CSS rule.

= 0.5.7 =
* Rebuilt the single subscription plan experience as a premium standalone product landing page, with a clean plugin-owned header, conversion-focused hero section, improved demo product visual, trust row, benefits section and polished FAQ area.
* Removed reliance on the active WordPress theme's blog/post chrome for subscription plan pages.
* Improved the Blank theme so it behaves as a beautiful universal default rather than an empty placeholder.

= 0.5.6 =
* Fixed the blank plan preview caused by over-aggressive block-theme CSS hiding the content wrapper.
* Added a plugin-owned single subscription plan template so plan pages render without the active theme's default post title/meta area.
* Kept the no-fake-gallery behaviour when only one product image is present.

= 0.5.5 =
* More aggressively removed the active WordPress theme's default single-post title/meta/header area on subscription plan pages, including the dangling “Written by in” text left by block themes.
* Pulled the subscription product card upwards by collapsing leftover block-theme spacing above plan content.
* Stopped showing demo/gallery colour swatches when a product only has one image or no real gallery images.

= 0.5.4 =
* Tidied subscription plan title placement by hiding the active theme's default post title/meta on plan pages and rendering the plan title inside the subscription layout.
* Removed random post-author/meta text from plan previews.
* Fixed Setup Wizard theme option toggling so selected theme buttons update visibly when clicked.

= 0.5.3 =
* Restored the Product Description field in the plan editor.
* Improved Blank theme admin previews with polished demo copy, a demo product image illustration, demo gallery thumbnails and demo pricing when a plan has no content yet.
* Kept real public product pages clean: demo content only appears for admin previews.

= 0.5.2 =
* Made the Theme Gallery interactive: selecting a theme now updates the live preview, selected card state and Apply button immediately.
* Fixed Preview with a plan so it opens the most recently edited subscription plan in a new tab instead of the Plans list.
* Added temporary theme preview support with the ssubs_preview_theme URL parameter for admins/editors, so different themes can be previewed on a real plan before applying them.
* Enqueued admin JavaScript on Simple Subscriptions admin pages with cache-busting so Theme Gallery interactions load reliably.

= 0.5.1 =
* Fixed plan creation/editing page after adding the Product Gallery meta box by restoring the missing gallery render callback.

= 0.5.0 =
* Added a Theme Gallery admin page with Blank, Tech, Fashion, Beauty, Calm, Sea, Elegant and Futuristic product page themes.
* Added Theme Gallery to the Simple Subscriptions menu and setup wizard.
* Added product-gallery image support for plans so themes can use a main uploaded product photo plus a thumbnail gallery.
* Added real frontend styling for all product page themes, with special polish for the Blank theme as the flexible default.

= 0.4.2 =
* Fixed Create plan links so they explicitly open the Simple Subscriptions plan post type.
* Disabled the block/page editor for subscription plans so adding a plan opens a plan-focused product builder with the pricing, add-ons, product details and FAQ boxes.
* Improved test-mode warning contrast and made hero ghost buttons readable on the blue gradient background.

= 0.4.1 =
* Fixed the internal SSUBS_VERSION constant so WordPress actually cache-busts the refreshed admin CSS.
* Added filemtime-based admin CSS versioning so future admin UI changes are not hidden by browser or WordPress cache.
* Strengthened the admin visual refresh with a more obvious background, sticky navigation surface and richer cards.

= 0.4.0 =
* Full admin UX refresh across the plugin, including improved visual hierarchy, cross-screen navigation, calmer page headers, better table styling, clearer settings summaries and more polished forms, cards and action areas.

= 0.3.17 =
* Reworked admin notice rendering so setup wizard warnings use self-contained high-contrast markup instead of relying on stylesheet specificity or cache behaviour.

= 0.3.16 =
* Corrected the setup wizard notice CSS selector so notices shown after the hero banner use readable high-contrast colours when warning about missing live Stripe keys.

= 0.3.15 =
* Fixed setup wizard hero notice contrast where the dark hero styling was overriding admin notice text colour.

= 0.3.14 =
* Improved admin notice styling in the setup wizard and settings pages so error, success and info messages always have strong colour contrast and remain easy to read.

= 0.3.13 =
* Prevented live mode from being enabled until both live Stripe keys are saved and the live connection check has passed.
* Reset saved Stripe connection status whenever publishable or secret keys are changed, so old successful checks cannot validate new keys.

= 0.3.12 =
* Added a proper demo checkout confirmation page after Stripe payment.
* Demo sign-ups now trigger customer welcome and admin new sign-up notification emails after successful Stripe checkout.
* Demo notification sends are recorded in the audit log and protected from duplicate sends on refresh.

= 0.3.10 =
* Added a direct-render fallback for the demo checkout and demo portal so the Tools buttons work even when a theme/page builder leaves shortcodes visible as plain text.
* Registered demo shortcodes defensively during construction and on init, and added a content filter fallback for raw demo shortcodes.

= 0.3.9 =
* Tidied Notifications into separate Email and Text Message sections with rounded collapsible cards.
* Made the demo checkout form post through admin-post.php again while keeping frontend compatibility, so Stripe Checkout launches more reliably from staging/demo pages.

= 0.3.8 =
* Fixed plan editor conditional fields so limited subscriptions now show a Total renewals number box immediately when selected.
* Renamed the pricing repeater button to Add additional subscription option.
* Fixed one-off add-ons so recurring interval options hide immediately when One-off add-on is selected.
* Removed the duplicate Product Description field from the lower Product Details box and now prefers the main WordPress editor content near the product title.
* Improved demo checkout form handling so staging demo signups post through the frontend page before redirecting to Stripe Checkout.

= 0.3.6 =
* Added daily, weekly, bi-weekly and bi-monthly recurring subscription intervals.
* Improved staging/test-mode banner contrast and added a clear move-to-live link on plugin screens.
* Added a fuller setup wizard with business details, mode choice, Stripe keys and optional Twilio/BulkSMS setup.
* Added built-in Twilio and BulkSMS SMS sending for template and manual SMS messages.
* Synced early/manual advance renewal payments back to Stripe by moving the Stripe-side next billing point after the charge.
* Added broader admin UI readability and visual polish across plugin screens.



= 0.3.4 =
* Fixed direct access to hidden Growth/Operations pages (vouchers, notifications, on-hold retries, audit log and staff roles) by registering them as hidden admin pages rather than removed submenu pages.
* Added a manage_options capability fallback for Simple Subscriptions permissions so site administrators are not locked out on upgraded installs.

= 0.3.3 =
* Fix missing datetime formatter that could fatal the Subscriptions table after renewal-date edits.
* Register admin detail screens with a manage_options fallback so site administrators can access vouchers, notifications, on-hold retries, audit log and staff roles after updates.
* Improve Stripe renewal-date sync messaging and store the Stripe-reported next billing point locally when available.

= 0.2.7 =
* Added tokenised demo portal records after successful demo Stripe Checkout.
* Demo portal now has working test actions for updating payment method via Stripe Checkout setup mode, moving the demo renewal date locally, and cancelling the Stripe test subscription at period end.
* Demo checkout success state now links directly to the matching demo customer portal.

= 0.2.4 =
* Fixed external Stripe hosted-page redirects so demo and customer flows no longer fall back to wp-admin.
* Condensed the admin menu into Dashboard, Subscriptions, Customers, Marketing, Operations, Reports, Demo Tools and Settings.

= 0.2.3 =
* Added demo checkout and demo portal shortcodes/pages, plus Demo Tools admin screen.

= 0.2.2 =
* Added subscription lifecycle service for shared admin/customer actions.
* Added live customer portal actions for cancel-at-period-end, payment-method update via Stripe Billing Portal, and guarded renewal-date requests.
* Added voucher-to-Stripe Coupon/Promotion Code sync and applies entered vouchers to Stripe Checkout.
* Added webhook-driven customer account creation, voucher redemption increments, notifications and cleaner invoice status handling.
* Added custom retry queue attempts for on-hold subscriptions.
* Added WordPress privacy export/erasure hooks for customer records.

= 0.2.1 =
* Moved customer fields from product pages to a standalone checkout page.
* Stripe Checkout no longer requires a packaged Composer vendor folder for the MVP flow.
* Product/add-on edits no longer call Stripe during post save.

= 0.2.0 =
* Added spec catch-up admin modules: dashboard, subscriptions, customers, on-hold retries, vouchers, notifications, reports, audit log, staff roles and setup wizard.
* Added Stripe Checkout starter flow from plan pages with pricing options, add-ons, voucher field and physical-product shipping collection.
* Added customer portal shortcode rendering and dynamic companion block/shortcode scaffolds.
* Added setup wizard theme choices: Minimal, Card/Grid and Classic.
* Added webhook processing for Checkout completion, subscription updates/deletions and invoice success/failure events.
* Added local voucher CRUD and notification template editing/preview screens.

= 0.1.8 =
* Added clearer Stripe key cleanup and invalid saved key handling.
* Added clear saved secret/webhook actions for test and live modes.
* Normalized pasted Stripe keys to avoid whitespace/zero-width copy-paste issues.

= 0.1.7 =
* Hardened Stripe key handling so browser password managers or stray WordPress config values cannot be saved/used as Stripe API keys.
* Added Stripe key format validation for test/live publishable keys, secret keys and webhook signing secrets.

= 0.1.6 =
* Added subscription length controls to pricing options: perpetual or limited renewals.
* Limited plans can store a custom number of renewal payments.
* Product previews now show whether a subscription renews until cancelled or stops after the configured number of renewals.
* Improved add-on UI so recurring interval and cancellable-add-on controls only show for recurring add-ons.

= 0.1.5 =
* Replaced the normal Stripe Connect/platform setup with a simpler direct Stripe setup.
* Settings now ask for only test/live publishable and secret keys in the main flow.
* Added Check Stripe Connection buttons for test and live mode.
* Added automatic webhook endpoint creation, storing the returned webhook signing secret privately.
* Added a minimal Stripe webhook REST endpoint at /wp-json/ssubs/v1/webhooks/stripe.
* Moved webhook signing secret entry to an advanced manual fallback.

= 0.1.3 =
* Pricing UI now accepts normal currency amounts like 24.99 and converts to Stripe minor units internally.
* Plan edit screen now has inline add-ons, including recurring and one-off add-ons, unlimited per plan.
* Product pages can be created and previewed before Stripe is connected; checkout remains disabled until payment setup is complete.
* Added Stripe Connect buttons and OAuth callback handling for test/staging and live accounts.

= 0.1.0 =
* Initial scaffold: activation/deactivation, database schema, roles and capabilities, encrypted credential storage, Plan and Extra custom post types with meta boxes, settings screen with a store-configuration guard on publishing plans.

= 0.2.9 =
* Removed customer-facing renewal-date-change controls from live, impersonated and demo portals.
* Added customer-facing reactivation for cancelled or pending-cancel subscriptions while keeping the stored renewal date unchanged.

= 0.2.8 =
* Added admin subscription impersonation links for test/live customer portal viewing.
* Improved HTML email templates with plan, amount, renewal date, status and customer details.
* Added notification defaults reset action.
* Polished admin and frontend UI styles.

= 0.3.1 =
* Removed the Stripe Setup Wizard block from Settings.
* Made Dashboard the top-level landing page for the plugin menu.
* Removed the duplicate Reports menu and folded reporting into Dashboard.
* Added dashboard charts for subscribers, revenue, cancellations and status breakdown.
* Removed grace days from on-hold retry management.
