I'm wondering why pygame is somehow rendering half of the text beneath the Rect objects. My end goal is to place the texts on top of the Rects, the color is not going to remain red, it's just there for debugging (It's white originally). I couldn't solve it on my own so I'm seeking help.
here is the current screen:

the code for drawing the line and rect objects:
def draw(self, height, width):
self._screen.fill((255,255,255))
square_size = self.SCREEN_SIZE/9
#draw lines
for i in range(self.rows+1):
thick = 4 if i % 3 == 0 else 1
offset = i * square_size
pygame.draw.line(self._screen, self.BLACK, (0, offset), (width, offset), width=thick)
pygame.draw.line(self._screen, self.BLACK, (offset, 0), (offset, height), width=thick)
for i in range(self.rows):
for j in range(self.cols):
self._board.init_square(motherboard[i][j], i, j)
pygame.draw.rect(self._screen, (250,0,0), (i*square_size+3, j*square_size+3, square_size-4, square_size-4))
# if self._board.board[i][j].value != 0:
self.display_numbers(self._board.board[i][j].value, ((j*square_size), (i*square_size)+20))
and the display_numbers() function:
def display_numbers(self, value, position):
# print(position)
f_img = self._font.render(str(value), True, (0, 0, 0))
self._screen.blit(f_img, position)
# print(f"took {time.time()-t0} seconds to create font")