Acceptance Criteria
cover and content-place are facets; the inline content-place block, the cover foreground block, and the cover scrim-consume block are gone from engine.tsFacetResult.state carries cross-facet values that are never emitted, so cover mode does not leak a data-cover attributeFacetResult.styles is an ordered [prop, value] pair list, preserving the duplicate --cover-scrim-dir declaration that CSS last-wins depends onFacet.postAssemble runs against assembled children; cover's foreground-polarity flip on the content overlay happens thereFacetInput.seedAxes + orderFacets(facets, { seeded }) let a facet declare after on an axis still resolved inline; seeded values are readable but never emitted, and a facet-supplied value shadows the seed it replacescover declares after: ['media-position', 'content-place'], encoding the explicit-direction-overrides-derived-direction rule the code previously stated only in a comment- All 630 pre-existing transform tests pass unmodified, including
cover.test.ts - New unit tests cover the state channel, duplicate style declarations, both phases, seeding, and seed shadowing
npm run build, the full repo suite, and refrakt contracts --check pass
Approach
The cover axis splits across three points in transformRune: the scrim-reroute decision during bg resolution, the scrim-meta consume, and — 500 lines later — the cover foreground and data attributes. The last of these mutates the assembled content overlay, which is why resolve alone cannot express the axis.
Leave the ~200-line bg block inline; it is WORK-520's job. bg continues to read isCover locally, which stays correct because the facet's state is derived from the same seeded media-position.
Two incidental findings surfaced while reading this code; record but do not fix them here.
- The cover block guards on
!bgDataAttrs['data-color-scheme'], but the only assignment to that key requires !isCover — inside cover mode the condition can never be false. Preserve the behaviour exactly (seed from both bags) rather than acting on the analysis. findByName and findDeepByDataName in engine.ts are the same recursive lookup written twice, 1200 lines apart. Consolidate the one the facet needs into helpers.findNodeByDataName rather than adding a third copy; the other remains.
References
- SPEC-124 — facet registry (the spec this work item realizes)
- SPEC-089 — cover layout,
content-place, and the scrim reroute - SPEC-088 — the scrim vocabulary this axis reroutes