Skip to contentWolf-Rayet

Decision records

ADR-0108 A stacking context casts

Accepted2026-09-18Phase 7

Amends ADR-0013. Supersedes ADR-0100's overlay shadow.

#Context

ADR-0013 replaced elevation with three enumerated stacking contexts, encoded structurally rather than luminously: a context is declared, and a full perimeter border is what says which one it is. The reasoning was that a luminance ramp is a tax every raised surface pays forever, and a border says the same thing for free.

The maintainer asked for elevation.

The original reasoning still holds and it was answering a narrower question than it appeared to. What ADR-0013 rejected was elevation as a *substitute* for the declaration: a set of surfaces told apart by how bright they are, with the hierarchy living in the luminance and nowhere else. That is still rejected. What it did not consider is elevation as a second reading of a declaration that already exists structurally.

#Decision

  • Each stacking context carries a shadow. base casts nothing, because

it is the substrate and there is nothing under it. raised casts a small one, overlay a larger one.

  • The border still carries the declaration. A component's context is

still said by its perimeter, and the shadow is the same statement reaching the eye a second way. Remove every shadow and the system still works; remove every border and it does not. That ordering is what keeps this an amendment to ADR-0013 rather than a reversal of it.

  • The colour is the theme's own scrim role, composed at use. Not a

literal, not a new ramp. rgb(from var(--wr-scrim) r g b / alpha), which is the mechanism ADR-0014 already chose for the overlay's dimming, so a shadow resolves in whatever theme the element is rendered in rather than in the one it was written for. The verifier fails a shadow that names a colour instead.

  • The geometry is indices into the space scale, so a shadow gets denser

with everything else rather than being the one spatial value that did not.

  • The budget prices it like anything else. No exemption. Measured: the

four modal scenes moved by 5.91e-3 to 8.78e-3 and no scene crossed a ceiling. Emission is read off rendered pixels, so a shadow that spends too much fails a scene rather than being argued about in a review.

  • ADR-0100's hard offset on the overlay is removed. It was a second

box-shadow on the same rule as this one, so one of the two was always dead CSS that read as a decision. The soft cast is the one kept: a hard offset in the mark colour spends the demand's own hue a second time on something that is not the demand, while the cast spends the scrim, which is the role this context already uses to say there is a plane between you and the page.

#Consequences

Five components draw it: modal on the overlay context, and the three shell panels and popover on raised. Those are the components that declare a stacking context, which is the rule ADR-0013 set and this record does not change. A component that wants a shadow declares a context to get one.

Two independent checks had to learn the property. The token verifier keeps its own list of what a context carries and rejected shadow until it was taught to read the sub-node, the way it already reads border after an index passes.

base carrying no shadow is checked rather than assumed: a component aliasing shadow from the base context fails, because a context that spends nothing on a property has none to alias.

#Alternatives

A luminance ramp per context. What ADR-0013 rejected, and still rejected for its own reason: the hierarchy would live in the brightness rather than in the declaration, and every raised surface would pay for it on every render.

A shadow on every component with a ground. Rejected. It would put an elevation on 29 components, most of which sit in the flow of a page and are not above anything, and the budget would pay for all of them.

Keep ADR-0100's hard offset as well. Not available. Two box-shadow declarations on one rule is one box-shadow.