Definition
The brain narrows its perceptual focus to a subset of incoming signals — usually the ones aligned with current goals — and filters out the rest. This filter explains banner blindness, change blindness, and why critical alerts can sit on screen unread. Anything that looks like noise will be treated as noise.
Why it matters for ShurIQ reports
A reader scanning for the recommendation will skip past anything that visually resembles boilerplate. Critical changes (a competitor's score moved, an evidence chain updated) need a distinct visual register that does not mimic decoration or chrome. If a delta marker looks like a tooltip, it will be ignored.
Takeaways
- Style critical changes in a register reserved exclusively for them — never share the visual treatment of decorative elements.
- Avoid placing meaningful content in zones the reader has trained themselves to ignore (top-banner, right-rail).
- For change blindness, animate transitions at a pace the reader can follow; instant swaps go unseen.
- Test for accidental similarity between alert states and ad-like placements; banner blindness is real and ruthless.
Visual motion language
Critical change uses a glow-burst paired with color-emphasis on the changed value, holding 1s before resolving. Non-critical updates opacity-decay quietly so attention is not stolen.
Origins
Donald Broadbent's Filter Theory, 1958 — followed by Cherry, Treisman, and Kahneman through the 1960s and 1970s.
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 · selective-attention · Cavalry scene
// Motion family: single-form (stacked dome bands with traveling highlight)
// Palette: sage-grey + 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_selective-attention_";
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 = "#4A5A4A";
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 });
// 12 horizontal bands forming a half-circle dome profile
var N = 12;
var BAND_H = 28;
var TOTAL_H = N * BAND_H;
var startY = (TOTAL_H / 2) - BAND_H / 2;
for (var i = 0; i < N; i++) {
// Width follows half-circle profile: max at middle (index N/2)
var t = i / (N - 1); // 0..1
var phase = t * Math.PI; // 0..π
var w = Math.sin(phase) * 380 + 50;
var b = api.primitive("rectangle", PREFIX + "band_" + i);
api.set(b, {
"generator.dimensions": [w, BAND_H - 4],
"position.x": 0,
"position.y": startY - i * BAND_H,
"opacity": 40
});
api.setFill(b, true);
api.set(b, { "material.materialColor": CREAM });
// Initial fade-in
api.keyframe(b, 0, { "opacity": 0 });
api.keyframe(b, 18, { "opacity": 40 });
// Traveling highlight: each band brightens at its own frame
var hlFrame = 30 + i * 4;
api.keyframe(b, hlFrame, { "opacity": 40 });
api.keyframe(b, hlFrame + 5, { "opacity": 100 });
api.keyframe(b, hlFrame + 10, { "opacity": 40 });
}
var layerCount = api.getAllSceneLayers().length;
console.log("scene built: selective-attention (" + layerCount + " layers)");
})();