Subtle elevation: one shared shadow scale, no big halos
Menus, popovers, the composer, the New Tab box, find bars, palettes, sheets and the tab drag ghost each cast their own drop shadow, many of them big and soft (0 16px 34px at 28-30%, 0 12px 40px at 22%, an opaque 12 pt halo around a docked column). Every shadow now comes from one two-step scale, the same numbers on the web and in AppKit: a tight, low-alpha drop under the surface, with the thin rim carrying the edge. Nothing gets a new look; shadows only get smaller.
Built on current base, which has #20461 (one popup hairline) and #20481 (device-pixel rims). The rims are untouched; only the drops change.
Tokens
| Step | Web (pages/shared/desktop.css) | Native (PopupStyle) | Used by |
|---|---|---|---|
--elevation-1 / .elevation1 | 0 1px 2px black 7% (dark 12%) | offset 1, blur 2, alpha 0.07 | rows, cards, inline surfaces, a selected segment, a switch knob |
--elevation-2 / .elevation2 | 0 2px 6px black 11% (dark 16%) | offset 2, blur 6, alpha 0.11 | popovers, menus, palette, hover cards, composer, New Tab box, sheets, toasts, find bars, lifted tabs |
- Dark mode keeps the geometry and darkens the alpha a little (
prefers-color-scheme: dark, ordata-theme="dark"in the agent pane). --ui-popup-dropis nowvar(--elevation-2), so--ui-popup-shadowand--acpmux-popup-elevation(every Base UI menu and pane popover) follow. Rims stay separate: #20461's--ui-popup-edgehairline and #20481's--cmux-hairlinerings are untouched.- Native:
Elevation(offset, blur, alpha,layerRadius= blur / 2 for Core Animation,layerOffset(flipped:),shadow()forNSShadow).PopupStyle.standard.elevationis.elevation2, and the oldshadowOffset/shadowBlur/shadowAlpha/shadow()are gone, so no call site can keep its own numbers. appearance.borders = noneclears rims only, so shadows stay. Reduce Transparency and Increase Contrast behave as before.
Inventory (before → after)
Web (webviews/src):
| Surface | File | Before | After | Owner |
|---|---|---|---|---|
Every Base UI menu/popover, pane menus, model picker, omnibox, slash/@ menus, summary card, .nt-popover, .lg-palette | ui/popupSurface.css --ui-popup-drop | 0 2px 8px 12% | --elevation-2 | Leo 2841396b |
| Composer (rest and focus) | acpmux/composerLocation.css | 0 8px 24px 18% | --elevation-2 | Leo 0f8d6805 (#20303) |
| Permission card | acpmux/composerLocation.css | 0 4px 14px 10% | --elevation-2 | Leo 0f8d6805 |
| New Tab box (rest and focus) | acpmux/newtab/screen.css | 0 12px 32px -18px 40% | --elevation-2 | Lawrence 663bd736 |
| New Tab box (old pane) | acpmux/styles.css | 0 12px 32px -18px 40% | --elevation-2 | Leo b75d89c9 |
| New Tab selected kind | acpmux/styles.css | 0 1px 2px 25% | --elevation-1 | Leo b75d89c9 |
| File search palette | acpmux/styles.css | 0 16px 40px 35% | --elevation-2 | Leo e2e74d24 |
| Pane sidebar overlay | acpmux/styles.css | 0 8px 24px 35% | --elevation-2 | Leo bd5b4722 |
| Chat find bar | acpmux/conversation/conversation.css | fallback 0 4px 14px 18% | fallback --elevation-2 | Leo 622e57ee |
| Jump-to-latest button | acpmux/conversation/conversation.css | 0 4px 14px 14% + 0 1px 2px 10% | --elevation-2 | Leo 641a5af3 |
| Minimap hover card | acpmux/threadMinimap/threadMinimap.css | 0 4px 14px 9% | --elevation-2 | Lawrence 225ea274 |
| Handoff targets menu | acpmux/handoff/styles.css | 0 4px 16px 12% (text color) | --elevation-2 | Leo a15090ff |
| Add project dialog | acpmux/addProject.css | 0 12px 36px 27% | --elevation-2 | Leo 224eda31 |
| PDF viewer / large page / page | acpmux/composerAttachments.css | 0 16px 44px 28% / 0 8px 24px 18% / 0 1px 2px 15% | -2 / -2 / -1 | Leo e08117d6 |
| Effort slider thumb | acpmux/composerControls.css | 0 1px 3px 20% | --elevation-1 | Lawrence 8a44d921 |
| Tooltips (Base UI and title) | pages/shared/desktop.css | 0 2px 8px 16% | --elevation-2 | Leo 66dd3104 |
| Page menu | pages/shared/pageBase.css | 0 6px 24px 18% | --elevation-2 | Lawrence 82ae6117 |
| Markdown link card/popover | pages/markdown/styles.css | 0 6px 24px 18% | --elevation-2 | Lawrence 68855685 |
| Cloud create sheet | pages/cloud/styles.css | 0 12px 40px 22% | --elevation-2 | Lawrence bdaaf04c |
| Bottom sheet | ui/ui.css .ui-sheet | 0 -8px 30px 22% | --elevation-2 | Lawrence d5189aab |
| Channels side sheet | pages/home-channels/ledger.css | -12px 0 32px -16px 35% | --elevation-2 | Lawrence c93267a0 |
| Channels message toolbar | pages/home-channels/styles.css | 0 2px 8px 12% | --elevation-2 | Lawrence 9f8d556c |
| Icon picker bar | icon-picker/styles.css | 0 4px 18px 16% | --elevation-2 | Lawrence 6d7b696a |
| Viewer picker | viewer-empty/styles.css | 0 14px 44px 24% | --elevation-2 | Lawrence 99df3371 |
| Diff base picker, toolbar menu, diff find bar | styles.css | 0 16px 34px 28-30% | --elevation-2 | Lawrence 14aa604e |
| Diff file-tree context menu | styles.css | 0 8px 24px 18% | --elevation-2 | Lawrence d13dde39 |
| Diff pill button | styles.css | 0 6px 18px 22% | --elevation-2 | Lawrence 14aa604e |
| Diff file search sidebar | styles.css | -18px 0 42px 34% | --elevation-2 | Lawrence b129a866 |
| Diff comment card | styles.css | 0 1px 2px 10% + 0 2px 8px 6% | --elevation-1 | Lawrence ed02a990 |
| Dev only: optchat tip, pane preview frame, gallery window, prototype | various | up to 0 24px 64px 50% | --elevation-2 | Lawrence, Leo |
Native (Packages/macOS/CmuxNext):
| Surface | File | Before | After | Owner |
|---|---|---|---|---|
| Popover host (hover cards, group editors, icon picker, omnibox suggestions, sidebar update notes, web popups) | CmuxNextDesign/PopupStyle.swift PopupHostView | blur 8, offset 2, 12% | .elevation2 | Leo e17da11b |
| Toast | CmuxNextDesign/Toast/CmuxToastView.swift | blur 8, 12% | .elevation2 | Leo |
Command palette, page info bubble (NSShadow) | CmuxNextPalette/PaletteContentView.swift, PageInfoPanel.swift (now drawn by PopupHostView) | blur 8, 12% | .elevation2 | Leo |
| Omnibar card top | CmuxNextBrowser/UI/OmnibarViews.swift | blur 8, 12% | .elevation2 | Leo |
Omnibar bar (opt-in shadow) | CmuxNextBrowser/UI/OmnibarViews.swift | CA radius 6 (≈ blur 12), 18% | .elevation2 | Lawrence ff755bea |
| Tab drag ghost | CmuxNextApp/Drag/TabDragGhostPanel.swift | CA radius 10 (≈ blur 20), offset 3, 28% | .elevation2 | Lawrence a367ef42 |
| Lifted tab, group chip, sidebar drag lift | TabCell.swift, TabGroupChipCell.swift, DragLiftView.swift | CA radius 8 (≈ blur 16), 12% | .elevation2 | Leo 16566c51 |
| Docked column backdrop | CmuxNextLayout/Views/DockBackdropView.swift | CA radius 12, offset 0, 100% of the theme shadow color | .elevation2 | Lawrence fa21a064 |
| Task board card | CmuxNextTasks/Views/TasksBoardView.swift | radius 2 / 5 (hover), 30% / 60% | .elevation1 / .elevation2 | Lawrence 2964b216 |
| Page info switch knob | PageInfoToggle.swift | CA radius 1, 18% | .elevation1 | Lawrence ddeefff0 |
Left as they are:
- Cmd-hold shortcut hint chips (
ShortcutHintChipView, Lawrence's): CA radius 2 at 22% black. Tight, so unchanged; the alpha is above the scale's 16% cap, noted here rather than changed. - Group editor bubble (sidebar groups and tab group chips): it has no shadow code of its own and draws through
PopupHostView, so it follows the shared value swap. Its openers and code are untouched (deferred to Lawrence's chief). - Three directional shadows became the plain downward step: the bottom sheet (
0 -8px 30px), the diff file-search drawer (-18px 0 42px) and the Channels side sheet (-12px 0 32px -16px). Their rims carry the edge now. - The OptChat inspector's tip (
0 4px 14px18%): a standalone page bundled into optchat-chief without the desktop layer, so the tokens are undefined there; the web ratchet skips it. - System window shadows (
hasShadow = trueon the native tooltip, Quick Composer, restart notice, feed, notifications, update sheet and onboarding drag panels): AppKit's own panel shadow. - Focus glows (
PaneOverlayViewring glow, launch mark), which are colored rings, not elevation. - Sidebar notice card and terminal find bar: they cast no shadow today, so nothing to retoken. No sidebar layout changes.
Captures
Fleet DEV builds on a cua-4 capture slot, the same seeded window: before = feat-cmux-next 772b6ea30a5b (build nxtip3-v1), after = this branch 10d7d6927907 (build subtleelev2). Dark, light, and dark over a desktop wallpaper. Each still is before | after. The mini's host name is blurred.
The difference is easiest to see on the New Tab box (right pane: the soft 32px halo under it is gone), the model picker and the command palette (a tight edge instead of a spread). The hover card was already on the shared popup shadow, so it changes only slightly.












Recording (dark, 8 s, watched): the main window from both builds side by side. debug.window_record captures the main window only, so it shows the composer and New Tab box at rest; the menus, palette and hover card are in the stills above.
plan image 20519/dark-1-composer.jpg
plan image 20519/dark-2-model-picker.jpg
plan image 20519/dark-3-palette.jpg
plan image 20519/dark-4-hover-card.jpg
plan image 20519/light-1-composer.jpg
plan image 20519/light-2-model-picker.jpg
plan image 20519/light-3-palette.jpg
plan image 20519/light-4-hover-card.jpg
plan image 20519/wallpaper-1-composer.jpg
plan image 20519/wallpaper-2-model-picker.jpg
plan image 20519/wallpaper-3-palette.jpg
plan image 20519/wallpaper-4-hover-card.jpg
plan gif 20519/elevation-dark-before-after.gif (from elevation-dark-before-after.mp4)
plan video 20519/elevation-dark-before-after.mp4
uploaded 20519/dark-1-composer.jpg
uploaded 20519/dark-2-model-picker.jpg
uploaded 20519/dark-3-palette.jpg
uploaded 20519/dark-4-hover-card.jpg
uploaded 20519/light-1-composer.jpg
uploaded 20519/light-2-model-picker.jpg
uploaded 20519/light-3-palette.jpg
uploaded 20519/light-4-hover-card.jpg
uploaded 20519/wallpaper-1-composer.jpg
uploaded 20519/wallpaper-2-model-picker.jpg
uploaded 20519/wallpaper-3-palette.jpg
uploaded 20519/wallpaper-4-hover-card.jpg
uploaded 20519/elevation-dark-before-after.gif
uploaded 20519/elevation-dark-before-after.mp4
Full quality:
Not captured: a toast, a tab drag and a native context menu. A no-activate slot can't raise them without closing tabs. The toast, the tab drag ghost and the lifted tab are covered by SubtleElevationTests below.
Testing (red and green)
- Web,
heavy --mem 4G bun test test/subtle-elevation.test.ts: red on2da8059cd2ac(38 of 39 failed: no tokens, 30+ literal blurred drops, every swept surface on its own shadow) → green on the head (39/39). It fails on any blurred drop that is not--elevation-1/2, on tokens over 8px blur or 16% alpha (light and dark), when the native numbers drift from the web ones, and when a swept surface stops naming the scale. - Native, fleet
run-swift-testing-suites.sh Packages/macOS/CmuxNext(Xcode 26.6, aws-m4pro):- red on
2da8059cd2ac(step keyop-next-theme-shadows-red-2da8059cd2ac…):SubtleElevationTests7 of 8 failed with 18 issues, for example the drag ghost at radius 10 / 28%, a lifted tab at radius 8, and the paletteNSShadowat blur 8 / 12%. Every other suite passed. - green on
10d7d6927907(op-next-theme-shadows-green-10d7d6927907…): 291/291 suites PASS,SubtleElevationTests8/8. The updatedPolishCalmChromeTests,PaletteShadowTestsandOmnibarCardElevationTestspass too. - Both steps exit 1 only on the fleet's same-tree guard (
AcpmuxBundleReplacedTestsskipped: the head's cmux-tui tree isn't published). That is unrelated to this change. - The dock backdrop check in
noNativeShadowPassesTheCapwas added after the red run, so its red is not recorded.
- red on
- Also passing:
popup-surface.test.ts(browser lane, CI only; it now readselevation2) andui-rules. - Guards:
- Clean:
check-theme-scope,check-system-blue,check-motion,crash_ratchet(ok),check-no-godfiles --base <merge-base>(no touched file flagged),vp check, type-scale, text-focus. - Base reds in files this PR doesn't touch:
check-concurrency(ControlWorkspaceInfoCache.swift)lint-ios-package-conventions(PaneAnimationsSetting.swift)check-layers(summary.css raw z-index)
- Clean:
- A review subagent found three problems, now fixed: the test target didn't compile (
TabCellisn't a view), the OptChat inspector's committed page went stale, and a host without desktop.css would lose the popup shadow and rim (--ui-popup-dropnow falls back to the same step).
Changelog
Changed: Menus, popovers, cards and the composer use a subtle shadow instead of a large soft one.
🤖 Generated with Claude Code