ERC721 burn functionality

This is my NFT contract
My question is about burn function, I am calling _burn function which is actually defined in ERC721 and transferring the token to address(0).
Now, I tried to decipher the linearization and hooks but still couldnt understand how the _beforeTokenTransfer in ERC721Enumerable is being called when i calling burn function of this contract.
Any relevant articles explaining this will also do.

contract FansNFT is
    Context,
    AccessControlEnumerable,
    ERC2981,
    ERC721Enumerable,
    ERC721Pausable,
    ERC721URIStorage
{
    using Counters for Counters.Counter;

    bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE");
    bytes32 public constant PAUSER_ROLE = keccak256("PAUSER_ROLE");

    // Counters.Counter private _tokenIdTracker;

    string private _baseTokenURI;
    uint96 public royaltyValue = 500; //Makes it at 3% as feeDenominator in ERC2981 defaults 
                                    //to 10000 so fees are expressed in basis points,

    /**
     * @dev Grants `DEFAULT_ADMIN_ROLE`, `MINTER_ROLE` and `PAUSER_ROLE` to the
     * account that deploys the contract.
     *
     * Token URIs will be autogenerated based on `baseURI` and their token IDs.
     * See {ERC721-tokenURI}.
     */
    constructor() ERC721("ama.fans", "AMAF") {
        _setupRole(DEFAULT_ADMIN_ROLE, _msgSender());
        super._setRoleAdmin(MINTER_ROLE, DEFAULT_ADMIN_ROLE);
        super._setRoleAdmin(PAUSER_ROLE, DEFAULT_ADMIN_ROLE);
        _setupRole(MINTER_ROLE, _msgSender());
        _setupRole(PAUSER_ROLE, _msgSender());

    }

    function _baseURI() internal view  override returns (string memory) {
        return _baseTokenURI;
    }


    function setRoyaltyValue(uint96 _royaltyValue) 
        external 
        onlyRole(DEFAULT_ADMIN_ROLE){
            royaltyValue = _royaltyValue;
        }

    /**
     * @dev Creates a new token for `to`. Its token ID will be automatically
     * assigned (and available on the emitted {IERC721-Transfer} event), and the token
     * URI autogenerated based on the base URI passed at construction.
     *
     * See {ERC721-_mint}.
     *
     * Requirements:
     *
     * - the caller must have the `MINTER_ROLE`.
     */
    function mint(address to, string memory _tokenURI) 
            public  
            whenNotPaused() 
            returns(uint256) {
        require(hasRole(MINTER_ROLE, _msgSender()), "ERC721PresetMinterPauserAutoId: must have minter role to mint");
        
        // _tokenIdTracker.increment();
        // uint256 newNftTokenId = _tokenIdTracker.current();

        // We cannot just use balanceOf to create the new tokenId because tokens
        // can be burned (destroyed), so we need a separate counter.
        _safeMint(to, totalSupply());
        _setTokenURI(totalSupply(), _tokenURI);
        _setTokenRoyalty(totalSupply(), to, royaltyValue);

        return totalSupply();
    }

    /**
     * @dev Pauses all token transfers.
     *
     * See {ERC721Pausable} and {Pausable-_pause}.
     *
     * Requirements:
     *
     * - the caller must have the `PAUSER_ROLE`.
     */
    function pause() public virtual {
        require(hasRole(PAUSER_ROLE, _msgSender()), "ERC721PresetMinterPauserAutoId: must have pauser role to pause");
        _pause();
    }

    /**
     * @dev Unpauses all token transfers.
     *
     * See {ERC721Pausable} and {Pausable-_unpause}.
     *
     * Requirements:
     *
     * - the caller must have the `PAUSER_ROLE`.
     */
    function unpause() public virtual {
        require(hasRole(PAUSER_ROLE, _msgSender()), "ERC721PresetMinterPauserAutoId: must have pauser role to unpause");
        _unpause();
    }

    function _beforeTokenTransfer(
        address from,
        address to,
        uint256 tokenId
    ) internal  override(ERC721, ERC721Enumerable, ERC721Pausable) {
        super._beforeTokenTransfer(from, to, tokenId);
    }

    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId)
        public
        view
        override(AccessControlEnumerable, ERC2981, ERC721, ERC721Enumerable)
        returns (bool)
    {
        return super.supportsInterface(interfaceId);
    }
    
    function _burn(uint256 tokenId) internal pure override(ERC721, ERC721URIStorage) {
        super._burn(tokenId);
        super._resetTokenRoyalty(tokenId);
    }
    
    function tokenURI(uint256 tokenId) public view  override(ERC721, ERC721URIStorage) returns (string memory) {
        return super.tokenURI(tokenId);

    }

}

This is where _beforeTokenTransfer is called during burn: