The trouble is that save_post
fires in lots of places other than the “edit post” screen – when it does, your code will think the checkbox is unchecked and overwrite your saved state.
Add an additional hidden input to your meta box:
<?php
// Don't global post, use the $post parameter already passed to the function
// global $post;
// Avoid undefined index errors by passing the third argument "single" true
// The double !! will cast the value to a boolean true/false
$show_author = !! get_post_meta( $post->ID, 'show_author', true );
?>
<input type="checkbox" name="show_author" <?php checked( $show_author ) /* WordPress helper function */ ?> style="margin-left:15px" /> Check the box to display the author's byline and author box.
<input type="hidden" name="do_show_author" value="1" />
And then check that it exists before saving your checkbox state:
function save_details( $post_ID ) {
if ( isset( $_POST['do_show_author'] ) ) {
// Use isset - unchecked checkboxes won't send a value to $_POST, you'll get an undefined index error
update_post_meta( $post_ID, 'show_author', isset( $_POST['show_author'] ) ? '1' : '0' );
}
}