Context transition is the one DAX concept that quietly breaks more reports than any other. You write a measure, test it in one visual, and it's correct. Drop the same measure into a table with a different grouping, and the numbers shift in ways that feel like a bug. It usually isn't. It's context transition.
The receipt
Picture a grocery receipt. Each line item has a price and a quantity — that's row context: you're standing on one specific row, looking at one specific item. Now picture the total at the bottom of the receipt. That total was built by walking down every row and adding things up — that's filter context: a set of rows the calculation considers.
CALCULATE is the cashier. The moment you call CALCULATE inside a row context — say, while you're standing on one line item — it takes everything true about that row and turns it into a filter, as if the cashier rang up just that one item on its own till. That conversion, from "I'm standing on this row" to "now only this row is in scope," is context transition.
Where it bites
It shows up constantly inside iterators like SUMX, AVERAGEX, or RANKX, because those functions create row context on every pass, and any CALCULATE (explicit or implicit, via another measure) inside them triggers transition. A measure that looks innocent in a single-row card visual can behave completely differently inside SUMX, because now it's being transitioned row by row.
A rule of thumb
If a measure's result changes depending on what visual or iterator it's placed inside, ask whether a CALCULATE somewhere in its chain is converting row context to filter context, and whether that's actually what you want. Once you can name what's happening, the "weird" numbers stop being weird.