Status: Canonical (v1.0)
Last updated: December 17, 2025
Audience: Design Systems, Product Design, Front-End Engineering
Applies to: Modality-neutral interactive operability (pointer, touch, stylus, gaze, switch, remote)
Companion specs:
cem-colors) — color intensity perception affected by densitycem-dimension) — gaps/insets/rhythm; must never violate D2 safety minimumscem-controls) — visual control geometry (--cem-control-*, icon-button, row heights) and per-mode visual overridescem-shape) — bend consumes --cem-control-height from D2c Controls for round-endscem-layering) — overlay/modal control sizingcem-stroke) — focus ring offset; D2 constrains adjacent zones so indicators have roomcem-timing) — timing for density transitionsIn CEM terms, coupling names the moment when user intent successfully binds to an interactive affordance—independent of input modality:
This supports the UI-space meaning you called out: proximity implies relationship/coupling between controls, and insufficient distancing causes interference.
D2. Coupling & Compactness (this canvas)
D2c. Controls (from cem-controls)
D1. Space & Rhythm (from cem-dimension)
D5. Stroke & Separation (from cem-stroke)
--cem-stroke-focus, --cem-stroke-indicator-offset, zebra ring tokens)Boundary heuristic:
cem-controls)--cem-stroke-focus, --cem-stroke-indicator-offset)To keep the naming dimensional and unambiguous, use three core nouns:
These values are mode-invariant — density modes MUST NOT change zone-min or guard-min.
| Token | Value | Description | tier |
|---|---|---|---|
--cem-coupling-zone-min |
3rem |
Minimum operable zone in both dimensions; nominally 48 px @ 16 px root | required |
--cem-coupling-guard-min |
0.5rem |
Minimum distancing between adjacent operable zones; nominally 8 px | required |
--cem-coupling-halo |
0.25rem |
Invisible expansion beyond visuals; may vary by mode (nominally 4 px) | required |
Interpretation:
Accessibility baseline:
--cem-coupling-zone-min: 3rem (48 px at a 16 px root).
This aligns with common Android / Material-style 48dp touch-target guidance and gives room for touch, stylus,
gaze/dwell, remote focus, and switch-scanning contexts.--cem-coupling-guard-min: 0.5rem (8 px at a 16 px root) aligns with common 8dp spacing guidance and prevents
adjacent operable zones or external focus indicators from visually or functionally colliding.When D5 indicators render outside the control edge (e.g., outline-offset, zebra rings),
--cem-coupling-guard-min SHOULD be large enough to prevent indicator collisions between adjacent controls.
Define the worst-case outward indicator extent as:
4 * --cem-zebra-strip-size--cem-stroke-indicator-offset + --cem-stroke-focusCompatibility guideline:
--cem-coupling-guard-min SHOULD be ≥
max(4 * --cem-zebra-strip-size, --cem-stroke-indicator-offset + --cem-stroke-focus)
Default CEM values satisfy this (8px guard vs 8px zebra extent when --cem-zebra-strip-size = 2px).
Visual control geometry — --cem-control-height, --cem-control-padding-x, --cem-control-padding-y,
--cem-icon-button-size, --cem-icon-button-icon-size, and the list/menu/table row heights — is defined and
governed in D2c Controls (cem-controls).
D2 references this geometry only as a normative constraint: visual sizes MUST NOT shrink the operable zone below
--cem-coupling-zone-min, and adjacent layouts MUST NOT shrink distancing below --cem-coupling-guard-min,
regardless of how Controls geometry varies across coupling modes. When visuals fall below the zone, components MUST
use halo expansion (see §6.1).
Coupling-mode overrides for visual geometry live in D2c Controls; D2 owns only the operability portions of mode behavior (halo policy, see §5).
forgiving
balanced
compact
D2 owns only the halo portion of mode behavior. Visual geometry overrides live in D2c Controls
(see cem-controls §3.2).
:root { --cem-coupling: balanced; }
:root[data-cem-coupling="balanced"] { /* baseline halo */ }
:root[data-cem-coupling="forgiving"] {
/* Visuals are larger (D2c); halo can be smaller because visuals already meet the zone */
--cem-coupling-halo: 0.125rem;
}
:root[data-cem-coupling="compact"] {
/* Visuals shrink (D2c); halo grows to preserve the operable zone */
--cem-coupling-halo: 0.375rem;
}
| Token | forgiving | compact |
|---|---|---|
--cem-coupling-halo |
0.125rem |
0.375rem |
Governance rule: do not reduce --cem-coupling-zone-min or --cem-coupling-guard-min per mode. Visual geometry
overrides are governed in D2c Controls.
--cem-control-padding-* come from D2c Controls; the safety floor (min-block-size: --cem-coupling-zone-min) is the
D2 contribution.
Token generation is necessary but not sufficient. A component is only coupling-safe when its rendered implementation preserves the zone, guard, and halo contract:
min-block-size and min-inline-size when the visible element itself owns the operable zone.gap = max(layout-gap, guard-min), not as a raw D1 spacing token..cem-control {
min-inline-size: var(--cem-coupling-zone-min);
min-block-size: var(--cem-coupling-zone-min);
padding-inline: var(--cem-control-padding-x);
padding-block: var(--cem-control-padding-y);
}
/* Optional: halo expansion when visible chrome is smaller than the operable contract */
.cem-coupling-halo {
position: relative;
}
.cem-coupling-halo::after {
content: "";
position: absolute;
inset: calc(-1 * var(--cem-coupling-halo));
background: transparent;
pointer-events: auto;
}
.cem-actions {
display: flex;
gap: max(var(--cem-gap-related, 0px), var(--cem-coupling-guard-min));
}
If you want proximity to intentionally communicate relationship, add an optional D1/D2 bridge token set:
:root {
/* Within this distance, controls are perceived as a group (segmented, paired actions). */
--cem-coupling-affinity-max: 0.375rem;
/* Beyond this distance, controls read as independent. */
--cem-coupling-decouple-min: 0.75rem;
}
Guidance:
guard is safety; affinity/decouple is meaning.data-cem-coupling="forgiving|balanced|compact" to the library’s density knob.Example mapping guidance:
(Exact numeric mapping remains an implementation choice per Angular Material version.)
coupling (semantic), with exactly three modes: forgiving | balanced | compactrem for all coupling and geometry valuesA draft becomes “canonical” when all of the following are true:
Minimal core: only these coupling policy anchors are required:
--cem-coupling-zone-min--cem-coupling-guard-min--cem-coupling-haloInvariants are explicit:
zone-min and guard-min are mode-invariantOrthogonality is enforceable:
gap = max(D1 gap, D2 guard)Component mapping is possible without special cases:
Accessibility posture is documented:
| Mode | Product intent | Visual geometry | Halo (--cem-coupling-halo) |
Typical surfaces |
|---|---|---|---|---|
forgiving |
Minimize mis-coupling for imprecise input | Larger controls/rows; more internal padding | Smaller (visuals already meet zone) | mobile-first, kiosks, accessibility-first, gaze/dwell |
balanced |
General default across modalities | Baseline control heights/rows | Baseline | mixed pointer + touch, general app UI |
compact |
Increase information density without breaking operability | Smaller visual heights/rows; reduced chrome | Larger (use halo to preserve zone) | data grids, admin tools, scan-heavy panels |
Normative rule:
--cem-coupling-zone-min and --cem-coupling-guard-min are mode-invariant.Use this checklist to implement Coupling consistently. The same rules apply whether input is pointer, touch, stylus, gaze, switch scanning, or remote focus.
--cem-coupling-zone-min in both dimensions or be wrapped/expanded so the operable zone meets the minimum.--cem-coupling-guard-min between their operable zones.compact).min-block-size to --cem-coupling-zone-min (or set visible height ≥ zone-min).--cem-control-height and --cem-control-padding-* for visual sizing; do not shrink below operability. These
tokens are owned by D2c Controls (see cem-controls).gap (or dividers) that respects --cem-coupling-guard-min.--cem-coupling-zone-min.zone-min in compact, but operability must still meet zone-min via:
zone-min where the row itself is the interactive affordance.gap or reserved spacing to avoid interference.--cem-table-row-height (owned by D2c Controls) to be below zone-min only if row actions / selection / checkboxes still meet the zone rule via:
Validate each mode on at least one representative surface:
Pass criteria:
guard-mincem-stroke §5 for focus indicator thickness)Use a text field, primary action, and icon action in one row. This validates mixed-width controls and compact visual chrome.
.cem-proof-form-trio {
display: flex;
align-items: center;
gap: max(var(--cem-gap-related, 0px), var(--cem-coupling-guard-min));
}
.cem-proof-form-trio :is(input, button) {
min-block-size: var(--cem-coupling-zone-min);
}
.cem-proof-form-trio .cem-icon-button {
min-inline-size: var(--cem-coupling-zone-min);
min-block-size: var(--cem-coupling-zone-min);
}
Checks:
--cem-coupling-guard-min.Use interactive rows with a trailing action cluster. This validates row affordances plus nested controls.
.cem-proof-nav-list {
display: grid;
gap: max(var(--cem-gap-related, 0px), var(--cem-coupling-guard-min));
}
.cem-proof-nav-row {
min-block-size: var(--cem-coupling-zone-min);
display: grid;
grid-template-columns: 1fr auto;
align-items: center;
column-gap: max(var(--cem-gap-related, 0px), var(--cem-coupling-guard-min));
}
.cem-proof-nav-actions {
display: flex;
gap: max(var(--cem-gap-related, 0px), var(--cem-coupling-guard-min));
}
Checks:
compact, reduced row chrome does not reduce the operable zone.Use a dense data row with selection and inline row actions. This validates the hardest scan-heavy layout.
.cem-proof-data-row {
min-block-size: var(--cem-table-row-height);
}
.cem-proof-data-row :is(input[type="checkbox"], button, a) {
min-inline-size: var(--cem-coupling-zone-min);
min-block-size: var(--cem-coupling-zone-min);
}
.cem-proof-data-actions {
display: flex;
gap: max(var(--cem-gap-related, 0px), var(--cem-coupling-guard-min));
}
Checks:
--cem-coupling-zone-min, but row selection and row actions still
expose full operable zones.| Source table | Section | Description |
|---|---|---|
cem-coupling-minimums |
§4.1 | Hard safety minimums: --cem-coupling-zone-min, --cem-coupling-guard-min, --cem-coupling-halo (mode-invariant safety contract) |
cem-coupling-halo-overrides |
§5.2 | Forgiving/compact override values for --cem-coupling-halo only (generator-only; no new tokens) |
Generator derivation rules:
cem-coupling-minimums → token list (tier in last column).cem-coupling-halo-overrides → override data only; the token is already declared in the base :root block.zone-min and guard-min are never overridden per mode (mode-invariant).--cem-control-*, --cem-icon-button-*, row heights) is owned by D2c Controls and is NOT
declared by this generator. See cem-controls §7.