@markmiro/hairy 0.0.0-stage → 0.1.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 +127 -2
- package/dist/chunk-JIET4PY7.js +2641 -0
- package/dist/chunk-JIET4PY7.js.map +1 -0
- package/dist/index.d.ts +1298 -0
- package/dist/index.js +37 -0
- package/dist/index.js.map +1 -0
- package/dist/react.d.ts +17 -0
- package/dist/react.js +29 -0
- package/dist/react.js.map +1 -0
- package/package.json +60 -3
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/color.ts","../src/gl.ts","../src/settings.ts","../src/fur.ts","../src/options.ts","../src/index.ts"],"sourcesContent":["/*\n Color helpers, from huet's core/color.ts: OKLab conversions, CIE lightness\n and APCA contrast. Opaque sRGB hex in, opaque sRGB hex out.\n*/\n\nexport type Triple = readonly [number, number, number];\nconst clamp01 = (x: number) => Math.max(0, Math.min(1, x));\n\nexport function rgb(hex: string): Triple {\n if (!/^#(?:[\\da-f]{3}|[\\da-f]{6})$/i.test(hex))\n throw new TypeError(`Expected an opaque hex color, got ${hex}`);\n const n = parseInt(hex.slice(1), 16);\n if (hex.length === 4)\n return [((n >> 8) & 15) / 15, ((n >> 4) & 15) / 15, (n & 15) / 15];\n return [((n >> 16) & 255) / 255, ((n >> 8) & 255) / 255, (n & 255) / 255];\n}\nconst linear = (v: number) =>\n v <= 0.04045 ? v / 12.92 : ((v + 0.055) / 1.055) ** 2.4;\nconst gamma = (v: number) =>\n v <= 0.0031308 ? 12.92 * v : 1.055 * v ** (1 / 2.4) - 0.055;\n\n/*\n CIE lightness L* (0–1) of a color with OKLab lightness L, treating L³ as its\n luminance (exact for neutrals). Above the toe, L* is an affine function of\n OKLab L. Near black, OKLab's cube root is infinitely steep: sRGB 0 → 1 spans\n 6.7% of OKLab's lightness range but 0.27% of L*'s.\n*/\nconst lightnessToe = 6 / 29;\nexport const lightnessOf = (L: number) =>\n L > lightnessToe ? 1.16 * L - 0.16 : (24389 / 2700) * L ** 3;\nexport const fromLightness = (v: number) =>\n v > 0.08 ? (v + 0.16) / 1.16 : Math.cbrt((v * 2700) / 24389);\n/** CIE lightness L* of a color, from 0 (black) to 1 (white). */\nexport function lightness(hex: string): number {\n return lightnessOf(toOklab(hex)[0]);\n}\n\n/** APCA's screen luminance, with its soft clamp near black. */\nexport function apcaY(hex: string): number {\n const [r, g, b] = rgb(hex);\n let y = 0.2126729 * r ** 2.4 + 0.7151522 * g ** 2.4 + 0.072175 * b ** 2.4;\n if (y < 0.022) y += (0.022 - y) ** 1.414;\n return y;\n}\n/**\n * APCA lightness contrast (Lc) of `text` on `background`, using the APCA-W3\n * 0.0.98G-4g constants. Positive for dark text on a lighter background,\n * negative for light text on a darker one. Black on white is about 106.\n */\nexport function apca(text: string, background: string): number {\n return apcaFromY(apcaY(text), apcaY(background));\n}\n/** `apca` from the `apcaY` of the text (`t`) and the background (`b`). */\nexport function apcaFromY(t: number, b: number): number {\n if (Math.abs(b - t) < 0.0005) return 0;\n const sapc = b > t\n ? (b ** 0.56 - t ** 0.57) * 1.14\n : (b ** 0.65 - t ** 0.62) * 1.14;\n return Math.sign(sapc) * Math.max(0, Math.abs(sapc) - 0.027) * 100;\n}\n\n// OKLab conversion matrices: https://bottosson.github.io/posts/oklab/\n/** Gamma-encoded sRGB channels (0–1) to OKLab. */\nfunction oklabFromRgb(r: number, g: number, b: number): Triple {\n (r = linear(r)), (g = linear(g)), (b = linear(b));\n const l = Math.cbrt(0.4122214708 * r + 0.5363325363 * g + 0.0514459929 * b);\n const m = Math.cbrt(0.2119034982 * r + 0.6806995451 * g + 0.1073969566 * b);\n const s = Math.cbrt(0.0883024619 * r + 0.2817188376 * g + 0.6299787005 * b);\n return [\n 0.2104542553 * l + 0.793617785 * m - 0.0040720468 * s,\n 1.9779984951 * l - 2.428592205 * m + 0.4505937099 * s,\n 0.0259040371 * l + 0.7827717662 * m - 0.808675766 * s,\n ];\n}\nexport function toOklab(hex: string): Triple {\n return oklabFromRgb(...rgb(hex));\n}\n\nfunction fromLab([L, a, b]: Triple): number[] {\n const l = (L + 0.3963377774 * a + 0.2158037573 * b) ** 3;\n const m = (L - 0.1055613458 * a - 0.0638541728 * b) ** 3;\n const s = (L - 0.0894841775 * a - 1.291485548 * b) ** 3;\n return [\n 4.0767416621 * l - 3.3077115913 * m + 0.2309699292 * s,\n -1.2684380046 * l + 2.6097574011 * m - 0.3413193965 * s,\n -0.0041960863 * l - 0.7034186147 * m + 1.707614701 * s,\n ];\n}\nconst fits = ([r, g, b]: number[]) =>\n r >= -1e-7 && r <= 1 + 1e-7 && g >= -1e-7 && g <= 1 + 1e-7 && b >= -1e-7 && b <= 1 + 1e-7;\n/**\n * Map into gamma-encoded sRGB channels (0–1) by reducing chroma, preserving\n * OKLCH hue and lightness.\n */\nfunction rgbFromOklab([L, a, b]: Triple): Triple {\n L = clamp01(L);\n let channels = fromLab([L, a, b]);\n if (!fits(channels)) {\n let low = 0,\n high = 1;\n for (let i = 0; i < 20; i++) {\n const mid = (low + high) / 2;\n if (fits(fromLab([L, a * mid, b * mid]))) low = mid;\n else high = mid;\n }\n channels = fromLab([L, a * low, b * low]);\n }\n return [clamp01(gamma(channels[0])), clamp01(gamma(channels[1])), clamp01(gamma(channels[2]))];\n}\nconst hexBytes = Array.from({ length: 256 }, (_, i) => i.toString(16).padStart(2, \"0\"));\nexport function fromOklab(lab: Triple): string {\n const [r, g, b] = rgbFromOklab(lab);\n return \"#\" + hexBytes[Math.round(r * 255)] + hexBytes[Math.round(g * 255)] + hexBytes[Math.round(b * 255)];\n}\n","/*\n The GPU side of the fur: one WebGL2 context that every fur on the page\n shares, so the browser's limit of about 16 contexts never comes into it.\n\n Each fur keeps its own 2D canvas behind its element. To draw a frame, the\n fur's hairs are drawn into the shared canvas and copied into its own canvas\n with `drawImage`, which stays on the GPU. Only the furs that are moving draw.\n\n Each hair is an instanced strip of triangles. Its data (root, the directions\n it lies and stands in, length, curl, shade…) is uploaded once, when the hairs\n grow. Each frame sends a few numbers: the lift, the time, the pointer, and\n the brushed hairs' bends while brushing. The vertex shader works out every\n hair's curve, its waves, coils or frizz, its width and color, the way\n fur.ts's `shape()` did on the CPU, and the fragment shader smooths its edges.\n\n Without WebGL2, or with only a slow software renderer\n (`failIfMajorPerformanceCaveat`), there's no fur at all: it's an\n enhancement, and the element keeps its own background.\n*/\n\n/** Floats per hair in the instance data: see `hairAttributes`. */\nexport const hairFloats = 15;\n/** The color ramps' width and rows: fur shades, sheen, then a pattern's markings and its third color. */\nexport const rampWidth = 64;\nexport const rampRows = 4;\n/** Glitter's sparkle candidates per hair at density 1; only a few show. */\nconst flakesPerDensity = 2;\n/** The most glitter a fur draws, as a density. */\nexport const maxGlitterDensity = 10;\n/** The shared canvas never grows past this many pixels a side; furs lower their pixel ratio to fit. */\nconst largest = 4096;\n\nexport type BufferGamut = \"srgb\" | \"display-p3\";\n\n/** Everything a fur's frame needs besides its hairs. Lengths in CSS px. */\nexport interface Frame {\n /** The fur canvas's size in CSS px, and its pixels per CSS px. */\n width: number;\n height: number;\n dpr: number;\n lift: number;\n sway: number;\n time: number;\n hovering: boolean;\n pointerX: number;\n pointerY: number;\n near: number;\n base: number;\n hoverTop: number;\n hoverStretch: number;\n clicked: number;\n grown: number;\n droop: number;\n scale: number;\n thickness: number;\n taper: number;\n /** How far each hair's edge fades past the usual pixel, in CSS px at scale 1. */\n softness: number;\n /** 0 straight, 1 wavy, 2 curly, 3 frizzy. */\n hairType: number;\n typeAmount: number;\n tightness: number;\n /** 0 round, 1 sharp, 2 square. */\n tip: number;\n /** 0 natural, 1 glitter. */\n material: number;\n materialAmount: number;\n /** Glitter: how many flakes, how big, and how much their sizes differ. */\n glitterDensity: number;\n glitterSize: number;\n glitterSizeVariation: number;\n /** 0 none, 1 zebra, 2 tiger, 3 dalmatian, 4 leopard, 5 giraffe; and how big its marks are. */\n pattern: number;\n patternScale: number;\n /** The element's center, and half its size, in CSS px on the fur canvas: what the pattern is laid out on. */\n body: { x: number; y: number; w: number; h: number };\n /** The undercoat: a blurred rounded box with a vertical gradient. */\n coat: { x: number; y: number; w: number; h: number; radius: number; blur: number; top: number; bottom: number };\n}\n\nexport interface Layer {\n /** The color space the ramps should be written in. */\n readonly gamut: BufferGamut;\n /** The largest canvas side, in device px, a fur can draw. */\n readonly largest: number;\n /**\n * New hairs: `hairFloats` per hair, in drawing order. The layer doesn't keep\n * `data`: after a lost context comes back, `onRestore` must set the hairs again.\n * The bends start at zero.\n */\n setHairs(data: Float32Array, count: number): void;\n /** Each hair's brushed bend, x then y. */\n setBends(bends: Float32Array): void;\n /** The color ramps, `rampWidth` × `rampRows` RGBA bytes. */\n setRamp(bytes: Uint8Array): void;\n /** Draws a frame into `target`, a 2D context whose canvas is the frame's size in device px. Returns false if it couldn't. */\n render(target: CanvasRenderingContext2D, frame: Frame): boolean;\n dispose(): void;\n}\n\n// ---- Shaders ----\n\n/*\n Coat patterns, shared by the hairs and the undercoat. A pattern is worked out\n on the skin: each hair takes the color where its root grows, so markings\n have the soft, hairy edges real ones do, and the undercoat between the hairs\n shows the same marks.\n\n `patternAt` gives two weights, 0 to 1: how far a point is in the markings\n (stripes, spots, rosette rings, giraffe patches), then how far it's in the\n pattern's third color (the insides of a leopard's rosettes, the darker\n middles of giraffe patches), which goes on top.\n*/\nconst patterns = /* glsl */ `\nuniform int uPattern; // 0 none, 1 zebra, 2 tiger, 3 dalmatian, 4 leopard, 5 giraffe\nuniform float uPatternScale; // pattern units per CSS px is 1 / (uScale * uPatternScale)\nuniform vec4 uBody; // the element's center, then half its size, in canvas CSS px\nuniform float uScale;\nuniform sampler2D uRamp;\n\nvec3 ramp(float row, float u) {\n return textureLod(uRamp, vec2((clamp(u, 0.0, 1.0) * ${rampWidth - 1}.0 + 0.5) / ${rampWidth}.0, (row + 0.5) / ${rampRows}.0), 0.0).rgb;\n}\n/** The fur's shade \\`u\\`, in the pattern's colors: ground, then markings, then the third color on top. */\nvec3 coatColor(float u, vec2 marks) {\n return mix(mix(ramp(0.0, u), ramp(2.0, u), marks.x), ramp(3.0, u), marks.y);\n}\n\nuint pcg(uint v) {\n uint s = v * 747796405u + 2891336453u;\n uint w = ((s >> ((s >> 28u) + 4u)) ^ s) * 277803737u;\n return (w >> 22u) ^ w;\n}\nfloat rand(ivec2 c, uint k) { return float(pcg(pcg(uint(c.x) ^ k) + uint(c.y))) / 4294967295.0; }\nvec2 rand2(ivec2 c) { return vec2(rand(c, 0x2545f491u), rand(c, 0x9e3779b9u)); }\n// Gradient noise, about -0.7 to 0.7.\nfloat gnoise(vec2 p) {\n ivec2 i = ivec2(floor(p));\n vec2 f = fract(p);\n vec2 u = f * f * f * (f * (f * 6.0 - 15.0) + 10.0);\n float a = rand(i, 11u) * 6.2831853, b = rand(i + ivec2(1, 0), 11u) * 6.2831853;\n float c = rand(i + ivec2(0, 1), 11u) * 6.2831853, d = rand(i + ivec2(1, 1), 11u) * 6.2831853;\n return mix(\n mix(dot(vec2(cos(a), sin(a)), f), dot(vec2(cos(b), sin(b)), f - vec2(1.0, 0.0)), u.x),\n mix(dot(vec2(cos(c), sin(c)), f - vec2(0.0, 1.0)), dot(vec2(cos(d), sin(d)), f - vec2(1.0)), u.x),\n u.y);\n}\nfloat fbm(vec2 p) { return 0.6 * gnoise(p) + 0.28 * gnoise(p * 2.07 + 17.3) + 0.12 * gnoise(p * 4.13 - 31.9); }\nvec2 warp(vec2 p, float size, float amount) {\n return p + amount * vec2(fbm(p / size), fbm(p / size + vec2(5.2, 1.3)));\n}\n\n// Zebra: bold black stripes, as wide as the white between them, running up\n// and down and bending as they go, forking where they get wide.\nvec2 zebra(vec2 q, vec2 n) {\n vec2 w = warp(q, 34.0, 9.0);\n // Leaning back toward the ends, like the stripes on a flank.\n float x = w.x + 0.28 * w.y * clamp(n.x, -1.0, 1.0);\n float a = 6.2831853 * x / 13.0;\n // A second harmonic splits a stripe in two where it's strong: the forks.\n float fork = smoothstep(0.15, 0.45, gnoise(q / 26.0 + 9.1));\n float v = cos(a) + fork * 0.9 * cos(2.0 * a + 3.1);\n float th = 0.05 + 0.35 * gnoise(q / 22.0 - 4.7);\n return vec2(smoothstep(th - 0.12, th + 0.12, v), 0.0);\n}\n\n// Tiger: narrow, broken black stripes on orange, from the back down, each\n// tapering to a point at its own length, and often doubled.\nvec2 tiger(vec2 q, vec2 n) {\n vec2 w = warp(q, 30.0, 8.0);\n float period = 17.0;\n float x = w.x + 0.22 * w.y + 0.35 * w.y * clamp(n.x, -1.0, 1.0);\n float id = floor(x / period);\n float d = abs(fract(x / period) - 0.5) * period;\n // Each stripe its own width along its length; where it runs out, it breaks.\n float width = 3.6 * (0.45 + 1.1 * gnoise(vec2(id * 3.7, w.y / 11.0)));\n // Narrowing to a point on the way down: some end partway, some run off the bottom.\n float reach = 0.45 + 0.75 * rand(ivec2(int(id), 0), 13u);\n width *= 1.0 - smoothstep(reach - 0.7, reach, n.y + 0.15 * gnoise(q / 14.0));\n float mark = 1.0 - smoothstep(width - 0.7, width + 0.7, d);\n // Doubled: a pale line down the middle of some.\n float split = smoothstep(0.1, 0.3, gnoise(vec2(id * 5.3 + 2.0, w.y / 18.0)));\n mark *= 1.0 - split * (1.0 - smoothstep(0.25 * width, 0.25 * width + 0.6, d));\n return vec2(mark, 0.0);\n}\n\n// Dalmatian: round black spots, well apart and of every size, with ragged edges.\nvec2 dalmatian(vec2 q, vec2 n) {\n float cell = 19.0;\n vec2 p = q / cell;\n ivec2 i = ivec2(floor(p));\n float edge = 1.1 * fbm(q / 4.0);\n float mark = 0.0;\n for (int y = -1; y <= 1; y++)\n for (int x = -1; x <= 1; x++) {\n ivec2 c = i + ivec2(x, y);\n if (rand(c, 3u) < 0.12) continue;\n vec2 at = (vec2(c) + 0.15 + 0.7 * rand2(c)) * cell;\n float s = rand(c, 5u);\n float r = 2.6 + 5.4 * s * s;\n // Slightly oval, each its own way.\n float t = rand(c, 7u) * 6.2831853;\n vec2 d = q - at;\n d = vec2(dot(d, vec2(cos(t), sin(t))), dot(d, vec2(-sin(t), cos(t)))) * vec2(1.0, 1.0 + 0.3 * rand(c, 9u));\n float dist = length(d) + edge;\n mark = max(mark, 1.0 - smoothstep(r - 0.5, r + 0.5, dist));\n }\n return vec2(mark, 0.0);\n}\n\n// Leopard: rosettes packed close but each its own shape, a ring of black\n// blotches around a deeper tawny middle, sometimes with a dot of black in it,\n// and a few solid spots. Each rosette fills a Voronoi cell, its ring part way\n// out to the cell's edge, so the rings follow the cells' uneven shapes and\n// leave a band of ground between neighbors.\nvec2 leopard(vec2 q, vec2 n) {\n float cell = 19.0;\n vec2 w = warp(q, 20.0, 3.0) + 0.8 * vec2(gnoise(q / 3.0), gnoise(q / 3.0 + 7.7));\n vec2 p = w / cell;\n ivec2 i = ivec2(floor(p));\n // The nearest rosette's middle, then the distance to its cell's edge.\n vec2 near = vec2(0.0);\n ivec2 id = i;\n float best = 1e9;\n for (int y = -1; y <= 1; y++)\n for (int x = -1; x <= 1; x++) {\n ivec2 c = i + ivec2(x, y);\n vec2 at = vec2(c) + 0.5 + 0.85 * (rand2(c) - 0.5);\n float d = dot(p - at, p - at);\n if (d < best) { best = d; near = at; id = c; }\n }\n float edge = 1e9;\n for (int y = -2; y <= 2; y++)\n for (int x = -2; x <= 2; x++) {\n ivec2 c = i + ivec2(x, y);\n vec2 at = vec2(c) + 0.5 + 0.85 * (rand2(c) - 0.5);\n vec2 to = at - near;\n if (dot(to, to) < 1e-6) continue;\n edge = min(edge, dot(0.5 * (near + at) - p, normalize(to)));\n }\n vec2 from = (p - near) * cell;\n float f = length(from), e = max(0.0, edge) * cell;\n // 0 at the rosette's middle, 1 at the edge it shares with the next.\n float r = f / max(f + e, 1e-3);\n float kind = rand(id, 3u);\n if (kind < 0.16) {\n // A solid spot.\n float size = 0.32 + 0.12 * rand(id, 5u) + 0.05 * gnoise(q / 2.0);\n return vec2(1.0 - smoothstep(size - 0.05, size + 0.05, r), 0.0);\n }\n // The ring, breaking into three to five blotches around the middle.\n vec2 around = from / max(f, 1e-3);\n float g = gnoise(around * 1.35 + rand2(id) * 40.0) + 0.3 * gnoise(q / 2.2);\n float open = smoothstep(-0.3, -0.12, g);\n float inner = 0.54 + 0.1 * gnoise(q / 3.2 + 3.0) + 0.06 * (rand(id, 9u) - 0.5);\n float outer = 0.78 + 0.07 * gnoise(q / 3.2 - 5.0);\n float ring = smoothstep(inner - 0.05, inner + 0.03, r) * (1.0 - smoothstep(outer - 0.03, outer + 0.05, r)) * open;\n float inside = 1.0 - smoothstep(inner - 0.04, inner + 0.04, r);\n // A dot or two of black in the middle of most.\n for (int k = 0; k < 2; k++) {\n uint key = 21u + uint(k) * 4u;\n if (rand(id, key) > (k == 0 ? 0.65 : 0.25)) continue;\n float a = rand(id, key + 1u) * 6.2831853;\n vec2 o = vec2(cos(a), sin(a)) * (f + e) * inner * 0.45 * rand(id, key + 2u);\n float size = 0.9 + 0.7 * rand(id, key + 3u) - 0.2 * float(k);\n float spot = length(from - o) + 0.35 * gnoise(q / 1.8);\n ring = max(ring, 1.0 - smoothstep(size - 0.4, size + 0.4, spot));\n }\n return vec2(ring, inside * (1.0 - ring) * 0.9);\n}\n\n// Giraffe: big brown patches, darker toward their middles, in a net of\n// narrow cream lines with jagged edges.\nvec2 giraffe(vec2 q, vec2 n) {\n float cell = 24.0;\n vec2 w = warp(q, 20.0, 5.0) + 1.1 * vec2(gnoise(q / 2.8), gnoise(q / 2.8 + 7.7));\n vec2 p = w / cell;\n ivec2 i = ivec2(floor(p));\n // The nearest patch's middle, then the distance to its edge with the next.\n vec2 near = vec2(0.0);\n float best = 1e9;\n for (int y = -1; y <= 1; y++)\n for (int x = -1; x <= 1; x++) {\n ivec2 c = i + ivec2(x, y);\n vec2 at = vec2(c) + 0.1 + 0.8 * rand2(c);\n float d = dot(p - at, p - at);\n if (d < best) { best = d; near = at; }\n }\n float edge = 1e9;\n for (int y = -2; y <= 2; y++)\n for (int x = -2; x <= 2; x++) {\n ivec2 c = i + ivec2(x, y);\n vec2 at = vec2(c) + 0.1 + 0.8 * rand2(c);\n vec2 to = at - near;\n if (dot(to, to) < 1e-6) continue;\n edge = min(edge, dot(0.5 * (near + at) - p, normalize(to)));\n }\n edge *= cell;\n float line = 1.9 + 0.7 * gnoise(q / 9.0);\n float tile = smoothstep(line - 0.5, line + 0.5, edge);\n return vec2(tile, tile * smoothstep(3.0, 11.0, edge) * 0.75);\n}\n\n/** The pattern's weights at \\`pos\\`, in canvas CSS px: markings, then the third color. */\nvec2 patternAt(vec2 pos) {\n if (uPattern == 0) return vec2(0.0);\n vec2 q = (pos - uBody.xy) / max(1e-3, uScale * uPatternScale);\n vec2 n = (pos - uBody.xy) / max(vec2(1.0), uBody.zw);\n if (uPattern == 1) return zebra(q, n);\n if (uPattern == 2) return tiger(q, n);\n if (uPattern == 3) return dalmatian(q, n);\n if (uPattern == 4) return leopard(q, n);\n return giraffe(q, n);\n}\n`;\n\nconst common = /* glsl */ `#version 300 es\nprecision highp float;\nprecision highp int;\n\nlayout(location = 0) in vec4 aRootRest; // root x, y; the direction it lies in at rest\nlayout(location = 1) in vec4 aLeanStand; // how far it leans out of the outline; the direction it stands in\nlayout(location = 2) in vec4 aHair; // length, curl, sway phase, rim (1 on the outline)\nlayout(location = 3) in vec3 aLook; // shade (0 to 1), kind (0 underfur, 1 guard hair, 2 sheen), seed (0 to 1)\nlayout(location = 4) in vec2 aBend; // how far the pointer has brushed it\n\nuniform vec2 uView;\nuniform float uDpr;\nuniform float uLift, uSway, uTime, uHovering, uNear;\nuniform vec2 uPointer;\nuniform float uBase, uHoverTop, uHoverStretch, uClicked, uGrown, uDroop;\nuniform float uThickness, uTaper, uSoftness;\nuniform int uType;\nuniform float uTypeAmount, uTightness;\nuniform int uTip;\nuniform float uMaterialAmount;\nuniform float uGlitterDensity, uGlitterSize, uGlitterVariation;\n${patterns}\nconst float TAU = 6.2831853;\n\nfloat hash(float x) { return fract(sin(x * 78.233 + 0.31) * 43758.5453); }\nfloat vnoise(float x) {\n float i = floor(x), f = fract(x);\n return mix(hash(i), hash(i + 1.0), f * f * (3.0 - 2.0 * f)) * 2.0 - 1.0;\n}\n/** The pattern where this hair grows, from a point a little off its root, so the markings' edges are ragged hair by hair. */\nvec2 hairMarks() {\n if (uPattern == 0) return vec2(0.0);\n vec2 off = vec2(hash(aLook.z * 13.7) - 0.5, hash(aLook.z * 29.1) - 0.5) * 2.4 * uScale;\n return patternAt(aRootRest.xy + off);\n}\nvec2 clip(vec2 p) { return vec2(p.x / uView.x * 2.0 - 1.0, 1.0 - p.y / uView.y * 2.0); }\n\n// This hair's curve this frame: a cubic from its root, and its length and lift.\nvec2 P0, P1, P2, P3;\nfloat LEN, LIFT;\n\nvoid shape() {\n vec2 root = aRootRest.xy, rest = aRootRest.zw;\n float rim = aHair.w;\n // Below 0 (a bounce swinging past rest), the hairs press flatter than they lie.\n float l = max(-0.5, uLift);\n // A little higher right under the pointer.\n if (uHovering > 0.5) {\n vec2 d = root - uPointer;\n l += 0.12 * exp(-dot(d, d) / uNear);\n }\n float L = min(1.0, l);\n float a = uSway * sin(uTime * 2.2 + aHair.z);\n vec2 dir = (rest + aLeanStand.xy) * (1.0 - L) + aLeanStand.zw * L + aBend + vec2(-rest.y, rest.x) * a;\n if (uType == 3) {\n // Frizz: hairs fly off from the combed direction, less as they stand.\n float turn = (hash(aLook.z * 7.13) - 0.5) * 1.2 * uTypeAmount * (1.0 - 0.5 * L);\n float c = cos(turn), s = sin(turn);\n dir = vec2(dir.x * c - dir.y * s, dir.x * s + dir.y * c);\n }\n float dl = length(dir);\n dir = dl > 1e-5 ? dir / dl : vec2(0.0, 1.0);\n // Stretch: hovering stretches hairs as they rise from rest to the hover\n // lift, a click further along its own rise and fall.\n float hovered = uHoverTop - uBase > 1e-3 ? (l - uBase) / (uHoverTop - uBase) : 0.0;\n float stretch = uHoverStretch * clamp(hovered, 0.0, 1.3) + uClicked;\n // Outline hairs reach out as they stand; middle ones point at you, so they look shorter.\n float len = aHair.x * uGrown * (1.0 + stretch) * (1.0 + rim * 0.3 * l - (1.0 - rim) * 0.35 * L);\n float curl = aHair.y * (1.0 - 0.5 * L);\n // Hairs droop under their weight until they stand.\n float droop = 0.2 * uDroop * (1.0 - L) * len;\n vec2 side = vec2(-dir.y, dir.x);\n P0 = root;\n P1 = root + dir * len * 0.34;\n P2 = root + dir * len * 0.68 + side * curl * len * 0.3 + vec2(0.0, droop * 0.4);\n P3 = root + dir * len * 0.92 + side * curl * len * 0.55 + vec2(0.0, droop);\n LEN = len;\n LIFT = L;\n}\n\nvec2 bezier(float t) {\n float u = 1.0 - t;\n return u * u * u * P0 + 3.0 * u * u * t * P1 + 3.0 * u * t * t * P2 + t * t * t * P3;\n}\nvec2 slope(float t) {\n float u = 1.0 - t;\n return 3.0 * u * u * (P1 - P0) + 6.0 * u * t * (P2 - P1) + 3.0 * t * t * (P3 - P2);\n}\n\n// The point \\`t\\` of the way along the hair, with its type's waves, coils or frizz.\nvec2 along(float t) {\n vec2 p = bezier(t);\n if (uType == 0 || uTypeAmount <= 0.0) return p;\n vec2 T = slope(t);\n float tl = length(T);\n T = tl > 1e-5 ? T / tl : vec2(1.0, 0.0);\n vec2 N = vec2(-T.y, T.x);\n float seed = aLook.z;\n if (uType == 1) {\n // Wavy: ripples side to side, growing in from the root.\n float A = 0.13 * LEN * uTypeAmount * smoothstep(0.0, 0.3, t);\n return p + N * A * sin(TAU * (1.4 * uTightness * t + seed));\n }\n if (uType == 2) {\n // Curly: a coil seen from the side, looping back on itself, turning either way.\n float R = 0.14 * LEN * uTypeAmount * smoothstep(0.0, 0.12, t);\n float th = TAU * 2.5 * uTightness * t;\n float spin = seed > 0.5 ? 1.0 : -1.0;\n return p + R * (N * spin * sin(th) + T * (cos(th) - 1.0));\n }\n // Frizzy: kinks at random, broad bends with fine zigzags on them, more toward the tip.\n float A = 0.2 * LEN * uTypeAmount * pow(t, 0.7);\n float f = 7.0 * uTightness;\n float kink = 0.6 * vnoise(t * f + seed * 97.0) + 0.4 * vnoise(t * f * 3.1 + seed * 31.0);\n return p + N * A * kink + T * A * 0.35 * vnoise(t * f * 1.3 + seed * 53.0);\n}\n`;\n\nconst hairVertex = /* glsl */ `${common}\nuniform int uSegments;\nout vec4 vColor;\nout float vAcross;\nout float vHalf;\nout float vAlong;\nflat out float vRound;\nflat out float vFade;\n\nvoid main() {\n shape();\n // Two vertices per step along the hair, then two past the tip for its end.\n int k = gl_VertexID / 2;\n float side = gl_VertexID % 2 == 0 ? -1.0 : 1.0;\n bool end = k > uSegments;\n float t = end ? 1.0 : float(k) / float(uSegments);\n vec2 p = along(t);\n float e = 0.5 / float(uSegments);\n vec2 T = along(min(1.0, t + e)) - along(max(0.0, t - e));\n float tl = length(T);\n T = tl > 1e-6 ? T / tl : vec2(1.0, 0.0);\n vec2 N = vec2(-T.y, T.x);\n\n float kind = aLook.y;\n bool sheen = kind > 1.5;\n // Narrowing from root to tip by the taper; a sharp end narrows on to a point.\n float width = sheen ? 0.7 * uScale * uThickness : (kind > 0.5 ? 1.1 : 0.95) * uScale * uThickness * mix(1.0, uTaper, t);\n if (!sheen && uTip == 1) width *= clamp((1.0 - t) / 0.35, 0.0, 1.0);\n // Half the width in device px, and the strip's half width with room for the\n // soft edge: a pixel, plus the softness, centered on the hair's edge.\n float hw = 0.5 * width * uDpr;\n float fade = 1.0 + uSoftness * uScale * uDpr;\n float g = max(hw, 0.5) + 0.5 * fade + 0.5;\n bool rounded = sheen || uTip == 0;\n vec2 pos = p + N * side * g / uDpr;\n float to = -(1.0 - t) * LEN * uDpr;\n if (end) {\n // A round end reaches half the width past the tip; the others just the soft edge.\n float past = rounded ? g : 0.5 * fade + 0.5;\n pos += T * past / uDpr;\n to = past;\n }\n gl_Position = vec4(clip(pos), 0.0, 1.0);\n vAcross = side * g;\n vHalf = hw;\n vAlong = to;\n vRound = rounded ? 1.0 : 0.0;\n vFade = fade;\n\n // Darker at the root, lighter and a little see-through toward the tip.\n float shade = aLook.x;\n vec2 marks = hairMarks();\n if (sheen) {\n // On markings, the shine is their own highlight.\n vec3 gloss = mix(mix(ramp(1.0, shade), ramp(2.0, 1.0), marks.x), ramp(3.0, 1.0), marks.y);\n vColor = vec4(gloss, 0.35);\n return;\n }\n float m = smoothstep(0.3, 0.7, t);\n float u = shade + mix(-1.0, 1.0, m) / 23.0;\n vColor = vec4(coatColor(u, marks), mix(1.0, 0.75, m));\n}\n`;\n\nconst hairFragment = /* glsl */ `#version 300 es\nprecision highp float;\nin vec4 vColor;\nin float vAcross;\nin float vHalf;\nin float vAlong;\nflat in float vRound;\nflat in float vFade;\nout vec4 outColor;\n\nvoid main() {\n // How much of this pixel the hair covers: an edge fading over vFade px\n // (one, unless softened), a hw circle past a round tip, and hairs thinner\n // than a pixel fade instead.\n float hw = max(vHalf, 0.5);\n float d = vRound > 0.5 && vAlong > 0.0 ? length(vec2(vAlong, vAcross)) : abs(vAcross);\n float cover = clamp((hw + 0.5 * vFade - d) / vFade, 0.0, 1.0);\n if (vRound < 0.5) cover *= clamp((0.5 * vFade - vAlong) / vFade, 0.0, 1.0);\n float a = vColor.a * cover * min(1.0, vHalf * 2.0);\n if (a < 0.002) discard;\n outColor = vec4(vColor.rgb * a, a);\n}\n`;\n\nconst flakeVertex = /* glsl */ `${common}\nout vec2 vUV;\nout float vBright;\nout float vFade;\nout vec3 vColor;\n\nvoid main() {\n shape();\n // Six vertices per flake: a square around a point on the hair.\n int k = gl_VertexID / 6, c = gl_VertexID % 6;\n float s = aLook.z * 91.7 + float(k) * 13.1;\n // Each candidate shows by its own chance, so more density adds flakes and\n // keeps the ones already there; the last candidate fades in by its share.\n float keep = clamp(uGlitterDensity * ${flakesPerDensity}.0 - float(k), 0.0, 1.0);\n bool show = aLook.y < 1.5 && hash(s + 1.7) < 0.03 * keep;\n float t = mix(0.25, 1.0, hash(s));\n vec2 p = along(t);\n vec2 T = along(min(1.0, t + 0.04)) - along(max(0.0, t - 0.04));\n // A flake flashes when its hair turns it toward the light, so it twinkles as the fur moves.\n float glint = 0.5 + 0.5 * cos(atan(T.y, T.x) * 3.0 + hash(s + 3.1) * TAU + uTime * 1.3);\n float flash = pow(glint, 12.0);\n // Its own size: up to 2^variation times bigger or smaller, evenly spread between.\n float own = exp2(uGlitterVariation * (2.0 * hash(s + 5.3) - 1.0));\n float size = show ? (0.5 + 1.4 * flash) * uScale * (0.7 + 0.3 * uThickness) * uGlitterSize * own : 0.0;\n // The amount sets how bright the flashes are.\n float bright = flash * uMaterialAmount;\n vec2 corner = vec2(c == 1 || c == 2 || c == 4 ? 1.0 : -1.0, c == 2 || c == 4 || c == 5 ? 1.0 : -1.0);\n // The square reaches past the flake for its rays.\n float reach = 3.0;\n gl_Position = vec4(clip(p + corner * size * reach), 0.0, 1.0);\n vUV = corner * reach;\n vBright = bright;\n vFade = min(1.0, uMaterialAmount);\n // Tinted like the fur's sheen; the brightest flash nearly white.\n vColor = mix(ramp(1.0, 1.0), vec3(1.0), clamp(0.25 + 0.6 * bright, 0.0, 1.0));\n}\n`;\n\nconst flakeFragment = /* glsl */ `#version 300 es\nprecision highp float;\nin vec2 vUV;\nin float vBright;\nin float vFade;\nin vec3 vColor;\nout vec4 outColor;\n\nvoid main() {\n float core = exp(-dot(vUV, vUV) * 2.0);\n float rays = (exp(-abs(vUV.x) * 2.5 - vUV.y * vUV.y * 0.4) + exp(-abs(vUV.y) * 2.5 - vUV.x * vUV.x * 0.4)) * vBright;\n float a = clamp(core * (0.55 * vFade + 0.45 * min(vBright, 1.0)) + rays * 0.7, 0.0, 1.0);\n if (a < 0.003) discard;\n // A little lighter than covering, so sparkles brighten what's under them.\n outColor = vec4(vColor * a, a * 0.8);\n}\n`;\n\nconst coatVertex = /* glsl */ `#version 300 es\nprecision highp float;\nuniform vec2 uView;\nout vec2 vPos;\nvoid main() {\n vec2 c = vec2(gl_VertexID % 2 == 0 ? 0.0 : 1.0, gl_VertexID < 2 ? 0.0 : 1.0);\n vPos = c * uView;\n gl_Position = vec4(c.x * 2.0 - 1.0, 1.0 - c.y * 2.0, 0.0, 1.0);\n}\n`;\n\nconst coatFragment = /* glsl */ `#version 300 es\nprecision highp float;\nprecision highp int;\nuniform vec4 uBox;\nuniform float uRadius, uBlur;\nuniform vec2 uGradient;\nin vec2 vPos;\nout vec4 outColor;\n${patterns}\n\nvoid main() {\n // The shade deep in the fur, between the hairs: a rounded box, blurred.\n vec2 q = abs(vPos - (uBox.xy + uBox.zw * 0.5)) - (uBox.zw * 0.5 - uRadius);\n float sd = length(max(q, 0.0)) + min(max(q.x, q.y), 0.0) - uRadius;\n // Clamped, as tanh overflows far from the edge on some GPUs.\n float x = clamp(sd / (max(uBlur, 0.01) * 1.41421356), -4.0, 4.0);\n float cover = 0.5 - 0.5 * tanh(x * (1.1283792 + 0.1009 * x * x));\n if (cover < 0.002) discard;\n float g = clamp((vPos.y - uGradient.x) / max(1.0, uGradient.y - uGradient.x), 0.0, 1.0);\n vec2 marks = patternAt(vPos);\n outColor = vec4(mix(coatColor(0.46, marks), coatColor(0.3, marks), g) * cover, cover);\n}\n`;\n\n// ---- The shared context ----\n\ntype Uniforms = Record<string, WebGLUniformLocation | null>;\ninterface Program {\n program: WebGLProgram;\n u: Uniforms;\n}\ninterface Shared {\n canvas: HTMLCanvasElement;\n gl: WebGL2RenderingContext;\n gamut: BufferGamut;\n largest: number;\n lost: boolean;\n hair: Program;\n flake: Program;\n coat: Program;\n empty: WebGLVertexArrayObject;\n layers: Set<GpuLayer>;\n}\n\nlet shared: Shared | null | undefined;\n\nfunction compile(gl: WebGL2RenderingContext, vertex: string, fragment: string): Program {\n const program = gl.createProgram()!;\n for (const [type, source] of [[gl.VERTEX_SHADER, vertex], [gl.FRAGMENT_SHADER, fragment]] as const) {\n const shader = gl.createShader(type)!;\n gl.shaderSource(shader, source);\n gl.compileShader(shader);\n if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS) && !gl.isContextLost()) {\n throw new Error(`hairy: shader failed to compile: ${gl.getShaderInfoLog(shader)}`);\n }\n gl.attachShader(program, shader);\n gl.deleteShader(shader);\n }\n gl.linkProgram(program);\n if (!gl.getProgramParameter(program, gl.LINK_STATUS) && !gl.isContextLost()) {\n throw new Error(`hairy: shaders failed to link: ${gl.getProgramInfoLog(program)}`);\n }\n const u: Uniforms = {};\n const count = gl.getProgramParameter(program, gl.ACTIVE_UNIFORMS) as number;\n for (let i = 0; i < count; i++) {\n const name = gl.getActiveUniform(program, i)!.name;\n u[name] = gl.getUniformLocation(program, name);\n }\n return { program, u };\n}\n\nfunction build(s: Pick<Shared, \"gl\">) {\n const { gl } = s;\n return {\n hair: compile(gl, hairVertex, hairFragment),\n flake: compile(gl, flakeVertex, flakeFragment),\n coat: compile(gl, coatVertex, coatFragment),\n empty: gl.createVertexArray()!,\n };\n}\n\nfunction connect(): Shared | null {\n if (shared !== undefined) return shared;\n shared = null;\n if (typeof document === \"undefined\") return null;\n const canvas = document.createElement(\"canvas\");\n canvas.width = canvas.height = 256;\n let gl: WebGL2RenderingContext | null = null;\n try {\n gl = canvas.getContext(\"webgl2\", {\n alpha: true,\n premultipliedAlpha: true,\n antialias: false,\n depth: false,\n stencil: false,\n preserveDrawingBuffer: false,\n // Without a real GPU, the fur would be too slow to animate: leave it off.\n failIfMajorPerformanceCaveat: true,\n });\n } catch {\n gl = null;\n }\n if (!gl) return null;\n let gamut: BufferGamut = \"srgb\";\n if (\"drawingBufferColorSpace\" in gl) {\n try {\n gl.drawingBufferColorSpace = \"display-p3\";\n gamut = gl.drawingBufferColorSpace === \"display-p3\" ? \"display-p3\" : \"srgb\";\n } catch {\n gamut = \"srgb\";\n }\n }\n const viewport = gl.getParameter(gl.MAX_VIEWPORT_DIMS) as Int32Array;\n const size = Math.min(largest, gl.getParameter(gl.MAX_RENDERBUFFER_SIZE) as number, viewport[0], viewport[1]);\n let programs: ReturnType<typeof build>;\n try {\n programs = build({ gl });\n } catch (error) {\n console.warn(error);\n return null;\n }\n const s: Shared = { canvas, gl, gamut, largest: size, lost: false, ...programs, layers: new Set() };\n canvas.addEventListener(\"webglcontextlost\", (event) => {\n // Ask for the context back. Until then, each fur keeps its last frame.\n event.preventDefault();\n s.lost = true;\n });\n canvas.addEventListener(\"webglcontextrestored\", () => {\n try {\n Object.assign(s, build(s));\n } catch (error) {\n console.warn(error);\n return;\n }\n if (s.gamut === \"display-p3\") gl.drawingBufferColorSpace = \"display-p3\";\n s.lost = false;\n for (const layer of s.layers) layer.restore();\n });\n return (shared = s);\n}\n\n/** Whether this browser can draw fur: WebGL2 on a real GPU. */\nexport const gpuSupported = () => connect() !== null;\n\n/**\n * A fur's GPU data, in the shared context: its hairs, bends and ramps. Only\n * the GPU holds the hairs. If the context is lost and comes back, the layer\n * starts empty and `onRestore` grows the hairs again (growing is seeded, so\n * they come back the same) and redraws. It keeps the small ramps to upload again.\n */\nclass GpuLayer implements Layer {\n private count = 0;\n private rampBytes: Uint8Array = new Uint8Array(rampWidth * rampRows * 4);\n private vao: WebGLVertexArrayObject | null = null;\n private hairBuffer: WebGLBuffer | null = null;\n private bendBuffer: WebGLBuffer | null = null;\n private texture: WebGLTexture | null = null;\n private disposed = false;\n private s: Shared;\n private onRestore: () => void;\n\n constructor(s: Shared, onRestore: () => void) {\n this.s = s;\n this.onRestore = onRestore;\n this.create();\n s.layers.add(this);\n }\n\n get gamut() {\n return this.s.gamut;\n }\n get largest() {\n return this.s.largest;\n }\n\n private create() {\n const { gl } = this.s;\n this.vao = gl.createVertexArray();\n this.hairBuffer = gl.createBuffer();\n this.bendBuffer = gl.createBuffer();\n gl.bindVertexArray(this.vao);\n gl.bindBuffer(gl.ARRAY_BUFFER, this.hairBuffer);\n const stride = hairFloats * 4;\n ([[0, 4, 0], [1, 4, 16], [2, 4, 32], [3, 3, 48]] as const).forEach(([location, size, offset]) => {\n gl.enableVertexAttribArray(location);\n gl.vertexAttribPointer(location, size, gl.FLOAT, false, stride, offset);\n gl.vertexAttribDivisor(location, 1);\n });\n gl.bindBuffer(gl.ARRAY_BUFFER, this.bendBuffer);\n gl.enableVertexAttribArray(4);\n gl.vertexAttribPointer(4, 2, gl.FLOAT, false, 8, 0);\n gl.vertexAttribDivisor(4, 1);\n gl.bindVertexArray(null);\n this.texture = gl.createTexture();\n gl.bindTexture(gl.TEXTURE_2D, this.texture);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);\n this.uploadRamp();\n }\n\n restore() {\n if (this.disposed) return;\n this.create();\n // The new buffers are empty until the fur sets its hairs again.\n this.count = 0;\n this.onRestore();\n }\n\n private uploadRamp() {\n const { gl } = this.s;\n gl.bindTexture(gl.TEXTURE_2D, this.texture);\n gl.pixelStorei(gl.UNPACK_ALIGNMENT, 1);\n gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA8, rampWidth, rampRows, 0, gl.RGBA, gl.UNSIGNED_BYTE, this.rampBytes);\n }\n\n setHairs(data: Float32Array, count: number) {\n // While the context is lost, there's nothing to upload into; `restore` asks again.\n if (this.s.lost) return;\n this.count = count;\n const { gl } = this.s;\n gl.bindBuffer(gl.ARRAY_BUFFER, this.hairBuffer);\n gl.bufferData(gl.ARRAY_BUFFER, data, gl.STATIC_DRAW);\n // A buffer given only a size starts zeroed: no bends.\n gl.bindBuffer(gl.ARRAY_BUFFER, this.bendBuffer);\n gl.bufferData(gl.ARRAY_BUFFER, count * 2 * 4, gl.DYNAMIC_DRAW);\n }\n\n setBends(bends: Float32Array) {\n if (this.s.lost) return;\n const { gl } = this.s;\n gl.bindBuffer(gl.ARRAY_BUFFER, this.bendBuffer);\n gl.bufferSubData(gl.ARRAY_BUFFER, 0, bends);\n }\n\n setRamp(bytes: Uint8Array) {\n this.rampBytes = bytes;\n if (!this.s.lost) this.uploadRamp();\n }\n\n render(target: CanvasRenderingContext2D, f: Frame) {\n const s = this.s;\n if (s.lost || this.disposed) return false;\n const { gl, canvas } = s;\n const width = target.canvas.width, height = target.canvas.height;\n if (!width || !height) return false;\n // Grow the shared canvas to fit, in steps, so it isn't resized every time.\n if (canvas.width < width || canvas.height < height) {\n canvas.width = Math.min(s.largest, Math.max(canvas.width, Math.ceil(width / 128) * 128));\n canvas.height = Math.min(s.largest, Math.max(canvas.height, Math.ceil(height / 128) * 128));\n }\n // Draw into the top-left corner, as the 2D canvas sees it (WebGL counts rows from the bottom).\n const y = canvas.height - height;\n gl.viewport(0, y, width, height);\n gl.enable(gl.SCISSOR_TEST);\n gl.scissor(0, y, width, height);\n gl.clearColor(0, 0, 0, 0);\n gl.clear(gl.COLOR_BUFFER_BIT);\n gl.enable(gl.BLEND);\n gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA);\n gl.activeTexture(gl.TEXTURE0);\n gl.bindTexture(gl.TEXTURE_2D, this.texture);\n\n // The undercoat.\n const c = f.coat;\n gl.useProgram(s.coat.program);\n let u = s.coat.u;\n gl.uniform2f(u.uView, f.width, f.height);\n gl.uniform4f(u.uBox, c.x, c.y, Math.max(0, c.w), Math.max(0, c.h));\n gl.uniform1f(u.uRadius, Math.max(0, Math.min(c.radius, c.w / 2, c.h / 2)));\n gl.uniform1f(u.uBlur, c.blur);\n gl.uniform2f(u.uGradient, c.top, c.bottom);\n this.patternUniforms(u, f);\n gl.bindVertexArray(s.empty);\n if (c.w > 0 && c.h > 0) gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);\n\n // The hairs, then glitter on top.\n if (this.count) {\n gl.bindVertexArray(this.vao);\n const segments = segmentsFor(f);\n gl.useProgram(s.hair.program);\n this.uniforms(s.hair.u, f);\n gl.uniform1i(s.hair.u.uSegments, segments);\n gl.drawArraysInstanced(gl.TRIANGLE_STRIP, 0, (segments + 1) * 2 + 2, this.count);\n const flakes = Math.ceil(f.glitterDensity * flakesPerDensity);\n if (f.material === 1 && f.materialAmount > 0 && f.glitterSize > 0 && flakes > 0) {\n gl.useProgram(s.flake.program);\n this.uniforms(s.flake.u, f);\n gl.drawArraysInstanced(gl.TRIANGLES, 0, flakes * 6, this.count);\n }\n }\n gl.bindVertexArray(null);\n gl.disable(gl.SCISSOR_TEST);\n\n target.setTransform(1, 0, 0, 1, 0, 0);\n target.clearRect(0, 0, width, height);\n target.drawImage(canvas, 0, 0, width, height, 0, 0, width, height);\n return true;\n }\n\n private uniforms(u: Uniforms, f: Frame) {\n const { gl } = this.s;\n const set1 = (name: string, value: number) => u[name] && gl.uniform1f(u[name], value);\n const seti = (name: string, value: number) => u[name] && gl.uniform1i(u[name], value);\n gl.uniform2f(u.uView, f.width, f.height);\n set1(\"uDpr\", f.dpr);\n set1(\"uLift\", f.lift);\n set1(\"uSway\", f.sway);\n set1(\"uTime\", f.time);\n set1(\"uHovering\", f.hovering ? 1 : 0);\n set1(\"uNear\", f.near);\n if (u.uPointer) gl.uniform2f(u.uPointer, f.pointerX, f.pointerY);\n set1(\"uBase\", f.base);\n set1(\"uHoverTop\", f.hoverTop);\n set1(\"uHoverStretch\", f.hoverStretch);\n set1(\"uClicked\", f.clicked);\n set1(\"uGrown\", f.grown);\n set1(\"uDroop\", f.droop);\n set1(\"uThickness\", f.thickness);\n set1(\"uTaper\", f.taper);\n set1(\"uSoftness\", f.softness);\n seti(\"uType\", f.hairType);\n set1(\"uTypeAmount\", f.typeAmount);\n set1(\"uTightness\", f.tightness);\n seti(\"uTip\", f.tip);\n set1(\"uMaterialAmount\", f.materialAmount);\n set1(\"uGlitterDensity\", f.glitterDensity);\n set1(\"uGlitterSize\", f.glitterSize);\n set1(\"uGlitterVariation\", f.glitterSizeVariation);\n this.patternUniforms(u, f);\n }\n\n private patternUniforms(u: Uniforms, f: Frame) {\n const { gl } = this.s;\n if (u.uRamp) gl.uniform1i(u.uRamp, 0);\n if (u.uPattern) gl.uniform1i(u.uPattern, f.pattern);\n if (u.uPatternScale) gl.uniform1f(u.uPatternScale, f.patternScale);\n if (u.uScale) gl.uniform1f(u.uScale, f.scale);\n if (u.uBody) gl.uniform4f(u.uBody, f.body.x, f.body.y, f.body.w, f.body.h);\n }\n\n dispose() {\n if (this.disposed) return;\n this.disposed = true;\n this.s.layers.delete(this);\n if (this.s.lost) return;\n const { gl } = this.s;\n gl.deleteVertexArray(this.vao);\n gl.deleteBuffer(this.hairBuffer);\n gl.deleteBuffer(this.bendBuffer);\n gl.deleteTexture(this.texture);\n }\n}\n\n/** Steps along each hair: enough for its waves, coils or kinks to stay smooth. */\nfunction segmentsFor(f: Frame) {\n const tight = Math.max(0, f.tightness);\n if (f.hairType === 0 || f.typeAmount <= 0) return 8;\n if (f.hairType === 1) return Math.min(48, Math.ceil(8 + 14 * tight));\n if (f.hairType === 2) return Math.min(64, Math.ceil(6 + 25 * tight));\n return Math.min(64, Math.ceil(8 + 30 * tight));\n}\n\n/** A new fur's GPU layer, or null when the browser can't draw fur. */\nexport function createLayer(onRestore: () => void): Layer | null {\n const s = connect();\n if (!s || s.lost) return null;\n return new GpuLayer(s, onRestore);\n}\n","/*\n The fur's settings and named presets, from huet's demo/fur/fur.ts.\n*/\n\n/** Curves for the poof's rise and fall, from 0 to 1. Some overshoot, then come back. */\nexport const eases = {\n linear: (t: number) => t,\n /** Speeds up steadily, like something dropping. */\n gravity: (t: number) => t * t,\n \"ease-in\": (t: number) => t ** 3,\n \"ease-out\": (t: number) => 1 - (1 - t) ** 3,\n \"ease-in-out\": (t: number) => (t < 0.5 ? 4 * t ** 3 : 1 - (-2 * t + 2) ** 3 / 2),\n \"back-out\": (t: number) => 1 + 2.70158 * (t - 1) ** 3 + 1.70158 * (t - 1) ** 2,\n \"elastic-out\": (t: number) =>\n t <= 0 ? 0 : t >= 1 ? 1 : 2 ** (-10 * t) * Math.sin(((10 * t - 0.75) * 2 * Math.PI) / 3) + 1,\n};\nexport type Ease = keyof typeof eases;\n/** Where along `ease` (0–1) the curve first reaches `f`, by bisection. */\nexport function easeInverse(ease: (t: number) => number, f: number) {\n let lo = 0, hi = 1;\n for (let i = 0; i < 24; i++) {\n const mid = (lo + hi) / 2;\n if (ease(mid) < f) lo = mid;\n else hi = mid;\n }\n return hi;\n}\n\n/** The choices for each setting that picks from a list, in the order the playground shows them. */\nexport const settingChoices = {\n /** Straight hairs follow one smooth curve; wavy ones ripple side to side; curly ones coil into loops; frizzy ones kink at random and fly away. */\n hairType: [\"straight\", \"wavy\", \"curly\", \"frizzy\"],\n /** Round tips end in a half circle; sharp ones narrow to a fine point; square ones are cut straight across. */\n tipShape: [\"round\", \"sharp\", \"square\"],\n /** Natural fur, or glitter, with sparkling flakes. */\n material: [\"natural\", \"glitter\"],\n /** A coat pattern, as on an animal: none, zebra stripes, tiger stripes, dalmatian spots, leopard rosettes or giraffe patches. */\n pattern: [\"none\", \"zebra\", \"tiger\", \"dalmatian\", \"leopard\", \"giraffe\"],\n /** The pattern's colors: the animal's own, or tints of the fur's color. */\n patternColors: [\"natural\", \"tinted\"],\n /** When the label gets a halo: \"auto\" only when a pattern needs one, or \"always\" or \"never\". */\n halo: [\"auto\", \"always\", \"never\"],\n} as const;\nexport type HairType = (typeof settingChoices.hairType)[number];\nexport type TipShape = (typeof settingChoices.tipShape)[number];\nexport type Material = (typeof settingChoices.material)[number];\nexport type Pattern = (typeof settingChoices.pattern)[number];\nexport type PatternColors = (typeof settingChoices.patternColors)[number];\nexport type Halo = (typeof settingChoices.halo)[number];\nexport type ChoiceSetting = keyof typeof settingChoices;\n\n/**\n * Every setting the fur has, at its defaults (the Plush preset). Each fur\n * keeps its own copy. The ones marked \"regrows\" change the hairs themselves,\n * so changing them grows the hairs again.\n */\nexport const defaultSettings = {\n /** Palette: where its middle sits (L*, 0–1, from the color), how far it reaches below and above that. */\n shift: -0.13,\n darker: 0.4,\n lighter: 0.22,\n /** Hairs per area (regrows). */\n density: 1.65,\n /** Hair length. Changing it grows or shrinks the hairs with the hover spring. */\n length: 0.8,\n thickness: 0.75,\n /** How much hairs curl (regrows). */\n curl: 0.95,\n /** How much hairs droop under their weight. */\n droop: 0.4,\n /** How much hair lengths vary, 0 all the same (regrows). */\n lengthVariation: 1,\n /** How much hair directions vary from the combed flow (regrows). */\n messiness: 1,\n /** How far hairs along the outline lean out, making the fuzzy edge (regrows). */\n fuzz: 2,\n /**\n * How far from the button's edge the fur starts, in px at scale 1 (regrows):\n * above 0 the outline hairs and the fur's body sit out past the edge, below\n * 0 they move in, eating into the button.\n */\n distance: 0,\n /** Tip width relative to the root. */\n taper: 0.31,\n /**\n * How soft each hair's edge is, in px at scale 1: 0 is the crisp\n * pixel-wide edge, higher fades it out over that many more pixels, up to 2. Each\n * hair gets wider to hold the fade, so it costs a little more to draw.\n */\n softness: 0,\n /** The hairs' pattern: straight, wavy, curly or frizzy. */\n hairType: \"straight\" as HairType,\n /** How strong the waves, curls or frizz are: 0 is straight, 1 the usual amount. */\n typeAmount: 1,\n /** How many waves, turns or kinks fit along each hair: higher is tighter. */\n tightness: 1,\n /** How each hair ends: round, sharp or square. */\n tipShape: \"round\" as TipShape,\n /** What the hair looks made of: natural or glitter. */\n material: \"natural\" as Material,\n /** How bright glitter's flashes are. */\n materialAmount: 1,\n /** Glitter: how many flakes there are, 1 the usual amount. */\n glitterDensity: 1,\n /** Glitter: how big the flakes are, 1 the usual size. */\n glitterSize: 1,\n /** Glitter: how much flake sizes differ, 0 all the same; at 1 they range from half to twice the size. */\n glitterSizeVariation: 0,\n /** A coat pattern, as on an animal: \"none\", \"zebra\", \"tiger\", \"dalmatian\", \"leopard\" or \"giraffe\". */\n pattern: \"none\" as Pattern,\n /** The pattern's colors: \"natural\" takes the animal's own, \"tinted\" makes them from the fur's color. */\n patternColors: \"natural\" as PatternColors,\n /** How big the pattern's stripes, spots or patches are, 1 the usual size. */\n patternScale: 1,\n /**\n * A soft glow behind the label, in the fur's base color, so it reads where\n * the fur alone doesn't, as on a zebra's white and black at once: \"auto\"\n * adds it only when a pattern needs one, or \"always\" or \"never\".\n */\n halo: \"auto\" as Halo,\n /** How far the halo's shade moves from the base color, away from the label's: darker under a light label, lighter under a dark one (L, 0–1). */\n haloShade: 0.3,\n /** How far the halo's glow spreads round the letters, 1 the usual size. */\n haloSize: 1,\n /** How strong the halo is, 1 the usual; 0 has none. */\n haloStrength: 1,\n /** How many hairs catch the light (regrows). */\n sheen: 0.1,\n /** Where the band of shine sits, 0 at the top to 1 at the bottom, and how far it spreads (regrows). */\n sheenPosition: 0.1,\n sheenSpread: 0.32,\n /** How dark the hairs along the top edge are, turned away from the light; also keeps the shine off it (regrows). */\n edgeShadow: 0,\n /** On wide-gamut screens, how far colors move out toward the more vivid colors sRGB can't show (0 to 1). */\n vividness: 0,\n /** How far the hairs stand at rest, with no hover: 0 is combed flat, 1 standing up. */\n static: 0,\n /** How much further the hairs stand when hovered, on top of `static` (up to 1). */\n hover: 0.35,\n /**\n * The hover spring: how fast it moves (rad/s) and its damping ratio (lower\n * bounces more, 1 doesn't overshoot). Hovering out and clicking move on\n * springs like it.\n */\n hoverSpeed: 22,\n hoverDamping: 0.9,\n /** The hover-out spring (without a click playing), back down to rest: speed (rad/s) and damping ratio. */\n leaveSpeed: 7,\n leaveDamping: 0.25,\n // Hovering out along a curve, set aside for now: it springs instead.\n // /**\n // * Hovering out (without a click playing): the fur falls at `leaveFallSpeed`\n // * along `leaveEase`, then lands and wobbles out like\n // * e^(−settle·t)·cos(bounce·t).\n // */\n // leaveFallSpeed: 1.55,\n // leaveEase: \"gravity\" as Ease,\n // leaveSettle: 1.4,\n // leaveBounce: 5.5,\n /** How much the hairs sway while hovered. */\n sway: 0.05,\n /**\n * How much longer the hairs grow as they rise to the hover lift: 0.5 makes\n * them half as long again (regrows, to make room).\n */\n hoverStretch: 0,\n /** How much lighter the fur gets as it rises to the hover lift, in L* (0–1); below 0 darkens. */\n hoverLight: 0.05,\n /**\n * A click poofs the fur up by `poofHeight` on the rise spring, hangs there\n * for `poofHold` seconds, then comes back down to where it rests (hovered,\n * or flat if the pointer has left) on the fall spring, which also springs\n * the click's stretch back. Speeds in rad/s, then damping ratios (lower\n * bounces more, 1 doesn't overshoot).\n */\n clickRiseSpeed: 49,\n clickRiseDamping: 0.9,\n clickFallSpeed: 8.5,\n clickFallDamping: 0.2,\n // A click along curves, set aside for now: it springs instead.\n // /**\n // * A click poofs the fur up by `poofHeight` over `poofRise` seconds, hangs\n // * there for `poofHold` seconds, then falls at `poofFallSpeed` back to\n // * where it rests (hovered, or flat if the pointer has left). It lands with\n // * whatever speed the fall curve ends with, overshoots, and wobbles out like\n // * e^(−settle·t)·cos(bounce·t).\n // */\n poofHeight: 0.53,\n /** How much longer still the hairs grow at the top of a click, on top of `hoverStretch` (regrows). */\n clickStretch: 0,\n /** How much lighter still a click makes the fur, on top of `hoverLight`, springing back with the click. */\n clickLight: 0,\n // poofRise: 0.13,\n // poofSettle: 3.1,\n // poofBounce: 15,\n // /** The curve of the poof's rise. */\n // poofEase: \"ease-out\" as Ease,\n /** Seconds the fur hangs at the top of the poof. */\n poofHold: 0,\n // /**\n // * How fast the fall back down goes, and its curve. Speeds are in lift per\n // * second: a full drop from upright (1) to flat (0) takes 1 ÷ speed seconds,\n // * and a shorter drop takes proportionally less.\n // */\n // poofFallSpeed: 1.45,\n // poofFallEase: \"gravity\" as Ease,\n /** How strongly the pointer brushes the hairs. */\n brush: 1.05,\n /** How brushed hairs spring back: speed (rad/s) and damping ratio (lower bounces more). */\n brushSpeed: 6,\n brushDamping: 0.32,\n};\ntype Widen<T> = { -readonly [K in keyof T]: T[K] extends number ? number : T[K] };\nexport type FurSettings = Widen<typeof defaultSettings>;\n// The curves' easings, set aside for now with them.\n// export type EaseSetting = \"poofEase\" | \"poofFallEase\" | \"leaveEase\";\nexport type NumericSetting = { [K in keyof FurSettings]: FurSettings[K] extends number ? K : never }[keyof FurSettings];\n\n/** Whether `value` can be `key`'s: a finite number for a number setting, or one of its choices. */\nexport function isSettingValue(key: keyof FurSettings, value: unknown): boolean {\n if (!(key in defaultSettings)) return false;\n if (typeof defaultSettings[key] === \"number\") return typeof value === \"number\" && Number.isFinite(value);\n const choices = (settingChoices as Record<string, readonly string[]>)[key];\n return typeof value === \"string\" && (!choices || choices.includes(value));\n}\n\n/** Settings that change the hairs themselves, so the fur is grown again when they change. */\nexport const regrowSettings: ReadonlySet<keyof FurSettings> = new Set<keyof FurSettings>([\n \"density\", \"curl\", \"lengthVariation\", \"messiness\", \"fuzz\", \"distance\",\n \"sheen\", \"sheenPosition\", \"sheenSpread\", \"edgeShadow\",\n // These two size the canvas margin the hairs can reach into.\n \"hoverStretch\", \"clickStretch\",\n]);\n\n/** Named starting points for the settings, most related first. The first, Plush, is the default. */\nconst presetSettings = {\n // Most related first, from Plush (the default) out to long hair; then the fun ones.\n /** Dense, short, neat fur with a springy click. */\n Plush: { ...defaultSettings },\n /** Sparse, thick, glossy strands, with a smooth hover that brightens, a slight bounce as it leaves and a soft, bouncy click that darkens. */\n Teddy: {\n ...defaultSettings,\n shift: -0.27,\n darker: 0.2,\n lighter: 0.22,\n density: 0.8,\n length: 0.4,\n thickness: 2.05,\n curl: 0.25,\n droop: 0,\n lengthVariation: 1,\n messiness: 2.5,\n fuzz: 0,\n distance: 0,\n taper: 0.58,\n sheen: 1.3,\n sheenPosition: 0.3,\n sheenSpread: 0.59,\n edgeShadow: 0.31,\n vividness: 0,\n static: 0,\n hover: 0.34,\n hoverSpeed: 22,\n hoverDamping: 0.95,\n leaveSpeed: 15,\n leaveDamping: 0.55,\n // leaveFallSpeed: 0.8,\n // leaveEase: \"ease-out\",\n // leaveSettle: 3.7,\n // leaveBounce: 0,\n sway: 0.14,\n hoverStretch: 0,\n hoverLight: 0.09,\n poofHeight: 0.29,\n clickStretch: 0.37,\n clickLight: -0.1,\n clickRiseSpeed: 22,\n clickRiseDamping: 0.75,\n clickFallSpeed: 11,\n clickFallDamping: 0.4,\n // poofRise: 0.15,\n // poofSettle: 11.7,\n // poofBounce: 0,\n // poofEase: \"ease-out\",\n poofHold: 0,\n // poofFallSpeed: 1.35,\n // poofFallEase: \"ease-out\",\n brush: 1.05,\n brushSpeed: 6,\n brushDamping: 0.32,\n },\n /** Curly, messy fur that stands up on its own, with a springy, rippling hover and click. */\n Fluffy: {\n ...defaultSettings,\n shift: -0.18,\n darker: 0.31,\n lighter: 0.17,\n density: 1,\n length: 0.95,\n thickness: 0.8,\n curl: 0.9,\n droop: 0,\n lengthVariation: 2,\n messiness: 1.35,\n fuzz: 0,\n distance: 0,\n taper: 0.31,\n sheen: 2.5,\n sheenPosition: 0.71,\n sheenSpread: 0.23,\n edgeShadow: 0,\n vividness: 0,\n static: 0.6,\n hover: 0.1,\n hoverSpeed: 26.5,\n hoverDamping: 0.45,\n leaveSpeed: 14,\n leaveDamping: 0.45,\n // leaveFallSpeed: 1.3,\n // leaveEase: \"gravity\",\n // leaveSettle: 3.2,\n // leaveBounce: 6,\n sway: 0.14,\n hoverStretch: 0.1,\n hoverLight: 0.07,\n poofHeight: 0.55,\n clickStretch: 0.34,\n clickLight: -0.08,\n clickRiseSpeed: 49,\n clickRiseDamping: 0.9,\n clickFallSpeed: 9,\n clickFallDamping: 0.3,\n // poofRise: 0.13,\n // poofSettle: 3.3,\n // poofBounce: 10,\n // poofEase: \"ease-out\",\n poofHold: 0,\n // poofFallSpeed: 1.2,\n // poofFallEase: \"gravity\",\n brush: 2.2,\n brushSpeed: 14.5,\n brushDamping: 0.3,\n },\n /** Long, thick, curly, heavily drooping fur set deep into the button, with sharp tips, a little shine and a quick, bouncy hover that stretches it. */\n Fuzzy: {\n ...defaultSettings,\n shift: -0.17,\n darker: 0.7,\n lighter: 0.13,\n density: 0.55,\n length: 1.1,\n thickness: 2.5,\n curl: 1.4,\n droop: 2.55,\n lengthVariation: 2.5,\n messiness: 1,\n fuzz: 2,\n distance: -10,\n taper: 0.21,\n hairType: \"curly\",\n typeAmount: 0.15,\n tightness: 1.2,\n tipShape: \"sharp\",\n sheen: 1.5,\n sheenPosition: 0.24,\n sheenSpread: 0.29,\n edgeShadow: 0.41,\n vividness: 1,\n static: 0.58,\n hover: 0.06,\n hoverSpeed: 25.5,\n hoverDamping: 0.2,\n leaveSpeed: 7,\n leaveDamping: 0.2,\n // leaveFallSpeed: 0.35,\n // leaveEase: \"gravity\",\n // leaveSettle: 1,\n // leaveBounce: 5.5,\n sway: 0.23,\n hoverStretch: 0.23,\n hoverLight: 0.05,\n poofHeight: 0.12,\n clickStretch: 0,\n clickLight: -0.11,\n clickRiseSpeed: 35.5,\n clickRiseDamping: 0.9,\n clickFallSpeed: 8,\n clickFallDamping: 0.2,\n // poofRise: 0.15,\n // poofSettle: 3.1,\n // poofBounce: 15,\n // poofEase: \"ease-out\",\n poofHold: 0,\n // poofFallSpeed: 1,\n // poofFallEase: \"gravity\",\n brush: 0.45,\n brushSpeed: 4.5,\n brushDamping: 0.45,\n },\n /** Thin, long, curly, droopy hair with lots of shine and a softer click. */\n Shaggy: {\n ...defaultSettings,\n shift: -0.12,\n darker: 0.4,\n lighter: 0.22,\n density: 1.25,\n length: 0.95,\n thickness: 0.3,\n curl: 1.7,\n droop: 2.05,\n lengthVariation: 1.4,\n messiness: 2.3,\n fuzz: 2,\n taper: 1,\n sheen: 4,\n sheenPosition: 0.21,\n sheenSpread: 0.05,\n edgeShadow: 0.47,\n static: 0,\n hover: 0.34,\n hoverSpeed: 7.5,\n hoverDamping: 0.5,\n leaveSpeed: 6,\n leaveDamping: 0.25,\n // leaveFallSpeed: 1.15,\n // leaveEase: \"gravity\",\n // leaveSettle: 1.4,\n // leaveBounce: 5.5,\n sway: 0.05,\n hoverStretch: 0,\n hoverLight: 0,\n poofHeight: 0.19,\n clickStretch: 0,\n clickRiseSpeed: 49.5,\n clickRiseDamping: 0.9,\n clickFallSpeed: 8.5,\n clickFallDamping: 0.3,\n // poofRise: 0.16,\n // poofSettle: 2.5,\n // poofBounce: 7.5,\n // poofEase: \"ease-in-out\",\n poofHold: 0.06,\n // poofFallSpeed: 0.9,\n // poofFallEase: \"gravity\",\n brush: 1.05,\n brushSpeed: 4.5,\n brushDamping: 0.32,\n },\n /** Long, sparse, messy, gently wavy strands with a bright band of shine along the top, a bouncy hover, and barely react to a click. */\n Mane: {\n ...defaultSettings,\n shift: -0.15,\n darker: 1,\n lighter: 0.26,\n density: 0.7,\n length: 2.22,\n thickness: 1,\n curl: 0.25,\n droop: 0,\n lengthVariation: 1,\n messiness: 2.2,\n fuzz: 0,\n taper: 0.32,\n hairType: \"wavy\",\n typeAmount: 0.15,\n tightness: 0.95,\n sheen: 2.3,\n sheenPosition: 0,\n sheenSpread: 0.06,\n edgeShadow: 0.3,\n vividness: 0,\n static: 0.19,\n hover: 0.17,\n hoverSpeed: 20.5,\n hoverDamping: 0.3,\n leaveSpeed: 6,\n leaveDamping: 0.8,\n // leaveFallSpeed: 0.9,\n // leaveEase: \"gravity\",\n // leaveSettle: 4.1,\n // leaveBounce: 3,\n sway: 0.05,\n hoverStretch: 0.1,\n hoverLight: 0,\n poofHeight: 0.17,\n clickStretch: 0.05,\n clickRiseSpeed: 58,\n clickRiseDamping: 0.75,\n clickFallSpeed: 9.5,\n clickFallDamping: 0.25,\n // poofRise: 0.11,\n // poofSettle: 3.1,\n // poofBounce: 15,\n // poofEase: \"ease-out\",\n poofHold: 0,\n // poofFallSpeed: 1.35,\n // poofFallEase: \"gravity\",\n brush: 0.45,\n brushSpeed: 6.5,\n brushDamping: 0.6,\n },\n /** Sparse, thick, very messy glittering curls with square ends set into the button, like tinsel, with slow, gentle motion that darkens on hover and click. */\n Tinsel: {\n ...defaultSettings,\n shift: -0.3,\n darker: 1,\n lighter: 0.34,\n density: 0.25,\n length: 1.3,\n thickness: 2.9,\n curl: 1.45,\n droop: 0.7,\n lengthVariation: 0.9,\n messiness: 3,\n fuzz: 0,\n distance: -6,\n taper: 1,\n typeAmount: 0.85,\n tightness: 3,\n tipShape: \"square\",\n material: \"glitter\",\n materialAmount: 2,\n glitterDensity: 2.75,\n glitterSize: 0.25,\n glitterSizeVariation: 0.85,\n sheen: 1.1,\n sheenPosition: 0.23,\n sheenSpread: 0.35,\n edgeShadow: 0.44,\n vividness: 1,\n static: 0.42,\n hover: 0.05,\n hoverSpeed: 22,\n hoverDamping: 0.5,\n leaveSpeed: 38.5,\n leaveDamping: 0.9,\n // leaveFallSpeed: 0.4,\n // leaveEase: \"ease-in-out\",\n // leaveSettle: 1.4,\n // leaveBounce: 5.5,\n sway: 0.05,\n hoverStretch: 0.32,\n hoverLight: -0.08,\n poofHeight: 0.23,\n clickStretch: 0,\n clickLight: -0.15,\n clickRiseSpeed: 28.5,\n clickRiseDamping: 0.9,\n clickFallSpeed: 8.5,\n clickFallDamping: 0.9,\n // poofRise: 0.17,\n // poofSettle: 2.5,\n // poofBounce: 3,\n // poofEase: \"ease-in-out\",\n poofHold: 0,\n // poofFallSpeed: 0.3,\n // poofFallEase: \"ease-out\",\n brush: 0.3,\n brushSpeed: 3.5,\n brushDamping: 0.65,\n },\n /** A few thick, tightly curled, pointed strands that spring up on hover and stretch out on a click. */\n Coil: {\n ...defaultSettings,\n shift: 0,\n darker: 0.15,\n lighter: 0.12,\n density: 0.2,\n length: 0.5,\n thickness: 2,\n curl: 2.25,\n droop: 0,\n lengthVariation: 2,\n messiness: 1.9,\n fuzz: 0,\n distance: 0,\n taper: 1,\n sheen: 0.6,\n sheenPosition: 0.38,\n sheenSpread: 0.65,\n edgeShadow: 0.48,\n vividness: 1,\n static: 0.58,\n hover: 1,\n hoverSpeed: 28,\n hoverDamping: 0.55,\n leaveSpeed: 9,\n leaveDamping: 0.9,\n // leaveFallSpeed: 0.6,\n // leaveEase: \"ease-out\",\n // leaveSettle: 4.1,\n // leaveBounce: 3,\n sway: 0.3,\n hoverStretch: 1.35,\n hoverLight: 0.05,\n poofHeight: 1,\n clickStretch: 0.86,\n clickLight: -0.04,\n clickRiseSpeed: 41.5,\n clickRiseDamping: 0.7,\n clickFallSpeed: 11.5,\n clickFallDamping: 0.3,\n // poofRise: 0.12,\n // poofSettle: 4.6,\n // poofBounce: 9.5,\n // poofEase: \"ease-out\",\n poofHold: 0.05,\n // poofFallSpeed: 1.9,\n // poofFallEase: \"ease-out\",\n brush: 0.75,\n brushSpeed: 8,\n brushDamping: 1.05,\n },\n /** Long, thin, glossy, loosely wavy hairs with sharp ends that droop heavily from just inside the button, with a quick, bouncy hover and click and a light brush. */\n Mustache: {\n ...defaultSettings,\n shift: -0.07,\n darker: 0.28,\n lighter: 0.29,\n density: 0.8,\n length: 0.85,\n thickness: 0.65,\n curl: 0.05,\n droop: 3.35,\n lengthVariation: 1.15,\n messiness: 1.05,\n fuzz: 0.65,\n distance: -5,\n taper: 0.36,\n hairType: \"wavy\",\n typeAmount: 1.45,\n tightness: 0.2,\n tipShape: \"sharp\",\n materialAmount: 0.6,\n glitterSize: 0.6,\n glitterSizeVariation: 1.1,\n sheen: 2.8,\n sheenPosition: 0.28,\n sheenSpread: 0.26,\n edgeShadow: 0.63,\n vividness: 0,\n static: 0,\n hover: 0.1,\n hoverSpeed: 21,\n hoverDamping: 0.3,\n leaveSpeed: 12.5,\n leaveDamping: 0.9,\n // leaveFallSpeed: 0.2,\n // leaveEase: \"ease-out\",\n // leaveSettle: 1.6,\n // leaveBounce: 0,\n sway: 0.25,\n hoverStretch: 0.95,\n hoverLight: 0.04,\n poofHeight: 0.25,\n clickStretch: 0.09,\n clickLight: -0.1,\n clickRiseSpeed: 55.5,\n clickRiseDamping: 0.65,\n clickFallSpeed: 17,\n clickFallDamping: 0.35,\n // poofRise: 0.09,\n // poofSettle: 1,\n // poofBounce: 0,\n // poofEase: \"ease-in-out\",\n poofHold: 0,\n // poofFallSpeed: 0.2,\n // poofFallEase: \"ease-out\",\n brush: 0.15,\n brushSpeed: 3,\n brushDamping: 0.7,\n },\n /** Sparse, thick, drooping bristles with square ends that stand up on their own, a quick hover, a high, snappy click and a strong brush. */\n Bristle: {\n ...defaultSettings,\n shift: -0.13,\n darker: 0.4,\n lighter: 0.22,\n density: 0.3,\n length: 0.71,\n thickness: 1.65,\n curl: 1.05,\n droop: 1.8,\n lengthVariation: 0.7,\n messiness: 1,\n fuzz: 2,\n distance: 0,\n taper: 1,\n typeAmount: 1.45,\n tightness: 0.6,\n tipShape: \"square\",\n sheen: 0.1,\n sheenPosition: 0.1,\n sheenSpread: 0.32,\n edgeShadow: 0,\n vividness: 0,\n static: 0.86,\n hover: 0.07,\n hoverSpeed: 27,\n hoverDamping: 0.9,\n leaveSpeed: 7,\n leaveDamping: 0.25,\n sway: 0.11,\n hoverStretch: 0.16,\n hoverLight: 0.07,\n poofHeight: 1,\n clickStretch: 0.1,\n clickLight: 0,\n clickRiseSpeed: 53,\n clickRiseDamping: 0.9,\n clickFallSpeed: 27.5,\n clickFallDamping: 0.4,\n poofHold: 0,\n brush: 2.35,\n brushSpeed: 13.5,\n brushDamping: 0.8,\n },\n\n // Velvet is set aside for now. To bring it back, uncomment it and its\n // big-button scale (1.2) in the playground's presetBigScale.\n // /** Very short, thick, neat pile that grows out long when hovered or clicked. */\n // Velvet: {\n // ...defaultSettings,\n // shift: 0,\n // darker: 0.37,\n // lighter: 0.12,\n // density: 0.8,\n // length: 0.15,\n // thickness: 2.2,\n // curl: 0.25,\n // droop: 0,\n // lengthVariation: 1,\n // messiness: 0,\n // fuzz: 0,\n // taper: 0.32,\n // sheen: 1.2,\n // sheenPosition: 0.04,\n // sheenSpread: 0.52,\n // edgeShadow: 0.21,\n // vividness: 0.38,\n // static: 0.32,\n // hover: 0.68,\n // hoverSpeed: 12.5,\n // hoverDamping: 0.45,\n // leaveFallSpeed: 0.9,\n // leaveEase: \"gravity\",\n // leaveSettle: 4.1,\n // leaveBounce: 3,\n // sway: 0.14,\n // hoverStretch: 0.83,\n // hoverLight: 0,\n // poofHeight: 1.29,\n // clickStretch: 0.59,\n // poofRise: 0.11,\n // poofSettle: 3.1,\n // poofBounce: 15,\n // poofEase: \"ease-out\",\n // poofHold: 0,\n // poofFallSpeed: 1.35,\n // poofFallEase: \"gravity\",\n // brush: 2.6,\n // brushSpeed: 3,\n // brushDamping: 0.6,\n // },\n};\n\nexport type PresetName = Lowercase<keyof typeof presetSettings>;\n/** Named starting points for the settings, by id. The first, Plush, is the default. */\nexport const presets = Object.fromEntries(\n Object.entries(presetSettings).map(([name, settings]) => [name.toLowerCase(), settings as FurSettings]),\n) as Record<PresetName, Readonly<FurSettings>>;\n/** Each preset's display name, by id, in order. */\nexport const presetNames = Object.fromEntries(\n Object.keys(presetSettings).map((name) => [name.toLowerCase(), name]),\n) as Record<PresetName, string>;\n","import { apca, fromLightness, fromOklab, lightness, toOklab } from \"./color\";\nimport { createLayer, hairFloats, maxGlitterDensity, rampRows, rampWidth, type BufferGamut, type Frame } from \"./gl\";\n// The curves' easings, set aside for now: every motion springs.\n// import { easeInverse, eases, regrowSettings, type FurSettings } from \"./settings\";\nimport { regrowSettings, settingChoices, type FurSettings, type Pattern } from \"./settings\";\n\n/*\n Fur for one element, on a canvas behind its label, in the fur's color: a\n little darker in the shadows and between hairs, lighter where the light\n catches the tips. From huet's demo/fur/fur.ts.\n\n The hairs grow here, on the CPU, once; the springs, brushing and colors\n are worked out here each frame. The GPU draws them (see gl.ts).\n\n Cost: an element is a cached frame until it's hovered. Only the hovered\n element animates, so the live budget is one element at a time.\n*/\n\n/** How far, in CSS px, the fur can reach past the element's box, at a scale of 1. */\nconst halo = 32;\n/** The font size, in CSS px, at which an `em` scale of 1 is a scale of 1. */\nconst emBase = 16;\n/**\n * A `scale` option or `--hairy-scale` value as a number: a number as it is,\n * and \"1.5em\" as 1.5 × the element's font size over 16px. Undefined for\n * anything else, and for 0, which draws nothing.\n */\nfunction scaleOf(value: number | string | undefined, fontSize: number) {\n if (typeof value === \"number\") return value;\n const n = parseFloat(value ?? \"\");\n if (!n) return undefined;\n return /^\\s*[\\d.eE+-]+em\\s*$/.test(value!) ? (n * fontSize) / emBase : n;\n}\n\n/** Lightness steps in the palette, and in the sheen's. */\nconst levels = 24;\nconst sheenLevels = 4;\n\n// Browser-only lookups, made on first use so the module can be imported on a server.\nlet reduceMotionQuery: MediaQueryList | undefined;\nlet wideScreenQuery: MediaQueryList | undefined;\nconst reduceMotion = () => (reduceMotionQuery ??= matchMedia(\"(prefers-reduced-motion: reduce)\")).matches;\nconst wideScreen = () => (wideScreenQuery ??= matchMedia(\"(color-gamut: p3)\")).matches;\n/** Whether this screen can show wide-gamut (Display P3) color. */\nexport const supportsWideGamut = () => typeof matchMedia === \"function\" && wideScreen();\n\n// Reads any CSS color as hex by drawing it.\nlet probe: CanvasRenderingContext2D | undefined;\nexport function hexOf(css: string) {\n probe ??= document.createElement(\"canvas\").getContext(\"2d\", { willReadFrequently: true })!;\n probe.clearRect(0, 0, 1, 1);\n probe.fillStyle = \"#000\";\n probe.fillStyle = css;\n probe.fillRect(0, 0, 1, 1);\n const [r, g, b] = probe.getImageData(0, 0, 1, 1).data;\n return \"#\" + [r, g, b].map((v) => v.toString(16).padStart(2, \"0\")).join(\"\");\n}\n\ntype Lab = [number, number, number];\ntype Gamut = \"srgb\" | \"display-p3\";\n\n/**\n * The color's hue at L* `L` (0–1), with `saturation` times its chroma (1 is\n * the color's own) around `middle`. Shadows get slightly more chroma, as color pools in the shade, and\n * highlights keep nearly all of it, so the light doesn't wash the fur out.\n * Yellows warm toward orange in the shade instead of going olive, as yellow\n * fur does. Colors past sRGB lose chroma to fit.\n */\nfunction shadeOf(color: string, L: number, middle: number, saturation: number): Lab {\n const [, a, b] = toOklab(color);\n const depth = clamp((middle - L) / 0.2, 0, 1);\n const k = saturation * (L < middle ? 1 + 0.6 * (middle - L) : 1);\n let hue = Math.atan2(b, a);\n const degrees = (hue * 180) / Math.PI;\n if (degrees > 60 && degrees < 125) hue -= ((22 * Math.PI) / 180) * depth * smoothstep(125, 95, degrees);\n const chroma = Math.hypot(a, b) * k;\n return [fromLightness(clamp(L, 0, 1)), chroma * Math.cos(hue), chroma * Math.sin(hue)];\n}\n\n/** OKLab to linear-light sRGB, unclamped, so colors past sRGB come out below 0 or above 1. */\nfunction linearSrgb([L, a, b]: Lab): Lab {\n const l = (L + 0.3963377774 * a + 0.2158037573 * b) ** 3;\n const m = (L - 0.1055613458 * a - 0.0638541728 * b) ** 3;\n const s = (L - 0.0894841775 * a - 1.291485548 * b) ** 3;\n return [\n 4.0767416621 * l - 3.3077115913 * m + 0.2309699292 * s,\n -1.2684380046 * l + 2.6097574011 * m - 0.3413193965 * s,\n -0.0041960863 * l - 0.7034186147 * m + 1.707614701 * s,\n ];\n}\n/** Linear sRGB to linear Display P3. */\nconst linearP3 = ([r, g, b]: Lab): Lab => [\n 0.8224621 * r + 0.177538 * g,\n 0.0331941 * r + 0.9668058 * g,\n 0.0170827 * r + 0.0723974 * g + 0.9105199 * b,\n];\nconst linearIn = (lab: Lab, gamut: Gamut) => (gamut === \"srgb\" ? linearSrgb(lab) : linearP3(linearSrgb(lab)));\nconst fitsIn = (lab: Lab, gamut: Gamut) => linearIn(lab, gamut).every((v) => v >= -1e-6 && v <= 1 + 1e-6);\n/** The most chroma a lightness and hue can have in a gamut, as a fraction of `lab`'s chroma (0 if none). */\nfunction room(lab: Lab, gamut: Gamut) {\n if (Math.hypot(lab[1], lab[2]) < 1e-5) return 1;\n let lo = 0, hi = 4;\n for (let i = 0; i < 18; i++) {\n const mid = (lo + hi) / 2;\n if (fitsIn([lab[0], lab[1] * mid, lab[2] * mid], gamut)) lo = mid;\n else hi = mid;\n }\n return lo;\n}\nconst encode = (v: number) => (v <= 0.0031308 ? 12.92 * v : 1.055 * v ** (1 / 2.4) - 0.055);\n\n/**\n * An OKLab color as gamma-encoded channels (0–1) in `buffer`'s color space,\n * fitted to `gamut` first. On a wide gamut, `vivid` (0–1) moves its chroma\n * out toward the wider gamut's edge as far as it is toward sRGB's, so a vivid\n * sRGB color becomes as vivid as the screen can show. Colors past the gamut\n * lose chroma to fit.\n */\nfunction encodeIn(lab: Lab, gamut: Gamut, vivid: number, buffer: BufferGamut): Lab {\n let c = lab;\n if (gamut !== \"srgb\" && vivid > 0) {\n const spread = room(c, gamut) / Math.max(1e-3, room(c, \"srgb\"));\n const k = 1 + clamp(vivid, 0, 1) * (Math.min(spread, 3) - 1);\n if (k > 1) c = [c[0], c[1] * k, c[2] * k];\n }\n const fit = room(c, gamut);\n if (fit < 1) c = [c[0], c[1] * fit, c[2] * fit];\n const [r, g, b] = linearIn(c, buffer);\n return [encode(clamp(r, 0, 1)), encode(clamp(g, 0, 1)), encode(clamp(b, 0, 1))];\n}\n\nfunction rng(seed: number) {\n return () => {\n seed |= 0;\n seed = (seed + 0x6d2b79f5) | 0;\n let t = Math.imul(seed ^ (seed >>> 15), 1 | seed);\n t = (t + Math.imul(t ^ (t >>> 7), 61 | t)) ^ t;\n return ((t ^ (t >>> 14)) >>> 0) / 4294967296;\n };\n}\n\nconst clamp = (v: number, lo: number, hi: number) => Math.min(hi, Math.max(lo, v));\nconst smoothstep = (a: number, b: number, x: number) => {\n const t = clamp((x - a) / (b - a), 0, 1);\n return t * t * (3 - 2 * t);\n};\n\n/**\n * Where the fur's middle shade sits, and how far its palette reaches, for a\n * color lightened by `light` (L*, 0–1). Level `u` 0.6 of the way up is the\n * middle, so most of the fur reads as the color.\n */\nfunction bandOf(color: string, S: FurSettings, light: number) {\n const Ls = lightness(color);\n const middle = clamp(Ls + S.shift + light, 0.05, 0.95);\n const low = Math.max(0.02, middle - S.darker), high = Math.min(0.97, middle + S.lighter);\n const at = (u: number) => (u < 0.6 ? middle - ((0.6 - u) / 0.6) * (middle - low) : middle + ((u - 0.6) / 0.4) * (high - middle));\n return { middle, high, at };\n}\n\n/** The shades most hairs take (levels 0.35 to 0.85), at rest and fully hovered, as hex. */\nfunction labelShades(color: string, S: FurSettings) {\n const shades: string[] = [];\n for (const light of [0, S.hoverLight]) {\n const { middle, at } = bandOf(color, S, light);\n for (const u of [0.35, 0.6, 0.85]) shades.push(fromOklab(shadeOf(color, at(u), middle, 1)));\n }\n return shades;\n}\n/** The label's lowest APCA contrast (unsigned Lc) over the shades most hairs take. */\nexport function labelContrast(label: string, color: string, S: FurSettings) {\n return Math.min(...labelShades(color, S).map((shade) => Math.abs(apca(label, shade))));\n}\n\n/** The Lc a label should reach: 60 for large or bold text, 75 otherwise. */\nconst labelTarget = (text: { size: number; weight: number }) => (text.size >= 24 || (text.size >= 16 && text.weight >= 600) ? 60 : 75);\n\n/**\n * A label color that reads on `color`'s fur, by APCA, and its contrast: the\n * lowest Lc over the shades most hairs take, at rest and fully hovered. It\n * prefers a light or dark tint of the fur's own hue, when that reaches the\n * target Lc, and otherwise takes whichever of the tints, white or black reads\n * best. The target is Lc 60 for large or bold text and Lc 75 otherwise.\n */\nexport function autoLabel(color: string, S: FurSettings, text: { size: number; weight: number } = { size: 16, weight: 700 }) {\n return pickLabel(labelShades(color, S), color, labelTarget(text));\n}\n\n/** `autoLabel` over any `shades`, with tints of `color`'s hue. */\nfunction pickLabel(shades: string[], color: string, target: number) {\n const worst = (label: string) => Math.min(...shades.map((shade) => Math.abs(apca(label, shade))));\n const [, a, b] = toOklab(color);\n const chroma = Math.hypot(a, b), hue = Math.atan2(b, a);\n const tint = (L: number, c: number) => fromOklab([fromLightness(L), c * Math.cos(hue), c * Math.sin(hue)]);\n const tints = chroma > 0.02 ? [tint(0.96, Math.min(chroma, 0.035)), tint(0.16, Math.min(chroma, 0.05))] : [];\n const scored = (list: string[]) => list.map((label) => ({ label, lc: worst(label) })).sort((x, y) => y.lc - x.lc);\n const [bestTint] = scored(tints);\n if (bestTint && bestTint.lc >= target) return bestTint;\n return scored([...tints, \"#ffffff\", \"#000000\"])[0];\n}\n\n/** The coat's distinct colors: the ground, then a pattern's markings and third color. */\nconst coatColors = (coat: ReturnType<typeof coatOf>) => [...new Set([coat.ground, coat.marks, coat.third])];\n\n/**\n * How the label reads on the fur: its color, and the halo behind it.\n *\n * On auto, a pattern is checked whole: if one label reads on the ground and\n * the markings alike, it's used bare. If none does (black on a zebra's white\n * vanishes into its stripes), the label is picked for the coat's main color,\n * and a halo in that main color, shaded away from the label, backs each letter.\n */\nexport function labelLook(\n coat: ReturnType<typeof coatOf>,\n S: FurSettings,\n label: string | undefined,\n own: string,\n text: { size: number; weight: number },\n) {\n const target = labelTarget(text);\n const colors = coatColors(coat);\n const shades = colors.flatMap((color) => labelShades(color, S));\n let color: string;\n if (label === \"auto\") {\n const whole = pickLabel(shades, coat.label, target);\n color = whole.lc >= target || colors.length === 1 ? whole.label : pickLabel(labelShades(coat.label, S), coat.label, target).label;\n } else color = label ?? own;\n const bare = Math.min(...shades.map((shade) => Math.abs(apca(color, shade))));\n const halo = S.haloStrength > 0 && (S.halo === \"always\" || (S.halo === \"auto\" && colors.length > 1 && bare < target));\n if (!halo) return { color, contrast: bare, halo, shadow: \"\" };\n const backing = haloOf(coat.label, color, S.haloShade);\n return {\n color,\n // The halo backs every letter, so the label reads against it.\n contrast: Math.max(bare, Math.abs(apca(color, backing))),\n halo,\n shadow: haloShadow(backing, S.haloSize, S.haloStrength),\n };\n}\n\n/** The halo's color behind `label`: `base`, `shade` (L, 0–1) darker under a light label, or lighter under a dark one. */\nfunction haloOf(base: string, label: string, shade: number) {\n const [L, a, b] = toOklab(base);\n const step = lightness(label) > lightness(base) ? shade : -shade;\n return fromOklab([clamp(L - step, 0, 1), a, b]);\n}\n\n/**\n * The halo as a CSS `text-shadow`, in `color`: a thin, crisp edge hugging\n * the letters, so they stay sharp, then a glow fading out wide into the fur.\n * `size` spreads the glow, `strength` scales how opaque it is. In em, so it\n * follows the font size.\n */\nfunction haloShadow(color: string, size: number, strength: number) {\n const [r, g, b] = [1, 3, 5].map((i) => parseInt(color.slice(i, i + 2), 16));\n const alpha = (a: number) => `rgb(${r} ${g} ${b} / ${+Math.min(1, a * strength).toFixed(3)})`;\n // Text shadows don't spread, so the edge is a ring of copies, moved out a\n // little all round.\n const edge = Array.from({ length: 12 }, (_, i) => {\n const angle = (i / 12) * Math.PI * 2;\n return `${(Math.cos(angle) * 0.03).toFixed(3)}em ${(Math.sin(angle) * 0.03).toFixed(3)}em 0.01em ${alpha(1)}`;\n });\n const glow = ([blur, a]: [number, number]) => `0 0 ${+(blur * size).toFixed(3)}em ${alpha(a)}`;\n return [...edge, ...([[0.35, 0.7], [0.6, 0.45], [0.95, 0.25]] as [number, number][]).map(glow)].join(\", \");\n}\n\n/**\n * Each pattern's coat in nature, as hex: the ground, the markings, and a\n * third color on top (the tawny middles of a leopard's rosettes, the darker\n * middles of a giraffe's patches). `own` is the color the fur's takes the\n * place of when the pattern is tinted: most of the coat, or on a giraffe,\n * the patches.\n */\nconst coats: Record<Exclude<Pattern, \"none\">, { ground: string; marks: string; third: string; own: \"ground\" | \"marks\" }> = {\n zebra: { ground: \"#eeeae1\", marks: \"#17140f\", third: \"#eeeae1\", own: \"ground\" },\n tiger: { ground: \"#d4701c\", marks: \"#1b110a\", third: \"#d4701c\", own: \"ground\" },\n dalmatian: { ground: \"#f2efe7\", marks: \"#1c1a18\", third: \"#f2efe7\", own: \"ground\" },\n leopard: { ground: \"#d9a85c\", marks: \"#21170f\", third: \"#a9661f\", own: \"ground\" },\n giraffe: { ground: \"#ecdcb8\", marks: \"#91501f\", third: \"#673312\", own: \"marks\" },\n};\n\n/**\n * The colors the fur is drawn in: its ground (most of it), and a pattern's\n * markings and third color, as hex. With no pattern, all three are `color`.\n * Tinted, they're `color`'s hue at the lightness the animal's own are from\n * the color `color` stands in for, so the stripes stay dark and a giraffe's\n * lines light, in any color.\n */\nexport function coatOf(color: string, S: FurSettings) {\n if (S.pattern === \"none\" || !(S.pattern in coats)) return { ground: color, marks: color, third: color, label: color };\n const coat = coats[S.pattern];\n if (S.patternColors !== \"tinted\") return { ...coat, label: coat[coat.own] };\n const from = lightness(coat[coat.own]), base = lightness(color);\n const tint = (hex: string) => {\n const L = clamp(base + lightness(hex) - from, 0.03, 0.97);\n // Far from the color's own lightness, a little less of its chroma, as fur goes grey toward black and white.\n return fromOklab(shadeOf(color, L, L, 1 - 0.6 * smoothstep(0.15, 0.6, Math.abs(L - base))));\n };\n const pick = (key: \"ground\" | \"marks\" | \"third\") => (key === coat.own ? color : tint(coat[key]));\n return { ground: pick(\"ground\"), marks: pick(\"marks\"), third: pick(\"third\"), label: color };\n}\n\ninterface Strands {\n n: number;\n /** Each hair's root, x then y, in drawing order: what brushing needs. */\n roots: Float32Array;\n}\n\n/**\n * How far the pointer has brushed each hair and how fast that's changing, x\n * then y per hair. Made on the first brush and dropped once the hairs settle,\n * so fur that isn't being brushed holds none.\n */\ninterface Brush {\n /** The bends, as the GPU takes them. */\n bends: Float32Array;\n speeds: Float32Array;\n}\n\n/**\n * Grows hairs over a w × h rounded rectangle, offset by `pad` for the canvas\n * margin. At a `scale` of 2 the hairs are twice as long and thick, and there\n * are fewer per area, so each one shows.\n */\nfunction grow(w: number, h: number, radius: number, seed: number, scale: number, pad: number, S: FurSettings): Strands & { data: Float32Array } {\n const random = rng(seed);\n const cx = w / 2, cy = h / 2, r = Math.min(radius, w / 2, h / 2);\n // Signed distance to the rounded rectangle: negative inside.\n const sdf = (x: number, y: number) => {\n const qx = Math.abs(x - cx) - (w / 2 - r), qy = Math.abs(y - cy) - (h / 2 - r);\n return Math.hypot(Math.max(qx, 0), Math.max(qy, 0)) + Math.min(Math.max(qx, qy), 0) - r;\n };\n // The fur's outline, moved out (or in) from the element's by `distance`.\n const off = S.distance * scale, reach = Math.max(0, off);\n const max = Math.max(0, Math.round(((w * h) / scale ** 1.6 + ((w + h) * 7) / scale) * S.density));\n const f = () => new Float32Array(max);\n const s = {\n x: f(), y: f(), restX: f(), restY: f(), leanX: f(), leanY: f(), standX: f(), standY: f(),\n len: f(), curl: f(), phase: f(), rim: f(),\n };\n const shadeLevel = f(), kindOf = f(), seedOf = f();\n // Each hair's seed for its waves, coils, frizz and glitter, from its own\n // sequence, so the hairs grow where they always have.\n const seedRandom = rng(seed ^ 0x5bd1e995);\n const lists: number[][][] = [0, 1].map(() => Array.from({ length: levels }, () => []));\n const sheen: number[][] = Array.from({ length: sheenLevels }, () => []);\n let n = 0;\n for (let tries = 0; n < max && tries < max * 4; tries++) {\n const x = random() * (w + 4 + reach * 2) - 2 - reach, y = random() * (h + 4 + reach * 2) - 2 - reach;\n const d = sdf(x, y) - off;\n if (d > 0.5) continue;\n const rim = smoothstep(-9 * scale, 0, d);\n // Denser along the outline, where the fuzz shows.\n if (random() > 0.4 + 0.6 * rim) continue;\n const gx = sdf(x + 0.5, y) - sdf(x - 0.5, y), gy = sdf(x, y + 0.5) - sdf(x, y - 0.5);\n const g = Math.hypot(gx, gy) || 1;\n const outX = gx / g, outY = gy / g;\n // Hairs lie along the surface, combed away from the middle and down: the\n // part of \"outward and down\" that runs along the surface. On top they flow\n // sideways, on the ends and bottom they hang, and in the top middle they\n // lie down rather than stand up. Mirrored across the middle.\n const fromX = x - cx, fromY = y - cy;\n const side = Math.tanh(fromX / (12 * scale));\n const wantX = side * 0.6, wantY = 1;\n const along = wantX * outX + wantY * outY;\n let ax = (wantX - along * outX) * 1.4;\n let ay = (wantY - along * outY) * 1.4 + 0.3;\n const al = Math.hypot(ax, ay) || 1;\n ax /= al; ay /= al;\n const swirl = side * 0.2 * Math.sin((Math.abs(fromX) * 0.05 + y * 0.035) / scale) + 0.5 * S.messiness * (random() - 0.5);\n s.restX[n] = ax * Math.cos(swirl) - ay * Math.sin(swirl);\n s.restY[n] = ax * Math.sin(swirl) + ay * Math.cos(swirl);\n // Outline hairs lean out a little to make the fuzzy edge; least on top, so it doesn't bristle.\n const lean = 0.32 * S.fuzz * rim * (0.25 + 0.75 * smoothstep(-1, 0.2, outY));\n s.leanX[n] = outX * lean; s.leanY[n] = outY * lean;\n const stand = random() * Math.PI * 2;\n const guard = random() < 0.3 + 0.3 * rim ? 1 : 0;\n s.x[n] = x + pad; s.y[n] = y + pad;\n s.standX[n] = outX * rim + Math.cos(stand) * (1 - rim);\n s.standY[n] = outY * rim + Math.sin(stand) * (1 - rim);\n // Average length, plus a random part scaled by `lengthVariation`.\n const vary = (spread: number) => (random() - 0.5) * spread * S.lengthVariation;\n const base = (guard ? 9.5 + vary(5) : 5.5 + vary(3)) + rim * (4 + vary(4));\n // Relative to `length`, which is applied as the hairs are drawn so it can animate.\n s.len[n] = Math.max(1, base) * scale;\n s.curl[n] = (random() * 2 - 1) * (guard ? 0.9 : 0.6) * S.curl;\n s.phase[n] = random() * Math.PI * 2;\n s.rim[n] = rim;\n // Soft light from above: a little lighter on top, a little darker\n // underneath and toward the ends. Guard hairs catch slightly more of it.\n const px = fromX / (w / 2), py = fromY / (h / 2);\n const occlusion = rim * Math.max(0, py) * 0.15;\n // The top edge, where the surface turns away from the light: it can be in\n // shadow, like the rim of a lit ball, rather than catching the shine.\n const topEdge = rim * smoothstep(-0.2, -0.9, outY) * clamp(S.edgeShadow, 0, 1);\n const shade = clamp(0.6 - 0.18 * py - 0.06 * px * px - occlusion - 0.4 * topEdge + (random() - 0.5) * 0.32 + (guard ? 0.06 : -0.08), 0, 1);\n // Sheen: a few hairs catch the light, most in a soft band across the element\n // at `sheenPosition` (0 top, 1 bottom), `sheenSpread` wide, and some along\n // the top edge unless it's in shadow.\n const center = clamp(S.sheenPosition, 0, 1) * 2 - 1, spread = Math.max(0.03, S.sheenSpread);\n const band = Math.exp(-((py - center) ** 2) / (2 * spread * spread));\n const shine = (0.14 * band + 0.04 * smoothstep(0.4, -0.9, py) * rim * (1 - topEdge)) * S.sheen;\n seedOf[n] = seedRandom();\n if (random() < shine) {\n const level = Math.floor(random() * sheenLevels);\n sheen[level].push(n);\n shadeLevel[n] = level / (sheenLevels - 1);\n kindOf[n] = 2;\n } else {\n const level = Math.round(shade * (levels - 1));\n lists[guard][level].push(n);\n shadeLevel[n] = level / (levels - 1);\n kindOf[n] = guard;\n }\n n++;\n }\n // Drawn in order: underfur, then the longer guard hairs, each dark to\n // light, then the few sheen hairs on top.\n const order = [...lists[0].flat(), ...lists[1].flat(), ...sheen.flat()];\n const count = order.length;\n // What the GPU draws each hair from: see gl.ts's attributes.\n const data = new Float32Array(count * hairFloats);\n const roots = new Float32Array(count * 2);\n order.forEach((i, j) => {\n data.set([\n s.x[i], s.y[i], s.restX[i], s.restY[i],\n s.leanX[i], s.leanY[i], s.standX[i], s.standY[i],\n s.len[i], s.curl[i], s.phase[i], s.rim[i],\n shadeLevel[i], kindOf[i], seedOf[i],\n ], j * hairFloats);\n roots[j * 2] = s.x[i];\n roots[j * 2 + 1] = s.y[i];\n });\n return { n: count, roots, data };\n}\n\nexport interface FurConfig {\n settings: FurSettings;\n /** The fur's color as hex, or undefined for the element's own background. */\n color?: string;\n /** \"auto\", a hex color, or undefined to leave the element's color alone. */\n label?: string;\n /** A number, or \"<n>em\" to size the hairs from the element's font size (16px is 1em). */\n scale?: number | `${number}em`;\n /** How far to move the fur down, in CSS px. Defaults to 0. */\n translate?: number;\n /** Canvas pixels per CSS pixel. Defaults to the screen's, up to 2. */\n pixelRatio?: number;\n wideGamut: boolean;\n}\n\nexport type FurMotion = \"hover\" | \"leave\" | \"click\";\n\nexport interface FurLabel {\n color: string;\n /** Unsigned Lc: its lowest over the coat, or against the halo backing it. */\n contrast: number;\n /** Whether a halo backs it: always, never, or on auto, when a pattern needs one. */\n halo: boolean;\n}\n\nexport interface Fur {\n /** Applies new settings, colors or scale, regrowing the hairs only when needed. */\n update(config: FurConfig): void;\n /** Plays a motion as if the pointer did it: hovering in, hovering out, or a click. */\n play(motion: FurMotion): void;\n /** The label color in use (hex), its APCA contrast on the fur (unsigned Lc), and whether a halo backs it. */\n readonly label: FurLabel | null;\n /** How far, in CSS px, the longest hairs can reach past the element's box, hovered, clicked or drooping. */\n readonly reach: number;\n /** Removes the fur and everything it changed on the element. */\n destroy(): void;\n}\n\n/** A fur that draws nothing, for browsers without WebGL2 on a real GPU: the element keeps its own look. */\nconst inert: Fur = { update() {}, play() {}, label: null, reach: 0, destroy() {} };\n\nexport function mountFur(button: HTMLElement, initial: FurConfig): Fur {\n let config = initial;\n let S = config.settings;\n // Redraw if the GPU's context is lost and comes back.\n let destroyed = false;\n const layer = createLayer(() => {\n if (destroyed) return;\n // The layer has put back its ramps; the hairs grow again, the same as before.\n plant();\n draw();\n });\n if (!layer) return inert;\n const events = new AbortController();\n const on = <K extends keyof HTMLElementEventMap>(type: K, listener: (event: HTMLElementEventMap[K]) => void) =>\n button.addEventListener(type, listener, { signal: events.signal });\n\n // The element's own styles, put back by `destroy`.\n const before = {\n position: button.style.position,\n isolation: button.style.isolation,\n backgroundColor: button.style.backgroundColor,\n color: button.style.color,\n textShadow: button.style.textShadow,\n };\n const computed = getComputedStyle(button);\n // The flat background the fur replaces, and the color it takes by default.\n const ownBackground = computed.backgroundColor;\n // The canvas sits behind the element's content, above its (hidden) background.\n if (computed.position === \"static\") button.style.position = \"relative\";\n button.style.isolation = \"isolate\";\n\n // The canvas, remade when the color setup changes, since a canvas's color\n // space and depth are fixed once its context exists. The GPU draws each\n // frame and copies it in.\n let canvas!: HTMLCanvasElement, ctx!: CanvasRenderingContext2D;\n let setup = \"\";\n const gamutNow = (): Gamut => (config.wideGamut && layer.gamut === \"display-p3\" && wideScreen() ? \"display-p3\" : \"srgb\");\n function makeCanvas() {\n const gamut = gamutNow();\n setup = gamut;\n const next = document.createElement(\"canvas\");\n next.setAttribute(\"aria-hidden\", \"true\");\n next.setAttribute(\"data-hairy\", \"\");\n Object.assign(next.style, { position: \"absolute\", pointerEvents: \"none\", zIndex: \"-1\" });\n ctx = next.getContext(\"2d\", { colorSpace: gamut })!;\n if (canvas) canvas.replaceWith(next);\n else button.prepend(next);\n canvas = next;\n }\n makeCanvas();\n\n // `scale` sizes the hairs; `pad` is the canvas margin they can reach into.\n let scale = 1, pad = halo;\n let w = 0, h = 0, radius = 0, dpr = 1;\n // How far the canvas is moved down, in CSS px: `translate`.\n let shift = 0;\n let strands: Strands | null = null, brush: Brush | null = null;\n // Spring state: `lift` 0 is combed flat, 1 is standing up.\n let lift = clamp(S.static, 0, 1), velocity = 0, target = lift, hovering = false;\n // A click's poof: which stage it's in and for how long, and where it peaks.\n // It rises on the click's rise spring until it gets there (or turns back,\n // overshooting it: `rose` says it has started up), then hangs there.\n let stage: \"rise\" | \"hold\" | null = null, stageTime = 0;\n let risePeak = 0, rose = false;\n // Rising and falling along curves, set aside for now:\n // let stage: \"rise\" | \"hold\" | \"fall\" | \"leave\" | null = null, stageTime = 0;\n // let riseFrom = 0, risePeak = 0, leaveFrom = 0;\n // How stretched a click has the hairs, 0 to 1: it rises and holds with the\n // click, then springs back on the click's fall spring (`recoil`), so the\n // hairs snap back, overshoot a little shorter and wobble out.\n let poof = 0, poofVelocity = 0, recoil = false;\n // let poof = 0, poofFrom = 0, poofVelocity = 0, recoil = false;\n // The hair length being drawn, springing toward `S.length` when it changes.\n let grown = S.length, growth = 0;\n // The rest a fall is heading for; when it changes mid-fall, the fall carries on from where it is.\n // let fallTarget = NaN;\n // Which spring moves the fur: hovering in, a click's way back down, or hovering out.\n let spring: \"hover\" | \"click\" | \"leave\" = \"hover\";\n let pointerX = -1e3, pointerY = -1e3, brushing = 0;\n let frame = 0, last = 0, time = 0;\n let label: Fur[\"label\"] = null;\n\n const seed = [...(button.textContent ?? \"\")].reduce((a, c) => (a * 31 + c.charCodeAt(0)) | 0, 7);\n\n // The fur's color, and its color ramps for each amount of hover and click\n // lightening, worked out as they're first needed and kept until the colors\n // or settings change. Steps of 0.001 L* are too small to see, so slow fades\n // don't step; each new step costs a fraction of a millisecond.\n let surface = \"#000\";\n // The colors the fur takes: see `coatOf`.\n let coat = coatOf(surface, S);\n const shades = new Map<number, Uint8Array>();\n // The lightening whose ramps the GPU has, as a key of `shades`.\n let uploaded = -1;\n\n function readColors() {\n surface = hexOf(config.color ?? ownBackground);\n coat = coatOf(surface, S);\n shades.clear();\n uploaded = -1;\n useShades(0);\n // Once the fur is drawn, it replaces the flat background, so no hard edge shows.\n button.style.backgroundColor = \"transparent\";\n // The element's own label color, for a halo when `label` is left out.\n button.style.color = before.color;\n const style = getComputedStyle(button);\n const text = { size: parseFloat(style.fontSize) || 16, weight: parseFloat(style.fontWeight) || 400 };\n const wanted = config.label === undefined || config.label === \"auto\" ? config.label : hexOf(config.label);\n const look = labelLook(coat, S, wanted, hexOf(style.color), text);\n // Without `label`, nothing is reported, but a halo still keeps the element's own label readable.\n button.style.textShadow = look.shadow || before.textShadow;\n label = config.label === undefined ? null : { color: look.color, contrast: look.contrast, halo: look.halo };\n if (label) button.style.color = label.color;\n }\n\n /** Switches to the ramps lightened by `light` (L*, 0–1), working them out the first time. */\n function useShades(light: number) {\n const key = Math.round(light * 1000);\n if (key === uploaded) return;\n let ramps = shades.get(key);\n if (!ramps) {\n if (shades.size > 2000) shades.clear();\n ramps = rampsAt(key / 1000);\n shades.set(key, ramps);\n }\n layer!.setRamp(ramps);\n uploaded = key;\n }\n\n /**\n * The fur's color ramps, lightened by `light`, as the GPU takes them: a\n * row each of `rampWidth` RGBA texels.\n * - Fur: the palette from the darkest hairs (0) to the lightest (1).\n * - Sheen: lighter than the brightest fur, with some of its color, so it\n * reads as light on the hair. Glitter's sparkles take its top.\n * - A pattern's markings, then its third color: palettes like the fur's.\n * With no pattern, copies of the fur's.\n */\n function rampsAt(light: number) {\n const { middle, high } = bandOf(coat.ground, S, light);\n const gamut = gamutNow(), buffer = layer!.gamut;\n const bytes = new Uint8Array(rampWidth * rampRows * 4);\n const palette = (color: string) => {\n const band = bandOf(color, S, light);\n return (u: number) => shadeOf(color, band.at(u), band.middle, 1);\n };\n const fur = palette(coat.ground);\n const patterned = S.pattern !== \"none\";\n const rows = [\n fur,\n (u: number) => shadeOf(coat.ground, Math.min(0.97, high + 0.03 + 0.06 * u), middle, 0.8),\n patterned ? palette(coat.marks) : null,\n patterned ? palette(coat.third) : null,\n ];\n rows.forEach((row, r) => {\n if (!row) {\n // The fur's own row again.\n bytes.copyWithin(r * rampWidth * 4, 0, rampWidth * 4);\n return;\n }\n for (let i = 0; i < rampWidth; i++) {\n const [cr, cg, cb] = encodeIn(row(i / (rampWidth - 1)), gamut, S.vividness, buffer);\n const k = (r * rampWidth + i) * 4;\n bytes[k] = Math.round(cr * 255);\n bytes[k + 1] = Math.round(cg * 255);\n bytes[k + 2] = Math.round(cb * 255);\n bytes[k + 3] = 255;\n }\n });\n return bytes;\n }\n\n /**\n * How much the fur is lightened now: by `hoverLight` as far as it has\n * risen toward the hover lift (with the hover's own timing), and by\n * `clickLight` as far through a click as it is (with the click's rise,\n * hang and spring-back). The hover part stops at the hover lift, so a\n * click's extra lift doesn't also brighten it, however small the hover lift.\n */\n function lightNow() {\n if (!S.hoverLight && !S.clickLight) return 0;\n const base = clamp(S.static, 0, 1), hoverTop = Math.min(1, base + S.hover);\n const hovered = hoverTop - base > 1e-3 ? clamp((lift - base) / (hoverTop - base), 0, 1) : 0;\n return S.hoverLight * hovered + S.clickLight * clamp(poof, -0.5, 1);\n }\n\n /**\n * Room around the element for the hairs at their longest: the halo fits\n * hairs up to length 1.4, and grows for longer ones and for the stretch\n * of hovering and clicking.\n */\n const padFor = (scale: number) =>\n Math.round(\n halo * scale * Math.max(1, S.length / 1.4) * (1 + Math.max(0, S.hoverStretch) + Math.max(0, S.clickStretch)) + Math.max(0, S.distance) * scale,\n );\n\n /**\n * How far the longest hairs reach past the outline: guard hairs on the rim\n * at full length variation, either drooping at rest or standing out with\n * the hover's overshoot and a click's stretch. Never past the canvas.\n */\n const reachFor = (scale: number) => {\n const longest = (13.5 + 4.5 * Math.max(0, S.lengthVariation)) * scale * Math.max(0, S.length);\n const resting = longest * (1 + 0.2 * Math.max(0, S.droop));\n const standing = longest * 1.3 * (1 + 1.3 * Math.max(0, S.hoverStretch) + Math.max(0, S.clickStretch));\n return Math.min(pad, Math.max(0, Math.round(Math.max(resting, standing) + S.distance * scale)));\n };\n\n function layout() {\n const b = button.getBoundingClientRect();\n const style = getComputedStyle(button);\n w = b.width; h = b.height;\n // A scale in em follows the font size: the resize observer runs this\n // again when the element resizes, as it does when its font size changes.\n const fontSize = parseFloat(style.fontSize) || emBase;\n scale = scaleOf(config.scale, fontSize) ?? scaleOf(style.getPropertyValue(\"--hairy-scale\"), fontSize) ?? 1;\n pad = padFor(scale);\n Object.assign(canvas.style, { inset: `-${pad}px`, width: `calc(100% + ${pad * 2}px)`, height: `calc(100% + ${pad * 2}px)` });\n radius = parseFloat(style.borderTopLeftRadius) || 0;\n place();\n dpr = config.pixelRatio ?? Math.min(2, devicePixelRatio || 1);\n // The GPU draws up to a size; past it, draw fewer pixels per CSS pixel.\n dpr = Math.min(dpr, layer!.largest / Math.max(1, w + pad * 2, h + pad * 2));\n canvas.width = Math.round((w + pad * 2) * dpr);\n canvas.height = Math.round((h + pad * 2) * dpr);\n plant();\n }\n\n /** Grows the hairs and hands them to the GPU, which keeps the only copy of what it draws them from. */\n function plant() {\n const { data, ...rest } = grow(w, h, radius, seed, scale, pad, S);\n strands = rest;\n // The GPU's bends start at zero.\n brush = null;\n layer!.setHairs(data, rest.n);\n }\n\n const choice = <K extends keyof typeof settingChoices>(key: K, value: string) =>\n Math.max(0, (settingChoices[key] as readonly string[]).indexOf(value));\n\n /** This frame, for the GPU: where the springs are, and the settings it draws with. */\n function frameNow(): Frame {\n // Below 0 (a bounce swinging past rest), the hairs press flatter than they lie.\n const up = Math.max(-0.5, lift);\n const base = clamp(S.static, 0, 1);\n // Undercoat: follows the fur's outline, `distance` out from the\n // element's. Dense fur hides the body's edge a little inside the outline;\n // sparse fur would leave a gap between it and the hairs, so the body\n // reaches out to where they grow, with a softer edge.\n const sparse = 1 - clamp(S.density, 0, 1);\n const rr = Math.min(radius, w / 2, h / 2);\n const inset = Math.min((3 - S.distance - 5 * sparse) * scale, Math.min(w, h) / 2 - 1);\n return {\n width: canvas.width / dpr,\n height: canvas.height / dpr,\n dpr,\n lift,\n sway: reduceMotion() ? 0 : S.sway * Math.min(1, Math.abs(up) * 3),\n time,\n hovering,\n pointerX,\n pointerY,\n near: 2 * (22 * scale) ** 2,\n base,\n // Stretch: hovering stretches hairs as they rise from rest to the hover\n // lift (and a little past it in a bouncy overshoot). A click stretches\n // them further along its own rise and fall, `poof`, so it works even\n // when the fur already stands fully upright.\n hoverTop: Math.min(1, base + S.hover),\n hoverStretch: S.hoverStretch,\n clicked: S.clickStretch * clamp(poof, -0.5, 1),\n grown,\n droop: S.droop,\n scale,\n thickness: S.thickness,\n taper: clamp(S.taper, 0.05, 1),\n softness: clamp(S.softness, 0, 2),\n hairType: choice(\"hairType\", S.hairType),\n typeAmount: Math.max(0, S.typeAmount),\n tightness: clamp(S.tightness, 0.1, 4),\n tip: choice(\"tipShape\", S.tipShape),\n material: choice(\"material\", S.material),\n materialAmount: Math.max(0, S.materialAmount),\n glitterDensity: clamp(S.glitterDensity, 0, maxGlitterDensity),\n glitterSize: Math.max(0, S.glitterSize),\n glitterSizeVariation: clamp(S.glitterSizeVariation, 0, 3),\n pattern: choice(\"pattern\", S.pattern),\n patternScale: clamp(S.patternScale, 0.1, 10),\n body: { x: pad + w / 2, y: pad + h / 2, w: w / 2, h: h / 2 },\n coat: {\n x: pad + inset, y: pad + inset, w: w - inset * 2, h: h - inset * 2,\n radius: Math.max(0, rr - inset),\n // In CSS pixels, the same at any pixel ratio: divided by it, it was\n // twice as wide on 1x screens and when zoomed out, and showed past the hairs.\n blur: (1.25 + sparse) * scale,\n top: pad, bottom: pad + h,\n },\n };\n }\n\n /** Moves the canvas by `translate`. */\n function place() {\n shift = Number.isFinite(config.translate) ? config.translate! : 0;\n canvas.style.translate = shift ? `0 ${shift}px` : \"\";\n }\n\n function draw() {\n if (!strands || destroyed) return;\n useShades(lightNow());\n layer!.render(ctx, frameNow());\n }\n\n /** Springs each brushed hair back toward where it lies; returns whether any is still moving. */\n function relax(dt: number) {\n if (!brush || brushing <= 0) return false;\n const { bends, speeds } = brush;\n // Springy, so brushed hair bounces back up rather than lying flat like wet fur.\n const k = S.brushSpeed ** 2, damping = 2 * S.brushSpeed * S.brushDamping;\n let moving = 0;\n for (let i = 0; i < bends.length; i += 2) {\n let bx = bends[i], by = bends[i + 1], vx = speeds[i], vy = speeds[i + 1];\n if (bx === 0 && by === 0 && vx === 0 && vy === 0) continue;\n vx += (-k * bx - damping * vx) * dt;\n vy += (-k * by - damping * vy) * dt;\n bx += vx * dt;\n by += vy * dt;\n if (Math.abs(bx) + Math.abs(by) + Math.abs(vx) + Math.abs(vy) < 0.002) bx = by = vx = vy = 0;\n else moving++;\n bends[i] = bx; bends[i + 1] = by; speeds[i] = vx; speeds[i + 1] = vy;\n }\n layer!.setBends(bends);\n brushing = moving;\n // Settled: every bend is zero, on the GPU too, so let the arrays go.\n if (!moving) brush = null;\n return moving > 0;\n }\n\n /** A spring's stiffness and damping from its speed (rad/s) and damping ratio. */\n const springOf = (speed: number, ratio: number): [number, number] => [speed * speed, 2 * speed * ratio];\n /** Steps the lift toward `to` on a spring with stiffness `k` and damping `damping`. */\n function springLift(to: number, k: number, damping: number, dt: number) {\n // Small steps, so stiff springs stay stable at low frame rates.\n const steps = Math.ceil(dt * 240);\n for (let i = 0; i < steps; i++) {\n velocity += (k * (to - lift) - damping * velocity) * (dt / steps);\n lift += velocity * (dt / steps);\n }\n }\n /** Steps the click's stretch toward `to` on a spring, like `springLift`. */\n function springPoof(to: number, k: number, damping: number, dt: number) {\n const steps = Math.ceil(dt * 240);\n for (let i = 0; i < steps; i++) {\n poofVelocity += (k * (to - poof) - damping * poofVelocity) * (dt / steps);\n poof += poofVelocity * (dt / steps);\n }\n }\n\n function tick(now: number) {\n const dt = Math.min(0.05, last ? (now - last) / 1000 : 1 / 60);\n last = now;\n time += dt;\n if (reduceMotion()) {\n lift = target;\n velocity = 0;\n stage = null;\n poof = 0;\n poofVelocity = 0;\n recoil = false;\n grown = S.length;\n growth = 0;\n } else if (stage === \"rise\" || stage === \"hold\") {\n // Up toward the peak on the rise spring, stretching on it too. Once it\n // reaches the peak (or turns back, overshooting past it), it hangs\n // there on the same spring, then lets go onto the fall spring.\n stageTime += dt;\n const [k, damping] = springOf(S.clickRiseSpeed, S.clickRiseDamping);\n springLift(risePeak, k, damping, dt);\n springPoof(1, k, damping, dt);\n if (stage === \"rise\") {\n if (velocity > 0.01) rose = true;\n const there = Math.abs(risePeak - lift) < 0.003 && Math.abs(velocity) < 0.05;\n if ((rose && velocity <= 0) || there || stageTime > 2) {\n stage = \"hold\";\n stageTime = 0;\n }\n }\n if (stage === \"hold\" && stageTime >= S.poofHold) {\n stage = null;\n spring = \"click\";\n recoil = true;\n }\n } else {\n // Hovering in, out, or a click coming back down, each on its own spring,\n // which follows the rest wherever it moves (the pointer leaves or comes back).\n const [k, damping] =\n spring === \"click\" ? springOf(S.clickFallSpeed, S.clickFallDamping)\n : spring === \"leave\" ? springOf(S.leaveSpeed, S.leaveDamping)\n : springOf(S.hoverSpeed, S.hoverDamping);\n springLift(target, k, damping, dt);\n }\n // Rising, holding and falling along curves, set aside for now:\n // if (stage === \"rise\") {\n // // Up to the peak, along the rise curve.\n // stageTime += dt;\n // const duration = Math.max(0.01, S.poofRise);\n // const ease = eases[S.poofEase] ?? eases[\"ease-out\"];\n // const u = Math.min(1, stageTime / duration);\n // lift = riseFrom + (risePeak - riseFrom) * ease(u);\n // poof = poofFrom + (1 - poofFrom) * ease(u);\n // velocity = 0;\n // if (u >= 1) {\n // stage = \"hold\";\n // stageTime = 0;\n // }\n // } else if (stage === \"hold\") {\n // // Hang at the top.\n // stageTime += dt;\n // lift = risePeak;\n // poof = 1;\n // velocity = 0;\n // if (stageTime >= S.poofHold) {\n // stage = \"fall\";\n // stageTime = 0;\n // fallTarget = NaN;\n // recoil = true;\n // poofVelocity = 0;\n // }\n // } else if (stage === \"fall\" || stage === \"leave\") {\n // // Down to where the fur rests now, along the fall curve: a click's fall\n // // from its peak, or hovering out from wherever the fur was. The fall\n // // keeps the same speed however far it goes, so a long drop (to flat)\n // // takes longer than a short one (back to hovering).\n // const click = stage === \"fall\";\n // const from = click ? risePeak : leaveFrom;\n // const speed = Math.max(0.05, click ? S.poofFallSpeed : S.leaveFallSpeed);\n // const ease = eases[click ? S.poofFallEase : S.leaveEase] ?? eases.gravity;\n // const duration = Math.max(0.01, Math.abs(target - from) / speed);\n // if (target !== fallTarget) {\n // // Just started, or the rest changed mid-fall (the pointer left or came\n // // back): carry on from where the fur is now, at the same speed.\n // const f = Math.abs(target - from) < 1e-6 ? 1 : clamp((lift - from) / (target - from), 0, 1);\n // stageTime = easeInverse(ease, f) * duration;\n // fallTarget = target;\n // }\n // stageTime += dt;\n // const u = Math.min(1, stageTime / duration);\n // lift = from + (target - from) * ease(u);\n // if (u >= 1) {\n // stage = null;\n // spring = click ? \"click\" : \"leave\";\n // // Land with the curve's final speed, so a curve that ends moving\n // // (like gravity) overshoots and bounces.\n // velocity = ((target - from) * (ease(1) - ease(0.98))) / (0.02 * duration);\n // // A fall keeps its speed however short it is, so a short drop would\n // // land as hard as a long one and dip far below where the fur rests\n // // (with static, nearly flat). Land softly enough to dip at most half\n // // the drop. Below flat the hairs only press a little flatter, so that\n // // part of the dip is left alone, and falls to flat bounce as before.\n // if (velocity < 0) {\n // const a = click ? S.poofSettle : S.leaveSettle;\n // const b = click ? S.poofBounce : S.leaveBounce;\n // const dip = -velocity / Math.sqrt(a * a + b * b);\n // const room = 0.5 * Math.abs(target - from) + Math.max(0, dip - target);\n // if (dip > room) velocity *= room / dip;\n // }\n // } else velocity = 0;\n // } else {\n // // A landing wobbles with its own settle and bounce, even if the target\n // // changes on the way (the pointer leaves). Hovering in uses the hover spring.\n // let k: number, damping: number;\n // if (spring === \"hover\") {\n // const w = S.hoverSpeed;\n // k = w * w;\n // damping = 2 * w * S.hoverDamping;\n // } else {\n // const a = spring === \"click\" ? S.poofSettle : S.leaveSettle;\n // const b = spring === \"click\" ? S.poofBounce : S.leaveBounce;\n // k = a * a + b * b;\n // damping = 2 * a;\n // }\n // // Small steps, so stiff springs stay stable at low frame rates.\n // const steps = Math.ceil(dt * 240);\n // for (let i = 0; i < steps; i++) {\n // velocity += (k * (target - lift) - damping * velocity) * (dt / steps);\n // lift += velocity * (dt / steps);\n // }\n // }\n if (recoil) {\n // The click's stretch springs back on its own, even once the fur has\n // landed, on the click's fall spring.\n const [k, damping] = springOf(S.clickFallSpeed, S.clickFallDamping);\n springPoof(0, k, damping, dt);\n // With the click's landing settle and bounce, along curves, set aside for now:\n // const a = S.poofSettle, b = S.poofBounce;\n // const k = a * a + b * b, damping = 2 * a;\n if (Math.abs(poof) < 0.002 && Math.abs(poofVelocity) < 0.01) {\n poof = 0;\n poofVelocity = 0;\n recoil = false;\n }\n }\n if (!reduceMotion() && (grown !== S.length || growth !== 0)) {\n // Grow or shrink toward the length setting, on the hover spring.\n const [k, damping] = springOf(S.hoverSpeed, S.hoverDamping);\n const steps = Math.ceil(dt * 240);\n for (let i = 0; i < steps; i++) {\n growth += (k * (S.length - grown) - damping * growth) * (dt / steps);\n grown += growth * (dt / steps);\n }\n if (Math.abs(S.length - grown) < 0.002 && Math.abs(growth) < 0.002) {\n grown = S.length;\n growth = 0;\n }\n }\n const moving = relax(dt);\n draw();\n const settled = stage === null && !recoil && growth === 0 && grown === S.length && Math.abs(target - lift) < 0.002 && Math.abs(velocity) < 0.002 && !moving;\n if (settled) spring = \"hover\";\n if (settled && (!hovering || reduceMotion())) {\n lift = target;\n draw();\n frame = 0;\n last = 0;\n return;\n }\n frame = requestAnimationFrame(tick);\n }\n const run = () => {\n if (!frame) frame = requestAnimationFrame(tick);\n };\n const focused = () => {\n try {\n return button.matches(\":focus-visible\");\n } catch {\n return false;\n }\n };\n const aim = () => {\n const rest = clamp(S.static, 0, 1);\n target = hovering || focused() ? Math.min(1, rest + S.hover) : rest;\n run();\n };\n /** Plays the click poof. */\n const startPoof = () => {\n if (reduceMotion()) return;\n stage = \"rise\";\n stageTime = 0;\n // The rise spring carries on from however the fur is moving.\n rose = false;\n recoil = false;\n // Along curves, set aside for now, the rise started still:\n // riseFrom = lift;\n // poofFrom = Math.max(0, poof);\n // poofVelocity = 0;\n // Capped where the hairs look fully upright: higher would just hang there\n // unseen and make the visible part of the fall look sudden. Hang time\n // controls the pause instead.\n risePeak = Math.max(lift, Math.min(1, Math.max(lift, target) + S.poofHeight));\n spring = \"click\";\n run();\n };\n const hoverIn = () => {\n hovering = true;\n // Coming back while hovering out: rise again with the hover spring.\n if (spring === \"leave\") spring = \"hover\";\n // Along curves, set aside for now:\n // if (stage === \"leave\" || spring === \"leave\") {\n // stage = null;\n // spring = \"hover\";\n // }\n aim();\n };\n const hoverOut = () => {\n hovering = false;\n pointerX = pointerY = -1e3;\n aim();\n // A click plays out on its own (its fall heads for the new rest);\n // otherwise hovering out springs back on its own spring.\n if (stage === null && spring === \"hover\") spring = \"leave\";\n // Falling along a curve, set aside for now:\n // if (stage === null && !reduceMotion() && Math.abs(lift - target) > 0.002) {\n // stage = \"leave\";\n // stageTime = 0;\n // leaveFrom = lift;\n // fallTarget = NaN;\n // }\n };\n\n let lastX = 0, lastY = 0;\n const local = (event: PointerEvent) => {\n const rect = button.getBoundingClientRect();\n pointerX = event.clientX - rect.left + pad;\n // The canvas is moved by `shift`; the hairs are where it draws them.\n pointerY = event.clientY - rect.top + pad - shift;\n };\n on(\"pointerenter\", (event) => {\n local(event);\n lastX = pointerX; lastY = pointerY;\n hoverIn();\n });\n // Brushing: hairs near the pointer are pushed the way it moves, then spring back.\n on(\"pointermove\", (event) => {\n local(event);\n if (!strands || reduceMotion()) return;\n let mx = pointerX - lastX, my = pointerY - lastY;\n lastX = pointerX; lastY = pointerY;\n const speed = Math.hypot(mx, my);\n if (speed < 0.01) return;\n // A fast flick (like leaving quickly) shouldn't comb the fur flat.\n const most = 16 * scale;\n if (speed > most) { mx *= most / speed; my *= most / speed; }\n // Movement is measured relative to the hair size, so big fur brushes like small fur.\n mx /= scale; my /= scale;\n // While a click plays, brush only lightly, so its bounce shows.\n const clicking = stage === \"rise\" || stage === \"hold\" || stage === \"fall\" || spring === \"click\";\n const { roots, n } = strands, reach = 34 * scale, push = 0.09 * S.brush * (clicking ? 0.3 : 1);\n brush ??= { bends: new Float32Array(n * 2), speeds: new Float32Array(n * 2) };\n const { bends, speeds } = brush;\n for (let i = 0; i < n * 2; i += 2) {\n const dx = roots[i] - pointerX, dy = roots[i + 1] - pointerY;\n const d2 = dx * dx + dy * dy;\n if (d2 > reach * reach * 4) continue;\n const f = Math.exp(-d2 / (2 * reach * reach)) * push;\n speeds[i] += mx * f * 4;\n speeds[i + 1] += my * f * 4;\n const v = Math.hypot(speeds[i], speeds[i + 1]);\n if (v > 8) { speeds[i] *= 8 / v; speeds[i + 1] *= 8 / v; }\n // Keep a brushed hair from folding over completely.\n const b = Math.hypot(bends[i], bends[i + 1]);\n if (b > 1.1) { bends[i] *= 1.1 / b; bends[i + 1] *= 1.1 / b; }\n }\n brushing = 1;\n run();\n });\n on(\"pointerleave\", hoverOut);\n on(\"pointerdown\", (event) => {\n local(event);\n startPoof();\n });\n on(\"keydown\", (event) => {\n if (event.repeat || (event.key !== \"Enter\" && event.key !== \" \")) return;\n startPoof();\n });\n on(\"focus\", () => {\n if (!focused() || hovering) return;\n aim();\n });\n on(\"blur\", aim);\n\n const refresh = () => {\n if (setup !== gamutNow()) {\n makeCanvas();\n layout();\n } else if (padFor(scale) !== pad) layout();\n readColors();\n place();\n draw();\n // Settings may have moved where the fur rests or hovers: spring there.\n aim();\n };\n const regrow = () => {\n layout();\n refresh();\n };\n const resize = new ResizeObserver(regrow);\n resize.observe(button);\n // Draw right away, rather than waiting for the first resize callback.\n layout();\n readColors();\n draw();\n\n return {\n update(next) {\n const regrows =\n next.scale !== config.scale ||\n next.pixelRatio !== config.pixelRatio ||\n (Object.keys(next.settings) as (keyof FurSettings)[]).some((key) => regrowSettings.has(key) && next.settings[key] !== S[key]);\n config = next;\n S = next.settings;\n if (regrows) regrow();\n else refresh();\n },\n play(motion) {\n if (motion === \"click\") startPoof();\n else if (motion === \"hover\") hoverIn();\n else hoverOut();\n },\n get label() {\n return label;\n },\n get reach() {\n return reachFor(scale);\n },\n destroy() {\n destroyed = true;\n layer.dispose();\n events.abort();\n resize.disconnect();\n if (frame) cancelAnimationFrame(frame);\n frame = 0;\n canvas.remove();\n Object.assign(button.style, before);\n },\n };\n}\n","import { defaultSettings, isSettingValue, presets, type FurSettings, type PresetName } from \"./settings\";\n\n/**\n * The public option names, by group, and the setting each one sets. The groups\n * follow the playground: how the fur is shaded, its shine, the hairs, and how\n * it moves at rest, on hover, on hover out, on click and when brushed.\n */\nexport const optionGroups = {\n shade: {\n /** Moves the fur's middle shade lighter or darker than the color, in L* (0–1). */\n lightness: \"shift\",\n /** How much darker the darkest hairs are than the middle shade. */\n shadows: \"darker\",\n /** How much lighter the lightest hairs are than the middle shade. */\n highlights: \"lighter\",\n /** On wide-gamut (P3) screens, how far colors move out toward the more vivid ones sRGB can't show (0 to 1). */\n vividness: \"vividness\",\n },\n shine: {\n /** How many glossy hairs catch the light. 0 is matte. */\n amount: \"sheen\",\n /** Where the band of shine sits: 0 at the top, 1 at the bottom. */\n position: \"sheenPosition\",\n /** How wide the band of shine is. */\n spread: \"sheenSpread\",\n /** Darkens the hairs along the top edge, where the surface turns away from the light. */\n edgeShadow: \"edgeShadow\",\n },\n hair: {\n density: \"density\",\n length: \"length\",\n thickness: \"thickness\",\n /** Tip width compared to the root. */\n taper: \"taper\",\n /** How soft each hair's edge is, in px: 0 is crisp, higher fades it over more pixels, up to 2. */\n softness: \"softness\",\n curl: \"curl\",\n droop: \"droop\",\n /** How much hair lengths differ. 0 makes them all the same. */\n lengthVariation: \"lengthVariation\",\n /** How far hairs stray from the combed direction. */\n messiness: \"messiness\",\n /** How far hairs along the outline lean out, softening the edge. */\n fuzz: \"fuzz\",\n /** Where the fur starts from the element's edge, in px. Below 0 it eats into the element. */\n distance: \"distance\",\n /** The hairs' pattern: \"straight\", \"wavy\", \"curly\" or \"frizzy\". */\n type: \"hairType\",\n /** How strong the waves, curls or frizz are: 0 is straight, 1 the usual amount. */\n typeAmount: \"typeAmount\",\n /** How many waves, turns or kinks fit along each hair: higher is tighter. */\n tightness: \"tightness\",\n /** How each hair ends: \"round\", \"sharp\" or \"square\". */\n end: \"tipShape\",\n },\n material: {\n /** What the hair looks made of: \"natural\" or \"glitter\". */\n type: \"material\",\n /** How bright glitter's flashes are. */\n amount: \"materialAmount\",\n },\n pattern: {\n /** A coat pattern, as on an animal: \"none\", \"zebra\", \"tiger\", \"dalmatian\", \"leopard\" or \"giraffe\". */\n type: \"pattern\",\n /** \"natural\" takes the animal's own colors; \"tinted\" makes them from the fur's color. */\n colors: \"patternColors\",\n /** How big the stripes, spots or patches are: 1 the usual size. */\n scale: \"patternScale\",\n },\n halo: {\n /** When the label gets a halo: \"auto\" only when a pattern needs one, or \"always\" or \"never\". */\n when: \"halo\",\n /** How far its shade moves from the base color, away from the label's: darker under a light label, lighter under a dark one (L, 0–1). */\n shade: \"haloShade\",\n /** How far the glow spreads round the letters: 1 the usual size. */\n size: \"haloSize\",\n /** How strong it is: 1 the usual, 0 none. */\n strength: \"haloStrength\",\n },\n glitter: {\n /** How many flakes there are: 1 the usual amount, 0 none. */\n density: \"glitterDensity\",\n /** How big the flakes are: 1 the usual size. */\n size: \"glitterSize\",\n /** How much flake sizes differ: 0 all the same; at 1 they range from half to twice the size. */\n sizeVariation: \"glitterSizeVariation\",\n },\n rest: {\n /** How far the hairs stand up on their own: 0 lies combed flat, 1 stands straight up. */\n static: \"static\",\n },\n hover: {\n /** How much further the hairs stand up on hover, on top of the rest's static. */\n static: \"hover\",\n /** How much longer the hairs grow as they rise. 1 doubles them. */\n stretch: \"hoverStretch\",\n /** How much lighter the fur gets as it rises, in L*. Below 0 darkens. */\n lightness: \"hoverLight\",\n /** How far each hair rocks from side to side while hovered. */\n sway: \"sway\",\n /** How quickly the fur rises (rad/s). */\n speed: \"hoverSpeed\",\n /** How much the rise bounces: lower overshoots, 1 doesn't. */\n damping: \"hoverDamping\",\n },\n leave: {\n /** How quickly the fur springs back to rest when the pointer leaves (rad/s). */\n speed: \"leaveSpeed\",\n /** How much it bounces past rest: lower overshoots, 1 doesn't. */\n damping: \"leaveDamping\",\n // Falling along a curve, set aside for now: hovering out springs instead.\n // /** How fast the fur falls when the pointer leaves: a full drop takes 1 ÷ this many seconds. */\n // fallSpeed: \"leaveFallSpeed\",\n // /** The curve of the fall. */\n // easing: \"leaveEase\",\n // /** How quickly the landing bounce fades. */\n // settle: \"leaveSettle\",\n // /** How fast the fur wobbles after it lands. 0 doesn't wobble. */\n // bounce: \"leaveBounce\",\n },\n click: {\n /** How much further a click makes the fur stand up, on top of hovering. */\n static: \"poofHeight\",\n /** How much longer still the hairs grow at the top of a click. */\n stretch: \"clickStretch\",\n /** How much lighter still a click makes the fur, in L*. */\n lightness: \"clickLight\",\n /** How quickly the fur poofs up (rad/s). */\n riseSpeed: \"clickRiseSpeed\",\n /** How far the poof overshoots its peak: lower overshoots more, 1 doesn't. */\n riseDamping: \"clickRiseDamping\",\n /** Seconds the fur hangs at the top. */\n hold: \"poofHold\",\n /** How quickly the fur comes back down, and the stretch springs back (rad/s). */\n fallSpeed: \"clickFallSpeed\",\n /** How much it bounces on the way down: lower bounces more, 1 doesn't. */\n fallDamping: \"clickFallDamping\",\n // Rising and falling along curves, set aside for now: a click springs instead.\n // /** Seconds the fur takes to poof up. */\n // rise: \"poofRise\",\n // /** The curve of the rise. */\n // riseEasing: \"poofEase\",\n // /** How fast the fall comes down: a full drop takes 1 ÷ this many seconds. */\n // fallSpeed: \"poofFallSpeed\",\n // /** The curve of the fall. */\n // fallEasing: \"poofFallEase\",\n // /** How quickly the landing bounce fades. */\n // settle: \"poofSettle\",\n // /** How fast the fur wobbles after it lands. 0 doesn't wobble. */\n // bounce: \"poofBounce\",\n },\n brush: {\n /** How strongly moving the pointer across the fur pushes the hairs. 0 turns brushing off. */\n amount: \"brush\",\n /** How quickly brushed hairs spring back. */\n speed: \"brushSpeed\",\n /** How much brushed hairs wobble on the way back. */\n damping: \"brushDamping\",\n },\n} as const satisfies Record<string, Record<string, keyof FurSettings>>;\n\nexport type OptionGroup = keyof typeof optionGroups;\ntype GroupOptions<G extends OptionGroup> = {\n [K in keyof (typeof optionGroups)[G]]?: (typeof optionGroups)[G][K] extends keyof FurSettings\n ? FurSettings[(typeof optionGroups)[G][K]] extends number ? number : FurSettings[(typeof optionGroups)[G][K]]\n : never;\n};\n/** The fur's look and motion, by group. Each value overrides the preset's. */\nexport type FurOptions = { [G in OptionGroup]?: GroupOptions<G> };\n\n/** A hair size: a number (1 is the default size, in CSS px), or \"<n>em\" to follow the element's font size. */\nexport type HairScale = number | `${number}em`;\n\nexport interface HairyOptions extends FurOptions {\n /** The starting settings. Defaults to \"plush\". */\n preset?: PresetName;\n /** The fur's color, any CSS color. Defaults to the element's background color. */\n color?: string;\n /**\n * The label's color. \"auto\" picks a readable one for the fur by APCA\n * contrast; a CSS color sets it; leave it out to keep the element's own.\n */\n label?: \"auto\" | (string & {});\n /**\n * Hair size: at 2 the hairs are twice as long and thick, and fewer, so each\n * shows. In em (\"1em\", \"1.5em\"), it follows the element's font size, with\n * 16px as 1em, so the fur shrinks and grows with a responsive element.\n * Defaults to the element's `--hairy-scale` CSS variable (a number or an\n * em value), or 1.\n */\n scale?: HairScale;\n /**\n * Moves the fur down, in CSS px; below 0 moves it up. Hair combs down, so\n * it hangs further below the element than it reaches above it, and the\n * label can look high: a few px up (-4 or so) centers the fur on it.\n * Defaults to 0.\n */\n translate?: number;\n /** Draw in Display P3 on screens that support it. Defaults to true. */\n wideGamut?: boolean;\n /** Canvas pixels per CSS pixel. Defaults to the screen's, up to 2; set it higher to bake large images. */\n pixelRatio?: number;\n}\n\n/** The full settings for `options`: the preset's, with each grouped option on top. */\nexport function resolveSettings(options: FurOptions & { preset?: PresetName }): FurSettings {\n const base = (options.preset && presets[options.preset]) || defaultSettings;\n const settings = { ...base } as FurSettings;\n for (const [group, names] of Object.entries(optionGroups) as [OptionGroup, Record<string, keyof FurSettings>][]) {\n const values = options[group] as Record<string, unknown> | undefined;\n if (!values) continue;\n for (const [name, key] of Object.entries(names)) {\n const value = values[name];\n if (!isSettingValue(key, value)) continue;\n Object.assign(settings, { [key]: value });\n }\n }\n return settings;\n}\n\n/**\n * The grouped options that turn `preset` into `settings`: only the values\n * that differ, so they stay short. The inverse of `resolveSettings`.\n */\nexport function diffOptions(settings: FurSettings, preset: PresetName = \"plush\"): FurOptions {\n const base = presets[preset] ?? defaultSettings;\n const out: Record<string, Record<string, unknown>> = {};\n for (const [group, names] of Object.entries(optionGroups) as [OptionGroup, Record<string, keyof FurSettings>][]) {\n for (const [name, key] of Object.entries(names)) {\n if (settings[key] === base[key]) continue;\n (out[group] ??= {})[name] = settings[key];\n }\n }\n return out as FurOptions;\n}\n","import { mountFur, type FurLabel, type FurMotion } from \"./fur\";\nimport { resolveSettings, type HairyOptions, type OptionGroup, optionGroups } from \"./options\";\n\nexport type { FurLabel, FurMotion } from \"./fur\";\nexport type { ChoiceSetting, Ease, FurSettings, Halo, HairType, Material, Pattern, PatternColors, PresetName, TipShape } from \"./settings\";\nexport type { FurOptions, HairScale, HairyOptions, OptionGroup } from \"./options\";\nexport { autoLabel, labelContrast, supportsWideGamut } from \"./fur\";\nexport { gpuSupported as supportsFur } from \"./gl\";\nexport { eases, defaultSettings, isSettingValue, presets, presetNames, regrowSettings, settingChoices } from \"./settings\";\nexport { optionGroups, resolveSettings, diffOptions } from \"./options\";\nexport { apca } from \"./color\";\n\nexport interface Hairy {\n /**\n * Changes the options. Top-level options replace the old ones; each group\n * (`hair`, `hover`…) is merged into the old group, value by value.\n */\n update(options: HairyOptions): void;\n /** Replaces all the options, so anything left out goes back to its default. */\n set(options: HairyOptions): void;\n /** Plays a motion as if the pointer did it: \"hover\" in, \"leave\" (hover out), or a \"click\". */\n play(motion: FurMotion): void;\n /** The label color in use, its APCA contrast on the fur (unsigned Lc) and whether a halo backs it, when `label` is set. */\n readonly label: FurLabel | null;\n /** How far, in CSS px, the longest hairs can reach past the element's box, hovered, clicked or drooping. */\n readonly reach: number;\n /** Removes the fur, and puts back the element's own styles. */\n destroy(): void;\n}\n\nconst configOf = (options: HairyOptions) => ({\n settings: resolveSettings(options),\n color: options.color,\n label: options.label,\n scale: options.scale,\n translate: options.translate,\n pixelRatio: options.pixelRatio,\n wideGamut: options.wideGamut ?? true,\n});\n\n/**\n * Adds fur to an element you already have, usually a button. The fur is drawn\n * on a canvas behind the element's content, in `color` (or the element's own\n * background), and reacts to hover, click, keyboard focus and brushing.\n *\n * ```js\n * import { hairy } from \"@markmiro/hairy\";\n * const fur = hairy(document.querySelector(\"#adopt\"), { preset: \"plush\", color: \"#ff4d70\", label: \"auto\" });\n * ```\n */\nexport function hairy(element: HTMLElement, options: HairyOptions = {}): Hairy {\n let current: HairyOptions = { ...options };\n const fur = mountFur(element, configOf(current));\n return {\n update(next) {\n const merged: HairyOptions = { ...current, ...next };\n for (const group of Object.keys(optionGroups) as OptionGroup[]) {\n if (next[group]) Object.assign(merged, { [group]: { ...current[group], ...next[group] } });\n }\n current = merged;\n fur.update(configOf(current));\n },\n set(next) {\n current = { ...next };\n fur.update(configOf(current));\n },\n play: (motion) => fur.play(motion),\n get label() {\n return fur.label;\n },\n get reach() {\n return fur.reach;\n },\n destroy: () => fur.destroy(),\n };\n}\n"],"mappings":"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","names":["color","halo","spread","scale"]}
|