I think you’re on the right track here, but you'll need one helper object that you use as a page parameter for your wizard pages, with also a ModuleType enum attribute to keep track of where you are.
The 40 modules that can be checked are in a separate (persistable) entity with the same enumeration as the helper object. You could also give them a sorting integer attribute. Then you can have one next and one previous button microflow. You retrieve the current module, split on current ModuleType, get the first Module that is chosen and has a higher (next) or lower (previous) sorting number, change the helper object ModuleType to target type and show the corresponding wizard page.
You can also create one snippet for the wizard steps using a layout grid with Auto-fill columns and dynamic classes on the columns. To hide steps you can add a dynamic class that sets display none, based on booleans in your helper object kept in sync for each module that is selected/needed. Then a dynamic class could be something like: if $currentObject/ShowMortgageStep then if $currentObject/CurrentModuleType = MyModule.Enum_ModuleType.MortageValue then 'wizard-step-active' else '' else 'display-none-class'
It can easily get out of hand, especially when you’re adding subflows to validate stuff, but this would be my approach: a helper object, an enum, a snippet for the steps and dynamic classes.