You might use OnObjectEnter script triggers to control access to the fields. The trigger's script can use go to field, go to object or go to next field to kick the user out of a field to which they are not permitted access. Back up the triggers with validation rules that prohibit modification when the category selected does not permit it.
As an example, this validation calculation:
category = "Product"
will prohibit modification of the field is category = "Service" (or any other value except "Product")
It's probably overkill, but you could also split your table into three tables linked in a one to one relationship. Fields in Table 1 can always be edited. Fields in Table 2 can only be edited for products, those in table 3 can only be dited for services. Settings in Manage | Security whould use a lock expression based on the category field to control access to records in tables 2 and 3 on a record by record basis.
Many thanks for these ideas. They seem very logical and should indeed solve my problem. I hadn't even considered them before. Perhaps I just need to think a little more laterally in the future. I'll give these a try and let you know how I get on.