why is kses removing semicolon from inline style?

There are no signs that this was accidental or a bug, and has been in core for many years. This is because of this set of lines at the end of the main loop of safecss_filter_attr:

            // Only add the CSS part if it passes the regex check.
            if ( $allow_css ) {
                if ( '' !== $css ) {
                    $css .= ';';
                }

                $css .= $css_item;
            }

The root of the question is a broken assumption that wp_kses modifies the original HTML string, which is not the case.

Instead, wp_kses uses regular expressions to break apart your HTML into arrays which are then further subdivided by more regular expressions. It’s these arrays that are then going to be processed to remove attributes and tags etc. Then these are reassembled to create a brand new HTML string.