* fix(course): coerce metadata.discount to number before save Normalize string discount values from the landing page pricing form and coerce legacy string metadata on ZCourseUpdate validation so course settings saves do not fail with a Zod type error. Fixes classroomio/classroomio#828 Co-authored-by: Rotimi Best <rotimi-best@users.noreply.github.com> * refactor(utils): add shared toFiniteNumber for metadata discount coercion Co-authored-by: Rotimi Best <rotimi-best@users.noreply.github.com> * fix(utils): only coerce string discount values in metadata preprocess Reject broad Number() coercion on booleans and arrays. String and finite number discounts are normalized; invalid types are left for Zod to reject. Addresses Greptile review on #830 Co-authored-by: Rotimi Best <rotimi-best@users.noreply.github.com> * refactor(dashboard): use writable $derived in pricing form again Keep toFiniteNumber coercion in setter effect; derived fields stay in sync when course loads or updates (Svelte 5 writable derived). Co-authored-by: Rotimi Best <rotimi-best@users.noreply.github.com> * fix(utils): reject invalid metadata.discount instead of clearing it Only coerce numeric strings in preprocess; leave invalid strings, non-finite numbers, and other types for Zod to reject. Co-authored-by: Rotimi Best <rotimi-best@users.noreply.github.com> --------- Co-authored-by: Cursor Agent <cursoragent@cursor.com> Co-authored-by: Rotimi Best <rotimi-best@users.noreply.github.com>