# Figma Overlay Check

> Overlay a matching Figma design on a local webpage target. Use a DOM node selected in Cursor, Codex, browser tooling, or another AI environment when supplied; otherwise locate a module from a user screenshot, correcting small crop errors; when neither is supplied, default to whole-page comparison. Use for design QA, pixel-perfect review, "overlay comparison", "design diff", "还原度", or "叠图比对" requests. Requires a locally runnable web project, Figma MCP, and browser automation.

- Skill: `dengshangli/figma-overlay-check` (Agent Skill, multi-file: 15 files)
- Install (CLI): `npx skillmds@latest add dengshangli/figma-overlay-check`
- Raw SKILL.md: https://api.skillmd.com/api/skills/dengshangli/figma-overlay-check/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Design & Media
- Author: dengshangli (https://skillmd.com/u/dengshangli)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/dengshangli/figma-overlay-check

---


# Figma Target Overlay Check

Choose the target automatically: use an explicit **AI/tool-selected DOM node** first, otherwise use a **screenshot locator**, and default to the **whole page** when the user supplied neither. A selected rendered DOM node is authoritative. A screenshot helps find a module but does not define its final boundary. Whole-page mode matches the complete rendered page to a page-level Figma Frame.

Keep every comparison-only file under `<project-root>/.figma-overlay-check/`. Add one marked side-effect import to the browser entry. Leave the overlay active until the user explicitly asks the AI in conversation to delete or remove it.

## Required outcome

- Accept a user-provided module screenshot or the current DOM selection exposed by Cursor, Codex, browser tooling, or another AI host; default to whole-page comparison when neither was supplied.
- Use an available selected element handle, browser locator, CSS selector, inspected-element reference, or source-linked DOM selection directly; do not require a screenshot in DOM-selection mode.
- For screenshot input, automatically locate the module and identify one stable DOM element that owns the complete module.
- Automatically locate the corresponding Figma Frame, Component, Instance, or Section and export that exact node as PNG. In whole-page mode, use the complete page-level Frame.
- Correct small boundary mistakes: discard neighboring page content from an over-cropped screenshot and restore omitted module edges from the complete DOM/Figma nodes.
- Overlay only the matched target, at its logical Figma size, with its top-left edge aligned to the live target's top-left edge.
- Expose matching evidence and confidence. Never silently choose among materially ambiguous targets.
- Perform one grouped automatic UI correction pass unless the user explicitly requests review-only behavior.
- Keep the implementation semantic. Never replace ordinary UI with a flattened image.
- Create exactly one temporary overlay source file and one exported Figma design image.
- Put all generated source, screenshots, crops, diffs, dependencies, and manifest files inside `.figma-overlay-check/`.
- Add the exact `.figma-overlay-check/` rule to the project-root `.gitignore` idempotently.
- Keep the draggable, collapsible overlay panel focused on comparison controls; do not expose a delete action in the page UI.
- Let the user switch repeatedly to a newly selected DOM node, screenshot, or explicit whole-page target without deleting the active overlay between targets.
- Do not commit comparison-only files unless explicitly requested.

## Workflow

```text
Task Progress:
- [ ] Step 1: Resolve selected-DOM, screenshot, or default whole-page mode
- [ ] Step 2: Verify and capture the live DOM target
- [ ] Step 3: Match and export the complete Figma target node
- [ ] Step 4: Install and geometrically verify the target overlay
- [ ] Step 5: Run one automatic correction pass and verify it
- [ ] Step 6: Record deletion state and leave the overlay active
```

## Step 1: Resolve the target input

Choose exactly one input mode with this precedence:

1. An explicitly supplied DOM selection, locator, or selector.
2. A supplied screenshot.
3. `full-page` when the user supplied neither.

Before applying that precedence, inspect `.figma-overlay-check/.figma-overlay-state.json`. If a valid active session exists and the user supplied no **new** target, continue the current target; do not reinterpret the absence of new input as a switch to `full-page`. Enter `full-page` by default only on the initial invocation with no active session, or when the user explicitly asks to switch to the whole page.

If the user explicitly refers to a selected node but the host does not expose it, ask for a selector or screenshot. That is a failed DOM-selection input, not permission to silently switch to whole-page mode.

### Mode A: AI/tool-selected DOM node

Cursor, Codex, browser developer tools, browser automation, and other AI environments expose selections differently. Use the strongest selection reference the host actually provides:

1. a live element handle or browser locator;
2. an inspected-element reference plus page/route context;
3. a unique CSS selector;
4. a source-linked component/element selection that can be mapped to a rendered instance.

Do not assume a proprietary selection API exists. Inspect the host's available context or browser tools. If selection state is unavailable, ask for a selector or screenshot instead of guessing.

Resolve the reference in the running page and record its route, state, stable selector, `getBoundingClientRect()`, tag, visible text, role, classes/data attributes, and a short child-structure fingerprint. A live handle is useful for discovery but must not be serialized into the temporary overlay source; derive a selector plus landmark checks that can be re-resolved after refresh.

The selected rendered element is the requested comparison boundary. Do not walk to an ancestor merely because it looks more like a conventional module. Only substitute another element when the selected node has no rendered box (`display: contents`, a non-element node, or an unrendered framework wrapper); use its nearest rendered owner or combined rendered children and report that normalization. If a source selection maps to multiple rendered instances, use the currently inspected browser instance or route/state evidence; otherwise ask the user which instance they mean.

Record `targetInput.mode` as `dom-selection` and, when known, the selecting host such as `cursor`, `codex`, `browser-devtools`, or `other`. Do not add permanent ids or data attributes to application code solely to preserve the selection.

### Mode B: Screenshot locator

Preserve the original screenshot unchanged as `.figma-overlay-check/user-module.png` when a local attachment path is available. Record its pixel dimensions, but do not treat those dimensions as CSS dimensions or Figma logical dimensions.

Extract matching landmarks before searching:

- visible text, icons, images, colors, and distinctive shapes;
- internal layout such as rows, columns, cards, gaps, and alignment;
- likely clipped edges and any neighboring content visible at the perimeter;
- screenshot scale clues such as browser device-pixel ratio or a known viewport width.

The screenshot may be slightly over-cropped or under-cropped. It must never be stretched to force a match, used as the overlay image, or copied into application assets. Record `targetInput.mode` as `screenshot`.

### Mode C: Default whole page

Enter this mode automatically only when the user supplied no screenshot, DOM selection, locator, or selector. Do not ask the user to choose between module and page. Record `targetInput.mode` as `full-page`.

Use the requested/current route and state. Identify the page canvas as the stable rendered element that owns the complete page represented by the Figma Frame: normally the application root or its page-level child containing all intended sections and the page background. Do not choose an inner content column merely because it has a convenient width. Set the browser viewport width to the Figma page Frame's logical width before final geometry checks.

## Step 2: Verify and capture the live target

Run the local page and reproduce the likely route, state, viewport, fonts, and deterministic data. Capture a clean full-page screenshot under `.figma-overlay-check/` and inspect the rendered DOM.

For DOM-selection mode, skip screenshot-to-page search. Resolve the selected target, verify its recorded fingerprint, confirm the selector is unique, and continue at **Target verification** below.

For full-page mode, skip screenshot-to-page search and boundary correction. Resolve the page canvas, verify that it contains the intended complete route content, record its stable selector and page-level landmark fingerprint, and continue at **Target verification** below.

For screenshot mode, locate the screenshot in the page using multiple independent signals:

1. Search visible DOM text from the screenshot and inspect the matching elements and ancestors.
2. Compare stable visual landmarks against the full-page screenshot. Ignore narrow perimeter bands when they appear clipped; prefer the screenshot's central, distinctive content.
3. Enumerate visible semantic ancestors around each match (`section`, `article`, `nav`, `header`, `footer`, form, card, modal, or a component root) and inspect their rectangles, text, images, and siblings.
4. Select the **smallest coherent semantic DOM element that contains the stable matched core and owns the whole intended module**. Do not select an arbitrary crop rectangle, text leaf, broad page wrapper, `body`, or viewport.

Record the target element's stable selector, document-space rectangle, visible text summary, and matching evidence. Prefer a stable id or data attribute; otherwise derive a selector from the application structure and verify that it resolves uniquely after refresh.

### Boundary correction

The final live comparison boundary is the full rectangle of the selected DOM module, not the user's screenshot bounds.

- **Over-cropped screenshot:** when a small perimeter area belongs to siblings or an ancestor outside the selected module, exclude it. Save a diagnostic crop only if useful; do not destructively alter the original screenshot.
- **Under-cropped screenshot:** when the stable core lies inside a coherent module but one or more module edges are absent, extend to the selected module's full DOM rectangle. Confirm the recovered area belongs to the same component using background continuity, borders, repeated layout, text, or child ownership.
- Treat the correction as small when the recovered/excluded band is no more than roughly 15% on any edge and the semantic ownership is clear. This is a confidence guide, not a reason to force a match.
- If the screenshot contains multiple complete modules, omits the distinctive core, crosses unrelated containers substantially, or two candidates remain plausible, show the best candidates and ask the user which module they intended. Do not edit UI at low confidence.

Skip boundary correction in DOM-selection and full-page modes. Set `boundaryCorrection` to `null` unless a non-rendering DOM selection required the explicitly reported normalization above.

### Target verification

Refresh once and verify the selector still resolves to the same target with the same landmark content.

Capture the target element's complete rendered rectangle as `.figma-overlay-check/normalized-target.png`. In screenshot mode, this boundary-corrected image naturally drops neighboring pixels and restores omitted edges. In DOM-selection mode, it is an exact capture of the selected rendered target. In full-page mode, capture the complete page canvas at the Figma Frame viewport width. Preserve `user-module.png` separately when screenshot input exists.

## Step 3: Match the complete Figma target

Use Figma MCP `get_metadata` or `get_design_context` on the user-provided Figma file/selection.

- In DOM-selection or screenshot mode, search within the relevant page or parent Frame and export the exact matching module node. Do not export the whole page merely because it contains the module.
- In full-page mode, match the current route/page landmarks to one complete page-level Frame and export that Frame. Prefer the current Figma selection when it is a page-level Frame. If several page Frames remain equally plausible, show the strongest candidates and ask rather than choosing arbitrarily.

Rank candidate Frame, Component, Instance, or Section nodes using:

- exact and fuzzy matches for visible text and layer names;
- component hierarchy and child count/order;
- image/icon landmarks, background, border, and layout direction;
- aspect ratio and dimensions, allowing for responsive implementation drift and screenshot scale;
- proximity to already identified parent page/frame context.

Inspect previews of the strongest candidates when metadata alone is insufficient. Compare candidate previews with `normalized-target.png`, not with the raw screenshot perimeter. Select automatically only when one candidate has consistent semantic and visual evidence and clearly outranks alternatives. Otherwise present the top candidates and pause before UI edits.

Export the exact matched node through Figma MCP as `.figma-overlay-check/design.png`. Record its node id, node type, logical width, and logical height. Confirm PNG dimensions with `file` or `sips`, but use the Figma node's logical dimensions for CSS. Figma's 4096 px export cap must not change overlay geometry.

In module modes, never export an enclosing page as a substitute for a missing module match. In full-page mode, never export an inner module as a substitute for the page Frame. Never use an application screenshot as the design reference.

## Step 4: Install the target overlay

Create exactly one temporary source file:

```text
<project>/.figma-overlay-check/__figma_overlay__.ts
```

Keep the route guard, target selector, target verification, overlay image, geometry updates, and listeners in this file. Load `design.png` through the framework's supported asset mechanism; if necessary, embed it in this temporary file. Do not put it under `src/` or `public/`.

Inject the bundled panel and page-entry import:

```bash
node <skill>/scripts/inject-overlay-panel.mjs \
  <project>/.figma-overlay-check/__figma_overlay__.ts

node <skill>/scripts/inject-page-entry.mjs \
  --project-root=<absolute-project-root> \
  --entry=<absolute-browser-entry> \
  --imported-path=<relative-overlay-module-path>
```

Capture the entry injector's JSON output for the manifest. Let it add a marked `"use client"` only when its Next.js App Router checks pass. Never hand-edit the marked blocks.

The temporary module must:

1. Guard browser APIs when server evaluation is possible and initialize idempotently after `document.body` and `document.fonts.ready`.
2. Restrict itself to the target route and state.
3. Resolve the recorded unique target selector, then verify its landmark text/structure before mounting. If verification fails, keep the overlay hidden and report target loss; do not attach to a different element opportunistically.
4. Append the overlay root to `document.body` with `position: absolute`, maximum z-index, and `pointer-events: none`.
5. Set the overlay image width and height to the exact numeric Figma node logical dimensions in CSS pixels, with `max-width: none`. Never derive size from the raw screenshot, PNG, viewport, body, or target element.
6. Align its document-space left/top to the target's `getBoundingClientRect()` plus scroll offsets. Do not center it or add margin, padding, or transforms.
7. Recompute position after resize, scroll, route/state changes, and layout changes without scaling the image.
8. Scope the comparison to the selected target. Module-mode exports contain only the matched module. Full-page exports contain the complete page Frame.
9. Mount the injected panel exactly once:

```javascript
mountFigmaOverlayPanel({
  frameWidth: figmaNodeWidth,
  frameHeight: figmaNodeHeight,
  overlayTitle: targetInput.mode === 'full-page' ? 'Figma Page' : 'Figma Module',
  overlayImage,
  initialMode: 'opacity',
  initialOpacity: 0.5,
  getGeometry: () => ({
    canvas: targetLabel,
    widthDelta,
    leftDelta,
    topDelta,
  }),
});
```

Use the bundled panel unchanged per task. It provides `Hide Image`, `Opacity Overlay`, `Show Image`, opacity control, geometry metrics, dragging, and collapse/restore. It intentionally contains no delete control. Keep it fixed at the bottom-right with a 12 CSS px inset and width no greater than 300 CSS px.

### Geometry verification

Before visual comparison, numerically verify:

```javascript
() => {
  const image = document.querySelector('[data-figma-overlay-image]');
  const target = document.querySelector('THE_RECORDED_UNIQUE_SELECTOR');
  if (!image || !target) return null;
  const a = image.getBoundingClientRect();
  const b = target.getBoundingClientRect();
  return {
    overlayWidth: a.width,
    overlayHeight: a.height,
    targetWidth: b.width,
    targetHeight: b.height,
    leftDelta: a.left - b.left,
    topDelta: a.top - b.top,
  };
}
```

`overlayWidth` and `overlayHeight` must equal the Figma node's logical size within 0.1 CSS px. `leftDelta` and `topDelta` must each be within 0.1 CSS px. Target size differences are design discrepancies to inspect, not permission to scale the overlay.

The panel preset owns all panel DOM, styles, labels, mode handling, dragging, collapse handle, and metric formatting. Do not recreate or restyle it in the temporary file.

## Hot-switch an active target

When a valid v4 manifest already exists and the user selects or supplies a different target, treat the request as `switch-target`. Do not delete the active overlay, do not create a second overlay session, and do not discard completed UI fixes.

The user interaction is simply:

1. select another DOM node or provide another screenshot; or explicitly request the whole page;
2. ask the AI to switch/continue the overlay on that target;
3. wait for one full page reload showing the new overlay.

The page panel cannot perform Figma matching by itself. Do not add a fake `Switch Target` button that implies it can call Figma MCP without the AI.

### Switch transaction

Keep the current overlay visible until the new live target and Figma node have both been matched with sufficient confidence. Then switch as one recoverable transaction:

1. Validate the existing manifest, canonical project root, current marked import, current source/image paths, and `switchState`. If `switchState` is already `switching`, recover or roll back that interrupted transaction before accepting another target.
2. Set `switchState` to `switching` before changing current files. The deletion command must reject the request while this state is active.
3. Stage the next exported design, next page-specific source body/configuration, next normalized target, and rollback copies under a revision-specific directory such as `.figma-overlay-check/.switch-<next-revision>/`. Transient staging files are allowed only during the transaction and must never be imported by application code. Keep the bundled panel preset block unchanged; it is not target-specific.
4. Reuse the existing marked page import when the browser entry is unchanged. When the new target uses a different browser entry, run:

```bash
node <skill>/scripts/switch-page-entry.mjs \
  --project-root=<absolute-project-root> \
  --manifest=<project>/.figma-overlay-check/.figma-overlay-state.json \
  --entry=<absolute-new-browser-entry> \
  --imported-path=<new-entry-relative-overlay-module-path>
```

This script validates the current manifest, injects the new entry, removes only the old recorded import and skill-added `"use client"` block, preserves pre-existing directives, updates the manifest's entry fields, and rolls both entries back if migration fails. It is also idempotent when the entry is unchanged.

5. Atomically replace `design.png` and the page-specific portion of `__figma_overlay__.ts` from staging while preserving its injected panel preset block. Keep the same canonical filenames so the single import remains valid. Replace current diagnostic artifacts rather than mixing them with the previous target's artifacts.
6. Write the complete new manifest last. Increment `sessionRevision` by exactly one, increment `switchCount`, replace all target/Figma/evidence/artifact fields, and set `switchState` to `ready`. Keep the same `sessionId` for the whole multi-target review session.
7. Perform a **full browser reload**. Do not rely on HMR: the old overlay root and idempotency guards may otherwise retain the previous target in memory.
8. Verify that exactly one overlay root and one panel exist, the new selector/fingerprint resolves, the design image is the new Figma node, and geometry deltas meet the normal thresholds. Remove the switch staging directory after verification.
9. If any step before the ready manifest or verification fails, restore the previous source, design, entry markers, and manifest from staging; reload and confirm the previous overlay still works. Never leave `switchState: switching` without reporting the recovery needed.

At stable state there must still be exactly one temporary overlay source, one current design image, one manifest, one marked entry import, one panel, and one active target. Old comparison rasters are replaced; prior application UI fixes remain.

Run the normal single automatic correction pass for every successfully switched target, then wait for the next user-selected target. Deletion is an end-of-session conversation command, not a panel action.

## Delete by conversation command

Only delete an overlay after the user explicitly tells the AI in conversation to delete or remove it, for example “删除叠图”, “移除叠图”, or “remove the overlay”. That instruction authorizes the AI to run:

```bash
node <skill>/scripts/delete-overlay.mjs \
  --project-root=<absolute-project-root>
```

Do not infer deletion from target switching, review completion, or an unrelated cleanup request. The command validates the canonical project root, latest v4 manifest, generated paths, current marked import, and any skill-added `"use client"` directive. It rejects deletion while `switchState` is not `ready`, removes only those marked entry changes and the exact `.figma-overlay-check/` directory, and preserves `.gitignore`, pre-existing directives, and all UI fixes. Report what it removed after success. Never start an HTTP cleanup server or expose cleanup credentials in the page.

## Step 5: Compare and correct

Use opacity mode for coarse alignment and difference mode for fine geometry, typography, and color inspection. Crop diagnostic regions with `scripts/crop.mjs`; amplify dark differences with `scripts/amplify.mjs`; sample exact colors with `scripts/color-sample.mjs` when useful.

Perform one automatic correction pass:

1. Identify the highest-impact differences inside the matched target.
2. Edit the relevant application component and styles in one grouped pass.
3. Refresh, revalidate the target selector and geometry, and check opacity and difference modes.
4. Stop and return control to the user. Do not calculate a pixel-difference percentage or begin another pass automatically.

Preserve semantic implementation:

- Keep text selectable and controls interactive.
- Never use `design.png`, the user's screenshot, crops, diffs, canvas, video, data URLs, or flattened SVG/UI images as application implementation.
- Use images only for content that is genuinely an image asset in the design, exported from that exact asset node.
- After edits, inspect changed source and DOM for accidental flattened replacements.

Only skip edits when the user explicitly requests review-only/report-only behavior.

## Step 6: Manifest and handoff

Create `.figma-overlay-check/.figma-overlay-state.json` using manifest version 4, including the fields required by the deletion command and module evidence:

```json
{
  "version": 4,
  "sessionId": "random-session-id",
  "sessionRevision": 1,
  "switchCount": 0,
  "switchState": "ready",
  "projectRoot": "/absolute/project",
  "overlayDirectory": "/absolute/project/.figma-overlay-check",
  "pageUrl": "http://localhost:3000/page",
  "figmaFrameWidth": 640,
  "figmaFrameHeight": 420,
  "figmaNodeId": "123:456",
  "figmaNodeType": "COMPONENT",
  "targetInput": { "mode": "full-page" },
  "targetSelector": "#__next",
  "targetEvidence": ["complete route content", "page background", "matching page-level Figma Frame"],
  "boundaryCorrection": null,
  "staticImagePath": "/absolute/project/.figma-overlay-check/design.png",
  "downloadedImagePath": "/absolute/project/.figma-overlay-check/design.png",
  "temporarySourcePath": "/absolute/project/.figma-overlay-check/__figma_overlay__.ts",
  "entryImport": {
    "path": "/absolute/project/src/app/page.tsx",
    "importedPath": "../../.figma-overlay-check/__figma_overlay__",
    "startMarker": "FIGMA_OVERLAY_START",
    "endMarker": "FIGMA_OVERLAY_END"
  },
  "useClientDirective": null,
  "cleanupMode": "ai-command",
  "artifactPaths": [
    "/absolute/project/.figma-overlay-check/normalized-target.png",
    "/absolute/project/.figma-overlay-check/page.png",
    "/absolute/project/.figma-overlay-check/difference-shot.png"
  ]
}
```

All generated paths must resolve inside the canonical overlay directory. Include `user-module.png` in `artifactPaths` only in screenshot mode. `entryImport` must describe exactly one marked side-effect import. Copy `useClientDirective` exactly from the entry injector or switch script. On initial creation use revision `1`, switch count `0`, and state `ready`; on each committed target switch increment revision and switch count once. Read and validate any existing manifest before replacement.

Before handoff, verify panel modes, opacity, metrics, dragging, collapse/restore, and the absence of any delete control. Confirm the target selector still identifies the same target. In module modes, confirm no outside page region is covered; in full-page mode, confirm the overlay covers exactly the page canvas.

At handoff, report:

- the input mode, matched live target, and Figma node;
- whether and how screenshot boundaries were corrected;
- the UI fixes made and any remaining uncertainty;
- the current session revision and whether this target was hot-switched;
- that `.figma-overlay-check/` and the marked page-entry import remain active.

Ask the user to point out any remaining issue. Tell them they can say “删除叠图” (or an equivalent explicit instruction) when finished; the AI will then remove the marked import and `.figma-overlay-check/` while preserving UI fixes.

## Frequent failure modes

| Symptom | Cause | Response |
|---|---|---|
| Match lands on a heading or image | A visual leaf was mistaken for the module | Walk up to the smallest coherent semantic owner and verify siblings |
| Screenshot includes part of the next section | Over-cropped locator | Exclude pixels outside the selected DOM module |
| Screenshot misses a border or final row | Under-cropped locator | Recover the full DOM/Figma node bounds |
| Tool reports a selected node but no selection context is available | Host selection is not exposed to the agent | Ask for a stable selector or screenshot |
| Source-selected component renders more than once | Source location is not an instance identity | Use the inspected browser instance or ask which route/instance is intended |
| No screenshot or selected target was supplied | No module target was requested | Enter full-page mode automatically |
| Whole-page match selects an inner content column | Page canvas ownership was inferred from width alone | Use the application/page root that owns all sections and background |
| New target appears only after a second refresh | HMR retained the old idempotent overlay root | Always perform one full reload after committing a switch |
| Deletion reports that switching is in progress | Manifest is intentionally protected or a switch was interrupted | Finish or roll back the staged switch, set the ready manifest, then retry |
| Switching to another route leaves an old import | Entry migration was skipped | Use `switch-page-entry.mjs` and verify both entries before reloading |
| Two repeated cards look identical | Candidate is ambiguous | Use text, parent hierarchy, route/state, and Figma ancestry; ask if still tied |
| Overlay fits only after scaling | Viewport/state mismatch or real size drift | Reproduce design context; never scale to hide the discrepancy |
| Text ghosts drift line by line | Browser line-height differs | Set measured line-height explicitly |
| Every color is slightly off | Display P3 versus sRGB | Relaunch screenshots with forced sRGB before editing CSS |

## Rules

- Compare one explicit module target at a time, or one whole page in fallback mode.
- Accept screenshot input or a DOM node selected through Cursor, Codex, browser tooling, or another AI host; default to whole-page comparison only when neither is supplied.
- In DOM-selection mode, the selected rendered element is authoritative; derive a refresh-safe selector and fingerprint without requiring a screenshot.
- In screenshot mode, the screenshot is a locator; the complete DOM element and complete Figma node define the final boundaries.
- In full-page mode, use the complete page canvas and corresponding page-level Figma Frame at the Frame's logical viewport width.
- Automatically correct only small, well-supported crop errors. Do not guess across ambiguous or unrelated regions.
- Export the matched module node in module modes and the matched page Frame in full-page mode; never cross those scopes as a convenience fallback.
- Render at exact Figma logical size and align exact top-left edges; never stretch, center, or fit-to-target.
- Verify overlay size and edge deltas numerically before comparison.
- Keep every comparison artifact under `.figma-overlay-check/` and keep exactly one temporary source file.
- Use the bundled injectors, panel preset, v4 manifest, and conversation-driven deletion command.
- Detect an active session and hot-switch new targets transactionally; never delete between targets.
- Keep one `sessionId`, increment `sessionRevision`/`switchCount` once per successful switch, and allow deletion only in `switchState: ready`.
- Reuse the current entry import when possible and use `scripts/switch-page-entry.mjs` when the browser entry changes.
- Complete one correction pass, visually verify it, and return control to the user.
- Never flatten ordinary UI or reference comparison artifacts from application code.
- Keep the overlay active at handoff; delete it only after an explicit user instruction in the AI conversation.

