Even though they are estimated plans and not the actual ones, the difference to me looks like it is coming from joining the tables:
RATING_CONTRIB_LOSS
,
RATING_CONTRIB_USR
,
cmbgrp
,
rating_revision_set
,
and the Rating
table from the ratings CTE
.
Joining these tables spawn huge table spools (lazy spool), that could be even bigger on the actual plan.

For every row in the top part of the nested loops operator, the bottom result set is scanned resulting in
3361 rows * 3359 in the first table spool
--> Nested loops
--> Top(1)
and
1541 Rows * 3359 in the second table spool
--> Nested loops
--> Top(1)

These table spools are not present in either of the two plans in the temp table queries.

What I am getting at is that the query part that inserts into the table is alike to the corresponding query part of the CTE
. There are some differences but I think that the major cause of the slowdown is because of the table spools.
An example of a difference is that the full table scan on RATING_CONTRIB_LOSS
in the CTE
plan is changed to a scan with a residual predicate in the temp table plan.
CTE

Temp table

And you could argue that the second part of the query that uses the temp table might access the RATING_CONTRIB_LOSS
table again. And I would have to agree because it will be doing an expensive key lookup.

However, the second table spool in the CTE
plan is also based on a nested loops join with theRATING_CONTRIB_LOSS
table, which is not present in the temp table plan, and that is a big plus.
Conclusion
I do believe that the difference in execution time comes from the query using the temp table's result in such a way that costly operators are not used. More specifically the Table spools. I would need the actual plan to be 100% sure.
As a sidenote, rewriting CTE's into temp tables or just splitting up queries in general can in many cases give better execution times.
It is easier to guess how many apples are in a bag with apples and pears than guess how many apples are in a bag with apples, pears, mango's, oranges, peaches, .... (Yes the fruit = tables).
I would also use actual #temp tables to store your intermediary results in.
Comparison CTE & Temp table insert query parts
Plan with CTE part 1

Plan with CTE part 2

Plan with temp table part 1

Difference on RATING_CONTRIB_LOSS & Hash match join <> Nested Loops Join. Rest is very much alike, Same operations (2x) on Rating table
;
) Do they like conffusing themselves and others? (the scripts above have 1 and 3 statements respectively while they look like 2 and 4)... Not to mention the error we'll get if we run them in a single batch.