design language · density kernel (2026-09-05)
2xs — the fifth rung: operation density for pro tools
Below xs sits one more rung, and only one: 2xs trades comfort for information density where the audience is a professional non-touch pointer user — inspector panels, data grids, tool palettes (IDE layers panels, Figma property panels). Every number is still an equation from the ruler: text 10px, lines 14px, rows 24px, and the sheet's ONE scoped law — the hit floor redeclares at 6U (24px, the WCAG 2.5.8 AA minimum) inside the scope, because a 2xs subtree is by construction a non-touch surface. Opt-in only, never the default: this page is the rung's standard and its acceptance demo.
the scale
Five rungs, computed live — not copied
Every bar below consumes its --jx-* alias directly inside each rung's own [data-density] scope, and the numbers are measured used values in this very page (the kernel gate's technique in real Chromium) — move the kernel and this table moves with it; it cannot rot. G stays 8px at 2xs on purpose: the xs optical floor holds one step further down (text needs its gutter, and B = G means the inset cannot shrink alone) — the compactness comes from text and block, not the inline axis.
- 2xs's hit-min (24px) is the ONE scoped floor:
--jx-hit-floorredeclares at 6U inside[data-density='2xs']; every other rung and every unpinned read keep the :root 7U guardrail (28px) - 2xs's secondary text is honestly degenerate — max(0.625rem, 9px) = 10px = the primary size; differentiate secondary roles by ink, never by size, below xs
the scene
The same inspector at 2xs and at default
A plausible pro-tool inspector — a layers list, property rows with selects, a tool strip — built from real registry components (the Item family, Select, PressButton, Badge, Kbd). Left: the whole panel inside a 2xs scope. Right: the identical scene at default density. Nothing per-size in any component's css; one attribute moves every row.
the inspector scene — 2xs beside default
A plausible pro-tool inspector composed from real registry components: left inside a data-density='2xs' scope, right identical at default. One attribute moves every row; nothing per-size exists in any component's css. The drawer carries the sheet's REAL 2xs scope block (live extract from jixoai.css) — the scoped 24px hit floor and every alias the stage consumes.
- inspector/shell frame · 4 constraintslocked ⌥1
- inspector/rows list · virtualized⌥2
- scrim/hover overlay · pass-through⌥3
- palette/text tokens · 12 refslocked ⌥4
- normal
- multiply
- screen
- overlay
- solid
- gradient
- none
- inspector/shell frame · 4 constraintslocked ⌥1
- inspector/rows list · virtualized⌥2
- scrim/hover overlay · pass-through⌥3
- palette/text tokens · 12 refslocked ⌥4
- normal
- multiply
- screen
- overlay
- solid
- gradient
- none
/* ── the 2xs scope (2026-09-05-density-2xs) — the pro-tool extreme.
The ONE scoped floor in the sheet (the canvas-bug law: custom
properties substitute their var() at the DECLARING element, so a
:root-only hit-min would hand descendants the root-substituted
28px whatever this scope says): the scope redeclares BOTH the
floor and the 2xs hit-min — inside it the guardrail is 6U = 24px,
the WCAG 2.5.8 AA minimum, the deliberate pro-pointer stance for
non-touch operation surfaces (the adoption law: opt-in only,
never default). The §4 coefficient carrier (2026-09-21) keeps the
scoped floor law intact: --jx-hit's frozen triple-max reads
var(--jx-hit-floor) — resolved against THIS scope's 6U — and the
kernel internal --jx-density-hit-min-2xs stays redeclared (the
kernel's own, unfazed by the split). Placement keeps the chrome
scope pinned AFTER every density scope (:where() source order). */
:where([data-density='2xs']) {
--jx-hit-floor: calc(var(--jx-unit) * 6); /* scoped: 24px = WCAG 2.5.8 AA */
--jx-density-hit-min-2xs: max(var(--jx-density-row-min-2xs), var(--jx-hit-floor));
--jx-text: calc(var(--jx-density-text-2xs) * var(--jx-density-coefficient, 1));
--jx-leading-base: var(--jx-density-leading-2xs);
--jx-leading: calc(var(--jx-leading-base) * var(--jx-density-coefficient, 1));
--jx-line-base: var(--jx-density-line-2xs);
--jx-line: calc(var(--jx-line-base) * var(--jx-density-coefficient, 1));
--jx-gap-base: var(--jx-density-inline-gap-2xs);
--jx-gap: calc(var(--jx-gap-base) * var(--jx-density-coefficient, 1));
--jx-media-gutter-base: var(--jx-density-media-gutter-2xs);
--jx-media-gutter: calc(var(--jx-media-gutter-base) * var(--jx-density-coefficient, 1));
--jx-gap-end-base: var(--jx-density-end-gap-2xs);
--jx-gap-end: calc(var(--jx-gap-end-base) * var(--jx-density-coefficient, 1));
--jx-stack-base: var(--jx-density-stack-gap-2xs);
--jx-stack: calc(var(--jx-stack-base) * var(--jx-density-coefficient, 1));
--jx-inset-base: var(--jx-density-inline-inset-2xs);
--jx-inset: calc(var(--jx-inset-base) * var(--jx-density-coefficient, 1));
--jx-chip-radius-base: var(--jx-density-chip-radius-2xs);
--jx-chip-radius: calc(var(--jx-chip-radius-base) * var(--jx-density-coefficient, 1));
--jx-gap-content-base: var(--jx-density-content-gap-2xs);
--jx-gap-content: calc(var(--jx-gap-content-base) * var(--jx-density-coefficient, 1));
--jx-row-min: max(
calc(var(--jx-unit) * var(--jx-density-row-floor-2xs)),
calc(
(var(--jx-density-line-2xs) + var(--jx-density-stack-gap-2xs) + var(--jx-density-stack-gap-2xs)) *
var(--jx-density-coefficient, 1)
)
);
--jx-hit: max(
var(--jx-hit-floor),
calc(var(--jx-unit) * var(--jx-density-row-floor-2xs)),
calc(
(var(--jx-density-line-2xs) + var(--jx-density-stack-gap-2xs) + var(--jx-density-stack-gap-2xs)) *
var(--jx-density-coefficient, 1)
)
);
--jx-icon-base: var(--jx-density-media-icon-2xs);
--jx-icon: calc(var(--jx-icon-base) * var(--jx-density-coefficient, 1));
--jx-image-base: var(--jx-density-media-image-2xs);
--jx-image: calc(var(--jx-image-base) * var(--jx-density-coefficient, 1));
--jx-text-secondary-base: var(--jx-density-secondary-text-2xs);
--jx-text-secondary: calc(var(--jx-text-secondary-base) * var(--jx-density-coefficient, 1));
--jx-leading-secondary-base: var(--jx-density-secondary-leading-lg);
--jx-leading-secondary: calc(var(--jx-leading-secondary-base) * var(--jx-density-coefficient, 1));
--jx-line-secondary-base: var(--jx-density-secondary-line-2xs);
--jx-line-secondary: calc(var(--jx-line-secondary-base) * var(--jx-density-coefficient, 1));
--jx-toggle-track: var(--jx-line);
--jx-toggle-width: calc(var(--jx-toggle-track) * 2);
--jx-toggle-knob: calc(var(--jx-toggle-track) - var(--jx-unit));
--jx-slider-track: max(var(--jx-unit), calc(var(--jx-line) / 2));
--jx-textarea-min: max(var(--jx-hit), calc(var(--jx-line) * 3 + var(--jx-stack) * 2 + 2px));
--jx-color-lane: max(var(--jx-hit), calc(var(--jx-icon) + var(--jx-inset) * 2 + 2px));
}- what to see at 2xs: 24px rows (down from 40), 10px body text, 14px icons, 28px images — and hit lanes that stop at 24px, the scoped floor, instead of re-inflating to the 28px guardrail
- the two selects share one bound state with this page — the scene is live, not a screenshot; toggle them
law
The adoption law — opt-in operation surfaces only
2xs is a scoped tool, not a product-wide mood. FOR: professional non-touch high-density operation surfaces — inspector panels, property rows, data grids, tool palettes, layers lists — where information density IS the feature and the pointer is precise. NEVER: general marketing or docs UI, prose surfaces, touch-first flows, auth or checkout. NOT the default anywhere: DEFAULT_DENSITY stays 'default', no family fallback becomes 2xs, the canvas stage's density select keeps the standard four stops (xs/sm/default/lg). xs keeps its own role (dense non-touch metadata surfaces); 2xs goes further (operation surfaces) — a product can run an xs nav rail beside a 2xs inspector.
T_2xs = T_base − 3·U/4 → 10px (the pro-tool body; 9px stays UNSHIPPED)
L_2xs = T_2xs × 14/10 → 14px (integer line, the xs precedent)
G_2xs = U × 2 → 8px B_2xs = G_2xs (THE balance invariant —
the inset cannot shrink without
hurting every control at once)
S_2xs = U × 1 → 4px
contentGap = max(U/2, S/2) → 2px
rowMin = max(L + 2·S, 6·U) → max(22, 24) = 24px (the floor side wins —
pinned AT WCAG 2.5.8 AA)
hitMin = max(rowMin, hitFloor) → 24px INSIDE the scope — the ONE scoped floor
(--jx-hit-floor: 6U inside [data-density='2xs'];
the :root guardrail stays 7U everywhere else)
icon = L → 14px · image = 2L → 28px · media gutter = G = 8px
secondary = max(0.625rem, T − U/4) → 10px — DEGENERATE: equals the primary size,
the role distinction dies at its floor<!-- the whole opt-in: ONE attribute on the operation-surface root -->
<section data-density="2xs">
<!-- layers list, property rows, tool palettes — every child scales -->
</section>
<!-- component opinion: the same single prop as any rung -->
<ItemGroup density="2xs"><!-- … --></ItemGroup>- the scoped floor is the sheet's ONLY scoped floor — legal because stamping
data-density='2xs'declares the modality (professional non-touch pointer), the same opt-in semantics the 2026-08-29 ruling established for the 28px guardrail; 24px still satisfies WCAG 2.5.8 AA - 9px body exists in the grammar (one more −U/4 step) and stays UNSHIPPED — going below 10px is a new ruling, not a parameter tweak
- verified: the kernel gate asserts the whole 2xs row in real Chromium
(
node scripts/verify-density-kernel.mjs), and the context specs lock resolution + stamping — see the changeopenspec/changes/2026-09-05-density-2xs