ADR-103 ActifActive contract

Dark-mode elevation: a dark variant for every shadow, and a raised surface

DateDate
2026-09-28
DécideursDecision makers
Guilherme Negreiros — Design System Lead

Context

semantic.shadow.* (ADR-046) had no dark variant: semantic.dark.json only held colours. A black shadow at 10–12 % opacity nearly vanishes on a dark background, so in dark mode raised elements lost their elevation. The site compensated with its own scale outside the tokens (--agtc-shadow-sm/md/lg in site/build.js), darker in dark mode — which agtc-top-nav then consumed and shipped without (issue #208).

Human rule, 2026-09-28: both modes must always offer the same options, adapted to each mode.

The research note on issue #210 compared five reference systems. All of them do two things in dark mode:

SystemDark-mode elevation
AtlassianSeparate elevation.surface.* and elevation.shadow.* tokens; the higher the surface, the lighter it is; *raised* and *overlay* pair a surface with a shadow in both modes
Apple HIG (iOS)*Base* and *elevated* background sets; elevated backgrounds are lighter
Material 3Tonal difference first; shadows express distance, sparingly
CarbonLayers lighten at each level (g100: #161616 → #262626 → #393939); shadow token .3 → .8 opacity
Radix ThemesSame shadow geometry in both modes, much stronger black alphas in dark

Decision

1. **Every non-deprecated semantic.shadow.* token has a variant in semantic.dark.json — same geometry, opacity raised about ×4–5 (header, raised, card → about .50). 2. New token semantic.color.background.surface-raised for dropdown menus, popovers and mobile nav panels, paired with shadow.raised: the same white as surface in light mode, one step lighter than surface in dark mode (#1b1f27 over #13161d). In dark mode the surface, not the shadow, carries most of the elevation. 3. No light ring built into the shadow (unlike Radix): raised panels already draw border.default; a ring would double it. 4. The site's own shadow scale is removed. Its four uses consume the tokens (sm → shadow.header, md/lg → shadow.raised); raised site panels and the agtc-top-nav mobile panel use surface-raised. 5. Guardrail:** scripts/audit-tokens.js check 6 fails --ci when a non-deprecated semantic.shadow.* token has no dark variant (governance test tests/governance/tokens-audit-dark-shadow-parity.spec.js). 6. semantic.shadow.card-hover is marked $deprecated (decided in issue #206), so it gets no dark variant; issue #209 adds its alternative once ADR-102 is merged.

Rejected alternatives

mode; on Agentica's near-black page a shadow alone stays barely visible (checked on before/after captures, issue #210).

discreet hover"; mixing an elevation role into it would couple two decisions.

component already shipped depending on it (issue #208).

Consequences

mobile panel background changes in dark mode (components patch).

under this ADR, not a new decision.

them to dark primitives is part of issue #212.

Implementation

DateEvent
2026-09-28Decision adopted (issue #210); tokens, check 6, site and agtc-top-nav updated