Why your duplicate rows survive every attempt to remove them
Two rows that look identical on screen are frequently not identical to a computer, and the reasons are almost always invisible. The commonest is a trailing space, picked up when a value was pasted from a web page or exported from a system that padded its fields. "Ana" and "Ana " differ by one byte, so any comparison treats them as distinct, the duplicate check finds nothing, and the row you can plainly see twice stays twice.
There are subtler versions. A non-breaking space, U+00A0, is what you get when text comes from HTML, and it looks exactly like a space while comparing unequal to one. Numbers stored as text compare unequal to the same numbers stored as numbers, which is why a column of ids can fail to match itself after a round trip through CSV. Unicode makes it worse: an accented character can be a single code point or a base letter followed by a combining accent, identical on screen and different in memory, which is what normalisation forms exist to reconcile.
The order of operations therefore matters more than the operations. Trimming has to happen before deduplication, not after, or the padded row survives the comparison as a distinct value and gets removed only from the tidied output, leaving the duplicate behind. Blank-row removal has to come before deduplication too, otherwise several blank rows are themselves duplicates of each other and the count of what was removed becomes confusing to read. This tool runs trim, then blank-row removal, then deduplication, and reports each separately so the numbers add up.
What counts as a duplicate is a decision, not a fact. Matching on every column is the strict reading and the safe default: two rows are the same row only if they agree everywhere. Matching on a key column instead, so that a later record supersedes an earlier one, is a different job with different risks, and it is the one the spreadsheet comparison tool is for. Conflating them in a single button is how people delete rows they meant to keep.
The masking half of the tool has its own subtlety worth stating. Replacing a value with one bullet per character preserves its length, and length is information: a masked phone number of ten characters beside one of nine tells a reader something about both. A fixed-width mask gives that away nothing, at the cost of the column no longer showing which entries were longer, which is a trade worth making by default. Removing the column outright gives away less still, and is the right choice whenever the recipient has no reason to know the column ever existed.