LAWSOFUX · motion lab
Concept · von-restorff-effect

Von Restorff Effect

Grid stagger reveal palette · forest / cream takeaways · 4

Definition

An item that visually departs from its peers is remembered better than any of the peers. The isolation does the memory work — color, size, position, motion. Use it sparingly; once everything is emphasized, nothing is.

Why it matters for ShurIQ reports

The hero score, the moved competitor row, the contradicted assumption — each is a candidate for von Restorff treatment. A subtle accent color on a single delta marker, or a slightly larger gap card for the lead insight, will be recalled long after the rest of the brief has faded. The discipline is to use the effect at most once per surface.

Takeaways

Visual motion language

The stand-out element uses a one-time glow-burst with color-emphasis on entry, then settles into a slightly elevated steady state (1.05× scale or 8% lighter background). The arrival is the memory moment.

Cavalry recreation seed. 4×4 grid of 80×80 dark-green squares, 8px stroke, 100px spacing. All fade in together over 800ms. At t=1.1s replace the row-3-col-3 cell with a cream circle ø60 — scale 0→1 with elastic overshoot over 600ms. Hold 3s. Loop with brief 800ms reset where the cream circle shrinks back and the dark square reappears.

Origins

Hedwig von Restorff, 1933 — German psychiatrist whose memory study formalized the isolation effect.

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 · von-restorff-effect · Cavalry scene
// Motion family: grid-stagger (uniform grid + isolated different element)
// 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_von-restorff-effect_";

  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 });

  var COLS = 4, ROWS = 4, SIZE = 80, GAP = 20;
  var SPACE = SIZE + GAP;
  var startX = -((COLS - 1) * SPACE) / 2;
  var startY =  ((ROWS - 1) * SPACE) / 2;

  var oddRow = 2, oddCol = 2; // 0-indexed: row 3 col 3 in 1-indexed

  for (var r = 0; r < ROWS; r++) {
    for (var c = 0; c < COLS; c++) {
      if (r === oddRow && c === oddCol) continue; // skip — replaced by circle
      var sq = api.primitive("rectangle", PREFIX + "sq_" + r + "_" + c);
      api.set(sq, {
        "generator.dimensions": [SIZE, SIZE],
        "position.x": startX + c * SPACE,
        "position.y": startY - r * SPACE,
        "opacity": 0
      });
      api.setFill(sq, false);
      api.setStroke(sq, true);
      api.set(sq, { "stroke.strokeColor": DARK, "stroke.width": 8 });
      api.keyframe(sq, 0,  { "opacity": 0   });
      api.keyframe(sq, 18, { "opacity": 100 });
    }
  }

  // The "different" element: cream circle
  var hero = api.primitive("ellipse", PREFIX + "hero");
  api.set(hero, {
    "generator.radius": [30, 30],
    "position.x": startX + oddCol * SPACE,
    "position.y": startY - oddRow * SPACE,
    "opacity": 0,
    "scale.x": 0.0, "scale.y": 0.0
  });
  api.setFill(hero, true);
  api.set(hero, { "material.materialColor": CREAM });
  api.keyframe(hero, 24, { "opacity": 0,   "scale.x": 0.0, "scale.y": 0.0 });
  api.keyframe(hero, 38, { "opacity": 100, "scale.x": 1.2, "scale.y": 1.2 });
  api.keyframe(hero, 48, { "opacity": 100, "scale.x": 1.0, "scale.y": 1.0 });
  api.magicEasing(hero, "scale.x", 38, "EaseOut", "");
  api.magicEasing(hero, "scale.y", 38, "EaseOut", "");

  // Sustain pulse
  api.keyframe(hero, 72,  { "scale.x": 1.0,  "scale.y": 1.0  });
  api.keyframe(hero, 96,  { "scale.x": 1.08, "scale.y": 1.08 });
  api.keyframe(hero, 120, { "scale.x": 1.0,  "scale.y": 1.0  });

  var layerCount = api.getAllSceneLayers().length;
  console.log("scene built: von-restorff-effect (" + layerCount + " layers)");
})();