CSS custom properties cascade; preprocessor variables do not

A Sass variable is resolved at build time and does not exist in the output. A custom property is a real value in the cascade, which means it inherits, it can be changed per selector, and JavaScript can read and write it.

:root { --gutter: 16px; }
.compact { --gutter: 8px; }

.card { padding: var(--gutter); }   // 16px, or 8px inside .compact

// and at runtime
document.documentElement.style.setProperty('--gutter', '24px');

That is the capability no preprocessor has: theming without recompiling, and a value a media query can change. Support is Chrome, Firefox and Safari but not IE or Edge yet, so this year it is additive — declare a static fallback before the var() and browsers that do not understand it use the first declaration.