<div class="cube"></div>

<p>Без <code>opacity</code> контекст наложения строится относительно корневого элемента.
Поэтому порядок отрисовки такой: фон корневого элемента (фактический <code>z-index</code> — минус
бесконечность), затем <code>::before</code> (<code>z-index</code> отрицательный), затем сам
<code>.cube</code> (<code>z-index</code> автоматический, по факту нулевой).</p>
<p>С <code>opacity</code> (и
<a href="https://developer.mozilla.org/ru/docs/Web/CSS/CSS_Positioning/Understanding_z_index/The_stacking_context#Контекст_наложения">еще
несколькими свойствами</a>) контекст наложения строится относительно <code>.cube</code>. Поэтому порядок
отрисовки <code>.cube</code> и его потомков такой: фон <code>.cube</code> (фактический
<code>z-index</code> — минус бесконечность), затем <code>::before</code> (любой <code>z-index</code>,
даже отрицательный, будет выше минус бесконечности). Поэтому <code>::before</code> перекрывает фон
<code>.cube</code> и скрывает его.</p>
<p>Ну а сама <code>opacity</code> применяется к уже итоговому отрисованному <code>.cube</code>, как к
единой картинке (текстуре). Поэтому мы видим не 2 полупрозрачных слоя, просвечивающих друг через друга, а один
полупрозрачный слой.</p>