As a matter of habit, I put all inner joins that may limit the result set as the first joins, then the left joins that have where conditions on them. I am not sure whether the optimizer sees that only those tables are needed to determine which rows will be in the end result and automatically prioritizes them as far as joins. With 40+ joins, I would want if this re-ordering of the declared joins may be significant.
If that doesn't help, then I would put all of those in a sub-query to break up the problem for the optimizer (OFFSET 0 being an optimization fence, though if this is an example of "simple" pagination then I assume but am not sure that OFFSET 20 would also be an optimization fence). Else, put all that in a CTE with MATERIALIZED keyword when on v12 and without on 9.5 since it did not exist yet and was default behavior then.
With an empty database, there are no statistics so perhaps the optimizer has too many plans that are very close in expected costs. I'd be curious if the planning time gets shorter once you have data, assuming default_statistics_target is left at the standard 100, or is not increased too hugely.