The starting styles lose to any equal rule written below them.
The common read: @starting-style is a rule like any other, so it can go anywhere the selector matches.
The declarations inside @starting-style are resolved by the ordinary cascade at the ordinary weight, so a later rule of equal specificity overwrites them before the browser ever samples them as a from-state. That is the entire mechanism, and it is why the block goes AFTER the rule it primes. The at-rule gets no boost, no priority and no special phase; it groups declarations the way @media groups them, and grouped declarations sort where their selector and their position put them.
What the browser is doing with them is worth one sentence, because it explains why a from-state has to be supplied at all. A transition needs a before-change style and an after-change style, and an element that was not rendered a moment ago has no before-change style for this style change, so the browser substitutes a starting style: the after-change style with any matching @starting-style declarations applied on top.
Applied on top by the cascade. Put an equal-weight rule below the block and there is nothing left on top, the substituted style equals the end state, and two identical values start no transition.
This ships in every browser. It landed recently enough that it is worth checking against your own support floor. The placement rule is the part that survives every version of that check, because it is a cascade fact rather than an implementation detail, and it is also why the nested form is the one to reach for by default: written inside the rule it primes, @starting-style cannot be lifted above it by an editor, a sort-properties tool or a merge.
The rule is in the file. The browser read it. Nothing happened. This is not a bug report.
