Use of rewind_posts() cause pagination to break

The issue has nothing to do with rewind_posts(). The reason the same posts are showing up on page 2 is because your template is only ever going to show the 10 latest posts. This is because you’re using your own secondary query to display posts:

$args = [
   'posts_per_page' => 10
];

$q = new WP_Query($args);

That’s the query your template is displaying, and there’s nothing there telling it to query a second page of posts when you’re on page 2.

The problem is that in home.php you should not be using new WP_Query() to query posts for the loop. WordPress has already queried the correct posts for you, and you display them with The Loop.

The reason the solution you’ve copied uses it is because the original question it was answering was apparently regarding displaying those posts on a static homepage template that had not already queried the correct posts, and pagination isn’t required.

Also, the reason the original answer uses rewind_posts() is because it seems to be for displaying different groups of posts out of order. That’s not what you want. All you want to do is display the first post separately, and then the rest of the posts, without re-displaying the first one.

Given all that, the proper solution is to use this structure:

global $wp_query;

while ( have_posts() ) {
    the_post();

    // If we're on the first post.
    if ( 0 === $wp_query->current_post ) {
        // Display post as banner.
        break;
    }
}

// Display separator, open grid, etc.
while ( have_posts() ) {
    the_post();
    // Display post as card.
}

understrap_pagination();