Definition
Elements enclosed inside a shared boundary are read as belonging together, regardless of their visual similarity. A border, a tinted background, or a card edge is enough to forge a group in the reader's eye. The boundary does the grouping work without any other cue.
Why it matters for ShurIQ reports
Gap cards, evidence panels, and stack-rank rows all rely on bounded regions to communicate "this is one unit of meaning." A faint card border or a 4% tinted background is what turns a wall of data into discrete claims. Lose the bounding and the report dissolves into noise; over-bound it and every card competes for attention.
Takeaways
- Use one bounding technique per region (border or background — not both) to avoid visual stacking.
- Make boundaries quiet: 8–12% opacity backgrounds, 1px hairline borders. The boundary's job is to group, not to shout.
- Nest boundaries only one level deep; cards-within-cards-within-cards collapses the grouping signal.
- When two adjacent regions belong to different sections, increase the gap before increasing the boundary contrast.
Visual motion language
Cards animate in with a bounded-region reveal — the boundary draws first, then the contents fade in. The sequence makes group membership the reader's first impression.
Origins
Gestalt psychology — early 20th century perceptual organization research.
Cavalry scene
The script below builds this concept's motion in Cavalry through the Stallion bridge. Pipe to cavalry_run_script via MCP, or paste into Cavalry's JavaScript Editor.
// Laws of UX · law-of-common-region · Cavalry scene
// Motion family: single-form (square outline + 3x3 grid + center pulse)
// Palette: forest-green + cream
// To run: pipe to cavalry_run_script tool, or paste into Cavalry's JavaScript Editor
// Built 2026-04-30 by ShurAI
(function () {
var PREFIX = "claude_lawofux_law-of-common-region_";
var existing = api.getAllSceneLayers();
for (var i = 0; i < existing.length; i++) {
try {
var nm = api.getNiceName(existing[i]);
if (nm && nm.indexOf("claude_lawofux_") === 0) api.deleteLayer(existing[i]);
} catch (e) {}
}
var BG = "#2D5A3F";
var DARK = "#1E4530";
var CREAM = "#D6CDB0";
var bg = api.primitive("rectangle", PREFIX + "bg");
api.set(bg, { "generator.dimensions": [1080, 1080] });
api.setFill(bg, true);
api.set(bg, { "material.materialColor": BG });
// Outer container square outline
var box = api.primitive("rectangle", PREFIX + "box");
api.set(box, {
"generator.dimensions": [400, 400],
"position.x": 0, "position.y": 0,
"opacity": 0
});
api.setFill(box, false);
api.setStroke(box, true);
api.set(box, { "stroke.strokeColor": CREAM, "stroke.width": 10 });
api.keyframe(box, 0, { "opacity": 0 });
api.keyframe(box, 18, { "opacity": 60 });
// 3x3 grid of dots
var COLS = 3, ROWS = 3, SPACE = 110, R = 22;
var startX = -((COLS - 1) * SPACE) / 2;
var startY = ((ROWS - 1) * SPACE) / 2;
for (var r = 0; r < ROWS; r++) {
for (var c = 0; c < COLS; c++) {
var d = api.primitive("ellipse", PREFIX + "dot_" + r + "_" + c);
var isCenter = (r === 1 && c === 1);
api.set(d, {
"generator.radius": [R, R],
"position.x": startX + c * SPACE,
"position.y": startY - r * SPACE,
"opacity": 0
});
api.setFill(d, true);
api.set(d, { "material.materialColor": isCenter ? CREAM : DARK });
var inF = 12 + (r * 3 + c) * 2;
api.keyframe(d, inF, { "opacity": 0 });
api.keyframe(d, inF + 10, { "opacity": 100 });
if (isCenter) {
api.keyframe(d, 60, { "scale.x": 1.0, "scale.y": 1.0 });
api.keyframe(d, 90, { "scale.x": 1.15, "scale.y": 1.15 });
api.keyframe(d, 120, { "scale.x": 1.0, "scale.y": 1.0 });
}
}
}
// Stroke opacity oscillation on box
api.keyframe(box, 30, { "opacity": 100 });
api.keyframe(box, 60, { "opacity": 60 });
api.keyframe(box, 90, { "opacity": 100 });
api.keyframe(box, 120, { "opacity": 60 });
var layerCount = api.getAllSceneLayers().length;
console.log("scene built: law-of-common-region (" + layerCount + " layers)");
})();