feat(emails): trial-aware downgrade email and member warnings before a downgrade (#2924) master
* fix(emails): tell trial users their trial ended when downgraded to free The plan-downgraded email told workspaces whose trial ran out (or was cancelled) that their "subscription ended" and asked them to re-subscribe. It now reads the downgrade reason and speaks about the trial, with an Upgrade CTA instead. * feat(emails): warn workspace members before a downgrade removes them Non-owner members are removed when a workspace drops to free, but only owners were warned beforehand. Members now get a heads-up 3 days before a cancelled plan ends (cancelled again if the owner resumes), and when a trial is about to end without a payment method. * fix(emails): only call a downgrade a trial when no card converted it A subscription cancelled within the hour after trial_end was always treated as a trial, so a customer who converted and then cancelled read "You cancelled your trial". Trial-ending member warnings now always send right away, and very large workspaces skip scheduling so the reminder ids never overflow Stripe's metadata limit. * fix(emails): keep member warning chunks stable across webhook retries Recipients are sorted before chunking, so a Stripe redelivery reuses each idempotency key for the same members instead of skipping a different group. The webhook test now tells owner and member reminder ids apart.