* M5: Locked layers follow Figma's rules: no nudge, a locked parent's children stay locked (#1560)
Pins Figma's locked-layer behaviour (measured in Figma's web app, 2026-11-10; help center "Lock and unlock layers") in a new lock_behaviour_tests suite. Fixes the divergences: transform.nudge and transform.nudgeSize skip locked layers, object.toggleLock without a value counts a child of a locked parent as locked (so it never locks the child on its own), and the Layers panel padlock on such a child is inert.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Model-Effort: Opus 5.5 drove; Fable 5.1 briefed; Sonnet 5.5 wrote at medium
* Layers panel: a padlock sweep skips the children of a locked layer (#1560)
A padlock drag sweep no longer collects rows with `locked_above`, so
dragging across a locked frame's children leaves their own flags alone
and draws no swept value on them. An eye sweep is unchanged.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Model-Effort: Opus 5.5 drove; Opus 5.5 briefed; Sonnet 5.5 wrote at medium
* M5: Lock/Unlock leaves a locked layer's child alone in a mixed selection (#1560)
With a locked frame's child and an unlocked layer selected, Lock/Unlock set both own flags, so
the child stayed locked once the frame was unlocked. With no explicit `locked` value, the command
now skips a layer whose parent is locked, as its padlock does; an explicit value (scripts) still
sets it.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Model-Effort: Opus 5.5 drove and wrote
---------
Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-authored-by: FredApps <FredApps@users.noreply.github.com>
fit_selection checks every coordinate is finite (a NaN y or x1 left a NaN centre) and leaves the view as it is for such a rectangle. A point selection is centred in the area above the toolbar at its zoom, not in the whole viewport. Tests pin the exact short-canvas and no-inset positions, the narrow-canvas margins, lines, tiny and huge rectangles, the bottomInset clamp and that it is never saved, the unchanged Zoom to fit centre, the pill strip the app hands the engine (shown and hidden), and the Shift+2 centre without reading the inset back.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Model-Effort: Opus 5.5 triaged and briefed; Sonnet 5.5 verified and wrote at medium
The inset was clamped to leave 100 points and the fit kept at least 50, so in a canvas 130
points high the selection ended behind the toolbar. The real inset is kept and the margin
shrinks to a quarter of the area when 40 points a side does not fit.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Model-Effort: Opus 5.5 drove and wrote
Figma holds a US registration for DEV MODE (US 7574348). Display text only: the view.devMode label, Inspect tab, shortcut row, refusal messages, CLI help, docs and all locale catalogs now say Developer Mode. Command ids, preference keys and saved fields are unchanged; "Dev Mode" stays a search alias in the Actions palette. Adds a naming guard test.
Drops the "Figma-class" self-description from the MCP instructions and the "Accessibility at Figma" aside from pref.uiScaleUp help. Help text only; ids and preference keys unchanged. Adds a display-name guard over mcp/src and engine/src/cmd string literals.
Zoom to selection (Shift+2) fits the selection into the canvas above the floating bottom toolbar with a 40 pt margin on all sides, centred in that area (measured in Figma's web app, 2026-11-09). ViewState gains an unsaved bottom_inset, set by the UI each frame from the toolbar pill and by view.set bottomInset. Zoom to fit is unchanged.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Model-Effort: Opus 5.5 drove and briefed; Sonnet 5.5 measured and wrote at medium
Found while testing crates/engine/src/dev/tailwind.rs:300 (the "font-family" arm, via arb at :103)
Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>