As you've correctly stated in your title, custom properties cascade. In fact, this is why the module is called CSS Custom Properties for Cascading Variables. That means your custom property --color is evaluated as-is per element, just as with any other CSS property. In terms of the actual styles that are applied to your elements, what you really only have is:
* {
  color: var(--color);
}
The var(--color) value is then evaluated for each element based on how the --color property cascades. So it follows that:
- The bodyelement has a blue foreground.
- Any divelements have a green foreground.
- The element whose ID is "alert" has a red foreground.
- Because you don't have a --colordefinition for*, it's inherited by default. Therefore all other elements inherit--colorfrom their parent element:body > pinherits frombody, becoming blue, and#alert > pinherits from#alert, becoming red.
If you really do want to express the cascaded values in terms of CSS, you could say that it translates to the following:
:root {
  color: blue;
}
div {
  color: green;
}
#alert {
  color: red;
}
* {
  color: inherit;
}
But only because the original CSS contains an explicit * { color: var(--color); } definition which ensures that every element's color maps to --color.
Note also that the code that you have comes from an example within the spec, which itself is described as follows:
If a custom property is declared multiple times, the standard cascade rules help resolve it. Variables always draw from the computed value of the associated custom property on the same element
One more question I have is if :root translates to body in CSS.
- :rootdoesn't translate to any element in CSS, because CSS is document language-agnostic.
- :rootdoesn't translate to- bodyin HTML; it corresponds to- html.