# genai-mesh-gradient

Adopt this skill: https://proskills.md/skills/other/9929y-genai-mesh-gradient

Page: https://proskills.md/skills/other/9929y-genai-mesh-gradient
This document is the public skill bundle for that page. It contains SKILL.md and every helper file the catalog carries. No login is required.

## File: SKILL.md
size: 12118
sha: cf0939ed2b0c21e3b3f71550d07ae5a925287567
upstream: https://github.com/9929y/genai-mesh-gradient/blob/HEAD/SKILL.md

````text
---
name: genai-mesh-gradient
description: A research-informed GenAI visual-generation workflow. Translate user intent and design constraints into controllable mesh gradients; generate and refine mesh gradients for presentations, web backgrounds and brand visuals, with palette selection and brand-design guidance. Use editable Figma layers or SVG/code routes for sky-inspired, dreamlike, flower-inspired, diffuse, heightmap and multipoint effects, including reference reconstruction.
---

# GenAI Mesh Gradient

A research-informed agent skill for controllable visual generation. The workflow connects
user input, explicit design constraints and feedback to editable visual output.
Read the English-first README for the two related papers and the precise connection.
This package supplies agent instructions and procedural renderers; it does not
implement or reproduce the papers' trained diffusion models. Do not present
their reported metrics as results for this skill or infer sole invention from
coauthorship. Use an external image-generation tool only when the task calls for
model-generated pixels and label that output accurately.

Turn a visual reference into an explicit recipe, render it in a suitable tool,
inspect the result, and adjust the parameter responsible for the mismatch.
Prefer an editable construction when the user needs to keep designing.

This skill supplies design decisions and small rendering helpers. It does not
install an app, establish a Figma connection, or grant file permissions.

## Start with the actual request

Identify the reference or palette, intended use, dimensions, transparency,
editability, and whether the user wants a still, ambient motion, or image reveal.
Use provided context; ask only when a missing choice changes the outcome.
If dimensions are unspecified, use a 1200 × 800 landscape study and say so.

Read [art-direction.md](references/art-direction.md) for the intended use,
palette selection, brand judgment and an editing process a non-specialist can
follow. For a deck, design in its actual slide ratio with a quiet text zone.
For a website, check mobile crop and text protection. Do not deliver an artwork
that only looks good without its real foreground content.

When color is undecided, offer a small comparison: monochromatic, analogous,
and a restrained contrasting accent (or neutral-plus-accent for dense content).
Use the same geometry and seed so the user is choosing color, not different
compositions. Explain roles, a fitting use and a tradeoff; lock the selected
palette before making a large batch. Do not overwrite supplied brand colors.

Distinguish three tasks:

- **Reconstruct:** preserve the reference's composition, color proportions,
  bright and dark masses, direction, and edge behavior. Do not replace these
  with a random attractive palette.
- **Generate:** design a new composition from the requested palette and mood.
  Label it as an original study rather than an exact recreation.
- **Image-derived abstraction:** extract color, connected regions, approximate
  coverage, position, luminance, and major structure before choosing a renderer.

## Choose a route by capability

Read [adapters.md](references/adapters.md) for the selected tool only.

| Need | Route | What stays editable |
|---|---|---|
| Figma still, color masses, soft topology | Native radial fills and optional vector shapes | Shape, fill, stop alpha, position, scale, stacking |
| Portable still without a write connection | Layered SVG | Paths and gradient definitions in an SVG editor; import fidelity must be checked |
| Warped flow, diffusion, paint simulation, continuous reveal | Canvas/WebGL or a tool with documented shader support | Parameters/code; an exported bitmap is flattened |
| Model-generated material or complex illustration | Available image-generation tool | Usually pixels; never describe it as editable mesh geometry |

Discover the actual connector tools before promising an action. A connection
with only read tools cannot create native Figma layers. If a Figma write tool
exists, use its current instructions and required session flow. Otherwise offer
SVG or a runnable renderer, or explain the one missing connection. Do not
silently substitute a bitmap for requested editable layers.

## Write a compact recipe before rendering

Use normalized coordinates with the origin at the top left. Specify:

```text
effect: sky-inspired | dreamlike | flower-inspired | diffuse | heightmap | multipoint
optional browser study: atmospheric | fluid | pigment | oil | silhouette | petal
canvas: width, height, opaque base or transparent
palette: ordered colors with intended roles and rough area proportions
regions: color, center(x,y), extent(rx,ry), direction, opacity, edge softness
structure: bright/dark masses, silhouette or petal boundary if required
material: grain scale/amount, optional warp, pooling or brush hierarchy
seed: fixed for reproducible comparisons
delivery: native Figma | layered SVG | rendered image | executable code
```

Several disconnected regions may share one color. One average position per
color loses a composition with the same hue in opposite corners.
Region radii and alpha are not area coverage: overlap and stacking change the
visible proportions. Inspect the composite before claiming a palette match.

## Build the still first

For the Figma workflow, read [figma-recipes.md](references/figma-recipes.md):
Sky-inspired, Dreamlike, Flower-inspired, Diffuse, Heightmap, and Multipoint.
For matching an existing bitmap, also read the fitting and detail-calibration
procedure there. These are distinct construction choices, not six filters.

Read [effects.md](references/effects.md) only for the related browser-rendering
families (atmospheric, fluid, pigment, brush, silhouette and petal). Keep each
visual grammar separate from presets such as pale, dark, or saturated. A
fidelity level is a mode of an effect, not a new effect family.

1. Block the base and major color masses. Match composition and light/dark
   balance before adding texture.
2. Adjust overlap, asymmetry, edge softness, and local contrast. A few strong
   masses often work better than many weak ones.
3. Add only the material cues that distinguish the requested family. Keep
   fine grain separate from low-frequency boundary distortion.
4. Render at the intended dimensions. Inspect both the whole image and a
   detail crop at normal display scale.
5. Fix the dominant mismatch, keeping seed and unrelated parameters fixed.
   Stop when the reference/use-case criteria pass.

## Simplify the user's edits

Expose a few meaningful choices first: use-case/quiet zone, palette, composition,
fusion/softness and contrast. Keep per-layer controls available for refinement.
Return `massNodes` from the native helper so later edits can target each group's
transform and its separate color fill without changing the mask.

For size, aspect ratio, palette sample recipes and blur, read
[palettes-and-layout.md](references/palettes-and-layout.md). At a 1536×1024
reference size, compare **100 / 150 / 200 px** for broad light fields. The current soft
Flower uses **125–160 px** and **56–85% plane opacity**; the 40-level Heightmap uses **24–38 px**;
scale a chosen radius by min(width,height)/1024 when resizing the canvas.
Changing export scale alone does not require changing the layer radius again.
Tune sample-specific values for edge fusion and contour identity; use broader diffusion only when it serves the composition;
judge each layer rather than imposing one number. The Gaussian-mask method has
no extra layer blur by default. For a different aspect ratio, recompose the
centers and quiet zone, and define physical mass radii relative to the short
side; do not nonuniformly stretch or assume a centered crop will work.

Use `scripts/palette_studies.js` for the exact four-pool browser palette examples
and three recomposed Gaussian-mask layout specs. These are original sample
recipes, not automatic replicas of the six Figma studies. Inspect a selected
sample in `design/illustrations/` when matching its appearance; a method label
alone is not enough. The old radial `petal` SVG sketch is not the Flower target.

For normal recoloring, edit the named color fills, preserve geometry, then
inspect the composite. For layout, move/scale/rotate a whole mass group.
Keep raster corrections off during substantial redesign.

The current blue/orange gallery can be reconstructed with
`scripts/blue_orange_studies.js`, inlined after `figma_native.js`; read the
current construction table in `figma-recipes.md`. This six-study builder has
been executed in live Figma and returns native artboard/layer IDs. Its paths
use a 3:2 composition; recompose before adapting to a different ratio.

Helpers:

- `scripts/figma_native.js` defines `buildMesh(figma, spec)` for native Gaussian
  alpha-mask groups with separate solid color fills. Read the adapter first.
  It deliberately creates no texture,
  segmentation, mesh control-point grid, or animation.
- `python3 scripts/render_svg.py --effect atmospheric --output study.svg`
  creates an original deterministic SVG study. Run `--help` for dimensions,
  seed, palette and texture options. It provides four schematic families;
  it does not analyze an input image or reproduce all six advanced effects.

## Diagnose instead of adding more blur

| Symptom | Likely cause | First correction |
|---|---|---|
| Defocused photograph | Renderer still depends on fine source pixels | Rebuild from simplified regions; discard fine texture |
| Muddy/gray mixture | Too much overlapping complementary pigment | Separate major masses; reduce broad alpha; restore a light or dark anchor |
| Visible colored circles | Similar circular masses and isolated boundaries | Vary aspect/placement; overlap; use shaped vectors where contours matter |
| Horizontal sunset bands | Centers aligned on rows | Change topology and direction, not just hue |
| Texture covers everything | Grain too large or opaque | Lower amount; inspect at actual display size |
| Petal looks like a flower icon | Perfect radial symmetry, central rosette | Enlarge/crop planes; use a curved shadow and transmitted light if the reference calls for it |
| Dreamlike looks ornamental | Thin closed highlight loop replaces broad light | Remove the outline and restore unequal offset light/shadow regions |
| Heightmap stays simple despite many layers | Repeated scaled outline, no saddles | Change the height field and inspect splits/merges before increasing levels |
| Export differs from preview | Different dimensions, color/filter handling or pipeline | Render both through the same pipeline; check actual exported pixels |

## Add motion only when requested

Read [motion.md](references/motion.md). Keep the still's settings independent
from reveal progress and ambient time. Do not assume every effect should end
at a photograph: use the user's requested endpoint.

## Deliver with evidence

Return the usable artifact or Figma node link, route, effect and key adjustable
parameters. State what is editable and which effects were approximated or
rasterized. Confirm export dimensions, background/alpha and orientation.
For a reference match, discuss composition/coverage/edges rather than claiming
pixel identity without an image comparison.

Keep original references unchanged. Do not publish private file links, local
paths, personal conversation transcripts, or third-party reference images as
part of a reusable recipe. Use original examples or licensed assets.

## Scope of evidence

The Figma recipes are grounded in read-only inspection of existing native
artwork and recovered historical construction records. The original chat UI
could not be restored. Node structures and representative renders were checked;
design intent and undocumented algorithms are identified as interpretations.
Browser effect and motion guidance additionally synthesizes archived prototype
notes. Parameter ranges are starting points. See `index.html` for validation
status. Neither raw history nor private Figma file links are bundled.
````

## File: README.md
size: 12132
sha: f243688ae9be629c3c66e0c025960307856960de
upstream: https://github.com/9929y/genai-mesh-gradient/blob/HEAD/README.md

````text
# GenAI Mesh Gradient

**A research-informed agent skill for controllable visual generation.**

Translate a visual brief into a clear recipe, generate mesh-gradient artwork,
and refine it through feedback. The skill combines palette and composition
guidance with editable Figma construction, layered SVG alternatives and output
inspection. Use it for presentation covers, website heroes, thumbnails and
consistent brand visuals.

[Research connection](#research-connection) · [Install and use](#install-and-use) ·
[For agents](#for-agents) · [Illustrated guide](index.html) · [中文简要说明](#中文简要说明)

## Samples

Six native Figma studies, each **1536×1024 (3:2)**, share a blue, apricot and warm-white
palette. The JPEGs are flattened previews; the recipes and builder describe
their editable construction. These are the existing October 24 studies.

| Sky-inspired | Dreamlike |
|---|---|
| <img src="design/illustrations/sky-blue-orange.jpg" width="384" height="256" alt="Sky: blue and apricot"> | <img src="design/illustrations/dreamlike-blue-orange.jpg" width="384" height="256" alt="Dreamlike: offset light and shadow"> |
| Flower-inspired | Diffuse |
| <img src="design/illustrations/flower-soft-blue-orange.jpg" width="384" height="256" alt="Flower: cropped translucent planes"> | <img src="design/illustrations/diffuse-blue-orange.jpg" width="384" height="256" alt="Diffuse: blue mist and warm paper"> |
| Heightmap | Multipoint |
| <img src="design/illustrations/heightmap-soft-blue-orange.jpg" width="384" height="256" alt="Heightmap: peaks, saddles and ridges"> | <img src="design/illustrations/multipoint-blue-orange.jpg" width="384" height="256" alt="Multipoint: eleven Gaussian fields"> |

| Study | Native construction | Reference settings |
|---|---|---|
| Sky-inspired | Broad diagonal current; 3 curved planes + 2 light fields | 125–155 px blur |
| Dreamlike | Unequal offset light and shadow; 2 planes + 4 fields | 120–165 px blur |
| Flower-inspired | Magnified cropped petals; 4 translucent planes + 2 reflections | Plane opacity 56–85%; blur 125–160 px |
| Diffuse | 1 curve + 3 broad radial fields | 155–185 px blur |
| Heightmap | Warped field with peaks, valleys and saddles; marching-squares contours | 40 levels; blur 24–38 px |
| Multipoint | 11 Gaussian alpha-mask groups with separate color fills | No extra layer blur |

[Full recipes and controls](references/figma-recipes.md) ·
[Six-study builder](scripts/blue_orange_studies.js) ·
[Required native helper](scripts/figma_native.js)

The builder runs inside a connected Figma execution tool. Heightmap exposes
`detail`, `warp`, `levels`, `blurMin` and `blurMax`; valid ranges and examples
are in the recipes. The guide also compares the same Sky at 100/150/200 px blur.

Four browser palette studies keep the same composition and change only color
roles. Exact colors, layer order and fade stops are in the
[palette/layout recipes](references/palettes-and-layout.md).

| Monochromatic | Analogous warm |
|---|---|
| ![Warm monochrome](design/illustrations/palette-mono.svg) | ![Analogous warm](design/illustrations/palette-adjacent.svg) |
| Apricot/cobalt | Neutral/accent |
| ![Apricot cobalt](design/illustrations/palette-blue-orange.svg) | ![Cool neutral](design/illustrations/palette-neutral.svg) |

## Research connection

Generative interface research asks how outputs can respond to user input,
design rules and feedback. This skill applies those ideas at the workflow level:
it converts an open-ended brief into an explicit recipe that an agent can
execute, inspect and revise.

For example, “make it softer and leave room for a title” becomes a protected
text area, color roles, region positions, opacity and edge-softness settings.
The agent selects a rendering route and adjusts the parameter responsible for
the visible mismatch. The package's practical contribution is this reusable
workflow, its editable construction recipes and its rendering helpers.

| Research idea | Application in the skill | Inspectable implementation |
|---|---|---|
| User input as a generation condition | Specify purpose, palette, reference structure, size and editability | [Recipe and route selection](SKILL.md) |
| Design knowledge as a constraint | Protect content areas; control color roles, composition and scale | [Art direction](references/art-direction.md) and [Figma recipes](references/figma-recipes.md) |
| Feedback during refinement | Inspect actual output; adjust a relevant parameter; hold composition fixed for palette comparison | [Diagnosis workflow](SKILL.md#diagnose-instead-of-adding-more-blur) and [interactive guide](index.html#direction) |
| Usable output beyond a preview | Preserve separate color/mask groups and expose node IDs for later edits | [Native helper](scripts/figma_native.js) and [study builder](scripts/blue_orange_studies.js) |

Related research:

- [*Automated UI Interface Generation via Diffusion Models: Enhancing Personalization and Efficiency*](https://arxiv.org/abs/2503.20229)
  (2025; public preprint submitted March 26). Discusses conditional inputs,
  design optimization and feedback in UI generation.
- [*Generative Modeling of Human-Computer Interfaces with Diffusion Processes and Conditional Control*](https://arxiv.org/abs/2601.06823)
  (2026; public preprint submitted January 11). Discusses user intent, context
  and task constraints in conditional interface generation.

The connection is between research ideas and the design workflow. The repository
contains agent instructions and procedural Figma/SVG helpers, rather than the
papers' trained diffusion models, weights or experimental reproduction. An
external image-generation tool can be used for model-generated material; its
output is usually pixels. The papers' results do not measure this package.
Independent adoption, productivity gains and business outcomes have not been
established for the skill.

## Install and use

Install the complete folder, including `SKILL.md`, `references/`, `scripts/`
and `design/`. For Codex, a typical installation is:

```sh
git clone https://github.com/9929y/genai-mesh-gradient.git \
  ~/.codex/skills/genai-mesh-gradient
```

Reload the client's skill list if needed. Other agents have their own loading
conventions. Installing the files alone does not enable automatic invocation in
every client or establish a Figma connection.

1. Provide the use case, size/aspect ratio, a reference or brand colors, the area
   reserved for content, and the required output format and editability.
2. If colors are undecided, compare a few palettes on the same composition before
   producing a larger set.
3. For native Figma output, connect a tool that can write to the canvas and specify
   the target file. The agent must check the connection's actual capabilities.
4. Review the result in its intended slide or page. Refine palette, distribution,
   fusion and contrast while preserving the chosen composition during color comparison.

Example request:

> Use $genai-mesh-gradient to create a 16:9 presentation-cover gradient.
> Compare monochromatic, analogous and restrained contrasting palettes using
> the same composition. Keep the left third quiet for a dark title. After I
> choose a direction, build editable layers in my Figma file, inspect the result,
> and explain how to change its colors and softness.

Previously published as **Mesh Gradient Generation** (`mesh-gradient-generation`).
For an existing installation, rename its folder to `genai-mesh-gradient`, update
its contents and saved prompts, then reload the client. The package supplies no
automatic alias for the old invocation.

## For agents

When working in the repository, read [AGENTS.md](AGENTS.md), then
[SKILL.md](SKILL.md). A skill loader normally loads `SKILL.md` directly.
Read only the references required for the task:

| Task | Read next |
|---|---|
| Choose use case, palette, brand direction or editing controls | [Art direction](references/art-direction.md) |
| Adapt sample colors, aspect ratio or blur | [Palette/layout recipes](references/palettes-and-layout.md) |
| Build the six native effects or reconstruct a reference | [Figma recipes](references/figma-recipes.md) |
| Operate Figma, export SVG or select another renderer | [Tool adapters](references/adapters.md) and the connector's current instructions |
| Explore fluid, pigment, oil/brush or silhouette rendering | [Related effects](references/effects.md) |
| Add ambient motion or source-image reveal | [Motion guidance](references/motion.md) |

Inspect the target tool and existing artwork before editing. Return the artifact
or node link, adjustable controls, verification results and relevant limits.
Repository instructions do not authorize changes to unrelated files.

### Included helpers and editing limits

- `scripts/figma_native.js`: `buildMesh(figma, spec)` creates isolated native
  Gaussian-mask groups with separate color fills and returns their node IDs.
  Inline it into a supported Figma execution tool; it is not a standalone plugin.
- `scripts/blue_orange_studies.js`: rebuilds the six native studies after
  `figma_native.js` is inlined. Supply a clear x/y position; optional `keys`
  selects studies and `heightmap` controls detail, warp, levels and blur.
  The builder was executed and visually inspected in live Figma. Its paths use
  a 3:2 composition; recompose when changing the aspect ratio.
- `scripts/render_svg.py`: a Python 3 standard-library generator for four
  original schematic families. It does not segment an input image or reproduce
  every advanced effect.

  ```sh
  python3 scripts/render_svg.py --effect atmospheric --seed 17 \
    --width 1200 --height 800 --output study.svg
  ```

- `scripts/palette_studies.js`: four palette previews and three recomposed
  layouts. `layoutSpec` converts short-side support radii to the native helper's
  per-axis units. Browser-layout parity with live Figma remains unverified.
- `index.html`: the single illustrated guide, with English explanations and
  short Chinese notes, real Figma samples, the Sky blur comparison, palette
  controls and 16:9 / 1:1 / 9:16 layout studies. Download the **whole repository**
  and open it locally. Its controls do not sync edits to Figma.

Native layers, imported SVG and flattened images have different editing limits.
The package does not include automatic PPT creation, image segmentation or a
complete shader/reveal engine. For broad light fields, compare 100/150/200 px
at 1536×1024; Flower uses 125–160 px and 56–85% plane opacity, while Heightmap
uses 24–38 px across 40 levels. Scale the chosen radius with the short side.
Gaussian-mask masses use no extra layer blur by default. Recompose for a new
aspect ratio. The legacy SVG `petal` sketch is not the Flower visual target.

Recipes draw on inspected native artwork and recovered construction records.
The six-study builder and mask helper have been run in Figma; browser layouts
still need target calibration. See the guide for verification scope.

## 中文简要说明

这份 Skill 帮助 AI Agent 把用途、配色、构图和修改要求写成具体配方，再生成可编辑的
Figma 图层或 SVG。适合 PPT 封面、网页主视觉、缩略图和品牌视觉。

方法与生成式界面研究中的“条件输入、设计约束、反馈修改”相连。当前实现是 Agent
指令与图形脚本；论文模型和实验结果不属于本包的实现或成绩。

安装时保留完整目录，用 `$genai-mesh-gradient` 调用。说明画幅、品牌色、文字位置和
可编辑要求；需要 Figma 原生图层时，先接通支持画布写入的工具。MCP 在这里是 Agent
读取和操作 Figma 的连接通道，安装 Skill 本身不会建立连接。

先固定构图比较配色，选定后再调整融合、对比与细节。六类样例、参数及操作说明见
[同一份图解页](index.html)。原生图层、SVG 与位图的可编辑程度不同，交付前应核对。

## License

[MIT](LICENSE). Independent community project; not affiliated with Figma or an
image-generation provider.
````

## File: scripts/blue_orange_studies.js
size: 12459
sha: eb8d932ba3f5383e1a152f61132ff8300d5c4f7c
upstream: https://github.com/9929y/genai-mesh-gradient/blob/HEAD/scripts/blue_orange_studies.js

```text
// Inline after figma_native.js in a supported Figma Plugin API tool.
// Additive: creates six artboards at a caller-supplied clear page position.
function buildBlueOrangeStudies(figma, options) {
  const {x,y,width=1536,height=1024,keys=['sky','dreamlike','flower','diffuse','heightmap','multipoint']}=options||{};
  if(!Array.isArray(keys)||keys.some(k=>!['sky','dreamlike','flower','diffuse','heightmap','multipoint'].includes(k))||new Set(keys).size!==keys.length)throw new Error('Choose unique study keys');
  if(![x,y,width,height].every(Number.isFinite)||width<=0||height<=0||width>8192||height>8192)throw new Error('Supply a clear x/y and valid dimensions');
  if(Math.abs(width/height-1.5)>.001)throw new Error('These study compositions use 3:2; recompose for a different ratio');
  if(typeof buildMesh!=='function')throw new Error('Inline figma_native.js before this source');
  const H={detail:1,warp:1,levels:40,blurMin:24,blurMax:38,...(options?.heightmap||{})};
  if(![H.detail,H.warp,H.levels,H.blurMin,H.blurMax].every(Number.isFinite)||H.detail<0||H.detail>2||H.warp<0||H.warp>2||!Number.isInteger(H.levels)||H.levels<12||H.levels>80||H.blurMin<0||H.blurMax<H.blurMin||H.blurMax>200)throw new Error('Invalid Heightmap controls');
  const P={cream:'#F8F1E8',white:'#FFF7EB',ice:'#DFE8F4',mist:'#B9CEE9',blue:'#7398D1',cobalt:'#3E64AC',navy:'#263C78',orange:'#EB7D45',peach:'#F4B78B',pale:'#F8D8B9'};
  const ids=[],boards=[],s=Math.min(width,height)/1024;
  const rgb=hex=>({r:parseInt(hex.slice(1,3),16)/255,g:parseInt(hex.slice(3,5),16)/255,b:parseInt(hex.slice(5,7),16)/255});
  const solid=hex=>({type:'SOLID',color:rgb(hex)});
  function linear(colors,angle=0){const a=angle*Math.PI/180,c=Math.cos(a),v=Math.sin(a);return{type:'GRADIENT_LINEAR',gradientTransform:[[c,v,.5-.5*c-.5*v],[-v,c,.5+.5*v-.5*c]],gradientStops:colors.map((hex,i)=>({position:i/(colors.length-1),color:{...rgb(hex),a:1}}))};}
  function blur(n,r){n.effects=r?[{type:'LAYER_BLUR',radius:r*s,visible:true}]:[];}
  function board(key,name,index,fill){const f=figma.createFrame();ids.push(f.id);f.name=`Mesh study / ${key} / ${name}`;f.resize(width,height);f.x=x+(index%3)*(width+200*s);f.y=y+Math.floor(index/3)*(height+200*s);f.fills=[fill||solid(P.cream)];f.clipsContent=true;boards.push({key,id:f.id,name,width,height});return f;}
  function path(f,name,d,colors,angle=0,radius=0,alpha=1){const v=figma.createVector();ids.push(v.id);f.appendChild(v);v.name=name;v.x=0;v.y=0;let k=0;const data=d.replace(/-?\d+(?:\.\d+)?/g,n=>(Number(n)*(k++%2?height/1024:width/1536)).toFixed(3));v.vectorPaths=[{windingRule:'NONZERO',data}];v.fills=[Array.isArray(colors)?linear(colors,angle):solid(colors)];v.strokes=[];v.opacity=alpha;blur(v,radius);return v;}
  function pool(f,name,color,cx,cy,rx,ry,alpha=1,radius=0,angle=0){const v=figma.createRectangle();ids.push(v.id);f.appendChild(v);v.name=name;const w=rx*2*width,h=ry*2*height;v.resize(w,h);const a=angle*Math.PI/180,c=Math.cos(a),q=Math.sin(a);v.relativeTransform=[[c,-q,cx*width-c*w/2+q*h/2],[q,c,cy*height-q*w/2-c*h/2]];v.strokes=[];v.fills=[{type:'GRADIENT_RADIAL',gradientTransform:[[1,0,0],[0,1,0]],gradientStops:[{position:0,color:{...rgb(color),a:alpha}},{position:.28,color:{...rgb(color),a:alpha*.84}},{position:.68,color:{...rgb(color),a:alpha*.28}},{position:1,color:{...rgb(color),a:0}}]}];blur(v,radius);return v;}

  if(keys.includes('sky')){
    const sky=board('sky','Apricot current / blue hour',0,linear([P.navy,P.blue,P.ice],-55));
    path(sky,'01 / broad diagonal apricot current','M -260 740 C 90 690 300 560 540 470 C 870 350 1050 210 1270 80 C 1450 -30 1590 -90 1780 -70 L 1800 510 C 1420 470 1230 600 970 720 C 680 850 320 1050 -260 1150 Z',[P.orange,P.peach,P.pale],-22,140,.97);
    path(sky,'02 / open ivory atmosphere','M -240 -160 L 1780 -160 L 1730 180 C 1400 10 1100 140 880 240 C 460 410 240 440 -240 360 Z',[P.ice,P.white,P.pale],-16,155,.86);
    path(sky,'03 / lower cobalt depth','M -200 1260 L 1740 1260 L 1770 590 C 1400 570 1230 740 990 840 C 540 1010 330 920 -200 1130 Z',[P.navy,P.cobalt,P.blue],-26,145,.92);
    pool(sky,'04 / sunlit cream opening',P.white,.94,.14,.64,.56,.82,140,18);
    pool(sky,'05 / reflected warm edge',P.peach,.14,.96,.64,.36,.48,125,-22);
  }

  if(keys.includes('dreamlike')){
    const dream=board('dreamlike','Suspended light / blue shadow',1,linear([P.mist,P.blue,P.ice],12));
    path(dream,'01 / descending blue shadow','M 110 -220 C 420 -120 620 70 630 290 C 650 510 420 680 620 1190 L 1160 1240 C 970 950 910 760 1010 560 C 1170 240 1080 -20 900 -220 Z',[P.navy,P.cobalt,P.blue],68,130,.90);
    pool(dream,'02 / asymmetric apricot light',P.orange,.05,.56,.77,.65,1,125,-22);
    path(dream,'03 / broad suspended ivory field','M 710 -240 C 1120 -110 1030 120 1030 320 C 1030 560 900 710 970 1240 L 1740 1240 L 1740 -220 Z',[P.ice,P.white,P.pale],75,165,.94);
    pool(dream,'04 / warm light echo',P.peach,.48,.69,.44,.29,.62,125,25);
    pool(dream,'05 / lower cool return',P.cobalt,.30,1.14,.66,.43,.78,140,-20);
    pool(dream,'06 / upper mist reflection',P.mist,.12,-.10,.70,.35,.67,120,10);
  }

  if(keys.includes('flower')){
    const flower=board('flower','Magnified petal / luminous apricot',2,linear([P.pale,P.peach,P.orange],24));
    path(flower,'01 / cropped blue petal','M -280 -220 L 650 -220 C 440 130 390 390 430 620 C 460 870 620 1080 580 1270 L -280 1270 Z',[P.ice,P.blue,P.cobalt],78,125,.82);
    path(flower,'02 / deep interval behind petal','M 330 -220 C 310 140 390 310 380 500 C 350 750 430 990 660 1240 L 1010 1250 C 660 920 670 650 610 450 C 550 230 620 30 770 -220 Z',[P.blue,P.navy,P.cobalt],65,145,.56);
    path(flower,'03 / luminous apricot face','M 770 -230 C 640 100 590 370 650 590 C 720 850 1020 1020 1160 1240 L 1790 1240 L 1790 -230 Z',[P.pale,P.peach,P.orange],80,145,.85);
    pool(flower,'04 / light through upper petal',P.white,.57,.10,.47,.62,.75,125,-14);
    path(flower,'05 / cropped cool shadow at right','M 1170 -250 C 1290 -40 1260 150 1430 300 C 1570 420 1690 420 1820 400 L 1820 -250 Z',[P.navy,P.blue,P.peach],45,160,.60);
    pool(flower,'06 / reflected peach at lower left',P.peach,.02,.88,.43,.44,.50,135,-16);
  }

  if(keys.includes('diffuse')){
  const diffuse=board('diffuse','Blue mist / warm paper',3,linear([P.ice,P.cream,P.pale],-35));
  pool(diffuse,'01 / blue field',P.cobalt,.12,.20,.7,.76,.8,165,-20);
  pool(diffuse,'02 / apricot field',P.orange,.88,.74,.75,.88,.65,185,25);
  pool(diffuse,'03 / pale central space',P.white,.52,.47,.78,.72,.92,160,-20);
  path(diffuse,'04 / low contrast blue drift','M -180 1200 C 80 760 510 1000 890 660 C 1180 400 1420 470 1750 290 L 1750 740 C 1410 770 1280 700 1050 900 C 640 1280 300 1100 100 1250 Z',[P.mist,P.blue,P.ice],-28,155,.68);

  }

  function mix(a,b,t){const A=rgb(a),B=rgb(b);return '#'+['r','g','b'].map(k=>Math.round((A[k]+(B[k]-A[k])*t)*255).toString(16).padStart(2,'0')).join('');}
  function ramp(t){const stops=[P.navy,P.cobalt,P.blue,P.ice,P.cream,P.peach,P.orange];const k=t*(stops.length-1),i=Math.min(stops.length-2,Math.floor(k));return mix(stops[i],stops[i+1],k-i);}
  // Sample a warped multi-hill scalar field; marching squares preserves splits,
  // islands and saddles. These contours are not scaled copies of a single path.
  function heightContours(){
    const nx=112,ny=80,pad=.18,vals=[],lo=-pad,span=1+2*pad;
    const gauss=(u,v,cx,cy,rx,ry,a)=>{const dx=u-cx,dy=v-cy,c=Math.cos(a),s=Math.sin(a);return Math.exp(-.5*(((c*dx+s*dy)/rx)**2+((-s*dx+c*dy)/ry)**2));};
    const raw=(x,y)=>{const u=x+H.warp*(.065*Math.sin(2*Math.PI*y)+.035*Math.sin(4*Math.PI*x+2*Math.PI*y)),v=y+H.warp*.065*Math.sin(2*Math.PI*x-.7);return .5+.19*Math.sin(2*Math.PI*(.85*u+.70*v))+.14*Math.cos(2*Math.PI*(1.55*u-.55*v))+.115*Math.sin(2*Math.PI*(.60*u-1.45*v))+.15*gauss(u,v,.16,.22,.28,.14,-.48)+H.detail*(.10*Math.sin(2*Math.PI*(2.8*u+1.25*v))+.065*Math.cos(2*Math.PI*(-2.3*u+2.15*v)))+.13*gauss(u,v,.78,.76,.25,.16,-.60)-.12*gauss(u,v,.48,.55,.13,.29,-.35);};
    let min=Infinity,max=-Infinity;
    for(let j=0;j<=ny;j++){vals[j]=[];for(let i=0;i<=nx;i++){const v=raw(lo+i/nx*span,lo+j/ny*span);vals[j][i]=v;if(i>0&&i<nx&&j>0&&j<ny){min=Math.min(min,v);max=Math.max(max,v);}}}
    for(let j=0;j<=ny;j++)for(let i=0;i<=nx;i++)vals[j][i]=(i===0||j===0||i===nx||j===ny)?-1:(vals[j][i]-min)/(max-min);
    const result=[];
    for(let level=1;level<=H.levels;level++){
      const t=level/(H.levels+1),pts=new Map(),adj=new Map();
      function edge(i,j,e){let ai=i,aj=j,bi=i,bj=j,key;
        if(e===0){bi++;key=`h:${i}:${j}`;}if(e===1){ai++;bi++;bj++;key=`v:${i+1}:${j}`;}if(e===2){aj++;bj++;bi++;key=`h:${i}:${j+1}`;}if(e===3){bj++;key=`v:${i}:${j}`;}
        if(!pts.has(key)){const A=vals[aj][ai],B=vals[bj][bi],q=(t-A)/(B-A);pts.set(key,[(lo+(ai+(bi-ai)*q)/nx*span)*1536,(lo+(aj+(bj-aj)*q)/ny*span)*1024]);}return key;
      }
      function segment(i,j,a,b){const A=edge(i,j,a),B=edge(i,j,b);if(!adj.has(A))adj.set(A,[]);if(!adj.has(B))adj.set(B,[]);adj.get(A).push(B);adj.get(B).push(A);}
      const table={1:[[3,0]],2:[[0,1]],3:[[3,1]],4:[[1,2]],6:[[0,2]],7:[[3,2]],8:[[2,3]],9:[[0,2]],11:[[1,2]],12:[[3,1]],13:[[0,1]],14:[[3,0]]};
      for(let j=0;j<ny;j++)for(let i=0;i<nx;i++){
        const z=[vals[j][i],vals[j][i+1],vals[j+1][i+1],vals[j+1][i]],c=z.reduce((m,v,k)=>m+(v>=t?1<<k:0),0),inside=z.reduce((a,b)=>a+b,0)/4>=t;
        const pairs=c===5?(inside?[[0,1],[2,3]]:[[3,0],[1,2]]):c===10?(inside?[[3,0],[1,2]]:[[0,1],[2,3]]):(table[c]||[]);for(const pair of pairs)segment(i,j,...pair);
      }
      const seen=new Set(),loops=[];
      for(const start of adj.keys()){if(seen.has(start))continue;let cur=start,prev=null,loop=[];for(let safe=0;safe<20000;safe++){if(seen.has(cur))break;seen.add(cur);loop.push(pts.get(cur));const ns=adj.get(cur);const next=ns.find(k=>k!==prev);prev=cur;cur=next;if(cur===start||!cur)break;}if(cur===start&&loop.length>=12)loops.push(loop);}
      const pathData=loops.map(ps=>{const p=ps.filter((_,i)=>i%2===0);if(p.length<4)return '';let d=`M ${p[0][0]} ${p[0][1]}`;for(let k=0;k<p.length;k++){const a=p[(k+p.length-1)%p.length],b=p[k],c=p[(k+1)%p.length],e=p[(k+2)%p.length];d+=` C ${b[0]+(c[0]-a[0])/6} ${b[1]+(c[1]-a[1])/6} ${c[0]-(e[0]-b[0])/6} ${c[1]-(e[1]-b[1])/6} ${c[0]} ${c[1]}`;}return d+' Z';}).join(' ');
      if(pathData)result.push({t,data:pathData,loopCount:loops.length});
    }
    return result;
  }
  if(keys.includes('heightmap')){
    const heightmap=board('heightmap','Crosscurrents / peaks and saddles',4,solid(P.navy));
    const contours=heightContours();
    for(let i=0;i<contours.length;i++){const c=contours[i],v=path(heightmap,`Height ${String(i+1).padStart(2,'0')} / ${c.loopCount} region(s)`,c.data,ramp(c.t),0,H.blurMin+(H.blurMax-H.blurMin)*(1-c.t),1);v.vectorPaths=[{windingRule:'EVENODD',data:v.vectorPaths[0].data}];}
    boards[boards.length-1].contourTopology=contours.map(c=>({height:c.t,regions:c.loopCount}));
  }

  if(keys.includes('multipoint')){
  const mesh=buildMesh(figma,{name:'Mesh study / multipoint / Porcelain blue and apricot',width,height,x:x+2*(width+200*s),y:y+(height+200*s),base:P.cream,regions:[
    {color:P.blue,x:.19,y:.16,rx:.92,ry:1.02,alpha:.94,angle:-20},
    {color:P.peach,x:.84,y:.69,rx:1.03,ry:1.18,alpha:.94,angle:20},
    {color:P.cobalt,x:.35,y:.77,rx:1.2,ry:.35,alpha:.98,angle:-28},
    {color:P.navy,x:-.03,y:.96,rx:.9,ry:.35,alpha:.9,angle:-30},
    {color:P.white,x:.5,y:.4,rx:.95,ry:.32,alpha:.97,angle:-30},
    {color:P.orange,x:.83,y:.23,rx:.53,ry:.68,alpha:.96,angle:28},
    {color:P.pale,x:.62,y:.47,rx:.52,ry:.38,alpha:.82,angle:-22},
    {color:P.navy,x:.99,y:.94,rx:.78,ry:.7,alpha:.7,angle:-20},
    {color:P.ice,x:.92,y:.62,rx:.65,ry:.45,alpha:.88,angle:12},
    {color:P.white,x:.39,y:.62,rx:.6,ry:.16,alpha:.65,angle:-28},
    {color:P.peach,x:.1,y:1.12,rx:.95,ry:.48,alpha:.84,angle:15}
  ]});
  ids.push(...mesh.createdNodeIds);boards.push({key:'multipoint',id:mesh.frameId,name:'Porcelain blue and apricot',width,height,massNodes:mesh.massNodes});
  }
  return{createdNodeIds:ids,mutatedNodeIds:[figma.currentPage.id],boards,palette:P,heightmapSettings:keys.includes('heightmap')?H:undefined,referenceSize:{width:1536,height:1024},note:'All native, no imported reference bitmaps. Curve and radial studies are purpose-designed examples, not exact replays of historical artwork.'};
}
if(typeof module!=='undefined'&&module.exports)module.exports={buildBlueOrangeStudies};
```

## File: scripts/figma_native.js
size: 3502
sha: 91a3a35902705d2bf5aa0702c5b13f95c3d47da1
upstream: https://github.com/9929y/genai-mesh-gradient/blob/HEAD/scripts/figma_native.js

```text
// Inline into a documented Figma Plugin API execution tool, then call buildMesh.
// This additive helper builds editable radial masses, not a mesh control grid.
function buildMesh(figma, spec) {
  const finite = (v, name) => {
    if (typeof v !== 'number' || !Number.isFinite(v)) throw new Error(`Invalid ${name}`);
    return v;
  };
  const rgb = (hex) => {
    if (typeof hex !== 'string' || !/^#[0-9a-f]{6}$/i.test(hex)) throw new Error('Use #RRGGBB colors');
    return { r: parseInt(hex.slice(1,3),16)/255,
      g: parseInt(hex.slice(3,5),16)/255, b: parseInt(hex.slice(5,7),16)/255 };
  };
  const width = finite(spec.width, 'width'), height = finite(spec.height, 'height');
  if (width <= 0 || height <= 0 || width > 16384 || height > 16384) throw new Error('Invalid canvas size');
  const x = finite(spec.x, 'canvas x'), y = finite(spec.y, 'canvas y');
  const baseColor = spec.base === null ? null : rgb(spec.base || '#f2d5c5');
  if (!Array.isArray(spec.regions) || !spec.regions.length || spec.regions.length > 256) {
    throw new Error('Supply 1–256 ordered regions');
  }
  // Validate the entire recipe before creating any node.
  const regions = spec.regions.map((r, i) => {
    const color = rgb(r.color);
    ['x','y','rx','ry'].forEach(k => finite(r[k], `region ${i} ${k}`));
    if (r.rx <= 0 || r.ry <= 0 || r.rx > 4 || r.ry > 4) throw new Error('Invalid region extent');
    const alpha = finite(r.alpha ?? 1, 'alpha');
    const angle = finite(r.angle ?? 0, 'angle');
    if (alpha < 0 || alpha > 1) throw new Error('Invalid alpha');
    return {...r, color, alpha, angle};
  });
  const affectedParentId = figma.currentPage.id;
  const frame = figma.createFrame();
  const createdNodeIds = [frame.id];
  const massNodes = [];
  frame.name = spec.name || 'Mesh / radial field';
  frame.resize(width, height);
  frame.x = x; frame.y = y; frame.clipsContent = true;
  frame.fills = baseColor ? [{type:'SOLID', color:baseColor}] : [];
  for (const [i,r] of regions.entries()) {
    const group = figma.createFrame();
    createdNodeIds.push(group.id); frame.appendChild(group);
    group.name = `Mass ${i+1} / move-scale-rotate`;
    const w=r.rx*2*width, h=r.ry*2*height;
    group.resize(w,h);group.fills=[];group.clipsContent=false;group.opacity=r.alpha;
    const a=r.angle*Math.PI/180,c=Math.cos(a),s=Math.sin(a);
    group.relativeTransform=[[c,-s,r.x*width-c*w/2+s*h/2],
      [s,c,r.y*height-s*w/2-c*h/2]];
    const mask=figma.createRectangle();createdNodeIds.push(mask.id);
    group.appendChild(mask);mask.resize(w,h);mask.name='Soft boundary / alpha mask';
    mask.strokes=[];
    mask.fills = [{type:'GRADIENT_RADIAL',
      gradientTransform:[[1,0,0],[0,1,0]],
      gradientStops:Array.from({length:49},(_,k)=>({position:k/48,
        color:{r:0,g:0,b:0,a:k===48?0:Math.exp(-8*(k/48)**2)}}))}];
    mask.isMask=true;mask.maskType='ALPHA';
    const color=figma.createRectangle();createdNodeIds.push(color.id);
    group.appendChild(color);color.resize(w,h);color.name='Color / edit Fill';
    color.strokes=[];color.fills=[{type:'SOLID',color:r.color}];
    massNodes.push({groupId:group.id,maskId:mask.id,colorId:color.id,
      center:{x:r.x,y:r.y},halfExtent:{x:r.rx,y:r.ry},angle:r.angle,alpha:r.alpha});
  }
  return {frameId:frame.id, createdNodeIds, mutatedNodeIds:[affectedParentId],
    bounds:{x,y,width,height}, regionCount:regions.length,massNodes,
    method:'editable Gaussian radial-mask groups', background:baseColor?'opaque':'transparent'};
}
```

## File: scripts/palette_studies.js
size: 5331
sha: 5bd18e4e037704f61e54597b848fb16fcdacf5bf
upstream: https://github.com/9929y/genai-mesh-gradient/blob/HEAD/scripts/palette_studies.js

```text
/* Portable palette/layout studies. No connection or Figma writes on load. */
(function (root) {
  'use strict';
  const palettes = {
    mono: {name:'Monochromatic', colors:['#fff4e7','#fddaaa','#f6ad71','#b7542e'], advice:'Monochromatic: use tonal separation for coherent covers and section backgrounds. Similar midtones can flatten the composition.'},
    adjacent: {name:'Analogous warm', colors:['#fff4e7','#e6be6c','#f6ad71','#c97c83'], advice:'Analogous warm: let gold, apricot or rose lead. Keep the other colors subordinate.'},
    contrast: {name:'Apricot × cobalt', colors:['#f8f1e8','#f4b78b','#7398d1','#3e64ac'], advice:'Apricot × cobalt: warm white and apricot set the atmosphere; blue supplies structure. Compare coverage and negative space; reduce overlap if it turns gray.'},
    neutral: {name:'Neutral + accent', colors:['#f4f5f3','#d5dede','#91a9b4','#3f708e'], advice:'Neutral + accent: suitable for content-heavy pages. Keep a blue anchor to preserve visual identity.'}
  };
  // CSS background order is front to back. Positions/stops match the guide.
  const pools = [[1,.18,.28,.60],[2,.78,.28,.62],[3,.65,.95,.50],[2,.25,.88,.60]];
  function colorsValid(colors) {
    if (!Array.isArray(colors)||colors.length!==4||colors.some(c=>!/^#[0-9a-f]{6}$/i.test(c))) throw new Error('Supply four #RRGGBB role colors');
    return colors;
  }
  function paletteCSS(colors) {
    const c=colorsValid(colors);
    return pools.map(([k,x,y,end])=>`radial-gradient(ellipse at ${x*100}% ${y*100}%,${c[k]} 0%,transparent ${end*100}%)`).join(',')+','+c[0];
  }
  function paletteSVG(key, width=1200, height=600) {
    const c=colorsValid(palettes[key]?.colors);
    if (![width,height].every(n=>Number.isFinite(n)&&n>0&&n<=16384)) throw new Error('Invalid size');
    const defs=pools.map(([k,x,y,end],i)=>{
      const rx=Math.SQRT2*Math.max(x,1-x)*width;
      const ry=Math.SQRT2*Math.max(y,1-y)*height;
      return `<radialGradient id="pool${i}" gradientUnits="userSpaceOnUse" cx="0" cy="0" r="1" gradientTransform="translate(${x*width} ${y*height}) scale(${rx} ${ry})"><stop stop-color="${c[k]}"/><stop offset="${end}" stop-color="${c[k]}" stop-opacity="0"/></radialGradient>`;
    }).join('');
    return `<svg xmlns="http://www.w3.org/2000/svg" width="${width}" height="${height}" viewBox="0 0 ${width} ${height}"><title>${key} / fixed four-pool palette study</title><defs>${defs}</defs><rect width="100%" height="100%" fill="${c[0]}"/>`+pools.map((_,i)=>i).reverse().map(i=>`<rect width="100%" height="100%" fill="url(#pool${i})"/>`).join('')+'</svg>';
  }
  function layoutSpec(width, height, key='contrast') {
    if (![width,height].every(n=>Number.isFinite(n)&&n>0&&n<=16384)) throw new Error('Invalid canvas size');
    const c=colorsValid(palettes[key]?.colors), short=Math.min(width,height), ratio=width/height;
    let layout, quietZone, regions;
    // [color index, normalized center, short-side support half-extents, angle, alpha]
    if (ratio>=1.35) {
      layout='wide'; quietZone={x:.06,y:.17,width:.33,height:.55};
      regions=[[1,.74,.24,1.15,.92,-18,.93],[2,.94,.80,1.0,.86,15,.96],[3,.59,1.02,.9,.68,-28,.92],[2,.53,.80,.82,.48,-32,.8]];
    } else if (ratio<=.8) {
      layout='portrait'; quietZone={x:.09,y:.055,width:.82,height:.24};
      regions=[[1,.32,.58,1.2,1.0,-30,.96],[2,.91,.73,1.1,1.25,25,.96],[3,.35,.99,1.1,.8,-15,.93],[2,.91,.43,.8,.9,18,.72]];
    } else {
      layout='square'; quietZone={x:.08,y:.08,width:.60,height:.25};
      regions=[[1,.30,.70,1.2,.85,-26,.94],[2,.93,.49,1.0,1.0,20,.94],[3,.84,.99,1.05,.8,-18,.90],[2,.15,.98,.9,.7,15,.72]];
    }
    return {name:`Palette / ${key} / ${layout}`,width,height,base:c[0],layout,quietZone,
      regions:regions.map(([k,x,y,rx,ry,angle,alpha])=>({color:c[k],x,y,rx:rx*short/width,ry:ry*short/height,angle,alpha}))};
  }
  function layoutSVG(spec, showQuiet=true) {
    const {width:w,height:h,regions,quietZone:q}=spec;
    const prefix=`layout-${w}-${h}-`;
    const defs=regions.map((r,i)=>`<radialGradient id="${prefix}mass${i}">`+Array.from({length:49},(_,k)=>`<stop offset="${k/48}" stop-color="${r.color}" stop-opacity="${k===48?0:Math.exp(-8*(k/48)**2)*r.alpha}"/>`).join('')+'</radialGradient>').join('');
    const masses=regions.map((r,i)=>`<ellipse cx="0" cy="0" rx="${r.rx*w}" ry="${r.ry*h}" transform="translate(${r.x*w} ${r.y*h}) rotate(${r.angle})" fill="url(#${prefix}mass${i})"/>`).join('');
    const quiet=showQuiet?`<rect x="${q.x*w}" y="${q.y*h}" width="${q.width*w}" height="${q.height*h}" rx="${.008*Math.min(w,h)}" fill="white" fill-opacity=".38" stroke="#60472e" stroke-opacity=".6" stroke-width="${Math.min(w,h)*.002}" stroke-dasharray="${Math.min(w,h)*.01} ${Math.min(w,h)*.008}"/><text x="${(q.x+.025)*w}" y="${(q.y+.04)*h}" fill="#493d33" font-family="sans-serif" font-size="${Math.min(w,h)*.022}">TITLE ZONE</text>`:'';
    return `<svg xmlns="http://www.w3.org/2000/svg" width="${w}" height="${h}" viewBox="0 0 ${w} ${h}" role="img" aria-label="${spec.layout} recomposed palette study"><defs>${defs}</defs><rect width="100%" height="100%" fill="${spec.base}"/>${masses}${quiet}</svg>`;
  }
  const api={palettes,pools,paletteCSS,paletteSVG,layoutSpec,layoutSVG};
  root.MeshGradientStudies=api;
  if(typeof module!=='undefined'&&module.exports) module.exports=api;
})(globalThis);
```

## File: scripts/render_svg.py
size: 6305
sha: dcd452209b95b1dfce9210d9e6336e085aff3f64
upstream: https://github.com/9929y/genai-mesh-gradient/blob/HEAD/scripts/render_svg.py

```text
#!/usr/bin/env python3
"""Deterministic original mesh studies. Python 3 standard library only."""
import argparse
import html
import math
from pathlib import Path
import random
import re

EFFECTS = ('atmospheric', 'fluid', 'pigment', 'petal')
DEFAULT_PALETTE = ('#f2d5c5', '#eb765c', '#b3a3bd', '#f6c46e', '#7798a0')

def render_svg(effect='atmospheric', width=1200, height=800, seed=17,
               palette=DEFAULT_PALETTE, transparent=False, texture=0.035):
    """Return SVG text. No file writes, image analysis, or network access."""
    if effect not in EFFECTS:
        raise ValueError('Unknown effect')
    if not all(isinstance(n, int) and 16 <= n <= 16384 for n in (width, height)):
        raise ValueError('Dimensions must be integers in 16..16384')
    if not 2 <= len(palette) <= 12 or any(not re.fullmatch(r'#[0-9a-fA-F]{6}', c) for c in palette):
        raise ValueError('Supply 2..12 #RRGGBB colors')
    if not math.isfinite(texture) or not 0 <= texture <= .2:
        raise ValueError('Texture must be between 0 and .2')
    rng = random.Random(seed)
    defs = []
    shapes = []
    count = 9 if effect != 'petal' else 8
    d = min(width, height)
    for i in range(count):
        color = palette[1 + i % (len(palette)-1)]
        gid = f'gradient-{i}'
        defs.append(f'<radialGradient id="{gid}"><stop offset="0" stop-color="{color}"/>'
                    f'<stop offset=".28" stop-color="{color}" stop-opacity=".90"/>'
                    f'<stop offset="1" stop-color="{color}" stop-opacity="0"/></radialGradient>')
        cx, cy = rng.uniform(.02,.98)*width, rng.uniform(.02,.98)*height
        rx, ry = rng.uniform(.25,.55)*width, rng.uniform(.25,.55)*height
        angle = rng.uniform(-65,65)
        if effect == 'fluid':
            rx, ry = rng.uniform(.45,.85)*width, rng.uniform(.06,.15)*height
            angle = -24 + rng.uniform(-16,16)
        if effect == 'petal':
            # Curved, asymmetric lobes around a loose center; not source-derived.
            theta = i * math.tau / count + rng.uniform(-.18,.18)
            cx, cy = width*.50 + rng.uniform(-.06,.06)*width, height*.52 + rng.uniform(-.06,.06)*height
            length = rng.uniform(.36,.58)*d
            spread = rng.uniform(.09,.20)*d
            angle = theta*180/math.pi
            path = (f'M 0 0 C {-spread:.3f} {-length*.22:.3f} '
                    f'{-spread:.3f} {-length:.3f} 0 {-length:.3f} '
                    f'C {spread*1.35:.3f} {-length*.83:.3f} '
                    f'{spread:.3f} {-length*.12:.3f} 0 0 Z')
            shapes.append(f'<path id="petal-{i}" d="{path}" fill="url(#{gid})" '
                          f'transform="translate({cx:.3f} {cy:.3f}) rotate({angle:.3f})"/>')
        else:
            shapes.append(f'<ellipse id="mass-{i}" cx="{cx:.3f}" cy="{cy:.3f}" '
                          f'rx="{rx:.3f}" ry="{ry:.3f}" fill="url(#{gid})" '
                          f'transform="rotate({angle:.3f} {cx:.3f} {cy:.3f})"/>')
    if effect == 'pigment':
        defs.append(f'<filter id="bleed" x="-20%" y="-20%" width="140%" height="140%" '
                    f'color-interpolation-filters="sRGB"><feTurbulence type="fractalNoise" '
                    f'baseFrequency="{5/d:.6f} {9/d:.6f}" numOctaves="2" seed="{seed % 10000}" '
                    f'result="noise"/><feDisplacementMap in="SourceGraphic" in2="noise" '
                    f'scale="{d*.045:.3f}" xChannelSelector="R" yChannelSelector="G"/></filter>')
    if texture:
        defs.append(f'<filter id="grain" x="0" y="0" width="100%" height="100%" '
                    f'color-interpolation-filters="sRGB"><feTurbulence type="fractalNoise" '
                    f'baseFrequency=".75" numOctaves="2" seed="{seed % 10000}" result="noise"/>'
                    f'<feColorMatrix in="noise" type="saturate" values="0"/>'
                    f'<feComposite in2="SourceGraphic" operator="in"/></filter>')
    bg = '' if transparent else f'<rect id="base" width="100%" height="100%" fill="{palette[0]}"/>'
    attr = ' filter="url(#bleed)"' if effect == 'pigment' else ''
    masses = f'<g id="color-masses"{attr}>' + ''.join(shapes) + '</g>'
    # Grain is clipped to artwork alpha. Transparent corners do not get a gray sheet.
    if texture:
        alpha_shapes = re.sub(r' id="[^"]+"', '', bg + masses)
        defs.append('<mask id="art-alpha" mask-type="alpha">' + alpha_shapes + '</mask>')
    grain = (f'<g mask="url(#art-alpha)"><rect id="texture" width="100%" height="100%" '
             f'fill="white" opacity="{texture}" filter="url(#grain)"/></g>') if texture else ''
    title = html.escape(f'{effect} — original procedural study, seed {seed}')
    return (f'<svg xmlns="http://www.w3.org/2000/svg" width="{width}" height="{height}" '
            f'viewBox="0 0 {width} {height}" role="img" aria-labelledby="title">'
            f'<title id="title">{title}</title><defs>'+''.join(defs)+'</defs>'
            +bg+masses+grain+'</svg>')

def main():
    parser = argparse.ArgumentParser(description=__doc__)
    parser.add_argument('--effect', choices=EFFECTS, default='atmospheric')
    parser.add_argument('--width', type=int, default=1200)
    parser.add_argument('--height', type=int, default=800)
    parser.add_argument('--seed', type=int, default=17)
    parser.add_argument('--palette', help='Comma-separated #RRGGBB colors; first is the base')
    parser.add_argument('--transparent', action='store_true')
    parser.add_argument('--texture', type=float, default=.035, help='Fine grain opacity, 0..0.2')
    parser.add_argument('--output', type=Path, required=True)
    parser.add_argument('--force', action='store_true', help='Overwrite the named output')
    args = parser.parse_args()
    try:
        svg = render_svg(args.effect, args.width, args.height, args.seed,
                         tuple(c.strip() for c in args.palette.split(',')) if args.palette else DEFAULT_PALETTE,
                         args.transparent, args.texture)
        with args.output.open('w' if args.force else 'x', encoding='utf-8') as target:
            target.write(svg)
    except (ValueError, OSError) as error:
        parser.exit(2, f'Error: {error}\n')
    print(f'Created {args.output} ({args.width}x{args.height}; {args.effect})')

if __name__ == '__main__':
    main()
```

## File: references/adapters.md
size: 7008
sha: b395ee328157ad907a116f4c1f57fe849213b8e4
upstream: https://github.com/9929y/genai-mesh-gradient/blob/HEAD/references/adapters.md

````text
# Tool adapters

## Figma

MCP is the connection that lets an agent inspect and operate a Figma file.
This skill supplies the recipe; the installed connector supplies the actions.
Tool names, permissions and availability vary by client.

1. Discover current tools. Confirm native canvas writes (`use_figma` or an
   equivalent documented tool), readback, screenshots and export separately.
   Read-only design-context tools are insufficient for native creation.
2. Resolve the user-selected file and page. Use any connector-required session
   creation and propagate its returned session ID. Do not reuse another user's
   sample file key or hardcode a team. New-file creation must follow the
   connector's team-selection rules.
3. Load the installed Figma write guidance if available; otherwise consult the
   current official API/tool documentation linked below. Inspect the target
   page before placing artwork; find a clear area beside existing content.
4. Define the recipe. Use `scripts/figma_native.js` only for radial mass artwork.
   Each mass has an isolated frame, radial alpha mask, and solid color rectangle.
   This keeps color editing independent of the falloff curve.
   Its `buildMesh(figma, spec)` is a function library, not a CLI and not a
   standalone Figma plugin. Inline the file into the documented JavaScript
   execution tool, append the invocation, and return its result.
5. Read the returned IDs and inspect the actual rendered composition. Adjust
   the specific masses by ID. Verify the export in the intended format.
   If an effect-only edit leaves the preview pixels unchanged despite different
   saved effect values, check a fresh export before judging it. A temporary
   clone can isolate a stale node preview; place it in clear space, return its
   IDs and remove it after export. Do not keep adding blur to compensate for
   an unchanged cached render.

For the current six blue/orange examples, also inline
`scripts/blue_orange_studies.js` and call `buildBlueOrangeStudies` with a clear
x/y and proportional 3:2 dimensions. This builder was executed in live Figma;
see `figma-recipes.md` for its exact shapes, counts and blur values.

Example invocation after loading the radial helper into the write tool:

```js
// Resolve this from a prior page read. Do not invent the page ID.
const page = await figma.getNodeByIdAsync(PAGE_ID);
if (!page || page.type !== 'PAGE') throw new Error('Target page unavailable');
await figma.setCurrentPageAsync(page);
return buildMesh(figma, {
  name: 'Coral / soft field', width: 1200, height: 800,
  x: CLEAR_X, y: CLEAR_Y, base: '#f2d5c5',
  regions: [
    {color:'#ec694e', x:.22, y:.25, rx:.62, ry:.60, alpha:.95},
    {color:'#f5b657', x:.75, y:.35, rx:.52, ry:.65, alpha:.85},
    {color:'#8c81a4', x:.42, y:.85, rx:.68, ry:.50, alpha:.75},
    {color:'#f7e8cc', x:.80, y:.85, rx:.45, ry:.38, alpha:.90}
  ]
});
```

The helper creates an opaque base unless `base: null` is explicitly supplied.
For changing size/ratio, see [palettes-and-layout.md](palettes-and-layout.md):
keep physical radii relative to the short side, then convert to these per-axis units.

Region `rx/ry` are normalized half-extents of the mask frame, not Gaussian
standard deviations; most visible pigment sits well inside that frame.
`angle` is clockwise degrees in the top-left coordinate system. The alpha
falloff samples `exp(-8*r*r)` at 49 stops, with a zero-alpha outer endpoint.
It returns every created node ID, plus the parent page ID it affected.
It uses no unsupported `GRADIENT_MESH` paint type: the result is a layered
radial-gradient approximation with editable geometry, not a mesh control grid.
No text/fonts, bitmap texture, true refraction, blur or motion are added.

Figma details:

- RGB and gradient-stop alpha use 0–1 values. Solid paint RGB excludes alpha;
  paint opacity and gradient-stop RGBA are distinct.
- Reassign fills as new arrays. Use the connector's asynchronous page switch.
- Do not assume every Plugin API method exists in a connector's execution
  environment. Follow its documented subset.
- After an uncertain failed write, inspect for partial creation before retrying;
  the helper is additive and a blind rerun creates duplicates. If IDs were
  returned, target them. If not, inspect the named frame and its bounds.
- Export filters and blend modes may render differently outside Figma. A
  native layer count is not visual proof; inspect pixels too.

For reference fitting, separate raster corrections or other native effect
families, read [figma-recipes.md](figma-recipes.md).

## Layered SVG and another design application

Run the Python helper with Python 3. It uses only the standard library, has no
network calls, and refuses to overwrite an existing output unless `--force`
is passed. Example:

```sh
python3 scripts/render_svg.py --effect atmospheric --seed 17 \
  --width 1200 --height 800 --palette '#f1d9c9,#e98273,#b3a3bd,#f5ca82' \
  --output study.svg
```

Use `--transparent` only when transparent delivery is wanted. Verify the alpha
by viewing on both light and dark backgrounds; a pale opaque base is not
transparency. Keep a common crop/viewBox for comparisons.

Open/import into the requested application using its available connector or
UI. SVG paths and gradients may remain editable; filter support varies.
Confirm object structure in the receiving editor. If filter appearance fails,
choose native path reconstruction or an explicitly labeled raster export.
Do not promise equivalent editability in every application.

## Canvas, WebGL, shaders

Choose this route when the image needs continuous domain warp, structured
brush rendering, source analysis or reveal. Check the target renderer's actual
API before producing code. The two bundled helpers do not supply this engine.

Keep one parameter schema and one rendering pipeline for preview and export.
Render exports again at the target resolution; do not enlarge the preview.
Fix seeds, orientation and alpha handling. For SVG turbulence/displacement,
specify `color-interpolation-filters` deliberately and inspect browser/editor
differences. A noise displacement approximates material; it is not a simulation.

## Image generation

Use an available image-generation tool for a final bitmap when that fits the
request. Supply reference composition, palette, positions, material and crop,
then inspect the returned image. Describe the result as a raster; importing it
as an image fill in Figma does not make its pigment or topology editable.

## Primary documentation (checked 2026-10-24)

- [Figma MCP setup](https://developers.figma.com/docs/figma-mcp-server/)
- [Figma MCP tools](https://developers.figma.com/docs/figma-mcp-server/tools-and-prompts/)
- [Figma paints](https://developers.figma.com/docs/plugins/api/Paint/)
- [SVG turbulence](https://developer.mozilla.org/en-US/docs/Web/SVG/Reference/Element/feTurbulence)
- [SVG displacement](https://developer.mozilla.org/en-US/docs/Web/SVG/Reference/Element/feDisplacementMap)
````

## File: references/art-direction.md
size: 10203
sha: eac66cf5722d688fc06155acf8395a86298f86b4
upstream: https://github.com/9929y/genai-mesh-gradient/blob/HEAD/references/art-direction.md

```text
# Use, palette and art direction

This is design guidance, not a claim that a color harmony guarantees good taste.
Evaluate the gradient inside its actual slide, website or brand application.

## Start from use

| Use | Composition | Deliver and verify |
|---|---|---|
| Presentation cover/divider | One dominant mass, a quiet title area, one restrained accent | Actual deck ratio; commonly 16:9, but use the deck's own dimensions. Export at slide-display resolution (e.g. 1920×1080 for a 1080p deck); keep editable masters separately |
| Dense presentation/content slide | Pale or dark quiet field; put movement near margins | Keep chart/label meanings distinct from decorative color. Test projector-like low contrast and an exported slide, not only the design canvas |
| Web hero | Plan a safe title zone, desktop/mobile crops and sufficient bleed | Check actual viewport ratios, compression and text contrast. Use a stable image/CSS fallback if animation is too costly |
| Cards/thumbnails | A recognizable large shape and color identity at small size | Inspect at actual card size. Grain and fine petals may disappear; do not compensate by over-sharpening everything |
| Brand/social campaign | A repeatable relationship between palette, geometry and material | Keep brand anchors and a small family of layouts. Variants should remain recognizable when viewed together |
| Print/poster | Clear hierarchy at viewing distance; preserve room for content | Use the printer's size, resolution and color-profile requirements. An sRGB screen preview does not establish CMYK/print fidelity |

For editable PPT objects, verify the target application's SVG import and
ungroup behavior. Do not promise that Figma masks and filters become equivalent
PowerPoint objects. A high-resolution background bitmap with an editable design
master is often appropriate when only slide text must remain editable.

## Choose palettes by roles

Respect existing brand colors and usage constraints. If none exist, infer a
candidate direction from the audience, context and reference; do not assign
universal meanings such as “blue always means trust.” Ask only about preferences
that materially affect the result.

Define a background/base, dominant pigment, supporting pigment, light anchor,
and optional accent. Some roles can share a hue. Start with 3–5 useful colors,
then add a color only when it solves a visible composition problem. A fixed
60/30/10 ratio is not a requirement: inspect the rendered distribution.

Offer a small comparison at the same crop, geometry, opacity and seed:

| Direction | Build it | Why choose it | Watch for |
|---|---|---|---|
| Monochromatic | One hue family; vary lightness and chroma, with a compatible light or dark anchor | Cohesive identity, restrained deck/background | Flatness if all tones have equal lightness; muddy darks if made only by adding black |
| Analogous | Neighboring hue families with a deliberate warm/cool bias | Gentle depth and easy transitions | Similar midtones can merge; preserve a clear light/dark hierarchy |
| Complementary / split contrast | A dominant family plus a smaller opposing or split-opposing accent | Distinctive focal tension | Broad overlapping complements can desaturate; reduce accent extent/alpha before changing the whole palette |
| Neutral plus accent | Tinted neutrals with one controlled pigment family | Dense decks, UI-heavy compositions, adaptable brand system | Too little color identity; accent must stay visible at the intended size |

Use OKLCH/OKLab when available to adjust lightness and chroma more deliberately
than equal steps in RGB or HSL. Chroma limits vary with hue and lightness;
gamut-map to the delivery space instead of blindly clipping channels.
Color-space interpolation changes the mixture: inspect the actual target tool,
not just a color-wheel relationship. The SVG helper uses supplied HEX colors;
it is not an OKLCH palette-generation engine.

Example studies (not universal brand prescriptions):

- **Warm monochrome:** ivory #FFF4E7, pale apricot #FDDAAA, peach #F6AD71,
  burnt orange #B7542E. Separate structure through lightness.
- **Adjacent warm:** ivory #FFF4E7, gold #E6BE6C, peach #F6AD71,
  rose #C97C83. Keep one warm family dominant.
- **Apricot/cobalt contrast:** cream #F8F1E8, apricot #F4B78B, blue #7398D1,
  cobalt #3E64AC. Retain a warm pale area and control blue/orange overlap;
  the label describes a visual direction, not exact opposite hue angles.
- **Cool neutral/accent:** paper #F4F5F3, mist #D5DEDE, blue gray #91A9B4,
  blue #3F708E. Keep one darker mass or quiet dark text zone.

Provide each proposal as role-labeled swatches plus a rendered example and one
sentence explaining its use/tradeoff. A list of HEX values alone is not enough.
Let the user choose before producing dozens of color variants. If they say
“more elegant,” translate that into a concrete hypothesis—less competing
saturation, clearer hierarchy, more negative space—and show the comparison.

## Judge it as a brand designer

Check these relationships, rather than prescribing a fashionable color scheme:

1. **Purpose:** does the field support the message and audience, or compete
   with the product/photography/type?
2. **Hierarchy:** is there a dominant mass, a supporting mass, and somewhere
   quiet? Avoid equally sized, equally bright blobs scattered everywhere.
3. **Distinctiveness:** which combination of hue bias, topology and edge rhythm
   makes this brand recognizable across several applications?
4. **Material consistency:** are soft diffusion, crisp contour and grain used
   intentionally? A restrained soft field does not need every texture effect.
5. **Color economy:** is each additional hue doing a job? Compare overlap,
   luminance and crop before increasing saturation.
6. **System:** do the cover, content slide, thumbnail and mobile crop still
   belong together? Preserve palette roles and shape grammar, vary emphasis.

Avoid presenting “premium,” “calm” or “bold” as measured results. Describe the
visible decisions and test them with the intended application.

## A small editing surface

Start with these choices; add deeper parameters only when needed:

- **Purpose / quiet zone:** where content sits and which edge may crop.
- **Palette:** replace role colors while holding geometry and seed fixed.
- **Distribution:** select a composition; move, resize or rotate whole masses.
- **Fusion:** widen or tighten overlap/falloff; use blur only for the chosen method.
- **Contrast / accent:** adjust light/dark separation and the accent's coverage.

Name colors by role and layers by function. Return the base and mass color-node
IDs from a connector workflow. A normal “make it apricot/blue” edit changes those
fills, not the entire scene. Preserve the original until the replacement is
reviewed. Avoid a new page and a new export for every tiny slider change.

For the **blurred vector route**, compare 100, 150 and 200 px at a reference
1536×1024 size, then scale by the shorter dimension if the canvas changes.
This is a tuning bracket, not a minimum/maximum requirement. Prefer lower
values when contour identity matters. Judge the actual render: broad blur
can erase structure and color separation. The guide contains a real Figma
Sky comparison. The current cropped Flower uses 125–160 px with 56–85%
plane opacity; the 40-level Heightmap uses 24–38 px to retain smaller ridges. Compare their
actual samples and tune opacity/blur separately. Other ranges are starting points.
See [palettes-and-layout.md](palettes-and-layout.md) for formulas, the four
rendered palette recipes and cross-ratio re-layout.

For the **mask-group route**, softness comes from the alpha falloff and support
extent. Edit the color rectangle for hue, the entire group for placement, and
the mask only for falloff. Do not add a 200 px blur automatically. These routes
are alternatives, and matching their visual appearance requires calibration.

## Readability and export

For web text, WCAG 2.2's minimum contrast is 4.5:1 for normal text and 3:1 for
large text (as defined by the standard). Evaluate the actual background under
the text at every relevant crop/state; checking only palette swatches misses
bright or dark pockets produced by overlap. Use a stable quiet zone, scrim or
solid backing when the gradient cannot guarantee legibility. Motion introduces
more states to check. Do not label a whole palette “accessible” from one sample.

Check color profiles, transparency and export dimensions. Dither/grain can help
with visible banding but also dirties quiet backgrounds and increases file size;
compare at intended display size and compression. Do not use texture to conceal
a poor color or contour transition.

## Primary sources

- [W3C CSS Color 4: OKLab / OKLCH](https://www.w3.org/TR/css-color-4/#ok-lab)
  — color-space concepts; not evidence that a harmony is aesthetically superior.
- [WCAG 2.2 contrast minimum](https://www.w3.org/TR/WCAG22/#contrast-minimum)
  — the text-contrast thresholds and their conditions.

The composition, harmony and brand-judgment guidance above is a synthesized
design framework, not an externally validated preference study.

## Reference grammar before softness

Judge the thumbnail first: where are the largest bright/dark regions, how much
of the frame do they occupy, and what direction connects them? Match these
relationships before grain. Sky may need one wide current; Dreamlike may need
unequal offset lights and a shadow; Flower may need just a cropped magnified
surface rather than recognizable flower anatomy. A method name is insufficient
without a viewed reference. Do not invent a thin decorative loop because the
label says “dreamlike,” or a radial rosette because it says “flower.”

For Heightmap complexity, distinguish the number of levels from field structure.
A repeated scaled outline stays one-centered even with many layers. Add genuine
peaks, valleys, curved ridges and saddles, then inspect region splits/merges and
the actual crop. Only then increase levels or soften transitions. Avoid adding
high-frequency detail that disappears at the target display size.
```

## File: references/effects.md
size: 6605
sha: 7420b752016435a19329405d030ee10d341ad105
upstream: https://github.com/9929y/genai-mesh-gradient/blob/HEAD/references/effects.md

```text
# Effect recipes

All numeric ranges below are tunable starting points, not universal visual
rules. Scale lengths with the shorter canvas dimension D. Choose palette and
composition from the user's reference; do not force the example colors.

## Atmospheric color field

**Target:** broad, overlapping color masses with a readable light/dark pattern;
neither discrete glowing circles nor a blurred landscape.

Start with about 7–10 asymmetric elliptical masses, then adjust the count to
the composition. Let adjacent masses overlap substantially (roughly one third
of their width is a useful first study). Use transparent gradient edges so
neighboring colors can meet without a hard ring. Preserve two or three
recognizable hue zones. Avoid arranging all centers along a horizontal line.

Native Figma route: opaque base plus separate ellipses with radial fills,
each fading from its color to the same RGB with zero alpha. Edge softness
comes primarily from gradient stops. Add a small layer blur only if needed;
do not blur until the topology disappears. The helper uses no layer blur.

Controls: mass size, center/extent, stop position, alpha, local contrast.
A pale/porcelain mode reduces contrast; a mineral mode uses a dark base and
one restrained bright accent. These remain the same family.

## Fluid field

**Target:** directional, curved color streams; the image should have a dominant
flow and counterflow rather than evenly stretched stripes.

Construct long elliptical/vector masses along curved directions. In a shader,
warp the sample domain with a smooth seeded vector field, then evaluate the
color field in that domain. Start with low-frequency displacement around
0.01–0.04 D. Increase curvature before adding fine turbulence. Warping a photo
directly retains unwanted texture if the goal is a newly designed field.

Native stretched shapes and SVG ellipses are a static approximation. Use
curved vector paths or a documented shader renderer when the exact topology
matters. No native fluid simulation is provided here.

Controls: flow length, curl scale, direction bias, warp amount, mass definition.

## Pigment diffusion

**Target:** soft uneven deposits, localized pooling and occasional darker rims.
Uniform grain over a smooth field does not alone create wet pigment.

Start from several broad deposits. Perturb boundaries with a stable,
low-frequency field; add selective darker pooling at some boundaries. Keep
fine paper grain independent and much smaller. Use a few quiet open areas
so the entire image does not become noise.

SVG `feTurbulence` plus `feDisplacementMap` approximates uneven bleeding;
it is not a physical fluid/pigment solver. The included SVG helper implements
boundary displacement and optional fine grain, but not a pooling simulation.
Figma imported SVG filters may change or disappear: inspect the import,
rebuild the crucial edges with paths, or label a baked texture as raster.

Controls: deposit size, bleed irregularity, pooling, drying edge, warp.

## Oil / brush

**Target:** coherent painted masses with large, medium and small strokes;
the image should not be a photograph under a brush-texture overlay.

Analyze image-derived work into multiple connected regions per color. Retain
centers, extents and dominant directions. Lay down large paint masses, then
medium strokes along regional axes, then sparse small strokes and canvas grain.
Keep dark accents deliberate so they do not contaminate all colors.

An optional coverage correction uses target_i proportional to weight_i^gamma,
normalized to sum to one. Gamma > 1 favors dominant colors; gamma < 1 makes
weights more even. Measure the composite using a defined nearest-palette
assignment (prefer a perceptual color space), state how unassigned pixels and
transparency are handled, then adjust the corresponding stroke budget/area.
This is a visual proxy, not a universal quality score.

Abstract / Balanced / Defined vary structure retention and stroke scale.
They are modes. The native radial helper and SVG helper do not implement this
brush planner. Use vector stroke construction or a code renderer.

Controls: brush size/width, paint density, angle jitter, canvas grain.

## Chromatic silhouette

**Target:** major contours and luminance masses remain recognizable while fine
detail disappears and interior color is redesigned.

Use a user-supplied mask or a coarse structure map. Recolor inside and outside
with separate gradients while preserving enough luminance separation to read
the form. Do not mistake simple luminance thresholding for reliable subject
segmentation. If a silhouette matters and segmentation is poor, use a supplied
mask, a manual path, or an available segmentation tool and describe the choice.

Figma route: editable vector outline with gradient fills and feathered companion
shapes. Shader route: coarse masks, limited tonal bands and soft chromatic
offset. Strong color remapping is optional; source color fidelity may matter.

Controls: retained structure, edge softness, tonal contrast, chromatic split,
source-to-remapped color mix. Neither included helper extracts a silhouette.

## Flower / petal diffusion

For the actual Figma Flower visual target, inspect the native sample images in
`index.html` and use `figma-recipes.md`. The legacy radial `petal` helper below
is only a schematic construction experiment and is not a faithful example of
those soft folded planes.

**Target:** asymmetric lobed/petal-like boundaries and translucent interior
glow; botanical anatomy is optional.

Start with about 5–12 overlapping curved petal regions. Vary length, width,
direction and alpha. Avoid identical radial petals unless the reference calls
for symmetry. Allow some edges to remain discernible while others merge into
the background. Build interior highlights separately from the outer silhouette.

Use vector paths with gradient fills for editable Figma artwork. The SVG
helper uses curved petal paths and radial fills for an original schematic study;
it does not derive petals from a source image or model volumetric translucency.

Controls: petal count, length, width, edge softness, interior glow.

## How to compare

Render one reference/palette at a fixed seed, crop and dimensions. Change one
meaningful control at a time. Check hue proportions, composition, dominant
direction, recognizable structure and material edges. If a control changes
pixels but not its intended visual quality, fix the mapping rather than
declaring it validated. Recheck coupled controls (soft edges can hide chromatic
split, and grain can conceal subtle pooling).
```

## File: references/figma-recipes.md
size: 12824
sha: a25d6a8b86a9d524442ae281f978652fca9c70d4
upstream: https://github.com/9929y/genai-mesh-gradient/blob/HEAD/references/figma-recipes.md

````text
# Figma construction recipes

These recipes generalize existing editable artwork inspected on 2026-10-24.
Observed structure is evidence; explanations of the visual role are design
interpretations. The private source file and original reference images are not
redistributed. Counts and blur radii below describe inspected examples, not
mandatory defaults. A 200 px blur at 1536×1024 is very different from 200 px
on a small thumbnail. Preserve relative scale and judge the actual render. Read
[palettes-and-layout.md](palettes-and-layout.md) for adjustable blur ranges,
ratio changes, concrete palette recipes and the new controlled comparison.

## Current gallery: six blue / orange studies

The current gallery was redrawn as native Figma artwork, all **1536×1024**.
Palette anchors: warm white #FFF7EB, cream #F8F1E8, ice #DFE8F4, mist #B9CEE9,
blue #7398D1, cobalt #3E64AC, navy #263C78, orange #EB7D45 and peach #F4B78B.
The examples keep warm paper and apricot alongside blue; this is the current
sample direction, not a universal restriction on the user's brand palette.

| Study | Actual construction | Layer blur at reference size |
|---|---|---|
| Sky | 3 broad curved vectors + 2 radial fields | 125–155 px |
| Dreamlike | 2 broad curved vectors + 4 offset radial fields | 120–165 px |
| Flower | 4 magnified, cropped planes + 2 light fields | Planes 125/145/145/160 px, opacity 82/56/85/60%; light fields 125/135 px |
| Diffuse | 1 curved vector + 3 broad radial fields | 155–185 px |
| Heightmap | Warped multi-peak scalar field, marching-squares extraction, 40 Bézier levels | 24–38 px |
| Multipoint | 11 isolated Gaussian alpha-mask groups, 49 stops each | Extra blur 0 |

Inline `scripts/figma_native.js` followed by `scripts/blue_orange_studies.js`
into a supported Figma execution tool, switch to the user-selected page and
choose a clear x/y before calling:

```js
return buildBlueOrangeStudies(figma, {x:clearX, y:clearY, width:1536, height:1024});
```

The function is additive, returns every created ID, and has been executed in
live Figma with the six actual renders inspected. It accepts proportional
3:2 canvas sizes; it rejects other ratios so it does not silently stretch the
petals. Use the layout guidance to recompose for another aspect ratio.
These are designed original examples, not exact replays of the old artwork.
The Heightmap implementation now samples a warped scalar field on a 112×80 grid,
combining broad ridges, Gaussian hills/valleys and secondary undulations. It
extracts 40 thresholds with marching squares, resolves ambiguous cells from
the center value, joins closed loops, smooths to Bézier curves, and uses even-odd
fills for holes. Distinct regions can split/merge between levels. This is a new
algorithm; it does not claim to recover the historical source algorithm.

The revision was compared with original visual references and earlier studies.
Sky retains a broad diagonal warm current and open upper light. Dreamlike uses
warm left light, upper blue shadow and a large offset pale region. Flower uses
magnified cropped planes, a curved dark interval and warm transmitted light,
with no central flower symbol. Geometry is newly designed in a blue/apricot
palette, not a pixel reconstruction; original grain is not recreated.

Flower plane opacity is 82/56/85/60%, with blur 125/145/145/160 px. Its upper
warm-white and lower-left peach fields use fill alpha .75/.50 and blur
125/135 px. Keep opacity, edge softness and plane thickness as separate edits.
Multipoint retains a long blue sweep and narrow pale passages.

Optional selection and Heightmap controls:

```js
return buildBlueOrangeStudies(figma, {
  x: clearX, y: clearY, width: 1536, height: 1024,
  keys: ['heightmap'],
  heightmap: {detail: 1, warp: 1, levels: 40, blurMin: 24, blurMax: 38}
});
```

`detail` weights the secondary undulations; `warp` weights coordinate bending
(both 0–2). `levels` is an integer from 12–80. `blurMin/blurMax` are reference
pixel radii at a 1024 short side (0–200, max >= min). Counts alone do not add
structural complexity: first adjust the field, then levels and fusion.
The result returns `contourTopology` with the closed-region count per height.
Region counts cover the padded field; some regions can be outside the crop.
These controls rebuild a study; they are not a two-way live editing UI.

The current 100/150/200 comparison changes all five blur radii on temporary
copies of the same blue/orange Sky. Geometry, fills and opacity stay fixed;
those copies were removed after export. The final six editable studies remain.

## 1. Sky-inspired: a directional field

**Observed:** representative artboards combine about 5–6 native layers:
radial gradient rectangles, curved vector regions with linear gradient fills,
and broad layer blur. Inspected examples use a 200 px blur on 1536×1024.

**Reusable recipe:** establish a dominant diagonal or gently curved sweep.
Build a wide warm light mass, a complementary cooler/darker mass, then a
feathered curved band that connects them. Let one area breathe. Make the
composition feel like changing atmospheric light without imposing a literal
skyline or horizontal sunset stripes unless requested.

Tune sweep angle, highlight height/width, dark-mass extent, path curvature,
stop positions and scaled blur. Use more masses only when the composition
needs them. Keep color-proportion changes separate from layout changes.

## 2. Dreamlike: pools and echoes

**Observed:** similar primitives to Sky-inspired—native radial rectangles and
linear-filled vectors—but in arrangements named double light pool, refracted
light and floating warm island. Inspected examples have about 6 layers and
the same broad blur setting.

**Reusable interpretation:** use two or three offset focal pools, a soft
countershape and a pale passage between them. Avoid making every mass equally
large, bright or centered. Distinction comes from composition and contrast,
not a special Dreamlike API. A folded/refraction-like edge here is a visual
illusion, not evidence of physically simulated glass.

Tune focal separation, one dominant accent, the light passage, local overlap
and softness. Preserve both warm and cool contrast when the reference has it.

## 3. Flower-inspired: soft lobes and folded planes

**Observed:** representative frames mix 2–4 curved vectors with radial light
masses. Vectors carry linear gradients and different opacities; broad blur
merges them into the surrounding field.

**Reusable recipe:** create asymmetric petal/leaf-like curves with one offset
focal area. Use gradients along each lobe, a darker interval between some
forms and independent interior highlights. Do not rely on radial blobs alone
when a shaped boundary is the defining feature. Keep literal flower anatomy
only if it is part of the request.

Tune path tangents, length/width, overlap, direction, opacity and edge blur.
The current guide uses the four-plane magnified blue/apricot Flower described
above. Preserve large cropped surfaces and the dark interval between them.
Tune opacity and blur independently; the current planes use 125–160 px blur.
Inspect the actual sample, not the legacy radial `petal` SVG sketch.

## 4. Diffuse: soften a composition, preserve its hierarchy

**Observed:** the diffusion study contains Sky-, Dreamlike- and Flower-like
arrangements in pale and richer color treatments. It uses the same native
radial/vector primitives; no fluid solver or raster pigment simulation was
found in the inspected frames.

**Reusable recipe:** retain the chosen family's major masses, expand selected
soft regions, reduce minor accents and let boundary transitions spread.
Keep a readable luminance hierarchy. This is a treatment of a composition,
not proof of a new physical material engine. Do not confuse it with the
browser pigment-displacement experiment in `effects.md`.

## 5. Heightmap-inspired: stacked tonal contours

**Observed:** two method studies contain 24 native vector layers each, named
with ascending height values. Their fills are solid or linear gradients and
they use broad blur. Structure confirms stacked contour-like regions; it
does not establish the original scalar-field generation algorithm.

**Improved implementation option:** define a smooth scalar field h(x,y),
extract ordered iso-contours, map height to a palette ramp, and place nested
paths in consistent order. Alternatively design contour paths manually.
Use blur to join bands only as needed. Keep contour topology and tonal order
coherent, otherwise the result becomes unrelated soft stripes.

Tune field scale, contour spacing, number of levels, ramp contrast and blur.
The current builder includes the scalar-field contour extractor described above.
For more detail, change secondary field frequencies/amplitudes and warp before
increasing the number of levels. Excessive blur can erase every smaller ridge.

## 6. Multipoint / layered radial: color-and-mask groups

**Observed:** a newer multipoint study uses 18 isolated mass frames per sampled
artboard. Each contains a radial ALPHA mask and a separate solid color fill.
The mask has 49 stops sampling exp(-8r²), with a transparent endpoint. Parent
opacity and transforms control intensity, elongation and direction; those
groups have no layer-blur effect. Separate earlier layered-radial studies use
about 5 radial gradient rectangles with broad blur.

**Reusable recipe:** use a clipped artboard and an optional base. Give each
mass its own isolated group: mask first, solid-color rectangle after it.
The frame boundary prevents the mask from hiding unrelated sibling masses.
Transform the group as a unit so its color and softness stay aligned.

Start with broad foundation masses, then medium transitions and a small
number of accents. The included `buildMesh` implements these groups with a
fixed Gaussian-like profile. Node IDs identify all created groups/masks/fills.
Recolor the solid fill; modify position/scale/rotation on its group.

18 masses was an observed choice, not a required minimum. Avoid adding layers
to compensate for an incorrect palette or badly placed major mass.

## Matching an existing gradient bitmap

Recovered historical records show an earlier six-image reconstruction using
32 editable masses per image, plus two independent raster-detail layers.
The count 32 is specific to that run. Do not describe the entire result as
fully vector if raster corrections are present.

### Fit the broad field

Represent the image as an opaque base and ordered elliptical Gaussian masses:

```text
u = cos(theta)*(x-cx) + sin(theta)*(y-cy)
v = -sin(theta)*(x-cx) + cos(theta)*(y-cy)
alpha = opacity * exp(-0.5*((u/sigmaX)^2 + (v/sigmaY)^2))
composite_next = composite + alpha*(massColor - composite)
```

The recovered run optimized base RGB and each mass's center, log-scales,
rotation, opacity and RGB with bounded L-BFGS-B at a reduced analysis size.
It added masses near high residual-error regions (16 → 24 → 32 in that run).
This explains how position and portion were preserved beyond simple palette
extraction. It is not a segmentation model. Generic optimizer code is not
bundled; use available numerical libraries if this precision is needed.

Map the result to native mask/color groups. Calibrate the mathematical model
against an actual Figma export: stop interpolation, compositing, color space
and integer rounding may disagree. A low loss from the fitting renderer alone
does not establish a low error in Figma.

### Optional detail correction

Only when the user wants a close bitmap match and accepts mixed media:

1. Export the native-only rendering N at the reference crop and resolution.
2. Compare to target T in a defined, consistent color representation.
3. Compute a positive correction P=max(T-N,0) on a black raster and a negative
   correction Q=1-max(N-T,0) on a white raster (values normalized 0..1).
4. Place P as Linear Dodge and Q as Linear Burn above the native composition.
   Keep them independently switchable and name them as raster corrections.
5. Export again and compare actual pixels. Blend implementation/clipping can
   invalidate the simple algebra; use observed results, with a bounded number
   of correction rounds, rather than promising an exact match.

The residual includes everything the native model missed, not necessarily just
grain. Check its magnitude and visual content. It must not become a hidden
full-image replacement used to claim a native reconstruction. Disable it after
large recoloring or geometry changes, or recompute for the new target.

Report native-only and corrected comparisons separately. Define MAE/RMSE
units, dimensions, crop, alpha background and color handling. Tiny historical
errors after raster correction are not a transferable accuracy guarantee.
````

## File: references/motion.md
size: 3257
sha: 71c55da6c4870a4e26ee522c5f94f5b2b770ff36
upstream: https://github.com/9929y/genai-mesh-gradient/blob/HEAD/references/motion.md

```text
# Optional motion and image reveal

Apply only when motion is requested. Approve the still's visual direction
first so texture, composition and timing are not all changing together.

## Two independent variables

Use `progress` for reveal (0 = abstraction, 1 = chosen endpoint) and `time` for
ambient life. Keep the seed and still parameters separate. A comparison at
the same progress is deterministic only with time fixed too. Pause freezes
both; reduced-motion delivery supplies a still and manual access to the endpoint.

Ambient drift can start around 1–2% of canvas size over 7–12 seconds. Treat
these as tuning values, not a required style. Attenuate distortion to zero
at a photographic endpoint; never distort the final source unintentionally.

## Common rejected mechanisms

- Individual blobs visibly translating and scaling back into photo positions.
- Obvious low-, mid- and high-frequency stage windows.
- An abstract layer fading away while a separate photograph fades in.

These can suit other briefs, but they often reveal the construction when the
desired effect is organic information reconstruction. Numerical continuity
alone does not establish perceptual naturalness.

## A workable research direction

Give the renderer one continuous information-capacity field `r(x,y,progress)`.
Use it to control color correction, structure and detail with overlapping
responses rather than separate staged gates. Keep spatial differences subtle
unless the user wants a directional wipe. Sample a continuous scale-space
representation or correct the template's own material units.

For dither/glyph resolve, keep cells fixed and use a stable threshold field.
What changes is the information carried per cell. Do not generate new random
thresholds every frame. Glyphs can carry luminance and structure without
requiring thousands of DOM nodes; an atlas/canvas or shader can render them.

Choose the endpoint explicitly:

- Resolve to photo: at progress 1, reproduce the supplied source with the same
  crop, orientation, color and alpha handling.
- Hold material: retain brush, silhouette or petal character at progress 1.

A capped reveal value is a design choice, not a successful photo endpoint.
Do not carry historical preferences about one endpoint into every new task.

## Verify before adjusting aesthetic timing

Use an asymmetric four-corner orientation fixture through the same image upload,
offscreen, blur, display and export path. Canvas, texture uploads and framebuffer
passes can disagree on vertical origin. Centralize coordinate conversions;
do not scatter unexplained `1-y` fixes. Avoid reversed-edge `smoothstep` calls;
use `1 - smoothstep(low, high, value)` when an inverted ramp is needed.

At fixed time/seed, inspect progress 0, .25, .5, .75 and 1; scrub forward/back
to the same value and compare. Play continuously and reverse mid-reveal.
Confirm every paused state is coherent and the endpoint meets the selected
goal. Quantitative frame differences can expose pops but cannot certify a
natural transition. Test the actual target device and reduced-motion mode.

The bundled native/SVG helpers create stills only. These motion instructions
are implementation guidance; they are not an included tested animation engine.
```

## File: references/palettes-and-layout.md
size: 6692
sha: 0c645208e2f3fca55fe2d18d5cd402c30ed145e3
upstream: https://github.com/9929y/genai-mesh-gradient/blob/HEAD/references/palettes-and-layout.md

````text
# Palette samples, size, aspect ratio and blur

Use this when choosing colors, reproducing the guide's palette previews,
adapting an artwork or explaining practical user controls. Native samples in
`design/illustrations/` are rendered images: use them as visual targets, not
as files that contain editable Figma nodes.

## Four actual palette studies

| Key | Base / dominant / support / accent | Use and tradeoff |
|---|---|---|
| mono | #FFF4E7 / #FDDAAA / #F6AD71 / #B7542E | Warm tonal identity; maintain light/dark separation |
| adjacent | #FFF4E7 / #E6BE6C / #F6AD71 / #C97C83 | Gentle warm variation; keep one hue family dominant |
| contrast | #F8F1E8 / #F4B78B / #7398D1 / #3E64AC | Apricot/cobalt tension; retain warm space and avoid muddy broad overlap |
| neutral | #F4F5F3 / #D5DEDE / #91A9B4 / #3F708E | Quiet content settings; protect the actual text area |

These are original browser studies. `scripts/palette_studies.js` supplies
`paletteCSS(colors)` and `paletteSVG(key,width,height)` from the same recipe.
The four SVG files in `design/illustrations/` are generated with the latter.
Keep the geometry fixed when comparing palette choices.

CSS layers, front to back:

| Role | Center x/y | Solid start / transparent end |
|---|---|---|
| Dominant | 18% / 28% | 0% / 60% |
| Support | 78% / 28% | 0% / 62% |
| Accent | 65% / 95% | 0% / 50% |
| Support, second region | 25% / 88% | 0% / 60% |
| Base | Whole frame | Opaque |

Use ellipse radial gradients, CSS default farthest-corner extent and no extra
blur. The SVG helper uses equivalent explicit ellipse extents. Renderer and
color handling can differ, so check the receiving editor. These linear-fade
palette previews are not identical to the Gaussian-mask Figma construction.
To transfer the direction, map colors by role and preserve the major centers,
then calibrate extents/alpha against an actual target render.

## Same ratio: scale the artwork

For a canvas scale k, multiply coordinates, vector control points, mass
dimensions and native layer-blur radii by k. A 1536×1024 master at 150 px blur
becomes 3072×2048 at 300 px blur. If only exporting the same Figma master at 2×,
leave its layer radius at 150 px: export scaling already scales its appearance.

## New ratio: recompose

1. Reserve the actual foreground-content area in the new frame.
2. Keep centers normalized: cx=u*width, cy=v*height.
3. Define physical mass radii from short side S=min(width,height), e.g.
   rxPx=.6*S, ryPx=.9*S. Change centers/angles to fit the new composition.
4. For `buildMesh`, convert back to its per-axis units:
   region.rx=rxPx/width and region.ry=ryPx/height. These are support half-extents,
   not Gaussian sigma and not visible coverage percentages.
5. Reposition shaped vectors and adjust their control points deliberately.
   Preserving short-side radii is a starting strategy, not a way to preserve
   every contour or reference composition automatically.
6. Inspect the result with actual text. Recheck cropped web viewports and
   thumbnails; a quiet area in the master may be outside the visible crop.

`layoutSpec(width,height,key)` returns three original example layouts:
wide (ratio >=1.35), portrait (ratio <=.8) and square/intermediate. These
thresholds belong to the demo, not a universal device classification. Wide
places color right/below a left title area; square reserves upper left;
portrait reserves the top and moves masses down. They are re-layouts, not
stretched/cropped images or guaranteed accessible backgrounds.

In a supported Figma execution tool, inline the two helper sources, choose
a clear page-level position, then call:

```js
const spec = MeshGradientStudies.layoutSpec(1080, 1920, 'contrast');
const result = buildMesh(figma, {...spec, x: clearX, y: clearY});
return result;
```

`clearX/clearY` must come from the current canvas; do not paste them as
undefined variables. `quietZone` is layout metadata for placing foreground
content; the native builder does not create text or draw the guide rectangle.
The SVG preview uses the same Gaussian falloff recipe, but live Figma parity
of these new specs has not been verified. The guide's existing Figma samples
are separate inspected artwork.

## Adjustable blur

The current Flower planes use 125–160 px blur with 56–85% opacity; current
Heightmap layers use 24–38 px across 40 extracted levels. Flower needs broad
edge fusion; Heightmap needs enough local definition to retain smaller ridges.
Tune supporting light fields separately.
Read the current construction table in `figma-recipes.md` for exact per-family
settings and the executable six-study builder.

The 200 px radius in historical 1536×1024 studies was an observed setting,
not a mandatory default. A new controlled comparison on the blue/orange
Sky study changed all five layer-blur radii to 100 / 150 / 200 px on
temporary copies. Geometry, fills, ordering and opacity stayed fixed. The
three source PNGs were actually exported from Figma; copies were then removed.
The public guide uses full-resolution quality-95 JPEG encodings for smaller
page downloads. They are viewing samples, not lossless pixel-comparison targets.

Use `blur = b * min(width,height) / 1024`, choosing b for the intended structure, not imposing one interval:

| Intended treatment | Suggested b at 1536×1024 | Inspect |
|---|---|---|
| Translucent Flower planes | 125–160 px in the current sample | Tune 56–85% opacity independently of edge fusion |
| Soft Heightmap contours | 24–38 px in the current 40-level sample | Preserve splits, saddles and smaller ridges while joining levels |
| Broad Sky / Dreamlike | 120–180 px | Direction and pale passage vs uniform haze |
| Diffuse field | 160–200 px | Fusion vs lost tonal hierarchy |
| Gaussian alpha-mask groups | Extra blur 0 by default | Support size, overlap and falloff instead |

The exact current gallery values and Sky comparison have been rendered in
Figma. Other proposed ranges are starting points, not established optima. Values outside these
ranges may fit a request; different layers may need different radii.
At a 1080 px short side, b=100/150/200 gives about 105/158/211 px. Avoid
rounding every value back to 200. Blur does not fix the wrong palette,
an incorrect contour or a badly positioned light mass.

## Editing handoff

Give the user five choices: use/quiet zone, palette, distribution,
fusion and contrast. Recolor named fills, move/resize/rotate whole groups,
adjust selected vector blur or mask falloff, and review the actual composite.
Keep raster residual corrections off during substantial redesign. Return
node IDs and the chosen palette/layout/softness values so revisions are targeted.
````

## File: AGENTS.md
size: 2289
sha: ab4d6ad93e5d19a1268d393c9e79678301777ac6
upstream: https://github.com/9929y/genai-mesh-gradient/blob/HEAD/AGENTS.md

```text
# Agent entry

For an agent working directly in this repository, read `SKILL.md` next. It is
the execution workflow. A skill loader may load `SKILL.md` directly; do not
assume every client auto-loads this file. README is the English-first human guide with a short Chinese summary.

Read selectively:

| Task | Reference |
|---|---|
| Palette, use case, brand judgment | `references/art-direction.md` |
| Exact sample colors, size/ratio, blur and editing | `references/palettes-and-layout.md` |
| Six Figma construction families / reference matching | `references/figma-recipes.md` |
| Target tool / Figma connection | `references/adapters.md` and its current connector documentation |
| Browser material studies or motion | `references/effects.md` or `references/motion.md` only as needed |

When modifying the package:

- Preserve the name **GenAI Mesh Gradient** and invocation `genai-mesh-gradient`.
- Keep the research connection grounded in the two public papers linked from README.
  Distinguish agent orchestration and procedural rendering from trained diffusion
  models; do not claim paper reproduction, sole invention or unmeasured impact.
- Maintain the single `index.html` and existing README. Use English for primary
  explanations, controls and captions, with concise Chinese support. Keep project
  introductions and footers free of personal-name attribution; retain legal notices.
- Use the real Figma samples as visual targets. The old `petal` sketch is not a
  faithful Flower example. Label native exports, controlled variants and new
  procedural studies accurately; keep original references unchanged.
- Keep sample illustrations in `design/illustrations/`; share their paths
  between README and HTML. Do not publish private file keys or user transcripts.
- Keep palette geometry in `scripts/palette_studies.js` consistent with the
  four palette SVGs. After a code change, run the relevant helper and inspect
  the guide at desktop and mobile widths; check local image/reference links.
- Blur is adjustable. Recompose across aspect ratios. A mask-based field has
  no extra blur by default. Never describe a rendered bitmap as editable layers.

These instructions do not establish a connector or authorize changes to an
unrelated Figma file or external publication.
```

## File: design/illustrations/diffuse-blue-orange.jpg
size: 127548
sha: d95490a20a33265826d02139093b8bbb4a472ccf
upstream: https://github.com/9929y/genai-mesh-gradient/blob/HEAD/design/illustrations/diffuse-blue-orange.jpg

Content is not inlined in the catalog. Read the upstream file: https://github.com/9929y/genai-mesh-gradient/blob/HEAD/design/illustrations/diffuse-blue-orange.jpg

## File: design/illustrations/dreamlike-blue-orange.jpg
size: 154653
sha: bf23b47cff1e53879ef4f4ccc3d5b454ea5a9e74
upstream: https://github.com/9929y/genai-mesh-gradient/blob/HEAD/design/illustrations/dreamlike-blue-orange.jpg

Content is not inlined in the catalog. Read the upstream file: https://github.com/9929y/genai-mesh-gradient/blob/HEAD/design/illustrations/dreamlike-blue-orange.jpg

## File: design/illustrations/flower-soft-blue-orange.jpg
size: 138520
sha: 669569aaaeda7732a62d1101b126b19745492b65
upstream: https://github.com/9929y/genai-mesh-gradient/blob/HEAD/design/illustrations/flower-soft-blue-orange.jpg

Content is not inlined in the catalog. Read the upstream file: https://github.com/9929y/genai-mesh-gradient/blob/HEAD/design/illustrations/flower-soft-blue-orange.jpg

## File: design/illustrations/heightmap-soft-blue-orange.jpg
size: 169803
sha: 5bbd858caf0f418031b302907cc6d1ce3e1a32df
upstream: https://github.com/9929y/genai-mesh-gradient/blob/HEAD/design/illustrations/heightmap-soft-blue-orange.jpg

Content is not inlined in the catalog. Read the upstream file: https://github.com/9929y/genai-mesh-gradient/blob/HEAD/design/illustrations/heightmap-soft-blue-orange.jpg

## File: design/illustrations/multipoint-blue-orange.jpg
size: 133860
sha: fa37d22165ab8d977221589e4afc8e5d663bf9a5
upstream: https://github.com/9929y/genai-mesh-gradient/blob/HEAD/design/illustrations/multipoint-blue-orange.jpg

Content is not inlined in the catalog. Read the upstream file: https://github.com/9929y/genai-mesh-gradient/blob/HEAD/design/illustrations/multipoint-blue-orange.jpg

## File: design/illustrations/palette-adjacent.svg
size: 1508
sha: b29d4a110d8cd4916189e7f6bd3408adb6c24512
upstream: https://github.com/9929y/genai-mesh-gradient/blob/HEAD/design/illustrations/palette-adjacent.svg

```text
<svg xmlns="http://www.w3.org/2000/svg" width="1200" height="600" viewBox="0 0 1200 600"><title>adjacent / fixed four-pool palette study</title><defs><radialGradient id="pool0" gradientUnits="userSpaceOnUse" cx="0" cy="0" r="1" gradientTransform="translate(216 168.00000000000003) scale(1391.5861453751256 610.940258945177)"><stop stop-color="#e6be6c"/><stop offset="0.6" stop-color="#e6be6c" stop-opacity="0"/></radialGradient><radialGradient id="pool1" gradientUnits="userSpaceOnUse" cx="0" cy="0" r="1" gradientTransform="translate(936 168.00000000000003) scale(1323.703894381217 610.940258945177)"><stop stop-color="#f6ad71"/><stop offset="0.62" stop-color="#f6ad71" stop-opacity="0"/></radialGradient><radialGradient id="pool2" gradientUnits="userSpaceOnUse" cx="0" cy="0" r="1" gradientTransform="translate(780 570) scale(1103.0865786510142 806.1017305526642)"><stop stop-color="#c97c83"/><stop offset="0.5" stop-color="#c97c83" stop-opacity="0"/></radialGradient><radialGradient id="pool3" gradientUnits="userSpaceOnUse" cx="0" cy="0" r="1" gradientTransform="translate(300 528) scale(1272.7922061357856 746.7047609329942)"><stop stop-color="#f6ad71"/><stop offset="0.6" stop-color="#f6ad71" stop-opacity="0"/></radialGradient></defs><rect width="100%" height="100%" fill="#fff4e7"/><rect width="100%" height="100%" fill="url(#pool3)"/><rect width="100%" height="100%" fill="url(#pool2)"/><rect width="100%" height="100%" fill="url(#pool1)"/><rect width="100%" height="100%" fill="url(#pool0)"/></svg>
```

## File: design/illustrations/palette-blue-orange.svg
size: 1508
sha: 59cd2571f6ddc7cc9eb53795817861fad5d2b82a
upstream: https://github.com/9929y/genai-mesh-gradient/blob/HEAD/design/illustrations/palette-blue-orange.svg

```text
<svg xmlns="http://www.w3.org/2000/svg" width="1200" height="600" viewBox="0 0 1200 600"><title>contrast / fixed four-pool palette study</title><defs><radialGradient id="pool0" gradientUnits="userSpaceOnUse" cx="0" cy="0" r="1" gradientTransform="translate(216 168.00000000000003) scale(1391.5861453751256 610.940258945177)"><stop stop-color="#f4b78b"/><stop offset="0.6" stop-color="#f4b78b" stop-opacity="0"/></radialGradient><radialGradient id="pool1" gradientUnits="userSpaceOnUse" cx="0" cy="0" r="1" gradientTransform="translate(936 168.00000000000003) scale(1323.703894381217 610.940258945177)"><stop stop-color="#7398d1"/><stop offset="0.62" stop-color="#7398d1" stop-opacity="0"/></radialGradient><radialGradient id="pool2" gradientUnits="userSpaceOnUse" cx="0" cy="0" r="1" gradientTransform="translate(780 570) scale(1103.0865786510142 806.1017305526642)"><stop stop-color="#3e64ac"/><stop offset="0.5" stop-color="#3e64ac" stop-opacity="0"/></radialGradient><radialGradient id="pool3" gradientUnits="userSpaceOnUse" cx="0" cy="0" r="1" gradientTransform="translate(300 528) scale(1272.7922061357856 746.7047609329942)"><stop stop-color="#7398d1"/><stop offset="0.6" stop-color="#7398d1" stop-opacity="0"/></radialGradient></defs><rect width="100%" height="100%" fill="#f8f1e8"/><rect width="100%" height="100%" fill="url(#pool3)"/><rect width="100%" height="100%" fill="url(#pool2)"/><rect width="100%" height="100%" fill="url(#pool1)"/><rect width="100%" height="100%" fill="url(#pool0)"/></svg>
```

## File: design/illustrations/palette-mono.svg
size: 1504
sha: 3074eb125b667c0de59ec74aa7b88962146b1ef3
upstream: https://github.com/9929y/genai-mesh-gradient/blob/HEAD/design/illustrations/palette-mono.svg

```text
<svg xmlns="http://www.w3.org/2000/svg" width="1200" height="600" viewBox="0 0 1200 600"><title>mono / fixed four-pool palette study</title><defs><radialGradient id="pool0" gradientUnits="userSpaceOnUse" cx="0" cy="0" r="1" gradientTransform="translate(216 168.00000000000003) scale(1391.5861453751256 610.940258945177)"><stop stop-color="#fddaaa"/><stop offset="0.6" stop-color="#fddaaa" stop-opacity="0"/></radialGradient><radialGradient id="pool1" gradientUnits="userSpaceOnUse" cx="0" cy="0" r="1" gradientTransform="translate(936 168.00000000000003) scale(1323.703894381217 610.940258945177)"><stop stop-color="#f6ad71"/><stop offset="0.62" stop-color="#f6ad71" stop-opacity="0"/></radialGradient><radialGradient id="pool2" gradientUnits="userSpaceOnUse" cx="0" cy="0" r="1" gradientTransform="translate(780 570) scale(1103.0865786510142 806.1017305526642)"><stop stop-color="#b7542e"/><stop offset="0.5" stop-color="#b7542e" stop-opacity="0"/></radialGradient><radialGradient id="pool3" gradientUnits="userSpaceOnUse" cx="0" cy="0" r="1" gradientTransform="translate(300 528) scale(1272.7922061357856 746.7047609329942)"><stop stop-color="#f6ad71"/><stop offset="0.6" stop-color="#f6ad71" stop-opacity="0"/></radialGradient></defs><rect width="100%" height="100%" fill="#fff4e7"/><rect width="100%" height="100%" fill="url(#pool3)"/><rect width="100%" height="100%" fill="url(#pool2)"/><rect width="100%" height="100%" fill="url(#pool1)"/><rect width="100%" height="100%" fill="url(#pool0)"/></svg>
```

## File: design/illustrations/palette-neutral.svg
size: 1507
sha: c785e3e83c2f8dd3224f3b3e483a026188368dfe
upstream: https://github.com/9929y/genai-mesh-gradient/blob/HEAD/design/illustrations/palette-neutral.svg

```text
<svg xmlns="http://www.w3.org/2000/svg" width="1200" height="600" viewBox="0 0 1200 600"><title>neutral / fixed four-pool palette study</title><defs><radialGradient id="pool0" gradientUnits="userSpaceOnUse" cx="0" cy="0" r="1" gradientTransform="translate(216 168.00000000000003) scale(1391.5861453751256 610.940258945177)"><stop stop-color="#d5dede"/><stop offset="0.6" stop-color="#d5dede" stop-opacity="0"/></radialGradient><radialGradient id="pool1" gradientUnits="userSpaceOnUse" cx="0" cy="0" r="1" gradientTransform="translate(936 168.00000000000003) scale(1323.703894381217 610.940258945177)"><stop stop-color="#91a9b4"/><stop offset="0.62" stop-color="#91a9b4" stop-opacity="0"/></radialGradient><radialGradient id="pool2" gradientUnits="userSpaceOnUse" cx="0" cy="0" r="1" gradientTransform="translate(780 570) scale(1103.0865786510142 806.1017305526642)"><stop stop-color="#3f708e"/><stop offset="0.5" stop-color="#3f708e" stop-opacity="0"/></radialGradient><radialGradient id="pool3" gradientUnits="userSpaceOnUse" cx="0" cy="0" r="1" gradientTransform="translate(300 528) scale(1272.7922061357856 746.7047609329942)"><stop stop-color="#91a9b4"/><stop offset="0.6" stop-color="#91a9b4" stop-opacity="0"/></radialGradient></defs><rect width="100%" height="100%" fill="#f4f5f3"/><rect width="100%" height="100%" fill="url(#pool3)"/><rect width="100%" height="100%" fill="url(#pool2)"/><rect width="100%" height="100%" fill="url(#pool1)"/><rect width="100%" height="100%" fill="url(#pool0)"/></svg>
```

## File: design/illustrations/sky-blue-orange.jpg
size: 147690
sha: 7740a64e9cd95ab4afcdc352bb76916f6f28cb31
upstream: https://github.com/9929y/genai-mesh-gradient/blob/HEAD/design/illustrations/sky-blue-orange.jpg

Content is not inlined in the catalog. Read the upstream file: https://github.com/9929y/genai-mesh-gradient/blob/HEAD/design/illustrations/sky-blue-orange.jpg

## File: design/illustrations/sky-blur-100-blue-orange.jpg
size: 147730
sha: b7644731ac763463ff5483e7ed449bf6d456d0ec
upstream: https://github.com/9929y/genai-mesh-gradient/blob/HEAD/design/illustrations/sky-blur-100-blue-orange.jpg

Content is not inlined in the catalog. Read the upstream file: https://github.com/9929y/genai-mesh-gradient/blob/HEAD/design/illustrations/sky-blur-100-blue-orange.jpg

## File: design/illustrations/sky-blur-150-blue-orange.jpg
size: 147160
sha: d6887d175ddda9dbf3863dab3fba7a00cd93f09b
upstream: https://github.com/9929y/genai-mesh-gradient/blob/HEAD/design/illustrations/sky-blur-150-blue-orange.jpg

Content is not inlined in the catalog. Read the upstream file: https://github.com/9929y/genai-mesh-gradient/blob/HEAD/design/illustrations/sky-blur-150-blue-orange.jpg

## File: design/illustrations/sky-blur-200-blue-orange.jpg
size: 148939
sha: f16aff52975400d5daf5d712fe10fff2f7da28cf
upstream: https://github.com/9929y/genai-mesh-gradient/blob/HEAD/design/illustrations/sky-blur-200-blue-orange.jpg

Content is not inlined in the catalog. Read the upstream file: https://github.com/9929y/genai-mesh-gradient/blob/HEAD/design/illustrations/sky-blur-200-blue-orange.jpg

## File: index.html
size: 41588
sha: 21e2e5b95d78b616d044caf79c4330eaef410c6e
upstream: https://github.com/9929y/genai-mesh-gradient/blob/HEAD/index.html

Content is not inlined in the catalog. Read the upstream file: https://github.com/9929y/genai-mesh-gradient/blob/HEAD/index.html

## File: LICENSE
size: 1068
sha: d6029ae6f588a5e55192155267fcdb97dcaf9093
upstream: https://github.com/9929y/genai-mesh-gradient/blob/HEAD/LICENSE

```text
MIT License

Copyright (c) 2026 Yanice Yang

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
```
