@originkit/avatars 0.1.0 → 0.2.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 +22 -0
- package/dist/controls.d.ts +1 -4
- package/dist/controls.js +55 -5
- package/dist/kinds.js +16 -16
- package/dist/share.js +2 -2
- package/dist/variants.d.ts +2 -0
- package/dist/variants.js +2 -0
- package/package.json +17 -3
- package/react/index.d.ts +28 -0
- package/react/index.js +869 -0
- package/react/styles.js +1 -0
package/react/index.js
ADDED
|
@@ -0,0 +1,869 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
"use client";import{useEffect as useEffect2,useInsertionEffect,useMemo as useMemo15,useRef as useRef15,useState as useState2}from"react";var BLACK="#000000",WHITE="#ffffff";var hexToInt=hex=>parseInt(hex.slice(1),16),intToHex=value=>`#${value.toString(16).padStart(6,"0")}`,channels=hex=>[1,3,5].map(start=>parseInt(hex.slice(start,start+2),16)),fromChannels=values=>`#${values.map(v=>Math.round(v).toString(16).padStart(2,"0")).join("")}`;function mix(hex,target,amount){let to=channels(target);return fromChannels(channels(hex).map((v,i)=>v+(to[i]-v)*amount))}function luminance(hex){let[r,g,b]=channels(hex).map(v=>{let unit=v/255;return unit<=.04045?unit/12.92:((unit+.055)/1.055)**2.4});return .2126*r+.7152*g+.0722*b}var inkOn=hex=>luminance(hex)>.179?BLACK:WHITE;function contrast(a,b){let[light,dark]=[luminance(a),luminance(b)].sort((x,y)=>y-x);return(light+.05)/(dark+.05)}var SEPARATOR=255,utf8=new TextEncoder;function feed(hash,bytes){for(let byte of bytes)hash=Math.imul(hash^byte,3432918353),hash=hash<<13|hash>>>19;return hash}function finalize(hash){return hash=Math.imul(hash^hash>>>16,2246822507),hash=Math.imul(hash^hash>>>13,3266489909),(hash^hash>>>16)>>>0}function normalize(name){return name.normalize("NFC").trim().toLowerCase()}var COLOR_PREFIX="color:",colorKey=key2=>`${COLOR_PREFIX}${key2}`;function createTraits(name,overrides={}){let seed=normalize(name),state=feed(1779033703^seed.length,utf8.encode(seed)),fixed=key2=>{let value=overrides[key2];return typeof value=="number"&&Number.isFinite(value)?Math.min(1,Math.max(0,value)):void 0},t=(key2=>fixed(key2)??finalize(feed(feed(state,Uint8Array.of(SEPARATOR)),utf8.encode(key2)))/2**32),index=(key2,count)=>Math.min(count-1,Math.floor(t(key2)*count));return t.num=(key2,min,max)=>min+t(key2)*(max-min),t.int=(key2,min,max)=>min+index(key2,max-min+1),t.jitter=(key2,amount)=>(t(key2)*2-1)*amount,t.pick=(key2,options)=>options[index(key2,options.length)],t.forced=fixed,t.color=key2=>{let picked=overrides[colorKey(key2)];return Number.isInteger(picked)&&picked>=0&&picked<=16777215?intToHex(picked):void 0},t.text=key2=>{let words=overrides[key2];return typeof words=="string"?words:void 0},t}var TOP=.999;function bands(entries){let total=entries.reduce((sum,entry)=>sum+(entry.weight??1),0),start=0;return entries.map(entry=>{let width=(entry.weight??1)/total,band2={...entry,start,end:start+width,middle:start+width/2};return start+=width,band2})}var bandAt=(entries,position)=>{let found=bands(entries).findIndex(band2=>position<band2.end);return found===-1?entries.length-1:found};function choice(t,key2,label,layout,entries){return{type:"choice",id:key2,label,layout,options:bands(entries).map((band2,i)=>({id:String(i),label:band2.label,color:band2.color,set:{[key2]:band2.middle}})),selected:String(bandAt(entries,t(key2)))}}function turnOf(t,natural){let set=t.forced("angle");return set===void 0?(t("angle")*2-1)*natural:set*360-180}function turnSlider(t,natural){let turn2=turnOf(t,natural);return{type:"slider",id:"angle",label:"Angle",value:(turn2+180)/360,display:`${Math.round(turn2)}\xB0`,range:[-180,180]}}var clearingColor=(control,key2)=>({...control,options:control.options.map(option=>({...option,set:{...option.set,[colorKey(key2)]:void 0}}))});function palette(t,key2,label,colors){let control=clearingColor(choice(t,key2,label,"swatches",colors.map(color=>({label:color,color}))),key2),picked=t.color(key2);return{...control,selected:picked?"custom":control.selected,custom:{id:colorKey(key2),color:picked??control.options[Number(control.selected)].color}}}function fixedPalette(t,key2,label,colors){let id=colorKey(key2),current=t.color(key2)??colors[0];return{type:"choice",id:key2,label,layout:"swatches",options:colors.map((color,i)=>({id:color,label:color,color,set:{[id]:i===0?void 0:hexToInt(color)}})),selected:current,custom:{id,color:current}}}function optional(t,chanceKey,percent,kindKey,label,layout,entries){let present2=t(chanceKey)*100<percent;return{type:"choice",id:chanceKey,label,layout,options:[{id:"none",label:"None",set:{[chanceKey]:TOP}},...bands(entries).map((band2,i)=>({id:String(i),label:band2.label,color:band2.color,set:{[chanceKey]:0,[kindKey]:band2.middle}}))],selected:present2?String(bandAt(entries,t(kindKey))):"none"}}function toggle(t,key2,percent,label){return{type:"choice",id:key2,label,layout:"switch",options:[{id:"on",label:"On",set:{[key2]:0}},{id:"off",label:"Off",set:{[key2]:TOP}}],selected:t(key2)*100<percent?"on":"off"}}function automatic(t,key2,label,labels,current){let forced=t.forced(key2);return{type:"choice",id:key2,label,layout:"list",options:[{id:"auto",label:`Auto (${current})`,set:{[key2]:void 0}},...labels.map((entry,i)=>({id:String(i),label:entry,set:{[key2]:(i+.5)/labels.length}}))],selected:forced===void 0?"auto":String(Math.floor(forced*labels.length))}}function slider(t,key2,label,min,max,unit=""){let value=t(key2),shown2=min+value*(max-min);return{type:"slider",id:key2,label,value,display:`${Number.isInteger(min)&&Number.isInteger(max)&&max-min>10?Math.round(shown2):shown2.toFixed(1)}${unit}`,range:[min,max]}}var fromVariants=(variants,label)=>Object.entries(variants).map(([name,variant],i)=>({label:label(name,i),weight:variant.weight??1})),spaced=name=>{let words=name.replace(/([a-z])([A-Z])/g,"$1 $2").toLowerCase();return words.charAt(0).toUpperCase()+words.slice(1)};var VARIANCE="variance";function plainFirst([count,,from]){let named11=Array.isArray(from)?from:[];return[...named11,...Array.from({length:count},(_,i)=>i).filter(i=>!named11.includes(i))]}var varianceSet=t=>t.forced(VARIANCE),varianceOf=t=>varianceSet(t)??1,keptOf=(count,fewest,variance)=>Math.min(count,fewest+Math.floor(variance*(count-fewest+1)));function calmed(t,{features,lists={},rarer=[]}){let variance=varianceSet(t);if(variance===void 0)return t;let keep=.2+(1-.2)*variance,calm=(key2=>{let value=t(key2);if(t.forced(key2)!==void 0)return value;let list=lists[key2];if(list){let[count,fewest,from]=list,kept=keptOf(count,fewest,variance);return from==="end"?1-(1-value)*(kept/count):(plainFirst(list)[Math.floor(value*kept)]+.5)/count}return rarer.includes(key2)?variance===0?.999:Math.min(.999,value/variance):features?.test(key2)?.5+(value-.5)*keep:value});return calm.num=(key2,min,max)=>min+calm(key2)*(max-min),calm.int=(key2,min,max)=>min+Math.floor(calm(key2)*(max-min+1)),calm.jitter=(key2,amount)=>(calm(key2)*2-1)*amount,calm.pick=(key2,options)=>options[Math.floor(calm(key2)*options.length)],calm.forced=t.forced,calm.color=t.color,calm.text=t.text,calm}function narrowed(control,t,{lists={}}){let variance=varianceSet(t),list=lists[control.id];if(variance===void 0||!list||t.forced(control.id)!==void 0)return control;let[count,fewest,from]=list,kept=keptOf(count,fewest,variance),plain=plainFirst(list).slice(0,kept),offered=position=>from==="end"?position>=1-kept/count:plain.includes(Math.floor(position*count));return{...control,options:control.options.filter(option=>option.id===control.selected||offered(Number(option.set[control.id])))}}function possibilitiesSlider(t,[low,medium,high]){let variance=Math.min(varianceOf(t),.999);return{type:"slider",id:VARIANCE,label:"Possibilities",value:variance,display:`${Math.round(variance*100)}%`,range:[0,100],ends:["Low","High"],note:variance<1/3?`Low: ${low}`:variance<2/3?`Medium: ${medium}`:`High: ${high}`}}var CALMING={features:/^flow\.[a-z]$|^(turn|softness)$/,lists:{flow:[12,8,[0,3,8,5,1,7,4,6,9,10,11,2]]}},PALETTE_ORDER={Sky:[0,2,8,5,4,11,6,9,1,10,3,7],Aura:[0,2,5,8,6,3,13,9,11,14,1,4,7,10,12]},NOTES=["calm glows and gentle daytime skies, upright, nearly smooth, the horizon in its place.","more formations and skies, grainier, the horizon higher or lower.","every formation and sky, up to the deepest and night, at any grain and horizon."];var SKIES=[{label:"Clear",stops:["#80bae2","#82bae5","#87bee7","#8dc1e9","#94c4ea","#9bc7ea","#9fcaec","#a8cff0","#aed1ef","#b2d4f0","#b9d7f3","#bcdaf2","#c2dcf3","#c5dff6","#c9e2f8","#cbe4f8","#cee8f9","#d2e9f9","#d6edfc","#daeefc","#daeefc"]},{label:"Evening",stops:["#0e1120","#111f3a","#1b2946","#213153","#283a62","#2e406e","#31487e","#374f7d","#405783","#485f88","#54668a","#607091","#687a92","#758497","#878c90","#9b9289","#ae9984","#c2a27c","#d3aa74","#e7b36a","#e7b36a"]},{label:"Dawn",stops:["#8492c4","#7e96cc","#849bd1","#87a3d5","#89a8d7","#8eafdc","#92b5dd","#96bce3","#98bfe8","#9cc4e8","#9fc6ed","#a5cae7","#adcde2","#b8cfde","#c2d4d8","#cbd7d5","#d5dbcf","#dddfc9","#eae4c3","#f5e7bb","#f5e7bb"]},{label:"Ember",stops:["#283544","#273a4e","#293b53","#2a3c54","#2c3e56","#2e4058","#2d4159","#2f435b","#31475f","#334961","#314b64","#345068","#37516c","#455167","#5c4f61","#774c55","#9d4345","#c63232","#e64d2e","#ef843e","#ef843e"]},{label:"Pastel",stops:["#9cb9be","#afc4cf","#c0cedb","#cdd4e4","#d6d9ec","#dcdaef","#dedbee","#e4d9e9","#e8d8e3","#edd5e2","#f3d3dd","#f6d1d9","#facfd6","#facfd6","#f8ced2","#f4c9d2","#edc2cc","#e1b5c2","#d2a5b5","#bd8fa8","#bd8fa8"]},{label:"Noon",stops:["#174e8d","#1462ae","#1765b0","#1768b2","#116bb7","#0b6fba","#0672ba","#0676be","#107dc2","#167fc1","#2685c7","#338bcb","#3c92cf","#4597d1","#4d9cd5","#54a1d9","#5ba7db","#63aae0","#67afe1","#69b4e4","#69b4e4"]},{label:"Golden",stops:["#976e8d","#a27a96","#ae86a0","#b592a6","#bf9eaf","#c7a7b2","#cdacb3","#d1b2af","#d8b8ac","#debba7","#e4c1a3","#e9c69e","#efcb9a","#f7d096","#fcd391","#ffd490","#fccd87","#f3bd77","#eaa863","#de8f49","#de8f49"]},{label:"Night",stops:["#11111a","#131623","#151827","#171a2b","#181b2c","#1b1e2f","#1c1f32","#1e2134","#1f2136","#212338","#20253b","#222a3f","#283047","#2c374d","#35415b","#3b4b64","#58505f","#755556","#955b4f","#b9663e","#b9663e"]},{label:"Mist",stops:["#ccd8ec","#cddcf2","#d4e1f2","#d9e5f3","#e0eaf6","#e5ebf7","#eaeef9","#eef2fb","#f0f4fd","#f6f7fc","#f7f8fc","#f9fafe","#fbfcfe","#fdfdff","#fdfdfd","#fefefe","#ffffff","#ffffff","#ffffff","#ffffff","#ffffff"]},{label:"Dusk",stops:["#3e748e","#5a88ab","#7395b2","#879eb5","#99a9b9","#aab3bc","#babec1","#c7c6c4","#d2cdc7","#d9d2c8","#ddd3c9","#e1d3c5","#e7d1bb","#eccdb1","#f0c6a3","#f7c297","#fcba86","#fcb482","#f6a071","#f5815e","#f5815e"]},{label:"Orchid",stops:["#d068a4","#d36eac","#cf75b2","#cc7db6","#c882b8","#c585b9","#c68abe","#c58cbf","#c28cbe","#c38dbf","#c28cbe","#c58fc1","#c690c1","#c892c3","#ca95c3","#ce99c5","#d09bc7","#d49fc9","#d8a4cb","#dea9ce","#dea9ce"]},{label:"Haze",stops:["#546f82","#7b94a5","#8fa1ab","#97a6ad","#96a7ae","#98a9b1","#9aabb5","#9eabbb","#a0adc0","#a5afc0","#aeb0bd","#b7b0b8","#c1afb1","#cbb0ad","#d4b0a7","#e0b0a2","#ebb19c","#f5b296","#fbb592","#fdc787","#fdc787"]}];var TYPES=["Aura","Sky"],PALETTES=[{label:"Sunrise",colors:["#e2545b","#f6a47c","#fff0c2","#f7b7a3"]},{label:"Ember",colors:["#1d1622","#3a2232","#ffd28a","#ff7a1f"]},{label:"Meadow",colors:["#3d9e62","#a5d89a","#f1f9cf","#6fc08a"]},{label:"Blossom",colors:["#e8447a","#f6a3bf","#fff1f4","#f27aa3"]},{label:"Aurora",colors:["#04120f","#1f9f57","#e5ffc9","#34c5c2"]},{label:"Twilight",colors:["#4757b3","#a9b0ea","#eceefe","#7d86d6"]},{label:"Dream",colors:["#b98ae6","#f2b0dc","#fff4c0","#d8a6f0"]},{label:"Nebula",colors:["#0d0b16","#4b2a5e","#ffb2df","#c0549b"]},{label:"Sky",colors:["#3f86dc","#8fc3f2","#e4f8ff","#b8eff0"]},{label:"Craft",colors:["#1f6b4e","#3fd86b","#ebe8e1","#9fb3b0"]},{label:"Cobalt",colors:["#071466","#0f3fd6","#3da4ff","#1a6cf5"]},{label:"Flowy",colors:["#f04f4b","#c859b4","#eef0f6","#ffb347"]},{label:"Forest",colors:["#146b10","#2f8f1a","#e3f00f","#f6e21a"]},{label:"Fern",colors:["#4f9a3a","#86c06a","#e9f2df","#a9d48c"]},{label:"Mint",colors:["#0f4f2b","#169660","#c8e8d8","#4aae38"]}],PARTS=["deep","mid","light","accent"],round2=value=>Math.round(value*100)/100,oval=(cx,cy,rx,ry,color,turn2=0,opacity)=>({kind:"oval",cx,cy,rx,ry,turn:turn2,color,opacity}),ring=(cx,cy,r,width,color,opacity)=>({kind:"stroke",d:`M${cx-r} ${cy}a${r} ${r} 0 1 0 ${r*2} 0a${r} ${r} 0 1 0 ${-r*2} 0`,width,color,opacity}),FLOWS=[{name:"Glow",base:c=>c.mid,blobs:(c,j)=>[oval(20+j("a",8),10,46,30,c.deep,-15),oval(55+j("b",8),58+j("c",6),26,22,c.light),oval(88,92,30,26,c.accent),oval(30,62,18,16,c.light,0,.8)]},{name:"Horizon",base:c=>c.deep,blobs:(c,j)=>[oval(50,18,70,36,c.deep),oval(50,66,80,10,c.mid,0,.8),oval(50+j("a",10),98,76,22,c.accent),oval(50+j("b",12),106,48,12,c.light)]},{name:"Streak",base:c=>c.deep,blobs:(c,j)=>[oval(40,60,22,56,c.accent,35,.5),oval(52+j("a",6),50,13,50,c.light,35+j("b",10)),oval(88,90,30,26,c.mid),oval(10,8,30,24,c.deep)]},{name:"Arc",base:c=>c.mid,blobs:(c,j)=>[{kind:"stroke",d:`M-10 ${round2(78+j("a",6))}Q50 ${round2(28+j("b",8))} 110 ${round2(78+j("c",6))}`,width:17,color:c.light},oval(50,112,70,24,c.deep),oval(94,4,34,26,c.accent),oval(6,12,26,22,c.deep,0,.7)]},{name:"Swirl",base:c=>c.mid,blobs:(c,j)=>[oval(80,20,40,30,c.deep,20),{kind:"stroke",d:`M10 ${round2(88+j("a",6))}C30 50 ${round2(70+j("b",10))} 70 ${round2(86+j("c",6))} 30`,width:19,color:c.light},oval(14,30,22,26,c.accent),oval(60,104,34,18,c.deep,0,.8)]},{name:"Drift",base:c=>c.mid,blobs:(c,j)=>[oval(24+j("a",8),22+j("b",8),26,22,c.deep),oval(74+j("c",8),30+j("d",8),22,24,c.light),oval(40+j("e",8),70+j("f",8),24,20,c.accent),oval(84,84,22,20,c.deep,0,.8),oval(12,90,20,18,c.light,0,.9)]},{name:"Break",base:c=>c.deep,blobs:(c,j)=>[oval(96+j("a",6),2,40,30,c.mid),oval(82,54,26,30,c.accent,-20),oval(28+j("b",8),96,30,20,c.light),oval(20,26,30,30,c.deep)]},{name:"Split",base:c=>c.light,blobs:(c,j)=>[oval(10,10,72,40,c.deep,-35+j("a",10)),oval(92,92,40,30,c.accent,-35),oval(60,56,18,14,c.light)]},{name:"Bloom",base:c=>c.deep,blobs:(c,j)=>[oval(50,52,40,40,c.accent),oval(50+j("a",6),52+j("b",6),26,26,c.mid),oval(50+j("a",6),52+j("b",6),12,12,c.light)]},{name:"Veil",base:c=>c.light,blobs:(c,j)=>[oval(52+j("a",6),62,50,22,c.mid,-8),oval(24,82+j("b",4),20,12,c.deep,-20),oval(58,76,14,9,c.accent),oval(74,58,18,9,c.deep,15,.6),oval(18,48,16,14,c.mid,0,.9),oval(88,88,16,10,c.mid,0,.8)]},{name:"Rise",base:c=>c.light,blobs:(c,j)=>{let y=110+j("a",6);return[oval(50,y,82,76,mix(c.light,c.mid,.45)),oval(50,y,66,62,c.mid),oval(50,y,52,48,c.deep),oval(50,y,36,34,c.accent),oval(50,y,20,18,mix(c.accent,"#fff6a8",.6))]}},{name:"Rings",base:c=>c.mid,softness:.55,blobs:(c,j)=>[oval(30,10,50,34,c.accent,0,.8),ring(26+j("a",6),34,30,12,c.light),ring(66+j("b",6),14,26,10,c.light,.8),oval(80,96,44,26,c.deep),oval(10,96,26,18,c.deep,0,.8)]}],SOFTNESS=[9,16],auraTraits=(name,overrides)=>calmed(createTraits(name,overrides),CALMING);function named(name){let variant=/^(.*)#(\d+)$/.exec(name);return{from:variant?variant[1]:name,step:variant?Number(variant[2])-1:0}}function stepped(name,overrides,key2,count,order){let{from,step}=named(name),t=createTraits(from,overrides),value=t(key2),own2=Math.min(count-1,Math.floor(value*count));if(t.forced(key2)!==void 0)return own2;let variance=varianceSet(t),list=CALMING.lists?.[key2],plainest=order??(Array.isArray(list?.[2])?list[2]:Array.from({length:count},(_,i)=>i));if(variance===void 0)return(own2+step)%count;let plain=plainest.slice(0,keptOf(count,list?.[1]??Math.min(count,8),variance));return plain[(Math.floor(value*plain.length)+step)%plain.length]}var typeOf=(name,overrides)=>TYPES[stepped(name,overrides,"type",TYPES.length)],flowOf=(name,overrides)=>FLOWS[stepped(name,overrides,"flow",FLOWS.length)],SKY_PICKS=[0,7,13,20],palettesOf=type=>type==="Sky"?SKIES.map(({label,stops:stops2})=>({label,stops:stops2,colors:SKY_PICKS.map(i=>stops2[i])})):PALETTES;function horizonOf(t){let set=t.forced("horizon");if(set!==void 0)return set*2-1;let variance=varianceSet(t);return variance===void 0?0:(t("horizon")*2-1)*variance*.7}function grainOf(t,type){let variance=varianceOf(t),[low,calmest,wildest]=type==="Sky"?[.03,.07,.32]:[.08,.2,.55];return low+t("grain")*(calmest+(wildest-calmest)*variance-low)}var paletteOf=(name,overrides,type)=>stepped(name,overrides,"palette",palettesOf(type).length,PALETTE_ORDER[type]);function palettesOffered(t,type){let order=PALETTE_ORDER[type],variance=varianceSet(t);return variance===void 0?order:order.slice(0,keptOf(order.length,8,variance))}function coloursOf(name,overrides,t,type){let{colors}=palettesOf(type)[paletteOf(name,overrides,type)];return Object.fromEntries(PARTS.map((part,i)=>[part,t.color(part)??colors[i]]))}var FACES=["None","Dots","Calm","Smile"],faceOf=t=>t.forced("face")===void 0?"None":FACES[Math.min(FACES.length-1,Math.floor(t("face")*FACES.length))],FACE_MARKS={None:{eyes:"",mouth:""},Dots:{eyes:'<circle cx="-10" cy="-3" r="3.4"/><circle cx="10" cy="-3" r="3.4"/>',mouth:'<path d="M-5 7Q0 11 5 7" fill="none"/>'},Calm:{eyes:'<path d="M-14 -3Q-10 1 -6 -3M6 -3Q10 1 14 -3" fill="none"/>',mouth:'<path d="M-4 7Q0 10 4 7" fill="none"/>'},Smile:{eyes:'<circle cx="-10" cy="-4" r="3"/><circle cx="10" cy="-4" r="3"/>',mouth:'<path d="M-9 5Q0 15 9 5" fill="none"/>'}};function blobMarkup(blob3){let opacity=blob3.opacity===void 0?"":` opacity="${blob3.opacity}"`;if(blob3.kind==="stroke")return`<path d="${blob3.d}" fill="none" stroke="${blob3.color}" stroke-width="${blob3.width}" stroke-linecap="round"${opacity}/>`;let turn2=blob3.turn?` transform="rotate(${round2(blob3.turn)} ${round2(blob3.cx)} ${round2(blob3.cy)})"`:"";return`<ellipse cx="${round2(blob3.cx)}" cy="${round2(blob3.cy)}" rx="${round2(blob3.rx)}" ry="${round2(blob3.ry)}" fill="${blob3.color}"${turn2}${opacity}/>`}function createAura(name,overrides){let t=auraTraits(name,overrides),type=typeOf(name,overrides),c=coloursOf(name,overrides,t,type),shared={seed:t.int("grain.seed",1,999),face:FACE_MARKS[faceOf(t)],blinkDelay:round2(t.num("blink",0,4))};if(type==="Sky"){let colours=PARTS.some(part=>t.color(part)!==void 0)?PARTS.map(part=>c[part]):SKIES[paletteOf(name,overrides,type)].stops,lift=2**(horizonOf(t)*1.2),stops2=colours.map((color,i)=>`<stop offset="${round2((i/(colours.length-1))**lift)}" stop-color="${color}"/>`).join("");return{type,colour:id=>`<defs><linearGradient id="${id}-sky" gradientUnits="userSpaceOnUse" x1="0" y1="0" x2="0" y2="100">${stops2}</linearGradient></defs><rect x="-60" y="-60" width="220" height="220" fill="url(#${id}-sky)"/>`,blur:0,grain:round2(grainOf(t,type)),turn:0,...shared}}let flow=flowOf(name,overrides),j=(key2,amount)=>t.jitter(`flow.${key2}`,amount),base=`<rect x="-60" y="-60" width="220" height="220" fill="${flow.base(c)}"/>`,shapes=flow.blobs(c,j),blur2=round2(t.num("softness",...SOFTNESS)*(flow.softness??1));return{type,colour:()=>base+shapes.map(blobMarkup).join(""),blur:blur2,grain:round2(grainOf(t,type)),turn:round2(t.jitter("turn",30)),...shared}}var colourLayer=(aura,id)=>aura.blur?`<defs>${blurFilter(`${id}-blur`,aura.blur)}</defs><g filter="url(#${id}-blur)"><g transform="rotate(${aura.turn} 50 50)">${aura.colour(id)}</g></g>`:aura.colour(id),CORNER=22.22,FACE_STYLE='fill="#ffffff" stroke="#ffffff" stroke-width="2.6" stroke-linecap="round" stroke-linejoin="round" opacity="0.92"',grainFilter=(id,frequency,seed)=>`<filter id="${id}" x="0" y="0" width="100%" height="100%" color-interpolation-filters="sRGB"><feTurbulence type="fractalNoise" baseFrequency="${frequency}" numOctaves="3" seed="${seed}" stitchTiles="stitch"/><feColorMatrix type="matrix" values="0.33 0.33 0.33 0 0 0.33 0.33 0.33 0 0 0.33 0.33 0.33 0 0 0 0 0 0 1"/></filter>`,blurFilter=(id,blur2)=>`<filter id="${id}" filterUnits="userSpaceOnUse" x="-60" y="-60" width="220" height="220" color-interpolation-filters="sRGB"><feGaussianBlur stdDeviation="${blur2}"/></filter>`;function auraSvg(name,overrides){let aura=createAura(name,overrides),face=aura.face.eyes?`<g transform="translate(50 52)" ${FACE_STYLE}>${aura.face.eyes}${aura.face.mouth}</g>`:"";return`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><defs><clipPath id="aura-tile"><rect width="100" height="100" rx="${CORNER}"/></clipPath>`+grainFilter("aura-grain",2.2,aura.seed)+'</defs><g clip-path="url(#aura-tile)">'+colourLayer(aura,"aura")+`<rect width="100" height="100" filter="url(#aura-grain)" opacity="${aura.grain}" style="mix-blend-mode:overlay"/>`+face+"</g></svg>"}var controls=(name,overrides)=>{let t=auraTraits(name,overrides),type=typeOf(name,overrides),colours=coloursOf(name,overrides,t,type),face=faceOf(t),sky=type==="Sky",swatch=({colors,stops:stops2})=>stops2?`linear-gradient(${stops2.join(", ")})`:`conic-gradient(${colors.map((color,i)=>`${color} 0 ${(i+1)*25}%`).join(", ")})`;return[{title:"Aura",controls:[{...choice(t,"type","Type","list",TYPES.map(label=>({label}))),selected:String(TYPES.indexOf(type))},...sky?[]:[{...narrowed(choice(t,"flow","Formation","list",FLOWS.map(({name:label})=>({label}))),t,CALMING),selected:String(FLOWS.indexOf(flowOf(name,overrides)))}],(()=>{let control=PARTS.reduce(clearingColor,choice(t,"palette",sky?"Sky":"Palette","swatches",palettesOf(type).map(palette2=>({label:palette2.label,color:swatch(palette2)})))),selected=String(paletteOf(name,overrides,type)),offered=new Set(palettesOffered(t,type).map(String));return{...control,selected,options:control.options.filter(option=>offered.has(option.id)||option.id===selected)}})(),...sky?[{type:"slider",id:"horizon",label:"Horizon",value:(horizonOf(t)+1)/2,display:`${Math.round(horizonOf(t)*100)}%`,range:[-100,100],ends:["Lower","Higher"]}]:[],{type:"colors",id:"aura.colors",label:"Colours",colors:PARTS.map(part=>({id:colorKey(part),color:colours[part]}))},possibilitiesSlider(t,NOTES),slider(t,"grain","Grain",0,100,"%"),...sky?[]:[slider(t,"softness","Softness",0,100,"%"),slider(t,"turn","Turn",-30,30,"\xB0")]]},{title:"Face",controls:[{...choice(t,"face","Face","list",FACES.map(label=>({label}))),selected:String(FACES.indexOf(face))}]}]};var TONES=[[.2,{l:.86,c:.085}],[.36,{l:.9,c:.028}],[.62,{l:.73,c:.135}],[.8,{l:.62,c:.165}],[.93,{l:.87,c:.16}],[1,{l:.34,c:.035}]],TONE_BANDS=[{label:"Pastel",weight:.2},{label:"Pale",weight:.16},{label:"Mid",weight:.26},{label:"Deep",weight:.18},{label:"Bright",weight:.13},{label:"Ink",weight:.07}],DARK_SURFACE={l:.145,c:0,h:0},SURFACE_CONTRAST=1.5,PLATE_CONTRAST=1.25,EYE_CONTRAST=4.5,cube=v=>v*v*v;function toLinear({l,c,h}){let radians=h*Math.PI/180,a=c*Math.cos(radians),b=c*Math.sin(radians),lp=cube(l+.3963377774*a+.2158037573*b),mp=cube(l-.1055613458*a-.0638541728*b),sp=cube(l-.0894841775*a-1.291485548*b);return[4.0767416621*lp-3.3077115913*mp+.2309699292*sp,-1.2684380046*lp+2.6097574011*mp-.3413193965*sp,-.0041960863*lp-.7034186147*mp+1.707614701*sp]}var inGamut=rgb=>rgb.every(v=>v>=-1e-4&&v<=1+1e-4);function toDisplayable(color){let rgb=toLinear(color);if(!inGamut(rgb)){let low=0,high=color.c;for(let i=0;i<12;i++){let mid=(low+high)/2;inGamut(toLinear({...color,c:mid}))?low=mid:high=mid}rgb=toLinear({...color,c:low})}return rgb.map(v=>Math.min(1,Math.max(0,v)))}function luminance2(color){let[r,g,b]=toDisplayable(color);return .2126*r+.7152*g+.0722*b}function contrast2(a,b){let x=luminance2(a),y=luminance2(b);return(Math.max(x,y)+.05)/(Math.min(x,y)+.05)}function ensureContrast(fg,bg,min){if(contrast2(fg,bg)>=min)return fg;let lean=fg.l>=bg.l?1:-1;for(let direction of[lean,-lean]){let probe={...fg};for(let i=0;i<60;i++){if(probe.l=Math.min(1,Math.max(0,probe.l+direction*.02)),contrast2(probe,bg)>=min)return probe;if(probe.l===0||probe.l===1)break}}let black={...fg,l:0,c:0},white={...fg,l:1,c:0};return contrast2(black,bg)>=contrast2(white,bg)?black:white}function toHex(color){return`#${toDisplayable(color).map(v=>{let encoded=v<=.0031308?12.92*v:1.055*v**.4166666666666667-.055;return Math.round(encoded*255).toString(16).padStart(2,"0")}).join("")}`}function createPalette(hue,tone2,picked){if(picked)return{head:picked,eye:inkOn(picked)};let swatch=(TONES.find(([edge])=>tone2<edge)??TONES[0])[1],plate={l:.965,c:.01,h:hue},onDark=ensureContrast({...swatch,h:hue},DARK_SURFACE,SURFACE_CONTRAST),head2=ensureContrast(onDark,plate,PLATE_CONTRAST),eye3=onDark.l>=.5?{l:.17,c:.02,h:hue}:{l:.97,c:.012,h:hue};return{head:toHex(head2),eye:toHex(ensureContrast(eye3,head2,EYE_CONTRAST))}}var CONTAINERS=["#17181c","#e6e1ff","#1f2a44","#d6f0ff","#3a2346","#ffe4d6","#163a33","#fff1c4","#ffd8e6"],RANGE=[.5,1],POSITION=.8,sizeAt=position=>RANGE[0]+(RANGE[1]-RANGE[0])*position,CORNER2=.22,FILL=.86,round22=value=>Math.round(value*100)/100,shown=t=>(t.forced("container")??1)<.5;function containerOf(t){if(shown(t))return{size:sizeAt(t.forced("container.size")??POSITION),color:t.color("container.color")??CONTAINERS[0]}}function containerControls(t){let on=shown(t),toggle2={type:"choice",id:"container",label:"Container",layout:"switch",options:[{id:"on",label:"On",set:{container:0}},{id:"off",label:"Off",set:{container:void 0}}],selected:on?"on":"off"};if(!on)return[toggle2];let position=t.forced("container.size")??POSITION,size={type:"slider",id:"container.size",label:"Container size",value:position,display:`${Math.round(sizeAt(position)*100)}%`,range:[RANGE[0]*100,RANGE[1]*100]};return[toggle2,size,fixedPalette(t,"container.color","Container colour",CONTAINERS)]}function inContainer(art,container,id){let open2='<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">';if(!container)return`${open2}${art}</svg>`;let side=round22(container.size*100),card=`<rect x="${round22(50-side/2)}" y="${round22(50-side/2)}" width="${side}" height="${side}" rx="${round22(side*CORNER2)}"/>`;return open2+`<clipPath id="${id}">${card}</clipPath>`+card.replace("/>",` fill="${container.color}"/>`)+`<g clip-path="url(#${id})"><g transform="translate(50 50) scale(${round22(container.size*FILL)}) translate(-50 -50)">${art}</g></g></svg>`}var round23=v=>Math.round(v*100)/100,fmt=v=>{let rounded=round23(v);return Object.is(rounded,-0)?"0":String(rounded)},wrap=(items,i)=>items[(i%items.length+items.length)%items.length];function superellipse({cx,cy,rx,ry,n,rot}){let k=Math.min(1,(8*2**(-1/n)-4)/3),ax=rx*k,ay=ry*k,points=[[rx,0],[rx,ay],[ax,ry],[0,ry],[-ax,ry],[-rx,ay],[-rx,0],[-rx,-ay],[-ax,-ry],[0,-ry],[ax,-ry],[rx,-ay],[rx,0]],angle=rot*Math.PI/180,cos=Math.cos(angle),sin=Math.sin(angle),at3=i=>{let[x,y]=points[i];return`${fmt(cx+x*cos-y*sin)} ${fmt(cy+x*sin+y*cos)}`},d=`M${at3(0)}`;for(let i=1;i<13;i+=3)d+=`C${at3(i)} ${at3(i+1)} ${at3(i+2)}`;return`${d}Z`}function circle(cx,cy,r){let left=`${fmt(cx-r)} ${fmt(cy)}`,right=`${fmt(cx+r)} ${fmt(cy)}`;return`M${left}A${fmt(r)} ${fmt(r)} 0 1 0 ${right}A${fmt(r)} ${fmt(r)} 0 1 0 ${left}Z`}function spline(cx,cy,rx,ry,radii,rot){let start=rot*Math.PI/180,points=radii.map((radius,i)=>{let angle=start+2*Math.PI*i/radii.length;return[cx+rx*radius*Math.cos(angle),cy+ry*radius*Math.sin(angle)]}),[firstX,firstY]=points[0],d=`M${fmt(firstX)} ${fmt(firstY)}`;for(let i=0;i<points.length;i++){let[x0,y0]=wrap(points,i-1),[x1,y1]=wrap(points,i),[x2,y2]=wrap(points,i+1),[x3,y3]=wrap(points,i+2);d+=`C${fmt(x1+(x2-x0)/6)} ${fmt(y1+(y2-y0)/6)} ${fmt(x2-(x3-x1)/6)} ${fmt(y2-(y3-y1)/6)} ${fmt(x2)} ${fmt(y2)}`}return`${d}Z`}function polygon({cx,cy,rx,ry,sides,round:round4,rot}){let k=round4>0?round4<1?round4/2:.5:0,start=rot*Math.PI/180-Math.PI/2,vertices=Array.from({length:sides},(_,i)=>{let angle=start+2*Math.PI*i/sides;return[cx+rx*Math.cos(angle),cy+ry*Math.sin(angle)]}),cut=(i,j)=>{let[x0,y0]=wrap(vertices,i),[x1,y1]=wrap(vertices,j);return`${fmt(x0+(x1-x0)*k)} ${fmt(y0+(y1-y0)*k)}`},d=`M${cut(0,-1)}`;for(let i=0;i<sides;i++){let[x,y]=wrap(vertices,i);d+=`Q${fmt(x)} ${fmt(y)} ${cut(i,i+1)}`,k<.5&&(d+=`L${cut(i+1,i)}`)}return`${d}Z`}function box(cx,cy,rx,ry){let left=fmt(cx-rx),right=fmt(cx+rx);return`M${left} ${fmt(cy-ry)}H${right}V${fmt(cy+ry)}H${left}Z`}function taper(cx,cy,rx,ry,tip){let height=Math.max(1.05,tip),tangentX=rx*Math.sqrt(1-1/(height*height)),tangentY=cy-ry/height,apex=cy-height*ry,easeX=tangentX*.14,easeY=tangentY+.86*(apex-tangentY);return`M${fmt(cx-tangentX)} ${fmt(tangentY)}L${fmt(cx-easeX)} ${fmt(easeY)}Q${fmt(cx)} ${fmt(apex)} ${fmt(cx+easeX)} ${fmt(easeY)}L${fmt(cx+tangentX)} ${fmt(tangentY)}Z`}var polygonPath=b=>polygon({...b,sides:b.sides,round:b.round}),splinePath=b=>spline(b.cx,b.cy,b.rx,b.ry,b.radii,b.rot),shrunk=k=>b=>({cx:b.cx,cy:b.cy,rx:b.rx*k,ry:b.ry*k}),splineFace=b=>shrunk(Math.min(...b.radii)*.95)(b),round={name:"Round",core:1},organic={name:"Organic",core:.98,path:splinePath,face:splineFace},boxy={name:"Boxy",core:.86,body:(t,b)=>{b.n=t.num("body.n",3.4,6),b.rot=t.num("body.rot",-20,20)}},capsule={name:"Capsule",core:1.02,body:(t,b)=>{b.ry*=t.num("capsule.squat",.55,.68)},face:shrunk(.94),decorate:(_t,b,out)=>{for(let side of[-1,1])out.circles.push({cx:b.cx+side*(b.rx-b.ry),cy:b.cy,r:b.ry})},path:b=>box(b.cx,b.cy,b.rx-b.ry,b.ry)},nub={name:"Nub",core:.88,decorate:(t,b,out)=>{let count=t.int("nub.n",1,2);for(let i=0;i<count;i++){let angle=t.num(`nub.a${i}`,0,2*Math.PI);out.circles.push({cx:b.cx+Math.cos(angle)*b.rx*.88,cy:b.cy+Math.sin(angle)*b.rx*.88,r:b.rx*t.num(`nub.r${i}`,.24,.4)})}}},cloud={name:"Cloud",core:.78,face:splineFace,path:splinePath,decorate:(t,b,out)=>{let count=t.int("cloud.n",4,6);for(let i=0;i<count;i++){let angle=Math.PI+Math.PI*(i+.5)/count;out.circles.push({cx:b.cx+Math.cos(angle)*b.rx*.8,cy:b.cy+Math.sin(angle)*b.rx*.5,r:b.rx*t.num(`cloud.r${i}`,.44,.62)})}}},droplet={name:"Droplet",core:.78,body:(_t,b)=>{b.cy+=.22*b.ry,b.n=2},face:b=>({cx:b.cx,cy:b.cy+b.ry*.05,rx:b.rx*.88,ry:b.ry*.88}),decorate:(t,b,out)=>{out.paths.push(taper(b.cx,b.cy,b.rx,b.ry,t.num("droplet.tip",1.4,1.65)))}},hexagon={name:"Hexagon",core:1.05,path:polygonPath,face:shrunk(.84),body:(t,b)=>{b.sides=6,b.rot=t.num("body.rot",-12,12),b.round=t.num("poly.round",.24,.5)}},sun={name:"Sun",core:.7,decorate:(t,b,out)=>{let count=t.int("sun.n",6,9),distance2=b.rx*t.num("sun.dist",1,1.08),radius=b.rx*t.num("sun.r",.2,.26),offset=t.num("sun.rot",0,2*Math.PI);for(let i=0;i<count;i++){let angle=offset+2*Math.PI*i/count;out.circles.push({cx:b.cx+Math.cos(angle)*distance2,cy:b.cy+Math.sin(angle)*distance2,r:radius})}}},triangle={name:"Triangle",core:1.15,path:polygonPath,body:(t,b)=>{b.sides=3,b.rot=t.num("body.rot",-5,5),b.round=t.num("poly.round",.24,.5)},face:b=>({cx:b.cx,cy:b.cy+b.ry*.1,rx:b.rx*.54,ry:b.ry*.36})},BANDS=[[round,.22],[organic,.48],[boxy,.6],[capsule,.7],[nub,.79],[cloud,.86],[droplet,.915],[hexagon,.95],[sun,.98],[triangle,1]],r2=value=>Math.round(value*100)/100,PLAIN=[{name:"Oval",core:.95,body:(_t,b)=>{b.rx*=.8,b.ry*=1.12,b.n=2}},{name:"Pill",core:.98,body:(t,b)=>{b.rx*=.62,b.n=t.num("pill.n",2.6,3.2)},face:shrunk(.9)},{name:"Spindle",core:1.04,body:(t,b)=>{b.ry*=t.num("spindle.squat",.5,.62)},face:shrunk(.66),path:({cx,cy,rx,ry})=>`M${r2(cx-rx)} ${r2(cy)}Q${r2(cx)} ${r2(cy-ry*2)} ${r2(cx+rx)} ${r2(cy)}Q${r2(cx)} ${r2(cy+ry*2)} ${r2(cx-rx)} ${r2(cy)}Z`},{name:"Diamond",core:.84,body:(t,b)=>{b.n=t.num("diamond.n",2.6,3.4),b.rot=45},face:shrunk(.74)},{name:"Wide",core:1.04,body:(_t,b)=>{b.ry*=.66,b.n=2.2},face:shrunk(.9)}],pickShape=value=>(BANDS.find(([,edge])=>value<edge)??BANDS[BANDS.length-1])[0],drawBody=(shape,body)=>shape.path?shape.path(body):superellipse(body);var SHAPE_PICK="shape.pick",byName=name=>[...BANDS.map(([shape])=>shape),...PLAIN].find(shape=>shape.name===name),EVERY_SHAPE=["Round","Boxy","Capsule","Oval","Pill","Spindle","Diamond","Wide","Droplet","Hexagon","Organic","Triangle","Nub","Cloud","Sun"].map(byName),FEWEST=8;function shapesOffered(t){let variance=varianceSet(t);return variance===void 0?BANDS.map(([shape])=>shape):EVERY_SHAPE.slice(0,FEWEST+Math.floor(variance*(EVERY_SHAPE.length-FEWEST+1)))}function shapeFor(t){let picked=t.forced(SHAPE_PICK);if(picked!==void 0)return EVERY_SHAPE[Math.floor(picked*EVERY_SHAPE.length)];if(varianceSet(t)===void 0)return pickShape(t("shape"));let offered=shapesOffered(t);return offered[Math.floor(t("shape")*offered.length)]}var pickOf=shape=>({[SHAPE_PICK]:(EVERY_SHAPE.indexOf(shape)+.5)/EVERY_SHAPE.length}),calmed2=t=>calmed(t,{features:/^(body|eye|gaze|capsule|nub|cloud|droplet|poly|sun)\./}),NOTES2=["calm, simple shapes like circles, ovals, pills and rounded squares, with even eyes.","a wider mix, adding drops, hexagons and soft lumps.","anything goes, from lumpy clouds to triangles and rays."];var HUE_SWATCHES=11,EXTRAS={Round:[["body.n","Softness",0,100,"%"]],Organic:[["body.pts","Lumps",6,8]],Boxy:[["body.n","Squareness",0,100,"%"],["body.rot","Tilt",-20,20,"\xB0"]],Capsule:[["capsule.squat","Thickness",0,100,"%"]],Nub:[["nub.n","Nubs",1,2]],Cloud:[["cloud.n","Lobes",4,6]],Droplet:[["droplet.tip","Point",0,100,"%"]],Hexagon:[["poly.round","Corners",0,100,"%"],["body.rot","Tilt",-12,12,"\xB0"]],Sun:[["sun.n","Rays",6,9],["sun.r","Ray size",0,100,"%"]],Triangle:[["poly.round","Corners",0,100,"%"],["body.rot","Tilt",-5,5,"\xB0"]],Oval:[],Pill:[["pill.n","Squareness",0,100,"%"]],Spindle:[["spindle.squat","Thickness",0,100,"%"]],Diamond:[["diamond.n","Squareness",0,100,"%"]],Wide:[]};function shapeControl(t){let shape=shapeFor(t),offered=shapesOffered(t);return{type:"choice",id:"shape",label:"Shape",layout:"list",options:(offered.includes(shape)?offered:[...offered,shape]).map(entry=>({id:entry.name,label:entry.name,set:pickOf(entry)})),selected:shape.name}}var controls2=(name,overrides)=>{let t=createTraits(name,overrides),shape=shapeFor(t),extras=EXTRAS[shape.name].map(([key2,label,min,max,unit])=>Number.isInteger(min)&&max-min<10?choice(t,key2,label,max-min<3?"segmented":"list",Array.from({length:max-min+1},(_,i)=>({label:String(min+i)}))):slider(t,key2,label,min,max,unit)),hues=Array.from({length:HUE_SWATCHES},(_,i)=>createPalette((i+.5)*360/HUE_SWATCHES,t("tone")).head);return[{title:"Body",controls:[possibilitiesSlider(t,NOTES2),shapeControl(t),slider(t,"body.r","Body size",0,100,"%"),slider(t,"body.ratio","Stretch",0,100,"%"),...extras]},{title:"Colour",controls:[palette(t,"hue","Colour",hues),clearingColor(choice(t,"tone","Tone","list",TONE_BANDS),"hue")]},{title:"Eyes",controls:[slider(t,"eye.rx","Eye size",0,100,"%"),slider(t,"eye.ratio","Eye height",0,100,"%"),slider(t,"eye.gap","Gap",0,100,"%"),slider(t,"eye.lean","Lean",-100,100,"%"),slider(t,"gaze.x","Look across",-100,100,"%"),slider(t,"gaze.y","Look up",-100,100,"%")]},{title:"Container",controls:containerControls(t)}]};function layoutEyes(t,body,face){let baseWidth=t.num("eye.rx",.075,.105)*body.rx,ratio=t.num("eye.ratio",1.9,3.2),scale=t.num("eye.scale",.78,1.24),stretch=t.num("eye.stretch",.85,1.18),clearance=t.num("eye.gap",.1,.24)*body.rx,widest=baseWidth*Math.max(1,scale),tallest=baseWidth*ratio*Math.max(1,scale*stretch),baseGap=widest+body.rx*.03+clearance,gazeX=t.jitter("gaze.x",.09)*face.rx,gazeY=t.num("gaze.y",-.2,.08)*face.ry,offsetY=t.jitter("eye.dy",.04)*face.ry,reach=Math.hypot(widest,tallest),needed=Math.hypot((Math.abs(gazeX)+baseGap+reach)/face.rx,(Math.abs(gazeY)+Math.abs(offsetY)+reach)/face.ry),fit=needed>.9?.9/needed:1,width=baseWidth*fit,height=width*ratio,gap=baseGap*fit,room=Math.max(0,Math.min(1,clearance/tallest)),maxLean=Math.min(12,Math.asin(room)*180/Math.PI),lean=t.num("eye.lean",-1,1)*maxLean,secondLean=Math.max(-12,Math.min(12,lean+t.jitter("eye.lean2",3.5))),cx=face.cx+gazeX*fit,cy=face.cy+gazeY*fit,n=t.num("eye.n",3.5,6);return[{cx:cx-gap,cy,rx:width,ry:height,n,rot:lean},{cx:cx+gap,cy:cy+offsetY*fit,rx:width*scale,ry:height*scale*stretch,n,rot:secondLean}]}function describe(name,overrides){let t=calmed2(createTraits(name,overrides)),{head:head2,eye:eye3}=createPalette(t.num("hue",0,360),t("tone"),t.color("hue")),shape=shapeFor(t),radius=t.num("body.r",31,38)*shape.core,body={cx:50+t.jitter("body.x",1.5),cy:50+t.jitter("body.y",1.5),rx:radius,ry:radius*t.num("body.ratio",.92,1.08),n:t.num("body.n",1.9,2.5),rot:0,radii:Array.from({length:t.int("body.pts",6,8)},(_,i)=>1+t.jitter(`body.r${i}`,.16))};shape.body?.(t,body);let face=shape.face?.(body)??body,decoration={circles:[],paths:[]};shape.decorate?.(t,body,decoration);let[left,right]=layoutEyes(t,body,face);return{head:head2,eye:eye3,circles:decoration.circles,bodyPaths:[...decoration.paths,drawBody(shape,body)],eyes:[left,right],container:containerOf(t)}}function blobParts(name,overrides){let{head:head2,eye:eye3,circles,bodyPaths,eyes:eyes2,container}=describe(name,overrides),[left,right]=eyes2;return{colors:{body:head2,accent:head2,visor:head2,light:eye3},head:[...circles.map(({cx,cy,r})=>circle(cx,cy,r)),...bodyPaths],accents:[],visor:[],visorShapes:[],eyes:eyes2.map(superellipse),eyeShapes:eyes2.map(e=>({kind:"superellipse",...e})),lights:[],lightShapes:[],chrome:[],chromeShapes:[],studs:[],studShapes:[],speckle:0,eyeY:(left.cy+right.cy)/2,painted:!0,container}}function generateBlob(name,overrides){let{head:head2,eye:eye3,circles:circleList,bodyPaths,eyes:eyeList,container}=describe(name,overrides),circles=circleList.map(({cx,cy,r})=>`<circle cx="${round23(cx)}" cy="${round23(cy)}" r="${round23(r)}"/>`).join(""),paths=bodyPaths.map(d=>`<path d="${d}"/>`).join(""),eyes2=eyeList.map(e=>`<path d="${superellipse(e)}"/>`).join("");return inContainer(`<g fill="${head2}">${circles}${paths}</g><g fill="${eye3}">${eyes2}</g>`,container,"blob-card")}var CALMING2={features:/^(depth|lean|tilt|spread|eyes\.y|core\.y|body\.size|eye\.(gap|lean|size))$/,lists:{shape:[18,8,[1,3,6,15,17,9,12,0,7,10,16,14,5,2,11,8,4,13]],"eye.kind":[12,1]},rarer:["mouth"]},NOTES3=["soft, simple shapes like capsules, eggs, pebbles and pillows, with one kind of eye.","adds apples, gems, peanuts, clouds and clovers, and more kinds of eye.","anything goes, up to flowers, stars and bursts."];function draw(element,colors,idPrefix){let attributes2=Object.entries(element.attributes??{}).map(([key2,raw])=>{let value=typeof raw=="string"?raw:colors[raw.name],scoped=key2==="id"?`${idPrefix}${value}`:value.replace("url(#",`url(#${idPrefix}`);return` ${key2}="${scoped}"`}).join(""),children=(element.children??[]).map(child=>draw(child,colors,idPrefix)).join("");return`<${element.name}${attributes2}>${children}</${element.name}>`}var scopeIds=(markup,stem,ids)=>ids===stem?markup:markup.replace(new RegExp(`(id="|href="#|url\\(#)${stem}-`,"g"),`$1${ids}-`);function scopeAll(avatar,stem,ids){if(ids===stem)return avatar;let scope=value=>typeof value=="string"?scopeIds(value,stem,ids):Array.isArray(value)?value.map(scope):value;return Object.fromEntries(Object.entries(avatar).map(([key2,value])=>[key2,scope(value)]))}function pickVariant(t,key2,variants,names=Object.keys(variants)){let remaining=t(key2)*names.reduce((sum,name)=>sum+(variants[name].weight??1),0);for(let name of names)if(remaining-=variants[name].weight??1,remaining<0)return name;return names[names.length-1]}var PALETTES2=[{label:"Azure",core:"#1584ff",accent:"#3deaff"},{label:"Lemon",core:"#ffb800",accent:"#fff35c"},{label:"Magenta",core:"#ff0a9c",accent:"#ff7ae6"},{label:"Ocean",core:"#0057ff",accent:"#00e0c6"},{label:"Emerald",core:"#08c236",accent:"#3fe6c4"},{label:"Plum",core:"#9b1fe8",accent:"#ff5cab"},{label:"Sunset",core:"#ff4d1a",accent:"#ffc02e"},{label:"Teal",core:"#008f8f",accent:"#5cc8ff"},{label:"Violet",core:"#7032ff",accent:"#e05cff"},{label:"Lime",core:"#5ccc00",accent:"#e6ff4d"},{label:"Coral",core:"#ff2a52",accent:"#ff9d5c"},{label:"Grape",core:"#4b1fd1",accent:"#ff7ad9"},{label:"Lagoon",core:"#00aec4",accent:"#3cf2a6"},{label:"Ruby",core:"#e0002e",accent:"#ff3dd2"},{label:"Indigo",core:"#2c31ff",accent:"#35c0ff"},{label:"Peach",core:"#ff7a45",accent:"#ffb3c7"},{label:"Arctic",core:"#00b3ff",accent:"#a5f3ff"},{label:"Mango",core:"#ff8c00",accent:"#ffe14d"},{label:"Forest",core:"#00995c",accent:"#7dff8a"},{label:"Rose",core:"#ff3d7f",accent:"#ffc2e0"},{label:"Cobalt",core:"#1a3dff",accent:"#9d7dff"},{label:"Candy",core:"#ff3db8",accent:"#ffd23d"},{label:"Aqua",core:"#00d4b4",accent:"#4da6ff"},{label:"Amber",core:"#ff9f1a",accent:"#ff4d6d"}],PHRASES=["say hi!","good vibes only","hello, legend","stay curious","big mood","main character","dream bigger","on a roll","pure magic","made you look","vibe check","soft launch","stay golden","level up","zero chill","hey, you"];var EYE_KINDS=["Pill","Oval","Dot","Slit","Wide","Bar","Square","Diamond","Happy","Sparkle","Heart","Cross"],MOUTH_ODDS=30,MOUTHS=["Smile","Grin","Ooh","Cat","Flat","Smirk","Wobbly"],MAX_TEXT=28,VIEW_BOX="-2 -2 104 104",REACH=49,OUTLINE_POINTS=360,MONO="ui-monospace, 'SF Mono', Menlo, Consolas, 'Liberation Mono', monospace",CHARACTER=.6,TITLE_SIZE=7.6,SEEDS=997,round24=value=>Math.round(value*100)/100,escaped=text=>text.replace(/[&<>"']/g,char=>`&#${char.charCodeAt(0)};`),turn=(t,key2)=>t.num(key2,0,2*Math.PI),SHAPES=[{name:"Scallop",effect:"wiggle",waves:t=>[[t.int("scallop.n",12,15),t.num("depth",.05,.07),turn(t,"a")]]},{name:"Capsule",effect:"bounce",wide:1.65,lean:16,waves:t=>[[4,t.num("depth",-.1,-.06),0],[2,.03,0]]},{name:"Clover",effect:"squish",wide:1.12,lean:10,waves:t=>[[4,t.num("depth",.16,.2),0],[8,-.055,0],[2,.04,turn(t,"a")]]},{name:"Egg",effect:"bounce",wide:.72,lean:14,waves:t=>[[1,t.num("depth",.07,.12),Math.PI/2],[3,.025,turn(t,"a")]]},{name:"Star",effect:"wiggle",lean:14,waves:t=>[[5,t.num("depth",.2,.25),-Math.PI/2],[10,.025,-Math.PI]]},{name:"Cloud",effect:"squish",wide:1.5,lean:6,waves:t=>[[6,t.num("depth",.07,.1),turn(t,"a")],[3,.05,turn(t,"b")],[12,-.018,0]]},{name:"Pillow",effect:"bounce",waves:t=>[[3,t.num("depth",.11,.14),turn(t,"a")],[2,.07,turn(t,"b")],[6,.04,turn(t,"c")]]},{name:"Apple",effect:"bounce",wide:1.08,lean:14,waves:t=>[[1,t.num("depth",.68,.76),-Math.PI/2]]},{name:"Flower",effect:"wiggle",waves:t=>[[6,t.num("depth",.17,.21),turn(t,"a")],[12,-.05,0]]},{name:"Bean",effect:"squish",wide:1.3,lean:22,waves:t=>[[2,t.num("depth",.16,.2),Math.PI/2],[1,.1,Math.PI/2],[3,.09,-Math.PI/2]]},{name:"Gem",effect:"wiggle",wide:1.18,lean:12,waves:t=>[[6,t.num("depth",-.09,-.07),0],[2,.03,0]]},{name:"Trefoil",effect:"squish",lean:18,waves:t=>[[3,t.num("depth",.2,.25),-Math.PI/2],[6,-.06,-Math.PI]]},{name:"Kite",effect:"bounce",wide:.84,waves:t=>[[4,t.num("depth",.13,.17),0],[8,.035,0]]},{name:"Burst",effect:"wiggle",waves:t=>[[t.int("burst.n",8,10),t.num("depth",.12,.15),turn(t,"a")]]},{name:"Peanut",effect:"squish",lean:20,waves:t=>[[2,t.num("depth",.3,.34),0],[4,-.03,0]]},{name:"Tile",effect:"bounce",lean:24,waves:t=>[[4,t.num("depth",-.11,-.08),0]]},{name:"Prism",effect:"bounce",lean:14,waves:t=>[[3,t.num("depth",.1,.13),Math.PI/2],[6,.015,0]]},{name:"Pebble",effect:"squish",wide:1.22,lean:20,waves:t=>[[2,t.num("depth",.05,.08),turn(t,"a")],[3,.05,turn(t,"b")],[5,.03,turn(t,"c")]]}],shapeOf=t=>t.pick("shape",SHAPES);function drawOutline(t,shape){let waves=shape.waves(t),wide=shape.wide??1,lean=t.jitter("lean",shape.lean??0)*Math.PI/180,turned2=Array.from({length:OUTLINE_POINTS},(_,i)=>{let angle=i*2*Math.PI/OUTLINE_POINTS,r=1+waves.reduce((sum,[count,depth,start])=>sum+depth*Math.cos(count*angle+start),0),x=r*wide*Math.cos(angle),y=r*Math.sin(angle);return[x*Math.cos(lean)-y*Math.sin(lean),x*Math.sin(lean)+y*Math.cos(lean)]}),middle=axis=>{let values=turned2.map(point4=>point4[axis]);return(Math.min(...values)+Math.max(...values))/2},[mx,my]=[middle(0),middle(1)],raw=turned2.map(([x,y])=>[x-mx,y-my]),scale=REACH*t.num("body.size",.88,1)/Math.max(...raw.flatMap(([x,y])=>[Math.abs(x),Math.abs(y)])),points=raw.map(([x,y])=>[50+x*scale,50+y*scale]),reachAlong=(axis,at3)=>Math.min(...[-1,1].map(side=>Math.max(0,...points.filter(p=>Math.abs(p[1-axis]-at3)<3&&(p[axis]-50)*side>0).map(p=>Math.abs(p[axis]-50)))));return{d:`M${points.map(([x,y])=>`${round24(x)} ${round24(y)}`).join("L")}Z`,rx:scale*wide,ry:scale,across:y=>reachAlong(0,y),tall:reachAlong(1,50)}}function coloursOf2(t){let palette2=PALETTES2[Math.floor(t("palette")*PALETTES2.length)],core=t.color("core")??palette2.core;return{core,accent:t.color("accent")??palette2.accent,edge:t.color("edge")??mix(core,WHITE,.5)}}var defaultTitle=t=>t.pick("title",PHRASES),over=({cx,cy,rx,ry})=>`gradientUnits="userSpaceOnUse" cx="0" cy="0" r="1" gradientTransform="translate(${round24(cx)} ${round24(cy)}) scale(${round24(rx)} ${round24(ry)})"`;function grainFilter2(id,seed,cut){return`<filter id="${id}" x="0" y="0" width="100%" height="100%" color-interpolation-filters="sRGB"><feTurbulence type="fractalNoise" baseFrequency="1.73 1.57" numOctaves="2" seed="${seed}"/><feColorMatrix values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 20 ${round24(cut)}"/><feComposite in2="SourceAlpha" operator="in"/></filter>`}function drawDefs(t,outline,rx,ry,core,accent){let blend2=t.num("blend",.22,.62),seed=t.int("grain.seed",1,SEEDS),cut=t.num("grain",-15.6,-14.2),centre={cx:50+t.jitter("core.x",.3)*rx,cy:50+t.jitter("core.y",.28)*ry,rx:rx*.98,ry:ry*.98},side=turn(t,"accent.side"),sideways={cx:50+Math.cos(side)*rx*.92,cy:50+Math.sin(side)*ry*.92,rx:rx*.9,ry:ry*.72};return`<defs><path id="bubble-shape" d="${outline}"/><clipPath id="bubble-clip"><use href="#bubble-shape"/></clipPath><radialGradient id="bubble-core" ${over(centre)}><stop offset="0" stop-color="${core}"/><stop offset="${round24(blend2)}" stop-color="${core}"/><stop offset="1" stop-color="${core}" stop-opacity="0"/></radialGradient><radialGradient id="bubble-accent" ${over(sideways)}><stop offset="0" stop-color="${accent}"/><stop offset="1" stop-color="${accent}" stop-opacity="0"/></radialGradient><radialGradient id="bubble-rim" ${over({cx:50,cy:50,rx,ry})}><stop offset="0.55" stop-color="#000"/><stop offset="0.98" stop-color="#fff"/></radialGradient><mask id="bubble-edges" maskUnits="userSpaceOnUse" x="-2" y="-2" width="104" height="104"><rect x="-2" y="-2" width="104" height="104" fill="url(#bubble-rim)"/></mask><filter id="bubble-soft" x="-5%" y="-5%" width="110%" height="110%"><feGaussianBlur stdDeviation="0.3"/></filter>`+grainFilter2("bubble-grain",seed,cut)+grainFilter2("bubble-rim-grain",seed+1,cut+.8)+"</defs>"}var EYE_SIZES={Pill:[4,10.5],Oval:[5.6,8],Dot:[5.6,5.6],Slit:[2.6,11.5],Wide:[8.4,5],Bar:[9,2.8],Square:[6,6,1.6],Diamond:[5.6,5.6,1,45]},LINE='fill="none" stroke="#fff" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"',EYE_PATHS={Happy:`<path d="M-2.8 1.4Q0 -3 2.8 1.4" ${LINE}/>`,Sparkle:'<path d="M0 -4Q0.7 -0.7 4 0Q0.7 0.7 0 4Q-0.7 0.7 -4 0Q-0.7 -0.7 0 -4Z" fill="#fff"/>',Heart:'<path d="M0 3.4C-4.6 0.4 -3.6 -3.6 -1.4 -3.2C-0.6 -3 0 -2.2 0 -1.6C0 -2.2 0.6 -3 1.4 -3.2C3.6 -3.6 4.6 0.4 0 3.4Z" fill="#fff"/>',Cross:`<path d="M-2.2 -2.2L2.2 2.2M2.2 -2.2L-2.2 2.2" ${LINE}/>`},MOUTH_PATHS={Smile:`<path d="M-3 -0.6Q0 2.6 3 -0.6" ${LINE}/>`,Grin:'<path d="M-3.4 -1.2H3.4Q3.4 3 0 3Q-3.4 3 -3.4 -1.2Z" fill="#fff"/>',Ooh:'<ellipse rx="1.7" ry="2.2" fill="#fff"/>',Cat:`<path d="M-3.4 -0.4Q-1.7 2 0 -0.2Q1.7 2 3.4 -0.4" ${LINE}/>`,Flat:`<path d="M-2.6 0H2.6" ${LINE}/>`,Smirk:`<path d="M-2.6 0.6Q0.6 1.6 3 -1" ${LINE}/>`,Wobbly:`<path d="M-3.6 0Q-2.7 -1.2 -1.8 0T0 0T1.8 0T3.6 0" ${LINE}/>`},eyeKindOf=t=>t.pick("eye.kind",EYE_KINDS),mouthOf=t=>t("mouth")*100<MOUTH_ODDS?t.pick("mouth.kind",MOUTHS):void 0;function drawEyes(t,eyesY){let scale=t.num("eye.size",.8,1.3),gap=t.num("eye.gap",4.6,11)*scale,lean=round24(t.num("eye.lean",-24,24)),kind=eyeKindOf(t),drawn=EYE_PATHS[kind];if(drawn)return[50-gap,50+gap].map(x=>`<g><g transform="translate(${round24(x)} ${eyesY}) rotate(${lean}) scale(${round24(scale)})">${drawn}</g></g>`).join("");let[wide,tall,corner,turned2=0]=EYE_SIZES[kind],width=round24(wide*scale),height=round24(tall*scale),rx=round24(corner===void 0?Math.min(width,height)/2:corner*scale);return[50-gap,50+gap].map(x=>`<g><rect x="${round24(x-width/2)}" y="${round24(eyesY-height/2)}" width="${width}" height="${height}" rx="${rx}" fill="#fff" transform="rotate(${round24(lean+turned2)} ${round24(x)} ${round24(eyesY)})"/></g>`).join("")}function drawMouth(t,eyesY,wordsTop){let mouth3=mouthOf(t);if(!mouth3)return"";let scale=round24(t.num("eye.size",.8,1.3));return`<g data-mouth="" transform="translate(50 ${round24(Math.min(eyesY+8.5*scale,(eyesY+5*scale+wordsTop)/2))}) scale(${scale})">${MOUTH_PATHS[mouth3]}</g>`}function createBubble(name,overrides,ids="bubble"){let t=calmed(createTraits(name,overrides),CALMING2),shape=shapeOf(t),{d,rx,ry,across,tall}=drawOutline(t,shape),{core,accent,edge}=coloursOf2(t),tilt=round24(t.jitter("tilt",13)),spread=Math.min(tall,34)*t.num("spread",.85,1.15),title=t.text("text.title")?.slice(0,MAX_TEXT),eyesY=round24(title?50-.36*spread:50+t.jitter("eyes.y",7)),titleY=round24(50+.34*spread),room=Math.min(across(titleY-3),across(titleY+3))*1.7,fontSize=title?round24(Math.min(TITLE_SIZE,room/(title.length*CHARACTER))):0,words=title?`<text x="50" y="${titleY}" transform="rotate(${tilt} 50 50)" text-anchor="middle" font-family="${MONO}" font-size="${fontSize}" font-weight="500" fill="#fff">${escaped(title)}</text>`:"",wordsTop=title?titleY-.75*fontSize:1/0;return{art:scopeIds(drawDefs(t,d,rx,ry,core,accent)+`<g clip-path="url(#bubble-clip)"><use href="#bubble-shape" fill="${edge}"/><g filter="url(#bubble-soft)"><use href="#bubble-shape" fill="${edge}"/><use href="#bubble-shape" fill="url(#bubble-core)"/><use href="#bubble-shape" fill="url(#bubble-accent)"/></g></g><use href="#bubble-shape" fill="#fff" filter="url(#bubble-grain)"/><g mask="url(#bubble-edges)"><use href="#bubble-shape" fill="#fff" filter="url(#bubble-rim-grain)"/></g>`,"bubble",ids)+words,eyes:`<g transform="rotate(${tilt} 50 50)">${drawEyes(t,eyesY)}${drawMouth(t,eyesY,wordsTop)}</g>`,effect:shape.effect,blinkDelay:t.num("blink",0,4)}}var bubbleSvg=(name,overrides)=>{let{art,eyes:eyes2}=createBubble(name,overrides);return`<svg xmlns="http://www.w3.org/2000/svg" viewBox="${VIEW_BOX}">${art}${eyes2}</svg>`};var COLOURS=["core","accent","edge"];function paletteControl(t){let swatches=PALETTES2.map(({label,core,accent})=>({label,color:`radial-gradient(circle at 50% 45%, ${core} 35%, ${accent} 75%, ${mix(core,WHITE,.5)})`}));return COLOURS.reduce(clearingColor,choice(t,"palette","Colour","swatches",swatches))}var controls3=(name,overrides)=>{let t=calmed(createTraits(name,overrides),CALMING2),list=control=>narrowed(control,t,CALMING2),colours=coloursOf2(t);return[{title:"Words",controls:[{type:"text",id:"text.title",label:"Title",value:t.text("text.title")??"",placeholder:defaultTitle(t),maxLength:MAX_TEXT},slider(t,"tilt","Tilt",-13,13,"\xB0")]},{title:"Colour",controls:[paletteControl(t),{type:"colors",id:"bubble.colors",label:"Blend",colors:[colours.core,colours.accent,colours.edge].map((color,i)=>({id:colorKey(COLOURS[i]),color}))},slider(t,"blend","Core size",0,100,"%"),slider(t,"grain","Grain",0,100,"%")]},{title:"Shape",controls:[possibilitiesSlider(t,NOTES3),list(choice(t,"shape","Shape","list",SHAPES.map(({name:label})=>({label})))),slider(t,"depth","Depth",0,100,"%"),slider(t,"body.size","Body size",0,100,"%")]},{title:"Eyes",controls:[list(choice(t,"eye.kind","Eyes","list",EYE_KINDS.map(label=>({label})))),optional(t,"mouth",MOUTH_ODDS,"mouth.kind","Mouth","list",MOUTHS.map(label=>({label}))),slider(t,"eye.size","Eye size",0,100,"%"),slider(t,"eye.gap","Gap",0,100,"%"),slider(t,"eye.lean","Lean",-100,100,"%")]}]};var CALMING3={features:/^(head|eye|side|top|mouth|port|lens|screen|vent)\./,lists:{head:[8,8],face:[4,1],eye:[6,1],mouth:[4,1],top:[8,1,"end"],side:[5,1,"end"]},rarer:["trim.straps","trim.studs"]},NOTES4=["plain bots, with one face style, dot eyes, hardly any add-ons and even proportions.","more face styles and eyes, and some antennas, ears and side parts.","anything goes: every face, eye, antenna and bit of trim."];var fmt2=v=>{let rounded=Math.round(v*100)/100;return Object.is(rounded,-0)?"0":String(rounded)},handle=n=>Math.min(1,(8*2**(-1/n)-4)/3);function superellipse2({cx,cy,rx,ry,n,nLower=n}){let upper=handle(n),lower=handle(nLower),at3=(x,y)=>`${fmt2(cx+x)} ${fmt2(cy+y)}`;return`M${at3(rx,0)}C${at3(rx,ry*lower)} ${at3(rx*lower,ry)} ${at3(0,ry)}C${at3(-rx*lower,ry)} ${at3(-rx,ry*lower)} ${at3(-rx,0)}C${at3(-rx,-ry*upper)} ${at3(-rx*upper,-ry)} ${at3(0,-ry)}C${at3(rx*upper,-ry)} ${at3(rx,-ry*upper)} ${at3(rx,0)}Z`}function circle2(cx,cy,r){let left=`${fmt2(cx-r)} ${fmt2(cy)}`,right=`${fmt2(cx+r)} ${fmt2(cy)}`;return`M${left}A${fmt2(r)} ${fmt2(r)} 0 1 0 ${right}A${fmt2(r)} ${fmt2(r)} 0 1 0 ${left}Z`}function rod(x1,y1,x2,y2,r){let length=Math.hypot(x2-x1,y2-y1),nx=-(y2-y1)/length*r,ny=(x2-x1)/length*r,arc=`A${fmt2(r)} ${fmt2(r)} 0 0 0`;return`M${fmt2(x1+nx)} ${fmt2(y1+ny)}L${fmt2(x2+nx)} ${fmt2(y2+ny)}${arc} ${fmt2(x2-nx)} ${fmt2(y2-ny)}L${fmt2(x1-nx)} ${fmt2(y1-ny)}${arc} ${fmt2(x1+nx)} ${fmt2(y1+ny)}Z`}function roundedPolygon(vertices,round4){let count=vertices.length,k=round4/2,at3=i=>vertices[(i%count+count)%count],cut=(i,j)=>{let[x0,y0]=at3(i),[x1,y1]=at3(j);return`${fmt2(x0+(x1-x0)*k)} ${fmt2(y0+(y1-y0)*k)}`},d=`M${cut(0,-1)}`;for(let i=0;i<count;i++){let[x,y]=at3(i);d+=`Q${fmt2(x)} ${fmt2(y)} ${cut(i,i+1)}L${cut(i+1,i)}`}return`${d}Z`}function crescent(cx,cy,width,lift,thickness){let left=`${fmt2(cx-width)} ${fmt2(cy)}`,right=`${fmt2(cx+width)} ${fmt2(cy)}`;return`M${left}Q${fmt2(cx)} ${fmt2(cy-lift*2)} ${right}Q${fmt2(cx)} ${fmt2(cy-lift*2+thickness*2)} ${left}Z`}function curve(x1,y1,cx,cy,x2,y2,r){let along2=Array.from({length:17},(_,i)=>{let u=i/16,point4=[(1-u)**2*x1+2*u*(1-u)*cx+u*u*x2,(1-u)**2*y1+2*u*(1-u)*cy+u*u*y2],tangent=[2*(1-u)*(cx-x1)+2*u*(x2-cx),2*(1-u)*(cy-y1)+2*u*(y2-cy)],length=Math.hypot(...tangent)||1;return{point:point4,normal:[-tangent[1]/length,tangent[0]/length]}}),side=sign=>along2.map(({point:point4,normal})=>`${fmt2(point4[0]+normal[0]*r*sign)} ${fmt2(point4[1]+normal[1]*r*sign)}`),[left,right]=[side(1),side(-1).reverse()],cap=`A${fmt2(r)} ${fmt2(r)} 0 0 1`;return`M${left.join("L")}${cap} ${right[0]}L${right.join("L")}${cap} ${left[0]}Z`}function shapePath(shape){switch(shape.kind){case"superellipse":return superellipse2(shape);case"crescent":return crescent(shape.cx,shape.cy,shape.width,shape.lift,shape.thickness);case"rod":return rod(shape.x1,shape.y1,shape.x2,shape.y2,shape.r);case"circle":return circle2(shape.cx,shape.cy,shape.r);case"curve":return curve(shape.x1,shape.y1,shape.cx,shape.cy,shape.x2,shape.y2,shape.r)}}var MARGIN=5,headroom=head2=>head2.cy-head2.ry-MARGIN,sideroom=head2=>head2.cx-head2.rx-MARGIN,clear=()=>[];function antenna(t,head2){let ball=t.num("top.ball",4.2,5.8),length=Math.min(t.num("top.length",12,20),headroom(head2)-ball),lean=t.jitter("top.lean",6),top=head2.cy-head2.ry,[x,y]=[head2.cx+lean,top-length];return[rod(head2.cx,top+4,x,y,1.9),circle2(x,y,ball)]}function twinAntennas(t,head2){let ball=t.num("top.ball",3.2,4.2),length=Math.min(t.num("top.length",11,17),headroom(head2)-ball),spread=t.num("top.spread",8,13),top=head2.cy-head2.ry;return[-1,1].flatMap(side=>{let[x,y]=[head2.cx+side*(spread+5),top-length];return[rod(head2.cx+side*spread*.6,top+4,x,y,1.7),circle2(x,y,ball)]})}function bolt(t,head2){let r=t.num("top.bolt",5.5,7.5),top=head2.cy-head2.ry;return[superellipse2({cx:head2.cx,cy:top-3,rx:r*1.5,ry:r*.9,n:4}),superellipse2({cx:head2.cx,cy:top+2,rx:r*.8,ry:r,n:3})]}function crest(t,head2){let top=head2.cy-head2.ry,bumps=t.int("top.bumps",3,4);return Array.from({length:bumps},(_,i)=>{let offset=(i-(bumps-1)/2)*8.5,r=6.4-Math.abs(offset)*.12;return circle2(head2.cx+offset,top-Math.min(4.6,headroom(head2)-r)+Math.abs(offset)*.18,r)})}function catEars(t,head2){let top=head2.cy-head2.ry,height=Math.min(t.num("top.ear",13,18),headroom(head2)),spread=head2.rx*t.num("top.spread",.46,.6);return[-1,1].map(side=>roundedPolygon([[head2.cx+side*(spread-10),top+6],[head2.cx+side*(spread+2),top-height],[head2.cx+side*(spread+12),top+6]],.42))}function propeller(t,head2){let top=head2.cy-head2.ry,lift=Math.min(t.num("top.length",7,11),headroom(head2)-3),span=t.num("top.span",13,18),y=top-lift;return[rod(head2.cx,top+4,head2.cx,y,1.9),superellipse2({cx:head2.cx-span/2-1,cy:y,rx:span/2+1,ry:3,n:2.2}),superellipse2({cx:head2.cx+span/2+1,cy:y,rx:span/2+1,ry:3,n:2.2}),circle2(head2.cx,y,3.4)]}function earDiscs(t,head2){if(Math.floor(t("side")*SIDES.length)!==0)return[];let r=Math.min(t.num("side.r",7,10),sideroom(head2)/2+3),y=head2.cy+t.num("side.y",-5,3);return[-1,1].map(side=>({x:head2.cx+side*(head2.rx+r*.2),y,r}))}var discs=(t,head2)=>earDiscs(t,head2).map(({x,y,r})=>circle2(x,y,r));function earBolts(t,head2){let ball=t.num("side.ball",3.6,4.8),reach=Math.min(t.num("side.reach",7,11),sideroom(head2)-ball),y=head2.cy+t.num("side.y",-6,2);return[-1,1].flatMap(side=>{let x=head2.cx+side*(head2.rx+reach);return[rod(head2.cx+side*(head2.rx-4),y,x,y,1.8),circle2(x,y,ball)]})}function headphones(t,head2){let rx=Math.min(t.num("side.cup",6,7.5),sideroom(head2)/2+2),ry=Math.min(head2.ry*.6,t.num("side.tall",13,16));return[-1,1].map(side=>superellipse2({cx:head2.cx+side*(head2.rx+rx*.3),cy:head2.cy,rx,ry,n:3.4}))}function fins(t,head2){let reach=Math.min(t.num("side.reach",8,12),sideroom(head2)),y=head2.cy+t.num("side.y",-6,4);return[-1,1].map(side=>{let root=head2.cx+side*(head2.rx-5);return roundedPolygon([[root,y-11],[head2.cx+side*(head2.rx+reach),y+2],[root,y+11]],.5)})}var SIDES=[discs,earBolts,headphones,fins,clear],TOP_OPTIONS=[{label:"Antenna",weight:2},{label:"Twin antennas"},{label:"Bolt"},{label:"Crest"},{label:"Cat ears"},{label:"Propeller"},{label:"None"}],SIDE_NAMES=["Discs","Bolts","Headphones","Fins","None"],buildAttachments=(t,head2)=>[...t.pick("top",[antenna,antenna,twinAntennas,bolt,crest,catEars,propeller,clear])(t,head2),...t.pick("side",SIDES)(t,head2)];var squircle=(cx,cy,rx,ry,n)=>({kind:"superellipse",cx,cy,rx,ry,n,rot:0});function eye(kind,x,y,r){switch(kind){case"bar":return squircle(x,y,r*.58,r*1.3,4);case"pixel":return squircle(x,y,r*.92,r*.92,8);case"diamond":return squircle(x,y,r*1.25,r*1.25,1.2);case"slit":return squircle(x,y,r*1.3,r*.42,4);case"happy":return{kind:"crescent",cx:x,cy:y+r*.45,width:r*1.2,lift:r*.9,thickness:r*.5};default:return squircle(x,y,r,r*1.28,2)}}var ring2=(cx,cy,r)=>({kind:"circle",cx,cy,r}),bar=(x1,y1,x2,y2,r)=>({kind:"rod",x1,y1,x2,y2,r}),PAIR_EYES=["dot","bar","pixel","diamond","slit","happy"],LENS_EYES=["dot","pixel","diamond","bar"],CYCLOPS_EYES=["dot","pixel","diamond"],EYE_LABELS={dot:"Dots",bar:"Bars",pixel:"Squares",diamond:"Diamonds",slit:"Slits",happy:"Happy"},MOUTH_KINDS=["Smile","Flat","Equalizer","Chirp"],FACE_NAMES=["Band","Screen","Goggles","Porthole"];function mouth(t,x,y,width){switch(t.pick("mouth",["smile","flat","equalizer","chirp"])){case"flat":return[{kind:"rod",x1:x-width,y1:y,x2:x+width,y2:y,r:1.3}];case"chirp":return[{kind:"circle",cx:x,cy:y,r:width*.34}];case"equalizer":{let bars=t.int("mouth.bars",4,6);return Array.from({length:bars},(_,i)=>{let barX=x-width+2*width*i/(bars-1),reach=t.num(`mouth.bar${i}`,.8,3.4);return{kind:"rod",x1:barX,y1:y-reach,x2:barX,y2:y+reach,r:1}})}default:return[{kind:"crescent",cx:x,cy:y+1.6,width,lift:-2.2,thickness:-1.4}]}}function vents(t,x,y,width){let count=t.int("vent.n",3,5);return Array.from({length:count},(_,i)=>{let slotX=x-width+2*width*i/(count-1);return bar(slotX,y-2.2,slotX,y+2.2,.95)})}function band(t,box2){let ry=box2.ry*t.num("band.ry",.46,.56),y=box2.cy-box2.ry*.26,r=Math.min(ry*.54,box2.rx*.2),gap=box2.rx*t.num("eye.gap",.4,.54),kind=t.pick("eye",PAIR_EYES);return{visor:[squircle(box2.cx,y,box2.rx,ry,t.num("band.n",3.4,5.5)),...vents(t,box2.cx,box2.cy+box2.ry*.72,box2.rx*.42)],eyes:[eye(kind,box2.cx-gap,y,r),eye(kind,box2.cx+gap,y,r)],lights:[],eyeY:y}}function screen(t,box2){let eyeY=box2.cy-box2.ry*.26,mouthY=box2.cy+box2.ry*.5,r=Math.min(box2.ry*.24,box2.rx*.2),gap=box2.rx*t.num("eye.gap",.38,.52),kind=t.pick("eye",PAIR_EYES);return{visor:[squircle(box2.cx,box2.cy,box2.rx,box2.ry,t.num("screen.n",3.6,5.5))],eyes:[eye(kind,box2.cx-gap,eyeY,r),eye(kind,box2.cx+gap,eyeY,r)],lights:mouth(t,box2.cx,mouthY,box2.rx*t.num("mouth.width",.26,.4)),eyeY}}function goggles(t,box2){let lens=Math.min(box2.rx*.46,box2.ry*.74),y=box2.cy-box2.ry*.2,gap=box2.rx-lens,r=lens*t.num("lens.pupil",.4,.52),kind=t.pick("eye",LENS_EYES);return{visor:[ring2(box2.cx-gap,y,lens),ring2(box2.cx+gap,y,lens),bar(box2.cx-gap,y,box2.cx+gap,y,2),...vents(t,box2.cx,box2.cy+box2.ry*.82,box2.rx*.34)],eyes:[eye(kind,box2.cx-gap,y,r),eye(kind,box2.cx+gap,y,r)],lights:[],eyeY:y}}function porthole(t,box2){let r=Math.min(box2.rx,box2.ry)*t.num("port.r",.86,1),pupil=r*t.num("port.pupil",.42,.56);return{visor:[ring2(box2.cx,box2.cy,r)],eyes:[eye(t.pick("eye",CYCLOPS_EYES),box2.cx,box2.cy,pupil)],lights:[],eyeY:box2.cy}}var buildFace=(t,box2)=>t.pick("face",[band,screen,goggles,porthole])(t,box2);var CENTER_X=50,CENTER_Y=58;function head(rx,ry,path,faceRx,faceRy,faceDrop=0){let cy=CENTER_Y;return{cx:CENTER_X,cy,rx,ry,path,face:{cx:CENTER_X,cy:cy+ry*faceDrop,rx:rx*faceRx,ry:ry*faceRy}}}var place=(rx,ry,n,nLower=n)=>({cx:CENTER_X,cy:CENTER_Y,rx,ry,n,nLower}),tv=t=>{let[rx,ry]=[t.num("head.rx",33,37),t.num("head.ry",25,29)];return head(rx,ry,superellipse2(place(rx,ry,t.num("head.n",4.5,6))),.8,.68)},cube2=t=>{let r=t.num("head.rx",29,33);return head(r,r,superellipse2(place(r,r,t.num("head.n",4.5,6))),.78,.66)},orb=t=>{let r=t.num("head.rx",31,35);return head(r,r,superellipse2(place(r,r,t.num("head.n",2,2.3))),.72,.6)},pill=t=>{let[rx,ry]=[t.num("head.rx",24,27),t.num("head.ry",33,36)];return head(rx,ry,superellipse2(place(rx,ry,3)),.78,.52,-.12)},dome=t=>{let[rx,ry]=[t.num("head.rx",31,35),t.num("head.ry",29,32)];return head(rx,ry,superellipse2(place(rx,ry,2.1,t.num("head.n",5,6.5))),.78,.58,.12)},acorn=t=>{let[rx,ry]=[t.num("head.rx",31,35),t.num("head.ry",29,33)];return head(rx,ry,superellipse2(place(rx,ry,t.num("head.n",5,6.5),2.1)),.78,.54,-.14)},bucket=t=>{let[rx,ry]=[t.num("head.rx",31,35),t.num("head.ry",27,31)],top=rx*t.num("head.taper",.68,.8),[cx,cy]=[CENTER_X,CENTER_Y],path=roundedPolygon([[cx-top,cy-ry],[cx+top,cy-ry],[cx+rx,cy+ry],[cx-rx,cy+ry]],t.num("head.round",.55,.75));return head(rx,ry,path,.7,.62,.08)},octagon=t=>{let r=t.num("head.rx",31,34),corner=r/Math.cos(Math.PI/8),vertices=Array.from({length:8},(_,i)=>{let angle=Math.PI/8+i*Math.PI/4;return[CENTER_X+corner*Math.cos(angle),CENTER_Y+corner*Math.sin(angle)]});return head(r,r,roundedPolygon(vertices,t.num("head.round",.45,.65)),.76,.64)},HEADS=[tv,cube2,orb,pill,dome,acorn,bucket,octagon],HEAD_NAMES=["TV","Cube","Orb","Pill","Dome","Acorn","Bucket","Octagon"],pickHead=t=>t.pick("head",HEADS)(t);var PAINTS=[{body:"#f2483f",accents:["#ffd23f","#f6efe2","#1f2a6b"]},{body:"#ff8a2b",accents:["#fff1cf","#2740a8","#7a2bd6"]},{body:"#ffc933",accents:["#ff5a4f","#2b63ff","#6a3fd1"]},{body:"#35c46b",accents:["#fff1cf","#ffd23f","#0f5e6e"]},{body:"#16b8a6",accents:["#fff1cf","#17406b","#ffd23f"]},{body:"#35a7ff",accents:["#ffd23f","#fff1cf","#5a2bc8"]},{body:"#3b5bff",accents:["#ff8a2b","#ffd23f","#8ff0d8"]},{body:"#8a4dff",accents:["#ffd23f","#6ff0c8","#ffb3d9"]},{body:"#ff5fa2",accents:["#fff1cf","#ffd23f","#4a2bb8"]},{body:"#c9d2e6",accents:["#ff5a4f","#3b5bff","#0f7f70"]},{body:"#f4efe3",accents:["#ff5a4f","#16b8a6","#3b5bff"]}],VISOR="#000000",LIGHTS=["#59f5b0","#4fe3ff","#ffc24b","#ff6fb5","#eef4ff","#c9ff4d"];function pickColors(t){let paint=t.pick("paint",PAINTS);return{body:t.color("paint")??paint.body,accent:t.color("paint.accent")??t.pick("paint.accent",paint.accents),visor:VISOR,light:t.color("paint.light")??t.pick("paint.light",LIGHTS)}}var indexOf=(value,count)=>Math.floor(value*count),TALL_HEADS=["TV","Pill","Dome","Acorn","Bucket"],SQUARE_HEADS=["TV","Cube","Orb","Dome","Acorn"],CUT_HEADS=["Bucket","Octagon"],EYES_FOR={Band:PAIR_EYES,Screen:PAIR_EYES,Goggles:LENS_EYES,Porthole:CYCLOPS_EYES},controls4=(name,overrides)=>{let t=calmed(createTraits(name,overrides),CALMING3),list=control=>narrowed(control,t,CALMING3),head2=HEAD_NAMES[indexOf(t("head"),HEAD_NAMES.length)],face=FACE_NAMES[indexOf(t("face"),FACE_NAMES.length)],paint=PAINTS[indexOf(t("paint"),PAINTS.length)],top=list(choice(t,"top","Top","list",TOP_OPTIONS)),side=list(choice(t,"side","Sides","list",SIDE_NAMES.map(label=>({label})))),topName=TOP_OPTIONS[Number(top.selected)].label,hasParts=topName!=="None"||SIDE_NAMES[Number(side.selected)]!=="None";return[{title:"Head",controls:[possibilitiesSlider(t,NOTES4),choice(t,"head","Head","list",HEAD_NAMES.map(label=>({label}))),slider(t,"head.rx","Head size",0,100,"%"),...TALL_HEADS.includes(head2)?[slider(t,"head.ry","Height",0,100,"%")]:[],...SQUARE_HEADS.includes(head2)?[slider(t,"head.n","Squareness",0,100,"%")]:[],...CUT_HEADS.includes(head2)?[slider(t,"head.round","Corners",0,100,"%")]:[],...head2==="Bucket"?[slider(t,"head.taper","Taper",0,100,"%")]:[]]},{title:"Face",controls:[list(choice(t,"face","Style","list",FACE_NAMES.map(label=>({label})))),list(choice(t,"eye","Eyes","list",EYES_FOR[face].map(kind=>({label:EYE_LABELS[kind]})))),...face==="Screen"?[list(choice(t,"mouth","Mouth","list",MOUTH_KINDS.map(label=>({label}))))]:[],...face==="Band"||face==="Screen"?[slider(t,"eye.gap","Eye gap",0,100,"%")]:[]]},{title:"Parts",controls:[top,...topName==="Antenna"?[slider(t,"top.length","Antenna length",0,100,"%"),slider(t,"top.lean","Antenna lean",-100,100,"%")]:[],side,toggle(t,"trim.straps",60,"Chrome straps"),toggle(t,"trim.studs",75,"Studs")]},{title:"Paint",controls:[palette(t,"paint","Colour",PAINTS.map(({body})=>body)),...hasParts?[palette(t,"paint.accent","Parts",paint.accents)]:[],palette(t,"paint.light","Lights",LIGHTS),slider(t,"speckle","Speckle",0,100,"%")]},{title:"Container",controls:containerControls(t)}]};var circle3=(cx,cy,r)=>({kind:"circle",cx,cy,r}),MIN_ROOM=6;function buildTrim(t,head2){let{cx,cy,ry,rx,face}=head2,top=cy-ry,faceTop=face.cy-face.ry,headroom2=faceTop-top,sideroom2=rx-face.rx,chrome=earDiscs(t,head2).map(({x,y,r})=>circle3(x,y,r*.5)),studs=[];if(headroom2>=MIN_ROOM&&t("trim.straps")*100<60){let gap=rx*t.num("trim.gap",.34,.46);for(let side of[-1,1])chrome.push({kind:"rod",x1:cx+side*gap,y1:top+3,x2:cx+side*gap*1.08,y2:faceTop-1.5,r:.9})}if(t("trim.studs")*100<75){if(headroom2>=MIN_ROOM){let y=top+headroom2*.5;for(let side of[-1,1])studs.push(circle3(cx+side*rx*.17,y,1.9))}if(sideroom2>=MIN_ROOM)for(let side of[-1,1]){let x=cx+side*(face.rx+sideroom2*.5);studs.push(circle3(x,cy-3.2,1.5),circle3(x,cy+3.2,1.5))}}return{chrome,studs}}function botParts(name,overrides){let t=calmed(createTraits(name,overrides),CALMING3),head2=pickHead(t),face=buildFace(t,head2.face),{chrome,studs}=buildTrim(t,head2);return{colors:pickColors(t),head:[head2.path],accents:buildAttachments(t,head2),visor:face.visor.map(shapePath),visorShapes:face.visor,eyes:face.eyes.map(shapePath),eyeShapes:face.eyes,lights:face.lights.map(shapePath),lightShapes:face.lights,chrome:chrome.map(shapePath),chromeShapes:chrome,studs:studs.map(shapePath),studShapes:studs,speckle:t("speckle"),eyeY:face.eyeY,container:containerOf(t)}}var CHROME="#c9ced8",layer=(fill,paths)=>paths.length?`<g fill="${fill}">${paths.map(d=>`<path d="${d}"/>`).join("")}</g>`:"";function generateBot(name,overrides){let{colors,head:head2,accents,visor,eyes:eyes2,lights,chrome,studs,container}=botParts(name,overrides),art=layer(colors.accent,accents)+layer(colors.body,head2)+layer(CHROME,chrome)+layer(colors.visor,[...visor,...studs])+layer(colors.light,[...eyes2,...lights]);return inContainer(art,container,"bot-card")}var CALMING4={features:/^(eye)\.|^(weight|tilt)$/,lists:{mood:[10,8,[0,1,4,3,2,7,8,9,5,6]],pose:[6,2]}},NOTES5=["sweet looks like content, happy and blushing, standing straight.","adds surprise, and leans and close ups.","every expression, up to grumpy, in any pose."];var TILES=["#ffffff","#fff3d6","#ffe0e6","#dff1ff","#e3f7dc","#efe6ff","#ffe8cf","#fff8b8","#d9f5f0"],INK="#1f1a17",PINK="#f2896a",BLUSH="#ff9aa2",TONGUE="#ff7a93",HEART="#ef4b5f",LENS="#2b211d",GLINT="#6d6058",round25=value=>Math.round(value*100)/100,point=(x,y)=>`${round25(x)} ${round25(y)}`,at=([x,y])=>point(x,y);function blob(points){let n=points.length,d=`M${at(points[0])}`;for(let i=0;i<n;i++){let[p0,p1,p2,p3]=[points[(i+n-1)%n],points[i],points[(i+1)%n],points[(i+2)%n]];d+=`C${point(p1[0]+(p2[0]-p0[0])/6,p1[1]+(p2[1]-p0[1])/6)} ${point(p2[0]-(p3[0]-p1[0])/6,p2[1]-(p3[1]-p1[1])/6)} ${at(p2)}`}return`${d}Z`}var CHEEK_PAWS=[{from:[43.4,48.8],inOutline:!0,lines:"M20.5 55Q22.6 52.4 26 51.2Q30.6 50 34.6 46.8Q36.8 44.6 38.6 44.4Q40.6 44.4 40.2 46.4Q39.4 49.4 37.6 51.4Q37.4 52.4 39 52.8Q41.6 53.6 43.6 54.8Q44.8 55.8 43.8 56.6Q41.6 57.4 38.6 57.8Q37 58.4 36.4 61.2Q35.8 64 33.2 66.4Q35.6 68 37.6 71.6Q39 75.6 39.2 80Q39 84 37.2 86.8",fill:"M20.5 55Q22.6 52.4 26 51.2Q30.6 50 34.6 46.8Q36.8 44.6 38.6 44.4Q40.6 44.4 40.2 46.4Q39.4 49.4 37.6 51.4Q37.4 52.4 39 52.8Q41.6 53.6 43.6 54.8Q44.8 55.8 43.8 56.6Q41.6 57.4 38.6 57.8Q37 58.4 36.4 61.2Q35.8 64 33.2 66.4Q35.6 68 37.6 71.6Q39 75.6 39.2 80Q39 84 37.2 86.8L36.4 112L18.4 112Q18 100 16.6 92Q14.4 86 13.8 78Q13.8 70 16 65Q13.6 64 14.6 60Z"},{from:[55.7,47.4],inOutline:!0,lines:"M79.4 50.6Q74 48.6 67.4 48.2Q65.8 47.8 65.2 45.6Q64.4 42.2 62.6 41.2Q61.4 41 61.6 43Q62 46.4 62.4 48.6Q62.2 51.4 59.6 52.8Q57 54 56.4 55.6Q56.4 57.2 58.6 57.6Q62.4 57.8 64.4 57.8Q65.6 59.4 66 62Q66.4 63.8 68.6 65.2Q66.8 67.6 65.2 72Q64.4 76 64.8 80Q65.2 82.4 66 83.6",fill:"M79.4 50.6Q74 48.6 67.4 48.2Q65.8 47.8 65.2 45.6Q64.4 42.2 62.6 41.2Q61.4 41 61.6 43Q62 46.4 62.4 48.6Q62.2 51.4 59.6 52.8Q57 54 56.4 55.6Q56.4 57.2 58.6 57.6Q62.4 57.8 64.4 57.8Q65.6 59.4 66 62Q66.4 63.8 68.6 65.2Q66.8 67.6 65.2 72Q64.4 76 64.8 80Q65.2 82.4 66 83.6L66 112L92 112Q91 100 89.6 93Q86.2 89.2 83.4 86.2Q86 85 87.6 82Q89 76 88 70Q86 65 82.6 61Q81 58 80.2 53Z"}],CHEEK_SIDES=["M14.6 60Q13.6 64 16 65Q13.8 70 13.8 78Q14.4 86 16.6 92Q18 100 18.4 112","M80.2 53Q81 58 82.6 61Q86 65 88 70Q89 76 87.6 82Q86 85 83.4 86.2Q86.2 89.2 89.6 93Q91 100 92 112"],TABBY_CHIN="M38.8 77.4Q47 78.2 54 76.8Q60 75.4 64.2 74.4",SHADES_AT=[41.5,47.5],LENSES="M11 36.6Q20 35.6 30 36.6Q35 37.4 37.8 39.8Q37.6 47 34.6 51.6Q30.6 55 24 55.2Q17.4 54.6 14.2 49Q12 44 11 36.6ZM44.6 41Q46 40.2 52 39.4Q62 38.6 70 39.4Q73 39.8 74.2 41.2Q73.4 49 69.6 54.4Q65 59.6 58.8 60.2Q52 60 48.4 55.2Q45.4 50 44.6 41ZM37.6 39.6Q41 39.8 44.8 41.2L44.8 44.4Q41 43.2 37.4 43.4Z",SHADES_BAR="M10.4 36Q22 34.4 37.6 38.6Q41 39.6 44.8 40.6Q60 38 74.4 40.2",SHADES_GLINT="M14.6 38.6Q24 37.6 32.4 39.6M47.6 42.4Q58 41 70.4 42M13.4 40.6Q13.6 45 15.6 49",SHADES_END=[74.2,41.2],SHADES_PAW={from:SHADES_END,lines:"M73.6 44.8Q74 41.6 77.4 40.4Q82 39.4 86.6 42.6Q91.6 46.6 94 55Q95.8 63.6 95.4 72Q94.8 82 91.6 88.6Q88 93.6 82.6 94.4Q76 94 71 90Q68.6 88 67.6 86.6M73.6 44.8Q72.2 47 73.6 49Q75.6 50.4 74.6 52.6Q74.4 55.4 76.6 56.4Q78.2 57.6 77.4 60Q78 62.6 80.4 63.8Q82.6 64.8 84.6 65M82 65.4Q79.6 69 79.4 73Q79.4 77 79.8 80M75.4 48.2Q79 47 82.8 47.4M76.4 55.8Q78.6 54.2 80.6 53.8",fill:"M73.6 44.8Q74 41.6 77.4 40.4Q82 39.4 86.6 42.6Q91.6 46.6 94 55Q95.8 63.6 95.4 72Q94.8 82 91.6 88.6Q88 93.6 82.6 94.4Q76 94 71 90Q68.6 88 67.6 86.6L79.8 80Q79.4 77 79.4 73Q79.6 69 82 65.4L84.6 65Q82.6 64.8 80.4 63.8Q78 62.6 77.4 60Q78.2 57.6 76.6 56.4Q74.4 55.4 74.6 52.6Q75.6 50.4 73.6 49Q72.2 47 73.6 44.8Z"},SALUTE={from:[35,39.4],lines:"M26.7 84Q20 81 12 76Q7 70 6.6 62Q7.6 56 13 50.4Q15.6 47.6 14.4 42.6Q15.4 39.6 20 38.8L22.6 38.4Q22.4 34 24.6 31.8Q27.6 30.2 30 31.4M26 34.6Q28.6 35.6 28.6 38.4L28.6 42.6Q33 42.4 37 44Q38.6 46 37.4 47Q34 47.8 29.6 47.6Q28.6 50.6 28.4 55Q26.6 57.4 24.4 58.6Q26.4 61.4 28.4 63Q30 68 31.6 72.4Q32.6 74.6 34.6 75",fill:"M26.7 84Q20 81 12 76Q7 70 6.6 62Q7.6 56 13 50.4Q15.6 47.6 14.4 42.6Q15.4 39.6 20 38.8L22.6 38.4Q22.4 34 24.6 31.8Q27.6 30.2 30 31.4L26 34.6Q28.6 35.6 28.6 38.4L28.6 42.6Q33 42.4 37 44Q38.6 46 37.4 47Q34 47.8 29.6 47.6Q28.6 50.6 28.4 55Q26.6 57.4 24.4 58.6Q26.4 61.4 28.4 63Q30 68 31.6 72.4Q32.6 74.6 34.6 75L30 80Z"},MITTEN="M-6.4 -1Q-7 -7.6 -2.4 -9.6Q2.6 -11 6 -7.6Q8.6 -4.4 7.8 1Q7.2 6.6 3 8.4Q-1.6 9.6 -4.4 7.6Q-7.4 5.6 -6.4 2.4Q-7.6 0.6 -6.4 -1Z",MITTEN_CREASES="M-6 -3.8Q-1 -4.6 3.8 -4.4M-5.4 2.2Q-2.6 1.4 -0.6 0.4",tabbyStripes=fur=>mix(fur,"#e0a020",.3),CHARACTERS=[{name:"Tabby",head:[[18.5,43],[18.6,36],[19.6,31],[21.4,29.6],[25,29.6],[27.6,30.8],[29.2,32],[32,30.6],[40,29.6],[50,29.2],[56,30],[57.2,30.6],[59,28.4],[61.8,25.8],[64.2,24.2],[65.6,24.6],[66.4,27.4],[67.2,31.2],[69,32.6],[73,35.4],[76,39.6],[78.4,44.6],[79.4,48.6],[80.2,53],[81,57.4],[82.6,61],[86,65],[88,70],[88.8,76],[87.6,82],[83.4,86.2],[86.2,89.2],[89.6,93],[91,100],[92,112],[19,112],[18,100],[17,91],[15,84.6],[14,78],[14,72],[15,68],[16.4,65.4],[15.4,63.6],[14.4,59.6],[14.2,54.6],[15,50],[16.6,46.4]],body:"",furs:["#f2cd7a","#c9c3bb","#f3a85b","#e9e4dc","#8a8a92"],eyes:[[43.4,48.8],[55.7,47.4]],mouth:[51.1,56.2,.95,0],nose:(_,weight)=>`<path d="M47.9 51.8Q47.9 50.6 51.1 50.6Q54.3 50.6 54.3 51.8Q53.7 53.8 51.1 54.1Q48.5 53.8 47.9 51.8Z" fill="${INK}"/><path d="M51.1 54V56.2" fill="none" stroke="${INK}" stroke-width="${round25(weight)}" stroke-linecap="round"/>`,cheeks:[[36,55],[62,54]],shoulders:[[21,82],[80,80]],chest:[51,88],whiskers:"M8 50.2L20 53M7.6 60L17.4 60M79.8 48.2L85 44.6M81 54.4L88.4 53.2",markings:fur=>`<g clip-path="url(#buddy-head)"><path d="M34.4 32.2L35.4 40.2M43 31.2L43.6 38.6M50 31.6L50.6 37.4M75.2 45.8L78.6 46.4" fill="none" stroke="${tabbyStripes(fur)}" stroke-width="3.6" stroke-linecap="round"/><path d="M15 74.6L24 74.4M16 86L28 82.6M74 68.4L85 66.6M75 79L85 80.4" fill="none" stroke="${tabbyStripes(fur)}" stroke-width="4.6" stroke-linecap="round"/><ellipse cx="23.8" cy="35.4" rx="2.2" ry="2.6" fill="${tabbyStripes(fur)}"/><ellipse cx="63.6" cy="28.8" rx="1.3" ry="2" transform="rotate(-15 63.6 28.8)" fill="${tabbyStripes(fur)}"/></g>`,shades:[.62,-4],ovalEyes:!0,weight:1.75,frame:""},{name:"Calico",head:[[23.4,6.8],[26,9],[32,13.4],[40,17.8],[50,17.6],[58,19],[64.6,20.6],[72,15.6],[78,12.2],[84,10.6],[84.8,14],[84.2,24],[83,33],[82.4,40],[83,52],[80,62],[70,69.4],[57.6,73.4],[45,75],[33,72.6],[24,70],[18.6,65.4],[15.4,60],[14.4,52],[15,44],[17.4,36],[20,29],[20.4,20],[21.4,12]],body:"M24 69C18 76 12 88 7.5 105L93 105C92 90 89 76 79 64Z",furs:["#fdf0d8","#ffffff","#f1e6da","#fbe3c8","#eef0f3"],eyes:[[27.5,47],[54,49.5]],mouth:[38.2,62,1,0],nose:(_,weight)=>`<path d="M34.8 53.8Q38.2 52.8 41.8 53.8Q40.6 56.6 38.2 57Q35.8 56.6 34.8 53.8Z" fill="${PINK}" stroke="${INK}" stroke-width="${round25(weight*.8)}" stroke-linejoin="round"/><path d="M38.2 57V61" fill="none" stroke="${INK}" stroke-width="${round25(weight)}" stroke-linecap="round"/>`,cheeks:[[22,58],[68,60]],shoulders:[[22,80],[80,78]],chest:[45,88],whiskers:"M9.4 58.4L14.6 58.2M11.4 64L16 61.4",details:(fur,_,weight)=>`<path d="M73.6 17L82.8 12.4Q83.4 22 81.6 33Q78 31 74.6 30.6Q76 27 73.6 26Q75.6 23.4 73.4 21Z" fill="${mix(fur,PINK,.6)}"/><path d="M25.4 11.4Q28 17 29.8 22.6M24.6 22.6L29.8 24.4L27.4 26M71.4 25.2L76.4 26.4M70.4 29.4L75.6 29M23.8 80Q21.6 88 19.6 96" fill="none" stroke="${INK}" stroke-width="${round25(weight*.8)}" stroke-linecap="round" stroke-linejoin="round"/><path d="M31.4 84Q32.6 93.4 35.6 87.6Q36.6 94.6 39.6 89.6M40.6 91.6Q43.6 96 46.4 88.6" fill="none" stroke="${mix(fur,"#b8875a",.5)}" stroke-width="1.6" stroke-linecap="round"/><circle cx="51.6" cy="86.2" r="0.9" fill="${mix(fur,"#b8875a",.5)}"/>`,markings:(_,patch)=>`<g clip-path="url(#buddy-head)"><path d="${blob([[21,8],[32,13],[40,18],[64,20.6],[72,15.6],[84,10.6],[84.4,38],[74,37.6],[62,36.4],[52,37.4],[47,34],[45.6,28.6],[42,24.4],[36,23.6],[30,26.6],[25,30],[20,29]])}" fill="${patch}"/><path d="M39.6 19.2Q37.6 23 36.2 27.4M48.2 20.4Q47.2 25 46.4 30M55.2 21Q53.4 25.4 51.6 30.4" fill="none" stroke="${mix(patch,INK,.22)}" stroke-width="2.2" stroke-linecap="round"/></g><g clip-path="url(#buddy-body)"><ellipse cx="71.6" cy="96.4" rx="5" ry="7" fill="${patch}"/></g>`,shades:[1,0],weight:1.25,frame:""}],PATCHES=["#f0a04b","#3a3330","#8c8279","#d9772f","#c9a27a"],MOODS=[{name:"Content",eyes:["dot","dot"],mouth:"w"},{name:"Happy",eyes:["happy","happy"],mouth:"smile"},{name:"Smug",eyes:["half","half"],mouth:"smirk"},{name:"Wink",eyes:["dot","wink"],mouth:"w"},{name:"Blushing",eyes:["dot","dot"],mouth:"w",blush:!0},{name:"Surprised",eyes:["round","round"],mouth:"o"},{name:"Grumpy",eyes:["dot","dot"],mouth:"frown",brows:!0},{name:"Sleepy",eyes:["line","line"],mouth:"o"},{name:"In love",eyes:["heart","heart"],mouth:"w"},{name:"Cheeky",eyes:["dot","dot"],mouth:"tongue"}],GESTURES=[{name:"Cheeks"},{name:"Shades"},{name:"Salute"},{name:"Heart"},{name:"Wave"},{name:"Shy"},{name:"Peace"},{name:"Chill"}],POSES=[{name:"Centre",transform:""},{name:"Mirrored",transform:"translate(100 0) scale(-1 1)",mirrored:!0},{name:"Close up",transform:"translate(50 56) scale(1.2) translate(-50 -56)"},{name:"Peeking",transform:"translate(0 16)"},{name:"Small",transform:"translate(50 110) scale(0.84) translate(-50 -110)"},{name:"Tilted",transform:"rotate(-9 50 100)"}],characterOf=t=>t.pick("character",CHARACTERS),moodOf=t=>t.pick("mood",MOODS),gestureOf=t=>t.pick("gesture",GESTURES).name,poseOf=t=>t.pick("pose",POSES);function coloursOf3(t,character){return{tile:t.color("tile")??t.pick("tile",TILES),fur:t.color("fur")??t.pick("fur",character.furs),patch:t.color("patch")??t.pick("patch",PATCHES)}}function drawEye(kind,size,oval3){let line4=`fill="none" stroke="${INK}" stroke-width="${round25(1.7*size)}" stroke-linecap="round"`;switch(kind){case"happy":return`<path d="M${point(-2.6*size,.8*size)}Q0 ${round25(-2.6*size)} ${point(2.6*size,.8*size)}" ${line4}/>`;case"half":return`<g data-pupil=""><circle cx="0" cy="${round25(.5*size)}" r="${round25(1.9*size)}" fill="${INK}"/></g><path d="M${point(-3*size,-.9*size)}H${round25(3*size)}" ${line4}/>`;case"wink":return`<path d="M${point(-2.6*size,.6*size)}Q0 ${round25(-2.2*size)} ${point(2.6*size,.6*size)}" ${line4}/>`;case"round":return`<circle cx="0" cy="0" r="${round25(3.4*size)}" fill="#fff" stroke="${INK}" stroke-width="${round25(1.4*size)}"/><g data-pupil=""><circle cx="0" cy="0" r="${round25(1.6*size)}" fill="${INK}"/></g>`;case"line":return`<path d="M${point(-2.6*size,.2*size)}Q0 ${round25(1.6*size)} ${point(2.6*size,.2*size)}" ${line4}/>`;case"heart":{let s=size*.95;return`<g data-pupil=""><path d="M0 ${round25(2.6*s)}C${point(-4*s,0)} ${point(-3.2*s,-3*s)} ${point(-1.5*s,-3*s)}C${point(-.6*s,-3*s)} 0 ${round25(-2.2*s)} 0 ${round25(-1.6*s)}C0 ${round25(-2.2*s)} ${point(.6*s,-3*s)} ${point(1.5*s,-3*s)}C${point(3.2*s,-3*s)} ${point(4*s,0)} 0 ${round25(2.6*s)}Z" fill="${HEART}"/></g>`}default:return oval3?`<g data-pupil=""><ellipse cx="0" cy="0" rx="${round25(1.45*size)}" ry="${round25(2.1*size)}" fill="${INK}"/></g>`:`<g data-pupil=""><circle cx="0" cy="0" r="${round25(2*size)}" fill="${INK}"/><circle cx="${round25(.7*size)}" cy="${round25(-.7*size)}" r="${round25(.6*size)}" fill="#fff"/></g>`}}function drawMouth2(kind,weight){let line4=`fill="none" stroke="${INK}" stroke-width="${round25(weight)}" stroke-linecap="round" stroke-linejoin="round"`,w="M-3.8 0Q-1.9 2.8 0 0Q1.9 2.8 3.8 0";switch(kind){case"smile":return`<path d="M-4.2 -0.4Q0 7 4.2 -0.4Z" fill="${INK}" stroke="${INK}" stroke-width="${round25(weight*.8)}" stroke-linejoin="round"/><path d="M-2.2 3.2Q0 5.2 2.2 3.2Q0 1.8 -2.2 3.2Z" fill="${TONGUE}"/>`;case"smirk":return`<path d="M-3.4 0.8Q0.6 2.6 4 -0.8" ${line4}/>`;case"o":return`<ellipse cx="0" cy="1.6" rx="1.6" ry="2" fill="${INK}"/>`;case"frown":return`<path d="M-3.4 2.4Q-1.6 0 0 -0.4Q1.8 0 4.4 3" ${line4}/>`;case"tongue":return`<path d="M-1.6 1.2Q0 6.4 1.6 1.2Z" fill="${TONGUE}" stroke="${INK}" stroke-width="${round25(weight*.7)}"/><path d="${w}" ${line4}/>`;default:return`<path d="${w}" ${line4}/>`}}var placed=(from,to,scale=1,turn2=0)=>`translate(${at(to)}) rotate(${round25(turn2)}) scale(${round25(scale)}) translate(${point(-from[0],-from[1])})`;function createBuddy(name,overrides,ids="buddy"){let t=calmed(createTraits(name,overrides),CALMING4),character=characterOf(t),mood=moodOf(t),gesture=gestureOf(t),pose=poseOf(t),{tile,fur,patch}=coloursOf3(t,character),weight=character.weight*t.num("weight",.88,1.12),line4=`stroke="${INK}" stroke-width="${round25(weight)}" stroke-linejoin="round"`,lines=(d,w=weight)=>`<path d="${d}" fill="none" stroke="${INK}" stroke-width="${round25(w)}" stroke-linecap="round" stroke-linejoin="round"/>`,head2=blob(character.head),lift=t.jitter("eye.y",1),eyeSize=t.num("eye.size",.88,1.15),eyes2=mood.eyes.map((kind,i)=>{let[x,y]=character.eyes[i],eye3=drawEye(kind,eyeSize,!!character.ovalEyes),blinks=kind!=="happy"&&kind!=="wink"&&kind!=="line";return`<g transform="translate(${point(x,y+lift)})"><g data-widen="">${blinks?`<g data-blink="">${eye3}</g>`:eye3}</g></g>`}).join(""),[mx,my,ms,mt]=character.mouth,mouth3=`<g transform="translate(${point(mx,my)}) rotate(${mt}) scale(${ms})">${drawMouth2(mood.mouth,weight/ms)}</g>`,blush=mood.blush?character.cheeks.map(([x,y])=>`<ellipse cx="${round25(x+(x<50?3:-3))}" cy="${round25(y-4)}" rx="3.6" ry="2" fill="${BLUSH}" fill-opacity="0.75"/>`).join(""):"",brows=mood.brows?character.eyes.map(([x,y],i)=>`<path d="M${point(x+(i?3.6:-3.6),y-5.2)}L${point(x+(i?-2.2:2.2),y-3.8)}" fill="none" stroke="${INK}" stroke-width="${round25(weight*.8)}" stroke-linecap="round"/>`).join(""):"",whiskers=character.whiskers?lines(character.whiskers,weight*.9):"",drawArt=(art,to,scale,traced,turn2=0)=>`<g transform="${placed(art.from,to,scale,turn2)}">`+(art.inOutline&&character.name===traced||!art.fill?"":`<path d="${art.fill}" fill="${fur}"/>`)+lines(art.lines,weight/scale)+"</g>",[shoulderL,shoulderR]=character.shoulders,[cheekL,cheekR]=character.cheeks,[eyeL,eyeR]=character.eyes,armWidth=10.5*(character.arms??1),arm=(from,to,bulge)=>{let bend=[(from[0]+to[0])/2+bulge,(from[1]+to[1])/2+4],d=`M${at(from)}Q${at(bend)} ${at(to)}`;return`<path d="${d}" fill="none" stroke="${INK}" stroke-width="${round25(armWidth+weight*2)}" stroke-linecap="round"/><path d="${d}" fill="none" stroke="${fur}" stroke-width="${round25(armWidth)}" stroke-linecap="round"/>`},mitten=([x,y],turn2,extra="")=>`<g transform="translate(${point(x,y)}) rotate(${round25(turn2)})">${extra}<path d="${MITTEN}" fill="${fur}" ${line4}/>${lines(MITTEN_CREASES,weight*.85)}</g>`,reach=(from,to,bulge,turn2,extra="")=>arm(from,to,bulge)+mitten(to,turn2,extra),front=(()=>{switch(gesture){case"Cheeks":{let scale=character.arms??1,paws=CHEEK_PAWS.map((paw,i)=>drawArt(paw,character.eyes[i],scale,"Tabby")).join(""),sides=character.name==="Tabby"?lines(TABBY_CHIN):CHEEK_SIDES.map((side,i)=>`<g transform="${placed(CHEEK_PAWS[i].from,character.eyes[i],scale)}">${lines(side,weight/scale)}</g>`).join("");return paws+sides}case"Shades":{let[scale,turn2]=character.shades,middle=[(eyeL[0]+eyeR[0])/2,(eyeL[1]+eyeR[1])/2],glasses2=`<g transform="${placed(SHADES_AT,middle,scale,turn2)}"><path d="${LENSES}" fill="${LENS}" stroke="${INK}" stroke-width="${round25(1.3/scale)}" stroke-linejoin="round"/>${lines(SHADES_BAR,2.8)}<path d="${SHADES_GLINT}" fill="none" stroke="${GLINT}" stroke-width="0.9" stroke-linecap="round"/><ellipse cx="32" cy="43" rx="1.9" ry="1.2" transform="rotate(15 32 43)" fill="${GLINT}"/><ellipse cx="66.4" cy="45.2" rx="2.1" ry="1.3" transform="rotate(10 66.4 45.2)" fill="${GLINT}"/></g>`,r=turn2*Math.PI/180,dx=(SHADES_END[0]-SHADES_AT[0])*scale,dy=(SHADES_END[1]-SHADES_AT[1])*scale,end=[middle[0]+dx*Math.cos(r)-dy*Math.sin(r),middle[1]+dx*Math.sin(r)+dy*Math.cos(r)];return glasses2+drawArt(SHADES_PAW,end,Math.max(.8,scale),"Calico")}case"Salute":return drawArt(SALUTE,eyeL,character.arms??1,"");case"Heart":{let[cx,cy]=character.chest;return`<path d="M${point(cx,cy+3)}C${point(cx-7,cy-2)} ${point(cx-5,cy-8)} ${point(cx-2,cy-7.4)}C${point(cx-.8,cy-7.2)} ${point(cx,cy-6)} ${point(cx,cy-5)}C${point(cx,cy-6)} ${point(cx+.8,cy-7.2)} ${point(cx+2,cy-7.4)}C${point(cx+5,cy-8)} ${point(cx+7,cy-2)} ${point(cx,cy+3)}Z" fill="${HEART}" ${line4}/>`+reach(shoulderL,[cx-8,cy-1],-4,60)+reach(shoulderR,[cx+8,cy-1],4,-60)}case"Wave":{let hand=[cheekR[0]+12,cheekR[1]-16],marks2=lines(`M${point(hand[0]+8,hand[1]-7)}q3 3 0 6M${point(hand[0]+11,hand[1]-9)}q4.4 4.6 0 9.2`,weight*.8);return reach(shoulderR,hand,8,12)+marks2}case"Shy":{let x=(cheekL[0]+cheekR[0])/2,y=Math.max(cheekL[1],cheekR[1])+12;return reach(shoulderL,[x-5.4,y],-5,50)+reach(shoulderR,[x+5.4,y],5,-50)}case"Peace":{let finger=d=>`<path d="${d}" fill="none" stroke="${INK}" stroke-width="${round25(4.4+weight*2)}" stroke-linecap="round"/><path d="${d}" fill="none" stroke="${fur}" stroke-width="4.4" stroke-linecap="round"/>`,fingers=finger("M-2.6 -6L-4.8 -14.6")+finger("M2.6 -6L5.4 -14");return reach(shoulderR,[cheekR[0]+10,cheekR[1]-2],6,0,fingers)}default:return""}})();return scopeAll({defs:`<clipPath id="buddy-head"><path d="${head2}"/></clipPath><clipPath id="buddy-body"><path d="${character.body||head2}"/></clipPath>`,tile,pose:`${pose.transform} rotate(${round25(t.jitter("tilt",5))} 50 100) ${character.frame}`.trim(),mirrored:!!pose.mirrored,ears:["",""],body:(character.body?`<path d="${character.body}" fill="${fur}" ${line4}/>`:"")+`<path d="${head2}" fill="${fur}" ${line4}/>${character.markings(fur,patch)}${character.details?.(fur,patch,weight)??""}`,eyes:eyes2,face:(character.nose?.(fur,weight)??"")+mouth3+blush+brows+whiskers,front,blinkDelay:t.num("blink",0,4)},"buddy",ids)}var TILE_SHAPE='<rect width="100" height="100" rx="22.22"/>',buddySvg=(name,overrides)=>{let b=createBuddy(name,overrides);return`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><defs>${b.defs}<clipPath id="buddy-tile">${TILE_SHAPE}</clipPath></defs>`+TILE_SHAPE.replace("/>",` fill="${b.tile}"/>`)+`<g clip-path="url(#buddy-tile)"><g transform="${b.pose}">${b.body}${b.face}${b.eyes}${b.front}</g></g></svg>`};var named2=list=>list.map(({name:label})=>({label})),controls5=(name,overrides)=>{let t=calmed(createTraits(name,overrides),CALMING4),list=control=>narrowed(control,t,CALMING4),character=characterOf(t);return[{title:"Buddy",controls:[choice(t,"character","Character","list",named2(CHARACTERS)),list(choice(t,"mood","Expression","list",named2(MOODS))),possibilitiesSlider(t,NOTES5),choice(t,"gesture","Gesture","list",named2(GESTURES)),list(choice(t,"pose","Pose","list",named2(POSES))),slider(t,"eye.size","Eye size",0,100,"%"),slider(t,"tilt","Tilt",-5,5,"\xB0"),slider(t,"weight","Line weight",0,100,"%")]},{title:"Colour",controls:[palette(t,"tile","Colour",TILES),palette(t,"fur","Fur",character.furs),...character.name==="Calico"?[palette(t,"patch","Patches",PATCHES)]:[]]}]};var CALMING5={features:/^(eye|face|mouth)\.|^(wobble|tilt|weight)$/,lists:{mood:[24,8,[1,5,7,3,6,8,2,0,19,12,15,16,22,4,14,18,9,23,21,17,10,13,20,11]]},rarer:["cheeks","nose"]},NOTES6=["mild emotions like cute, happy and sleepy, drawn with a steady hand.","adds winks, laughs, mischief and tears, cheeks and noses, with looser lines.","every emotion, up to starstruck, hypnotised and dizzy, at its wobbliest."];var TILES2=["#ffffff","#fbf6ec","#f2f2ef","#fdeef0","#eaf6ee","#eaf2fb","#f1ecfa","#f7efe2","#fff7d6"],INKS=["#111111","#2b2d42","#4a2c1d","#1f3a5f","#ffffff"],round26=value=>Math.round(value*100)/100,point2=(x,y)=>`${round26(x)} ${round26(y)}`;function blob2(pen,key2,cx,cy,rx,ry,cut){let{t,wobble}=pen,waves=[2,3,5].map(count=>[count,t.jitter(`${key2}.a${count}`,wobble),t.num(`${key2}.p${count}`,0,2*Math.PI)]),points=Array.from({length:32},(_,i)=>{let angle=i/32*2*Math.PI,r=1+waves.reduce((sum,[count,amount,start])=>sum+amount*Math.cos(count*angle+start),0),x=cx+rx*r*Math.cos(angle),y=cy+ry*r*Math.sin(angle);return cut&&(y=Math.max(y,cy+cut.at*ry+cut.slope*(x-cx))),[x,y]}),mid=i=>{let[ax,ay]=points[i%points.length],[bx,by2]=points[(i+1)%points.length];return point2((ax+bx)/2,(ay+by2)/2)};return`<path d="M${mid(0)}${points.map((_,i)=>`Q${point2(...points[(i+1)%points.length])} ${mid(i+1)}`).join("")}Z"/>`}function stroke(pen,key2,d){let nudge=index2=>round26(pen.t.jitter(`${key2}.n${index2}`,pen.wobble*10)),index=0;return`<path d="${d.replace(/Q(-?[\d.]+) (-?[\d.]+)/g,(_,x,y)=>`Q${round26(Number(x)+nudge(index++))} ${round26(Number(y)+nudge(index++))}`)}" fill="none"/>`}var EYES={dot:(pen,{x,y,r},key2)=>blob2(pen,key2,x,y,r*.82,r*.92),big:(pen,{x,y,r},key2)=>blob2(pen,key2,x,y,r*1.08,r*1.14),angry:(pen,{x,y,r,side},key2)=>blob2(pen,key2,x,y,r*1.02,r*.95,{at:-.18,slope:-side*.5}),flat:(pen,{x,y,r},key2)=>blob2(pen,key2,x,y,r*1.08,r*.92,{at:-.05,slope:0})+stroke(pen,`${key2}.lid`,`M${point2(x-r*1.25,y-r*.05)}Q${point2(x,y-r*.12)} ${point2(x+r*1.25,y-r*.05)}`),ring:(pen,{x,y,r},key2)=>`<circle cx="${round26(x)}" cy="${round26(y)}" r="${round26(r*.95)}" fill="none"/>`+blob2(pen,key2,x,y-r*.12,r*.44,r*.48),arc:(pen,{x,y,r},key2)=>stroke(pen,key2,`M${point2(x-r,y+r*.35)}Q${point2(x,y-r*1.1)} ${point2(x+r,y+r*.35)}`),closed:(pen,{x,y,r},key2)=>stroke(pen,key2,`M${point2(x-r,y-r*.15)}Q${point2(x,y+r*.85)} ${point2(x+r,y-r*.15)}`),heart:(_pen,{x,y,r})=>{let s=r*.11;return`<path d="M${point2(x,y+8*s)}C${point2(x-11*s,y)} ${point2(x-8*s,y-9*s)} ${point2(x,y-4*s)}C${point2(x+8*s,y-9*s)} ${point2(x+11*s,y)} ${point2(x,y+8*s)}Z"/>`},cross:(pen,{x,y,r},key2)=>stroke(pen,key2,`M${point2(x-r*.75,y-r*.75)}Q${point2(x,y)} ${point2(x+r*.75,y+r*.75)}`)+stroke(pen,`${key2}.b`,`M${point2(x+r*.75,y-r*.75)}Q${point2(x,y)} ${point2(x-r*.75,y+r*.75)}`),teary:(pen,eye3,key2)=>EYES.dot(pen,eye3,key2)+`<path d="M${point2(eye3.x+eye3.side*eye3.r*.2,eye3.y+eye3.r*1.2)}q-1.6 2.6 0 4q1.6 -1.4 0 -4Z" fill="none"/>`,star:(pen,{x,y,r},key2)=>`<path d="M${Array.from({length:10},(_,i)=>{let angle=-Math.PI/2+i*Math.PI/5,reach=r*(i%2?.45:1.05)*(1+pen.t.jitter(`${key2}.t${i}`,pen.wobble*1.5));return point2(x+reach*Math.cos(angle),y+reach*Math.sin(angle))}).join("L")}Z"/>`,spiral:(pen,{x,y,r,side},key2)=>{let turns=3.5*Math.PI,waver=pen.t.jitter(`${key2}.w`,pen.wobble*2);return`<path d="M${Array.from({length:33},(_,i)=>{let angle=i/32*turns,reach=(r*1.05*(1-i/32)+r*.1)*(1+waver*Math.sin(angle*1.5));return point2(x+side*reach*Math.cos(angle),y+reach*Math.sin(angle))}).join("L")}" fill="none" stroke-width="2.2"/>`}},brow=(pen,{x,y,r,side},key2,lift)=>stroke(pen,key2,`M${point2(x-r*1.1,y-r*(1.75+lift*side))}Q${point2(x,y-r*2.15)} ${point2(x+r*1.1,y-r*(1.75-lift*side))}`),MOUTHS2={fangs:["M-5 0Q0 0.6 5 0M-3.3 0.2l1.3 2.8l1.3 -2.8M0.7 0.2l1.3 2.8l1.3 -2.8"],cat:["M-5 -1Q-2.5 3.8 0 0Q2.5 3.8 5 -1"],frown:["M-3.8 2.2Q0 -2.2 3.8 2.2"],wavy:["M-4.5 1Q-2.2 -2 0 0.6Q2.2 3 4.5 -0.6"],smile:["M-4.5 -1Q0 4.6 4.5 -1"],oh:["M-3 1.4a3 3.6 0 1 0 6 0a3 3.6 0 1 0 -6 0Z"],line:["M-3 0.5Q0 0.2 3 0.5"],smirk:["M-4.5 1Q1 2.6 4.5 -2"],grin:["M-5.5 -0.5Q0 0 5.5 -0.5Q5 6 0 6.2Q-5 6 -5.5 -0.5Z",!0],tongue:["M-4.5 -1Q0 4 4.5 -1M0.5 2.2Q1 6 3.4 5.4Q5 4.4 3.6 1.4"],kiss:["M-1.2 -3Q3 -2.2 0 0Q3 2.2 -1.2 3"],shout:["M-4.2 3.2Q-4 -2.8 0 -3Q4 -2.8 4.2 3.2Q0 2 -4.2 3.2Z",!0],teeth:["M-5.5 -2.4Q0 -2.7 5.5 -2.4Q5.8 0 5.5 2.4Q0 2.7 -5.5 2.4Q-5.8 0 -5.5 -2.4ZM-1.8 -2.4Q-1.7 0 -1.8 2.4M1.8 -2.4Q1.9 0 1.8 2.4",!1,1.3]},MOODS2=[{name:"Grumpy",eyes:["angry","angry"],mouth:"fangs"},{name:"Cute",eyes:["dot","dot"],mouth:"cat"},{name:"Skeptical",eyes:["ring","dot"],mouth:"wavy",brows:[-.15,.45]},{name:"Unimpressed",eyes:["flat","flat"],mouth:"frown"},{name:"Mischief",eyes:["flat","angry"],mouth:"fangs"},{name:"Happy",eyes:["arc","arc"],mouth:"smile"},{name:"Shocked",eyes:["big","big"],mouth:"oh"},{name:"Sleepy",eyes:["closed","closed"],mouth:"line"},{name:"Smug",eyes:["flat","flat"],mouth:"smirk",brows:[null,-.35]},{name:"Teary",eyes:["teary","teary"],mouth:"wavy",brows:[.3,-.3]},{name:"In love",eyes:["heart","heart"],mouth:"tongue"},{name:"Dizzy",eyes:["cross","cross"],mouth:"grin"},{name:"Wink",eyes:["dot","closed"],mouth:"smile"},{name:"Starstruck",eyes:["star","star"],mouth:"grin"},{name:"Worried",eyes:["dot","dot"],mouth:"frown",brows:[.35,-.35]},{name:"Laughing",eyes:["arc","arc"],mouth:"grin"},{name:"Surprised",eyes:["ring","ring"],mouth:"oh"},{name:"Furious",eyes:["angry","angry"],mouth:"shout"},{name:"Kissy",eyes:["closed","closed"],mouth:"kiss"},{name:"Neutral",eyes:["dot","dot"],mouth:"line"},{name:"Hypnotised",eyes:["spiral","spiral"],mouth:"wavy"},{name:"Nervous",eyes:["big","big"],mouth:"teeth"},{name:"Sly",eyes:["flat","flat"],mouth:"cat"},{name:"Silly",eyes:["dot","big"],mouth:"tongue"}],moodOf2=t=>t.pick("mood",MOODS2),CHEEK_ODDS=35,CHEEKS=["Rosy","Hatched","Freckles"],NOSE_ODDS=30,NOSES=["Dot","Hook","Line"],present=(t,key2,odds,kinds)=>t(key2)*100<odds?t.pick(`${key2}.kind`,kinds):void 0;function drawCheeks(pen,eyes2){let kind=present(pen.t,"cheeks",CHEEK_ODDS,CHEEKS);return kind?eyes2.map(({x,y,r,side},i)=>{let cx=x+side*r*.35,cy=y+r*1.75;return kind==="Rosy"?`<ellipse cx="${round26(cx)}" cy="${round26(cy)}" rx="${round26(r*.62)}" ry="${round26(r*.36)}" fill="#ff8fa3" fill-opacity="0.55" stroke="none"/>`:kind==="Freckles"?[-.4,0,.4].map((dx,j)=>`<circle cx="${round26(cx+dx*r)}" cy="${round26(cy+(j===1?-.25:.1)*r)}" r="0.7" stroke="none"/>`).join(""):[-.45,0,.45].map((dx,j)=>stroke(pen,`cheek${i}.${j}`,`M${point2(cx+dx*r-1.2,cy+1.6)}Q${point2(cx+dx*r,cy)} ${point2(cx+dx*r+1.2,cy-1.6)}`)).join("").replace(/<path /g,'<path stroke-width="1.6" ')}).join(""):""}function drawNose(pen,y){let kind=present(pen.t,"nose",NOSE_ODDS,NOSES);return kind?kind==="Dot"?blob2(pen,"nose",0,y,1.5,1.2):kind==="Hook"?stroke(pen,"nose",`M${point2(.6,y-2.6)}Q${point2(-2.4,y+1.4)} ${point2(1.2,y+1.6)}`):stroke(pen,"nose",`M${point2(0,y-2.2)}Q${point2(.4,y)} ${point2(0,y+2)}`):""}var COLOURWAYS=[{label:"Sorbet",colors:["#fc8b8a","#38aa85","#fcc73a","#263252"]},{label:"Lagoon",colors:["#1c7ed6","#22b8cf","#94d82d","#0b4f6c"]},{label:"Ember",colors:["#e03131","#f76707","#fab005","#5c3d2e"]},{label:"Candy",colors:["#ff5d8f","#a06cd5","#4cc9f0","#ffbe0b"]},{label:"Forest",colors:["#2b9348","#80b918","#d4a373","#354f52"]},{label:"Berry",colors:["#d63384","#7048e8","#ffa94d","#4a1942"]},{label:"Citrus",colors:["#ff7b00","#ffd60a","#38b000","#0077b6"]},{label:"Dusk",colors:["#3d5a80","#ee6c4d","#98c1d9","#293241"]},{label:"Rose",colors:["#e56b6f","#b56576","#6d597a","#eaac8b"]},{label:"Mint",colors:["#20c997","#f783ac","#4dabf7","#495057"]}],PARTS2=["left","right","mouth"];function coloursOf4(t){let tile=t.color("tile")??t.pick("tile",TILES2),ink=t.color("ink")??INKS[0];if((t.forced("colourful")??1)>=.5)return{tile,ink};let order=t.pick("colourway",COLOURWAYS).colors.map((color,i)=>[t(`colourway.${i}`)+(contrast(color,tile)<1.5?1:0),color]).sort(([a],[b])=>a-b);return{tile,ink,parts:Object.fromEntries(PARTS2.map((part,i)=>[part,t.color(part)??order[i][1]]))}}function createDoodle(name,overrides){let t=calmed(createTraits(name,overrides),CALMING5),mood=moodOf2(t),{tile,ink,parts}=coloursOf4(t),tint=part=>parts?` color="${parts[part]}"`:"",pen={t,wobble:t.num("wobble",.02,.09)},r=t.num("eye.size",8.4,11),gap=t.num("eye.gap",17.5,23),eyeY=t.num("eye.y",-7,-3),eyes2=[-1,1].map(side=>({x:side*gap,y:eyeY+t.jitter(`eye.dy${side}`,.8),r:r*(1+t.jitter(`eye.r${side}`,.06)),side})),drawEye3=(eye3,i)=>`<g${tint(PARTS2[i])}>${EYES[mood.eyes[i]](pen,eye3,`eye${i}`)}${mood.brows?.[i]!=null?brow(pen,eye3,`brow${i}`,mood.brows[i]):""}</g>`,[d,filled,fine]=MOUTHS2[mood.mouth],size=t.num("mouth.size",1.3,1.7),mouthY=eyeY+t.num("mouth.y",16,21);return{tile,ink,face:`translate(${round26(50+t.jitter("face.x",4))} ${round26(52+t.jitter("face.y",4))}) rotate(${round26(t.jitter("tilt",7))})`,weight:round26(t.num("weight",3.2,4.2)),eyes:eyes2.map(drawEye3).join(""),mouth:`<g transform="translate(${round26(t.jitter("mouth.x",2))} ${round26(mouthY)}) scale(${round26(size)})"${tint("mouth")}>`+(filled?`<path d="${d}" stroke="none"/>`:stroke(pen,"mouth",d).replace("<path ",fine?`<path stroke-width="${fine}" `:"<path "))+"</g>",marks:`<g${tint("mouth")}>${drawCheeks(pen,eyes2)}${drawNose(pen,round26(eyeY+(mouthY-eyeY)*.5))}</g>`,mood:mood.name,blinkDelay:t.num("blink",0,4)}}var INK_STYLE=weight=>`fill="currentColor" stroke="currentColor" stroke-width="${weight}" stroke-linecap="round" stroke-linejoin="round"`,doodleSvg=(name,overrides)=>{let doodle=createDoodle(name,overrides);return`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><rect width="100" height="100" rx="22.22" fill="${doodle.tile}"/><g transform="${doodle.face}" color="${doodle.ink}" ${INK_STYLE(doodle.weight)}>${doodle.marks}${doodle.eyes}${doodle.mouth}</g></svg>`};var labelled=labels=>labels.map(label=>({label})),controls6=(name,overrides)=>{let t=calmed(createTraits(name,overrides),CALMING5),list=control=>narrowed(control,t,CALMING5),{parts}=coloursOf4(t);return[{title:"Face",controls:[list(choice(t,"mood","Emotion","list",MOODS2.map(({name:label})=>({label})))),possibilitiesSlider(t,NOTES6),optional(t,"cheeks",CHEEK_ODDS,"cheeks.kind","Cheeks","list",labelled(CHEEKS)),optional(t,"nose",NOSE_ODDS,"nose.kind","Nose","list",labelled(NOSES)),slider(t,"eye.size","Eye size",0,100,"%"),slider(t,"eye.gap","Eye gap",0,100,"%"),slider(t,"mouth.size","Mouth size",0,100,"%"),slider(t,"face.y","Face height",-100,100,"%"),slider(t,"face.x","Face across",-100,100,"%"),slider(t,"tilt","Tilt",-7,7,"\xB0")]},{title:"Lines",controls:[slider(t,"wobble","Hand-drawn",0,100,"%"),slider(t,"weight","Line weight",0,100,"%")]},{title:"Colour",controls:[palette(t,"tile","Colour",TILES2),{...toggle(t,"colourful",50,"Colourful"),selected:parts?"on":"off"},...parts?[PARTS2.reduce(clearingColor,choice(t,"colourway","Colourway","swatches",COLOURWAYS.map(({label,colors})=>({label,color:`conic-gradient(${colors.map((color,i)=>`${color} 0 ${(i+1)*25}%`).join(", ")})`})))),{type:"colors",id:"ink",label:"Inks",colors:PARTS2.map(part=>({id:colorKey(part),color:parts[part]}))}]:[fixedPalette(t,"ink","Ink",INKS)]]}]};var CALMING6={features:/^(head|eye|ear|whisker|lid|body)\.|^tilt$/,lists:{mood:[13,8,[2,4,3,1,7,0,5,8,12,6,9,10,11]],pose:[6,2],"fur.style":[3,1]}},NOTES7=["mild moods like curious, happy and sleepy, with smooth fur, sitting in from the corner.","adds sassy and sly looks, fluffy and chubby cheeks, and more poses.","every expression, up to smitten, menacing and dizzy, in any pose."];var TILES3=["#2fe370","#ffd23f","#ff5fa2","#3fa9ff","#ff8a2b","#9b6bff","#ff4b4b","#16c8b0","#b6f03c"],FURS=["#050505","#26262b","#4a4a55","#e0893b","#7a5136"],EYE_COLOURS=["#f3f7f3","#ffe14d","#c8f55a","#8fe0ff","#ffb347"],TONGUE2="#ff7aa8",round27=value=>Math.round(value*100)/100,point3=(x,y)=>`${round27(x)} ${round27(y)}`,at2=([x,y])=>point3(x,y),lerp=(a,b,k)=>[a[0]+(b[0]-a[0])*k,a[1]+(b[1]-a[1])*k],polygon2=points=>`M${points.map(at2).join("L")}Z`,distance=(a,b)=>Math.hypot(b[0]-a[0],b[1]-a[1]),ellipse=([x,y],rx,ry,turn2,fill)=>`<ellipse cx="${round27(x)}" cy="${round27(y)}" rx="${round27(rx)}" ry="${round27(ry)}" transform="rotate(${round27(turn2)} ${point3(x,y)})" fill="${fill}"/>`;function turned([x,y],degrees){let r=degrees*Math.PI/180;return[x*Math.cos(r)-y*Math.sin(r),x*Math.sin(r)+y*Math.cos(r)]}function smooth(points){let n=points.length,d=`M${at2(points[0])}`;for(let i=0;i<n;i++){let[p0,p1,p2,p3]=[points[(i+n-1)%n],points[i],points[(i+1)%n],points[(i+2)%n]];d+=`C${point3(p1[0]+(p2[0]-p0[0])/6,p1[1]+(p2[1]-p0[1])/6)} ${point3(p2[0]-(p3[0]-p1[0])/6,p2[1]-(p3[1]-p1[1])/6)} ${at2(p2)}`}return`${d}Z`}var VIEWS=[{name:"Three-quarter",centre:[55,58],nose:[42.8,57.2],tilt:-18,frame:"",head:[[14.5,46],[22,37.5],[33,31.5],[48,26.5],[63,25.5],[77.5,28.8],[86.7,37.5],[90.8,46.7],[91.7,54.2],[90.8,61],[87.5,69.5],[80,77],[62,85],[45,90],[35.8,90],[27.5,87.5],[19,81.7],[12.8,73.3],[10.8,63.3],[11.6,54]],cheeks:[7,8,9,10,15,16,17,18,19],body:[[35.8,88],[35,130],[130,130],[130,112],[100,84],[86.7,70.4]],ears:[{inner:[29.2,32.9],tip:[6.2,29],outer:[12.3,52.9]},{inner:[47.9,25.8],tip:[60.2,6.2],outer:[77.5,28.8]}],whiskers:[[[22.7,65.8],[10.5,64.6],[.8,66.7]],[[22.9,69.2],[11.5,71.3],[.8,77.9]],[[24,73.2],[14.5,78.2],[6.8,86.3]],[[70,51.3],[83,42.8],[94.2,37.3]],[[71.7,55.4],[85,51],[98.5,49.2]],[[73.3,59.2],[86,59.2],[95,62.7]]],eyes:[{c:[-14.1,-6.6],rx:9.4,ry:7.2},{c:[20.4,-6.6],rx:11.6,ry:8.6}],noseShape:"M-2.9 -0.7Q0 -2 3 -1Q3.4 -0.4 2.5 0.5L0.6 1.7Q-0.2 2.2 -1.1 1.5L-2.7 0.3Q-3.4 -0.2 -2.9 -0.7Z",noseTint:[WHITE,.17],earTint:[WHITE,.2]},{name:"Front",centre:[66,55],nose:[55.8,57],tilt:1,frame:"translate(-2 1) translate(66 55) scale(0.95) translate(-66 -55)",head:[[31.7,26.7],[45,17.5],[61,13.5],[75,12.5],[84,14.5],[96,19],[106,26],[112,40],[114,55],[112,70],[105,82],[90,90],[70,93],[50,90],[36,83],[27,76],[21.5,67],[19.6,58],[20.5,48],[24.5,37.5]],cheeks:[8,9,10,15,16,17,18,19],body:[[35,82],[24.5,130],[130,130],[130,60],[105,82]],ears:[{inner:[61,13.5],tip:[41.5,-1],outer:[31.7,27.5]},{inner:[84,14.5],tip:[110,-6],outer:[108,30]}],whiskers:[[[31.9,57.9],[20,54.3],[9.2,51]],[[31.3,62.1],[20,61.9],[8.8,61.7]],[[31,66.4],[21,69],[10.8,71.7]],[[87.5,61.7],[94,60.4],[104,58.5]],[[88.3,66.3],[95,66.9],[104,67.8]],[[87.5,70.8],[94,73.4],[104,77]]],eyes:[{c:[-14.9,-7.6],rx:9.5,ry:7.4},{c:[23.8,-7],rx:12.4,ry:8.4}],noseShape:"M-3.3 -1.3Q0 -2 3.3 -1.3Q3.9 -0.8 3.1 0L0.9 1.6Q0 2.2 -0.9 1.6L-3.1 0Q-3.9 -0.8 -3.3 -1.3Z",noseTint:["#f27ba3",1],earTint:["#9b87b0",.42],greyWhiskers:!0,tallPupils:!0}],POSES2=[{name:"Corner",x:0,y:0,scale:1,turn:0},{name:"Other corner",x:0,y:0,scale:1,turn:0,mirrored:!0},{name:"Centre",x:-6,y:-2,scale:.78,turn:8},{name:"Peeking",x:-4,y:24,scale:.9,turn:10},{name:"Close up",x:4,y:6,scale:1.25,turn:2},{name:"Tilted",x:2,y:2,scale:.95,turn:-12}],EARS=[{name:"Classic",height:1,flare:0,round:3.4},{name:"Folded",height:.5,flare:-12,round:4.6,folded:!0},{name:"Tall",height:1.32,flare:-4,round:2.2},{name:"Notched",height:1,flare:0,round:3.2,notch:!0},{name:"Short",height:.72,flare:8,round:3.6},{name:"Tufted",height:1.12,flare:0,round:1.6,tuft:!0},{name:"Mismatched",height:1,flare:0,round:3.4,odd:!0},{name:"Wide",height:.9,flare:16,round:3}],OWL_VIEW={name:"Owl",centre:[50.5,53],nose:[47.6,54.5],tilt:-10,frame:"",head:[[28.5,31],[40,24],[55,21.5],[64.5,22.3],[76,26.5],[85,34],[89.5,44],[90.6,52],[88.5,62],[82,70.5],[65,78],[40,80],[23.5,77],[15.5,70],[11,60],[10.6,52],[12,45.5],[18,37]],cheeks:[],body:[[23.5,76],[20.5,92],[19.2,130],[130,130],[130,118],[100,95],[90,80],[82,70.5]],ears:[{inner:[28.5,31],tip:[6,27],outer:[12,45.5]},{inner:[64.5,22.3],tip:[85.5,12.8],outer:[85,34]}],whiskers:[],eyes:[{c:[-15.7,-6.6],rx:10.8,ry:9.4},{c:[17.6,-7.4],rx:12.4,ry:10}],noseShape:"",noseTint:[WHITE,.9],earTint:[WHITE,.2]},DOG_VIEW={name:"Dog",centre:[52,50],nose:[65.6,53.8],tilt:-12,frame:"",head:[[41,29.5],[48,27.5],[55.8,26.3],[66,30],[79.3,39],[84,44],[87.3,51.8],[86,58],[81,64],[74.6,68.6],[66,73],[50,75],[35,73.5],[30,72],[26.3,67.4],[21,70.2],[16.6,66],[16,60],[17.9,55],[20,48],[25,40],[33,33.5]],cheeks:[],body:[[30,72],[28.3,79.7],[16,100],[13,130],[86,130],[82.1,100],[74.2,76.6],[74.6,68.6]],ears:[{inner:[41,29.5],tip:[23,19.5],outer:[17.9,55]},{inner:[55.8,26.3],tip:[70.5,12.8],outer:[79.3,39]}],whiskers:[],eyes:[{c:[-20,-8.7],rx:9.7,ry:7.8},{c:[6.5,-9.1],rx:7.6,ry:6.2}],noseShape:"M-4.8 -1.6Q-4.6 -3.3 0 -3.3Q4.8 -3.3 5 -1.6Q5 1 2.4 2.6Q0.6 3.4 -0.4 3.2Q-2.6 2.8 -4.2 0.8Q-5 -0.4 -4.8 -1.6Z",noseTint:[WHITE,0],earTint:[WHITE,.22]},DOG_MUZZLE=[[-23.7,6],[-19.7,3.2],[-7.8,-2.9],[.55,-3.6],[7.3,-1.3],[9.6,4.1],[6.7,11.8],[.3,16.8],[-13.4,16],[-22.1,11.2]],DOG_SMIRK="M0.6 3.2Q0.6 4.6 -0.4 5Q-3 8.6 -6.8 8Q-10.6 7.4 -12.4 4.6Q-12.8 4 -13.2 3.6M1.2 4.2Q2 7 3.4 7.6Q4.4 8.1 5.4 8",DOG_FANG="M-6.2 8.1L-9.8 7.4Q-9.5 10.8 -8.4 12Q-7.9 12.5 -7.5 11.8Q-6.6 10 -6.2 8.1Z",MUZZLE="#f5f5f5",COLLAR="M30.5 73.8Q52 83.4 74.2 73.4L74.2 76.6Q51 91 30.7 77.8Z",BONE="M-4.6 -1.2H4.6A1.9 1.9 0 1 1 5.6 1.8L5.6 1.8A1.9 1.9 0 1 1 4.6 1.2H-4.6A1.9 1.9 0 1 1 -5.6 -1.8L-5.6 -1.8A1.9 1.9 0 1 1 -4.6 -1.2Z",COLLARS=["","#e2364c","#2f7df6","#f5b700","#7a4fd6","#16b38a"],mirrored=points=>points.map(([x,y])=>[100-x,y]),TIGER_HALF=[[43,25.5],[30,27],[21,33],[16.5,40],[15.5,48],[15.5,56],[18,63],[23,69],[28.7,75.8],[38,80]],TIGER_WHISKERS=[[[37.5,48.4],[25,48.8],[13.2,50.6]],[[37,51.8],[24.5,53.4],[12.8,56.2]],[[37.5,55],[25.5,58.4],[14.4,63]]],TIGER_VIEW={name:"Tiger",centre:[50,50],nose:[50,45.8],tilt:0,frame:"",head:[[50,25],...mirrored(TIGER_HALF),[50,81],...[...TIGER_HALF].reverse()],cheeks:[],body:[[28.7,74],[21.5,100],[19.5,130],[80.5,130],[78.5,100],[71.3,74]],ears:[{inner:[43,25.5],tip:[23,12],outer:[17.5,37]},{inner:[57,25.5],tip:[77,12],outer:[82.5,37]}],whiskers:[...TIGER_WHISKERS,...TIGER_WHISKERS.map(mirrored)],eyes:[{c:[-14.1,-8.7],rx:9.2,ry:7.2},{c:[14.1,-8.7],rx:9.2,ry:7.2}],noseShape:"M-4.6 -2.4Q0 -2.9 4.6 -2.4Q5.2 -2.1 4.7 -1.4L0.9 2.4Q0 3.2 -0.9 2.4L-4.7 -1.4Q-5.2 -2.1 -4.6 -2.4Z",noseTint:[WHITE,.33],earTint:[WHITE,1],pupilsIn:!0},bothSides=(d,paint)=>`<path d="${d}" ${paint}/><path d="${d}" transform="translate(100 0) scale(-1 1)" ${paint}/>`,TIGER_SPIKES="M16.6 39.5L8.9 45.9L15.6 49ZM15.4 51.5L8.4 56.2L16 60Z",TIGER_STRIPES="M16.5 44.5L21.5 40.8L22.8 46.5L27.8 43.5M19.8 64L24.5 60.5L26 67L32 63.5",TIGER_BROWS="M32.3 30.4Q35 31.2 36.8 33.6M35.5 29.2Q38 30.6 39.2 33.6",TIGER_FLICKS="M41.3 19.8Q43.4 21.4 43 24.2",TIGER_CHEST="M27.9 88.2Q50 76.5 72.1 88.2Q74 95 74.6 102L25.4 102Q26 95 27.9 88.2Z",TIGER_PAD="M0 3.2Q-2 0.8 -7 0.6Q-14.5 0.6 -17.6 4.6Q-17.4 9.8 -12 11.6Q-5.4 12.8 -1.4 9.6Q0.6 7.2 0 3.2Z",SPECIES=[{name:"Cat",ears:"point",nose:"cat",whiskers:!0,fangs:!0},{name:"Dog",ears:"point",head:"dog",cheeks:"Smooth",nose:"dog",fangs:!0,view:DOG_VIEW,earRound:8,earBulge:3.6},{name:"Owl",ears:"tuft",head:"owl",cheeks:"Smooth",nose:"beak",view:OWL_VIEW},{name:"Bear",ears:"round",nose:"bear",cheeks:"Chubby"},{name:"Tiger",ears:"point",head:"tiger",cheeks:"Smooth",nose:"tiger",whiskers:!0,fangs:!0,view:TIGER_VIEW,earInset:.14}],BEAK="#f1f1f1",FUR_STYLES=[{name:"Smooth"},{name:"Fluffy"},{name:"Chubby"}],MOODS3=[{name:"Annoyed",lids:[[20,0],[20,0]],pupil:"none",mouth:"none",fangs:1},{name:"Smug",lids:[[10,0],[10,0]],pupil:"hang",mouth:"smirk",fangs:1},{name:"Curious",lids:["open","open"],pupil:"big",mouth:"w"},{name:"Sleepy",lids:["closed","closed"],pupil:"none",mouth:"flat"},{name:"Happy",lids:["happy","happy"],pupil:"none",mouth:"smile"},{name:"Shocked",lids:["open","open"],pupil:"tiny",mouth:"oh"},{name:"Sly",lids:["closed",[6,.1]],pupil:"hang",mouth:"smirk",fangs:1},{name:"Grumpy",lids:[[-7,.28],[-7,.28]],pupil:"hang",mouth:"frown"},{name:"Hungry",lids:["open","open"],pupil:"big",mouth:"tongue"},{name:"Smitten",lids:[[3,.12],[3,.12]],pupil:"heart",mouth:"w"},{name:"Menacing",lids:[[27,-.05],[27,-.05]],pupil:"slit",mouth:"smirk",fangs:2},{name:"Dizzy",lids:["open","open"],pupil:"cross",mouth:"oh"},{name:"Sassy",lids:[[15,0],[15,0]],pupil:"hang",mouth:"open",fangs:1}],MOUTHS3={none:"",smirk:"M-14.9 6.9Q-12.8 11 -9.1 10.7Q-3.5 10.2 -0.3 6.6Q6.5 11.2 13.4 11.2Q19.4 10.8 19.9 6.1",w:"M-7 5.6Q-4.6 9.4 -0.4 5.8Q4.4 10 9.4 5.8",smile:"M-10 5.8Q-5.5 12 -0.4 7.4Q6 13.6 14 6",frown:"M-6.5 10.4Q2 4.6 10.5 10.4",flat:"M-4.5 8.6Q2 9.6 8.5 8.4",oh:"",tongue:"M-7 5.6Q-4.6 9.4 -0.4 5.8Q4.4 10 9.4 5.8",open:"M-7.3 8Q-3 4.6 0.4 5.6Q2.4 7.4 5.4 7Q13 6.4 19.6 7.2Q19.8 14.6 15 19.4Q11 22.4 6.7 22.2Q0.6 22 -3.8 17.6Q-7.6 13.4 -7.3 8Z"},MOUTH_INSIDE="#d43369",FANG="M9.4 10.7L14.6 11.3Q14.4 15.2 12.8 16.4Q12.1 16.9 11.6 16.1Q10.2 13.6 9.4 10.7Z",FAR_FANG="M-5.2 10.1L-8.6 10.6Q-8.4 13.6 -7.3 14.4Q-6.8 14.7 -6.5 14.2Q-5.7 12.3 -5.2 10.1Z",OPEN_FANG="M11.6 8.1L15.2 7.8Q14.8 11.8 13.8 14Q13.3 14.8 12.8 13.9Q12.1 11.4 11.6 8.1Z",viewOf=t=>t.pick("view",VIEWS),speciesOf=t=>t.pick("animal",SPECIES),moodOf3=t=>t.pick("mood",MOODS3),poseOf2=t=>t.pick("pose",POSES2),earsOf=t=>t.pick("ears",EARS),furStyleOf=t=>t.pick("fur.style",FUR_STYLES);function coloursOf5(t){return{tile:t.color("tile")??t.pick("tile",TILES3),fur:t.color("fur")??FURS[0],eye:t.color("eyes.color")??EYE_COLOURS[0]}}function drawEar(inner,tip,outer,centre,style,fur,shade,bulge=1.7,inset=0){let middle=lerp(inner,outer,.5),centroid=[(inner[0]+tip[0]+outer[0])/3,(inner[1]+tip[1]+outer[1])/3],bowed=(from,to,by2)=>{let mid=lerp(from,to,.5),away=distance(mid,centroid)||1;return[mid[0]+(mid[0]-centroid[0])/away*by2,mid[1]+(mid[1]-centroid[1])/away*by2]},a=lerp(tip,inner,Math.min(.4,style.round/distance(tip,inner))),b=lerp(tip,outer,Math.min(.4,style.round/distance(tip,outer))),outerEdge=style.notch?(()=>{let dent=lerp(lerp(b,outer,.42),centroid,.22);return`L${at2(lerp(b,outer,.32))}L${at2(dent)}L${at2(lerp(b,outer,.52))}L${at2(outer)}`})():`Q${at2(bowed(b,outer,bulge+.1))} ${at2(outer)}`,inside=lerp(middle,centre,.3),ear=`<path d="M${at2(inner)}Q${at2(bowed(inner,a,bulge-.1))} ${at2(a)}Q${at2(tip)} ${at2(b)}${outerEdge}L${at2(inside)}Z" fill="${fur}"/>`,liningTip=style.round>4?.17+(style.round-4)*.06:.17,lining=style.folded?"":`<path d="${polygon2([lerp(tip,centroid,liningTip+inset),lerp(inner,centroid,.42+inset),lerp(outer,centroid,.3+inset)])}" fill="${shade}" stroke="${shade}" stroke-width="1.4" stroke-linejoin="round"/>`,tufts=style.tuft?[-12,0,12].map(spread=>{let[x,y]=turned([tip[0]-middle[0],tip[1]-middle[1]],spread),length=Math.hypot(x,y);return`M${at2(tip)}l${point3(x/length*4.2,y/length*4.2)}`}).join(""):"";return ear+lining+(tufts?`<path d="${tufts}" stroke="${fur}" stroke-width="0.9" stroke-linecap="round" fill="none"/>`:"")}function drawRoundEar(inner,tip,outer,style,fur,shade){let middle=lerp(inner,outer,.5),base=distance(inner,outer);{let r=base*.42*Math.sqrt(style.height)*(style.folded?.8:1),[x,y]=lerp(middle,tip,.3);return`<circle cx="${round27(x)}" cy="${round27(y)}" r="${round27(r)}" fill="${fur}"/>`+(style.folded?"":`<circle cx="${round27(x)}" cy="${round27(y)}" r="${round27(r*.55)}" fill="${shade}"/>`)}}function drawOwlTuft(inner,tip,outer,centre,style,fur,grey){let tuft=drawEar(inner,tip,outer,centre,{...style,folded:!0},fur,grey,1.3);if(style.folded)return tuft;let centroid=[(inner[0]+tip[0]+outer[0])/3,(inner[1]+tip[1]+outer[1])/3],from=lerp(tip,outer,.1),to=lerp(outer,inner,.52),bend=lerp(lerp(tip,outer,.6),centroid,.05),back=lerp(bend,inner,.5);return tuft+`<path d="M${at2(from)}Q${at2(bend)} ${at2(to)}Q${at2(back)} ${at2(from)}Z" fill="${grey}"/>`}function eyeShape(lid2,rx,ry,inner){if(typeof lid2=="string")return`M${point3(-rx,0)}A${round27(rx)} ${round27(ry)} 0 1 0 ${point3(rx,0)}A${round27(rx)} ${round27(ry)} 0 1 0 ${point3(-rx,0)}Z`;let[slope,depth]=lid2,d=depth*ry,m=Math.tan(slope*Math.PI/180)*inner,a=1/rx**2+m**2/ry**2,b=2*m*d/ry**2,root=Math.sqrt(Math.max(0,b**2-4*a*(d**2/ry**2-1))),[x1,x2]=[(-b-root)/(2*a),(-b+root)/(2*a)];return`M${point3(x2,d+m*x2)}A${round27(rx)} ${round27(ry)} 0 ${d<0?1:0} 1 ${point3(x1,d+m*x1)}Z`}function drawPupil(pupil,lid2,rx,ry,inner,gaze,ink,tall){if(pupil==="none")return"";if(pupil==="hang"){let r=ry*.38,x=gaze*rx*.42,[slope,depth]=typeof lid2=="string"?[0,-.3]:lid2,y=depth*ry+Math.tan(slope*Math.PI/180)*x*inner+r*.45;return tall?`<ellipse cx="${round27(x)}" cy="${round27(y+r*.2)}" rx="${round27(r*.78)}" ry="${round27(r*1.25)}" fill="${ink}"/>`:`<circle cx="${round27(x)}" cy="${round27(y)}" r="${round27(r)}" fill="${ink}"/>`}if(pupil==="big"){let x=gaze*rx*.22;return`<circle cx="${round27(x)}" cy="0" r="${round27(ry*.56)}" fill="${ink}"/><circle cx="${round27(x+ry*.2)}" cy="${round27(-ry*.2)}" r="${round27(ry*.16)}" fill="#fff"/>`}if(pupil==="tiny")return`<circle cx="0" cy="${round27(ry*.05)}" r="${round27(ry*.2)}" fill="${ink}"/>`;if(pupil==="slit")return`<ellipse cx="${round27(gaze*rx*.3)}" cy="${round27(ry*.15)}" rx="${round27(ry*.16)}" ry="${round27(ry*.8)}" fill="${ink}"/>`;if(pupil==="heart"){let s=ry*.075;return`<path d="M0 ${round27(7*s)}C${point3(-10*s,0)} ${point3(-7*s,-8*s)} 0 ${round27(-3.5*s)}C${point3(7*s,-8*s)} ${point3(10*s,0)} 0 ${round27(7*s)}Z" transform="translate(0 ${round27(ry*.15)})" fill="${ink}"/>`}let k=ry*.42;return`<path d="M${point3(-k,-k)}L${point3(k,k)}M${point3(k,-k)}L${point3(-k,k)}" stroke="${ink}" stroke-width="${round27(ry*.2)}" stroke-linecap="round"/>`}function drawNose2(species,view,fur){if(species.nose==="cat")return`<path d="${view.noseShape}" fill="${mix(fur,...view.noseTint)}"/>`;let big="M-4.2 -1.8Q0 -3.2 4.2 -1.8Q5 -0.6 3.6 1Q1.6 2.8 0 2.8Q-1.6 2.8 -3.6 1Q-5 -0.6 -4.2 -1.8Z";return species.nose==="dog"?`<path d="${smooth(DOG_MUZZLE)}" fill="${MUZZLE}"/><path d="${view.noseShape}" fill="${fur}"/>`:`<ellipse cx="2" cy="5" rx="11" ry="8.2" fill="${mix(fur,WHITE,.22)}"/><path d="${big}" fill="${fur}"/>`}var drawBeak=open2=>open2?`<path d="M-4.2 0.6Q-3.6 -1.8 -0.4 -1.6Q2.8 -1.4 3.6 0.4Q2 3 -0.6 4.6Q-2.8 3 -4.2 0.6Z" fill="${BEAK}"/><path d="M-2.6 6Q-0.6 5.2 1.4 6Q0.2 8.4 -1 9.6Q-1.8 7.8 -2.6 6Z" fill="${BEAK}"/>`:`<path d="M-4.2 0.6Q-3.6 -1.8 -0.4 -1.6Q2.8 -1.4 3.6 0.4Q1.6 4.6 -1.1 8.6Q-1.6 8.9 -1.9 8.2Q-3 4.4 -4.2 0.6Z" fill="${BEAK}"/>`,drawOwlFace=(eyes2,fur,grey)=>eyes2.map(({c,rx,ry},i)=>{let side=i?1:-1;return ellipse([c[0]+side*rx*.12,c[1]+ry*.34],rx*1.44,ry*1.55,0,grey)+ellipse([c[0],c[1]+ry*.06],rx+1.8,ry*.86+1.8,0,fur)}).join(""),OWL_CHEST=[[32.3,43.3,79],[43.3,54.2,79],[28,39.5,88],[39.5,51,88]].map(([a,b,y])=>`M${a} ${y}Q${round27((a+b)/2)} ${y+10} ${b} ${y}Q${round27((a+b)/2)} ${y+5} ${a} ${y}Z`).join(""),OWL_WING="M83.2 77.5C72 70.5 62 74 63 85C63.6 92 66.5 96 69.5 101L71.8 101C68.8 95.5 66.6 91 66.2 85C65.6 77.4 73 74 83.2 77.5ZM72.6 87.3Q76.5 93 80.5 101L82.4 101Q77.8 92.4 72.6 87.3Z";function drawAccents(mood,fur){let dashes=colour=>`<path d="${[-40,0,40].map(a=>{let[x,y]=turned([0,-1],a);return`M${point3(90+x*5.5,14+y*5.5)}L${point3(90+x*9,14+y*9)}`}).join("")}" stroke="${colour}" stroke-width="1.6" stroke-linecap="round"/>`;return mood.name==="Happy"||mood.name==="Smitten"?dashes("#fff"):mood.name==="Curious"||mood.name==="Shocked"||mood.name==="Dizzy"?dashes(fur):mood.name==="Smug"||mood.name==="Sly"?'<path d="M7 66Q7.4 69.6 11 70Q7.4 70.4 7 74Q6.6 70.4 3 70Q6.6 69.6 7 66Z" fill="#fff"/>':""}var bothPads=paint=>`<path d="${TIGER_PAD}" ${paint}/><path d="${TIGER_PAD}" transform="scale(-1 1)" ${paint}/>`;function drawTigerFace(mood,view,fur,clip){let nose=[[-6.9,4.3],[-8.5,6.4],[-5,6.4]].flatMap(([x,y])=>[[x,y],[-x,y]]).map(([x,y])=>`<circle cx="${x}" cy="${y}" r="0.55" fill="${fur}"/>`).join("")+`<path d="${view.noseShape}" fill="${mix(fur,...view.noseTint)}"/>`;if(mood.mouth==="open"||mood.mouth==="oh"||mood.mouth==="tongue"){let mouth3="M-13 18.8Q-13 12.8 -7 12.8H7Q13 12.8 13 18.8V24Q13 30 7 30H-7Q-13 30 -13 24Z";return nose+`<clipPath id="${clip}"><path d="${mouth3}"/></clipPath><path d="${mouth3}" fill="${MOUTH_INSIDE}"/><ellipse cx="0" cy="28" rx="10" ry="5.5" fill="${TONGUE2}" clip-path="url(#${clip})"/><path d="M-10 12.8L-6.6 12.8L-8.4 17.6ZM10 12.8L6.6 12.8L8.4 17.6Z" fill="#fff"/>`}let fang="M-11.3 13.2L-8.5 13.2L-10.1 17.4Z";return nose+`<rect x="-14.5" y="12.8" width="29.1" height="19.9" rx="5.5" fill="${MUZZLE}"/>`+(mood.fangs?`<path d="${fang}" fill="${MUZZLE}" stroke="${fur}" stroke-width="0.7" stroke-linejoin="round"/>`:"")+(mood.fangs===2?`<path d="${fang}" transform="scale(-1 1)" fill="${MUZZLE}" stroke="${fur}" stroke-width="0.7" stroke-linejoin="round"/>`:"")}function createKitty(name,overrides,animals=!1,ids=prefixOf(animals)){let t=calmed(createTraits(name,overrides),CALMING6),id=part=>`${ids}-${part}`,species=animals?speciesOf(t):SPECIES[0],view=species.view??viewOf(t),{centre}=view,mood=moodOf3(t),pose=poseOf2(t),style=earsOf(t),fluff=species.cheeks??furStyleOf(t).name,{tile,fur,eye:eyeColour}=coloursOf5(t),shade=mix(fur,...view.earTint),grey=mix(fur,WHITE,.23),ink=mix(fur,"#000000",.7),sx=t.num("head.width",.94,1.06),sy=t.num("head.height",.95,1.05),grow=([x,y])=>[centre[0]+(x-centre[0])*sx,centre[1]+(y-centre[1])*sy],outward=(p,by2)=>{let away=distance(p,centre);return[p[0]+(p[0]-centre[0])/away*by2,p[1]+(p[1]-centre[1])/away*by2]},outline=view.head.map((p,i)=>grow(fluff==="Chubby"&&view.cheeks.includes(i)?outward(p,2.6):p)),headPath=smooth(outline),spikes=fluff==="Fluffy"?view.cheeks.filter(i=>view.cheeks.includes(i+1)).map(i=>{let[a,b]=[outline[i],outline[i+1]];return polygon2([lerp(a,b,.15),outward(lerp(a,b,.5),3.2+t.num(`fluff.${i}`,0,1.6)),lerp(a,b,.85)])}).join(""):"",earSize=t.num("ear.size",.9,1.1),ears=view.ears.map(({inner,tip,outer},i)=>{let out=i===0?-1:1,odd=style.odd&&i===1,middle=lerp(inner,outer,.5),flare=style.flare+(odd?38:0)+t.jitter(`ear.lean${i}`,4),reach=turned([tip[0]-middle[0],tip[1]-middle[1]],out*flare),height=style.height*earSize*(odd?.85:1),tipAt=[middle[0]+reach[0]*height,middle[1]+reach[1]*height],kind=species.ears;if(kind==="point"){let rounded={...style,round:Math.max(style.round,species.earRound??0)};return drawEar(grow(inner),grow(tipAt),grow(outer),centre,rounded,fur,shade,species.earBulge,species.earInset)}return kind==="tuft"?drawOwlTuft(grow(inner),grow(tipAt),grow(outer),centre,style,fur,grey):drawRoundEar(grow(inner),grow(tipAt),grow(outer),style,fur,shade)}),length=t.num("whisker.length",.85,1.15),keep=t.int("whisker.n",2,3),whiskers=species.whiskers?view.whiskers.filter((_,i)=>keep===3||i%3!==1).map(([root,bend,end],i)=>{let spin=t.jitter(`whisker.${i}`,5),from=grow(root),reach=p=>{let v=turned([(p[0]-root[0])*length,(p[1]-root[1])*length],spin);return[from[0]+v[0],from[1]+v[1]]};return`M${at2(from)}Q${at2(reach(bend))} ${at2(reach(end))}`}).join(""):"",faceAt=`translate(${point3(...grow(view.nose))}) rotate(${view.tilt}) scale(${round27((sx+sy)/2)})`,face=inner=>`<g transform="${faceAt}">${inner}</g>`,eyeScale=t.num("eye.size",.9,1.12),gap=t.num("eye.gap",-1.5,1.5),lift=t.num("eye.y",-1,1),gaze=t("gaze")<.75?1:-1,slopeShift=t.jitter("lid.slope",3),eyes2=view.eyes.map(({c,rx:baseX,ry:baseY},i)=>{let rx=baseX*eyeScale,ry=baseY*eyeScale,side=i===0?-1:1,inner=-side,raw=mood.lids[i],lid2=typeof raw=="string"?raw:[raw[0]+slopeShift,raw[1]],move=`translate(${point3(c[0]+side*gap,c[1]+lift)})`;if(lid2==="closed"||lid2==="happy"){let bend=lid2==="happy"?-ry*1.1:ry*.9,end=lid2==="happy"?ry*.3:-ry*.1;return`<g transform="${move}"><g data-widen=""><path d="M${point3(-rx*.85,end)}Q0 ${round27(bend)} ${point3(rx*.85,end)}" fill="none" stroke="${eyeColour}" stroke-width="1.8" stroke-linecap="round"/></g></g>`}let shape=eyeShape(lid2,rx,ry,inner);return`<g transform="${move}"><g data-widen=""><g data-blink=""><clipPath id="${id(`eye${i}`)}"><path d="${shape}"/></clipPath><path d="${shape}" fill="${eyeColour}"/><g clip-path="url(#${id(`eye${i}`)})"><g data-pupil="">${drawPupil(mood.pupil,lid2,rx,ry,inner,view.pupilsIn?inner:gaze,ink,view.tallPupils)}</g></g></g></g></g>`}).join(""),open2=`<clipPath id="${id("mouth")}"><path d="${MOUTHS3.open}"/></clipPath><path d="${MOUTHS3.open}" fill="${MOUTH_INSIDE}"/><ellipse cx="9.5" cy="20" rx="15" ry="9.5" transform="rotate(-10 9.5 20)" fill="${TONGUE2}" clip-path="url(#${id("mouth")})"/>`,dog=species.head==="dog",mouthInk=species.nose==="bear"||dog?fur:grey,mouthWidth=dog?1.5:1.15,mouth3=mood.mouth==="open"?open2:mood.mouth==="oh"?`<ellipse cx="1.8" cy="9.4" rx="2.4" ry="3" fill="${mix(fur,WHITE,.12)}" stroke="${mouthInk}" stroke-width="1"/>`:MOUTHS3[mood.mouth]?`<path d="${MOUTHS3[mood.mouth]}" fill="none" stroke="${mouthInk}" stroke-width="${mouthWidth}" stroke-linecap="round" stroke-linejoin="round"/>`:"",tongue2=mood.mouth==="tongue"||dog&&(mood.mouth==="smile"||mood.mouth==="w")?`<path d="M-0.4 6.4Q2.2 14.6 5.2 7.4Z" fill="${TONGUE2}"/>`:"",fangs=species.fangs?(mood.fangs?`<path d="${mood.mouth==="open"?OPEN_FANG:FANG}" fill="#fff"/>`:"")+(mood.fangs===2?`<path d="${FAR_FANG}" fill="#fff"/>`:""):"",eyeSpots=view.eyes.map(({c,rx,ry},i)=>({c:[c[0]+(i?1:-1)*gap,c[1]+lift],rx:rx*eyeScale,ry:ry*eyeScale})),behindEyes=species.head==="owl"?drawOwlFace(eyeSpots,fur,grey):"",owl=species.head==="owl"?`<path d="${OWL_CHEST}${OWL_WING}" fill="${grey}"/>${drawAccents(mood,fur)}`:"",collar=dog?`<path d="${COLLAR}" fill="${t.pick("collar",COLLARS)||mix(fur,WHITE,.24)}"/><path d="${BONE}" transform="translate(58.2 84.6) rotate(-5) scale(1.12)" fill="${MUZZLE}" stroke="${fur}" stroke-width="1.3" paint-order="stroke"/>`:"",tiger=species.head==="tiger",stripes=tiger?bothSides(TIGER_SPIKES,`fill="${fur}"`)+bothSides(TIGER_STRIPES,`fill="none" stroke="${mix(fur,WHITE,.38)}" stroke-width="2.2" stroke-linejoin="round" stroke-linecap="round"`)+bothSides(TIGER_BROWS,'fill="none" stroke="#fff" stroke-width="0.8" stroke-linecap="round"')+bothSides(TIGER_FLICKS,`fill="none" stroke="${grey}" stroke-width="0.9" stroke-linecap="round"`)+`<path d="${TIGER_CHEST}" fill="${mix(fur,WHITE,.2)}"/>`:"",dogMouth=mood.mouth==="smirk"?`<path d="${DOG_SMIRK}" fill="none" stroke="${fur}" stroke-width="${mouthWidth}" stroke-linecap="round" stroke-linejoin="round"/>`:"",scale=pose.scale*t.num("body.size",.96,1.04),mirror=pose.mirrored?"translate(100 0) scale(-1 1) ":"";return{defs:`<clipPath id="${id("face")}"><path d="${headPath}"/></clipPath>`+(tiger?`<clipPath id="${id("pads")}"><g transform="${faceAt}">${bothPads("")}</g></clipPath>`:"")+`<filter id="${id("grain")}" x="0" y="0" width="100%" height="100%"><feTurbulence type="fractalNoise" baseFrequency="2.2" numOctaves="1" seed="7"/><feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.32 -0.12"/></filter>`,tile,pose:`${mirror}translate(${point3(50+pose.x,50+pose.y)}) rotate(${round27(pose.turn+t.jitter("tilt",5))}) scale(${round27(scale)}) translate(-50 -50) ${view.frame}`.trim(),mirrored:!!pose.mirrored,body:`<path d="${polygon2(view.body)}" fill="${fur}"/>${collar}<path d="${headPath}" fill="${fur}"/>`+owl+stripes+(spikes?`<path d="${spikes}" fill="${fur}"/>`:"")+(tiger?"":`<path d="${whiskers}" fill="none" stroke="${view.greyWhiskers?grey:fur}" stroke-width="1" stroke-linecap="round"/><g clip-path="url(#${id("face")})"><path d="${whiskers}" fill="none" stroke="${grey}" stroke-width="1" stroke-linecap="round"/></g>`),ears,earsFront:species.ears==="tuft",eyes:face(eyes2),discs:(behindEyes?face(behindEyes):"")+(tiger?`<g transform="${faceAt}">${bothPads(`fill="${MUZZLE}"`)}</g>`:""),face:(tiger?`<path d="${whiskers}" fill="none" stroke="#fff" stroke-width="0.7" stroke-linecap="round"/><g clip-path="url(#${id("pads")})"><path d="${whiskers}" fill="none" stroke="${fur}" stroke-width="0.7" stroke-linecap="round"/></g>`:"")+face(species.nose==="beak"?`<g>${drawBeak(mood.mouth==="open"||mood.mouth==="oh"||mood.mouth==="tongue")}</g>`:dog?drawNose2(species,view,fur)+(dogMouth||`<g transform="scale(-1 1)">${tongue2}${mouth3}${fangs}</g>`)+(dogMouth&&mood.fangs===2?`<path d="${DOG_FANG}" fill="#fff"/>`:""):tiger?drawTigerFace(mood,view,fur,id("roar")):drawNose2(species,view,fur)+tongue2+mouth3+fangs),blinkDelay:t.num("blink",0,4)}}var TILE_SHAPE2='<rect width="100" height="100" rx="22.22"/>',prefixOf=animals=>animals?"animal":"kitty",tileMarkup=(fill,ids)=>TILE_SHAPE2.replace("/>",` fill="${fill}"/>`)+TILE_SHAPE2.replace("/>",` filter="url(#${ids}-grain)" clip-path="url(#${ids}-tile)"/>`),still=animals=>(name,overrides)=>{let cat=createKitty(name,overrides,animals),tile=`${prefixOf(animals)}-tile`;return`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><defs>${cat.defs}<clipPath id="${tile}">${TILE_SHAPE2}</clipPath></defs>`+tileMarkup(cat.tile,prefixOf(animals))+`<g clip-path="url(#${tile})"><g transform="${cat.pose}">${cat.earsFront?"":cat.ears.join("")}${cat.body}${cat.discs}${cat.face}${cat.earsFront?cat.ears.join(""):""}${cat.eyes}</g></g></svg>`},animalSvg=still(!0);var named3=list=>list.map(({name:label})=>({label})),controlsFor=animals=>(name,overrides)=>{let t=calmed(createTraits(name,overrides),CALMING6),list=control=>narrowed(control,t,CALMING6),species=animals?speciesOf(t):SPECIES[0];return[{title:"Face",controls:[list(choice(t,"mood","Expression","list",named3(MOODS3))),possibilitiesSlider(t,NOTES7),fixedPalette(t,"eyes.color","Eye colour",EYE_COLOURS),slider(t,"eye.size","Eye size",0,100,"%"),slider(t,"eye.gap","Eye gap",0,100,"%"),...species.whiskers?[slider(t,"whisker.length","Whiskers",0,100,"%")]:[]]},{title:animals?"Animal":"Cat",controls:[...animals?[choice(t,"animal","Animal","list",named3(SPECIES))]:[],...species.view?[]:[choice(t,"view","View","list",named3(VIEWS))],choice(t,"ears","Ears","list",named3(EARS)),list(choice(t,"pose","Pose","list",named3(POSES2))),...species.cheeks?[]:[list(choice(t,"fur.style","Cheeks","list",named3(FUR_STYLES)))],slider(t,"head.width","Head width",0,100,"%"),slider(t,"tilt","Tilt",-5,5,"\xB0")]},{title:"Colour",controls:[palette(t,"tile","Colour",TILES3),fixedPalette(t,"fur","Fur",FURS)]}]},animalControls=controlsFor(!0);var CALMING7={lists:{mouth:[30,8,[0,24,4,25,1,8,2,6,22,3]],"mouth.hover":[30,8,[0,24,4,25,1,8,2,6,22,3]],eyes:[26,3,[23,24,25,0,1,2,7]],eyebrows:[15,2,[8,9,10,11,12,14,4,5]],"glasses.variant":[5,1]},rarer:["glasses"]},NOTES8=["a few calm eyes and brows, simple mouths and hardly ever glasses.","more eyes, brows and mouths, and glasses now and then.","every eye, brow, mouth and pair of glasses."];var adventurer_neutral_default={$schema:"https://cdn.hopjs.net/npm/@dicebear/schema@2.0.1/dist/definition.min.json",$comment:"Exported by DiceBear Studio for Figma. https://www.figma.com/community/plugin/1005765655729342787",meta:{license:{name:"CC BY 4.0",url:"https://creativecommons.org/licenses/by/4.0/",text:"Remix of \u201EAdventurer Neutral\u201D (https://www.figma.com/community/file/1184595184137881796) by \u201ELisa Wischofsky\u201D, licensed under \u201ECC BY 4.0\u201D (https://creativecommons.org/licenses/by/4.0/)"},creator:{name:"Lisa Wischofsky",url:"https://www.instagram.com/lischi_art/"},source:{name:"Adventurer Neutral",url:"https://www.figma.com/community/file/1184595184137881796"}},canvas:{elements:[{name:"eyes",type:"component",attributes:{transform:"translate(36.7 101.2)"}},{name:"eyebrows",type:"component",attributes:{transform:"translate(36.6 29.5)"}},{name:"mouth",type:"component",attributes:{transform:"translate(114.5 217.6)"}},{name:"glasses",type:"component",attributes:{transform:"translate(15.5 93.3)"}}],width:400,height:400},attributes:{fill:"none","shape-rendering":"auto"},components:{eyebrows:{width:320.6,height:138.7,variants:{variant01:{elements:[{name:"path",type:"element",attributes:{d:"M297.9 50c1.6 1 1 2.9 1.2 4.5v34c.2 2.8-2.5 4.2-4.7 5l-120 41.1c-2.6.2-2.9-1.7-3.6-3.6l-5-18c1 5.8 1 11.7 1.4 17.5 0 1.4.4 4-1 4.9-2 1.4-4 0-4.6-2Q156.3 114 150.9 95c-.4-1.8-.6-3.9 1.4-4.9q3.1-.6 4 2.5l3.7 13.7q-1-7.9-1.2-15.8c0-1.3-.1-3.7 1.7-3.8l4.4-.7 123.6-35.2c3.3-.9 6-2.1 9.4-.8M8.4 82.4c13.6 1.4 27.3 1.4 41 2.6 21 1 42 2.6 63.1 3.4l23.4 1.6c2.8 2.2 1.1 8.1 2 11.4.5-3 .1-7 1.9-9.5 2.1-1.8 5-.1 4.7 2.6l-7 42.2c-.8 2.9-4.5 2.5-5.3-.2l-.3-14.8c-1 4.3-1.4 8.7-2.4 13-.5 1.6-1.2 2.8-3.1 2.4L7.5 115.8q-2.8-.5-3-3.3c-1.5-8-2.6-16-4.2-24-.2-1.7-.8-3.1.5-4.6 2.2-2.2 4.8-1.6 7.6-1.5",fill:{type:"color",name:"ink"}}}],tags:["mood:negative"]},variant02:{elements:[{name:"path",type:"element",attributes:{d:"M291.3 46c1.6-.3 3.3.7 4.8 1q-.1 2-.5 3.7-2.6 2.1-5.4 3.8A804 804 0 0 1 220 95a290 290 0 0 1-35.5 15.4 50 50 0 0 1-21 3.5c-3.4-.4-6.2-3-6.3-6.5 0-4.2 3-8.6 5.1-12.1 1.3-2.7 4.5-3 7-4.1L281 49.7c3.4-1.2 6.9-2.8 10.4-3.7M23.3 81.1l90 18c2.3.4 4.7.1 7 .5 2.4 2.3 3.6 6.2 4.5 9.4 1.1 4-.2 8.7-4 11-4 2.6-9.9 2.2-14.5 1.9-8.7-1-17.4-3.8-25.6-6.8a418 418 0 0 1-57-27c-1.7-.9-3.7-1.9-4.8-3.5-.4-2.9 1.9-4.1 4.4-3.5",fill:{type:"color",name:"ink"}}}],tags:["mood:negative"]},variant03:{elements:[{name:"path",type:"element",attributes:{d:"M140.4 28.9c2.2-.1 2.8 1.7 2.6 3.6-.5 4.7-.7 9.8-2.3 14.2l-4 .9c-1.2-4.8 0-10.3.7-15.1.3-1.7.8-3.8 3-3.6m20.8 6.2q-.1 4.9-.7 9.6c41.7.5 83.3.4 125 .8q3.1.2 5.9 1.6c-.6 1.5-.2 3.8-2.3 4-8 1.4-16.5.6-24.7 1l-52 1.5c-17 .2-34 1.2-51.1 1.4-3.3.4-6-2.7-7.2-5.5 0-4.4 1-9.1 2-13.5 1.3-2.4 2.9-1.6 5-.9m-36.9 5.6c-.1 4.8 0 10.8-2.3 15.2-3.2 1.5-7.1 1.8-10.6 2.5l-77 14c-4.2.8-8.6 2.2-13 2.1-2.6-.5-3.3-3.7-.8-5 3.2-1.4 7-1.7 10.3-2.6l87.3-20.3 1.3-5.7q2.4-.3 4.8-.2",fill:{type:"color",name:"ink"}}}],tags:["mood:negative"]},variant04:{elements:[{name:"path",type:"element",attributes:{d:"M266.7 19.2c14 7 27.7 17.3 36.5 30.5A3 3 0 0 1 299 54a104.4 104.4 0 0 0-132.7 19.6c-1.7 2-4 3.6-6.3 1.2-1.7-2.6-2.2-6-3.3-9q-2.7 7.3-6.2 14.1c-1.5 3.2-6 1.1-7-1.4q-4.7-10.3-9-20.8v17c-.2 2 .3 4.3-2.1 5.1-2 .3-4.4-1-5.3-2.9-3.3-5.8-6.2-11.9-9.5-17.8 1 5.5 2.6 11 3.1 16.6.1 2-2.3 3.4-4 2.3a133 133 0 0 0-58.3-10 65 65 0 0 0-36 12.6c-3.1 2.4-5.2 5.5-8 8.2-1.7.7-3.3-.3-4.9-.7q-.1-2.8.7-5.6a87 87 0 0 1 40-50c13.6-7.4 30.2-9 44.6-3.4a57 57 0 0 1 27.7 24c2.3-2.9 4.3-6 6.8-8.8 1.6-1.5 4.6-1.5 5.6.7l7 15.8 4.4-22.2q.3-2.4 1.6-4.5c1.6-1.2 2.9-.2 4.6.1l.8 2.6q3-7.2 8.5-12.8a62 62 0 0 1 34.5-16.5C220 3.7 245 8.6 266.7 19.2",fill:{type:"color",name:"ink"}}}],tags:["mood:positive"]},variant05:{elements:[{name:"path",type:"element",attributes:{d:"M207.6 32.9c6.2-.5 13-.6 18.5 3a10 10 0 0 1 4.4 10.7C229 52.7 224 57.5 219 61a68 68 0 0 1-30.5 11.5 30 30 0 0 1-17.5-2.6 10 10 0 0 1-5.2-10.3c1-5.8 5.5-10.5 10-14 9.1-7 20.5-11.3 31.9-12.8M76.6 49.7a47 47 0 0 1 26.3 5.3c3.8 2.2 7.3 5.9 7.9 10.5.3 4.2-2 7.8-5.2 10.2-4.5 3.6-9.9 5-15.4 6-10 1-20.6.3-29.5-4.6-3.9-2.2-7.9-5.8-8.5-10.5-.7-4.3 2-8.5 5.4-10.9a36 36 0 0 1 19-6",fill:{type:"color",name:"ink"}}}]},variant06:{elements:[{name:"path",type:"element",attributes:{d:"M186.4 33.5a71 71 0 0 1 28.8 7.3c3.3 1.8 7 4 7.3 8.3-5.1-.9-10.1-2.1-15.4-2.3A59 59 0 0 0 174 54c-2.6 1.4-5 3.3-7.7 4.4-1.8.2-3.9-2-4-3.8-.1-5.8 2-11.9 6.6-15.7a27 27 0 0 1 17.6-5.4M98.4 51.1c5.8.2 11 5.3 12.5 10.6.8 2.7-.5 5.8-3.5 5.7-8.9.2-18.2 0-26.8 2.2-7.6 2-14.8 6.7-21.4 10.8q-1.9 1-4 1.2.3-3 2-5.2Q62 69.7 67.9 64c5.9-5.2 13-9 20.3-11.7q5-1.7 10.2-1.3",fill:{type:"color",name:"ink"}}}],tags:["mood:positive"]},variant07:{elements:[{name:"path",type:"element",attributes:{d:"M136.4 44.3c.6 4.7-1.5 9.4-4.2 13a44 44 0 0 1-12.9 11.2c-7.6 4.3-16 7.7-24.2 10.8a424 424 0 0 1-73.5 19.5c-3.3.5-7 1.5-10.3 1-2-.8-2-2.7-1.1-4.4 2.3-1.8 5.4-2.8 8.1-4l107.8-44.1c3.4-1.3 6.6-3.4 10.3-3m26.9.2 148 22.8c2.6.4 5.4.5 7.9 1.4 2.4 1.1 1.7 5-1 5.2q-14.4 1.6-28.8 2c-15.4 0-30.7.3-46-1.2-21-1.7-42.3-4.6-62.3-11-7-2.5-14.9-5.5-20.2-10.7-1.8-2-4.1-4.3-3.2-7.1 1.2-2.2 3.6-1.6 5.6-1.4",fill:{type:"color",name:"ink"}}}],tags:["mood:negative"]},variant08:{elements:[{name:"path",type:"element",attributes:{d:"M215.3.8A86 86 0 0 1 276 16a83 83 0 0 1 29 33c1 3-.3 3.8-2.5 5.3-4-2.2-6.9-5.6-10.5-8.3-13-9.7-28-16.3-43.8-20.2-14.9-3.5-30.5-5-45.8-2.8-4.8.4-9.3 2-14 2.7-2.4.2-5-1.3-4.1-4 1.9-4.2 4.2-8.6 7.6-11.7a45 45 0 0 1 23.5-9m-148 76.3c13.3-.8 26.3-.6 39 4.3 5.8 2.3 11.5 5.9 14 12a14 14 0 0 1-1.8 12.6c-5-.7-9.4-2.6-14.2-3.8a203 203 0 0 0-71-6c-5 .4-9.9 2-14.7 1.8-1.8-.5-1.2-2.2-1-3.5.9-2.5 3.6-3.9 5.7-5.1a119 119 0 0 1 44-12.3",fill:{type:"color",name:"ink"}}}],tags:["mood:positive"]},variant09:{elements:[{name:"path",type:"element",attributes:{d:"M81.4 21.6c6.8.2 14.2 2.9 18 9 1 1.4.6 3.6.7 5.3-6.3.2-12.5.3-18.7 1.8A112 112 0 0 0 39.8 58a90 90 0 0 0-22 23c-1.4 2.3-2.4 5.1-4.3 7l-3.8.3q-.2-2.7.2-5.2A89 89 0 0 1 48 32.2a65 65 0 0 1 33.4-10.6m181.5 38.6a71 71 0 0 1 30 10l-.2 4.7c-4 1.6-7.3-.1-11.3-.8-6.8-1.2-14-1.2-20.9-1a198 198 0 0 0-84 23.7l-4.3 1.5c-2.6-5.4-3.7-11-.2-16.2a48 48 0 0 1 23.7-15.4c21.3-7.4 44.8-9 67.2-6.5",fill:{type:"color",name:"ink"}}}],tags:["mood:positive"]},variant10:{elements:[{name:"path",type:"element",attributes:{d:"M229.4 27c24.7 1 48 9 69.4 21 2.3 1.3 5 2.5 6.8 4.3 1.3 2.4-.4 5.1-3.2 4.2a234 234 0 0 0-51-12c-20.3-2.4-40-3.7-60.2-.1-3.2.4-6.9 2.1-10.1 1.5-2.7-1.6-1.2-6 1.3-7.3a79 79 0 0 1 47-11.6M92.3 45.4q5.2 1 9.7 3.8l-.4 3.6q-4 1-8.2 1.4a152 152 0 0 0-38.8 9.7 141 141 0 0 0-35.2 18.7c-2.8 2-4.1 4.8-8 4.4l-1.6-2.6q1.3-2.4 2.8-4.7a90 90 0 0 1 38.6-29.3 71 71 0 0 1 41.1-5",fill:{type:"color",name:"ink"}}}],tags:["mood:positive"]},variant11:{elements:[{name:"path",type:"element",attributes:{d:"M215.4 2.4c17 2 34 7.5 48.6 16.5a57 57 0 0 1 18.2 17c1 1.1 1.3 3.5-.2 4.3-1.2 1.2-2.8.5-4.1-.1a143 143 0 0 0-54-15c-13.5-.8-28.2-.9-41.1 3.8-3 1-5.5 3-8.5 3.9-1.3.2-2.4-1.1-2.9-2.3a18 18 0 0 1 .2-14.8A23 23 0 0 1 184.9 5a73 73 0 0 1 30.5-2.6m-117 54.2C106.6 59 113 67.4 111.9 76q-2.7 1-5.5.8a108 108 0 0 0-42.9 5.8c-14 4.7-28.5 11.6-39.4 21.8-1.3 1.3-4.2 3-5.5.8-1.7-2.4 0-4.1 1.4-6a128 128 0 0 1 49-39c8.8-3.7 20-6.5 29.4-3.6",fill:{type:"color",name:"ink"}}}],tags:["mood:positive"]},variant12:{elements:[{name:"path",type:"element",attributes:{d:"M98.6 38.3C93.1 31 84.1 29 75.4 29.9A68 68 0 0 0 40.9 47a87 87 0 0 0-24.7 35.3c-.7 1.9-1.3 4.7 1 5.7 2.1.2 2.9 0 4.1-1.6A117 117 0 0 1 64.9 51a61 61 0 0 1 26.5-5.7q1.5 0 3.2.4 2.5.5 5 .3c2.8-2.3.7-5.3-1-7.6zm178.7 18.4a147 147 0 0 0-59-19c-10-.8-21.4-.3-30.6 4-6.8 3.2-12.4 8.6-13.6 16.2l-.1 1c-.4 2.9-1 6.8 1.3 8.8 2 .8 3.6-.4 5.2-1.5q1.2-.8 2.3-1.3a111 111 0 0 1 45.6-9.7 144 144 0 0 1 46.5 7.3c1.5.4 2.7.7 3.9-.6 1.8-2 .5-4.3-1.5-5.3",fill:{type:"color",name:"ink"}}}],tags:["mood:positive"]},variant13:{elements:[{name:"path",type:"element",attributes:{d:"M298.4 55.4a134 134 0 0 0-92-35 175 175 0 0 0-26.4 3.1q-2.1 5-3.6 10l-1 3.7-.2-1.4-1.3-11.4-3.3-1.5-.8 1.1c-.6.8-1.3 1.6-1.3 2.4q0 5.6.7 11.3a113 113 0 0 1 .9 10.5c.1 2.4.3 5 1.6 6.8 2.8.8 6-.3 9-1.3l3-1c19-5.5 39.3-6.8 58.8-4.4 20 2.3 40 8.3 57.4 18.6q3 1.5 6.2 2.5l1.7-3.4q-4.1-5.8-9.5-10.5m-191.7-7.4q.4-6.3 0-12.7c-.2-2.5-1.8-2.5-3.6-2.6h-1c-1 3.6-1.1 7.5-1.3 11.3l-.2 5a199 199 0 0 1-4.9-12.2c-.4-1.1-.9-2.3-2.2-2.3q-3.8 0-7.5.9l-3.5.5c-18.1 3.2-37 9.6-52 20.4a53 53 0 0 0-16.8 18.5c-1.4 3.1-2.8 6.5-1.5 10h.4c1 .4 2.6.8 3.4.1l2.7-2.1q3-2.7 6.5-4.6A153 153 0 0 1 93.4 63q2.8 0 5.5.5t5.6.5c1.8-1.2 1.9-3.6 2-5.7v-1.9z",fill:{type:"color",name:"ink"}}}],tags:["mood:positive"]},variant14:{elements:[{name:"path",type:"element",attributes:{d:"M201.5 28.2c.8-1 2.1-2.4 1.7-3.6-.3-2.5-3.5-3.1-5.2-1.5l-8.3 7.3q-3.2 3-6.5 5.8l-3 2.8a44 44 0 0 0-7.4 7.5l.9 1q.9 1.5 2.7 1.8c1.5 0 2.7-1.1 3.8-2.1l.4-.4q6.5-6 13.1-11.7l7.6-6.8zm22.6-1q.6-2.7-1.6-4c-2-.4-3.9.7-5.6 1.7l-1.3.7-13.4 7.8q-7.3 4.1-14.4 8.4c-1.6.8-1.7 2-1.7 3.4v1.4l1.2.4c1.2.4 2.3.8 3.6 0q7.5-4.2 15.1-8.7l13.5-7.7 1-.5a10 10 0 0 0 3.6-3m26.7-.2c2-.8 4.2.2 4.4 2.6 0 2.3-1.7 2.9-3.5 3.5q-.4 0-.8.3l-37.6 11.6c-1.3.4-2.6.7-4 0-1.8-1.2-1.7-4.3.4-5.2q2.7-1.1 5.6-1.9l2.7-.8 11.4-3.6zm23 11.9q1.3-2.3-.5-4.4c-2.2-.7-4.9-.1-7.4.5l-2.5.5-8.5 1.7-12.4 2.5c-2 .5-3.7 1.6-3.2 3.9q1 2.8 4 2 6-1 12-2.3t11.6-2.2l1.3-.3q3.1-.3 5.6-1.9M90.2 43.2l5.8 3.7 2.3 1.4q2.6 1.4 5 3.4c1.7 1.3 1.2 4.2-.9 5-1.8.3-3-.5-4.4-1.3l-1-.6-17.8-11.4c-1-.8-2.4-1.7-2.4-3-.3-2.4 2.2-4 4.4-2.8q4.5 2.6 9 5.6m-21.9.8q-3-1-6-1.7c-2.4-.5-4 2-3.2 4.2a9 9 0 0 0 4 2.3l.5.1.3.2 12 3.8 12.5 4c2.4.7 4.8.5 5.3-2.5-.2-2-2-2.8-3.7-3.4h-.2l-.7-.3-18.2-5.9zm203.2-.2 10.4-.3 8.8-.2c1.7 0 3.6 0 4.3 1.5 1.3 1.8-.2 3.8-2 4.2q-4.4.8-9 .6h-6.6q-2.6.2-5 .1c-1.3 0-3.2-.3-3.5-1.7a3 3 0 0 1 2.6-4.2M44.7 51.3c-2 0-4.2-.2-6.1.4a3.2 3.2 0 0 0-.2 4.7q2.7 1.1 5.5 1h.2l.3.1 22 1.2 2.6.2q2.8.5 5.4 0c2-.7 2.6-3.2 1.2-4.6-.9-1-2-1-3-1.2h-1.2l-12.5-.9-12.5-.8zm-11.3 8.9 4.4-.4q6.4-.7 12.6-.4c3 .2 3.1 4.7.3 5.4q-4.5.9-9 1a76 76 0 0 0-8.9.5q-3.7.4-7.3.1C23 66 22.7 62 25 61.1q2.7-1 5.7-.8zm-3.5 13.6c3-1 2.8-5.2-.5-5.6q-4.2.1-8.6 1l-4 .7-2.5.4c-2.3.3-4.8.6-6 2.2-1.2 2.4.5 4.6 3 4.4q9.4-1.1 18.6-3",fill:{type:"color",name:"ink"}}}],tags:["mood:positive"]},variant15:{elements:[{name:"path",type:"element",attributes:{d:"M252.8 54.5c-.6-3-2.5-5-4.6-6.9A50 50 0 0 0 202.5 36a38 38 0 0 0-23.6 17.1 26 26 0 0 0-3.8 17.6c.2 1.7.4 3 2.5 3.6q3.3 0 6.5-.7h.3l6.2-1.3q8-1.5 15.7-3.2 22.5-4.7 44.9-11c1.8-.3 1.7-1.7 1.6-3zm-138.4 25c-.8-9.8-8.8-17.4-17.8-20.3-13.3-4-28.5-.4-38.5 9.3a28 28 0 0 0-9.1 16c0 2.8 2.4 2.9 4.4 3h.8l9-.3a336 336 0 0 0 35.3-1.8q6.4-.4 12.7-1.1c2.5 0 3.3-2.6 3.1-4.7",fill:{type:"color",name:"ink"}}}],tags:["mood:positive"]}}},eyes:{width:328.2,height:144.2,variants:{variant01:{elements:[{name:"path",type:"element",attributes:{d:"M274.3 9.8c11.8 7 21 17.6 26.7 30 5.9-3.1 11.6-6.7 17.6-9.6 1.8-1 4.4.5 4 2.6.2 1.5-2 2.5-3 3.2l-16.4 9a65.7 65.7 0 0 1-39.4 82.3 66 66 0 0 1-78.5-27.5 64 64 0 0 1-9.3-33A65 65 0 0 1 229.3 2c15.2-3 31.6 0 45 7.8",fill:{type:"color",name:"ink"}}},{name:"circle",type:"element",attributes:{cx:"241.1",cy:"66.2",r:"59.6",fill:{type:"color",name:"sclera"}}},{name:"path",type:"element",attributes:{d:"M74.3 23.7a55 55 0 1 1-55.7 38.7L7.3 58c-2-.8-4-1.4-5.4-3q-.5-4 3.2-3.7c5.2 1.3 10 4.2 15.2 5.6 1.4-1.7 2.2-3.8 3.3-5.7a55 55 0 0 1 50.7-27.4",fill:{type:"color",name:"ink"}}},{name:"circle",type:"element",attributes:{cx:"71.2",cy:"78.7",r:"49.3",fill:{type:"color",name:"sclera"}}},{name:"path",type:"element",attributes:{d:"M262.6 42.2a25 25 0 0 1 27.9 24.6c-.3 4.8-1.8 9.7-4.6 13.6A25 25 0 0 1 267.3 91a24.5 24.5 0 0 1-21.8-38 25 25 0 0 1 17-10.8M92.7 55.3a23 23 0 0 1 19.7 7.5q6 6.8 5.7 16c0 12-10.7 22.8-22.8 22.3a23 23 0 0 1-22.9-22.3 23 23 0 0 1 20.3-23.5",fill:{type:"color",name:"eyes"}}}],tags:["mood:positive"]},variant02:{elements:[{name:"path",type:"element",attributes:{d:"M243.3.9a65 65 0 0 1 57.5 38.4l23.8-15 3.6 3.4c-3.2 3.6-7.1 5.4-11 8l-14.3 9a66 66 0 0 1-18 69.8 65 65 0 0 1-42.6 16.8 65.7 65.7 0 0 1-61.5-90A65 65 0 0 1 243.3 1",fill:{type:"color",name:"ink"}}},{name:"circle",type:"element",attributes:{cx:"241.1",cy:"66.2",r:"59.6",fill:{type:"color",name:"sclera"}}},{name:"path",type:"element",attributes:{d:"M98.3 30.7A55 55 0 1 1 19 61.5C13.1 58 6.8 55 1.2 51c-2-1.1-1.5-4.2.7-4.7 1.6-.5 3.1.6 4.6 1.3l14.4 8.5a55 55 0 0 1 77.4-25.3",fill:{type:"color",name:"ink"}}},{name:"circle",type:"element",attributes:{cx:"71.2",cy:"78.6",r:"49.3",fill:{type:"color",name:"sclera"}}},{name:"path",type:"element",attributes:{d:"M211.6 43a24 24 0 0 1 20.2 7.3 24 24 0 0 1-2.3 34.7 23.9 23.9 0 0 1-38.7-20.2A24 24 0 0 1 211.6 43M42.8 57.6a21.8 21.8 0 1 1 11.6 42 22 22 0 0 1-25.7-14 22.3 22.3 0 0 1 14.1-28",fill:{type:"color",name:"eyes"}}}],tags:["mood:positive"]},variant03:{elements:[{name:"path",type:"element",attributes:{d:"M271.7 8.4a66 66 0 0 1 28 28.7q8.4-5 16.7-10.2c1.6-.9 3.2-2 5-2.4 1.9.5 2.7 1.3 2.6 3.4-.4 1.3-1.7 2-2.8 2.8-6.4 4-13 7.6-19.4 11.8a64 64 0 0 1 .8 45.6 65.5 65.5 0 0 1-73.5 42.1A65.2 65.2 0 1 1 271.7 8.4",fill:{type:"color",name:"ink"}}},{name:"circle",type:"element",attributes:{cx:"241.2",cy:"66.2",r:"59.6",fill:{type:"color",name:"sclera"}}},{name:"path",type:"element",attributes:{d:"M99 31.1a55 55 0 1 1-82.8 49.7A68 68 0 0 1 19 60.4q-6.5-4-12.8-8.6c-1.7-1.2-1.8-2.1-1.5-4.1q2-2 4.3-.7 6.2 4 12.3 8.3A55.4 55.4 0 0 1 99 31",fill:{type:"color",name:"ink"}}},{name:"path",type:"element",attributes:{d:"M62.5 30.1a49.4 49.4 0 1 1 12.8 97.6 49.3 49.3 0 0 1-12.8-97.6",fill:{type:"color",name:"sclera"}}},{name:"path",type:"element",attributes:{d:"M210.8 44.3c12-2.9 24.8 4.2 29.3 15.6a25.6 25.6 0 1 1-29.3-15.6M82.5 55.2c9.5-2 19.6 2.5 24.5 11a25 25 0 0 1 2.2 18.5A24 24 0 0 1 93.3 100a23 23 0 1 1-10.8-44.8",fill:{type:"color",name:"eyes"}}}],tags:["mood:positive"]},variant04:{elements:[{name:"path",type:"element",attributes:{d:"M297.3 32.8A65 65 0 0 0 183 36.5a70 70 0 0 0-6.5 20q-6.7.5-13 2l.3 1.5c.3 1.4.6 2.6 2.3 3q3.6.2 7.1-.3l2.8-.2a65.1 65.1 0 0 0 120.4 38.4c6.5-10.2 9.8-22 10-34q0-5.7-.8-11.2l-.4-3 3-.2q3.3-.2 6.8-1c1.1-.5 1.4-1.7 1.6-2.8l.4-1.4c-4.4-1.1-8.7-.8-13.2-.3l-1.4-3.5q-2.1-5.4-5.1-10.7m.6 14.7a59.9 59.9 0 0 0-106.7-13.8 58 58 0 0 0-8.8 22.5q9-.9 17.9-1.5l14.5-1.1 10.9-.7q7.3-.3 14.5-1.1 24.6-1.7 49.2-3.7z",fill:{type:"color",name:"ink"},"fill-rule":"evenodd","clip-rule":"evenodd"}},{name:"path",type:"element",attributes:{d:"M299.4 53.2a59.8 59.8 0 0 1-67.2 71.8 59.7 59.7 0 0 1-50.7-63l8.4-.8L239 58q6.8-.9 13.4-1.4c15.7-1 31.3-2.6 47-3.4",fill:{type:"color",name:"sclera"}}},{name:"path",type:"element",attributes:{d:"M239 58c.5 7.7-1.4 14.9-7 20.4a24.6 24.6 0 0 1-42.2-17.1z",fill:{type:"color",name:"eyes"}}},{name:"path",type:"element",attributes:{d:"M97.7 30.4c12 6.5 21 17.4 25.6 30.1l8 .8-.1.7-.6 3q-1.7 1-3.9 1.3l-1.6.4a55 55 0 1 1-109 9L9 75.4l.1-1.3c.1-1.2.2-2.7 1.2-3.3q2.3-.5 4.8-.8l1.8-.3a55 55 0 0 1 80.9-39.4m19.7 30.8a49.3 49.3 0 0 0-94.7 8l21-1.6L62.3 66q5.7-.1 11.3-.8 5.9-.7 11.7-.9l6.3-.4c8.6-.6 17.3-1.2 25.8-2.7",fill:{type:"color",name:"ink"},"fill-rule":"evenodd","clip-rule":"evenodd"}},{name:"path",type:"element",attributes:{d:"m115.2 67.6 3.8-1a49.5 49.5 0 0 1-85.8 43.2A50 50 0 0 1 22 75.3c16.4-1.6 33-2.6 49.4-4.4z",fill:{type:"color",name:"sclera"}}},{name:"path",type:"element",attributes:{d:"M115.2 67.6c-.1 3.9.5 7.4-.7 11.2-2 7.3-8 12.9-15 15.1a22.3 22.3 0 0 1-28.1-22v-1l38.4-3z",fill:{type:"color",name:"eyes"}}}],tags:["mood:negative"]},variant05:{elements:[{name:"path",type:"element",attributes:{d:"M258.8 3.3a66 66 0 0 1 34 22.7c7.5-5.1 14.7-10.7 22.4-15.7l3 1.3c-.3 2.1-.2 3.6-2.2 4.9l-20 14.2a65 65 0 0 1 9.8 44c-.5 2.7-3 3.4-5.5 3.6q-29.6 1.7-59 5.4c-11 1.4-22.2 2-33.2 3.6L194.5 89c-5 .7-9.5 1.7-14.5.3a65.2 65.2 0 0 1 78.8-86.1",fill:{type:"color",name:"ink"}}},{name:"path",type:"element",attributes:{d:"M249.8 7.2a60 60 0 0 1 50.7 65.2q-7 .8-14.2 1.2c-18 1.2-36 3.3-53.8 5.4Q212 82 192 84.5l-7.3.8a59.3 59.3 0 0 1 35.4-74.9 61 61 0 0 1 29.7-3.2",fill:{type:"color",name:"sclera"}}},{name:"path",type:"element",attributes:{d:"M205.2 43.7c6-1 12.2-.5 17.5 2.7A25 25 0 0 1 235 69.8c-.3 3.2-1.5 6.3-2.5 9.2l-5.1.7q-18 2.6-35.4 4.8l-.6-.8a24 24 0 0 1-5.7-14.9c-.8-11.8 8-23 19.5-25.1",fill:{type:"color",name:"eyes"}}},{name:"path",type:"element",attributes:{d:"M100.8 32.2A55 55 0 0 1 124.1 94c-5.3 1-10.4.5-15.8.5-24-.2-48-.1-72 1.5-5.9-.2-12.6 1.6-17.8-1.3-1-4.5-2.1-9.1-2.3-13.8-.3-10 2.2-20 6.8-29q-9.2-5.6-18.2-11.6C3 38.8 3.1 37.5 4 35.5c2.8-1 4.5.5 6.8 1.8L26 47a55.3 55.3 0 0 1 74.8-14.9",fill:{type:"color",name:"ink"}}},{name:"path",type:"element",attributes:{d:"M85.1 31.3a49.4 49.4 0 0 1 34.3 57.9l-5.6.1-38.4-.3q-20 0-40 1.6c-3.8.2-8 .7-11.6-.3-1.6-3-1.6-7.1-1.8-10.5a49 49 0 0 1 63.1-48.5",fill:{type:"color",name:"sclera"}}},{name:"path",type:"element",attributes:{d:"M89.3 56q6-1.5 11.8.1c8.3 2.6 14.7 10 15.6 18.7a26 26 0 0 1-2.9 14.5L75.4 89l-.3-.8a25 25 0 0 1-2.4-12.4 22 22 0 0 1 16.6-19.9",fill:{type:"color",name:"eyes"}}}],tags:["mood:positive"]},variant06:{elements:[{name:"path",type:"element",attributes:{d:"M246.2 0c1.7.5 1.9 2 2 3.6 0 6.7-1 13.4-.8 20.2 8.3.5 16 2 24 4.4q4.7-10.7 8.8-21.6c1-1.8 1.5-4.1 4-3.8 2.4.3 2.6 3 1.8 4.8l-9 22.6A70 70 0 0 1 295 41l14.6-13.8c1.7-1.6 3.4-1 5.4-1.1-.2 2 .3 3.6-1.4 5.1q-7.1 7.1-14.6 13.9a30 30 0 0 1 6.7 16.7c.7 9.9-4.8 18.3-12 24.4a79 79 0 0 1-40.5 16.1c-16.6 1.8-33.8.9-49.5-5a56 56 0 0 1-24.4-16.5c-5-6.4-7.8-14.7-5.7-22.8a38 38 0 0 1 18.3-22.4 95 95 0 0 1 49.5-12.1q.2-10 1.1-19.7c0-2 1.2-4.3 3.6-3.7M56.3 18.2c2-.2 2.6 2.2 3.1 3.6 1.2 5 1.3 10.2 2.2 15.3a99 99 0 0 1 25.7.7c10.9 2 22 6 30.2 13.9 5 4.6 8.4 11.2 8.2 18.1a27 27 0 0 1-9.9 18.5 65 65 0 0 1-33 13.7 84 84 0 0 1-47.4-6.3c-8.5-4.1-17-11.2-19.2-20.8a23 23 0 0 1 2-14.8Q12.4 55 6.7 49.4c-.8-1-2.4-2.2-2-3.6 0-2.6 3.5-3 5-1.4l11.7 10.9q5-5.4 11.2-9.2l-8.3-18.4c-1.1-2.2-.8-4.4-.7-6.8q2 .3 3.8.8c1.2 1.2 1.8 3 2.6 4.5l7.5 17.2q9-3.8 18.3-5.6c-.4-5.4-1.7-10.6-2-16 0-1.6.4-4.1 2.5-3.6",fill:{type:"color",name:"ink"}}},{name:"path",type:"element",attributes:{d:"M223.8 30.5A103 103 0 0 1 268 33c9.5 3 19.2 7.5 26 15a22 22 0 0 1 6 17.7c-1.1 7.2-5.8 13-11.4 17.3a74 74 0 0 1-31.1 12.8 102 102 0 0 1-47.6-2.6c-9.5-3-19.1-7.8-25.6-15.5-4.3-5-6.9-12.4-4.9-19 1.6-6.6 6.7-12 12-16a76 76 0 0 1 32.4-12.3m-168 13.3c15.6-3 33-1.7 47.4 5 6.4 3.1 13.4 8.3 15.8 15.3 2 5.6.3 11.7-3.4 16.2a44 44 0 0 1-18.5 12.3 81 81 0 0 1-39.8 3.8c-9-1.3-18.5-4.3-26-9.6-5.1-4-9.5-9-9.8-15.9-.2-6.6 3.9-12 8.7-16.1a59 59 0 0 1 25.6-11",fill:{type:"color",name:"sclera"}}},{name:"path",type:"element",attributes:{d:"M276.5 46c2.2-1.6 4.7-.3 6 1.6 1.8 3.2 2.1 6.7 2.5 10.2.4 5.2.8 10.7-.3 15.9q-.5 2-2 3.5c-3 1.4-6.9-1.3-7.6-4.2-2-6.2-2-13.2-1.4-19.7.4-2.3.6-5.9 2.8-7.3M97.6 53.1a4 4 0 0 1 6 2.4c1.8 5.1 1.9 11 2 16.3-.1 3.1-.4 8-3.8 9.5-2.6 1-4.6-1.4-5.4-3.6a45 45 0 0 1-1.5-17c.3-2.3.4-6.2 2.7-7.6",fill:{type:"color",name:"eyes"}}}],tags:["mood:positive"]},variant07:{elements:[{name:"path",type:"element",attributes:{d:"M224.8 24.5a103 103 0 0 1 57 7.8 46 46 0 0 1 21.2 19 26 26 0 0 1-.2 24c-4.2 8-12 14-20 18.2a95 95 0 0 1-44.5 9.6c-12 0-24-1.8-35.2-6a56 56 0 0 1-23.7-16.3 27 27 0 0 1-6-22A35 35 0 0 1 188 38.4a82 82 0 0 1 36.9-13.9",fill:{type:"color",name:"ink"}}},{name:"path",type:"element",attributes:{d:"M231.3 29.5c8.4-.3 17.2-.6 25.5 1A74 74 0 0 1 287 42c5.5 4 10.4 9.1 12.3 15.8s-.2 14.1-4.7 19.4A54 54 0 0 1 270 92.6q-15 5-30.8 4.9A93 93 0 0 1 209 93a54 54 0 0 1-24.8-15.2c-4.3-5-7-12.4-4.9-19 1.5-6.5 6.7-12 12-16 11.4-8.2 26-12 39.9-13.3",fill:{type:"color",name:"sclera"}}},{name:"path",type:"element",attributes:{d:"M57.8 37.6c16.3-2.3 34.2-1 49 6.6 7.8 4 15.5 10.4 18 19 2.4 7.2-.1 14.8-4.6 20.5A51 51 0 0 1 95.6 99a90 90 0 0 1-45.3 1.8 54 54 0 0 1-27.2-14c-4.7-4.7-8-11.2-7.4-18 .6-7.3 5-13.7 10.5-18.2a65 65 0 0 1 31.6-13.1",fill:{type:"color",name:"ink"}}},{name:"path",type:"element",attributes:{d:"M55.8 43.7c15.6-3 33-1.7 47.4 5 6.4 3 13.5 8.3 15.8 15.3a17 17 0 0 1-3.3 16.2A44 44 0 0 1 97 92.6a81 81 0 0 1-39 3.9c-9.3-1.3-19-4.3-26.7-9.8-5.2-4-9.6-9-10-15.9-.1-6.8 4.3-12.5 9.4-16.6a60 60 0 0 1 25-10.5",fill:{type:"color",name:"sclera"}}},{name:"path",type:"element",attributes:{d:"M276.5 46c2.1-1.6 4.7-.3 6 1.7 2.4 4 2.4 9.6 2.8 14.1.2 4.4.5 9.6-1.3 13.7-2 4.1-7.4 1.4-8.7-1.8a50 50 0 0 1-1.6-20.4c.4-2.3.6-5.9 2.8-7.3m-175.3 6.9c2.1.5 2.8 3.7 3.3 5.6q1.3 7.6 1 15.3c-.3 2.6-.7 5.7-3.1 7.2-2 1.3-4.3 0-5.3-2-2.1-3.8-2.2-9-2.3-13.2 0-4.4-.1-8.7 2.2-12.6 1.4-.3 2.7-1 4.2-.3",fill:{type:"color",name:"eyes"}}}],tags:["mood:positive"]},variant08:{elements:[{name:"path",type:"element",attributes:{d:"M242.5 30a57 57 0 0 1 34 5.5 42 42 0 0 1 18.1 18 33 33 0 0 1 2.1 21.8c-2 8-7.2 15.2-13.7 20.2a57 57 0 0 1-54.2 7.8 44 44 0 0 1-21.4-16.6 34 34 0 0 1-5.4-15.9 35 35 0 0 1 10.3-26c8-8.4 18.9-13 30.2-14.8",fill:{type:"color",name:"ink"}}},{name:"path",type:"element",attributes:{d:"M243.5 36c14-2.1 29.7 1.5 39.8 11.8 6.6 6.5 10.4 17 7.7 26-2 8.2-7.7 14.5-14.6 19.2a52 52 0 0 1-43 5.6 39 39 0 0 1-21.8-16.1c-3-5-4.1-11-3.5-16.7.7-6.8 4.5-13.1 9.3-17.9a47 47 0 0 1 26-12",fill:{type:"color",name:"sclera"}}},{name:"path",type:"element",attributes:{d:"M53.8 45.5c17.6-2.7 37.9 3.4 47.7 19.1a31 31 0 0 1 2 29.2c-3 6.3-8 11.6-13.8 15.4a52 52 0 0 1-24.4 7.8 48 48 0 0 1-39.4-15.8 31 31 0 0 1-7.5-22.4c.5-8.3 4.6-15.7 10.5-21.4a48 48 0 0 1 24.9-11.9",fill:{type:"color",name:"ink"}}},{name:"path",type:"element",attributes:{d:"M60.9 51a43 43 0 0 1 27.3 8c5.2 3.7 9.5 9.1 11.2 15.3A25 25 0 0 1 97.3 93a37 37 0 0 1-23 16.7 45 45 0 0 1-40.8-9 27 27 0 0 1-9.2-22.3C25 73 27.4 67.7 31 63.6A41 41 0 0 1 61 51",fill:{type:"color",name:"sclera"}}},{name:"path",type:"element",attributes:{d:"M235.8 54.4q5.7-1.4 11 1a16 16 0 0 1 8.8 17.5 16 16 0 0 1-15.3 12.8 15.9 15.9 0 0 1-4.5-31.3",fill:{type:"color",name:"eyes"}}},{name:"path",type:"element",attributes:{d:"M238 60c4-.7 7.8.6 10.1 4 3 4 2.3 9.8-1.3 13.2-4.4 4-12 3.4-15.2-1.7a10 10 0 0 1 6.3-15.5",fill:{type:"color",name:"sclera"}}},{name:"path",type:"element",attributes:{d:"M303 61c1.7.3 3.6-.3 4.6 1.4q2.3 4 2.9 8.5a35 35 0 0 1-9.9 29.3c-3.2 3-7.8 6-12.3 6-2.8.1-4.3-2.6-2.4-4.7 3.3-1.6 6.6-2.1 9.5-4.6 6.3-5.3 9.6-14 9.6-22.1 0-4-1.6-7.2-2.7-11z",fill:{type:"color",name:"ink"}}},{name:"path",type:"element",attributes:{d:"M64.7 65.3c4.5-.9 9.2.5 12.7 3.3a17 17 0 0 1 4.7 19.8 16 16 0 0 1-14.8 10.2c-8.5.6-16-6.4-16.5-14.8-1-8.7 5.3-17 14-18.5",fill:{type:"color",name:"eyes"}}},{name:"path",type:"element",attributes:{d:"M63.8 71.6c5.1-2 11 .6 13 5.7 2.8 6.4-1.6 14.7-8.7 15.4a10 10 0 0 1-10-4.8 11.4 11.4 0 0 1 5.7-16.3",fill:{type:"color",name:"sclera"}}},{name:"path",type:"element",attributes:{d:"M14.7 80.4c.5 4-1.4 7.4-1.6 11.4-.3 6 2.4 12.1 7.3 15.9 2.4 1.9 5 2.8 7.7 4.3 2 .8 1.9 2 1.6 3.9-1.5 1.8-3.3 1.5-5.3.8a26 26 0 0 1-16-16 25 25 0 0 1 1.4-19.4c1.3-1.9 3-.9 5-.9",fill:{type:"color",name:"ink"}}}],tags:["mood:positive"]},variant09:{elements:[{name:"path",type:"element",attributes:{d:"M239.3.9a65.3 65.3 0 0 1 66.3 75.4c-1 7.6-4 14.4-6.8 21.4q-2.3 1-4.4 1.6c-3.2 0-6.4-1.4-9.4-2.2a176 176 0 0 0-47.7-7 97 97 0 0 0-39.3 8.4c-2.9 1.3-5.6 3-8.6 3.9-3.6-.3-4.4-3.2-6-5.8a66 66 0 0 1 12.9-77.9 65 65 0 0 1 43-17.8",fill:{type:"color",name:"ink"}}},{name:"path",type:"element",attributes:{d:"M241.3 6.7a59 59 0 0 1 57.1 43.1 60 60 0 0 1-4.2 43.6c-6.2-1-11.9-3.2-18-4.4a157 157 0 0 0-51.4-3.5A91 91 0 0 0 190 96.7a60 60 0 0 1 9.8-73.4 59 59 0 0 1 41.5-16.6",fill:{type:"color",name:"sclera"}}},{name:"path",type:"element",attributes:{d:"M65.6 23.9a55.4 55.4 0 0 1 59.8 45.3 55 55 0 1 1-59.9-45.4",fill:{type:"color",name:"ink"}}},{name:"path",type:"element",attributes:{d:"M60.8 30.5a49.6 49.6 0 0 1 59.6 52.3 50 50 0 0 1-45.1 45 49.3 49.3 0 0 1-14.5-97.3",fill:{type:"color",name:"sclera"}}},{name:"path",type:"element",attributes:{d:"M203.7 51.5a15.9 15.9 0 1 1 7.1 30.9c-9.2 2.2-18.8-5-19-14.6a16 16 0 0 1 12-16.3M87.7 62.4c9.5-3.2 20 4.4 20.4 14.4.8 8.8-6.9 17-15.8 16.7-8.6.4-16-7.1-16-15.7a16 16 0 0 1 11.4-15.4",fill:{type:"color",name:"eyes"}}},{name:"path",type:"element",attributes:{d:"m283.1 109.5 3.2 1c-.5 1.7-.3 3.3-1.7 4.5a40 40 0 0 1-25.3 9.9c-3.8-.1-8.6-1-11.5-3.8l-.4-3.6 2.8-1c4.5 2.2 9 3.5 14.1 2.3 7.5-1.3 12.6-5.5 18.8-9.3M31.4 124.6c2.2-.5 3.8 1.4 5.5 2.6a53 53 0 0 0 33.4 11.4c5.8.1 10.8-2.2 16.7-1.3-.5 2.4 0 4.4-3 5A58 58 0 0 1 31.3 130c-1.8-1.4-2.3-4.4.2-5.3",fill:{type:"color",name:"ink"}}}],tags:["mood:positive"]},variant10:{elements:[{name:"path",type:"element",attributes:{d:"M240.3.9a65.2 65.2 0 0 1 65.3 75.5c-1 7.5-4 14.2-6.8 21.2-1.4.6-2.9 1.5-4.4 1.8-2.4 0-4.8-1-7-1.6a179 179 0 0 0-49.1-7.6 96 96 0 0 0-43 9.6c-3.2 1.3-6 4-9 1.3A65 65 0 0 1 240.2.9",fill:{type:"color",name:"ink"}}},{name:"path",type:"element",attributes:{d:"M241.3 6.7a59 59 0 0 1 57.1 43.1 59 59 0 0 1-4.3 43.5c-5.3-.6-10.2-2.6-15.4-3.8-16-3.7-33-5.8-49.4-4.4A92 92 0 0 0 190 96.6a59.5 59.5 0 0 1 51.3-90",fill:{type:"color",name:"sclera"}}},{name:"path",type:"element",attributes:{d:"M65.6 23.9a55.4 55.4 0 0 1 59.8 45.4 54.9 54.9 0 0 1-101 38.2c-5-8-7.6-17.2-8.2-26.6a55 55 0 0 1 49.4-57",fill:{type:"color",name:"ink"}}},{name:"path",type:"element",attributes:{d:"M60.8 30.5a49.3 49.3 0 1 1 20.9 96.3 49.3 49.3 0 0 1-21-96.3",fill:{type:"color",name:"sclera"}}},{name:"path",type:"element",attributes:{d:"M203.7 51.5a15.9 15.9 0 1 1 7.2 30.9c-9.2 2.3-19-5-19-14.5a16 16 0 0 1 11.8-16.4m-116 10.9a16 16 0 1 1-4.4 28.4 15.9 15.9 0 0 1 4.4-28.4",fill:{type:"color",name:"eyes"}}}],tags:["mood:positive"]},variant11:{elements:[{name:"path",type:"element",attributes:{d:"M240.3.9a65.3 65.3 0 0 1 65.5 73.7c-.3 2.7-3.2 3.6-5.5 3.8-23 1-45.4 3.7-68 6.3q-19.7 1.7-39.2 4.6c-4.6.5-8.6 1.7-13.1 0A65 65 0 0 1 240.3.8",fill:{type:"color",name:"ink"}}},{name:"path",type:"element",attributes:{d:"M250.5 7.3a60 60 0 0 1 50.2 60.5c-.2 1.4.2 3.5-.7 4.6-4.2.7-8.5.7-12.7 1.1-18.4 1.2-36.6 3.4-54.9 5.5q-20.5 3-40.3 5.5l-7.3.8a59.2 59.2 0 0 1 65.7-78",fill:{type:"color",name:"sclera"}}},{name:"path",type:"element",attributes:{d:"M195.5 48A24.8 24.8 0 0 1 235 68.8a31 31 0 0 1-2.6 10.2q-20.5 3-40.3 5.5a24 24 0 0 1-6.4-15.7c-.5-8 3.4-16 9.8-20.8",fill:{type:"color",name:"eyes"}}},{name:"path",type:"element",attributes:{d:"M100.2 31.9a55 55 0 0 1 23.9 61.8c-4 1.2-7.7.8-11.8.8-25.4-.3-50.6-.3-76 1.4-5.6-.3-13 1.8-17.8-1.4a55.2 55.2 0 0 1 81.7-62.7",fill:{type:"color",name:"ink"}}},{name:"path",type:"element",attributes:{d:"M94.8 35.3a49 49 0 0 1 24.6 53.9l-5.7.1-38.2-.4q-23.2.3-46.2 2c-1.8-.2-5.8.5-6.1-2a49 49 0 0 1 71.6-53.6",fill:{type:"color",name:"sclera"}}},{name:"path",type:"element",attributes:{d:"M87 56.6q7-2.4 14.1-.5a22 22 0 0 1 15.4 17.7 24 24 0 0 1-2.8 15.5l-19.2-.2H85l-9.5-.2-.4-.7a24 24 0 0 1-2.5-11.4 22 22 0 0 1 14.5-20.2",fill:{type:"color",name:"eyes"}}}],tags:["mood:positive"]},variant12:{elements:[{name:"path",type:"element",attributes:{d:"M273.6 9.5A64 64 0 0 1 302.1 43a64 64 0 0 1 .5 45.1c-1 2.9-2.9 5.2-6.3 4.8-15-.8-30 .1-45 .5q-15 1.5-30 3.8-15.7 2.9-31 6.1c-4.3-.1-5.3-4.2-7.2-7.3a65.5 65.5 0 0 1 47.1-94.2 65 65 0 0 1 43.4 7.7",fill:{type:"color",name:"ink"}}},{name:"path",type:"element",attributes:{d:"M242.3 6.7a59 59 0 0 1 54.4 80.6l-3.2-.3q-25 .5-48.7 1.5a287 287 0 0 0-34 5.2c-6.7 1.2-13.4 3.2-20.2 4a60 60 0 0 1 10.7-75.9 59 59 0 0 1 41-15.1",fill:{type:"color",name:"sclera"}}},{name:"path",type:"element",attributes:{d:"M257.7 52.1a26.6 26.6 0 0 1 37.2 19.5 27 27 0 0 1-1.4 15.4q-25 .5-48.7 1.5A26.6 26.6 0 0 1 257.7 52",fill:{type:"color",name:"eyes"}}},{name:"path",type:"element",attributes:{d:"M76.3 23.9a54.8 54.8 0 0 1 42.8 81.8c-1.1 1.8-2.9 4-5 4.7-3 .8-6.6-.2-9.6-.9q-13-3-26.3-5.1-19.4-1.4-39 0c-4.7.4-9.7 1.4-14.5 1-2.3-1-3.7-4.2-4.6-6.4a55 55 0 0 1 56.2-75",fill:{type:"color",name:"ink"}}},{name:"path",type:"element",attributes:{d:"M85.8 31.5a49.3 49.3 0 0 1 26.7 74l-4.1-.7c-12.4-2.2-24.9-5-36.5-6.8-7.6.2-15-.4-22.6.3l-22 1.8q-1-1.6-1.8-3.4a49 49 0 0 1 10.3-52.4c12.7-13.2 28.4-17.7 50-12.8",fill:{type:"color",name:"sclera"}}},{name:"path",type:"element",attributes:{d:"M71.5 80a22.7 22.7 0 1 1 36.9 24.8c-12.4-2.2-24.9-5-36.5-6.8l-.2-.6a23 23 0 0 1-.2-17.4",fill:{type:"color",name:"eyes"}}}],tags:["mood:positive"]},variant13:{elements:[{name:"path",type:"element",attributes:{d:"M239.3.9a65 65 0 0 1 63.5 43.4c2.1 5.6 2.6 11.1 3.6 17-1.3 1.4-1.7 3.3-4 3-7-.4-14-2.1-21-2.3-8.8 0-17.4-.4-26.1 1-9.9 1.6-19.6 2.6-29.1 5.7A175 175 0 0 0 193.7 81c-3.4 1.7-6.5 3.8-9.9 5.3-2 .7-4.4.3-5.3-2a66 66 0 0 1 17.2-65.2A65 65 0 0 1 239.3 1",fill:{type:"color",name:"ink"}}},{name:"path",type:"element",attributes:{d:"M241.3 6.6a59 59 0 0 1 59 52.5q-22.4-4.4-45-2.5-9 1.2-17.9 2.9c-13.4 3-31.4 11-48.6 17.1l-5.8 3A60 60 0 0 1 203.5 20a59 59 0 0 1 37.8-13.4",fill:{type:"color",name:"sclera"}}},{name:"path",type:"element",attributes:{d:"M203.5 39.1a26 26 0 0 1 30.3 11.1c1.9 3 2.7 6 3.6 9.3-13.4 3-31.4 11-48.6 17.1-3.5-7-4.3-15.2-1.3-22.6 2.9-7 8.8-12.6 16-14.9",fill:{type:"color",name:"eyes"}}},{name:"path",type:"element",attributes:{d:"M95.7 29.4a55 55 0 0 1 29.4 61.2l-2.9 1.5q-14.7-4.1-29.9-5.4a348 348 0 0 0-54 0c-7 .2-13.5 2-20.5 1.6-.8-2.4-1.7-4.8-1.7-7.5a55 55 0 0 1 79.6-51.5",fill:{type:"color",name:"ink"}}},{name:"path",type:"element",attributes:{d:"M81.5 30.4a49.6 49.6 0 0 1 38.6 55.3 83 83 0 0 0-12.3-3q-18.7-2.9-37.7-2.4c-15.1.9-31.1 2.2-46 3-1.8-1.2-2-1.3-2-3.4a49.4 49.4 0 0 1 59.5-49.4",fill:{type:"color",name:"sclera"}}},{name:"path",type:"element",attributes:{d:"M26 68.5a23.1 23.1 0 0 1 42.7.8c1.5 3.6 1.4 7.1 1.4 11l-5.7.3c-13.4 1-27.3 2-40.4 2.8.2-5.2-.3-10 2-14.9",fill:{type:"color",name:"eyes"}}}],tags:["mood:positive"]},variant14:{elements:[{name:"path",type:"element",attributes:{d:"M243.3 21.3a75 75 0 0 1 33.2 4.3 46 46 0 0 1 26.2 23.8c1.4 3.3 3.1 7.5 2.2 11.1-3 3.2-8.5 1-12.5 1q-19.1-.9-38 .6c-14 1-28.5 1.7-42 5.3a188 188 0 0 0-25.2 7.4c-3.7 1.2-6.8 3-11 2.2 1.4-16.9 13-31.4 26.4-41a87 87 0 0 1 40.7-14.7",fill:{type:"color",name:"ink"}}},{name:"path",type:"element",attributes:{d:"M183 70.6a58 58 0 0 1 18.2-26.5 161 161 0 0 1 25.2-12.8c10-3.6 20.2-5.5 30.9-4.3 11.6 1 23.2 5 31.9 13q7.4 7 10.1 16.7c-16.7-2.2-34.3-.9-51 0-7.7 1-15.4 1-23 2.3a222 222 0 0 0-42.2 11.6",fill:{type:"color",name:"sclera"}}},{name:"path",type:"element",attributes:{d:"M226.4 31.3c1 9.3 0 18.5-1 27.7l-1.6.3c-7.5 1.3-15.3 3.2-22.5 5.2q-1-9.6-.2-19V44c7.9-4.6 16.4-9.5 25.3-12.8",fill:{type:"color",name:"eyes"}}},{name:"path",type:"element",attributes:{d:"M53.5 45.5a80 80 0 0 1 50.9 8.2c8.7 4.8 16.9 12 20.6 21.4.7 2.1 1.6 4.6-.7 6q-4-.2-8-1c-9.4-1.8-19.4-2.1-29-2.6-10.7-.4-21.3.5-32 .6-12.5.9-24.8 3-37 5-2.5.6-3.2-2.4-3.2-4.2.2-12.4 9.1-22.3 19.8-27.5q9-3.8 18.6-6",fill:{type:"color",name:"ink"}}},{name:"path",type:"element",attributes:{d:"M20.8 76.6c1.6-7 5.1-12.1 10.6-16.6l3.4-2.6A69 69 0 0 1 88 53a51 51 0 0 1 30.6 21.5c-20.2-3.5-40-2.6-60.3-2.4q-12.1 1.1-23.6 2.7-7 .3-14 1.7",fill:{type:"color",name:"sclera"}}},{name:"path",type:"element",attributes:{d:"M58.9 50.1c.1 7.4.3 14.7-.5 22l-3 .4q-10.6 1-20.6 2.4-.4-8.8 0-17.5a69 69 0 0 1 24-7.3",fill:{type:"color",name:"eyes"}}}],tags:["mood:positive"]},variant15:{elements:[{name:"path",type:"element",attributes:{d:"M190.3 38c5.5-1.2 11.7 2.4 17 3.9a183 183 0 0 0 69 7.7c6.2-.6 12.8-2.4 19-2 6.2.7 10.4 6.1 11 12a66 66 0 0 1-35.5 64.6A65.4 65.4 0 0 1 178.4 48c1.4-5.3 6.8-9 12-10m-77.8 5.5c3.6 2.3 5.8 6.6 7.7 10.3A55.3 55.3 0 0 1 79.5 133 55 55 0 0 1 17 87.8c-.5-3.7-1.5-7.6.2-11.1 1.6-4.2 5.7-7.1 10.1-7.6q7.5-.8 14.8-2A124 124 0 0 0 92.4 45a16.5 16.5 0 0 1 20.2-1.5",fill:{type:"color",name:"ink"}}},{name:"path",type:"element",attributes:{d:"M197.7 44.4c12.2 5 25.5 8 38.6 9.8a172 172 0 0 0 47 .3c3.9-.6 8.1-1.8 12-1.6 2.4.1 4.4 2.7 4.8 5a59 59 0 0 1-37 63.6 59.6 59.6 0 0 1-79.4-70.2c1.6-6.3 8-10 14-6.9M112 51c4.9 7 7.6 15.3 8.5 23.7A50 50 0 0 1 70.3 128 49 49 0 0 1 22 81.8c-.5-3.2 2.1-6.5 5.2-7 3.3-.7 6.7-.8 10-1.2C55.8 71.4 73.8 64 89.4 54c3.1-1.9 5.9-4.3 9-6.1 4.4-2.3 11-1.2 13.7 3.2",fill:{type:"color",name:"sclera"}}},{name:"path",type:"element",attributes:{d:"M217.8 73.7A22 22 0 0 1 242 94.8c.9 11-7.5 21.2-18.4 22.8a22.1 22.1 0 1 1-5.7-43.8M84.8 82.3c6-1.3 12.6.9 17 5a19.5 19.5 0 1 1-17-5",fill:{type:"color",name:"eyes"}}}],tags:["mood:negative"]},variant16:{elements:[{name:"path",type:"element",attributes:{d:"M179.1 51.4c2.5.2 5 1.4 7.4 2.3 9.3 3.6 18.8 6 28.5 8.3 21 5 42.8 8.8 64.3 6.9q11-1.6 22-3.8c2.6-.7 5.5.7 5.2 3.6a65.5 65.5 0 0 1-113 42A73 73 0 0 1 178 83.9c1.2 8 2.5 15.7 6.2 23 3 6 7.3 11 11.6 16-1.1 1.3-2.5 3.3-4.5 2-3.6-2.7-6.2-6.8-8.8-10.4-6.2-9-8.8-19.5-10-30.2-1-7.3 0-15 1.3-22.2.7-3.6 1.9-8.7 5.2-10.7",fill:{type:"color",name:"ink"}}},{name:"path",type:"element",attributes:{d:"M182.2 57.9c5 1.8 9.7 3.8 14.8 5.1 13.9 3.7 28.1 7.8 42.3 9.6l7.7 1.5c9 2.1 33 1.1 47-1.9l6.6-1A60 60 0 0 1 227 124a59.7 59.7 0 0 1-45-66.1",fill:{type:"color",name:"sclera"}}},{name:"path",type:"element",attributes:{d:"M294 72.2a26 26 0 0 1-5.9 16.4 23.5 23.5 0 0 1-41-14.5c8.9 2.1 32.9 1.1 47-1.9",fill:{type:"color",name:"eyes"}}},{name:"path",type:"element",attributes:{d:"M120.4 56.6c2.2.8 3.2 3 4.1 5 5.6 12 7.7 26.3 4.8 39.3a41 41 0 0 1-12 23c-1.6 1.6-3.5 1.5-5.6 1.4v-3.1c2.1-2.6 4.8-4.6 6.5-7.5a53 53 0 0 0 7-25.2A54.7 54.7 0 0 1 39 123c-9-6.5-16-15.9-19.7-26.4-.6-2-1.2-4.4-.5-6.3a9 9 0 0 1 5.6-2c8.8-.6 17.3-2.7 26.1-4.5 7.5-1.5 14.6-3.9 22-6 9.5-3.2 18.9-7.8 28-11.9q7.9-3.5 15.3-7.8c1.4-.7 3-1.8 4.7-1.6",fill:{type:"color",name:"ink"}}},{name:"path",type:"element",attributes:{d:"M118 63a49.4 49.4 0 1 1-93.8 30.7q22.6-2.4 44.1-8.7c14.2-4.3 30-12 43-18.6l6.8-3.3",fill:{type:"color",name:"sclera"}}},{name:"path",type:"element",attributes:{d:"M111.3 66.4a25 25 0 0 1 1.9 22.3 24 24 0 0 1-24 14.2c-10-.8-18-8-20.8-17.5l-.1-.4c14.2-4.3 30-12 43-18.6",fill:{type:"color",name:"eyes"}}}],tags:["mood:negative"]},variant17:{elements:[{name:"path",type:"element",attributes:{d:"M246.3 44.6q2.4 0 4.9.6c-.3 2.3.3 4.3-2.6 4.8l-28.3 2c-4.3.2-8.8 1.2-13 .9q-3-1-2.1-4.1c1.4-1.4 3.2-1.6 5-1.7 12-.6 24-1.9 36.1-2.5m56.9 15.3 3.1 2.2a66 66 0 0 1-34.2 61.5 65.4 65.4 0 0 1-96-53c2.1-3.2 5.8-3 9.2-3.2l92-6.2c8.7-.2 17.2-1.6 25.9-1.3",fill:{type:"color",name:"ink"}}},{name:"path",type:"element",attributes:{d:"M300.6 65.5a59.2 59.2 0 0 1-68.3 59.5 60 60 0 0 1-35.3-18.9 58 58 0 0 1-14.8-32.5c11.2-1.2 22.4-1.7 33.6-2.6q14.4-1.2 28.6-1.9 28.1-2 56.2-3.6",fill:{type:"color",name:"sclera"}}},{name:"path",type:"element",attributes:{d:"M244.4 69.1c.8 10 1.4 22.3-3.2 31.6-2 3.9-5.2 7.3-10 6.4-4.9-1-8.3-6.8-10.2-11.1a72 72 0 0 1-5-23.4l-.2-1.6q12.6-1 25-1.7z",fill:{type:"color",name:"eyes"}}},{name:"path",type:"element",attributes:{d:"M80.6 58.1c1.3 1.3 2.2 2 2.1 3.9-1.4 2.5-5 2-7.4 2.3-8 .2-16 1.7-24 1.7-2.8-.3-2.2-2.5-2.6-4.5 10.3-2.7 21.4-1.8 32-3.4m18.6 18.4c8.1-.7 16.1-1.4 24.3-1l2.6 2.5a55.1 55.1 0 0 1-109.6 6.7c1-.9 2.2-2.7 3.6-2.8 13-1.6 26-1.7 39.1-3 13.4-.6 26.7-1.7 40-2.4",fill:{type:"color",name:"ink"}}},{name:"path",type:"element",attributes:{d:"M120.7 81a49.5 49.5 0 0 1-49.4 47 50 50 0 0 1-48.6-40.7q17-1.5 34-2.3L79 83.5c13.9-.8 27.8-2.2 41.7-2.4",fill:{type:"color",name:"sclera"}}},{name:"path",type:"element",attributes:{d:"M79 83.5a42 42 0 0 1-2.2 20.7c-1.4 3-4 6.2-7.5 6.3-3.4.2-6-2.4-7.7-5a38 38 0 0 1-4.8-20.6z",fill:{type:"color",name:"eyes"}}}],tags:["mood:negative"]},variant18:{elements:[{name:"path",type:"element",attributes:{d:"M301.5 45.6c1.2 1.4 2.4 2.4 2.9 4.2a65.5 65.5 0 0 1-79 79.6 65 65 0 0 1-49-71.6c.6-3.4 1.8-7.2 5.7-8 8.6-1.6 17.5-1.4 26.2-2.3a999 999 0 0 1 73-2.1c6.8-.4 13.5.4 20.2.2",fill:{type:"color",name:"ink"}}},{name:"path",type:"element",attributes:{d:"m291.4 51 7.4.5a59 59 0 0 1-37.2 70.5 59.3 59.3 0 0 1-79-66q2.7-1.1 5.7-1.4 25.3-2 50.8-3 26-1.2 52.3-.5",fill:{type:"color",name:"sclera"}}},{name:"path",type:"element",attributes:{d:"M239.2 51.5q26.1-1 52.1-.4.5 2.4.5 4.9a26.5 26.5 0 1 1-52.6-4.5",fill:{type:"color",name:"eyes"}}},{name:"path",type:"element",attributes:{d:"M116.3 57.5c2-.3 3.8.3 5.8.7A55 55 0 1 1 16 76.8c6.5-3.3 13.1-3.8 20.4-5.5Q67.3 64.9 98.3 60q9-1.6 18-2.5",fill:{type:"color",name:"ink"}}},{name:"path",type:"element",attributes:{d:"M118 62.9a55 55 0 0 1 2.6 15.9 49.6 49.6 0 0 1-54.3 48.9 50 50 0 0 1-44.4-47.3c14.4-3.6 29.1-6.2 43.7-9q23.7-4.2 47.2-8z",fill:{type:"color",name:"sclera"}}},{name:"path",type:"element",attributes:{d:"M112.8 63.4q.4 2 .4 4.3a23.9 23.9 0 0 1-47.5 3.7 2324 2324 0 0 1 47.1-8",fill:{type:"color",name:"eyes"}}}],tags:["mood:negative"]},variant19:{elements:[{name:"path",type:"element",attributes:{d:"M303.7 45.4c3.8 2.6 8 5.3 11.1 8.9q.3 2.5 0 5c-1.9.7-3.3 1.1-5.3.3a142 142 0 0 0-91.4 0c-12.5 4.2-25 10.3-35.2 18.8-1.4 1-4 2.9-5.3 1.1-1.7-1.6-.7-3.5.2-5.2a81 81 0 0 1 30.6-30.4 94 94 0 0 1 95.3 1.5M89.8 57.2a57 57 0 0 1 31.2 18c2.8 3.8 6.5 8 5.9 13.1-1.6 0-3.3.7-4.6-.5a51 51 0 0 0-13.9-8 100 100 0 0 0-48.6-5.1 75 75 0 0 0-36 13.7c-1.9 1.3-3.1 2.8-5.6 1.8-1.2-1.9-1-4.5.3-6.2 16-21.8 45-31.8 71.3-26.8",fill:{type:"color",name:"ink"}}}],tags:["mood:positive"]},variant20:{elements:[{name:"path",type:"element",attributes:{d:"m304.2 58.6 2.6 1.1-.5 3c-2.2 3.8-6 7-9 10.1q-8.7 7.7-19.1 12.9c-14 7-30.3 9.9-45.9 8.4A111 111 0 0 1 178.1 73c-1.4-1.1-2.9-2-2.5-4 .6-2.5 4-3.4 6.2-2.5 21.2 6.3 42.6 6.7 64.5 5.5 16.3-1.6 32-4.3 47.5-9.7 3.6-1.2 6.8-2.8 10.4-3.7M124.9 69.2c2.8 1.4 2.2 4.4 0 6.2a79 79 0 0 1-39.6 18.8c-7.8 1-15.1 2.3-23 1.1a85 85 0 0 1-39-12.5c-2.1-1.4-4.7-2.9-6.2-5q-.7-3.7 3.2-4.2c2.7.3 5.4 1.4 8 2 7.6 2.2 15.3 3 23 3.9a169 169 0 0 0 64.2-7.6c3-.8 6.3-3 9.4-2.7",fill:{type:"color",name:"ink"}}}],tags:["mood:positive"]},variant21:{elements:[{name:"circle",type:"element",attributes:{cx:"71.3",cy:"78.6",r:"55",fill:{type:"color",name:"ink"}}},{name:"circle",type:"element",attributes:{cx:"71.1",cy:"78.6",r:"49.3",fill:{type:"color",name:"sclera"}}},{name:"path",type:"element",attributes:{d:"M274.3 51.7c13-.6 27-1.3 39.8 1.5 2.2.6 3 1.3 2.3 3.7-2 1.7-6 3.3-6.8 6 0 6 9 6 9.7 10.9-.3 3-2.4 3.3-5 3.1q-11.5-1-23-1.4c-16 0-32-.2-48 .9-7.6.7-15.2.6-22.8 1.2-11 1-22.1 1.3-33.1 3.3q-4.1 1-8.2 1c-2-1.2-3.1-5.5-.6-6.8 5.3-3 11.3-5 17.2-6.8 15-5 30.7-8.3 46.2-11.7 10.7-2.4 21.5-3.7 32.3-4.9",fill:{type:"color",name:"ink"}}},{name:"path",type:"element",attributes:{d:"M89.7 56.5q5.3-1.5 10.4-.2a20.2 20.2 0 0 1-5.8 39.6 20.1 20.1 0 0 1-4.5-39.5",fill:{type:"color",name:"eyes"}}}],tags:["mood:positive"]},variant22:{elements:[{name:"path",type:"element",attributes:{d:"M234.6 1.2a66 66 0 0 1 62 30.4 65 65 0 0 1-14.3 85.2A65.4 65.4 0 1 1 234.6 1.2",fill:{type:"color",name:"ink"}}},{name:"path",type:"element",attributes:{d:"M233.5 7a59.7 59.7 0 1 1 15.1 118.3 59.7 59.7 0 0 1-15-118.2",fill:{type:"color",name:"sclera"}}},{name:"circle",type:"element",attributes:{cx:"212.1",cy:"65.2",r:"22.2",fill:{type:"color",name:"eyes"}}},{name:"path",type:"element",attributes:{d:"M17.3 55.3c14.4.7 28.7 1.5 43 3.9 21.1 3.4 42.9 9 62.1 18.4 2.9 1.6 2.5 3.3 1.6 6.1q-3.4.1-6.7-1a260 260 0 0 0-34-7.2c-10.5-1.4-20.6-3.2-31-3.7-11-1-21.9-.7-33-.7-2 0-5 .7-6.6-.7-.7-2.1.8-4.7 1.3-6.8-.9-1.5-3-3.4-2.4-5.4 1-2.4 3.4-3 5.7-3",fill:{type:"color",name:"ink"}}}],tags:["mood:positive"]},variant23:{elements:[{name:"circle",type:"element",attributes:{cx:"242.7",cy:"65.9",r:"65.2",fill:{type:"color",name:"ink"}}},{name:"circle",type:"element",attributes:{cx:"241.2",cy:"66.2",r:"59.6",fill:{type:"color",name:"sclera"}}},{name:"path",type:"element",attributes:{d:"M65.5 23.9a55.3 55.3 0 0 1 60 45.4 54.9 54.9 0 0 1-103.8 33.1A54 54 0 0 1 17 69.8 54.5 54.5 0 0 1 65.5 24",fill:{type:"color",name:"ink"}}},{name:"path",type:"element",attributes:{d:"M62.5 30.1a49.4 49.4 0 1 1-6 95.5 49.5 49.5 0 0 1-20.2-81.8 50 50 0 0 1 26.2-13.7",fill:{type:"color",name:"sclera"}}},{name:"path",type:"element",attributes:{d:"M243 33.5c-3.8 4-6.6 8.6-6.6 14.3A21 21 0 0 0 249 68.2a19 19 0 0 0 17.7-2 36.3 36.3 0 1 1-52.7-31 39 39 0 0 1 29.2-1.7M76.3 44.7A35 35 0 0 1 99 49c-3 3-5.4 6.3-5.5 10.8a14.6 14.6 0 0 0 11.8 15.5c3.4.6 6.2-.5 9.4-1.5a34 34 0 0 1-14.8 31.6 33.3 33.3 0 1 1-23.6-60.7",fill:{type:"color",name:"eyes"}}},{name:"path",type:"element",attributes:{d:"M211.7 66.3c2.3-1 4.8-1.3 7 .2 3.5 2.3 3.4 7.5.8 10.5-2.7 3-7.8 3.2-10.4-.1-2.8-3.4-1.3-8.7 2.6-10.6m-148 6c4.8-1.6 9.3 3.6 7.1 8-1.6 3.7-7 4.4-9.4 1.4-2.6-3-1.5-8 2.3-9.4m157.1 9.2q3.9-1 7.8.1c6.1 2.4 8 11.2 3.5 16-4 4.8-11.7 5-15.6 0-4.5-5.3-2.5-13.9 4.3-16.1m-150 8c3.4-1 7.1-.6 9.6 2.2 3.5 3.4 3.4 9.6-.6 12.6-4 3.5-10.7 1.8-13.2-2.8a8.3 8.3 0 0 1 4.2-12",fill:{type:"color",name:"sclera"}}}],tags:["mood:positive"]},variant24:{elements:[{name:"path",type:"element",attributes:{d:"M235.6 1a65.4 65.4 0 0 1 59.6 101.7A65.2 65.2 0 1 1 235.6 1",fill:{type:"color",name:"ink"}}},{name:"path",type:"element",attributes:{d:"M233.6 7a59.6 59.6 0 1 1 15.2 118.3A59.6 59.6 0 0 1 233.6 7.1",fill:{type:"color",name:"sclera"}}},{name:"path",type:"element",attributes:{d:"M65.6 23.9a55.4 55.4 0 0 1 58.6 40 55.5 55.5 0 0 1-26.7 63 54.7 54.7 0 0 1-81.3-46.1 55 55 0 0 1 49.4-57",fill:{type:"color",name:"ink"}}},{name:"path",type:"element",attributes:{d:"M62.6 30a49 49 0 0 1 57.2 56.7 49.1 49.1 0 0 1-93.1 12.9A49.3 49.3 0 0 1 62.6 30",fill:{type:"color",name:"sclera"}}},{name:"path",type:"element",attributes:{d:"M210.8 44.3c12-2.9 24.9 4.2 29.3 15.6a26 26 0 0 1 0 18.7 25.6 25.6 0 1 1-29.3-34.3M82.6 55.2a23 23 0 0 1 27 18c.7 5.7.6 11.4-2.6 16.3a23 23 0 0 1-23.6 11 23.1 23.1 0 0 1-.8-45.3",fill:{type:"color",name:"eyes"}}}],tags:["mood:positive"]},variant25:{elements:[{name:"path",type:"element",attributes:{d:"M234.6 1.2a66 66 0 0 1 68.2 43.3 65 65 0 0 1-20.5 72.3A65.4 65.4 0 1 1 234.6 1.2",fill:{type:"color",name:"ink"}}},{name:"circle",type:"element",attributes:{cx:"241.2",cy:"66.2",r:"59.6",fill:{type:"color",name:"sclera"}}},{name:"path",type:"element",attributes:{d:"M65.6 23.9a55.3 55.3 0 0 1 59.7 44.8 55 55 0 1 1-59.8-44.8",fill:{type:"color",name:"ink"}}},{name:"path",type:"element",attributes:{d:"M62.6 30a49 49 0 0 1 57 57.5 49.4 49.4 0 1 1-57-57.4",fill:{type:"color",name:"sclera"}}},{name:"circle",type:"element",attributes:{cx:"216.3",cy:"66.3",r:"23.8",fill:{type:"color",name:"eyes"}}},{name:"path",type:"element",attributes:{d:"M42.8 57.7a22 22 0 0 1 28 16.4 21.7 21.7 0 0 1-17.5 25.6 22 22 0 0 1-24.6-14 22.3 22.3 0 0 1 14.1-28",fill:{type:"color",name:"eyes"}}}],tags:["mood:positive"]},variant26:{elements:[{name:"circle",type:"element",attributes:{cx:"244.2",cy:"65.9",r:"65.4",fill:{type:"color",name:"ink"}}},{name:"path",type:"element",attributes:{d:"M233.6 7a59.7 59.7 0 1 1 15.1 118.4A59.7 59.7 0 0 1 233.6 7.1",fill:{type:"color",name:"sclera"}}},{name:"path",type:"element",attributes:{d:"M65.5 23.9a55.3 55.3 0 0 1 60 45.9 54.9 54.9 0 0 1-100.2 39 57 57 0 0 1-9.1-28 55 55 0 0 1 49.4-57",fill:{type:"color",name:"ink"}}},{name:"circle",type:"element",attributes:{cx:"71.2",cy:"78.7",r:"49.3",fill:{type:"color",name:"sclera"}}},{name:"path",type:"element",attributes:{d:"M260.7 41.2a25 25 0 0 1 17.7 1.5c10 4.7 16.7 17.4 12.9 28.1a24.3 24.3 0 0 1-36.6 14.6 24.5 24.5 0 0 1 6-44.2M92.8 55.3c12.7-1.6 25 8.5 25.3 21.5 1 12.4-9.3 24.2-21.8 24.3a23 23 0 0 1-23.9-22.3 23 23 0 0 1 20.4-23.5",fill:{type:"color",name:"eyes"}}}],tags:["mood:positive"]}}},glasses:{width:363,height:164.5,probability:10,variants:{variant01:{elements:[{name:"path",type:"element",attributes:{d:"M274.5 1c10.7-.3 21.3 0 32-.3 14-.6 28-.3 42-.5 3.9.2 9-.1 12.2 2.3 2.4 1.7 2.2 5.6 2.4 8.2-.2 4.3-.3 9.4-2.4 13.3-5 2-11.4 1.2-16.8 1.9.4 12.3 1.7 24.6 1.3 36.8-.7 14-3.7 28-10.3 40.3-8.1 13-20 24.4-33.6 31.6a77 77 0 0 1-33.4 7.7c-6.2.2-12 .5-18.2-.8-9.4-2-18.8-4.5-27-10a82 82 0 0 1-25.3-30.7 193 193 0 0 1-13.3-44c-.5-2.2-2.4-3.4-4.3-4.4-6.7-3-15-.5-18.8 5.6q-1 3.9-1.2 7.7c-.6 7.6-2.3 15.3-3.9 22.8-3.1 13.6-9 26.3-16.8 37.8a51 51 0 0 1-16.2 14.8 76 76 0 0 1-34.4 10.3c-7.3-.2-14.2-.4-21.1-2.5-5.5-1.3-10.5-4.8-15.2-8a58 58 0 0 1-15.3-16.7Q29 111.7 24.7 97.5a98 98 0 0 1-5.2-28.7c-4.6.7-9.4 2.2-14 2-4.4-1-5.3-7.7-5.5-11.2.1-2.4-.2-6.8 2.7-7.7a368 368 0 0 1 67.5-22.3c17-3.7 34.8-8.3 52.3-6.7 11.2 1 22.8 4 31.7 11 3.2 2.5 5.5 6.9 9.4 7.7 7 1.8 14.5-1.3 20.9-4a43 43 0 0 1 19-22.8 89 89 0 0 1 20.8-8.3c16.7-4 33-4.6 50.2-5.5",fill:{type:"color",name:"glasses"}}},{name:"path",type:"element",attributes:{d:"M12.6 62.9c1.2-1.2 3.4 0 2.4 1.6-1.2 1.2-3.4 0-2.4-1.6",fill:{type:"color",name:"glasses"}}},{name:"ellipse",type:"element",attributes:{cx:"310.5",cy:"42.2",rx:"14",ry:"10.5",fill:"#ffffff"}},{name:"ellipse",type:"element",attributes:{cx:"116.5",cy:"60.8",rx:"11",ry:"8.1",fill:"#ffffff"}}],tags:["eyewear:sunglasses"]},variant02:{elements:[{name:"path",type:"element",attributes:{d:"M313.5.5 332 .3h15.2q4.6-.1 9.3.4c2.6.6 5.6 2 6 4.9 1 5 .5 12-1 17-.5 1.7-1.8 2-3.4 2.3q-5.3.6-10.4.8l-3.8.2.6 13c.7 11.7 1.4 23.6-.4 34.8q-1.5 11.3-5.7 21.9a67 67 0 0 1-15.4 22.6 75 75 0 0 1-36.2 21.8q-16.5 3.5-33.3 2.1a87 87 0 0 1-27-8.4c-10.5-6-18.5-15-24.8-25.2A134 134 0 0 1 185 60.2a63 63 0 0 0-1.6-8.4c-.4-1.8-2.6-3-4.1-4-6.7-3.3-16.4-.9-19 6.7a56 56 0 0 0-.6 8.6q0 4.4-.6 8.6c-2 13-4.8 26.1-10.6 38a70 70 0 0 1-22.4 29.6 73 73 0 0 1-64 7.7 63 63 0 0 1-18.8-14 107 107 0 0 1-20.8-43.2q-3-10.2-3-20.9l-4.9.9q-3.6.8-7.2 1.1-3.5.4-5.3-2.6A20 20 0 0 1 .3 55.6l.1-.5q.1-1.8 1.6-2.8c27.5-12.6 56-20.6 85.5-26.5 11.3-2.3 22.5-3.8 34-3 10 0 20 2.3 28.9 7a42 42 0 0 0 35.1-.1c3-1.5 5-3.7 7-6q1.6-2.1 3.9-4.1c9.8-9.1 23-13.3 36.1-14.8 13.1-2.4 26.3-3 39.5-3.7h1.5l1-.1 16.7-.1q11.1.1 22.3-.4m-23 6.2c8.3-.3 16.3-.4 24.1 3l2.2.9c3.1 1.3 6.8 2.8 7.8 6a98 98 0 0 1 8.4 40 96 96 0 0 1-5.2 37.3 61 61 0 0 1-18.2 23.9 76 76 0 0 1-17.8 10.2 66 66 0 0 1-29.3 6.2c-5.8-.4-11.6-1.8-17.2-3.2l-.9-.2c-6-1.5-10.7-4.6-15.7-7.9l-.8-.5a70 70 0 0 1-17.1-17 58 58 0 0 1-6.3-13.3l-1.2-3.1a101 101 0 0 1-6-37.3c.2-7.8 1.3-17 5.6-23.6 5.1-6.4 12-12.2 19.8-15 9.3-2.9 19.2-4.3 28.8-5a321 321 0 0 1 39-1.4M118 28.8h-2.6c-8.6-1-17.9.9-26.5 2.6l-3.5.6-6.8 1.5c-9.4 2-18.7 4-27.7 7.7l-2.8 1c-5.8 2.2-12 4.6-15 10.3-4.8 9.8-3.7 19.6-2.5 29.9l.4 3.3A92 92 0 0 0 44.2 119c5 8 10.9 15 19.4 19.6 12.8 7 28 6.1 41.4 1.5 11.4-4.4 21.8-9.8 28.6-20.3 8.8-14 13.9-30.7 15.5-47.2q1.3-14.1-2.7-27.8-.6-2.3-2-4.1a36 36 0 0 0-19.1-11.4q-3.5-.5-7.2-.5",fill:{type:"color",name:"glasses"},"fill-rule":"evenodd","clip-rule":"evenodd"}}],tags:["eyewear:glasses"]},variant03:{elements:[{name:"path",type:"element",attributes:{d:"M236.8 91.4A27.9 27.9 0 1 1 194 116c-8.6-10.2-25.5-14-36.5-5.2-3.2 3-6.6 7.3-6.7 11.9a27.5 27.5 0 0 1-53 5.6 27.6 27.6 0 0 1 10.6-32.7A28 28 0 0 1 134 93a29 29 0 0 1 16 17.4 27 27 0 0 1 22.4-10c8.2-.1 15.4 3.2 22 8a28 28 0 0 1 42.3-17m-22.6 2.4a22.4 22.4 0 0 1 29.9 23 23 23 0 0 1-18.1 20.2 22.6 22.6 0 0 1-26-16.3c-3-11.1 3.3-23 14.2-26.9m-70.6 15.8a22 22 0 0 0-23-12.8 22 22 0 0 0-12.6 37.3c6.1 6 15.7 8 23.7 4.8 6.8-2.6 12.2-9 13.4-16.2.5-4.6.7-9-1.5-13.1",fill:{type:"color",name:"glasses"},"fill-rule":"evenodd","clip-rule":"evenodd"}}],tags:["eyewear:glasses"]},variant04:{elements:[{name:"path",type:"element",attributes:{d:"M282.5.8a79.9 79.9 0 0 1 39 141 80 80 0 0 1-92.5 6.4 80 80 0 0 1-38.2-69.3c-5-5.3-10.7-9.6-18.3-9.7-7.8 0-14.3 5.7-17.3 12.6.8 6.7 1.6 13.3.7 20A69.8 69.8 0 0 1 20 117.1a70 70 0 0 1 21-75.7 71 71 0 0 1 46.4-16.9c12 .5 24 3.7 34.3 9.9A70 70 0 0 1 152.5 72c4.9-5.7 11.3-10 19-10 7.4-.3 14.2 2.6 19.7 7.3a89 89 0 0 1 8-25A80 80 0 0 1 282.4.8M257 8.6a72.4 72.4 0 0 1 85.9 80 72.7 72.7 0 1 1-86-80m-147.4 28a62.6 62.6 0 1 0-37.8 118.9c15.4 3.4 32 1.3 45.7-6.7a63 63 0 0 0 30.2-41.9 63 63 0 0 0-38-70.4",fill:{type:"color",name:"glasses"},"fill-rule":"evenodd","clip-rule":"evenodd"}}],tags:["eyewear:glasses"]},variant05:{elements:[{name:"path",type:"element",attributes:{d:"M294.5 30.7c12.7.7 25.7 1.8 37.4 7.6q1.7.8 3.3 1.9 2 1.4 4.3 2.3 3.4.4 7 .5 4 0 8 .7c2.1.8 2.2 2.8 2.4 4.8v1c0 2.2 0 4.2-2.4 5.4q-3.3.3-6.7.2h-3.1a92 92 0 0 1-11.5 52.3 82 82 0 0 1-43.9 37.2 79 79 0 0 1-77.4-14.3 89 89 0 0 1-30.7-53.4q-.8-5-2.3-9.6c-2-5.5-10.5-8.8-14.5-3.7-3.3 3.7-3.2 8-3.2 12.6v3.5a77 77 0 0 1-41.3 65.4 65 65 0 0 1-46.2 5.3A62 62 0 0 1 43 131.2 71 71 0 0 1 26.2 86l-1.5-.2c-1.4-.2-2.7-.3-3.4-2v-.4c-.4-2.2-.9-5.5 1.4-6.5q1.5-.8 3-1.3c2.2-1 4.4-1.8 6.2-3.5a89 89 0 0 1 37.6-17.4 152 152 0 0 1 69-.8c5.8 1.3 12 1.5 17.7-.5a50 50 0 0 1 22.3-2.5c5.8.5 11.9.3 17.4-1.9 12.1-4.6 24-9.1 36.6-12.3q30.5-7.8 62-6m-25 13c17.6-1 36-.8 53.3 3.7A19 19 0 0 1 337 62.9c1.3 7.9.3 15.5-1.3 23.3a81 81 0 0 1-24.7 39 73 73 0 0 1-81.6 9.6 80 80 0 0 1-33.2-32.9 61 61 0 0 1-6.4-35.5A98 98 0 0 1 210 56.1a215 215 0 0 1 59.5-12.4M134.7 63.5q-17.1-3.2-34.7-2a167 167 0 0 0-46.4 9.3 60 60 0 0 0-15 8c-4.1 2.9-5.5 9.2-5.7 13.9.3 8.9 3.6 17.8 8 25.5a56.4 56.4 0 0 0 66.7 25.6 68 68 0 0 0 46.6-62.1 47 47 0 0 0-1.5-10c-.2-1.7-1.7-2.5-3-3.3q-.4 0-.6-.3a58 58 0 0 0-14.4-4.6",fill:{type:"color",name:"glasses"},"fill-rule":"evenodd","clip-rule":"evenodd"}}],tags:["eyewear:glasses"]}}},mouth:{width:206.2,height:137.7,variants:{variant01:{elements:[{name:"path",type:"element",attributes:{d:"M186.5 29c2.4 1 1.9 3.5 1.4 5.5a92 92 0 0 1-28.4 34 97 97 0 0 1-60 17.5c-26.8-1-53-12-73.5-29.3-.4-2.4-.4-3.7 1.5-5.4 51.8-7.1 106.8-15 159-22.2",fill:{type:"color",name:"ink"}}},{name:"path",type:"element",attributes:{d:"M180.4 36c-8.2 15-21 27.4-36.4 34.9a89 89 0 0 1-40.5 9.2c-24.7.2-49-9-68.6-23.9 48-6.6 97.7-13.8 145.5-20.3",fill:{type:"color",name:"throat"}}}],tags:["mood:positive"]},variant02:{elements:[{name:"path",type:"element",attributes:{d:"m131.5 24 1.2 2.4c.4 2.7-2 3.4-3.9 4.4l-12 5a184 184 0 0 1-73.8 12c-4.9-.6-10.1-.7-14.8-2-2.4-1-2.7-4-.4-5.2 2.7 0 5.5.9 8.2 1 7.2 1 14.3.7 21.5.7a189 189 0 0 0 65.7-15.5c2.8-1.2 5.2-2.6 8.3-2.7",fill:{type:"color",name:"ink"}}}],tags:["mood:positive"]},variant03:{elements:[{name:"path",type:"element",attributes:{d:"M83.5 89.3a37 37 0 0 1 27.4 11.6 53 53 0 0 1 11 18c.4 3.5 2.2 6.4-1.4 8.8-8.4.2-16.7.8-25 1-12.3 1-24.7.5-37 2-1.9-2-2.3-3.8-2.5-6.4-1-8.6 1.2-17.9 6.7-24.7a28 28 0 0 1 20.8-10.3",fill:{type:"color",name:"ink"}}},{name:"path",type:"element",attributes:{d:"M91 95.9c12.6 3 22 14 25.5 26.2-18.3.4-36.6 1.7-54.8 2.2a28 28 0 0 1 7.6-23.1c5.8-5.7 14-7 21.7-5.3",fill:{type:"color",name:"throat"}}}],tags:["mood:negative"]},variant04:{elements:[{name:"path",type:"element",attributes:{d:"M135.6 105c2.5.2 4.7 1.4 4 4.2-1.5 2-4.5 1.3-6.7 1.5A155 155 0 0 0 89 119a74 74 0 0 0-14 6.2c-2 1-3.3 2.6-5.6 1.5-2.2-1.6-1.2-3.5 0-5.2q12.9-7.3 27.1-11a144 144 0 0 1 39-5.5",fill:{type:"color",name:"ink"}}}],tags:["mood:negative"]},variant05:{elements:[{name:"path",type:"element",attributes:{d:"M132.5 20c18 0 37.2 2.1 54 9-52.2 7.3-107.2 15.2-159 22.3 8-7 17.7-12.3 27.4-16.5a79 79 0 0 1 39.6-7.4q1.5.2 2.7-.4c10.2-5.9 23.7-6.7 35.3-7",fill:{type:"color",name:"lips"}}},{name:"path",type:"element",attributes:{d:"M186.5 29c2.4 1 1.9 3.5 1.4 5.5a92 92 0 0 1-28.4 34 97 97 0 0 1-60 17.5c-26.8-1-53-12-73.5-29.3-.4-2.4-.4-3.7 1.5-5.4 51.8-7.1 106.8-15 159-22.2",fill:{type:"color",name:"ink"}}},{name:"path",type:"element",attributes:{d:"M187.9 34.5c-1.2 4.7-1.9 9.2-3.7 13.7a72 72 0 0 1-28.4 33.5 103 103 0 0 1-45.3 16 96 96 0 0 1-58-11.3A61 61 0 0 1 26 56.7 122 122 0 0 0 99.5 86a92 92 0 0 0 88.4-51.5",fill:{type:"color",name:"lips"}}},{name:"path",type:"element",attributes:{d:"M180.4 36c-8.2 15-21 27.4-36.4 34.9a89 89 0 0 1-40.5 9.2c-24.7.2-49-9-68.6-23.9 48-6.6 97.7-13.8 145.5-20.3",fill:{type:"color",name:"teeth"}}}],tags:["mood:positive"]},variant06:{elements:[{name:"path",type:"element",attributes:{d:"M79.5 18.2a84 84 0 0 1 43.7 8.6 188 188 0 0 1-65.7 15.5c-7.2 0-14.3.2-21.5-.6a17 17 0 0 1 7.7-13 68 68 0 0 1 35.8-10.5",fill:{type:"color",name:"lips"}}},{name:"path",type:"element",attributes:{d:"m131.5 24 1.2 2.4c.4 2.7-2 3.4-3.9 4.4l-12 5a184 184 0 0 1-73.8 12c-4.9-.6-10.1-.7-14.8-2-2.4-1-2.7-4-.4-5.2 2.7 0 5.5.9 8.2 1 7.2 1 14.3.7 21.5.7a189 189 0 0 0 65.7-15.5c2.8-1.2 5.2-2.6 8.3-2.7",fill:{type:"color",name:"ink"}}},{name:"path",type:"element",attributes:{d:"M116.7 35.8c-2 10.1-10.3 17.2-19.2 21.6a56 56 0 0 1-34 4.7c-8.7-1.7-16.5-6-20.5-14.4q9.7.8 19.5 0a184 184 0 0 0 54.2-12",fill:{type:"color",name:"lips"}}}],tags:["mood:positive"]},variant07:{elements:[{name:"path",type:"element",attributes:{d:"M91.3 81.7a44 44 0 0 1 30.5 37.3 50 50 0 0 0-10.9-18 37 37 0 0 0-27.4-11.7 28 28 0 0 0-20.8 10.3c-5.5 6.8-7.7 16-6.7 24.7-.7-4.7-1.9-9.1-1.8-13.9a31 31 0 0 1 10-23.3 29 29 0 0 1 27-5.4",fill:{type:"color",name:"lips"}}},{name:"path",type:"element",attributes:{d:"M83.5 89.3a37 37 0 0 1 27.4 11.6 53 53 0 0 1 11 18c.4 3.5 2.2 6.4-1.4 8.8-8.4.2-16.7.8-25 1-12.3 1-24.7.5-37 2-1.9-2-2.3-3.8-2.5-6.4-1-8.6 1.2-17.9 6.7-24.7a28 28 0 0 1 20.8-10.3",fill:{type:"color",name:"ink"}}},{name:"path",type:"element",attributes:{d:"M91 95.9c12.6 3 22 14 25.5 26.2-18.3.4-36.6 1.7-54.8 2.2a28 28 0 0 1 7.6-23.1c5.8-5.7 14-7 21.7-5.3",fill:{type:"color",name:"teeth"}}},{name:"path",type:"element",attributes:{d:"M120.4 127.7c-9.3 7.3-23.5 8.7-35 9.1-8.5 0-19.8-.6-26.8-6.1 12.2-1.5 24.6-1 36.9-2 8.3-.2 16.6-.8 25-1",fill:{type:"color",name:"lips"}}}],tags:["mood:negative"]},variant08:{elements:[{name:"path",type:"element",attributes:{d:"M111.5 93.6c9 .5 16.9 6.7 24.1 11.4a144 144 0 0 0-66 16.5c3.2-8.1 7.8-18.1 16.6-21.4 4-2 7.7-1.2 11.9-.9 4-3.3 8-6 13.4-5.6",fill:{type:"color",name:"lips"}}},{name:"path",type:"element",attributes:{d:"M135.6 105c2.5.2 4.7 1.4 4 4.2-1.5 2-4.5 1.3-6.7 1.5A155 155 0 0 0 89 119a74 74 0 0 0-14 6.2c-2 1-3.3 2.6-5.6 1.5-2.2-1.6-1.2-3.5 0-5.2q12.9-7.3 27.1-11a144 144 0 0 1 39-5.5",fill:{type:"color",name:"ink"}}},{name:"path",type:"element",attributes:{d:"M132.9 110.7a40 40 0 0 1-24.5 18.5 47 47 0 0 1-33.2-4q6.5-3.8 13.9-6.2a155 155 0 0 1 43.8-8.3",fill:{type:"color",name:"lips"}}}],tags:["mood:negative"]},variant09:{elements:[{name:"path",type:"element",attributes:{d:"M102.5 36.7q4.5-.2 9.2.3l1.2 2.4-1.2 2.5c-7.7.8-15.5 0-23.2.6l-84 .6c-1.7 0-4.6-.6-4.4-2.7-.6-1.7 1.8-3.3 3.3-3.2z",fill:{type:"color",name:"ink"}}}]},variant10:{elements:[{name:"path",type:"element",attributes:{d:"M110.5 29.1c3.7-1.3 5.5 4 2.2 5.5-5.7 2.8-10.8 6.6-13 12.8-2.3 6.4.5 13.1 4.8 18 3 3.4 6.6 5.4 10.3 7.7 2 1 1.4 2.8 1.2 4.6l-2.5 1a37 37 0 0 1-15.9-12.4C95.3 63 94.3 59.6 93 56c-25 2-50.3 2.8-75.4 4.7-1.8-.3-2.4-2-3.5-3.3 1.1-1.2 1.7-2.7 3.5-2.8l52-3c7.8-.7 15.7-.5 23.4-1.5a28 28 0 0 1 17.6-21",fill:{type:"color",name:"ink"}}}]},variant11:{elements:[{name:"path",type:"element",attributes:{d:"m3.7 34.9 55.8-.4c15.6-.5 31.3-.2 47-.4 3.8 0 7.3-.2 10.9 1.4 4.2 1.9 7.8 6 7.6 10.9.4 6.4-5.6 11-11.5 11.3l-99 .6c-4.4-.1-8.1 1-12.4-.5l-.8-2.3c1.7-5.7 2.5-11.2-.1-16.7-1-2 .2-3.9 2.5-3.9",fill:{type:"color",name:"ink"}}},{name:"path",type:"element",attributes:{d:"M117 42c2.1 1.8 3.2 4.8 1.3 7.3-2.4 3.3-7.5 2.6-11.1 2.5l-.1-12c3.3.3 7.2-.2 9.9 2.2M8.2 40.6h5q.3 6 .2 12H8.3q.6-6-.1-12m10.8 0h13.6l.2 12H19.6zm19.6-.3 19-.1v12l-18.9.3zm24.7-.1q9.4 0 18.7-.2l.3 12-18.6.3q-.4-6-.4-12.1m24.6-.3q6.8.2 13.4 0v12H88.1z",fill:{type:"color",name:"teeth"}}}]},variant12:{elements:[{name:"path",type:"element",attributes:{d:"M156.5 34c1.5 0 3.5-.4 4.6.8 1.8 1.5.8 4.5-1.6 4.7-5.3.8-10.7.6-16 1.3l-14.6 2q4.5 9.7 6 20.4c1.2 9.5.6 18.9-4.4 27.2a28 28 0 0 1-19 13.2 47 47 0 0 1-27-4.2A88 88 0 0 1 51.9 72a118 118 0 0 0-18.5 16.2c-1.6 1.6-3.5 4-5.7 1.9-1.9-1.7-.3-4 1-5.5a129 129 0 0 1 34.7-26.5 225 225 0 0 1 93-24.3",fill:{type:"color",name:"ink"}}},{name:"path",type:"element",attributes:{d:"m123.3 43.8 4 11.6q3 10.6 1.8 21.5a25 25 0 0 1-11.1 18c-7.4 4.5-16.6 4-24.7 1.5A76 76 0 0 1 57 69q13.8-8.7 29.3-14.6c1.7 2.4 3.2 5.1 5.4 7.1 1.4 1.5 4.4.1 4-2C95.4 57 93 55 92 52.8q-.2-.6.7-.9 15.1-5.1 30.7-8.1",fill:{type:"color",name:"tongue"}}}],tags:["mood:negative"]},variant13:{elements:[{name:"path",type:"element",attributes:{d:"M125.5 33.1c12.3.2 24.4 2 36 6.5a93 93 0 0 1 43.8 35c1.1 1.5.8 3.5 1 5.4-7.3.5-14.5 0-21.7.7.1 7.4 0 14.4-3.8 21-2.2 3.8-5.7 7.2-10.3 7.2-4.5 0-8.2-3.5-10.4-7.1a44 44 0 0 1-4.5-21q-38 0-76.1.4c-7.4-.3-14.7.6-22 .4-7.5-.2-14.2.8-21.5-.8 0-1.6-.5-4 .6-5.3A123 123 0 0 1 125.5 33",fill:{type:"color",name:"ink"}}},{name:"path",type:"element",attributes:{d:"M115.5 39.9q10.5-.8 21 0a89 89 0 0 1 48.7 20.8q-17 .6-33.7.6c-31 1.1-62 .8-93 1.8 6.2-4.2 12.2-8.4 18.9-11.7q18-9.1 38-11.5",fill:{type:"color",name:"throat"}}},{name:"path",type:"element",attributes:{d:"M175.5 66.8c5.2 0 10.6-.6 15.7 0 2.3 2 4.2 4.8 6.3 7.1-5.9.6-11.9 0-17.7.8-1.2 7.1-.3 16.6-3.6 23.4-1.2 2.7-3.3 4-5.7 5.6-2.3-1.6-4.5-3-5.7-5.6-3.4-6.8-3.4-15.7-4.1-23.2-5.7-.5-11.4 0-17.2-.1l-98.4.5c2.1-2 4.6-5.6 7.5-6.2 18-.8 36-.3 53.9-1.1 11-.5 22-.1 33-.6 12-.3 24-.1 36-.6",fill:"#6fa942"}}],tags:["mood:negative"]},variant14:{elements:[{name:"path",type:"element",attributes:{d:"M101.7 21.4c15.5 1.8 31.3 5.5 44.5 14.2 7 4.6 13.5 11.3 15.3 19.8 2.4 8.6-3.6 18.2-11.7 21.4-7.2 3-14 1.8-21.3.1q-9-1.5-18-1.8-34-1.6-67.2 5.7c-5.7 1-11.1 3.3-16.8 3.8-6.5.1-13-3.1-16.8-8.5-3-4.1-4.4-9.6-4.3-14.7.6-7.8 5.4-15 11.2-19.9A85 85 0 0 1 52 24.7a157 157 0 0 1 49.7-3.3",fill:{type:"color",name:"ink"}}},{name:"path",type:"element",attributes:{d:"M112.5 29a76 76 0 0 1-35.8 13 92 92 0 0 1-41.5-5c8.8-4.8 19.4-7 29.2-8.8 16.1-2.2 32.1-2.4 48 .8",fill:{type:"color",name:"teeth"}}},{name:"path",type:"element",attributes:{d:"M120.3 30.7c11 3.2 22.5 7.7 30.4 16.5 4.2 4.8 7 11.2 4 17.4s-9.7 8.6-16.2 8a234 234 0 0 0-69-2 240 240 0 0 0-36 6.8c-5.7 1.3-11.3 2.1-16.2-1.8-6.6-5.3-7.4-14.6-3.5-21.8a40 40 0 0 1 14.7-13.6c4 2.5 8.4 3.7 13 5a95 95 0 0 0 67-6.8c4.3-2 7.8-5.1 11.8-7.7",fill:{type:"color",name:"throat"}}}],tags:["mood:negative"]},variant15:{elements:[{name:"path",type:"element",attributes:{d:"M76.5 0c9.4-.6 18.3 5.2 25.2 11.2a121 121 0 0 1 23.5 31.5 211 211 0 0 1 23.6 76.7c.4 4.4 1.5 8.7-2.5 11.8a80 80 0 0 1-23.8 6 144 144 0 0 1-48-4.8c-2.4-.7-4.5-.9-5.4-3.6A210 210 0 0 1 51 63a121 121 0 0 1 1.8-37 44 44 0 0 1 8.7-18.4c3.8-4.4 9.2-7.6 15-7.6",fill:{type:"color",name:"ink"}}},{name:"path",type:"element",attributes:{d:"M81 6a48 48 0 0 1 23.3 16.3 74 74 0 0 1-45.8 5.8c1.2-6.2 3.7-13 8.2-17.5 3.6-3.8 9-6 14.3-4.6",fill:{type:"color",name:"teeth"}}},{name:"path",type:"element",attributes:{d:"M108.3 27.3A179 179 0 0 1 135.8 84c-6.3 1.3-12 4-17.5 7a94 94 0 0 0-30 27c-2.3 3.6-4.7 6.5-4.6 11q-4.5-1.2-9-2c-8.4-18-14-37.2-16.9-56.7a124 124 0 0 1-.3-37c5.4 1 10.4 2.3 16 2q7.5-.6 15-2c6.9-1.2 13.2-3.9 19.8-6.1",fill:{type:"color",name:"throat"}}},{name:"path",type:"element",attributes:{d:"M134 90c1.5-.6 2.4.2 3.8.7 2.7 11.7 5 23.5 5.6 35.5a90 90 0 0 1-24.6 5.6c-10.5 1-20.3-.7-30.6-1.8a75 75 0 0 1 17.9-23 82 82 0 0 1 28-17",fill:{type:"color",name:"tongue"}}}],tags:["mood:negative"]},variant16:{elements:[{name:"path",type:"element",attributes:{d:"M127.7 27.7c1.5-.4 3.3-1 4.9-.8 2 .8 2 3 1 4.7-4 2.6-10 2.8-14.2 4.8a79 79 0 0 1 0 41 55 55 0 0 1-20.7 31.3c-7 5-15.6 7.4-24.2 6.5A42 42 0 0 1 45.9 98a72 72 0 0 1-11.3-60.2c-2.4-.8-5.6-1.2-7.5-2.9-.6-1.2-.2-2.8-.3-4.1 4.5 0 8.3 1.6 12.7 2.5 29.5 6 59.5 3 88.2-5.5",fill:{type:"color",name:"ink"}}},{name:"path",type:"element",attributes:{d:"M113.4 37.5a68 68 0 0 1-6.7 54.2c-4 6.5-9.6 12-16.7 15.1a29 29 0 0 1-25.4-.5c-8-4-14.6-11.4-18.7-19.3a70 70 0 0 1-5.5-48c10.5 2.4 21 3 31.8 3.2-1 6.8-1 13.4-1.2 20.2 0 2-.2 4 .5 6 1 1.6 4.6 1.1 4.7-1.1.6-8.5-.1-16.8 1.5-25.2 12-.2 24-2.2 35.7-4.6",fill:{type:"color",name:"tongue"}}}],tags:["mood:positive"]},variant17:{elements:[{name:"path",type:"element",attributes:{d:"M68.7 13.2c6 1.3 12 4.5 15.7 9.3 1.3 2.3 0 5-2.8 4.7-2.2-1.3-4-3.4-6-4.8a22 22 0 0 0-15.1-3.7c-2.6.4-5.4 1.6-6.9 3.9-1.5 2-1.2 4.7-.3 7 1.7 4.5 6 7.9 10.2 9.7 2.3 1.1 5.2 1.3 7.3 2.8 1.7 1.8.6 4.3-1.7 4.8-4.7 1-8.7 2.6-11.7 6.5A17 17 0 0 0 58.8 76 18.3 18.3 0 0 0 83 78c2.5-1.9 3.6-4.4 5.6-6.6 3-1.4 5 1 4 3.9a23 23 0 0 1-27.2 11.4 24 24 0 0 1-17.2-19.3A23 23 0 0 1 59.5 44 23 23 0 0 1 47 29.7c-1.5-5.3.8-11.3 5.5-14.2 4.6-3.3 10.7-3.2 16.1-2.3",fill:{type:"color",name:"ink"}}}],tags:["mood:positive"]},variant18:{elements:[{name:"path",type:"element",attributes:{d:"M59.7 27.8q6.3-1 12.1 1.3a26 26 0 0 1 14.5 18.3c3.2 12.1-1.3 26-11.7 33.2-3 2.5-6.7 3.5-10.4 2.2-3.6-1.8-5.3-5.3-6.2-9-1.5-5.2 1.2-10.5.1-16-1-4.3-4.7-7.5-6.5-11.5-1.3-2.7-2.5-6-2.1-9 .7-5 5.4-8.8 10.2-9.5",fill:{type:"color",name:"ink"}}}]},variant19:{elements:[{name:"path",type:"element",attributes:{d:"M123 16c6 4.4 11.7 10 15.3 16.6 2.6 4.9 3.2 11.7-.5 16.2-4.1 5.3-11.4 7.5-17.8 8.7A151 151 0 0 1 72.5 56c-5.7-1.1-10.2 1.6-16 2.6a70 70 0 0 1-27 1c-5.2-1-10.3-3.2-13.4-7.7-2.8-3.9-2.6-9.3-1.1-13.7Q17.5 32 22 27c1.4-1.7 3.1-1 5-1.1.3 1.8 1 3.2-.4 4.8-2.6 3.3-5.2 6.4-6.4 10.6a8 8 0 0 0 2.4 9c3 2.5 7.1 3.6 11 4a76 76 0 0 0 23-1.8c5.7-1 10-3.5 15.9-2.5 12 2 23.8 3.5 36 2.8 7-.2 14-1 20.3-4 3.2-1.9 6-4.2 5.6-8.3-.2-6-6-11.8-10.2-15.7-2.5-2.7-6.7-4-6-8.4 1.8-.8 3-1.8 4.8-.3",fill:{type:"color",name:"ink"}}}],tags:["mood:positive"]},variant20:{elements:[{name:"path",type:"element",attributes:{d:"M111.5 70c4.7 1.3 9 4.7 12.2 8.2 1.4 1.7 3.6 3.9 3 6.2-.4 2.5-3.7 3-5 .8a28 28 0 0 0-9.5-8.5c-2.2-1.5-6.7-.6-6.6-4.2.5-3 3.6-2.9 6-2.5m-7.1 13.4c5 1.5 8.4 5.8 8.8 11 1.3 13.2-9.4 25.8-21.8 29.2-12.4 3.7-28.9-1-35-13.2-2.5-4.2-3.8-9.2-2-14 1.8-4 5.8-5.6 10-6 5-.6 9.5 1 13.9 3.5 3.8-4 7.7-7.6 12.9-9.8 4-1.7 9-2 13.2-.7",fill:{type:"color",name:"ink"}}},{name:"path",type:"element",attributes:{d:"M105.4 90.5c3.2 3.4 2.3 9.5.5 13.4a25.5 25.5 0 0 1-26 15c-7.2-1.2-14.2-4.1-18.1-10.8-1.5-2.5-3.5-6.6-2-9.4 2.2-3.8 8.7-3.2 12.2-1.8 2.8.7 5.6 4 8.4 3.6 3.7-3.6 6.5-7.5 11.2-10 4.3-2.3 9.6-3.2 13.8 0",fill:{type:"color",name:"throat"}}}],tags:["mood:positive"]},variant21:{elements:[{name:"path",type:"element",attributes:{d:"M87.4 22c4.8-.5 10.3.1 13.8 3.7 3.7 4 4.1 9.5 3.2 14.6a31 31 0 0 1-24.9 23.3 33 33 0 0 1-22.1-4.1 26 26 0 0 1-11-13 15 15 0 0 1-.5-10.6c1.3-3.2 4.1-5 7.3-5.7 5.7-1.9 11.7.2 16.7 3 4.5-5 10.5-10.2 17.5-11.1",fill:{type:"color",name:"ink"}}},{name:"path",type:"element",attributes:{d:"M87 28.1c3.3-1 7.4-.6 10 1.8 2 2 2.1 5.9 1.7 8.5a25 25 0 0 1-20 19.4 27 27 0 0 1-19-3.8c-4.3-2.5-7.4-7-8.8-11.7-.7-2.5-.4-5.1 2-6.4 2.6-1.1 5.8-1 8.5-.5 3.5.7 5.8 2.9 9 4.3 2 0 2.6-1.4 3.8-2.6 3.3-4 7.7-7.6 12.7-9.1",fill:{type:"color",name:"throat"}}}],tags:["mood:positive"]},variant22:{elements:[{name:"path",type:"element",attributes:{d:"M121.5 32.2a57 57 0 0 1 29.5 3.7c4.7 2.3 8.7 6 9.7 11.4a19 19 0 0 1-4 14.2A61 61 0 0 1 136 78c-16.5 8.7-34 12-52.5 13.7a90 90 0 0 1-59.1-12.1 42 42 0 0 1-16-16c-2.6-5.3-2.3-12 1.9-16.4C15 42 22.7 40 29.5 39.3a93 93 0 0 1 44.8 8.5 118 118 0 0 1 47.2-15.6",fill:{type:"color",name:"ink"}}},{name:"path",type:"element",attributes:{d:"M146.9 40.4a85 85 0 0 1-12.1 8.3c-2.7 1.5-3.8 4.1-5.5 6.6a30 30 0 0 1-5.7 6.7c-3-1-6-2.8-9.1-3.5-3 .5-6 1.9-8.9 2.7-10 2.8-20.7 5-31.1 4.9q-4.4 0-8.7.8c.3 2.5-.5 4.7 2.8 5 14.7.9 29.8-2 43.7-6.7 4.7-2 7.7 3.1 12.8 1.8 4.4-1.3 7.4-6.6 10-10 1.7-2.9 4.4-4.2 7-6q5.4-3.4 10.4-7.4c1.5 2.6 3.2 4.7 2.5 7.8-1.4 6.4-6.6 11-11.5 15A107 107 0 0 1 99.2 84c-14.5 2-28 4.2-42.6 1.5a79 79 0 0 1-36.1-16.1c-3.8-3.4-8.4-8.5-7.8-14 .3-3.8 3.9-6.3 7-7.7A51 51 0 0 1 45 45.5a89 89 0 0 1 25.4 7.2c1.5.6 3.4 1.7 5 1.5 3.2-1.2 5.8-3.5 8.8-5a102 102 0 0 1 28.2-9.8c11.5-2 23.4-2.9 34.6 1",fill:{type:"color",name:"teeth"}}}],tags:["mood:positive"]},variant23:{elements:[{name:"path",type:"element",attributes:{d:"M141.5 23.3a31 31 0 0 1 22.7 17.4 48 48 0 0 1 3.5 23.7 53 53 0 0 1-15 30.3 66 66 0 0 1-33.2 18.8 141 141 0 0 1-62 .3A85 85 0 0 1 18.9 94c-4.5-4.2-9-9.1-11-15a30 30 0 0 1 1.5-23.6c3.4-6.3 10-10.5 17-10.7 12.8-.7 24 4.2 36 4.7 7.9.2 16-1 23.3-3.9C97 40.7 106.9 31 118.5 26.4c7.4-3 15-4.6 23-3",fill:{type:"color",name:"ink"}}},{name:"path",type:"element",attributes:{d:"M144.5 30.3c7 2.5 12.7 7.9 15.1 15q-4.3 3.8-9 7.3c-3.6 2.6-7.2 4.4-10 8-3.1 4-5.9 9.9-10.3 12.5-3.4-.4-6.7-2.9-9.8-4-2.5-.7-5.4.4-7.8 1A167 167 0 0 1 75.5 76a46 46 0 0 0-9.6 1q0 1.8.3 3.6c1.9 1.5 5 1.3 7.3 1.5q23-1 45-7.3c3.7 0 9.3 5.2 13.9 3.5 5.3-2.5 9-9 12.3-13.6 2-2.8 4.6-4 7.2-5.9q5-3.4 9.6-7.3a46 46 0 0 1-.4 17 53 53 0 0 1-15 24.5 67 67 0 0 1-37.1 16.6 141 141 0 0 1-36.5.8 87 87 0 0 1-48.4-19.6c-5-4.7-9.8-8.9-11.2-16-2.3-8.6.4-20.7 10.1-23.5 8.2-2 17.8.5 26 2.2 12 2.8 25 2.4 36.7-1.7 14-4.9 25-17 38.8-21.3a30 30 0 0 1 20-.2",fill:{type:"color",name:"teeth"}}}],tags:["mood:positive"]},variant24:{elements:[{name:"path",type:"element",attributes:{d:"M140.8 23a38 38 0 0 1 21.2 9.9 39 39 0 0 1 12 29.5c.3 9.8-2.4 19.1-6.7 27.8a83 83 0 0 1-70.7 45.3 107 107 0 0 1-82.1-34A46 46 0 0 1 2.9 72.4a25 25 0 0 1 10.5-20.2 42 42 0 0 1 23-6.7 86 86 0 0 1 40.3 11 80 80 0 0 1 34-28.9c9.4-4.2 19.8-6 30-4.6",fill:{type:"color",name:"ink"}}},{name:"path",type:"element",attributes:{d:"M140 28.7A32 32 0 0 1 162.9 43c6 9.6 6.6 21 3.8 31.8q-6-.8-12-.2c-10.8.6-21.7 3.4-32 7a43 43 0 0 0-.5-23.9c-1.7-3.8-5.4-6.2-9.6-4.3-6.6 3.1-10.3 11.9-13 18.2-4.8-1.6-11.3-3.8-16-1.2-4 2.2-3.9 6.5-2.5 10.3 2.6 6.2 7.7 11 12.6 15.4a114 114 0 0 0-31.1 29c-15-4.7-28.7-13-40-23.7A46 46 0 0 1 8.9 77c-1-6.4.7-13.2 5.4-17.8 4.4-4.6 11-6.7 17.2-7.5a69 69 0 0 1 35.2 6.5c3.8 1.5 7 3.8 10.8 5.4 2.7.3 3.7-3.4 5-5.1A70 70 0 0 1 121.3 30c6-1.8 12.6-1.9 18.8-1.4",fill:{type:"color",name:"throat"}}},{name:"path",type:"element",attributes:{d:"M115.5 58.3c2.6 2.3 2.7 6.8 2.8 10 0 11-3.1 22-8 31.7-4-2-7.9-4.1-11.3-7.2a54 54 0 0 1-12-13c-.8-1.4-.8-3-1-4.6 5-.7 9.1 1 13.7 2.9 2.8 1 3.9-1.4 5-3.5 2.4-5.5 5.1-13.3 10.8-16.3",fill:{type:"color",name:"uvula"}}},{name:"path",type:"element",attributes:{d:"M165.1 80.3a71 71 0 0 1-11 19.7c-3.8 4.8-8.6 8.9-13 13a77 77 0 0 1-35.1 15.6q-19 2.8-37.5-1.6c8-11.1 18.6-19.9 30.3-27.1 3.7 2.3 7.5 5.1 11.7 6.6 1.4.7 2.8-.4 3.6-1.5 3.1-4.9 4.8-10 6.8-15.4.3-1.4 1.6-1.6 2.8-2.1 13-4.7 27.5-8.1 41.4-7.2",fill:{type:"color",name:"tongue"}}}],tags:["mood:positive"]},variant25:{elements:[{name:"path",type:"element",attributes:{d:"M129.3 23.4c11 1.4 21.9 7 27.2 17a31 31 0 0 1 3.3 21.2 54 54 0 0 1-14.5 27.6 77 77 0 0 1-44.8 23 93 93 0 0 1-42.9-3 77 77 0 0 1-23.8-13 62 62 0 0 1-19.5-25.6 33 33 0 0 1-1.8-17.2A21 21 0 0 1 25.3 38a37 37 0 0 1 21.2-1.8c9 1.2 16.7 5 24.7 9.1a72 72 0 0 1 58.1-22",fill:{type:"color",name:"ink"}}},{name:"path",type:"element",attributes:{d:"M124.5 29c8.8.3 17.4 3.2 23.7 9.6q-4.7 5.4-11 8.5c-1.7.9-3.7 1.7-5 3-2.5 3-3.7 8.2-6.7 10.5-3.6-1.2-6.8-3.9-10-5.8a175 175 0 0 1-44 4.5q-16.5.4-33-2.4c-1.8-.3-4-1-5.8-.4-2.2 1.5-4 3.6-5.8 5.4l-5.5-8.5-2.7-1.3c2.7-6 8.4-9.5 14.8-10.3a54 54 0 0 1 34 8.6c2 1 3.6 2.3 5.8.9 2.8-2.2 5.1-5 8-7.1 12-9.6 27.7-16 43.2-15.3",fill:{type:"color",name:"teeth"}}},{name:"path",type:"element",attributes:{d:"M151.8 43.7a29 29 0 0 1 2.2 17.7c-2 9.5-7 17.8-13.9 24.6a75 75 0 0 1-41.6 20.7 89 89 0 0 1-34-1.7A71 71 0 0 1 27 81a39 39 0 0 1-9.3-23c2.6 2.7 3.8 6.3 6.3 9 4.2 3.3 7.7-2.1 10.5-4.7a219 219 0 0 0 80.2-1.2c3.7 1.5 8.4 6 12.7 5 6-2.3 6-11.9 12.3-13.6a43 43 0 0 0 12.2-8.8",fill:{type:"color",name:"throat"}}}],tags:["mood:positive"]},variant26:{elements:[{name:"path",type:"element",attributes:{d:"M123.5 15.8a55 55 0 0 1 38.6 13c6 5.6 9.7 13.4 9.9 21.6A44 44 0 0 1 162 78a88 88 0 0 1-35.5 26.5c-7.3 2.9-14.4 5.8-22.1 7.3a86 86 0 0 1-50-5.3A131 131 0 0 1 16 81.8 55 55 0 0 1 3 62.9C.9 57.4.5 51 4 46c3.7-5.4 10-7.7 16.2-8.8 12.6-1.8 24.4.4 36.5 3.7a92 92 0 0 1 25-16.2c13-5.7 27.4-9.3 41.7-8.9",fill:{type:"color",name:"ink"}}},{name:"path",type:"element",attributes:{d:"M149 26.7c-3.5 2.7-7.4 4.8-10.9 7.4-4.3 4-7.6 11-12.7 14-5.2 1-10.5-3.2-15.2-1q-14 5.2-28.5 7.9a118 118 0 0 1-43.7.9c-4.2-1.1-7 1.3-11.4 1.8-4.4-4.2-7.5-9.2-12.7-12.5 12.7-5.4 28.7-2 41.6 1.5 4 1.2 6-2.5 8.8-4.5a97 97 0 0 1 47.2-19.9 68 68 0 0 1 37.5 4.4",fill:{type:"color",name:"teeth"}}},{name:"path",type:"element",attributes:{d:"M154.5 30.3a26 26 0 0 1 11.8 21.1c-.2 7.4-3 14-6.8 20.2a46 46 0 0 0-20-2.8 138 138 0 0 0-42 9.6c-9 3.7-18 8.3-25.7 14.3q-5.4 4.3-8.7 10.4a93 93 0 0 1-21.6-9.8A103 103 0 0 1 15 72c-3.7-4.7-7.5-10.4-7.7-16.5C7 53 8.2 51 9 48.8c5.4 3.7 9.3 8.7 14.2 12.9 4 3.4 9.2-.7 13.8 0q8.7 1.4 17.5 1.8Q85.3 63 114 52c4.2.8 10 2.7 14 1 5-2.8 8.6-8.6 12.2-12.9 1.5-1.7 3.8-3 5.7-4.2 2.9-1.7 5.5-4 8.5-5.6",fill:{type:"color",name:"throat"}}},{name:"path",type:"element",attributes:{d:"M142.5 74.6q6.8-.1 13.3 1.9a87 87 0 0 1-35.9 24.4 86 86 0 0 1-51.2 3.9q2.9-4.1 6.8-7.4a103 103 0 0 1 31-16c11.5-3.8 23.8-6.6 36-6.8",fill:{type:"color",name:"tongue"}}}],tags:["mood:positive"]},variant27:{elements:[{name:"path",type:"element",attributes:{d:"M130.7 16.3c.6 7-.9 13.3-1.6 20.1-2.7 24.2-9.4 48-19.1 70.2-3.7 7.4-6.8 15.8-14 20.4-3.8 2.8-9 2-13.2.1a44 44 0 0 1-12.4-8.6 171 171 0 0 1-30-42.1c-6.7-12.6-11.6-25.8-17-38.9-1-2.1-1.2-4.1 1-5.4 4.4-.1 8.7 1.4 13 1.4 10 .4 20 .5 29.9-.9 17.7-2 35-7.1 51.5-13.9 4.3-1.5 7.2-4.3 11.9-2.4",fill:{type:"color",name:"ink"}}},{name:"path",type:"element",attributes:{d:"M125.4 22.4a298 298 0 0 1-8.9 48A52 52 0 0 0 90.1 77a67 67 0 0 0-27.3 23.9 198 198 0 0 1-19.4-31.5c-5.4-10.1-9.3-20.7-14-31.2 9.5.8 18.6 2 28 1 23.3-.7 46.8-7.7 68-16.8",fill:{type:"color",name:"throat"}}},{name:"path",type:"element",attributes:{d:"M114.7 76.5A184 184 0 0 1 99 115a18 18 0 0 1-6.7 7.4c-4 1.7-9.1-1.2-12.4-3.5-5.4-3.4-8.6-8.3-12.9-12.7a36 36 0 0 1 10.4-13.7c7.8-6.7 17.1-12 27-15q5-1.3 10.2-1",fill:{type:"color",name:"tongue"}}}],tags:["mood:positive"]},variant28:{elements:[{name:"path",type:"element",attributes:{d:"M130.7 16.2c.5 6.9-.8 13.4-1.6 20.2-2.7 24.2-9.4 48-19.1 70.2-3.7 7.4-6.8 15.8-14 20.4-4.2 3-10.3 1.7-14.6-.6-9.5-4.6-15.1-12.2-21.7-20.2a199 199 0 0 1-26-44q-5.4-12.4-10.3-24.7c-1-2.1-1.2-4 1-5.4 4.7 0 9.3 1.5 14 1.5 9.4.2 18.8.4 28-.8 20-2.3 39.7-8.3 58-16.5 2.2-1 4-.6 6.3-.1",fill:{type:"color",name:"ink"}}},{name:"path",type:"element",attributes:{d:"M125.4 22.4c-2 15.1-4 30.2-8 45a209 209 0 0 1-19 49c-2.2 3.4-5.3 7.3-10 6.4-7.4-1.5-14-8-18.6-13.7a169 169 0 0 1-24.6-36.4c-6.2-11-10.7-22.9-15.7-34.5l14.4 1.2c1.1 6 4.6 11.5 8.4 16 5.1 6 12.3 9.9 20.2 10 6.2-.4 12-3 16.6-7.3 8-7.4 12-17 14.5-27.4a265 265 0 0 0 21.8-8.3",fill:{type:"color",name:"throat"}}},{name:"path",type:"element",attributes:{d:"M97.1 32.5c-2.5 8.8-7 18.4-15 23.6a18 18 0 0 1-18.5 1.1 34 34 0 0 1-14-17.6c16.2-.4 32.1-2.3 47.5-7",fill:{type:"color",name:"teeth"}}}],tags:["mood:positive"]},variant29:{elements:[{name:"path",type:"element",attributes:{d:"M124.4 18.2c1.5.3 2.8 1.6 2.7 3.2-7 16.8-15 33.2-25.1 48.4-4.7 7-9.2 14.2-14.5 20.7-2.2 3.2-8 2.9-10.8.7q-10.4-7.6-19.1-16.9c-9.2-10.4-18-20.1-24.7-32.4-.8-1.9-2.3-4-.8-5.8.6-1.3 3-1 3.6.1Q43.5 50 54.2 61.7A154 154 0 0 0 76.9 84q1.8 1.4 3.7 2c2.7.4 4-1.2 5.4-3.1 13.5-19 25.7-38.8 34.6-60.4.9-2 1.5-3.7 3.8-4.3",fill:{type:"color",name:"ink"}}}],tags:["mood:positive"]},variant30:{elements:[{name:"path",type:"element",attributes:{d:"M124.4 17.7c2.3.2 3.1 2.7 2.3 4.7L122 32.9c-8.4 19.3-19.5 37-31.8 54.2-1.4 1.8-2.9 4-4.8 5.2-3 .8-6.1.8-8.7-1.1a129 129 0 0 1-24.3-22.8Q41.7 57 33.6 43.2c-1-2-2.6-4.4-1.2-6.8 1-1.5 3.2-2 4.9-2.5 11-3.1 22.1-6.5 33.3-9.3a235 235 0 0 1 35.9-5.7c5.9-.6 12-1.4 17.9-1.2",fill:{type:"color",name:"ink"}}},{name:"path",type:"element",attributes:{d:"M120.3 23.4A317 317 0 0 1 86 82.9c-1 1.1-2.2 2.8-3.7 3-2.2.6-3.7-.8-5.4-1.9a155 155 0 0 1-22.7-22.3 137 137 0 0 1-16.6-22.3c15-4 29.9-8.6 45.1-11.4 12.5-2.5 25-3.3 37.6-4.6",fill:{type:"color",name:"throat"}}}],tags:["mood:positive"]}}}},colors:{background:{values:["#763900","#9e5622","#ecad80","#f2d3b1"]},eyes:{values:["#000000"]},glasses:{values:["#000000"]},ink:{values:["#000000"]},lips:{values:["#d31e1e"]},sclera:{values:["#ffffff"]},teeth:{values:["#ffffff"]},throat:{values:["#8f2e45"]},tongue:{values:["#ea869e"]},uvula:{values:["#d32020"]}}};var components=adventurer_neutral_default.components,placement=Object.fromEntries(adventurer_neutral_default.canvas.elements.map(element=>[element.name,element.attributes.transform])),INK2=Object.fromEntries(Object.entries(adventurer_neutral_default.colors).filter(([name])=>name!=="background").map(([name,color])=>[name,color.values[0]])),SKINS=adventurer_neutral_default.colors.background.values,EFFECTS=["confetti","hearts","stars","shine","snooze","storm"],hasTag=(variant,tag)=>variant.tags?.includes(tag)??!1,fillOf=element=>{let fill=element.attributes?.fill;return typeof fill=="object"?fill.name:null},tagged=(variants,tag)=>Object.keys(variants).filter(name=>hasTag(variants[name],tag));function drawEyes2(variant,colors,idPrefix){let clip=`${idPrefix}whites`,whites=[],pieces=[],onPupil=!1;for(let element of variant.elements){let fill=fillOf(element),moves=fill==="eyes"||onPupil&&fill==="sclera";fill==="sclera"&&!moves&&whites.push(element),pieces.push({element,moves}),onPupil=moves}let open2=whites.length>0&&pieces.some(piece=>piece.moves),markup=pieces.map(({element,moves})=>{let art=draw(element,colors,idPrefix);return open2&&moves?`<g clip-path="url(#${clip})"><g data-pupils="">${art}</g></g>`:art}).join(""),clipPath=`<clipPath id="${clip}">${whites.map(element=>draw(element,colors,idPrefix)).join("")}</clipPath>`;return{markup:open2?clipPath+markup:markup,open:open2}}function chooseEffect(t,eyesOpen,restingMouth,glasses2){let forced=t.forced("effect.forced");return forced!==void 0?EFFECTS[Math.floor(forced*EFFECTS.length)]:glasses2&&hasTag(glasses2,"eyewear:sunglasses")?"shine":eyesOpen?hasTag(restingMouth,"mood:negative")?"storm":t.pick("effect",["confetti","hearts","stars"]):"snooze"}function createFace(name,idPrefix,overrides){let t=calmed(createTraits(name,overrides),CALMING7),render=variant=>variant.elements.map(element=>draw(element,INK2,idPrefix)).join(""),eyes2=drawEyes2(components.eyes.variants[pickVariant(t,"eyes",components.eyes.variants)],INK2,idPrefix),eyebrows2=components.eyebrows.variants[pickVariant(t,"eyebrows",components.eyebrows.variants)],glasses2=t("glasses")*100<components.glasses.probability?components.glasses.variants[pickVariant(t,"glasses.variant",components.glasses.variants)]:null,mouthVariants=components.mouth.variants,restingMouth=pickVariant(t,"mouth",mouthVariants),happy=tagged(mouthVariants,"mood:positive"),unhappy=tagged(mouthVariants,"mood:negative"),effect=chooseEffect(t,eyes2.open,mouthVariants[restingMouth],glasses2),tapMouths=effect==="storm"?unhappy:happy;return{skin:t.color("skin")??t.pick("skin",SKINS),at:placement,eyes:eyes2.markup,eyebrows:render(eyebrows2),glasses:glasses2&&render(glasses2),mouths:{rest:render(mouthVariants[restingMouth]),hover:render(mouthVariants[pickVariant(t,"mouth.hover",mouthVariants,happy)]),tap:render(mouthVariants[pickVariant(t,"mouth.tap",mouthVariants,tapMouths)])},eyesOpen:eyes2.open,effect,blinkDelay:t.num("blink",0,4)}}function faceSvg(name,overrides){let face=createFace(name,"f-",overrides);return`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 400 400" fill="none"><rect width="400" height="400" rx="96" fill="${face.skin}"/><g transform="${face.at.eyes}">${face.eyes}</g><g transform="${face.at.eyebrows}">${face.eyebrows}</g><g transform="${face.at.mouth}">${face.mouths.rest}</g>`+(face.glasses?`<g transform="${face.at.glasses}">${face.glasses}</g>`:"")+"</svg>"}var{eyes,eyebrows,mouth:mouth2,glasses}=adventurer_neutral_default.components,numbered=label=>(_,i)=>`${label} ${i+1}`,controls7=(name,overrides)=>{let t=calmed(createTraits(name,overrides),CALMING7),list=control=>narrowed(control,t,CALMING7),effect=createFace(name,"",overrides).effect;return[{title:"Face",controls:[palette(t,"skin","Colour",SKINS),possibilitiesSlider(t,NOTES8),list(choice(t,"eyes","Eyes","list",fromVariants(eyes.variants,numbered("Eyes")))),list(choice(t,"eyebrows","Brows","list",fromVariants(eyebrows.variants,numbered("Brows")))),list(choice(t,"mouth","Mouth","list",fromVariants(mouth2.variants,numbered("Mouth"))))]},{title:"Accessories",controls:[optional(t,"glasses",glasses.probability,"glasses.variant","Glasses","list",fromVariants(glasses.variants,(variant,i)=>variant==="variant01"?"Shades":`Style ${i}`))]},{title:"Reactions",controls:[list(choice(t,"mouth.hover","On hover","list",fromVariants(mouth2.variants,numbered("Mouth")))),automatic(t,"effect.forced","Tap effect",EFFECTS.map(spaced),spaced(effect))]}]};var CALMING8={features:/^eye\.(size|gap|y)$|^mouth\.(size|y)$|^nose\.size$/,lists:{feeling:[10,8,[0,4,7,3,6,2,9,1,5,8]]},rarer:["spots","blush"]},NOTES9=["happy, sleepy and smug faces, the eyes and mouth in their usual places.","more feelings, bigger or smaller eyes and mouths.","every feeling, sad and angry too, at any size."];var r22=value=>Math.round(value*100)/100,COLOURS2=["#4fcfd6","#e2483d","#8fd94a","#f0b821","#7a6cf0","#ff8a3d","#e8569a","#4f8ff0","#3fbf8a","#c06bdb"],IRISES=["#1f5f6b","#5b3a1f","#2f6b2a","#3b2a6e","#7a2e22","#1d3f7a","#2a2a33","#6b4a12"],FEELINGS=[{name:"Happy",lid:.14,tilt:0,lift:2,browTilt:-6,pupil:1,look:[0,0],mouth:"smile"},{name:"Grumpy",lid:.44,tilt:14,lift:-1,browTilt:18,pupil:1,look:[0,.1],mouth:"flat"},{name:"Surprised",lid:0,tilt:0,lift:7,browTilt:-4,pupil:.72,look:[0,0],mouth:"o"},{name:"Sleepy",lid:.56,tilt:-4,lift:-2,browTilt:0,pupil:1,look:[0,.3],mouth:"smile"},{name:"Grin",lid:.06,tilt:0,lift:4,browTilt:-8,pupil:1,look:[.2,-.2],mouth:"grin"},{name:"Sad",lid:.24,tilt:-16,lift:1,browTilt:-18,pupil:1.05,look:[0,.35],mouth:"frown"},{name:"Smug",lid:.4,tilt:-10,lift:0,browTilt:-4,pupil:.95,look:[.4,0],mouth:"smirk"},{name:"Joy",lid:0,tilt:0,lift:5,browTilt:-8,pupil:1,look:[0,0],mouth:"laugh",closed:!0},{name:"Angry",lid:.34,tilt:24,lift:-2,browTilt:26,pupil:.85,look:[0,0],mouth:"grit"},{name:"Bored",lid:.52,tilt:0,lift:-1,browTilt:2,pupil:.9,look:[-.4,0],mouth:"flat"}],KINDS=[{name:"Monster",eyes:"white",r:13,y:33,gap:18,patch:1.28,brows:"arcs",feature:"nose",mouthY:73,mouthW:33,toothy:!0},{name:"Duck",eyes:"bead",r:9.5,y:39,gap:22,brows:"none",feature:"bill",mouthY:70,mouthW:26,toothy:!1},{name:"Cyclops",eyes:"white",single:!0,r:21,y:33,gap:0,patch:1.15,brows:"arcs",feature:"none",mouthY:75,mouthW:33,toothy:!0},{name:"Bear",eyes:"white",r:7.6,y:30,gap:13.5,brows:"pads",feature:"bear",mouthY:80,mouthW:15,toothy:!1},{name:"Imp",eyes:"bead",r:10.5,y:35,gap:19.5,patch:1.55,brows:"none",feature:"nose",mouthY:73,mouthW:34,toothy:!0},{name:"Chick",eyes:"white",r:13,y:38,gap:19,brows:"none",feature:"beak",mouthY:60,mouthW:10,toothy:!1},{name:"Grump",eyes:"white",r:10,y:30,gap:18,brows:"wedges",feature:"jaw",mouthY:72,mouthW:16,toothy:!1}],critterTraits=(name,overrides)=>calmed(createTraits(name,overrides),CALMING8);function named4(name){let variant=/^(.*)#(\d+)$/.exec(name);return{from:variant?variant[1]:name,step:variant?Number(variant[2])-1:0}}function kindOf(name,overrides){let{from,step}=named4(name),t=createTraits(from,overrides),own2=Math.min(KINDS.length-1,Math.floor(t("kind")*KINDS.length));return t.forced("kind")!==void 0?KINDS[own2]:KINDS[(own2+step)%KINDS.length]}var feelingOf=t=>t.pick("feeling",FEELINGS),EYE_STYLES=["white","bead"],BROWS=["arcs","pads","wedges","none"],PATCH=1.3,SPOTS_PERCENT=25,BLUSH_PERCENT=30;function styledOf(name,overrides){let t=critterTraits(name,overrides),kind=kindOf(name,overrides),picked=(key2,list)=>{let set=t.forced(key2);return set===void 0?void 0:list[Math.min(list.length-1,Math.floor(set*list.length))]},patch=t.forced("patch");return{...kind,eyes:picked("eye.style",EYE_STYLES)??kind.eyes,brows:picked("brows",BROWS)??kind.brows,patch:patch===void 0?kind.patch:patch<.5?kind.patch??PATCH:void 0}}function coloursOf6(t){let body=t.color("body")??t.pick("body",COLOURS2);return{body,lid:mix(body,BLACK,.1),shade:mix(body,BLACK,.16),dark:mix(body,"#120d1c",.78),light:mix(body,WHITE,.32),iris:t.color("iris")??t.pick("iris",IRISES),cream:mix("#f4ead6",body,.12),plate:mix(body,"#ffd76a",.62),comb:standout(body,["#e2392f","#ffd23f","#ff8a3d"]),beak:standout(body,["#ff9d2e","#ffd84a","#3f6fd8"]),bill:standout(body,["#ff7a2f","#e8452b","#ffb02e"])}}var standout=(body,choices)=>choices.reduce((best,choice2)=>contrast(choice2,body)>contrast(best,body)?choice2:best);function eyeMarkup(id,k,f2,c,cx,cy,r,side){if(f2.closed){let lash=k.eyes==="bead"?mix(c.iris,"#0b0b12",.62):c.iris;return`<path class="closed" d="M${r22(cx-r*.82)} ${r22(cy+r*.25)}Q${r22(cx)} ${r22(cy-r*.75)} ${r22(cx+r*.82)} ${r22(cy+r*.25)}" fill="none" stroke="${lash}" stroke-width="${r22(Math.max(1.8,r*.26))}" stroke-linecap="round"/>`}let bead=k.eyes==="bead",[rx,ry]=bead?[r*.86,r]:[r,r],clip=`${id}-eye${side}`,reach=r*(bead?.12:.32),[lx,ly]=[cx+f2.look[0]*reach*1.6,cy+f2.look[1]*reach*1.6],top=cy-ry*1.3,height=ry*2.6,scale=(.3+2*f2.lid)/2.6,ink="#0b0b12",beadColour=mix(c.iris,ink,.62),pupil=bead?`<ellipse cx="${r22(lx+rx*.3)}" cy="${r22(ly-ry*.36)}" rx="${r22(r*.26)}" ry="${r22(r*.22)}" fill="#ffffff"/><circle cx="${r22(lx-rx*.3)}" cy="${r22(ly+ry*.38)}" r="${r22(r*.1)}" fill="#ffffff"/>`:`<circle cx="${r22(lx)}" cy="${r22(ly)}" r="${r22(r*.58*f2.pupil)}" fill="${c.iris}" stroke="${mix(c.iris,ink,.45)}" stroke-width="${r22(r*.07)}"/><circle cx="${r22(lx)}" cy="${r22(ly)}" r="${r22(r*.3*f2.pupil)}" fill="${ink}"/><circle cx="${r22(lx+r*.22)}" cy="${r22(ly-r*.24)}" r="${r22(r*.17*f2.pupil)}" fill="#ffffff"/><circle cx="${r22(lx-r*.2)}" cy="${r22(ly+r*.22)}" r="${r22(r*.07*f2.pupil)}" fill="#ffffff"/>`,layer2=(fill,stretch)=>`<rect class="lid" x="${r22(cx-rx*1.4)}" y="${r22(top)}" width="${r22(rx*2.8)}" height="${r22(height*stretch)}" fill="${fill}" style="--lid:${r22(scale)}" transform="translate(0 ${r22(top)}) scale(1 ${r22(scale)}) translate(0 ${r22(-top)})"/>`,lid2=(bead?"":layer2("#cfd6de",1.09))+layer2(c.dark,1.03)+layer2(c.body,1);return`<clipPath id="${clip}"><ellipse cx="${r22(cx)}" cy="${r22(cy)}" rx="${r22(rx)}" ry="${r22(ry)}"/></clipPath><ellipse cx="${r22(cx)}" cy="${r22(cy)}" rx="${r22(rx)}" ry="${r22(ry)}" fill="${bead?beadColour:"#ffffff"}"/><g clip-path="url(#${clip})"><g class="pupil" style="--reach:${r22(reach)}">${pupil}</g><g transform="rotate(${r22(side*f2.tilt)} ${r22(cx)} ${r22(cy)})"><g class="lids">${lid2}</g></g></g><ellipse cx="${r22(cx)}" cy="${r22(cy)}" rx="${r22(rx)}" ry="${r22(ry)}" fill="none" stroke="${c.shade}" stroke-width="${r22(Math.max(.9,r*.08))}"/>`}function browMarkup(k,f2,c,cx,cy,r,side){if(k.brows==="none")return"";let y=cy-r*(k.brows==="pads"?1.75:1.42)-f2.lift*.7,turn2=`rotate(${r22(side*f2.browTilt)} ${r22(cx)} ${r22(y)})`;if(k.brows==="pads")return`<ellipse cx="${r22(cx)}" cy="${r22(y)}" rx="${r22(r*1.2)}" ry="${r22(r*.62)}" fill="${c.dark}" transform="${turn2}"/>`;if(k.brows==="wedges")return`<path d="M${r22(cx-side*r*1.5)} ${r22(y-r*.2)}L${r22(cx+side*r*1.25)} ${r22(y+r*.2)}L${r22(cx+side*r*1.2)} ${r22(y+r*.75)}L${r22(cx-side*r*1.45)} ${r22(y+r*.45)}Z" fill="${c.shade}" stroke="${c.shade}" stroke-width="1.6" stroke-linejoin="round" transform="${turn2}"/>`;let thick=Math.max(2.4,r*.3);return`<path d="M${r22(cx-r*1.02)} ${r22(y+r*.22)}Q${r22(cx)} ${r22(y-r*.42-thick)} ${r22(cx+r*1.02)} ${r22(y+r*.22)}Q${r22(cx)} ${r22(y-r*.42+thick*.4)} ${r22(cx-r*1.02)} ${r22(y+r*.22)}Z" fill="${c.dark}" stroke="${c.dark}" stroke-width="0.9" stroke-linejoin="round" transform="${turn2}"/>`}var TONGUE3="#f2849f",GUMS="#d8577a",TOOTH_SHADE="#d9dee6";function mouthMarkup(id,mouth3,c,y,w,teeth){let ink=`fill="none" stroke="${c.dark}" stroke-width="2.6" stroke-linecap="round"`,clip=`${id}-mouth`,chinUnder=at3=>`<path d="M${r22(50-w*.4)} ${r22(at3)}Q50 ${r22(at3+2)} ${r22(50+w*.4)} ${r22(at3)}" fill="none" stroke="${c.shade}" stroke-width="1.6" stroke-linecap="round"/>`,inside=(shape,fill)=>`<clipPath id="${clip}">${shape}</clipPath>${shape.replace("/>",` fill="${c.dark}"/>`)}<g clip-path="url(#${clip})">${fill}</g>`,row=(count,from,to,base,tip)=>Array.from({length:count},(_,i)=>{let a=from+(to-from)*i/count,b=from+(to-from)*(i+1)/count;return`<path d="M${r22(a)} ${r22(base)}L${r22((a+b)/2)} ${r22(tip)}L${r22(b)} ${r22(base)}Z" fill="#ffffff" stroke="#ffffff" stroke-width="0.8" stroke-linejoin="round"/>`}).join("");switch(mouth3){case"smile":return`<path d="M${r22(50-w*.62)} ${r22(y-1)}Q50 ${r22(y+w*.34)} ${r22(50+w*.62)} ${r22(y-1)}" ${ink}/>`;case"flat":return`<path d="M${r22(50-w*.5)} ${r22(y+1)}Q50 ${r22(y+1.6)} ${r22(50+w*.5)} ${r22(y+.4)}" ${ink}/>`;case"frown":return`<path d="M${r22(50-w*.5)} ${r22(y+4)}Q50 ${r22(y-w*.22)} ${r22(50+w*.5)} ${r22(y+4)}" ${ink}/>`;case"smirk":return`<path d="M${r22(50-w*.45)} ${r22(y+1.5)}Q${r22(50+w*.15)} ${r22(y+5)} ${r22(50+w*.6)} ${r22(y-3.5)}" ${ink}/>`;case"o":return inside(`<ellipse cx="50" cy="${r22(y+2)}" rx="${r22(Math.max(3.4,w*.18))}" ry="${r22(Math.max(4.4,w*.22))}"/>`,`<ellipse cx="50" cy="${r22(y+2+w*.2)}" rx="${r22(w*.16)}" ry="${r22(w*.1)}" fill="${TONGUE3}"/>`);case"grin":{let h=w*.62,shape=`<path d="M${r22(50-w)} ${r22(y-2)}Q50 ${r22(y+3)} ${r22(50+w)} ${r22(y-2)}Q50 ${r22(y+h*2)} ${r22(50-w)} ${r22(y-2)}Z"/>`,chin=`<path d="M${r22(50-w*.55)} ${r22(y+h*1.35)}Q50 ${r22(y+h*1.55)} ${r22(50+w*.55)} ${r22(y+h*1.35)}" fill="none" stroke="${c.shade}" stroke-width="1.8" stroke-linecap="round"/>`,gums=`<ellipse cx="50" cy="${r22(y+h*1.25)}" rx="${r22(w*.62)}" ry="${r22(h*.42)}" fill="${GUMS}"/>`,lip=`<path d="M${r22(50-w)} ${r22(y-2)}Q50 ${r22(y+3)} ${r22(50+w)} ${r22(y-2)}" fill="none" stroke="${TOOTH_SHADE}" stroke-width="2.6"/>`;return chin+inside(shape,gums+row(teeth,50-w*.92,50+w*.92,y-2.5,y+h*.36)+lip+row(Math.max(2,teeth-2),50-w*.5,50+w*.5,y+h*1.12,y+h*.86))}case"laugh":{let h=w*.55,shape=`<path d="M${r22(50-w*.85)} ${r22(y-2)}Q50 ${r22(y-4)} ${r22(50+w*.85)} ${r22(y-2)}Q50 ${r22(y+h*2.2)} ${r22(50-w*.85)} ${r22(y-2)}Z"/>`,tongue2=`<ellipse cx="50" cy="${r22(y+h*1.12)}" rx="${r22(w*.5)}" ry="${r22(h*.48)}" fill="${TONGUE3}"/><path d="M50 ${r22(y+h*.78)}V${r22(y+h*1.2)}" stroke="${mix(TONGUE3,BLACK,.18)}" stroke-width="1.2" stroke-linecap="round"/>`;return chinUnder(y+h*1.6)+inside(shape,`<rect x="${r22(50-w)}" y="${r22(y-6)}" width="${r22(w*2)}" height="6.4" fill="#ffffff"/><rect x="${r22(50-w)}" y="${r22(y-6)}" width="${r22(w*2)}" height="3.4" fill="${TOOTH_SHADE}"/>${tongue2}`)}case"grit":{let shape=`<rect x="${r22(50-w*.72)}" y="${r22(y-4.5)}" width="${r22(w*1.44)}" height="9" rx="4.5"/>`,gaps=Array.from({length:5},(_,i)=>`<path d="M${r22(50-w*.72+(i+1)*w*1.44/6)} ${r22(y-4)}V${r22(y+4)}" stroke="${c.dark}" stroke-width="1.1"/>`).join("");return chinUnder(y+9)+inside(shape,`<rect x="${r22(50-w*.72)}" y="${r22(y-3.2)}" width="${r22(w*1.44)}" height="6.4" fill="#ffffff"/><rect x="${r22(50-w*.72)}" y="${r22(y-3.2)}" width="${r22(w*1.44)}" height="1.6" fill="${TOOTH_SHADE}"/>${gaps}`)}}}function featureMarkup(k,f2,c,t,mouthY){let open2=f2.mouth==="grin"||f2.mouth==="laugh"||f2.mouth==="o";switch(k.feature){case"nose":{let[w,h,y]=k.name==="Imp"?[12,8.5,50]:[9,6,52],s=t.num("nose.size",.85,1.2);return`<ellipse cx="50" cy="${y}" rx="${r22(w*s)}" ry="${r22(h*s)}" fill="${c.dark}"/><ellipse cx="${r22(50+w*.15*s)}" cy="${r22(y-h*.42*s)}" rx="${r22(w*.4*s)}" ry="${r22(h*.22*s)}" fill="${mix(c.dark,WHITE,.32)}"/>`}case"bear":return`<ellipse cx="50" cy="83" rx="40" ry="31" fill="${c.cream}"/><ellipse cx="50" cy="60" rx="${r22(t.num("nose.size",11,14))}" ry="9" fill="${c.dark}"/><ellipse cx="53" cy="56" rx="5" ry="2.2" fill="${mix(c.dark,WHITE,.34)}"/>`;case"bill":{let drop=open2?7:0,curve2=f2.mouth==="frown"?-5:f2.mouth==="flat"||f2.mouth==="grit"?0:5;return`<path d="M24 ${66+drop*.3}Q34 ${84+drop} 56 ${86+drop}Q80 ${86+drop} 86 ${70+drop*.4}Q88 64 78 64Z" fill="${mix(c.bill,BLACK,.22)}"/>`+(open2?`<path d="M30 68Q50 ${80+drop} 80 68Z" fill="${c.dark}"/>`:"")+`<path d="M22 62Q24 54 40 55Q62 50 82 58Q92 62 86 68Q72 ${74-curve2*.4} 50 ${74+curve2*.2}Q30 ${76+curve2*.4} 24 70Q20 66 22 62Z" fill="${c.bill}" stroke="${mix(c.bill,BLACK,.3)}" stroke-width="1.4" stroke-linejoin="round"/><path d="M36 59Q50 55 64 57" fill="none" stroke="${mix(c.bill,WHITE,.45)}" stroke-width="2.6" stroke-linecap="round"/>`}case"beak":{let open3=f2.mouth==="grin"||f2.mouth==="laugh"||f2.mouth==="o"?3:0;return`<path d="M6 -6Q20 2 18 14Q28 4 36 10Q40 0 34 -8Z" fill="${c.comb}"/><path d="M8 -4Q20 4 18 12" fill="none" stroke="${mix(c.comb,BLACK,.2)}" stroke-width="2" stroke-linecap="round"/><path d="M49 ${66+open3}Q44 ${72+open3} 46 ${78+open3}Q50 ${82+open3} 54 ${78+open3}Q56 ${72+open3} 51 ${66+open3}Z" fill="${c.comb}"/>`+(open3?`<path d="M42 ${mouthY+1}Q50 ${mouthY+7} 58 ${mouthY+1}Z" fill="${c.dark}"/>`:"")+`<path d="M40 ${mouthY-2}Q50 ${mouthY-10} 60 ${mouthY-2}Q50 ${mouthY+4+open3} 40 ${mouthY-2}Z" fill="${c.beak}"/>`}case"jaw":return`<path d="M14 54L50 60L86 54L88 104L12 104Z" fill="${c.plate}"/><path d="M14 54L50 60L86 54" fill="none" stroke="${mix(c.plate,BLACK,.12)}" stroke-width="1.2"/><path d="M24 66Q22 72 26 78M76 66Q78 72 74 78" fill="none" stroke="${mix(c.plate,BLACK,.12)}" stroke-width="1.4" stroke-linecap="round"/>`;default:return""}}function marks(t,c,eyes2,y,r){let spots=t("spots")*100<SPOTS_PERCENT?[[-34,60,2.2],[-29,66,1.6],[-38,67,1.4],[34,60,2.2],[29,66,1.6],[38,67,1.4],[-8,10,1.8],[6,7,1.4],[14,12,1.2]].map(([x,sy,size])=>`<circle cx="${r22(50+x)}" cy="${r22(sy)}" r="${r22(size)}" fill="${c.shade}"/>`).join(""):"",blush=t("blush")*100<BLUSH_PERCENT?eyes2.map(x=>`<ellipse cx="${r22(x+(x<50?-r*.35:x>50?r*.35:0))}" cy="${r22(y+r*1.45)}" rx="${r22(Math.max(4,r*.55))}" ry="${r22(Math.max(2.2,r*.28))}" fill="${mix(c.body,"#ff6f91",.55)}"/>`).join(""):"";return spots+blush}function createCritter(name,overrides,id="critter"){let t=critterTraits(name,overrides),k=styledOf(name,overrides),f2=feelingOf(t),c=coloursOf6(t),size=t.num("eye.size",.88,1.14),r=k.r*size,gap=k.gap*t.num("eye.gap",.92,1.1),y=k.y+t.jitter("eye.y",2.5),sides=k.single?[0]:[-1,1],at3=side=>[50+side*gap,y],mouthW=k.mouthW*t.num("mouth.size",.85,1.15),teeth=t.int("teeth",4,7),front=k.feature==="bill"||k.feature==="beak",mouth3=front?"":mouthMarkup(id,f2.mouth==="smile"&&k.toothy&&t("toothy")<.6?"grin":f2.mouth,c,k.mouthY+t.jitter("mouth.y",2),mouthW,teeth),patches=k.patch?sides.map(side=>`<ellipse cx="${r22(at3(side)[0])}" cy="${r22(y)}" rx="${r22(r*k.patch)}" ry="${r22(r*k.patch*.92)}" fill="${c.light}"/>`).join(""):"",eye3=side=>eyeMarkup(id,k,f2,c,at3(side)[0],y,r,side||1);return{kind:k.name,feeling:f2.name,body:c.body,back:patches+marks(t,c,sides.map(side=>at3(side)[0]),y,r)+(front?"":featureMarkup(k,f2,c,t,k.mouthY)),eyes:{left:eye3(sides[0]),right:sides.length>1?eye3(sides[1]):""},brows:sides.map(side=>browMarkup(k,f2,c,at3(side)[0],y,r,side||1)).join(""),mouth:mouth3,front:front?featureMarkup(k,f2,c,t,k.mouthY):"",blink:{period:r22(t.num("blink.period",3.4,6)),delay:r22(t.num("blink.delay",0,3))}}}var CORNER3=22.22;function critterSvg(name,overrides){let k=createCritter(name,overrides);return`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><defs><clipPath id="critter-tile"><rect width="100" height="100" rx="${CORNER3}"/></clipPath></defs><g clip-path="url(#critter-tile)"><rect width="100" height="100" fill="${k.body}"/>${k.back}${k.eyes.left}${k.eyes.right}${k.brows}${k.mouth}${k.front}</g></svg>`}var titled=word=>word[0].toUpperCase()+word.slice(1),own=(control,selected)=>({...control,selected:String(selected)}),controls8=(name,overrides)=>{let t=critterTraits(name,overrides),kind=kindOf(name,overrides),styled=styledOf(name,overrides),mouthed=kind.feature!=="bill"&&kind.feature!=="beak";return[{title:"Critter",controls:[{...choice(t,"kind","Creature","list",KINDS.map(({name:label})=>({label}))),selected:String(KINDS.indexOf(kind))},narrowed(choice(t,"feeling","Feeling","list",FEELINGS.map(({name:label})=>({label}))),t,CALMING8),possibilitiesSlider(t,NOTES9),slider(t,"eye.size","Eye size",0,100,"%"),...kind.single?[]:[slider(t,"eye.gap","Eye gap",0,100,"%")],slider(t,"eye.y","Eye height",-100,100,"%"),...mouthed?[slider(t,"mouth.size","Mouth size",0,100,"%")]:[],own(choice(t,"eye.style","Eyes","list",EYE_STYLES.map(style=>({label:titled(style)}))),EYE_STYLES.indexOf(styled.eyes)),own(choice(t,"brows","Brows","list",BROWS.map(style=>({label:titled(style)}))),BROWS.indexOf(styled.brows)),{...choice(t,"patch","Eye patches","list",[{label:"On"},{label:"Off"}]),selected:styled.patch?"0":"1",options:[{id:"0",label:"On",set:{patch:0}},{id:"1",label:"Off",set:{patch:.999}}],layout:"switch"},toggle(t,"spots",SPOTS_PERCENT,"Spots"),toggle(t,"blush",BLUSH_PERCENT,"Blush")]},{title:"Colour",controls:[palette(t,"body","Colour",COLOURS2),palette(t,"iris","Iris",IRISES)]}]};var PLAINEST=[13,8,[0,1,4,2,3,12,9,6,7,5,8,10,11]],CALMING9={features:/^eye\.(size|gap|y)$|^tilt$/,lists:{"eye.left":PLAINEST,"eye.right":PLAINEST}},NOTES10=["plain circles, lids, smiles and pills, upright and evenly spaced.","more shapes, a little tilted, set wider or closer.","every eye, up to moons, rings, slants and squints, at any size, gap and tilt."];var round28=value=>Math.round(value*100)/100,f=round28,EYES2=[{name:"Full",draw:r=>`<circle r="${f(r)}"/>`},{name:"Lid",draw:r=>`<path d="M${f(-r)} 0A${f(r)} ${f(r)} 0 0 0 ${f(r)} 0Z"/>`},{name:"Smile",draw:r=>`<path d="M${f(-1.05*r)} ${f(.75*r)}Q0 ${f(-.3*r)} ${f(1.05*r)} ${f(.75*r)}Q0 ${f(.25*r)} ${f(-1.05*r)} ${f(.75*r)}Z" stroke-width="${f(r*.1)}"/>`},{name:"Pill",draw:r=>`<rect x="${f(-.46*r)}" y="${f(-.95*r)}" width="${f(.92*r)}" height="${f(1.9*r)}" rx="${f(.46*r)}"/>`},{name:"Sleepy",draw:r=>{let[top,side]=[-.2*r,.98*r];return`<path d="M${f(-side)} ${f(top)}H${f(side)}A${f(r)} ${f(r)} 0 0 1 ${f(-side)} ${f(top)}Z" stroke-width="${f(r*.16)}"/>`}},{name:"Ring",draw:r=>`<circle r="${f(r*.78)}" fill="none" stroke-width="${f(r*.42)}"/>`},{name:"Dash",draw:r=>`<rect x="${f(-.95*r)}" y="${f(.1*r)}" width="${f(1.9*r)}" height="${f(.44*r)}" rx="${f(.22*r)}"/>`},{name:"Dome",draw:r=>`<path d="M${f(-r)} ${f(.4*r)}A${f(r)} ${f(r)} 0 0 1 ${f(r)} ${f(.4*r)}Z"/>`},{name:"Slant",draw:r=>`<path d="M${f(-r)} 0A${f(r)} ${f(r)} 0 0 0 ${f(r)} 0Z" transform="rotate(20)"/>`},{name:"Dot",draw:r=>`<circle r="${f(r*.5)}"/>`},{name:"Moon",draw:r=>`<path d="M${f(.2*r)} ${f(-r)}A${f(r)} ${f(r)} 0 1 0 ${f(.2*r)} ${f(r)}A${f(.72*r)} ${f(r)} 0 1 1 ${f(.2*r)} ${f(-r)}Z"/>`},{name:"Squint",draw:r=>`<path d="M${f(-.55*r)} ${f(-.6*r)}L${f(.5*r)} 0L${f(-.55*r)} ${f(.6*r)}" fill="none" stroke-width="${f(r*.38)}"/>`},{name:"Oval",draw:r=>`<ellipse rx="${f(r*.68)}" ry="${f(r*1.08)}"/>`}],TILES4=["#000000","#1d1330","#0e2620","#2a1019","#0f1b3b","#15151c","#262019","#101418"],INKS2=["#ffffff","#fff3d6","#cbfff0","#ffd3ea","#ffe08a","#aee9ff"],PAIR_PERCENT=55,glanceTraits=(name,overrides)=>calmed(createTraits(name,overrides),CALMING9),leftOf=t=>t.pick("eye.left",EYES2),rightOf=t=>t.forced("eye.right")===void 0&&t("pair")*100<PAIR_PERCENT?leftOf(t):t.pick("eye.right",EYES2);function coloursOf7(t){return{tile:t.color("tile")??t.pick("tile",TILES4),ink:t.color("ink")??t.pick("ink",INKS2)}}function createGlance(name,overrides){let t=glanceTraits(name,overrides),{tile,ink}=coloursOf7(t),r=t.num("eye.size",11,14.5),gap=t.num("eye.gap",16,22),place2=(side,eye3)=>({at:`translate(${f(side*gap)} 0)${side>0?" scale(-1 1)":""}`,shape:eye3.draw(r)});return{tile,ink,face:`translate(50 ${f(t.num("eye.y",42,52))}) rotate(${f(t.jitter("tilt",6))})`,left:place2(-1,leftOf(t)),right:place2(1,rightOf(t)),blink:{period:f(t.num("blink.period",3.4,6)),delay:f(t.num("blink.delay",0,3)),twice:t("blink.twice")<.4}}}var EYE_STYLE=ink=>`fill="${ink}" stroke="${ink}" stroke-width="0" stroke-linecap="round" stroke-linejoin="round"`,CORNER4=22.22;function glanceSvg(name,overrides){let g=createGlance(name,overrides);return`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><rect width="100" height="100" rx="${CORNER4}" fill="${g.tile}"/><g transform="${g.face}" ${EYE_STYLE(g.ink)}><g transform="${g.left.at}">${g.left.shape}</g><g transform="${g.right.at}">${g.right.shape}</g></g></svg>`}var named5=EYES2.map(({name:label})=>({label})),controls9=(name,overrides)=>{let t=glanceTraits(name,overrides);return[{title:"Eyes",controls:[narrowed(choice(t,"eye.left","Left eye","list",named5),t,CALMING9),{...narrowed(choice(t,"eye.right","Right eye","list",named5),t,CALMING9),selected:String(EYES2.indexOf(rightOf(t)))},possibilitiesSlider(t,NOTES10),slider(t,"eye.size","Eye size",0,100,"%"),slider(t,"eye.gap","Eye gap",0,100,"%"),slider(t,"eye.y","Eye height",0,100,"%"),slider(t,"tilt","Tilt",-6,6,"\xB0")]},{title:"Colour",controls:[palette(t,"tile","Colour",TILES4),palette(t,"ink","Eyes",INKS2)]}]};var CALMING10={lists:{mood:[9,8,[0,6,2,1,3,8,4,5,7]],hat:[5,3,[0,2,1,3,4]],opening:[5,3,[0,4,2,1,3]]}},NOTES11=["beanies and goggle holes, calm and bored eyes.","more hats and holes, and more moods.","every hat, hole and mood, angry eyes and open faces too."];var r23=value=>Math.round(value*100)/100,BEANIES=["#1b1b1f","#c23a2e","#d9a43a","#20324f","#3f5f3a","#e9e4d8","#6b3a5a","#2f7f86"],MASKS=["#a9aaac","#26262b","#d8d2c4","#6c7558","#d98fa0","#8fa3b8","#4a5a7a","#efe7d2"],CLOTHES=["#1c1c20","#7b5a3c","#2b3a55","#5b6b4a","#a8322d","#cfcac0","#3b3b42","#c99a3e"],SKINS2=["#e3a980","#f2c7a5","#c98b5f","#9c6340","#6e4329","#f5d6bf"],TILES5=["#d9dadd","#e4ddd3","#d3dbe3","#e2d6dd","#d6ded3","#cfcfd4"],HATS=[{name:"Cuffed",hat:"cuffed"},{name:"Pompom",hat:"pompom"},{name:"Watch cap",hat:"watch"},{name:"Slouch",hat:"slouch"},{name:"Bare",hat:"none"}],OPENINGS=[{name:"Goggles",opening:"goggles"},{name:"Three holes",opening:"three"},{name:"Slot",opening:"slot"},{name:"Open face",opening:"open"},{name:"Two holes",opening:"holes"}],CLOTHING=[{name:"Coat",clothing:"coat"},{name:"Puffer",clothing:"puffer"},{name:"Hoodie",clothing:"hoodie"},{name:"Bomber",clothing:"bomber"},{name:"Turtleneck",clothing:"turtleneck"}],MOODS4=[{name:"Bored",lid:.5,tilt:0,look:[-.55,.35],pupil:1},{name:"Wide",lid:.08,tilt:0,look:[0,0],pupil:.85},{name:"Sleepy",lid:.68,tilt:-4,look:[0,.5],pupil:1},{name:"Side eye",lid:.38,tilt:6,look:[.8,.1],pupil:1},{name:"Surprised",lid:0,tilt:0,look:[0,-.2],pupil:.7},{name:"Suspicious",lid:.46,tilt:14,look:[-.7,0],pupil:.95},{name:"Calm",lid:.3,tilt:-2,look:[0,.15],pupil:1},{name:"Angry",lid:.36,tilt:24,look:[0,0],pupil:.9},{name:"Weary",lid:.58,tilt:-12,look:[.3,.4],pupil:1}],knitTraits=(name,overrides)=>calmed(createTraits(name,overrides),CALMING10),hatOf=t=>t.pick("hat",HATS).hat,openingOf=t=>t.pick("opening",OPENINGS).opening,clothingOf=t=>t.pick("clothing",CLOTHING).clothing,moodOf4=t=>t.pick("mood",MOODS4);function coloursOf8(t){return{beanie:t.color("beanie")??t.pick("beanie",BEANIES),mask:t.color("mask")??t.pick("mask",MASKS),clothes:t.color("clothes")??t.pick("clothes",CLOTHES),skin:t.color("skin")??t.pick("skin",SKINS2),tile:t.color("tile")??t.pick("tile",TILES5)}}function along(curve2,x0,x1,lift=0){let steps=Math.ceil(Math.abs(x1-x0));return Array.from({length:steps+1},(_,i)=>{let x=x0+(x1-x0)*i/steps;return`${r23(x)} ${r23(curve2(x)+lift)}`}).join("L")}function ribs(id,colour,pitch,depth=1){let light=mix(colour,WHITE,.12*depth),dark=mix(colour,BLACK,.16*depth);return`<pattern id="${id}" patternUnits="userSpaceOnUse" width="${pitch}" height="${pitch*3}"><rect width="${pitch}" height="${pitch*3}" fill="${colour}"/><rect x="${r23(pitch*.08)}" width="${r23(pitch*.38)}" height="${pitch*3}" fill="${light}"/><rect x="${r23(pitch*.62)}" width="${r23(pitch*.16)}" height="${pitch*3}" fill="${dark}"/><path d="M${r23(pitch*.08)} 0L${r23(pitch*.27)} ${r23(pitch*.5)}L${r23(pitch*.46)} 0M${r23(pitch*.08)} ${r23(pitch*1.5)}L${r23(pitch*.27)} ${r23(pitch*2)}L${r23(pitch*.46)} ${r23(pitch*1.5)}" fill="none" stroke="${mix(colour,BLACK,.1)}" stroke-width="${r23(pitch*.07)}"/></pattern>`}var stops=list=>list.map(([offset,colour,opacity])=>`<stop offset="${offset}" stop-color="${colour}" stop-opacity="${opacity}"/>`).join(""),BLURS={b4:.4,b8:.8,b14:1.4,b24:2.4},ROOM='filterUnits="userSpaceOnUse" x="-10" y="-10" width="120" height="120"',soft=(id,d,colour,opacity,width,blur2)=>`<path d="${d}" fill="none" stroke="${colour}" stroke-opacity="${opacity}" stroke-width="${width}" stroke-linecap="round" filter="url(#${id}-${blur2})"/>`,OPEN='transform="translate(50 46) scale(1.22) translate(-50 -46)"',HEAD="M50 15.5C66.5 15.5 78.5 26 79.2 41.5C79.4 44 79.6 46 79.8 47.5Q82.6 50 80.2 52.6Q83 55.6 79.8 58.6Q82 61.8 77.8 64C73.5 68.6 62.5 71 50 71C37.5 71 26.5 68.6 22.2 64Q18 61.8 20.2 58.6Q17 55.6 19.8 52.6Q17.4 50 20.2 47.5C20.4 46 20.6 44 20.8 41.5C21.5 26 33.5 15.5 50 15.5Z",NECK="M39 61H61Q61.2 70 62.6 75.2Q50 78.6 37.4 75.2Q38.8 70 39 61Z",BODY="M19 104C19.5 90 24 80.5 35 75.6Q38.5 74.2 42 74H58Q61.5 74.2 65 75.6C76 80.5 80.5 90 81 104Z",TEE="M41.5 74H58.5L57 104H43Z";function pill2(x0,y0,x1,y1){let r=(x1-x0)/2;return`M${r23(x0+r)} ${y0}A${r23(r)} ${r23(r)} 0 0 1 ${x1} ${r23(y0+r)}V${r23(y1-r)}A${r23(r)} ${r23(r)} 0 0 1 ${r23(x0+r)} ${y1}A${r23(r)} ${r23(r)} 0 0 1 ${x0} ${r23(y1-r)}V${r23(y0+r)}A${r23(r)} ${r23(r)} 0 0 1 ${r23(x0+r)} ${y0}Z`}function openingShape(opening){let eyes2=(xs,y,rx,ry,open2=0,drop=0,iris=.64)=>xs.map(x=>({x,y,rx,ry,open:open2,drop,iris}));switch(opening){case"goggles":return{d:pill2(36.9,33.3,47.95,51.7)+pill2(52.05,33.3,63.1,51.7),eyes:eyes2([42.43,57.57],42.5,4.42,8.1,.24,.2,.82)};case"slot":return{d:"M38 38.5H62Q69 38.5 69 45.5Q69 52 62 52H38Q31 52 31 45.5Q31 38.5 38 38.5Z",eyes:eyes2([41.5,58.5],45.2,5.2,4.8)};case"holes":return{d:"M34.5 45.5A7 6.8 0 1 0 48.5 45.5A7 6.8 0 1 0 34.5 45.5ZM51.5 45.5A7 6.8 0 1 0 65.5 45.5A7 6.8 0 1 0 51.5 45.5Z",eyes:eyes2([41.5,58.5],45.5,5.6,5.4)};case"three":return{d:"M34.5 45A7 6.6 0 1 0 48.5 45A7 6.6 0 1 0 34.5 45ZM51.5 45A7 6.6 0 1 0 65.5 45A7 6.6 0 1 0 51.5 45ZM43.5 61.5A6.5 4 0 1 0 56.5 61.5A6.5 4 0 1 0 43.5 61.5Z",eyes:eyes2([41.5,58.5],45,5.6,5.2),mouth:!0};case"open":return{d:"M50 36Q67 36 67 50Q67 66 50 66Q33 66 33 50Q33 36 50 36Z",eyes:eyes2([42,58],46,5,4.2),mouth:!0,nose:!0}}}var eyeRect=(e,grow=0)=>`x="${r23(e.x-e.rx-grow)}" y="${r23(e.y-e.ry-grow)}" width="${r23(2*(e.rx+grow))}" height="${r23(2*(e.ry+grow))}" rx="${r23(e.rx+grow)}" ry="${r23(Math.min(e.rx,e.ry)+grow)}"`;function eyesMarkup(id,m,eyes2){return eyes2.map((e,i)=>{let side=i===0?-1:1,clip=`${id}-eye${i}`,radius=e.rx*e.iris*m.pupil,[px,py]=[e.x+m.look[0]*e.rx*.36,e.y+e.ry*e.drop+m.look[1]*e.ry*.3],top=e.y-e.ry-.4,height=2*e.ry+.8,scale=(e.y-e.ry+2*e.ry*(e.open+(1-e.open)*m.lid)-top)/height,layer2=(fill,stretch,opacity=1)=>`<rect class="lid" x="${r23(e.x-e.rx*2.2)}" y="${r23(top)}" width="${r23(e.rx*4.4)}" height="${r23(height*stretch)}" fill="${fill}"${opacity<1?` fill-opacity="${opacity}"`:""} style="--lid:${r23(scale)}" transform="translate(0 ${r23(top)}) scale(1 ${r23(scale)}) translate(0 ${r23(-top)})"/>`;return`<g class="eye" data-eye="${i}"><clipPath id="${clip}"><rect ${eyeRect(e)}/></clipPath><rect ${eyeRect(e)} fill="url(#${id}-white)"/><g clip-path="url(#${clip})"><g class="pupil"><circle cx="${r23(px)}" cy="${r23(py)}" r="${r23(radius)}" fill="url(#${id}-pupil)"/><circle cx="${r23(px+radius*.38)}" cy="${r23(py-radius*.4)}" r="${r23(radius*.17)}" fill="#ffffff" fill-opacity="0.9"/><circle cx="${r23(px-radius*.35)}" cy="${r23(py+radius*.45)}" r="${r23(radius*.22)}" fill="#ffffff" fill-opacity="0.12"/></g><rect ${eyeRect(e)} fill="url(#${id}-eyeball)"/><g transform="rotate(${r23(-side*m.tilt)} ${r23(e.x)} ${r23(e.y)})"><g class="lids">${layer2("#2a1810",1.14,.1)}${layer2("#2a1810",1.06,.16)}${layer2(`url(#${id}-lash)`,1.02)}${layer2(`url(#${id}-lid)`,1)}</g></g></g></g>`}).join("")}function bandOf(hat){let arch=(x0,x1,sides,middle)=>x=>{let t=(x-x0)/(x1-x0);return sides-4*(sides-middle)*t*(1-t)},wrap2=(middle,sides,half)=>x=>middle+(sides-middle)*Math.abs((x-50)/half)**2.6;switch(hat){case"none":return;case"watch":return{x0:22,x1:78,top:arch(22,78,23,18.5),bottom:wrap2(30.5,40,28),peak:[50,11.5]};case"slouch":{let bottom=wrap2(35,47,29);return{x0:20.5,x1:79.5,top:x=>bottom(x)-6.5,bottom,peak:[56,2.5]}}default:return{x0:20.5,x1:79.5,top:arch(20.5,79.5,24.5,19.5),bottom:wrap2(35,47,29),peak:[50,hat==="pompom"?9.5:8]}}}var around=count=>Array.from({length:count-1},(_,k)=>{let angle=-Math.PI/2+(k+1)*Math.PI/count;return{sin:Math.sin(angle),cos:Math.cos(angle),angle}}),lit=angle=>Math.max(0,Math.cos(angle+.45));function hatMarkup(id,hat,band2){let{x0,x1,top,bottom,peak}=band2,[px,py]=peak,half=(x1-x0)/2,inset=hat==="slouch"?1.5:4.5,[l,r]=[x0+inset,x1-inset],[ly,ry]=[top(l),top(r)],crown=hat==="slouch"?`M${l} ${r23(ly+1)}C${l-2} ${py+12} ${px-20} ${py} ${px} ${py}C${px+16} ${py} ${r+5} ${py+8} ${r+1.5} ${py+16}C${r+.5} ${r23(ry-6)} ${r} ${r23(ry-2)} ${r} ${r23(ry+1)}Z`:`M${l} ${r23(ly+2)}C${l-1} ${r23(py+(ly-py)*.5)} ${px-12.5} ${py} ${px} ${py}C${px+12.5} ${py} ${r+1} ${r23(py+(ry-py)*.5)} ${r} ${r23(ry+2)}Z`,bandPath=`M${x0} ${r23(top(x0)+3)}Q${x0} ${r23(top(x0))} ${x0+3} ${r23(top(x0+3))}L${along(top,x0+3,x1-3)}Q${x1} ${r23(top(x1))} ${x1} ${r23(top(x1)+3)}Q${x1+2.6} ${r23((top(x1)+bottom(x1))/2+1.5)} ${x1-.6} ${r23(bottom(x1-.6))}L${along(bottom,x1-.6,x0+.6)}Q${x0-2.6} ${r23((top(x0)+bottom(x0))/2+1.5)} ${x0} ${r23(top(x0)+3)}Z`,crownRibs=around(12).map(({sin,cos,angle})=>{let xb=50+(half-inset)*sin,yb=top(xb)+1,start=`M${r23(px+(xb-50)*.08)} ${py+1}`,bend=`Q${r23(xb+(xb-50)*.08+(px-50)*.4)} ${r23(py+(yb-py)*.45)} ${r23(xb)} ${r23(yb)}`,gleam=50+(half-inset)*Math.sin(angle+Math.PI/24-.05),gb=top(gleam)+1;return soft(id,start+bend,"#000000",.5,r23(.35+.8*cos),"b4")+soft(id,`M${r23(px+(gleam-50)*.08)} ${py+2}Q${r23(gleam+(gleam-50)*.08+(px-50)*.4)} ${r23(py+(gb-py)*.45)} ${r23(gleam)} ${r23(gb)}`,"#ffffff",r23(.03+.12*lit(angle)),r23(.5+1.2*cos),"b8")}).join(""),step=Math.PI/14,cuffRibs=around(14).map(({sin,cos,angle})=>{let xt=50+half*sin,xb=50+(half-.8)*sin,mid=(top(xt)+bottom(xt))/2,groove=`M${r23(xt)} ${r23(top(xt)+.2)}Q${r23(50+(half+.6)*sin)} ${r23(mid)} ${r23(xb)} ${r23(bottom(xb)-.2)}`,g=Math.sin(angle-step*.62),gt=50+half*g,gb=50+(half-.8)*g,gleam=`M${r23(gt)} ${r23(top(gt)+1.2)}Q${r23(50+(half+.6)*g)} ${r23((top(gt)+bottom(gt))/2)} ${r23(gb)} ${r23(bottom(gb)-1.4)}`;return soft(id,groove,"#000000",.55,r23(.4+.9*cos),"b4")+soft(id,gleam,"#ffffff",r23(.05+.2*lit(angle-step)),r23(.6+2*cos),"b8")}).join("");return`<g filter="url(#${id}-fuzz)"><clipPath id="${id}-crown"><path d="${crown}"/></clipPath><path d="${crown}" fill="url(#${id}-beanie)"/><g clip-path="url(#${id}-crown)">${crownRibs}<path d="${crown}" fill="url(#${id}-dome)"/></g><clipPath id="${id}-band"><path d="${bandPath}"/></clipPath><path d="${bandPath}" fill="url(#${id}-beanie)"/><g clip-path="url(#${id}-band)">${cuffRibs}<path d="${bandPath}" fill="url(#${id}-round)"/>`+soft(id,`M${along(top,x0,x1,-.3)}`,"#000000",.6,1.6,"b8")+soft(id,`M${along(top,x0+3,x1-3,1.8)}`,"#ffffff",.14,2,"b14")+soft(id,`M${along(bottom,x0,x1,-.4)}`,"#000000",.45,2.6,"b14")+"</g></g>"}function pompomMarkup(id,band2){let[cx,cy]=[band2.peak[0],band2.peak[1]-3.4];return`<g class="pompom">${Array.from({length:18},(_,i)=>{let a=i/18*Math.PI*2,reach=4.3+i%3*.35;return`<circle cx="${r23(cx+Math.cos(a)*reach)}" cy="${r23(cy+Math.sin(a)*reach*.9)}" r="${r23(2.1+i%2*.3)}" fill="url(#${id}-pom)"/>`}).join("")}<circle cx="${cx}" cy="${r23(cy)}" r="4.9" fill="url(#${id}-pom)"/></g>`}function clothesMarkup(id,clothing,c){let cloth=c.clothes,dark=mix(cloth,BLACK,.4),body=`<path d="${BODY}" fill="${cloth}"/>`,tee=`<path d="${TEE}" fill="#ecebe7"/><path d="${TEE}" fill="url(#${id}-tee)"/>`,form=soft(id,"M21.5 96C22.8 86 27 80 35.5 76.2","#ffffff",.16,2.4,"b14")+soft(id,"M78.5 96C77.2 86 73 80 64.5 76.2","#ffffff",.07,2.4,"b14")+`<path d="${BODY}" fill="url(#${id}-round)"/>`;switch(clothing){case"coat":{let lapel=mix(cloth,WHITE,.05);return{under:body+tee+soft(id,"M42.6 74.6Q45.3 88 47.6 104","#000000",.3,1.8,"b8")+soft(id,"M57.4 74.6Q54.7 88 52.4 104","#000000",.3,1.8,"b8")+soft(id,"M33.6 84.6Q38 93.5 41.2 104","#000000",.5,1.6,"b8")+soft(id,"M66.4 84.6Q62 93.5 58.8 104","#000000",.5,1.6,"b8")+`<path d="M35.2 75.4L41.6 74.2Q44.4 88 46.6 104H41Q37.8 93 33.2 84L36.9 81.6Z" fill="${lapel}"/><path d="M64.8 75.4L58.4 74.2Q55.6 88 53.4 104H59Q62.2 93 66.8 84L63.1 81.6Z" fill="${lapel}"/>`+soft(id,"M41.2 75Q44 88 46.2 104","#ffffff",.16,.7,"b4")+soft(id,"M58.8 75Q56 88 53.8 104","#ffffff",.08,.7,"b4")+soft(id,"M33.6 84.2L36.9 81.6","#000000",.45,.6,"b4")+soft(id,"M66.4 84.2L63.1 81.6","#000000",.45,.6,"b4")+form,over:""}}case"hoodie":return{under:body+`<path d="M29 77.5Q31 70.5 40 69.5H60Q69 70.5 71 77.5Q66 83.5 50 84Q34 83.5 29 77.5Z" fill="${mix(cloth,WHITE,.04)}"/><path d="M35.5 75Q50 70 64.5 75Q60.5 81 50 81.5Q39.5 81 35.5 75Z" fill="${dark}"/>`+soft(id,"M30 78Q36 84 50 84.2Q64 84 70 78","#000000",.45,1.6,"b8")+soft(id,"M31.5 75.5Q33 71.5 39 70.8","#ffffff",.18,1.4,"b8")+soft(id,"M33 79.5Q37 76.5 36.5 73M67 79.5Q63 76.5 63.5 73","#000000",.3,.8,"b4")+form,over:soft(id,"M45.3 80Q44.8 88 45.4 95.5M56.3 80Q56.8 88 56.2 95.5","#000000",.35,1.4,"b8")+'<path d="M44.5 79.5Q44 88 44.6 95M55.5 79.5Q56 88 55.4 95" fill="none" stroke="#efece6" stroke-width="1.1" stroke-linecap="round"/><rect x="43.8" y="94.4" width="1.6" height="3" rx="0.6" fill="#c9c5bd"/><rect x="54.6" y="94.4" width="1.6" height="3" rx="0.6" fill="#c9c5bd"/>'};case"puffer":return{under:body+`<clipPath id="${id}-body"><path d="${BODY}"/></clipPath><g clip-path="url(#${id}-body)">`+[82,89,96,103].map(y=>soft(id,`M18 ${y-3.6}Q50 ${y-.6} 82 ${y-3.6}`,"#ffffff",.16,3,"b14")+soft(id,`M14 ${y}Q50 ${y+3} 86 ${y}`,"#000000",.55,1,"b4")).join("")+"</g>"+soft(id,"M50 77V104","#000000",.5,.9,"b4")+form,over:`<path d="M36.5 72.5Q50 76.5 63.5 72.5L64 79.5Q50 83.5 36 79.5Z" fill="${cloth}"/><path d="M36.5 72.5Q50 76.5 63.5 72.5L64 79.5Q50 83.5 36 79.5Z" fill="url(#${id}-round)"/>`+soft(id,"M37.5 74.5Q50 78.2 62.5 74.5","#ffffff",.2,1.4,"b8")+soft(id,"M36.5 80Q50 84 63.5 80","#000000",.45,1.4,"b8")+soft(id,"M50 77.5V83","#000000",.5,.7,"b4")};case"turtleneck":return{under:`<path d="${BODY}" fill="url(#${id}-cloth)"/>`+form,over:`<path d="M36 72.5Q50 70.5 64 72.5Q65.5 76.5 63.5 80Q50 83 36.5 80Q34.5 76.5 36 72.5Z" fill="url(#${id}-cloth)"/><path d="M36 72.5Q50 70.5 64 72.5Q65.5 76.5 63.5 80Q50 83 36.5 80Q34.5 76.5 36 72.5Z" fill="url(#${id}-round)"/>`+soft(id,"M37 74Q50 72.4 63 74","#ffffff",.18,1.6,"b8")+soft(id,"M36.5 80.4Q50 83.6 63.5 80.4","#000000",.5,1.6,"b8")};case"bomber":return{under:body+tee+soft(id,"M42.5 86Q43.3 95 44 104M57.5 86Q56.7 95 56 104","#000000",.35,1.8,"b8")+`<path d="M41.5 86L43 104H39.5L37.5 86.5Z" fill="${cloth}"/><path d="M58.5 86L57 104H60.5L62.5 86.5Z" fill="${cloth}"/>`+soft(id,"M41.6 86.5L43 103.5M58.4 86.5L57 103.5","#000000",.6,.6,"b4")+`<path d="M34.5 75.5Q41 78.5 41.5 86L39.5 86.5Q38.6 80.5 32.5 77.5Z" fill="url(#${id}-cloth)"/><path d="M65.5 75.5Q59 78.5 58.5 86L60.5 86.5Q61.4 80.5 67.5 77.5Z" fill="url(#${id}-cloth)"/>`+form,over:""}}}function createKnit(name,overrides,id="knit"){let t=knitTraits(name,overrides),c=coloursOf8(t),hat=hatOf(t),band2=bandOf(hat),opening=openingShape(openingOf(t)),mood=moodOf4(t),clothes=clothesMarkup(id,clothingOf(t),c),knit=`url(#${id}-mask)`,skinDark=mix(c.skin,BLACK,.32),blurs=Object.entries(BLURS).map(([key2,std])=>`<filter id="${id}-${key2}" ${ROOM}><feGaussianBlur stdDeviation="${std}"/></filter>`).join(""),defs="<defs>"+ribs(`${id}-mask`,c.mask,1,.65)+ribs(`${id}-beanie`,c.beanie,.9,.55)+ribs(`${id}-cloth`,c.clothes,2.4)+blurs+`<filter id="${id}-fuzz" ${ROOM}><feTurbulence type="fractalNoise" baseFrequency="1.6" numOctaves="2" seed="3" result="wobble"/><feDisplacementMap in="SourceGraphic" in2="wobble" scale="0.32" xChannelSelector="R" yChannelSelector="G" result="fuzzy"/><feTurbulence type="fractalNoise" baseFrequency="3.2" numOctaves="1" seed="7" result="fleck"/><feColorMatrix in="fleck" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.5 0 0 0 -0.18" result="specks"/><feComposite in="specks" in2="fuzzy" operator="in" result="flecked"/><feMerge><feMergeNode in="fuzzy"/><feMergeNode in="flecked"/></feMerge></filter><radialGradient id="${id}-ball" cx="0.42" cy="0.36" r="0.66">${stops([[0,WHITE,.26],[.45,WHITE,.04],[.8,BLACK,.1],[1,BLACK,.3]])}</radialGradient><linearGradient id="${id}-under" x1="0" y1="0" x2="0" y2="1">${stops([[.7,BLACK,0],[1,BLACK,.26]])}</linearGradient><radialGradient id="${id}-dome" cx="0.4" cy="0.3" r="0.8">${stops([[0,WHITE,.16],[.4,WHITE,0],[.8,BLACK,.3],[1,BLACK,.5]])}</radialGradient><linearGradient id="${id}-round" x1="0" y1="0" x2="1" y2="0">${stops([[0,BLACK,.5],[.12,BLACK,.16],[.3,WHITE,.1],[.46,WHITE,.03],[.7,BLACK,.08],[.88,BLACK,.3],[1,BLACK,.55]])}</linearGradient><linearGradient id="${id}-tee" x1="0" y1="0" x2="1" y2="0">${stops([[0,BLACK,.2],[.3,BLACK,0],[.7,BLACK,.02],[1,BLACK,.26]])}</linearGradient><radialGradient id="${id}-pom" cx="0.38" cy="0.32" r="0.7">${stops([[0,mix(c.beanie,WHITE,.3),1],[.55,c.beanie,1],[1,mix(c.beanie,BLACK,.4),1]])}</radialGradient><linearGradient id="${id}-skin" x1="0" y1="0" x2="0" y2="1">${stops([[0,mix(c.skin,BLACK,.18),1],[.5,c.skin,1],[1,mix(c.skin,WHITE,.12),1]])}</linearGradient><linearGradient id="${id}-white" x1="0" y1="0" x2="0" y2="1">${stops([[0,"#c9c3be",1],[.4,"#eae6e2",1],[.78,"#f8f6f3",1],[1,"#ddd8d3",1]])}</linearGradient><radialGradient id="${id}-eyeball" cx="0.5" cy="0.6" r="0.62">${stops([[0,BLACK,0],[.72,BLACK,0],[1,BLACK,.24]])}</radialGradient><radialGradient id="${id}-pupil" cx="0.42" cy="0.38" r="0.65">${stops([[0,"#2b1a12",1],[.7,"#120a07",1],[1,"#070403",1]])}</radialGradient><linearGradient id="${id}-lid" x1="0" y1="0" x2="0" y2="1">${stops([[0,mix(c.skin,WHITE,.14),1],[.55,c.skin,1],[.9,mix(c.skin,BLACK,.14),1],[.97,mix(c.skin,WHITE,.06),1],[1,mix(c.skin,BLACK,.2),1]])}</linearGradient><linearGradient id="${id}-lash" x1="0" y1="0" x2="0" y2="1">${stops([[0,mix(c.skin,BLACK,.5),1],[1,mix(c.skin,BLACK,.62),1]])}</linearGradient><linearGradient id="${id}-studio" x1="0" y1="0" x2="0" y2="1">${stops([[0,mix(c.tile,WHITE,.3),1],[.55,c.tile,1],[1,mix(c.tile,BLACK,.1),1]])}</linearGradient><radialGradient id="${id}-light" cx="0.45" cy="0.35" r="0.7">${stops([[0,WHITE,.22],[1,WHITE,0]])}</radialGradient><clipPath id="${id}-tile"><rect width="100" height="100" rx="22.22"/></clipPath><clipPath id="${id}-head"><path d="${HEAD}"/></clipPath><clipPath id="${id}-holes"><path d="${opening.d}"/></clipPath></defs>`,folds=[52.6,58.6,64].map((y,i)=>soft(id,`M19.5 ${y}Q23.5 ${y-.6} ${27-i} ${y+.8}`,"#000000",.32,1,"b8")+soft(id,`M80.5 ${y}Q76.5 ${y-.6} ${73+i} ${y+.8}`,"#000000",.38,1,"b8")+soft(id,`M18.6 ${y-3}Q21.5 ${y-3.6} 24.5 ${y-2.6}`,"#ffffff",.2,1.2,"b8")+soft(id,`M81.4 ${y-3}Q78.5 ${y-3.6} 75.5 ${y-2.6}`,"#ffffff",.1,1.2,"b8")).join(""),gather=band2?"":[-1,-.4,.4,1].map(s=>soft(id,`M50 16.4Q${r23(50+s*6)} 18.5 ${r23(50+s*11)} ${r23(24+Math.abs(s)*2)}`,"#000000",.28,.7,"b4")).join(""),head2=`<g filter="url(#${id}-fuzz)"><path d="${NECK}" fill="${knit}"/><path d="${NECK}" fill="url(#${id}-round)"/>`+soft(id,"M39.4 72.8Q50 75 60.6 72.8","#ffffff",.14,1.4,"b8")+soft(id,"M39 75.2Q50 77.6 61 75.2","#000000",.35,1.2,"b4")+"</g>"+clothes.over+`<ellipse cx="50" cy="70" rx="15" ry="3" fill="#000000" fill-opacity="0.42" filter="url(#${id}-b14)"/><g filter="url(#${id}-fuzz)"><path d="${HEAD}" fill="${knit}"/><path d="${HEAD}" fill="url(#${id}-ball)"/><path d="${HEAD}" fill="url(#${id}-under)"/><g clip-path="url(#${id}-head)">${folds}${gather}</g></g>`,skin=`<g ${OPEN}><path d="${opening.d}" fill="url(#${id}-skin)"/><g clip-path="url(#${id}-holes)">`+opening.eyes.map(e=>`<rect ${eyeRect(e,.3)} fill="none" stroke="${skinDark}" stroke-opacity="0.5" stroke-width="1.2" filter="url(#${id}-b4)"/>`).join("")+opening.eyes.map(e=>`<rect ${eyeRect(e,.5)} transform="translate(0 0.6)" fill="none" stroke="#ffffff" stroke-opacity="0.22" stroke-width="0.8" filter="url(#${id}-b4)"/>`).join("")+(opening.nose?soft(id,"M48.5 52Q50 57 47.5 58.5Q50 59.8 52.5 58.5Q50 57 51.5 52",skinDark,.8,.7,"b4"):"")+(opening.mouth?`<path d="M45.5 ${opening.nose?61.5:61.8}Q50 ${opening.nose?63.4:63.2} 54.5 ${opening.nose?61.5:61.8}" fill="none" stroke="${mix(c.skin,"#7a2d2d",.55)}" stroke-width="0.9" stroke-linecap="round"/>`:"")+`<path d="${opening.d}" fill="none" stroke="#000000" stroke-opacity="0.45" stroke-width="2.6" filter="url(#${id}-b8)"/></g></g>`;return{defs,back:`<g clip-path="url(#${id}-tile)"><rect width="100" height="100" fill="url(#${id}-studio)"/><rect width="100" height="100" fill="url(#${id}-light)"/>`+clothes.under+`<ellipse cx="50" cy="76.6" rx="12.5" ry="2.6" fill="#000000" fill-opacity="0.4" filter="url(#${id}-b14)"/>`+head2+skin+"</g>",live:(band2&&hat==="pompom"?pompomMarkup(id,band2):"")+`<g ${OPEN}>${eyesMarkup(id,mood,opening.eyes)}</g>`,front:`<g clip-path="url(#${id}-tile)"><g filter="url(#${id}-fuzz)"><g ${OPEN}><path d="${opening.d}" fill="none" stroke="${mix(c.mask,WHITE,.06)}" stroke-width="0.9"/><path d="${opening.d}" fill="none" stroke="${mix(c.mask,BLACK,.35)}" stroke-width="0.35" stroke-opacity="0.5"/></g></g>`+(band2?`<g clip-path="url(#${id}-head)">${soft(id,`M${along(band2.bottom,band2.x0,band2.x1,1.2)}`,"#000000",.5,3.6,"b14")}</g>`:"")+(band2?hatMarkup(id,hat,band2):"")+"</g>",blink:{period:r23(t.num("blink.period",3.6,6.2)),delay:r23(t.num("blink.delay",0,3))}}}function knitSvg(name,overrides){let k=createKnit(name,overrides);return`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">${k.defs}${k.back}${k.live}${k.front}</svg>`}var named6=list=>list.map(({name:label})=>({label})),controls10=(name,overrides)=>{let t=knitTraits(name,overrides),list=control=>narrowed(control,t,CALMING10);return[{title:"Knit",controls:[list(choice(t,"mood","Mood","list",named6(MOODS4))),list(choice(t,"hat","Hat","list",named6(HATS))),list(choice(t,"opening","Holes","list",named6(OPENINGS))),possibilitiesSlider(t,NOTES11),choice(t,"clothing","Clothes","list",named6(CLOTHING))]},{title:"Colour",controls:[...hatOf(t)==="none"?[]:[palette(t,"beanie","Beanie",BEANIES)],palette(t,"mask","Mask",MASKS),palette(t,"clothes","Clothes colour",CLOTHES),palette(t,"skin","Skin",SKINS2),palette(t,"tile","Background",TILES5)]}]};var CALMING11={features:/^eye\.(size|gap|y)$|^mouth\.(size|y)$|^(left|right)\.(x|y)$/,lists:{eyes:[12,8,[0,4,2,5,3,1,6,9,10,8,7,11]],mouth:[12,8,[0,1,4,3,2,5,6,8,7,9,10,11]]}},NOTES12=["round and matching eyes over a full grin, a tooth missing now and then.","more eyes and gaps, and the eyes and grin a little bigger or smaller.","every pair of eyes, googly ones too, and every gap, at any size."];var r24=value=>Math.round(value*100)/100,COLOURS3=["#8a49bd","#f76b4f","#425fe6","#f76cc0","#f7cf2a","#5ccd73","#20b8c9","#ff9a2e","#e94158","#7b5cf0"],INK3="#111114",WHITE3="#ffffff",round3=(size=1,look=[0,0])=>({kind:"round",size,look}),PAIRS=[{name:"Round",left:round3(1,[.1,0]),right:round3(1,[-.1,0])},{name:"Goggles",joined:"goggles",look:[0,-1]},{name:"Round & block",left:round3(1.05,[-.6,.35]),right:{kind:"block",look:[-.55,-.1]}},{name:"Bubbles",joined:"bubbles",look:[0,-.7]},{name:"Wink",left:round3(1,[0,0]),right:{kind:"wink"}},{name:"Block & round",left:{kind:"block",look:[.35,.2]},right:round3(1.05,[.55,-.4])},{name:"Lids",left:{kind:"lid",look:[0,-1]},right:{kind:"lid",look:[0,-1]}},{name:"Big & small",left:round3(1.2,[.4,.2]),right:round3(.72,[-.3,-.3])},{name:"Blocks",left:{kind:"block",look:[.5,0]},right:{kind:"block",look:[.5,0]}},{name:"Other wink",left:{kind:"wink"},right:round3(1,[-.2,.2])},{name:"Round & lid",left:round3(1,[.3,-.3]),right:{kind:"lid",look:[-.3,-1]}},{name:"Googly",left:round3(1.05,[-.7,-.5]),right:round3(1.05,[.7,.55])}],MOUTHS4=[{name:"Grin",width:1,height:1,gaps:[]},{name:"Gap",width:1,height:1,gaps:["fourth"]},{name:"Back left",width:1,height:1.04,gaps:[],corner:-1},{name:"Middle gap",width:.96,height:1.05,gaps:["middle"]},{name:"Front gap",width:1,height:1,gaps:["second"]},{name:"Back right",width:1.04,height:1,gaps:[],corner:1},{name:"Wide",width:1.16,height:.9,gaps:[]},{name:"Two gaps",width:1.04,height:1.04,gaps:["second","fourth"]},{name:"Small",width:.78,height:.86,gaps:["middle"]},{name:"Snaggle",width:1,height:1.06,gaps:["second"],corner:1},{name:"Chipped",width:1,height:1.02,gaps:[],chips:["second"]},{name:"Chipped back",width:1.02,height:1,gaps:[],chips:["fourth"],corner:-1}],grinTraits=(name,overrides)=>calmed(createTraits(name,overrides),CALMING11),pairOf=t=>t.pick("eyes",PAIRS),mouthOf2=t=>t.pick("mouth",MOUTHS4);function coloursOf9(t){return{body:t.color("body")??t.pick("body",COLOURS3)}}var roundnessOf=t=>t.forced("roundness")??0,EYE={r:10.6,gap:11.5,y:33};function eye2(spec,cx,cy,r,skew){let pupil=(look,reachX,reachY,size=r*.34)=>({cx:r24(cx+(look[0]+skew[0])*reachX),cy:r24(cy+(look[1]+skew[1])*reachY),r:r24(size),reach:r24(Math.min(reachX,reachY)*.5)});switch(spec.kind){case"round":{let s=r*spec.size;return{white:`<circle cx="${r24(cx)}" cy="${r24(cy)}" r="${r24(s)}"/>`,pupils:[pupil(spec.look,s*.5,s*.5,Math.max(2.8,s*.4))],cx,cy}}case"block":{let[w,h]=[r*2.3,r*1.36];return{white:`<rect x="${r24(cx-w/2)}" y="${r24(cy-h/2)}" width="${r24(w)}" height="${r24(h)}" rx="0.6"/>`,pupils:[pupil(spec.look,w*.34,h*.2,r*.4)],cx,cy}}case"lid":{let top=cy-r*.32,side=Math.sqrt(r*r-(r*.32)**2);return{white:`<path d="M${r24(cx-side)} ${r24(top)}H${r24(cx+side)}A${r24(r)} ${r24(r)} 0 0 1 ${r24(cx-side)} ${r24(top)}Z"/>`,pupils:[pupil(spec.look,r*.4,r*.3,r*.4)],cx,cy}}case"wink":return{white:`<path d="M${r24(cx-r*.8)} ${r24(cy+r*.25)}C${r24(cx-r*.45)} ${r24(cy-r*.38)} ${r24(cx+r*.42)} ${r24(cy-r*.5)} ${r24(cx+r*.86)} ${r24(cy+r*.22)}" fill="none" stroke="${WHITE3}" stroke-width="${r24(r*.2)}" stroke-linecap="round" stroke-linejoin="round"/>`,pupils:[],cx,cy}}}function pairMarkup(id,pair,t){let r=EYE.r*t.num("eye.size",.9,1.12),gap=EYE.gap*t.num("eye.gap",.95,1.12),y=EYE.y+t.jitter("eye.y",2.5),skew=key2=>[t.jitter(`${key2}.x`,.25),t.jitter(`${key2}.y`,.2)],blinks=[];if("joined"in pair){let look=[pair.look[0]+skew("left")[0],pair.look[1]+skew("left")[1]];if(pair.joined==="goggles"){let top=y-r*.55,lobe=gap*.98,white=`<path d="M${r24(50-gap-lobe)} ${r24(top)}H${r24(50+gap+lobe)}V${r24(top+r*.25)}A${r24(lobe)} ${r24(lobe*.95)} 0 0 1 50 ${r24(top+r*.25)}A${r24(lobe)} ${r24(lobe*.95)} 0 0 1 ${r24(50-gap-lobe)} ${r24(top+r*.25)}Z"/>`,pupils=[-1,1].map(side=>({cx:r24(50+side*gap+look[0]*2.4),cy:r24(top+Math.max(0,look[1]+1)*3),r:r24(r*.36),reach:1.4}));blinks.push({white,pupils,cx:50,cy:y})}else{let white=[-1,1].map(side=>`<circle cx="${r24(50+side*gap*.78)}" cy="${r24(y)}" r="${r24(r)}"/>`).join(""),pupils=[-1,1].map(side=>({cx:r24(50+side*gap*.78+look[0]*4),cy:r24(y+look[1]*r*.52),r:r24(r*.34),reach:2.6}));blinks.push({white,pupils,cx:50,cy:y})}}else blinks.push(eye2(pair.left,50-gap,y,r,skew("left")),eye2(pair.right,50+gap,y,r,skew("right")));return blinks.map((drawn,i)=>{let clip=`${id}-eye${i}`,stroke2=drawn.white.includes("stroke="),pupils=drawn.pupils.map(p=>`<circle class="pupil" style="--reach:${p.reach}" cx="${p.cx}" cy="${p.cy}" r="${p.r}" fill="${INK3}"/>`).join("");return`<g class="eye" data-eye="${i}">`+(stroke2?drawn.white:`<clipPath id="${clip}">${drawn.white}</clipPath><g fill="${WHITE3}">${drawn.white}</g><g clip-path="url(#${clip})">${pupils}</g>`)+"</g>"})}function mouthMarkup2(id,mouth3,t,lineColour){let w=28*mouth3.width*t.num("mouth.size",.92,1.08),h=27*mouth3.height*t.num("mouth.size",.92,1.08),top=50+t.jitter("mouth.y",2),n=t.int("teeth",4,6),clip=`${id}-mouth`,lobe=w*.28,dip=h*.27,half=w-lobe,shape=`M${r24(50-half)} ${r24(top)}C${r24(50-half*.55)} ${r24(top)} ${r24(50-half*.45)} ${r24(top+dip)} 50 ${r24(top+dip)}C${r24(50+half*.45)} ${r24(top+dip)} ${r24(50+half*.55)} ${r24(top)} ${r24(50+half)} ${r24(top)}A${r24(lobe)} ${r24(lobe)} 0 0 1 ${r24(50+w)} ${r24(top+lobe)}A${r24(w)} ${r24(h-lobe)} 0 0 1 ${r24(50-w)} ${r24(top+lobe)}A${r24(lobe)} ${r24(lobe)} 0 0 1 ${r24(50-w+lobe)} ${r24(top)}Z`,outline=`<path d="${shape}"/>`,focus=top-h*2.2,[above,below]=[top-4,top+h+4],through=(x,y)=>[50+(x-50)*(y-focus)/(top-focus),y],at3=i=>50-w+2*w*i/n,edge=i=>i<=0?50-w-12:i>=n?50+w+12:at3(i),side=(i,f2)=>{let[x1,y1]=through(edge(i),above),[x2,y2]=through(edge(i),below);return[x1+(x2-x1)*f2,y1+(y2-y1)*f2]},lines=Array.from({length:n-1},(_,i)=>{let[[x1,y1],[x2,y2]]=[side(i+1,0),side(i+1,1)];return`<path d="M${r24(x1)} ${r24(y1)}L${r24(x2)} ${r24(y2)}" stroke="${lineColour}" stroke-width="0.95"/>`}).join(""),tooth=i=>{let[a,b,c,d]=[side(i,0),side(i+1,0),side(i+1,1),side(i,1)];return`<path d="M${r24(a[0])} ${r24(a[1])}L${r24(b[0])} ${r24(b[1])}L${r24(c[0])} ${r24(c[1])}L${r24(d[0])} ${r24(d[1])}Z" fill="${INK3}"/>`},bottom=below,chip=i=>{let[from,to]=[side(i,.5),side(i+1,.6)],points=Array.from({length:9},(_,k)=>{let f2=k/8,lift=k===0||k===8?0:(k%2?-1:1)*h*.024*(.6+t(`chip.${i}.${k}`)*.8);return[from[0]+(to[0]-from[0])*f2,from[1]+(to[1]-from[1])*f2+lift]}),edgeLine=points.slice(1,-1).map(([x,y],k)=>{let[nx,ny]=points[k+2];return`Q${r24(x)} ${r24(y)} ${r24((x+nx)/2)} ${r24((y+ny)/2)}`}).join(""),[low,high]=[side(i,1),side(i+1,1)];return`<path d="M${r24(from[0])} ${r24(from[1])}${edgeLine}L${r24(to[0])} ${r24(to[1])}L${r24(high[0])} ${r24(high[1]+2)}L${r24(low[0])} ${r24(low[1]+2)}Z" fill="${INK3}"/>`},both2=[...mouth3.gaps,...mouth3.chips??[]].includes("second")&&n<5,index={second:1,middle:Math.floor((n-1)/2),fourth:both2?n-1:n-2},gaps=mouth3.gaps.map(gap=>tooth(index[gap])).join("")+(mouth3.chips??[]).map(gap=>chip(index[gap])).join(""),back=end=>tooth(end<0?0:n-1),corner=mouth3.corner?back(mouth3.corner):"";return`<clipPath id="${clip}">${outline}</clipPath><g fill="${WHITE3}">${outline}</g><g clip-path="url(#${clip})">${gaps}${corner}${lines}</g><path d="${shape}" fill="none" stroke="${lineColour}" stroke-width="0.5"/>`}function createGrin(name,overrides,id="grin"){let t=grinTraits(name,overrides),{body}=coloursOf9(t);return{body,corner:r24(96*(.2222+(.5-.2222)*roundnessOf(t))),eyes:pairMarkup(id,pairOf(t),t),mouth:mouthMarkup2(id,mouthOf2(t),t,body),blink:{period:r24(t.num("blink.period",3.2,5.6)),delay:r24(t.num("blink.delay",0,3))}}}var buttonMarkup=(body,corner)=>`<rect x="2" y="2" width="96" height="96" rx="${corner}" fill="${body}"/>`;function grinSvg(name,overrides){let g=createGrin(name,overrides);return`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">${buttonMarkup(g.body,g.corner)}${g.eyes.join("")}${g.mouth}</svg>`}var controls11=(name,overrides)=>{let t=grinTraits(name,overrides),list=control=>narrowed(control,t,CALMING11);return[{title:"Face",controls:[list(choice(t,"eyes","Eyes","list",PAIRS.map(({name:label})=>({label})))),list(choice(t,"mouth","Grin","list",MOUTHS4.map(({name:label})=>({label})))),possibilitiesSlider(t,NOTES12),{type:"slider",id:"roundness",label:"Roundness",value:roundnessOf(t),display:`${Math.round(roundnessOf(t)*100)}%`,range:[0,100],ends:["Tile","Circle"]},slider(t,"eye.size","Eye size",0,100,"%"),slider(t,"eye.gap","Eye gap",0,100,"%"),slider(t,"mouth.size","Grin size",0,100,"%"),choice(t,"teeth","Teeth","list",["4","5","6"].map(label=>({label})))]},{title:"Colour",controls:[palette(t,"body","Colour",COLOURS3)]}]};var CALMING12={features:/^(waist|tilt|body\.size|eye\.(size|gap))$|^(sparkle|burst|flower|cloud)\.n$/,lists:{shape:[9,8,[5,7,6,2,1,4,0,8,3]]}},NOTES13=["soft shapes like clouds, chips and stars, upright, even and middling in size.","more lean and size, and every point and lobe count.","every shape, up to bursts, at any lean and size."];var TILES6=["#ff2626","#ffe45e","#2bd467","#2f87f2","#b35cf6","#ff8a1f","#ff5aa5","#14c8bd","#6a5cff","#9be22d","#f5efe0"],NIGHTS=["#2a0f55","#0d2a5e","#4f1030","#083f37","#23252f"],FILLS=[{color:BLACK,weight:6},{color:"#1c1b4b",weight:.5},{color:"#3d1f0f",weight:.5},{color:"#0f3d2e",weight:.5},{color:WHITE,weight:.5},...["#ffd23d","#ff5a5f","#ff5ad6","#38f0c8","#36b6ff","#b6ff3d"].map(color=>({color,weight:1,bright:!0}))];var CELL=5,SOFTEN=4,round29=value=>Math.round(value*100)/100;function polar(degrees,radius){let radians=degrees*Math.PI/180;return`${round29(50+radius*Math.cos(radians))} ${round29(50+radius*Math.sin(radians))}`}function radial(tips,radius,waist,rotation2=-90){let step=360/tips,curves=Array.from({length:tips},(_,i)=>{let next=(i+1)%tips;return`Q${polar(rotation2+(i+.5)*step,waist)} ${polar(rotation2+next*step,radius(next))}`});return`M${polar(rotation2,radius(0))}${curves.join("")}Z`}function lobes(count,ring4,radius){let step=360/count,arcs=Array.from({length:count},(_,i)=>{let r=round29(radius(i));return`A${r} ${r} 0 1 1 ${polar(-90+(i+1)*step,ring4)}`});return`M${polar(-90,ring4)}${arcs.join("")}Z`}function stepped2(rows){let top=50-rows.length*CELL/2;return rows.map((half,i)=>`M${50-half*CELL} ${top+i*CELL}h${half*2*CELL}v${CELL}h${-half*2*CELL}z`).join("")}var SHAPES2=[{name:"Sparkle",pixel:!1,effect:"pop",count:{key:"sparkle.n",label:"Points",min:4,max:6},draw:(t,count)=>radial(count,()=>33,t.num("waist",8,13))},{name:"Wedge",pixel:!1,effect:"drop",eyeY:-8,draw:t=>radial(3,()=>31,t.num("waist",12,16),90)},{name:"Star",pixel:!1,effect:"pop",draw:t=>radial(5,()=>31,t.num("waist",12,17))},{name:"Burst",pixel:!1,effect:"spin",count:{key:"burst.n",label:"Spikes",min:12,max:17},draw:(t,count)=>radial(count,i=>31+t.jitter(`burst.r${i}`,3),t.num("waist",17,21))},{name:"Flower",pixel:!1,effect:"spin",count:{key:"flower.n",label:"Petals",min:5,max:7},draw:(t,count)=>radial(count,()=>17,t.num("waist",38,45))},{name:"Cloud",pixel:!1,effect:"drop",count:{key:"cloud.n",label:"Lobes",min:5,max:6},draw:(t,count)=>lobes(count,13,i=>11.5+t.num(`cloud.r${i}`,0,2.5)+t.num("waist",0,1))},{name:"Diamond",pixel:!0,effect:"hop",draw:t=>{let reach=t.int("waist",5,6);return stepped2(Array.from({length:reach*2+1},(_,i)=>reach+1-Math.abs(i-reach)))}},{name:"Chip",pixel:!0,effect:"hop",draw:t=>{let half=t.int("waist",6,7);return stepped2([half-2,half-1,half-1,half,half,half-1,half-1,half-2])}},{name:"Cross",pixel:!0,effect:"hop",draw:t=>{let arm=t.int("waist",2,3),reach=arm+4;return stepped2(Array.from({length:reach*2},(_,i)=>{let fromEnd=Math.min(i,reach*2-1-i);return fromEnd<3?arm:fromEnd===3?reach-1:reach}))}}],EYE_KINDS2=["Oval","Square","Pill"],shapeOf2=t=>t.pick("shape",SHAPES2);function fillOf2(t){let paint=FILLS[bandAt(FILLS,t("fill"))],picked=t.color("fill");return{bright:!picked&&!!paint.bright,color:picked??paint.color}}var tilesFor=bright=>bright?NIGHTS:TILES6;function eyeKindOf2(t,shape){let forced=t.forced("eyes.kind");return forced!==void 0?EYE_KINDS2[Math.floor(forced*EYE_KINDS2.length)]:shape.pixel?"Square":fillOf2(t).bright?"Pill":"Oval"}function drawEyes3(t,shape,paint){let kind=eyeKindOf2(t,shape),scale=t.num("eye.size",.85,1.25),gap=t.num("eye.gap",5.5,8.5),y=50+(shape.eyeY??0),[width,height]=(kind==="Pill"?[6.5,13]:[4,7]).map(v=>round29(v*scale));return[-gap,gap].map(offset=>{let x=round29(50+offset);if(kind==="Oval")return`<ellipse cx="${x}" cy="${y}" rx="${round29(3.3*scale)}" ry="${round29(4.8*scale)}" fill="${paint}"/>`;let corner=kind==="Pill"?` rx="${width/2}"`:"";return`<rect x="${round29(x-width/2)}" y="${round29(y-height/2)}" width="${width}" height="${height}"${corner} fill="${paint}"/>`}).join("")}var TILE_SHAPE3='<rect x="5" y="5" width="90" height="90" rx="20"/>',VIEW_BOX2="5 5 90 90";function createGlyph(name,overrides){let t=calmed(createTraits(name,overrides),CALMING12),shape=shapeOf2(t),{bright,color:paint}=fillOf2(t),tile=t.color("tile")??t.pick("tile",tilesFor(bright)),count=shape.count?t.int(shape.count.key,shape.count.min,shape.count.max):0,size=round29(t.num("body.size",.92,1.08)),tilt=round29(t.jitter("tilt",12)),finish=shape.pixel?'shape-rendering="crispEdges"':`transform="translate(50 50) rotate(${tilt}) scale(${size}) translate(-50 -50)" stroke="${paint}" stroke-width="${SOFTEN}" stroke-linejoin="round"`;return{tile,body:`<path d="${shape.draw(t,count)}" fill="${paint}" ${finish}/>`,eyes:drawEyes3(t,shape,bright?tile:inkOn(paint)),pixel:shape.pixel,effect:shape.effect,blinkDelay:t.num("blink",0,4)}}var glyphSvg=(name,overrides)=>{let glyph=createGlyph(name,overrides),tile=TILE_SHAPE3.replace("/>",` fill="${glyph.tile}"/>`);return`<svg xmlns="http://www.w3.org/2000/svg" viewBox="${VIEW_BOX2}">${tile}${glyph.body}${glyph.eyes}</svg>`};function fillControl(t){let picked=t.color("fill"),control=clearingColor(choice(t,"fill","Fill","swatches",FILLS.map(({color,weight})=>({label:color,weight,color}))),"fill");return{...control,selected:picked?"custom":control.selected,custom:{id:colorKey("fill"),color:picked??FILLS[Number(control.selected)].color}}}var controls12=(name,overrides)=>{let t=calmed(createTraits(name,overrides),CALMING12),shape=shapeOf2(t),{bright}=fillOf2(t),count=shape.count?[choice(t,shape.count.key,shape.count.label,"list",Array.from({length:shape.count.max-shape.count.min+1},(_,i)=>({label:String(shape.count.min+i)})))]:[];return[{title:"Colour",controls:[fillControl(t),palette(t,"tile","Tile",tilesFor(bright))]},{title:"Shape",controls:[possibilitiesSlider(t,NOTES13),narrowed(choice(t,"shape","Shape","list",SHAPES2.map(({name:label})=>({label}))),t,CALMING12),...count,...shape.pixel?[slider(t,"waist","Width",0,100,"%")]:[slider(t,"body.size","Body size",0,100,"%"),slider(t,"tilt","Tilt",-12,12,"\xB0"),slider(t,"waist","Waist",0,100,"%")]]},{title:"Eyes",controls:[automatic(t,"eyes.kind","Eyes",EYE_KINDS2,eyeKindOf2(t,shape)),slider(t,"eye.size","Eye size",0,100,"%"),slider(t,"eye.gap","Gap",0,100,"%")]}]};var GLOWS=[{label:"Mint",glow:"#3fe07a",accent:"#9df25c"},{label:"Sky",glow:"#4f8dff",accent:"#62e6ff"},{label:"Orchid",glow:"#a56bff",accent:"#ff7ee8"},{label:"Lagoon",glow:"#2fd6d0",accent:"#7fb4ff"},{label:"Peach",glow:"#ff9a5c",accent:"#ffd65c"},{label:"Rose",glow:"#ff6fa8",accent:"#ffb36b"},{label:"Lemon",glow:"#f2d33f",accent:"#8ff05c"},{label:"Iris",glow:"#6a63ff",accent:"#e07bff"},{label:"Coral",glow:"#ff6a6a",accent:"#ff9ee0"}],BODIES=[{name:"Bun",rx:38,ry:31,power:2.5,taper:.1,foot:.86},{name:"Tall",rx:27,ry:39,power:2.2,taper:.14,foot:.92},{name:"Ghost",rx:30,ry:36,power:3,taper:.06,foot:.96,hem:[3.5,.075]},{name:"Mochi",rx:44,ry:23,power:2.3,taper:.06,foot:.8},{name:"Pear",rx:31,ry:37,power:2.1,taper:.42,foot:.9},{name:"Puff",rx:35,ry:32,power:2,taper:.04,foot:.94,bumps:[7,.07]},{name:"Cube",rx:33,ry:31,power:4.2,taper:.03,foot:1,lean:8},{name:"Bell",rx:33,ry:35,power:2.7,taper:.34,foot:.8},{name:"Bean",rx:39,ry:26,power:2.3,taper:.1,foot:.9,bumps:[2,.13],lean:16},{name:"Drop",rx:29,ry:36,power:1.7,taper:.5,foot:1}],TOPPERS=[{name:"Crown",neck:15,d:"M-17 12Q-12 6 -12 -2L-11 -8Q-10 -10 -8 -8L-3 -3L2 -9Q3 -10 4 -9L9 -3L12 -8Q13 -9 13 -7L13 -2Q13 6 18 12Z"},{name:"Horn",neck:10,d:"M-13 12Q-5 6 -3.5 -3Q-2 -14 -1 -18Q0 -20 1 -18Q2 -14 3.5 -3Q5 6 13 12Z"},{name:"Ears",neck:25,d:"M-27 16Q-21 2 -20 -6Q-19 -10 -16 -10Q-9 -6 -6 2Q-4 8 1 12H-1Q4 8 6 2Q9 -6 16 -10Q19 -10 20 -6Q21 2 27 16Z"},{name:"Sprout",neck:8,d:"M-9 12Q-2 7 -1.3 0V-5Q-11 -5 -12 -14Q-3 -15 0 -7Q3 -15 12 -14Q11 -5 1.3 -5V0Q2 7 9 12Z"},{name:"Antenna",neck:8,d:"M-9 12Q-2 7 -1.4 0V-11H1.4V0Q2 7 9 12ZM-5.4 -14.5a5.4 5.4 0 1 1 10.8 0a5.4 5.4 0 1 1 -10.8 0Z"},{name:"Flame",neck:12,d:"M-15 12Q-7 7 -7 0Q-8 -5 -4 -8Q-4 -13 1 -18Q1 -11 6 -8Q9 -4 8 0Q8 7 15 12Z"},{name:"Horns",neck:19,d:"M-21 14Q-15 6 -14 -4Q-14 -11 -13 -14Q-8 -9 -7 -2Q-5 8 1 12H-1Q5 8 7 -2Q8 -9 13 -14Q14 -11 14 -4Q15 6 21 14Z"},{name:"Bow",neck:15,d:"M0 2Q-7 -10 -15 -8Q-17 -1 -15 6Q-7 7 0 2Q7 7 15 6Q17 -1 15 -8Q7 -10 0 2Z"},{name:"Bare",neck:0,d:""}],OUTLINE_POINTS2=360,CENTRE_Y=55,round210=value=>Math.round(value*100)/100,signedPower=(value,power)=>Math.sign(value)*Math.abs(value)**power,bodyOf=t=>t.pick("body",BODIES),topperOf=t=>t.pick("topper",TOPPERS);function coloursOf10(t){let picked=t.color("glow"),pair=t.pick("glow",GLOWS),glow=picked??pair.glow;return{glow,accent:t.color("accent")??(picked?mix(picked,WHITE,.35):pair.accent),ink:t.color("ink")??mix(glow,BLACK,.2)}}function drawOutline2(t,body){let size=t.num("body.size",.92,1.06),rx=body.rx*size,ry=body.ry*size,start=t.num("wave",0,2*Math.PI),lean=t.jitter("lean",body.lean??0)*Math.PI/180,points=Array.from({length:OUTLINE_POINTS2},(_,i)=>{let angle=i*2*Math.PI/OUTLINE_POINTS2,spread=1+(body.bumps?body.bumps[1]*Math.cos(body.bumps[0]*angle+start):0),x=rx*signedPower(Math.cos(angle),2/body.power)*spread,y=ry*signedPower(Math.sin(angle),2/body.power)*spread;return x*=1+body.taper*y/ry,y>0&&(y*=body.foot),body.hem&&y>0&&(y+=ry*body.hem[1]*Math.cos(body.hem[0]*2*Math.PI*x/(rx*2))*(y/ry)),[x*Math.cos(lean)-y*Math.sin(lean),x*Math.sin(lean)+y*Math.cos(lean)+CENTRE_Y]}),ys=points.map(([,y])=>y),top=Math.min(...ys),bottom=Math.max(...ys),peak=points[ys.indexOf(top)];return{d:`M${points.map(([x,y])=>`${round210(50+x)} ${round210(y)}`).join("L")}Z`,rx,ry:(bottom-top)/2,middle:(top+bottom)/2,top,peakX:50+peak[0]}}function drawDefs2(outline,glow,accent){let{d,ry,middle}=outline,top=round210(middle-ry),bottom=round210(middle+ry),blur2=(id,amount)=>`<filter id="${id}" filterUnits="userSpaceOnUse" x="-30" y="-30" width="160" height="160"><feGaussianBlur stdDeviation="${amount}"/></filter>`;return`<defs><path id="jelly-shape" d="${d}"/><mask id="jelly-inside" maskUnits="userSpaceOnUse" x="-30" y="-30" width="160" height="160"><use href="#jelly-shape" fill="#fff"/></mask><linearGradient id="jelly-frost" gradientUnits="userSpaceOnUse" x1="50" y1="${top}" x2="50" y2="${bottom}"><stop offset="0" stop-color="${mix(glow,WHITE,.9)}"/><stop offset="1" stop-color="${mix(glow,WHITE,.72)}"/></linearGradient><linearGradient id="jelly-sheen" gradientUnits="userSpaceOnUse" x1="50" y1="${top}" x2="50" y2="${round210(middle+ry*.1)}"><stop offset="0" stop-color="#fff" stop-opacity="0.85"/><stop offset="1" stop-color="#fff" stop-opacity="0"/></linearGradient><linearGradient id="jelly-pearl" x1="0.5" y1="1" x2="0.5" y2="0"><stop offset="0.3" stop-color="#ffffff"/><stop offset="0.52" stop-color="${mix(accent,WHITE,.55)}"/><stop offset="0.76" stop-color="${mix(glow,WHITE,.42)}"/><stop offset="1" stop-color="${mix(mix(glow,"#ff8ee0",.5),WHITE,.5)}"/></linearGradient>`+blur2("jelly-wide",8.5)+blur2("jelly-mid",4.6)+blur2("jelly-rim",2.4)+blur2("jelly-edge",.5)+"</defs>"}var pool=(cy,wide,tall,fill,blur2,opacity=1)=>`<ellipse cx="50" cy="${round210(cy)}" rx="${round210(wide)}" ry="${round210(tall)}" fill="${fill}" opacity="${opacity}" filter="url(#${blur2})"/>`;function layoutOf(t){let body=bodyOf(t),topper=topperOf(t),outline=drawOutline2(t,body);return{body,topper,outline,face:{x:round210(50+t.jitter("face.x",outline.rx*.2)),y:round210(outline.middle+t.num("face.y",-.42,-.08)*outline.ry),size:round210(t.num("face.size",.8,1.1)*Math.min(1,outline.rx/30)),tilt:round210(t.jitter("face.tilt",9))},crown:{x:round210(outline.peakX),y:round210(outline.top),scale:round210(t.num("topper.size",.85,1.1))}}}function jellyArt(t){let{topper,outline,crown:at3}=layoutOf(t),{glow,accent}=coloursOf10(t),crown=paint=>topper.d?`<path d="${topper.d}" transform="translate(${at3.x} ${at3.y}) scale(${at3.scale})" fill="${paint}" stroke="${paint}" stroke-width="1.2" stroke-linejoin="round"/>`:"",join=topper.d?`<mask id="jelly-whole" maskUnits="userSpaceOnUse" x="-30" y="-30" width="160" height="160"><use href="#jelly-shape" fill="#fff"/>${crown("#fff")}</mask><g mask="url(#jelly-whole)"><ellipse cx="${round210(outline.peakX)}" cy="${round210(outline.top+2)}" rx="${topper.neck}" ry="3.6" fill="#fff" filter="url(#jelly-rim)"/></g>`:"",{rx,ry,middle}=outline,size=t.num("pool",.86,1.08),light=pool(middle-ry*.5,rx*.8,ry*.42,accent,"jelly-wide",.22)+pool(middle+ry*.2,rx*.8*size,ry*.5*size,glow,"jelly-wide")+pool(middle+ry*.24,rx*.5*size,ry*.22*size,glow,"jelly-mid",.7)+pool(middle+ry*.64,rx*.56,ry*.12,accent,"jelly-mid",.75)+pool(middle+ry*.98,rx*.4,ry*.15,"#fff","jelly-mid");return drawDefs2(outline,glow,accent)+crown("url(#jelly-pearl)")+'<use href="#jelly-shape" fill="url(#jelly-frost)"/><g mask="url(#jelly-inside)">'+light+'<use href="#jelly-shape" fill="url(#jelly-sheen)"/><use href="#jelly-shape" fill="none" stroke="#fff" stroke-width="5.5" stroke-opacity="0.85" filter="url(#jelly-rim)"/><use href="#jelly-shape" fill="none" stroke="#fff" stroke-width="1.4" stroke-opacity="0.7" filter="url(#jelly-edge)"/></g>'+join}var FACE_LINE='fill="none" stroke-width="2.7" stroke-linecap="round" stroke-linejoin="round"';var CALMING13={features:/^(face|body|topper)\.(x|y|size|tilt)$|^(lean|pool|angle|frost)$/,lists:{body:[10,8,[0,3,1,4,7,6,2,5,8,9]],topper:[9,8,[8,3,7,2,0,4,1,5,6]],face:[12,8,[2,4,5,11,0,8,7,3,10,9,1,6]]}},NOTES14=["rounded buns and bells with gentle faces, the frost and glow in their middle range.","more lean, and the face moves about more.","every body, face and topper, up to dizzy faces and horns, at any frost and glow."];var gummyTraits=(name,overrides)=>calmed(createTraits(name,overrides),CALMING13),dot=(x,y,r=2.7)=>["dot",x,y,r],line=d=>["line",d],FACES2=[{name:"Wink",eyes:[dot(-9,-4),line("M12 -8L6 -4L12 0")],mouth:[line("M-11 7Q0 13 11 6"),line("M4 9.5Q5 16 10 14.5Q14 12 11 6")]},{name:"Deadpan",eyes:[line("M-16 -2L-5 -5"),line("M5 -5L16 -3")],mouth:[line("M0 3L5 11.5L-5 11.5Z")]},{name:"Happy",eyes:[line("M-13 0Q-9 -7 -5 0"),line("M5 0Q9 -7 13 0")],mouth:[line("M-5 6Q0 12 5 6")]},{name:"Wow",eyes:[dot(-9,-3,3),dot(9,-3,3)],mouth:[["ring",0,8,3.4,4.4]]},{name:"Sleepy",eyes:[line("M-13 -4Q-9 1 -5 -4"),line("M5 -4Q9 1 13 -4")],mouth:[dot(0,7,2)]},{name:"Cat",eyes:[dot(-10,-3),dot(10,-3)],mouth:[line("M-7 5Q-3.5 10 0 5Q3.5 10 7 5")]},{name:"Dizzy",eyes:[line("M-13 -6L-7 0"),line("M-7 -6L-13 0"),line("M7 -6L13 0"),line("M13 -6L7 0")],mouth:[line("M-5 8L5 8")]},{name:"Grin",eyes:[dot(-9,-4),dot(9,-4)],mouth:[line("M-8 4Q0 5 8 4Q6 13 0 13Q-6 13 -8 4Z")]},{name:"Smug",eyes:[line("M-14 -3Q-9 -1 -4 -3"),line("M4 -3Q9 -1 14 -3")],mouth:[line("M-6 7Q2 10.5 8 4")]},{name:"Pout",eyes:[dot(-9,-2),dot(9,-2)],mouth:[line("M-14 -8L-5 -6"),line("M5 -6L14 -8"),line("M-4 10Q0 6 4 10")]},{name:"Kiss",eyes:[line("M-13 -4Q-9 1 -5 -4"),dot(9,-3)],mouth:[line("M-1 3.5Q4.5 5 0.5 7.5Q4.5 10 -1 11.5")]},{name:"Shy",eyes:[dot(-8,-2,2),dot(8,-2,2)],mouth:[line("M-2.5 7Q0 9 2.5 7")]}],faceOf2=t=>t.pick("face",FACES2),frostOf=t=>t.num("frost",.74,.94),poolOf=t=>t.num("pool",.86,1.08);function coloursOf11(t){let colours=coloursOf10(t);return{...colours,ink:t.color("ink")??mix(colours.glow,BLACK,.55)}}var LINE_RADIUS=1.35,PIECE=2.5,round211=value=>Math.round(value*100)/100;function pointsOf(d){let tokens=d.match(/[MLQZ]|-?\d*\.?\d+/g),runs=[],run=[],i=0,next=()=>Number(tokens[i++]);for(;i<tokens.length;){let command=tokens[i++],from=run[run.length-1];if(command==="M")run=[[next(),next()]],runs.push(run);else if(command==="L")run.push([next(),next()]);else if(command==="Q"){let[cx,cy,x,y]=[next(),next(),next(),next()],pieces=Math.max(2,Math.ceil((Math.hypot(cx-from[0],cy-from[1])+Math.hypot(x-cx,y-cy))/PIECE));for(let s=1;s<=pieces;s++){let u=s/pieces,a=(1-u)**2,b=2*u*(1-u),c=u*u;run.push([a*from[0]+b*cx+c*x,a*from[1]+b*cy+c*y])}}else command==="Z"&&run.push(run[0])}return runs}var ringPoints=(cx,cy,rx,ry)=>{let pieces=Math.ceil(2*Math.PI*Math.max(rx,ry)/PIECE);return Array.from({length:pieces+1},(_,i)=>{let angle=i/pieces*2*Math.PI;return[cx+rx*Math.cos(angle),cy+ry*Math.sin(angle)]})},placer=({x,y,size,tilt})=>{let turn2=tilt*Math.PI/180,[c,s]=[Math.cos(turn2),Math.sin(turn2)];return([px,py])=>[x+size*(c*px-s*py),y+size*(s*px+c*py)]};function piecesOf(d){let tokens=d.match(/[MLQZ]|-?\d*\.?\d+/g),pieces=[],start=[0,0],at3=[0,0],i=0,next=()=>Number(tokens[i++]);for(;i<tokens.length;){let command=tokens[i++];if(command==="M")at3=start=[next(),next()];else if(command==="L"){let to=[next(),next()];pieces.push([at3,to]),at3=to}else if(command==="Q"){let control=[next(),next()],to=[next(),next()];pieces.push([at3,control,to]),at3=to}else command==="Z"&&(pieces.push([at3,start]),at3=start)}return pieces}function shapesOf(marks2,place2){let to=placer(place2),r=round211(LINE_RADIUS*place2.size),at3=point4=>to(point4).map(round211);return marks2.flatMap(mark=>{if(mark[0]==="dot"){let[cx,cy]=at3([mark[1],mark[2]]);return[{kind:"circle",cx,cy,r:round211(mark[3]*place2.size)}]}if(mark[0]==="ring"){let[cx,cy]=at3([mark[1],mark[2]]);return[{kind:"superellipse",cx,cy,rx:round211(mark[3]*place2.size),ry:round211(mark[4]*place2.size),n:2,rot:place2.tilt,stroke:r}]}return piecesOf(mark[1]).map(points=>{let[[x1,y1],[x2,y2]]=[at3(points[0]),at3(points[points.length-1])];if(points.length===2)return{kind:"rod",x1,y1,x2,y2,r};let[cx,cy]=at3(points[1]);return{kind:"curve",x1,y1,cx,cy,x2,y2,r}})})}var reachOf=marks2=>marks2.flatMap(mark=>{if(mark[0]==="dot"){let[,x,y,r]=mark;return[[x-r,y],[x+r,y],[x,y-r],[x,y+r]]}return mark[0]==="ring"?ringPoints(mark[1],mark[2],mark[3],mark[4]):pointsOf(mark[1]).flat()}),MARGIN2=1.18,FIT_STEPS=20;function insideOf(d){let outline=d.slice(1,-1).split("L").map(point4=>point4.split(" ").map(Number));return(x,y)=>{let within=!1;for(let a=0,b=outline.length-1;a<outline.length;b=a++){let[xa,ya]=outline[a],[xb,yb]=outline[b];ya>y!=yb>y&&x<(xb-xa)*(y-ya)/(yb-ya)+xa&&(within=!within)}return within}}function fitted(face,place2,outline){let inside=insideOf(outline.d),reach=reachOf([...face.eyes,...face.mouth]).map(([x,y])=>[x*MARGIN2,y*MARGIN2]),fit=place2;for(let step=0;step<FIT_STEPS;step++){let to=placer(fit);if(reach.every(point4=>inside(...to(point4))))break;fit={...fit,size:fit.size*.95,x:fit.x+(50-fit.x)*.15,y:fit.y+(outline.middle-fit.y)*.15}}return{x:round211(fit.x),y:round211(fit.y),size:round211(fit.size),tilt:fit.tilt}}var marksMarkup=marks2=>marks2.map(mark=>mark[0]==="dot"?`<circle cx="${mark[1]}" cy="${mark[2]}" r="${mark[3]}" fill="currentColor" stroke="none"/>`:mark[0]==="ring"?`<ellipse cx="${mark[1]}" cy="${mark[2]}" rx="${mark[3]}" ry="${mark[4]}"/>`:`<path d="${mark[1]}"/>`).join("");function placePath(d,x,y,scale){let tokens=d.match(/[a-zA-Z]|-?\d*\.?\d+/g)??[],out=[],i=0,next=()=>Number(tokens[i++]),at3=(value,offset)=>round211(value*scale+offset);for(;i<tokens.length;){let command=tokens[i++];if(command==="Z"||command==="z")out.push("Z");else if(command==="H")out.push(`H${at3(next(),x)}`);else if(command==="V")out.push(`V${at3(next(),y)}`);else if(command==="a"){let[rx,ry,turn2,large,sweep,dx,dy]=Array.from({length:7},next);out.push(`a${round211(rx*scale)} ${round211(ry*scale)} ${turn2} ${large} ${sweep} ${round211(dx*scale)} ${round211(dy*scale)}`)}else{let pairs=command==="Q"?2:1,values=[];for(let p=0;p<pairs;p++)values.push(at3(next(),x),at3(next(),y));out.push(`${command}${values.join(" ")}`)}}return out.join("")}function gummyParts(name,overrides){let t=gummyTraits(name,overrides),{topper,outline,face:placed3,crown}=layoutOf(t),face=faceOf2(t),place2=fitted(face,placed3,outline),{glow,accent,ink}=coloursOf11(t),eyeShapes=shapesOf(face.eyes,place2),eyePoints=eyeShapes.flatMap(shape=>shape.kind==="rod"||shape.kind==="curve"?[shape.y1,shape.y2]:"cy"in shape?[shape.cy]:[]);return{colors:{body:glow,accent,visor:glow,light:ink},head:[outline.d],accents:topper.d?[placePath(topper.d,crown.x,crown.y,crown.scale)]:[],visor:[],visorShapes:[],eyes:[],eyeShapes,lights:[],lightShapes:shapesOf(face.mouth,place2),chrome:[],chromeShapes:[],studs:[],studShapes:[],speckle:0,eyeY:eyePoints.reduce((sum,y)=>sum+y,0)/eyePoints.length,painted:!0,jelly:{frost:round211(frostOf(t)),pool:round211(poolOf(t))},container:containerOf(t)}}function gummySvg(name,overrides){let t=gummyTraits(name,overrides),{face:placed3,outline}=layoutOf(t),face=faceOf2(t),{glow,ink}=coloursOf11(t),{x,y,size,tilt}=fitted(face,placed3,outline),frost=frostOf(t),shell=[.06,-.12].map(by2=>mix(glow,WHITE,Math.min(1,frost+by2))),art=jellyArt(t).replace(/(<linearGradient id="jelly-frost"[^>]*><stop offset="0" stop-color=")[^"]+("\/><stop offset="1" stop-color=")[^"]+/,`$1${shell[0]}$2${shell[1]}`)+`<g transform="translate(${x} ${y}) rotate(${tilt}) scale(${size})" color="${ink}" stroke="${ink}" ${FACE_LINE}>${marksMarkup(face.eyes)}${marksMarkup(face.mouth)}</g>`;return inContainer(art,containerOf(t),"gummy-card")}var named7=list=>list.map(({name:label})=>({label})),controls13=(name,overrides)=>{let t=gummyTraits(name,overrides),list=control=>narrowed(control,t,CALMING13),{accent,ink}=coloursOf11(t);return[{title:"Face",controls:[list(choice(t,"face","Face","list",named7(FACES2))),slider(t,"face.size","Face size",0,100,"%"),slider(t,"face.y","Face height",0,100,"%"),slider(t,"face.x","Face across",-100,100,"%"),slider(t,"face.tilt","Face tilt",-9,9,"\xB0")]},{title:"Shape",controls:[possibilitiesSlider(t,NOTES14),list(choice(t,"body","Body","list",named7(BODIES))),list(choice(t,"topper","Topper","list",named7(TOPPERS))),slider(t,"body.size","Body size",0,100,"%"),...topperOf(t).d?[slider(t,"topper.size","Topper size",0,100,"%")]:[]]},{title:"Colour",controls:[palette(t,"glow","Colour",GLOWS.map(({glow})=>glow)),{type:"colors",id:"gummy.colors",label:"Topper, face",colors:[{id:colorKey("accent"),color:accent},{id:colorKey("ink"),color:ink}]},slider(t,"pool","Glow",0,100,"%"),slider(t,"frost","Frost",0,100,"%")]},{title:"Container",controls:containerControls(t)}]};var CALMING14={lists:{face:[12,8,[0,9,8,5,7,4,3,11,1,2,10,6]],pose:[4,2]},rarer:["blush"]},NOTES15=["only gentle, happy feelings, each type's own eyes, its arms or hands at rest, and no blush.","more feelings, cheeky ones too, other types' eyes, and the odd wave.","every feeling, sad, worried and grumpy too, every eye and every pose."];var mallowTraits=(name,overrides)=>calmed(createTraits(name,overrides),CALMING14),PASTELS=["#ffd6bf","#c2eed8","#fbe8ad","#f9cddc","#b5e7e3","#d9edb4","#c9d3fb"],oval2=(cx,cy,rx,ry)=>({kind:"superellipse",cx,cy,rx,ry,n:2,rot:0}),disc=(cx,cy,r)=>({kind:"circle",cx,cy,r}),line2=r=>({arc:(x1,y1,cx,cy,x2,y2)=>({kind:"curve",x1,y1,cx,cy,x2,y2,r}),bar:(x1,y1,x2,y2)=>({kind:"rod",x1,y1,x2,y2,r}),ring:(cx,cy,rx,ry)=>({kind:"superellipse",cx,cy,rx,ry,n:2,rot:0,stroke:r})}),both=draw2=>[draw2(-1),draw2(1)],open=(y,width,depth)=>({kind:"crescent",cx:0,cy:y,width,lift:0,thickness:depth}),BUN_LINE=.38,BUN_X=8.55,BUN_Y=-6,bun=line2(BUN_LINE),bunOvals=(dy=0,rx=1.8,ry=3)=>[oval2(-BUN_X,BUN_Y+dy,rx,ry),oval2(BUN_X,BUN_Y+dy,rx,ry)],bunSmile=(width=3.8,bow=2.3,y=-3.3)=>bun.arc(-width,y,0,y+bow*2,width,y),bunBrows=(y,lift)=>both(s=>bun.bar(s*(BUN_X+1.9),y,s*(BUN_X-1.8),y-lift)),BUN_FACES=[{name:"Content",eyes:bunOvals(),mouth:[bunSmile()]},{name:"Laugh",eyes:both(s=>bun.bar(s*10.2,-8.2,s*7.2,-6)).concat(both(s=>bun.bar(s*7.2,-6,s*10.2,-3.8))),mouth:[open(-3.6,3.9,3.6)]},{name:"Sad",eyes:bunOvals(.6,1.7,2.6),mouth:[bun.arc(-3,-.9,0,-4.7,3,-.9),...bunBrows(-9.6,1.4)]},{name:"Wow",eyes:bunOvals(-.3,2.1,3.3),mouth:[bun.ring(0,-1.4,1.4,1.8)]},{name:"Sleepy",eyes:both(s=>bun.arc(s*10.4,-6,s*8.55,-3.4,s*6.7,-6)),mouth:[bunSmile(2.2,1,-2.8)]},{name:"Joy",eyes:bunOvals(-.3),mouth:[open(-3.4,3.4,3.1)]},{name:"Grumpy",eyes:bunOvals(.7,1.8,2.3),mouth:[bun.bar(-2.6,-1.8,2.6,-1.8),...bunBrows(-10.6,-1.6)]},{name:"Wink",eyes:[oval2(-BUN_X,BUN_Y,1.8,3),bun.arc(6.7,-5.2,8.55,-8.6,10.4,-5.2)],mouth:[bunSmile(4.2,2.6)]},{name:"Shy",eyes:bunOvals(.9,1.5,2.4),mouth:[bunSmile(1.8,.8,-2.4)]},{name:"Bliss",eyes:both(s=>bun.arc(s*10.4,-5.2,s*8.55,-8.8,s*6.7,-5.2)),mouth:[bunSmile()]},{name:"Worried",eyes:bunOvals(.4,1.7,2.8),mouth:[bun.arc(-3.2,-2,-1.6,-3.4,0,-2),bun.arc(0,-2,1.6,-.6,3.2,-2),...bunBrows(-9.8,1)]},{name:"Cheeky",eyes:bunOvals(),mouth:[bun.arc(-3.2,-2.6,.6,-.4,3.8,-4.2)]}],GHOST_X=10.5,GHOST_Y=-7,ghost=line2(.62),lid=line2(.85),ghostEyes=(dy=0,rx=4.4,ry=5.6)=>{let at3=side=>[side*GHOST_X,GHOST_Y+dy];return{eyes:both(s=>oval2(...at3(s),rx,ry)),shine:both(s=>disc(at3(s)[0]+rx*.34,at3(s)[1]-ry*.42,rx*.3))}},ghostSmile=(width=2.6,bow=1.4,y=-2.2)=>ghost.arc(-width,y,0,y+bow*2,width,y),ghostLids=bow=>both(s=>lid.arc(s*GHOST_X-3.2,GHOST_Y+bow/2,s*GHOST_X,GHOST_Y-bow*1.5,s*GHOST_X+3.2,GHOST_Y+bow/2)),ghostBrows=(y,lift)=>both(s=>ghost.bar(s*(GHOST_X+3.2),y,s*(GHOST_X-2.4),y-lift)),tongue=(y,width,depth)=>oval2(0,y+depth*.62,width*.42,depth*.27),GHOST_FACES=[{name:"Content",...ghostEyes(),mouth:[ghostSmile()]},{name:"Laugh",eyes:ghostLids(2.2),mouth:[open(-2.6,3.2,3.4)],tint:[tongue(-2.6,3.2,3.4)]},{name:"Sad",...ghostEyes(1,4,4.8),mouth:[ghost.arc(-2.4,0,0,-3,2.4,0),...ghostBrows(-14.4,1.4)]},{name:"Wow",...ghostEyes(-.4,4.8,6.2),mouth:[ghost.ring(0,.2,1.5,1.9)]},{name:"Sleepy",eyes:ghostLids(-1.9),mouth:[ghostSmile(1.6,.8,-1.4)]},{name:"Joy",...ghostEyes(-.3),mouth:[open(-2.4,2.6,3)],tint:[tongue(-2.4,2.6,3)]},{name:"Grumpy",...ghostEyes(.8,4.2,4.6),mouth:[ghost.bar(-2,-1.4,2,-1.4),...ghostBrows(-15.6,-1.8)]},{name:"Wink",eyes:[oval2(-GHOST_X,GHOST_Y,4.4,5.6),lid.arc(GHOST_X-3.2,GHOST_Y+1.1,GHOST_X,GHOST_Y-3.3,GHOST_X+3.2,GHOST_Y+1.1)],shine:[disc(-GHOST_X+1.5,GHOST_Y-2.35,1.32)],mouth:[ghostSmile(3,1.7)]},{name:"Shy",...ghostEyes(1,3.6,4.6),mouth:[ghostSmile(1.6,.7,-1.2)]},{name:"Bliss",eyes:ghostLids(2),mouth:[ghostSmile()]},{name:"Worried",...ghostEyes(.6,4.2,5.2),mouth:[ghost.arc(-2.6,-1.2,-1.3,-2.4,0,-1.2),ghost.arc(0,-1.2,1.3,0,2.6,-1.2),...ghostBrows(-14.6,1)]},{name:"Cheeky",...ghostEyes(),mouth:[ghost.arc(-2.6,-1.8,.6,.4,3,-3.2)]}],CLOUD_X=7.6,CLOUD_Y=-2.5,cloud2=line2(.55),brow2=line2(.42),cloudLid=line2(.7),cloudEyes=([lx,ly],size=1,only)=>{let sides=only===void 0?[-1,1]:[only],pupil=s=>[s*CLOUD_X+lx*2,CLOUD_Y+ly*2];return{white:sides.map(s=>oval2(s*CLOUD_X,CLOUD_Y,5.6,6.2)),eyes:sides.map(s=>oval2(...pupil(s),3.3*size,3.9*size)),shine:sides.map(s=>disc(pupil(s)[0]+1.1*size,pupil(s)[1]-1.5*size,1.05*size))}},cloudBrows=(lift=0)=>both(s=>brow2.arc(s*(CLOUD_X+3.4),CLOUD_Y-7.6,s*(CLOUD_X+1.2),CLOUD_Y-9.8,s*(CLOUD_X-1.4),CLOUD_Y-9.6-lift)),cloudLids=(bow,sides=[-1,1])=>sides.map(s=>cloudLid.arc(s*CLOUD_X-3.4,CLOUD_Y+bow/2,s*CLOUD_X,CLOUD_Y-bow*1.5,s*CLOUD_X+3.4,CLOUD_Y+bow/2)),cloudSmile=(width=2.6,bow=1.1,y=5.8)=>cloud2.arc(-width,y,.3,y+bow*2,width+.6,y-.8),winking=()=>{let{white,eyes:eyes2,shine}=cloudEyes([.3,-.3],1,-1);return{white,shine,eyes:[...eyes2,...cloudLids(2.2,[1])]}},CLOUD_FACES=[{name:"Content",...cloudEyes([.45,-.45]),mouth:[cloudSmile(),...cloudBrows()]},{name:"Laugh",eyes:cloudLids(2.4),mouth:[open(4.6,3,3.2),...cloudBrows(.4)],tint:[tongue(4.6,3,3.2)]},{name:"Sad",...cloudEyes([0,.55]),mouth:[cloud2.arc(-2.4,7.4,0,4.6,2.4,7.4),...cloudBrows(1.6)]},{name:"Wow",...cloudEyes([0,0],.85),mouth:[cloud2.ring(0,7.2,1.4,1.8),...cloudBrows(1)]},{name:"Sleepy",eyes:cloudLids(-2.1),mouth:[cloud2.arc(-1.4,5.6,0,6.8,1.4,5.6),...cloudBrows()]},{name:"Joy",...cloudEyes([.2,-.5]),mouth:[open(4.8,2.6,2.9),...cloudBrows(.6)],tint:[tongue(4.8,2.6,2.9)]},{name:"Grumpy",...cloudEyes([0,.2]),mouth:[cloud2.bar(-2,6,2,6),...cloudBrows(-1.8)]},{name:"Wink",...winking(),mouth:[cloudSmile(2.9,1.3),...cloudBrows()]},{name:"Shy",...cloudEyes([-.5,.45]),mouth:[cloudSmile(1.6,.6),...cloudBrows(.6)]},{name:"Bliss",eyes:cloudLids(2.2),mouth:[cloudSmile(),...cloudBrows()]},{name:"Worried",...cloudEyes([0,-.1]),mouth:[cloud2.arc(-2.6,6.2,-1.3,5,0,6.2),cloud2.arc(0,6.2,1.3,7.4,2.6,6.2),...cloudBrows(1.4)]},{name:"Cheeky",...cloudEyes([.6,0]),mouth:[cloud2.arc(-2.6,6,.6,8,3.4,4.6),...cloudBrows(-.6)]}],WAVING=[.94,-.12,.34,.17,-62],GHOST_WAVING=[.98,-.42,.32,.16,-75],CLOUD_FEET=[[-.29,1.02,.2,.12,0],[.37,1.02,.21,.12,0]],TYPES2=[{name:"Bun",colour:"#c4e2f4",ink:"#2e3850",body:{rx:220,ry:230,top:2.15,base:3,taper:.05,dips:[0],dip:.1,width:.25},tint:"#f2a7b8",poses:[{name:"Rest",arms:[-1,1].map(side=>[side*1.1,.33,.35,.18,side*70]),hands:[]},{name:"Out",arms:[-1,1].map(side=>[side*1.16,.22,.3,.17,side*25]),hands:[]},{name:"Cheer",arms:[-1,1].map(side=>[side*1.08,-.15,.33,.18,side*-55]),hands:[]},{name:"Wave",arms:[[-1.1,.33,.35,.18,-70],[1.08,-.15,.33,.18,-55]],hands:[]}],blush:both(s=>oval2(s*(BUN_X+1.2),BUN_Y+5.2,2.1,1.05)),eyes:{x:BUN_X,y:BUN_Y,h:3},unit:1/22,faces:BUN_FACES},{name:"Ghost",colour:"#c6b6f6",ink:"#2b1818",tint:"#f07888",body:{rx:30,ry:33,top:2.2,base:4.5,taper:.07,dips:[-.5,0,.5],dip:.13,width:.19},poses:[{name:"Rest",arms:[],hands:[[-.8,.42,.26,.21,-28],[.84,.22,.22,.25,18]]},{name:"Low",arms:[],hands:[[-.86,.6,.22,.2,-10],[.88,.55,.22,.2,10]]},{name:"Hug",arms:[],hands:[[-.55,.32,.21,.19,-25],[.58,.28,.2,.21,25]]},{name:"Wave",arms:[GHOST_WAVING],hands:[[-.8,.42,.26,.21,-28]]}],blush:both(s=>oval2(s*(GHOST_X+2.6),GHOST_Y+7,2.6,1.3)),eyes:{x:GHOST_X,y:GHOST_Y,h:5.6},unit:1/30,faces:GHOST_FACES},{name:"Cloud",colour:"#82b8ee",ink:"#1d1515",tint:"#ef6f80",body:{rx:30,ry:27,top:2,base:2,taper:0,dips:[],dip:0,width:1,lobes:[[-2.4,-9.5,17],[17.4,-10.3,10.3],[-18.1,1.6,11.8],[21.3,3.2,9.5],[-7,9.2,17.6],[8,9.6,17.4]]},poses:[{name:"Rest",arms:CLOUD_FEET,hands:[[-.43,.47,.22,.2,-30],[.71,.35,.19,.22,15]]},{name:"Low",arms:CLOUD_FEET,hands:[[-.55,.72,.2,.18,-10],[.6,.7,.2,.18,10]]},{name:"Chin",arms:CLOUD_FEET,hands:[[-.43,.47,.22,.2,-30],[.16,.5,.19,.17,5]]},{name:"Wave",arms:[...CLOUD_FEET,WAVING],hands:[[-.43,.47,.22,.2,-30]]}],blush:both(s=>oval2(s*(CLOUD_X+3.5),CLOUD_Y+7,2.2,1.1)),eyes:{x:CLOUD_X,y:CLOUD_Y,h:6.2},unit:1/30,faces:CLOUD_FACES}],FEELINGS2=BUN_FACES.map(({name})=>name);function typeOf2(name,overrides){let{t,step}=named8(name,overrides),own2=TYPES2.indexOf(t.pick("type",TYPES2));return TYPES2[t.forced("type")===void 0?(own2+step)%TYPES2.length:own2]}function named8(name,overrides){let variant=/^(.*)#(\d+)$/.exec(name),from=variant?variant[1]:name;return{from,t:createTraits(from,overrides),step:variant?Number(variant[2])-1:0}}var faceOf3=(t,type)=>type.faces[Math.floor(t("face")*type.faces.length)];function eyesOf(name,overrides,type){let{t,step}=named8(name,overrides),set=t.forced("eyes");if(set!==void 0)return TYPES2[Math.min(TYPES2.length-1,Math.floor(set*TYPES2.length))];let value=t("eyes"),variance=varianceSet(t),kept=variance===void 0?TYPES2.length:keptOf(TYPES2.length,1,variance),along2=((value<.5?0:value<.75?1:2)+step)%kept;return TYPES2[(TYPES2.indexOf(type)+along2)%TYPES2.length]}function borrowed(shape,from,to){let side=(shape.kind==="rod"||shape.kind==="curve"?shape.x1+shape.x2:shape.cx)<0?-1:1,size=to.eyes.h/from.eyes.h;return placed2(shape,side*(to.eyes.x-from.eyes.x*size),to.eyes.y-from.eyes.y*size,size)}var POSE_COUNT=4;function poseOf3(name,overrides){let{from,step}=named8(name,overrides),t=mallowTraits(from,overrides),own2=Math.floor(t("pose")*POSE_COUNT),variance=varianceSet(t);return t.forced("pose")!==void 0?own2:(own2+step)%(variance===void 0?POSE_COUNT:keptOf(POSE_COUNT,2,variance))}var BLUSH_PERCENT2=30,blushes=t=>t("blush")*100<BLUSH_PERCENT2,coloursFor=type=>[type.colour,...PASTELS];function coloursOf12(t,type){return{body:t.color("colour")??type.colour,ink:t.color("ink")??type.ink,tint:t.color("tint")??type.tint}}var OUTLINE_POINTS3=240,SPAN=82,round212=value=>Math.round(value*100)/100,signedPower2=(value,power)=>Math.sign(value)*Math.abs(value)**power;function outlineOf({rx,ry,top,base,taper:taper2,dips,dip,width}){return Array.from({length:OUTLINE_POINTS3},(_,i)=>{let angle=i/OUTLINE_POINTS3*2*Math.PI,sin=Math.sin(angle),power=sin<0?top:base,x=rx*signedPower2(Math.cos(angle),2/power),y=ry*signedPower2(sin,2/power),down=y/ry;if(x*=1+taper2*down,down>0){let across=x/(rx*(1+taper2)),near=dips.reduce((sum,at3)=>sum+Math.exp(-(((across-at3)/width)**2)),0);y-=ry*dip*Math.min(1,near)*down**6}return[x,y]})}function pieceOf([x,y,rx,ry,turn2],body){let[c,s]=[Math.cos(turn2*Math.PI/180),Math.sin(turn2*Math.PI/180)];return Array.from({length:96},(_,i)=>{let angle=i/96*2*Math.PI,[px,py]=[rx*body.rx*Math.cos(angle),ry*body.rx*Math.sin(angle)];return[x*body.rx+c*px-s*py,y*body.ry+s*px+c*py]})}function placed2(shape,x,y,size){let to=(px,py)=>[round212(x+size*px),round212(y+size*py)],by2=value=>round212(value*size);switch(shape.kind){case"superellipse":{let[cx,cy]=to(shape.cx,shape.cy);return{...shape,cx,cy,rx:by2(shape.rx),ry:by2(shape.ry),...shape.stroke?{stroke:by2(shape.stroke)}:{}}}case"circle":{let[cx,cy]=to(shape.cx,shape.cy);return{...shape,cx,cy,r:by2(shape.r)}}case"rod":{let[x1,y1]=to(shape.x1,shape.y1),[x2,y2]=to(shape.x2,shape.y2);return{...shape,x1,y1,x2,y2,r:by2(shape.r)}}case"curve":{let[x1,y1]=to(shape.x1,shape.y1),[cx,cy]=to(shape.cx,shape.cy),[x2,y2]=to(shape.x2,shape.y2);return{...shape,x1,y1,cx,cy,x2,y2,r:by2(shape.r)}}case"crescent":{let[cx,cy]=to(shape.cx,shape.cy);return{...shape,cx,cy,width:by2(shape.width),thickness:by2(shape.thickness)}}}}var pathOf=points=>`M${points.map(([x,y])=>`${round212(x)} ${round212(y)}`).join("L")}Z`;function figureOf(type){let{body}=type,outlines=body.lobes?.map(([x2,y2,r])=>pieceOf([x2/body.rx,y2/body.ry,r/body.rx,r/body.rx,0],body))??[outlineOf(body)],poses=type.poses.map(({arms,hands})=>({arms:arms.map(piece=>pieceOf(piece,body)),hands:hands.map(piece=>pieceOf(piece,body))})),all=[...outlines.flat(),...poses[0].arms.flat(),...poses[0].hands.flat()],[left,right]=[Math.min(...all.map(([x2])=>x2)),Math.max(...all.map(([x2])=>x2))],[high,low]=[Math.min(...all.map(([,y2])=>y2)),Math.max(...all.map(([,y2])=>y2))],scale=SPAN/Math.max(right-left,low-high),frame=([x2,y2])=>[50+(x2-(left+right)/2)*scale,50+(y2-(high+low)/2)*scale],[x,y]=frame([0,0]);return{body:outlines.map(outline=>pathOf(outline.map(frame))),poses:poses.map(({arms,hands})=>({arms:arms.map(piece=>pathOf(piece.map(frame))),hands:hands.map(piece=>pathOf(piece.map(frame)))})),middle:{x:round212(x),y:round212(y)},unit:type.unit*type.body.rx*scale,top:round212(frame([0,high])[1]),bottom:round212(frame([0,low])[1])}}var FIGURES=new Map(TYPES2.map(type=>[type,figureOf(type)]));function describe2(name,overrides){let t=mallowTraits(name,overrides),type=typeOf2(name,overrides),figure=FIGURES.get(type),face=faceOf3(t,type),from=eyesOf(name,overrides,type),eyeFace=faceOf3(t,from),own2=shape=>from===type?shape:borrowed(shape,from,type),at3=shape=>placed2(shape,figure.middle.x,figure.middle.y,figure.unit);return{t,type,figure,pose:figure.poses[poseOf3(name,overrides)],eyes:eyeFace.eyes.map(own2).map(at3),mouth:face.mouth.map(at3),shine:(eyeFace.shine??[]).map(own2).map(at3),tint:[...face.tint??[],...blushes(t)?type.blush:[]].map(at3),white:(eyeFace.white??[]).map(own2).map(at3),colours:coloursOf12(t,type)}}var middleOf=shape=>shape.kind==="rod"||shape.kind==="curve"?(shape.y1+shape.y2)/2:shape.cy;function mallowParts(name,overrides){let{t,figure,pose,eyes:eyes2,mouth:mouth3,shine,tint,white,colours}=describe2(name,overrides);return{colors:{body:colours.body,accent:colours.body,visor:colours.tint,light:colours.ink},head:figure.body,accents:pose.arms,visor:[],visorShapes:[],eyes:[],eyeShapes:eyes2,lights:[],lightShapes:mouth3,chrome:[],chromeShapes:[],studs:[],studShapes:[],speckle:0,eyeY:round212(eyes2.reduce((sum,shape)=>sum+middleOf(shape),0)/eyes2.length),painted:!0,matte:!0,raised:pose.hands,shineShapes:shine,tintShapes:tint,whiteShapes:white,container:containerOf(t)}}function markupOf(shape){let stroked=shape.kind==="superellipse"&&shape.stroke?` fill="none" stroke="currentColor" stroke-width="${round212(shape.stroke*2)}"`:"";return`<path d="${shapePath(shape)}"${stroked}/>`}function mallowSvg(name,overrides){let{t,type,figure,pose,eyes:eyes2,mouth:mouth3,shine,tint,white,colours}=describe2(name,overrides),{body,ink}=colours,clay=d=>`<path d="${d}"/>`,art=`<defs><linearGradient id="mallow-clay" gradientUnits="userSpaceOnUse" x1="50" y1="${figure.top}" x2="50" y2="${figure.bottom}"><stop offset="0" stop-color="${mix(body,WHITE,.4)}"/><stop offset="0.55" stop-color="${body}"/><stop offset="1" stop-color="${mix(body,type.ink,.12)}"/></linearGradient></defs><g fill="url(#mallow-clay)">${[...pose.arms,...figure.body].map(clay).join("")}<g fill="${mix(body,WHITE,.22)}" stroke="${mix(body,type.ink,.2)}" stroke-width="0.6">${pose.hands.map(clay).join("")}</g></g><g fill="#f2ede0">${white.map(markupOf).join("")}</g><g fill="${ink}" color="${ink}">${[...eyes2,...mouth3].map(markupOf).join("")}</g><g fill="${colours.tint}">${tint.map(markupOf).join("")}</g><g fill="#ffffff">${shine.map(markupOf).join("")}</g>`;return inContainer(art,containerOf(t),"mallow-card")}var EYES3=["Bun's","Ghost's","Cloud's"],controls14=(name,overrides)=>{let t=mallowTraits(name,overrides),type=typeOf2(name,overrides),{ink,tint}=coloursOf12(t,type);return[{title:"Face",controls:[{...choice(t,"type","Type","list",TYPES2.map(({name:label})=>({label}))),selected:String(TYPES2.indexOf(type))},narrowed(choice(t,"face","Feeling","list",FEELINGS2.map(label=>({label}))),t,CALMING14),{...choice(t,"eyes","Eyes","list",EYES3.map(label=>({label}))),selected:String(TYPES2.indexOf(eyesOf(name,overrides,type)))},possibilitiesSlider(t,NOTES15),{...narrowed(choice(t,"pose","Pose","list",type.poses.map(({name:label})=>({label}))),t,CALMING14),selected:String(poseOf3(name,overrides))},toggle(t,"blush",BLUSH_PERCENT2,"Blush")]},{title:"Colour",controls:[fixedPalette(t,"colour","Colour",coloursFor(type)),{type:"colors",id:"mallow.ink",label:"Face, pink",colors:[{id:colorKey("ink"),color:ink},{id:colorKey("tint"),color:tint}]}]},{title:"Container",controls:containerControls(t)}]};var CALMING15={features:/^(body\.size|eye\.(size|ratio|gap)|brow\.y|fluff|tilt|bumps|angle)$/,lists:{body:[9,8,[7,2,0,1,3,8,6,5,4]],pose:[9,8,[0,3,6,2,5,4,7,8,1]],"eye.kind":[3,1]}},NOTES16=["smooth bodies peeking from a corner or the side, glossy eyes, barely turned.","more eye styles, depth and turn.","every body and pose, up to spikes and hanging upside down, at any turn."];var TILES7=["#3f4ff0","#7a3dff","#0fa3b1","#ff4f8b","#ff7a1a","#17a85a","#e8344a","#1f2a6b","#c23dd6"];var EYE_KINDS3=["Glossy","Sleepy","Tiny"],FORMATIONS=[{label:"Pair",weight:5},{label:"Close",weight:2},{label:"Wide",weight:2},{label:"One",weight:1.5},{label:"Three",weight:1.5}],POSES3=[{name:"Corner",x:68,y:96,size:60,eyeX:62,eyeY:67,lean:-9,effect:"peek"},{name:"Hanging",x:50,y:-14,size:66,eyeX:50,eyeY:33,lean:4,effect:"wobble"},{name:"Right",x:106,y:56,size:67,eyeX:67,eyeY:53,lean:-7,effect:"peek"},{name:"Other corner",x:32,y:96,size:60,eyeX:38,eyeY:67,lean:9,effect:"pop"},{name:"Top corner",x:76,y:2,size:62,eyeX:66,eyeY:32,lean:8,effect:"wobble"},{name:"Left",x:-6,y:56,size:67,eyeX:33,eyeY:53,lean:7,effect:"peek"},{name:"Rising",x:50,y:112,size:70,eyeX:50,eyeY:67,lean:-3,effect:"pop"},{name:"Top left",x:24,y:2,size:62,eyeX:34,eyeY:32,lean:-8,effect:"wobble"},{name:"Whole",x:50,y:54,size:31,eyeX:50,eyeY:54,lean:-5,effect:"pop"}],bump=(angle,at3,width,height)=>{let away=Math.atan2(Math.sin(angle-at3),Math.cos(angle-at3));return height*Math.exp(-((away/width)**2))},BODIES2=[{name:"Fluffy",counted:!0,shape:(a,depth,count,start)=>depth*Math.cos(count*a+start)+.03*Math.cos(3*a+start)},{name:"Ears",shape:(a,depth)=>bump(a,-.42,.17,depth*4.4)+bump(a,.42,.17,depth*4.4)},{name:"Swell",shape:(a,depth,_count,start)=>depth*2.4*Math.cos(3*a+start)+depth*.9*Math.cos(5*a+start*2)},{name:"Tuft",shape:(a,depth)=>bump(a,0,.14,depth*6)+bump(a,-.3,.09,depth*3.2)+bump(a,.32,.1,depth*3.6)},{name:"Spiky",counted:!0,shape:(a,depth,count,start)=>depth*1.1*(Math.abs(Math.sin(((count+5)*a+start)/2))*2-1)},{name:"Horns",shape:(a,depth)=>bump(a,-.62,.1,depth*5.4)+bump(a,.62,.1,depth*5.4)},{name:"Drips",shape:(a,depth,_count,_start,pick)=>[-.9,-.45,0,.5,.95].reduce((sum,at3,i)=>sum+bump(a,at3+pick(i)*.1,.11,depth*(2.5+pick(i+5)*3)),0)},{name:"Dome",shape:(a,depth)=>depth*.4*Math.cos(2*a)+bump(a,0,.5,depth*2.2)},{name:"Lumpy",shape:(a,depth,_count,start)=>depth*1.7*Math.cos(2*a+start)+depth*1.3*Math.cos(3*a+start*3)+depth*Math.cos(7*a+start*5)}],VIEW_BOX3="5 5 90 90",TILE_SHAPE4='<rect x="5" y="5" width="90" height="90" rx="20"/>',OUTLINE_POINTS4=360,RINGS=3,RING_STEP=.13,SPARKLE="M0-1Q.12-.12 1 0Q.12 .12 0 1Q-.12 .12-1 0Q-.12-.12 0-1Z",NATURAL_ANGLE=32,FACE_EDGE=9,round213=value=>Math.round(value*100)/100,poseOf4=t=>t.pick("pose",POSES3),bodyOf2=t=>t.pick("body",BODIES2),eyeKindOf3=t=>t.pick("eye.kind",EYE_KINDS3),angleOf=t=>turnOf(t,NATURAL_ANGLE);function formationOf(t){let position=t("eye.formation"),total=FORMATIONS.reduce((sum,{weight})=>sum+weight,0),edge=0;for(let{label,weight}of FORMATIONS)if(edge+=weight/total,position<edge)return label;return FORMATIONS[0].label}function coloursOf13(t){let tile=t.color("tile")??t.pick("tile",TILES7);return{tile,body:t.color("body")??mix(tile,WHITE,.86),iris:t.color("iris")??mix(tile,BLACK,.66)}}function drawOutline3(t,pose,body,grown){let size=pose.size*t.num("body.size",.92,1.08),depth=t.num("fluff",.04,.09),count=t.int("bumps",5,9),start=t.num("wave",0,2*Math.PI)+grown*2.4,pick=i=>t(`body.pick${i}`),facing=pose.x===50&&pose.y===54?-Math.PI/2:Math.atan2(54-pose.y,50-pose.x);return`M${Array.from({length:OUTLINE_POINTS4},(_,i)=>{let angle=i*2*Math.PI/OUTLINE_POINTS4,r=size*(1+grown)*(1+body.shape(angle-facing,depth,count,start,pick));return`${round213(pose.x+r*Math.cos(angle))} ${round213(pose.y+r*Math.sin(angle))}`}).join("L")}Z`}function drawEye2(t,side,radius,x,y,body,tile){let kind=eyeKindOf3(t),size=round213(radius*(kind==="Tiny"?.56:.86)),offX=round213(radius-size-.8),offY=round213(-(radius-size)*.7),sparkle=round213(size*.34),glint=`translate(${round213(offX+size*.26)} ${round213(offY-size*.26)}) scale(${sparkle})`,lidY=round213(-radius*.36),lidWide=round213(Math.sqrt(radius**2-lidY**2)),cover=round213(radius+.6),lid2=kind==="Sleepy"?`<path d="M${-lidWide-.6} ${lidY}A${cover} ${cover} 0 0 1 ${lidWide+.6} ${lidY}Z" fill="${body}"/><path d="M${-lidWide} ${lidY}H${lidWide}" stroke="${tile}" stroke-width="1.5" stroke-linecap="round"/>`:"",lift=round213(t.num("brow.y",1.5,4)),arch=round213(radius*.74),brow3=t("brows")*100<80?`<path data-brow="" d="M${round213(side*arch-3.6)} ${round213(-radius-lift+1)}q3.6 -3 7.2 -.4" fill="none" stroke="${tile}" stroke-width="1.6" stroke-linecap="round"/>`:"";return`<g transform="translate(${round213(x)} ${round213(y)})">${brow3}<g data-eye=""><circle r="${round213(radius)}" fill="#fff"/><g data-iris=""><circle cx="${offX}" cy="${offY}" r="${size}" fill="url(#peek-iris)"/><path d="${SPARKLE}" transform="${glint}" fill="#fff"/><circle cx="${round213(offX+size*.56)}" cy="${round213(offY-size*.02)}" r="${round213(size*.08)}" fill="#fff"/></g>${lid2}</g></g>`}function drawFace(t,pose,body,tile){let formation=formationOf(t),scale=t.num("eye.size",.8,1.2),radians=(pose.lean+t.jitter("tilt",8))*Math.PI/180,big=11*scale,small=big*t.num("eye.ratio",.68,1),spread={Close:.74,Wide:1.34}[formation]??1,gap=t.num("eye.gap",10.5,14)*scale*spread,eyes2=formation==="One"?[{side:0,radius:big*1.42,by:0}]:formation==="Three"?[{side:-1,radius:small*.84,by:-gap*1.5},{side:0,radius:big,by:0},{side:1,radius:small*.84,by:gap*1.5}]:[{side:-1,radius:big,by:-gap},{side:1,radius:small,by:gap}],turn2=angleOf(t)*Math.PI/180,spots=eyes2.map(({radius,by:by2})=>{let x=pose.eyeX-50+Math.cos(radians)*by2,y=pose.eyeY-50+Math.sin(radians)*by2;return{radius,across:50+x*Math.cos(turn2)-y*Math.sin(turn2),down:50+x*Math.sin(turn2)+y*Math.cos(turn2)}}),backInside=axis=>{let low=Math.min(...spots.map(spot=>spot[axis]-spot.radius)),high=Math.max(...spots.map(spot=>spot[axis]+spot.radius));return low<FACE_EDGE?FACE_EDGE-low:high>100-FACE_EDGE?100-FACE_EDGE-high:0},pushX=backInside("across"),pushY=backInside("down"),shiftX=pushX*Math.cos(turn2)+pushY*Math.sin(turn2),shiftY=pushY*Math.cos(turn2)-pushX*Math.sin(turn2);return eyes2.map(({side,radius,by:by2})=>drawEye2(t,side,radius,pose.eyeX+shiftX+Math.cos(radians)*by2,pose.eyeY+shiftY+Math.sin(radians)*by2,body,tile)).join("")}function createPeek(name,overrides,ids="peek"){let t=calmed(createTraits(name,overrides),CALMING15),pose=poseOf4(t),shape=bodyOf2(t),{tile,body,iris}=coloursOf13(t),size=pose.size*t.num("body.size",.92,1.08),rings=Array.from({length:RINGS},(_,i)=>{let ring4=RINGS-i;return`<path d="${drawOutline3(t,pose,shape,ring4*RING_STEP)}" fill="${mix(tile,WHITE,round213(.05+i*.05))}"/>`}).join(""),toCentre=Math.hypot(50-pose.x,54-pose.y)||1;return scopeAll({defs:`<defs><linearGradient id="peek-tile" gradientUnits="userSpaceOnUse" x1="50" y1="5" x2="50" y2="95"><stop offset="0" stop-color="${tile}"/><stop offset="1" stop-color="${mix(tile,WHITE,.14)}"/></linearGradient><linearGradient id="peek-body" gradientUnits="userSpaceOnUse" x1="50" y1="${round213(pose.y-size)}" x2="50" y2="${round213(pose.y+size)}"><stop offset="0" stop-color="${body}"/><stop offset="1" stop-color="${mix(body,WHITE,.6)}"/></linearGradient><linearGradient id="peek-iris" x1="0.5" y1="0" x2="0.5" y2="1"><stop offset="0" stop-color="${iris}"/><stop offset="1" stop-color="${mix(iris,tile,.62)}"/></linearGradient></defs>`,tile:"url(#peek-tile)",angle:angleOf(t),turn:`rotate(${round213(angleOf(t))} 50 50)`,rings,body:`<path d="${drawOutline3(t,pose,shape,0)}" fill="url(#peek-body)"/>`,face:drawFace(t,pose,body,tile),effect:pose.effect,into:{x:round213((50-pose.x)/toCentre*7),y:round213((54-pose.y)/toCentre*7)},origin:{x:pose.x,y:pose.y},blinkDelay:t.num("blink",0,4)},"peek",ids)}var peekSvg=(name,overrides)=>{let peek=createPeek(name,overrides),tile=TILE_SHAPE4.replace("/>",` fill="${peek.tile}"/>`);return`<svg xmlns="http://www.w3.org/2000/svg" viewBox="${VIEW_BOX3}">${peek.defs}${tile}<clipPath id="peek-box">${TILE_SHAPE4}</clipPath><g clip-path="url(#peek-box)"><g transform="${peek.turn}">${peek.rings}${peek.body}${peek.face}</g></g></svg>`};var controls15=(name,overrides)=>{let t=calmed(createTraits(name,overrides),CALMING15),list=control=>narrowed(control,t,CALMING15),{body,iris}=coloursOf13(t);return[{title:"Shape",controls:[possibilitiesSlider(t,NOTES16),list(choice(t,"body","Body","list",BODIES2.map(({name:label})=>({label})))),turnSlider(t,NATURAL_ANGLE),list(choice(t,"pose","Peeking from","list",POSES3.map(({name:label})=>({label})))),...bodyOf2(t).counted?[choice(t,"bumps","Bumps","list",[5,6,7,8,9].map(count=>({label:String(count)})))]:[],slider(t,"fluff","Depth",0,100,"%"),slider(t,"body.size","Body size",0,100,"%")]},{title:"Colour",controls:[palette(t,"tile","Colour",TILES7),{type:"colors",id:"peek.colors",label:"Body, eyes",colors:[{id:colorKey("body"),color:body},{id:colorKey("iris"),color:iris}]}]},{title:"Eyes",controls:[choice(t,"eye.formation","Formation","list",FORMATIONS),list(choice(t,"eye.kind","Eyes","list",EYE_KINDS3.map(label=>({label})))),toggle(t,"brows",80,"Brows"),slider(t,"eye.size","Eye size",0,100,"%"),...formationOf(t)==="One"?[]:[slider(t,"eye.gap","Gap",0,100,"%"),slider(t,"tilt","Tilt",-8,8,"\xB0")]]}]};var CALMING16={lists:{hair:[14,8,[0,1,6,5,3,4,7,13,8,12,10,11,2,9]],mouth:[6,2,[3,1,5,0,2,4]],"hat.kind":[5,3]},rarer:["hat","beard","glasses","mark","earring"]},NOTES17=["everyday hair, a smile, and hardly ever a hat, beard, glasses or mark.","more hairstyles and mouths, with hats, beards and glasses now and then.","every hairstyle up to mohawks, every mouth, hat and extra."];var SKINS3=[["#fde3cf","#eebf9f"],["#f5cda9","#dfa97f"],["#eab98e","#cf9468"],["#d9a273","#b97f52"],["#c18a5e","#9c6a42"],["#9b6a45","#7b4f30"],["#74492e","#5a3621"],["#4e3020","#3a2316"],["#eda4ab","#d67f8a"]],HAIR_COLORS=[["#17151a","#35313b"],["#2f1e16","#4e3424"],["#5e3a22","#7e5433"],["#8a3f1f","#b05f33"],["#d8ae62","#ecca8d"],["#e8d9bb","#f6edd9"],["#8e8f96","#b1b2b8"],["#e588ad","#f4afc9"],["#3f7fc2","#68a4dd"]],HAT_COLORS=[["#d0353a","#a82329"],["#2e7ea8","#1f5f82"],["#10525c","#0b3a42"],["#e4b23f","#c0902a"],["#3e8f5b","#2d6c44"],["#6b4bb8","#503693"],["#22242c","#3a3d48"]],EARRINGS=["#ffd84a","#e23a78","#35c4cf"],INK4="#1b171b",RED="#c2353f",FRAMES="#1c1a22",TINT="#2f3140",COLOR_TILE="#f6f4ee",SANTA_RED=HAT_COLORS[0],RETRO={tile:"#86bd72",pale:"#def3c6",dark:"#0f3a30"},SCREENS=[RETRO.tile,"#e0a458","#7fa8d9","#e39ab5","#b4b0a4"];function paintOf(t,key2,colors,towards,amount){let picked=t.color(key2);return picked?[picked,mix(picked,towards,amount)]:t.pick(key2,colors)}function inksOn(tile=RETRO.tile){return tile===RETRO.tile?RETRO:{tile,pale:mix(tile,WHITE,.72),dark:mix(tile,BLACK,.74)}}var pickLook=t=>({skin:paintOf(t,"skin",SKINS3,BLACK,.18),hair:paintOf(t,"hair.color",HAIR_COLORS,WHITE,.2),hat:paintOf(t,"hat.color",HAT_COLORS,BLACK,.2),earring:t.pick("earring.color",EARRINGS),inks:inksOn(t.color("screen"))}),isPaleHair=([color])=>parseInt(color.slice(1,3),16)>176;function paints(theme,{skin,hair,hat,earring,inks}){if(theme==="color")return{s:skin[0],d:skin[1],h:hair[0],H:hair[1],f:hair[0],c:hat[0],C:hat[1],b:hat[1],w:"#dcd9d1",g:FRAMES,L:TINT,x:INK4,r:RED,e:earring,m:skin[1]};let{pale,dark}=inks,paleHair=isPaleHair(hair);return{s:pale,d:pale,h:paleHair?pale:dark,H:pale,f:dark,c:dark,C:pale,b:dark,w:pale,g:dark,L:dark,x:dark,r:pale,e:dark,m:dark}}var sprite=(top,...rows)=>({top,rows}),HEAD2=sprite(5,"......ssssssss......",".....ssssssssss.....",".....ssssssssss.....",".....ssssssssss.....",".....ssssssssssdd...",".....ssssssssssdd...",".....ssssssssssd....",".....ssssssssss.....",".....ssssssssss.....","......sssssssdd.....",".......sssssddd.....",".........ddddd......",".........ddddd......"),NOSE=sprite(11,".........d..........",".........dd........."),HAIRS=[{name:"crop",takesHat:!0,front:sprite(3,".......hhhhhhh......",".....hhhhhhhhhh.....","....hhhhhhhhhhhh....","....hhHhhhhhhhhh....","....hh.....hhhhh....","....h........hhh....",".............hh.....",".............h......")},{name:"sidePart",takesHat:!0,front:sprite(2,"......hhhhhhhh......","....hhhhhhhhhhhh....","...hhhhhhhhhhhhhh...","...hhhhhhhhHhhhhh...","...hhhhhhh...hhhh...","...hhh........hhh...","....h.........hh....","..............h.....")},{name:"spiky",takesHat:!1,front:sprite(1,"........h..h........",".....h.hh.hh.h......",".....hhhhhhhhhh.h...","....hhhhhhHhhhhhh...","....hhhhhhhhhhhh....","....hh.h..h.hhhh....","....h........hhh....",".............hh.....")},{name:"curly",takesHat:!1,front:sprite(2,".......hh..hh.......",".....hhhhhhhhhh.....","....hhhhhHhhHhhh....","...hhHhhhhhhhhhhh...","...hhhhhHhhHhhhhh...","...hhh..h..h..hhh...","....h.........hhh...","...............hh...")},{name:"afro",takesHat:!1,front:sprite(0,"......hhhhhhhh......","....hhhhhhhhhhhh....","...hhhhhhhhhhhhhh...","..hhhhhHhhhhHhhhhh..","..hhhhhhhhhhhhhhhh..","..hhhHhhhhhhhhHhhh..","..hhhhhhhhhhhhhhhh..","..hhhh........hhhh..","..hhh..........hhh..","..hhh...........hh..","...hh...........hh..","...h............h..."),wraps:!0},{name:"long",takesHat:!0,wraps:!0,front:sprite(3,"......hhhhhhhh......","....hhhhhhhhhhh.....","....hhhhhHhhhhhh....","....hhhh....hhhh....","....hh.......hhh....","....h.........hh...."),back:sprite(4,"....hhhhhhhhhhhh....","...hhhhhhhhhhhhhh...","...hhhhhhhhhhhhhh...","...hhhhhhhhhhhhhh...","...hhhhhhhhhhhhhhh..","...hhhhhhhhhhhhhhh..","...hhhhhhhhhhhhhhh..","...hhhhhhhhhhhhhhh..","...hhhhhhhhhhhhhhh..","...hhhhhhhhhhhhhhh..","...hhhhhhhhhhhhhhh..","...hhhhh.....hhhhh..","...hhhh......hhhhh..","...hh.........hhh...")},{name:"bob",takesHat:!0,wraps:!0,front:sprite(3,"......hhhhhhhh......","....hhhhhhhhhhh.....","....hhhhhhHhhhhh....","....hhhhhh..hhhh....","....hhh......hhh....","....hh........hh...."),back:sprite(4,"....hhhhhhhhhhhh....","...hhhhhhhhhhhhhh...","...hhhhhhhhhhhhhh...","...hhhhhhhhhhhhhh...","...hhhhhhhhhhhhhhh..","...hhhhhhhhhhhhhhh..","...hhhhhhhhhhhhhhh..","...hhhhhhhhhhhhhhh..","...hhhhhhhhhhhhhhh..","...hhh.........hhh..")},{name:"bun",takesHat:!1,front:sprite(0,"........hhhh........",".......hhHhhh.......",".......hhhhhh.......",".......hhhhhh.......",".....hhhhhhhhhh.....","....hhhhhhHhhhhh....","....hhhhh...hhhh....","....hh.......hhh....","....h.........hh....")},{name:"ponytail",takesHat:!0,front:sprite(3,"......hhhhhhhh......","....hhhhhhhhhhh.....","....hhhhhhHhhhhh....","....hhh.....hhhh....","....h........hhh....",".............hh....."),back:sprite(5,"...............hhh..","..............hhhhh.","..............hhhhh.","...............hhhh.","...............hhhh.","................hhh.","................hhh.","................hh..","................h...")},{name:"mohawk",takesHat:!1,front:sprite(0,"........hhh.........",".......hhhhh........",".......hhHhh........",".......hhhhh........",".......hhHhh........",".......hhhhh........")},{name:"dreads",takesHat:!1,wraps:!0,front:sprite(0,"...........h..h.h...",".........h.hh.h.h.h.","......hh.hhhhhhhh...","....hhhhhhhhhhhhhh..","...hhhhhhhhhhhhhhhh.","...hhhhhhHhhhhhhhhh.","...hhh.hh....hhhhh..","...hh.........hhhh..","...hh.........hh.hh.","...h..........hh.hh.","...h..........h..hh.","...h.............h..")},{name:"balding",takesHat:!0,front:sprite(7,"....hh........hhh...","...hhh........hhhh..","...hh..........hhh..","....h...........h...")},{name:"slick",takesHat:!0,front:sprite(3,".....hhhhhhhhhh.....","....hhhhhHhhhhhh....","....hhhhhhhhhhhh....","....h.......hhhh....","....h.........hh....","..............h.....")},{name:"hijab",takesHat:!1,wraps:!0,front:sprite(2,"......hhhhhhhh......","....hhhhhhhhhhhh....","...hhhhhhhhhhhhhh...","...hhhhhHhhhhhhhhh..","...hhhhhhhhhhhhhhh..","...hhhh.....hhhhhh..","...hhh.......hhhhh..","...hh.........hhhh..","...hh.........hhhh..","...hh.........hhhh..","...hh.........hhhh..","...hh.........hhhh..","...hhh.......hhhhh..","...hhhh.....hhhhhh..","....hhhhhhhhhhhhh...","....hhhhhhhhhhhhh...",".....hhhhhhhhhhh....")}],HATS2=[{name:"cap",bottom:6,sprite:sprite(2,"......cccccccc......","....cccccccccccc....","....ccccCCcccccc....","....cccccccccccc....",".bbbbbbbbbbbcccc....")},{name:"backwardsCap",bottom:6,sprite:sprite(2,"......cccccccc......","....cccccccccccc....","....ccccccCCcccc....","....cccccccccccc....","....ccccbbbbbbbbbbb.")},{name:"beanie",bottom:6,sprite:sprite(2,".......cccccc.......",".....cccccccccc.....","....cccccccccccc....","....cCcCcCcCcCcc....","....CCCCCCCCCCCC....")},{name:"bucket",bottom:6,sprite:sprite(2,".......cccccc.......",".....cccccccccc.....",".....cccccccccc.....",".....CCCCCCCCCC.....","...bbbbbbbbbbbbbb...")},{name:"santa",bottom:6,sprite:sprite(0,".......ccccccc......",".....ccccccccccc....","....cccccccccccccww.","....cccccccccccc.www","...ccccccccccccc.www","...wwwwwwwwwwwwww...","...wwwwwwwwwwwwww...")}],BEARDS={moustache:sprite(12,".......fffff........"),goatee:sprite(15,"........fff........."),full:sprite(11,".....f........f.....",".....ff.fffff.f.....",".....fff...ffff.....","......ffffffff......",".......fffff........")},GLASSES={frames:sprite(8,".....ggggggggggggg..",".....g...g...g......",".....g...g...g......",".....ggggggggg......"),shades:sprite(8,".....ggggggggggggg..",".....gLLLgLLLg......",".....gLLLgLLLg......",".....ggggggggg......")},EARRING=sprite(12,"................e..."),EYEBROWS={flat:sprite(7,"......fff.fff......."),arched:sprite(7,".......f...f........","......f.f.f.f......."),worried:sprite(7,"........f.f.........","......ff...ff......."),stern:sprite(7,"......f.....f.......",".......ff.ff........")},MARKS={freckles:sprite(11,"......m.....m......."),mole:sprite(12,"............m......."),cheek:sprite(11,".............m......")},EYE_SPACINGS=[[7,11],[6,12],[7,12]],EYE_SPACING_NAMES=["Close","Wide","Uneven"],MOUTHS5={line:sprite(13,"........xxx........."),small:sprite(13,".........xx........."),smirk:sprite(13,"...........x........","........xxx........."),smile:sprite(13,".......x...x........","........xxx........."),frown:sprite(13,"........xxx.........",".......x...x........"),tiny:sprite(13,".........x..........")};var GRID=20,MARGIN3=2,MOUTH_NAMES=["line","small","smirk","smile","frown","tiny"],key=(x,y)=>`${x},${y}`;function toCells({top,rows},paint,belowRow=-1,mirrored2=!1){let cells=new Map;return rows.forEach((row,line4)=>{let y=top+line4;y<=belowRow||[...row].forEach((letter,x)=>{letter!=="."&&cells.set(key(mirrored2?GRID-1-x:x,y),paint[letter])})}),cells}var inkAt=(...columns)=>Array.from({length:GRID},(_,x)=>columns.includes(x)?"x":".").join("");function eyeSprites([left,right],tall){let pair=inkAt(left,right);return{open:{top:tall?9:10,rows:tall?[pair,pair]:[pair]},wide:{top:tall?8:9,rows:tall?[pair,pair,pair]:[pair,pair]},shut:{top:10,rows:[inkAt(left,left+1,right,right+1)]}}}var merged=(...layers)=>new Map(layers.flatMap(layer2=>[...layer2])),NEIGHBOURS=[[1,0],[-1,0],[0,1],[0,-1]];function outlineOf2(shape,color){let outline=new Map;for(let cell of shape.keys()){let[x,y]=cell.split(",").map(Number);for(let[dx,dy]of NEIGHBOURS){let next=key(x+dx,y+dy);shape.has(next)||outline.set(next,color)}}return outline}function rimOf(shape,against,color){let rimmed=new Map(shape);for(let cell of shape.keys()){let[x,y]=cell.split(",").map(Number);NEIGHBOURS.some(([dx,dy])=>{let next=key(x+dx,y+dy);return!shape.has(next)&&against.has(next)})&&rimmed.set(cell,color)}return rimmed}function toRects(cells){let out="";for(let y=-MARGIN3;y<GRID+MARGIN3;y++){let x=-MARGIN3;for(;x<GRID+MARGIN3;){let color=cells.get(key(x,y));if(!color){x++;continue}let width=1;for(;cells.get(key(x+width,y))===color;)width++;out+=`<rect x="${x}" y="${y}" width="${width}" height="1" fill="${color}"/>`,x+=width}}return out}var chance=(t,key2,percent)=>t(key2)*100<percent;function pickTraits(t){let hair=t.pick("hair",HAIRS),hat=hair.takesHat&&chance(t,"hat",38)?t.pick("hat.kind",HATS2):null,facialHair=hair.name==="hijab"||!chance(t,"beard",34)?null:t.pick("beard.kind",Object.keys(BEARDS)),glasses2=chance(t,"glasses",24)?t.pick("glasses.kind",["frames","frames","shades"]):null,earring=!hair.wraps&&chance(t,"earring",16);return{hair,hat,facialHair,glasses:glasses2,earring,mouth:t.pick("mouth",MOUTH_NAMES),mirrored:t("mirrored")<.5,brows:chance(t,"brows",55)?t.pick("brows.kind",Object.keys(EYEBROWS)):null,mark:chance(t,"mark",30)?t.pick("mark.kind",Object.keys(MARKS)):null,eyeSpacing:glasses2?EYE_SPACINGS[0]:t.pick("eyes.spacing",EYE_SPACINGS),tallEyes:!glasses2&&chance(t,"eyes.tall",65)}}function tileOf(color){let span=GRID+MARGIN3*2;return`<rect x="${-MARGIN3}" y="${-MARGIN3}" width="${span}" height="${span}" rx="5.33" fill="${color}" shape-rendering="auto"/>`}function createPixelFace(name,theme,overrides){let t=calmed(createTraits(name,overrides),CALMING16),picked=pickLook(t),traits=pickTraits(t),{hair,hat,facialHair,glasses:glasses2,earring,mirrored:mirrored2,brows,mark}=traits,retro=theme==="retro",look={...picked,hair:hair.name==="hijab"?picked.hat:picked.hair,hat:hat?.name==="santa"?SANTA_RED:picked.hat},paint=paints(theme,look),cellsOf=(sprite2,belowRow=-1)=>toCells(sprite2,paint,belowRow,mirrored2),{inks}=look,hairLine=hat?hat.bottom:-1,headCells=cellsOf(HEAD2),rim=cells=>retro&&isPaleHair(look.hair)?rimOf(cells,headCells,inks.dark):cells,back=hair.back?rim(cellsOf(hair.back)):new Map,front=rim(cellsOf(hair.front,hairLine)),head2=merged(headCells,earring?cellsOf(EARRING):new Map),hatCells=hat?cellsOf(hat.sprite):null,body=merged(back,head2),outline=retro?outlineOf2(merged(body,front),inks.dark):new Map,hatOutline=retro&&hatCells?outlineOf2(hatCells,inks.dark):new Map,rects=sprite2=>toRects(cellsOf(sprite2)),optional2=sprite2=>sprite2?cellsOf(sprite2):new Map,beard=optional2(facialHair?BEARDS[facialHair]:void 0),eyes2=eyeSprites(traits.eyeSpacing,traits.tallEyes),nose=retro?new Map:cellsOf(NOSE);return{tile:tileOf(retro?inks.tile:COLOR_TILE),headMask:toRects(headCells),behind:toRects(merged(outline,body)),face:toRects(merged(nose,optional2(mark?MARKS[mark]:void 0),beard,optional2(brows?EYEBROWS[brows]:void 0))),front:toRects(front),hat:hatCells?toRects(merged(hatOutline,hatCells)):null,glasses:glasses2?rects(GLASSES[glasses2]):null,eyes:{open:rects(eyes2.open),wide:rects(eyes2.wide),shut:rects(eyes2.shut)},mouths:{rest:rects(MOUTHS5[traits.mouth]),hover:rects(MOUTHS5.smile)},eyesVisible:glasses2!=="shades",blinkDelay:t.num("blink",0,4)}}var pixelSvg=(name,theme,overrides)=>{let f2=createPixelFace(name,theme,overrides),span=GRID+MARGIN3*2;return`<svg xmlns="http://www.w3.org/2000/svg" viewBox="${-MARGIN3} ${-MARGIN3} ${span} ${span}" shape-rendering="crispEdges">`+f2.tile+f2.behind+f2.face+f2.eyes.open+f2.mouths.rest+f2.front+(f2.glasses??"")+(f2.hat??"")+"</svg>"};var named9=names=>names.map(name=>({label:spaced(name)})),firsts=colors=>colors.map(([color])=>color),indexOf2=(value,count)=>Math.floor(value*count);function tone(t,key2,colors,label){let position=index=>(index+.5)/colors.length,pale=colors.findIndex(isPaleHair),dark=colors.findIndex(color=>!isPaleHair(color));return{type:"choice",id:key2,label,layout:"segmented",options:[{id:"dark",label:"Dark",set:{[key2]:position(dark)}},{id:"pale",label:"Light",set:{[key2]:position(pale)}}],selected:isPaleHair(colors[indexOf2(t(key2),colors.length)])?"pale":"dark"}}var builder=theme=>(name,overrides)=>{let t=calmed(createTraits(name,overrides),CALMING16),list=control=>narrowed(control,t,CALMING16),retro=theme==="retro",hair=HAIRS[indexOf2(t("hair"),HAIRS.length)],hijab=hair.name==="hijab",wearsHat=hair.takesHat&&t("hat")*100<38,hat=HATS2[indexOf2(t("hat.kind"),HATS2.length)],wearsGlasses=t("glasses")*100<24,hairColor=retro?hijab?tone(t,"hat.color",HAT_COLORS,"Scarf"):tone(t,"hair.color",HAIR_COLORS,"Hair tone"):hijab?palette(t,"hat.color","Scarf colour",firsts(HAT_COLORS)):palette(t,"hair.color","Hair colour",firsts(HAIR_COLORS));return[{title:"Person",controls:[retro?fixedPalette(t,"screen","Colour",SCREENS):palette(t,"skin","Colour",firsts(SKINS3)),choice(t,"mirrored","Facing","segmented",[{label:"Right"},{label:"Left"}]),possibilitiesSlider(t,NOTES17)]},{title:"Hair",controls:[list(choice(t,"hair","Hair","list",named9(HAIRS.map(entry=>entry.name)))),hairColor]},{title:"Face",controls:[...wearsGlasses?[]:[choice(t,"eyes.spacing","Eye spacing","segmented",EYE_SPACING_NAMES.map(label=>({label}))),toggle(t,"eyes.tall",65,"Tall eyes")],optional(t,"brows",55,"brows.kind","Brows","list",named9(Object.keys(EYEBROWS))),list(choice(t,"mouth","Mouth","list",named9(MOUTH_NAMES))),optional(t,"mark",30,"mark.kind","Marks","list",named9(Object.keys(MARKS))),...hijab?[]:[optional(t,"beard",34,"beard.kind","Beard","list",named9(Object.keys(BEARDS)))]]},{title:"Accessories",controls:[...hair.takesHat?[optional(t,"hat",38,"hat.kind","Hat","list",named9(HATS2.map(entry=>entry.name)))]:[],...!retro&&wearsHat&&hat.name!=="santa"?[palette(t,"hat.color","Hat colour",firsts(HAT_COLORS))]:[],optional(t,"glasses",24,"glasses.kind","Glasses","segmented",[{label:"Frames",weight:2},{label:"Shades"}]),...hair.wraps?[]:[toggle(t,"earring",16,"Earring")]]}]},colorControls=builder("color"),retroControls=builder("retro");var CALMING17={features:/^(eye|mouth)\.(size|gap|y)$|^eye[01]\.(size|y|turn)$|^(weight|tilt)$/,lists:{"eye.left":[13,8,[2,0,7,9,5,3,6,12,10,1,8,11,4]],"eye.right":[13,8,[2,0,7,9,5,3,6,12,10,1,8,11,4]],mouth:[10,8,[0,2,1,3,5,6,8,4,9,7]]}},NOTES18=["the plainest eyes and mouths, like discs, donuts, pills and smiles, set evenly.","adds triangles, chevrons, hearts and a cat mouth, sized and placed more freely.","every shape, up to leaves, pluses and a shout, at the widest spread of sizes and tilts."];var TILES8=["#f9f8f4","#ffffff","#fbefe6","#edf5ef","#ecf1f8","#f4eef8","#fff5d6","#f1efe9"],round214=value=>Math.round(value*100)/100,line3=d=>`<path d="${d}" fill="none"/>`,solid=d=>`<path d="${d}"/>`,ringRadius=(r,w)=>Math.max(r,w/2+2.2),ring3=(r,w)=>`<circle r="${round214(ringRadius(r,w))}" fill="none"/>`,by=reach=>(a,w)=>reach*a+w/2,EYES4=[{name:"Donut",span:(a,w)=>ringRadius(a,w)+w/2,draw:(_at,a,w)=>ring3(a,w)},{name:"Chevron",span:by(.45),draw:at3=>line3(`M${at3(-.45,-.85)}L${at3(.45,0)}L${at3(-.45,.85)}`)},{name:"Disc",span:by(.85),draw:(_at,a)=>`<circle r="${round214(a*.85)}"/>`},{name:"Cloud",span:by(1.15),draw:at3=>line3(`M${at3(-1.15,.5)}L${at3(1.15,.5)}L${at3(.15,-.5)}`)},{name:"Plus",span:by(.85),draw:at3=>line3(`M${at3(-.85,0)}L${at3(.85,0)}M${at3(0,-.85)}L${at3(0,.85)}`)},{name:"Arch",span:by(1),draw:at3=>line3(`M${at3(-1,.35)}Q${at3(0,-1.05)} ${at3(1,.35)}`)},{name:"Square",span:by(.6),draw:at3=>solid(`M${at3(-.6,-.6)}L${at3(.6,-.6)}L${at3(.6,.6)}L${at3(-.6,.6)}Z`)},{name:"Pill",span:by(0),draw:at3=>line3(`M${at3(0,-.75)}L${at3(0,.75)}`)},{name:"Heart",span:by(.7),draw:at3=>solid(`M${at3(-.7,-.3)}L${at3(0,.5)}L${at3(.7,-.3)}`)},{name:"Dash",span:by(.8),draw:at3=>line3(`M${at3(-.8,0)}L${at3(.8,0)}`)},{name:"Triangle",span:by(.8),draw:at3=>solid(`M${at3(0,-.75)}L${at3(.8,.55)}L${at3(-.8,.55)}Z`)},{name:"Leaf",span:by(.75),draw:at3=>solid(`M${at3(-.75,.75)}Q${at3(-.6,-.6)} ${at3(.75,-.75)}Q${at3(.6,.6)} ${at3(-.75,.75)}Z`)},{name:"Dome",span:by(.85),draw:(at3,a)=>solid(`M${at3(-.85,.42)}A${round214(a*.85)} ${round214(a*.85)} 0 0 1 ${at3(.85,.42)}Z`)}],MOUTHS6=[{name:"Smile",span:by(.2),draw:(at3,a)=>line3(`M${at3(-1,-.2)}A${round214(a*1.4)} ${round214(a*1.4)} 0 0 0 ${at3(1,-.2)}`)},{name:"Oh",span:(a,w)=>a*.1+w,draw:(_at,a,w)=>ring3(a*.1+w/2,w)},{name:"Flat",span:by(0),draw:at3=>line3(`M${at3(-.65,0)}L${at3(.65,0)}`)},{name:"Grin",span:by(.25),draw:(at3,a)=>solid(`M${at3(-.8,-.25)}L${at3(.8,-.25)}A${round214(a*.8)} ${round214(a*.55)} 0 0 1 ${at3(-.8,-.25)}Z`)},{name:"Wave",span:by(.25),draw:at3=>line3(`M${at3(-1,0)}Q${at3(-.5,-.45)} ${at3(0,0)}T${at3(1,0)}`)},{name:"Peep",span:by(.12),draw:(_at,a)=>`<circle r="${round214(a*.12)}"/>`},{name:"Frown",span:by(.15),draw:(at3,a)=>line3(`M${at3(-.7,.25)}A${round214(a)} ${round214(a)} 0 0 1 ${at3(.7,.25)}`)},{name:"Shout",span:by(.25),draw:at3=>solid(`M${at3(-.6,-.25)}L${at3(.6,-.25)}L${at3(.3,.25)}L${at3(-.3,.25)}Z`)},{name:"Smirk",span:by(.25),draw:at3=>line3(`M${at3(-.6,.05)}Q${at3(.25,.3)} ${at3(.7,-.25)}`)},{name:"Cat",span:by(.1),draw:at3=>line3(`M${at3(-.8,-.1)}Q${at3(-.4,.35)} ${at3(0,0)}Q${at3(.4,.35)} ${at3(.8,-.1)}`)}],PARTS3=["left","right","mouth"];function coloursOf14(t){let tile=t.color("tile")??t.pick("tile",TILES8),order=t.pick("colourway",COLOURWAYS).colors.map((color,i)=>[t(`colourway.${i}`)+(contrast(color,tile)<1.5?1:0),color]).sort(([a],[b])=>a-b);return{tile,parts:Object.fromEntries(PARTS3.map((part,i)=>[part,t.color(part)??order[i][1]]))}}var scaled=a=>(x,y)=>`${round214(x*a)} ${round214(y*a)}`;function createShapeFace(name,overrides){let t=calmed(createTraits(name,overrides),CALMING17),{tile,parts}=coloursOf14(t),size=t.num("eye.size",13,17),w=size*t.num("weight",.68,.9),gap=t.num("eye.gap",1.5,6),eyes2=[-1,1].map((side,i)=>{let shape=t.pick(i?"eye.right":"eye.left",EYES4),r=size*(1+t.jitter(`eye${i}.size`,.14)),a=Math.max(r-w/2,r*.45);return{side,shape,r,a,dy:t.jitter(`eye${i}.y`,1.8),x:side*(gap+Math.max(shape.span(a,w),r*.8))}}),mouth3=t.pick("mouth",MOUTHS6),m=t.num("mouth.size",19,28),rise=mouth3.span(m,w),above=Math.max(...eyes2.map(({r,dy})=>r-dy)),drop=Math.max(...eyes2.map(({r,dy})=>r+dy))+t.num("mouth.y",5,13)+rise,across=Math.max(...eyes2.map(({x,shape,a})=>Math.abs(x)+shape.span(a,w)),m+w/2)*2,fit=Math.min(1,80/across,76/(above+drop+rise)),placed3=(transform,color,markup)=>`<g transform="${transform}" color="${color}"><g>${markup}</g></g>`,flip=t("mouth.flip")<.5?-1:1;return{tile,face:`translate(50 50) scale(${round214(fit)}) rotate(${round214(t.jitter("tilt",5))}) translate(0 ${round214((above-drop-rise)/2)})`,weight:round214(w),eyes:eyes2.map(({side,shape,a,x,dy},i)=>placed3(`translate(${round214(x)} ${round214(dy)}) rotate(${round214(t.jitter(`eye${i}.turn`,10))}) scale(${-side} 1)`,parts[PARTS3[i]],shape.draw(scaled(a),a,w))).join(""),mouth:placed3(`translate(0 ${round214(drop)}) scale(${flip} 1)`,parts.mouth,mouth3.draw(scaled(m),m,w)),blinkDelay:t.num("blink",0,4)}}var shapeSvg=(name,overrides)=>{let face=createShapeFace(name,overrides);return`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><rect width="100" height="100" rx="22.22" fill="${face.tile}"/><g transform="${face.face}" ${INK_STYLE(face.weight)}>${face.eyes}${face.mouth}</g></svg>`};var named10=list=>list.map(({name:label})=>({label})),controls16=(name,overrides)=>{let t=calmed(createTraits(name,overrides),CALMING17),list=control=>narrowed(control,t,CALMING17),{parts}=coloursOf14(t);return[{title:"Face",controls:[list(choice(t,"eye.left","Left eye","list",named10(EYES4))),list(choice(t,"eye.right","Right eye","list",named10(EYES4))),list(choice(t,"mouth","Mouth","list",named10(MOUTHS6))),possibilitiesSlider(t,NOTES18),slider(t,"eye.size","Eye size",0,100,"%"),slider(t,"eye.gap","Eye gap",0,100,"%"),slider(t,"mouth.size","Mouth size",0,100,"%"),slider(t,"mouth.y","Mouth drop",0,100,"%"),slider(t,"weight","Weight",0,100,"%"),slider(t,"tilt","Tilt",-5,5,"\xB0")]},{title:"Colour",controls:[palette(t,"tile","Tile",TILES8),PARTS3.reduce(clearingColor,choice(t,"colourway","Colourway","swatches",COLOURWAYS.map(({label,colors})=>({label,color:`conic-gradient(${colors.map((color,i)=>`${color} 0 ${(i+1)*25}%`).join(", ")})`})))),{type:"colors",id:"colours",label:"Colours",colors:PARTS3.map(part=>({id:colorKey(part),color:parts[part]}))}]}]};var KINDS2=[{id:"bots",label:"Bots",group:"3D",hint:"Move your mouse and it looks at you",defaultName:"Nova",controls:controls4,essentials:["head","face","eye","mouth","paint"],styleKeys:["head"],displayKeys:["container.size"],svg:generateBot,parts:botParts},{id:"blobs",label:"Blobs",group:"3D",hint:"Move your mouse and it looks at you",defaultName:"Rex-7",controls:controls2,essentials:["shape","hue","tone"],styleKeys:["shape"],displayKeys:["container.size"],svg:generateBlob,parts:blobParts},{id:"gummies",label:"Gummies",group:"3D",hint:"A jelly in 3D, lit from inside. It watches you, and boings when tapped",defaultName:"Juju",controls:controls13,essentials:["body","topper","face","glow","gummy.colors"],styleKeys:["body","face","topper","glow"],svg:gummySvg,parts:gummyParts},{id:"mallows",label:"Mallows",group:"3D",hint:"Soft clay in 3D, a bun, a ghost or a cloud, and every one feels something different. It watches you, and boings when tapped",defaultName:"Momo",controls:controls14,essentials:["type","face","eyes","colour","mallow.ink"],styleKeys:["face"],displayKeys:["container.size"],svg:mallowSvg,parts:mallowParts},{id:"faces",label:"Faces",group:"Illustrated",hint:"Its eyes follow you. Tap it to see what it does",defaultName:"Maya",controls:controls7,essentials:["eyes","eyebrows","mouth","glasses","skin"],styleKeys:["mouth"],svg:faceSvg},{id:"bubbles",label:"Bubbles",group:"Illustrated",hint:"Its eyes follow you. Write anything on it",defaultName:"Felix",controls:controls3,essentials:["shape","eye.kind","mouth","palette","bubble.colors"],styleKeys:["shape","palette"],svg:bubbleSvg},{id:"pixels",label:"Pixels",group:"Pixel",hint:"Its eyes follow you. Hover over it and it perks up",defaultName:"Finn",controls:colorControls,essentials:["hair","hat","skin","hair.color","hat.color"],styleKeys:["hair"],svg:(name,overrides)=>pixelSvg(name,"color",overrides)},{id:"glyphs",label:"Glyphs",group:"Illustrated",hint:"Its eyes follow you. Hover over it and it grows",defaultName:"Priya",controls:controls12,essentials:["shape","eyes.kind","fill","tile"],styleKeys:["shape"],svg:glyphSvg},{id:"peeks",label:"Peeks",group:"Illustrated",hint:"It's watching you. Tap it to see what it does",defaultName:"Milo",controls:controls15,essentials:["body","pose","eye.kind","tile","peek.colors"],styleKeys:["body","pose","tile"],svg:peekSvg},{id:"doodles",label:"Doodles",group:"Illustrated",hint:"Its eyes follow you. Hover over it and it perks up",defaultName:"Kiko",controls:controls6,essentials:["mood","tile","colourful","ink"],styleKeys:["mood","tile"],svg:doodleSvg},{id:"animals",label:"Animals",group:"Illustrated",hint:"A cat, a dog, an owl, a bear or a tiger, drawn like the cats. Hover over it and its ears twitch",defaultName:"Biscuit",controls:animalControls,essentials:["animal","mood","eyes.color","tile","fur"],styleKeys:["mood","ears","tile"],svg:animalSvg},{id:"buddies",hidden:!0,label:"Buddies",group:"Illustrated",hint:"A tabby or a calico, up to something. Hover over it and its eyes widen",defaultName:"Mochi",controls:controls5,essentials:["character","mood","gesture","tile","fur"],styleKeys:["gesture","mood","tile"],svg:buddySvg},{id:"shapes",label:"Shapes",group:"Illustrated",hint:"A face put together from bold shapes. Its eyes follow you. Tap it and they hop",defaultName:"Lumi",controls:controls16,essentials:["eye.left","eye.right","mouth","tile","colourway"],styleKeys:["eye.left","eye.right","mouth","colourway"],svg:shapeSvg},{id:"critters",label:"Critters",group:"Illustrated",hint:"A monster, a cyclops, a bear, a duck, a chick, an imp or a grump, up close. It watches you and blinks, and pops when tapped",defaultName:"Gobo",controls:controls8,essentials:["kind","feeling","eye.style","body","iris"],styleKeys:["feeling","body"],svg:critterSvg},{id:"grins",label:"Grins",group:"Illustrated",hint:"A button of a face, a tile or round, with a big toothy grin. Its googly eyes follow you and blink, and it chomps when tapped",defaultName:"Zuzu",controls:controls11,essentials:["eyes","mouth","teeth","body"],styleKeys:["eyes","mouth","body"],svg:grinSvg},{id:"knits",hidden:!0,label:"Knits",group:"Illustrated",hint:"A bust in a knitted balaclava and a ribbed beanie. Its eyes follow you and blink",defaultName:"Kade",controls:controls10,essentials:["mood","hat","mask"],styleKeys:["mood","mask","clothes"],svg:knitSvg},{id:"glances",label:"Glances",group:"Illustrated",hint:"Just two eyes. They follow you, glance about and blink, and pop when tapped",defaultName:"Nyx",controls:controls9,essentials:["eye.left","eye.right","tile","ink"],styleKeys:["eye.left","eye.right","tile"],svg:glanceSvg},{id:"auras",still:!0,label:"Auras",group:"Illustrated",hint:"Soft colour melting together under a fine grain, or a sky, on a rounded tile. It holds perfectly still",defaultName:"Luma",controls,essentials:["type","flow","palette","aura.colors","face"],styleKeys:[],svg:auraSvg}],SHOWN=KINDS2.filter(kind=>!kind.hidden),toDataUri=svg=>`data:image/svg+xml,${encodeURIComponent(svg)}`;var createEyes=(seconds,random)=>({x:0,y:0,goalX:0,goalY:0,jitterX:0,jitterY:0,darting:!1,nextGlance:seconds+1,nextJitter:seconds,blinkAt:seconds+1+random()*3});function stepEyes(eyes2,{seconds,delta,alive,target,random}){let between=(low,high)=>low+random()*(high-low),{goalX,goalY}=eyes2;if(target)goalX=target.x,goalY=target.y;else if(!alive)goalX=0,goalY=0;else if(seconds>=eyes2.nextGlance){let centred=random()<.35;goalX=centred?0:between(-.75,.75),goalY=centred?0:between(-.5,.5),eyes2.nextGlance=seconds+between(1.1,3.2)}let blinking=seconds>=eyes2.blinkAt&&seconds<eyes2.blinkAt+.17,jump=Math.hypot(goalX-eyes2.goalX,goalY-eyes2.goalY);alive&&!blinking&&jump>.85&&random()<.5&&(eyes2.blinkAt=seconds),eyes2.goalX=goalX,eyes2.goalY=goalY;let away=Math.hypot(goalX-eyes2.x,goalY-eyes2.y);eyes2.darting=away>(eyes2.darting?.02:.3);let reach=1-Math.exp(-(eyes2.darting?42:11)*delta);if(eyes2.x+=(goalX-eyes2.x)*reach,eyes2.y+=(goalY-eyes2.y)*reach,!alive)return eyes2.jitterX=0,eyes2.jitterY=0,1;seconds>=eyes2.nextJitter&&(eyes2.jitterX=between(-.035,.035),eyes2.jitterY=between(-.035,.035),eyes2.nextJitter=seconds+between(.5,1.5));let sinceBlink=seconds-eyes2.blinkAt;return sinceBlink>.17&&random()<delta/3.6&&(eyes2.blinkAt=seconds+(random()<.2?.17*2.5:0)),sinceBlink<0||sinceBlink>=.17?1:Math.abs(sinceBlink/.17*2-1)}function fieldBounds(field,size){let[left,right,top,bottom]=[size,0,size,0];for(let y=0;y<size;y++)for(let x=0;x<size;x++)field[(y*size+x)*4]<=.003||(left=Math.min(left,x),right=Math.max(right,x+1),top=Math.min(top,y),bottom=Math.max(bottom,y+1));if(right<=left)return{cx:0,cy:0,half:1};let toSpace=2/size;return{cx:(left+right)/2*toSpace-1,cy:1-(top+bottom)/2*toSpace,half:Math.max(right-left,bottom-top)/2*toSpace}}var COARSEST=48,REFINE_PASSES=28,REFINE_RELAXATION=1.5;function halved(values,size){let half=size>>1,out=new Float32Array(half*half);for(let y=0;y<half;y++)for(let x=0;x<half;x++){let i=y*2*size+x*2;out[y*half+x]=(values[i]+values[i+1]+values[i+size]+values[i+size+1])/4}return out}function doubled(values,half,size){let out=new Float32Array(size*size);for(let y=0;y<size;y++){let fy=Math.min(half-1.001,Math.max(0,(y-.5)/2)),y0=Math.floor(fy),ty=fy-y0;for(let x=0;x<size;x++){let fx=Math.min(half-1.001,Math.max(0,(x-.5)/2)),x0=Math.floor(fx),tx=fx-x0,i=y0*half+x0,top=values[i]+(values[i+1]-values[i])*tx,bottom=values[i+half]+(values[i+half+1]-values[i+half])*tx;out[y*size+x]=top+(bottom-top)*ty}}return out}function solveHeight(coverage,size){let coarse=size>=COARSEST*2?solveHeight(halved(coverage,size),size>>1):null,height=coarse?doubled(coarse,size>>1,size):new Float32Array(size*size),cells=new Int32Array(size*size),count=0;for(let y=1;y<size-1;y++)for(let x=1;x<size-1;x++){let i=y*size+x;coverage[i]>0?cells[count++]=i:height[i]=0}let spacing=2/size,source=spacing*spacing/4,relaxation=coarse?REFINE_RELAXATION:2/(1+Math.sin(Math.PI/size)),passes=coarse?REFINE_PASSES:Math.round(size*1.25);for(let pass=0;pass<passes;pass++)for(let c=0;c<count;c++){let i=cells[c],relaxed=(height[i-1]+height[i+1]+height[i-size]+height[i+size])/4+source;height[i]+=relaxation*(relaxed*coverage[i]-height[i])}return height}function smooth2(values,size){let source=values;for(let pass=0;pass<2;pass++){let out=new Float32Array(values.length);for(let y=1;y<size-1;y++)for(let x=1;x<size-1;x++){let i=y*size+x;out[i]=(4*source[i]+2*(source[i-1]+source[i+1]+source[i-size]+source[i+size])+source[i-size-1]+source[i-size+1]+source[i+size-1]+source[i+size+1])/16}source=out}return source}function blur(values,size,radius){let width=radius*2+1,source=values;for(let pass=0;pass<12;pass++){let[step,line4]=pass%2?[size,1]:[1,size],target=new Float32Array(values.length);for(let row=0;row<size;row++){let sum=0;for(let i=0;i<size;i++)sum+=source[row*line4+i*step],i>=width&&(sum-=source[row*line4+(i-width)*step]),i>=radius&&(target[row*line4+(i-radius)*step]=sum/width)}source=target}return source}function filleted(coverage,size){return blur(coverage,size,4).map(value=>Math.min(1,Math.max(0,(value-.5)*16+.5)))}function rasterizer(size){let canvas=document.createElement("canvas");canvas.width=canvas.height=size;let context=canvas.getContext("2d",{willReadFrequently:!0});return context.scale(size/100,size/100),draw2=>{context.clearRect(0,0,100,100),draw2(context);let{data}=context.getImageData(0,0,size,size),alpha=new Float32Array(size*size);for(let i=0;i<alpha.length;i++)alpha[i]=data[i*4+3]/255;return alpha}}var blended=(a,b)=>{let[high,low]=a>b?[a,b]:[b,a];return high>0?high+low*low/(3*high):0},CLAY_DEPTH=2.56,PRESS_FILLET=.012,PRESS_DEPTH=2,PRESS_BACK=1.3;function pressedOn(body,piece){if(piece<=0)return[body,0];let[under,on]=[Math.sqrt(Math.max(body,0)),Math.sqrt(piece)*PRESS_DEPTH],fillet=PRESS_FILLET*Math.min(1,under/PRESS_FILLET),rise=on*on/(on+fillet),front=under+rise,back=smoothMax(under,rise*PRESS_BACK,PRESS_FILLET*2);return[((front+back)/2)**2,(front-back)/2]}var smoothMax=(a,b,k)=>{let h=Math.max(k-Math.abs(a-b),0)/k;return Math.max(a,b)+h*h*k/4};function buildField(parts){let rasterize=rasterizer(320),fill=paths=>rasterize(context=>{for(let d of paths)context.fill(new Path2D(d))}),accents=fill(parts.accents),visor=fill(parts.visor),chrome=fill(parts.chrome),studs=fill(parts.studs),head2=fill(parts.head),headHeight=smooth2(solveHeight(parts.painted?filleted(head2,320):head2,320),320),accentHeight=smooth2(solveHeight(accents,320),320),accentBody=smooth2(accents,320),recess=smooth2(smooth2(visor,320),320),visorEdge=blur(visor,320,1),chromeRise=smooth2(chrome,320),studRise=smooth2(smooth2(studs,320),320),raised=parts.raised?.length?smooth2(solveHeight(fill(parts.raised),320),320):null,field=new Float32Array(320*320*4);for(let i=0;i<320*320;i++){let skin=headHeight[i]*(1-.15*recess[i]),part=accentHeight[i]+.004*accentBody[i],rise=1+.07*Math.max(0,1-Math.abs(visorEdge[i]-.3)/.3)+.06*chromeRise[i]+.16*studRise[i],height=parts.matte?blended(skin,part*CLAY_DEPTH):Math.max(skin,part),[pressed,forward]=raised?pressedOn(height,raised[i]):[height,0];field[i*4]=pressed*rise,field[i*4+1]=forward,field[i*4+3]=Math.min(1,Math.max(0,(part-skin)/.002+.5))}return field}var VERTEX_SHADER=`#version 300 es
|
|
3
|
+
out vec2 vUv;
|
|
4
|
+
void main() {
|
|
5
|
+
vec2 corner = vec2((gl_VertexID << 1) & 2, gl_VertexID & 2);
|
|
6
|
+
vUv = corner * 2.0 - 1.0;
|
|
7
|
+
gl_Position = vec4(vUv, 0.0, 1.0);
|
|
8
|
+
}`,FRAGMENT_SHADER=`#version 300 es
|
|
9
|
+
precision highp float;
|
|
10
|
+
|
|
11
|
+
// Rays per pixel along each side. Set per program, so the loop below can be unrolled.
|
|
12
|
+
#ifndef SAMPLES
|
|
13
|
+
#define SAMPLES 1
|
|
14
|
+
#endif
|
|
15
|
+
|
|
16
|
+
const float VIEW = 1.04; // Half the frame, leaving room to tilt and bob.
|
|
17
|
+
const float CAMERA = 7.0;
|
|
18
|
+
const float THICKNESS = 0.8; // k: 1 is a full sphere, lower flattens the bot.
|
|
19
|
+
const float DEPTH = 1.4; // No surface point has a larger |z|, hands pressed on in front included.
|
|
20
|
+
const float EDGE = 0.0024; // Height of the outline, just above the blurred edge.
|
|
21
|
+
// Enough to cross the avatar's box from corner to corner at the finest safe stride.
|
|
22
|
+
const int MAX_STEPS = 128;
|
|
23
|
+
const float FAR_STEP = 0.06; // Stride through empty space.
|
|
24
|
+
const float NEAR_STEP = 0.007; // Fine enough not to skip through a thin rim.
|
|
25
|
+
const float FLECK_SCALE = 62.0; // Flecks per unit along each axis.
|
|
26
|
+
// Measures across the shell's detail, in viewBox units, matching what the field used to blur.
|
|
27
|
+
const float RIM_WIDTH = 0.88; // The chrome bezel round the glass.
|
|
28
|
+
const float BEVEL_OUT = 0.53; // Where the glass's bevelled edge begins, inside its outline...
|
|
29
|
+
const float BEVEL_IN = 0.8; // ...and where the flat black screen takes over.
|
|
30
|
+
const float STUD_RING = 0.3; // The chrome ring round a stud.
|
|
31
|
+
const float FAR = 4.0; // Past this a part is simply absent, which lets a morph grow it.
|
|
32
|
+
const float PAINTED_GAZE = 0.4; // How far painted eyes shift with the gaze, against a bot's lights.
|
|
33
|
+
// What each shape is for, as the stage tags them.
|
|
34
|
+
const int ROLE_LIGHT = 0;
|
|
35
|
+
const int ROLE_EYE = 1;
|
|
36
|
+
const int ROLE_GLASS = 2;
|
|
37
|
+
const int ROLE_STUD = 3;
|
|
38
|
+
const int ROLE_CHROME = 4;
|
|
39
|
+
const int ROLE_SHINE = 5; // A white glint on an eye, which blinks and looks with it.
|
|
40
|
+
const int ROLE_TINT = 6; // A mark in the visor's colour, such as a tongue, which stays put.
|
|
41
|
+
const int ROLE_WHITE = 7; // The white of an eye, under its pupil: it blinks, but stays put as the pupil looks.
|
|
42
|
+
const vec3 EYE_WHITE = vec3(1.0, 0.97, 0.9);
|
|
43
|
+
|
|
44
|
+
uniform sampler2D uField; // Height, how far forward the surface is centred, unused, accent.
|
|
45
|
+
uniform mat3 uRotation;
|
|
46
|
+
uniform vec3 uPosition;
|
|
47
|
+
uniform float uScale;
|
|
48
|
+
uniform vec3 uBody;
|
|
49
|
+
uniform vec3 uAccent;
|
|
50
|
+
uniform vec3 uVisor;
|
|
51
|
+
uniform vec3 uLight;
|
|
52
|
+
uniform float uEyeY;
|
|
53
|
+
uniform float uPainted; // 1 when the lights are eyes on the skin, not LEDs.
|
|
54
|
+
// The glass, studs, chrome and lights as shapes in the 100\xD7100 viewBox, and those of the
|
|
55
|
+
// face a morph is leaving. Drawn from these, every edge is exact at any zoom.
|
|
56
|
+
const int MAX_SHAPES = 32;
|
|
57
|
+
uniform vec4 uShapeA[MAX_SHAPES];
|
|
58
|
+
uniform vec4 uShapeB[MAX_SHAPES];
|
|
59
|
+
uniform int uShapes;
|
|
60
|
+
uniform vec4 uFromShapeA[MAX_SHAPES];
|
|
61
|
+
uniform vec4 uFromShapeB[MAX_SHAPES];
|
|
62
|
+
uniform int uFromShapes;
|
|
63
|
+
uniform float uShapeMix;
|
|
64
|
+
uniform float uSpeckle;
|
|
65
|
+
uniform vec3 uJelly; // A gummy: 1, then how milky its shell is and how big its glow. 2 is clay.
|
|
66
|
+
uniform vec4 uFigure; // The outline's centre and half its size, then the field's peak.
|
|
67
|
+
uniform vec4 uBox; // Where anything is drawn, across and up: its left, bottom, right and top.
|
|
68
|
+
uniform float uStride; // How far the march may step, for how far outside the surface it is.
|
|
69
|
+
uniform float uOpen;
|
|
70
|
+
uniform vec2 uLook;
|
|
71
|
+
uniform float uTexel;
|
|
72
|
+
uniform float uPixel;
|
|
73
|
+
uniform vec4 uFrame; // Maps the whole-pixel viewport onto the slot: scale, then offset.
|
|
74
|
+
uniform float uStep; // One pixel, in the slot's own -1 to 1 space.
|
|
75
|
+
uniform vec3 uTile; // The container: half its side and its corner radius in slot space, and how shown.
|
|
76
|
+
uniform vec3 uTileColor; // Its colour, as displayed.
|
|
77
|
+
|
|
78
|
+
in vec2 vUv;
|
|
79
|
+
out vec4 outColor;
|
|
80
|
+
|
|
81
|
+
// textureLod, not texture: gradients inside the march loop make Direct3D compilers
|
|
82
|
+
// unroll it, which slows both compiling and drawing.
|
|
83
|
+
vec4 fieldAt(vec2 p) {
|
|
84
|
+
return textureLod(uField, vec2(p.x, -p.y) * 0.5 + 0.5, 0.0);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Where \`value\` crosses \`level\`, as a hard edge softened over exactly one pixel, the way
|
|
89
|
+
* a vector shape is drawn. \`slope\` is the value's slope across the field, and \`pixelX\` and
|
|
90
|
+
* \`pixelY\` how far one pixel reaches over it, so each pixel's own edge width is exact.
|
|
91
|
+
*/
|
|
92
|
+
float sharp(float value, vec2 slope, float level, vec2 pixelX, vec2 pixelY) {
|
|
93
|
+
float perPixel = length(vec2(dot(slope, pixelX), dot(slope, pixelY)));
|
|
94
|
+
return clamp((value - level) / max(perPixel, 1e-6) + 0.5, 0.0, 1.0);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* The field read through a cubic B-spline, from four bilinear reads. A plain read joins
|
|
99
|
+
* texels with straight lines, so a sharpened edge drawn from it turns into short straight
|
|
100
|
+
* dashes. This one curves smoothly between texels. Too costly for the march, which only
|
|
101
|
+
* needs to find the surface, so it is kept for what is drawn: masks and normals.
|
|
102
|
+
*/
|
|
103
|
+
vec4 smoothFieldAt(vec2 p) {
|
|
104
|
+
float size = 2.0 / uTexel;
|
|
105
|
+
vec2 coord = (vec2(p.x, -p.y) * 0.5 + 0.5) * size - 0.5;
|
|
106
|
+
vec2 cell = floor(coord);
|
|
107
|
+
vec2 f = coord - cell;
|
|
108
|
+
vec2 f2 = f * f;
|
|
109
|
+
vec2 f3 = f2 * f;
|
|
110
|
+
vec2 w0 = (1.0 - 3.0 * f + 3.0 * f2 - f3) / 6.0;
|
|
111
|
+
vec2 w1 = (4.0 - 6.0 * f2 + 3.0 * f3) / 6.0;
|
|
112
|
+
vec2 w2 = (1.0 + 3.0 * f + 3.0 * f2 - 3.0 * f3) / 6.0;
|
|
113
|
+
vec2 w3 = f3 / 6.0;
|
|
114
|
+
vec2 g0 = w0 + w1;
|
|
115
|
+
vec2 g1 = w2 + w3;
|
|
116
|
+
vec2 h0 = (cell - 0.5 + w1 / g0) / size;
|
|
117
|
+
vec2 h1 = (cell + 1.5 + w3 / g1) / size;
|
|
118
|
+
return g0.y * (g0.x * textureLod(uField, h0, 0.0) + g1.x * textureLod(uField, vec2(h1.x, h0.y), 0.0)) +
|
|
119
|
+
g1.y * (g0.x * textureLod(uField, vec2(h0.x, h1.y), 0.0) + g1.x * textureLod(uField, h1, 0.0));
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* How far in front of its middle \`p\` is. The surface is centred on z = 0, except where clay
|
|
124
|
+
* is pressed onto its front: there it is centred further forward, so a hand stands proud of
|
|
125
|
+
* the front only, and past the body's edge is a ball in front of it rather than a fin.
|
|
126
|
+
*/
|
|
127
|
+
float offMiddle(vec3 p, vec4 field) {
|
|
128
|
+
return p.z - 2.0 * THICKNESS * field.g;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
float surface(vec3 p) {
|
|
132
|
+
vec4 field = fieldAt(p.xy);
|
|
133
|
+
float z = offMiddle(p, field);
|
|
134
|
+
return field.r - EDGE - z * z / (4.0 * THICKNESS * THICKNESS);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/** The surface formula's slope at \`p\`, from the field's slopes there: down it, inside is lower. */
|
|
138
|
+
vec3 slopeOf(vec3 p, vec4 field, vec4 dx, vec4 dy) {
|
|
139
|
+
float z = offMiddle(p, field);
|
|
140
|
+
return vec3(dx.r + z * dx.g / THICKNESS, dy.r + z * dy.g / THICKNESS, -z / (2.0 * THICKNESS * THICKNESS));
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/** Every channel's slope at \`p\`, along x and along y. */
|
|
144
|
+
void slopeAt(vec2 p, out vec4 dx, out vec4 dy) {
|
|
145
|
+
float e = uTexel * 2.0;
|
|
146
|
+
dx = (smoothFieldAt(p + vec2(e, 0.0)) - smoothFieldAt(p - vec2(e, 0.0))) / (2.0 * e);
|
|
147
|
+
dy = (smoothFieldAt(p + vec2(0.0, e)) - smoothFieldAt(p - vec2(0.0, e))) / (2.0 * e);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* How far \`v\` is from a shape's outline, in viewBox units, negative inside, and which way
|
|
152
|
+
* is out. Each kind of shape is a formula, so the outline is exact, as in a vector drawing,
|
|
153
|
+
* with no picture of it in between to blur or step at any zoom.
|
|
154
|
+
*/
|
|
155
|
+
/** What a shape is for, and what kind of shape it is, from the number the stage packs them in. */
|
|
156
|
+
int roleOf(vec4 b) { return int(b.w + 0.5) / 8; }
|
|
157
|
+
int kindOf(vec4 b) { return int(b.w + 0.5) - 8 * roleOf(b); }
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* How far \`v\` is from a quadratic B\xE9zier from \`p0\` through control \`p1\` to \`p2\`, exactly, and
|
|
161
|
+
* which way is out: the nearest point solves a cubic, which has a closed form.
|
|
162
|
+
*/
|
|
163
|
+
float curveDistance(vec2 v, vec2 p0, vec2 p1, vec2 p2, out vec2 outward) {
|
|
164
|
+
vec2 a = p1 - p0;
|
|
165
|
+
vec2 b = p0 - 2.0 * p1 + p2;
|
|
166
|
+
vec2 c = a * 2.0;
|
|
167
|
+
vec2 d = p0 - v;
|
|
168
|
+
// Nearly straight, it is a segment, and the cubic would divide by nothing.
|
|
169
|
+
if (dot(b, b) < 1e-6) {
|
|
170
|
+
vec2 along = p2 - p0;
|
|
171
|
+
float h = clamp(dot(v - p0, along) / max(dot(along, along), 1e-6), 0.0, 1.0);
|
|
172
|
+
vec2 off = v - p0 - along * h;
|
|
173
|
+
float distance = length(off);
|
|
174
|
+
outward = off / max(distance, 1e-6);
|
|
175
|
+
return distance;
|
|
176
|
+
}
|
|
177
|
+
float kk = 1.0 / dot(b, b);
|
|
178
|
+
float kx = kk * dot(a, b);
|
|
179
|
+
float ky = kk * (2.0 * dot(a, a) + dot(d, b)) / 3.0;
|
|
180
|
+
float kz = kk * dot(d, a);
|
|
181
|
+
float p = ky - kx * kx;
|
|
182
|
+
float q = kx * (2.0 * kx * kx - 3.0 * ky) + kz;
|
|
183
|
+
float h = q * q + 4.0 * p * p * p;
|
|
184
|
+
vec2 nearest;
|
|
185
|
+
if (h >= 0.0) {
|
|
186
|
+
h = sqrt(h);
|
|
187
|
+
vec2 x = (vec2(h, -h) - q) / 2.0;
|
|
188
|
+
vec2 roots = sign(x) * pow(abs(x), vec2(1.0 / 3.0));
|
|
189
|
+
float t = clamp(roots.x + roots.y - kx, 0.0, 1.0);
|
|
190
|
+
nearest = d + (c + b * t) * t;
|
|
191
|
+
} else {
|
|
192
|
+
float z = sqrt(-p);
|
|
193
|
+
float angle = acos(clamp(q / (p * z * 2.0), -1.0, 1.0)) / 3.0;
|
|
194
|
+
float m = cos(angle);
|
|
195
|
+
float n = sin(angle) * 1.732050808;
|
|
196
|
+
vec2 t = clamp(vec2(m + m, -n - m) * z - kx, 0.0, 1.0);
|
|
197
|
+
vec2 first = d + (c + b * t.x) * t.x;
|
|
198
|
+
vec2 second = d + (c + b * t.y) * t.y;
|
|
199
|
+
nearest = dot(first, first) < dot(second, second) ? first : second;
|
|
200
|
+
}
|
|
201
|
+
// \`nearest\` runs from \`v\` to the curve, so out is the other way.
|
|
202
|
+
float distance = length(nearest);
|
|
203
|
+
outward = -nearest / max(distance, 1e-6);
|
|
204
|
+
return distance;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
float shapeDistance(vec4 a, vec4 b, vec2 v, out vec2 outward) {
|
|
208
|
+
float inside;
|
|
209
|
+
vec2 slope;
|
|
210
|
+
int kind = kindOf(b);
|
|
211
|
+
if (kind == 3) {
|
|
212
|
+
// A curved stroke, drawn exactly rather than as straight pieces, whose joins would kink.
|
|
213
|
+
return curveDistance(v, a.xy, a.zw, b.xy, outward) - b.z;
|
|
214
|
+
}
|
|
215
|
+
if (kind == 0) {
|
|
216
|
+
// A superellipse: |x/rx|^n + |y/ry|^n = 1, turned by b.y. Above about 5.2 the curve
|
|
217
|
+
// drawn for still pictures stops getting squarer, so this stops there too.
|
|
218
|
+
float n = min(b.x, 5.19);
|
|
219
|
+
float c = cos(b.y);
|
|
220
|
+
float s = sin(b.y);
|
|
221
|
+
vec2 d = v - a.xy;
|
|
222
|
+
vec2 local = vec2(c * d.x + s * d.y, -s * d.x + c * d.y);
|
|
223
|
+
vec2 q = max(abs(local) / a.zw, 1e-6);
|
|
224
|
+
float size = pow(pow(q.x, n) + pow(q.y, n), 1.0 / n);
|
|
225
|
+
inside = size - 1.0;
|
|
226
|
+
vec2 along = sign(local) * pow(q, vec2(n - 1.0)) / a.zw * pow(max(size, 1e-4), 1.0 - n);
|
|
227
|
+
slope = vec2(c * along.x - s * along.y, s * along.x + c * along.y);
|
|
228
|
+
} else if (kind == 1) {
|
|
229
|
+
// A crescent: the sliver between two parabolas that meet at its points.
|
|
230
|
+
float width = a.z;
|
|
231
|
+
float lift = a.w;
|
|
232
|
+
float thickness = b.x;
|
|
233
|
+
float u = (v.x - a.x) / width;
|
|
234
|
+
float curve = 1.0 - u * u;
|
|
235
|
+
float centre = a.y - (lift - thickness * 0.5) * curve;
|
|
236
|
+
float spread = abs(thickness) * 0.5 * curve;
|
|
237
|
+
float off = v.y - centre;
|
|
238
|
+
inside = abs(off) - spread;
|
|
239
|
+
float bend = -2.0 * u / width;
|
|
240
|
+
slope = vec2(sign(off) * (lift - thickness * 0.5) * bend - abs(thickness) * 0.5 * bend, sign(off));
|
|
241
|
+
} else {
|
|
242
|
+
// A capsule round the segment from a.xy to a.zw, or a circle when they meet. Exact.
|
|
243
|
+
vec2 pa = v - a.xy;
|
|
244
|
+
vec2 ba = a.zw - a.xy;
|
|
245
|
+
float h = clamp(dot(pa, ba) / max(dot(ba, ba), 1e-6), 0.0, 1.0);
|
|
246
|
+
vec2 d = pa - ba * h;
|
|
247
|
+
float distance = length(d);
|
|
248
|
+
outward = d / max(distance, 1e-6);
|
|
249
|
+
return distance - b.x;
|
|
250
|
+
}
|
|
251
|
+
// The formula over its own slope is the distance, to first order, which near the outline
|
|
252
|
+
// is all an edge needs.
|
|
253
|
+
float steep = max(length(slope), 1e-6);
|
|
254
|
+
outward = slope / steep;
|
|
255
|
+
float distance = inside / steep;
|
|
256
|
+
// Stroked, a superellipse is a ring that thick either side of its outline.
|
|
257
|
+
if (kind == 0 && b.z > 0.0) {
|
|
258
|
+
if (distance < 0.0) outward = -outward;
|
|
259
|
+
return abs(distance) - b.z;
|
|
260
|
+
}
|
|
261
|
+
return distance;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
/** How much of a pixel lies inside, for a pixel reaching \`pixelX\` and \`pixelY\`. */
|
|
265
|
+
float coverAt(float distance, vec2 outward, vec2 pixelX, vec2 pixelY) {
|
|
266
|
+
float perPixel = length(vec2(dot(outward, pixelX), dot(outward, pixelY)));
|
|
267
|
+
return clamp(0.5 - distance / max(perPixel, 1e-6), 0.0, 1.0);
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
vec4 shapeA(int i, bool before) { return before ? uFromShapeA[i] : uShapeA[i]; }
|
|
271
|
+
vec4 shapeB(int i, bool before) { return before ? uFromShapeB[i] : uShapeB[i]; }
|
|
272
|
+
|
|
273
|
+
/** The shell's detail near one point: how far it is from each part's outline, and which way is out. */
|
|
274
|
+
struct Trim {
|
|
275
|
+
float glass;
|
|
276
|
+
vec2 glassOut;
|
|
277
|
+
float stud;
|
|
278
|
+
vec2 studOut;
|
|
279
|
+
float chrome;
|
|
280
|
+
vec2 chromeOut;
|
|
281
|
+
};
|
|
282
|
+
|
|
283
|
+
/** The nearest outline of each part among one face's shapes, in a single pass over them. */
|
|
284
|
+
Trim trimOf(bool before, vec2 v) {
|
|
285
|
+
Trim trim = Trim(FAR, vec2(1.0, 0.0), FAR, vec2(1.0, 0.0), FAR, vec2(1.0, 0.0));
|
|
286
|
+
int count = before ? uFromShapes : uShapes;
|
|
287
|
+
for (int i = 0; i < MAX_SHAPES; i++) {
|
|
288
|
+
if (i >= count) break;
|
|
289
|
+
vec4 b = shapeB(i, before);
|
|
290
|
+
int role = roleOf(b);
|
|
291
|
+
if (role < ROLE_GLASS) continue;
|
|
292
|
+
vec2 way;
|
|
293
|
+
float d = shapeDistance(shapeA(i, before), b, v, way);
|
|
294
|
+
if (role == ROLE_GLASS && d < trim.glass) {
|
|
295
|
+
trim.glass = d;
|
|
296
|
+
trim.glassOut = way;
|
|
297
|
+
} else if (role == ROLE_STUD && d < trim.stud) {
|
|
298
|
+
trim.stud = d;
|
|
299
|
+
trim.studOut = way;
|
|
300
|
+
} else if (role == ROLE_CHROME && d < trim.chrome) {
|
|
301
|
+
trim.chrome = d;
|
|
302
|
+
trim.chromeOut = way;
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
return trim;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
/**
|
|
309
|
+
* The same, eased from the old face's to the new one's during a morph. Blending distances
|
|
310
|
+
* grows, shrinks and moves each part rather than fading it.
|
|
311
|
+
*/
|
|
312
|
+
Trim morphedTrim(vec2 v) {
|
|
313
|
+
Trim now = trimOf(false, v);
|
|
314
|
+
if (uFromShapes == 0) return now;
|
|
315
|
+
Trim before = trimOf(true, v);
|
|
316
|
+
Trim trim = now;
|
|
317
|
+
trim.glass = mix(before.glass, now.glass, uShapeMix);
|
|
318
|
+
trim.stud = mix(before.stud, now.stud, uShapeMix);
|
|
319
|
+
trim.chrome = mix(before.chrome, now.chrome, uShapeMix);
|
|
320
|
+
if (now.glass >= FAR) trim.glassOut = before.glassOut;
|
|
321
|
+
if (now.stud >= FAR) trim.studOut = before.studOut;
|
|
322
|
+
if (now.chrome >= FAR) trim.chromeOut = before.chromeOut;
|
|
323
|
+
return trim;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
/** How much of the pixel the lights cover, the eyes read where a blink has squashed them. */
|
|
327
|
+
float lightsAt(bool before, vec2 atLit, vec2 atLid, vec2 litX, vec2 litY, vec2 lidX, vec2 lidY) {
|
|
328
|
+
float cover = 0.0;
|
|
329
|
+
int count = before ? uFromShapes : uShapes;
|
|
330
|
+
for (int i = 0; i < MAX_SHAPES; i++) {
|
|
331
|
+
if (i >= count) break;
|
|
332
|
+
vec4 b = shapeB(i, before);
|
|
333
|
+
int role = roleOf(b);
|
|
334
|
+
if (role != ROLE_LIGHT && role != ROLE_EYE) continue;
|
|
335
|
+
bool blinks = role == ROLE_EYE;
|
|
336
|
+
vec2 way;
|
|
337
|
+
float d = shapeDistance(shapeA(i, before), b, blinks ? atLid : atLit, way);
|
|
338
|
+
cover = max(cover, coverAt(d, way, blinks ? lidX : litX, blinks ? lidY : litY));
|
|
339
|
+
}
|
|
340
|
+
return cover;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
/**
|
|
344
|
+
* How much of the pixel the glints, the tinted marks and the whites of the eyes cover, in that
|
|
345
|
+
* order. Clay draws them. \`atStill\` is where the pixel is for a blink with no gaze.
|
|
346
|
+
*/
|
|
347
|
+
vec3 marksAt(bool before, vec2 atLit, vec2 atLid, vec2 atStill, vec2 litX, vec2 litY, vec2 lidX, vec2 lidY) {
|
|
348
|
+
vec3 cover = vec3(0.0);
|
|
349
|
+
int count = before ? uFromShapes : uShapes;
|
|
350
|
+
for (int i = 0; i < MAX_SHAPES; i++) {
|
|
351
|
+
if (i >= count) break;
|
|
352
|
+
vec4 b = shapeB(i, before);
|
|
353
|
+
int role = roleOf(b);
|
|
354
|
+
if (role < ROLE_SHINE) continue;
|
|
355
|
+
bool shine = role == ROLE_SHINE;
|
|
356
|
+
bool white = role == ROLE_WHITE;
|
|
357
|
+
vec2 way;
|
|
358
|
+
float d = shapeDistance(shapeA(i, before), b, shine ? atLid : white ? atStill : atLit, way);
|
|
359
|
+
float c = coverAt(d, way, shine || white ? lidX : litX, shine || white ? lidY : litY);
|
|
360
|
+
if (shine) cover.x = max(cover.x, c);
|
|
361
|
+
else if (white) cover.z = max(cover.z, c);
|
|
362
|
+
else cover.y = max(cover.y, c);
|
|
363
|
+
}
|
|
364
|
+
return cover;
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
float softbox(vec2 p, vec2 center, vec2 size, float blur) {
|
|
368
|
+
vec2 d = abs(p - center) - size;
|
|
369
|
+
// A smooth maximum. A plain one folds along the box's diagonals, which glossy skin
|
|
370
|
+
// mirrors as crease lines.
|
|
371
|
+
float edge = 0.5 * (d.x + d.y + sqrt((d.x - d.y) * (d.x - d.y) + blur * blur));
|
|
372
|
+
return smoothstep(blur, -blur, edge);
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
/** A dark studio: a large softbox above left and a strip light to the right. */
|
|
376
|
+
vec3 studio(vec3 r) {
|
|
377
|
+
// A smooth |z|, for the same reason as the softbox's smooth maximum.
|
|
378
|
+
vec2 q = r.xy / (sqrt(r.z * r.z + 0.04) + 0.6);
|
|
379
|
+
vec3 color = mix(vec3(0.02, 0.02, 0.035), vec3(0.34, 0.36, 0.42), smoothstep(-0.6, 0.9, r.y));
|
|
380
|
+
color += vec3(1.0, 0.98, 0.95) * 3.2 * softbox(q, vec2(-0.4, 0.58), vec2(0.5, 0.3), 0.2);
|
|
381
|
+
color += vec3(0.85, 0.9, 1.0) * 0.8 * softbox(q, vec2(1.1, -0.05), vec2(0.1, 0.8), 0.4);
|
|
382
|
+
return color;
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
float hash(vec3 cell) {
|
|
386
|
+
vec3 q = fract(cell * 0.3183 + 0.1) * 17.0;
|
|
387
|
+
return fract(q.x * q.y * q.z * (q.x + q.y + q.z));
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
/** Tiny pale flecks, set in the bot's own space so they turn with it. */
|
|
391
|
+
float flecks(vec3 p) {
|
|
392
|
+
vec3 scaled = p * FLECK_SCALE;
|
|
393
|
+
vec3 cell = floor(scaled);
|
|
394
|
+
float seed = hash(cell);
|
|
395
|
+
if (seed > 0.2 + 0.28 * uSpeckle) return 0.0;
|
|
396
|
+
vec3 offset = vec3(hash(cell + 1.0), hash(cell + 2.0), hash(cell + 3.0)) - 0.5;
|
|
397
|
+
float distanceFromCentre = length(fract(scaled) - 0.5 - offset * 0.5);
|
|
398
|
+
float size = 0.1 + 0.2 * hash(cell + 4.0);
|
|
399
|
+
return smoothstep(size, size * 0.55, distanceFromCentre);
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
/**
|
|
403
|
+
* A gummy, after its still picture: a pale frosted shell, a pool of colour glowing inside it, a
|
|
404
|
+
* brighter band low down and a white foot, a frosty rim, a pearly topper and an inked face.
|
|
405
|
+
*
|
|
406
|
+
* The pool is read where the ray, bent a little as it enters, would cross the body's middle.
|
|
407
|
+
* It slides against the shell as the gummy turns, which is what makes it look inside it
|
|
408
|
+
* rather than painted on. Its shape is the body's own, deepest where the body is thickest.
|
|
409
|
+
*/
|
|
410
|
+
vec3 jellyShade(vec3 p, vec3 n, vec3 view, float topper, float light) {
|
|
411
|
+
vec3 white = vec3(1.0);
|
|
412
|
+
// Up the figure, from -1 at its foot to 1 at its top.
|
|
413
|
+
float up = (p.y - uFigure.y) / uFigure.z;
|
|
414
|
+
vec3 inward = view * uRotation;
|
|
415
|
+
vec2 through = p.xy - inward.xy * (max(p.z, 0.0) / max(inward.z, 0.3)) * 0.65;
|
|
416
|
+
// Sat low in the body, as the pool is in the still picture, leaving frost above it for the face.
|
|
417
|
+
float deep = fieldAt(through + vec2(0.0, 0.3 * uFigure.z)).r / uFigure.w;
|
|
418
|
+
// A bigger glow starts nearer the edge and is full sooner. The middle of its range is as before.
|
|
419
|
+
float grow = clamp((uJelly.z - 0.86) / 0.22, 0.0, 1.0);
|
|
420
|
+
float pool = smoothstep(mix(0.36, 0.1, grow), mix(0.95, 0.72, grow), deep) * (1.0 - topper);
|
|
421
|
+
float band = smoothstep(-0.98, -0.62, up) * smoothstep(-0.2, -0.55, up);
|
|
422
|
+
float foot = smoothstep(-0.7, -0.97, up);
|
|
423
|
+
|
|
424
|
+
vec3 frost = mix(uBody, white, uJelly.y);
|
|
425
|
+
vec3 glow = mix(uBody, uAccent, band * 0.55);
|
|
426
|
+
vec3 body = mix(frost, glow, pool * 0.9);
|
|
427
|
+
body = mix(body, white, foot * 0.6 * (1.0 - pool * 0.6));
|
|
428
|
+
|
|
429
|
+
vec3 key = normalize(vec3(-0.45, 0.8, 0.65));
|
|
430
|
+
float facing = max(dot(n, view), 0.0);
|
|
431
|
+
float rim = pow(1.0 - facing, 2.6);
|
|
432
|
+
float wrapped = smoothstep(-0.8, 1.0, dot(n, key));
|
|
433
|
+
// Light passes through, so the far side only dims a little and keeps its colour.
|
|
434
|
+
vec3 color = body * mix(0.66, 1.06, wrapped) + glow * pool * 0.22;
|
|
435
|
+
|
|
436
|
+
// Pearl: white where it faces you, shifting through the gummy's own colours towards its edge.
|
|
437
|
+
vec3 sheenTint = mix(mix(uAccent, white, 0.5), mix(uBody, vec3(1.0, 0.55, 0.85), 0.45), smoothstep(0.2, 0.9, 1.0 - facing));
|
|
438
|
+
vec3 pearl = mix(white, sheenTint, 0.3 + 0.55 * (1.0 - facing)) * mix(0.72, 1.08, wrapped);
|
|
439
|
+
color = mix(color, pearl, topper);
|
|
440
|
+
color = mix(color, uLight, light);
|
|
441
|
+
|
|
442
|
+
// Thin at the edge, so the frost scatters the most light there.
|
|
443
|
+
color = mix(color, mix(frost, white, 0.55), rim * 0.6 * (1.0 - light));
|
|
444
|
+
// A soft sheen across the top, as in the still picture.
|
|
445
|
+
color += white * 0.16 * smoothstep(0.25, 0.95, up) * facing * (1.0 - topper) * (1.0 - light);
|
|
446
|
+
|
|
447
|
+
vec3 reflected = reflect(-view, n);
|
|
448
|
+
float highlight = max(dot(reflected, key), 0.0);
|
|
449
|
+
color += studio(reflected) * mix(0.05, 0.5, pow(1.0 - facing, 3.0)) * mix(1.0, 0.45, light);
|
|
450
|
+
color += mix(body, white, 0.7) * pow(highlight, 8.0) * 0.16;
|
|
451
|
+
color += white * pow(highlight, 120.0) * 0.95;
|
|
452
|
+
return color;
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
/**
|
|
456
|
+
* Clay, lit as the LanderStudio ClayRobot is: a blue-grey sky dome, a little stronger from
|
|
457
|
+
* above and from the sun's side, and one warm sun, fitted against a studio
|
|
458
|
+
* still. The colour is an albedo relative to the clay those were fitted under. There is no
|
|
459
|
+
* gloss, and creases, such as where an arm joins, fall into soft occlusion rather than a line.
|
|
460
|
+
*
|
|
461
|
+
* \`local\` is the normal in the field's own space and \`gradient\` the surface's slope there,
|
|
462
|
+
* which turn the probes along the normal into distances.
|
|
463
|
+
*/
|
|
464
|
+
vec3 clayShade(vec3 p, vec3 n, vec3 local, float gradient, vec3 paint, float light, vec3 marks) {
|
|
465
|
+
const vec3 SKY = vec3(0.456, 0.52, 0.541);
|
|
466
|
+
const vec3 SKY_UP = vec3(0.03, 0.019, 0.011);
|
|
467
|
+
const vec3 SKY_SIDE = vec3(0.01, 0.052, 0.081);
|
|
468
|
+
const vec3 SKY_AWAY = vec3(-0.151, -0.124, -0.087);
|
|
469
|
+
const vec3 SUN_COLOR = vec3(0.293, 0.227, 0.17);
|
|
470
|
+
// Its sun is moved round to the upper left, where both mallows' references are lit from.
|
|
471
|
+
const vec3 SUN = vec3(-0.77, 0.56, 0.31);
|
|
472
|
+
// The clay the light was fitted under, #eeefeb, in linear.
|
|
473
|
+
const vec3 FITTED = vec3(0.855, 0.863, 0.83);
|
|
474
|
+
|
|
475
|
+
float occluded = 0.0;
|
|
476
|
+
for (int i = 1; i <= 3; i++) {
|
|
477
|
+
float h = 0.045 * float(i);
|
|
478
|
+
occluded += clamp(surface(p + local * h) / (gradient * h), 0.0, 1.0) / float(i);
|
|
479
|
+
}
|
|
480
|
+
// Floored, so a crease reads as a soft shade, never a dark cut.
|
|
481
|
+
float ao = mix(0.45, 1.0, clamp(1.0 - occluded / 1.83, 0.0, 1.0));
|
|
482
|
+
|
|
483
|
+
float side = -n.x;
|
|
484
|
+
vec3 sky = (SKY + SKY_UP * n.y + SKY_SIDE * max(side, 0.0) + SKY_AWAY * max(-side, 0.0)) * ao;
|
|
485
|
+
vec3 lit = sky + SUN_COLOR * max(dot(n, SUN), 0.0) * mix(0.6, 1.0, ao);
|
|
486
|
+
// That studio was darker than the canvas: exposed up, so the front keeps the clay's own pastel.
|
|
487
|
+
vec3 color = paint / FITTED * lit * 1.55;
|
|
488
|
+
// The whites of the eyes are lit too, a little, so they sit on the clay rather than over it.
|
|
489
|
+
color = mix(color, EYE_WHITE * mix(0.85, 1.0, ao) * mix(0.84, 1.03, clamp(dot(n, SUN) * 0.5 + 0.5, 0.0, 1.0)), marks.z);
|
|
490
|
+
color = mix(color, uLight * mix(0.8, 1.0, ao), light);
|
|
491
|
+
color = mix(color, uVisor * mix(0.8, 1.0, ao), marks.y);
|
|
492
|
+
return mix(color, vec3(1.0), marks.x);
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
/**
|
|
496
|
+
* Where the ray through \`uv\` meets the surface's tangent plane at \`p\`, as an offset from \`p\`.
|
|
497
|
+
* For a neighbouring pixel's ray, that's how far one pixel reaches across the field there.
|
|
498
|
+
*/
|
|
499
|
+
vec2 reachTo(vec2 uv, vec3 p, vec3 normal, vec3 origin) {
|
|
500
|
+
vec3 direction = normalize(vec3(uv * VIEW, -CAMERA)) * uRotation;
|
|
501
|
+
float along = dot(direction, normal);
|
|
502
|
+
// Edge-on, a pixel reaches a long way across the surface, but not forever.
|
|
503
|
+
along = sign(along) * max(abs(along), 0.02);
|
|
504
|
+
return (origin + direction * (dot(p - origin, normal) / along) - p).xy;
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
/**
|
|
508
|
+
* The colour where a ray through \`uv\` meets the surface at \`p\`. \`spacing\` is the spacing of the
|
|
509
|
+
* rays this one stands for, which sets how wide every edge drawn on the surface is. Worked out
|
|
510
|
+
* from the rays themselves rather than from the GPU's derivatives, it holds for extra rays too.
|
|
511
|
+
*/
|
|
512
|
+
vec3 shade(vec3 p, vec3 view, vec3 origin, vec2 uv, float spacing) {
|
|
513
|
+
vec4 sx, sy;
|
|
514
|
+
slopeAt(p.xy, sx, sy);
|
|
515
|
+
vec4 field = smoothFieldAt(p.xy);
|
|
516
|
+
vec3 surfaceNormal = -normalize(slopeOf(p, field, sx, sy));
|
|
517
|
+
vec3 n = uRotation * surfaceNormal;
|
|
518
|
+
float fine = smoothstep(0.012, 0.0055, uPixel);
|
|
519
|
+
vec2 pixelX = reachTo(uv + vec2(spacing, 0.0), p, surfaceNormal, origin);
|
|
520
|
+
vec2 pixelY = reachTo(uv + vec2(0.0, spacing), p, surfaceNormal, origin);
|
|
521
|
+
|
|
522
|
+
float front = step(0.0, offMiddle(p, field));
|
|
523
|
+
|
|
524
|
+
// Into the viewBox the shapes are measured in, whose y runs down, and a pixel's reach there.
|
|
525
|
+
vec2 at = vec2(50.0 + 50.0 * p.x, 50.0 - 50.0 * p.y);
|
|
526
|
+
vec2 boxX = vec2(50.0 * pixelX.x, -50.0 * pixelX.y);
|
|
527
|
+
vec2 boxY = vec2(50.0 * pixelY.x, -50.0 * pixelY.y);
|
|
528
|
+
Trim trim = morphedTrim(at);
|
|
529
|
+
float glassD = trim.glass;
|
|
530
|
+
float studD = trim.stud;
|
|
531
|
+
float glass = coverAt(glassD, trim.glassOut, boxX, boxY);
|
|
532
|
+
float stud = coverAt(studD, trim.studOut, boxX, boxY);
|
|
533
|
+
float part = coverAt(trim.chrome, trim.chromeOut, boxX, boxY);
|
|
534
|
+
// The glass and the studs are the dark parts. A bezel rings the glass, and a thinner one
|
|
535
|
+
// each stud, and each is an exact distance wide, so it stays an even band at any zoom.
|
|
536
|
+
float visor = max(glass, stud) * front;
|
|
537
|
+
float bezel = coverAt(glassD - RIM_WIDTH, trim.glassOut, boxX, boxY) * (1.0 - glass);
|
|
538
|
+
float ring = coverAt(studD - STUD_RING, trim.studOut, boxX, boxY) * (1.0 - stud);
|
|
539
|
+
float chrome = max(max(bezel, ring), part) * (1.0 - visor);
|
|
540
|
+
// The glass bevels down to the screen, which reflects nothing.
|
|
541
|
+
float screen = smoothstep(BEVEL_OUT, BEVEL_IN, -glassD) * front;
|
|
542
|
+
float accented = sharp(field.a, vec2(sx.a, sy.a), 0.5, pixelX, pixelY);
|
|
543
|
+
vec3 paint = mix(uBody, uAccent, accented);
|
|
544
|
+
paint = mix(paint, mix(paint, vec3(1.0), 0.78), flecks(p) * step(0.001, uSpeckle) * fine);
|
|
545
|
+
|
|
546
|
+
// A bot's lights sit behind its glass, so they glide with its gaze and clip to it. A face
|
|
547
|
+
// painted on skin mostly stays where it's drawn, as the body already turns to look: its eyes
|
|
548
|
+
// shift a little towards what they see and its mouth not at all, so it never slides off.
|
|
549
|
+
// A blink squashes the eyes towards their middle.
|
|
550
|
+
vec2 lit = p.xy - uLook * (1.0 - uPainted);
|
|
551
|
+
vec2 seen = p.xy - uLook * mix(1.0, PAINTED_GAZE, uPainted);
|
|
552
|
+
float shows = mix(glass * front, front, uPainted);
|
|
553
|
+
float light = 0.0;
|
|
554
|
+
vec3 marks = vec3(0.0);
|
|
555
|
+
// Read only where lights can be: behind a bot's glass, or on a blob's face.
|
|
556
|
+
if (shows > 0.0) {
|
|
557
|
+
float open = max(uOpen, 0.06);
|
|
558
|
+
vec2 lid = vec2(seen.x, uEyeY + (seen.y - uEyeY) / open);
|
|
559
|
+
vec2 atLit = vec2(50.0 + 50.0 * lit.x, 50.0 - 50.0 * lit.y);
|
|
560
|
+
vec2 atLid = vec2(50.0 + 50.0 * lid.x, 50.0 - 50.0 * lid.y);
|
|
561
|
+
vec2 atStill = vec2(50.0 + 50.0 * p.x, 50.0 - 50.0 * (uEyeY + (p.y - uEyeY) / open));
|
|
562
|
+
// Squashed by the blink, a pixel reaches further up and down an eye.
|
|
563
|
+
vec2 lidX = vec2(boxX.x, boxX.y / open);
|
|
564
|
+
vec2 lidY = vec2(boxY.x, boxY.y / open);
|
|
565
|
+
float now = lightsAt(false, atLit, atLid, boxX, boxY, lidX, lidY);
|
|
566
|
+
// Lights can't be grown from nothing, so a morph cross-fades them instead.
|
|
567
|
+
float before = uFromShapes > 0 ? lightsAt(true, atLit, atLid, boxX, boxY, lidX, lidY) : 0.0;
|
|
568
|
+
light = mix(before, now, uShapeMix) * shows;
|
|
569
|
+
if (uJelly.x > 1.5) {
|
|
570
|
+
vec3 nowMarks = marksAt(false, atLit, atLid, atStill, boxX, boxY, lidX, lidY);
|
|
571
|
+
vec3 beforeMarks = uFromShapes > 0 ? marksAt(true, atLit, atLid, atStill, boxX, boxY, lidX, lidY) : vec3(0.0);
|
|
572
|
+
marks = mix(beforeMarks, nowMarks, uShapeMix) * shows;
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
if (uJelly.x > 1.5) {
|
|
577
|
+
float gradient = length(slopeOf(p, field, sx, sy));
|
|
578
|
+
return clayShade(p, n, surfaceNormal, gradient, paint, light, marks);
|
|
579
|
+
}
|
|
580
|
+
if (uJelly.x > 0.5) return jellyShade(p, n, view, accented, light);
|
|
581
|
+
|
|
582
|
+
vec3 key = normalize(vec3(-0.45, 0.8, 0.65));
|
|
583
|
+
float wrapped = smoothstep(-0.55, 1.0, dot(n, key));
|
|
584
|
+
|
|
585
|
+
// Light scattering inside the skin keeps shadows saturated rather than grey.
|
|
586
|
+
vec3 shadow = pow(paint, vec3(1.8)) * 0.3;
|
|
587
|
+
vec3 color = mix(shadow, paint * 1.22, wrapped * wrapped * (3.0 - 2.0 * wrapped));
|
|
588
|
+
color += paint * 0.5 * smoothstep(0.1, -1.0, n.y) * max(dot(n, normalize(vec3(0.6, -0.5, 0.4))), 0.0);
|
|
589
|
+
|
|
590
|
+
float facing = max(dot(n, view), 0.0);
|
|
591
|
+
float fresnel = pow(1.0 - facing, 3.5);
|
|
592
|
+
vec3 reflected = reflect(-view, n);
|
|
593
|
+
float highlight = max(dot(reflected, key), 0.0);
|
|
594
|
+
// Bots are satin, with a broad soft sheen. Blobs stay wet and glossy.
|
|
595
|
+
float wetness = uPainted;
|
|
596
|
+
color = mix(color, uVisor, visor);
|
|
597
|
+
color = mix(color, uLight * mix(1.7, 1.0, uPainted), light);
|
|
598
|
+
color += studio(reflected) * mix(mix(0.05, 0.1, wetness), mix(0.5, 0.75, wetness), fresnel) * mix(1.0, 0.16, visor) * mix(1.0, 0.4, light * uPainted);
|
|
599
|
+
color += mix(paint, vec3(1.0), 0.6) * pow(highlight, mix(5.0, 7.0, wetness)) * mix(0.26, 0.2, wetness) * (1.0 - visor);
|
|
600
|
+
color += vec3(1.0) * pow(highlight, mix(46.0, 140.0, wetness)) * mix(0.32, 0.8, wetness) * (1.0 - visor * 0.5);
|
|
601
|
+
color += mix(paint, vec3(1.0), 0.5) * pow(1.0 - facing, 5.0) * 0.3 * (1.0 - visor);
|
|
602
|
+
|
|
603
|
+
// The screen reflects nothing: only black, and the lights on it.
|
|
604
|
+
color = mix(color, mix(uVisor, uLight * 1.7, light), screen);
|
|
605
|
+
|
|
606
|
+
// Polished steel, rounded like a tube: bright along its crest whatever it reflects,
|
|
607
|
+
// so the bezel reads as one unbroken band even where the studio behind it is dark.
|
|
608
|
+
// Its crest runs along the middle of each band, and along the chrome parts themselves.
|
|
609
|
+
float across = part > 0.5 ? 0.5
|
|
610
|
+
: studD < glassD ? clamp(1.0 - studD / STUD_RING, 0.0, 1.0)
|
|
611
|
+
: clamp(1.0 - glassD / RIM_WIDTH, 0.0, 1.0);
|
|
612
|
+
float crest = sin(across * 3.14159);
|
|
613
|
+
vec3 metal = studio(reflected) * 0.75 + vec3(0.3, 0.31, 0.34) + vec3(0.5, 0.51, 0.54) * crest * crest
|
|
614
|
+
+ vec3(0.7) * pow(highlight, 22.0);
|
|
615
|
+
return mix(color, metal, chrome);
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
struct March {
|
|
619
|
+
bool hit;
|
|
620
|
+
float closest; // The most the ray came to being inside, which is above 0 if it is.
|
|
621
|
+
float closestAt;
|
|
622
|
+
float previous;
|
|
623
|
+
float skim; // The nearest it came to a part it passed by on its way, and where.
|
|
624
|
+
float skimAt;
|
|
625
|
+
float skimEnd; // Where it was seen pulling away from that part again.
|
|
626
|
+
};
|
|
627
|
+
|
|
628
|
+
/** How far one pixel's rays are apart at distance \`t\`, for rays \`spacing\` apart in the slot. */
|
|
629
|
+
float reachAt(float t, float spacing) {
|
|
630
|
+
return t * spacing * VIEW / CAMERA;
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
/** The highest the formula gets along the ray between \`low\` and \`high\`, where it rises and falls once. */
|
|
634
|
+
float peakAlong(vec3 origin, vec3 direction, float low, float high, out float peakAt) {
|
|
635
|
+
for (int i = 0; i < 10; i++) {
|
|
636
|
+
float third = (high - low) / 3.0;
|
|
637
|
+
if (surface(origin + direction * (low + third)) < surface(origin + direction * (high - third))) low += third;
|
|
638
|
+
else high -= third;
|
|
639
|
+
}
|
|
640
|
+
peakAt = (low + high) * 0.5;
|
|
641
|
+
return surface(origin + direction * peakAt);
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
/** Where the ray enters the surface, between a point outside it and one inside. */
|
|
645
|
+
float entryBetween(vec3 origin, vec3 direction, float outside, float inside) {
|
|
646
|
+
for (int i = 0; i < 6; i++) {
|
|
647
|
+
float mid = (outside + inside) * 0.5;
|
|
648
|
+
if (surface(origin + direction * mid) > 0.0) inside = mid;
|
|
649
|
+
else outside = mid;
|
|
650
|
+
}
|
|
651
|
+
return inside;
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
/**
|
|
655
|
+
* Steps along a ray from \`start\` until it is inside the bot, remembering its nearest approach
|
|
656
|
+
* if it misses, and the nearest it came to any part it passed by before going on to hit another.
|
|
657
|
+
*/
|
|
658
|
+
March march(vec3 origin, vec3 direction, float spacing, float start) {
|
|
659
|
+
// Only the stretch of the ray inside the avatar's box. Turned far round, a ray crosses
|
|
660
|
+
// the whole depth at a slant, and stepping through all of it would run out of steps
|
|
661
|
+
// before it reached the far side, slicing parts off flat or losing them altogether.
|
|
662
|
+
vec3 toward = sign(direction) * max(abs(direction), vec3(1e-6));
|
|
663
|
+
vec3 a = (vec3(uBox.xy, -DEPTH) - origin) / toward;
|
|
664
|
+
vec3 b = (vec3(uBox.zw, DEPTH) - origin) / toward;
|
|
665
|
+
vec3 lo = min(a, b);
|
|
666
|
+
vec3 hi = max(a, b);
|
|
667
|
+
float near = max(max(max(lo.x, lo.y), lo.z), start);
|
|
668
|
+
float far = min(min(hi.x, hi.y), hi.z);
|
|
669
|
+
|
|
670
|
+
March m = March(false, -1e6, near, near, -1e6, near, near);
|
|
671
|
+
float last = -1e6;
|
|
672
|
+
float lastAt = near;
|
|
673
|
+
bool rising = false;
|
|
674
|
+
float t = near;
|
|
675
|
+
for (int i = 0; i < MAX_STEPS && t < far; i++) {
|
|
676
|
+
vec3 p = origin + direction * t;
|
|
677
|
+
vec4 field = fieldAt(p.xy);
|
|
678
|
+
float height = field.r;
|
|
679
|
+
float z = offMiddle(p, field);
|
|
680
|
+
float value = height - EDGE - z * z / (4.0 * THICKNESS * THICKNESS);
|
|
681
|
+
// Rising towards a part and falling away again is passing it by.
|
|
682
|
+
if (rising && value < last && last > m.skim) {
|
|
683
|
+
m.skim = last;
|
|
684
|
+
m.skimAt = lastAt;
|
|
685
|
+
m.skimEnd = t;
|
|
686
|
+
}
|
|
687
|
+
rising = value > last;
|
|
688
|
+
last = value;
|
|
689
|
+
lastAt = t;
|
|
690
|
+
if (value > m.closest) {
|
|
691
|
+
m.closest = value;
|
|
692
|
+
m.closestAt = t;
|
|
693
|
+
}
|
|
694
|
+
if (value > 0.0) {
|
|
695
|
+
m.hit = true;
|
|
696
|
+
break;
|
|
697
|
+
}
|
|
698
|
+
m.previous = t;
|
|
699
|
+
t += height < EDGE * 0.5 ? FAR_STEP : clamp(-value * uStride, NEAR_STEP, FAR_STEP);
|
|
700
|
+
}
|
|
701
|
+
|
|
702
|
+
// A ray by the outline came closest somewhere between its steps, and as the bot moves the
|
|
703
|
+
// steps shift, so taking the best step alone makes the edge crawl. Narrowing in on the
|
|
704
|
+
// true closest point holds it still.
|
|
705
|
+
if (!m.hit && m.closest > -max(EDGE, reachAt(m.closestAt, spacing))) {
|
|
706
|
+
float at;
|
|
707
|
+
float value = peakAlong(origin, direction, max(near, m.closestAt - FAR_STEP), min(far, m.closestAt + FAR_STEP), at);
|
|
708
|
+
if (value > m.closest) {
|
|
709
|
+
m.closest = value;
|
|
710
|
+
m.closestAt = at;
|
|
711
|
+
}
|
|
712
|
+
// It may even have stepped clean over a thin part, which is a hit after all.
|
|
713
|
+
if (value > 0.0) {
|
|
714
|
+
m.hit = true;
|
|
715
|
+
m.previous = max(near, at - FAR_STEP);
|
|
716
|
+
}
|
|
717
|
+
}
|
|
718
|
+
return m;
|
|
719
|
+
}
|
|
720
|
+
|
|
721
|
+
void rayAt(vec2 uv, out vec3 origin, out vec3 direction, out vec3 ray) {
|
|
722
|
+
vec3 camera = vec3(0.0, 0.0, CAMERA);
|
|
723
|
+
ray = normalize(vec3(uv * VIEW, -CAMERA));
|
|
724
|
+
// Into the bot's own space, where the field is axis-aligned.
|
|
725
|
+
origin = (camera - uPosition) * uRotation / uScale;
|
|
726
|
+
direction = ray * uRotation;
|
|
727
|
+
}
|
|
728
|
+
|
|
729
|
+
/**
|
|
730
|
+
* How fast the surface's formula changes from one ray to the next at \`p\`: its slope, less
|
|
731
|
+
* the part along the ray. Over the pixel's reach, that's how much a pixel spans of it.
|
|
732
|
+
*/
|
|
733
|
+
float acrossRays(vec3 p, vec3 direction) {
|
|
734
|
+
float e = uTexel * 2.0;
|
|
735
|
+
vec4 dx = (smoothFieldAt(p.xy + vec2(e, 0.0)) - smoothFieldAt(p.xy - vec2(e, 0.0))) / (2.0 * e);
|
|
736
|
+
vec4 dy = (smoothFieldAt(p.xy + vec2(0.0, e)) - smoothFieldAt(p.xy - vec2(0.0, e))) / (2.0 * e);
|
|
737
|
+
vec3 slope = slopeOf(p, smoothFieldAt(p.xy), dx, dy);
|
|
738
|
+
return max(length(slope - direction * dot(slope, direction)), 1e-4);
|
|
739
|
+
}
|
|
740
|
+
|
|
741
|
+
/** How much of a pixel a part covers, from how far inside it (or outside, below 0) its ray got. */
|
|
742
|
+
float coverOf(vec3 origin, vec3 direction, float value, float t, float spacing) {
|
|
743
|
+
return clamp(0.5 + value / (acrossRays(origin + direction * t, direction) * reachAt(t, spacing)), 0.0, 1.0);
|
|
744
|
+
}
|
|
745
|
+
|
|
746
|
+
/**
|
|
747
|
+
* The deepest a ray gets inside the bot after entering at \`entry\`, by the formula. Past a
|
|
748
|
+
* pixel's worth the answer no longer matters, which most rays are within a step or two.
|
|
749
|
+
*/
|
|
750
|
+
float deepest(vec3 origin, vec3 direction, float entry, float reach, out float deepestAt) {
|
|
751
|
+
deepestAt = entry;
|
|
752
|
+
float best = 0.0;
|
|
753
|
+
for (int i = 0; i < 3; i++) {
|
|
754
|
+
float t = entry + reach * (i == 0 ? 2.0 : i == 1 ? 8.0 : 24.0);
|
|
755
|
+
float value = surface(origin + direction * t);
|
|
756
|
+
if (value > best) {
|
|
757
|
+
best = value;
|
|
758
|
+
deepestAt = t;
|
|
759
|
+
}
|
|
760
|
+
}
|
|
761
|
+
// Slopes never pass 1, so a pixel's worth of depth is at most its reach.
|
|
762
|
+
if (best >= reach) return best;
|
|
763
|
+
// A grazing ray: it skims in and out again, so find how deep it got.
|
|
764
|
+
float at;
|
|
765
|
+
float value = peakAlong(origin, direction, entry, entry + reach * 48.0, at);
|
|
766
|
+
if (value > best) {
|
|
767
|
+
best = value;
|
|
768
|
+
deepestAt = at;
|
|
769
|
+
}
|
|
770
|
+
return best;
|
|
771
|
+
}
|
|
772
|
+
|
|
773
|
+
/** The displayed colour where the ray meets the surface at \`t\`. */
|
|
774
|
+
vec3 colorAt(vec3 origin, vec3 direction, vec3 ray, vec2 uv, float spacing, float t) {
|
|
775
|
+
vec3 color = shade(origin + direction * t, -ray, origin, uv, spacing);
|
|
776
|
+
color = color / (1.0 + color * 0.16);
|
|
777
|
+
return pow(color, vec3(1.0 / 2.2));
|
|
778
|
+
}
|
|
779
|
+
|
|
780
|
+
/**
|
|
781
|
+
* One ray through the slot at \`uv\`: its colour, not yet weighted, and how much of its pixel
|
|
782
|
+
* the bot covers. \`spacing\` is the spacing of the rays this one stands for.
|
|
783
|
+
*
|
|
784
|
+
* Every edge is worked out, not sampled. How close a ray that misses a part came to it, or
|
|
785
|
+
* how deep one that hits got, over how fast that changes from ray to ray, is its signed
|
|
786
|
+
* distance to that part's edge in pixels. Edged over one pixel from that, as a vector shape
|
|
787
|
+
* is, the outline is even on every side and in every pose, and moves without crawling. Where
|
|
788
|
+
* one part crosses in front of another, both colours are blended the same way.
|
|
789
|
+
*/
|
|
790
|
+
vec4 trace(vec2 uv, float spacing) {
|
|
791
|
+
vec3 origin, direction, ray;
|
|
792
|
+
rayAt(uv, origin, direction, ray);
|
|
793
|
+
March m = march(origin, direction, spacing, -1e6);
|
|
794
|
+
|
|
795
|
+
if (!m.hit) {
|
|
796
|
+
if (m.closest <= -reachAt(m.closestAt, spacing)) return vec4(0.0);
|
|
797
|
+
float coverage = coverOf(origin, direction, m.closest, m.closestAt, spacing);
|
|
798
|
+
if (coverage <= 0.0) return vec4(0.0);
|
|
799
|
+
return vec4(colorAt(origin, direction, ray, uv, spacing, m.closestAt), coverage);
|
|
800
|
+
}
|
|
801
|
+
|
|
802
|
+
float at = entryBetween(origin, direction, m.previous, m.closestAt);
|
|
803
|
+
float reach = reachAt(at, spacing);
|
|
804
|
+
vec3 color = colorAt(origin, direction, ray, uv, spacing, at);
|
|
805
|
+
float coverage = 1.0;
|
|
806
|
+
|
|
807
|
+
float deepestAt;
|
|
808
|
+
float depth = deepest(origin, direction, at, reach, deepestAt);
|
|
809
|
+
if (depth < reach) {
|
|
810
|
+
// It only grazes this part, which covers only some of the pixel. Whether the rest shows
|
|
811
|
+
// the background or more of the bot depends on what lies behind.
|
|
812
|
+
float part = coverOf(origin, direction, depth, deepestAt, spacing);
|
|
813
|
+
float exit = deepestAt;
|
|
814
|
+
for (int i = 0; i < 8; i++) {
|
|
815
|
+
if (surface(origin + direction * exit) < 0.0) break;
|
|
816
|
+
exit += reach * 4.0;
|
|
817
|
+
}
|
|
818
|
+
March behind = march(origin, direction, spacing, exit);
|
|
819
|
+
if (behind.hit) {
|
|
820
|
+
float back = entryBetween(origin, direction, behind.previous, behind.closestAt);
|
|
821
|
+
color = mix(colorAt(origin, direction, ray, uv, spacing, back), color, part);
|
|
822
|
+
} else {
|
|
823
|
+
coverage = part;
|
|
824
|
+
}
|
|
825
|
+
}
|
|
826
|
+
|
|
827
|
+
// On its way in it passed close by a part in front, so it is beside that part's edge.
|
|
828
|
+
if (m.skim < 0.0 && m.skim > -reachAt(m.skimAt, spacing)) {
|
|
829
|
+
float skimAt;
|
|
830
|
+
float skim = peakAlong(origin, direction, m.skimAt - FAR_STEP, m.skimEnd, skimAt);
|
|
831
|
+
if (skim < 0.0) {
|
|
832
|
+
float front = coverOf(origin, direction, skim, skimAt, spacing);
|
|
833
|
+
if (front > 0.0) color = mix(color, colorAt(origin, direction, ray, uv, spacing, skimAt), front);
|
|
834
|
+
}
|
|
835
|
+
}
|
|
836
|
+
return vec4(color, coverage);
|
|
837
|
+
}
|
|
838
|
+
|
|
839
|
+
/** How much of the pixel at \`uv\` the container covers, edged by the pixel. */
|
|
840
|
+
float tileCover(vec2 uv) {
|
|
841
|
+
vec2 d = abs(uv) - vec2(uTile.x - uTile.y);
|
|
842
|
+
float distance = length(max(d, 0.0)) + min(max(d.x, d.y), 0.0) - uTile.y;
|
|
843
|
+
return smoothstep(uStep * 0.5, -uStep * 0.5, distance);
|
|
844
|
+
}
|
|
845
|
+
|
|
846
|
+
void main() {
|
|
847
|
+
vec2 uv = vUv * uFrame.xy + uFrame.zw;
|
|
848
|
+
vec4 sum = vec4(0.0);
|
|
849
|
+
#if SAMPLES == 1
|
|
850
|
+
vec4 centre = trace(uv, uStep);
|
|
851
|
+
sum = vec4(centre.rgb * centre.a, centre.a);
|
|
852
|
+
#else
|
|
853
|
+
// Small bots get several rays a pixel, which keeps their edges from crawling as they move.
|
|
854
|
+
for (int i = 0; i < SAMPLES * SAMPLES; i++) {
|
|
855
|
+
vec2 offset = (vec2(float(i % SAMPLES), float(i / SAMPLES)) + 0.5) / float(SAMPLES) - 0.5;
|
|
856
|
+
vec4 ray = trace(uv + offset * uStep, uStep / float(SAMPLES));
|
|
857
|
+
sum += vec4(ray.rgb * ray.a, ray.a);
|
|
858
|
+
}
|
|
859
|
+
sum /= float(SAMPLES * SAMPLES);
|
|
860
|
+
#endif
|
|
861
|
+
|
|
862
|
+
// The bot stays inside its container, which sits behind it.
|
|
863
|
+
float card = tileCover(uv) * uTile.z;
|
|
864
|
+
sum *= 1.0 - uTile.z + card;
|
|
865
|
+
sum += vec4(uTileColor, 1.0) * card * (1.0 - sum.a);
|
|
866
|
+
if (sum.a <= 0.0) discard;
|
|
867
|
+
outColor = sum;
|
|
868
|
+
}`;var MAX_SHAPES=32,KINDS3={superellipse:0,crescent:1,rod:2,circle:2,curve:3},ROLES={light:0,eye:1,glass:2,stud:3,chrome:4,shine:5,tint:6,white:7};function shapesOf2(parts){let a=new Float32Array(MAX_SHAPES*4),b=new Float32Array(MAX_SHAPES*4),tagged2=(shapes2,role)=>shapes2.map(shape=>[shape,role]),shapes=[...tagged2(parts.eyeShapes,ROLES.eye),...tagged2(parts.lightShapes,ROLES.light),...tagged2(parts.visorShapes,ROLES.glass),...tagged2(parts.studShapes,ROLES.stud),...tagged2(parts.chromeShapes,ROLES.chrome),...tagged2(parts.shineShapes??[],ROLES.shine),...tagged2(parts.tintShapes??[],ROLES.tint),...tagged2(parts.whiteShapes??[],ROLES.white)].slice(0,MAX_SHAPES);return shapes.forEach(([shape,role],i)=>{let code=KINDS3[shape.kind]+8*role;switch(shape.kind){case"superellipse":a.set([shape.cx,shape.cy,shape.rx,shape.ry],i*4),b.set([shape.n,shape.rot*Math.PI/180,shape.stroke??0,code],i*4);break;case"crescent":a.set([shape.cx,shape.cy,shape.width,shape.lift],i*4),b.set([shape.thickness,0,0,code],i*4);break;case"rod":a.set([shape.x1,shape.y1,shape.x2,shape.y2],i*4),b.set([shape.r,0,0,code],i*4);break;case"circle":a.set([shape.cx,shape.cy,shape.cx,shape.cy],i*4),b.set([shape.r,0,0,code],i*4);break;case"curve":a.set([shape.x1,shape.y1,shape.cx,shape.cy],i*4),b.set([shape.x2,shape.y2,shape.r,code],i*4);break}}),{a,b,count:shapes.length}}var MAX_PIXEL_RATIO=4,SUPERSAMPLE_BELOW=400,MORPH_MS=520,MAX_TILT=.34,GAZE_X=.1,GAZE_Y=.065,FITTED_HALF=.894,VIEW_HALF=1.04,TILE_FILL=.8,TILE_CORNER=.22,FIT_RATE=7,WANDER_AFTER=2.2,POKE_SECONDS=1.1,POKE_RATE=19,POKE_DAMPING=4.2,linear=hex=>{let channel=start=>(parseInt(hex.slice(start,start+2),16)/255)**2.2;return[channel(1),channel(3),channel(5)]},display=hex=>[1,3,5].map(start=>parseInt(hex.slice(start,start+2),16)/255);function peakOf(field){let peak=0;for(let i=0;i<field.length;i+=4)peak=Math.max(peak,field[i]);return peak||1}var THICKNESS=.8,BOX_MARGIN=.03;function boxOf(field){let size=320,[left,right,top,bottom]=[size,0,size,0];for(let y=0;y<size;y++)for(let x=0;x<size;x++)field[(y*size+x)*4]<=0||(left=Math.min(left,x),right=Math.max(right,x+1),top=Math.min(top,y),bottom=Math.max(bottom,y+1));if(right<=left)return[-1,-1,1,1];let at3=cell=>cell*2/size-1;return[at3(left)-BOX_MARGIN,-at3(bottom)-BOX_MARGIN,at3(right)+BOX_MARGIN,-at3(top)+BOX_MARGIN]}function strideOf(field){let size=320,cell=2/size,[slope,bend,peak]=[0,0,0];for(let y=0;y<size-1;y++)for(let x=0;x<size-1;x++){let i=(y*size+x)*4,[across,up]=[i+4,i+size*4];peak=Math.max(peak,field[i]),slope=Math.max(slope,Math.hypot(field[across]-field[i],field[up]-field[i])/cell),bend=Math.max(bend,Math.hypot(field[across+1]-field[i+1],field[up+1]-field[i+1])/cell)}let steepest=Math.hypot(slope,Math.sqrt(peak)/THICKNESS)+2*Math.sqrt(peak)*bend;return .9/Math.max(1.125,steepest)}var lookOf=(parts,field=buildField(parts))=>({field,bounds:fieldBounds(field,320),box:boxOf(field),stride:strideOf(field),eyeY:(50-parts.eyeY)/50,painted:parts.painted?1:0,peak:peakOf(field),shapes:shapesOf2(parts)}),paintOf2=({colors,speckle,jelly,matte})=>({body:linear(colors.body),accent:linear(colors.accent),visor:linear(colors.visor),light:linear(colors.light),speckle,jelly:jelly?[1,jelly.frost,jelly.pool]:matte?[2,0,0]:[0,0,0]}),tileOf2=({container})=>container?{size:container.size,color:display(container.color),shown:1}:{size:1,color:[0,0,0],shown:0},shapeOf3=({container:_,colors:__,speckle:___,jelly:____,...shape})=>JSON.stringify(shape),mix2=(a,b,t)=>a+(b-a)*t,mixRgb=(a,b,t)=>[mix2(a[0],b[0],t),mix2(a[1],b[1],t),mix2(a[2],b[2],t)],clamp=(v,low,high)=>Math.min(high,Math.max(low,v)),easePaint=(a,b,t)=>({body:mixRgb(a.body,b.body,t),accent:mixRgb(a.accent,b.accent,t),visor:mixRgb(a.visor,b.visor,t),light:mixRgb(a.light,b.light,t),speckle:mix2(a.speckle,b.speckle,t),jelly:mixRgb(a.jelly,b.jelly,t)}),blend=(a,b,t,field)=>({field,box:t>=1?b.box:[Math.min(a.box[0],b.box[0]),Math.min(a.box[1],b.box[1]),Math.max(a.box[2],b.box[2]),Math.max(a.box[3],b.box[3])],stride:t>=1?b.stride:Math.min(a.stride,b.stride),eyeY:mix2(a.eyeY,b.eyeY,t),painted:mix2(a.painted,b.painted,t),peak:mix2(a.peak,b.peak,t),shapes:t<.5?a.shapes:b.shapes,bounds:{cx:mix2(a.bounds.cx,b.bounds.cx,t),cy:mix2(a.bounds.cy,b.bounds.cy,t),half:mix2(a.bounds.half,b.bounds.half,t)}}),easeTile=(tile,goal,t)=>{let from=tile.shown<.01?{...goal,shown:tile.shown}:tile;return{size:mix2(from.size,goal.shown?goal.size:from.size,t),color:goal.shown?mixRgb(from.color,goal.color,t):from.color,shown:mix2(from.shown,goal.shown,t)}};function easeOutBack(p){return 1+(1.2+1)*(p-1)**3+1.2*(p-1)**2}function rotation(pitch,yaw,roll){let[cx,sx]=[Math.cos(pitch),Math.sin(pitch)],[cy,sy]=[Math.cos(yaw),Math.sin(yaw)],[cz,sz]=[Math.cos(roll),Math.sin(roll)];return new Float32Array([cy*cz,sx*sy*cz+cx*sz,-cx*sy*cz+sx*sz,-cy*sz,-sx*sy*sz+cx*cz,cx*sy*sz+sx*cz,sy,-sx*cy,cx*cy])}function compile(gl,type,source){let shader=gl.createShader(type);if(gl.shaderSource(shader,source),gl.compileShader(shader),!gl.getShaderParameter(shader,gl.COMPILE_STATUS))throw new Error(gl.getShaderInfoLog(shader)??"Shader failed to compile");return shader}function createProgram(gl,samples){let program=gl.createProgram(),vertex=compile(gl,gl.VERTEX_SHADER,VERTEX_SHADER),source=FRAGMENT_SHADER.replace("#version 300 es",`#version 300 es
|
|
869
|
+
#define SAMPLES ${samples}`),fragment=compile(gl,gl.FRAGMENT_SHADER,source);if(gl.attachShader(program,vertex),gl.attachShader(program,fragment),gl.linkProgram(program),gl.deleteShader(vertex),gl.deleteShader(fragment),!gl.getProgramParameter(program,gl.LINK_STATUS))throw new Error(gl.getProgramInfoLog(program)??"Shader failed to link");return program}function createStage(canvas,onLost,{followAnywhere=!1}={}){let context=canvas.getContext("webgl2",{alpha:!0,antialias:!1,premultipliedAlpha:!0});if(!context)return null;let gl=context;gl.enable(gl.BLEND),gl.blendFunc(gl.ONE,gl.ONE_MINUS_SRC_ALPHA);let format=gl.getExtension("OES_texture_float_linear")?gl.RGBA32F:gl.RGBA16F;gl.clearColor(0,0,0,0);let programs=[1,2].map(samples=>{let program=createProgram(gl,samples);gl.useProgram(program);let uniform=name=>gl.getUniformLocation(program,name);return gl.uniform1f(uniform("uTexel"),2/320),{program,rotation:uniform("uRotation"),position:uniform("uPosition"),scale:uniform("uScale"),body:uniform("uBody"),accent:uniform("uAccent"),visor:uniform("uVisor"),light:uniform("uLight"),eyeY:uniform("uEyeY"),painted:uniform("uPainted"),speckle:uniform("uSpeckle"),jelly:uniform("uJelly"),figure:uniform("uFigure"),box:uniform("uBox"),stride:uniform("uStride"),open:uniform("uOpen"),shapesA:uniform("uShapeA"),shapesB:uniform("uShapeB"),shapeCount:uniform("uShapes"),fromA:uniform("uFromShapeA"),fromB:uniform("uFromShapeB"),fromCount:uniform("uFromShapes"),shapeMix:uniform("uShapeMix"),look:uniform("uLook"),pixel:uniform("uPixel"),frame:uniform("uFrame"),step:uniform("uStep"),tile:uniform("uTile"),tileColor:uniform("uTileColor")}}),still2=matchMedia("(prefers-reduced-motion: reduce)").matches,view={animate:!0,follow:!0},bots=new Map,pointer={x:0,y:0,active:!1,movedAt:-1/0},frame=0,lastFrame=0,upload=bot=>{gl.bindTexture(gl.TEXTURE_2D,bot.texture),gl.texSubImage2D(gl.TEXTURE_2D,0,0,0,320,320,gl.RGBA,gl.FLOAT,bot.live)},add=(slot,look,parts)=>{let texture=gl.createTexture();gl.bindTexture(gl.TEXTURE_2D,texture),gl.texStorage2D(gl.TEXTURE_2D,1,format,320,320),gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MIN_FILTER,gl.LINEAR),gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_MAG_FILTER,gl.LINEAR),gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_WRAP_S,gl.CLAMP_TO_EDGE),gl.texParameteri(gl.TEXTURE_2D,gl.TEXTURE_WRAP_T,gl.CLAMP_TO_EDGE);let bot={slot,texture,from:look,to:look,live:look.field.slice(),morphStart:-1/0,phase:bots.size*1.37,yaw:0,pitch:0,hover:0,pose:{x:0,y:0,z:0},eyes:createEyes(performance.now()/1e3,Math.random),fit:1,fitGoal:1,zoom:1,zoomGoal:1,tile:tileOf2(parts),tileGoal:tileOf2(parts),paint:paintOf2(parts),paintGoal:paintOf2(parts),shape:shapeOf3(parts),pokedAt:-1/0};bots.set(slot,bot),upload(bot)},onPointer=event=>{if(event.pointerType==="touch")return;let area=(canvas.parentElement??canvas).getBoundingClientRect(),inside=followAnywhere||event.clientX>=area.left&&event.clientX<=area.right&&event.clientY>=area.top&&event.clientY<=area.bottom;pointer.active=inside,inside&&(pointer.x=event.clientX,pointer.y=event.clientY,pointer.movedAt=performance.now()/1e3)};window.addEventListener("pointermove",onPointer);let onLostContext=event=>{event.preventDefault(),cancelAnimationFrame(frame),onLost()};canvas.addEventListener("webglcontextlost",onLostContext);function eyeTarget(box2,seconds){let fresh=!view.animate||still2||seconds-pointer.movedAt<WANDER_AFTER;return!view.follow||!pointer.active||!fresh?null:{x:clamp((pointer.x-(box2.left+box2.width/2))/260,-1,1),y:clamp((pointer.y-(box2.top+box2.height/2))/200,-1,1)}}function drawBot(bot,now,delta,canvasBox,ratio){let box2=bot.slot.getBoundingClientRect();if(box2.width===0)return;let progress=still2?1:Math.min(1,(now-bot.morphStart)/MORPH_MS),eased=easeOutBack(progress);if(bot.from!==bot.to){let{field:a}=bot.from,{field:b}=bot.to;for(let i=0;i<a.length;i++)bot.live[i]=a[i]+(b[i]-a[i])*eased;upload(bot),progress===1&&(bot.from=bot.to)}let seconds=now/1e3,sway=still2||!view.animate?0:1,towards=(pointer.x-(box2.left+box2.width/2))/innerWidth,above=(pointer.y-(box2.top+box2.height/2))/innerHeight,following=pointer.active&&view.follow,yawGoal=following?clamp(towards*1.6,-MAX_TILT,MAX_TILT):0,pitchGoal=following?clamp(above*1.4,-MAX_TILT,MAX_TILT):0;bot.yaw+=(yawGoal-bot.yaw)*.08,bot.pitch+=(pitchGoal-bot.pitch)*.08;let hovered=view.animate&&!still2&&bot.slot.matches(":hover");bot.hover+=((hovered?1:0)-bot.hover)*.14;let poked=(now-bot.pokedAt)/1e3,boinging=poked<POKE_SECONDS,boing=boinging?Math.exp(-POKE_DAMPING*poked):0,wobble=boinging?boing*Math.sin(poked*POKE_RATE):0,yaw=bot.pose.y+bot.yaw+sway*Math.sin(seconds*.7+bot.phase)*.2,pitch=bot.pose.x+bot.pitch+sway*Math.sin(seconds*.5+bot.phase*1.6)*.08-wobble*.12,roll=bot.pose.z+sway*Math.sin(seconds*.6+bot.phase*.7)*.05+wobble*.16,bob=sway*Math.sin(seconds*1.3+bot.phase)*.035+(boinging?boing*Math.abs(Math.sin(poked*POKE_RATE*.5))*.09:0),open2=stepEyes(bot.eyes,{seconds,delta,alive:view.animate&&!still2,target:eyeTarget(box2,seconds),random:Math.random}),left=(box2.left-canvasBox.left)*ratio,bottom=(canvasBox.bottom-box2.bottom)*ratio,size=box2.width*ratio,x0=Math.floor(left),y0=Math.floor(bottom),width=Math.ceil(left+size)-x0,height=Math.ceil(bottom+size)-y0;gl.viewport(x0,y0,width,height),gl.scissor(x0,y0,width,height);let look=blend(bot.from,bot.to,clamp(eased,0,1),bot.live);bot.fit+=(bot.fitGoal-bot.fit)*(1-Math.exp(-FIT_RATE*delta)),bot.zoom+=(bot.zoomGoal-bot.zoom)*(1-Math.exp(-FIT_RATE*delta)),bot.tile=still2?bot.tileGoal:easeTile(bot.tile,bot.tileGoal,1-Math.exp(-FIT_RATE*delta)),bot.paint=still2?bot.paintGoal:easePaint(bot.paint,bot.paintGoal,1-Math.exp(-FIT_RATE*delta));let{paint}=bot,{tile}=bot,fit=mix2(bot.fit,1,tile.shown),contained=VIEW_HALF*tile.size*TILE_FILL*bot.zoom,fitted2=mix2(1,mix2(FITTED_HALF,contained,tile.shown)/look.bounds.half,fit),bobbed=bob*mix2(1,tile.size,tile.shown),drawn=size*look.bounds.half*fitted2/FITTED_HALF,uniforms=programs[drawn<SUPERSAMPLE_BELOW?1:0];gl.useProgram(uniforms.program),gl.uniform4f(uniforms.frame,width/size,height/size,(x0+width/2-left-size/2)/(size/2),(y0+height/2-bottom-size/2)/(size/2)),gl.uniform1f(uniforms.step,2/size);let half=Math.max(0,tile.size-2/size);gl.uniform3f(uniforms.tile,half,half*2*TILE_CORNER,tile.shown),gl.uniform3fv(uniforms.tileColor,tile.color),gl.bindTexture(gl.TEXTURE_2D,bot.texture),gl.uniformMatrix3fv(uniforms.rotation,!1,rotation(pitch,yaw,roll)),gl.uniform3f(uniforms.position,-look.bounds.cx*fitted2*fit,bobbed-look.bounds.cy*fitted2*fit,0),gl.uniform1f(uniforms.scale,fitted2*(1+.07*bot.hover+.06*Math.sin(progress*Math.PI)+.06*wobble)),gl.uniform3fv(uniforms.body,paint.body),gl.uniform3fv(uniforms.accent,paint.accent),gl.uniform3fv(uniforms.visor,paint.visor),gl.uniform3fv(uniforms.light,paint.light),gl.uniform1f(uniforms.eyeY,look.eyeY),gl.uniform1f(uniforms.painted,look.painted),gl.uniform1f(uniforms.speckle,paint.speckle),gl.uniform3fv(uniforms.jelly,paint.jelly),gl.uniform4f(uniforms.figure,look.bounds.cx,look.bounds.cy,look.bounds.half,look.peak),gl.uniform4fv(uniforms.box,look.box),gl.uniform1f(uniforms.stride,look.stride),gl.uniform1f(uniforms.open,open2),gl.uniform4fv(uniforms.shapesA,bot.to.shapes.a),gl.uniform4fv(uniforms.shapesB,bot.to.shapes.b),gl.uniform1i(uniforms.shapeCount,bot.to.shapes.count);let morphing=bot.from.shapes!==bot.to.shapes;gl.uniform4fv(uniforms.fromA,bot.from.shapes.a),gl.uniform4fv(uniforms.fromB,bot.from.shapes.b),gl.uniform1i(uniforms.fromCount,morphing?bot.from.shapes.count:0),gl.uniform1f(uniforms.shapeMix,morphing?clamp(eased,0,1):1),gl.uniform2f(uniforms.look,(bot.eyes.x+bot.eyes.jitterX)*GAZE_X,-(bot.eyes.y+bot.eyes.jitterY)*GAZE_Y),gl.uniform1f(uniforms.pixel,2.4/size),gl.drawArrays(gl.TRIANGLES,0,3)}function render(now){frame=requestAnimationFrame(render);let delta=Math.min(.1,(now-lastFrame)/1e3);lastFrame=now;let canvasBox=canvas.getBoundingClientRect(),ratio=Math.min(devicePixelRatio,MAX_PIXEL_RATIO),width=Math.round(canvasBox.width*ratio),height=Math.round(canvasBox.height*ratio);(canvas.width!==width||canvas.height!==height)&&(canvas.width=width,canvas.height=height),gl.disable(gl.SCISSOR_TEST),gl.clear(gl.COLOR_BUFFER_BIT),gl.enable(gl.SCISSOR_TEST);for(let bot of bots.values())drawBot(bot,now,delta,canvasBox,ratio)}return frame=requestAnimationFrame(render),{setView(next){Object.assign(view,next)},show(slot,parts){let existing=bots.get(slot),shape=shapeOf3(parts);if(existing&&(existing.tileGoal=tileOf2(parts),existing.paintGoal=paintOf2(parts),existing.shape===shape))return;let look=lookOf(parts),bot=existing;if(!bot)return add(slot,look,parts);bot.shape=shape;let t=clamp(easeOutBack(Math.min(1,(performance.now()-bot.morphStart)/MORPH_MS)),0,1);bot.from=blend(bot.from,bot.to,t,bot.live.slice()),bot.to=look,bot.morphStart=performance.now()},pose(slot,pose){let bot=bots.get(slot);bot&&(bot.pose=pose)},fit(slot,fitted2){let bot=bots.get(slot);bot&&(bot.fitGoal=fitted2?1:0)},zoom(slot,scale){let bot=bots.get(slot);bot&&(bot.zoomGoal=scale)},poke(slot){let bot=bots.get(slot);bot&&view.animate&&!still2&&(bot.pokedAt=performance.now())},dispose(){cancelAnimationFrame(frame),window.removeEventListener("pointermove",onPointer),canvas.removeEventListener("webglcontextlost",onLostContext);for(let bot of bots.values())gl.deleteTexture(bot.texture);for(let{program}of programs)gl.deleteProgram(program)}}}import{useMemo}from"react";var AuraAvatar_default={root:"AuraAvatar_root",tile:"AuraAvatar_tile",colour:"AuraAvatar_colour",grain:"AuraAvatar_grain",face:"AuraAvatar_face"};import{jsx,jsxs}from"react/jsx-runtime";var GRAIN_FREQUENCY=.8;function pictures(aura){let picture=svg=>`data:image/svg+xml,${encodeURIComponent(svg)}`;return{colour:picture(`<svg xmlns="http://www.w3.org/2000/svg" viewBox="-30 -30 160 160" width="160" height="160">${colourLayer(aura,"aura")}</svg>`),grain:picture(`<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%"><defs>${grainFilter("grain",GRAIN_FREQUENCY,aura.seed)}</defs><rect width="100%" height="100%" filter="url(#grain)"/></svg>`)}}function AuraAvatar({name,overrides}){let aura=useMemo(()=>createAura(name,overrides),[name,overrides]),{colour,grain}=useMemo(()=>pictures(aura),[aura]);return jsx("div",{className:AuraAvatar_default.root,"data-type":aura.type,children:jsxs("div",{className:AuraAvatar_default.tile,children:[jsx("img",{className:AuraAvatar_default.colour,src:colour,alt:"",draggable:!1}),jsx("img",{className:AuraAvatar_default.grain,src:grain,alt:"",draggable:!1,style:{opacity:aura.grain}}),aura.face.eyes&&jsx("svg",{className:AuraAvatar_default.face,viewBox:"0 0 100 100","aria-hidden":"true",children:jsx("g",{transform:"translate(50 52)",dangerouslySetInnerHTML:{__html:`<g ${FACE_STYLE}>${aura.face.eyes}${aura.face.mouth}</g>`}})})]})})}import{useId,useMemo as useMemo2,useRef as useRef2}from"react";import{useEffect,useRef,useState}from"react";var LOOK_RANGE=340,IDLE_MS=2600;function onCanvas(element,x,y){let canvas=element.closest("[data-canvas]");if(!canvas)return!0;let box2=canvas.getBoundingClientRect();return x>=box2.left&&x<=box2.right&&y>=box2.top&&y<=box2.bottom}function usePointerLook(ref,look,enabled=!0,wander=!0){let latest=useRef(look);latest.current=look,useEffect(()=>{if(!enabled||matchMedia("(prefers-reduced-motion: reduce)").matches){latest.current(0,0);return}let element=ref.current,frame=0,idle=0,glance=()=>{if(!wander)return;let angle=Math.random()*2*Math.PI;latest.current(Math.cos(angle)*.8,Math.sin(angle)*.8),idle=window.setTimeout(glance,IDLE_MS)},away=!1,onMove=event=>{if(!onCanvas(element,event.clientX,event.clientY)){away||(away=!0,cancelAnimationFrame(frame),clearTimeout(idle),latest.current(0,0),idle=window.setTimeout(glance,IDLE_MS));return}away=!1,clearTimeout(idle),idle=window.setTimeout(glance,IDLE_MS*2),cancelAnimationFrame(frame),frame=requestAnimationFrame(()=>{let box2=element.getBoundingClientRect(),dx=event.clientX-(box2.left+box2.width/2),dy=event.clientY-(box2.top+box2.height/2),distance2=Math.hypot(dx,dy)||1,reach=Math.min(1,distance2/LOOK_RANGE);latest.current(dx/distance2*reach,dy/distance2*reach)})};return window.addEventListener("pointermove",onMove),idle=window.setTimeout(glance,IDLE_MS),()=>{window.removeEventListener("pointermove",onMove),cancelAnimationFrame(frame),clearTimeout(idle)}},[ref,enabled,wander])}function useTapReaction(ref,duration,enabled=!0){let[tap,setTap]=useState(0),[tapped,setTapped]=useState(!1),listening=useRef(enabled);return listening.current=enabled,useEffect(()=>{let slot=ref.current.parentElement,onTap=()=>{listening.current&&(setTap(count=>count+1),setTapped(!0))};return slot.addEventListener("click",onTap),()=>slot.removeEventListener("click",onTap)},[ref]),useEffect(()=>{if(!tap)return;let timer=setTimeout(()=>setTapped(!1),duration);return()=>clearTimeout(timer)},[tap,duration]),{tap,tapped}}var BubbleAvatar_default={root:"BubbleAvatar_root",jelly:"BubbleAvatar_jelly",layer:"BubbleAvatar_layer",eyes:"BubbleAvatar_eyes",blink:"BubbleAvatar_blink",float:"BubbleAvatar_float",squish:"BubbleAvatar_squish",wiggle:"BubbleAvatar_wiggle",bounce:"BubbleAvatar_bounce"};import{jsx as jsx2,jsxs as jsxs2}from"react/jsx-runtime";var EFFECT_MS=900,LOOK_REACH=3;function BubbleAvatar({name,overrides,follow,animate,selected}){let ids=`bubble-${useId().replace(/\W/g,"")}`,bubble=useMemo2(()=>createBubble(name,overrides,ids),[name,overrides,ids]),rootRef=useRef2(null),{tapped}=useTapReaction(rootRef,EFFECT_MS,selected&&animate);return usePointerLook(rootRef,(x,y)=>{let root=rootRef.current;root.style.setProperty("--look-x",String(x*LOOK_REACH)),root.style.setProperty("--look-y",String(y*LOOK_REACH))},follow,animate),jsx2("div",{ref:rootRef,className:BubbleAvatar_default.root,style:{"--blink-delay":`${bubble.blinkDelay}s`},"data-animated":animate,"data-selected":selected,"data-effect":bubble.effect,"data-tapped":tapped,children:jsxs2("div",{className:BubbleAvatar_default.jelly,children:[jsx2("svg",{className:BubbleAvatar_default.layer,viewBox:VIEW_BOX,"aria-hidden":"true",dangerouslySetInnerHTML:{__html:bubble.art}}),jsx2("svg",{className:BubbleAvatar_default.layer,viewBox:VIEW_BOX,"aria-hidden":"true",children:jsx2("g",{className:BubbleAvatar_default.eyes,dangerouslySetInnerHTML:{__html:bubble.eyes}})})]})})}import{useId as useId2,useMemo as useMemo3,useRef as useRef3}from"react";var KittyAvatar_default={root:"KittyAvatar_root",sprite:"KittyAvatar_sprite",head:"KittyAvatar_head",eyes:"KittyAvatar_eyes",blink:"KittyAvatar_blink",ear:"KittyAvatar_ear",twitch:"KittyAvatar_twitch",right:"KittyAvatar_right"};import{jsx as jsx3,jsxs as jsxs3}from"react/jsx-runtime";var LOOK_REACH2=2.4;function BuddyAvatar({name,overrides,follow,animate}){let ids=`buddy-${useId2().replace(/\W/g,"")}`,buddy=useMemo3(()=>createBuddy(name,overrides,ids),[name,overrides,ids]),rootRef=useRef3(null);return usePointerLook(rootRef,(x,y)=>{let across=buddy.mirrored?-x:x,root=rootRef.current;root.style.setProperty("--look-x",String(across*LOOK_REACH2)),root.style.setProperty("--look-y",String(y*LOOK_REACH2))},follow,animate),jsx3("div",{ref:rootRef,className:KittyAvatar_default.root,style:{"--blink-delay":`${buddy.blinkDelay}s`},"data-animated":animate,children:jsxs3("svg",{className:KittyAvatar_default.sprite,viewBox:"0 0 100 100","aria-hidden":"true",children:[jsx3("defs",{dangerouslySetInnerHTML:{__html:`${buddy.defs}<clipPath id="${ids}-tile">${TILE_SHAPE}</clipPath>`}}),jsx3("g",{dangerouslySetInnerHTML:{__html:TILE_SHAPE.replace("/>",` fill="${buddy.tile}"/>`)}}),jsx3("g",{clipPath:`url(#${ids}-tile)`,children:jsx3("g",{transform:buddy.pose,children:jsxs3("g",{className:KittyAvatar_default.head,children:[jsx3("g",{className:KittyAvatar_default.ear,dangerouslySetInnerHTML:{__html:buddy.ears[0]}}),jsx3("g",{className:`${KittyAvatar_default.ear} ${KittyAvatar_default.right}`,dangerouslySetInnerHTML:{__html:buddy.ears[1]}}),jsx3("g",{dangerouslySetInnerHTML:{__html:buddy.body+buddy.face}}),jsx3("g",{className:KittyAvatar_default.eyes,dangerouslySetInnerHTML:{__html:buddy.eyes}}),jsx3("g",{dangerouslySetInnerHTML:{__html:buddy.front}})]})})})]})})}import{useId as useId3,useMemo as useMemo4,useRef as useRef4}from"react";var CritterAvatar_default={root:"CritterAvatar_root",sprite:"CritterAvatar_sprite",face:"CritterAvatar_face",brows:"CritterAvatar_brows",mouth:"CritterAvatar_mouth",blink:"CritterAvatar_blink",eye:"CritterAvatar_eye",pop:"CritterAvatar_pop",flutter:"CritterAvatar_flutter"};import{jsx as jsx4,jsxs as jsxs4}from"react/jsx-runtime";var EFFECT_MS2=700;function CritterAvatar({name,overrides,follow,animate,selected}){let id=useId3().replace(/:/g,""),critter=useMemo4(()=>createCritter(name,overrides,id),[name,overrides,id]),rootRef=useRef4(null),{tap,tapped}=useTapReaction(rootRef,EFFECT_MS2,selected&&animate);usePointerLook(rootRef,(x,y)=>{let root=rootRef.current;root.style.setProperty("--look-x",String(x)),root.style.setProperty("--look-y",String(y))},follow,animate);let html=markup=>({__html:markup});return jsx4("div",{ref:rootRef,className:CritterAvatar_default.root,style:{"--period":`${critter.blink.period}s`,"--delay":`${critter.blink.delay}s`},"data-animated":animate,"data-tapped":tapped,children:jsxs4("svg",{className:CritterAvatar_default.sprite,viewBox:"0 0 100 100","aria-hidden":"true",children:[jsx4("defs",{children:jsx4("clipPath",{id:`${id}-tile`,children:jsx4("rect",{width:"100",height:"100",rx:CORNER3})})}),jsxs4("g",{clipPath:`url(#${id}-tile)`,children:[jsx4("rect",{width:"100",height:"100",fill:critter.body}),jsxs4("g",{className:CritterAvatar_default.face,children:[jsx4("g",{dangerouslySetInnerHTML:html(critter.back)}),jsx4("g",{className:CritterAvatar_default.eye,"data-side":"left",dangerouslySetInnerHTML:html(critter.eyes.left)}),jsx4("g",{className:CritterAvatar_default.eye,"data-side":"right",dangerouslySetInnerHTML:html(critter.eyes.right)}),jsx4("g",{className:CritterAvatar_default.brows,dangerouslySetInnerHTML:html(critter.brows)}),jsx4("g",{className:CritterAvatar_default.mouth,dangerouslySetInnerHTML:html(critter.mouth)}),jsx4("g",{className:CritterAvatar_default.mouth,dangerouslySetInnerHTML:html(critter.front)})]},tap)]})]})})}import{useMemo as useMemo5,useRef as useRef5}from"react";var DoodleAvatar_default={root:"DoodleAvatar_root",sprite:"DoodleAvatar_sprite",look:"DoodleAvatar_look",eyes:"DoodleAvatar_eyes",mouth:"DoodleAvatar_mouth",blink:"DoodleAvatar_blink",wiggle:"DoodleAvatar_wiggle"};import{jsx as jsx5,jsxs as jsxs5}from"react/jsx-runtime";var LOOK_REACH3=3.2;function DoodleAvatar({name,overrides,follow,animate}){let doodle=useMemo5(()=>createDoodle(name,overrides),[name,overrides]),rootRef=useRef5(null);return usePointerLook(rootRef,(x,y)=>{let root=rootRef.current;root.style.setProperty("--look-x",String(x*LOOK_REACH3)),root.style.setProperty("--look-y",String(y*LOOK_REACH3))},follow,animate),jsx5("div",{ref:rootRef,className:DoodleAvatar_default.root,style:{"--blink-delay":`${doodle.blinkDelay}s`},"data-animated":animate,children:jsxs5("svg",{className:DoodleAvatar_default.sprite,viewBox:"0 0 100 100","aria-hidden":"true",children:[jsx5("rect",{width:"100",height:"100",rx:"22.22",fill:doodle.tile}),jsx5("g",{className:DoodleAvatar_default.look,children:jsxs5("g",{transform:doodle.face,color:doodle.ink,fill:"currentColor",stroke:"currentColor",strokeWidth:doodle.weight,strokeLinecap:"round",strokeLinejoin:"round",children:[jsx5("g",{dangerouslySetInnerHTML:{__html:doodle.marks}}),jsx5("g",{className:DoodleAvatar_default.eyes,dangerouslySetInnerHTML:{__html:doodle.eyes}}),jsx5("g",{className:DoodleAvatar_default.mouth,dangerouslySetInnerHTML:{__html:doodle.mouth}})]})})]})})}import{useId as useId4,useMemo as useMemo6,useRef as useRef6}from"react";var FaceAvatar_default={root:"FaceAvatar_root",arrive:"FaceAvatar_arrive",tile:"FaceAvatar_tile",eyes:"FaceAvatar_eyes",eyebrows:"FaceAvatar_eyebrows",mouth:"FaceAvatar_mouth",glasses:"FaceAvatar_glasses",blink:"FaceAvatar_blink",mouthRest:"FaceAvatar_mouthRest",mouthHover:"FaceAvatar_mouthHover",mouthTap:"FaceAvatar_mouthTap",tapped:"FaceAvatar_tapped",squash:"FaceAvatar_squash",sweep:"FaceAvatar_sweep",burst:"FaceAvatar_burst",fly:"FaceAvatar_fly",confetti:"FaceAvatar_confetti",hearts:"FaceAvatar_hearts",stars:"FaceAvatar_stars",shine:"FaceAvatar_shine",snooze:"FaceAvatar_snooze",drift:"FaceAvatar_drift",storm:"FaceAvatar_storm",rain:"FaceAvatar_rain"};import{jsx as jsx6,jsxs as jsxs6}from"react/jsx-runtime";var EFFECT_MS3=1300,PARTICLES=16,GLYPHS={confetti:["\u25A0","\u25CF","\u25B2"],hearts:["\u2665"],stars:["\u2605","\u2726"],shine:["\u2726","\u2727"],snooze:["z","Z"],storm:["\u25CF"]};function Burst({effect}){let glyphs=GLYPHS[effect];return jsx6("div",{className:`${FaceAvatar_default.burst} ${FaceAvatar_default[effect]}`,"aria-hidden":"true",children:Array.from({length:PARTICLES},(_,i)=>{let angle=i*2.39996,reach=.72+i*7%5*.09,style={"--x":Math.cos(angle)*reach,"--y":Math.sin(angle)*reach,"--spin":`${i*97%360}deg`,"--wait":`${i%5*45}ms`,"--hue":i*47%360};return jsx6("span",{style,children:glyphs[i%glyphs.length]},i)})})}function FaceAvatar({name,overrides,follow,animate,selected}){let id=useId4().replace(/\W/g,""),face=useMemo6(()=>createFace(name,`${id}-`,overrides),[name,id,overrides]),rootRef=useRef6(null),{tap,tapped}=useTapReaction(rootRef,EFFECT_MS3,selected&&animate);return usePointerLook(rootRef,(x,y)=>{let root=rootRef.current;root.style.setProperty("--look-x",x.toFixed(3)),root.style.setProperty("--look-y",y.toFixed(3))},follow,animate),jsxs6("div",{ref:rootRef,className:`${FaceAvatar_default.root} ${tapped?FaceAvatar_default.tapped:""}`,style:{"--blink-delay":`${face.blinkDelay}s`},"data-animated":animate,"data-effect":face.effect,"data-tapped":tapped,children:[jsxs6("div",{className:FaceAvatar_default.tile,children:[jsxs6("svg",{viewBox:"0 0 400 400",fill:"none","aria-hidden":"true",children:[jsx6("rect",{width:"400",height:"400",fill:face.skin}),jsx6("g",{transform:face.at.eyes,children:jsx6("g",{className:FaceAvatar_default.eyes,children:jsx6("g",{className:face.eyesOpen?FaceAvatar_default.blink:void 0,dangerouslySetInnerHTML:{__html:face.eyes}})})}),jsx6("g",{transform:face.at.eyebrows,children:jsx6("g",{className:FaceAvatar_default.eyebrows,dangerouslySetInnerHTML:{__html:face.eyebrows}})}),jsx6("g",{transform:face.at.mouth,children:jsxs6("g",{className:FaceAvatar_default.mouth,children:[jsx6("g",{className:FaceAvatar_default.mouthRest,dangerouslySetInnerHTML:{__html:face.mouths.rest}}),jsx6("g",{className:FaceAvatar_default.mouthHover,dangerouslySetInnerHTML:{__html:face.mouths.hover}}),jsx6("g",{className:FaceAvatar_default.mouthTap,dangerouslySetInnerHTML:{__html:face.mouths.tap}})]})}),face.glasses&&jsx6("g",{transform:face.at.glasses,children:jsx6("g",{className:FaceAvatar_default.glasses,dangerouslySetInnerHTML:{__html:face.glasses}})})]}),tapped&&face.effect==="shine"&&jsx6("div",{className:FaceAvatar_default.sweep},tap)]}),tapped&&animate&&jsx6(Burst,{effect:face.effect},tap)]})}import{useMemo as useMemo7,useRef as useRef7}from"react";var GlanceAvatar_default={root:"GlanceAvatar_root",sprite:"GlanceAvatar_sprite",eyes:"GlanceAvatar_eyes",lean:"GlanceAvatar_lean",lid:"GlanceAvatar_lid",blink:"GlanceAvatar_blink","blink-twice":"GlanceAvatar_blink-twice",pop:"GlanceAvatar_pop",flutter:"GlanceAvatar_flutter"};import{jsx as jsx7,jsxs as jsxs7}from"react/jsx-runtime";var EFFECT_MS4=700;function GlanceAvatar({name,overrides,follow,animate,selected}){let glance=useMemo7(()=>createGlance(name,overrides),[name,overrides]),rootRef=useRef7(null),{tap,tapped}=useTapReaction(rootRef,EFFECT_MS4,selected&&animate);usePointerLook(rootRef,(x,y)=>{let root=rootRef.current;root.style.setProperty("--look-x",String(x)),root.style.setProperty("--look-y",String(y))},follow,animate);let eye3=(side,{at:at3,shape})=>jsx7("g",{transform:at3,children:jsx7("g",{className:GlanceAvatar_default.lean,"data-side":side,children:jsx7("g",{className:GlanceAvatar_default.lid,dangerouslySetInnerHTML:{__html:shape}})})});return jsx7("div",{ref:rootRef,className:GlanceAvatar_default.root,style:{"--period":`${glance.blink.period}s`,"--delay":`${glance.blink.delay}s`},"data-animated":animate,"data-tapped":tapped,"data-twice":glance.blink.twice,children:jsxs7("svg",{className:GlanceAvatar_default.sprite,viewBox:"0 0 100 100","aria-hidden":"true",children:[jsx7("rect",{width:"100",height:"100",rx:CORNER4,fill:glance.tile}),jsx7("g",{transform:glance.face,children:jsxs7("g",{className:GlanceAvatar_default.eyes,...attributes(EYE_STYLE(glance.ink)),children:[eye3("left",glance.left),eye3("right",glance.right)]},tap)})]})})}function attributes(markup){let camel=key2=>key2.replace(/-([a-z])/g,(_,letter)=>letter.toUpperCase());return Object.fromEntries([...markup.matchAll(/([\w-]+)="([^"]*)"/g)].map(([,key2,value])=>[camel(key2),value]))}import{useId as useId5,useMemo as useMemo8,useRef as useRef8}from"react";var GlyphAvatar_default={root:"GlyphAvatar_root",sprite:"GlyphAvatar_sprite",ink:"GlyphAvatar_ink",eyes:"GlyphAvatar_eyes",blink:"GlyphAvatar_blink",turn:"GlyphAvatar_turn",breathe:"GlyphAvatar_breathe",sway:"GlyphAvatar_sway",bob:"GlyphAvatar_bob"};import{jsx as jsx8,jsxs as jsxs8}from"react/jsx-runtime";var LOOK_REACH4=3.4,PIXEL_STEP=2.5;function GlyphAvatar({name,overrides,follow,animate,selected}){let box2=`glyph-${useId5().replace(/\W/g,"")}-box`,glyph=useMemo8(()=>createGlyph(name,overrides),[name,overrides]),rootRef=useRef8(null);return usePointerLook(rootRef,(x,y)=>{let cell=value=>glyph.pixel?Math.round(value)*PIXEL_STEP:value*LOOK_REACH4,root=rootRef.current;root.style.setProperty("--look-x",String(cell(x))),root.style.setProperty("--look-y",String(cell(y)))},follow,animate),jsx8("div",{ref:rootRef,className:GlyphAvatar_default.root,style:{"--blink-delay":`${glyph.blinkDelay}s`},"data-animated":animate,"data-selected":selected,"data-pixel":glyph.pixel,"data-effect":glyph.effect,children:jsxs8("svg",{className:GlyphAvatar_default.sprite,viewBox:VIEW_BOX2,"aria-hidden":"true",children:[jsx8("clipPath",{id:box2,dangerouslySetInnerHTML:{__html:TILE_SHAPE3}}),jsx8("g",{dangerouslySetInnerHTML:{__html:TILE_SHAPE3},fill:glyph.tile}),jsxs8("g",{clipPath:`url(#${box2})`,children:[jsx8("g",{className:GlyphAvatar_default.ink,dangerouslySetInnerHTML:{__html:glyph.body}}),jsx8("g",{className:GlyphAvatar_default.eyes,dangerouslySetInnerHTML:{__html:glyph.eyes}})]})]})})}import{useId as useId6,useMemo as useMemo9,useRef as useRef9}from"react";var GrinAvatar_default={root:"GrinAvatar_root",sprite:"GrinAvatar_sprite",eyes:"GrinAvatar_eyes",mouth:"GrinAvatar_mouth",blink:"GrinAvatar_blink",chomp:"GrinAvatar_chomp",pop:"GrinAvatar_pop"};import{jsx as jsx9,jsxs as jsxs9}from"react/jsx-runtime";var EFFECT_MS5=650;function GrinAvatar({name,overrides,follow,animate,selected}){let id=useId6().replace(/:/g,""),grin=useMemo9(()=>createGrin(name,overrides,id),[name,overrides,id]),rootRef=useRef9(null),{tap,tapped}=useTapReaction(rootRef,EFFECT_MS5,selected&&animate);return usePointerLook(rootRef,(x,y)=>{let root=rootRef.current;root.style.setProperty("--look-x",String(x)),root.style.setProperty("--look-y",String(y))},follow,animate),jsx9("div",{ref:rootRef,className:GrinAvatar_default.root,style:{"--period":`${grin.blink.period}s`,"--delay":`${grin.blink.delay}s`},"data-animated":animate,"data-tapped":tapped,children:jsxs9("svg",{className:GrinAvatar_default.sprite,viewBox:"0 0 100 100","aria-hidden":"true",children:[jsx9("g",{dangerouslySetInnerHTML:{__html:buttonMarkup(grin.body,grin.corner)}}),jsxs9("g",{children:[jsx9("g",{className:GrinAvatar_default.eyes,dangerouslySetInnerHTML:{__html:grin.eyes.join("")}}),jsx9("g",{className:GrinAvatar_default.mouth,dangerouslySetInnerHTML:{__html:grin.mouth}})]},tap)]})})}import{useId as useId7,useMemo as useMemo10,useRef as useRef10}from"react";import{Fragment,jsx as jsx10,jsxs as jsxs10}from"react/jsx-runtime";var LOOK_REACH5=2.4;function KittyAvatar({name,overrides,follow,animate,animals=!1}){let ids=`${prefixOf(animals)}-${useId7().replace(/\W/g,"")}`,cat=useMemo10(()=>createKitty(name,overrides,animals,ids),[name,overrides,animals,ids]),tile=`${ids}-tile`,ears=jsxs10(Fragment,{children:[jsx10("g",{className:KittyAvatar_default.ear,dangerouslySetInnerHTML:{__html:cat.ears[0]}}),jsx10("g",{className:`${KittyAvatar_default.ear} ${KittyAvatar_default.right}`,dangerouslySetInnerHTML:{__html:cat.ears[1]}})]}),rootRef=useRef10(null);return usePointerLook(rootRef,(x,y)=>{let across=cat.mirrored?-x:x,root=rootRef.current;root.style.setProperty("--look-x",String(across*LOOK_REACH5)),root.style.setProperty("--look-y",String(y*LOOK_REACH5))},follow,animate),jsx10("div",{ref:rootRef,className:KittyAvatar_default.root,style:{"--blink-delay":`${cat.blinkDelay}s`},"data-animated":animate,children:jsxs10("svg",{className:KittyAvatar_default.sprite,viewBox:"0 0 100 100","aria-hidden":"true",children:[jsx10("defs",{dangerouslySetInnerHTML:{__html:`${cat.defs}<clipPath id="${tile}">${TILE_SHAPE2}</clipPath>`}}),jsx10("g",{dangerouslySetInnerHTML:{__html:tileMarkup(cat.tile,ids)}}),jsx10("g",{clipPath:`url(#${tile})`,children:jsx10("g",{transform:cat.pose,children:jsxs10("g",{className:KittyAvatar_default.head,children:[!cat.earsFront&&ears,jsx10("g",{dangerouslySetInnerHTML:{__html:cat.body+cat.discs+cat.face}}),cat.earsFront&&ears,jsx10("g",{className:KittyAvatar_default.eyes,dangerouslySetInnerHTML:{__html:cat.eyes}})]})})})]})})}import{useId as useId8,useMemo as useMemo11,useRef as useRef11}from"react";var KnitAvatar_default={root:"KnitAvatar_root",layer:"KnitAvatar_layer",blink:"KnitAvatar_blink",flutter:"KnitAvatar_flutter",bounce:"KnitAvatar_bounce"};import{jsx as jsx11,jsxs as jsxs11}from"react/jsx-runtime";var EFFECT_MS6=700;function pictures2(knit){let picture=body=>`data:image/svg+xml,${encodeURIComponent(`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">${knit.defs}${body}</svg>`)}`;return{back:picture(knit.back),front:picture(knit.front)}}function KnitAvatar({name,overrides,follow,animate,selected}){let id=useId8().replace(/:/g,""),knit=useMemo11(()=>createKnit(name,overrides,id),[name,overrides,id]),{back,front}=useMemo11(()=>pictures2(knit),[knit]),rootRef=useRef11(null),{tap,tapped}=useTapReaction(rootRef,EFFECT_MS6,selected&&animate);return usePointerLook(rootRef,(x,y)=>{let root=rootRef.current;root.style.setProperty("--look-x",String(x)),root.style.setProperty("--look-y",String(y))},follow,animate),jsxs11("div",{ref:rootRef,className:KnitAvatar_default.root,style:{"--period":`${knit.blink.period}s`,"--delay":`${knit.blink.delay}s`},"data-animated":animate,"data-tapped":tapped,children:[jsx11("img",{className:KnitAvatar_default.layer,src:back,alt:"",draggable:!1}),jsx11("svg",{className:KnitAvatar_default.layer,viewBox:"0 0 100 100","aria-hidden":"true",dangerouslySetInnerHTML:{__html:knit.defs+knit.live}},tap),jsx11("img",{className:KnitAvatar_default.layer,src:front,alt:"",draggable:!1})]})}import{useId as useId9,useMemo as useMemo12,useRef as useRef12}from"react";var PeekAvatar_default={root:"PeekAvatar_root",sprite:"PeekAvatar_sprite",creature:"PeekAvatar_creature",rings:"PeekAvatar_rings",face:"PeekAvatar_face",blink:"PeekAvatar_blink",breathe:"PeekAvatar_breathe",peek:"PeekAvatar_peek",wobble:"PeekAvatar_wobble",widen:"PeekAvatar_widen",ripple:"PeekAvatar_ripple"};import{jsx as jsx12,jsxs as jsxs12}from"react/jsx-runtime";var EFFECT_MS7=900,LOOK_REACH6=2.2;function PeekAvatar({name,overrides,follow,animate,selected}){let ids=`peek-${useId9().replace(/\W/g,"")}`,peek=useMemo12(()=>createPeek(name,overrides,ids),[name,overrides,ids]),rootRef=useRef12(null),{tapped}=useTapReaction(rootRef,EFFECT_MS7,selected&&animate);usePointerLook(rootRef,(x,y)=>{let turn2=-peek.angle*Math.PI/180,root=rootRef.current;root.style.setProperty("--look-x",String((x*Math.cos(turn2)-y*Math.sin(turn2))*LOOK_REACH6)),root.style.setProperty("--look-y",String((x*Math.sin(turn2)+y*Math.cos(turn2))*LOOK_REACH6))},follow,animate);let style={"--blink-delay":`${peek.blinkDelay}s`,"--into-x":`${peek.into.x}px`,"--into-y":`${peek.into.y}px`,"--origin":`${peek.origin.x}px ${peek.origin.y}px`};return jsx12("div",{ref:rootRef,className:PeekAvatar_default.root,style,"data-animated":animate,"data-selected":selected,"data-effect":peek.effect,"data-tapped":tapped,children:jsxs12("svg",{className:PeekAvatar_default.sprite,viewBox:VIEW_BOX3,"aria-hidden":"true",children:[jsx12("g",{dangerouslySetInnerHTML:{__html:peek.defs}}),jsx12("clipPath",{id:`${ids}-box`,dangerouslySetInnerHTML:{__html:TILE_SHAPE4}}),jsx12("g",{dangerouslySetInnerHTML:{__html:TILE_SHAPE4},fill:peek.tile}),jsx12("g",{clipPath:`url(#${ids}-box)`,children:jsxs12("g",{transform:peek.turn,children:[jsx12("g",{className:PeekAvatar_default.rings,dangerouslySetInnerHTML:{__html:peek.rings}}),jsxs12("g",{className:PeekAvatar_default.creature,children:[jsx12("g",{dangerouslySetInnerHTML:{__html:peek.body}}),jsx12("g",{className:PeekAvatar_default.face,dangerouslySetInnerHTML:{__html:peek.face}})]})]})})]})})}import{useId as useId10,useMemo as useMemo13,useRef as useRef13}from"react";var PixelAvatar_default={root:"PixelAvatar_root",arrive:"PixelAvatar_arrive",sprite:"PixelAvatar_sprite",face:"PixelAvatar_face",eyes:"PixelAvatar_eyes",glasses:"PixelAvatar_glasses",open:"PixelAvatar_open",wide:"PixelAvatar_wide",mouthHover:"PixelAvatar_mouthHover",shut:"PixelAvatar_shut",person:"PixelAvatar_person",mouthRest:"PixelAvatar_mouthRest"};import{jsx as jsx13,jsxs as jsxs13}from"react/jsx-runtime";var SPAN2=GRID+MARGIN3*2,Markup=({html,className})=>jsx13("g",{className,dangerouslySetInnerHTML:{__html:html}});function PixelAvatar({name,theme,overrides,follow,animate}){let clip=`${useId10().replace(/\W/g,"")}-head`,face=useMemo13(()=>createPixelFace(name,theme,overrides),[name,theme,overrides]),rootRef=useRef13(null);return usePointerLook(rootRef,(x,y)=>{let root=rootRef.current;root.style.setProperty("--look-x",String(Math.round(x*1.4))),root.style.setProperty("--look-y",String(Math.round(y*1.2)))},follow,animate),jsx13("div",{ref:rootRef,className:PixelAvatar_default.root,style:{"--blink-delay":`${face.blinkDelay}s`},"data-animated":animate,children:jsxs13("svg",{className:PixelAvatar_default.sprite,viewBox:`${-MARGIN3} ${-MARGIN3} ${SPAN2} ${SPAN2}`,shapeRendering:"crispEdges","aria-hidden":"true",children:[jsx13("clipPath",{id:clip,dangerouslySetInnerHTML:{__html:face.headMask}}),jsx13(Markup,{html:face.tile}),jsxs13("g",{className:PixelAvatar_default.person,children:[jsx13(Markup,{html:face.behind}),jsx13("g",{clipPath:`url(#${clip})`,children:jsxs13("g",{className:PixelAvatar_default.face,children:[jsx13(Markup,{html:face.face}),jsx13(Markup,{html:face.mouths.rest,className:PixelAvatar_default.mouthRest}),jsx13(Markup,{html:face.mouths.hover,className:PixelAvatar_default.mouthHover})]})}),face.eyesVisible&&jsxs13("g",{className:PixelAvatar_default.eyes,children:[jsx13(Markup,{html:face.eyes.open,className:PixelAvatar_default.open}),jsx13(Markup,{html:face.eyes.wide,className:PixelAvatar_default.wide}),jsx13(Markup,{html:face.eyes.shut,className:PixelAvatar_default.shut})]}),jsx13(Markup,{html:face.front}),face.glasses&&jsx13(Markup,{html:face.glasses,className:PixelAvatar_default.glasses}),face.hat&&jsx13(Markup,{html:face.hat,className:PixelAvatar_default.hat})]})]})})}import{useMemo as useMemo14,useRef as useRef14}from"react";var ShapeAvatar_default={root:"ShapeAvatar_root",sprite:"ShapeAvatar_sprite",eyes:"ShapeAvatar_eyes",mouth:"ShapeAvatar_mouth",blink:"ShapeAvatar_blink",hop:"ShapeAvatar_hop"};import{jsx as jsx14,jsxs as jsxs14}from"react/jsx-runtime";var EFFECT_MS8=700,LOOK_REACH7=3.4;function ShapeAvatar({name,overrides,follow,animate,selected}){let face=useMemo14(()=>createShapeFace(name,overrides),[name,overrides]),rootRef=useRef14(null),{tapped}=useTapReaction(rootRef,EFFECT_MS8,selected&&animate);return usePointerLook(rootRef,(x,y)=>{let root=rootRef.current;root.style.setProperty("--look-x",String(x*LOOK_REACH7)),root.style.setProperty("--look-y",String(y*LOOK_REACH7))},follow,animate),jsx14("div",{ref:rootRef,className:ShapeAvatar_default.root,style:{"--blink-delay":`${face.blinkDelay}s`},"data-animated":animate,"data-tapped":tapped,children:jsxs14("svg",{className:ShapeAvatar_default.sprite,viewBox:"0 0 100 100","aria-hidden":"true",children:[jsx14("rect",{width:"100",height:"100",rx:"22.22",fill:face.tile}),jsxs14("g",{transform:face.face,fill:"currentColor",stroke:"currentColor",strokeWidth:face.weight,strokeLinecap:"round",strokeLinejoin:"round",children:[jsx14("g",{className:ShapeAvatar_default.eyes,dangerouslySetInnerHTML:{__html:face.eyes}}),jsx14("g",{className:ShapeAvatar_default.mouth,dangerouslySetInnerHTML:{__html:face.mouth}})]})]})})}import{css}from"./styles.js";import{Fragment as Fragment2,jsx as jsx15,jsxs as jsxs15}from"react/jsx-runtime";var LIVE={auras:AuraAvatar,bubbles:BubbleAvatar,buddies:BuddyAvatar,critters:CritterAvatar,doodles:DoodleAvatar,faces:FaceAvatar,glances:GlanceAvatar,glyphs:GlyphAvatar,grins:GrinAvatar,animals:props=>jsx15(KittyAvatar,{...props,animals:!0}),knits:KnitAvatar,peeks:PeekAvatar,pixels:props=>jsx15(PixelAvatar,{...props,theme:"color"}),shapes:ShapeAvatar},injected=!1;function Avatar({style,name,overrides={},size=96,follow=!0,animate=!0,label="",className}){let kind=KINDS2.find(each=>each.id===style);if(!kind)throw new Error(`Unknown style "${style}". Styles: ${KINDS2.map(each=>each.id).join(", ")}`);useInsertionEffect(()=>{if(injected)return;injected=!0;let tag=document.createElement("style");tag.dataset.originkitAvatars="",tag.textContent=css,document.head.append(tag)},[]);let[live,setLive]=useState2(!1);useEffect2(()=>setLive(!0),[]);let box2={position:"relative",display:"inline-block",width:size,height:size,flex:"none"},still2=jsx15("img",{src:toDataUri(kind.svg(name,overrides)),alt:"",draggable:!1,style:{display:"block",width:"100%",height:"100%"}}),Live=LIVE[kind.id];return jsx15("span",{className,style:box2,role:"img","aria-label":label||void 0,"aria-hidden":label?void 0:!0,children:live?kind.parts?jsx15(Avatar3D,{kind,name,overrides,follow,animate,fallback:still2}):Live?jsx15(Live,{name,overrides,follow,animate,selected:!0},kind.id==="faces"?name:void 0):still2:still2})}function Avatar3D(props){let{kind,name,overrides,follow,animate,fallback}=props,canvasRef=useRef15(null),slotRef=useRef15(null),[stage,setStage]=useState2(null),[failed,setFailed]=useState2(!1),parts=useMemo15(()=>kind.parts(name,overrides),[kind,name,overrides]);return useEffect2(()=>{let created=createStage(canvasRef.current,()=>setFailed(!0),{followAnywhere:!0});return created||setFailed(!0),setStage(created),()=>created?.dispose()},[]),useEffect2(()=>{stage&&(stage.show(slotRef.current,parts),stage.fit(slotRef.current,!0))},[stage,parts]),useEffect2(()=>stage?.setView({animate,follow}),[stage,animate,follow]),failed?fallback:jsxs15(Fragment2,{children:[jsx15("canvas",{ref:canvasRef,"aria-hidden":"true",style:{position:"absolute",inset:0,width:"100%",height:"100%",pointerEvents:"none"}}),jsx15("span",{ref:slotRef,onClick:()=>animate&&stage?.poke(slotRef.current),style:{position:"absolute",inset:0,display:"block"}})]})}export{Avatar,LIVE};
|