0ea3469899
The Policies tab gets the redesign Grant asked for: replace the table view + verbose disclosure form with a card grid where each existing policy renders as a buy-page-style tier card sitting next to a dashed "+ Add tier" placeholder. Click the placeholder, it morphs into an editable draft tier card with inline form fields; submit Create on the card and it flips into a read-only preview. Multiple drafts can coexist for parallel multi-tier authoring with side-by-side comparison. New JS helpers: - helpIcon(text) — small "?" hover tooltip for compact form labels - slugify(s) — URL-safe slug derivation from display name - renderTierCard(pol, product, onMutate) — read-only buy-page-style preview card with Edit / Hide-Show / Delete actions - renderAddTierCard(onClick) — dashed placeholder with "+" affordance - renderDraftTierCard(product, onCommit, onCancel) — inline editable card with name + slug + price + duration + entitlement bubble picker + recurring/trial toggles - renderPolicyCardGrid(product, policies, byPolicyCounts, onMutate) — ties them together. Submitting "+ Add tier" appends a fresh placeholder, so operators can keep clicking to author multiple tiers in one session. formInput() upgraded: - New `help:` option renders a helpIcon next to the label (replaces verbose hint text under the input) - New `placeholder:` option for cleaner empty-state cues Auto-slug: - Product create form's Display name field mirrors a slugified version into the Slug field as the operator types — until they manually edit the slug, which arms a "userOverridden" guard so manual edits stick. Re-arms when the slug field is cleared. Legacy "Create a new policy" disclosure form unsurfaced from the Policies route — the card grid replaces it. Advanced fields (custom grace seconds, tip recipient, tier rank) still live on the existing Edit modal of an already-committed tier card. Power-user flow: card grid creates the basics, Edit modal refines. Test count unchanged (78). UI-only release.