The box-shadow token --focus-ring hardcodes var(--color-surface-default) as its
gap-fill (render-css.ts:184), so a control focused inside a raised/overlay/filled
plane showed a mismatched halo; box-shadow rings are also clipped by overflow:hidden
and die under forced-colors. Migrate the last 5 box-shadow consumers to the canonical
outline pattern already used by button/card/~40 components:
outline: var(--focus-ring-width) solid var(--focus-ring-color)
outline-offset: var(--focus-ring-offset) (or 0, flush, for input + scrollbar)
- command-input (offset 0, keeps border-color shift) - collapsible-trigger - toggle -
splitter-resize-trigger (offset var) - scroll-area-scrollbar (offset 0)
Outline follows border-radius on every evergreen browser, isn't clipped by overflow,
and the forced-colors fallback already maps outline. The gap-color mismatch disappears
-- no --focus-ring-surface token needed.
NOTE: the box-shadow token --focus-ring now has zero CSS consumers (only THEMING.md +
a palabras doc reference it). Left in place -- it's a public foundation token; removing
it is a separate API decision (bundle with the --size-* orphan cleanup).
Verified: grep 0 box-shadow focus rings in component CSS; eidos suite 15/239 unchanged;
served rule confirmed in browser ([data-toggle]:focus-visible -> outline). Visual look
on keyboard focus worth a live Tab-through (CDP screenshot hung all session).
- floating-gap canon: --floating-gap-menu 0 -> var(--space-1); FloatingContent
reads --floating-gap via a reactive $derived (was a one-shot rAF that never
reached portaled menus -> they fell back to sideOffset, flush); nav-menu wired
to the token via CSS.
- focus-ring: exclude item/option/content from the universal archetype ring; menu
rows use the canonical highlight on :focus-visible too (no thick keyboard border,
no ring framing the whole float).
- overscroll-behavior: contain on the ScrollArea viewport + 7 overlay scroll regions
(no scroll chaining to the page).
- archetypes.css: default rules wrapped in :where() so component recipes always win.
- radius decoupled from size (Radix model) in toggle/textarea/menubar/nav-menu/
virtual-list/grid; toggle `rounded` prop.
Canon-read + token reach portaled menus pending a fresh-load check (the dev tab
cached the floating module) -- see CONTINUE-floating-gap-canon.md.
Coherence audit (ARCHETYPE_COHERENCE_AUDIT_2026-06-19): 8 archetypes + 8 closed
decisions, the §13 construction contract, per-component deviation matrix (88/117
deviate). Master guides (soma/COMPONENT_GUIDE, eidos/components/README) point to it.
A1 — elevation bundle via `data-depth`: the plane paints surface·border·shadow·halo
(added `border` to the depth bundle). z-index is NOT painted — stacking is a
positioning concern owned by the floating-wrapper. Popover migrated to the overlay
plane (panel + arrow consume it); recipe orphans pruned.
Popover fixes: arrow un-clipped via an inner [data-popover-viewport] (Radix-style;
the absolute arrow escapes the scroll clip), sized via density tokens (not soma's
hardcoded 10×5), border-seam overlap keyed on data-side, hover-bounce guard in
scheduleHoverOpen (ignore hover-open when already open). Dialog.Close composes
IconButton/Button (neutral) — closes the Lote ② debt.
Option lists: density-driven padding/radius via --space-* + concentric radius,
ScrollArea adoption, emerge open/close events (combobox/select/command), and the
canonical option-highlight in archetypes.css.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- scroll-area soma: defer the mount-frame request to `$effect` so SSR
doesn't hit `dom::window_required` during constructor evaluation.
- scroll-area recipe: scrollbars now `position: absolute` (overlay
style) so the horizontal track lands at the viewport's block-end
instead of flowing below it. `:has` rules reserve corresponding edges
when both axes mount; corner switched to absolute as well.
- drawer demo: drop the ↑↓←→ glyph pop-outs and `overflow: visible`
during dragging. The handle's own pill grip is the affordance — the
same shape the splitter uses, no extra chrome.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
3 new layout primitives close the air port set (15 / 15 done).
`npm run component:audit`: 91 / 91 PASS, all 3 new PASS with 0 errors.
**scroll-area** — eidos compound wrapper over the existing soma:
`<ScrollArea><ScrollArea.Viewport>{content}</ScrollArea.Viewport>
<ScrollArea.Scrollbar orientation="vertical"><ScrollArea.Thumb />
</ScrollArea.Scrollbar><ScrollArea.Corner /></ScrollArea>`. Mirrors
Radix Primitives / Bits UI shape. Demo 667 lines.
**separator** — visual primitive (`scope: ['eidos']`) with conditional
ARIA: `role="separator"` + `aria-orientation` when not decorative,
`aria-hidden="true"` when decorative. New morfo
`src/uix/morfo/components/separator.ts`. Demo 645 lines.
**splitter** — eidos compound over existing soma:
`<Splitter orientation="horizontal"><Splitter.Panel>{a}</Splitter.Panel>
<Splitter.ResizeTrigger /><Splitter.Panel>{b}</Splitter.Panel>
</Splitter>`. Demo 824 lines.
**Splitter sema rewire — match Slider's handle/drag/commit shape:**
The morfo previously declared only `commit-resize`. Direct-manipulation
primitives (Slider, Splitter) should share the same event vocabulary so
audio/haptic projections feel coherent across the family. Renamed +
expanded to mirror Slider:
- `handle-pick` (family: handle, verb: pick, sequence: coincident,
target: resize-trigger) — fires on pointerdown when user grabs the
trigger.
- `handle-drag` (family: handle, verb: drag, sequence: coincident,
target: resize-trigger) — fires on each pointermove frame.
- `commit-set` (family: commit, verb: set, intent: neutral,
sequence: post, target: provider) — fires on pointerup. The runtime
`commit-set` handler is wired to call the consumer's `onResizeEnd`
callback, so sema and JS callback land at the same moment (parity
with Slider's `onValueCommit`).
Soma provider triggers these via `this.runtime.trigger(name)` in
`onpointerdown` / `onpointermove` / `notifyResizeEnd` (the latter
unchanged externally — internally now routes through the runtime
trigger).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>