Why does NULL = NULL evaluate to unknown instead of true?
Because NULL does not represent a value — it represents the absence of one. Asking whether two absences are equal is asking a question the database cannot answer. If I do not know your age and you do not know mine, we cannot conclude that we are the same age. SQL models that with a third truth value: besides TRUE and FALSE there is UNKNOWN, and a comparison involving NULL produces UNKNOWN.
This is where SQL differs from most programming languages. In JavaScript a missing value compares equal to another missing value; in Python None equals None. SQL deliberately refuses that, because a NULL in a stored column usually means "not recorded", and treating two unrecorded values as equal would silently make rows match that should not.
Three things follow from UNKNOWN. WHERE keeps only rows where the predicate is TRUE, so rows with UNKNOWN are dropped. NOT UNKNOWN is still UNKNOWN, so negating a comparison against NULL does not rescue it. And an aggregate such as COUNT counts only non-NULL values, which is why COUNT(column) can be smaller than COUNT(*).
The mental model that makes this click: think of the column as holding a set of possible values rather than one value. A NULL means that set is empty. Empty set equals empty set? There is nothing to compare, so the answer is unknown rather than true.