<!-- skill: Pixel Art | version: 1.0.0 | description: Craft crisp pixel art with tight palettes, clusters and clean exports | category: Video & Design -->
## Instructions
- Canvas sizes: 16x16 icons/loot, 32x32 characters/tiles, 64x64 portraits, 320x180 scene mockups scaled up; pixel-perfect: 1px = 1 unit, disable anti-aliasing and auto-AA brushes.
- Limited palettes: Resurrect 64 / Sweetie 16 / Endesga 32 for harmony; 4-8 colors per sprite (base + shadow + highlight + outline), max 1-2 ramps per material; Lospec to browse + import `.pal`.
- Clusters: group same-color pixels into readable chunks (3+ px), kill orphans (single stray pixels) and jaggies (staircase 1-2-3 steps) by redrawing diagonals at consistent 2:1 or 1:1 stair rhythm.
- Lineart: 1px sel-out (selective outlining — darker shade of neighbor, not black) on lit sides, full dark outline only in shadow; avoid banding (parallel same-color rows) and pillow-shading (edge halo).
- Shading: light source fixed top-left, 2 tones max at 16px (base + 1 shadow), dither (checkerboard) only for gradients on large areas; hue-shift shadows toward blue/purple, highlights toward yellow.
- Tiles: 16x16 grid, 1px overlap-safe edges, test 3x3 tile stamp for seams; autotile bitmask (2x2/47-tile) for terrain; keep contrast low on repeat fills so sprites pop.
- Animation: 2-4 frames idle (bob 1px), 4-6 run cycle, 12fps retro / 24fps smooth; onion skin ±1 frame, fixed pivot (feet center), export sprite strip + `.json` atlas.
- Aseprite path: paid Steam/app ($20) — timeline, onion skin, palette control, CLI export; free path: Piskel (browser) for starters, LibreSprite (fork) offline — both open `.aseprite` via export.
- Readability: silhouette first (fill black, must read at 1x), then internal detail; 1px eyes at 16px, 2px at 32px; test at 1x, 2x, and game-background (dark + light).
- Export scale: nearest-neighbor only, integer scales (200/300/400%, never 150/250%), PNG-8 with embedded palette; spritesheet `power-of-two` padding, pivot metadata in filename (`hero_idle_0.png`).
- Workflow: sketch 1x silhouette → block palette flats → sel-out line → shade pass → cleanup (orphans/jaggies/banding) → animate → export @1x + @4x preview GIF.
- Color discipline: no pure black `#000`/white `#fff` fills (use `#1a1c2c`/`#f4f4f4`), lock alpha at 100% (no semi-pixels), ramp check: sort by value, gaps even.
## Examples
- 16x16 sword icon: black silhouette readable at 1x, 5-color ramp, 1px highlight edge, sel-out sides, PNG @1x + 4x nearest preview.
- 32x32 hero run: 6-frame cycle at 12fps, feet pivot locked, 1px bob, onion-skin cleanup, strip export + atlas JSON for Godot/Unity.
- Grass autotile: 16px base + edge overlays, 3x3 seam test on dark/light bg, 47-tile bitmask set, low-contrast fill so character reads.
## Workflows
1. Lock canvas (16/32) + palette (Resurrect/Sweetie) + light dir top-left.
2. Block black silhouette → verify readability at 1x on both backgrounds.
3. Flat fills from ramp, sel-out lineart, then 1-2 tone shade pass.
4. Cleanup sweep: orphans, jaggies, banding, pillow-shade, AA strays.
5. Animate (onion skin, fixed pivot) → play at 12fps → fix pops.
6. Export PNG nearest integer-scale + strip/atlas + preview GIF @4x.
## Templates
- Palette + canvas presets (Aseprite/Piskel import):
```txt
# Sweetie-16 hex ramp (paste into .pal / Lospec import)
1a1c2c 5d275d b13e53 ef7d57 ffcd75 a7f070 38b764 257179
29366f 3b5dc9 41a6f6 73eff7 f4f4f4 94b0c2 566c86 333c57
# Canvas cheat-sheet
icon/loot .... 16x16  (eyes 1px, 4-6 colors)
character ..... 32x32  (eyes 2px, 6-8 colors)
portrait ...... 64x64  (dither allowed)
scene mockup .. 320x180 @1x, preview @4x = 1280x720
```
- Aseprite CLI export (strips + scaled):
```bash
# single sprite 1x + 4x nearest
aseprite -b hero.aseprite --save-as hero_1x.png
aseprite -b hero.aseprite --scale 4 --save-as hero_4x.png
# animation strip (horizontal) + atlas
aseprite -b hero_run.aseprite --sheet hero_run.png \
  --sheet-type horizontal --split-layers --list-tags \
  --data hero_run.json --format json-array --scale 1
# palette swap preview
aseprite -b hero.aseprite --palette night.gpl --save-as hero_night.png
```
- Godot atlas import snippet (nearest, no filter):
```gdscript
# set texture import: Filter OFF, Mipmap OFF
# AnimatedSprite2D from strip hero_run.png (6 frames of 32x32)
var frames := SpriteFrames.new()
var tex := load("res://art/hero_run.png") as Texture2D
for i in 6:
    var at := AtlasTexture.new()
    at.atlas = tex
    at.region = Rect2(i * 32, 0, 32, 32)
    frames.add_frame("run", at)
$AnimatedSprite2D.frames = frames
$AnimatedSprite2D.play("run")
```
## Tools
- SARAH shell_run for Aseprite CLI exports, ImageMagick `convert -scale 400% -filter point` previews, spritesheet packing.
- Aseprite (pro) or Piskel/LibreSprite (free); Lospec palette browser; game-engine import with filter-off.
## Advanced
- Dither control: 25/50% checker only on >32px gradients, ordered Bayer 2x2 max; never dither faces at 16px — banding risk outweighs texture gain.
- Mockup pipeline: graybox scene at 1x → palette pass with 3 values (bg/mid/fg) → atmospheric perspective (cool + desat far) → 4x GIF for portfolio.
- Porting: 1-bit (black/white) jam variant by threshold ramp at 50% value; outline pass converts sel-out to full 1px for readability on tiny screens.
## Documentation
- https://lospec.com/palette-list
- https://www.aseprite.org/docs/
- https://www.piskelapp.com/
- https://libresprite.github.io/
- https://lospec.com/articles/pixel-art-tutorials
