How to bring specific post to front of wordpress loop?

The 'the_posts' filter hook allows you to edit posts that are going to be displayed in a loop.

It’s fired for all queries (the main and the secondaries) so you need to check that the query you’re acting on is the right one.

That said in your case you can:

  1. send a query variable to individuate the selected post
  2. use 'the_posts' filter to move selected post on beginning of post array

1. Send a query variable to individuate the selected post

Post thumbnails should be printed using something like this:

<a href="https://wordpress.stackexchange.com/questions/174491/<?php esc_url( add_query_arg( array("psel' => get_the_ID() ) ) ) ?>">
  <?php the_thumbnail() ?>
</a>

add_query_arg() add a query variable to current url, it means that if you are on the page that has the url example.com/some/path/page/5 by clicking on the post thumbnail for the post with ID 44 you are sent to the url example.com/some/path/page/5?psel=44.

Once the url is the same posts that are shown will be the same, but thanks to the psel url variable you can reorder posts to have the selected post on beginning of posts array.

2. Use 'the_posts' filter to move selected post on beginning of post array

Once you have the selected post id in a url variable, to put related post object on top of posts array is just a matter of a couple of PHP functions

function get_selected_post_index() {
  $selID = filter_input(INPUT_GET, 'psel', FILTER_SANITIZE_NUMBER_INT);
  if ($selID) {
    global $wp_query;
    return array_search($selID, wp_list_pluck($wp_query->posts, 'ID'), true);
  }
  return false;
}

add_filter('the_posts', function($posts, $wp_query) {

  // nothing to do if not main query or there're no posts or no post is selected
  if ($wp_query->is_main_query() && ! empty($posts) && ($i = get_selected_post_index())) {
      $sel = $posts[$i]; // get selected post object
      unset($posts[$i]); // remove it from posts array
      array_unshift($posts, $sel); // put selected post to the beginning of the array
  }

  return $posts;

}, 99, 2);

Previous code will assure that posts are ordered like you want.

The get_selected_post_index() function can be also used inside your templates to know if there is a selected post or not (and modify your template accordingly), because it returns false when no post is selected (or if a wrong Id is sent via psel url variable).