(motir-core) 3D / Immersive never treats the app shell CHROME — the top bar and rail render byte-identically to the default style, so the frame around the floating cards is flat and the style does not read as different
Type
Implementation defect (code) — a coverage gap in the style's rule set, not a planning mistake. The card that shipped the style asked for the right thing; the ladder it was written against has no row for this surface, which is why the fix is gated on MOTIR-4252.
⚠️ The estimate below is PROVISIONAL. It is priced before the design exists. MOTIR-4252 AC 9 obliges that card's run to re-read these criteria and re-estimate this card in the same pass — the header instrument in particular (a scroll-linked lift needs a signal, and <main> rather than the document is the app's only scroller) can move the number materially.
Parent
Parentless at the ROOT, by the forward ladder. The chain this defect sits under — MOTIR-1052 → MOTIR-804 → MOTIR-464 — is entirely done, so no rung above is eligible and a new child would re-open a shipped ancestor chain. Same placement as MOTIR-3522, MOTIR-4230, MOTIR-4232 and MOTIR-4234. The design blocker MOTIR-4252 sits BESIDE this card, never under it.
Discovered in
Out-of-band dogfooding, reported by Yue while running data-style="3d-immersive" in the signed-in app: "the whole nav bar is not 3d". Found while debugging whether MOTIR-4230's merged fix had worked — it had; it addressed a different surface (the canvas behind the content), and this is what remains.
Reproduction
Sign in, Appearance → Style → 3D / Immersive, open any signed-in route. Cards, buttons, popovers and page panels carry their depth; the top bar and the left rail are the same flat surfaces they are under the default style.
Root cause
The [data-style='3d-immersive'] block contains no rule for either chrome host. Verified on origin/main @ 819606e99 over packages/design-system/theme.css:1120-1690: the block targets cards, modals, popovers, buttons, inputs, board columns and the tilt planes, and never [data-surface='header'] or [data-surface='sidebar'].
Both hooks exist and are emitted:
app/(authed)/_components/TopNav.tsx:171→data-surface="header", on<header className="border-(--el-border) bg-(--el-page-bg) sticky top-0 z-30 border-b">. Its own comment says the hook is there so a surface-material style can treat the top bar as shell chrome, and is "inert under styles with no[data-surface='header']rule" — which is what 3D is.components/ui/Sidebar.tsx:309→data-surface="sidebar", on a root offlex h-full flex-col bg-(--el-sidebar-bg).
Mapping every chrome rule in the file to its owning style:
| style | [data-surface='sidebar'] | [data-surface='header'] |
|---|---|---|
| glassmorphism | ✅ 698 | — |
| aurora | ✅ 1094 | — |
| hand-drawn-indie | ✅ 1848, 1853 | ✅ 1848, 1866 |
| neumorphism | ✅ 2029, 2060, 2072 | — |
| retrofuturism | ✅ 2307 | — |
| 3d-immersive | none | none |
Neither host is reached by the global EVERY PANEL FLOATS rule either — that keys on the compiled .rounded-\(--radius-card\) class and neither chrome root carries it.
Measured, not read
Rendered on origin/main @ 819606e99 in headless Chromium (real Next build, signed-in session, /items, data-style="3d-immersive" chosen through the Appearance control and confirmed on <html data-style>): the shell root computes the immersive gradients (4230's fix is landing), and the top bar and rail compute a flat fill with a 1px hairline and no shadow — indistinguishable from the default style. Screenshot attached to this card's discussion.
What the fix is NOT
A blanket float on both hosts. The spec's own §4 says a quiet row is flat because the surface it sits in floats, so raising the rail without settling how its rows read against it re-creates 3522's mistake one level up. That is the whole reason MOTIR-4252 is a blocker rather than a note.
Acceptance criteria
Written against the DEFECT, not against the disposition — MOTIR-4252 has not chosen between the four candidate treatments yet, so no criterion below presumes one. AC 9 of that card amends these once it has.
- Under
data-style="3d-immersive", the top bar and the rail each render a treatment the[data-style='3d-immersive']block gives them — measured on the real compiled stylesheet in a browser, against the SAME two hosts under the default style, and the two must differ. The oracle is the default style's own computed value, never a hard-coded expectation. - The treatment implemented matches, element for element, what
docs/styles/3d-immersive.md§4's shell-chrome row specifies once MOTIR-4252 has written it. Spec and CSS agree row for row. - A guard test that closes over SURFACE CLASSES, the way MOTIR-3522's guard closed over control classes. It derives the set of
data-surfacevalues the tree actually emits (a scan, run in-test — not a hard-coded list) and asserts each one is classified for this style: treated, or deliberately untreated with a named reason. A newdata-surfaceappearing with no classification fails. Assert the CLASSIFICATION, not a count. - No other style's chrome changes.
glassmorphism,aurora,hand-drawn-indie,neumorphismandretrofuturismkeep the computed chrome treatment they have today, and the six styles that treat the chrome not at all still do not. - Light AND dark, on the palette-derived path: the treatment's resolved value differs between the two, which is the positive evidence the
--el-*reads are landing rather than frozen at one theme. - No motion is introduced for a reduced-motion user —
animation-nameon both hosts resolves tononeunderprefers-reduced-motion: reduce. - Where structure rests on a shadow,
prefers-contrast: moreandforced-colors: activerestore a solid hairline, matching the fallbackneumorphismships attheme.css:2051-2081. positionis not added to the sticky header — thehand-drawn-indieguard attheme.css:1845-1851holds; the header is already a containing block and overriding it breaks the sticky.- No
--color-*/--el-*colour token is added or changed: every colour is palette-derived so the style and palette axes stay disjoint, andstyleRegistry.test.ts's material-rule check still passes. - If the chosen treatment insets the rail,
AppLayout's collapsed-rail column stays derived rather than re-frozen to a constant — thecalc(var(--height-control) + var(--width-rail-chrome))sum from MOTIR-4232 gains the margin term rather than being replaced by a number. pnpm lint,pnpm typecheckand the theme + structural-guard lanes are green on the branch.
Context refs
packages/design-system/theme.css:1120-1690— the[data-style='3d-immersive']block; the absence is the defect.packages/design-system/theme.css:1212-1240— theIMMERSIVE BACKGROUNDrule after MOTIR-4230 (body, [data-app-shell]), the atmosphere any inset treatment would sit on.packages/design-system/theme.css:698·1094·1845-1878·2029-2081·2304-2325— the five styles that treat the chrome; the shape to mirror.app/(authed)/_components/TopNav.tsx:165-173·components/ui/Sidebar.tsx:307-312— the two hosts and their hooks.components/ui/AppLayout.tsx:126-150— the grid, and the collapsed-rail sum AC 10 protects.docs/styles/3d-immersive.md§4 / §4a / §8 — the ladder MOTIR-4252 amends, and the "half-3D" failure mode §8 already names.tests/theme/styleRegistry.test.ts— the material-rule check AC 9 must keep green.tests/theme/immersiveShellAtmosphere.test.ts— 4230's guard, which asserts the canvas and says nothing about the chrome.
Resolution
Open — blocked on MOTIR-4252.