paperlab 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +25 -7
- package/dist/chunk-3IMUEESH.js +7035 -0
- package/dist/chunk-3IMUEESH.js.map +1 -0
- package/dist/index.cjs +1938 -1753
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +582 -4400
- package/dist/index.d.ts +582 -4400
- package/dist/index.js +225 -6727
- package/dist/index.js.map +1 -1
- package/dist/slots-D0Nc_5dq.d.cts +6661 -0
- package/dist/slots-D0Nc_5dq.d.ts +6661 -0
- package/dist/stage.cjs +8871 -0
- package/dist/stage.cjs.map +1 -0
- package/dist/stage.d.cts +1156 -0
- package/dist/stage.d.ts +1156 -0
- package/dist/stage.js +2214 -0
- package/dist/stage.js.map +1 -0
- package/package.json +37 -8
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/config/merge.ts","../src/core/tessellation.ts","../src/deformers/curl.ts","../src/behaviors/peel.ts","../src/behaviors/unroll.ts","../src/behaviors/flip.ts","../src/behaviors/letter-fold.ts","../src/behaviors/hang.ts","../src/behaviors/fly.ts","../src/behaviors/fall.ts","../src/behaviors/carry.ts","../src/physics/aero.ts","../src/behaviors/flight.ts","../src/behaviors/crumple.ts","../src/behaviors/settle.ts","../src/behaviors/ribbon.ts","../src/config/schema.ts","../src/config/serialize.ts","../src/core/sheet.ts","../src/core/stock.ts","../src/config/presets/index.ts","../src/content/receipt.ts","../src/content/type.ts","../src/deformers/roll.ts","../src/deformers/bend.ts","../src/deformers/fold.ts","../src/deformers/wave.ts","../src/deformers/drape.ts","../src/deformers/crumple.ts","../src/deformers/registry.ts","../src/deformers/compose.ts","../src/core/normals.ts","../src/behaviors/registry.ts","../src/physics/idle.ts","../src/physics/cloth.ts","../src/scene/lighting.ts","../src/surface/translucency.ts","../src/surface/compose.ts","../src/scene/rig.tsx","../src/surface/PaperMaterial.tsx","../src/a11y/index.tsx","../src/motion/onTwos.ts","../src/states/machine.ts","../src/states/usePaperStates.ts","../src/PaperMesh.tsx","../src/core/stable.ts","../src/content/texture.ts","../src/content/card.ts","../src/scene/PaperLighting.tsx","../src/scene/environment.ts","../src/scene/color.ts","../src/field/dropZones.tsx","../src/field/sheetGrid.ts","../src/field/slots.ts","../src/content/atlas.ts","../src/field/compose.ts","../src/stage/path.ts","../src/field/layouts/index.ts","../src/content/backing.ts","../src/field/keyboardMirror.tsx","../src/field/framing.ts","../src/PaperField.tsx","../src/field/fieldGroup.tsx","../src/field/stack.ts","../src/field/backingSheet.tsx","../src/field/interactiveField.tsx","../src/config/diff.ts","../src/config/agent-payload.ts"],"sourcesContent":["/**\n * Deep-merge preset config with prop overrides (overrides win; arrays and\n * discriminated unions replace wholesale, plain objects merge).\n *\n * Lives in its own module (not serialize.ts) because the schema needs it to\n * validate state overrides — schema → serialize would be circular.\n */\nexport function mergeConfig<T>(base: T, override: unknown): T {\n if (override === undefined) return base\n if (\n base !== null &&\n override !== null &&\n typeof base === 'object' &&\n typeof override === 'object' &&\n !Array.isArray(base) &&\n !Array.isArray(override)\n ) {\n // A content/behavior union with a different `type` replaces wholesale —\n // merging { type: 'text' } over { type: 'image', src } would leak `src`.\n const b = base as Record<string, unknown>\n const o = override as Record<string, unknown>\n if ('type' in b && 'type' in o && b.type !== o.type) return override as T\n const out: Record<string, unknown> = { ...b }\n for (const key of Object.keys(o)) {\n out[key] = mergeConfig(b[key], o[key])\n }\n return out as T\n }\n return override as T\n}\n\n/**\n * Like {@link mergeConfig}, but an explicit `undefined` DELETES its key instead\n * of being ignored — the semantics a BASE-config write needs: structural\n * setters can clear `behavior`/`deformers` or toggle a surface effect off.\n * Discriminated unions (differing `type`) still replace wholesale.\n */\nexport function mergeWithDeletes<T>(base: T, patch: unknown): T {\n if (\n base !== null &&\n patch !== null &&\n typeof base === 'object' &&\n typeof patch === 'object' &&\n !Array.isArray(base) &&\n !Array.isArray(patch)\n ) {\n const b = base as Record<string, unknown>\n const p = patch as Record<string, unknown>\n if ('type' in b && 'type' in p && b.type !== p.type) return patch as T\n const out: Record<string, unknown> = { ...b }\n for (const [key, value] of Object.entries(p)) {\n if (value === undefined) delete out[key]\n else out[key] = mergeWithDeletes(b[key], value)\n }\n return out as T\n }\n return patch as T\n}\n","/**\n * How finely a sheet has to be subdivided for a deformer to look like the\n * surface it is approximating instead of like the polygons it is made of.\n *\n * A deformed mesh is a piecewise-linear stand-in for a curved surface, and the\n * error is the **sagitta**: the gap between a chord and the arc it cuts\n * across. For a chord of length `h` on a circle of radius `r` that gap is\n * `h²/8r` to well under a percent for any chord worth drawing. Invert it and\n * the whole question — \"how many segments does this need?\" — has a closed\n * form: pick the error you are willing to see, and the segment count falls\n * out of the radius.\n *\n * That is the difference between this and `minSegments`. `minSegments` is a\n * correctness FLOOR — the density below which a deformer stops working at\n * all. This is a QUALITY TARGET, and unlike a floor it has to depend on the\n * options: a bend at `curvature: 0.05` and a roll at `radius: 0.02` are not\n * remotely the same request, and one constant per deformer cannot answer for\n * both.\n */\n\nimport type { SheetDims } from '../deformers/types'\n\n/**\n * The error we are willing to see, in world units (a letter sheet is 1 × 1.4,\n * so 1 unit ≈ 216 mm and this is ≈ 0.09 mm).\n *\n * Calibrated, not picked: at `segments: 'auto'`'s old flat 72, the default\n * `roll` (radius 0.12 across a 1.4 span) already ran at a sagitta of 3.9e-4.\n * Setting the tolerance there means the tightest configuration in common use\n * keeps exactly the density it ships with today, and everything gentler —\n * which was paying for that same grid and getting fourteen times the\n * precision it needed — stops paying. The number is a statement about the\n * status quo, so changing it re-lights every preset in the library.\n */\nexport const SAG_TOL = 4e-4\n\n/**\n * Ceiling for `'auto'` in hero mode, and it is a CPU budget rather than a\n * round number.\n *\n * Hero mode re-deforms every vertex in JS on the main thread, every frame,\n * for any animated stack — and `wave` is animated, so a hanging poster pays\n * it forever rather than only while something plays. Measured, one sheet,\n * one re-deform (`drape + wave`, and `crumple` tracks it within 5%), before\n * and after the loop was rewritten around a single-function inner call site\n * and `computeSheetNormals`:\n *\n * | grid | verts | was | now |\n * | ----: | -----: | ---: | ---: |\n * | 72 | 3,796 | 0.74 | 0.27 |\n * | 128 | 11,868 | 2.30 | 0.84 |\n * | 192 | 26,634 | 5.01 | 1.89 |\n * | 256 | 47,288 | 8.74 | 3.38 |\n *\n * **192, raised from 128, and the price is why.** 128 was picked when it cost\n * 2.30 ms — the last step that still left room for a scene around it. 192 now\n * costs 1.89 ms, which is less than 128 ever did, so the old line was drawn\n * against a price that no longer exists.\n *\n * The reason it is nearly free in practice is the axis split: a demand lands\n * on the direction that bends and the other axis stays at `FLAT_SEGMENTS`. A\n * `drape` at its own defaults wants 154 across and two segments down, so the\n * raise costs it 0.02 ms rather than the 1.89 ms a square 192 grid implies.\n * The square case is reachable — a stack that bends both ways, `wave` over\n * `drape` — and it is opt-in through options rather than something a preset\n * hands anybody.\n *\n * What it buys, all of it previously capped: `drape` at its defaults (154),\n * `roll` and `fold` at `radius: 0.02` (175), `curl` at `radius: 0.02` (142).\n * No preset that ships reaches even 128 after the axis split, so this changes\n * nothing already in the library — it stops punishing people who ask for a\n * tighter crease than any preset uses.\n *\n * Still NOT high enough for everything the arithmetic asks: `wave` at\n * `amplitude: 0.3` wants 272 and a 16-fold `drape` at full depth wants 1377.\n * Those stay capped, and the gap is real rather than hidden. Set `segments`\n * to a number (up to the schema's 256) to go past it.\n *\n * A field is capped far lower and separately, because a field draws this\n * geometry N times — see `FIELD_AUTO_CEILING`.\n */\nexport const AUTO_CEILING = 192\n\n/**\n * What a sheet gets when nothing deforms it. A flat plane is exact at one\n * segment; this is the small margin that keeps anything interpolated across\n * the quad (lighting terms, translucency) from reading the corners only.\n */\nexport const FLAT_SEGMENTS = 8\n\n/**\n * What `'auto'` handed out flat, on every sheet, before it learned to adapt.\n *\n * Still load-bearing in two places: it is what `resolveSegments` assumes when\n * a caller has no deformer stack to ask (so the exported helper answers today\n * exactly what it answered before), and it is what a field is allowed to ask\n * for, since a field draws its buffer once per instance.\n */\nexport const LEGACY_FLAT_SEGMENTS = 72\n\n/**\n * Resolved counts are snapped to this ladder. Without it the grid would be a\n * continuous function of the options, so dragging a curvature slider would\n * rebuild the geometry — a new `PlaneGeometry`, a fresh base-position copy,\n * and a disposed buffer — on every tick. Snapped, a drag crosses a step\n * rarely and holds one buffer the rest of the time.\n */\nconst LADDER = [FLAT_SEGMENTS, 12, 16, 24, 32, 48, 64, LEGACY_FLAT_SEGMENTS, 96, 128, AUTO_CEILING] as const\n\n/** Smallest ladder step at or above `n`, clamped to the ceiling. */\nexport function quantizeSegments(n: number): number {\n for (const step of LADDER) if (n <= step) return step\n return AUTO_CEILING\n}\n\n/**\n * A resolved grid: segments along the sheet's own X and Y.\n *\n * Two numbers rather than one because a sheet is not subdivided by a single\n * density. A banner 1.5 wide and 8.5 tall, draped in folds that run across\n * its width, needs the folds resolved ACROSS and needs almost nothing down\n * the drop — and a single number, however it is distributed, answers one of\n * those questions by getting the other one wrong.\n */\nexport type SegmentPair = [x: number, y: number]\n\n/**\n * Split a deformer's segment demand onto the sheet's two axes.\n *\n * A deformer curves along ONE direction — `roll`, `bend`, `fold` and `wave`\n * all name it `angle`, `drape`'s folds run across the width, `curl` works\n * down a corner diagonal — and `segmentsForArc` answers in segments along\n * THAT direction. Turning that into a grid is a projection: the demand is\n * really a density (segments per world unit along the curve), and each axis\n * needs enough of it that a grid edge's component along the curve stays\n * inside the chord the sagitta bound allows.\n *\n * Hence `width·|cos θ|·density` and `height·|sin θ|·density`. A bend across\n * x asks everything of x and nothing of y, which is exactly right: the sheet\n * does not move along y, so subdividing it there buys a bigger buffer and an\n * identical picture.\n *\n * `null` is for a deformer with no single direction — `crumple`'s creases\n * run every way at once. That case keeps the old behaviour of spreading the\n * demand by aspect ratio, which is the honest answer when the demand really\n * is isotropic.\n */\nexport function axialSegments(sheet: SheetDims, angleDeg: number | null, n: number): SegmentPair {\n if (!(n > 0)) return [0, 0]\n if (angleDeg === null) {\n const long = Math.max(sheet.width, sheet.height)\n if (!(long > 0)) return [n, n]\n return [(sheet.width / long) * n, (sheet.height / long) * n]\n }\n const span = spanAlong(sheet, angleDeg)\n if (!(span > 0)) return [n, n]\n const rad = (angleDeg * Math.PI) / 180\n const density = n / span\n return [sheet.width * Math.abs(Math.cos(rad)) * density, sheet.height * Math.abs(Math.sin(rad)) * density]\n}\n\n/**\n * Extent of the sheet along a direction in its own plane, degrees. For a\n * rectangle centered on the origin this is exactly `|w·cos| + |h·sin|` — the\n * projection of both half-extents onto the axis, doubled.\n */\nexport function spanAlong(sheet: SheetDims, angleDeg: number): number {\n const rad = (angleDeg * Math.PI) / 180\n return Math.abs(sheet.width * Math.cos(rad)) + Math.abs(sheet.height * Math.sin(rad))\n}\n\n/**\n * Segments needed to hold a circular arc of radius `r` across `span` within\n * `tol`. Straight inversion of `sag = h²/8r`.\n *\n * A flat or near-flat arc (huge radius) needs nothing, hence the 0 — callers\n * take the max against the floor, so 0 means \"this deformer is not the reason\n * for any subdivision\", which is exactly true of a bend at curvature 0.\n */\nexport function segmentsForArc(span: number, radius: number, tol = SAG_TOL): number {\n if (!(span > 0) || !(radius > 0) || !Number.isFinite(radius)) return 0\n return span / Math.sqrt(8 * radius * tol)\n}\n\n/**\n * Same question for a sinusoid, which is the shape `wave` and `drape` both\n * make. Peak curvature of `A·sin(2πx/λ)` is `A(2π/λ)²` at the crest, so the\n * tightest radius on the curve is its reciprocal and the arc form takes over\n * from there.\n */\nexport function segmentsForSine(span: number, amplitude: number, wavelength: number, tol = SAG_TOL): number {\n if (!(amplitude > 0) || !(wavelength > 0)) return 0\n const k = (2 * Math.PI) / wavelength\n const peakCurvature = amplitude * k * k\n if (!(peakCurvature > 0)) return 0\n return segmentsForArc(span, 1 / peakCurvature, tol)\n}\n","import { z } from 'zod'\nimport type { Deformer } from './types'\nimport { segmentsForArc } from '../core/tessellation'\n\nexport const cornerNames = ['top-left', 'top-right', 'bottom-left', 'bottom-right'] as const\n\nexport const curlOptionsSchema = z.object({\n corner: z.enum(cornerNames).default('bottom-right'),\n /** How far the curl has traveled from the corner, as a fraction of the diagonal. */\n amount: z.number().min(0).max(1).default(0.35),\n /** Cylinder radius — curl sharpness. */\n radius: z.number().min(0.02).max(1).default(0.16),\n /** Skew of the fold line away from the corner diagonal, degrees. */\n skew: z.number().min(-40).max(40).default(0),\n})\n\nexport type CurlOptions = z.infer<typeof curlOptionsSchema>\n\nconst DEG = Math.PI / 180\n\nconst CORNER_SIGNS: Record<(typeof cornerNames)[number], [number, number]> = {\n 'top-left': [-1, 1],\n 'top-right': [1, 1],\n 'bottom-left': [-1, -1],\n 'bottom-right': [1, -1],\n}\n\n/**\n * Corner-anchored cylinder wrap — the peel/dog-ear deformer, and the\n * crown-jewel realism case: the mesh genuinely wraps the cylinder so content\n * bends with perfect continuity and the backside becomes visible.\n *\n * The fold line runs perpendicular to the corner diagonal and travels inward\n * with `amount`; everything cornerward of it wraps around the cylinder.\n */\nexport const curl: Deformer<CurlOptions> = {\n id: 'curl',\n label: 'Curl',\n defaults: curlOptionsSchema.parse({}),\n optionsSchema: curlOptionsSchema,\n geometry: {\n minSegments: 48,\n // Curl rolls the corner region around `radius`, travelling inward along\n // the diagonal as `amount` rises. The diagonal is the span the arc can\n // reach across, and `radius` is its curvature throughout.\n autoSegments: (o, sheet) => segmentsForArc(Math.hypot(sheet.width, sheet.height), o.radius),\n // The corner diagonal, plus whatever `skew` turns it by — the same\n // direction `displace` builds below, and the one the wrap runs along.\n axis: (o, sheet) => {\n const [sx, sy] = CORNER_SIGNS[o.corner]\n return Math.atan2(sy * sheet.height, sx * sheet.width) / DEG + o.skew\n },\n },\n displace(out, _uv, o, ctx) {\n const [sx, sy] = CORNER_SIGNS[o.corner]\n const { width, height } = ctx.sheet\n const cx = (sx * width) / 2\n const cy = (sy * height) / 2\n\n // Outward direction: from sheet center toward the corner, plus skew.\n const diag = Math.hypot(width, height)\n const baseX = (sx * width) / diag\n const baseY = (sy * height) / diag\n const skew = o.skew * DEG\n const cosK = Math.cos(skew)\n const sinK = Math.sin(skew)\n const dirX = baseX * cosK - baseY * sinK\n const dirY = baseX * sinK + baseY * cosK\n\n // Signed distance past the fold line (fold travels inward with amount).\n const travel = o.amount * diag * 0.5\n const e = (out.x - cx) * dirX + (out.y - cy) * dirY\n const s = e + travel\n if (s <= 0) return\n\n const theta = s / o.radius\n const sin = Math.sin(theta)\n const cos = Math.cos(theta)\n const boundary = e - s // = -travel\n const newE = boundary + (o.radius - out.z) * sin\n const newZ = o.radius * (1 - cos) + out.z * cos\n\n out.x += dirX * (newE - e)\n out.y += dirY * (newE - e)\n out.z = newZ\n },\n glsl: {\n chunk: /* glsl */ `\nvoid FN(inout vec3 p, vec2 uv, float t) {\n vec2 c = U_cornerSign * uSheet * 0.5;\n float diag = length(uSheet);\n vec2 base = U_cornerSign * uSheet / diag;\n float cosK = cos(U_skew);\n float sinK = sin(U_skew);\n vec2 dir = vec2(base.x * cosK - base.y * sinK, base.x * sinK + base.y * cosK);\n float travel = U_amount * diag * 0.5;\n float e = dot(p.xy - c, dir);\n float s = e + travel;\n if (s <= 0.0) return;\n float theta = s / U_radius;\n float sn = sin(theta);\n float cs = cos(theta);\n float newE = (e - s) + (U_radius - p.z) * sn;\n float newZ = U_radius * (1.0 - cs) + p.z * cs;\n p.xy += dir * (newE - e);\n p.z = newZ;\n}\n`,\n strength: 'amount',\n uniforms: (o) => {\n const [sx, sy] = CORNER_SIGNS[o.corner]\n return {\n cornerSign: [sx, sy],\n amount: o.amount,\n radius: o.radius,\n skew: o.skew * DEG,\n }\n },\n },\n}\n","import { z } from 'zod'\nimport type { Behavior } from './types'\nimport { cornerNames } from '../deformers/curl'\n\nexport const peelOptionsSchema = z.object({\n progress: z.number().min(0).max(1).default(0.35),\n /** 'auto' resolves per slot in a `sheet` field (outward-facing corner); standalone it means bottom-right. */\n corner: z.enum([...cornerNames, 'auto']).default('bottom-right'),\n /** Curl sharpness — small is a tight dog-ear, large a soft lift. */\n radius: z.number().min(0.05).max(0.6).default(0.16),\n})\n\nexport type PeelOptions = z.infer<typeof peelOptionsSchema>\n\nconst CORNER_UV: Record<(typeof cornerNames)[number], [number, number]> = {\n 'top-left': [0, 1],\n 'top-right': [1, 1],\n 'bottom-left': [0, 0],\n 'bottom-right': [1, 0],\n}\n\n/** Fields resolve 'auto' per slot; anywhere else it falls back to the default corner. */\nconst concreteCorner = (c: PeelOptions['corner']) => (c === 'auto' ? 'bottom-right' : c)\n\n/** A corner lifts and curls back — the hero-image hover peel. */\nexport const peel: Behavior<PeelOptions> = {\n id: 'peel',\n label: 'Peel',\n defaults: peelOptionsSchema.parse({}),\n optionsSchema: peelOptionsSchema,\n signature: ['progress', 'corner'],\n progressParam: 'progress',\n duration: 2.2,\n loopMode: 'yoyo',\n stack(o) {\n // A deep peel lifts on a softer cylinder — a fixed tight radius would\n // wind the sheet into a dart. Growing the radius with progress keeps the\n // curl reading as a page lift at every depth.\n return [\n {\n type: 'curl',\n options: {\n corner: concreteCorner(o.corner),\n amount: o.progress,\n radius: o.radius + o.progress * 0.3,\n skew: 0,\n },\n },\n ]\n },\n handles: [\n {\n id: 'corner',\n anchor: (o) => CORNER_UV[concreteCorner(o.corner)],\n drag(local, o, sheet) {\n // Pull toward the sheet center = more peel: distance from the flat\n // corner along the inward diagonal, normalized to half the diagonal.\n const [ux, uy] = CORNER_UV[concreteCorner(o.corner)]\n const cx = (ux - 0.5) * sheet.width\n const cy = (uy - 0.5) * sheet.height\n const diag = Math.hypot(sheet.width, sheet.height)\n const inX = -cx / Math.hypot(cx, cy)\n const inY = -cy / Math.hypot(cx, cy)\n const dist = (local.x - cx) * inX + (local.y - cy) * inY\n return { progress: Math.min(1, Math.max(0, dist / (diag * 0.5))) }\n },\n },\n ],\n}\n","import { z } from 'zod'\nimport type { Behavior } from './types'\n\nexport const unrollOptionsSchema = z.object({\n /** 0 = fully rolled cylinder, 1 = flat sheet. */\n progress: z.number().min(0).max(1).default(0.5),\n /** How tightly the paper is wound. */\n tightness: z.number().min(0).max(1).default(0.5),\n /** Idle rocking of the rolled end. */\n sway: z.number().min(0).max(1).default(0.25),\n})\n\nexport type UnrollOptions = z.infer<typeof unrollOptionsSchema>\n\n/**\n * A receipt unrolls from the bottom: the sheet hangs flat from its top edge\n * and the remaining paper is wound in a roll at the bottom. Content bends\n * true around the roll — the reference-image requirement.\n */\nexport const unroll: Behavior<UnrollOptions> = {\n id: 'unroll',\n label: 'Unroll',\n defaults: unrollOptionsSchema.parse({}),\n optionsSchema: unrollOptionsSchema,\n signature: ['progress', 'tightness'],\n progressParam: 'progress',\n duration: 3,\n loopMode: 'yoyo',\n stack(o, sheet) {\n const radius = 0.28 - o.tightness * 0.22\n // Rolling direction points down (-y): the region below the boundary is\n // wound. progress sweeps the boundary from the top edge (fully rolled)\n // past the bottom edge (flat, plus slack so the last bit fully relaxes).\n const start = -sheet.height / 2\n const end = sheet.height / 2 + radius * 2\n return [\n {\n type: 'roll',\n options: {\n angle: 270,\n boundary: start + o.progress * (end - start),\n radius,\n spiral: 0.02,\n },\n },\n ]\n },\n loop(o, t) {\n if (o.sway === 0) return {}\n // The rolled tail rocks gently; transient — never persisted.\n const wobble = Math.sin(t * 1.5) * 0.01 * o.sway\n return { progress: Math.min(1, Math.max(0, o.progress + wobble)) }\n },\n handles: [\n {\n id: 'roll-edge',\n anchor: (o) => [0.5, Math.max(0.02, Math.min(0.98, 1 - o.progress))],\n drag(local, _o, sheet) {\n // Dragging the roll edge down unrolls the paper.\n return { progress: Math.min(1, Math.max(0, 0.5 - local.y / sheet.height)) }\n },\n },\n ],\n}\n","import { z } from 'zod'\nimport type { Behavior } from './types'\n\nexport const flipOptionsSchema = z.object({\n /** 0 = flat, 1 = page fully turned over the spine. */\n progress: z.number().min(0).max(1).default(0.3),\n /** Which edge is the spine. */\n spine: z.enum(['left', 'right']).default('left'),\n /** Softness of the turning curl. */\n radius: z.number().min(0.1).max(0.8).default(0.3),\n})\n\nexport type FlipOptions = z.infer<typeof flipOptionsSchema>\n\n/**\n * A page turn: the free edge curls up and rolls over toward the spine —\n * the roll deformer with its boundary swept across the page.\n */\nexport const flip: Behavior<FlipOptions> = {\n id: 'flip',\n label: 'Flip',\n defaults: flipOptionsSchema.parse({}),\n optionsSchema: flipOptionsSchema,\n signature: ['progress', 'spine'],\n progressParam: 'progress',\n duration: 1.8,\n loopMode: 'yoyo',\n stack(o, sheet) {\n // Rolling direction points at the free edge; the boundary starts past\n // the free edge (flat) and sweeps to the spine (fully turned).\n const angle = o.spine === 'left' ? 0 : 180\n const start = sheet.width / 2\n const end = -sheet.width / 2\n return [\n {\n type: 'roll',\n options: {\n angle,\n boundary: start + o.progress * (end - start),\n radius: o.radius,\n spiral: 0,\n },\n },\n ]\n },\n handles: [\n {\n id: 'free-edge',\n anchor: (o) => (o.spine === 'left' ? [0.98, 0.5] : [0.02, 0.5]),\n drag(local, o, sheet) {\n // Dragging the free edge toward the spine turns the page.\n const x = o.spine === 'left' ? local.x : -local.x\n return { progress: Math.min(1, Math.max(0, 0.5 - x / sheet.width)) }\n },\n },\n ],\n}\n","import { z } from 'zod'\nimport type { Behavior } from './types'\n\nexport const letterFoldOptionsSchema = z.object({\n /** 0 = flat letter, 1 = fully tri-folded. */\n progress: z.number().min(0).max(1).default(0.4),\n /** Softness of the two creases. */\n crease: z.number().min(0).max(1).default(0.3),\n})\n\nexport type LetterFoldOptions = z.infer<typeof letterFoldOptionsSchema>\n\n/**\n * The classic tri-fold: the bottom third folds up first, then the top third\n * folds down over it. Two fold deformers stacked — order is the physics.\n */\nexport const letterFold: Behavior<LetterFoldOptions> = {\n id: 'letter-fold',\n label: 'Letter fold',\n defaults: letterFoldOptionsSchema.parse({}),\n optionsSchema: letterFoldOptionsSchema,\n signature: ['progress', 'crease'],\n progressParam: 'progress',\n duration: 2.6,\n loopMode: 'yoyo',\n stack(o, sheet) {\n const radius = 0.02 + o.crease * 0.06\n // The bottom flap leads, the top flap follows slightly behind so the\n // motion reads as two deliberate folds, not one collapse.\n const bottom = Math.min(1, o.progress * 1.25)\n const top = Math.max(0, o.progress * 1.25 - 0.25)\n return [\n {\n // Bottom third folds up and over (fold travels downward from -h/6).\n type: 'fold',\n options: {\n angle: 270,\n offset: sheet.height / 6,\n foldAngle: bottom * 165,\n radius,\n },\n },\n {\n // Top third folds down across the (already folded) bottom flap.\n type: 'fold',\n options: {\n angle: 90,\n offset: sheet.height / 6,\n foldAngle: top * 150,\n radius: radius * 1.6,\n },\n },\n ]\n },\n handles: [\n {\n id: 'top-flap',\n anchor: () => [0.5, 1],\n drag(local, _o, sheet) {\n // Pulling the top edge down folds the letter.\n return { progress: Math.min(1, Math.max(0, (sheet.height / 2 - local.y) / sheet.height)) }\n },\n },\n ],\n}\n","import { z } from 'zod'\nimport type { Behavior } from './types'\n\nexport const hangOptionsSchema = z.object({\n /** Wind strength driving the ripple. */\n wind: z.number().min(0).max(1).default(0.4),\n /** Gravity bulge of the hanging sheet. */\n sag: z.number().min(0).max(1).default(0.3),\n})\n\nexport type HangOptions = z.infer<typeof hangOptionsSchema>\n\n/** A poster hanging from its top edge, rippling in wind. */\nexport const hang: Behavior<HangOptions> = {\n id: 'hang',\n label: 'Hang',\n defaults: hangOptionsSchema.parse({}),\n optionsSchema: hangOptionsSchema,\n signature: ['wind', 'sag'],\n progressParam: 'wind',\n duration: 4,\n loopMode: 'yoyo',\n stack(o) {\n return [\n { type: 'bend', options: { curvature: 0.15 + o.sag * 0.55, angle: 90 } },\n {\n type: 'wave',\n options: {\n amplitude: o.wind * 0.055,\n wavelength: 0.45,\n speed: 0.9 + o.wind * 0.8,\n angle: 75,\n pinnedEdge: 'top',\n },\n },\n ]\n },\n}\n","import { z } from 'zod'\nimport type { Behavior } from './types'\n\nexport const flyOptionsSchema = z.object({\n /** Ripple energy. */\n flutter: z.number().min(0).max(1).default(0.5),\n /** Aerodynamic arc of the sheet. */\n curve: z.number().min(0).max(1).default(0.4),\n})\n\nexport type FlyOptions = z.infer<typeof flyOptionsSchema>\n\n/** A note carried on air — arched and fluttering. Pair with the `tumble` idle. */\nexport const fly: Behavior<FlyOptions> = {\n id: 'fly',\n label: 'Fly',\n defaults: flyOptionsSchema.parse({}),\n optionsSchema: flyOptionsSchema,\n signature: ['flutter', 'curve'],\n progressParam: 'flutter',\n duration: 3.5,\n loopMode: 'yoyo',\n stack(o) {\n return [\n { type: 'bend', options: { curvature: 0.25 + o.curve, angle: 0 } },\n {\n type: 'wave',\n options: {\n amplitude: o.flutter * 0.07,\n wavelength: 0.7,\n speed: 1.6,\n angle: 30,\n pinnedEdge: 'none',\n },\n },\n ]\n },\n}\n","import { z } from 'zod'\nimport type { Behavior } from './types'\n\nexport const fallOptionsSchema = z.object({\n /** Air resistance ripple while falling. */\n flutter: z.number().min(0).max(1).default(0.6),\n /** A falling sheet always lifts a corner. */\n curl: z.number().min(0).max(1).default(0.3),\n})\n\nexport type FallOptions = z.infer<typeof fallOptionsSchema>\n\n/** A dropped sheet — corner lifted, rippling. Pair with the `tumble` idle for the descent. */\nexport const fall: Behavior<FallOptions> = {\n id: 'fall',\n label: 'Fall',\n defaults: fallOptionsSchema.parse({}),\n optionsSchema: fallOptionsSchema,\n signature: ['flutter', 'curl'],\n progressParam: 'flutter',\n duration: 3,\n loopMode: 'yoyo',\n stack(o) {\n return [\n {\n type: 'curl',\n options: { corner: 'top-right', amount: o.curl * 0.4, radius: 0.3, skew: 0 },\n },\n {\n type: 'wave',\n options: {\n amplitude: o.flutter * 0.055,\n wavelength: 0.85,\n speed: 1.3,\n angle: 60,\n pinnedEdge: 'none',\n },\n },\n ]\n },\n}\n","import { z } from 'zod'\nimport type { Behavior } from './types'\nimport { cornerNames } from '../deformers/curl'\n\nexport const carryOptionsSchema = z.object({\n /**\n * The grab point — where the pointer was on the paper at pick time.\n * 'auto' is resolved by the carry controller (usually the peeled corner:\n * continuity from peel → carry is the immersion moment).\n */\n grab: z.enum([...cornerNames, 'auto']).default('auto'),\n /** From stock feel: a stamp is stiff — it flutters, it doesn't flow. */\n stiffness: z.number().min(0).max(1).default(0.7),\n flutter: z.number().min(0).max(1).default(0.5),\n /** How far the paper's yaw trails the drag direction (runtime transform). */\n lag: z.number().min(0).max(1).default(0.35),\n /** Drag-speed drive (0..1). Written live by the carry controller. */\n drive: z.number().min(0).max(1).default(0.25),\n})\n\nexport type CarryOptions = z.infer<typeof carryOptionsSchema>\n\ntype Corner = (typeof cornerNames)[number]\n\nconst concreteGrab = (g: CarryOptions['grab']): Corner => (g === 'auto' ? 'top-left' : g)\n\n/** Bend-axis angle pointing from the grab corner toward the sheet center. */\nconst DROOP_ANGLE: Record<Corner, number> = {\n 'top-left': -45,\n 'top-right': -135,\n 'bottom-left': 45,\n 'bottom-right': 135,\n}\n\n/** The edge the grab corner hangs from — that edge doesn't flutter. */\nconst PIN_EDGE: Record<Corner, 'top' | 'bottom'> = {\n 'top-left': 'top',\n 'top-right': 'top',\n 'bottom-left': 'bottom',\n 'bottom-right': 'bottom',\n}\n\n/**\n * A held paper, alive from motion (spec M6 §4.1, the field/cheap path):\n * droop away from the grab point + drag-velocity flutter. The hero path —\n * cloth with a single pin following the cursor — is the existing\n * `physics: 'cloth'` grab; this behavior is what fields and exports run.\n */\nexport const carry: Behavior<CarryOptions> = {\n id: 'carry',\n label: 'Carry',\n defaults: carryOptionsSchema.parse({}),\n optionsSchema: carryOptionsSchema,\n signature: ['stiffness', 'flutter'],\n progressParam: 'drive',\n duration: 2.4,\n loopMode: 'yoyo',\n stack(o) {\n const grab = concreteGrab(o.grab)\n // Softer paper droops harder from the pinch; motion adds a touch more.\n const droop = (1 - o.stiffness) * 1.6 + o.drive * 0.35\n return [\n {\n type: 'bend',\n options: { curvature: -droop, angle: DROOP_ANGLE[grab] },\n },\n {\n type: 'wave',\n options: {\n amplitude: o.flutter * (0.012 + o.drive * 0.085),\n wavelength: 0.55,\n speed: 1.4 + o.drive * 1.8,\n angle: DROOP_ANGLE[grab],\n pinnedEdge: PIN_EDGE[grab],\n },\n },\n ]\n },\n}\n","/**\n * The shared fake-aerodynamics core (spec M6 §4): velocity-linked lift +\n * curated noise, per v0.2's \"reads more real than a true sim\" doctrine.\n * Pure math, no three.js, no allocation in the per-frame paths — `carry`\n * and `flight` both source their motion here.\n */\n\nexport interface AeroPose {\n position: [number, number, number]\n rotation: [number, number, number]\n}\n\n/**\n * Critically-damped spring toward a target — the carry pin's cursor\n * follow. Mutates `state` in place; returns nothing.\n */\nexport interface DampedValue {\n value: number\n velocity: number\n}\n\nexport function dampTo(state: DampedValue, target: number, smoothing: number, dt: number): void {\n // Critically damped: ω from smoothing (≈ time to close 90% of the gap).\n const omega = 2 / Math.max(smoothing, 1e-4)\n const x = omega * dt\n const exp = 1 / (1 + x + 0.48 * x * x + 0.235 * x * x * x)\n const change = state.value - target\n const temp = (state.velocity + omega * change) * dt\n state.velocity = (state.velocity - omega * temp) * exp\n state.value = target + (change + temp) * exp\n}\n\n/** Coherent gust factor in [1-g, 1+g] — curated, seeded, cheap. */\nexport function gust(t: number, seed: number, gustiness: number): number {\n const n =\n Math.sin(t * 1.7 + seed * 12.9898) * 0.6 +\n Math.sin(t * 0.53 + seed * 78.233) * 0.3 +\n Math.sin(t * 3.1 + seed * 3.7) * 0.1\n return 1 + n * gustiness\n}\n\nexport interface FlightParams {\n wind: [number, number, number]\n gustiness: number\n tumble: number\n path: 'drift' | 'loop'\n /** Exit the scene → re-enter the opposite side (drift only). */\n respawn: boolean\n /** Half-extent of the drift travel before respawn wraps it. */\n range: number\n}\n\n/**\n * Free paper on the wind: the falling-leaf tumble core + a directional wind\n * vector + lift, so paper travels ACROSS, not just down. A pure function of\n * time and phase — instancing-safe, deterministic, loopable.\n */\nexport function flightPose(t: number, o: FlightParams, phase: number, pose: AeroPose): void {\n const g = gust(t + phase * 7.3, phase, o.gustiness)\n const time = t + phase * 11.7\n\n if (o.path === 'loop') {\n // A seamless closed circuit: travel scaled by the wind vector.\n const s = Math.max(0.2, Math.hypot(o.wind[0], o.wind[1], o.wind[2]))\n const a = time * 0.35\n pose.position[0] = Math.sin(a) * o.range * 0.8 * Math.sign(o.wind[0] || 1)\n pose.position[1] = Math.sin(a * 2) * o.range * 0.18 * s\n pose.position[2] = Math.cos(a) * o.range * 0.35\n } else {\n // Drift: travel along the wind; respawn wraps the along-wind coordinate.\n const travel = time * 0.55 * g\n const wrap = (v: number, r: number) => (o.respawn ? ((((v + r) % (2 * r)) + 2 * r) % (2 * r)) - r : v)\n pose.position[0] = wrap(o.wind[0] * travel, o.range)\n pose.position[1] = wrap(o.wind[1] * travel, o.range * 0.6) + Math.sin(time * 1.3) * 0.08 * g\n pose.position[2] = wrap(o.wind[2] * travel, o.range)\n }\n\n // The falling-leaf tumble: see-saw pitch/roll with a lift bob, gust-scaled.\n pose.rotation[0] = Math.sin(time * 0.5 + 1) * 0.65 * o.tumble\n pose.rotation[1] = Math.sin(time * 0.23) * 0.4 * o.tumble\n pose.rotation[2] = Math.sin(time * 0.7) * 0.55 * o.tumble\n pose.position[1] += Math.sin(time * 1.4) * 0.06 * o.tumble * g\n}\n\n/**\n * Carry flutter drive: how much a held paper ripples for a given drag speed\n * (world units/s). Saturates — a violent drag doesn't tear the illusion.\n */\nexport function carryDrive(speed: number): number {\n return Math.min(1, speed * 0.55)\n}\n","import { z } from 'zod'\nimport type { Behavior } from './types'\nimport { flightPose } from '../physics/aero'\n\nexport const flightOptionsSchema = z.object({\n /** Directional wind vector — paper travels ACROSS the scene, not just down. */\n wind: z\n .tuple([z.number().min(-2).max(2), z.number().min(-2).max(2), z.number().min(-2).max(2)])\n .default([0.6, 0.08, 0]),\n gustiness: z.number().min(0).max(1).default(0.4),\n tumble: z.number().min(0).max(1).default(0.6),\n /** 'loop' is a seamless idle cycle; 'drift' travels along the wind. */\n path: z.enum(['drift', 'loop']).default('drift'),\n /** Drift only: exit the scene → re-enter the opposite side. */\n respawn: z.boolean().default(true),\n /** Half-extent of the travel before respawn wraps it. */\n range: z.number().min(0.5).max(12).default(3.5),\n})\n\nexport type FlightOptions = z.infer<typeof flightOptionsSchema>\n\n/**\n * Untethered paper carried across the scene on the wind (spec M6 §4.2) —\n * the falling-leaf tumble core + directional travel + lift. Transform +\n * deformer based, so it's instancing-safe: a `scatter` layout + `flight`\n * idle = papers blowing through a hero section.\n */\nexport const flight: Behavior<FlightOptions> = {\n id: 'flight',\n label: 'Flight',\n defaults: flightOptionsSchema.parse({}),\n optionsSchema: flightOptionsSchema,\n signature: ['gustiness', 'tumble', 'path'],\n progressParam: 'tumble',\n duration: 6,\n loopMode: 'yoyo',\n stack(o) {\n // The sheet itself arcs and ripples; travel/tumble live in `transform`.\n return [\n { type: 'bend', options: { curvature: 0.35 + o.tumble * 0.4, angle: 20 } },\n {\n type: 'wave',\n options: {\n amplitude: 0.02 + o.gustiness * 0.03,\n wavelength: 0.8,\n speed: 1.1 + o.gustiness,\n angle: 35,\n pinnedEdge: 'none',\n },\n },\n ]\n },\n transform(o, t, pose) {\n flightPose(t, o, 0, pose)\n },\n}\n","import { z } from 'zod'\nimport type { Behavior } from './types'\n\nexport const crumpleBehaviorOptionsSchema = z.object({\n /** 0 = flat sheet, 1 = crushed. */\n progress: z.number().min(0).max(1).default(0.55),\n /** Few big facets at 0, many small ones at 1. */\n coarseness: z.number().min(0).max(1).default(0.35),\n /** How far the sheet curls in on itself as it crushes. */\n ball: z.number().min(0).max(1).default(0.5),\n /** A different crush of the same paper. */\n seed: z.number().int().min(0).max(7).default(0),\n})\n\nexport type CrumpleBehaviorOptions = z.infer<typeof crumpleBehaviorOptionsSchema>\n\n/**\n * A sheet being screwed up in a fist.\n *\n * Two deformers, in this order for a reason: `crumple` reads the flat sheet\n * position to place its creases, so it has to run before anything that moves\n * the sheet around. Crush the paper, then curl the crushed paper — the other\n * way round would crease a curved sheet as if it were still flat.\n */\nexport const crumpleBehavior: Behavior<CrumpleBehaviorOptions> = {\n id: 'crumple',\n label: 'Crumple',\n defaults: crumpleBehaviorOptionsSchema.parse({}),\n optionsSchema: crumpleBehaviorOptionsSchema,\n signature: ['progress', 'ball', 'coarseness'],\n progressParam: 'progress',\n duration: 2.6,\n loopMode: 'yoyo',\n stack(o) {\n return [\n {\n type: 'crumple',\n options: {\n amount: o.progress,\n scale: 1.5 + o.coarseness * 4.5,\n pull: 0.5,\n seed: o.seed,\n },\n },\n // The sheet closing in on itself. Paper does not crush flat, and\n // without this the result reads as texture rather than as a ball.\n {\n type: 'bend',\n options: { curvature: o.progress * o.ball * 0.9, angle: 35 },\n },\n ]\n },\n}\n","import { z } from 'zod'\nimport type { Behavior } from './types'\n\nexport const settleOptionsSchema = z.object({\n /**\n * How long ago it landed, 0..1.\n *\n * 0 is the instant of arrival — still carrying the shape it fell in. 1 is\n * a sheet that has been lying there, where its own weight has flattened\n * out everything except what its stiffness refuses to give up.\n */\n relax: z.number().min(0).max(1).default(0.45),\n /**\n * How hard the paper resists lying flat, 0..1.\n *\n * This is the stock, not the pose: tissue surrenders completely, card\n * never does. It is the whole reason a settled sheet reads as PAPER and\n * not as a decal — at 0 the mesh is a rectangle painted on the floor.\n */\n lift: z.number().min(0).max(1).default(0.45),\n /** Which corner stayed up. */\n corner: z.enum(['top-left', 'top-right', 'bottom-left', 'bottom-right']).default('top-right'),\n /**\n * Slack across the middle — the low, long undulation of a sheet that is\n * touching a floor in two places and bridging between them.\n */\n slack: z.number().min(0).max(1).default(0.4),\n})\n\nexport type SettleOptions = z.infer<typeof settleOptionsSchema>\n\n/**\n * A sheet that has landed and relaxed.\n *\n * The library could drop paper (`fall`), fly it (`fly`, `flight`), heap it\n * (`pile`) and catch it mid-air (`spill`) — and had no way at all to show a\n * sheet that has ARRIVED. Every reference installation worth copying has\n * paper on the floor: sheets settled on concrete after the fall, ribbons\n * pooling where they meet the ground. It is the most beautiful detail in the\n * set and it appears in it twice.\n *\n * The distinction from `fall` is not the shape, it is the CLOCK. `fall`\n * flutters — its wave carries `speed: 1.3`, and it is a sheet still arguing\n * with the air. This one is over. Everything here is static, and that is the\n * point: a settled sheet that ripples is a settled sheet nobody believes.\n *\n * Which is also why it composes rather than deforming: a landed sheet is a\n * gentle curl the stiffness held on to, plus a long slack undulation where\n * it bridges the floor. Both already exist, and a deformer that can be\n * spelled out of the ones we have does not earn a GLSL twin and a parity\n * case.\n */\nexport const settle: Behavior<SettleOptions> = {\n id: 'settle',\n label: 'Settle',\n defaults: settleOptionsSchema.parse({}),\n optionsSchema: settleOptionsSchema,\n signature: ['relax', 'lift'],\n progressParam: 'relax',\n duration: 2.4,\n loopMode: 'yoyo',\n stack(o) {\n // Relaxing flattens the sheet, so `relax` SUBTRACTS. Stiffness is the\n // floor under it: however long it lies there, `lift` is what it will\n // never give back.\n const held = o.lift * (1 - o.relax * 0.55)\n return [\n {\n type: 'curl',\n options: {\n corner: o.corner,\n // A settled corner turns up gently and over a long distance. A\n // tight curl reads as a sheet being rolled, which is a hand doing\n // something to it rather than gravity having finished with it.\n // Calibrated against `fall`, which lifts a corner by `curl * 0.4`\n // — a settled sheet should keep MORE than a falling one, not less,\n // because the corner it is holding up is the one thing gravity\n // could not take from it. The first pass at 0.32 with a 0.5 radius\n // rendered a flat rectangle, which is the one outcome this\n // behavior exists to avoid.\n amount: held * 0.75,\n radius: 0.2 + (1 - held) * 0.14,\n // Off the diagonal, because a corner that lifts along its exact\n // diagonal reads as folded rather than as fallen.\n skew: 11,\n },\n },\n {\n type: 'wave',\n options: {\n amplitude: o.slack * (1 - o.relax * 0.4) * 0.085,\n // Long: one slow rise across the sheet, not a ripple. A settled\n // sheet touches the floor in a couple of places and bridges\n // between them, and that bridge is a single arc.\n wavelength: 1.6,\n // Static. This is the whole behavior.\n speed: 0,\n angle: 22,\n pinnedEdge: 'none',\n },\n },\n ]\n },\n}\n","import { z } from 'zod'\nimport type { Behavior } from './types'\n\nexport const ribbonOptionsSchema = z.object({\n /**\n * How much of the drop is lying on the floor, as a fraction of the height.\n *\n * This is the whole image. A strip that stops dead at the ground reads as\n * a strip that was cut to fit; one that arrives with a length to spare and\n * turns over reads as paper meeting a floor, which is the thing the\n * reference installations are actually about.\n */\n pool: z.number().min(0).max(0.5).default(0.16),\n /** How tightly it turns where it lands. Low is a soft slump, high is a curl. */\n curl: z.number().min(0).max(1).default(0.45),\n /** Folds running down the length. A printed strip is never a flat plane. */\n drape: z.number().min(0).max(1).default(0.5),\n})\n\nexport type RibbonOptions = z.infer<typeof ribbonOptionsSchema>\n\n/**\n * A strip hung from the ceiling that reaches the floor and keeps going.\n *\n * The single most striking image in the reference set, and the reason it\n * took until now to build is that it needs three separate things that did\n * not exist a week ago: a room with a ceiling to hang from, hardware to hang\n * BY, and type that can be set down the length of a sheet without looking\n * like a caption. It is the payoff for all of them.\n *\n * The mathematics is not new, which is the point of the contribution ladder.\n * A ribbon is a `drape` down its length and a `fold` whose hinge sits at the\n * floor line rather than at the sheet's centre — `fold.offset` has always\n * been able to say \"crease here\", and nothing had ever asked it to.\n */\nexport const ribbon: Behavior<RibbonOptions> = {\n id: 'ribbon',\n label: 'Ribbon',\n defaults: ribbonOptionsSchema.parse({}),\n optionsSchema: ribbonOptionsSchema,\n /**\n * `curl`, not `pool` — and the reason is tessellation rather than taste.\n *\n * The grid is sized by sampling this parameter from 0 to 1, so it has to\n * BE a 0..1 parameter (a `pool` that stops at 0.5 would be sampled across\n * a range it rejects), and it should be the one that drives the geometry\n * hardest. `curl` opens the crease from a right angle to a fold back on\n * itself, and the sharpest turn is exactly the case that demands the most\n * segments across the hinge.\n */\n signature: ['pool', 'curl', 'drape'],\n progressParam: 'curl',\n duration: 3,\n loopMode: 'yoyo',\n stack(o, sheet) {\n // Where the floor is, in the sheet's own coordinates — a `pool` fraction\n // above the bottom edge, so the length below that line is what turns\n // over. This is why the behavior needs the sheet at all, where most take\n // only their options.\n //\n // The hinge travels DOWNWARD (-90°), and that is not cosmetic: it is\n // what makes \"past the crease\" mean \"below the floor line\" rather than\n // \"above it\". Pointed the other way, the fold would have turned the\n // whole drop from the ceiling down.\n const floorLine = -sheet.height / 2 + sheet.height * o.pool\n\n // How soft the crease is. `curl` drives this rather than the fold angle\n // — see the fold below for why.\n const radius = Math.min(0.5, Math.max(0.02, sheet.height * (0.035 - o.curl * 0.027)))\n\n /**\n * The hinge does not turn on the spot: it wraps a cylinder of radius\n * `radius / φ`, and the flap leaves that cylinder lower than the crease\n * line by exactly that much.\n *\n * Which means placing the crease AT the floor buries the pool under it.\n * That is what was happening — the pooled length came out about 9cm\n * below the ground on the ribbon stage's own numbers, so the one thing\n * the stage exists to show was inside the floor. The crease goes up by\n * the hinge's own radius so that the POOL lands on the line, which is\n * the thing that has to be true; where the crease sits is arithmetic.\n */\n const hingeDrop = radius / (Math.PI / 2)\n\n return [\n {\n // `drape` — the deformer named after the thing this is.\n //\n // It briefly used `wave` instead, to work around a report that\n // `drape` rendered an invisible sheet on the hero path. That report\n // was wrong: it rested on counting the colours in a screenshot, and\n // a near-flat strip filling the frame has about as many colours as\n // an empty one. `deformers/draws.test.ts` now asserts on geometry\n // what the screenshot was being asked to guess at.\n //\n // `wave` was never the same picture. A wave is a sine of fixed\n // amplitude end to end, so its folds ran just as deep at the clip as\n // at the floor; a hung strip is FLAT where it is held and gathers as\n // it falls, which is exactly `falloff`, and it narrows as it gathers,\n // which is `gather`. Neither has an equivalent in `wave`.\n type: 'drape',\n options: {\n // Depth at the free end. Larger than the wave's amplitude was,\n // because this one starts at nothing under the clip rather than\n // running at full depth the whole way down.\n amplitude: o.drape * 0.1,\n // Few and long. A printed strip carries two or three slow folds\n // down its drop; more than that is a curtain, not a ribbon.\n folds: 2.5,\n // Holds the top flat and gathers the movement toward the floor,\n // which is what a strip hung from a single clip does.\n falloff: 1.5,\n // Off a pure sine, so the folds do not read as corrugation.\n irregular: 0.5,\n // Gentle. The pooled length has to lie FLAT on the floor, and a\n // hard pinch would narrow it as it went.\n gather: 0.22,\n pinnedEdge: 'top',\n },\n },\n {\n // `fold`, not `roll` — and this is the second correction the render\n // forced. A roll wraps the pooled length around a cylinder, so it\n // curls up and over and ends in the air: a hook, not a pool. Paper\n // meeting a floor does not wrap, it CREASES and then lies down.\n //\n // A hinge at the floor line with a soft radius is exactly that: the\n // drop above stays vertical, and everything below turns through\n // roughly a right angle and runs out flat along the ground.\n type: 'fold',\n options: {\n // Travel measured down the drop, so the crease line sits across\n // the ribbon and the flap below it is what turns.\n angle: -90,\n offset: -floorLine - hingeDrop,\n // Exactly a right angle, at every setting, and this is the fix\n // for the thing the ribbon stage was actually failing at.\n //\n // A hinge is one angle: whatever it turns through, the pooled\n // length leaves the crease in a straight line and holds that\n // heading. Only 90° is the floor. It shipped as `62 + curl * 46`\n // (62°..108°), so below curl 0.61 the pool went on travelling\n // downward and vanished THROUGH the floor — which is why the one\n // stage built around this behavior rendered as flat strips\n // stopping at the ground — and above it the pool tilted back UP\n // and floated. Both halves of the range were wrong, in opposite\n // directions, and only the midpoint was ever right.\n //\n // Paper with more length than floor does not rise at a constant\n // angle; it buckles and lies in an S, which one hinge cannot\n // describe and should not pretend to.\n foldAngle: 90,\n // So `curl` drives the CREASE instead, which is what its own\n // description always claimed — \"how tightly it turns where it\n // lands. Low is a soft slump, high is a curl.\" A soft radius is a\n // sheet slumping over the join; a tight one is a sheet that has\n // been creased. It scales with the sheet, because a radius that\n // reads as a fold on a short strip reads as a knife-edge on a long\n // one.\n radius,\n },\n },\n ]\n },\n}\n","import { z } from 'zod'\nimport { mergeConfig } from './merge'\nimport { peelOptionsSchema } from '../behaviors/peel'\nimport { unrollOptionsSchema } from '../behaviors/unroll'\nimport { flipOptionsSchema } from '../behaviors/flip'\nimport { letterFoldOptionsSchema } from '../behaviors/letter-fold'\nimport { hangOptionsSchema } from '../behaviors/hang'\nimport { flyOptionsSchema } from '../behaviors/fly'\nimport { fallOptionsSchema } from '../behaviors/fall'\nimport { carryOptionsSchema } from '../behaviors/carry'\nimport { flightOptionsSchema } from '../behaviors/flight'\nimport { crumpleBehaviorOptionsSchema } from '../behaviors/crumple'\nimport { settleOptionsSchema } from '../behaviors/settle'\nimport { ribbonOptionsSchema } from '../behaviors/ribbon'\n\n/**\n * The zod schema is the single source of truth: it validates the public API,\n * generates editor panels, defines the `.paper` preset format, and feeds the docs.\n * If a feature can't serialize into this schema, it waits.\n *\n * Every schema here exports BOTH of its types, and the difference is\n * load-bearing. `z.infer` is the parsed config — every default filled in,\n * every field present — and it is what the renderer reads. `z.input` is what\n * a caller is allowed to write, where anything with a default is optional,\n * and it is what every public prop must take. Handing a component the\n * inferred type instead demands that the caller supply every field of every\n * nested object, which turns the documented one-liner into a type error.\n */\n\n// ── Sheet ────────────────────────────────────────────────────────────────────\n\nexport const sheetSchema = z.object({\n /** World units. A letter sheet is ~1 × 1.4, a receipt ~1 × 2.6. */\n width: z.number().positive().max(20).default(1),\n height: z.number().positive().max(20).default(1.4),\n /** Visual thickness in mm-ish units; drives edge/shadow treatment, not geometry (yet). */\n thickness: z.number().min(0).max(2).default(0.2),\n /**\n * `'auto'` sizes the grid from the active deformers' needs — genuinely, as\n * of 0.3.0. It asks each one what these options require (a gentle bend and\n * a tight roll are not the same request), takes the densest answer, and\n * snaps it to a ladder so dragging a slider does not rebuild the mesh.\n *\n * It is capped at 72, which is what it used to hand out flat regardless of\n * what was on the sheet, so `'auto'` can only ever subdivide LESS than it\n * did before — a blank sheet drops from 72 a side to 8, and stops being\n * tessellated as finely as a crumpled one.\n *\n * Set a number to take the decision yourself; a deformer's `minSegments`\n * still raises it, because that is a correctness floor rather than a\n * preference.\n */\n segments: z.union([z.literal('auto'), z.number().int().min(2).max(256)]).default('auto'),\n cornerRadius: z.number().min(0).max(0.5).default(0),\n})\n\nexport type SheetConfig = z.infer<typeof sheetSchema>\n\n// ── Stock ────────────────────────────────────────────────────────────────────\n\nexport const stockNames = [\n 'printer',\n 'thermal',\n 'kraft',\n 'newsprint',\n 'vellum',\n 'photo-gloss',\n 'sticker',\n] as const\nexport const stockSchema = z.enum(stockNames)\nexport type StockName = z.infer<typeof stockSchema>\n\n// ── Content ──────────────────────────────────────────────────────────────────\n\nconst blankContentBase = z.object({\n type: z.literal('blank'),\n})\n\nconst imageContentBase = z.object({\n type: z.literal('image'),\n /**\n * Empty means \"no picture yet\", and renders as bare stock rather than as\n * a failure. That is what lets a built-in preset be an image preset\n * without shipping — or fetching — a photograph: `photo-print` and\n * `postage-stamp` are containers for the caller's own art, handed over via\n * `<PaperField images={...} />` or `content.src`.\n */\n src: z.string().default(''),\n fit: z.enum(['cover', 'contain']).default('cover'),\n /** Read by the hidden DOM mirror and the no-WebGL fallback. */\n alt: z.string().optional(),\n})\n\nconst textContentBase = z.object({\n type: z.literal('text'),\n text: z.string().default('Dear reader,'),\n font: z.string().default('Georgia, \"Times New Roman\", serif'),\n /** px at texture resolution (long edge = 1024 logical px before DPR). */\n size: z.number().min(8).max(256).default(44),\n weight: z.number().min(100).max(900).default(400),\n color: z.string().default('#2b2620'),\n align: z.enum(['left', 'center', 'right']).default('left'),\n /** Fraction of the short edge. */\n padding: z.number().min(0).max(0.4).default(0.09),\n lineHeight: z.number().min(0.8).max(3).default(1.45),\n /**\n * Letter-spacing, in em. The one control display type cannot do without:\n * a line set large enough to be read across a room needs its tracking\n * pulled IN, and a small line of uppercase small-print needs it pushed\n * out, and neither is achievable by changing the size.\n */\n tracking: z.number().min(-0.1).max(0.6).default(0),\n /**\n * Where the block sits down the sheet.\n *\n * `top` is the old behaviour and stays the default, because a letter\n * starts at the top of the page. `center` is what a card, a label or a\n * poster wants — a block of type optically centred in the sheet rather\n * than hung from its top edge.\n */\n valign: z.enum(['top', 'center']).default('top'),\n})\n\n/**\n * A card: the small stiff printed thing paper is most often cut into.\n *\n * One type covers the index card, the library due-date card, the museum\n * wall label, the telegram slip and the gallery quote sheet, because they\n * are the same object — a tracked label, a rule, a body, and a line of small\n * print — differing only in which parts are present.\n *\n * It exists because `text` could not make any of them. `text` sets a block\n * of prose in one size and one weight; every artifact above is a\n * COMPOSITION, with a hierarchy and a rule in it, and composing one out of\n * plain text meant hand-placing newlines and hoping.\n */\nconst cardContentBase = z.object({\n type: z.literal('card'),\n /** Small, tracked, uppercase by convention — the label at the top. */\n title: z.string().default(''),\n /** The card's reason for existing. */\n body: z.string().default(''),\n /** Attribution, catalogue number, date — the line in small print at the foot. */\n note: z.string().default(''),\n /** A hairline under the title. What separates a label from a paragraph. */\n rule: z.boolean().default(true),\n /**\n * Ruled writing lines behind the body, as on an index card.\n *\n * Drawn UNDER the type and in the stock's own ink at low alpha, so they\n * read as printed on the card rather than as underlines on the words.\n */\n ruled: z.boolean().default(false),\n font: z.string().default('Georgia, \"Times New Roman\", serif'),\n /**\n * Body size, px at texture resolution. Title and note derive from it.\n *\n * Set larger than the `text` default on purpose. A card is a small object\n * read close up, so its type is LARGE relative to the sheet; at the text\n * block's 42 the composition floated in the middle of the card with a\n * third of the stock empty above and below it, which reads as a page that\n * was cropped rather than as a card that was set.\n */\n size: z.number().min(8).max(256).default(58),\n color: z.string().default('#2b2620'),\n align: z.enum(['left', 'center']).default('left'),\n padding: z.number().min(0).max(0.4).default(0.1),\n})\n\nconst receiptContentBase = z.object({\n type: z.literal('receipt'),\n store: z.string().default('PAPERLAB'),\n address: z.string().default('124 PAPER ST'),\n items: z.array(z.object({ name: z.string(), price: z.number() })).default([\n { name: 'CURL, TRUE', price: 12 },\n { name: 'ROLL, TIGHT', price: 8.5 },\n { name: 'SHEET, ONE', price: 0.99 },\n ]),\n taxRate: z.number().min(0).max(1).default(0.08),\n barcode: z.boolean().default(true),\n /** Fixed so presets render deterministically; omit for \"now\". */\n timestamp: z.string().optional(),\n footer: z.string().default('KEEP FOR YOUR RECORDS'),\n})\n\n/** What can print on the reverse side (letter front / blank back, printed front / kraft back). */\nexport const backContentSchema = z.discriminatedUnion('type', [\n blankContentBase,\n imageContentBase,\n textContentBase,\n cardContentBase,\n receiptContentBase,\n])\n\nexport type BackContentConfig = z.infer<typeof backContentSchema>\n\nconst withBack = { back: backContentSchema.optional() }\n\nexport const blankContentSchema = blankContentBase.extend(withBack)\nexport const imageContentSchema = imageContentBase.extend(withBack)\nexport const textContentSchema = textContentBase.extend(withBack)\nexport const cardContentSchema = cardContentBase.extend(withBack)\nexport const receiptContentSchema = receiptContentBase.extend(withBack)\n\nexport const contentSchema = z.discriminatedUnion('type', [\n blankContentSchema,\n imageContentSchema,\n textContentSchema,\n cardContentSchema,\n receiptContentSchema,\n])\n\nexport type ContentConfig = z.infer<typeof contentSchema>\n/** What a caller may WRITE — defaults still unfilled. This is the prop type. */\nexport type ContentConfigInput = z.input<typeof contentSchema>\n\n// ── Surface ──────────────────────────────────────────────────────────────────\n\nexport const paperEdges = ['top', 'right', 'bottom', 'left'] as const\n\n/**\n * Fragment-side effects, composed in registration order into one shader\n * program. Stocks contribute defaults (thermal → banding + yellowing);\n * explicit surface config overrides per effect.\n */\nexport const surfaceSchema = z.object({\n /** Paper fiber noise, 0..1. */\n grain: z.number().min(0).max(1).optional(),\n /** Light passing through the sheet from behind, 0..1. Stock defaults apply. */\n translucency: z.number().min(0).max(1).optional(),\n /** Torn-edge alpha with a lightened fiber band. */\n deckle: z\n .object({\n edges: z.array(z.enum(paperEdges)).default(['bottom']),\n roughness: z.number().min(0).max(1).default(0.5),\n })\n .optional(),\n /** Visual AO/highlight companion to the fold deformer. */\n creaseLines: z\n .object({\n /** Crease line direction, degrees (0 = horizontal lines). */\n angle: z.number().min(-360).max(360).default(0),\n /** Positions across the sheet, 0..1 fractions. */\n positions: z.array(z.number().min(0).max(1)).default([1 / 3, 2 / 3]),\n strength: z.number().min(0).max(1).default(0.5),\n })\n .optional(),\n /** Yellowing + foxing spots, 0..1. */\n aging: z.number().min(0).max(1).optional(),\n /** Reversed front-content ghost on the backside, 0..1. Stock defaults apply. */\n showThrough: z.number().min(0).max(1).optional(),\n /**\n * Postage-stamp perforation: alpha-punched semicircular holes along chosen\n * edges. `state` flips an edge to a ripped-through profile (torn) — set\n * automatically when a paper detaches from a `sheet` field, manual wins.\n */\n perforation: z\n .object({\n edges: z.union([z.array(z.enum(paperEdges)), z.literal('all')]).default('all'),\n /** World units — default tuned to stamp scale. */\n holeRadius: z.number().min(0.002).max(0.1).default(0.016),\n spacing: z.number().min(0.01).max(0.5).default(0.055),\n state: z\n .object({\n top: z.enum(['intact', 'torn']).optional(),\n right: z.enum(['intact', 'torn']).optional(),\n bottom: z.enum(['intact', 'torn']).optional(),\n left: z.enum(['intact', 'torn']).optional(),\n })\n .default({}),\n })\n .optional(),\n})\n\nexport type SurfaceConfig = z.infer<typeof surfaceSchema>\nexport type SurfaceConfigInput = z.input<typeof surfaceSchema>\nexport type PaperEdge = (typeof paperEdges)[number]\n\n// ── Behavior & deformers ─────────────────────────────────────────────────────\n\nexport const behaviorConfigSchema = z.discriminatedUnion('type', [\n peelOptionsSchema.extend({ type: z.literal('peel') }),\n unrollOptionsSchema.extend({ type: z.literal('unroll') }),\n flipOptionsSchema.extend({ type: z.literal('flip') }),\n letterFoldOptionsSchema.extend({ type: z.literal('letter-fold') }),\n hangOptionsSchema.extend({ type: z.literal('hang') }),\n flyOptionsSchema.extend({ type: z.literal('fly') }),\n fallOptionsSchema.extend({ type: z.literal('fall') }),\n carryOptionsSchema.extend({ type: z.literal('carry') }),\n flightOptionsSchema.extend({ type: z.literal('flight') }),\n crumpleBehaviorOptionsSchema.extend({ type: z.literal('crumple') }),\n settleOptionsSchema.extend({ type: z.literal('settle') }),\n ribbonOptionsSchema.extend({ type: z.literal('ribbon') }),\n])\n\nexport type BehaviorConfig = z.infer<typeof behaviorConfigSchema>\nexport type BehaviorConfigInput = z.input<typeof behaviorConfigSchema>\n\n/** Advanced escape hatch: a raw deformer stack (editing one forks the behavior). */\nexport const deformerInstanceSchema = z.object({\n type: z.string(),\n options: z.record(z.unknown()).default({}),\n enabled: z.boolean().default(true),\n})\n\nexport type DeformerInstanceConfig = z.infer<typeof deformerInstanceSchema>\nexport type DeformerInstanceConfigInput = z.input<typeof deformerInstanceSchema>\n\n// ── Physics ──────────────────────────────────────────────────────────────────\n\n/** Kept in sync with `idleNames` in physics/idle.ts (asserted by test). */\nexport const physicsNames = ['none', 'float', 'tumble', 'dangle', 'taped', 'breeze'] as const\n\nexport const clothConfigSchema = z.object({\n type: z.literal('cloth'),\n pins: z.enum(['top-edge', 'top-corners', 'corner', 'none']).default('top-edge'),\n wind: z.number().min(0).max(1).default(0.3),\n /** Bend stiffness: 1 = crisp paper, 0 = silk. */\n stiffness: z.number().min(0).max(1).default(0.8),\n gravity: z.number().min(0).max(2).default(1),\n /** Local-space ground plane the sheet settles onto. */\n floor: z.number().min(-5).max(0).default(-1.4),\n})\n\nexport type ClothConfig = z.infer<typeof clothConfigSchema>\n\nexport const physicsSchema = z.union([\n z.enum(physicsNames),\n z.literal('cloth').transform(() => clothConfigSchema.parse({ type: 'cloth' })),\n clothConfigSchema,\n])\n\nexport type PhysicsConfig = z.infer<typeof physicsSchema>\nexport type PhysicsConfigInput = z.input<typeof physicsSchema>\n\n// ── Scene ────────────────────────────────────────────────────────────────────\n\nexport const lightingNames = [\n 'studio',\n 'window',\n 'leaves',\n 'goldenhour',\n 'noir',\n 'nave',\n 'raking',\n 'lightbox',\n] as const\n\n/**\n * The film the picture is printed on — the tone curve that maps unbounded\n * scene light onto a screen.\n *\n * This matters more here than in most 3D work because the subject is almost\n * white. A sheet of printer stock sits at `#fbfaf7`, and a lit one runs past\n * 1.0 constantly, so the whole image lives in the part of the curve where\n * tone mappers disagree most.\n *\n * - `neutral` — **the default.** Khronos PBR Neutral, built specifically to\n * preserve hue and saturation through the highlight roll-off. On a warm\n * backlit hall it is the only one of the three that keeps the light warm.\n * - `agx` — filmic, with a long, very graceful roll-off. It also desaturates\n * hard as it approaches white, which is a look; on a scene whose subject\n * IS warm light through paper it bleaches the thing you came for.\n * - `filmic` — ACES. High contrast, drifts bright neutrals toward\n * yellow-green, and washes out badly once a source is bright enough to\n * clip. This is what every preset was pinned to before.\n *\n * Measured on `nave` rather than argued: rendered through all three with the\n * source authored as a real HDR emitter, `neutral` holds the cream glow,\n * `agx` and `filmic` both bleach it to grey-white.\n */\nexport const filmNames = ['agx', 'neutral', 'filmic'] as const\n\n/** Scene-level presentation, serialized with the paper. */\nexport const sceneSchema = z.object({\n lighting: z.enum(lightingNames).default('studio'),\n})\n\nexport type SceneConfig = z.infer<typeof sceneSchema>\nexport type SceneConfigInput = z.input<typeof sceneSchema>\nexport type LightingName = (typeof lightingNames)[number]\nexport type FilmName = (typeof filmNames)[number]\n\n// ── Interaction states ───────────────────────────────────────────────────────\n\n/**\n * A state is a set of parameter overrides on the base preset — never a\n * separate preset. The base stays the single source of truth; states are\n * diffs. Triggers are fixed and built-in for v1 (pointer + pick/drop flow);\n * `custom:*` names are the escape hatch for editor v2.\n */\nexport const coreStateNames = ['rest', 'hover', 'pressed', 'picked', 'placed'] as const\nexport type CoreStateName = (typeof coreStateNames)[number]\nexport type StateName = CoreStateName | `custom:${string}`\n\nconst isStateName = (s: string): boolean =>\n (coreStateNames as readonly string[]).includes(s) || s.startsWith('custom:')\n\n// Typed as plain string (not the template-literal union) so PaperConfig stays\n// assignable to PaperConfigInput; the refine still enforces valid names.\nconst stateNameSchema = z.string().refine(isStateName, {\n message: `state names are ${coreStateNames.join(', ')} or \"custom:<name>\"`,\n})\n\nexport const stateTransitionSchema = z.object({\n duration: z.number().min(0).max(5).default(0.35),\n /** GSAP ease name. */\n ease: z.string().default('power2.out'),\n})\n\nexport const stateDefSchema = z.object({\n /** Deep-partial override of the paper schema (behavior params, surface, …). */\n overrides: z.record(z.unknown()).default({}),\n /** Transition INTO this state. */\n transition: stateTransitionSchema.default({}),\n /** Chained actions after arriving. v1: 'emit:<event>' only. */\n onEnter: z.array(z.string().regex(/^emit:[\\w-]+$/, 'v1 actions are \"emit:<event>\"')).default([]),\n})\n\nexport const paperStatesSchema = z.object({\n initial: stateNameSchema.default('rest'),\n states: z\n .record(z.string(), stateDefSchema)\n .default({})\n .refine((rec) => Object.keys(rec).every(isStateName), {\n message: `state names are ${coreStateNames.join(', ')} or \"custom:<name>\"`,\n }),\n /** World-units drag distance that flips pressed → picked (pick-enabled behaviors only). */\n pickThreshold: z.number().min(0.005).max(1).default(0.1),\n})\n\nexport type StateTransitionConfig = z.infer<typeof stateTransitionSchema>\nexport type StateDef = z.infer<typeof stateDefSchema>\nexport type PaperStates = z.infer<typeof paperStatesSchema>\nexport type PaperStatesInput = z.input<typeof paperStatesSchema>\n\n// ── Paper config ─────────────────────────────────────────────────────────────\n\nexport const metaSchema = z.object({\n name: z.string().default('untitled'),\n author: z.string().optional(),\n version: z.string().default('0'),\n tags: z.array(z.string()).default([]),\n})\n\nexport const paperConfigSchema = z\n .object({\n meta: metaSchema.default({}),\n sheet: sheetSchema.default({}),\n stock: stockSchema.default('printer'),\n content: contentSchema.default({ type: 'blank' }),\n /** A behavior OR a raw deformer stack — if both are present, `deformers` wins (it's the fork). */\n behavior: behaviorConfigSchema.optional(),\n deformers: z.array(deformerInstanceSchema).optional(),\n surface: surfaceSchema.default({}),\n physics: physicsSchema.default('none'),\n scene: sceneSchema.default({}),\n onTwos: z.boolean().default(false),\n /** Interaction state machine — overrides-on-base diffs (spec M6 §1). */\n states: paperStatesSchema.optional(),\n })\n .superRefine((config, ctx) => {\n // Cloth owns vertex positions: Shape (behavior/deformers) and Simulation\n // (cloth) are alternatives, not layers. Idle presets compose fine.\n if (typeof config.physics === 'object' && (config.behavior || config.deformers)) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: ['physics'],\n message:\n 'cloth physics and behavior/deformers are exclusive — cloth owns the vertices (pick Shape OR Simulation)',\n })\n }\n // State overrides must stay serializable schema paths: merging them over\n // the base must still parse. (`paperConfigSchema` is initialized by the\n // time any parse runs; the merged candidate carries no `states`, so this\n // cannot recurse.)\n if (config.states) {\n const { states: _states, ...baseSansStates } = config\n for (const [name, def] of Object.entries(config.states.states)) {\n if (!def) continue\n if ((def.overrides as Record<string, unknown>).states !== undefined) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: ['states', 'states', name, 'overrides'],\n message: 'state overrides cannot override `states` (no nested state machines)',\n })\n continue\n }\n const candidate = mergeConfig(baseSansStates as Record<string, unknown>, def.overrides)\n const result = paperConfigSchema.safeParse(candidate)\n if (!result.success) {\n const first = result.error.issues[0]\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: ['states', 'states', name, 'overrides'],\n message: `state \"${name}\" overrides don't validate against the paper schema: ${\n first ? `${first.path.join('.')} — ${first.message}` : 'invalid'\n }`,\n })\n }\n }\n }\n })\n\nexport type PaperConfig = z.infer<typeof paperConfigSchema>\nexport type PaperConfigInput = z.input<typeof paperConfigSchema>\n","import { paperConfigSchema, type PaperConfig, type PaperConfigInput } from './schema'\n\nexport { mergeConfig, mergeWithDeletes } from './merge'\n\n/** Parse anything preset-shaped (object or JSON string) into a full, defaulted config. */\nexport function parsePreset(input: PaperConfigInput | string): PaperConfig {\n const raw = typeof input === 'string' ? JSON.parse(input) : input\n return paperConfigSchema.parse(raw)\n}\n\n/** Serialize a config to `.paper` JSON. */\nexport function serializePreset(config: PaperConfig): string {\n return JSON.stringify(config, null, 2)\n}\n","import * as THREE from 'three'\nimport type { SheetConfig } from '../config/schema'\nimport { FLAT_SEGMENTS, LEGACY_FLAT_SEGMENTS, quantizeSegments, type SegmentPair } from './tessellation'\n\n/**\n * Resolve the subdivision grid for a sheet.\n *\n * `minSegments` is the correctness floor the active deformers require, and it\n * applies however `segments` is set. `autoSegments` is what those deformers\n * WANT for the options they are carrying, and it is what `'auto'` resolves\n * to — see `stackAutoSegments` and `core/tessellation.ts`.\n *\n * Both are per axis, because a demand is a demand along a DIRECTION. A\n * banner draped in folds across its width needs those folds resolved across\n * and needs almost nothing down its drop; a single number spread by aspect\n * ratio gives the drop the density and the folds the leftovers, which is\n * both the expensive answer and the wrong-looking one. A bare number is\n * still accepted and still means \"this many, both ways\".\n *\n * `'auto'` used to hand the long side a flat 72 whatever was on the sheet, so\n * a blank page was tessellated exactly as finely as a crumpled one and every\n * `minSegments` in the library was dead weight — nothing could ever raise a\n * grid that already started at the highest value anyone asked for. It now\n * sizes to the work, quantized onto a ladder so that dragging a slider does\n * not rebuild the mesh.\n *\n * Omitting `autoSegments` keeps the old flat 72, which is what a caller with\n * no deformer stack in hand should get — this helper is exported, and its\n * answer to an unchanged call should not have changed.\n */\nexport function resolveSegments(\n sheet: SheetConfig,\n minSegments: number | SegmentPair = 2,\n autoSegments: number | SegmentPair = LEGACY_FLAT_SEGMENTS,\n): [number, number] {\n // A bare floor is a floor both ways — it says nothing about direction.\n const [minX, minY] = typeof minSegments === 'number' ? [minSegments, minSegments] : minSegments\n if (sheet.segments !== 'auto') {\n return [Math.max(sheet.segments, minX, 2), Math.max(sheet.segments, minY, 2)]\n }\n // A bare TARGET is the old contract: one density for the long edge, spread\n // over the short one by aspect, snapped to the ladder once. Callers with a\n // stack in hand pass a pair instead, and each axis is then snapped on its\n // own — which is the point of asking per axis at all.\n const [wantX, wantY] =\n typeof autoSegments === 'number'\n ? spreadByAspect(sheet, quantizeSegments(Math.max(autoSegments, FLAT_SEGMENTS)))\n : [\n quantizeSegments(Math.max(wantOrFlat(autoSegments[0]), FLAT_SEGMENTS)),\n quantizeSegments(Math.max(wantOrFlat(autoSegments[1]), FLAT_SEGMENTS)),\n ]\n return [Math.max(wantX, minX, 2), Math.max(wantY, minY, 2)]\n}\n\nconst wantOrFlat = (n: number) => (Number.isFinite(n) ? n : FLAT_SEGMENTS)\n\nfunction spreadByAspect(sheet: SheetConfig, target: number): [number, number] {\n const long = Math.max(sheet.width, sheet.height)\n if (!(long > 0)) return [target, target]\n return [Math.round((sheet.width / long) * target), Math.round((sheet.height / long) * target)]\n}\n\n/**\n * Geometry factory. The sheet lives in its local XY plane, centered on the\n * origin, facing +Z. Deformers displace these vertices; the base (flat)\n * positions are kept by the caller for re-deformation each frame.\n */\nexport function createSheetGeometry(\n sheet: SheetConfig,\n minSegments: number | SegmentPair = 2,\n autoSegments: number | SegmentPair = LEGACY_FLAT_SEGMENTS,\n): THREE.PlaneGeometry {\n const [sx, sy] = resolveSegments(sheet, minSegments, autoSegments)\n return new THREE.PlaneGeometry(sheet.width, sheet.height, sx, sy)\n}\n","import type { StockName } from '../config/schema'\n\n/**\n * A stock is a named bundle of material + geometry defaults — choosing paper\n * at a print shop. Individual controls always override; schema-wise these are\n * just defaults.\n */\nexport interface Stock {\n id: StockName\n label: string\n /** Base tint, also used as the canvas background behind content. */\n color: string\n roughness: number\n /** 0 = opaque. Vellum is translucent. */\n opacity: number\n /**\n * How much light passes THROUGH the sheet when something is behind it,\n * 0..1. Distinct from `opacity`: newsprint is fully opaque to look at and\n * still glows on a lightbox. This is what makes a backlit banner read.\n */\n translucency: number\n /** Ink multiply tint for content drawn on this stock (thermal prints grey-black). */\n inkColor: string\n /** Thermal-printer banding intensity baked into the grain effect. */\n banding: number\n /** Surface effects this stock ships with; explicit surface config overrides per key. */\n defaultSurface: { grain?: number; aging?: number }\n /** Reversed front-content ghost on the backside (thin stocks let ink show). */\n showThrough: number\n /** Glossy near-white glue underside (stickers) — forces showThrough 0. */\n adhesive: boolean\n}\n\nexport const stocks: Record<StockName, Stock> = {\n printer: {\n id: 'printer',\n label: 'Printer',\n color: '#fbfaf7',\n roughness: 0.88,\n opacity: 1,\n translucency: 0.2,\n inkColor: '#222222',\n banding: 0,\n defaultSurface: { grain: 0.12 },\n showThrough: 0,\n adhesive: false,\n },\n thermal: {\n id: 'thermal',\n label: 'Thermal',\n color: '#f6f3e9',\n roughness: 0.62,\n opacity: 1,\n translucency: 0.34,\n inkColor: '#3a3a3a',\n banding: 0.35,\n defaultSurface: { aging: 0.1 },\n showThrough: 0.06,\n adhesive: false,\n },\n kraft: {\n id: 'kraft',\n label: 'Kraft',\n color: '#c9a06c',\n roughness: 0.96,\n opacity: 1,\n translucency: 0.08,\n inkColor: '#33261a',\n banding: 0,\n defaultSurface: { grain: 0.5 },\n showThrough: 0,\n adhesive: false,\n },\n newsprint: {\n id: 'newsprint',\n label: 'Newsprint',\n color: '#e9e4d6',\n roughness: 0.95,\n opacity: 1,\n translucency: 0.38,\n inkColor: '#3d3a34',\n banding: 0,\n defaultSurface: { grain: 0.7, aging: 0.15 },\n showThrough: 0.06,\n adhesive: false,\n },\n vellum: {\n id: 'vellum',\n label: 'Vellum',\n color: '#f4f2ec',\n roughness: 0.42,\n opacity: 0.62,\n translucency: 0.86,\n inkColor: '#4a453d',\n banding: 0,\n defaultSurface: {},\n showThrough: 0.55,\n adhesive: false,\n },\n 'photo-gloss': {\n id: 'photo-gloss',\n label: 'Photo gloss',\n color: '#ffffff',\n roughness: 0.22,\n opacity: 1,\n translucency: 0.03,\n inkColor: '#111111',\n banding: 0,\n defaultSurface: {},\n showThrough: 0,\n adhesive: false,\n },\n // Photo-gloss-like face, glossy near-white glue underside. The default\n // carrier for perforated stamp sheets.\n sticker: {\n id: 'sticker',\n label: 'Sticker',\n color: '#ffffff',\n roughness: 0.3,\n opacity: 1,\n translucency: 0.06,\n inkColor: '#1a1a1a',\n banding: 0,\n defaultSurface: {},\n showThrough: 0,\n adhesive: true,\n },\n}\n\nexport function getStock(name: StockName): Stock {\n return stocks[name]\n}\n","import { paperConfigSchema, type PaperConfig, type PaperConfigInput } from '../schema'\n\n/**\n * Built-in `.paper` presets. A preset is the serialized closure of one Paper —\n * the unit of saving, sharing, and code export. Stored as plain JSON-safe\n * objects, validated on access.\n */\nconst builtins: Record<string, PaperConfigInput> = {\n 'receipt-unroll': {\n meta: { name: 'Receipt unroll', tags: ['receipt', 'unroll', 'hero'] },\n sheet: { width: 1, height: 2.6 },\n stock: 'thermal',\n content: {\n type: 'receipt',\n store: 'nawwara.studio',\n address: '124 Paper St',\n items: [\n { name: 'Curl, true', price: 12 },\n { name: 'Roll, tight', price: 8.5 },\n { name: 'Sheet, one', price: 0.99 },\n ],\n timestamp: '11.07.2026 18:42',\n },\n behavior: { type: 'unroll', progress: 0.55, tightness: 0.55, sway: 0.3 },\n surface: { deckle: { edges: ['bottom'], roughness: 0.6 } },\n },\n 'letter-fold': {\n meta: { name: 'Letter fold', tags: ['fold', 'text'] },\n sheet: { width: 1, height: 1.4 },\n stock: 'printer',\n content: {\n type: 'text',\n text: 'Dear you,\\n\\nSome things are worth folding carefully.\\n\\nYours,\\nN.',\n },\n behavior: { type: 'letter-fold', progress: 0.4, crease: 0.3 },\n surface: { creaseLines: { angle: 0, positions: [1 / 3, 2 / 3], strength: 0.5 } },\n },\n 'vintage-note': {\n meta: { name: 'Vintage note', tags: ['aging', 'text'] },\n sheet: { width: 1.1, height: 1.4 },\n stock: 'newsprint',\n content: {\n type: 'text',\n text: 'FOUND, ONE PAPER ENGINE.\\n\\nReward if returned to the web.',\n font: 'Georgia, serif',\n size: 40,\n },\n behavior: { type: 'peel', progress: 0.18, corner: 'top-right', radius: 0.22 },\n surface: { aging: 0.55, grain: 0.6, deckle: { edges: ['top', 'bottom'], roughness: 0.4 } },\n },\n 'hero-peel': {\n meta: { name: 'Hero peel', tags: ['peel', 'card', 'hero'] },\n sheet: { width: 1.5, height: 1 },\n stock: 'photo-gloss',\n // Was a live Unsplash URL — a third-party network fetch inside one of\n // the first things anybody renders, which fails offline, behind a proxy,\n // under a strict CSP, and on the day the URL changes. The demo here is\n // the PEEL; the photograph was incidental, and a typeset card is both\n // self-contained and more on-brand for a paper library.\n content: {\n type: 'card',\n title: 'Print no. 4',\n body: 'Lift the corner.',\n note: 'Gloss, 240gsm',\n align: 'center',\n },\n behavior: { type: 'peel', progress: 0.35, corner: 'bottom-right', radius: 0.16 },\n },\n 'page-flip': {\n meta: { name: 'Page flip', tags: ['flip', 'text'] },\n sheet: { width: 1, height: 1.4 },\n stock: 'printer',\n content: {\n type: 'text',\n text: 'Chapter One\\n\\nIt was a paper town, and everything in it folded.',\n },\n behavior: { type: 'flip', progress: 0.3, spine: 'left', radius: 0.3 },\n },\n 'hanging-poster': {\n meta: { name: 'Hanging poster', tags: ['hang', 'text', 'wind'] },\n sheet: { width: 1.1, height: 1.55 },\n stock: 'printer',\n // Also de-Unsplashed. A poster is a typographic object anyway — every\n // paper installation worth the name hangs WORDS — so this shows off the\n // tracking and the optical centring rather than someone else's photo.\n content: {\n type: 'text',\n text: 'THE\\nPAPER\\nSHOW',\n size: 96,\n align: 'center',\n valign: 'center',\n tracking: 0.08,\n lineHeight: 1.15,\n },\n behavior: { type: 'hang', wind: 0.45, sag: 0.3 },\n },\n 'pinned-sheet': {\n meta: { name: 'Pinned sheet', tags: ['cloth', 'wind', 'interactive'] },\n sheet: { width: 1.2, height: 1.5 },\n stock: 'printer',\n content: {\n type: 'text',\n text: 'Grab me.\\n\\n(cloth: pinned at the top edge,\\nwind from the left)',\n size: 40,\n },\n physics: { type: 'cloth', pins: 'top-edge', wind: 0.45, stiffness: 0.8, gravity: 1, floor: -1.4 },\n },\n 'flying-note': {\n meta: { name: 'Flying note', tags: ['fly', 'tumble', 'text'] },\n sheet: { width: 1, height: 0.7 },\n stock: 'printer',\n content: {\n type: 'text',\n text: 'meet me where\\nthe paper lands',\n size: 52,\n align: 'center',\n padding: 0.16,\n },\n behavior: { type: 'fly', flutter: 0.55, curve: 0.45 },\n physics: 'tumble',\n },\n 'blank-sheet': {\n meta: { name: 'Blank sheet', tags: ['starter'] },\n stock: 'printer',\n },\n // The M6 driving use case: one stamp of the 2×5 block. Hover peels the\n // outward-facing corner ('auto' resolves per sheet slot), pressing deepens\n // the peel; the perforation tears when it detaches (field auto-wiring).\n 'postage-stamp': {\n meta: { name: 'Postage stamp', tags: ['sticker', 'stamp', 'states', 'sheet'] },\n sheet: { width: 0.64, height: 0.78, thickness: 0.08 },\n stock: 'sticker',\n // No `src`: a stamp's art is the caller's, and the library ships no\n // assets and fetches none. The perforation, the sticker stock and the\n // peel — which is what this preset is actually here to demonstrate —\n // all read perfectly well on bare stock.\n content: { type: 'image', fit: 'cover', alt: 'A postage stamp' },\n behavior: { type: 'peel', progress: 0, corner: 'auto', radius: 0.12 },\n surface: { perforation: { edges: 'all', holeRadius: 0.014, spacing: 0.05 } },\n states: {\n initial: 'rest',\n states: {\n hover: {\n overrides: { behavior: { progress: 0.22 } },\n transition: { duration: 0.25, ease: 'power2.out' },\n },\n pressed: {\n overrides: { behavior: { progress: 0.5 } },\n transition: { duration: 0.16, ease: 'power3.out' },\n },\n // Picked is auto-choreographed at pick time (carry hanging from the\n // peeled corner); placed announces itself for a host postmark overlay.\n placed: { overrides: {}, onEnter: ['emit:postmark'] },\n },\n pickThreshold: 0.08,\n },\n },\n 'photo-print': {\n meta: { name: 'Photo print', tags: ['image', 'starter'] },\n sheet: { width: 1.2, height: 0.9 },\n stock: 'photo-gloss',\n // Same: the field starter is a CONTAINER. Its whole documented use is\n // `<PaperField images={photos} preset=\"photo-print\" />`, where the\n // photographs are the caller's.\n content: { type: 'image', fit: 'cover', alt: 'A photographic print' },\n // No print lies perfectly flat. A shade of bow is the whole difference\n // between a sheet of paper and a rectangle — and since this is the field\n // starter, it is what a layout's per-sheet bias has to scale.\n deformers: [{ type: 'bend', options: { curvature: 0.35, angle: 0 } }],\n },\n 'crumpled-note': {\n meta: { name: 'Crumpled note', tags: ['crumple', 'text', 'handled'] },\n sheet: { width: 1.1, height: 1.4 },\n stock: 'printer',\n content: {\n type: 'text',\n text: 'I wrote it out three times\\nand threw all three away.',\n size: 42,\n },\n behavior: { type: 'crumple', progress: 0.62, coarseness: 0.4, ball: 0.55 },\n // Handled paper is dirty paper: the grain is what stops the facets\n // reading as folded plastic.\n surface: { grain: 0.5, aging: 0.18 },\n },\n /**\n * The second after the fall. `fall` is a sheet still arguing with the air;\n * this one has stopped — which is the half of the story the library could\n * not tell, and the half every paper installation is actually made of.\n */\n /**\n * A strip hung the full drop of a room. Tall and narrow on purpose: the\n * proportion IS the object, and a ribbon that is not much longer than it\n * is wide is a poster.\n */\n 'paper-ribbon': {\n meta: { name: 'Paper ribbon', tags: ['ribbon', 'hang', 'text'] },\n sheet: { width: 0.85, height: 6.4 },\n stock: 'printer',\n content: {\n type: 'text',\n // Short words, set small. The measure on a 0.85-wide strip is about\n // 220px at texture resolution, and anything larger breaks mid-word —\n // a ribbon reading \"an d th e pa pe r\" is a ribbon nobody can read.\n text: 'the paper\\nkept going\\nlong after\\nthe floor\\nran out',\n size: 34,\n align: 'center',\n valign: 'center',\n lineHeight: 1.5,\n tracking: 0.02,\n },\n behavior: { type: 'ribbon', pool: 0.17, curl: 0.42, drape: 0.55 },\n surface: { grain: 0.18 },\n },\n 'settled-sheet': {\n meta: { name: 'Settled sheet', tags: ['settle', 'floor', 'text'] },\n sheet: { width: 1.2, height: 0.9 },\n stock: 'printer',\n content: {\n type: 'card',\n title: 'Found',\n body: 'on the floor, face up,\\nwhere somebody dropped it.',\n note: 'no. 31',\n },\n behavior: { type: 'settle', relax: 0.6, lift: 0.5, slack: 0.45 },\n surface: { grain: 0.2 },\n },\n 'typed-note': {\n meta: { name: 'Typed note', tags: ['text', 'starter'] },\n sheet: { width: 1, height: 1.4 },\n stock: 'printer',\n content: {\n type: 'text',\n text: 'Dear reader,\\n\\nPaper is the product. Everything else hangs off the sheet.\\n\\n— Paperlab',\n },\n },\n}\n\n/** User presets registered at runtime (the editor persists these to localStorage). */\nconst userPresets = new Map<string, PaperConfigInput>()\n\nexport function getPreset(name: string): PaperConfig {\n const raw = builtins[name] ?? userPresets.get(name)\n if (!raw) {\n throw new Error(`[paperlab] Unknown preset \"${name}\". Registered: ${listPresets().join(', ')}`)\n }\n return paperConfigSchema.parse(raw)\n}\n\n/** Register a user preset (validated). Built-in names are reserved. */\nexport function registerPreset(name: string, input: PaperConfigInput): void {\n if (name in builtins) {\n throw new Error(`[paperlab] \"${name}\" is a built-in preset — pick another name.`)\n }\n paperConfigSchema.parse(input) // fail fast on invalid configs\n userPresets.set(name, input)\n}\n\nexport function unregisterPreset(name: string): void {\n userPresets.delete(name)\n}\n\nexport function isBuiltinPreset(name: string): boolean {\n return name in builtins\n}\n\nexport function listPresets(): string[] {\n return [...Object.keys(builtins), ...userPresets.keys()]\n}\n\n/**\n * A collision-free preset name built from `base`: `base`, else `base 2`,\n * `base 3`, … The disambiguating suffix always grows from the SAME base — a\n * name derived from a synthetic base (e.g. an untitled import → \"imported\")\n * must not fall back to the original when it collides. `taken` reports whether\n * a candidate is already used (built-in or user preset).\n */\nexport function uniquePresetName(base: string, taken: (name: string) => boolean): string {\n if (!taken(base)) return base\n let n = 2\n let name = `${base} ${n}`\n while (taken(name)) name = `${base} ${++n}`\n return name\n}\n","import type { ContentConfig } from '../config/schema'\nimport type { Stock } from '../core/stock'\n\nexport type ReceiptContent = Extract<ContentConfig, { type: 'receipt' }>\n\nexport interface ReceiptTotals {\n subtotal: number\n tax: number\n total: number\n}\n\nexport function receiptTotals(content: ReceiptContent): ReceiptTotals {\n const subtotal = content.items.reduce((sum, item) => sum + item.price, 0)\n const tax = subtotal * content.taxRate\n return { subtotal, tax, total: subtotal + tax }\n}\n\n/** Deterministic bar widths from a string — stylized Code-128 look. */\nexport function barcodeBars(seed: string): number[] {\n // Not a scannable Code 128 (real encoding tracked for later) — but the\n // start/stop guard structure and 1–4 module widths match the real thing.\n let h = 2166136261\n for (let i = 0; i < seed.length; i++) {\n h ^= seed.charCodeAt(i)\n h = Math.imul(h, 16777619)\n }\n const bars: number[] = [2, 1, 1, 4] // start guard\n for (let i = 0; i < 30; i++) {\n h = Math.imul(h ^ (h >>> 15), 2246822519)\n bars.push(1 + (Math.abs(h) % 4))\n }\n bars.push(2, 3, 3, 1, 1, 2) // stop guard\n return bars\n}\n\nconst money = (v: number) => v.toFixed(2)\n\n/**\n * The procedural receipt: store header, line items, totals, barcode,\n * timestamp, footer. Pairs with `deckle: { edges: ['bottom'] }` for the\n * jagged thermal tear. One-liner meme potential by design.\n */\nexport function paintReceipt(\n ctx: CanvasRenderingContext2D,\n w: number,\n h: number,\n content: ReceiptContent,\n stock: Stock,\n): void {\n const ink = stock.inkColor\n const pad = w * 0.09\n const colWidth = w - pad * 2\n const base = Math.round(w / 15) // font size scales with receipt width\n const mono = (size: number, weight = 400) => `${weight} ${size}px ui-monospace, Menlo, Consolas, monospace`\n\n let y = h * 0.045\n const line = (step = 1.6) => (y += base * step)\n\n const center = (text: string, size = base, weight = 400) => {\n ctx.font = mono(size, weight)\n ctx.textAlign = 'center'\n ctx.fillText(text, w / 2, y)\n }\n const row = (left: string, right: string, size = base) => {\n ctx.font = mono(size)\n ctx.textAlign = 'left'\n ctx.fillText(left, pad, y)\n ctx.textAlign = 'right'\n ctx.fillText(right, w - pad, y)\n }\n const divider = () => {\n ctx.font = mono(base)\n ctx.textAlign = 'center'\n ctx.fillText('- '.repeat(Math.floor(colWidth / (base * 1.1))).trim(), w / 2, y)\n }\n\n ctx.fillStyle = ink\n ctx.textBaseline = 'top'\n\n center(content.store.toUpperCase(), base * 1.5, 700)\n line(2.4)\n center(content.address.toUpperCase())\n line(1.8)\n divider()\n line(1.8)\n\n for (const item of content.items) {\n row(item.name.toUpperCase(), money(item.price))\n line()\n }\n line(0.4)\n divider()\n line(1.8)\n\n const totals = receiptTotals(content)\n row('SUBTOTAL', money(totals.subtotal))\n line()\n row(`TAX ${(content.taxRate * 100).toFixed(0)}%`, money(totals.tax))\n line()\n row('TOTAL', money(totals.total), base * 1.15)\n line(2)\n\n center(content.timestamp ?? new Date().toLocaleString('en-GB'), base * 0.9)\n line(2.2)\n\n if (content.barcode) {\n const bars = barcodeBars(content.store)\n const modules = bars.reduce((a, b) => a + b, 0)\n const module = (colWidth * 0.85) / modules\n const barH = base * 3.2\n let x = (w - modules * module) / 2\n bars.forEach((width, i) => {\n if (i % 2 === 0) ctx.fillRect(x, y, width * module, barH)\n x += width * module\n })\n y += barH\n line(1.8)\n }\n\n center(content.footer.toUpperCase(), base * 0.9)\n}\n","/**\n * Line breaking, shared by every content type that sets prose.\n *\n * It lives on its own because `paintText` and `paintCard` were about to\n * carry two copies of it, and two copies of a line-breaker is two answers to\n * \"where does this wrap\" — which on a sheet that CURLS is not a cosmetic\n * disagreement: the reader sees the break land on a fold.\n */\n\n/**\n * Wrap a paragraph to a measure, breaking a word that cannot fit on its own.\n *\n * The last clause is the part the old loop got wrong. It appended a word\n * whenever the line was empty, on the reasonable theory that one word always\n * fits — but a long URL or a compound on a narrow banner does not, and it\n * ran off the edge of the sheet with nothing to stop it. A sheet is a\n * physical object: type that leaves it has left it.\n */\nexport function wrapLines(\n ctx: CanvasRenderingContext2D,\n text: string,\n maxWidth: number,\n font: string,\n): string[] {\n const previous = ctx.font\n ctx.font = font\n const out: string[] = []\n\n for (const paragraph of text.split('\\n')) {\n if (paragraph.trim() === '') {\n // An empty line is a paragraph break, and it should survive as one.\n out.push('')\n continue\n }\n let line = ''\n for (const word of paragraph.split(/\\s+/).filter(Boolean)) {\n const attempt = line ? `${line} ${word}` : word\n if (line && ctx.measureText(attempt).width > maxWidth) {\n out.push(line)\n line = word\n } else {\n line = attempt\n }\n // The word itself is wider than the measure: break it rather than\n // let it hang off the sheet.\n while (ctx.measureText(line).width > maxWidth && line.length > 1) {\n let cut = line.length - 1\n while (cut > 1 && ctx.measureText(line.slice(0, cut)).width > maxWidth) cut--\n out.push(line.slice(0, cut))\n line = line.slice(cut)\n }\n }\n if (line) out.push(line)\n }\n\n ctx.font = previous\n return out\n}\n\n/**\n * Ask the browser to actually load the face before painting with it.\n *\n * `document.fonts.ready` — which this library already awaited — resolves\n * when the fonts the DOCUMENT has requested have settled. A face named only\n * inside a canvas `ctx.font` string was never requested by anything, so on a\n * page where no DOM element uses it `ready` resolves immediately and the\n * canvas paints in the fallback. The sheet then renders in Times while the\n * preset says Playfair, silently and only sometimes, which is the worst\n * shape a bug can have.\n *\n * `fonts.load()` is the request. Failures are swallowed on purpose: a font\n * that will not load is a fallback, not an exception, and a sheet that\n * refuses to render is worse than one set in the wrong face.\n */\nexport async function ensureFont(font: string, size: number): Promise<void> {\n if (typeof document === 'undefined' || !document.fonts) return\n try {\n await document.fonts.load(`${size}px ${font}`)\n } catch {\n // Unparseable family list, or a face the browser will not fetch.\n }\n try {\n await document.fonts.ready\n } catch {\n // Ignored for the same reason.\n }\n}\n","import { z } from 'zod'\nimport type { Deformer } from './types'\nimport { segmentsForArc, spanAlong } from '../core/tessellation'\n\nexport const rollOptionsSchema = z.object({\n /** Direction of rolling in the sheet plane, degrees. 0 = +x, 90 = +y. */\n angle: z.number().min(-360).max(360).default(90),\n /** Signed distance (along the roll direction, from sheet center) where the roll begins. */\n boundary: z.number().min(-20).max(20).default(0),\n /** Cylinder radius — sharpness of the roll. */\n radius: z.number().min(0.01).max(2).default(0.12),\n /** Radius growth per radian so multi-turn rolls spiral instead of z-fighting. */\n spiral: z.number().min(0).max(0.2).default(0.015),\n})\n\nexport type RollOptions = z.infer<typeof rollOptionsSchema>\n\nconst DEG = Math.PI / 180\n\n/**\n * Wrap the sheet around a virtual cylinder lying across the roll direction.\n * Everything past `boundary` wraps; the wrap is C¹-continuous at the\n * boundary and preserves arc length (content never stretches).\n *\n * Points arriving with z ≠ 0 (from earlier deformers in the stack) ride\n * along the rolled surface's normal, so stacks compose sanely.\n */\nexport const roll: Deformer<RollOptions> = {\n id: 'roll',\n label: 'Roll',\n defaults: rollOptionsSchema.parse({}),\n optionsSchema: rollOptionsSchema,\n geometry: {\n minSegments: 48,\n // The winding radius is the tightest curvature on the sheet — `spiral`\n // only grows it as the roll winds outward, so the first turn is the one\n // that sets the density.\n autoSegments: (o, sheet) => segmentsForArc(spanAlong(sheet, o.angle), o.radius),\n axis: (o) => o.angle,\n },\n displace(out, _uv, o) {\n const dirX = Math.cos(o.angle * DEG)\n const dirY = Math.sin(o.angle * DEG)\n const d = out.x * dirX + out.y * dirY\n const s = d - o.boundary\n if (s <= 0) return\n\n const theta = s / o.radius\n const r = o.radius + o.spiral * theta\n const sin = Math.sin(theta)\n const cos = Math.cos(theta)\n // Surface point on the cylinder + incoming z offset along the surface normal.\n const newD = o.boundary + (r - out.z) * sin\n const newZ = r * (1 - cos) + out.z * cos\n\n out.x += dirX * (newD - d)\n out.y += dirY * (newD - d)\n out.z = newZ\n },\n glsl: {\n chunk: /* glsl */ `\nvoid FN(inout vec3 p, vec2 uv, float t) {\n vec2 dir = vec2(cos(U_angle), sin(U_angle));\n float d = dot(p.xy, dir);\n float s = d - U_boundary;\n if (s <= 0.0) return;\n float theta = s / U_radius;\n float r = U_radius + U_spiral * theta;\n float sn = sin(theta);\n float cs = cos(theta);\n float newD = U_boundary + (r - p.z) * sn;\n float newZ = r * (1.0 - cs) + p.z * cs;\n p.xy += dir * (newD - d);\n p.z = newZ;\n}\n`,\n uniforms: (o) => ({\n angle: o.angle * DEG,\n boundary: o.boundary,\n radius: o.radius,\n spiral: o.spiral,\n }),\n },\n}\n","import { z } from 'zod'\nimport type { Deformer } from './types'\nimport { segmentsForArc, spanAlong } from '../core/tessellation'\n\nexport const bendOptionsSchema = z.object({\n /** 1/radius in world units; sign flips the arc direction. 0 = flat. */\n curvature: z.number().min(-4).max(4).default(0.6),\n /** Bend axis direction in the sheet plane, degrees. 0 bends across x. */\n angle: z.number().min(-360).max(360).default(0),\n})\n\nexport type BendOptions = z.infer<typeof bendOptionsSchema>\n\nconst DEG = Math.PI / 180\nconst EPS = 1e-5\n\n/**\n * `sin(x) − x`, without the cancellation that eats it for small x.\n *\n * The arc's in-plane shift is `r·sin θ − d`, and `d` IS `r·θ` — so for a\n * gentle bend it is a difference of two nearly-equal large numbers, and the\n * answer is the few bits that survive. JS computes that in float64 and gets\n * away with it; the GLSL twin computes it in float32 and does not, which put\n * the two paths 6e-4 apart at low curvature — past the parity gate's epsilon.\n * The series is exact to well under a float32 ulp below |x| = 1 and both\n * implementations take the same branch, so the two paths agree by\n * construction rather than by luck.\n */\nfunction sinMinusX(x: number): number {\n if (Math.abs(x) > 1) return Math.sin(x) - x\n const x2 = x * x\n return ((-x * x2) / 6) * (1 - (x2 / 20) * (1 - (x2 / 42) * (1 - x2 / 72)))\n}\n\n/**\n * Gentle global arc around a cylinder centered on the sheet — a standing\n * paper's lean. Arc-length preserving, like roll, but symmetric about the\n * center instead of one-sided.\n *\n * Written in its cancellation-free form throughout: `r(1 − cos θ)` is\n * `2r·sin²(θ/2)`, and the in-plane shift goes through `sinMinusX`. Same arc,\n * same numbers to sixteen places — it is only the float32 half that could\n * tell the difference, and that is exactly the half the parity gate checks.\n */\nexport const bend: Deformer<BendOptions> = {\n id: 'bend',\n label: 'Bend',\n defaults: bendOptionsSchema.parse({}),\n optionsSchema: bendOptionsSchema,\n geometry: {\n minSegments: 16,\n // A pure circular arc of radius 1/curvature, so the sagitta form answers\n // this exactly. This is the deformer the old flat 72 over-served most:\n // at the default 0.6 it wants 24, and the field starter preset is a bend.\n autoSegments: (o, sheet) => segmentsForArc(spanAlong(sheet, o.angle), 1 / Math.abs(o.curvature)),\n axis: (o) => o.angle,\n },\n displace(out, _uv, o) {\n if (Math.abs(o.curvature) < EPS) return\n const dirX = Math.cos(o.angle * DEG)\n const dirY = Math.sin(o.angle * DEG)\n const d = out.x * dirX + out.y * dirY\n\n const r = 1 / o.curvature\n const theta = d * o.curvature\n const sin = Math.sin(theta)\n const halfSin = Math.sin(theta * 0.5)\n const z0 = out.z\n\n // (r − z)·sin θ − d, with d = r·θ folded in so the big terms never meet.\n const shift = r * sinMinusX(theta) - z0 * sin\n out.x += dirX * shift\n out.y += dirY * shift\n out.z = 2 * r * halfSin * halfSin + z0 * Math.cos(theta)\n },\n glsl: {\n chunk: /* glsl */ `\nfloat FN_sinm(float x) {\n if (abs(x) > 1.0) return sin(x) - x;\n float x2 = x * x;\n return (-x * x2 / 6.0) * (1.0 - (x2 / 20.0) * (1.0 - (x2 / 42.0) * (1.0 - x2 / 72.0)));\n}\n\nvoid FN(inout vec3 p, vec2 uv, float t) {\n if (abs(U_curvature) < 1e-5) return;\n vec2 dir = vec2(cos(U_angle), sin(U_angle));\n float d = dot(p.xy, dir);\n float r = 1.0 / U_curvature;\n float theta = d * U_curvature;\n float sn = sin(theta);\n float hs = sin(theta * 0.5);\n float z0 = p.z;\n float shift = r * FN_sinm(theta) - z0 * sn;\n p.xy += dir * shift;\n p.z = 2.0 * r * hs * hs + z0 * cos(theta);\n}\n`,\n strength: 'curvature',\n uniforms: (o) => ({ curvature: o.curvature, angle: o.angle * DEG }),\n },\n}\n","import { z } from 'zod'\nimport type { Deformer } from './types'\nimport { segmentsForArc, spanAlong } from '../core/tessellation'\n\nexport const foldOptionsSchema = z.object({\n /** Direction of the fold travel in the sheet plane, degrees (the crease line runs perpendicular). */\n angle: z.number().min(-360).max(360).default(90),\n /** Signed distance of the crease line from the sheet center, along the travel direction. */\n offset: z.number().min(-20).max(20).default(0),\n /** How far the flap folds over, degrees. 180 = flat against the sheet. */\n foldAngle: z.number().min(-180).max(180).default(90),\n /** Width of the soft hinge — paper never creases to a mathematical edge. */\n radius: z.number().min(0.005).max(0.5).default(0.04),\n})\n\nexport type FoldOptions = z.infer<typeof foldOptionsSchema>\n\nconst DEG = Math.PI / 180\n\n/**\n * Angular crease across a line: within the hinge width the sheet wraps a\n * small cylinder (a roll), beyond it the flap continues rigid at the full\n * fold angle. n folds = n instances stacked (half-fold, letter-fold,\n * accordion). Arc-length preserving like every Paperlab deformer.\n */\nexport const fold: Deformer<FoldOptions> = {\n id: 'fold',\n label: 'Fold',\n defaults: foldOptionsSchema.parse({}),\n optionsSchema: foldOptionsSchema,\n geometry: {\n minSegments: 48,\n // The fillet is an arc of `radius`; everything either side of it is flat.\n // The crease is small, but the grid is uniform, so the density it needs\n // is the density the whole sheet gets.\n autoSegments: (o, sheet) => segmentsForArc(spanAlong(sheet, o.angle), o.radius),\n axis: (o) => o.angle,\n },\n displace(out, _uv, o) {\n const phi = o.foldAngle * DEG\n if (Math.abs(phi) < 1e-6) return\n const dirX = Math.cos(o.angle * DEG)\n const dirY = Math.sin(o.angle * DEG)\n const d = out.x * dirX + out.y * dirY\n const s = d - o.offset\n if (s <= 0) return\n\n // Signed hinge cylinder: radius R = radius/phi carries the fold\n // direction, so one code path serves folds up and down.\n const R = o.radius / phi\n let newD: number\n let newZ: number\n if (s <= o.radius) {\n // Inside the hinge: identical to a roll of signed radius R.\n const theta = (s / o.radius) * phi\n const sin = Math.sin(theta)\n const cos = Math.cos(theta)\n newD = o.offset + (R - out.z) * sin\n newZ = R * (1 - cos) + out.z * cos\n } else {\n // Past the hinge: rigid flap continuing from the arc's end along its\n // tangent; incoming z rides the rotated surface normal.\n const rest = s - o.radius\n const sin = Math.sin(phi)\n const cos = Math.cos(phi)\n newD = o.offset + R * sin + rest * cos - out.z * sin\n newZ = R * (1 - cos) + rest * sin + out.z * cos\n }\n\n out.x += dirX * (newD - d)\n out.y += dirY * (newD - d)\n out.z = newZ\n },\n glsl: {\n chunk: /* glsl */ `\nvoid FN(inout vec3 p, vec2 uv, float t) {\n if (abs(U_foldAngle) < 1e-6) return;\n vec2 dir = vec2(cos(U_angle), sin(U_angle));\n float d = dot(p.xy, dir);\n float s = d - U_offset;\n if (s <= 0.0) return;\n float R = U_radius / U_foldAngle;\n float newD;\n float newZ;\n if (s <= U_radius) {\n float theta = (s / U_radius) * U_foldAngle;\n float sn = sin(theta);\n float cs = cos(theta);\n newD = U_offset + (R - p.z) * sn;\n newZ = R * (1.0 - cs) + p.z * cs;\n } else {\n float rest = s - U_radius;\n float sn = sin(U_foldAngle);\n float cs = cos(U_foldAngle);\n newD = U_offset + R * sn + rest * cs - p.z * sn;\n newZ = R * (1.0 - cs) + rest * sn + p.z * cs;\n }\n p.xy += dir * (newD - d);\n p.z = newZ;\n}\n`,\n strength: 'foldAngle',\n uniforms: (o) => ({\n angle: o.angle * DEG,\n offset: o.offset,\n foldAngle: o.foldAngle * DEG,\n radius: o.radius,\n }),\n },\n}\n","import { z } from 'zod'\nimport type { Deformer } from './types'\nimport { segmentsForSine, spanAlong } from '../core/tessellation'\n\nexport const waveOptionsSchema = z.object({\n amplitude: z.number().min(0).max(0.3).default(0.04),\n wavelength: z.number().min(0.05).max(2).default(0.5),\n /** Travel speed; 0 freezes the ripple. */\n speed: z.number().min(0).max(3).default(0.8),\n /** Travel direction in the sheet plane, degrees. */\n angle: z.number().min(-360).max(360).default(90),\n /** Zero the displacement at one edge (a taped/pinned edge doesn't ripple). */\n pinnedEdge: z.enum(['none', 'top', 'bottom', 'left', 'right']).default('none'),\n})\n\nexport type WaveOptions = z.infer<typeof waveOptionsSchema>\n\nconst DEG = Math.PI / 180\nconst TAU = Math.PI * 2\n\n/**\n * Traveling sine displacement with a quieter second harmonic — idle flutter\n * and wind ripple. The only time-driven deformer so far: stacks containing\n * it re-deform every frame.\n */\nexport const wave: Deformer<WaveOptions> = {\n id: 'wave',\n label: 'Wave',\n defaults: waveOptionsSchema.parse({}),\n optionsSchema: waveOptionsSchema,\n geometry: {\n minSegments: 32,\n // `displace` is sin(phase) + 0.35·sin(2.7·phase). The harmonic is a\n // third the amplitude but curvature carries the SQUARE of the frequency,\n // so 0.35 × 2.7² ≈ 2.6 — the quiet term is the one that sets the grid,\n // by a factor of two and a half. Take whichever asks for more anyway.\n autoSegments: (o, sheet) => {\n const span = spanAlong(sheet, o.angle)\n return Math.max(\n segmentsForSine(span, o.amplitude, o.wavelength),\n segmentsForSine(span, o.amplitude * 0.35, o.wavelength / 2.7),\n )\n },\n axis: (o) => o.angle,\n },\n animated: true,\n displace(out, uv, o, ctx) {\n if (o.amplitude === 0) return\n const dirX = Math.cos(o.angle * DEG)\n const dirY = Math.sin(o.angle * DEG)\n const d = out.x * dirX + out.y * dirY\n const phase = (d / o.wavelength - o.speed * ctx.t) * TAU\n let env = 1\n if (o.pinnedEdge === 'top') env = 1 - uv.y\n else if (o.pinnedEdge === 'bottom') env = uv.y\n else if (o.pinnedEdge === 'left') env = uv.x\n else if (o.pinnedEdge === 'right') env = 1 - uv.x\n out.z += o.amplitude * env * (Math.sin(phase) + 0.35 * Math.sin(phase * 2.7 + 1.3))\n },\n glsl: {\n chunk: /* glsl */ `\nvoid FN(inout vec3 p, vec2 uv, float t) {\n if (U_amplitude == 0.0) return;\n vec2 dir = vec2(cos(U_angle), sin(U_angle));\n float d = dot(p.xy, dir);\n float phase = (d / U_wavelength - U_speed * t) * 6.283185307179586;\n float env = 1.0;\n if (U_pin == 1.0) env = 1.0 - uv.y;\n else if (U_pin == 2.0) env = uv.y;\n else if (U_pin == 3.0) env = uv.x;\n else if (U_pin == 4.0) env = 1.0 - uv.x;\n p.z += U_amplitude * env * (sin(phase) + 0.35 * sin(phase * 2.7 + 1.3));\n}\n`,\n strength: 'amplitude',\n uniforms: (o) => ({\n amplitude: o.amplitude,\n wavelength: o.wavelength,\n speed: o.speed,\n angle: o.angle * DEG,\n pin: { none: 0, top: 1, bottom: 2, left: 3, right: 4 }[o.pinnedEdge],\n }),\n },\n}\n","import { z } from 'zod'\nimport type { Deformer } from './types'\nimport { segmentsForSine } from '../core/tessellation'\n\nexport const drapeOptionsSchema = z.object({\n /** Fold depth at the free edge, world units. */\n amplitude: z.number().min(0).max(0.6).default(0.12),\n /** How many folds run down the drop. */\n folds: z.number().min(0.5).max(16).default(4),\n /**\n * How fast folds deepen away from the pinned edge. 1 is linear; higher\n * holds the top flat and gathers all the movement at the free end, which\n * is what a sheet hung from a rod actually does.\n */\n falloff: z.number().min(0.3).max(4).default(1.6),\n /** How much a second, non-harmonic fold breaks the regularity. */\n irregular: z.number().min(0).max(1).default(0.45),\n /** How much the sheet narrows as its folds deepen. */\n gather: z.number().min(0).max(1).default(0.5),\n pinnedEdge: z.enum(['top', 'bottom']).default('top'),\n})\n\nexport type DrapeOptions = z.infer<typeof drapeOptionsSchema>\n\nconst TAU = Math.PI * 2\n\n/**\n * Hung paper: vertical folds running the length of the drop, shallow at the\n * fixed edge and deepening toward the free one.\n *\n * `wave` can put ripples on a sheet, but a traveling sine is a flag, not a\n * curtain — it kinks the sheet ACROSS its drop and it is uniform end to end.\n * Cloth hung from an edge does the opposite: the folds run WITH the drop and\n * they grow as they get further from whatever is holding the sheet up. Two\n * details do most of the work:\n *\n * - the folds are not harmonic. A pure sine reads as corrugated metal, so a\n * second wave at an incommensurate frequency breaks the repeat.\n * - gathered paper is narrower than flat paper. Pulling the surface toward\n * its centerline in proportion to fold depth is what stops the drape from\n * looking like a texture painted on a rectangle.\n */\nexport const drape: Deformer<DrapeOptions> = {\n id: 'drape',\n label: 'Drape',\n defaults: drapeOptionsSchema.parse({}),\n optionsSchema: drapeOptionsSchema,\n geometry: {\n minSegments: 48,\n // `folds` fold across the width, so the wavelength is width/folds, and\n // the irregular term rides at 1.7x that frequency. Same reasoning as\n // wave: the faster term usually wins despite the smaller amplitude.\n autoSegments: (o, sheet) => {\n if (o.folds <= 0) return 0\n const lambda = sheet.width / o.folds\n return Math.max(\n segmentsForSine(sheet.width, o.amplitude, lambda),\n segmentsForSine(sheet.width, o.amplitude * 0.6 * o.irregular, lambda / 1.7),\n )\n },\n // Across the width, always. `pinnedEdge` picks which end of the DROP the\n // folds grow from; it never turns the folds themselves, which run with\n // the drop and therefore vary across `uv.x`.\n axis: () => 0,\n },\n displace(out, uv, o) {\n if (o.amplitude === 0) return\n // Distance from the pinned edge, 0 at the fixing and 1 at the free end.\n const drop = o.pinnedEdge === 'top' ? 1 - uv.y : uv.y\n const depth = drop ** o.falloff\n const u = uv.x * TAU * o.folds\n const fold = Math.sin(u) + o.irregular * 0.6 * Math.sin(u * 1.7 + 2.1)\n out.z += o.amplitude * depth * fold\n const pinch = o.gather * depth * Math.min(o.amplitude * o.folds * 0.8, 0.6)\n out.x *= 1 - pinch\n },\n glsl: {\n chunk: /* glsl */ `\nvoid FN(inout vec3 p, vec2 uv, float t) {\n if (U_amplitude == 0.0) return;\n float drop = U_pin == 1.0 ? 1.0 - uv.y : uv.y;\n float depth = pow(drop, U_falloff);\n float u = uv.x * 6.283185307179586 * U_folds;\n float fold = sin(u) + U_irregular * 0.6 * sin(u * 1.7 + 2.1);\n p.z += U_amplitude * depth * fold;\n float pinch = U_gather * depth * min(U_amplitude * U_folds * 0.8, 0.6);\n p.x *= 1.0 - pinch;\n}\n`,\n strength: 'amplitude',\n uniforms: (o) => ({\n amplitude: o.amplitude,\n folds: o.folds,\n falloff: o.falloff,\n irregular: o.irregular,\n gather: o.gather,\n pin: o.pinnedEdge === 'top' ? 1 : 2,\n }),\n },\n}\n","import { z } from 'zod'\nimport type { Deformer } from './types'\n\nexport const crumpleOptionsSchema = z.object({\n /** How crushed, 0..1. Peak-to-peak height, and it drives the pull too. */\n amount: z.number().min(0).max(1).default(0.35),\n /** Facets per world unit. Higher is finer, and needs more segments to resolve. */\n scale: z.number().min(0.5).max(8).default(3),\n /**\n * How much the sheet draws in on itself. Crumpled paper occupies a smaller\n * footprint than flat paper; without this it reads as an embossed sheet\n * rather than a crushed one.\n */\n pull: z.number().min(0).max(1).default(0.4),\n /** A different crush of the same paper. */\n seed: z.number().int().min(0).max(7).default(0),\n})\n\nexport type CrumpleOptions = z.infer<typeof crumpleOptionsSchema>\n\n/**\n * GLSL's `mod`, which is not JS's `%`.\n *\n * `%` keeps the sign of the dividend, so a cell at a negative coordinate\n * hashes to a different bucket on the two paths — and the sheet is centred on\n * the origin, so HALF of every sheet is at a negative coordinate. Mirroring\n * `x - y·floor(x/y)` is the whole reason the two halves agree.\n */\nfunction mod(x: number, y: number): number {\n return x - y * Math.floor(x / y)\n}\n\n/**\n * Where the feature point of a cell sits, 0..1 within it.\n *\n * Deliberately integer arithmetic on small numbers rather than the usual\n * `fract(sin(dot(…)) * 43758.5)` hash: that one takes the sine of a large\n * argument and multiplies the result by forty thousand, which turns a\n * last-bit difference between a CPU and a GPU into a completely different\n * number. Every product here stays under 2^13, which is exact in float32 and\n * in a double alike, so the two implementations land on the same point rather\n * than on nearby ones. The pattern repeats every 64 cells — far outside any\n * sheet you would put on screen.\n */\nfunction jitter(cx: number, cy: number, seed: number): [number, number] {\n const hx = mod(cx * 37 + cy * 17 + seed * 5, 64)\n const hy = mod(cx * 23 + cy * 41 + seed * 11, 64)\n return [0.2 + (0.6 * mod(hx * 13, 7)) / 6, 0.2 + (0.6 * mod(hy * 29, 11)) / 10]\n}\n\n/**\n * `F2 − F1` tops out at 0.9315 of a cell on this jitter (measured across\n * every seed and the whole `scale` range), so this brings the field back to\n * ±amount/2 — `amount` is then a peak-to-peak height you can reason about\n * rather than an arbitrary knob. `crumple.test.ts` holds the bound.\n */\nconst NORM = 0.5366\n\n/** Which way a cell's facet is pushed — half up, half down. */\nfunction cellSign(cx: number, cy: number, seed: number): number {\n return 1 - 2 * mod(cx * 11 + cy * 7 + seed * 3, 2)\n}\n\n/**\n * Paper that has been handled.\n *\n * Six deformers and not one of them crushed a sheet — `wave` and `fold` were\n * the nearest and neither reads as crumpled. This is the missing primitive.\n *\n * The field is a jittered grid of cells, each pushed up or down, with the\n * height going to zero exactly on the boundary between them: `F2 − F1`, the\n * gap between the two nearest cell points, signed per cell. That vanishes on\n * every boundary, so the sheet stays continuous, and its gradient flips\n * across one — which is a crease. The result is an irregular polygonal\n * network of facets alternating toward and away from you, which is what a\n * sheet crushed in a fist actually is.\n *\n * **The normals matter more than the displacement here**, and getting there\n * took three tries worth recording. Three summed triangle waves: periodic,\n * an egg-crate. Plain distance-to-nearest (`F1`): irregular but smooth cone\n * tips, so it read as hammered metal. Only creases with a sign change across\n * them shade like paper.\n *\n * Both normal paths agree with that: the hero path averages vertex normals\n * over a dense grid, the field path probes two tangents a hundredth of a\n * sheet apart. Both need facets several segments wide.\n *\n * Cost, measured rather than assumed (`pnpm perf:field --soft`): a field of\n * these runs about four times longer per frame at ×20, and six at ×60, than\n * the same field of an undeformed preset. That ratio used to read 45%, and it\n * grew without this deformer getting one instruction slower — `'auto'` now\n * sizes the grid to the work, so the undeformed sheet it is measured against\n * went from 72 segments a side to 8 and got very cheap, while crumple keeps\n * the density its creases need. Which makes the point sharper than before:\n * almost none of this cost is geometry. It is the nine cell lookups per\n * probe, three probes deep for the normal.\n */\nexport const crumple: Deformer<CrumpleOptions> = {\n id: 'crumple',\n label: 'Crumple',\n defaults: crumpleOptionsSchema.parse({}),\n optionsSchema: crumpleOptionsSchema,\n // A crease the grid cannot resolve is a smooth bump, and a sheet of smooth\n // bumps is not a crumple. Measured (`pnpm perf:field`), the real cost of\n // this deformer is not geometry at all: it is nine cell evaluations per\n // probe and three probes per vertex for the normal.\n //\n // No `autoSegments` here, and that is the honest answer rather than an\n // omission. Every other deformer approximates a smooth surface, so its\n // density falls out of a radius; a crumple's creases are where the gradient\n // is MEANT to break, so there is no sagitta to bound. What it wants is\n // segments per cell, and at the default `scale: 3` across a 1.4 span that\n // works out to the 72 this floor already asks for. So crumple is the one\n // deformer `'auto'` does not make cheaper — its floor was never the no-op\n // the others' were.\n geometry: { minSegments: 72 },\n displace(out, _uv, o) {\n if (o.amount === 0) return\n const qx = out.x * o.scale\n const qy = out.y * o.scale\n const gx = Math.floor(qx)\n const gy = Math.floor(qy)\n\n // Nearest and second-nearest cell point, and which cell won.\n let f1 = 1e9\n let f2 = 1e9\n let winX = gx\n let winY = gy\n for (let dy = -1; dy <= 1; dy++) {\n for (let dx = -1; dx <= 1; dx++) {\n const cx = gx + dx\n const cy = gy + dy\n const [jx, jy] = jitter(cx, cy, o.seed)\n const ex = cx + jx - qx\n const ey = cy + jy - qy\n const dist = Math.sqrt(ex * ex + ey * ey)\n if (dist < f1) {\n f2 = f1\n f1 = dist\n winX = cx\n winY = cy\n } else if (dist < f2) {\n f2 = dist\n }\n }\n }\n\n // Zero on every cell boundary, so the sheet never tears; the sign flips\n // as you cross one, which is what makes the boundary a crease.\n out.z += cellSign(winX, winY, o.seed) * (f2 - f1) * o.amount * NORM\n // Drawing in happens after the cell lookup reads the flat position, so\n // both implementations hash the same cell.\n const pull = 1 - o.amount * o.pull * 0.35\n out.x *= pull\n out.y *= pull\n },\n glsl: {\n chunk: /* glsl */ `\nvec2 FN_jitter(float cx, float cy, float seed) {\n float hx = mod(cx * 37.0 + cy * 17.0 + seed * 5.0, 64.0);\n float hy = mod(cx * 23.0 + cy * 41.0 + seed * 11.0, 64.0);\n return vec2(0.2 + 0.6 * mod(hx * 13.0, 7.0) / 6.0, 0.2 + 0.6 * mod(hy * 29.0, 11.0) / 10.0);\n}\n\nfloat FN_sign(float cx, float cy, float seed) {\n return 1.0 - 2.0 * mod(cx * 11.0 + cy * 7.0 + seed * 3.0, 2.0);\n}\n\nvoid FN(inout vec3 p, vec2 uv, float t) {\n if (U_amount == 0.0) return;\n vec2 flat2 = p.xy;\n vec2 q = flat2 * U_scale;\n vec2 g = floor(q);\n\n float f1 = 1e9;\n float f2 = 1e9;\n vec2 win = g;\n for (int dy = -1; dy <= 1; dy++) {\n for (int dx = -1; dx <= 1; dx++) {\n vec2 c = g + vec2(float(dx), float(dy));\n float dist = length(c + FN_jitter(c.x, c.y, U_seed) - q);\n if (dist < f1) { f2 = f1; f1 = dist; win = c; }\n else if (dist < f2) { f2 = dist; }\n }\n }\n\n p.z += FN_sign(win.x, win.y, U_seed) * (f2 - f1) * U_amount * ${NORM};\n float pull = 1.0 - U_amount * U_pull * 0.35;\n p.xy = flat2 * pull;\n}\n`,\n // `amount` drives both the height and the pull, so a field instance's\n // bias scales the whole crush rather than half of it.\n strength: 'amount',\n uniforms: (o) => ({ amount: o.amount, scale: o.scale, pull: o.pull, seed: o.seed }),\n },\n}\n","import { z } from 'zod'\nimport type { AnyOptions, Deformer, DeformerInstance } from './types'\nimport { roll } from './roll'\nimport { curl } from './curl'\nimport { bend } from './bend'\nimport { fold } from './fold'\nimport { wave } from './wave'\nimport { drape } from './drape'\nimport { crumple } from './crumple'\n\nconst registry = new Map<string, Deformer<AnyOptions>>()\n\n/** Community deformers register here; built-ins are pre-registered. */\nexport function registerDeformer(deformer: Deformer<AnyOptions>): void {\n registry.set(deformer.id, deformer)\n}\n\nexport function getDeformer(id: string): Deformer<AnyOptions> {\n const d = registry.get(id)\n if (!d) {\n throw new Error(`[paperlab] Unknown deformer \"${id}\". Registered: ${[...registry.keys()].join(', ')}`)\n }\n return d\n}\n\nexport function listDeformers(): string[] {\n return [...registry.keys()]\n}\n\nregisterDeformer(roll)\nregisterDeformer(curl)\nregisterDeformer(bend)\nregisterDeformer(fold)\nregisterDeformer(wave)\nregisterDeformer(drape)\nregisterDeformer(crumple)\n\n/**\n * Resolve a raw `deformers` stack — the Advanced fork of a behavior — into\n * instances safe to render.\n *\n * The escape hatch used to pass its options straight through, so a preset\n * naming an option that doesn't exist (`frequency` where wave wants\n * `wavelength`) reached the GLSL builder as `undefined` and died there with\n * a message about `.length`, or reached the CPU path and quietly produced\n * NaN vertices. Parsing through each deformer's own schema turns that into\n * the validation error it always was, and fills in defaults for whatever a\n * hand-written preset left out.\n *\n * Disabled entries keep their slot: the GLSL uniform namespace is indexed by\n * position, so dropping one here would rename every uniform after it.\n */\nexport function resolveDeformerStack(\n raw: { type: string; options?: Record<string, unknown>; enabled?: boolean }[],\n): DeformerInstance[] {\n return raw.map((instance, i) => {\n const deformer = getDeformer(instance.type)\n // Strict: an unknown key here is almost always a typo for a real option,\n // and silently dropping it means the preset renders wrong with no clue\n // why. Every built-in schema is a plain object; anything exotic a\n // community deformer brings is parsed as it comes.\n const schema =\n deformer.optionsSchema instanceof z.ZodObject ? deformer.optionsSchema.strict() : deformer.optionsSchema\n const parsed = schema.safeParse(instance.options ?? {})\n if (!parsed.success) {\n const issue = parsed.error.issues[0]\n throw new Error(\n `[paperlab] deformers[${i}] (\"${instance.type}\"): ${\n issue ? `${issue.path.join('.') || 'options'} — ${issue.message}` : 'invalid options'\n }`,\n )\n }\n return {\n type: instance.type,\n options: parsed.data as Record<string, unknown>,\n enabled: instance.enabled,\n }\n })\n}\n\n/** True if any enabled instance re-deforms every frame (wave etc.). */\nexport function stackIsAnimated(stack: { type: string; enabled?: boolean }[]): boolean {\n return stack.some((i) => i.enabled !== false && registry.get(i.type)?.animated)\n}\n","import * as THREE from 'three'\nimport { computeSheetNormals } from '../core/normals'\nimport { axialSegments, type SegmentPair } from '../core/tessellation'\nimport type { AnyOptions, Deformer, DeformerContext, DeformerInstance, SheetDims } from './types'\nimport { getDeformer } from './registry'\n\n// Preallocated scratch — deformer loops are allocation-free.\nconst scratchPos = new THREE.Vector3()\nconst scratchUv = new THREE.Vector2()\n\n/**\n * The resolved stack, reused across frames: two parallel arrays rather than a\n * list of objects, refilled in place. `applyDeformerStack` runs every frame\n * for any animated sheet, and a `filter()` plus a registry lookup per vertex\n * is a per-frame allocation and 16k map probes for an answer that only\n * changes when the stack does.\n */\nconst activeFns: ((out: THREE.Vector3, uv: THREE.Vector2, o: AnyOptions, ctx: DeformerContext) => void)[] = []\nconst activeOptions: AnyOptions[] = []\n\n/**\n * Run an ordered deformer stack over a sheet geometry: each vertex starts\n * from its flat base position and flows through every enabled deformer in\n * order. Writes positions in place and recomputes normals.\n */\nexport function applyDeformerStack(\n geometry: THREE.BufferGeometry,\n basePositions: Float32Array,\n stack: DeformerInstance[],\n ctx: DeformerContext,\n): void {\n const position = geometry.attributes.position as THREE.BufferAttribute\n const uv = geometry.attributes.uv as THREE.BufferAttribute\n const array = position.array as Float32Array\n const uvArray = uv.array as Float32Array\n const count = position.count\n\n activeFns.length = 0\n activeOptions.length = 0\n for (const instance of stack) {\n if (instance.enabled === false) continue\n activeFns.push(getDeformer(instance.type).displace)\n activeOptions.push(instance.options)\n }\n\n // One deformer over every vertex, then the next — rather than every\n // deformer over one vertex, then the next. A deformer only ever reads and\n // writes the vertex it was handed, so sweeping the sheet per deformer is\n // the same composition in a different order, and it puts ONE function\n // behind the inner call site instead of the whole stack. It also costs an\n // extra pass over the position array per deformer, which is sequential and\n // measures as nothing beside what the call site buys.\n array.set(basePositions)\n for (let k = 0; k < activeFns.length; k++) {\n const displace = activeFns[k]!\n const options = activeOptions[k]\n for (let v = 0; v < count; v++) {\n const i3 = v * 3\n const i2 = v * 2\n scratchPos.set(array[i3]!, array[i3 + 1]!, array[i3 + 2]!)\n scratchUv.set(uvArray[i2]!, uvArray[i2 + 1]!)\n displace(scratchPos, scratchUv, options, ctx)\n array[i3] = scratchPos.x\n array[i3 + 1] = scratchPos.y\n array[i3 + 2] = scratchPos.z\n }\n }\n\n position.needsUpdate = true\n computeSheetNormals(geometry)\n}\n\n/** A single point through the stack — used for handle anchors and tests. */\nexport function displacePoint(\n point: THREE.Vector3,\n uvX: number,\n uvY: number,\n stack: DeformerInstance[],\n ctx: DeformerContext,\n): THREE.Vector3 {\n scratchUv.set(uvX, uvY)\n for (const instance of stack) {\n if (instance.enabled === false) continue\n getDeformer(instance.type).displace(point, scratchUv, instance.options, ctx)\n }\n return point\n}\n\n/**\n * The densest grid any deformer in the stack REQUIRES to work at all, per\n * axis — the componentwise max of every entry's floor projected onto the\n * sheet's own X and Y by the direction that entry curves in.\n */\nexport function stackMinSegments(stack: DeformerInstance[], sheet: SheetDims): SegmentPair {\n const out: SegmentPair = [2, 2]\n for (const instance of stack) {\n const deformer = getDeformer(instance.type)\n const floor = deformer.geometry?.minSegments\n if (!floor) continue\n take(out, deformer, instance.options, sheet, floor)\n }\n return out\n}\n\n/**\n * The densest grid any deformer in the stack WANTS, given the options it is\n * actually carrying — what `segments: 'auto'` resolves to, per axis.\n *\n * Disabled instances are skipped, exactly as `applyDeformerStack` skips them:\n * a deformer that is not displacing anything has no opinion about the grid.\n * (`stackMinSegments` does not skip them, and that difference is deliberate —\n * a floor is about what the stack could do, a target about what it is doing.)\n *\n * A deformer with no `autoSegments` falls back to its floor, which is the\n * right answer for one whose cost does not move with its options.\n */\nexport function stackAutoSegments(stack: DeformerInstance[], sheet: SheetDims): SegmentPair {\n const out: SegmentPair = [0, 0]\n for (const instance of stack) {\n if (instance.enabled === false) continue\n const deformer = getDeformer(instance.type)\n const geometry = deformer.geometry\n if (!geometry) continue\n const want = geometry.autoSegments\n ? geometry.autoSegments(instance.options, sheet)\n : (geometry.minSegments ?? 0)\n take(out, deformer, instance.options, sheet, want)\n }\n return out\n}\n\n/** Project one demand onto the two axes and keep it if it raises either. */\nfunction take(\n out: SegmentPair,\n deformer: Deformer<AnyOptions>,\n options: AnyOptions,\n sheet: SheetDims,\n demand: number,\n): void {\n // A community deformer whose `axis` cannot answer for these options — or\n // one that has none — falls back to spreading the demand over both axes,\n // which is the conservative half of the choice: it over-subdivides rather\n // than under-subdividing something that is actually bending.\n const declared = deformer.geometry?.axis?.(options, sheet)\n const angle = typeof declared === 'number' && Number.isFinite(declared) ? declared : null\n const [x, y] = axialSegments(sheet, angle, demand)\n if (x > out[0]) out[0] = x\n if (y > out[1]) out[1] = y\n}\n","import type * as THREE from 'three'\n\n/**\n * Recompute vertex normals for a sheet, straight over the typed arrays.\n *\n * Identical arithmetic to `BufferGeometry.computeVertexNormals()` — same\n * `cross(C − B, A − B)` per face, same accumulate-then-normalize — and it\n * agrees with it bit for bit (`core/normals.test.ts` asserts exact equality,\n * not a tolerance). What it does not do is go through `Vector3` and the\n * `BufferAttribute` accessors, which is three's cost and not the maths'.\n *\n * Worth having its own file because of where it sits: this runs once per\n * animated sheet per frame in hero mode, over a grid that `segments: 'auto'`\n * is allowed to take to 128 (16.6k vertices, 32.8k faces). Measured on a\n * `drape + wave` sheet at that ceiling it is 1.37 ms through three and\n * 0.18 ms here — normals were three quarters of the cost of a `roll`'s\n * frame and are now a tenth of it.\n *\n * Falls back to three for anything that is not an indexed mesh carrying a\n * normal attribute, which is the only shape this fast path knows.\n */\nexport function computeSheetNormals(geometry: THREE.BufferGeometry): void {\n const index = geometry.index\n const normalAttr = geometry.attributes.normal as THREE.BufferAttribute | undefined\n const positionAttr = geometry.attributes.position as THREE.BufferAttribute | undefined\n if (!index || !normalAttr || !positionAttr) {\n geometry.computeVertexNormals()\n return\n }\n const pos = positionAttr.array as Float32Array\n const nrm = normalAttr.array as Float32Array\n const idx = index.array as Uint16Array | Uint32Array\n\n nrm.fill(0)\n for (let i = 0, l = idx.length; i < l; i += 3) {\n const a = idx[i]! * 3\n const b = idx[i + 1]! * 3\n const c = idx[i + 2]! * 3\n const bx = pos[b]!\n const by = pos[b + 1]!\n const bz = pos[b + 2]!\n const cbx = pos[c]! - bx\n const cby = pos[c + 1]! - by\n const cbz = pos[c + 2]! - bz\n const abx = pos[a]! - bx\n const aby = pos[a + 1]! - by\n const abz = pos[a + 2]! - bz\n // The face normal, unnormalized — its length is twice the triangle's\n // area, which is the area weighting three's version also relies on.\n const nx = cby * abz - cbz * aby\n const ny = cbz * abx - cbx * abz\n const nz = cbx * aby - cby * abx\n nrm[a] = nrm[a]! + nx\n nrm[a + 1] = nrm[a + 1]! + ny\n nrm[a + 2] = nrm[a + 2]! + nz\n nrm[b] = nrm[b]! + nx\n nrm[b + 1] = nrm[b + 1]! + ny\n nrm[b + 2] = nrm[b + 2]! + nz\n nrm[c] = nrm[c]! + nx\n nrm[c + 1] = nrm[c + 1]! + ny\n nrm[c + 2] = nrm[c + 2]! + nz\n }\n\n for (let i = 0, l = nrm.length; i < l; i += 3) {\n const x = nrm[i]!\n const y = nrm[i + 1]!\n const z = nrm[i + 2]!\n // Divide rather than multiply by a reciprocal: `Vector3.normalize()`\n // divides, and one rounding difference per component is the whole\n // distance between \"bit-identical to three\" and \"close enough\", which\n // is not a claim worth weakening to save two multiplies.\n //\n // A vertex whose faces cancelled out has no normal to give. three's\n // `normalize()` divides by `length() || 1` and leaves the zero; so does\n // this, rather than dividing by zero and poisoning the lighting.\n const len = Math.sqrt(x * x + y * y + z * z) || 1\n nrm[i] = x / len\n nrm[i + 1] = y / len\n nrm[i + 2] = z / len\n }\n normalAttr.needsUpdate = true\n}\n","import type { AnyOptions } from '../deformers/types'\nimport type { Behavior } from './types'\nimport { peel } from './peel'\nimport { unroll } from './unroll'\nimport { flip } from './flip'\nimport { letterFold } from './letter-fold'\nimport { hang } from './hang'\nimport { fly } from './fly'\nimport { fall } from './fall'\nimport { carry } from './carry'\nimport { flight } from './flight'\nimport { crumpleBehavior } from './crumple'\nimport { settle } from './settle'\nimport { ribbon } from './ribbon'\n\nconst registry = new Map<string, Behavior<AnyOptions>>()\n\n/** Community behaviors register here; built-ins are pre-registered. */\nexport function registerBehavior(behavior: Behavior<AnyOptions>): void {\n registry.set(behavior.id, behavior)\n}\n\nexport function getBehavior(id: string): Behavior<AnyOptions> {\n const b = registry.get(id)\n if (!b) {\n throw new Error(`[paperlab] Unknown behavior \"${id}\". Registered: ${[...registry.keys()].join(', ')}`)\n }\n return b\n}\n\nexport function listBehaviors(): string[] {\n return [...registry.keys()]\n}\n\nregisterBehavior(peel)\nregisterBehavior(unroll)\nregisterBehavior(flip)\nregisterBehavior(letterFold)\nregisterBehavior(hang)\nregisterBehavior(fly)\nregisterBehavior(fall)\nregisterBehavior(carry)\nregisterBehavior(flight)\nregisterBehavior(crumpleBehavior)\nregisterBehavior(settle)\nregisterBehavior(ribbon)\n","import type { DeformerInstance } from '../deformers/types'\n\nexport const idleNames = ['float', 'tumble', 'dangle', 'taped', 'breeze'] as const\nexport type IdleName = (typeof idleNames)[number]\n\nexport interface IdlePose {\n /** Offsets added to the paper's base transform each frame. */\n position: [number, number, number]\n rotation: [number, number, number]\n}\n\n/**\n * Curated fake physics: hand-tuned motion presets, no simulation. Cheap\n * enough for both hero and field modes, and — for things like the\n * falling-leaf tumble — they read *more* real than a true sim.\n */\nexport interface IdlePreset {\n id: IdleName\n label: string\n /** Whole-sheet motion, written into `pose` (allocation-free). */\n transform?(t: number, pose: IdlePose): void\n /** Extra deformers appended after the behavior's stack. */\n stack?(): DeformerInstance[]\n}\n\nexport const idlePresets: Record<IdleName, IdlePreset> = {\n float: {\n id: 'float',\n label: 'Float',\n transform(t, pose) {\n pose.position[1] = Math.sin(t * 0.9) * 0.05\n pose.rotation[1] = Math.sin(t * 0.31) * 0.16\n pose.rotation[2] = Math.sin(t * 0.23 + 1.2) * 0.05\n },\n },\n tumble: {\n id: 'tumble',\n label: 'Tumble',\n transform(t, pose) {\n // Falling-leaf: velocity-linked lift bob + curated wobble.\n pose.rotation[0] = Math.sin(t * 0.5 + 1) * 0.6\n pose.rotation[2] = Math.sin(t * 0.7) * 0.5\n pose.position[1] = Math.sin(t * 1.4) * 0.07\n pose.position[0] = Math.sin(t * 0.35) * 0.14\n },\n stack: () => [\n {\n type: 'wave',\n options: { amplitude: 0.02, wavelength: 0.9, speed: 0.9, angle: 25, pinnedEdge: 'none' },\n },\n ],\n },\n dangle: {\n id: 'dangle',\n label: 'Dangle',\n transform(t, pose) {\n // A hung tail's pendulum sway.\n pose.rotation[2] = Math.sin(t * 1.5) * 0.06\n pose.rotation[0] = Math.sin(t * 1.1 + 0.7) * 0.03\n },\n },\n taped: {\n id: 'taped',\n label: 'Taped',\n // Taped at the top of a wall: the free bottom edge breathes.\n stack: () => [\n {\n type: 'wave',\n options: { amplitude: 0.025, wavelength: 1.2, speed: 0.45, angle: 90, pinnedEdge: 'top' },\n },\n ],\n },\n breeze: {\n id: 'breeze',\n label: 'Breeze',\n stack: () => [\n {\n type: 'wave',\n options: { amplitude: 0.035, wavelength: 0.5, speed: 1.0, angle: 20, pinnedEdge: 'none' },\n },\n ],\n },\n}\n\nexport function getIdlePreset(name: IdleName): IdlePreset {\n return idlePresets[name]\n}\n","export type PinMode = 'top-edge' | 'top-corners' | 'corner' | 'none'\n\nexport interface ClothParams {\n /** Bend-spring strength: 1 = crisp paper, 0 = silk. Fabric mode falls out for free. */\n stiffness: number\n gravity: number\n wind: number\n /** Local-space y of the ground plane; particles settle onto it. */\n floor: number\n}\n\ninterface Constraint {\n a: number\n b: number\n rest: number\n /** 0 = structural, 1 = shear, 2 = bend (scaled by stiffness at solve time). */\n kind: 0 | 1 | 2\n}\n\nconst FIXED_DT = 1 / 120\nconst SOLVER_ITERATIONS = 5\nconst SLEEP_EPSILON = 1e-6\nconst SLEEP_FRAMES = 45\n\n/**\n * Verlet mass-spring grid on the sheet's own vertices — structural + shear +\n * bend springs, pins as the interface, wind as a force field, fixed timestep\n * with substeps, sleep when kinetic energy is negligible.\n *\n * Constraint (enforced in the schema): cloth OWNS vertex positions — a paper\n * runs a behavior (deformer stack) OR cloth, never both. Pure JS, no three\n * dependency: the PaperMesh adapter copies `positions` into the geometry.\n */\nexport class ClothSim {\n readonly cols: number\n readonly rows: number\n readonly count: number\n readonly positions: Float32Array\n private readonly prev: Float32Array\n private readonly pinned: Uint8Array\n private readonly pinTargets: Float32Array\n private readonly constraints: Constraint[] = []\n private params: ClothParams\n private time = 0\n private accumulator = 0\n private stillFrames = 0\n private grabbedIndex = -1\n /** True when the sim has settled and steps are skipped. */\n asleep = false\n\n constructor(cols: number, rows: number, width: number, height: number, pins: PinMode, params: ClothParams) {\n this.cols = cols\n this.rows = rows\n this.count = cols * rows\n this.params = { ...params }\n this.positions = new Float32Array(this.count * 3)\n this.prev = new Float32Array(this.count * 3)\n this.pinned = new Uint8Array(this.count)\n this.pinTargets = new Float32Array(this.count * 3)\n\n // Grid matches PlaneGeometry vertex order: row-major, top row first,\n // x left→right, y top→bottom (from +h/2 down).\n for (let r = 0; r < rows; r++) {\n for (let c = 0; c < cols; c++) {\n const i3 = (r * cols + c) * 3\n this.positions[i3] = (c / (cols - 1) - 0.5) * width\n this.positions[i3 + 1] = (0.5 - r / (rows - 1)) * height\n this.positions[i3 + 2] = 0\n }\n }\n this.prev.set(this.positions)\n\n const idx = (r: number, c: number) => r * cols + c\n const link = (a: number, b: number, kind: 0 | 1 | 2) => {\n const dx = this.positions[a * 3]! - this.positions[b * 3]!\n const dy = this.positions[a * 3 + 1]! - this.positions[b * 3 + 1]!\n this.constraints.push({ a, b, rest: Math.hypot(dx, dy), kind })\n }\n for (let r = 0; r < rows; r++) {\n for (let c = 0; c < cols; c++) {\n if (c + 1 < cols) link(idx(r, c), idx(r, c + 1), 0)\n if (r + 1 < rows) link(idx(r, c), idx(r + 1, c), 0)\n if (c + 1 < cols && r + 1 < rows) {\n link(idx(r, c), idx(r + 1, c + 1), 1)\n link(idx(r, c + 1), idx(r + 1, c), 1)\n }\n if (c + 2 < cols) link(idx(r, c), idx(r, c + 2), 2)\n if (r + 2 < rows) link(idx(r, c), idx(r + 2, c), 2)\n }\n }\n\n // Pins hold their rest-pose position.\n const pin = (r: number, c: number) => {\n const i = idx(r, c)\n this.pinned[i] = 1\n this.pinTargets.set(this.positions.subarray(i * 3, i * 3 + 3), i * 3)\n }\n if (pins === 'top-edge') for (let c = 0; c < cols; c++) pin(0, c)\n if (pins === 'top-corners') {\n pin(0, 0)\n pin(0, cols - 1)\n }\n if (pins === 'corner') pin(0, 0)\n }\n\n setParams(params: Partial<ClothParams>): void {\n // Called every frame while cloth renders — plain numeric compare, no JSON.\n let changed = false\n for (const key of ['stiffness', 'gravity', 'wind', 'floor'] as const) {\n const value = params[key]\n if (value !== undefined && value !== this.params[key]) {\n this.params[key] = value\n changed = true\n }\n }\n if (changed) this.wake()\n }\n\n wake(): void {\n this.asleep = false\n this.stillFrames = 0\n }\n\n /** Nearest particle to a local-space point — the grab interface. */\n grabNearest(x: number, y: number, z: number): number {\n let best = -1\n let bestDist = Infinity\n for (let i = 0; i < this.count; i++) {\n const dx = this.positions[i * 3]! - x\n const dy = this.positions[i * 3 + 1]! - y\n const dz = this.positions[i * 3 + 2]! - z\n const d = dx * dx + dy * dy + dz * dz\n if (d < bestDist) {\n bestDist = d\n best = i\n }\n }\n this.grabbedIndex = best\n this.wake()\n return best\n }\n\n moveGrab(x: number, y: number, z: number): void {\n if (this.grabbedIndex < 0) return\n const i3 = this.grabbedIndex * 3\n this.positions[i3] = x\n this.positions[i3 + 1] = y\n this.positions[i3 + 2] = z\n this.prev[i3] = x\n this.prev[i3 + 1] = y\n this.prev[i3 + 2] = z\n this.wake()\n }\n\n release(): void {\n this.grabbedIndex = -1\n }\n\n step(delta: number): void {\n if (this.asleep) return\n this.accumulator = Math.min(this.accumulator + delta, FIXED_DT * 4)\n while (this.accumulator >= FIXED_DT) {\n this.substep(FIXED_DT)\n this.accumulator -= FIXED_DT\n }\n }\n\n private substep(dt: number): void {\n const { gravity, wind, stiffness, floor } = this.params\n const p = this.positions\n const damping = 0.985\n const dt2 = dt * dt\n this.time += dt\n\n let maxTravel = 0\n for (let i = 0; i < this.count; i++) {\n const i3 = i * 3\n if (this.pinned[i] || i === this.grabbedIndex) {\n if (this.pinned[i]) {\n p[i3] = this.pinTargets[i3]!\n p[i3 + 1] = this.pinTargets[i3 + 1]!\n p[i3 + 2] = this.pinTargets[i3 + 2]!\n }\n this.prev[i3] = p[i3]!\n this.prev[i3 + 1] = p[i3 + 1]!\n this.prev[i3 + 2] = p[i3 + 2]!\n continue\n }\n const x = p[i3]!\n const y = p[i3 + 1]!\n const z = p[i3 + 2]!\n // Gusty wind: coherent noise over time and position, pushing along +z\n // with a sideways component.\n const gust = wind * (0.55 + 0.45 * Math.sin(this.time * 1.7 + x * 2.1 + y * 1.3)) * 0.9\n const ax = gust * 0.25\n const az = gust\n const vx = (x - this.prev[i3]!) * damping\n const vy = (y - this.prev[i3 + 1]!) * damping\n const vz = (z - this.prev[i3 + 2]!) * damping\n this.prev[i3] = x\n this.prev[i3 + 1] = y\n this.prev[i3 + 2] = z\n p[i3] = x + vx + ax * dt2\n p[i3 + 1] = y + vy - gravity * 3.2 * dt2\n p[i3 + 2] = z + vz + az * dt2\n maxTravel = Math.max(maxTravel, vx * vx + vy * vy + vz * vz)\n }\n\n for (let iter = 0; iter < SOLVER_ITERATIONS; iter++) {\n for (const c of this.constraints) {\n const k = c.kind === 2 ? 0.25 + stiffness * 0.7 : c.kind === 1 ? 0.85 : 1\n const a3 = c.a * 3\n const b3 = c.b * 3\n const dx = p[b3]! - p[a3]!\n const dy = p[b3 + 1]! - p[a3 + 1]!\n const dz = p[b3 + 2]! - p[a3 + 2]!\n const dist = Math.sqrt(dx * dx + dy * dy + dz * dz)\n if (dist === 0) continue\n const diff = ((dist - c.rest) / dist) * 0.5 * k\n const aPinned = this.pinned[c.a] || c.a === this.grabbedIndex\n const bPinned = this.pinned[c.b] || c.b === this.grabbedIndex\n if (aPinned && bPinned) continue\n const aw = aPinned ? 0 : bPinned ? 2 : 1\n const bw = bPinned ? 0 : aPinned ? 2 : 1\n p[a3] = p[a3]! + dx * diff * aw\n p[a3 + 1] = p[a3 + 1]! + dy * diff * aw\n p[a3 + 2] = p[a3 + 2]! + dz * diff * aw\n p[b3] = p[b3]! - dx * diff * bw\n p[b3 + 1] = p[b3 + 1]! - dy * diff * bw\n p[b3 + 2] = p[b3 + 2]! - dz * diff * bw\n }\n }\n\n // Ground plane with friction.\n for (let i = 0; i < this.count; i++) {\n const i3 = i * 3\n if (p[i3 + 1]! < floor) {\n p[i3 + 1] = floor\n this.prev[i3] = this.prev[i3]! + (p[i3]! - this.prev[i3]!) * 0.5\n this.prev[i3 + 2] = this.prev[i3 + 2]! + (p[i3 + 2]! - this.prev[i3 + 2]!) * 0.5\n }\n }\n\n // Sleep bookkeeping: wind keeps the sheet awake by design.\n if (wind === 0 && this.grabbedIndex < 0) {\n if (maxTravel < SLEEP_EPSILON) {\n if (++this.stillFrames > SLEEP_FRAMES) this.asleep = true\n } else {\n this.stillFrames = 0\n }\n }\n }\n}\n","import { z } from 'zod'\nimport { filmNames, type FilmName, type LightingName } from '../config/schema'\n\n/**\n * Lighting presets: each is a key light + ambient level + contact shadow +\n * optional gobo (a texture the key light projects — window blinds, foliage).\n * Pure data here (testable in node); textures and R3F live in\n * PaperLighting.tsx. Serialized into presets as `scene.lighting`.\n *\n * A preset is the *starting point*, not the ceiling. `lightSchema` below is\n * the art-directable half: a handful of overrides that ride on top of a\n * named preset, so \"nave, but the sun is lower and the room is dimmer\" is a\n * thing you can say — and serialize — instead of a preset you have to fork.\n */\n\nexport interface LightingPreset {\n id: LightingName\n label: string\n ambient: number\n key: { color: string; intensity: number; position: [number, number, number] }\n contactShadowOpacity: number\n /** Contact shadow blur — hard for noir, long and soft for golden hour. */\n contactShadowBlur: number\n /** Renderer tone-mapping exposure while active. */\n exposure: number\n /**\n * The tone curve the picture is printed through.\n *\n * `exposure` picks the stop; this picks the FILM, and on a subject that is\n * almost white the film is the louder of the two. Every preset ships\n * `neutral` — Khronos PBR Neutral — because it is the only one of the\n * three that keeps a clipping sheet BOTH bright and the colour it actually\n * is. See the note on `filmNames` for what the other two do to warm light.\n */\n film: FilmName\n shadow: { mapSize: number; radius: number }\n gobo?: { kind: 'blinds' | 'leaves'; drift: number; angle: number }\n /**\n * Distance haze. Depth in a deep space is staged almost entirely by fog —\n * it is what turns a row of banners into a receding colonnade instead of\n * a flat row of rectangles.\n */\n fog?: { color: string; near: number; far: number }\n /**\n * The studio light: how strongly the room itself lights the paper.\n *\n * `<ambientLight>` adds brightness with no direction at all, which is the\n * single biggest reason a surface reads flat. This is the same brightness\n * with a SHAPE — an environment built from the sky below, so a sheet\n * turned toward the bright side of the room gets more light than one\n * turned away, and paper's sheen finally has something to reflect.\n */\n studio: number\n /**\n * The room, as three colours. It grades zenith → horizon → floor, carries\n * a soft disc of the key's own colour where the key stands, and becomes\n * both the environment map and (in stage mode) the cyclorama, so the\n * light and the space it is in cannot disagree.\n */\n sky: { zenith: string; horizon: string; ground: string }\n}\n\nexport const lightingPresets: Record<LightingName, LightingPreset> = {\n studio: {\n id: 'studio',\n label: 'Studio',\n ambient: 0.28,\n key: { color: '#ffffff', intensity: 1.6, position: [2.5, 4, 3] },\n contactShadowOpacity: 0.3,\n contactShadowBlur: 2.4,\n exposure: 1,\n film: 'neutral',\n shadow: { mapSize: 1024, radius: 4 },\n studio: 0.9,\n sky: { zenith: '#f6f7f9', horizon: '#e2e2e4', ground: '#b4b1ad' },\n },\n window: {\n id: 'window',\n label: 'Window',\n ambient: 0.22,\n key: { color: '#ffe3c0', intensity: 1.9, position: [3, 2.6, 2.6] },\n contactShadowOpacity: 0.35,\n contactShadowBlur: 2.6,\n exposure: 1,\n film: 'neutral',\n shadow: { mapSize: 1024, radius: 5 },\n gobo: { kind: 'blinds', drift: 0.004, angle: 0.62 },\n studio: 0.8,\n sky: { zenith: '#cfd8e6', horizon: '#f4e6d2', ground: '#8e8478' },\n },\n leaves: {\n id: 'leaves',\n label: 'Leaves',\n ambient: 0.2,\n key: { color: '#fff2d8', intensity: 2.0, position: [2.2, 3.6, 2.4] },\n contactShadowOpacity: 0.4,\n contactShadowBlur: 2.8,\n exposure: 1,\n film: 'neutral',\n shadow: { mapSize: 1024, radius: 6 },\n gobo: { kind: 'leaves', drift: 0.012, angle: 0.7 },\n studio: 0.85,\n sky: { zenith: '#bcd3c4', horizon: '#eae2c6', ground: '#6f7a5e' },\n },\n goldenhour: {\n id: 'goldenhour',\n label: 'Golden hour',\n ambient: 0.14,\n key: { color: '#ffb066', intensity: 2.4, position: [4, 0.9, 2.2] },\n contactShadowOpacity: 0.45,\n contactShadowBlur: 3.2,\n exposure: 1.15,\n film: 'neutral',\n shadow: { mapSize: 1024, radius: 7 },\n studio: 0.7,\n sky: { zenith: '#5d6f96', horizon: '#ffbe86', ground: '#4a3a2e' },\n },\n noir: {\n id: 'noir',\n label: 'Noir',\n ambient: 0.04,\n key: { color: '#ffffff', intensity: 2.6, position: [2, 3, 1.6] },\n contactShadowOpacity: 0.7,\n contactShadowBlur: 1.1,\n exposure: 1.05,\n film: 'neutral',\n shadow: { mapSize: 2048, radius: 1 },\n studio: 0.16,\n sky: { zenith: '#0d0d10', horizon: '#26262c', ground: '#050506' },\n },\n /**\n * A hard key at a grazing angle — the light paper is photographed under.\n *\n * This is the only preset in the set whose subject is the SURFACE rather\n * than the sheet. At eight degrees above the horizon the key skims across\n * the stock instead of landing on it, so every fibre, deckle tooth and\n * crease casts a shadow the length of itself and reads as RELIEF. It is\n * how a paper merchant shoots a swatch book, and it is the only way the\n * surface effects this library ships — grain, deckle, creaseLines, aging —\n * are visible as texture rather than as tint.\n *\n * Ambient and studio are both held down on purpose. Raking light works by\n * the shadows it casts, and fill is exactly the thing that fills those in;\n * turning `studio` up here does not brighten the picture so much as erase\n * the subject.\n */\n raking: {\n id: 'raking',\n label: 'Raking',\n // Lifted from 0.06/0.25 after looking at it: at the floor the shadow\n // side of a crumple went to near-black and the relief stopped reading as\n // relief and started reading as holes. This is the least fill that still\n // leaves a facet turned away from the key legible.\n ambient: 0.09,\n key: { color: '#fff6ea', intensity: 3.2, position: [5.81, 0.84, 1.24] },\n contactShadowOpacity: 0.6,\n contactShadowBlur: 1.6,\n exposure: 1,\n film: 'neutral',\n shadow: { mapSize: 2048, radius: 2 },\n studio: 0.32,\n sky: { zenith: '#2a2a2e', horizon: '#4a4844', ground: '#141314' },\n },\n /**\n * The sheet on a lightbox: the lamp is behind the paper and level with it.\n *\n * Every other front-lit preset shows you ink ON paper. This one shows you\n * light THROUGH it — which is the most beautiful thing paper does, and\n * which the library has been able to render since `translucency` became a\n * per-stock number without a single preset ever making it the subject.\n * Vellum glows, newsprint turns to a grey lantern with its fibres showing,\n * and a printed sheet reads backwards through itself.\n *\n * Printed a stop under for the same reason `nave` is: a backlit sheet\n * carries the lamp's whole intensity as transmission, so at 1.0 the paper\n * clips to flat white and takes its own texture with it.\n */\n lightbox: {\n id: 'lightbox',\n label: 'Lightbox',\n ambient: 0.05,\n key: { color: '#fdfdff', intensity: 4.5, position: [0, 0.7, -7.97] },\n // A sheet standing on a lit panel has almost nothing to cast onto.\n contactShadowOpacity: 0.15,\n contactShadowBlur: 4,\n exposure: 0.85,\n film: 'neutral',\n shadow: { mapSize: 1024, radius: 4 },\n studio: 0.35,\n sky: { zenith: '#dfe4ec', horizon: '#f6f8fc', ground: '#b9bec8' },\n },\n nave: {\n id: 'nave',\n label: 'Nave',\n // Dim, and the key sits BEHIND the walk rather than beside it: this mode\n // is carried by light coming through the paper, not off it. Ambient is\n // nearly nothing so the only bright thing in frame is the source itself —\n // what fills the shadow side is the room, which has a direction.\n ambient: 0.03,\n key: { color: '#fff1dc', intensity: 2.8, position: [0, 7, -16] },\n contactShadowOpacity: 0.55,\n contactShadowBlur: 3.6,\n // Printed a stop under. A backlit sheet carries its lamp's whole\n // intensity as transmission, so at 1.0 every banner in the hall clipped\n // to flat white and the folds — the entire reason the paper is draped —\n // vanished into the highlight.\n exposure: 0.8,\n film: 'neutral',\n shadow: { mapSize: 2048, radius: 6 },\n // Warm and light, not black: distance in a backlit hall washes TOWARD\n // the source, which is what separates haze from murk. It has to reach\n // past the end of the walk: at `far: 38` the back half of a 36-unit\n // colonnade was uniform fog colour, so the depth cue flattened exactly\n // where depth was the picture.\n fog: { color: '#a08d72', near: 9, far: 70 },\n studio: 0.55,\n sky: { zenith: '#241c17', horizon: '#fff4e2', ground: '#0e0b09' },\n },\n}\n\nexport function getLightingPreset(name: LightingName): LightingPreset {\n return lightingPresets[name]\n}\n\n// ── The authorable half ─────────────────────────────────────────────────────\n\n/**\n * Overrides on top of a named preset — the Blender-panel half of lighting.\n *\n * Every field is optional ON PURPOSE. An unset field means \"whatever the\n * preset says\", so a shared link carries the two sliders you actually moved\n * rather than a frozen copy of a rig you never touched, and re-basing onto\n * another preset keeps your intent instead of your numbers.\n */\nexport const lightSchema = z.object({\n /** Tone-mapping exposure — the stop the whole picture is printed at. */\n exposure: z.number().min(0.1).max(4).optional(),\n /**\n * The tone curve — the film, where `exposure` is the stop.\n *\n * `filmic` is ACES, which is what every preset used to be pinned to and is\n * kept so a scene tuned against it can say so. On near-white paper it is\n * the wrong film: it desaturates and drags bright neutrals toward\n * yellow-green, which is the sepia cast a lit sheet used to pick up.\n */\n film: z.enum(filmNames).optional(),\n /** Key light strength. */\n key: z.number().min(0).max(12).optional(),\n /** Key light colour. */\n color: z.string().optional(),\n /**\n * Where the key stands, degrees around the vertical. 0° is straight in\n * front of the paper (+Z, beside the camera), 90° is off to the right,\n * and ±180° is directly behind it — which is where `nave` puts it, and\n * why that preset is carried by light coming THROUGH the paper.\n */\n direction: z.number().min(-180).max(180).optional(),\n /** How high the key stands, degrees above the horizon. */\n height: z.number().min(-30).max(89).optional(),\n /** Flat fill from every direction at once. Cheap, and it kills form — reach for `studio` first. */\n ambient: z.number().min(0).max(2).optional(),\n /** The room's own light: an environment map built from `sky`. Directional fill, and the only thing paper's sheen has to reflect. */\n studio: z.number().min(0).max(3).optional(),\n /** Distance haze, as a multiple of the preset's. 0 clears the air entirely; 2 halves the distance you can see. */\n haze: z.number().min(0).max(3).optional(),\n})\n\nexport type LightOverrides = z.infer<typeof lightSchema>\nexport type LightOverridesInput = z.input<typeof lightSchema>\n\n/** Where a light stands, in the terms a person would say it in. */\nexport interface LightAngles {\n /** Degrees around the vertical: 0 = in front (+Z), 90 = right (+X), ±180 = behind. */\n azimuth: number\n /** Degrees above the horizon. */\n elevation: number\n /** Distance from the origin. Only the direction matters to a directional light; this keeps round-trips exact. */\n distance: number\n}\n\nconst DEG = 180 / Math.PI\n\n/**\n * Decompose a key light's position into the two angles the panel edits.\n *\n * A light at the origin has no direction to give, so it is reported as\n * straight overhead — the same fallback the transmission model makes, and\n * they have to agree.\n */\nexport function lightAngles(position: readonly [number, number, number]): LightAngles {\n const [x, y, z] = position\n const distance = Math.hypot(x, y, z)\n if (distance < 1e-9) return { azimuth: 0, elevation: 90, distance: 0 }\n const ground = Math.hypot(x, z)\n return {\n azimuth: ground < 1e-9 ? 0 : Math.atan2(x, z) * DEG,\n elevation: Math.atan2(y, ground) * DEG,\n distance,\n }\n}\n\n/** The inverse: put a light back where those angles say it stands. */\nexport function lightPosition(angles: LightAngles): [number, number, number] {\n const azimuth = angles.azimuth / DEG\n const elevation = angles.elevation / DEG\n const ground = Math.cos(elevation) * angles.distance\n return [Math.sin(azimuth) * ground, Math.sin(elevation) * angles.distance, Math.cos(azimuth) * ground]\n}\n\n/**\n * A preset with the overrides applied — the rig everything else reads.\n *\n * This is deliberately the ONLY way a light gets resolved. The transmission\n * uniforms, the shadow-casting lamp, the environment and the exposure all\n * come out of one object, because the bug this replaces was exactly that\n * disagreement: the banners computed their backlit glow from `studio` while\n * the hall was lit by `nave`, and a sheet lit from behind by a lamp that is\n * actually in front of it is not a subtle error.\n */\nexport function resolveLighting(\n base: LightingName | LightingPreset,\n overrides?: LightOverrides,\n): LightingPreset {\n const preset = typeof base === 'string' ? getLightingPreset(base) : base\n if (!overrides) return preset\n\n const { exposure, film, key, color, direction, height, ambient, studio, haze } = overrides\n const moved = direction !== undefined || height !== undefined\n const angles = moved ? lightAngles(preset.key.position) : null\n\n return {\n ...preset,\n ambient: ambient ?? preset.ambient,\n studio: studio ?? preset.studio,\n exposure: exposure ?? preset.exposure,\n film: film ?? preset.film,\n key: {\n color: color ?? preset.key.color,\n intensity: key ?? preset.key.intensity,\n position: angles\n ? lightPosition({\n azimuth: direction ?? angles.azimuth,\n elevation: height ?? angles.elevation,\n // A key that has been dragged onto the horizon still has to stand\n // somewhere, so a light collapsed to the origin gets a real\n // distance rather than staying at zero and losing its direction.\n distance: angles.distance || 10,\n })\n : preset.key.position,\n },\n fog: resolveFog(preset.fog, haze),\n }\n}\n\n/**\n * Haze as a multiplier on the preset's own depth cue, so one slider reads\n * \"thicker air\" rather than asking for two distances in world units. It\n * pulls both ends in together: at 2× you see half as far, and the wash\n * starts half as far out, which is what actual haze does.\n */\nfunction resolveFog(fog: LightingPreset['fog'], haze: number | undefined): LightingPreset['fog'] {\n if (!fog || haze === undefined || haze === 1) return fog\n if (haze <= 0) return undefined\n return { color: fog.color, near: fog.near / haze, far: fog.far / haze }\n}\n","import * as THREE from 'three'\nimport type { LightingName } from '../config/schema'\nimport { getLightingPreset, type LightingPreset } from '../scene/lighting'\n\n/**\n * Light passing THROUGH the paper.\n *\n * Every reference image for stage mode is lit from behind: the paper is a\n * filter, not a surface catching a key light. That single change is what\n * separates \"a render of some paper\" from the look — and it is cheap,\n * because paper is thin and diffuse. No refraction, no transmission pass,\n * no `MeshPhysicalMaterial` (which does not instance): one dot product and\n * an additive emissive term, so it works identically in the instanced field\n * path and the hero path.\n *\n * The detail that sells it is the ink filter. What comes through a backlit\n * sheet is the lamp MINUS whatever is printed on it, which is why the\n * calligraphy on a lit banner reads dark against a glowing field instead of\n * blowing out with everything else.\n */\n\n/** Declared by both stages of both pipelines. */\nexport const TRANSLUCENCY_VARYINGS = /* glsl */ `\nvarying vec3 vPlWorldNormal;\nvarying vec3 vPlViewDir;\n`\n\nexport interface TranslucencyVertexSlots {\n /** Object → world matrix expression. Instanced meshes must fold in `instanceMatrix`. */\n model: string\n /** Final object-space position expression. */\n position: string\n /** Final object-space normal expression. */\n normal: string\n}\n\n/**\n * Vertex side: publish the world-space normal and view vector. Doing this in\n * the vertex shader (rather than reconstructing from `vNormal`) keeps the\n * chunk independent of where in three's fragment pipeline it gets injected.\n */\nexport function translucencyVertexChunk(slots: TranslucencyVertexSlots): string {\n return /* glsl */ `\n {\n mat4 plModel = ${slots.model};\n vec4 plWorld = plModel * vec4(${slots.position}, 1.0);\n // Uniform scale only — layouts scale sheets evenly, so the plain 3×3 is\n // the correct normal matrix here and skips an inverse-transpose.\n vPlWorldNormal = normalize(mat3(plModel) * ${slots.normal});\n vPlViewDir = cameraPosition - plWorld.xyz;\n }\n`\n}\n\n/** How much of the incident key light a fully translucent sheet passes on. */\nexport const TRANSMISSION_GAIN = 0.5\n\n/** Fragment side: uniforms plus `plTransmission(inkFilter)`. */\nexport const TRANSLUCENCY_FRAGMENT = /* glsl */ `\nuniform float uTranslucency;\nuniform vec3 uBackLightDir;\nuniform vec3 uBackLightColor;\nuniform float uAmbientTransmission;\n${TRANSLUCENCY_VARYINGS}\n\nvec3 plTransmission(vec3 inkFilter) {\n if (uTranslucency <= 0.0) return vec3(0.0);\n vec3 n = normalize(vPlWorldNormal);\n // Sheets render double-sided; the back face needs the normal it actually shows.\n if (!gl_FrontFacing) n = -n;\n // The lamp is BEHIND this sheet when the face we are looking at points away\n // from it — that is the whole test.\n float behind = clamp(-dot(n, uBackLightDir), 0.0, 1.0);\n // A grazing view looks through more paper, and more paper passes less light.\n float thickness = abs(dot(n, normalize(vPlViewDir)));\n // Paper in a lit room glows whatever way it is turned — a sheet standing\n // edge-on to the only lamp is not black. Without this floor, a banner\n // whose face runs parallel to the key light gets neither diffuse nor\n // transmission and drops out of the picture entirely.\n vec3 arriving = uBackLightColor * behind + uAmbientTransmission;\n return arriving * uTranslucency * mix(0.25, 1.0, thickness) * inkFilter;\n}\n`\n\nexport interface TranslucencyValues {\n translucency: number\n /** Unit world direction from the scene toward the key light. */\n direction: THREE.Vector3\n color: THREE.Color\n /** Light the room passes through the sheet from every direction at once. */\n ambient: number\n}\n\n/**\n * Resolve the transmission uniforms from the paper and the scene's lighting\n * — the key light's own position and color, so translucency can never\n * disagree with the lamp casting the shadows.\n *\n * It takes a resolved rig as well as a name because a rig is no longer\n * always a preset: once the light can be moved, the lamp this sheet is\n * backlit by is the one the SCENE ended up with, not the one the paper was\n * authored against.\n */\nexport function translucencyValues(\n translucency: number,\n lighting: LightingName | LightingPreset,\n): TranslucencyValues {\n const preset = typeof lighting === 'string' ? getLightingPreset(lighting) : lighting\n const [x, y, z] = preset.key.position\n const direction = new THREE.Vector3(x, y, z)\n // A key light at the origin has no direction to give; treat it as overhead.\n if (direction.lengthSq() < 1e-12) direction.set(0, 1, 0)\n direction.normalize()\n const color = new THREE.Color(preset.key.color).multiplyScalar(preset.key.intensity * TRANSMISSION_GAIN)\n return { translucency, direction, color, ambient: preset.ambient * TRANSMISSION_GAIN }\n}\n\n/** Ready-to-bind uniform objects for a shader program. */\nexport function translucencyUniforms(\n translucency: number,\n lighting: LightingName | LightingPreset,\n): Record<string, { value: unknown }> {\n const values = translucencyValues(translucency, lighting)\n return {\n uTranslucency: { value: values.translucency },\n uBackLightDir: { value: values.direction },\n uBackLightColor: { value: values.color },\n uAmbientTransmission: { value: values.ambient },\n }\n}\n","import * as THREE from 'three'\nimport {\n paperEdges as paperEdgesOrder,\n type LightingName,\n type PaperEdge,\n type SurfaceConfig,\n} from '../config/schema'\nimport type { Stock } from '../core/stock'\nimport type { LightingPreset } from '../scene/lighting'\nimport {\n TRANSLUCENCY_FRAGMENT,\n TRANSLUCENCY_VARYINGS,\n translucencyUniforms,\n translucencyVertexChunk,\n} from './translucency'\n\n/**\n * Surface effects are fragment-side chunks composed into ONE shader program\n * per effect set (grain + deckle + aging = one program). Uniforms are\n * namespaced per effect; shared helpers (noise) are included once.\n */\n\nexport interface ComposedSurface {\n /** Distinguishes shader *structures* — same key ⇒ same program, only uniforms change. */\n structureKey: string\n vertexShader: string\n fragmentShader: string\n uniforms: Record<string, { value: unknown }>\n /** Deckle discards via alphaTest (not blending) so shadows stay correct. */\n alphaTest: number\n}\n\n/** Which content textures exist — part of the shader structure. */\nexport interface SurfaceMaps {\n hasFrontMap: boolean\n hasBackMap: boolean\n}\n\nconst VERTEX = /* glsl */ `\nvarying vec2 vPaperUv;\n${TRANSLUCENCY_VARYINGS}\nvoid main() {\n vPaperUv = uv;\n${translucencyVertexChunk({ model: 'modelMatrix', position: 'position', normal: 'normal' })}\n}\n`\n\nconst HELPERS = /* glsl */ `\nvarying vec2 vPaperUv;\nuniform float uBackDarken;\n\nfloat plHash(vec2 p) {\n return fract(sin(dot(p, vec2(127.1, 311.7))) * 43758.5453123);\n}\n\nfloat plNoise(vec2 p) {\n vec2 i = floor(p);\n vec2 f = fract(p);\n vec2 u = f * f * (3.0 - 2.0 * f);\n return mix(\n mix(plHash(i), plHash(i + vec2(1.0, 0.0)), u.x),\n mix(plHash(i + vec2(0.0, 1.0)), plHash(i + vec2(1.0, 1.0)), u.x),\n u.y\n );\n}\n\nfloat plFbm(vec2 p) {\n float v = 0.0;\n float a = 0.5;\n for (int i = 0; i < 4; i++) {\n v += a * plNoise(p);\n p *= 2.03;\n a *= 0.5;\n }\n return v;\n}\n`\n\nconst edgeFlags = (edges: PaperEdge[]): THREE.Vector4 =>\n new THREE.Vector4(\n edges.includes('top') ? 1 : 0,\n edges.includes('right') ? 1 : 0,\n edges.includes('bottom') ? 1 : 0,\n edges.includes('left') ? 1 : 0,\n )\n\nconst GRAIN_CHUNK = /* glsl */ `\nuniform float uGrainAmount;\nuniform float uGrainBanding;\n\nvoid plGrain(inout vec4 color, inout float rough) {\n float fiber = plFbm(vPaperUv * 240.0);\n float fleck = plNoise(vPaperUv * 900.0);\n float g = mix(0.5, fiber * 0.75 + fleck * 0.25, uGrainAmount);\n color.rgb *= 0.92 + g * 0.16;\n rough = clamp(rough + (g - 0.5) * uGrainAmount * 0.35, 0.0, 1.0);\n // Thermal-printer banding: faint horizontal density stripes.\n if (uGrainBanding > 0.0) {\n float band = sin(vPaperUv.y * 700.0) * 0.5 + 0.5;\n color.rgb *= 1.0 - uGrainBanding * 0.05 * band;\n }\n}\n`\n\nconst DECKLE_CHUNK = /* glsl */ `\nuniform vec4 uDeckleEdges; // top, right, bottom, left\nuniform float uDeckleRoughness;\n\nvoid plDeckle(inout vec4 color) {\n // Distance to each selected edge, gnawed by low-frequency noise.\n float depth = 0.012 + uDeckleRoughness * 0.05;\n float tear = 1.0;\n float fiberBand = 0.0;\n vec4 dists = vec4(1.0 - vPaperUv.y, 1.0 - vPaperUv.x, vPaperUv.y, vPaperUv.x);\n vec4 alongs = vec4(vPaperUv.x, vPaperUv.y, vPaperUv.x, vPaperUv.y);\n for (int e = 0; e < 4; e++) {\n if (uDeckleEdges[e] < 0.5) continue;\n float n = plFbm(vec2(alongs[e] * 26.0, float(e) * 7.31)) - 0.5;\n float boundary = depth * (0.55 + n * 1.6);\n float d = dists[e] - boundary;\n tear = min(tear, step(0.0, d));\n // Lightened fiber band just inside the tear.\n fiberBand = max(fiberBand, smoothstep(depth * 1.4, 0.0, d) * step(0.0, d));\n }\n color.a *= tear;\n color.rgb = mix(color.rgb, vec3(1.0), fiberBand * 0.35);\n}\n`\n\nconst CREASE_CHUNK = /* glsl */ `\nuniform float uCreaseAngle;\nuniform float uCreaseStrength;\nuniform float uCreasePositions[4];\nuniform int uCreaseCount;\n\nvoid plCrease(inout vec4 color, inout float rough) {\n vec2 dir = vec2(cos(uCreaseAngle), sin(uCreaseAngle));\n // Coordinate across the crease lines (0..1 over the sheet).\n float t = dot(vPaperUv - 0.5, vec2(-dir.y, dir.x)) + 0.5;\n for (int i = 0; i < 4; i++) {\n if (i >= uCreaseCount) break;\n float d = abs(t - uCreasePositions[i]);\n float shadow = smoothstep(0.014, 0.0, d);\n float sheen = smoothstep(0.02, 0.006, d) - smoothstep(0.006, 0.0, d);\n color.rgb *= 1.0 - shadow * uCreaseStrength * 0.28;\n color.rgb += sheen * uCreaseStrength * 0.05;\n rough = clamp(rough + shadow * uCreaseStrength * 0.2, 0.0, 1.0);\n }\n}\n`\n\nconst PERFORATION_CHUNK = /* glsl */ `\nuniform vec4 uPerfEdges; // top, right, bottom, left enabled\nuniform vec4 uPerfTorn; // 1 = ripped-through profile, 0 = clean punches\nuniform float uPerfRadius; // world units\nuniform float uPerfSpacing;\nuniform vec2 uSheetSize;\n\nvoid plPerforation(inout vec4 color) {\n // Per-edge distance/along coordinates, converted from UV to world units so\n // hole size is stable across sheet dimensions.\n vec4 dists = vec4(1.0 - vPaperUv.y, 1.0 - vPaperUv.x, vPaperUv.y, vPaperUv.x);\n vec4 alongs = vec4(vPaperUv.x, vPaperUv.y, vPaperUv.x, vPaperUv.y);\n vec4 distScale = vec4(uSheetSize.y, uSheetSize.x, uSheetSize.y, uSheetSize.x);\n vec4 alongScale = vec4(uSheetSize.x, uSheetSize.y, uSheetSize.x, uSheetSize.y);\n float fiber = 0.0;\n for (int e = 0; e < 4; e++) {\n if (uPerfEdges[e] < 0.5) continue;\n float d = dists[e] * distScale[e];\n float a = alongs[e] * alongScale[e];\n // Signed distance along the edge to the nearest hole center.\n float cell = mod(a + uPerfSpacing * 0.5, uPerfSpacing) - uPerfSpacing * 0.5;\n if (uPerfTorn[e] < 0.5) {\n // Intact: clean semicircular punches on the edge line (alphaTest, not\n // blending — shadow correctness per v0.2 §4.5).\n if (length(vec2(cell, d)) < uPerfRadius) color.a = 0.0;\n } else {\n // Torn: ripped profile following the hole rhythm — alternating tabs and\n // notches, gnawed by noise, with a lightened fiber band along the tear.\n float rhythm = abs(sin(a / uPerfSpacing * 3.14159265));\n float n = plNoise(vec2(a * 40.0, float(e) * 7.31)) - 0.5;\n float cut = uPerfRadius * (0.35 + rhythm * 1.35 + n * 0.9);\n if (d < cut) color.a = 0.0;\n fiber = max(fiber, smoothstep(uPerfRadius * 2.4, 0.0, d - cut) * step(cut, d));\n }\n }\n color.rgb = mix(color.rgb, vec3(1.0), fiber * 0.4);\n}\n`\n\nconst AGING_CHUNK = /* glsl */ `\nuniform float uAgingAmount;\n\nvoid plAging(inout vec4 color) {\n // Yellowing deepens toward the edges, like light exposure.\n float edge = max(abs(vPaperUv.x - 0.5), abs(vPaperUv.y - 0.5)) * 2.0;\n vec3 yellowed = color.rgb * vec3(1.0, 0.94, 0.78);\n color.rgb = mix(color.rgb, yellowed, uAgingAmount * (0.45 + edge * 0.55));\n // Foxing: sparse rusty blotches.\n float fox = plFbm(vPaperUv * 14.0 + 3.7);\n float spots = smoothstep(0.62, 0.78, fox) * uAgingAmount;\n color.rgb = mix(color.rgb, vec3(0.62, 0.45, 0.26), spots * 0.5);\n}\n`\n\n/**\n * Compose the enabled effects into one program. The shader owns the base\n * color entirely: the FRONT face samples the content texture, the BACK face\n * renders the stock (or content.back) with an optional reversed show-through\n * ghost — a single DoubleSide map would mirror the front content onto the\n * back, which real paper doesn't do.\n */\nexport function composeSurface(\n surface: SurfaceConfig,\n stock: Stock,\n thickness: number,\n maps: SurfaceMaps = { hasFrontMap: false, hasBackMap: false },\n /** World dims — perforation holes are sized in world units. */\n sheet: { width: number; height: number } = { width: 1, height: 1.4 },\n /** Whose key light transmission is measured against — a preset name or the scene's resolved rig. */\n lighting: LightingName | LightingPreset = 'studio',\n): ComposedSurface {\n const grain = surface.grain ?? stock.defaultSurface.grain\n const aging = surface.aging ?? stock.defaultSurface.aging\n const deckle = surface.deckle\n const creases = surface.creaseLines\n const perforation = surface.perforation\n const banding = stock.banding\n // Adhesive undersides are opaque backing-paper white — nothing shows through.\n const showThrough = stock.adhesive ? 0 : (surface.showThrough ?? stock.showThrough)\n\n const chunks: string[] = []\n const calls: string[] = []\n const uniforms: Record<string, { value: unknown }> = {\n // Backside darkening: thicker/opaque stock lets less light through.\n // Adhesive backs skip it — the glue layer is its own bright surface.\n uBackDarken: {\n value: stock.adhesive ? 1 : 1 - Math.min(0.45, 0.12 + thickness * 0.9) * stock.opacity,\n },\n uStockColor: { value: new THREE.Color(stock.color) },\n uOpacity: { value: stock.opacity },\n uShowThrough: { value: showThrough },\n // Always compiled in: the shader early-outs at zero translucency, which\n // is cheaper than carrying a second program structure for it.\n ...translucencyUniforms(surface.translucency ?? stock.translucency, lighting),\n }\n if (maps.hasFrontMap) uniforms.uFrontMap = { value: null }\n if (maps.hasBackMap) uniforms.uBackMap = { value: null }\n\n if (grain !== undefined || banding > 0) {\n chunks.push(GRAIN_CHUNK)\n calls.push('plGrain(csm_DiffuseColor, csm_Roughness);')\n uniforms.uGrainAmount = { value: grain ?? 0 }\n uniforms.uGrainBanding = { value: banding }\n }\n if (deckle) {\n chunks.push(DECKLE_CHUNK)\n calls.push('plDeckle(csm_DiffuseColor);')\n uniforms.uDeckleEdges = { value: edgeFlags(deckle.edges) }\n uniforms.uDeckleRoughness = { value: deckle.roughness }\n }\n if (perforation) {\n const edges = perforation.edges === 'all' ? [...paperEdgesOrder] : perforation.edges\n chunks.push(PERFORATION_CHUNK)\n calls.push('plPerforation(csm_DiffuseColor);')\n uniforms.uPerfEdges = { value: edgeFlags(edges) }\n uniforms.uPerfTorn = {\n value: new THREE.Vector4(\n ...paperEdgesOrder.map((e) => (edges.includes(e) && perforation.state[e] === 'torn' ? 1 : 0)),\n ),\n }\n uniforms.uPerfRadius = { value: perforation.holeRadius }\n uniforms.uPerfSpacing = { value: perforation.spacing }\n uniforms.uSheetSize = { value: new THREE.Vector2(sheet.width, sheet.height) }\n }\n if (creases) {\n chunks.push(CREASE_CHUNK)\n calls.push('plCrease(csm_DiffuseColor, csm_Roughness);')\n uniforms.uCreaseAngle = { value: (creases.angle * Math.PI) / 180 }\n uniforms.uCreaseStrength = { value: creases.strength }\n uniforms.uCreasePositions = { value: padPositions(creases.positions) }\n uniforms.uCreaseCount = { value: Math.min(creases.positions.length, 4) }\n }\n if (aging !== undefined) {\n chunks.push(AGING_CHUNK)\n calls.push('plAging(csm_DiffuseColor);')\n uniforms.uAgingAmount = { value: aging }\n }\n\n const frontExpr = maps.hasFrontMap ? 'texture2D(uFrontMap, vPaperUv).rgb' : 'uStockColor'\n // The back reads correctly when the sheet is flipped → mirror x. Adhesive\n // undersides (sticker stock) are glossy near-white regardless of the front.\n const backBaseExpr = stock.adhesive\n ? 'vec3(0.965, 0.96, 0.945)'\n : maps.hasBackMap\n ? 'texture2D(uBackMap, vec2(1.0 - vPaperUv.x, vPaperUv.y)).rgb'\n : 'uStockColor'\n\n const fragmentShader = /* glsl */ `\n${HELPERS}\nuniform vec3 uStockColor;\nuniform float uOpacity;\nuniform float uShowThrough;\n${maps.hasFrontMap ? 'uniform sampler2D uFrontMap;' : ''}\n${maps.hasBackMap && !stock.adhesive ? 'uniform sampler2D uBackMap;' : ''}\n${TRANSLUCENCY_FRAGMENT}\n${chunks.join('\\n')}\nvoid main() {\n vec3 front = ${frontExpr};\n if (gl_FrontFacing) {\n csm_DiffuseColor = vec4(front, uOpacity);\n } else {\n vec3 backBase = ${backBaseExpr};\n csm_DiffuseColor = vec4(backBase * mix(vec3(1.0), front, uShowThrough), uOpacity);\n }\n ${calls.join('\\n ')}\n if (!gl_FrontFacing) csm_DiffuseColor.rgb *= uBackDarken;\n ${stock.adhesive ? '// Adhesive underside: higher specular than the printed face.\\n if (!gl_FrontFacing) csm_Roughness = 0.18;' : ''}\n // What the key light pushes through the sheet, filtered by the ink on it.\n csm_Emissive = plTransmission(front);\n}\n`\n\n return {\n structureKey: `${[\n grain !== undefined || banding > 0 ? 'g' : '',\n deckle ? 'd' : '',\n creases ? 'c' : '',\n aging !== undefined ? 'a' : '',\n perforation ? 'p' : '',\n stock.adhesive ? 'A' : '',\n ].join('')}:${maps.hasFrontMap ? 'F' : ''}${maps.hasBackMap ? 'B' : ''}`,\n vertexShader: VERTEX,\n fragmentShader,\n uniforms,\n alphaTest: deckle || perforation ? 0.5 : 0,\n }\n}\n\nfunction padPositions(positions: number[]): number[] {\n const out = positions.slice(0, 4)\n while (out.length < 4) out.push(-1)\n return out\n}\n","import { createContext, useContext, type ReactNode } from 'react'\nimport type { LightingName } from '../config/schema'\nimport { getLightingPreset, type LightingPreset } from './lighting'\n\n/**\n * The rig in force, for anything that has to agree with the lamps.\n *\n * Transmission is the reason this exists. `translucencyValues()` reads the\n * key light's own position and colour so a sheet's backlit glow can never\n * disagree with the lamp casting its shadow — but it read it from the\n * paper's OWN `scene.lighting`, and in stage mode the banners never carried\n * one. Every banner in every stage computed its glow from `studio`, a lamp\n * up and to the right, while the hall was lit by `nave` from behind. The\n * coupling was correct and the wire was missing.\n *\n * So the scene publishes the rig it is actually using, and the paper reads\n * that in preference to its own name. Outside a stage there is no provider,\n * nothing changes, and a paper lights itself as it always did.\n */\nconst LightRigContext = createContext<LightingPreset | null>(null)\n\nexport function LightRig({ rig, children }: { rig: LightingPreset; children: ReactNode }) {\n return <LightRigContext.Provider value={rig}>{children}</LightRigContext.Provider>\n}\n\n/** The scene's rig if one is published, otherwise the paper's own preset. */\nexport function useLightRig(own: LightingName): LightingPreset {\n return useContext(LightRigContext) ?? getLightingPreset(own)\n}\n","import * as THREE from 'three'\nimport { useEffect, useMemo } from 'react'\nimport CustomShaderMaterial from 'three-custom-shader-material'\nimport type { LightingName, SurfaceConfig } from '../config/schema'\nimport type { Stock } from '../core/stock'\nimport { composeSurface } from './compose'\nimport { useLightRig } from '../scene/rig'\n\nexport interface PaperMaterialProps {\n stock: Stock\n texture: THREE.Texture | null\n /** content.back rendered on the reverse side (stock color otherwise). */\n backTexture?: THREE.Texture | null\n surface: SurfaceConfig\n thickness: number\n /** World dims — perforation holes are sized in world units. */\n sheet?: { width: number; height: number }\n /**\n * Scene lighting — transmission is measured against its key light. A\n * `<LightRig>` above this material wins over it: in a stage the paper is\n * lit by the hall, not by the preset it was authored with.\n */\n lighting?: LightingName\n}\n\n/**\n * The paper's skin: MeshStandardMaterial (real lighting preserved) extended\n * with the composed surface-effect chunks. Content textures are sampled by\n * OUR fragment (not material.map) so front and back faces can differ — real\n * paper doesn't mirror its front through the sheet. Programs rebuild only\n * on structure change; value edits mutate uniforms in place.\n */\nexport function PaperMaterial({\n stock,\n texture,\n backTexture,\n surface,\n thickness,\n sheet,\n lighting = 'studio',\n}: PaperMaterialProps) {\n const rig = useLightRig(lighting)\n const composed = composeSurface(\n surface,\n stock,\n thickness,\n {\n hasFrontMap: Boolean(texture),\n hasBackMap: Boolean(backTexture),\n },\n sheet,\n rig,\n )\n\n // Uniform objects bound to the current program; stable per structure.\n // biome-ignore lint/correctness/useExhaustiveDependencies: Uniform objects are bound per shader program — rebinding on value change would drop the binding every frame.\n const bound = useMemo(() => composed.uniforms, [composed.structureKey])\n useEffect(() => {\n for (const [key, uniform] of Object.entries(composed.uniforms)) {\n if (!bound[key] || key === 'uFrontMap' || key === 'uBackMap') continue\n if (bound[key].value instanceof THREE.Color && uniform.value instanceof THREE.Color) {\n ;(bound[key].value as THREE.Color).copy(uniform.value)\n } else {\n bound[key].value = uniform.value\n }\n }\n })\n useEffect(() => {\n if (bound.uFrontMap) bound.uFrontMap.value = texture\n if (bound.uBackMap) bound.uBackMap.value = backTexture ?? null\n }, [bound, texture, backTexture])\n\n return (\n <CustomShaderMaterial\n key={composed.structureKey}\n baseMaterial={THREE.MeshStandardMaterial}\n vertexShader={composed.vertexShader}\n fragmentShader={composed.fragmentShader}\n uniforms={bound}\n color=\"#ffffff\"\n roughness={stock.roughness}\n metalness={0}\n transparent={stock.opacity < 1}\n opacity={stock.opacity}\n alphaTest={composed.alphaTest}\n side={THREE.DoubleSide}\n />\n )\n}\n","import { useEffect, useState } from 'react'\nimport type { PaperConfig } from '../config/schema'\nimport { getStock } from '../core/stock'\nimport { receiptTotals, type ReceiptContent } from '../content/receipt'\n\n/**\n * Accessibility layer: reduced-motion handling, a hidden DOM mirror so the\n * paper's content exists for screen readers and find-in-page, and a no-WebGL\n * DOM fallback.\n */\n\nexport function usePrefersReducedMotion(override?: boolean): boolean {\n const [system, setSystem] = useState(\n () => typeof window !== 'undefined' && window.matchMedia?.('(prefers-reduced-motion: reduce)').matches,\n )\n useEffect(() => {\n const query = window.matchMedia?.('(prefers-reduced-motion: reduce)')\n if (!query) return\n const onChange = () => setSystem(query.matches)\n query.addEventListener('change', onChange)\n return () => query.removeEventListener('change', onChange)\n }, [])\n return override ?? system\n}\n\nlet webglSupport: boolean | null = null\n\nexport function supportsWebGL(): boolean {\n if (webglSupport !== null) return webglSupport\n try {\n const canvas = document.createElement('canvas')\n webglSupport = Boolean(canvas.getContext('webgl2') ?? canvas.getContext('webgl'))\n } catch {\n webglSupport = false\n }\n return webglSupport\n}\n\n/** Human-readable text equivalent of a paper's content. */\nexport function contentText(config: PaperConfig): string {\n const content = config.content\n if (content.type === 'text') return content.text\n if (content.type === 'image') return content.alt ?? 'An image printed on paper.'\n if (content.type === 'receipt') {\n const totals = receiptTotals(content as ReceiptContent)\n const items = content.items.map((i) => `${i.name} ${i.price.toFixed(2)}`).join(', ')\n return `Receipt from ${content.store}: ${items}. Total ${totals.total.toFixed(2)}. ${content.footer}`\n }\n return 'A blank sheet of paper.'\n}\n\nconst visuallyHidden: React.CSSProperties = {\n position: 'absolute',\n width: 1,\n height: 1,\n padding: 0,\n margin: -1,\n overflow: 'hidden',\n clip: 'rect(0 0 0 0)',\n whiteSpace: 'nowrap',\n border: 0,\n}\n\n/** Hidden DOM twin of the 3D paper — screen readers read it, ctrl-F finds it. */\nexport function PaperMirror({ config }: { config: PaperConfig }) {\n return (\n <div style={visuallyHidden} aria-hidden={false}>\n {contentText(config)}\n </div>\n )\n}\n\n/** No WebGL: the paper renders flat — content on a stock-tinted card. */\nexport function PaperFallback({ config }: { config: PaperConfig }) {\n const stock = getStock(config.stock)\n const isImage = config.content.type === 'image'\n return (\n <div\n role=\"img\"\n aria-label={contentText(config)}\n style={{\n width: '100%',\n height: '100%',\n display: 'grid',\n placeItems: 'center',\n background: 'transparent',\n }}\n >\n <div\n style={{\n aspectRatio: `${config.sheet.width} / ${config.sheet.height}`,\n maxWidth: '80%',\n maxHeight: '90%',\n background: stock.color,\n color: stock.inkColor,\n boxShadow: '0 6px 24px rgba(0,0,0,0.25)',\n padding: '8%',\n overflow: 'hidden',\n fontFamily: config.content.type === 'receipt' ? 'ui-monospace, monospace' : 'Georgia, serif',\n whiteSpace: 'pre-wrap',\n fontSize: 14,\n }}\n >\n {isImage && config.content.type === 'image' ? (\n <img\n src={config.content.src}\n alt={config.content.alt ?? ''}\n style={{ width: '100%', height: '100%', objectFit: 'cover', margin: '-8%' }}\n />\n ) : (\n contentText(config)\n )}\n </div>\n </div>\n )\n}\n","/**\n * Stop-motion feel: quantize continuous time to animation \"twos\"\n * (12 steps per second, like shooting on twos at 24fps). Applies to\n * deformer time, idle motion, and behavior progress; the camera is\n * excluded by default — quantized cameras read as jank, not craft.\n */\nexport const ON_TWOS_FPS = 12\n\nexport function quantizeTime(t: number, fps: number = ON_TWOS_FPS): number {\n return Math.floor(t * fps) / fps\n}\n\n/** Snap a 0..1 progress that plays over `duration` seconds to whole frames. */\nexport function quantizeProgress(p: number, duration: number, fps: number = ON_TWOS_FPS): number {\n const steps = Math.max(1, Math.round(duration * fps))\n return Math.round(p * steps) / steps\n}\n","import { gsap } from 'gsap'\nimport { mergeConfig } from '../config/merge'\nimport {\n paperConfigSchema,\n paperStatesSchema,\n stateDefSchema,\n type PaperConfig,\n type StateName,\n} from '../config/schema'\n\n/**\n * The interaction-state engine. A state is a set of parameter overrides on\n * the base preset — never a separate preset (spec M6 §1.1). The machine\n * resolves each state to a full config (base + overrides), keeps ONE live\n * tween target of flattened numeric leaves, and always tweens FROM CURRENT\n * VALUES: a pointer that enters/leaves rapidly retargets the same tween\n * values instead of stacking or snapping.\n *\n * Delivery split (spec v0.2 §4: GSAP owns values, useFrame owns uploads):\n * GSAP animates the STABLE `flat` object in place; per-tick values are polled\n * off `liveConfig` by the consumer's frame loop, never pushed through React.\n * `onChange` fires only on STRUCTURAL boundaries (a transition's start and\n * settle, a state swap, a rebase) so the React tree re-renders a handful of\n * times per interaction instead of once per frame.\n */\n\n/** Built-in trigger events (v1 — user-defined wiring is parked for editor v2). */\nexport type StateEvent = 'enter' | 'leave' | 'down' | 'up' | 'pick' | 'place' | 'return'\n\n/** The fixed v1 transition table: pointer flow + pick/drop flow. */\nexport const stateEventTransitions: Record<string, Partial<Record<StateEvent, StateName>>> = {\n rest: { enter: 'hover' },\n hover: { leave: 'rest', down: 'pressed' },\n pressed: { up: 'hover', pick: 'picked' },\n picked: { place: 'placed', return: 'rest' },\n placed: {},\n}\n\nconst DEFAULT_TRANSITION = { duration: 0.35, ease: 'power2.out' }\n\n/** The base config with `states` stripped — what a state resolves against. */\nexport function stripStates(config: PaperConfig): PaperConfig {\n if (!config.states) return config\n const { states: _states, ...rest } = config\n return rest as PaperConfig\n}\n\n/**\n * Resolve a state name to its full config: base + that state's overrides.\n * States without a recorded def (e.g. an untouched 'rest') are the base.\n * The merge re-parses so a structural override (a behavior swapped to\n * `{ type: 'carry' }`) comes back with every default filled.\n */\nexport function resolveStateConfig(base: PaperConfig, state: string): PaperConfig {\n const def = base.states?.states[state]\n const flat = stripStates(base)\n if (!def || Object.keys(def.overrides).length === 0) return flat\n return paperConfigSchema.parse(mergeConfig(flat as Record<string, unknown>, def.overrides))\n}\n\n/** Drop `undefined` leaves at every depth, and any object left empty by that. */\nfunction pruneUndefined(value: unknown): unknown {\n if (value === null || typeof value !== 'object' || Array.isArray(value)) return value\n const out: Record<string, unknown> = {}\n for (const [key, v] of Object.entries(value as Record<string, unknown>)) {\n if (v === undefined) continue\n const pruned = pruneUndefined(v)\n const isEmptyObject =\n pruned !== null &&\n typeof pruned === 'object' &&\n !Array.isArray(pruned) &&\n Object.keys(pruned).length === 0\n if (!isEmptyObject) out[key] = pruned\n }\n return out\n}\n\n/**\n * Record a patch into ONE state's override diff (Figma's overridden\n * affordance), returning a new base config with that state updated — the base\n * params and every other state stay untouched. This is how an authoring tool\n * writes while a state chip is active. `undefined` values are dropped at every\n * depth: an override can only SET a base param, never remove one. Re-parsing\n * runs the schema's per-state validation, so an override that wouldn't merge\n * cleanly throws here.\n */\nexport function recordStateOverride(\n config: PaperConfig,\n stateName: string,\n patch: Record<string, unknown>,\n): PaperConfig {\n const cleaned = pruneUndefined(patch) as Record<string, unknown>\n const states = config.states ?? paperStatesSchema.parse({})\n const def = states.states[stateName] ?? stateDefSchema.parse({})\n const overrides = mergeConfig(def.overrides, cleaned) as Record<string, unknown>\n return paperConfigSchema.parse({\n ...config,\n states: {\n ...states,\n states: { ...states.states, [stateName]: { ...def, overrides } },\n },\n })\n}\n\n// ── Numeric flattening (dot paths, array indices included) ──────────────────\n\nexport function flattenNumeric(\n value: unknown,\n prefix = '',\n out: Record<string, number> = {},\n): Record<string, number> {\n if (typeof value === 'number') {\n if (prefix) out[prefix] = value\n return out\n }\n if (value !== null && typeof value === 'object') {\n const entries = Array.isArray(value)\n ? value.map((v, i) => [String(i), v] as const)\n : Object.entries(value)\n for (const [key, v] of entries) {\n flattenNumeric(v, prefix ? `${prefix}.${key}` : key, out)\n }\n }\n return out\n}\n\nfunction setPath(target: Record<string, unknown>, path: string, value: number): void {\n const keys = path.split('.')\n let node: Record<string, unknown> = target\n for (let i = 0; i < keys.length - 1; i++) {\n const next = node[keys[i]!]\n if (next === null || typeof next !== 'object') return // structure changed under us\n node = next as Record<string, unknown>\n }\n node[keys[keys.length - 1]!] = value\n}\n\n/** Apply the flat numeric leaves onto a config object in place (no allocation). */\nfunction applyFlat(target: Record<string, unknown>, flat: Record<string, number>): void {\n for (const path in flat) setPath(target, path, flat[path]!)\n}\n\nconst clone = <T>(v: T): T => JSON.parse(JSON.stringify(v)) as T\n\n// ── The machine ──────────────────────────────────────────────────────────────\n\nexport interface PaperStateMachineOptions {\n /** Reduced motion: every transition applies instantly (duration 0). */\n instant?: boolean\n /**\n * Fires on STRUCTURAL boundaries only — a transition's start and settle, a\n * state swap, a rebase — with an immutable config snapshot. NOT per tick;\n * per-frame numeric values are polled off `liveConfig`.\n */\n onChange?: (config: PaperConfig, state: string) => void\n /** `onEnter` actions — v1 is 'emit:<event>' only; fires after arrival. */\n onAction?: (event: string, state: string) => void\n}\n\nexport class PaperStateMachine {\n state: string\n private base: PaperConfig\n private readonly opts: PaperStateMachineOptions\n /** Structural target of the current state; numeric leaves live in `flat`. */\n private structure: PaperConfig\n /**\n * The single live tween target — flattened numeric leaves of the config.\n * STABLE IDENTITY for the machine's lifetime: `goto`/`rebase` mutate it in\n * place (add/remove/keep keys) and never reassign, so an in-flight GSAP\n * tween keeps animating the same object across a rebase instead of freezing.\n */\n private readonly flat: Record<string, number> = {}\n /** Mutable working config, polled by the consumer's frame loop via `liveConfig`. */\n private live: PaperConfig\n private tween: gsap.core.Tween | null = null\n private resolved = new Map<string, PaperConfig>()\n\n constructor(base: PaperConfig, opts: PaperStateMachineOptions = {}) {\n this.base = base\n this.opts = opts\n this.state = base.states?.initial ?? 'rest'\n const target = this.resolve(this.state)\n this.structure = clone(target)\n this.live = clone(target)\n Object.assign(this.flat, flattenNumeric(target))\n }\n\n /** World-units drag distance that flips pressed → picked. */\n get pickThreshold(): number {\n return this.base.states?.pickThreshold ?? 0.1\n }\n\n /**\n * The live config — the mutable working object with the current tween values\n * applied in place. Cheap (no allocation); meant to be polled every frame.\n * Never hand this to React; use `structuralConfig()` for an immutable snapshot.\n */\n get liveConfig(): PaperConfig {\n applyFlat(this.live as unknown as Record<string, unknown>, this.flat)\n return this.live\n }\n\n /** Back-compat alias for `liveConfig` (tests, imperative reads). */\n get config(): PaperConfig {\n return this.liveConfig\n }\n\n /** True while a transition tween is in flight — consumers gate frame work on it. */\n get transitioning(): boolean {\n return this.tween !== null\n }\n\n /** Exposed for tests: the in-flight transition tween, if any. */\n get activeTween(): gsap.core.Tween | null {\n return this.tween\n }\n\n /** An immutable structural snapshot for React consumers (never the live object). */\n structuralConfig(): PaperConfig {\n const out = clone(this.structure) as unknown as Record<string, unknown>\n applyFlat(out, this.flat)\n return out as unknown as PaperConfig\n }\n\n /** Fire a built-in trigger; returns the new state or null if it doesn't apply. */\n send(event: StateEvent): string | null {\n const next = stateEventTransitions[this.state]?.[event]\n if (!next || next === this.state) return null\n this.goto(next)\n return next\n }\n\n /**\n * Drive to 'picked' through the legal chain (rest→hover→pressed→picked),\n * each hop instant so EVERY side effect fires (behavior override, backing\n * silhouette, onChange state reports, placed onEnter chain). This is the\n * keyboard/a11y entry point — it never produced pointer hover/press events,\n * so raw `send('pick')` from 'rest' was a no-op. Returns true if it landed.\n */\n pickProgrammatic(): boolean {\n for (const event of ['enter', 'down', 'pick'] as StateEvent[]) {\n const next = stateEventTransitions[this.state]?.[event]\n if (next && next !== this.state) this.goto(next, { instant: true })\n }\n return this.state === 'picked'\n }\n\n /** Instant, legal place (picked → placed) so onEnter/emit fires. */\n placeProgrammatic(): boolean {\n return this.driveInstant('place')\n }\n\n /** Instant, legal return (picked → rest). */\n returnProgrammatic(): boolean {\n return this.driveInstant('return')\n }\n\n private driveInstant(event: StateEvent): boolean {\n const next = stateEventTransitions[this.state]?.[event]\n if (!next || next === this.state) return false\n this.goto(next, { instant: true })\n return true\n }\n\n /** Transition to a state (escape hatch for custom states; `send` for triggers). */\n goto(state: string, opts?: { instant?: boolean }): void {\n const def = this.base.states?.states[state]\n const target = this.resolve(state)\n this.state = state\n\n const targetFlat = flattenNumeric(target)\n // Structure swaps immediately (content/stock changes don't interpolate);\n // numeric leaves keep their CURRENT values and tween to the target.\n this.structure = clone(target)\n this.live = clone(target)\n const changed: Record<string, number> = {}\n // Mutate `flat` in place (stable identity): drop stale keys, keep live\n // values for shared paths, seed new paths at their target.\n for (const path in this.flat) {\n if (!(path in targetFlat)) delete this.flat[path]\n }\n for (const [path, value] of Object.entries(targetFlat)) {\n const current = this.flat[path]\n // Paths new to this structure appear at their target value — there is\n // no current value to tween from.\n if (current === undefined) this.flat[path] = value\n else if (current !== value) changed[path] = value\n }\n\n const duration =\n this.opts.instant || opts?.instant ? 0 : (def?.transition.duration ?? DEFAULT_TRANSITION.duration)\n const ease = def?.transition.ease ?? DEFAULT_TRANSITION.ease\n\n // One tween, ever — kill the previous instead of stacking. Values pick up\n // exactly where the killed tween left them (this.flat is the target).\n this.tween?.kill()\n this.tween = null\n\n const arrive = () => {\n for (const [path, value] of Object.entries(changed)) this.flat[path] = value\n this.emitStructure()\n for (const action of def?.onEnter ?? []) {\n if (action.startsWith('emit:')) this.opts.onAction?.(action.slice(5), state)\n }\n }\n\n if (duration === 0 || Object.keys(changed).length === 0) {\n arrive()\n return\n }\n // Structural boundary #1: the start of the transition (React sees the new\n // state and structure). Ticks below never emit — GSAP mutates `flat`, the\n // consumer polls `liveConfig`; #2 is the settle in `arrive`.\n this.emitStructure()\n this.tween = gsap.to(this.flat, {\n ...changed,\n duration,\n ease,\n onComplete: () => {\n this.tween = null\n arrive()\n },\n })\n }\n\n /**\n * Swap the base config without resetting the machine — parameter edits and\n * runtime patches (torn perforation on detach) keep the current state and\n * live values instead of snapping back to `initial`. An in-flight tween is\n * left running on the SAME `flat` object, so the transition continues\n * smoothly to its target across the rebase (no freeze, no snap).\n */\n rebase(base: PaperConfig): void {\n this.base = base\n this.resolved.clear()\n const target = this.resolve(this.state)\n this.structure = clone(target)\n this.live = clone(target)\n const targetFlat = flattenNumeric(target)\n // In-place, identity-preserving: drop stale keys, seed genuinely new paths\n // at target, keep every existing (possibly mid-tween) value untouched.\n for (const path in this.flat) {\n if (!(path in targetFlat)) delete this.flat[path]\n }\n for (const [path, value] of Object.entries(targetFlat)) {\n if (!(path in this.flat)) this.flat[path] = value\n }\n // Structural change (e.g. perforation flipped to torn) → re-render the\n // structure; the tween keeps animating `flat`, so values never snap.\n this.emitStructure()\n }\n\n dispose(): void {\n this.tween?.kill()\n this.tween = null\n }\n\n private resolve(state: string): PaperConfig {\n let config = this.resolved.get(state)\n if (!config) {\n config = resolveStateConfig(this.base, state)\n this.resolved.set(state, config)\n }\n return config\n }\n\n private emitStructure(): void {\n this.opts.onChange?.(this.structuralConfig(), this.state)\n }\n}\n","import { useEffect, useMemo, useRef, useState } from 'react'\nimport type { PaperConfig } from '../config/schema'\nimport { PaperStateMachine, stripStates } from './machine'\n\nexport interface UsePaperStatesResult {\n /** The config to render this frame — animated when a machine is live. */\n config: PaperConfig\n /** Current state name ('rest' when no machine). */\n state: string\n /** Send triggers through this; null when states are absent or disabled. */\n machine: PaperStateMachine | null\n}\n\n/**\n * Bind a state machine to a config with `states`. The machine survives\n * config edits via `rebase` (current state and live values are kept —\n * flipping perforation to torn mid-pick must not snap the stamp to rest);\n * it is only rebuilt when states are toggled on/off.\n *\n * `animated` holds an IMMUTABLE structural snapshot for the React tree; it\n * updates only on structural boundaries (transition start/settle, state swap,\n * rebase), not per frame. Per-tick numeric values are read straight off\n * `machine.liveConfig` by the caller's frame loop — GSAP owns values, useFrame\n * owns uploads. `machine` is returned so the caller can poll it.\n */\nexport function usePaperStates(\n config: PaperConfig,\n enabled: boolean,\n instant: boolean,\n onAction?: (event: string, state: string) => void,\n onStateChange?: (state: string) => void,\n): UsePaperStatesResult {\n const live = enabled && Boolean(config.states)\n const key = useMemo(() => JSON.stringify(config), [config])\n\n // Callbacks live in refs so machine identity doesn't churn on new closures.\n const onActionRef = useRef(onAction)\n onActionRef.current = onAction\n const onStateChangeRef = useRef(onStateChange)\n onStateChangeRef.current = onStateChange\n\n const machineRef = useRef<PaperStateMachine | null>(null)\n const lastStateRef = useRef<string>('rest')\n const [animated, setAnimated] = useState<{ config: PaperConfig; state: string } | null>(null)\n\n // biome-ignore lint/correctness/useExhaustiveDependencies: key serializes the config — the machine rebases onto a new config instead of being rebuilt.\n useEffect(() => {\n if (!live) {\n machineRef.current?.dispose()\n machineRef.current = null\n setAnimated(null)\n return\n }\n if (machineRef.current) {\n machineRef.current.rebase(config)\n return\n }\n const machine = new PaperStateMachine(config, {\n instant,\n // Structural boundaries only (not per tick) — safe to route to React.\n onChange: (c, state) => {\n if (state !== lastStateRef.current) {\n lastStateRef.current = state\n onStateChangeRef.current?.(state)\n }\n setAnimated({ config: c, state })\n },\n onAction: (event, state) => onActionRef.current?.(event, state),\n })\n machineRef.current = machine\n lastStateRef.current = machine.state\n setAnimated({ config: machine.structuralConfig(), state: machine.state })\n }, [key, live, instant])\n\n useEffect(\n () => () => {\n machineRef.current?.dispose()\n machineRef.current = null\n },\n [],\n )\n\n return {\n config: live && animated ? animated.config : stripStates(config),\n state: live && animated ? animated.state : 'rest',\n machine: live ? machineRef.current : null,\n }\n}\n","import * as THREE from 'three'\nimport { gsap } from 'gsap'\nimport { useFrame, useThree } from '@react-three/fiber'\nimport type { ThreeEvent } from '@react-three/fiber'\nimport { forwardRef, useEffect, useImperativeHandle, useMemo, useRef } from 'react'\nimport type {\n BehaviorConfigInput,\n ClothConfig,\n ContentConfigInput,\n DeformerInstanceConfigInput,\n PaperConfig,\n PaperConfigInput,\n PhysicsConfigInput,\n SceneConfigInput,\n SheetConfig,\n StockName,\n SurfaceConfigInput,\n} from './config/schema'\nimport { paperConfigSchema } from './config/schema'\nimport { mergeConfig, parsePreset, serializePreset } from './config/serialize'\nimport { computeSheetNormals } from './core/normals'\nimport { useStable } from './core/stable'\nimport { createSheetGeometry, resolveSegments } from './core/sheet'\nimport { FLAT_SEGMENTS, type SegmentPair } from './core/tessellation'\nimport { getStock } from './core/stock'\nimport { getPreset } from './config/presets'\nimport { useContentTexture } from './content/texture'\nimport { applyDeformerStack, displacePoint, stackAutoSegments, stackMinSegments } from './deformers/compose'\nimport { stackIsAnimated } from './deformers/registry'\nimport type { DeformerInstance } from './deformers/types'\nimport { getBehavior } from './behaviors/registry'\nimport { resolveDeformerStack } from './deformers/registry'\nimport type { Behavior } from './behaviors/types'\nimport { getIdlePreset, type IdleName, type IdlePose } from './physics/idle'\nimport { ClothSim } from './physics/cloth'\nimport { PaperMaterial } from './surface/PaperMaterial'\nimport { usePrefersReducedMotion } from './a11y'\nimport { quantizeProgress, quantizeTime } from './motion/onTwos'\nimport { usePaperStates } from './states/usePaperStates'\nimport type { PaperStateMachine, StateEvent } from './states/machine'\n\nexport interface PaperMeshProps {\n /** Built-in preset name, or a (partial) preset object. Props below override it. */\n preset?: string | PaperConfigInput\n sheet?: Partial<SheetConfig>\n stock?: StockName\n /**\n * These take the schema's INPUT types, not its parsed ones: writing\n * `content={{ type: 'text', text: 'hi' }}` has to compile, and with the\n * inferred type it does not — it demands every field of every nested\n * object. Every default stays a default.\n */\n content?: ContentConfigInput\n behavior?: BehaviorConfigInput\n deformers?: DeformerInstanceConfigInput[]\n /** Fragment-side effects: grain, aging, deckle, creases, perforation. */\n surface?: SurfaceConfigInput\n /** Scene-level presentation that travels with the paper (lighting). */\n scene?: SceneConfigInput\n physics?: PhysicsConfigInput | 'cloth'\n onTwos?: boolean\n /** Show draggable behavior handles; cloth sheets become grabbable. */\n interactive?: boolean\n /** Start the behavior's transport loop on mount. */\n autoplay?: boolean\n /** Override prefers-reduced-motion (default: follow the system setting). */\n reducedMotion?: boolean\n position?: [number, number, number]\n rotation?: [number, number, number]\n /** Fires every animation tick with the behavior's progress (0..1). */\n onProgress?(value: number): void\n /** Fires when a handle drag ends, with the params the drag changed. */\n onBehaviorChange?(patch: Record<string, unknown>): void\n /**\n * Interaction states: when the config carries `states`, pointer triggers\n * are live by default. Set false to sculpt a stateful paper without the\n * machine firing (the editor's state-editing mode).\n */\n stateTriggers?: boolean\n /** Fires when the state machine changes state. */\n onStateChange?(state: string): void\n /** Fires for `onEnter` actions ('emit:<event>'). */\n onStateAction?(event: string, state: string): void\n}\n\nexport interface PaperHandle {\n play(): void\n pause(): void\n readonly playing: boolean\n /** Live-override a behavior param. 'progress' always maps to the behavior's progress param. */\n set(param: string, value: unknown): void\n getProgress(): number\n /** Current full state (including live overrides) as a preset. */\n snapshot(): PaperConfig\n toJSON(): string\n readonly mesh: THREE.Mesh | null\n /**\n * Where a behavior's grab point currently sits, in world space, or null\n * when the behavior has no handles (or `interactive` is off).\n *\n * The handle is not at the corner it names: it rides the deformed surface,\n * so its position is only known after the frame's deformer stack has run.\n * Anything that wants to point AT the handle — a coach-mark, a tooltip,\n * an arrow — has to ask the frame rather than compute a UV, which is why\n * reading it is a method here and not a prop the sheet could publish.\n *\n * Written into `target` when one is passed, so a per-frame reader does not\n * allocate a vector sixty times a second.\n */\n handlePoint(id?: string, target?: THREE.Vector3): THREE.Vector3 | null\n /** Interaction-state machine access (null when the config has no states). */\n readonly state: string\n sendState(event: StateEvent): string | null\n /**\n * Drive to 'picked' through the legal chain (rest→hover→pressed→picked),\n * instantly, so every side effect fires — the keyboard/a11y entry point\n * where no pointer hover/press ever ran. Returns true if it landed.\n */\n pickProgrammatic(): boolean\n /** Instant, legal place (picked → placed) so onEnter/emit fires. */\n placeProgrammatic(): boolean\n /** Instant, legal return (picked → rest). */\n returnProgrammatic(): boolean\n}\n\n/**\n * Everything {@link resolveConfig} reads, as a plain tuple.\n *\n * Compared with {@link useStable} rather than serialized: a dependency array\n * is evaluated on EVERY render, and `content` can hold a whole bitmap as a\n * data URL, so a `JSON.stringify` here was megabytes of garbage per frame of\n * a slider drag. (There was a `resolveConfigKey` exporting the string form\n * for consumers to key their own caches on; it was never part of the package\n * entry, so no consumer could reach it, and nothing else uses it now.)\n */\nfunction configInputs(props: PaperMeshProps): unknown[] {\n return [\n props.preset ?? null,\n props.sheet ?? null,\n props.stock ?? null,\n props.content ?? null,\n props.behavior ?? null,\n props.deformers ?? null,\n props.surface ?? null,\n props.scene ?? null,\n props.physics ?? null,\n props.onTwos ?? null,\n ]\n}\n\n/** Resolve once, and again only when the inputs actually differ. */\nexport function useResolvedConfig(props: PaperMeshProps): PaperConfig {\n const inputs = useStable(configInputs(props))\n // biome-ignore lint/correctness/useExhaustiveDependencies: `inputs` IS every prop resolveConfig reads; the props object itself is new each render.\n return useMemo(() => resolveConfig(props), [inputs])\n}\n\n/** Resolve preset + prop overrides into a validated config. */\nexport function resolveConfig(props: PaperMeshProps): PaperConfig {\n const base = props.preset\n ? typeof props.preset === 'string'\n ? getPreset(props.preset)\n : parsePreset(props.preset)\n : paperConfigSchema.parse({})\n const overrides: PaperConfigInput = {}\n if (props.sheet) overrides.sheet = { ...base.sheet, ...props.sheet }\n if (props.stock) overrides.stock = props.stock\n if (props.content) overrides.content = props.content\n if (props.behavior) overrides.behavior = props.behavior\n if (props.deformers) overrides.deformers = props.deformers\n // Surface merges over the stock's defaults rather than replacing them, so\n // `surface={{ grain: 0.6 }}` on thermal keeps thermal's banding.\n if (props.surface) overrides.surface = { ...base.surface, ...props.surface }\n if (props.scene) overrides.scene = { ...base.scene, ...props.scene }\n if (props.physics) overrides.physics = props.physics\n if (props.onTwos !== undefined) overrides.onTwos = props.onTwos\n return paperConfigSchema.parse(mergeConfig(base as PaperConfigInput, overrides))\n}\n\n/** Cloth grids cap their resolution — 5k verlet particles is the budget ceiling. */\nconst CLOTH_MAX_SEGMENTS = 28\n\n/** Where `'auto'` probes a behavior's sweep. Endpoints matter most — a play\n * usually starts or ends at its tightest. */\nconst PROGRESS_SAMPLES = [0, 0.25, 0.5, 0.75, 1] as const\n\nconst dragPlane = new THREE.Plane()\nconst dragPoint = new THREE.Vector3()\nconst planeNormal = new THREE.Vector3()\nconst anchorScratch = new THREE.Vector3()\nconst worldScratch = new THREE.Vector3()\nconst quatScratch = new THREE.Quaternion()\n\n/**\n * The atom: one sheet of paper, hero-mode CPU path. The deformer stack (or\n * the cloth sim — never both) writes geometry positions each frame. GSAP\n * owns animated values; useFrame owns geometry writes.\n */\nexport const PaperMesh = forwardRef<PaperHandle, PaperMeshProps>(function PaperMesh(props, ref) {\n // Each resolveConfig call is several zod parses (superRefine re-parses every\n // state override) — memoized so a render without config-prop changes is free.\n const resolved = useResolvedConfig(props)\n // Reduced motion: behaviors freeze at their resting pose, physics is off,\n // idle motion is off. The sheet still renders fully sculpted.\n const reduced = usePrefersReducedMotion(props.reducedMotion)\n // Interaction states: the machine animates a live config between state\n // overrides; `config` below is that animated view (the base when no states).\n // Reduced motion keeps the machine but makes transitions instant.\n const statesLive = Boolean(resolved.states) && props.stateTriggers !== false\n const {\n config,\n machine,\n state: machineState,\n } = usePaperStates(resolved, statesLive, reduced, props.onStateAction, props.onStateChange)\n const behavior: Behavior | null = config.behavior ? getBehavior(config.behavior.type) : null\n const machineRef = useRef<PaperStateMachine | null>(null)\n machineRef.current = machine\n // The animated `config` has `states` stripped — keep the resolved preset\n // around so snapshot()/toJSON() never lose the state machine.\n const resolvedRef = useRef(resolved)\n resolvedRef.current = resolved\n const isCloth = !reduced && typeof config.physics === 'object'\n const idle =\n !reduced && typeof config.physics === 'string' && config.physics !== 'none'\n ? getIdlePreset(config.physics as IdleName)\n : null\n\n const meshRef = useRef<THREE.Mesh>(null)\n const groupRef = useRef<THREE.Group>(null)\n const handleRefs = useRef<(THREE.Mesh | null)[]>([])\n\n const overridesRef = useRef<Record<string, unknown>>({})\n const dirtyRef = useRef(true)\n const playingRef = useRef(false)\n const tweenRef = useRef<gsap.core.Tween | null>(null)\n const draggingRef = useRef<string | null>(null)\n\n const configRef = useRef(config)\n configRef.current = config\n\n const controls = useThree((s) => s.controls) as { enabled?: boolean } | null\n const camera = useThree((s) => s.camera)\n\n const behaviorKey = JSON.stringify(config.behavior ?? null)\n const deformersKey = JSON.stringify(config.deformers ?? null)\n const sheetKey = JSON.stringify(config.sheet)\n const physicsKey = JSON.stringify(config.physics)\n\n // biome-ignore lint/correctness/useExhaustiveDependencies: The keys are change triggers; the body only touches refs.\n useEffect(() => {\n if (!draggingRef.current && !playingRef.current) overridesRef.current = {}\n dirtyRef.current = true\n }, [behaviorKey, deformersKey, sheetKey, physicsKey])\n\n // biome-ignore lint/correctness/useExhaustiveDependencies: Keyed on the stack shape — the probe reads config off a ref.\n const { minSegments, autoSegments, animatedStack } = useMemo(() => {\n const cfg = configRef.current\n const probe = buildStack(cfg, {})\n if (!probe) {\n return {\n minSegments: [2, 2] as SegmentPair,\n autoSegments: [FLAT_SEGMENTS, FLAT_SEGMENTS] as SegmentPair,\n animatedStack: false,\n }\n }\n\n // The grid is built once; a behavior's stack is not the same shape all\n // the way through. An unroll is a tight roll at one end of its progress\n // and a flat sheet at the other, so sizing to the configured moment\n // would leave the sheet under-tessellated for the rest of the play.\n // Sample the sweep and keep the densest answer. Every behavior's\n // progressParam is a 0..1 number — pinned by behaviors.test.ts, because\n // this loop silently samples the wrong range if that ever stops holding.\n //\n // Whether the stack is TIME-DRIVEN is answered off the same sweep, and\n // for the same reason: it is a property of the stack's shape, not of the\n // moment it happens to be at, and the frame loop needs it before it has\n // built anything — see `useFrame` below.\n const want = stackAutoSegments(probe, cfg.sheet)\n let animated = stackIsAnimated(probe)\n if (cfg.behavior && !cfg.deformers) {\n const param = getBehavior(cfg.behavior.type).progressParam\n for (const p of PROGRESS_SAMPLES) {\n const at = buildStack(cfg, { [param]: p })\n if (!at) continue\n const [x, y] = stackAutoSegments(at, cfg.sheet)\n if (x > want[0]) want[0] = x\n if (y > want[1]) want[1] = y\n animated ||= stackIsAnimated(at)\n }\n }\n return {\n minSegments: stackMinSegments(probe, cfg.sheet),\n autoSegments: want,\n animatedStack: animated,\n }\n }, [behaviorKey, deformersKey, physicsKey])\n\n // biome-ignore lint/correctness/useExhaustiveDependencies: Keyed on the sheet — rebuilding geometry on identity would orphan GPU buffers every render.\n const geometry = useMemo(() => {\n if (!isCloth) return createSheetGeometry(config.sheet, minSegments, autoSegments)\n // Cloth: explicit capped grid so sim particles == mesh vertices.\n const [sx, sy] = resolveSegments(config.sheet, 2)\n const capped = Math.min(Math.max(sx, sy), CLOTH_MAX_SEGMENTS)\n return new THREE.PlaneGeometry(config.sheet.width, config.sheet.height, capped, capped)\n }, [sheetKey, minSegments, autoSegments, isCloth])\n\n // Imperatively-created geometry is ours to free — R3F only auto-disposes\n // JSX-created objects, so a sheet change would otherwise orphan GPU buffers.\n useEffect(() => () => geometry.dispose(), [geometry])\n\n const basePositions = useMemo(\n () => Float32Array.from(geometry.attributes.position!.array as Float32Array),\n [geometry],\n )\n\n // biome-ignore lint/correctness/useExhaustiveDependencies: Rebuild only on geometry or pin layout change — sliders update the sim in place.\n const sim = useMemo(() => {\n if (!isCloth) return null\n const cloth = configRef.current.physics as ClothConfig\n const cols = (geometry.parameters as { widthSegments: number }).widthSegments + 1\n const rows = (geometry.parameters as { heightSegments: number }).heightSegments + 1\n return new ClothSim(cols, rows, config.sheet.width, config.sheet.height, cloth.pins, {\n stiffness: cloth.stiffness,\n gravity: cloth.gravity,\n wind: cloth.wind,\n floor: cloth.floor,\n })\n }, [geometry, isCloth, isCloth ? (config.physics as ClothConfig).pins : ''])\n\n const stock = getStock(config.stock)\n const texture = useContentTexture(config.content, config.sheet, stock)\n const backTexture = useContentTexture(config.content.back, config.sheet, stock)\n\n // Per-frame config: when a state machine is live it OWNS the animated numeric\n // values (GSAP tweens them); we poll its mutable liveConfig each frame rather\n // than routing every tick through React. Falls back to the React config for\n // non-stateful papers.\n const liveConfig = (): PaperConfig => machineRef.current?.liveConfig ?? configRef.current\n\n const effectiveOptions = (t: number): Record<string, unknown> | null => {\n const cfg = liveConfig()\n if (!cfg.behavior || !behavior) return null\n const o = { ...cfg.behavior, ...overridesRef.current }\n return behavior.loop ? { ...o, ...behavior.loop(o, t) } : o\n }\n\n const play = () => {\n if (!behavior) return\n playingRef.current = true\n if (tweenRef.current) {\n tweenRef.current.play()\n return\n }\n const param = behavior.progressParam\n const start = (effectiveOptions(0)?.[param] as number) ?? 0\n const state = { p: start }\n tweenRef.current = gsap.to(state, {\n p: 1,\n duration: behavior.duration * (1 - start),\n ease: 'power2.inOut',\n yoyo: behavior.loopMode === 'yoyo',\n repeat: -1,\n onRepeat: () => {\n if (behavior.loopMode === 'restart') state.p = 0\n },\n onUpdate: () => {\n const p = configRef.current.onTwos ? quantizeProgress(state.p, behavior.duration) : state.p\n overridesRef.current[param] = p\n dirtyRef.current = true\n props.onProgress?.(p)\n },\n })\n }\n\n const pause = () => {\n playingRef.current = false\n tweenRef.current?.pause()\n }\n\n // biome-ignore lint/correctness/useExhaustiveDependencies: Mount-only: autoplay starts once, and the cleanup kills the tween on unmount.\n useEffect(() => {\n if (props.autoplay && !reduced) play()\n return () => {\n tweenRef.current?.kill()\n tweenRef.current = null\n }\n }, [])\n\n const snapshot = (): PaperConfig => {\n // Re-attach `states`: the rendered config is the animated view with the\n // machine stripped, but a snapshot is a preset — states are part of it.\n const states = resolvedRef.current.states\n const cfg = states ? { ...configRef.current, states } : configRef.current\n if (!cfg.behavior) return states ? paperConfigSchema.parse(cfg) : cfg\n return paperConfigSchema.parse({\n ...cfg,\n behavior: { ...cfg.behavior, ...overridesRef.current },\n })\n }\n\n useImperativeHandle(ref, () => ({\n play,\n pause,\n get playing() {\n return playingRef.current\n },\n set(param: string, value: unknown) {\n const key = param === 'progress' && behavior ? behavior.progressParam : param\n overridesRef.current[key] = value\n dirtyRef.current = true\n if (behavior && key === behavior.progressParam) props.onProgress?.(value as number)\n },\n getProgress() {\n if (!behavior) return 0\n return (effectiveOptions(0)?.[behavior.progressParam] as number) ?? 0\n },\n snapshot,\n toJSON: () => serializePreset(snapshot()),\n get mesh() {\n return meshRef.current\n },\n handlePoint(id?: string, target?: THREE.Vector3) {\n const handles = behavior?.handles\n if (!handles?.length) return null\n const index = id ? handles.findIndex((h) => h.id === id) : 0\n const mesh = handleRefs.current[index]\n if (!mesh) return null\n return mesh.getWorldPosition(target ?? new THREE.Vector3())\n },\n get state() {\n return machineState\n },\n sendState: (event: StateEvent) => machineRef.current?.send(event) ?? null,\n pickProgrammatic: () => machineRef.current?.pickProgrammatic() ?? false,\n placeProgrammatic: () => machineRef.current?.placeProgrammatic() ?? false,\n returnProgrammatic: () => machineRef.current?.returnProgrammatic() ?? false,\n }))\n\n const idlePose = useRef<IdlePose>({ position: [0, 0, 0], rotation: [0, 0, 0] })\n\n useFrame(({ clock }, delta) => {\n const cfg = liveConfig()\n // Reduced motion freezes time-driven deformers at their resting phase.\n const now = reduced ? 0 : cfg.onTwos ? quantizeTime(clock.elapsedTime) : clock.elapsedTime\n\n // Whole-sheet motion — idle presets and behavior transforms (flight's\n // travel across the scene) compose additively; vertices stay untouched.\n const hasBehaviorTransform = Boolean(behavior?.transform && cfg.behavior)\n if ((idle?.transform || hasBehaviorTransform) && groupRef.current) {\n const pose = idlePose.current\n pose.position[0] = pose.position[1] = pose.position[2] = 0\n pose.rotation[0] = pose.rotation[1] = pose.rotation[2] = 0\n idle?.transform?.(now, pose)\n if (hasBehaviorTransform) {\n const o = effectiveOptions(now)\n if (o) behavior!.transform!(o, now, pose)\n }\n const base = props.position ?? [0, 0, 0]\n const baseRot = props.rotation ?? [0, 0, 0]\n groupRef.current.position.set(\n base[0] + pose.position[0],\n base[1] + pose.position[1],\n base[2] + pose.position[2],\n )\n groupRef.current.rotation.set(\n baseRot[0] + pose.rotation[0],\n baseRot[1] + pose.rotation[1],\n baseRot[2] + pose.rotation[2],\n )\n }\n\n // Simulation path: cloth owns the vertices.\n if (isCloth && sim) {\n const cloth = cfg.physics as ClothConfig\n sim.setParams({\n wind: cloth.wind,\n gravity: cloth.gravity,\n stiffness: cloth.stiffness,\n floor: cloth.floor,\n })\n sim.step(delta)\n if (!sim.asleep) {\n const position = geometry.attributes.position as THREE.BufferAttribute\n ;(position.array as Float32Array).set(sim.positions)\n position.needsUpdate = true\n computeSheetNormals(geometry)\n }\n return\n }\n\n // Shape path: the deformer stack.\n //\n // Decide whether there is anything to do BEFORE building it. A resting\n // sheet — no loop, no time-driven deformer, no transition, nothing\n // dirtied — used to expand its whole stack every frame and throw it\n // away, which is a behavior's `stack()` call and its deformer objects\n // sixty times a second for a picture that does not move.\n const animated = !reduced && animatedStack\n const hasLoop = !reduced && Boolean(cfg.behavior && behavior?.loop)\n // A state transition tweens numeric leaves off the React path, so the\n // stack must re-apply every frame while the machine is transitioning.\n const machineAnimating = Boolean(machineRef.current?.transitioning)\n if (!dirtyRef.current && !hasLoop && !animated && !machineAnimating) return\n\n const stack = buildStack(cfg, overridesRef.current, behavior, now)\n if (!stack) return\n dirtyRef.current = false\n\n const ctx = { t: now, sheet: cfg.sheet }\n applyDeformerStack(geometry, basePositions, stack, ctx)\n\n if (props.interactive && behavior?.handles) {\n const o = effectiveOptions(now)\n behavior.handles.forEach((h, i) => {\n const mesh = handleRefs.current[i]\n if (!mesh || !o) return\n const [u, v] = h.anchor(o, cfg.sheet)\n anchorScratch.set((u - 0.5) * cfg.sheet.width, (v - 0.5) * cfg.sheet.height, 0)\n displacePoint(anchorScratch, u, v, stack, ctx)\n mesh.position.copy(anchorScratch)\n })\n }\n })\n\n const localDragPoint = (e: ThreeEvent<PointerEvent>): { x: number; y: number } | null => {\n const group = groupRef.current\n if (!group) return null\n planeNormal.set(0, 0, 1).applyQuaternion(group.getWorldQuaternion(quatScratch))\n dragPlane.setFromNormalAndCoplanarPoint(planeNormal, group.getWorldPosition(dragPoint))\n const hit = e.ray.intersectPlane(dragPlane, dragPoint)\n if (!hit) return null\n group.worldToLocal(hit)\n return { x: hit.x, y: hit.y }\n }\n\n const onHandleDrag = (e: ThreeEvent<PointerEvent>) => {\n if (!behavior?.handles || !draggingRef.current) return\n const handleSpec = behavior.handles.find((h) => h.id === draggingRef.current)\n const local = localDragPoint(e)\n const o = effectiveOptions(0)\n if (!handleSpec || !local || !o) return\n Object.assign(overridesRef.current, handleSpec.drag(local, o, configRef.current.sheet))\n dirtyRef.current = true\n const p = overridesRef.current[behavior.progressParam]\n if (typeof p === 'number') props.onProgress?.(p)\n }\n\n // Cloth grab: pick the nearest particle, then drag it on a camera-facing\n // plane through the grab point — full 3D pull, not just in-plane.\n const grabAnchor = useRef(new THREE.Vector3())\n const clothDown = (e: ThreeEvent<PointerEvent>) => {\n if (!isCloth || !sim || !props.interactive || !groupRef.current) return\n e.stopPropagation()\n if (controls) controls.enabled = false\n grabAnchor.current.copy(e.point) // world-space anchor for the drag plane\n const local = groupRef.current.worldToLocal(worldScratch.copy(e.point))\n sim.grabNearest(local.x, local.y, local.z)\n draggingRef.current = 'cloth'\n ;(e.target as Element).setPointerCapture(e.pointerId)\n }\n const clothMove = (e: ThreeEvent<PointerEvent>) => {\n if (draggingRef.current !== 'cloth' || !sim || !groupRef.current) return\n camera.getWorldDirection(planeNormal)\n dragPlane.setFromNormalAndCoplanarPoint(planeNormal, grabAnchor.current)\n const hit = e.ray.intersectPlane(dragPlane, dragPoint)\n if (!hit) return\n groupRef.current.worldToLocal(hit)\n sim.moveGrab(hit.x, hit.y, hit.z)\n }\n const clothUp = (e: ThreeEvent<PointerEvent>) => {\n if (draggingRef.current !== 'cloth' || !sim) return\n draggingRef.current = null\n if (controls) controls.enabled = true\n sim.release()\n ;(e.target as Element).releasePointerCapture(e.pointerId)\n }\n\n // Interaction-state triggers (rest ↔ hover ↔ pressed); pick/place/return\n // are driven by the field's carry controller through `sendState`.\n const sendState = (event: StateEvent) => machineRef.current?.send(event)\n\n return (\n <group ref={groupRef} position={props.position} rotation={props.rotation}>\n <mesh\n ref={meshRef}\n geometry={geometry}\n castShadow\n receiveShadow\n frustumCulled={false}\n onPointerOver={statesLive ? () => sendState('enter') : undefined}\n onPointerOut={statesLive ? () => sendState('leave') : undefined}\n onPointerDown={\n isCloth || statesLive\n ? (e) => {\n if (isCloth) clothDown(e)\n if (statesLive) sendState('down')\n }\n : undefined\n }\n onPointerMove={isCloth ? clothMove : undefined}\n onPointerUp={\n isCloth || statesLive\n ? (e) => {\n if (isCloth) clothUp(e)\n if (statesLive) sendState('up')\n }\n : undefined\n }\n >\n <PaperMaterial\n stock={stock}\n texture={texture}\n backTexture={backTexture}\n surface={config.surface}\n thickness={config.sheet.thickness}\n sheet={config.sheet}\n lighting={config.scene.lighting}\n />\n </mesh>\n {props.interactive &&\n !isCloth &&\n behavior?.handles?.map((h, i) => (\n <mesh\n key={h.id}\n ref={(m) => {\n handleRefs.current[i] = m\n }}\n onPointerDown={(e) => {\n e.stopPropagation()\n draggingRef.current = h.id\n pause()\n if (controls) controls.enabled = false\n ;(e.target as Element).setPointerCapture(e.pointerId)\n }}\n onPointerMove={onHandleDrag}\n onPointerUp={(e) => {\n if (!draggingRef.current) return\n draggingRef.current = null\n if (controls) controls.enabled = true\n ;(e.target as Element).releasePointerCapture(e.pointerId)\n props.onBehaviorChange?.({ ...overridesRef.current })\n }}\n >\n <sphereGeometry args={[0.035, 16, 16]} />\n <meshBasicMaterial color=\"#4f7cff\" depthTest={false} transparent opacity={0.9} />\n </mesh>\n ))}\n </group>\n )\n})\n\n/** Expand the config into the deformer stack that should run this frame. */\nfunction buildStack(\n config: PaperConfig,\n overrides: Record<string, unknown>,\n behavior?: Behavior | null,\n t = 0,\n): DeformerInstance[] | null {\n // Cloth owns the vertices — no deformer stack.\n if (typeof config.physics === 'object') return null\n const idle =\n typeof config.physics === 'string' && config.physics !== 'none'\n ? getIdlePreset(config.physics as IdleName)\n : null\n const idleStack = idle?.stack?.() ?? []\n\n let shapeStack: DeformerInstance[] = []\n if (config.deformers) {\n // Raw deformer stack wins — it's the Advanced fork of a behavior.\n shapeStack = resolveDeformerStack(config.deformers)\n } else if (config.behavior) {\n const b = behavior ?? getBehavior(config.behavior.type)\n let options: Record<string, unknown> = { ...config.behavior, ...overrides }\n if (b.loop) options = { ...options, ...b.loop(options, t) }\n shapeStack = b.stack(options, config.sheet)\n }\n\n const combined = [...shapeStack, ...idleStack]\n return combined.length > 0 ? combined : null\n}\n","import { useRef } from 'react'\n\n/**\n * Deep-equality memo deps, without serializing anything.\n *\n * Several hooks here need to recompute on the CONTENT of a prop rather than\n * on its identity, because the props in question — the paper slots, a\n * preset, a content list — are rebuilt as fresh objects on every render of\n * whatever is above. The library used to spell that as\n * `[JSON.stringify(papers)]`, which reads well and is a trap: a dependency\n * array is evaluated on **every render**, so the serialization is paid every\n * render whether or not anything changed, and it is paid in garbage rather\n * than in time.\n *\n * That is affordable for a layout's options and ruinous for a paper. An\n * image slot carries its bitmap inline as a data URL, so a field of fourteen\n * photographs serialized roughly seventeen megabytes per render — and the\n * controls that render the most are the continuous ones, which is why\n * dragging a speed slider was the way to take the tab out with an\n * out-of-memory crash.\n *\n * `useStable` compares instead of serializing. Nothing is allocated, and the\n * comparison short-circuits on `Object.is` at every level, so the common\n * case — a fresh wrapper around the same inner objects — costs a handful of\n * pointer checks no matter how large the data URL underneath is.\n */\nexport function useStable<T>(value: T): T {\n const held = useRef(value)\n if (!deepEqual(held.current, value)) held.current = value\n return held.current\n}\n\n/**\n * Structural equality over JSON-shaped data, matching what the\n * `JSON.stringify` comparison it replaces considered equal.\n *\n * That last part is the reason for the `undefined` handling below: stringify\n * drops a key whose value is `undefined`, so `{a: 1, b: undefined}` and\n * `{a: 1}` used to compare equal and must go on doing so — a config that\n * spells an absent option either way should not rebuild the field.\n */\nexport function deepEqual(a: unknown, b: unknown): boolean {\n if (Object.is(a, b)) return true\n if (typeof a !== 'object' || typeof b !== 'object' || a === null || b === null) return false\n\n if (Array.isArray(a) || Array.isArray(b)) {\n if (!Array.isArray(a) || !Array.isArray(b) || a.length !== b.length) return false\n for (let i = 0; i < a.length; i++) if (!deepEqual(a[i], b[i])) return false\n return true\n }\n\n const left = a as Record<string, unknown>\n const right = b as Record<string, unknown>\n // Keys carrying `undefined` do not count, on either side — see above.\n const keys = new Set<string>()\n for (const key of Object.keys(left)) if (left[key] !== undefined) keys.add(key)\n for (const key of Object.keys(right)) if (right[key] !== undefined) keys.add(key)\n for (const key of keys) if (!deepEqual(left[key], right[key])) return false\n return true\n}\n","import * as THREE from 'three'\nimport { useEffect, useState } from 'react'\nimport type { BackContentConfig, ContentConfig, SheetConfig } from '../config/schema'\nimport type { Stock } from '../core/stock'\nimport { paintReceipt } from './receipt'\nimport { paintCard } from './card'\nimport { ensureFont, wrapLines } from './type'\n\n/**\n * All content is composited onto a canvas and applied as a texture — content\n * deforms with the mesh because the mesh deforms, never a 2D trick.\n * Long edge = 1024 logical px × DPR 2 so text stays crisp when curled.\n */\nconst LONG_EDGE = 1024\nconst DPR = 2\n\nexport function contentCanvasSize(sheet: SheetConfig): [number, number] {\n const long = Math.max(sheet.width, sheet.height)\n const w = Math.round((sheet.width / long) * LONG_EDGE * DPR)\n const h = Math.round((sheet.height / long) * LONG_EDGE * DPR)\n return [w, h]\n}\n\nfunction paintBackground(ctx: CanvasRenderingContext2D, w: number, h: number, stock: Stock) {\n ctx.fillStyle = stock.color\n ctx.fillRect(0, 0, w, h)\n}\n\nfunction paintImage(\n ctx: CanvasRenderingContext2D,\n w: number,\n h: number,\n img: HTMLImageElement,\n fit: 'cover' | 'contain',\n) {\n const scale =\n fit === 'cover' ? Math.max(w / img.width, h / img.height) : Math.min(w / img.width, h / img.height)\n const dw = img.width * scale\n const dh = img.height * scale\n ctx.drawImage(img, (w - dw) / 2, (h - dh) / 2, dw, dh)\n}\n\nfunction paintText(\n ctx: CanvasRenderingContext2D,\n w: number,\n h: number,\n content: Extract<ContentConfig, { type: 'text' }>,\n stock: Stock,\n) {\n const size = content.size * DPR\n const pad = content.padding * Math.min(w, h)\n const font = `${content.weight} ${size}px ${content.font}`\n ctx.font = font\n ctx.fillStyle = content.color === '#2b2620' ? stock.inkColor : content.color\n ctx.textBaseline = 'top'\n ctx.textAlign = content.align\n // Tracking is set before measuring, not after: `measureText` honours\n // `letterSpacing`, so wrapping against the untracked width would break\n // lines to a measure the painted line does not have.\n ctx.letterSpacing = `${content.tracking}em`\n\n const maxWidth = w - pad * 2\n const x = content.align === 'left' ? pad : content.align === 'right' ? w - pad : w / 2\n const lineStep = size * content.lineHeight\n\n const lines = wrapLines(ctx, content.text, maxWidth, font)\n // Re-assert: wrapLines restores the font it was handed, which drops the\n // spacing the measure was taken with.\n ctx.font = font\n ctx.letterSpacing = `${content.tracking}em`\n\n // `center` optically centres the whole block rather than hanging it from\n // the top edge — what a label or a poster wants, where `top` is what a\n // letter wants because a letter starts at the top of the page.\n const block = lines.length * lineStep\n let y = content.valign === 'center' ? Math.max(pad, (h - block) / 2) : pad\n\n for (const line of lines) {\n if (y > h - pad) break\n ctx.fillText(line, x, y)\n y += lineStep\n }\n ctx.letterSpacing = '0em'\n}\n\n/**\n * Render content to a canvas. Synchronous — image content needs a decoded\n * HTMLImageElement passed in (the hook below handles loading).\n */\nexport function renderContentToCanvas(\n content: ContentConfig | BackContentConfig,\n sheet: SheetConfig,\n stock: Stock,\n image?: HTMLImageElement,\n): HTMLCanvasElement {\n const [w, h] = contentCanvasSize(sheet)\n const canvas = document.createElement('canvas')\n canvas.width = w\n canvas.height = h\n const ctx = canvas.getContext('2d')!\n paintBackground(ctx, w, h, stock)\n if (content.type === 'image' && image && content.src) paintImage(ctx, w, h, image, content.fit)\n if (content.type === 'text') paintText(ctx, w, h, content, stock)\n if (content.type === 'receipt') paintReceipt(ctx, w, h, content, stock)\n if (content.type === 'card') paintCard(ctx, w, h, content, stock, DPR)\n return canvas\n}\n\nfunction makeTexture(canvas: HTMLCanvasElement): THREE.CanvasTexture {\n const tex = new THREE.CanvasTexture(canvas)\n tex.colorSpace = THREE.SRGBColorSpace\n tex.anisotropy = 8\n tex.generateMipmaps = true\n return tex\n}\n\n/**\n * React hook: content config → texture. Re-renders only on content change,\n * never per-frame. Waits for image decode / document.fonts.ready.\n */\nexport function useContentTexture(\n content: ContentConfig | BackContentConfig | undefined,\n sheet: SheetConfig,\n stock: Stock,\n): THREE.CanvasTexture | null {\n const [texture, setTexture] = useState<THREE.CanvasTexture | null>(null)\n const key = JSON.stringify({ content: content ?? null, w: sheet.width, h: sheet.height, stock: stock.id })\n\n // biome-ignore lint/correctness/useExhaustiveDependencies: key serializes the content, sheet and stock the canvas draws from.\n useEffect(() => {\n let disposed = false\n let tex: THREE.CanvasTexture | null = null\n\n if (!content) {\n setTexture(null)\n return\n }\n\n const commit = (canvas: HTMLCanvasElement) => {\n if (disposed) return\n tex = makeTexture(canvas)\n setTexture(tex)\n }\n\n if (content.type === 'image' && content.src) {\n const img = new Image()\n img.crossOrigin = 'anonymous'\n img.onload = () => commit(renderContentToCanvas(content, sheet, stock, img))\n // A URL that never loads must not leave the sheet textureless — it\n // still has stock, and bare stock is the honest picture of \"no image\".\n img.onerror = () => commit(renderContentToCanvas(content, sheet, stock))\n img.src = content.src\n } else if (content.type === 'text' || content.type === 'card') {\n // Ask for the face BY NAME. `document.fonts.ready` alone only waits for\n // what the document already requested, and a family named inside a\n // canvas font string was never requested by anything — so on a page\n // with no DOM element using it, `ready` resolves at once and the sheet\n // paints in the fallback.\n void ensureFont(content.font, content.size * DPR).then(() =>\n commit(renderContentToCanvas(content, sheet, stock)),\n )\n } else if (content.type === 'receipt') {\n document.fonts.ready.then(() => commit(renderContentToCanvas(content, sheet, stock)))\n } else {\n commit(renderContentToCanvas(content, sheet, stock))\n }\n\n return () => {\n disposed = true\n tex?.dispose()\n }\n }, [key])\n\n return texture\n}\n","import type { ContentConfig } from '../config/schema'\nimport type { Stock } from '../core/stock'\nimport { wrapLines } from './type'\n\nexport type CardContent = Extract<ContentConfig, { type: 'card' }>\n\n/**\n * The card: a tracked label, a rule, a body, and a line of small print.\n *\n * Held to the receipt's standard rather than the text block's, which is the\n * whole reason it exists. The receipt is the only content type in this\n * library anybody art-directed — it knows what a dashed rule is, what a\n * barcode looks like, and that a total belongs at the bottom — and\n * everything else went through one `fillText` loop in the system serif.\n *\n * The proportions below are the composition, and they are ratios of the body\n * size rather than numbers, so a card scales as a card instead of as a\n * paragraph that grew.\n */\n\n/** Title sits well under the body: it is a label, not a heading. */\nconst TITLE_RATIO = 0.52\n/** Small print smaller still, and the two are deliberately different sizes. */\nconst NOTE_RATIO = 0.46\n/** Tracking for the title. Uppercase at small sizes closes up without it. */\nconst TITLE_TRACKING = 0.16\nconst NOTE_TRACKING = 0.06\n\nexport function paintCard(\n ctx: CanvasRenderingContext2D,\n w: number,\n h: number,\n content: CardContent,\n stock: Stock,\n dpr: number,\n): void {\n const ink = content.color === '#2b2620' ? stock.inkColor : content.color\n const size = content.size * dpr\n const pad = content.padding * Math.min(w, h)\n const maxWidth = w - pad * 2\n const x = content.align === 'center' ? w / 2 : pad\n ctx.textAlign = content.align === 'center' ? 'center' : 'left'\n ctx.textBaseline = 'alphabetic'\n\n const titleSize = size * TITLE_RATIO\n const noteSize = size * NOTE_RATIO\n const bodyStep = size * 1.35\n\n // Measure the whole composition before drawing any of it, so the block can\n // be centred in the card. A card whose type is hung from the top edge\n // reads as a page that got cut off rather than as a card.\n const bodyLines = content.body ? wrapLines(ctx, content.body, maxWidth, `${size}px ${content.font}`) : []\n const titleBlock = content.title ? titleSize * 1.9 : 0\n const ruleBlock = content.rule && content.title ? titleSize * 0.9 : 0\n const noteBlock = content.note ? noteSize * 2.4 : 0\n const bodyBlock = bodyLines.length * bodyStep\n const total = titleBlock + ruleBlock + bodyBlock + noteBlock\n\n let y = Math.max(pad, (h - total) / 2) + size * 0.9\n\n if (content.title) {\n ctx.font = `${titleSize}px ${content.font}`\n ctx.letterSpacing = `${TITLE_TRACKING}em`\n ctx.fillStyle = ink\n ctx.globalAlpha = 0.72\n ctx.fillText(content.title.toUpperCase(), x, y - size * 0.5)\n ctx.globalAlpha = 1\n ctx.letterSpacing = '0em'\n y += titleBlock - size * 0.5\n\n if (content.rule) {\n // A hairline, not a border: it separates, it does not enclose.\n ctx.save()\n ctx.strokeStyle = ink\n ctx.globalAlpha = 0.28\n ctx.lineWidth = Math.max(1, dpr * 0.75)\n ctx.beginPath()\n ctx.moveTo(content.align === 'center' ? w / 2 - maxWidth / 2 : pad, y - titleSize * 0.5)\n ctx.lineTo(content.align === 'center' ? w / 2 + maxWidth / 2 : pad + maxWidth, y - titleSize * 0.5)\n ctx.stroke()\n ctx.restore()\n y += ruleBlock\n }\n }\n\n if (content.ruled && bodyLines.length > 0) {\n // Writing lines, drawn UNDER the type and in the stock's own ink at low\n // alpha, so they read as printed on the card rather than as underlines\n // on the words.\n ctx.save()\n ctx.strokeStyle = ink\n ctx.globalAlpha = 0.14\n ctx.lineWidth = Math.max(1, dpr * 0.6)\n for (let i = 0; i < bodyLines.length; i++) {\n const lineY = y + i * bodyStep + size * 0.28\n ctx.beginPath()\n ctx.moveTo(pad, lineY)\n ctx.lineTo(pad + maxWidth, lineY)\n ctx.stroke()\n }\n ctx.restore()\n }\n\n ctx.font = `${size}px ${content.font}`\n ctx.fillStyle = ink\n for (const line of bodyLines) {\n if (y > h - pad) break\n ctx.fillText(line, x, y)\n y += bodyStep\n }\n\n if (content.note) {\n ctx.font = `${noteSize}px ${content.font}`\n ctx.letterSpacing = `${NOTE_TRACKING}em`\n ctx.globalAlpha = 0.6\n ctx.fillText(content.note, x, Math.min(y + noteSize * 1.4, h - pad))\n ctx.globalAlpha = 1\n ctx.letterSpacing = '0em'\n }\n}\n","import * as THREE from 'three'\nimport { useEffect, useMemo, useRef } from 'react'\nimport { useFrame, useThree } from '@react-three/fiber'\nimport { ContactShadows } from '@react-three/drei'\nimport type { FilmName, LightingName } from '../config/schema'\nimport { buildEnvironment } from './environment'\nimport { resolveLighting, type LightingPreset, type LightOverrides } from './lighting'\nimport { usePrefersReducedMotion } from '../a11y'\n\n/**\n * The rig's film name, as a three constant.\n *\n * The mapping lives here rather than beside the presets because\n * `lighting.ts` is deliberately pure — it is the half that runs in node\n * under vitest, and importing three into it to name three integers would\n * trade that for nothing.\n */\nconst toneMappings: Record<FilmName, THREE.ToneMapping> = {\n agx: THREE.AgXToneMapping,\n neutral: THREE.NeutralToneMapping,\n filmic: THREE.ACESFilmicToneMapping,\n}\n\n/** Deterministic PRNG so gobos render identically everywhere. */\nfunction mulberry32(seed: number) {\n let a = seed\n return () => {\n a |= 0\n a = (a + 0x6d2b79f5) | 0\n let t = Math.imul(a ^ (a >>> 15), 1 | a)\n t = (t + Math.imul(t ^ (t >>> 7), 61 | t)) ^ t\n return ((t ^ (t >>> 14)) >>> 0) / 4294967296\n }\n}\n\n/**\n * Procedural gobo textures — no binary assets in the repo. White passes\n * light, dark blocks it (SpotLight.map multiplies the beam).\n */\nexport function makeGoboTexture(kind: 'blinds' | 'leaves'): THREE.CanvasTexture {\n const size = 512\n const canvas = document.createElement('canvas')\n canvas.width = canvas.height = size\n const ctx = canvas.getContext('2d')!\n ctx.fillStyle = '#ffffff'\n ctx.fillRect(0, 0, size, size)\n\n if (kind === 'blinds') {\n // Venetian slats: soft-edged dark bars, slightly rotated.\n ctx.save()\n ctx.translate(size / 2, size / 2)\n ctx.rotate(-0.06)\n const slat = 34\n const gap = 30\n for (let y = -size; y < size; y += slat + gap) {\n const grad = ctx.createLinearGradient(0, y, 0, y + slat)\n grad.addColorStop(0, 'rgba(20,20,20,0)')\n grad.addColorStop(0.25, 'rgba(20,20,20,0.92)')\n grad.addColorStop(0.75, 'rgba(20,20,20,0.92)')\n grad.addColorStop(1, 'rgba(20,20,20,0)')\n ctx.fillStyle = grad\n ctx.fillRect(-size, y, size * 2, slat)\n }\n ctx.restore()\n } else {\n // Dappled foliage: three scales of soft dark blobs.\n const rand = mulberry32(7)\n for (const [count, radius, alpha] of [\n [26, 70, 0.75],\n [40, 38, 0.6],\n [70, 16, 0.5],\n ] as const) {\n for (let i = 0; i < count; i++) {\n const x = rand() * size\n const y = rand() * size\n const r = radius * (0.6 + rand() * 0.8)\n const grad = ctx.createRadialGradient(x, y, 0, x, y, r)\n grad.addColorStop(0, `rgba(15,20,12,${alpha})`)\n grad.addColorStop(0.7, `rgba(15,20,12,${alpha * 0.55})`)\n grad.addColorStop(1, 'rgba(15,20,12,0)')\n ctx.fillStyle = grad\n ctx.beginPath()\n ctx.ellipse(x, y, r, r * (0.6 + rand() * 0.5), rand() * Math.PI, 0, Math.PI * 2)\n ctx.fill()\n }\n }\n }\n\n const texture = new THREE.CanvasTexture(canvas)\n texture.wrapS = texture.wrapT = THREE.RepeatWrapping\n return texture\n}\n\n/**\n * The studio light: the room, prefiltered, hung on the scene.\n *\n * Mounted as its own component so the PMREM pass runs when the RIG changes\n * and not when anything else in the lighting rerenders — it is a render\n * target and a chain of blur passes, which is cheap once and silly sixty\n * times a second.\n */\nfunction StudioLight({ rig }: { rig: LightingPreset }) {\n const gl = useThree((s) => s.gl)\n const scene = useThree((s) => s.scene)\n\n // Only the colours and the key's placement change the image; intensity is\n // applied by the scene, so dragging that slider must not rebuild anything.\n const sky = `${rig.sky.zenith}|${rig.sky.horizon}|${rig.sky.ground}|${rig.key.color}|${rig.key.intensity}|${rig.key.position.join()}`\n\n // biome-ignore lint/correctness/useExhaustiveDependencies: `sky` is the digest of everything the image is built from.\n useEffect(() => {\n const environment = buildEnvironment(gl, rig)\n const previous = scene.environment\n scene.environment = environment.texture\n return () => {\n scene.environment = previous\n environment.dispose()\n }\n }, [gl, scene, sky])\n\n useEffect(() => {\n const previous = scene.environmentIntensity\n scene.environmentIntensity = rig.studio\n return () => {\n scene.environmentIntensity = previous\n }\n }, [scene, rig.studio])\n\n return null\n}\n\n/**\n * How bright the hemisphere stand-in runs against the environment it\n * replaces. Prefiltered irradiance integrates the whole sky, and a\n * hemisphere light is one cosine term, so matching them by eye means\n * pushing the cheap one up.\n */\nconst HEMISPHERE_STAND_IN = 1.6\n\nexport interface PaperLightingProps {\n preset?: LightingName\n /**\n * Overrides on the preset — exposure, key, direction, height, ambient,\n * studio, haze. See `lightSchema`.\n */\n light?: LightOverrides\n /**\n * An already-resolved rig, which wins over `preset`/`light`. Stage mode\n * resolves once and hands the same object to the lamps and to the paper,\n * so the two cannot be resolved differently.\n */\n rig?: LightingPreset\n /** Local y of the ground the contact shadow sits on. */\n floor?: number\n /** Contact shadow footprint. */\n scale?: number\n /** Override prefers-reduced-motion (freezes gobo drift). */\n reducedMotion?: boolean\n /**\n * Shadow map resolution, overriding the preset's. 0 turns the shadow pass\n * off — it re-renders the scene's geometry, so on a weak machine it is\n * often the single most expensive thing in the frame.\n */\n shadowMapSize?: number\n /** Draw the soft contact shadow. It is its own render pass. */\n contactShadow?: boolean\n /**\n * Light the scene with the room as well as with the lamp. Off is one\n * fewer texture read per fragment and a flatter picture; it is a quality\n * knob, not an art-direction one — turn the studio light DOWN with\n * `light.studio` if you want less of it.\n */\n environment?: boolean\n}\n\n/**\n * A scene's lighting rig from one serialized name plus whatever the author\n * overrode: key light (spot with a procedural gobo, or directional), the\n * room as an environment map, ambient fill, tone-mapping exposure, distance\n * haze, and the contact shadow. Swap presets to restyle the same paper;\n * move the sliders to light it yourself.\n */\nexport function PaperLighting({\n preset = 'studio',\n light,\n rig,\n floor = -1.2,\n scale = 10,\n reducedMotion,\n shadowMapSize,\n contactShadow = true,\n environment = true,\n}: PaperLightingProps) {\n const p = useMemo(() => rig ?? resolveLighting(preset, light), [rig, preset, light])\n const mapSize = shadowMapSize ?? p.shadow.mapSize\n const castShadow = mapSize > 0\n const reduced = usePrefersReducedMotion(reducedMotion)\n const gl = useThree((s) => s.gl)\n const scene = useThree((s) => s.scene)\n\n useEffect(() => {\n const previousExposure = gl.toneMappingExposure\n const previousFilm = gl.toneMapping\n gl.toneMappingExposure = p.exposure\n gl.toneMapping = toneMappings[p.film]\n return () => {\n gl.toneMappingExposure = previousExposure\n gl.toneMapping = previousFilm\n }\n }, [gl, p.exposure, p.film])\n\n // Set imperatively rather than via <fog attach=\"fog\" />, which would bind\n // to whatever group this rig happens to be mounted under instead of the scene.\n useEffect(() => {\n if (!p.fog) return\n const previous = scene.fog\n scene.fog = new THREE.Fog(p.fog.color, p.fog.near, p.fog.far)\n return () => {\n scene.fog = previous\n }\n }, [scene, p.fog])\n\n // biome-ignore lint/correctness/useExhaustiveDependencies: Only the gobo kind rebuilds the texture — drift and intensity animate in place.\n const goboMap = useMemo(() => (p.gobo ? makeGoboTexture(p.gobo.kind) : null), [p.gobo?.kind])\n useEffect(() => () => goboMap?.dispose(), [goboMap])\n\n const driftRef = useRef(0)\n useFrame((_, delta) => {\n if (!goboMap || !p.gobo || reduced) return\n driftRef.current += delta * p.gobo.drift\n goboMap.offset.set(driftRef.current, driftRef.current * 0.6)\n })\n\n return (\n <>\n {p.studio > 0 &&\n (environment ? (\n <StudioLight rig={p} />\n ) : (\n // The studio light degrades rather than disappearing. A hemisphere\n // is the cheap half of what the room does — light from above, a\n // different colour from below — so a machine that cannot pay for\n // the environment still gets a lit figure with a top and a bottom\n // instead of a flat cut-out.\n <hemisphereLight\n color={p.sky.horizon}\n groundColor={p.sky.ground}\n intensity={p.studio * HEMISPHERE_STAND_IN}\n />\n ))}\n <ambientLight intensity={p.ambient} />\n {p.gobo && goboMap ? (\n <spotLight\n position={p.key.position}\n color={p.key.color}\n // decay 0 keeps intensity art-directable rather than distance-driven.\n intensity={p.key.intensity * 3.2}\n angle={p.gobo.angle}\n penumbra={0.5}\n decay={0}\n castShadow={castShadow}\n map={goboMap}\n shadow-mapSize={[mapSize || 1, mapSize || 1]}\n shadow-radius={p.shadow.radius}\n shadow-normalBias={0.05}\n />\n ) : (\n <directionalLight\n position={p.key.position}\n color={p.key.color}\n intensity={p.key.intensity}\n castShadow={castShadow}\n shadow-mapSize={[mapSize || 1, mapSize || 1]}\n shadow-radius={p.shadow.radius}\n shadow-normalBias={0.05}\n />\n )}\n {contactShadow && (\n <ContactShadows\n position={[0, floor, 0]}\n opacity={p.contactShadowOpacity}\n scale={scale}\n blur={p.contactShadowBlur}\n far={3}\n />\n )}\n </>\n )\n}\n","import * as THREE from 'three'\nimport type { LightingPreset } from './lighting'\nimport { lightAngles } from './lighting'\nimport { cssColorOr } from './color'\n\n/**\n * The room, drawn as an equirectangular image so it can light things.\n *\n * Stage mode already builds a graded sky around the whole space and it lit\n * nothing — it was a gradient mesh the camera looked at. This is the same\n * three colours plus a soft disc where the key stands, turned into an\n * environment map, so the hall is lit BY the room the viewer can see. That\n * is what puts direction into the fill: a banner turned toward the source\n * picks up the source, one turned away picks up the dark end of the room,\n * and paper's sheen finally has something to reflect.\n *\n * Procedural on purpose — the repo carries no HDRI, nothing is fetched, and\n * the grade stays editable from the same numbers the lights read.\n */\n\n/** Small is fine: PMREM blurs it into mip levels anyway, and roughness eats the detail. */\nconst WIDTH = 256\nconst HEIGHT = 128\n\n/**\n * Where a direction lands in an equirectangular image, matching three's own\n * `equirectUv`: `u = atan2(z, x) / 2π + 0.5`. Our azimuth is measured from\n * +Z instead (0° in front, 90° right), which works out to `u = 0.75 − az/360`.\n * Getting this right is what puts the bright patch of sky on the same side\n * of the room as the lamp casting the shadows.\n */\nexport function skyU(azimuthDeg: number): number {\n const u = 0.75 - azimuthDeg / 360\n return ((u % 1) + 1) % 1\n}\n\n/** Elevation to image row. Row 0 is the zenith — v is flipped by the texture. */\nexport function skyV(elevationDeg: number): number {\n return 0.5 - elevationDeg / 180\n}\n\n/**\n * Paint the room. The gradient runs zenith → horizon → ground with the\n * horizon held as a band rather than a hairline, because a room's brightest\n * region is the wall, not a mathematical line through it.\n */\nexport function drawSky(ctx: CanvasRenderingContext2D, preset: LightingPreset): void {\n // Guarded: a stage's sky colours are editable text, and `addColorStop`\n // throws on anything it cannot parse. See `cssColorOr`.\n const zenith = cssColorOr(preset.sky.zenith, '#241c17')\n const horizon = cssColorOr(preset.sky.horizon, '#fff4e2')\n const ground = cssColorOr(preset.sky.ground, '#141210')\n const grade = ctx.createLinearGradient(0, 0, 0, HEIGHT)\n grade.addColorStop(0, zenith)\n grade.addColorStop(0.32, zenith)\n grade.addColorStop(0.5, horizon)\n grade.addColorStop(0.58, horizon)\n grade.addColorStop(1, ground)\n ctx.fillStyle = grade\n ctx.fillRect(0, 0, WIDTH, HEIGHT)\n\n // The key's own patch of sky. Bright, wide and soft: this is a window or a\n // softbox, not a sun, and a hard disc would make the reflections read as\n // a lamp somebody left in shot.\n const angles = lightAngles(preset.key.position)\n const x = skyU(angles.azimuth) * WIDTH\n const y = skyV(angles.elevation) * HEIGHT\n const radius = WIDTH * 0.3\n const color = new THREE.Color(preset.key.color)\n // The disc carries the key's intensity, so turning the lamp up brightens\n // the room it is standing in rather than only the shadows it casts.\n const strength = Math.min(1, preset.key.intensity / 3)\n\n // Drawn three times across the seam so a key behind the paper — where the\n // wrap falls — is not sliced in half by the edge of the image.\n for (const offset of [-WIDTH, 0, WIDTH]) {\n const glow = ctx.createRadialGradient(x + offset, y, 0, x + offset, y, radius)\n glow.addColorStop(\n 0,\n `rgba(${(color.r * 255) | 0}, ${(color.g * 255) | 0}, ${(color.b * 255) | 0}, ${strength})`,\n )\n glow.addColorStop(1, `rgba(${(color.r * 255) | 0}, ${(color.g * 255) | 0}, ${(color.b * 255) | 0}, 0)`)\n ctx.fillStyle = glow\n ctx.fillRect(x + offset - radius, y - radius, radius * 2, radius * 2)\n }\n}\n\n/** The room as a texture. Caller owns disposal. */\nexport function makeSkyEquirect(preset: LightingPreset): THREE.CanvasTexture {\n const canvas = document.createElement('canvas')\n canvas.width = WIDTH\n canvas.height = HEIGHT\n const ctx = canvas.getContext('2d')!\n drawSky(ctx, preset)\n const texture = new THREE.CanvasTexture(canvas)\n texture.mapping = THREE.EquirectangularReflectionMapping\n texture.colorSpace = THREE.SRGBColorSpace\n return texture\n}\n\n/**\n * The room, prefiltered into the mip chain a rough surface needs.\n *\n * PMREM is the expensive part and it runs ONCE per rig — a render target and\n * a handful of blur passes — after which sampling it costs a texture read.\n * Both the target and the source canvas are the caller's to dispose.\n */\nexport function buildEnvironment(\n renderer: THREE.WebGLRenderer,\n preset: LightingPreset,\n): { texture: THREE.Texture; dispose(): void } {\n const equirect = makeSkyEquirect(preset)\n const pmrem = new THREE.PMREMGenerator(renderer)\n const target = pmrem.fromEquirectangular(equirect)\n pmrem.dispose()\n equirect.dispose()\n return {\n texture: target.texture,\n dispose: () => target.dispose(),\n }\n}\n","/**\n * Colour strings that came from a person, made safe to hand to a canvas.\n *\n * Every colour in a stage — zenith, horizon, ground, the source, the room —\n * is an editable text field, and a text field emits on every keystroke. So\n * the library is handed `#f`, and `#ff`, and `not-a-colour`, in the normal\n * course of somebody typing `#ffaa22`. That is expected input, not a bug in\n * the caller.\n *\n * It matters because `addColorStop` is one of the few canvas calls that\n * **throws** rather than ignoring what it cannot parse:\n *\n * ```\n * Failed to execute 'addColorStop' on 'CanvasGradient':\n * The value provided ('not-a-colour') could not be parsed as a color.\n * ```\n *\n * and the sky is built during render, so that throw reached React as an\n * uncaught error and took the whole editor down. Three.js is the forgiving\n * one here — `new THREE.Color('nonsense')` warns and carries on — which is\n * why only the gradient path ever broke.\n *\n * Validation is the canvas's own opinion rather than a regex, because the\n * set of things CSS calls a colour is large (`rebeccapurple`, `hsl(...)`,\n * `color-mix(...)`, whatever ships next) and a regex would reject valid\n * input the gradient would have accepted.\n */\n\n/** A 1×1 scratch context, made once, used only to ask \"is this a colour?\". */\nlet probe: CanvasRenderingContext2D | null | undefined\n\nfunction probeContext(): CanvasRenderingContext2D | null {\n if (probe !== undefined) return probe\n probe = typeof document === 'undefined' ? null : document.createElement('canvas').getContext('2d')\n return probe\n}\n\n/**\n * `value` if a canvas can parse it as a colour, else `fallback`.\n *\n * The test is two assignments from two different starting colours. An\n * invalid value leaves `fillStyle` untouched, so it still reads back as\n * whichever prior it started from and the two readings disagree; a valid one\n * normalizes to the same string both times. One assignment would not do —\n * the answer would depend on what the context happened to hold.\n */\nexport function cssColorOr(value: string, fallback: string): string {\n const ctx = probeContext()\n // No DOM (SSR, tests): pass the value through rather than invent a colour.\n // Nothing is being painted, so nothing can throw.\n if (!ctx) return value\n const previous = ctx.fillStyle\n ctx.fillStyle = '#000000'\n ctx.fillStyle = value\n const fromBlack = ctx.fillStyle\n ctx.fillStyle = '#ffffff'\n ctx.fillStyle = value\n const fromWhite = ctx.fillStyle\n ctx.fillStyle = previous\n return fromBlack === fromWhite ? value : fallback\n}\n","import * as THREE from 'three'\nimport { createContext, useContext, useEffect, useMemo, useRef, useSyncExternalStore } from 'react'\nimport type { PaperConfig } from '../config/schema'\n\n// ── Drop zones (spec M6 §5) ──────────────────────────────────────────────────\n\nexport interface DropZoneConfig {\n id: string\n /** Preset-name globs ('stamp-*'); omitted = accept all. */\n accept?: string[]\n /** World-space rect on the field plane. */\n bounds: { position: [number, number, number]; size: [number, number] }\n highlight?: 'none' | 'glow' | 'outline'\n}\n\nexport interface PlacedPaper {\n slot: number\n presetName: string\n config: PaperConfig\n}\n\nexport interface DropZoneProps extends DropZoneConfig {\n onPlace?(paper: PlacedPaper, zone: string): void\n}\n\nexport interface ZoneEntry extends DropZoneConfig {\n onPlace?: DropZoneProps['onPlace']\n}\n\n/** Shared zone state: `<DropZone>` children register; the carry loop hit-tests. */\nexport class DropZoneRegistry {\n private zones = new Map<string, ZoneEntry>()\n private hoveredId: string | null = null\n private listeners = new Set<() => void>()\n private version = 0\n\n register(zone: ZoneEntry): () => void {\n this.zones.set(zone.id, zone)\n this.notify()\n return () => {\n this.zones.delete(zone.id)\n this.notify()\n }\n }\n\n list(): ZoneEntry[] {\n return [...this.zones.values()]\n }\n\n get(id: string): ZoneEntry | undefined {\n return this.zones.get(id)\n }\n\n get hovered(): string | null {\n return this.hoveredId\n }\n\n setHovered(id: string | null): void {\n if (this.hoveredId === id) return\n this.hoveredId = id\n this.notify()\n }\n\n subscribe = (fn: () => void): (() => void) => {\n this.listeners.add(fn)\n return () => this.listeners.delete(fn)\n }\n\n getVersion = (): number => this.version\n\n private notify(): void {\n this.version++\n for (const fn of this.listeners) fn()\n }\n}\n\nexport const DropZoneContext = createContext<DropZoneRegistry | null>(null)\n\n// Compiled accept-globs, cached — zoneAccepts runs every frame in the carry\n// loop, and a fresh RegExp per glob per frame is pure GC churn.\nconst globCache = new Map<string, RegExp>()\nconst globRegExp = (glob: string): RegExp => {\n let re = globCache.get(glob)\n if (!re) {\n re = new RegExp(`^${glob.replace(/[.+^${}()|[\\]\\\\]/g, '\\\\$&').replace(/\\*/g, '.*')}$`, 'i')\n globCache.set(glob, re)\n }\n return re\n}\n\n/** True when `name` matches the zone's accept globs (all zones accept by default). */\nexport function zoneAccepts(zone: Pick<DropZoneConfig, 'accept'>, name: string): boolean {\n if (!zone.accept || zone.accept.length === 0) return true\n return zone.accept.some((glob) => globRegExp(glob).test(name))\n}\n\nexport const zoneContains = (zone: ZoneEntry, x: number, y: number): boolean =>\n Math.abs(x - zone.bounds.position[0]) <= zone.bounds.size[0] / 2 &&\n Math.abs(y - zone.bounds.position[1]) <= zone.bounds.size[1] / 2\n\n/**\n * A drop target inside a `<PaperField>`. While a paper is picked, its center\n * is tested against the bounds each frame; hovering applies the highlight\n * and release inside fires `placed` + `onPlace`.\n */\nexport function DropZone(props: DropZoneProps) {\n const registry = useContext(DropZoneContext)\n const { id, accept, bounds, highlight = 'glow', onPlace } = props\n\n // `onPlace` is a notification, not a dependency. The natural way to pass\n // one is an inline arrow, which is a new function on every render of the\n // page above — naming it here re-registered the zone on every one of those\n // renders, bumping the registry version and re-rendering every\n // `DropZoneVisual` in the field. Held in a ref, the registration depends on\n // what the zone IS, and the callback is read at the moment it fires.\n const place = useRef(onPlace)\n useEffect(() => {\n place.current = onPlace\n }, [onPlace])\n\n // biome-ignore lint/correctness/useExhaustiveDependencies: Serialized deps — re-registering on object identity would thrash the registry.\n useEffect(() => {\n if (!registry) return\n return registry.register({\n id,\n accept,\n bounds,\n highlight,\n onPlace: (paper, zone) => place.current?.(paper, zone),\n })\n }, [registry, id, JSON.stringify(accept ?? null), JSON.stringify(bounds), highlight])\n if (!registry) return null\n return <DropZoneVisual registry={registry} config={{ id, accept, bounds, highlight }} />\n}\n\n/** The translucent target — brightens when the carried paper is over it. */\nexport function DropZoneVisual({ registry, config }: { registry: DropZoneRegistry; config: DropZoneConfig }) {\n useSyncExternalStore(registry.subscribe, registry.getVersion, registry.getVersion)\n const hovered = registry.hovered === config.id\n const style = config.highlight ?? 'glow'\n const [w, h] = config.bounds.size\n // Memoized: an inline `new THREE.PlaneGeometry` in args would rebuild (and\n // leak) the edges every render — and this re-renders on every hover change.\n const edges = useMemo(() => {\n const plane = new THREE.PlaneGeometry(w, h)\n const geo = new THREE.EdgesGeometry(plane)\n plane.dispose()\n return geo\n }, [w, h])\n useEffect(() => () => edges.dispose(), [edges])\n return (\n <group position={config.bounds.position}>\n {style !== 'outline' && (\n <mesh>\n <planeGeometry args={[w, h]} />\n <meshBasicMaterial\n color={hovered && style === 'glow' ? '#8ea8ff' : '#5c6f9e'}\n transparent\n opacity={hovered && style === 'glow' ? 0.32 : 0.14}\n depthWrite={false}\n />\n </mesh>\n )}\n <lineSegments geometry={edges}>\n <lineBasicMaterial color={hovered ? '#aebfff' : '#6b7da8'} />\n </lineSegments>\n </group>\n )\n}\n","import { z } from 'zod'\nimport type { PaperEdge } from '../config/schema'\nimport type { CurlOptions } from '../deformers/curl'\n\n/**\n * Pure grid math for the `sheet` layout — a block of stamps on a shared\n * backing. Shared by the layout's pose function, the backing silhouette\n * renderer, the outward-corner smart default, and the torn-perforation\n * auto-wiring, so they can never disagree about where a slot sits.\n */\n\nexport const sheetLayoutSchema = z.object({\n rows: z.number().int().min(1).max(12).default(2),\n columns: z.number().int().min(1).max(12).default(5),\n /** World-units gap between slots. Stamps are printed in register — no jitter. */\n gutter: z.number().min(0).max(1).default(0.08),\n /** Slot footprint in world units (the paper preset should match). */\n cellWidth: z.number().min(0.1).max(4).default(0.72),\n cellHeight: z.number().min(0.1).max(4).default(0.86),\n /** Render the shared backing sheet behind the grid. */\n backing: z.boolean().default(true),\n backingMargin: z.number().min(0).max(1).default(0.12),\n})\n\nexport type SheetLayoutOptions = z.infer<typeof sheetLayoutSchema>\n\n/** Backing thickness + ε — papers float just above the backing sheet. */\nexport const SHEET_LIFT = 0.012\n\n/**\n * Cell footprint = the paper's own sheet dims unless the user set an\n * explicit cellWidth/cellHeight — so `gutter` is literally the spacing\n * between stamps, whatever preset populates the grid.\n */\nexport function withSheetCellFromPaper(\n parsed: SheetLayoutOptions,\n rawOptions: Record<string, unknown> | undefined,\n paperDims: { width: number; height: number } | undefined,\n): SheetLayoutOptions {\n if (!paperDims) return parsed\n const hasW = rawOptions !== undefined && rawOptions.cellWidth !== undefined\n const hasH = rawOptions !== undefined && rawOptions.cellHeight !== undefined\n if (hasW && hasH) return parsed\n return {\n ...parsed,\n cellWidth: hasW ? parsed.cellWidth : paperDims.width,\n cellHeight: hasH ? parsed.cellHeight : paperDims.height,\n }\n}\n\nexport function sheetSlotXY(i: number, o: SheetLayoutOptions): { x: number; y: number } {\n const col = i % o.columns\n const row = Math.floor(i / o.columns)\n return {\n x: (col - (o.columns - 1) / 2) * (o.cellWidth + o.gutter),\n y: ((o.rows - 1) / 2 - row) * (o.cellHeight + o.gutter),\n }\n}\n\n/** Grid bounds + margin — the backing sheet's size. */\nexport function sheetBackingSize(o: SheetLayoutOptions): { width: number; height: number } {\n return {\n width: o.columns * o.cellWidth + (o.columns - 1) * o.gutter + o.backingMargin * 2,\n height: o.rows * o.cellHeight + (o.rows - 1) * o.gutter + o.backingMargin * 2,\n }\n}\n\ntype Corner = CurlOptions['corner']\n\n/**\n * The corner facing away from the sheet's center — what a thumb would find\n * (spec M6 §1.3). A tie (an odd grid's exact-center row/column, where the\n * cell straddles the midline) breaks outward-and-down: strict `<` on both\n * axes sends the center right and down, so a dead-center cell peels\n * bottom-right — the standalone peel default.\n */\nexport function outwardCorner(i: number, o: Pick<SheetLayoutOptions, 'rows' | 'columns'>): Corner {\n const col = i % o.columns\n const row = Math.floor(i / o.columns)\n // Row 0 renders at the top of the grid.\n const horizontal = col + 0.5 < o.columns / 2 ? 'left' : 'right'\n const vertical = row + 0.5 < o.rows / 2 ? 'top' : 'bottom'\n return `${vertical}-${horizontal}` as Corner\n}\n\n/**\n * Perforation auto-wiring on detach: edges that faced a neighboring slot tear\n * through; edges on the sheet's outer boundary keep their clean punches.\n */\nexport function tornEdgesOnDetach(\n i: number,\n o: Pick<SheetLayoutOptions, 'rows' | 'columns'>,\n): Partial<Record<PaperEdge, 'torn' | 'intact'>> {\n const col = i % o.columns\n const row = Math.floor(i / o.columns)\n return {\n top: row > 0 ? 'torn' : 'intact',\n bottom: row < o.rows - 1 ? 'torn' : 'intact',\n left: col > 0 ? 'torn' : 'intact',\n right: col < o.columns - 1 ? 'torn' : 'intact',\n }\n}\n","import {\n contentSchema,\n paperConfigSchema,\n type ContentConfig,\n type ContentConfigInput,\n type PaperConfig,\n type PaperConfigInput,\n type PaperStatesInput,\n} from '../config/schema'\nimport { mergeConfig } from '../config/merge'\nimport { resolveConfig } from '../PaperMesh'\nimport { outwardCorner, sheetLayoutSchema } from './sheetGrid'\n\n/** A field slot references a preset — the spec's component/instance model. */\nexport interface FieldPaperSlot {\n preset?: string | PaperConfigInput\n /**\n * INPUT type, not the parsed one. A slot's content is written by a caller,\n * and the parsed type demands every default be supplied — which turned a\n * two-line content literal into a type error and is exactly the failure\n * `config/props.test.ts` was added to catch on the props. Parsed here\n * (`contentSchema.parse`) so consumers downstream still get a full config.\n */\n content?: ContentConfigInput\n /** Per-instance state overrides, merged over the preset's states (spec M6 §1.1). */\n states?: PaperStatesInput\n}\n\nexport interface FieldGroupData {\n config: PaperConfig\n /** Global slot indices this group renders (layout poses use global i / total n). */\n indices: number[]\n contents: ContentConfig[]\n}\n\nexport const EMPTY_SET: ReadonlySet<number> = new Set()\n\n/**\n * The effective slot list: explicit `papers`, the `images` sugar, or the\n * twelve-blank default. ONE derivation shared by PaperFieldMesh and the\n * PaperField wrapper, so the mesh and the keyboard mirror always agree on\n * which papers exist.\n */\nexport function effectiveFieldPapers(papers?: FieldPaperSlot[], images?: string[]): FieldPaperSlot[] {\n if (papers) return papers\n if (images) {\n return images.map((src) => ({\n content: { type: 'image', src, fit: 'cover' } as ContentConfig,\n }))\n }\n return Array.from({ length: 12 }, () => ({}))\n}\n\n/** Group slots by resolved preset — one instanced draw call per distinct preset. */\nexport function groupFieldPapers(\n papers: FieldPaperSlot[],\n fallback?: string | PaperConfigInput,\n): FieldGroupData[] {\n const groups = new Map<string, FieldGroupData>()\n papers.forEach((slot, i) => {\n const config = resolveConfig({ preset: slot.preset ?? fallback })\n const key = JSON.stringify(config)\n let group = groups.get(key)\n if (!group) {\n group = { config, indices: [], contents: [] }\n groups.set(key, group)\n }\n group.indices.push(i)\n group.contents.push(slot.content ? contentSchema.parse(slot.content) : config.content)\n })\n return [...groups.values()]\n}\n\n/**\n * Whether a field runs the per-paper interactive path. A stateful field is\n * interactive by nature — and \"stateful\" must RESOLVE presets: a slot naming\n * a stateful preset by string counts exactly like an inline `states` object.\n * The single decision shared by PaperFieldMesh (render path) and PaperField\n * (keyboard mirror), so pointer interaction and keyboard access never diverge.\n */\nexport function fieldIsInteractive(\n papers: FieldPaperSlot[],\n fallback?: string | PaperConfigInput,\n explicit?: boolean,\n): boolean {\n if (explicit !== undefined) return explicit\n return (\n papers.some((s) => s.states) || groupFieldPapers(papers, fallback).some((g) => Boolean(g.config.states))\n )\n}\n\n/**\n * Resolve one slot to its final render config: preset (or fallback) + slot\n * content + slot-level state overrides merged over the preset's states + the\n * `sheet` smart default (an 'auto' peel corner resolves to the corner facing\n * away from the sheet's center — what a thumb would find).\n */\nexport function resolveFieldSlotConfig(\n slot: FieldPaperSlot,\n fallback: string | PaperConfigInput | undefined,\n index: number,\n layoutId: string,\n layoutOptions: Record<string, unknown>,\n): PaperConfig {\n let config = resolveConfig({ preset: slot.preset ?? fallback })\n const patch: Record<string, unknown> = {}\n if (slot.content) patch.content = slot.content\n if (slot.states) patch.states = slot.states\n if (layoutId === 'sheet' && config.behavior?.type === 'peel' && config.behavior.corner === 'auto') {\n const o = sheetLayoutSchema.parse(layoutOptions)\n patch.behavior = { corner: outwardCorner(index, o) }\n }\n if (Object.keys(patch).length > 0) {\n config = paperConfigSchema.parse(mergeConfig(config as Record<string, unknown>, patch))\n }\n return config\n}\n","import * as THREE from 'three'\nimport { useEffect, useState } from 'react'\nimport type { ContentConfig, SheetConfig } from '../config/schema'\nimport type { Stock } from '../core/stock'\nimport { useStable } from '../core/stable'\nimport { renderContentToCanvas } from './texture'\n\n/**\n * Field mode packs every paper's content into one grid atlas — one texture,\n * one draw call. Tiles keep the sheet's aspect; images redraw their tile as\n * they decode (LQIP-ish: stock tint first, pixels when ready).\n */\n\nconst MAX_ATLAS = 4096\n\n/**\n * Grid shape for `count` tiles of a given aspect (height / width).\n *\n * Square tiles want a square grid, but a stage banner is 5.7 times taller\n * than it is wide, and packing those into a square GRID makes an atlas five\n * times taller than it is wide — which then has to be squashed to fit the\n * texture budget, and the content with it. Choosing cols/rows ≈ aspect keeps\n * the atlas itself roughly square whatever shape the paper is.\n */\nexport function atlasGrid(count: number, aspect = 1): { cols: number; rows: number } {\n const cols = Math.max(1, Math.min(count, Math.ceil(Math.sqrt(count * Math.max(aspect, 0.01)))))\n return { cols, rows: Math.max(1, Math.ceil(count / cols)) }\n}\n\nexport interface ContentAtlas {\n texture: THREE.CanvasTexture\n cols: number\n rows: number\n}\n\nexport function useContentAtlas(\n contents: ContentConfig[],\n sheet: SheetConfig,\n stock: Stock,\n): ContentAtlas | null {\n const [atlas, setAtlas] = useState<ContentAtlas | null>(null)\n // Compared rather than serialized. An image tile carries its bitmap inline\n // as a data URL, and this runs on every render of the field — building a\n // cache key out of the very thing that makes the cache worth having was\n // costing more per render than the atlas it was protecting.\n const stableContents = useStable(contents)\n\n // biome-ignore lint/correctness/useExhaustiveDependencies: the atlas is drawn from the contents, sheet and stock named below.\n useEffect(() => {\n let disposed = false\n const aspect = sheet.height / sheet.width\n const { cols, rows } = atlasGrid(contents.length, aspect)\n // Fit the tile to the budget WITHOUT breaking its aspect: a tile squashed\n // to fit renders its content squashed too. Resolution is the thing that\n // gives, never shape.\n let tileW = Math.min(1024, Math.floor(MAX_ATLAS / cols))\n let tileH = Math.round(tileW * aspect)\n if (tileH * rows > MAX_ATLAS) {\n tileH = Math.floor(MAX_ATLAS / rows)\n tileW = Math.max(1, Math.round(tileH / aspect))\n }\n\n const canvas = document.createElement('canvas')\n canvas.width = tileW * cols\n canvas.height = tileH * rows\n const ctx = canvas.getContext('2d')!\n ctx.fillStyle = stock.color\n ctx.fillRect(0, 0, canvas.width, canvas.height)\n\n const texture = new THREE.CanvasTexture(canvas)\n texture.colorSpace = THREE.SRGBColorSpace\n texture.anisotropy = 4\n setAtlas({ texture, cols, rows })\n\n const drawTile = (index: number, tile: HTMLCanvasElement) => {\n if (disposed) return\n const x = (index % cols) * tileW\n const y = Math.floor(index / cols) * tileH\n ctx.drawImage(tile, x, y, tileW, tileH)\n texture.needsUpdate = true\n }\n\n contents.forEach((content, index) => {\n if (content.type === 'image') {\n const img = new Image()\n img.crossOrigin = 'anonymous'\n img.onload = () => drawTile(index, renderContentToCanvas(content, sheet, stock, img))\n img.src = content.src\n } else if (content.type === 'text' || content.type === 'receipt') {\n document.fonts.ready.then(() => drawTile(index, renderContentToCanvas(content, sheet, stock)))\n } else {\n drawTile(index, renderContentToCanvas(content, sheet, stock))\n }\n })\n\n return () => {\n disposed = true\n texture.dispose()\n }\n }, [stableContents, sheet.width, sheet.height, stock.id])\n\n return atlas\n}\n","import type { DeformerInstance, SheetDims } from '../deformers/types'\nimport { getDeformer } from '../deformers/registry'\nimport {\n TRANSLUCENCY_FRAGMENT,\n TRANSLUCENCY_VARYINGS,\n translucencyVertexChunk,\n} from '../surface/translucency'\n\n/**\n * Compose a deformer stack into GLSL — the GPU twin of deformers/compose.ts.\n * Each stack entry gets its own uniform namespace (`uRoll0_angle`,\n * `uFold1_offset`, …) so the same deformer type can appear twice\n * (letter-fold is two folds). Golden-vector parity with the JS path is\n * enforced by the GPU harness test.\n */\n\nexport interface ComposedDisplacement {\n /** Uniform declarations + displacement functions. */\n functionsSrc: string\n /** `vec3 plDisplace(vec3 p, vec2 uv, float t)` applying the whole stack. */\n displaceSrc: string\n /** Initial uniform values, keyed by their namespaced GLSL names (uSheet included). */\n uniforms: Record<string, number | number[]>\n}\n\nfunction glslType(value: number | number[]): string {\n if (typeof value === 'number') return 'float'\n return ['float', 'vec2', 'vec3', 'vec4'][value.length - 1]!\n}\n\n/**\n * Just the uniform VALUES for a stack (same namespaced keys as\n * buildDisplacementGLSL) — cheap enough to call every frame while a behavior\n * animates. Structure (names) is stable as long as the stack's type order is.\n */\nexport function stackUniformValues(\n stack: DeformerInstance[],\n sheet: SheetDims,\n): Record<string, number | number[]> {\n const uniforms: Record<string, number | number[]> = { uSheet: [sheet.width, sheet.height] }\n stack.forEach((instance, i) => {\n if (instance.enabled === false) return\n const deformer = getDeformer(instance.type)\n if (!deformer.glsl) return\n const ns = `u${cap(instance.type)}${i}_`\n const values = deformer.glsl.uniforms(instance.options) as Record<string, number | number[]>\n for (const [key, value] of Object.entries(values)) uniforms[ns + key] = value\n })\n return uniforms\n}\n\nexport function buildDisplacementGLSL(stack: DeformerInstance[], sheet: SheetDims): ComposedDisplacement {\n const decls: string[] = ['uniform vec2 uSheet;', 'float plBias = 1.0;']\n const functions: string[] = []\n const calls: string[] = []\n const uniforms: Record<string, number | number[]> = { uSheet: [sheet.width, sheet.height] }\n\n stack.forEach((instance, i) => {\n if (instance.enabled === false) return\n const deformer = getDeformer(instance.type)\n if (!deformer.glsl) {\n throw new Error(\n `[paperlab] Deformer \"${instance.type}\" has no GLSL implementation — it can't run in field mode.`,\n )\n }\n const ns = `u${cap(instance.type)}${i}_`\n const fn = `pl_${instance.type}${i}`\n const values = deformer.glsl.uniforms(instance.options) as Record<string, number | number[]>\n for (const [key, value] of Object.entries(values)) {\n decls.push(`uniform ${glslType(value)} ${ns}${key};`)\n uniforms[ns + key] = value\n }\n const strength = deformer.glsl.strength\n functions.push(\n deformer.glsl.chunk.replaceAll('FN', fn).replace(/U_(\\w+)/g, (_, name: string) =>\n // The strength uniform reads through the per-instance bias, so one\n // instanced draw call can bend every sheet by a different amount.\n name === strength ? `(${ns}${name} * plBias)` : ns + name,\n ),\n )\n calls.push(`${fn}(q, uv, t);`)\n })\n\n const displaceSrc = /* glsl */ `\nvec3 plDisplace(vec3 p, vec2 uv, float t, float bias) {\n plBias = bias;\n vec3 q = p;\n ${calls.join('\\n ')}\n return q;\n}\n`\n\n return { functionsSrc: `${decls.join('\\n')}\\n${functions.join('\\n')}`, displaceSrc, uniforms }\n}\n\n/**\n * The field-mode CSM vertex shader: displaced position + numerically\n * recomputed normal (two tangent probes — exact normals of an arbitrary\n * stack have no closed form).\n */\nexport function buildFieldVertexShader(composed: ComposedDisplacement): string {\n return /* glsl */ `\nuniform float uPlTime;\nattribute float aPhase;\nattribute float aAtlas;\nattribute float aBias;\nvarying vec2 vPaperUv;\nvarying float vAtlas;\n${TRANSLUCENCY_VARYINGS}\n${composed.functionsSrc}\n${composed.displaceSrc}\nvoid main() {\n float t = uPlTime + aPhase;\n vec3 p = plDisplace(position, uv, t, aBias);\n vec2 step = uSheet * 0.01;\n vec3 px = plDisplace(position + vec3(step.x, 0.0, 0.0), uv + vec2(0.01, 0.0), t, aBias);\n vec3 py = plDisplace(position + vec3(0.0, step.y, 0.0), uv + vec2(0.0, 0.01), t, aBias);\n vec3 n = cross(px - p, py - p);\n csm_Normal = length(n) > 1e-12 ? normalize(n) : vec3(0.0, 0.0, 1.0);\n csm_Position = p;\n${translucencyVertexChunk({ model: 'modelMatrix * instanceMatrix', position: 'p', normal: 'csm_Normal' })}\n vPaperUv = uv;\n vAtlas = aAtlas;\n}\n`\n}\n\n/**\n * Field fragment shader: per-instance tile from the shared content atlas on\n * the FRONT face; the BACK face renders the stock with an optional reversed\n * show-through ghost (per-paper back textures are a hero-mode feature).\n */\nexport function buildFieldFragmentShader(): string {\n return /* glsl */ `\nuniform sampler2D uAtlas;\nuniform vec2 uAtlasGrid;\nuniform float uBackDarken;\nuniform vec3 uStockColor;\nuniform float uShowThrough;\nvarying vec2 vPaperUv;\nvarying float vAtlas;\n${TRANSLUCENCY_FRAGMENT}\nvoid main() {\n float col = mod(vAtlas, uAtlasGrid.x);\n float row = floor(vAtlas / uAtlasGrid.x);\n vec2 tiled = (vPaperUv + vec2(col, uAtlasGrid.y - 1.0 - row)) / uAtlasGrid;\n vec4 front = texture2D(uAtlas, tiled);\n if (gl_FrontFacing) {\n csm_DiffuseColor = front;\n } else {\n csm_DiffuseColor = vec4(uStockColor * mix(vec3(1.0), front.rgb, uShowThrough), 1.0);\n csm_DiffuseColor.rgb *= uBackDarken;\n }\n // Light coming through the sheet, filtered by what is printed on it. Same\n // ink either side — the light passes through the same fibres regardless of\n // which face happens to be turned toward the camera.\n csm_Emissive = plTransmission(front.rgb);\n}\n`\n}\n\nfunction cap(s: string): string {\n return s.charAt(0).toUpperCase() + s.slice(1).replace(/-(\\w)/g, (_, c: string) => c.toUpperCase())\n}\n","import { z } from 'zod'\n\n/**\n * The walk — a path across the ground plane that a figure follows and that\n * layouts arrange paper along. Pure 2D math (x, z on the floor, y is always\n * up), no three.js, so it tests in node and is cheap enough to call from\n * inside a layout's pure `pose`.\n *\n * Centripetal Catmull-Rom through the control points — it will not cusp or\n * overshoot when two points bunch together, which a uniform spline does —\n * resampled to a uniform arc-length polyline. That resampling is the point:\n * `pointAt(s)` advances at constant SPEED, so a figure stepping `s` forward\n * at a steady rate covers ground at a steady rate. A raw spline parameter\n * would have it sprint through the straights and crawl around the corners.\n */\n\n/** A point on the floor. */\nexport type Ground = [x: number, z: number]\n\nexport const walkPathSchema = z.object({\n /**\n * Control points on the ground plane, [x, z]. The default walks away from\n * the camera down -Z — the shot every reference image is composed on.\n */\n points: z\n .array(z.tuple([z.number(), z.number()]))\n .min(2)\n .default([\n [0, 9],\n [0, -9],\n ]),\n /** Join the last point back to the first: an endless walk, and the only form `phase` can slide. */\n closed: z.boolean().default(false),\n})\n\nexport type WalkPathOptions = z.infer<typeof walkPathSchema>\n\nexport interface WalkPath {\n /** Total arc length in world units. */\n readonly length: number\n readonly closed: boolean\n /** `s` is normalized arc length: 0 = the start, 1 = the end. Closed paths wrap, open paths clamp. */\n pointAt(s: number): Ground\n /** Unit forward direction at `s`. */\n tangentAt(s: number): Ground\n /** Unit LEFT-hand normal at `s` — the side of the aisle a walker's left hand points to. */\n normalAt(s: number): Ground\n}\n\n/** Polyline resolution. 24 per segment holds a tight curve to well under a millimetre of chord error. */\nconst SAMPLES_PER_SEGMENT = 24\n\n/** Coincident control points would collapse the knot spacing and divide by zero. */\nconst EPSILON = 1e-6\n\n/** Centripetal: alpha = 0.5. (0 would be uniform, 1 chordal.) */\nconst ALPHA = 0.5\n\nfunction knot(a: Ground, b: Ground, t: number): number {\n return t + Math.max(Math.hypot(b[0] - a[0], b[1] - a[1]), EPSILON) ** ALPHA\n}\n\n/** Linear interpolation in knot space — the Barry-Goldman building block. */\nfunction lerpKnot(a: Ground, b: Ground, ta: number, tb: number, t: number): Ground {\n const span = tb - ta\n const k = span === 0 ? 0 : (t - ta) / span\n return [a[0] + (b[0] - a[0]) * k, a[1] + (b[1] - a[1]) * k]\n}\n\n/** One centripetal Catmull-Rom segment p1→p2, `u` in 0..1. */\nfunction segmentPoint(p0: Ground, p1: Ground, p2: Ground, p3: Ground, u: number): Ground {\n const t0 = 0\n const t1 = knot(p0, p1, t0)\n const t2 = knot(p1, p2, t1)\n const t3 = knot(p2, p3, t2)\n const t = t1 + (t2 - t1) * u\n const a1 = lerpKnot(p0, p1, t0, t1, t)\n const a2 = lerpKnot(p1, p2, t1, t2, t)\n const a3 = lerpKnot(p2, p3, t2, t3, t)\n const b1 = lerpKnot(a1, a2, t0, t2, t)\n const b2 = lerpKnot(a2, a3, t1, t3, t)\n return lerpKnot(b1, b2, t1, t2, t)\n}\n\n/** The phantom control point beyond an open path's end: reflect the interior neighbor. */\nfunction reflect(end: Ground, inner: Ground): Ground {\n return [2 * end[0] - inner[0], 2 * end[1] - inner[1]]\n}\n\nexport function createWalkPath(options: WalkPathOptions): WalkPath {\n const pts = options.points as Ground[]\n const n = pts.length\n const closed = options.closed && n > 2\n const segments = closed ? n : n - 1\n\n // Resample the spline into a uniformly-indexed polyline, carrying the\n // cumulative arc length so `s` can be inverted by search.\n const samples: Ground[] = []\n const cumulative: number[] = []\n let total = 0\n for (let seg = 0; seg < segments; seg++) {\n const p1 = pts[seg]!\n const p2 = pts[(seg + 1) % n]!\n const p0 = closed ? pts[(seg - 1 + n) % n]! : seg > 0 ? pts[seg - 1]! : reflect(pts[0]!, pts[1]!)\n const p3 = closed ? pts[(seg + 2) % n]! : seg + 2 < n ? pts[seg + 2]! : reflect(pts[n - 1]!, pts[n - 2]!)\n // The last sample of a segment is the first of the next — emit it only\n // at the very end of an open path, where nothing follows to repeat it.\n const last = seg === segments - 1 && !closed ? SAMPLES_PER_SEGMENT : SAMPLES_PER_SEGMENT - 1\n for (let k = 0; k <= last; k++) {\n const point = segmentPoint(p0, p1, p2, p3, k / SAMPLES_PER_SEGMENT)\n const previous = samples[samples.length - 1]\n if (previous) total += Math.hypot(point[0] - previous[0], point[1] - previous[1])\n samples.push(point)\n cumulative.push(total)\n }\n }\n if (closed) {\n // Close the ring: the start point repeats as the final sample so a\n // search near s = 1 has a segment to land in.\n const first = samples[0]!\n const previous = samples[samples.length - 1]!\n total += Math.hypot(first[0] - previous[0], first[1] - previous[1])\n samples.push([first[0], first[1]])\n cumulative.push(total)\n }\n\n const length = total\n\n function normalize(s: number): number {\n if (!Number.isFinite(s)) return 0\n if (!closed) return Math.min(Math.max(s, 0), 1)\n const wrapped = s - Math.floor(s)\n return wrapped\n }\n\n function pointAt(s: number): Ground {\n const target = normalize(s) * length\n if (length === 0) return [samples[0]![0], samples[0]![1]]\n // Binary search for the first sample at or past the target distance.\n let low = 0\n let high = cumulative.length - 1\n while (low < high) {\n const mid = (low + high) >> 1\n if (cumulative[mid]! < target) low = mid + 1\n else high = mid\n }\n const i = Math.max(low, 1)\n const before = cumulative[i - 1]!\n const span = cumulative[i]! - before\n const k = span <= 0 ? 0 : (target - before) / span\n const a = samples[i - 1]!\n const b = samples[i]!\n return [a[0] + (b[0] - a[0]) * k, a[1] + (b[1] - a[1]) * k]\n }\n\n /** Central difference over a fixed world-space step — stable at any path length. */\n function tangentAt(s: number): Ground {\n const ds = length > 0 ? Math.min(0.01, 0.5 / length) : 0.01\n const here = normalize(s)\n const a = pointAt(closed ? here - ds : Math.max(here - ds, 0))\n const b = pointAt(closed ? here + ds : Math.min(here + ds, 1))\n const dx = b[0] - a[0]\n const dz = b[1] - a[1]\n const len = Math.hypot(dx, dz)\n // A degenerate path has no direction to report; -Z is the house forward.\n return len < EPSILON ? [0, -1] : [dx / len, dz / len]\n }\n\n function normalAt(s: number): Ground {\n const [tx, tz] = tangentAt(s)\n // Left of forward, with +Y up: right = forward × up, so left is its negation.\n return [tz, -tx]\n }\n\n return { length, closed, pointAt, tangentAt, normalAt }\n}\n\n/**\n * Building the arc-length table costs a few hundred flops, and `pose` runs\n * per sheet per frame — so paths are memoized by value. Same options in,\n * same object out, which keeps layouts pure from the outside.\n */\nconst cache = new Map<string, WalkPath>()\nconst CACHE_LIMIT = 32\n\nexport function getWalkPath(options: WalkPathOptions): WalkPath {\n const key = `${options.closed ? 'c' : 'o'}|${options.points.map((p) => `${p[0]},${p[1]}`).join(';')}`\n const hit = cache.get(key)\n if (hit) return hit\n const path = createWalkPath(options)\n if (cache.size >= CACHE_LIMIT) {\n const oldest = cache.keys().next().value\n if (oldest !== undefined) cache.delete(oldest)\n }\n cache.set(key, path)\n return path\n}\n","import { z } from 'zod'\nimport type { AnyOptions, SheetDims } from '../../deformers/types'\nimport { SHEET_LIFT, sheetLayoutSchema, sheetSlotXY, type SheetLayoutOptions } from '../sheetGrid'\nimport { getWalkPath, walkPathSchema } from '../../stage/path'\n\n/**\n * A layout is a pure `pose(i, n, options, phase)` function — no state, no\n * three.js. `phase` is the motion driver's continuous offset in turns\n * (0..1 = one full cycle); cyclic layouts use it, static ones ignore it.\n * Community layouts are ~30 lines.\n *\n * Every built-in names a place paper actually sits — a fanned swatch deck, a\n * slipped stack, a heap on a desk — because arrangement alone is what makes a\n * field read as a photo carousel instead of as paper. The other half of that\n * is `bias`: paper in the world does not all bend alike.\n */\n\nexport interface PaperPose {\n position: [number, number, number]\n rotation: [number, number, number]\n scale: number\n /**\n * How strongly this sheet takes the field's deformation: 1 = exactly as the\n * preset configures it, 0 = flat. Lets one instanced draw call curl the top\n * of a pile while the sheets pressed underneath stay flat. Omitted = 1.\n */\n bias?: number\n}\n\nexport interface Layout<O = Record<string, unknown>> {\n id: string\n label: string\n defaults: O\n optionsSchema: z.ZodType<O, z.ZodTypeDef, unknown>\n /**\n * `sheet` is the field's paper size. Layouts that arrange by CONTACT —\n * edges meeting, sheets resting on each other — cannot work without it,\n * and a layout that ignores it may simply omit the parameter.\n */\n pose(i: number, n: number, o: O, phase: number, sheet: SheetDims): PaperPose\n /**\n * Where along a walk this layout put each paper, as normalized arc length,\n * in the layout's own index order.\n *\n * Only layouts that arrange along a PATH can answer, which is why it is\n * optional. Stage mode uses it to let a viewer step from one paper to the\n * next: the stops have to be where the paper actually is, and the only\n * thing that knows that is the function that placed it.\n */\n walkStops?(n: number, o: O): number[]\n}\n\n/** For the odd caller that has no papers yet to measure. */\nexport const DEFAULT_SHEET: SheetDims = { width: 1, height: 1.4 }\n\nconst TAU = Math.PI * 2\nconst DEG = Math.PI / 180\n\n/** Deterministic per-index jitter — layouts must be pure. */\nfunction jitter(seed: number, i: number): number {\n let h = Math.imul((seed * 1000 + i + 1) ^ 0x9e3779b9, 2654435761)\n h = Math.imul(h ^ (h >>> 13), 3266489917)\n return (((h ^ (h >>> 16)) >>> 0) / 4294967295) * 2 - 1\n}\n\n/** 0 at the first sheet, 1 at the last — the spine of most layouts. */\nfunction ramp(i: number, n: number): number {\n return n > 1 ? i / (n - 1) : 1\n}\n\nconst ringSchema = z.object({\n radius: z.number().min(0.5).max(12).default(2.6),\n tiltDeg: z.number().min(-45).max(45).default(8),\n})\n/** Prints pegged around a circle — the one carousel worth keeping. */\nexport const ring: Layout<z.infer<typeof ringSchema>> = {\n id: 'ring',\n label: 'Ring',\n defaults: ringSchema.parse({}),\n optionsSchema: ringSchema,\n pose(i, n, o, phase) {\n const theta = (i / n + phase) * TAU\n return {\n position: [Math.sin(theta) * o.radius, 0, Math.cos(theta) * o.radius],\n // Face radially OUTWARD so the papers nearest the camera show their\n // front (content) side — you stand outside the ring, not inside it.\n rotation: [(o.tiltDeg * Math.PI) / 180, theta, 0],\n scale: 1,\n }\n },\n}\n\nconst fanSchema = z.object({\n /** Total angular sweep from the first sheet to the last, degrees. */\n sweep: z.number().min(0).max(180).default(72),\n /** Where the shared pin sits, in half-sheet-heights below center. 1 = the bottom edge. */\n hinge: z.number().min(0).max(4).default(1.15),\n /** Thickness step so the sheets stack in order instead of z-fighting. */\n lift: z.number().min(0.002).max(0.08).default(0.012),\n /** How much flatter the middle of the fan sits than its outer sheets. */\n bow: z.number().min(0).max(1).default(0.7),\n})\n/**\n * A Pantone deck, a paint-chip book, a hand of cards: every sheet pinned at\n * one shared point and swung open. The sheets nearest the outside of the\n * sweep carry the most curl, which is what sells the hinge as a hinge.\n */\nexport const fan: Layout<z.infer<typeof fanSchema>> = {\n id: 'fan',\n label: 'Fan',\n defaults: fanSchema.parse({}),\n optionsSchema: fanSchema,\n pose(i, n, o, _phase, sheet) {\n const f = n > 1 ? i / (n - 1) : 0.5\n const theta = (f - 0.5) * o.sweep * DEG\n const hinge = (o.hinge * sheet.height) / 2\n // Swing the sheet about the shared pivot, then shift so the middle sheet\n // sits at the origin — the fan stays centered as `sweep` opens and closes.\n const open = Math.abs(f - 0.5) * 2\n return {\n position: [-Math.sin(theta) * hinge, Math.cos(theta) * hinge - hinge, i * o.lift],\n rotation: [0, 0, theta],\n scale: 1,\n bias: 1 - (1 - open) * o.bow,\n }\n },\n}\n\nconst spreadSchema = z.object({\n /** How far each sheet slides past the one below it. */\n slip: z.number().min(0.02).max(2).default(0.3),\n /** Direction of the slide, degrees. 0 slides right, 90 slides up. */\n angle: z.number().min(-180).max(180).default(28),\n lift: z.number().min(0.002).max(0.08).default(0.012),\n /** How much more the sheets at the far end of the slide bow. */\n bow: z.number().min(0).max(1).default(0.6),\n /** Nothing hand-slid is perfectly square — a touch of per-sheet rotation. */\n drift: z.number().min(0).max(1).default(0.15),\n})\n/**\n * A ream pushed sideways, or a deck dealt across a table: parallel sheets at\n * a constant offset, each one bowing a little more as it comes free of the\n * stack's weight.\n */\nexport const spread: Layout<z.infer<typeof spreadSchema>> = {\n id: 'spread',\n label: 'Spread',\n defaults: spreadSchema.parse({}),\n optionsSchema: spreadSchema,\n pose(i, n, o) {\n const centered = i - (n - 1) / 2\n const a = o.angle * DEG\n return {\n position: [Math.cos(a) * o.slip * centered, Math.sin(a) * o.slip * centered, i * o.lift],\n rotation: [0, 0, jitter(11, i) * 0.2 * o.drift],\n scale: 1,\n bias: 1 - (1 - ramp(i, n)) * o.bow,\n }\n },\n}\n\nconst pileSchema = z.object({\n /** How far sheets wander from the center of the heap. */\n scatter: z.number().min(0).max(2).default(0.22),\n /** Widest angle a sheet sits off square, degrees. */\n turn: z.number().min(0).max(180).default(24),\n lift: z.number().min(0.002).max(0.08).default(0.011),\n /** How flat the sheets underneath are pressed by the ones on top. */\n press: z.number().min(0).max(1).default(0.85),\n seed: z.number().int().min(0).max(9999).default(3),\n})\n/**\n * The heap on a desk. The physical tell no parametric curve can fake: sheets\n * rest ON each other, so only the top of the pile keeps its curl and\n * everything below is pressed flat by the weight above it.\n */\nexport const pile: Layout<z.infer<typeof pileSchema>> = {\n id: 'pile',\n label: 'Pile',\n defaults: pileSchema.parse({}),\n optionsSchema: pileSchema,\n pose(i, n, o) {\n return {\n position: [jitter(o.seed, i) * o.scatter, jitter(o.seed + 1, i) * o.scatter * 0.8, i * o.lift],\n rotation: [0, 0, jitter(o.seed + 2, i) * o.turn * DEG],\n scale: 1,\n bias: 1 - (1 - ramp(i, n)) * o.press,\n }\n },\n}\n\nconst wallSchema = z.object({\n gapX: z.number().min(0.05).max(1).default(0.22),\n gapY: z.number().min(0.05).max(1).default(0.3),\n jitterAmt: z.number().min(0).max(1).default(0.25),\n /** Spread of sag across the wall — no two pinned sheets hang alike. */\n sag: z.number().min(0).max(1).default(0.45),\n})\n/** A studio wall of pinned sheets: a grid, but nothing hangs quite square. */\nexport const wall: Layout<z.infer<typeof wallSchema>> = {\n id: 'wall',\n label: 'Wall',\n defaults: wallSchema.parse({}),\n optionsSchema: wallSchema,\n pose(i, n, o, _phase, sheet) {\n const cols = Math.ceil(Math.sqrt((n * sheet.height) / sheet.width))\n const rows = Math.ceil(n / cols)\n const col = i % cols\n const row = Math.floor(i / cols)\n // Gaps are breathing room around the real paper — a wall of 1.2×0.9\n // prints and a wall of 1×1.4 letters both want even gutters.\n const cellW = sheet.width + o.gapX\n const cellH = sheet.height + o.gapY\n return {\n position: [\n (col - (cols - 1) / 2) * cellW,\n ((rows - 1) / 2 - row) * cellH,\n jitter(5, i) * 0.04 * o.jitterAmt * 4,\n ],\n rotation: [0, 0, jitter(6, i) * 0.05 * o.jitterAmt * 4],\n scale: 1,\n bias: 1 - Math.abs(jitter(7, i)) * o.sag,\n }\n },\n}\n\nconst spillSchema = z.object({\n spreadX: z.number().min(0.5).max(8).default(2.4),\n spreadY: z.number().min(0.5).max(8).default(1.5),\n depth: z.number().min(0).max(6).default(1.6),\n /** How far sheets pitch and roll out of the picture plane. */\n tumble: z.number().min(0).max(1).default(0.5),\n /** Spread of bend across the sheets — a spill does not fold them alike. */\n vary: z.number().min(0).max(1).default(0.6),\n seed: z.number().int().min(0).max(9999).default(7),\n})\n/**\n * A dropped folder's worth of paper, mid-air — what a `pile` looks like the\n * moment before it settles. Loose in all three axes, and (the part that\n * separates it from confetti) every sheet caught at its own angle AND its\n * own amount of bend.\n */\nexport const spill: Layout<z.infer<typeof spillSchema>> = {\n id: 'spill',\n label: 'Spill',\n defaults: spillSchema.parse({}),\n optionsSchema: spillSchema,\n pose(i, _n, o) {\n const tumble = o.tumble * 2\n return {\n position: [\n jitter(o.seed, i) * o.spreadX,\n jitter(o.seed + 1, i) * o.spreadY,\n jitter(o.seed + 2, i) * o.depth,\n ],\n rotation: [\n jitter(o.seed + 3, i) * 0.4 * tumble,\n jitter(o.seed + 4, i) * 0.5 * tumble,\n jitter(o.seed + 5, i) * 0.4 * tumble,\n ],\n scale: 0.85 + Math.abs(jitter(o.seed + 6, i)) * 0.3,\n bias: 1 - Math.abs(jitter(o.seed + 7, i)) * o.vary,\n }\n },\n}\n\nconst sweepSchema = z.object({\n columns: z.number().int().min(1).max(24).default(5),\n /** Breathing room around each specimen. */\n gap: z.number().min(0).max(2).default(0.22),\n /** Deformation at the first specimen and at the last. */\n from: z.number().min(0).max(1).default(0),\n to: z.number().min(0).max(1).default(1),\n})\n/**\n * A specimen chart: the same sheet mounted in a grid, its deformation ramped\n * across the series so one image shows a curl at ten stages instead of one.\n * The layout the rest of this library exists to make possible — and the one\n * that documents every deformer for free.\n *\n * Only as legible as the preset it charts: a sheet with no behavior or\n * deformers has nothing for the ramp to scale, and every specimen comes out\n * identical.\n */\nexport const sweep: Layout<z.infer<typeof sweepSchema>> = {\n id: 'sweep',\n label: 'Sweep',\n defaults: sweepSchema.parse({}),\n optionsSchema: sweepSchema,\n pose(i, n, o, _phase, sheet) {\n const cols = Math.min(o.columns, Math.max(n, 1))\n const rows = Math.ceil(n / cols)\n const col = i % cols\n const row = Math.floor(i / cols)\n return {\n position: [\n (col - (cols - 1) / 2) * (sheet.width + o.gap),\n ((rows - 1) / 2 - row) * (sheet.height + o.gap),\n 0,\n ],\n rotation: [0, 0, 0],\n scale: 1,\n bias: o.from + (o.to - o.from) * ramp(i, n),\n }\n },\n}\n\nconst bookSchema = z.object({\n /** How far the outermost page lifts off the block, degrees. */\n spread: z.number().min(0).max(150).default(55),\n /** Fraction of the pages bound to the left. 0 = a one-sided sample book. */\n split: z.number().min(0).max(1).default(0.5),\n /** Page thickness — the gap between pages of one block. */\n lift: z.number().min(0.001).max(0.05).default(0.008),\n /** How much more a lifted page arcs than one lying flat in the block. */\n gutter: z.number().min(0).max(1).default(0.6),\n})\n/**\n * An open codex: pages hinged on a shared spine, each block splaying away\n * from the gutter. `split` slides it between the two bound forms paper takes\n * — 0.5 is a book lying open, 0 is a swatch deck or sample book bound down\n * one side. Pages lying flat in the block are pressed by the ones above;\n * only the lifted pages keep their arc.\n */\nexport const book: Layout<z.infer<typeof bookSchema>> = {\n id: 'book',\n label: 'Book',\n defaults: bookSchema.parse({}),\n optionsSchema: bookSchema,\n pose(i, n, o, _phase, sheet) {\n const half = sheet.width / 2\n const left = Math.round(n * o.split)\n const onLeft = i < left\n const count = onLeft ? left : n - left\n const k = onLeft ? i : i - left\n const f = count > 1 ? k / (count - 1) : 1\n const theta = f * o.spread * DEG\n // Swing the page about the spine at x = 0; `side` mirrors the left block.\n const side = onLeft ? -1 : 1\n const cos = Math.cos(theta)\n const sin = Math.sin(theta)\n // Stack along the page's own normal so pages standing near-vertical\n // separate sideways rather than sinking into each other.\n const offset = k * o.lift\n return {\n position: [side * (half * cos - offset * sin), 0, half * sin + offset * cos],\n rotation: [0, -side * theta, 0],\n scale: 1,\n bias: 1 - (1 - f) * o.gutter,\n }\n },\n}\n\nconst accordionSchema = z.object({\n /** How far each panel tilts off the strip's line, degrees. 0 = flat, 90 = shut. */\n angle: z.number().min(0).max(89).default(55),\n /** A concertina holds its creases — how much bow the panels keep. */\n slack: z.number().min(0).max(1).default(0.15),\n})\n/**\n * A concertina: panels alternating about creases they genuinely share, so\n * the sheets read as ONE folded strip rather than as N separate papers —\n * the only layout here where that is true. Adjacent edges are solved to\n * meet, which is why it needs the sheet's real width.\n */\nexport const accordion: Layout<z.infer<typeof accordionSchema>> = {\n id: 'accordion',\n label: 'Accordion',\n defaults: accordionSchema.parse({}),\n optionsSchema: accordionSchema,\n pose(i, n, o, _phase, sheet) {\n const theta = o.angle * DEG\n const side = i % 2 === 0 ? 1 : -1\n // Solving edge-meets-edge for alternating ±angle puts every panel center\n // on one line, spaced by the panel's foreshortened width.\n const step = sheet.width * Math.cos(theta)\n return {\n position: [(i - (n - 1) / 2) * step, 0, 0],\n rotation: [0, side * theta, 0],\n scale: 1,\n bias: o.slack,\n }\n },\n}\n\nconst rackSchema = z.object({\n /** Gap along the row, as a fraction of the paper's width. Under 1 they overlap. */\n spacing: z.number().min(0.05).max(2).default(0.82),\n /** How far a sheet leans back off vertical, degrees. */\n lean: z.number().min(0).max(70).default(16),\n /** How much that lean differs sheet to sheet — nothing propped is uniform. */\n vary: z.number().min(0).max(1).default(0.55),\n /** Small rotations off square. */\n sway: z.number().min(0).max(1).default(0.35),\n seed: z.number().int().min(0).max(9999).default(5),\n})\n/**\n * Prints stood in a row and leaning back — against a wall, in a rack, propped\n * along a shelf. The one arrangement here that RESTS on a surface rather than\n * floating: every sheet pivots on the bottom edge it actually stands on, so\n * the row shares a floor. The further a sheet has leaned, the more it bows\n * under its own weight.\n *\n * (Stacking these front-to-back the way a letter tray really holds paper is\n * physically honest and visually useless — the front sheet hides the rest.\n * A row is the arrangement you can actually see.)\n */\nexport const rack: Layout<z.infer<typeof rackSchema>> = {\n id: 'rack',\n label: 'Rack',\n defaults: rackSchema.parse({}),\n optionsSchema: rackSchema,\n pose(i, n, o, _phase, sheet) {\n const lean = o.lean * DEG * (1 + jitter(o.seed, i) * o.vary)\n const half = sheet.height / 2\n return {\n position: [\n (i - (n - 1) / 2) * sheet.width * o.spacing,\n // Standing on the floor: the bottom edge stays at y = 0 as it leans.\n half * Math.cos(lean),\n -half * Math.sin(lean) + i * 0.004,\n ],\n rotation: [-lean, jitter(o.seed + 1, i) * 0.12 * o.sway, jitter(o.seed + 2, i) * 0.06 * o.sway],\n scale: 1,\n // A sheet leaning further has more of its own weight to carry.\n bias: o.lean === 0 ? 0 : Math.min(1, lean / (o.lean * DEG * (1 + o.vary))),\n }\n },\n}\n\nconst colonnadeSchema = z.object({\n /** The walk the colonnade is built along — see `stage/path`. */\n path: walkPathSchema.default({}),\n /** Half-width of the clear aisle: how far each banner stands off the walk line. */\n aisle: z.number().min(0.2).max(20).default(2.4),\n /** How much that gap opens and closes along the walk. Nothing hung by hand is a corridor. */\n breathe: z.number().min(0).max(1).default(0.3),\n /** Widest angle a banner turns off square to the aisle, degrees. */\n twist: z.number().min(0).max(90).default(22),\n /** Fraction of the walk left clear at each end, so the figure has somewhere to enter from. */\n margin: z.number().min(0).max(0.45).default(0.05),\n /** Spread of banner heights, 0..1. */\n rise: z.number().min(0).max(1).default(0.28),\n /**\n * How far the banners lift off the floor, as a fraction of their height.\n *\n * NEGATIVE is allowed, and it is what pooling actually requires. At 0 a\n * banner's bottom EDGE sits on the floor — which is not the same as paper\n * pooling on it, however much the old comment here claimed otherwise. A\n * ribbon creases a pool-length above its bottom edge, so it has to hang\n * that much lower for the crease to land on the ground and the slack to\n * lie ON it rather than in mid-air parallel to it.\n *\n * The bound used to be 0, so the one thing this option documented itself\n * as doing was the one thing it could not do.\n */\n hover: z.number().min(-0.5).max(1).default(0),\n /** Spread of deformation — no two lengths of hung paper drape alike. */\n drape: z.number().min(0).max(1).default(0.5),\n seed: z.number().int().min(0).max(9999).default(2),\n})\n/**\n * A nave of hanging banners flanking a walk: paper as ARCHITECTURE rather\n * than as an object on a desk. The first layout here that arranges along a\n * path instead of around an origin, which is what lets a figure walk through\n * it — the aisle is guaranteed clear because the banners are placed off the\n * walk line, not merely near it.\n *\n * Banners alternate ranks (left, right, left…) and the two ranks are\n * staggered by a quarter step, so you pass them one at a time rather than\n * through a ladder of matched pairs. Each faces across the aisle: a banner\n * ahead of you presents its face, which is the whole reason to print\n * anything on it.\n */\n/**\n * How far along the walk banner `i` stands, before any phase offset.\n *\n * Pulled out of `pose` because two things now need it and they must not\n * disagree: the banner is PLACED here, and stage mode STOPS here when the\n * viewer steps from one paper to the next. A stop that is not where the\n * paper is would be a navigation that misses everything it aims at.\n */\nexport function colonnadeStop(i: number, n: number, margin: number): number {\n const side = i % 2 === 0 ? 1 : -1\n const pairs = Math.max(Math.ceil(n / 2), 1)\n const k = Math.floor(i / 2)\n const span = 1 - margin * 2\n const step = pairs > 1 ? span / (pairs - 1) : 0\n return margin + (pairs > 1 ? k * step : span / 2) + side * step * 0.25\n}\n\nexport const colonnade: Layout<z.infer<typeof colonnadeSchema>> = {\n id: 'colonnade',\n label: 'Colonnade',\n defaults: colonnadeSchema.parse({}),\n optionsSchema: colonnadeSchema,\n walkStops(n, o) {\n return Array.from({ length: n }, (_, i) => colonnadeStop(i, n, o.margin))\n },\n pose(i, n, o, phase, sheet) {\n const path = getWalkPath(o.path)\n const side = i % 2 === 0 ? 1 : -1\n const base = colonnadeStop(i, n, o.margin)\n // Only a closed walk can slide: on an open one, offsetting by phase would\n // teleport the far banner back to the near end mid-shot.\n const s = path.closed ? base + phase : base\n const [px, pz] = path.pointAt(s)\n const [nx, nz] = path.normalAt(s)\n const scale = 1 + jitter(o.seed, i) * o.rise * 0.5\n const offset = o.aisle * (1 + jitter(o.seed + 1, i) * o.breathe)\n const height = sheet.height * scale\n // Face the centerline: the inward direction is the aisle normal, negated\n // on whichever rank this banner stands in.\n const yaw = Math.atan2(-side * nx, -side * nz) + jitter(o.seed + 2, i) * o.twist * DEG\n return {\n position: [px + nx * side * offset, height / 2 + height * o.hover, pz + nz * side * offset],\n rotation: [0, yaw, 0],\n scale,\n bias: 1 - Math.abs(jitter(o.seed + 3, i)) * o.drape,\n }\n },\n}\n\n/**\n * A block of stamps: flat rows × columns grid in register, floating a hair\n * above the (field-rendered) backing sheet. Standard layout contract — it\n * also works standalone as a plain grid; `backing`/`backingMargin` are read\n * by the field renderer, not by `pose`.\n */\nexport const sheet: Layout<SheetLayoutOptions> = {\n id: 'sheet',\n label: 'Sheet',\n defaults: sheetLayoutSchema.parse({}),\n optionsSchema: sheetLayoutSchema,\n pose(i, _n, o) {\n const { x, y } = sheetSlotXY(i, o)\n return { position: [x, y, SHEET_LIFT], rotation: [0, 0, 0], scale: 1 }\n },\n}\n\nconst registry = new Map<string, Layout<AnyOptions>>()\n\nexport function registerLayout(layout: Layout<AnyOptions>): void {\n registry.set(layout.id, layout)\n}\n\nexport function getLayout(id: string): Layout<AnyOptions> {\n const layout = registry.get(id)\n if (!layout) {\n throw new Error(`[paperlab] Unknown layout \"${id}\". Registered: ${[...registry.keys()].join(', ')}`)\n }\n return layout\n}\n\nexport function listLayouts(): string[] {\n return [...registry.keys()]\n}\n\nregisterLayout(ring)\nregisterLayout(fan)\nregisterLayout(spread)\nregisterLayout(pile)\nregisterLayout(wall)\nregisterLayout(spill)\nregisterLayout(sweep)\nregisterLayout(book)\nregisterLayout(accordion)\nregisterLayout(rack)\nregisterLayout(colonnade)\nregisterLayout(sheet)\n","import { sheetBackingSize, sheetSlotXY, type SheetLayoutOptions } from '../field/sheetGrid'\n\n/**\n * The backing sheet's generated content: per-slot ghost silhouettes a few\n * percent lighter than the backing tint. When a slot's paper detaches\n * (picked/placed), its silhouette lightens further and gains a faint\n * adhesive-sheen gradient — the visual proof of removal. Redrawn on state\n * change, never per-frame.\n */\n\nexport interface SilhouetteRect {\n /** Canvas-UV rect (0..1, y down) of slot i on the backing sheet. */\n x: number\n y: number\n w: number\n h: number\n}\n\n/** Pure: where each slot's silhouette sits on the backing, in canvas UV. */\nexport function silhouetteRects(o: SheetLayoutOptions, count: number): SilhouetteRect[] {\n const { width, height } = sheetBackingSize(o)\n const rects: SilhouetteRect[] = []\n for (let i = 0; i < count; i++) {\n const { x, y } = sheetSlotXY(i, o)\n rects.push({\n x: (x - o.cellWidth / 2 + width / 2) / width,\n // World y up → canvas y down.\n y: (height / 2 - y - o.cellHeight / 2) / height,\n w: o.cellWidth / width,\n h: o.cellHeight / height,\n })\n }\n return rects\n}\n\n/** Lighten a hex tint toward white by `amount` (0..1). */\nexport function lightenHex(hex: string, amount: number): string {\n const n = parseInt(hex.replace('#', ''), 16)\n const ch = (shift: number) => {\n const c = (n >> shift) & 0xff\n return Math.min(255, Math.round(c + (255 - c) * amount))\n }\n return `#${((ch(16) << 16) | (ch(8) << 8) | ch(0)).toString(16).padStart(6, '0')}`\n}\n\nexport interface BackingDrawSpec {\n options: SheetLayoutOptions\n count: number\n tint: string\n /** Slot indices whose paper has been picked/placed away. */\n removed: ReadonlySet<number>\n}\n\n/** Draw the backing content onto a canvas (called on state change only). */\nexport function drawBacking(canvas: HTMLCanvasElement, spec: BackingDrawSpec): void {\n const ctx = canvas.getContext('2d')\n if (!ctx) return\n const { width: cw, height: chh } = canvas\n ctx.fillStyle = spec.tint\n ctx.fillRect(0, 0, cw, chh)\n\n const rects = silhouetteRects(spec.options, spec.count)\n rects.forEach((r, i) => {\n const removed = spec.removed.has(i)\n const x = r.x * cw\n const y = r.y * chh\n const w = r.w * cw\n const h = r.h * chh\n const radius = Math.min(w, h) * 0.06\n\n ctx.fillStyle = lightenHex(spec.tint, removed ? 0.5 : 0.07)\n roundedRect(ctx, x, y, w, h, radius)\n ctx.fill()\n\n if (removed) {\n // Faint adhesive sheen: a diagonal highlight across the bare silhouette.\n const sheen = ctx.createLinearGradient(x, y, x + w, y + h)\n sheen.addColorStop(0, 'rgba(255,255,255,0)')\n sheen.addColorStop(0.5, 'rgba(255,255,255,0.35)')\n sheen.addColorStop(1, 'rgba(255,255,255,0)')\n ctx.fillStyle = sheen\n roundedRect(ctx, x, y, w, h, radius)\n ctx.fill()\n }\n })\n}\n\nfunction roundedRect(\n ctx: CanvasRenderingContext2D,\n x: number,\n y: number,\n w: number,\n h: number,\n r: number,\n): void {\n ctx.beginPath()\n ctx.moveTo(x + r, y)\n ctx.arcTo(x + w, y, x + w, y + h, r)\n ctx.arcTo(x + w, y + h, x, y + h, r)\n ctx.arcTo(x, y + h, x, y, r)\n ctx.arcTo(x, y, x + w, y, r)\n ctx.closePath()\n}\n","import { useState } from 'react'\nimport { contentText } from '../a11y'\nimport { contentSchema } from '../config/schema'\nimport { resolveConfig } from '../PaperMesh'\nimport type { FieldA11yController } from './interactiveField'\nimport type { FieldPaperSlot } from './slots'\n\n/** Carry state of the hidden keyboard mirror: which paper is aloft, which zone is focused. */\nexport interface KeyboardCarry {\n slot: number\n zoneIndex: number\n}\n\n/** A keyboard step's decision: the next carry state and whether it consumed the key. */\nexport interface KeyboardStepResult {\n carry: KeyboardCarry | null\n handled: boolean\n}\n\n/**\n * The M6 §6 keyboard flow as a pure step (so it's testable without a DOM):\n * given the current carry state, the focused paper `slot`, and the pressed\n * `key`, it drives the field `controller` (pick → move between zones → place /\n * cancel) and returns the next carry state. All side effects go through\n * `controller`; the caller applies `carry` to its state and calls\n * `preventDefault()` when `handled` is true.\n */\nexport function fieldKeyboardStep(\n carry: KeyboardCarry | null,\n slot: number,\n key: string,\n controller: FieldA11yController,\n): KeyboardStepResult {\n if (!carry) {\n // Not carrying: Enter/Space on a focused paper picks it up.\n if (key === 'Enter' || key === ' ') {\n return { carry: controller.pick(slot) ? { slot, zoneIndex: 0 } : null, handled: true }\n }\n return { carry, handled: false }\n }\n // Carrying: only the paper actually aloft responds.\n if (carry.slot !== slot) return { carry, handled: false }\n const zoneCount = Math.max(controller.zoneIds().length, 1)\n if (key === 'ArrowRight' || key === 'ArrowDown') {\n return { carry: { ...carry, zoneIndex: (carry.zoneIndex + 1) % zoneCount }, handled: true }\n }\n if (key === 'ArrowLeft' || key === 'ArrowUp') {\n return {\n carry: { ...carry, zoneIndex: (carry.zoneIndex - 1 + zoneCount) % zoneCount },\n handled: true,\n }\n }\n if (key === 'Enter' || key === ' ') {\n const zone = controller.zoneIds()[carry.zoneIndex]\n if (zone) controller.placeAtZone(slot, zone)\n return { carry: null, handled: true }\n }\n if (key === 'Escape') {\n controller.cancel(slot)\n return { carry: null, handled: true }\n }\n return { carry, handled: false }\n}\n\nconst mirrorHidden: React.CSSProperties = {\n position: 'absolute',\n width: 1,\n height: 1,\n padding: 0,\n margin: -1,\n overflow: 'hidden',\n clip: 'rect(0 0 0 0)',\n whiteSpace: 'nowrap',\n border: 0,\n}\n\n/**\n * The hidden DOM mirror of an interactive field: each paper is a button.\n * Keyboard flow — focus a paper, Enter picks it, arrow keys move between\n * zones, Enter places, Escape returns it to its slot (spec M6 §6). The key\n * handling lives in the pure {@link fieldKeyboardStep} so it can be tested.\n */\nexport function FieldKeyboardMirror({\n papers,\n controller,\n}: {\n papers: FieldPaperSlot[]\n controller: React.MutableRefObject<FieldA11yController | null>\n}) {\n const [carrying, setCarrying] = useState<{ slot: number; zoneIndex: number } | null>(null)\n\n const paperLabel = (slot: FieldPaperSlot, i: number): string => {\n try {\n const config = resolveConfig({ preset: slot.preset })\n const content = slot.content ? contentSchema.parse(slot.content) : config.content\n return `Paper ${i + 1}: ${contentText({ ...config, content })}`\n } catch {\n return `Paper ${i + 1}`\n }\n }\n\n const onKeyDown = (i: number) => (e: React.KeyboardEvent) => {\n const ctl = controller.current\n if (!ctl) return\n const { carry, handled } = fieldKeyboardStep(carrying, i, e.key, ctl)\n if (handled) e.preventDefault()\n if (carry !== carrying) setCarrying(carry)\n }\n\n return (\n <fieldset style={mirrorHidden}>\n <legend>Interactive papers</legend>\n {papers.map((slot, i) => (\n <button\n // biome-ignore lint/suspicious/noArrayIndexKey: a slot IS its index — the carry state and every keyboard step address a paper by slot number.\n key={i}\n type=\"button\"\n onKeyDown={onKeyDown(i)}\n aria-label={paperLabel(slot, i)}\n aria-pressed={carrying?.slot === i}\n >\n {paperLabel(slot, i)}\n {carrying?.slot === i && (\n <span aria-live=\"polite\">\n {' '}\n — carrying; zone {controller.current?.zoneIds()[carrying.zoneIndex] ?? 'none'}; Enter places,\n Escape returns\n </span>\n )}\n </button>\n ))}\n </fieldset>\n )\n}\n","import type { AnyOptions, SheetDims } from '../deformers/types'\nimport type { Layout } from './layouts'\nimport { withSheetCellFromPaper, type SheetLayoutOptions } from './sheetGrid'\n\n/**\n * Framing a field is arithmetic, not guesswork: layouts are pure `pose`\n * functions, so we can just ask one where all its sheets are and put the\n * camera where they all fit. Community layouts get framed for free.\n */\n\nexport interface FieldBounds {\n center: [number, number, number]\n /** Half-extents — the box reaches `center ± half`. */\n half: [number, number, number]\n}\n\n/** Cyclic layouts sweep as `phase` advances; frame the whole cycle, not one instant. */\nconst PHASE_SAMPLES = 8\n\n/**\n * Resolve a layout's options the one way both the renderer and the camera\n * must agree on — sheet grids size their cells from the papers themselves.\n */\nexport function resolveLayoutOptions(\n layoutId: string,\n layout: Layout<AnyOptions>,\n propOptions: Record<string, unknown> | undefined,\n firstSheet: SheetDims | undefined,\n): Record<string, unknown> {\n const parsed = layout.optionsSchema.parse({\n ...layout.defaults,\n ...propOptions,\n }) as Record<string, unknown>\n if (layoutId !== 'sheet') return parsed\n return withSheetCellFromPaper(\n parsed as unknown as SheetLayoutOptions,\n propOptions,\n firstSheet,\n ) as unknown as Record<string, unknown>\n}\n\n/**\n * The box `n` sheets occupy under a layout. Each sheet is treated as a ball\n * of its half-diagonal, which covers every rotation the pose can apply\n * without having to build the pose matrices.\n */\nexport function fieldBounds(\n layout: Layout<AnyOptions>,\n n: number,\n options: unknown,\n sheet: SheetDims,\n): FieldBounds {\n const reach = Math.hypot(sheet.width, sheet.height) / 2\n if (n <= 0) return { center: [0, 0, 0], half: [reach, reach, 0] }\n\n const min = [Infinity, Infinity, Infinity]\n const max = [-Infinity, -Infinity, -Infinity]\n for (let s = 0; s < PHASE_SAMPLES; s++) {\n for (let i = 0; i < n; i++) {\n const pose = layout.pose(i, n, options, s / PHASE_SAMPLES, sheet)\n const r = reach * Math.max(pose.scale, 0)\n for (let axis = 0; axis < 3; axis++) {\n min[axis] = Math.min(min[axis]!, pose.position[axis]! - r)\n max[axis] = Math.max(max[axis]!, pose.position[axis]! + r)\n }\n }\n }\n return {\n center: [(min[0]! + max[0]!) / 2, (min[1]! + max[1]!) / 2, (min[2]! + max[2]!) / 2],\n half: [(max[0]! - min[0]!) / 2, (max[1]! - min[1]!) / 2, (max[2]! - min[2]!) / 2],\n }\n}\n\n/** The field has always been viewed from a shade above eye level — keep that. */\nconst LIFT = 0.11\nconst DEG = Math.PI / 180\n\n/**\n * Where to put a perspective camera so every sheet a layout poses lands in\n * frame. Solved per sheet at its own depth rather than against the field's\n * bounding box: a `ring`'s widest sheets sit at mid-depth, and pretending\n * that width exists at the near face would shove the camera far enough back\n * to lose the gallery entirely.\n */\nexport function fitCamera(\n layout: Layout<AnyOptions>,\n n: number,\n options: unknown,\n sheet: SheetDims,\n fovDeg: number,\n aspect: number,\n margin = 1.06,\n): { position: [number, number, number]; target: [number, number, number] } {\n const { center } = fieldBounds(layout, n, options, sheet)\n const reach = (Math.hypot(sheet.width, sheet.height) / 2) * margin\n const vTan = Math.tan((fovDeg * DEG) / 2)\n const hTan = vTan * Math.max(aspect, 0.01)\n\n let distance = 0.1\n for (let s = 0; s < PHASE_SAMPLES; s++) {\n for (let i = 0; i < Math.max(n, 0); i++) {\n const pose = layout.pose(i, n, options, s / PHASE_SAMPLES, sheet)\n const r = reach * Math.max(pose.scale, 0)\n // Depth of this sheet in front of the field's center — a sheet further\n // back needs correspondingly less distance to fit.\n const depth = pose.position[2]! - center[2]!\n distance = Math.max(\n distance,\n (Math.abs(pose.position[0]! - center[0]!) + r) / hTan + depth,\n (Math.abs(pose.position[1]! - center[1]!) + r) / vTan + depth,\n )\n }\n }\n return {\n position: [center[0], center[1] + distance * LIFT, center[2] + distance],\n target: center,\n }\n}\n","import * as THREE from 'three'\nimport { gsap } from 'gsap'\nimport { Canvas, useFrame, useThree } from '@react-three/fiber'\nimport { forwardRef, useEffect, useMemo, useRef } from 'react'\nimport type { PaperConfigInput } from './config/schema'\nimport { usePrefersReducedMotion } from './a11y'\nimport { DropZoneContext, DropZoneRegistry, type DropZoneConfig, type PlacedPaper } from './field/dropZones'\nimport {\n EMPTY_SET,\n effectiveFieldPapers,\n fieldIsInteractive,\n groupFieldPapers,\n type FieldPaperSlot,\n} from './field/slots'\nimport { FieldGroup, type SharedMotion } from './field/fieldGroup'\nimport { BackingSheet } from './field/backingSheet'\nimport { InteractiveField, type FieldA11yController } from './field/interactiveField'\nimport { FieldKeyboardMirror } from './field/keyboardMirror'\nimport { DEFAULT_SHEET, getLayout } from './field/layouts'\nimport { useStable } from './core/stable'\nimport type { SheetLayoutOptions } from './field/sheetGrid'\nimport { fitCamera, resolveLayoutOptions } from './field/framing'\n\n// The field system lives in field/*; this module is the public composition.\n// Re-exported here so `import { … } from './PaperField'` (index.ts, tests,\n// consumers) keeps working across the split.\nexport {\n DropZone,\n DropZoneRegistry,\n zoneAccepts,\n type DropZoneConfig,\n type DropZoneProps,\n type PlacedPaper,\n} from './field/dropZones'\nexport {\n groupFieldPapers,\n resolveFieldSlotConfig,\n type FieldPaperSlot,\n type FieldGroupData,\n} from './field/slots'\nexport type { FieldA11yController } from './field/interactiveField'\nexport {\n fieldKeyboardStep,\n type KeyboardCarry,\n type KeyboardStepResult,\n} from './field/keyboardMirror'\n\nexport interface PaperFieldMeshProps {\n /** Per-paper slots; length sets the instance count. Slot presets override the shared one. */\n papers?: FieldPaperSlot[]\n /** Sugar: image URLs → papers with image content. */\n images?: string[]\n /** Shared preset for slots that don't name their own. */\n preset?: string | PaperConfigInput\n layout?: string\n layoutOptions?: Record<string, unknown>\n motion?: { driver?: 'autoplay' | 'drag' | 'none'; speed?: number }\n entrance?: { type?: 'rise' | 'scatter' | 'none'; stagger?: number; duration?: number }\n /** Override prefers-reduced-motion (default: follow the system setting). */\n reducedMotion?: boolean\n /**\n * Per-paper interaction (hero CPU path per slot instead of one instanced\n * draw call). Defaults to true when any slot's preset carries `states` —\n * a stateful field is interactive by nature.\n */\n interactive?: boolean\n /** Fires when any slot's state machine changes state. */\n onSlotStateChange?(slot: number, state: string): void\n /**\n * Fires with a paper's index when it is clicked. Supplying it is what makes\n * the papers pickable — without a handler nothing raycasts, which matters\n * because hit-testing an instanced mesh is per-instance work on a pointer\n * move and a field is the mode with hundreds of instances in it.\n */\n onSelect?(paper: number): void\n /** Serialized drop zones (the editor's path); `<DropZone>` children also work. */\n zones?: DropZoneConfig[]\n /** Fires when a picked paper settles into any zone. */\n onPlace?(paper: PlacedPaper, zone: string): void\n /** Imperative controls for the hidden keyboard flow (wired by PaperField). */\n a11yControllerRef?: React.MutableRefObject<FieldA11yController | null>\n /**\n * Lowers what `segments: 'auto'` may ask for, per sheet. A DEVICE knob, in\n * the same sense `<PaperStage>`'s `quality` is one: it describes what the\n * machine can draw, never what the artwork is, so it does not serialize\n * into a preset or a share link. It can only ever lower the field's own\n * ceiling; nothing here can subdivide a sheet further than the library\n * would on its own.\n */\n segmentCeiling?: number\n}\n\nexport interface PaperFieldProps extends PaperFieldMeshProps {\n children?: React.ReactNode\n className?: string\n style?: React.CSSProperties\n}\n\n/**\n * Field mode: sheets render as one instanced draw call PER DISTINCT PRESET\n * (usually one). Deformer stacks run as composed GLSL vertex chunks\n * (parity-tested against the CPU path); content lives in per-group atlases;\n * motion state (driver phase, entrance clock, layout morph) is shared so\n * mixed-preset fields move as one field.\n */\nexport const PaperFieldMesh = forwardRef<THREE.Group, PaperFieldMeshProps>(\n function PaperFieldMesh(props, ref) {\n const reduced = usePrefersReducedMotion(props.reducedMotion)\n\n const papers = useMemo<FieldPaperSlot[]>(\n () => effectiveFieldPapers(props.papers, props.images),\n [props.papers, props.images],\n )\n // Content-compared, not serialized: papers and preset are fresh objects\n // every render, and a paper can carry a whole bitmap inline. See\n // `useStable` for why stringifying these was the expensive half.\n const stablePapers = useStable(papers)\n const stablePreset = useStable(props.preset ?? null)\n const groups = useMemo(\n () => groupFieldPapers(stablePapers, stablePreset ?? undefined),\n [stablePapers, stablePreset],\n )\n const total = papers.length\n\n const layoutId = props.layout ?? 'ring'\n const layout = getLayout(layoutId)\n const firstSheet = groups[0]?.config.sheet\n const stableLayoutOptions = useStable(props.layoutOptions ?? {})\n // biome-ignore lint/correctness/useExhaustiveDependencies: `layout` is derived from layoutId, and the sheet enters by its two dimensions.\n const layoutOptions = useMemo(\n // Sheet grids size their cells from the papers themselves — gutter is\n // then literally the spacing between stamps (explicit cell dims win).\n () => resolveLayoutOptions(layoutId, layout, stableLayoutOptions, firstSheet),\n [layoutId, stableLayoutOptions, firstSheet?.width, firstSheet?.height],\n )\n\n // ── Shared motion state: one driver phase / entrance clock / morph for\n // every group, so a mixed-preset field moves as one field. ──\n const phaseRef = useRef(0)\n const dragVelRef = useRef(0)\n const mountTimeRef = useRef(-1)\n const morphRef = useRef<SharedMotion['morphRef']['current']>({ from: null, t: 1 })\n const prevLayout = useRef({ id: layoutId, options: layoutOptions })\n const gl = useThree((s) => s.gl)\n\n const driver = reduced ? 'none' : (props.motion?.driver ?? 'autoplay')\n const speed = props.motion?.speed ?? 0.5\n const entranceType = reduced ? 'none' : (props.entrance?.type ?? 'rise')\n\n useEffect(() => {\n const prev = prevLayout.current\n if (prev.id !== layoutId || JSON.stringify(prev.options) !== JSON.stringify(layoutOptions)) {\n morphRef.current = { from: prev, t: 0 }\n gsap.to(morphRef.current, { t: 1, duration: 0.9, ease: 'power2.inOut' })\n prevLayout.current = { id: layoutId, options: layoutOptions }\n }\n }, [layoutId, layoutOptions])\n\n useEffect(() => {\n if (driver !== 'drag') return\n const el = gl.domElement\n let lastX: number | null = null\n const down = (e: PointerEvent) => {\n lastX = e.clientX\n }\n const move = (e: PointerEvent) => {\n if (lastX === null) return\n const dx = e.clientX - lastX\n lastX = e.clientX\n phaseRef.current += dx * 0.0012\n dragVelRef.current = dx * 0.0012\n }\n const up = () => {\n lastX = null\n }\n el.addEventListener('pointerdown', down)\n window.addEventListener('pointermove', move)\n window.addEventListener('pointerup', up)\n return () => {\n el.removeEventListener('pointerdown', down)\n window.removeEventListener('pointermove', move)\n window.removeEventListener('pointerup', up)\n }\n }, [driver, gl])\n\n useFrame(({ clock }, delta) => {\n if (mountTimeRef.current < 0) mountTimeRef.current = clock.elapsedTime\n if (driver === 'autoplay') phaseRef.current += delta * speed * 0.02\n if (driver === 'drag') {\n phaseRef.current += dragVelRef.current * 0.5\n dragVelRef.current *= 0.94\n }\n })\n\n const shared: SharedMotion = {\n phaseRef,\n mountTimeRef,\n morphRef,\n layoutId,\n layoutOptions,\n sheet: firstSheet ?? DEFAULT_SHEET,\n entranceType,\n stagger: props.entrance?.stagger ?? 0.06,\n entranceDuration: props.entrance?.duration ?? 0.9,\n total,\n reduced,\n }\n\n // A stateful field is interactive by nature: per-paper hero path (CPU,\n // raycastable, per-slot state machines) instead of one instanced call.\n // (`groups` already resolved every preset, so reuse them for the check.)\n const interactive =\n props.interactive ?? (papers.some((s) => s.states) || groups.some((g) => Boolean(g.config.states)))\n\n const isSheet = layoutId === 'sheet'\n const sheetOptions = isSheet ? (layoutOptions as SheetLayoutOptions) : null\n\n if (interactive) {\n return (\n <group ref={ref}>\n <InteractiveField\n papers={papers}\n fallback={props.preset}\n layoutId={layoutId}\n layoutOptions={layoutOptions}\n sheetOptions={sheetOptions}\n sheet={firstSheet ?? DEFAULT_SHEET}\n reducedMotion={props.reducedMotion}\n zones={props.zones}\n onSlotStateChange={props.onSlotStateChange}\n onPlace={props.onPlace}\n a11yRef={props.a11yControllerRef}\n />\n </group>\n )\n }\n\n return (\n <group ref={ref}>\n {sheetOptions?.backing && <BackingSheet options={sheetOptions} count={total} removed={EMPTY_SET} />}\n {groups.map((group, gi) => (\n <FieldGroup\n // biome-ignore lint/suspicious/noArrayIndexKey: groups are derived from the slot list in order, so position is their only identity.\n key={`${gi}:${group.indices.length}`}\n group={group}\n shared={shared}\n onSelect={props.onSelect}\n segmentCeiling={props.segmentCeiling}\n />\n ))}\n </group>\n )\n },\n)\n\n/**\n * Frames whatever the layout actually lays out. A fixed camera can only suit\n * one layout — a `wall` of 12 runs past the top of a frame that a `pile`\n * leaves nearly empty — and layouts are pure, so the right distance is just\n * arithmetic over their poses.\n */\nfunction FitCamera(meshProps: PaperFieldMeshProps) {\n const camera = useThree((s) => s.camera)\n const width = useThree((s) => s.size.width)\n const height = useThree((s) => s.size.height)\n\n // The camera refits on prop CONTENT, not on identity — compared rather\n // than serialized, because this runs on every render of the field.\n const papersProp = useStable(meshProps.papers ?? null)\n const imagesProp = useStable(meshProps.images ?? null)\n const presetProp = useStable(meshProps.preset ?? null)\n const optionsProp = useStable(meshProps.layoutOptions ?? {})\n const field = useMemo(() => {\n const papers = effectiveFieldPapers(papersProp ?? undefined, imagesProp ?? undefined)\n const layoutId = meshProps.layout ?? 'ring'\n const layout = getLayout(layoutId)\n const sheet = groupFieldPapers(papers, presetProp ?? undefined)[0]?.config.sheet\n const options = resolveLayoutOptions(layoutId, layout, optionsProp, sheet)\n return { layout, n: papers.length, options, sheet: sheet ?? DEFAULT_SHEET }\n }, [papersProp, imagesProp, presetProp, meshProps.layout, optionsProp])\n\n useEffect(() => {\n if (!(camera instanceof THREE.PerspectiveCamera)) return\n const { position, target } = fitCamera(\n field.layout,\n field.n,\n field.options,\n field.sheet,\n camera.fov,\n width / Math.max(height, 1),\n )\n camera.position.set(...position)\n camera.lookAt(...target)\n camera.updateProjectionMatrix()\n }, [camera, width, height, field])\n\n return null\n}\n\n/** `<PaperField />` owns its own Canvas; PaperFieldMesh drops into existing scenes. */\nexport const PaperField = forwardRef<THREE.Group, PaperFieldProps>(function PaperField(\n { children, className, style, ...meshProps },\n ref,\n) {\n const registry = useMemo(() => new DropZoneRegistry(), [])\n const a11yRef = useRef<FieldA11yController | null>(null)\n\n // The SAME derivations PaperFieldMesh uses — a slot naming a stateful\n // preset by string, or an images-driven field, must get the keyboard\n // mirror exactly when the mesh goes interactive.\n const papers = useMemo(\n () => effectiveFieldPapers(meshProps.papers, meshProps.images),\n [meshProps.papers, meshProps.images],\n )\n const stablePapers = useStable(papers)\n const stablePreset = useStable(meshProps.preset ?? null)\n const interactive = useMemo(\n () => fieldIsInteractive(stablePapers, stablePreset ?? undefined, meshProps.interactive),\n [stablePapers, stablePreset, meshProps.interactive],\n )\n\n return (\n <div className={className} style={{ width: '100%', height: '100%', ...style }}>\n <DropZoneContext.Provider value={registry}>\n <Canvas shadows camera={{ position: [0, 0.6, 5.2], fov: 45 }} dpr={[1, 2]}>\n <FitCamera {...meshProps} />\n <ambientLight intensity={0.7} />\n <directionalLight\n position={[3, 5, 4]}\n intensity={1.4}\n castShadow\n shadow-mapSize={[1024, 1024]}\n shadow-normalBias={0.05}\n />\n <PaperFieldMesh ref={ref} a11yControllerRef={a11yRef} {...meshProps} />\n {children}\n </Canvas>\n {interactive && <FieldKeyboardMirror papers={papers} controller={a11yRef} />}\n </DropZoneContext.Provider>\n </div>\n )\n})\n","import * as THREE from 'three'\nimport { gsap } from 'gsap'\nimport { useFrame } from '@react-three/fiber'\nimport { useEffect, useMemo, useRef } from 'react'\nimport CustomShaderMaterial from 'three-custom-shader-material'\nimport { getStock } from '../core/stock'\nimport { createSheetGeometry } from '../core/sheet'\nimport { getBehavior } from '../behaviors/registry'\nimport { stackAutoSegments, stackMinSegments } from '../deformers/compose'\nimport type { SegmentPair } from '../core/tessellation'\nimport type { DeformerInstance, SheetDims } from '../deformers/types'\nimport type { AeroPose } from '../physics/aero'\nimport { useContentAtlas } from '../content/atlas'\nimport {\n buildDisplacementGLSL,\n buildFieldFragmentShader,\n buildFieldVertexShader,\n stackUniformValues,\n} from './compose'\nimport { getLayout, type PaperPose } from './layouts'\nimport { translucencyUniforms, translucencyValues } from '../surface/translucency'\nimport { useLightRig } from '../scene/rig'\nimport { fieldShapeStack } from './stack'\nimport type { FieldGroupData } from './slots'\n\nconst scratchObj = new THREE.Object3D()\nconst scratchAero: AeroPose = { position: [0, 0, 0], rotation: [0, 0, 0] }\n/**\n * Caps the FLOOR a deformer stack can demand of a field instance. Field mode\n * trades a deformer's stated minimum for instance count, which hero mode\n * never does.\n */\nexport const FIELD_SEGMENT_CAP = 48\n\n/**\n * Caps what `'auto'` may ASK for in a field, as distinct from the floor above.\n *\n * It used to sit at the old flat 72 on the grounds that a field draws this\n * buffer once per instance — a real argument, made when nothing else could\n * hold the count down. Two things changed. The demand now lands on the axis\n * that bends rather than being spread over both, so a banner asking 128\n * across asks 8 down and the buffer grows on one side only. And\n * `segmentCeiling` gives the caller a working lever, which is what the\n * quality tiers now use: `low` and `medium` cap themselves well below this\n * line, so raising it only raises what a machine that measured fast enough\n * is allowed to ask for.\n *\n * 128, matching what a hero sheet was allowed before the hero ceiling moved\n * to 192. A field still asks for less than one sheet does, which is the\n * asymmetry worth keeping.\n */\nexport const FIELD_AUTO_CEILING = 128\n\n/** Mirrors the hero path's sweep sampling — see PaperMesh. */\nconst PROGRESS_SAMPLES = [0, 0.25, 0.5, 0.75, 1] as const\n\n/** Motion state shared across groups so a mixed-preset field moves as one field. */\nexport interface SharedMotion {\n phaseRef: React.MutableRefObject<number>\n mountTimeRef: React.MutableRefObject<number>\n morphRef: React.MutableRefObject<{ from: { id: string; options: unknown } | null; t: number }>\n layoutId: string\n layoutOptions: Record<string, unknown>\n /** The field's paper size — one sheet for every group, so layouts agree. */\n sheet: SheetDims\n entranceType: 'rise' | 'scatter' | 'none'\n stagger: number\n entranceDuration: number\n total: number\n reduced: boolean\n}\n\n/** Opting a mesh out of raycasting entirely — cheaper than testing and discarding. */\nconst NO_RAYCAST = () => {}\n\n/** One instanced mesh: one preset's sheet/stock/behavior across its slots. */\nexport function FieldGroup({\n group,\n shared,\n onSelect,\n segmentCeiling,\n}: {\n group: FieldGroupData\n shared: SharedMotion\n /** Called with the paper's GLOBAL index — a group only holds the slots that share its preset. */\n onSelect?: (paper: number) => void\n /** Lowers what `'auto'` may ask for on this group's sheet. Never raises it. */\n segmentCeiling?: number\n}) {\n const autoCeiling = Math.min(segmentCeiling ?? FIELD_AUTO_CEILING, FIELD_AUTO_CEILING)\n const { config, indices, contents } = group\n const count = indices.length\n const stock = getStock(config.stock)\n // The scene's rig if it publishes one — in a stage the banners are lit by\n // the hall, not by the preset each one happens to carry.\n const rig = useLightRig(config.scene.lighting)\n // A raw deformer stack is the Advanced fork of a behavior and wins over one\n // — the same precedence the hero path's buildStack applies. Field mode used\n // to read `behavior` only, so a preset shaped by `deformers` rendered flat.\n const behavior = config.behavior && !config.deformers ? getBehavior(config.behavior.type) : null\n\n const progressRef = useRef(\n behavior ? ((config.behavior as Record<string, unknown>)[behavior.progressParam] as number) : 0,\n )\n const buildStackAt = (progress: number): DeformerInstance[] => fieldShapeStack(config, progress)\n // biome-ignore lint/correctness/useExhaustiveDependencies: Serialized deps — the stack rebuilds on shape, not on identity.\n const initialStack = useMemo(\n () => buildStackAt(progressRef.current),\n [\n JSON.stringify(config.behavior ?? null),\n JSON.stringify(config.deformers ?? null),\n JSON.stringify(config.sheet),\n ],\n )\n const structureKey = initialStack.map((i) => i.type).join('|')\n\n // biome-ignore lint/correctness/useExhaustiveDependencies: Keyed on sheet, stack structure, count and the ceiling — the only things that change the buffer.\n const geometry = useMemo(() => {\n const floor = stackMinSegments(initialStack, config.sheet)\n // Same sweep-sampling as the hero path: one buffer serves every instance\n // for the whole play, so it has to hold the densest moment of it, not the\n // current one.\n const want: SegmentPair = [0, 0]\n for (const p of PROGRESS_SAMPLES) {\n const [x, y] = stackAutoSegments(buildStackAt(p), config.sheet)\n if (x > want[0]) want[0] = x\n if (y > want[1]) want[1] = y\n }\n const geo = createSheetGeometry(\n {\n ...config.sheet,\n segments:\n config.sheet.segments === 'auto' ? 'auto' : Math.min(config.sheet.segments, FIELD_SEGMENT_CAP),\n },\n [Math.min(floor[0], FIELD_SEGMENT_CAP), Math.min(floor[1], FIELD_SEGMENT_CAP)],\n // Bounded by the auto ceiling and NOT by FIELD_SEGMENT_CAP, which is a\n // floor cap and stays one. Capping the target as well looked tidy and\n // was a visual regression: it is the only thing that could have held\n // `crumple` — whose creases have no target, only a floor of 72 — down\n // to 48 in a field, which is coarser than the deformer says it needs to\n // look like a crumple at all.\n [Math.min(want[0], autoCeiling), Math.min(want[1], autoCeiling)],\n )\n const atlasIdx = new Float32Array(count)\n const phase = new Float32Array(count)\n const bias = new Float32Array(count).fill(1)\n for (let i = 0; i < count; i++) {\n atlasIdx[i] = i\n phase[i] = ((indices[i]! * 0.618034) % 1) * 4 // golden-ratio spread by global slot\n }\n geo.setAttribute('aAtlas', new THREE.InstancedBufferAttribute(atlasIdx, 1))\n geo.setAttribute('aPhase', new THREE.InstancedBufferAttribute(phase, 1))\n // Per-sheet deformation strength, written from the layout's pose each\n // frame — how a single instanced draw call bends every sheet differently.\n geo.setAttribute('aBias', new THREE.InstancedBufferAttribute(bias, 1))\n return geo\n }, [JSON.stringify(config.sheet), structureKey, count, autoCeiling])\n\n // Imperatively created — R3F won't auto-dispose a geometry passed via args.\n useEffect(() => () => geometry.dispose(), [geometry])\n\n const atlas = useContentAtlas(contents, config.sheet, stock)\n\n // biome-ignore lint/correctness/useExhaustiveDependencies: Keyed on the stack structure — uniforms update in place, the program does not.\n const shader = useMemo(() => {\n const composed = buildDisplacementGLSL(initialStack, config.sheet)\n const uniforms: Record<string, { value: unknown }> = {}\n for (const [name, value] of Object.entries(composed.uniforms)) {\n uniforms[name] = {\n value: Array.isArray(value) && value.length === 2 ? new THREE.Vector2(...value) : value,\n }\n }\n uniforms.uPlTime = { value: 0 }\n uniforms.uAtlas = { value: null }\n uniforms.uAtlasGrid = { value: new THREE.Vector2(1, 1) }\n uniforms.uBackDarken = {\n value: 1 - Math.min(0.45, 0.12 + config.sheet.thickness * 0.9) * stock.opacity,\n }\n uniforms.uStockColor = { value: new THREE.Color(stock.color) }\n uniforms.uShowThrough = { value: config.surface.showThrough ?? stock.showThrough }\n // Transmission reads the scene's own key light, so a backlit sheet can\n // never disagree with the lamp casting its shadow.\n Object.assign(uniforms, translucencyUniforms(config.surface.translucency ?? stock.translucency, rig))\n return {\n vertexShader: buildFieldVertexShader(composed),\n fragmentShader: buildFieldFragmentShader(),\n uniforms,\n }\n }, [\n structureKey,\n JSON.stringify(config.sheet),\n stock.id,\n config.surface.showThrough,\n config.surface.translucency,\n ])\n\n // Moving a light writes four uniforms; it must never recompile a program,\n // which is what putting the rig in the memo above would have done on every\n // frame of a slider drag.\n useEffect(() => {\n const values = translucencyValues(config.surface.translucency ?? stock.translucency, rig)\n shader.uniforms.uTranslucency!.value = values.translucency\n ;(shader.uniforms.uBackLightDir!.value as THREE.Vector3).copy(values.direction)\n ;(shader.uniforms.uBackLightColor!.value as THREE.Color).copy(values.color)\n shader.uniforms.uAmbientTransmission!.value = values.ambient\n }, [shader, rig, config.surface.translucency, stock.translucency])\n\n useEffect(() => {\n if (!atlas) return\n shader.uniforms.uAtlas!.value = atlas.texture\n ;(shader.uniforms.uAtlasGrid!.value as THREE.Vector2).set(atlas.cols, atlas.rows)\n }, [atlas, shader])\n\n // Behavior progress loops on GSAP — the field is always alive.\n // biome-ignore lint/correctness/useExhaustiveDependencies: Keyed on the behavior itself; progress lives on a ref so the tween is not restarted each render.\n useEffect(() => {\n if (!behavior || shared.reduced) return\n const state = { p: progressRef.current }\n const tween = gsap.to(state, {\n p: 1,\n duration: behavior.duration * Math.max(0.05, 1 - state.p),\n ease: 'power2.inOut',\n yoyo: behavior.loopMode === 'yoyo',\n repeat: -1,\n onUpdate: () => {\n progressRef.current = state.p\n },\n })\n return () => {\n tween.kill()\n }\n }, [structureKey, shared.reduced])\n\n const meshRef = useRef<THREE.InstancedMesh>(null)\n\n useFrame(({ clock }) => {\n const mesh = meshRef.current\n if (!mesh) return\n const elapsed = clock.elapsedTime - Math.max(shared.mountTimeRef.current, 0)\n\n shader.uniforms.uPlTime!.value = shared.reduced ? 0 : clock.elapsedTime\n if (behavior) {\n const values = stackUniformValues(buildStackAt(progressRef.current), config.sheet)\n for (const [name, value] of Object.entries(values)) {\n const uniform = shader.uniforms[name]\n if (!uniform) continue\n if (uniform.value instanceof THREE.Vector2 && Array.isArray(value)) {\n uniform.value.set(value[0]!, value[1]!)\n } else {\n uniform.value = value\n }\n }\n }\n\n const layout = getLayout(shared.layoutId)\n const morph = shared.morphRef.current\n const behaviorTransform = behavior?.transform && config.behavior ? behavior : null\n const biasAttr = geometry.getAttribute('aBias') as THREE.InstancedBufferAttribute\n const biases = biasAttr.array as Float32Array\n let biasChanged = false\n for (let j = 0; j < count; j++) {\n const i = indices[j]!\n let pose = layout.pose(i, shared.total, shared.layoutOptions, shared.phaseRef.current, shared.sheet)\n if (morph.from && morph.t < 1) {\n const prev = getLayout(morph.from.id).pose(\n i,\n shared.total,\n morph.from.options,\n shared.phaseRef.current,\n shared.sheet,\n )\n pose = lerpPose(prev, pose, easeInOut(morph.t))\n }\n if (shared.entranceType !== 'none') {\n const tIn = Math.min(1, Math.max(0, (elapsed - i * shared.stagger) / shared.entranceDuration))\n if (tIn < 1) {\n pose = lerpPose(entrancePose(shared.entranceType, i, pose), pose, easeOut(tIn))\n }\n }\n const bias = Math.min(1, Math.max(0, pose.bias ?? 1))\n if (biases[j] !== bias) {\n biases[j] = bias\n biasChanged = true\n }\n scratchObj.position.set(...pose.position)\n scratchObj.rotation.set(...pose.rotation)\n scratchObj.scale.setScalar(pose.scale)\n // Behavior whole-sheet transforms (flight) run per instance, offset in\n // time by the same golden-ratio phase the shader flutter uses — pure\n // functions of t, so instancing stays exact.\n if (behaviorTransform) {\n const pose2 = scratchAero\n pose2.position[0] = pose2.position[1] = pose2.position[2] = 0\n pose2.rotation[0] = pose2.rotation[1] = pose2.rotation[2] = 0\n const t = shared.reduced ? 0 : clock.elapsedTime + ((i * 0.618034) % 1) * 4\n behaviorTransform.transform!(\n { ...config.behavior, [behaviorTransform.progressParam]: progressRef.current },\n t,\n pose2,\n )\n scratchObj.position.x += pose2.position[0]\n scratchObj.position.y += pose2.position[1]\n scratchObj.position.z += pose2.position[2]\n scratchObj.rotation.x += pose2.rotation[0]\n scratchObj.rotation.y += pose2.rotation[1]\n scratchObj.rotation.z += pose2.rotation[2]\n }\n scratchObj.updateMatrix()\n mesh.setMatrixAt(j, scratchObj.matrix)\n }\n mesh.instanceMatrix.needsUpdate = true\n if (biasChanged) biasAttr.needsUpdate = true\n })\n\n return (\n // biome-ignore lint/a11y/noStaticElementInteractions: An R3F <instancedMesh> is a three.js object, not a DOM node — it has no role to give and no keyboard to receive. The keyboard route into the same action is on the canvas, which `useWalk` makes focusable and drives with the arrow keys.\n <instancedMesh\n ref={meshRef}\n args={[geometry, undefined, count]}\n frustumCulled={false}\n castShadow\n receiveShadow\n // Only raycastable when somebody is listening: hit-testing an instanced\n // mesh is per-instance work on every pointer move, and this is the mode\n // that puts hundreds of instances on screen at once. Spread rather than\n // `raycast={undefined}`, which does not mean \"leave the default\" — it\n // assigns undefined over the method three is about to call.\n {...(onSelect ? {} : { raycast: NO_RAYCAST })}\n onClick={\n onSelect &&\n ((event) => {\n if (event.instanceId === undefined) return\n // `instanceId` counts within THIS group; the layout — and anything\n // that wants to know which paper was clicked — counts across all of\n // them, so the group's own index list is the translation.\n const paper = indices[event.instanceId]\n if (paper === undefined) return\n event.stopPropagation()\n onSelect(paper)\n })\n }\n >\n <CustomShaderMaterial\n key={`${structureKey}:${count}`}\n baseMaterial={THREE.MeshStandardMaterial}\n vertexShader={shader.vertexShader}\n fragmentShader={shader.fragmentShader}\n uniforms={shader.uniforms}\n roughness={stock.roughness}\n metalness={0}\n side={THREE.DoubleSide}\n />\n </instancedMesh>\n )\n}\n\nfunction entrancePose(type: 'rise' | 'scatter', i: number, target: PaperPose): PaperPose {\n if (type === 'rise') {\n return {\n position: [target.position[0], target.position[1] - 3.2, target.position[2] - 0.5],\n rotation: [target.rotation[0] - 0.7, target.rotation[1], target.rotation[2] + 0.25],\n scale: target.scale * 0.85,\n bias: target.bias,\n }\n }\n const a = i * 2.399\n return {\n position: [Math.cos(a) * 7, Math.sin(a * 1.3) * 4, Math.sin(a) * 6],\n rotation: [Math.sin(a) * 2, a, Math.cos(a) * 2],\n scale: target.scale * 0.6,\n bias: target.bias,\n }\n}\n\nfunction lerpPose(a: PaperPose, b: PaperPose, t: number): PaperPose {\n const lerp = (x: number, y: number) => x + (y - x) * t\n return {\n position: [\n lerp(a.position[0], b.position[0]),\n lerp(a.position[1], b.position[1]),\n lerp(a.position[2], b.position[2]),\n ],\n rotation: [\n lerp(a.rotation[0], b.rotation[0]),\n lerp(a.rotation[1], b.rotation[1]),\n lerp(a.rotation[2], b.rotation[2]),\n ],\n scale: lerp(a.scale, b.scale),\n bias: lerp(a.bias ?? 1, b.bias ?? 1),\n }\n}\n\nconst easeOut = (t: number) => 1 - (1 - t) ** 3\nconst easeInOut = (t: number) => (t < 0.5 ? 2 * t * t : 1 - (-2 * t + 2) ** 2 / 2)\n","import { getBehavior } from '../behaviors/registry'\nimport { resolveDeformerStack } from '../deformers/registry'\nimport type { PaperConfig } from '../config/schema'\nimport type { DeformerInstance } from '../deformers/types'\n\n/**\n * The deformer stack one field group renders, at a given behavior progress.\n *\n * A raw `deformers` array is the Advanced fork of a behavior and wins over\n * one — the same precedence the hero path's `buildStack` applies. Field mode\n * once read `behavior` only, so a preset shaped by `deformers` (the way to\n * say \"this print has a permanent bow\") silently rendered flat.\n */\nexport function fieldShapeStack(config: PaperConfig, progress: number): DeformerInstance[] {\n if (config.deformers) return resolveDeformerStack(config.deformers)\n if (!config.behavior) return []\n const behavior = getBehavior(config.behavior.type)\n const options = { ...config.behavior, [behavior.progressParam]: progress }\n return behavior.stack(options, config.sheet)\n}\n","import * as THREE from 'three'\nimport { useEffect, useMemo } from 'react'\nimport { drawBacking } from '../content/backing'\nimport { sheetBackingSize, type SheetLayoutOptions } from './sheetGrid'\n\n/** Warmer than printer stock — the classic gummed backing paper. */\nconst BACKING_TINT = '#f3ecdd'\n\n/**\n * The shared sheet behind a stamp grid: one extra paper sized to the grid\n * bounds + margin, non-interactive, excluded from `papers` indices. Its\n * content is a generated canvas of ghost silhouettes, redrawn on state\n * change (never per-frame).\n */\nexport function BackingSheet({\n options,\n count,\n removed,\n}: {\n options: SheetLayoutOptions\n count: number\n removed: ReadonlySet<number>\n}) {\n const { width, height } = sheetBackingSize(options)\n const canvas = useMemo(() => {\n if (typeof document === 'undefined') return null\n const c = document.createElement('canvas')\n const scale = Math.min(1024, Math.round(360 * Math.max(width, height))) / Math.max(width, height)\n c.width = Math.max(2, Math.round(width * scale))\n c.height = Math.max(2, Math.round(height * scale))\n return c\n }, [width, height])\n const texture = useMemo(() => (canvas ? new THREE.CanvasTexture(canvas) : null), [canvas])\n\n const removedKey = [...removed].sort((a, b) => a - b).join(',')\n // biome-ignore lint/correctness/useExhaustiveDependencies: Serialized deps — options and the removed set are fresh objects every render.\n useEffect(() => {\n if (!canvas || !texture) return\n drawBacking(canvas, { options, count, tint: BACKING_TINT, removed })\n texture.needsUpdate = true\n }, [canvas, texture, JSON.stringify(options), count, removedKey])\n useEffect(() => () => texture?.dispose(), [texture])\n\n return (\n <mesh receiveShadow>\n <planeGeometry args={[width, height]} />\n <meshStandardMaterial map={texture} color=\"#ffffff\" roughness={0.92} metalness={0} />\n </mesh>\n )\n}\n","import * as THREE from 'three'\nimport { gsap } from 'gsap'\nimport { useFrame, useThree, type ThreeEvent } from '@react-three/fiber'\nimport { useContext, useEffect, useMemo, useRef, useState } from 'react'\nimport { paperConfigSchema, type PaperConfigInput } from '../config/schema'\nimport { mergeConfig } from '../config/merge'\nimport { PaperMesh, type PaperHandle } from '../PaperMesh'\nimport { carryDrive, dampTo, type DampedValue } from '../physics/aero'\nimport { usePrefersReducedMotion } from '../a11y'\nimport type { SheetDims } from '../deformers/types'\nimport { getLayout, type PaperPose } from './layouts'\nimport { tornEdgesOnDetach, type SheetLayoutOptions } from './sheetGrid'\nimport {\n DropZoneContext,\n DropZoneRegistry,\n DropZoneVisual,\n zoneAccepts,\n zoneContains,\n type DropZoneConfig,\n type PlacedPaper,\n type ZoneEntry,\n} from './dropZones'\nimport { BackingSheet } from './backingSheet'\nimport { EMPTY_SET, resolveFieldSlotConfig, type FieldPaperSlot } from './slots'\n\n/** Imperative field controls for the hidden a11y keyboard flow. */\nexport interface FieldA11yController {\n pick(slot: number): boolean\n placeAtZone(slot: number, zoneId: string): void\n cancel(slot: number): void\n zoneIds(): string[]\n slotState(slot: number): string\n}\n\nexport interface InteractiveFieldProps {\n papers: FieldPaperSlot[]\n fallback?: string | PaperConfigInput\n layoutId: string\n layoutOptions: Record<string, unknown>\n sheetOptions: SheetLayoutOptions | null\n /** The field's paper size, for layouts that arrange by contact. */\n sheet: SheetDims\n reducedMotion?: boolean\n /** Serialized zones (the editor's) — merged with `<DropZone>` children. */\n zones?: DropZoneConfig[]\n onSlotStateChange?(slot: number, state: string): void\n onPlace?(paper: PlacedPaper, zone: string): void\n a11yRef?: React.MutableRefObject<FieldA11yController | null>\n}\n\n/** Behaviors with a grab point — the only ones a drag can pick (spec §1.1). */\nconst PICK_BEHAVIORS = new Set(['peel', 'carry'])\n\ninterface CarriedPaper {\n slot: number\n pointerId: number | null\n x: DampedValue\n y: DampedValue\n targetX: number\n targetY: number\n lastX: number\n lastY: number\n homePose: PaperPose\n settling: boolean\n}\n\ninterface PressState {\n slot: number\n pointerId: number\n startX: number\n startY: number\n}\n\n/**\n * The interactive field: one hero-path PaperMesh per slot posed by the\n * layout, plus the carry controller — press past `pickThreshold` tears the\n * paper off (perforation auto-wires torn), it flies with the cursor\n * fluttering from drag velocity, zones test its center each frame, release\n * settles (snap → press → flatten) or flutters back to its slot.\n */\nexport function InteractiveField(props: InteractiveFieldProps) {\n const { papers, fallback, layoutId, layoutOptions, sheetOptions } = props\n const total = papers.length\n const layout = getLayout(layoutId)\n const reduced = usePrefersReducedMotion(props.reducedMotion)\n const contextRegistry = useContext(DropZoneContext)\n // Editor-serialized zones need hover state even without a provider.\n const registry = useMemo(() => contextRegistry ?? new DropZoneRegistry(), [contextRegistry])\n const camera = useThree((s) => s.camera)\n const gl = useThree((s) => s.gl)\n const controls = useThree((s) => s.controls) as { enabled?: boolean } | null\n\n // Once a stamp leaves its slot the silhouette stays bare — paper has\n // memory: a returned stamp sits ON its silhouette, detached.\n const [removed, setRemoved] = useState<ReadonlySet<number>>(EMPTY_SET)\n // Runtime config patches (torn perforation, carry override) — merged over\n // the slot config; the machine `rebase`s instead of resetting.\n const [slotPatches, setSlotPatches] = useState<Record<number, Record<string, unknown>>>({})\n const [slotStates, setSlotStates] = useState<Record<number, string>>({})\n\n // biome-ignore lint/correctness/useExhaustiveDependencies: Serialized deps — slots and layout options are fresh objects every render.\n const slotConfigs = useMemo(\n () =>\n papers.map((slot, i) => {\n const config = resolveFieldSlotConfig(slot, fallback, i, layoutId, layoutOptions)\n const patch = slotPatches[i]\n return patch ? paperConfigSchema.parse(mergeConfig(config as Record<string, unknown>, patch)) : config\n }),\n [\n JSON.stringify(papers),\n JSON.stringify(fallback ?? null),\n layoutId,\n JSON.stringify(layoutOptions),\n slotPatches,\n ],\n )\n // biome-ignore lint/correctness/useExhaustiveDependencies: Serialized deps — poses depend on the layout, not on config identity.\n const poses = useMemo(\n () => slotConfigs.map((_, i) => layout.pose(i, total, layoutOptions, 0, props.sheet)),\n [layoutId, JSON.stringify(layoutOptions), total, props.sheet.width, props.sheet.height],\n )\n\n const groupRefs = useRef<(THREE.Group | null)[]>([])\n const handleRefs = useRef<(PaperHandle | null)[]>([])\n const pressRef = useRef<PressState | null>(null)\n const carriedRef = useRef<CarriedPaper | null>(null)\n\n // Registry zones can register after mount; read live in the frame loop.\n const zonesLive = (): ZoneEntry[] => [...(props.zones ?? []), ...registry.list()]\n\n const slotName = (i: number): string => {\n const preset = papers[i]?.preset ?? fallback\n return typeof preset === 'string' ? preset : (slotConfigs[i]?.meta.name ?? 'paper')\n }\n\n const onSlotState = (i: number, state: string) => {\n setSlotStates((prev) => ({ ...prev, [i]: state }))\n if (state === 'picked' || state === 'placed') {\n setRemoved((prev) => (prev.has(i) ? prev : new Set(prev).add(i)))\n }\n props.onSlotStateChange?.(i, state)\n }\n\n // ── Pointer → field-plane projection ──\n const raycaster = useMemo(() => new THREE.Raycaster(), [])\n const planeScratch = useMemo(() => new THREE.Plane(new THREE.Vector3(0, 0, 1), 0), [])\n const pointScratch = useMemo(() => new THREE.Vector3(), [])\n const ndcScratch = useMemo(() => new THREE.Vector2(), [])\n const planePoint = (clientX: number, clientY: number, planeZ: number): [number, number] | null => {\n const rect = gl.domElement.getBoundingClientRect()\n ndcScratch.set(\n ((clientX - rect.left) / rect.width) * 2 - 1,\n -((clientY - rect.top) / rect.height) * 2 + 1,\n )\n raycaster.setFromCamera(ndcScratch, camera)\n planeScratch.constant = -planeZ\n const hit = raycaster.ray.intersectPlane(planeScratch, pointScratch)\n return hit ? [hit.x, hit.y] : null\n }\n\n // ── Pick: the tear ──\n const pick = (slot: number, atX: number, atY: number, pointerId: number | null = null): boolean => {\n const config = slotConfigs[slot]\n const handle = handleRefs.current[slot]\n const home = poses[slot]\n if (!config?.states || !handle || !home) return false\n if (!config.behavior || !PICK_BEHAVIORS.has(config.behavior.type)) return false\n if (slotStates[slot] === 'placed' || carriedRef.current) return false\n\n // Auto-wire the sticker model: perforation edges that faced neighbors\n // tear through (manual state wins), and `picked` defaults to a carry\n // hanging from the peeled corner unless the preset choreographs its own.\n const patch: Record<string, unknown> = {}\n if (sheetOptions && config.surface.perforation) {\n const auto = tornEdgesOnDetach(slot, sheetOptions)\n patch.surface = {\n perforation: { state: { ...auto, ...config.surface.perforation.state } },\n }\n }\n const pickedOverrides = config.states.states.picked?.overrides as { behavior?: unknown } | undefined\n if (!pickedOverrides?.behavior) {\n const grab =\n config.behavior.type === 'peel' && config.behavior.corner !== 'auto'\n ? config.behavior.corner\n : 'top-left'\n patch.states = {\n states: {\n picked: { overrides: { behavior: { type: 'carry', grab, drive: 0.3 } } },\n },\n }\n }\n if (Object.keys(patch).length > 0) {\n setSlotPatches((prev) => ({ ...prev, [slot]: mergeConfig(prev[slot] ?? {}, patch) }))\n }\n\n // Drive the machine through rest→hover→pressed→picked so every side effect\n // fires for BOTH pointer (already at 'pressed') and keyboard (still at\n // 'rest') entry — raw send('pick') from 'rest' was a silent no-op.\n handle.pickProgrammatic()\n carriedRef.current = {\n slot,\n pointerId,\n x: { value: atX, velocity: 0 },\n y: { value: atY, velocity: 0 },\n targetX: atX,\n targetY: atY,\n lastX: atX,\n lastY: atY,\n homePose: home,\n settling: false,\n }\n if (controls) controls.enabled = false\n return true\n }\n\n // ── The settle: the 400ms that sells everything (spec §5.3) ──\n const settleInto = (carried: CarriedPaper, zone: ZoneEntry) => {\n const group = groupRefs.current[carried.slot]\n const handle = handleRefs.current[carried.slot]\n if (!group || !handle) return\n carried.settling = true\n handle.placeProgrammatic()\n handle.set('drive', 0)\n registry.setHovered(null)\n\n const paper: PlacedPaper = {\n slot: carried.slot,\n presetName: slotName(carried.slot),\n config: slotConfigs[carried.slot]!,\n }\n const zoneZ = zone.bounds.position[2]\n const done = () => {\n carriedRef.current = null\n if (controls) controls.enabled = true\n zone.onPlace?.(paper, zone.id)\n props.onPlace?.(paper, zone.id)\n }\n if (reduced) {\n group.position.set(group.position.x, group.position.y, zoneZ + 0.005)\n group.rotation.set(0, 0, 0)\n group.scale.setScalar(1)\n done()\n return\n }\n const tl = gsap.timeline({ onComplete: done })\n // 1 · Snap — position tweens to the drop point on the zone plane.\n tl.to(group.position, { z: zoneZ + 0.005, duration: 0.12, ease: 'power3.out' }, 0)\n tl.to(group.rotation, { x: 0, y: 0, z: 0, duration: 0.12, ease: 'power3.out' }, 0)\n // 2 · Press — the paper bows into the surface, shadow tightening.\n tl.to(group.scale, { x: 1.02, y: 1.02, z: 1, duration: 0.09, ease: 'power2.in' }, 0.12)\n tl.to(group.position, { z: zoneZ + 0.001, duration: 0.18, ease: 'power2.out' }, 0.12)\n // 3 · Flatten — tiny overshoot on scale (1.0 → 0.985 → 1.0).\n tl.to(group.scale, { x: 0.985, y: 0.985, duration: 0.06, ease: 'power1.inOut' }, 0.3)\n tl.to(group.scale, { x: 1, y: 1, duration: 0.06, ease: 'power1.out' }, 0.36)\n }\n\n // ── The return: flutter back to the slot on a slight arc (spec §5.4) ──\n const returnHome = (carried: CarriedPaper) => {\n const group = groupRefs.current[carried.slot]\n const handle = handleRefs.current[carried.slot]\n if (!group || !handle) return\n carried.settling = true\n registry.setHovered(null)\n\n const home = carried.homePose\n const done = () => {\n handle.returnProgrammatic()\n carriedRef.current = null\n if (controls) controls.enabled = true\n }\n if (reduced) {\n group.position.set(...home.position)\n group.rotation.set(...home.rotation)\n group.scale.setScalar(home.scale)\n done()\n return\n }\n const from = { x: group.position.x, y: group.position.y, z: group.position.z }\n const dist = Math.hypot(from.x - home.position[0], from.y - home.position[1])\n const duration = Math.min(0.8, Math.max(0.25, dist * 0.55))\n // Curved path: a slight arc perpendicular to the travel, not linear.\n const arc = Math.min(0.35, dist * 0.25)\n const proxy = { t: 0 }\n gsap.to(proxy, {\n t: 1,\n duration,\n ease: 'power2.inOut',\n onUpdate: () => {\n const t = proxy.t\n const lift = Math.sin(t * Math.PI) * arc\n group.position.x = from.x + (home.position[0] - from.x) * t\n group.position.y = from.y + (home.position[1] - from.y) * t + lift\n group.position.z = from.z + (home.position[2] - from.z) * t\n // Flutter decays as it approaches.\n handle.set('drive', (1 - t) * 0.5)\n },\n onComplete: done,\n })\n gsap.to(group.rotation, { x: home.rotation[0], y: home.rotation[1], z: home.rotation[2], duration })\n gsap.to(group.scale, { x: home.scale, y: home.scale, z: home.scale, duration: duration * 0.5 })\n }\n\n // ── Press / drag / release wiring ──\n // Handlers close over the current render's state, so the fresh closures live\n // in refs and the window listeners attach ONCE — re-subscribing per render\n // (worst: per slot-state change mid-drag) is listener churn for nothing.\n const onPointerMoveRef = useRef<(e: PointerEvent) => void>(() => {})\n onPointerMoveRef.current = (e: PointerEvent) => {\n const press = pressRef.current\n const carried = carriedRef.current\n if (carried && !carried.settling && (carried.pointerId === null || e.pointerId === carried.pointerId)) {\n const hit = planePoint(e.clientX, e.clientY, carried.homePose.position[2] + 0.15)\n if (hit) {\n carried.targetX = hit[0]\n carried.targetY = hit[1]\n }\n return\n }\n if (!press) return\n const hit = planePoint(e.clientX, e.clientY, poses[press.slot]?.position[2] ?? 0)\n if (!hit) return\n const dist = Math.hypot(hit[0] - press.startX, hit[1] - press.startY)\n const threshold = slotConfigs[press.slot]?.states?.pickThreshold ?? 0.1\n if (dist > threshold) {\n const { slot, pointerId } = press\n pressRef.current = null\n pick(slot, hit[0], hit[1], pointerId)\n }\n }\n const onPointerUpRef = useRef<(e: PointerEvent) => void>(() => {})\n onPointerUpRef.current = (e: PointerEvent) => {\n pressRef.current = null\n const carried = carriedRef.current\n if (!carried || carried.settling) return\n if (carried.pointerId !== null && e.pointerId !== carried.pointerId) return\n const name = slotName(carried.slot)\n const zone = zonesLive().find(\n (z) => zoneContains(z, carried.x.value, carried.y.value) && zoneAccepts(z, name),\n )\n if (zone) settleInto(carried, zone)\n else returnHome(carried)\n }\n useEffect(() => {\n const move = (e: PointerEvent) => onPointerMoveRef.current(e)\n const up = (e: PointerEvent) => onPointerUpRef.current(e)\n window.addEventListener('pointermove', move)\n window.addEventListener('pointerup', up)\n return () => {\n window.removeEventListener('pointermove', move)\n window.removeEventListener('pointerup', up)\n }\n }, [])\n\n // ── The carry loop: damped follow, velocity flutter, zone hover ──\n useFrame((_, delta) => {\n const carried = carriedRef.current\n if (!carried || carried.settling) return\n const group = groupRefs.current[carried.slot]\n const handle = handleRefs.current[carried.slot]\n if (!group || !handle) return\n const dt = Math.min(delta, 1 / 30)\n\n if (reduced) {\n // Reduced motion: direct cursor-following, no flutter, no lag.\n carried.x.value = carried.lastX = carried.targetX\n carried.y.value = carried.lastY = carried.targetY\n group.position.x = carried.targetX\n group.position.y = carried.targetY\n group.position.z = carried.homePose.position[2] + 0.15\n } else {\n dampTo(carried.x, carried.targetX, 0.09, dt)\n dampTo(carried.y, carried.targetY, 0.09, dt)\n const vx = (carried.x.value - carried.lastX) / dt\n const vy = (carried.y.value - carried.lastY) / dt\n carried.lastX = carried.x.value\n carried.lastY = carried.y.value\n const speed = Math.hypot(vx, vy)\n group.position.x = carried.x.value\n group.position.y = carried.y.value\n group.position.z = carried.homePose.position[2] + 0.15\n // Drag velocity becomes flutter + rotational lag: yaw trails the drag.\n handle.set('drive', carryDrive(speed))\n const lag = 0.25\n group.rotation.y += (THREE.MathUtils.clamp(-vx * lag, -0.6, 0.6) - group.rotation.y) * 0.12\n group.rotation.x += (THREE.MathUtils.clamp(vy * lag * 0.7, -0.5, 0.5) - group.rotation.x) * 0.12\n }\n\n // Zone hover: center test each frame; scale-up is the \"this will stick\" cue.\n const name = slotName(carried.slot)\n const zone = zonesLive().find(\n (z) => zoneContains(z, group.position.x, group.position.y) && zoneAccepts(z, name),\n )\n registry.setHovered(zone?.id ?? null)\n const targetScale = (zone ? 1.03 : 1) * carried.homePose.scale\n group.scale.x += (targetScale - group.scale.x) * 0.15\n group.scale.y = group.scale.z = group.scale.x\n })\n\n // ── a11y controller: keyboard pick → move between zones → place/escape ──\n // Same ref-delegation as the pointer listeners: the real implementation is\n // rebuilt per render (fresh closures), the published object is stable.\n const a11yImplRef = useRef<FieldA11yController | null>(null)\n a11yImplRef.current = {\n pick: (slot) => {\n const home = poses[slot]\n if (!home) return false\n // pick() drives the machine (rest→…→picked) itself — no raw events.\n return pick(slot, home.position[0], home.position[1])\n },\n placeAtZone: (slot, zoneId) => {\n const carried = carriedRef.current\n const zone = zonesLive().find((z) => z.id === zoneId)\n const group = groupRefs.current[slot]\n if (!carried || carried.slot !== slot || !zone || !group) return\n group.position.x = zone.bounds.position[0]\n group.position.y = zone.bounds.position[1]\n carried.x.value = group.position.x\n carried.y.value = group.position.y\n settleInto(carried, zone)\n },\n cancel: (slot) => {\n const carried = carriedRef.current\n if (carried && carried.slot === slot && !carried.settling) returnHome(carried)\n },\n zoneIds: () => zonesLive().map((z) => z.id),\n slotState: (slot) => slotStates[slot] ?? 'rest',\n }\n useEffect(() => {\n const ref = props.a11yRef\n if (!ref) return\n ref.current = {\n pick: (slot) => a11yImplRef.current?.pick(slot) ?? false,\n placeAtZone: (slot, zoneId) => a11yImplRef.current?.placeAtZone(slot, zoneId),\n cancel: (slot) => a11yImplRef.current?.cancel(slot),\n zoneIds: () => a11yImplRef.current?.zoneIds() ?? [],\n slotState: (slot) => a11yImplRef.current?.slotState(slot) ?? 'rest',\n }\n return () => {\n ref.current = null\n }\n }, [props.a11yRef])\n\n return (\n <group>\n {sheetOptions?.backing && <BackingSheet options={sheetOptions} count={total} removed={removed} />}\n {(props.zones ?? []).map((zone) => (\n <DropZoneVisual key={zone.id} registry={registry} config={zone} />\n ))}\n {slotConfigs.map((config, i) => {\n const pose = poses[i]!\n return (\n <group\n // biome-ignore lint/suspicious/noArrayIndexKey: a slot IS its index — refs, poses, drags and drops all address a paper by slot number.\n key={i}\n ref={(g) => {\n groupRefs.current[i] = g\n }}\n position={pose.position}\n rotation={pose.rotation}\n scale={pose.scale}\n onPointerDown={(e: ThreeEvent<PointerEvent>) => {\n if (carriedRef.current) return\n const hit = planePoint(e.clientX, e.clientY, pose.position[2])\n if (!hit) return\n pressRef.current = { slot: i, pointerId: e.pointerId, startX: hit[0], startY: hit[1] }\n }}\n >\n <PaperMesh\n ref={(h) => {\n handleRefs.current[i] = h\n }}\n preset={config}\n reducedMotion={props.reducedMotion}\n onStateChange={(state) => onSlotState(i, state)}\n />\n </group>\n )\n })}\n </group>\n )\n}\n","import {\n behaviorConfigSchema,\n clothConfigSchema,\n contentSchema,\n paperConfigSchema,\n sheetSchema,\n type PaperConfig,\n type PaperConfigInput,\n} from './schema'\n\n/**\n * Presets are diffable: exports emit only non-default values, so a shared\n * `.paper` file or JSX snippet reads like intent, not like a database dump.\n */\n\nfunction isPlainObject(v: unknown): v is Record<string, unknown> {\n return typeof v === 'object' && v !== null && !Array.isArray(v)\n}\n\n/** Keys of `value` that differ from `defaults` (deep compare, shallow recurse). */\nfunction diffAgainst(\n value: Record<string, unknown>,\n defaults: Record<string, unknown>,\n keep: string[] = [],\n): Record<string, unknown> {\n const out: Record<string, unknown> = {}\n for (const [key, v] of Object.entries(value)) {\n if (keep.includes(key)) {\n out[key] = v\n continue\n }\n if (JSON.stringify(v) !== JSON.stringify(defaults[key])) {\n out[key] =\n isPlainObject(v) && isPlainObject(defaults[key])\n ? diffAgainst(v, defaults[key] as Record<string, unknown>)\n : v\n }\n }\n return out\n}\n\n/** The minimal PaperConfigInput that parses back to `config`. */\nexport function diffConfig(config: PaperConfig): PaperConfigInput {\n const base = paperConfigSchema.parse({})\n const out: Record<string, unknown> = {}\n\n const sheet = diffAgainst(config.sheet as never, sheetSchema.parse({}) as never)\n if (Object.keys(sheet).length > 0) out.sheet = sheet\n\n if (config.stock !== base.stock) out.stock = config.stock\n\n if (config.content.type !== 'blank') {\n // Defaults for this content type; required fields (image src) always kept.\n const defaults = contentSchema.parse(\n config.content.type === 'image'\n ? { type: 'image', src: config.content.src }\n : { type: config.content.type },\n ) as Record<string, unknown>\n out.content = {\n type: config.content.type,\n ...diffAgainst(config.content as never, defaults, config.content.type === 'image' ? ['src'] : []),\n }\n }\n\n if (config.behavior) {\n const defaults = behaviorConfigSchema.parse({ type: config.behavior.type }) as Record<string, unknown>\n out.behavior = { type: config.behavior.type, ...diffAgainst(config.behavior as never, defaults) }\n }\n if (config.deformers) out.deformers = config.deformers\n\n if (Object.keys(config.surface).length > 0) out.surface = config.surface\n\n if (typeof config.physics === 'object') {\n const defaults = clothConfigSchema.parse({ type: 'cloth' }) as Record<string, unknown>\n out.physics = { type: 'cloth', ...diffAgainst(config.physics as never, defaults) }\n } else if (config.physics !== 'none') {\n out.physics = config.physics\n }\n\n if (config.scene.lighting !== 'studio') out.scene = { lighting: config.scene.lighting }\n if (config.onTwos) out.onTwos = true\n // States are already diffs on the base — emit them whole.\n if (config.states) out.states = config.states\n const meta = diffAgainst(config.meta as never, paperConfigSchema.parse({}).meta as never)\n if (Object.keys(meta).length > 0) out.meta = meta\n\n return out as PaperConfigInput\n}\n\n/** Render a value as compact JSX-attribute source. */\nfunction jsxValue(value: unknown): string {\n if (typeof value === 'string') return `\"${value}\"`\n return `{${JSON.stringify(value)}}`\n}\n\n/**\n * A plain `<Paper />` snippet with only the non-default props — the\n * secondary export for people who read code.\n */\nexport function buildJsxSnippet(config: PaperConfig): string {\n const diff = diffConfig(config) as Record<string, unknown>\n delete diff.meta\n const props = Object.entries(diff).map(([key, value]) => ` ${key}=${jsxValue(value)}`)\n if (props.length === 0) return '<Paper />'\n return `<Paper\\n${props.join('\\n')}\\n/>`\n}\n","import type { PaperConfig } from './schema'\nimport { getStock } from '../core/stock'\nimport { diffConfig } from './diff'\n\n/**\n * The primary export consumer is a coding agent; the human is the courier.\n * This template IS product surface: versioned, snapshot-tested, regenerated\n * from the config. Anatomy is fixed — install → inlined code → placement\n * contract → a verification step the agent can self-check → pre-empted\n * failure modes.\n */\n/**\n * v2: field exports (multi-preset galleries with inlined preset consts).\n * v3: interaction states, sheet/backing fields, drop zones, carry/flight.\n */\nexport const AGENT_PAYLOAD_VERSION = 3\n\nconst BEHAVIOR_PHRASES: Record<string, (o: Record<string, unknown>) => string> = {\n peel: (o) => `its ${String(o.corner ?? 'bottom-right').replace('-', ' ')} corner peeling up`,\n unroll: (o) =>\n (o.progress as number) < 0.35\n ? 'mostly wound into a roll at the bottom'\n : 'unrolling from a paper roll at the bottom',\n flip: () => 'mid page-turn',\n 'letter-fold': () => 'tri-folding like a letter',\n hang: () => 'hanging from its top edge, rippling',\n fly: () => 'arched and fluttering like it is airborne',\n fall: () => 'rippling with one corner lifted, like a dropped sheet',\n ribbon: (o) =>\n `hanging the full drop of the room and pooling on the floor, about ${Math.round((o as { pool: number }).pool * 100)}% of its length lying over`,\n settle: (o) =>\n (o as { relax: number }).relax > 0.7\n ? 'lying where it landed, flat but for one corner the stiffness kept'\n : 'just come to rest, still holding a little of the shape it fell in',\n carry: () => 'drooping from a pinched corner, fluttering as if being carried',\n flight: (o) =>\n o.path === 'loop' ? 'tumbling through a seamless airborne loop' : 'tumbling across the scene on the wind',\n crumple: (o) =>\n (o.progress as number) < 0.3\n ? 'lightly handled — a few soft creases across it'\n : (o.progress as number) < 0.7\n ? 'crushed into irregular creased facets, as if screwed up and flattened out again'\n : 'balled up in a fist',\n}\n\n/** One line an agent can verify against what it sees after `npm run dev`. */\nexport function describeConfig(config: PaperConfig): string {\n const stock = getStock(config.stock)\n const size = `${config.sheet.width}×${config.sheet.height}`\n\n let contentPhrase = 'a blank sheet'\n if (config.content.type === 'image') contentPhrase = 'a sheet printed with an image'\n if (config.content.type === 'text') contentPhrase = 'a sheet with typeset text'\n if (config.content.type === 'receipt') contentPhrase = `a store receipt for \"${config.content.store}\"`\n\n const parts = [`${contentPhrase} on ${stock.label.toLowerCase()} paper stock (${size})`]\n\n if (typeof config.physics === 'object') {\n parts.push(\n config.physics.pins === 'none'\n ? 'falling and settling as cloth'\n : `pinned (${config.physics.pins}) and moving like cloth in wind`,\n )\n } else if (config.behavior) {\n const phrase = BEHAVIOR_PHRASES[config.behavior.type]\n if (phrase) parts.push(phrase(config.behavior as Record<string, unknown>))\n }\n\n if (config.surface.deckle) {\n parts.push(\n `torn (deckled) ${config.surface.deckle.edges.join(' and ')} edge${config.surface.deckle.edges.length > 1 ? 's' : ''}`,\n )\n }\n if ((config.surface.aging ?? 0) > 0.3) parts.push('visibly aged and yellowed')\n\n return parts.join(', ')\n}\n\nfunction componentName(config: PaperConfig): string {\n const raw = config.meta.name === 'untitled' ? 'PaperlabPaper' : config.meta.name\n const pascal = raw\n .replace(/[^a-zA-Z0-9]+(.)/g, (_, c: string) => c.toUpperCase())\n .replace(/^./, (c) => c.toUpperCase())\n .replace(/[^a-zA-Z0-9]/g, '')\n return /^[A-Za-z]/.test(pascal) ? pascal : `Paper${pascal}`\n}\n\n/** The self-contained integration brief — one paste into a coding agent. */\nexport function buildAgentPayload(config: PaperConfig): string {\n const name = componentName(config)\n const preset = JSON.stringify(diffConfig(config), null, 2)\n\n return `Integrate a Paperlab paper component into this project. (paperlab agent-payload v${AGENT_PAYLOAD_VERSION})\n\n1. Install the dependencies:\n\n npm i paperlab three @react-three/fiber gsap\n\n2. Create the component below as \\`components/${name}.tsx\\` (or the project's\n component convention). It is self-contained and owns its own <Canvas>:\n\n\\`\\`\\`tsx\nimport { Paper, type PaperConfigInput } from 'paperlab'\n\nconst preset = ${preset.replace(/\\n/g, '\\n')} satisfies PaperConfigInput\n\nexport function ${name}() {\n return <Paper preset={preset} />\n}\n\\`\\`\\`\n\n3. Sizing: the component fills its parent container. Place it where I ask;\n give the parent an explicit height.\n\n4. Verify: run the dev server. You should see ${describeConfig(config)}.\n If the canvas is blank, the parent container almost certainly has no height —\n give it one (this is the classic React Three Fiber integration bug, not a\n paperlab bug).\n\nConstraints: don't modify the preset values; three >= 0.160 and React 19 are\nrequired; the component needs no props.`\n}\n"],"mappings":"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","names":["sheet","sheet","z","z","sheet","z","sheet","z","sheet","z","sheet","z","z","z","z","z","z","z","z","z","z","sheet","z","z","sheet","z","z","DEG","sheet","z","z","DEG","sheet","z","z","DEG","sheet","z","z","DEG","sheet","z","z","TAU","sheet","fold","z","z","z","THREE","z","sheet","registry","z","gust","z","z","DEG","THREE","z","THREE","sheet","THREE","jsx","sheet","useEffect","jsx","useEffect","useEffect","useMemo","useState","useMemo","useState","useEffect","THREE","gsap","useEffect","useMemo","useRef","useRef","THREE","useEffect","useState","sheet","useState","useEffect","jsx","useMemo","PaperMesh","useRef","useEffect","probe","gsap","THREE","useEffect","useMemo","useRef","useFrame","useThree","THREE","jsx","jsxs","useThree","useEffect","useMemo","useRef","useFrame","THREE","createContext","useContext","useEffect","useMemo","useRef","jsx","jsxs","registry","z","THREE","useEffect","useState","sheet","useState","useEffect","sheet","z","z","TAU","DEG","jitter","z","sheet","registry","useState","jsx","jsxs","carry","useState","sheet","DEG","THREE","gsap","useFrame","useThree","forwardRef","useEffect","useMemo","useRef","THREE","gsap","useFrame","useEffect","useMemo","useRef","CustomShaderMaterial","jsx","PROGRESS_SAMPLES","useRef","useMemo","useEffect","gsap","useFrame","CustomShaderMaterial","THREE","useEffect","useMemo","jsx","jsxs","useMemo","useEffect","THREE","gsap","useFrame","useThree","useContext","useEffect","useMemo","useRef","useState","jsx","jsxs","useContext","registry","useMemo","useThree","useState","useRef","gsap","hit","z","useEffect","useFrame","jsx","jsxs","forwardRef","PaperFieldMesh","useMemo","useRef","useThree","useEffect","gsap","useFrame","sheet","PaperField","registry","sheet"]}
|