# Paper-Cut Hills — `paper-cut-hills@1.0.0`

A diorama of layered paper hills in soft colours sliding past each other, a paper sun behind and birds crossing the sky. Loops perfectly.

A diorama of layered paper: rows of rolling hills cut from card, each layer a different colour and a little darker the nearer it sits, every layer casting a soft shadow on the one behind, a pale sun or moon behind the farthest ridge and a few paper birds crossing the sky. The layers slide sideways at different speeds, so the scene has real parallax, and each moves a whole number of its own repeats per loop so the loop is exact. Choose the number of layers, the colours (dawn, forest, dusk or snow), how many repeats the nearest layer moves per loop, whether birds fly and the seed.

- Kind: background; status: published; digest sha256:db56a4aabea20946b76f3d379905b4f86fc3e34cfd34d262057f74c940309056
- Role: Background (Canvas 2D): a handmade, calm, parallax landscape for titles, children's content and wellness.
- Implementation: canvas2d; entry `src/paper-cut-hills.js`
- Files: https://aipixelwizard.com/registry/paper-cut-hills/1.0.0/<path> (`LICENSE`, `asset.json`, `demo.js`, `index.html`, `src/paper-cut-hills.js`)
- Manifest JSON: https://aipixelwizard.com/api/v1/visuals/paper-cut-hills/versions/1.0.0
- Runnable demo: https://aipixelwizard.com/registry/paper-cut-hills/1.0.0/index.html (open over http; it imports sibling packages by relative path)
- Dependencies (exact): `apw-runtime@1.0.0` (demo) — Demo harness. The reusable source has no dependencies.

## Exports
- `createPaperCutHills({ layers?, palette?, speed?, birds?, seed? }) => { draw(ctx, info, width, height) }` — Canvas 2D scene; info.progress (0 to 1 over the loop) sets the place in the loop; it fills the canvas.
- `PALETTES: { dawn, forest, dusk, snow }` — Sky, sun and layer colours.

## Parameters
- `layers` (integer 3–7, default 6) — Layers
- `palette` (select one of dawn | forest | dusk | snow, default "dawn") — Colours
- `speed` (integer 1–3, default 1) — Speed: Repeats of the nearest layer's hills per loop.
- `birds` (boolean, default true) — Birds
- `seed` (integer 1–999, default 4) — Seed

## Composition
- Inputs: Canvas 2D context, info.progress (0 to 1 over the loop), width, height.
- Outputs: Fills the whole canvas.
- Coordinates: Layers are drawn farthest first; each layer's ridge is a sum of three sine harmonics of its own repeat length, longer for nearer layers.
- Lighting: Each layer casts a soft shadow upwards onto the one behind; the sun has a pale halo.
- Timing: Pure function of info.progress.
- Works with: kinetic-title, gradient-background
- A faint fixed paper grain is drawn over everything.

## Output and loop
- 1080×1080, 30 fps, 12 s, procedural
- Seamless loop: yes — Each layer moves exactly a whole number of its own repeats per loop and the birds make whole laps with whole wing-beats, so the last frame meets the first.
- Verified 2026-10-08 in Chrome 154.0.8037.97 headless on Linux 7.0.0-38-generic (x64), Node 22.14.0 (Canvas 2D); deterministic: yes; loop check: Frame 0 vs end state (progress 1): mean |Δ| 0.0000, max |Δ| 0 of 255.

## Use it
New project: Create the scene once, then each frame call hills.draw(ctx, { progress }, width, height).

Existing project: Copy src/paper-cut-hills.js. Call draw on your 2D canvas as the first thing in the frame.

Reuse ideas:
- Story title: Dawn, six layers.
- Nature video: Forest, fast.
- Bedtime: Dusk, no birds.

## Limitations
- The look is flat paper with soft shadows; there is no 3D or real lighting.
- Hills repeat exactly with the loop, so a very long clip can look cyclic.

## License
MIT. Copyright (c) 2026 AI Pixel Wizard. Released under the MIT License. See LICENSE in this folder.

Provenance: Original code written for AI Pixel Wizard in October 2026, to the catalog quality bar (docs/QUALITY.md).

