The web browser ecosystem makes this a pretty hard task, unfortunately. You need fallbacks that weaken the process to the point where it is basically useless in a lot of cases. But the goal of a client/server split in the KDF is actually quite sensible. The client side does the large amount of work to protect users from dictionary attacks. The server side does a relatively much smaller amount of work to protect itself from being easily exploited if its hashes are exfiltrated when the hashes aren't themselves vulnerable to dictionary attacks.