[{"data":1,"prerenderedAt":241},["ShallowReactive",2],{"profile":3,"source-jevvie":204},{"name":4,"meta":5,"statement":6,"lede":9,"description":10,"origin":11,"role":12,"work":13,"trajectory":53,"notes":83,"about":86,"contact":92,"home":106},"Chris Wijnia","Engineer · Co-founder",{"text":7,"accent":8},"I build software that holds up.","holds up.","I work out what’s worth building next.","Dutch engineer and co-founder. I work out what’s worth building next.","Netherlands","Product \u002F R&D",{"title":14,"accent":15,"outro":16,"projects":17},"A few things I’ve worked on.","worked on.","The work has changed a lot over the years. The habit of making things hasn’t.",[18,24,30,36,42,47],{"no":19,"name":20,"area":21,"period":22,"slug":23},"01","AI systems","Agents \u002F Automation \u002F Developer tools","2022–Now","ai-systems",{"no":25,"name":26,"area":27,"period":28,"slug":29},"02","1GRAM","Wallet software","2020–2021","1gram",{"no":31,"name":32,"area":33,"period":34,"slug":35},"03","MVRDV","Digital platform \u002F Architecture","2015–2019","mvrdv",{"no":37,"name":38,"area":39,"period":40,"slug":41},"04","JIJ & Overijssel","Public participation platform","2014–2018","jij-overijssel",{"no":43,"name":44,"area":45,"period":46,"slug":44},"05","100-100-100","Sustainability campaign platform","2014–2019",{"no":48,"name":49,"area":50,"period":51,"slug":52},"06","Archive","Design \u002F Web \u002F Software","2007–2022","archive",{"title":54,"eras":55},"Moving down the stack as the web evolved.",[56,60,64,67,71,75,79],{"year":57,"name":58,"line":59},"2005","Design","Learning the web by making things.",{"year":61,"name":62,"line":63},"2013","Product","Design became code.",{"name":65,"line":66},"Engineering","Code became systems.",{"year":68,"name":69,"line":70},"2018","Wallets","Software for a new kind of money.",{"year":72,"name":73,"line":74},"2021","Financial infra","Building systems where software meets regulation.",{"year":76,"name":77,"line":78},"2022","AI","From using models to orchestrating them.",{"year":80,"name":81,"line":82},"Now","Building","All of it, at once.",{"title":84,"intro":85},"Notes","Things I’m working on, learning or trying to understand.",{"title":87,"paragraphs":88},"I’ve been making things on computers for most of my life.",[89,90,91],"I grew up in the Netherlands and built my first websites at thirteen.","I like small teams, ambitious projects, good engineering and people who can disagree without making it tedious. I still enjoy opening an empty repository and figuring something out.","I work internationally. Outside work I train Muay Thai and like [chess](\u002Flab\u002Fchess), which I played competitively in Zwolle and taught to primary-school children there. I also build things that occasionally have no sensible commercial purpose.",{"title":93,"accent":94,"intro":95,"links":96},"Making something interesting?","interesting?","For collaborations, technical discussions, or a good reason I haven’t thought of.",[97,100,103],{"label":98,"href":99},"LinkedIn","https:\u002F\u002Fwww.linkedin.com\u002Fin\u002Fchris-wijnia-1364a29b",{"label":101,"href":102},"GitHub","https:\u002F\u002Fgithub.com\u002Fcwdx",{"label":104,"href":105},"X","https:\u002F\u002Fx.com\u002FChristianWijnia",{"hero":107,"chapters":114,"principles":178,"work":194,"contact":198},{"headline":108,"lede":112,"cue":113},[109,110,111],"Every system","is one bit,","repeated.","Chris Wijnia is a Dutch engineer and co-founder. He works on financial software and AI systems.","Scroll to scale up",[115,126,138,152,166],{"id":116,"power":117,"name":118,"label":119,"formation":116,"cell":120,"headline":121,"body":124,"prompt":125},"bit","2^0","Bit","The bit · 1 state of 2",16,[122,123],"Yes.","Or no.","Approve the payment or hold it. Trust the answer or ask again. Ship the pixel or move it one to the left. Everything I build ends in a decision small enough to fit in one bit. The work is making sure it is the right one.","Flip the bit. This page has two states.",{"id":127,"power":128,"name":129,"label":130,"formation":127,"cell":131,"headline":132,"body":136,"prompt":137},"byte","2^3","Byte","The byte · design",8,[133,134,135],"Eight bits","make a","letter.","I started in design, placing pixels one at a time until a shape read as a word. Software is built the same way: from the smallest unit up.","Flip a bit. Make a letter.",{"id":139,"power":140,"name":141,"label":142,"formation":139,"cell":143,"ink":144,"headline":145,"body":150,"prompt":151},"ledger","2^10","Ledger","The ledger · financial software",4,true,[146,147,148,149],"Money is","the least","forgiving","data type.","In financial software nothing is probably right. No rounding error is too small to matter, and no state is allowed to drift. Every debit meets its credit. Every action leaves a record that adds up, today and in the audit years from now.","Simulated ledger",{"id":153,"power":154,"name":155,"label":156,"formation":153,"cell":157,"headline":158,"body":163,"prompt":164,"note":165},"weights","2^20","Weights","The weights · AI systems",2,[159,160,161,162],"A million","decisions,","none made","on purpose.","A model is a vast field of numbers nobody set by hand. Useful, and never quite certain. I build the part around it: where it may act alone, where it has to ask, and how anyone can check afterwards what it did and why.","Confidence","ai-makes-software-cheaper",{"id":167,"power":168,"name":169,"label":170,"formation":171,"cell":143,"headline":172,"body":177},"company","2^n","Company","The company · co-founder","knot",[173,174,175,176],"A company","is a system","with people","inside.","A company runs on what good software runs on: clear states, clean interfaces, and nothing that only works as long as someone remembers.",[179,182,185,188,191],{"name":180,"line":181},"Resolution is a choice","Decide how much detail a problem deserves, then commit to it.",{"name":183,"line":184},"Two states beat five","If a feature cannot say yes or no, it is not finished.",{"name":186,"line":187},"The ledger balances","Every action leaves a record, and the records add up.",{"name":189,"line":190},"The model proposes","A person signs. The system always knows which is which.",{"name":192,"line":193},"Every pixel on purpose","Including the ones nobody will ever notice.",{"label":195,"headline":196},"Work · 2007–now",[197],"Work.",{"label":199,"headline":200,"intro":203},"Back to one bit",[201,202],"Send","one bit.","Building something where a wrong answer costs money, or where a machine’s answer has to be trusted? Tell me in a line. I will answer in more than one bit.",{"files":205},[206,211,216,221,226,231,236],{"path":207,"lines":208,"code":209,"html":210},"app\u002Fcomponents\u002Flab\u002FJevvieStudio.client.vue",142,"\u003Cscript setup lang=\"ts\">\nimport { jevvieColors } from '#core\u002Fdomain\u002Fpalette'\nimport { MOODS, SHAPES, TRICKS, type JevvieView, type Mood, type Shape, type Trick, type Wear } from '@cw\u002Fjevvie\u002Fcharacter'\n\nconst WEARS: readonly Wear[] = ['none', 'clip', 'pencil', 'pin', 'flag', 'antennas']\nconst NAMES: Partial\u003CRecord\u003CShape, string>> = { bar: 'Bar (the _)', chamfer: 'Chamfered bar', capsule: 'Rounded bar', sticky: 'Sticky note' }\nconst title = (s: string) => s.charAt(0).toUpperCase() + s.slice(1)\nconst options = \u003CT extends string>(list: readonly T[], name: (v: T) => string = title) => list.map((value) => ({ value, label: name(value) }))\n\nconst route = useRoute()\nconst router = useRouter()\nconst shape = ref\u003CShape>('bar')\nconst mood = ref\u003CMood>('happy')\nconst wear = ref\u003CWear>('none')\nconst valid = \u003CT extends string>(q: unknown, list: readonly T[]) => (typeof q === 'string' && (list as readonly string[]).includes(q) ? (q as T) : undefined)\n\u002F\u002F follows the address: a prerendered page gets its query only after hydration\nwatch(() => route.query, (q) => {\n  shape.value = valid(q.body, SHAPES) ?? shape.value\n  mood.value = valid(q.mood, MOODS) ?? mood.value\n  wear.value = valid(q.wear, WEARS) ?? wear.value\n}, { immediate: true })\nwatch([shape, mood, wear], ([body, m, w]) => {\n  void router.replace({ query: { ...route.query, body, mood: m, wear: w === 'none' ? undefined : w } })\n})\n\nconst canvas = useTemplateRef\u003CHTMLCanvasElement>('canvas')\nconst width = ref(64)\nlet view: JevvieView | undefined\nconst reduced = useReducedMotion()\nasync function mount() {\n  view?.dispose()\n  const { mountCharacter } = await import('@cw\u002Fjevvie\u002Fcharacter')\n  if (!canvas.value) return\n  view = await mountCharacter(canvas.value, { colors: jevvieColors, shape: shape.value, wear: wear.value, reduced })\n  width.value = canvas.value.width\n  view.mood(mood.value)\n}\nonMounted(mount)\nwatch([shape, wear], mount)\nwatch(mood, (m) => view?.mood(m))\nonBeforeUnmount(() => view?.dispose())\n\nfunction trick(t: Trick) { view?.trick(t) }\nfunction any\u003CT>(list: readonly T[]): T { return list[Math.floor(Math.random() * list.length)]! }\nfunction shuffle() {\n  shape.value = any(SHAPES); mood.value = any(MOODS); wear.value = Math.random() \u003C 0.3 ? any(WEARS) : 'none'\n}\n\nuseSiteTool(() => ({\n  name: 'jevvie_body',\n  description: 'Put Jevvie in the studio in another body',\n  arg: { name: 'body', description: 'Which body', values: options(SHAPES, String) },\n  doing: (label) => `turning into a ${label}`,\n  run: (value) => { shape.value = value as Shape },\n}))\nuseSiteTool(() => ({\n  name: 'jevvie_mood',\n  description: 'Set how Jevvie in the studio feels',\n  arg: { name: 'mood', description: 'Which mood', values: options(MOODS, String) },\n  doing: (label) => `feeling ${label}`,\n  run: (value) => { mood.value = value as Mood },\n}))\nuseSiteTool(() => ({\n  name: 'jevvie_trick',\n  description: 'Make Jevvie in the studio do a trick',\n  arg: { name: 'trick', description: 'Which trick', values: options(TRICKS, String) },\n  doing: (label) => `doing a ${label}`,\n  run: (value) => trick(value as Trick),\n  readOnly: true,\n}))\n\nconst { copy, copied } = useClipboard({ copiedDuring: 1500 })\nconst copyLink = () => copy(location.href)\nconst saving = ref(false)\nasync function save() {\n  const src = canvas.value\n  if (!src || saving.value) return\n  saving.value = true\n  const { data, width: w, height: h } = src.getContext('2d')!.getImageData(0, 0, src.width, src.height)\n  let [x0, y0, x1, y1] = [w, h, 0, 0]\n  for (let y = 0; y \u003C h; y++) for (let x = 0; x \u003C w; x++) if (data[(y * w + x) * 4 + 3]! > 8) { x0 = Math.min(x0, x); y0 = Math.min(y0, y); x1 = Math.max(x1, x); y1 = Math.max(y1, y) }\n  const SIZE = 512, LINE = 8, bw = x1 - x0 + 1, bh = y1 - y0 + 1\n  const f = Math.max(1, Math.floor((SIZE - 2 * (16 + LINE)) \u002F Math.max(bw, bh)))\n  const layer = (fill?: string) => {\n    const c = Object.assign(document.createElement('canvas'), { width: bw * f, height: bh * f }), ctx = c.getContext('2d')!\n    ctx.imageSmoothingEnabled = false\n    ctx.drawImage(src, x0, y0, bw, bh, 0, 0, bw * f, bh * f)\n    if (fill) { ctx.globalCompositeOperation = 'source-in'; ctx.fillStyle = fill; ctx.fillRect(0, 0, c.width, c.height) }\n    return c\n  }\n  const out = Object.assign(document.createElement('canvas'), { width: SIZE, height: SIZE }), ctx = out.getContext('2d')!\n  const [left, top] = [(SIZE - bw * f) \u002F 2, (SIZE - bh * f) \u002F 2].map(Math.round) as [number, number]\n  const white = layer('#fff')\n  for (let dy = -LINE; dy \u003C= LINE; dy++) for (let dx = -LINE; dx \u003C= LINE; dx++) if (dx * dx + dy * dy \u003C= LINE * LINE) ctx.drawImage(white, left + dx, top + dy)\n  ctx.drawImage(layer(), left, top)\n  const blob = await new Promise\u003CBlob | null>((r) => out.toBlob(r, 'image\u002Fpng'))\n  saving.value = false\n  if (!blob) return\n  const a = Object.assign(document.createElement('a'), { href: URL.createObjectURL(blob), download: `jevvie-${shape.value}-${mood.value}.png` })\n  a.click()\n  URL.revokeObjectURL(a.href)\n}\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003CWin title=\"CW\u002F_ · STUDIO\" as=\"section\" label=\"Jevvie’s studio\" class=\"studio\">\n    \u003Ctemplate #meta>{{ title(shape) }} · {{ title(mood) }}\u003C\u002Ftemplate>\n    \u003Cdiv class=\"studio__grid\">\n      \u003Cdiv class=\"studio__view\">\n        \u003Ccanvas ref=\"canvas\" class=\"studio__canvas\" :style=\"{ '--w': `${width}px` }\" role=\"img\" :aria-label=\"`Jevvie as ${shape}, ${mood}`\" \u002F>\n      \u003C\u002Fdiv>\n      \u003Cdiv class=\"studio__controls mono-label\">\n        \u003Cdiv class=\"studio__row\">\n          \u003Cspan>Body\u003C\u002Fspan>\n          \u003CSelectBtn v-model=\"shape\" :options=\"options(SHAPES, (s) => NAMES[s] ?? title(s))\" label=\"Body\" \u002F>\n        \u003C\u002Fdiv>\n        \u003Cdiv class=\"studio__row\">\n          \u003Cspan>Wear\u003C\u002Fspan>\n          \u003CSelectBtn v-model=\"wear\" :options=\"options(WEARS)\" label=\"Wear\" \u002F>\n        \u003C\u002Fdiv>\n        \u003Cdiv class=\"studio__row studio__row--top\">\n          \u003Cspan id=\"studio-mood\">Mood\u003C\u002Fspan>\n          \u003Cdiv class=\"studio__moods\" role=\"group\" aria-labelledby=\"studio-mood\">\n            \u003Cbutton v-for=\"m in MOODS\" :key=\"m\" type=\"button\" class=\"bare read-1 hit\" :aria-pressed=\"mood === m\" @click=\"mood = m\">{{ m }}\u003C\u002Fbutton>\n          \u003C\u002Fdiv>\n        \u003C\u002Fdiv>\n        \u003Cdiv class=\"studio__row\">\n          \u003Cspan>Trick\u003C\u002Fspan>\n          \u003Cspan class=\"btn-group\" role=\"group\" aria-label=\"Trick\">\n            \u003CBtn v-for=\"t in TRICKS\" :key=\"t\" variant=\"ghost\" size=\"sm\" @click=\"trick(t)\">{{ t }}\u003C\u002FBtn>\n          \u003C\u002Fspan>\n        \u003C\u002Fdiv>\n        \u003Cdiv class=\"studio__actions\">\n          \u003CBtn variant=\"amber\" size=\"md\" :disabled=\"saving\" @click=\"save\">Save sticker\u003C\u002FBtn>\n          \u003CBtn variant=\"ghost\" size=\"md\" @click=\"shuffle\">Shuffle ▚\u003C\u002FBtn>\n          \u003CBtn variant=\"ghost\" size=\"md\" @click=\"copyLink\">{{ copied ? 'Copied' : 'Copy link' }}\u003C\u002FBtn>\n        \u003C\u002Fdiv>\n        \u003Cp class=\"studio__note\">A 512 × 512 PNG, cut out and outlined, for a WhatsApp or Telegram sticker pack.\u003C\u002Fp>\n      \u003C\u002Fdiv>\n    \u003C\u002Fdiv>\n  \u003C\u002FWin>\n\u003C\u002Ftemplate>","\u003Cspan class=\"hljs-tag\">&lt;\u003Cspan class=\"hljs-name\">script\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">setup\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">lang\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;ts&quot;\u003C\u002Fspan>&gt;\u003C\u002Fspan>\u003Cspan class=\"language-javascript\">\n\u003Cspan class=\"hljs-keyword\">import\u003C\u002Fspan> { jevvieColors } \u003Cspan class=\"hljs-keyword\">from\u003C\u002Fspan> \u003Cspan class=\"hljs-string\">&#x27;#core\u002Fdomain\u002Fpalette&#x27;\u003C\u002Fspan>\n\u003Cspan class=\"hljs-keyword\">import\u003C\u002Fspan> { \u003Cspan class=\"hljs-variable constant_\">MOODS\u003C\u002Fspan>, \u003Cspan class=\"hljs-variable constant_\">SHAPES\u003C\u002Fspan>, \u003Cspan class=\"hljs-variable constant_\">TRICKS\u003C\u002Fspan>, type \u003Cspan class=\"hljs-title class_\">JevvieView\u003C\u002Fspan>, type \u003Cspan class=\"hljs-title class_\">Mood\u003C\u002Fspan>, type \u003Cspan class=\"hljs-title class_\">Shape\u003C\u002Fspan>, type \u003Cspan class=\"hljs-title class_\">Trick\u003C\u002Fspan>, type \u003Cspan class=\"hljs-title class_\">Wear\u003C\u002Fspan> } \u003Cspan class=\"hljs-keyword\">from\u003C\u002Fspan> \u003Cspan class=\"hljs-string\">&#x27;@cw\u002Fjevvie\u002Fcharacter&#x27;\u003C\u002Fspan>\n\n\u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">WEARS\u003C\u002Fspan>: readonly \u003Cspan class=\"hljs-title class_\">Wear\u003C\u002Fspan>[] = [\u003Cspan class=\"hljs-string\">&#x27;none&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-string\">&#x27;clip&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-string\">&#x27;pencil&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-string\">&#x27;pin&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-string\">&#x27;flag&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-string\">&#x27;antennas&#x27;\u003C\u002Fspan>]\n\u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">NAMES\u003C\u002Fspan>: \u003Cspan class=\"hljs-title class_\">Partial\u003C\u002Fspan>&lt;\u003Cspan class=\"hljs-title class_\">Record\u003C\u002Fspan>&lt;\u003Cspan class=\"hljs-title class_\">Shape\u003C\u002Fspan>, string&gt;&gt; = { \u003Cspan class=\"hljs-attr\">bar\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;Bar (the _)&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">chamfer\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;Chamfered bar&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">capsule\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;Rounded bar&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">sticky\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;Sticky note&#x27;\u003C\u002Fspan> }\n\u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> \u003Cspan class=\"hljs-title function_\">title\u003C\u002Fspan> = (\u003Cspan class=\"hljs-params\">s: string\u003C\u002Fspan>) =&gt; s.\u003Cspan class=\"hljs-title function_\">charAt\u003C\u002Fspan>(\u003Cspan class=\"hljs-number\">0\u003C\u002Fspan>).\u003Cspan class=\"hljs-title function_\">toUpperCase\u003C\u002Fspan>() + s.\u003Cspan class=\"hljs-title function_\">slice\u003C\u002Fspan>(\u003Cspan class=\"hljs-number\">1\u003C\u002Fspan>)\n\u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> options = &lt;T \u003Cspan class=\"hljs-keyword\">extends\u003C\u002Fspan> string&gt;\u003Cspan class=\"hljs-function\">(\u003Cspan class=\"hljs-params\">list: readonly T[], name: (v: T) =&gt; string = title\u003C\u002Fspan>) =&gt;\u003C\u002Fspan> list.\u003Cspan class=\"hljs-title function_\">map\u003C\u002Fspan>(\u003Cspan class=\"hljs-function\">(\u003Cspan class=\"hljs-params\">value\u003C\u002Fspan>) =&gt;\u003C\u002Fspan> ({ value, \u003Cspan class=\"hljs-attr\">label\u003C\u002Fspan>: \u003Cspan class=\"hljs-title function_\">name\u003C\u002Fspan>(value) }))\n\n\u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> route = \u003Cspan class=\"hljs-title function_\">useRoute\u003C\u002Fspan>()\n\u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> router = \u003Cspan class=\"hljs-title function_\">useRouter\u003C\u002Fspan>()\n\u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> shape = ref&lt;\u003Cspan class=\"hljs-title class_\">Shape\u003C\u002Fspan>&gt;(\u003Cspan class=\"hljs-string\">&#x27;bar&#x27;\u003C\u002Fspan>)\n\u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> mood = ref&lt;\u003Cspan class=\"hljs-title class_\">Mood\u003C\u002Fspan>&gt;(\u003Cspan class=\"hljs-string\">&#x27;happy&#x27;\u003C\u002Fspan>)\n\u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> wear = ref&lt;\u003Cspan class=\"hljs-title class_\">Wear\u003C\u002Fspan>&gt;(\u003Cspan class=\"hljs-string\">&#x27;none&#x27;\u003C\u002Fspan>)\n\u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> valid = &lt;T \u003Cspan class=\"hljs-keyword\">extends\u003C\u002Fspan> string&gt;\u003Cspan class=\"hljs-function\">(\u003Cspan class=\"hljs-params\">q: unknown, list: readonly T[]\u003C\u002Fspan>) =&gt;\u003C\u002Fspan> (\u003Cspan class=\"hljs-keyword\">typeof\u003C\u002Fspan> q === \u003Cspan class=\"hljs-string\">&#x27;string&#x27;\u003C\u002Fspan> &amp;&amp; (list \u003Cspan class=\"hljs-keyword\">as\u003C\u002Fspan> readonly string[]).\u003Cspan class=\"hljs-title function_\">includes\u003C\u002Fspan>(q) ? (q \u003Cspan class=\"hljs-keyword\">as\u003C\u002Fspan> T) : \u003Cspan class=\"hljs-literal\">undefined\u003C\u002Fspan>)\n\u003Cspan class=\"hljs-comment\">\u002F\u002F follows the address: a prerendered page gets its query only after hydration\u003C\u002Fspan>\n\u003Cspan class=\"hljs-title function_\">watch\u003C\u002Fspan>(\u003Cspan class=\"hljs-function\">() =&gt;\u003C\u002Fspan> route.\u003Cspan class=\"hljs-property\">query\u003C\u002Fspan>, \u003Cspan class=\"hljs-function\">(\u003Cspan class=\"hljs-params\">q\u003C\u002Fspan>) =&gt;\u003C\u002Fspan> {\n  shape.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan> = \u003Cspan class=\"hljs-title function_\">valid\u003C\u002Fspan>(q.\u003Cspan class=\"hljs-property\">body\u003C\u002Fspan>, \u003Cspan class=\"hljs-variable constant_\">SHAPES\u003C\u002Fspan>) ?? shape.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan>\n  mood.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan> = \u003Cspan class=\"hljs-title function_\">valid\u003C\u002Fspan>(q.\u003Cspan class=\"hljs-property\">mood\u003C\u002Fspan>, \u003Cspan class=\"hljs-variable constant_\">MOODS\u003C\u002Fspan>) ?? mood.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan>\n  wear.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan> = \u003Cspan class=\"hljs-title function_\">valid\u003C\u002Fspan>(q.\u003Cspan class=\"hljs-property\">wear\u003C\u002Fspan>, \u003Cspan class=\"hljs-variable constant_\">WEARS\u003C\u002Fspan>) ?? wear.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan>\n}, { \u003Cspan class=\"hljs-attr\">immediate\u003C\u002Fspan>: \u003Cspan class=\"hljs-literal\">true\u003C\u002Fspan> })\n\u003Cspan class=\"hljs-title function_\">watch\u003C\u002Fspan>([shape, mood, wear], \u003Cspan class=\"hljs-function\">(\u003Cspan class=\"hljs-params\">[body, m, w]\u003C\u002Fspan>) =&gt;\u003C\u002Fspan> {\n  \u003Cspan class=\"hljs-keyword\">void\u003C\u002Fspan> router.\u003Cspan class=\"hljs-title function_\">replace\u003C\u002Fspan>({ \u003Cspan class=\"hljs-attr\">query\u003C\u002Fspan>: { ...route.\u003Cspan class=\"hljs-property\">query\u003C\u002Fspan>, body, \u003Cspan class=\"hljs-attr\">mood\u003C\u002Fspan>: m, \u003Cspan class=\"hljs-attr\">wear\u003C\u002Fspan>: w === \u003Cspan class=\"hljs-string\">&#x27;none&#x27;\u003C\u002Fspan> ? \u003Cspan class=\"hljs-literal\">undefined\u003C\u002Fspan> : w } })\n})\n\n\u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> canvas = useTemplateRef&lt;\u003Cspan class=\"hljs-title class_\">HTMLCanvasElement\u003C\u002Fspan>&gt;(\u003Cspan class=\"hljs-string\">&#x27;canvas&#x27;\u003C\u002Fspan>)\n\u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> width = \u003Cspan class=\"hljs-title function_\">ref\u003C\u002Fspan>(\u003Cspan class=\"hljs-number\">64\u003C\u002Fspan>)\n\u003Cspan class=\"hljs-keyword\">let\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">view\u003C\u002Fspan>: \u003Cspan class=\"hljs-title class_\">JevvieView\u003C\u002Fspan> | \u003Cspan class=\"hljs-literal\">undefined\u003C\u002Fspan>\n\u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> reduced = \u003Cspan class=\"hljs-title function_\">useReducedMotion\u003C\u002Fspan>()\n\u003Cspan class=\"hljs-keyword\">async\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">function\u003C\u002Fspan> \u003Cspan class=\"hljs-title function_\">mount\u003C\u002Fspan>(\u003Cspan class=\"hljs-params\">\u003C\u002Fspan>) {\n  view?.\u003Cspan class=\"hljs-title function_\">dispose\u003C\u002Fspan>()\n  \u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> { mountCharacter } = \u003Cspan class=\"hljs-keyword\">await\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">import\u003C\u002Fspan>(\u003Cspan class=\"hljs-string\">&#x27;@cw\u002Fjevvie\u002Fcharacter&#x27;\u003C\u002Fspan>)\n  \u003Cspan class=\"hljs-keyword\">if\u003C\u002Fspan> (!canvas.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan>) \u003Cspan class=\"hljs-keyword\">return\u003C\u002Fspan>\n  view = \u003Cspan class=\"hljs-keyword\">await\u003C\u002Fspan> \u003Cspan class=\"hljs-title function_\">mountCharacter\u003C\u002Fspan>(canvas.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan>, { \u003Cspan class=\"hljs-attr\">colors\u003C\u002Fspan>: jevvieColors, \u003Cspan class=\"hljs-attr\">shape\u003C\u002Fspan>: shape.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">wear\u003C\u002Fspan>: wear.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan>, reduced })\n  width.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan> = canvas.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan>.\u003Cspan class=\"hljs-property\">width\u003C\u002Fspan>\n  view.\u003Cspan class=\"hljs-title function_\">mood\u003C\u002Fspan>(mood.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan>)\n}\n\u003Cspan class=\"hljs-title function_\">onMounted\u003C\u002Fspan>(mount)\n\u003Cspan class=\"hljs-title function_\">watch\u003C\u002Fspan>([shape, wear], mount)\n\u003Cspan class=\"hljs-title function_\">watch\u003C\u002Fspan>(mood, \u003Cspan class=\"hljs-function\">(\u003Cspan class=\"hljs-params\">m\u003C\u002Fspan>) =&gt;\u003C\u002Fspan> view?.\u003Cspan class=\"hljs-title function_\">mood\u003C\u002Fspan>(m))\n\u003Cspan class=\"hljs-title function_\">onBeforeUnmount\u003C\u002Fspan>(\u003Cspan class=\"hljs-function\">() =&gt;\u003C\u002Fspan> view?.\u003Cspan class=\"hljs-title function_\">dispose\u003C\u002Fspan>())\n\n\u003Cspan class=\"hljs-keyword\">function\u003C\u002Fspan> \u003Cspan class=\"hljs-title function_\">trick\u003C\u002Fspan>(\u003Cspan class=\"hljs-params\">t: Trick\u003C\u002Fspan>) { view?.\u003Cspan class=\"hljs-title function_\">trick\u003C\u002Fspan>(t) }\n\u003Cspan class=\"hljs-keyword\">function\u003C\u002Fspan> any&lt;T&gt;(\u003Cspan class=\"hljs-attr\">list\u003C\u002Fspan>: readonly T[]): T { \u003Cspan class=\"hljs-keyword\">return\u003C\u002Fspan> list[\u003Cspan class=\"hljs-title class_\">Math\u003C\u002Fspan>.\u003Cspan class=\"hljs-title function_\">floor\u003C\u002Fspan>(\u003Cspan class=\"hljs-title class_\">Math\u003C\u002Fspan>.\u003Cspan class=\"hljs-title function_\">random\u003C\u002Fspan>() * list.\u003Cspan class=\"hljs-property\">length\u003C\u002Fspan>)]! }\n\u003Cspan class=\"hljs-keyword\">function\u003C\u002Fspan> \u003Cspan class=\"hljs-title function_\">shuffle\u003C\u002Fspan>(\u003Cspan class=\"hljs-params\">\u003C\u002Fspan>) {\n  shape.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan> = \u003Cspan class=\"hljs-title function_\">any\u003C\u002Fspan>(\u003Cspan class=\"hljs-variable constant_\">SHAPES\u003C\u002Fspan>); mood.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan> = \u003Cspan class=\"hljs-title function_\">any\u003C\u002Fspan>(\u003Cspan class=\"hljs-variable constant_\">MOODS\u003C\u002Fspan>); wear.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan> = \u003Cspan class=\"hljs-title class_\">Math\u003C\u002Fspan>.\u003Cspan class=\"hljs-title function_\">random\u003C\u002Fspan>() &lt; \u003Cspan class=\"hljs-number\">0.3\u003C\u002Fspan> ? \u003Cspan class=\"hljs-title function_\">any\u003C\u002Fspan>(\u003Cspan class=\"hljs-variable constant_\">WEARS\u003C\u002Fspan>) : \u003Cspan class=\"hljs-string\">&#x27;none&#x27;\u003C\u002Fspan>\n}\n\n\u003Cspan class=\"hljs-title function_\">useSiteTool\u003C\u002Fspan>(\u003Cspan class=\"hljs-function\">() =&gt;\u003C\u002Fspan> ({\n  \u003Cspan class=\"hljs-attr\">name\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;jevvie_body&#x27;\u003C\u002Fspan>,\n  \u003Cspan class=\"hljs-attr\">description\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;Put Jevvie in the studio in another body&#x27;\u003C\u002Fspan>,\n  \u003Cspan class=\"hljs-attr\">arg\u003C\u002Fspan>: { \u003Cspan class=\"hljs-attr\">name\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;body&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">description\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;Which body&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">values\u003C\u002Fspan>: \u003Cspan class=\"hljs-title function_\">options\u003C\u002Fspan>(\u003Cspan class=\"hljs-variable constant_\">SHAPES\u003C\u002Fspan>, \u003Cspan class=\"hljs-title class_\">String\u003C\u002Fspan>) },\n  \u003Cspan class=\"hljs-attr\">doing\u003C\u002Fspan>: \u003Cspan class=\"hljs-function\">(\u003Cspan class=\"hljs-params\">label\u003C\u002Fspan>) =&gt;\u003C\u002Fspan> \u003Cspan class=\"hljs-string\">`turning into a \u003Cspan class=\"hljs-subst\">${label}\u003C\u002Fspan>`\u003C\u002Fspan>,\n  \u003Cspan class=\"hljs-attr\">run\u003C\u002Fspan>: \u003Cspan class=\"hljs-function\">(\u003Cspan class=\"hljs-params\">value\u003C\u002Fspan>) =&gt;\u003C\u002Fspan> { shape.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan> = value \u003Cspan class=\"hljs-keyword\">as\u003C\u002Fspan> \u003Cspan class=\"hljs-title class_\">Shape\u003C\u002Fspan> },\n}))\n\u003Cspan class=\"hljs-title function_\">useSiteTool\u003C\u002Fspan>(\u003Cspan class=\"hljs-function\">() =&gt;\u003C\u002Fspan> ({\n  \u003Cspan class=\"hljs-attr\">name\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;jevvie_mood&#x27;\u003C\u002Fspan>,\n  \u003Cspan class=\"hljs-attr\">description\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;Set how Jevvie in the studio feels&#x27;\u003C\u002Fspan>,\n  \u003Cspan class=\"hljs-attr\">arg\u003C\u002Fspan>: { \u003Cspan class=\"hljs-attr\">name\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;mood&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">description\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;Which mood&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">values\u003C\u002Fspan>: \u003Cspan class=\"hljs-title function_\">options\u003C\u002Fspan>(\u003Cspan class=\"hljs-variable constant_\">MOODS\u003C\u002Fspan>, \u003Cspan class=\"hljs-title class_\">String\u003C\u002Fspan>) },\n  \u003Cspan class=\"hljs-attr\">doing\u003C\u002Fspan>: \u003Cspan class=\"hljs-function\">(\u003Cspan class=\"hljs-params\">label\u003C\u002Fspan>) =&gt;\u003C\u002Fspan> \u003Cspan class=\"hljs-string\">`feeling \u003Cspan class=\"hljs-subst\">${label}\u003C\u002Fspan>`\u003C\u002Fspan>,\n  \u003Cspan class=\"hljs-attr\">run\u003C\u002Fspan>: \u003Cspan class=\"hljs-function\">(\u003Cspan class=\"hljs-params\">value\u003C\u002Fspan>) =&gt;\u003C\u002Fspan> { mood.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan> = value \u003Cspan class=\"hljs-keyword\">as\u003C\u002Fspan> \u003Cspan class=\"hljs-title class_\">Mood\u003C\u002Fspan> },\n}))\n\u003Cspan class=\"hljs-title function_\">useSiteTool\u003C\u002Fspan>(\u003Cspan class=\"hljs-function\">() =&gt;\u003C\u002Fspan> ({\n  \u003Cspan class=\"hljs-attr\">name\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;jevvie_trick&#x27;\u003C\u002Fspan>,\n  \u003Cspan class=\"hljs-attr\">description\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;Make Jevvie in the studio do a trick&#x27;\u003C\u002Fspan>,\n  \u003Cspan class=\"hljs-attr\">arg\u003C\u002Fspan>: { \u003Cspan class=\"hljs-attr\">name\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;trick&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">description\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;Which trick&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">values\u003C\u002Fspan>: \u003Cspan class=\"hljs-title function_\">options\u003C\u002Fspan>(\u003Cspan class=\"hljs-variable constant_\">TRICKS\u003C\u002Fspan>, \u003Cspan class=\"hljs-title class_\">String\u003C\u002Fspan>) },\n  \u003Cspan class=\"hljs-attr\">doing\u003C\u002Fspan>: \u003Cspan class=\"hljs-function\">(\u003Cspan class=\"hljs-params\">label\u003C\u002Fspan>) =&gt;\u003C\u002Fspan> \u003Cspan class=\"hljs-string\">`doing a \u003Cspan class=\"hljs-subst\">${label}\u003C\u002Fspan>`\u003C\u002Fspan>,\n  \u003Cspan class=\"hljs-attr\">run\u003C\u002Fspan>: \u003Cspan class=\"hljs-function\">(\u003Cspan class=\"hljs-params\">value\u003C\u002Fspan>) =&gt;\u003C\u002Fspan> \u003Cspan class=\"hljs-title function_\">trick\u003C\u002Fspan>(value \u003Cspan class=\"hljs-keyword\">as\u003C\u002Fspan> \u003Cspan class=\"hljs-title class_\">Trick\u003C\u002Fspan>),\n  \u003Cspan class=\"hljs-attr\">readOnly\u003C\u002Fspan>: \u003Cspan class=\"hljs-literal\">true\u003C\u002Fspan>,\n}))\n\n\u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> { copy, copied } = \u003Cspan class=\"hljs-title function_\">useClipboard\u003C\u002Fspan>({ \u003Cspan class=\"hljs-attr\">copiedDuring\u003C\u002Fspan>: \u003Cspan class=\"hljs-number\">1500\u003C\u002Fspan> })\n\u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> \u003Cspan class=\"hljs-title function_\">copyLink\u003C\u002Fspan> = (\u003Cspan class=\"hljs-params\">\u003C\u002Fspan>) =&gt; \u003Cspan class=\"hljs-title function_\">copy\u003C\u002Fspan>(location.\u003Cspan class=\"hljs-property\">href\u003C\u002Fspan>)\n\u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> saving = \u003Cspan class=\"hljs-title function_\">ref\u003C\u002Fspan>(\u003Cspan class=\"hljs-literal\">false\u003C\u002Fspan>)\n\u003Cspan class=\"hljs-keyword\">async\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">function\u003C\u002Fspan> \u003Cspan class=\"hljs-title function_\">save\u003C\u002Fspan>(\u003Cspan class=\"hljs-params\">\u003C\u002Fspan>) {\n  \u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> src = canvas.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan>\n  \u003Cspan class=\"hljs-keyword\">if\u003C\u002Fspan> (!src || saving.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan>) \u003Cspan class=\"hljs-keyword\">return\u003C\u002Fspan>\n  saving.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan> = \u003Cspan class=\"hljs-literal\">true\u003C\u002Fspan>\n  \u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> { data, \u003Cspan class=\"hljs-attr\">width\u003C\u002Fspan>: w, \u003Cspan class=\"hljs-attr\">height\u003C\u002Fspan>: h } = src.\u003Cspan class=\"hljs-title function_\">getContext\u003C\u002Fspan>(\u003Cspan class=\"hljs-string\">&#x27;2d&#x27;\u003C\u002Fspan>)!.\u003Cspan class=\"hljs-title function_\">getImageData\u003C\u002Fspan>(\u003Cspan class=\"hljs-number\">0\u003C\u002Fspan>, \u003Cspan class=\"hljs-number\">0\u003C\u002Fspan>, src.\u003Cspan class=\"hljs-property\">width\u003C\u002Fspan>, src.\u003Cspan class=\"hljs-property\">height\u003C\u002Fspan>)\n  \u003Cspan class=\"hljs-keyword\">let\u003C\u002Fspan> [x0, y0, x1, y1] = [w, h, \u003Cspan class=\"hljs-number\">0\u003C\u002Fspan>, \u003Cspan class=\"hljs-number\">0\u003C\u002Fspan>]\n  \u003Cspan class=\"hljs-keyword\">for\u003C\u002Fspan> (\u003Cspan class=\"hljs-keyword\">let\u003C\u002Fspan> y = \u003Cspan class=\"hljs-number\">0\u003C\u002Fspan>; y &lt; h; y++) \u003Cspan class=\"hljs-keyword\">for\u003C\u002Fspan> (\u003Cspan class=\"hljs-keyword\">let\u003C\u002Fspan> x = \u003Cspan class=\"hljs-number\">0\u003C\u002Fspan>; x &lt; w; x++) \u003Cspan class=\"hljs-keyword\">if\u003C\u002Fspan> (data[(y * w + x) * \u003Cspan class=\"hljs-number\">4\u003C\u002Fspan> + \u003Cspan class=\"hljs-number\">3\u003C\u002Fspan>]! &gt; \u003Cspan class=\"hljs-number\">8\u003C\u002Fspan>) { x0 = \u003Cspan class=\"hljs-title class_\">Math\u003C\u002Fspan>.\u003Cspan class=\"hljs-title function_\">min\u003C\u002Fspan>(x0, x); y0 = \u003Cspan class=\"hljs-title class_\">Math\u003C\u002Fspan>.\u003Cspan class=\"hljs-title function_\">min\u003C\u002Fspan>(y0, y); x1 = \u003Cspan class=\"hljs-title class_\">Math\u003C\u002Fspan>.\u003Cspan class=\"hljs-title function_\">max\u003C\u002Fspan>(x1, x); y1 = \u003Cspan class=\"hljs-title class_\">Math\u003C\u002Fspan>.\u003Cspan class=\"hljs-title function_\">max\u003C\u002Fspan>(y1, y) }\n  \u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> \u003Cspan class=\"hljs-variable constant_\">SIZE\u003C\u002Fspan> = \u003Cspan class=\"hljs-number\">512\u003C\u002Fspan>, \u003Cspan class=\"hljs-variable constant_\">LINE\u003C\u002Fspan> = \u003Cspan class=\"hljs-number\">8\u003C\u002Fspan>, bw = x1 - x0 + \u003Cspan class=\"hljs-number\">1\u003C\u002Fspan>, bh = y1 - y0 + \u003Cspan class=\"hljs-number\">1\u003C\u002Fspan>\n  \u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> f = \u003Cspan class=\"hljs-title class_\">Math\u003C\u002Fspan>.\u003Cspan class=\"hljs-title function_\">max\u003C\u002Fspan>(\u003Cspan class=\"hljs-number\">1\u003C\u002Fspan>, \u003Cspan class=\"hljs-title class_\">Math\u003C\u002Fspan>.\u003Cspan class=\"hljs-title function_\">floor\u003C\u002Fspan>((\u003Cspan class=\"hljs-variable constant_\">SIZE\u003C\u002Fspan> - \u003Cspan class=\"hljs-number\">2\u003C\u002Fspan> * (\u003Cspan class=\"hljs-number\">16\u003C\u002Fspan> + \u003Cspan class=\"hljs-variable constant_\">LINE\u003C\u002Fspan>)) \u002F \u003Cspan class=\"hljs-title class_\">Math\u003C\u002Fspan>.\u003Cspan class=\"hljs-title function_\">max\u003C\u002Fspan>(bw, bh)))\n  \u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> \u003Cspan class=\"hljs-title function_\">layer\u003C\u002Fspan> = (\u003Cspan class=\"hljs-params\">fill?: string\u003C\u002Fspan>) =&gt; {\n    \u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> c = \u003Cspan class=\"hljs-title class_\">Object\u003C\u002Fspan>.\u003Cspan class=\"hljs-title function_\">assign\u003C\u002Fspan>(\u003Cspan class=\"hljs-variable language_\">document\u003C\u002Fspan>.\u003Cspan class=\"hljs-title function_\">createElement\u003C\u002Fspan>(\u003Cspan class=\"hljs-string\">&#x27;canvas&#x27;\u003C\u002Fspan>), { \u003Cspan class=\"hljs-attr\">width\u003C\u002Fspan>: bw * f, \u003Cspan class=\"hljs-attr\">height\u003C\u002Fspan>: bh * f }), ctx = c.\u003Cspan class=\"hljs-title function_\">getContext\u003C\u002Fspan>(\u003Cspan class=\"hljs-string\">&#x27;2d&#x27;\u003C\u002Fspan>)!\n    ctx.\u003Cspan class=\"hljs-property\">imageSmoothingEnabled\u003C\u002Fspan> = \u003Cspan class=\"hljs-literal\">false\u003C\u002Fspan>\n    ctx.\u003Cspan class=\"hljs-title function_\">drawImage\u003C\u002Fspan>(src, x0, y0, bw, bh, \u003Cspan class=\"hljs-number\">0\u003C\u002Fspan>, \u003Cspan class=\"hljs-number\">0\u003C\u002Fspan>, bw * f, bh * f)\n    \u003Cspan class=\"hljs-keyword\">if\u003C\u002Fspan> (fill) { ctx.\u003Cspan class=\"hljs-property\">globalCompositeOperation\u003C\u002Fspan> = \u003Cspan class=\"hljs-string\">&#x27;source-in&#x27;\u003C\u002Fspan>; ctx.\u003Cspan class=\"hljs-property\">fillStyle\u003C\u002Fspan> = fill; ctx.\u003Cspan class=\"hljs-title function_\">fillRect\u003C\u002Fspan>(\u003Cspan class=\"hljs-number\">0\u003C\u002Fspan>, \u003Cspan class=\"hljs-number\">0\u003C\u002Fspan>, c.\u003Cspan class=\"hljs-property\">width\u003C\u002Fspan>, c.\u003Cspan class=\"hljs-property\">height\u003C\u002Fspan>) }\n    \u003Cspan class=\"hljs-keyword\">return\u003C\u002Fspan> c\n  }\n  \u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> out = \u003Cspan class=\"hljs-title class_\">Object\u003C\u002Fspan>.\u003Cspan class=\"hljs-title function_\">assign\u003C\u002Fspan>(\u003Cspan class=\"hljs-variable language_\">document\u003C\u002Fspan>.\u003Cspan class=\"hljs-title function_\">createElement\u003C\u002Fspan>(\u003Cspan class=\"hljs-string\">&#x27;canvas&#x27;\u003C\u002Fspan>), { \u003Cspan class=\"hljs-attr\">width\u003C\u002Fspan>: \u003Cspan class=\"hljs-variable constant_\">SIZE\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">height\u003C\u002Fspan>: \u003Cspan class=\"hljs-variable constant_\">SIZE\u003C\u002Fspan> }), ctx = out.\u003Cspan class=\"hljs-title function_\">getContext\u003C\u002Fspan>(\u003Cspan class=\"hljs-string\">&#x27;2d&#x27;\u003C\u002Fspan>)!\n  \u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> [left, top] = [(\u003Cspan class=\"hljs-variable constant_\">SIZE\u003C\u002Fspan> - bw * f) \u002F \u003Cspan class=\"hljs-number\">2\u003C\u002Fspan>, (\u003Cspan class=\"hljs-variable constant_\">SIZE\u003C\u002Fspan> - bh * f) \u002F \u003Cspan class=\"hljs-number\">2\u003C\u002Fspan>].\u003Cspan class=\"hljs-title function_\">map\u003C\u002Fspan>(\u003Cspan class=\"hljs-title class_\">Math\u003C\u002Fspan>.\u003Cspan class=\"hljs-property\">round\u003C\u002Fspan>) \u003Cspan class=\"hljs-keyword\">as\u003C\u002Fspan> [number, number]\n  \u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> white = \u003Cspan class=\"hljs-title function_\">layer\u003C\u002Fspan>(\u003Cspan class=\"hljs-string\">&#x27;#fff&#x27;\u003C\u002Fspan>)\n  \u003Cspan class=\"hljs-keyword\">for\u003C\u002Fspan> (\u003Cspan class=\"hljs-keyword\">let\u003C\u002Fspan> dy = -\u003Cspan class=\"hljs-variable constant_\">LINE\u003C\u002Fspan>; dy &lt;= \u003Cspan class=\"hljs-variable constant_\">LINE\u003C\u002Fspan>; dy++) \u003Cspan class=\"hljs-keyword\">for\u003C\u002Fspan> (\u003Cspan class=\"hljs-keyword\">let\u003C\u002Fspan> dx = -\u003Cspan class=\"hljs-variable constant_\">LINE\u003C\u002Fspan>; dx &lt;= \u003Cspan class=\"hljs-variable constant_\">LINE\u003C\u002Fspan>; dx++) \u003Cspan class=\"hljs-keyword\">if\u003C\u002Fspan> (dx * dx + dy * dy &lt;= \u003Cspan class=\"hljs-variable constant_\">LINE\u003C\u002Fspan> * \u003Cspan class=\"hljs-variable constant_\">LINE\u003C\u002Fspan>) ctx.\u003Cspan class=\"hljs-title function_\">drawImage\u003C\u002Fspan>(white, left + dx, top + dy)\n  ctx.\u003Cspan class=\"hljs-title function_\">drawImage\u003C\u002Fspan>(\u003Cspan class=\"hljs-title function_\">layer\u003C\u002Fspan>(), left, top)\n  \u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> blob = \u003Cspan class=\"hljs-keyword\">await\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">new\u003C\u002Fspan> \u003Cspan class=\"hljs-title class_\">Promise\u003C\u002Fspan>&lt;\u003Cspan class=\"hljs-title class_\">Blob\u003C\u002Fspan> | \u003Cspan class=\"hljs-literal\">null\u003C\u002Fspan>&gt;(\u003Cspan class=\"hljs-function\">(\u003Cspan class=\"hljs-params\">r\u003C\u002Fspan>) =&gt;\u003C\u002Fspan> out.\u003Cspan class=\"hljs-title function_\">toBlob\u003C\u002Fspan>(r, \u003Cspan class=\"hljs-string\">&#x27;image\u002Fpng&#x27;\u003C\u002Fspan>))\n  saving.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan> = \u003Cspan class=\"hljs-literal\">false\u003C\u002Fspan>\n  \u003Cspan class=\"hljs-keyword\">if\u003C\u002Fspan> (!blob) \u003Cspan class=\"hljs-keyword\">return\u003C\u002Fspan>\n  \u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> a = \u003Cspan class=\"hljs-title class_\">Object\u003C\u002Fspan>.\u003Cspan class=\"hljs-title function_\">assign\u003C\u002Fspan>(\u003Cspan class=\"hljs-variable language_\">document\u003C\u002Fspan>.\u003Cspan class=\"hljs-title function_\">createElement\u003C\u002Fspan>(\u003Cspan class=\"hljs-string\">&#x27;a&#x27;\u003C\u002Fspan>), { \u003Cspan class=\"hljs-attr\">href\u003C\u002Fspan>: \u003Cspan class=\"hljs-variable constant_\">URL\u003C\u002Fspan>.\u003Cspan class=\"hljs-title function_\">createObjectURL\u003C\u002Fspan>(blob), \u003Cspan class=\"hljs-attr\">download\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">`jevvie-\u003Cspan class=\"hljs-subst\">${shape.value}\u003C\u002Fspan>-\u003Cspan class=\"hljs-subst\">${mood.value}\u003C\u002Fspan>.png`\u003C\u002Fspan> })\n  a.\u003Cspan class=\"hljs-title function_\">click\u003C\u002Fspan>()\n  \u003Cspan class=\"hljs-variable constant_\">URL\u003C\u002Fspan>.\u003Cspan class=\"hljs-title function_\">revokeObjectURL\u003C\u002Fspan>(a.\u003Cspan class=\"hljs-property\">href\u003C\u002Fspan>)\n}\n\u003C\u002Fspan>\u003Cspan class=\"hljs-tag\">&lt;\u002F\u003Cspan class=\"hljs-name\">script\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n\n\u003Cspan class=\"hljs-tag\">&lt;\u003Cspan class=\"hljs-name\">template\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n  \u003Cspan class=\"hljs-tag\">&lt;\u003Cspan class=\"hljs-name\">Win\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">title\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;CW\u002F_ · STUDIO&quot;\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">as\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;section&quot;\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">label\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;Jevvie’s studio&quot;\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">class\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;studio&quot;\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n    \u003Cspan class=\"hljs-tag\">&lt;\u003Cspan class=\"hljs-name\">template\u003C\u002Fspan> #\u003Cspan class=\"hljs-attr\">meta\u003C\u002Fspan>&gt;\u003C\u002Fspan>{{ title(shape) }} · {{ title(mood) }}\u003Cspan class=\"hljs-tag\">&lt;\u002F\u003Cspan class=\"hljs-name\">template\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n    \u003Cspan class=\"hljs-tag\">&lt;\u003Cspan class=\"hljs-name\">div\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">class\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;studio__grid&quot;\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n      \u003Cspan class=\"hljs-tag\">&lt;\u003Cspan class=\"hljs-name\">div\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">class\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;studio__view&quot;\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n        \u003Cspan class=\"hljs-tag\">&lt;\u003Cspan class=\"hljs-name\">canvas\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">ref\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;canvas&quot;\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">class\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;studio__canvas&quot;\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">:style\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;{ &#x27;--w&#x27;: `${width}px` }&quot;\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">role\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;img&quot;\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">:aria-label\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;`Jevvie as ${shape}, ${mood}`&quot;\u003C\u002Fspan> \u002F&gt;\u003C\u002Fspan>\n      \u003Cspan class=\"hljs-tag\">&lt;\u002F\u003Cspan class=\"hljs-name\">div\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n      \u003Cspan class=\"hljs-tag\">&lt;\u003Cspan class=\"hljs-name\">div\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">class\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;studio__controls mono-label&quot;\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n        \u003Cspan class=\"hljs-tag\">&lt;\u003Cspan class=\"hljs-name\">div\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">class\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;studio__row&quot;\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n          \u003Cspan class=\"hljs-tag\">&lt;\u003Cspan class=\"hljs-name\">span\u003C\u002Fspan>&gt;\u003C\u002Fspan>Body\u003Cspan class=\"hljs-tag\">&lt;\u002F\u003Cspan class=\"hljs-name\">span\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n          \u003Cspan class=\"hljs-tag\">&lt;\u003Cspan class=\"hljs-name\">SelectBtn\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">v-model\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;shape&quot;\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">:options\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;options(SHAPES, (s) =&gt; NAMES[s] ?? title(s))&quot;\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">label\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;Body&quot;\u003C\u002Fspan> \u002F&gt;\u003C\u002Fspan>\n        \u003Cspan class=\"hljs-tag\">&lt;\u002F\u003Cspan class=\"hljs-name\">div\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n        \u003Cspan class=\"hljs-tag\">&lt;\u003Cspan class=\"hljs-name\">div\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">class\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;studio__row&quot;\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n          \u003Cspan class=\"hljs-tag\">&lt;\u003Cspan class=\"hljs-name\">span\u003C\u002Fspan>&gt;\u003C\u002Fspan>Wear\u003Cspan class=\"hljs-tag\">&lt;\u002F\u003Cspan class=\"hljs-name\">span\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n          \u003Cspan class=\"hljs-tag\">&lt;\u003Cspan class=\"hljs-name\">SelectBtn\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">v-model\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;wear&quot;\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">:options\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;options(WEARS)&quot;\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">label\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;Wear&quot;\u003C\u002Fspan> \u002F&gt;\u003C\u002Fspan>\n        \u003Cspan class=\"hljs-tag\">&lt;\u002F\u003Cspan class=\"hljs-name\">div\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n        \u003Cspan class=\"hljs-tag\">&lt;\u003Cspan class=\"hljs-name\">div\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">class\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;studio__row studio__row--top&quot;\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n          \u003Cspan class=\"hljs-tag\">&lt;\u003Cspan class=\"hljs-name\">span\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">id\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;studio-mood&quot;\u003C\u002Fspan>&gt;\u003C\u002Fspan>Mood\u003Cspan class=\"hljs-tag\">&lt;\u002F\u003Cspan class=\"hljs-name\">span\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n          \u003Cspan class=\"hljs-tag\">&lt;\u003Cspan class=\"hljs-name\">div\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">class\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;studio__moods&quot;\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">role\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;group&quot;\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">aria-labelledby\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;studio-mood&quot;\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n            \u003Cspan class=\"hljs-tag\">&lt;\u003Cspan class=\"hljs-name\">button\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">v-for\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;m in MOODS&quot;\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">:key\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;m&quot;\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">type\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;button&quot;\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">class\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;bare read-1 hit&quot;\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">:aria-pressed\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;mood === m&quot;\u003C\u002Fspan> @\u003Cspan class=\"hljs-attr\">click\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;mood = m&quot;\u003C\u002Fspan>&gt;\u003C\u002Fspan>{{ m }}\u003Cspan class=\"hljs-tag\">&lt;\u002F\u003Cspan class=\"hljs-name\">button\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n          \u003Cspan class=\"hljs-tag\">&lt;\u002F\u003Cspan class=\"hljs-name\">div\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n        \u003Cspan class=\"hljs-tag\">&lt;\u002F\u003Cspan class=\"hljs-name\">div\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n        \u003Cspan class=\"hljs-tag\">&lt;\u003Cspan class=\"hljs-name\">div\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">class\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;studio__row&quot;\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n          \u003Cspan class=\"hljs-tag\">&lt;\u003Cspan class=\"hljs-name\">span\u003C\u002Fspan>&gt;\u003C\u002Fspan>Trick\u003Cspan class=\"hljs-tag\">&lt;\u002F\u003Cspan class=\"hljs-name\">span\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n          \u003Cspan class=\"hljs-tag\">&lt;\u003Cspan class=\"hljs-name\">span\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">class\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;btn-group&quot;\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">role\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;group&quot;\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">aria-label\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;Trick&quot;\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n            \u003Cspan class=\"hljs-tag\">&lt;\u003Cspan class=\"hljs-name\">Btn\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">v-for\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;t in TRICKS&quot;\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">:key\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;t&quot;\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">variant\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;ghost&quot;\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">size\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;sm&quot;\u003C\u002Fspan> @\u003Cspan class=\"hljs-attr\">click\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;trick(t)&quot;\u003C\u002Fspan>&gt;\u003C\u002Fspan>{{ t }}\u003Cspan class=\"hljs-tag\">&lt;\u002F\u003Cspan class=\"hljs-name\">Btn\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n          \u003Cspan class=\"hljs-tag\">&lt;\u002F\u003Cspan class=\"hljs-name\">span\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n        \u003Cspan class=\"hljs-tag\">&lt;\u002F\u003Cspan class=\"hljs-name\">div\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n        \u003Cspan class=\"hljs-tag\">&lt;\u003Cspan class=\"hljs-name\">div\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">class\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;studio__actions&quot;\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n          \u003Cspan class=\"hljs-tag\">&lt;\u003Cspan class=\"hljs-name\">Btn\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">variant\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;amber&quot;\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">size\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;md&quot;\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">:disabled\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;saving&quot;\u003C\u002Fspan> @\u003Cspan class=\"hljs-attr\">click\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;save&quot;\u003C\u002Fspan>&gt;\u003C\u002Fspan>Save sticker\u003Cspan class=\"hljs-tag\">&lt;\u002F\u003Cspan class=\"hljs-name\">Btn\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n          \u003Cspan class=\"hljs-tag\">&lt;\u003Cspan class=\"hljs-name\">Btn\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">variant\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;ghost&quot;\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">size\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;md&quot;\u003C\u002Fspan> @\u003Cspan class=\"hljs-attr\">click\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;shuffle&quot;\u003C\u002Fspan>&gt;\u003C\u002Fspan>Shuffle ▚\u003Cspan class=\"hljs-tag\">&lt;\u002F\u003Cspan class=\"hljs-name\">Btn\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n          \u003Cspan class=\"hljs-tag\">&lt;\u003Cspan class=\"hljs-name\">Btn\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">variant\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;ghost&quot;\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">size\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;md&quot;\u003C\u002Fspan> @\u003Cspan class=\"hljs-attr\">click\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;copyLink&quot;\u003C\u002Fspan>&gt;\u003C\u002Fspan>{{ copied ? &#x27;Copied&#x27; : &#x27;Copy link&#x27; }}\u003Cspan class=\"hljs-tag\">&lt;\u002F\u003Cspan class=\"hljs-name\">Btn\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n        \u003Cspan class=\"hljs-tag\">&lt;\u002F\u003Cspan class=\"hljs-name\">div\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n        \u003Cspan class=\"hljs-tag\">&lt;\u003Cspan class=\"hljs-name\">p\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">class\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;studio__note&quot;\u003C\u002Fspan>&gt;\u003C\u002Fspan>A 512 × 512 PNG, cut out and outlined, for a WhatsApp or Telegram sticker pack.\u003Cspan class=\"hljs-tag\">&lt;\u002F\u003Cspan class=\"hljs-name\">p\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n      \u003Cspan class=\"hljs-tag\">&lt;\u002F\u003Cspan class=\"hljs-name\">div\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n    \u003Cspan class=\"hljs-tag\">&lt;\u002F\u003Cspan class=\"hljs-name\">div\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n  \u003Cspan class=\"hljs-tag\">&lt;\u002F\u003Cspan class=\"hljs-name\">Win\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n\u003Cspan class=\"hljs-tag\">&lt;\u002F\u003Cspan class=\"hljs-name\">template\u003C\u002Fspan>&gt;\u003C\u002Fspan>",{"path":212,"lines":213,"code":214,"html":215},"app\u002Fcomponents\u002Fonebit\u002FConfidence.vue",26,"\u003Cscript setup lang=\"ts\">\nimport { pickReadout, type JevPick } from '@cw\u002Fjevvie'\n\ndefineProps\u003C{ prompt: string }>()\nconst THRESHOLD = 0.95\nconst pick = useJevPick()\nconst picks = useJevPicks()\nconst readout = useTemplateRef\u003CHTMLElement>('readout')\nconst acts = (p: JevPick) => p.p >= THRESHOLD\nconst line = computed(() => pick.value && pickReadout(pick.value, 'this tab'))\nwatch(pick, () => { if (readout.value && line.value) glitchOnce(readout.value, line.value) }, { flush: 'post' })\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003Cdiv class=\"conf mono-label punch-box\">\n    \u003Cp>{{ prompt }}\u003C\u002Fp>\n    \u003Cp v-if=\"line\">\u003Cspan ref=\"readout\" aria-hidden=\"true\">{{ line }}\u003C\u002Fspan>\u003C\u002Fp>\n    \u003Cp v-else>No pick yet in this tab\u003C\u002Fp>\n    \u003Cspan class=\"visually-hidden\" role=\"status\">{{ pick && `Jev picked ${pick.action}, p ${pick.p.toFixed(2)}, would ${acts(pick) ? 'act' : 'ask'}` }}\u003C\u002Fspan>\n    \u003Cdiv class=\"conf__axis\" aria-hidden=\"true\">\n      \u003Cspan v-for=\"p in picks\" :key=\"p.at\" class=\"conf__mark\" :class=\"{ 'is-act': acts(p) }\" :style=\"{ left: `${p.p * 100}%` }\" \u002F>\n      \u003Cdiv class=\"conf__rule\" :style=\"{ left: `${THRESHOLD * 100}%` }\" \u002F>\n    \u003C\u002Fdiv>\n    \u003Cp class=\"conf__sides\">\u003Cspan>&lt; {{ THRESHOLD }} Ask a person\u003C\u002Fspan>\u003Cspan>≥ {{ THRESHOLD }} Act, and log it\u003C\u002Fspan>\u003C\u002Fp>\n  \u003C\u002Fdiv>\n\u003C\u002Ftemplate>","\u003Cspan class=\"hljs-tag\">&lt;\u003Cspan class=\"hljs-name\">script\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">setup\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">lang\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;ts&quot;\u003C\u002Fspan>&gt;\u003C\u002Fspan>\u003Cspan class=\"language-javascript\">\n\u003Cspan class=\"hljs-keyword\">import\u003C\u002Fspan> { pickReadout, type \u003Cspan class=\"hljs-title class_\">JevPick\u003C\u002Fspan> } \u003Cspan class=\"hljs-keyword\">from\u003C\u002Fspan> \u003Cspan class=\"hljs-string\">&#x27;@cw\u002Fjevvie&#x27;\u003C\u002Fspan>\n\ndefineProps&lt;{ \u003Cspan class=\"hljs-attr\">prompt\u003C\u002Fspan>: string }&gt;()\n\u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> \u003Cspan class=\"hljs-variable constant_\">THRESHOLD\u003C\u002Fspan> = \u003Cspan class=\"hljs-number\">0.95\u003C\u002Fspan>\n\u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> pick = \u003Cspan class=\"hljs-title function_\">useJevPick\u003C\u002Fspan>()\n\u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> picks = \u003Cspan class=\"hljs-title function_\">useJevPicks\u003C\u002Fspan>()\n\u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> readout = useTemplateRef&lt;\u003Cspan class=\"hljs-title class_\">HTMLElement\u003C\u002Fspan>&gt;(\u003Cspan class=\"hljs-string\">&#x27;readout&#x27;\u003C\u002Fspan>)\n\u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> \u003Cspan class=\"hljs-title function_\">acts\u003C\u002Fspan> = (\u003Cspan class=\"hljs-params\">p: JevPick\u003C\u002Fspan>) =&gt; p.\u003Cspan class=\"hljs-property\">p\u003C\u002Fspan> &gt;= \u003Cspan class=\"hljs-variable constant_\">THRESHOLD\u003C\u002Fspan>\n\u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> line = \u003Cspan class=\"hljs-title function_\">computed\u003C\u002Fspan>(\u003Cspan class=\"hljs-function\">() =&gt;\u003C\u002Fspan> pick.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan> &amp;&amp; \u003Cspan class=\"hljs-title function_\">pickReadout\u003C\u002Fspan>(pick.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan>, \u003Cspan class=\"hljs-string\">&#x27;this tab&#x27;\u003C\u002Fspan>))\n\u003Cspan class=\"hljs-title function_\">watch\u003C\u002Fspan>(pick, \u003Cspan class=\"hljs-function\">() =&gt;\u003C\u002Fspan> { \u003Cspan class=\"hljs-keyword\">if\u003C\u002Fspan> (readout.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan> &amp;&amp; line.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan>) \u003Cspan class=\"hljs-title function_\">glitchOnce\u003C\u002Fspan>(readout.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan>, line.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan>) }, { \u003Cspan class=\"hljs-attr\">flush\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;post&#x27;\u003C\u002Fspan> })\n\u003C\u002Fspan>\u003Cspan class=\"hljs-tag\">&lt;\u002F\u003Cspan class=\"hljs-name\">script\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n\n\u003Cspan class=\"hljs-tag\">&lt;\u003Cspan class=\"hljs-name\">template\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n  \u003Cspan class=\"hljs-tag\">&lt;\u003Cspan class=\"hljs-name\">div\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">class\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;conf mono-label punch-box&quot;\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n    \u003Cspan class=\"hljs-tag\">&lt;\u003Cspan class=\"hljs-name\">p\u003C\u002Fspan>&gt;\u003C\u002Fspan>{{ prompt }}\u003Cspan class=\"hljs-tag\">&lt;\u002F\u003Cspan class=\"hljs-name\">p\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n    \u003Cspan class=\"hljs-tag\">&lt;\u003Cspan class=\"hljs-name\">p\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">v-if\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;line&quot;\u003C\u002Fspan>&gt;\u003C\u002Fspan>\u003Cspan class=\"hljs-tag\">&lt;\u003Cspan class=\"hljs-name\">span\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">ref\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;readout&quot;\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">aria-hidden\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;true&quot;\u003C\u002Fspan>&gt;\u003C\u002Fspan>{{ line }}\u003Cspan class=\"hljs-tag\">&lt;\u002F\u003Cspan class=\"hljs-name\">span\u003C\u002Fspan>&gt;\u003C\u002Fspan>\u003Cspan class=\"hljs-tag\">&lt;\u002F\u003Cspan class=\"hljs-name\">p\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n    \u003Cspan class=\"hljs-tag\">&lt;\u003Cspan class=\"hljs-name\">p\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">v-else\u003C\u002Fspan>&gt;\u003C\u002Fspan>No pick yet in this tab\u003Cspan class=\"hljs-tag\">&lt;\u002F\u003Cspan class=\"hljs-name\">p\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n    \u003Cspan class=\"hljs-tag\">&lt;\u003Cspan class=\"hljs-name\">span\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">class\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;visually-hidden&quot;\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">role\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;status&quot;\u003C\u002Fspan>&gt;\u003C\u002Fspan>{{ pick &amp;&amp; `Jev picked ${pick.action}, p ${pick.p.toFixed(2)}, would ${acts(pick) ? &#x27;act&#x27; : &#x27;ask&#x27;}` }}\u003Cspan class=\"hljs-tag\">&lt;\u002F\u003Cspan class=\"hljs-name\">span\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n    \u003Cspan class=\"hljs-tag\">&lt;\u003Cspan class=\"hljs-name\">div\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">class\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;conf__axis&quot;\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">aria-hidden\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;true&quot;\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n      \u003Cspan class=\"hljs-tag\">&lt;\u003Cspan class=\"hljs-name\">span\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">v-for\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;p in picks&quot;\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">:key\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;p.at&quot;\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">class\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;conf__mark&quot;\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">:class\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;{ &#x27;is-act&#x27;: acts(p) }&quot;\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">:style\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;{ left: `${p.p * 100}%` }&quot;\u003C\u002Fspan> \u002F&gt;\u003C\u002Fspan>\n      \u003Cspan class=\"hljs-tag\">&lt;\u003Cspan class=\"hljs-name\">div\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">class\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;conf__rule&quot;\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">:style\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;{ left: `${THRESHOLD * 100}%` }&quot;\u003C\u002Fspan> \u002F&gt;\u003C\u002Fspan>\n    \u003Cspan class=\"hljs-tag\">&lt;\u002F\u003Cspan class=\"hljs-name\">div\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n    \u003Cspan class=\"hljs-tag\">&lt;\u003Cspan class=\"hljs-name\">p\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">class\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;conf__sides&quot;\u003C\u002Fspan>&gt;\u003C\u002Fspan>\u003Cspan class=\"hljs-tag\">&lt;\u003Cspan class=\"hljs-name\">span\u003C\u002Fspan>&gt;\u003C\u002Fspan>\u003Cspan class=\"hljs-symbol\">&amp;lt;\u003C\u002Fspan> {{ THRESHOLD }} Ask a person\u003Cspan class=\"hljs-tag\">&lt;\u002F\u003Cspan class=\"hljs-name\">span\u003C\u002Fspan>&gt;\u003C\u002Fspan>\u003Cspan class=\"hljs-tag\">&lt;\u003Cspan class=\"hljs-name\">span\u003C\u002Fspan>&gt;\u003C\u002Fspan>≥ {{ THRESHOLD }} Act, and log it\u003Cspan class=\"hljs-tag\">&lt;\u002F\u003Cspan class=\"hljs-name\">span\u003C\u002Fspan>&gt;\u003C\u002Fspan>\u003Cspan class=\"hljs-tag\">&lt;\u002F\u003Cspan class=\"hljs-name\">p\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n  \u003Cspan class=\"hljs-tag\">&lt;\u002F\u003Cspan class=\"hljs-name\">div\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n\u003Cspan class=\"hljs-tag\">&lt;\u002F\u003Cspan class=\"hljs-name\">template\u003C\u002Fspan>&gt;\u003C\u002Fspan>",{"path":217,"lines":218,"code":219,"html":220},"app\u002Fcomponents\u002Fsite\u002FCharacterSpecimens.vue",67,"\u003Cscript setup lang=\"ts\">\nimport { jevvieColors } from '#core\u002Fdomain\u002Fpalette'\nimport type { JevvieView, Mood, Shape, Trick, Wear } from '@cw\u002Fjevvie\u002Fcharacter'\n\nconst SHAPES: { shape: Shape; wear?: Wear; name: string; note: string }[] = [\n  { shape: 'bar', name: 'Bar', note: 'The logo’s _, got loose. Today’s.' },\n  { shape: 'block', name: 'Block', note: 'A terminal cursor █, come alive.' },\n  { shape: 'blob', name: 'Blob', note: 'Round, soft, easy to love.' },\n  { shape: 'bubble', name: 'Bubble', note: 'A speech bubble that talks back.' },\n  { shape: 'page', name: 'Page', note: 'A sheet from the Trajectory notebook, face doodled on.' },\n  { shape: 'clip', name: 'Clip', note: 'A binder clip: Office had a paperclip, a clipboard has these.' },\n  { shape: 'bar', wear: 'clip', name: 'Bar + clip', note: 'The _, clipped to the page.' },\n  { shape: 'bar', wear: 'pencil', name: 'Bar + pencil', note: 'A pencil behind the ear, for notes.' },\n  { shape: 'block', wear: 'pin', name: 'Block + pin', note: 'Pinned to the board.' },\n  { shape: 'page', wear: 'clip', name: 'Page + clip', note: 'The notebook page, on a clipboard.' },\n  { shape: 'chamfer', name: 'Chamfered bar', note: 'The _, one bevel round its edges to catch the light.' },\n  { shape: 'capsule', name: 'Rounded bar', note: 'The _, ends rounded like a pill.' },\n  { shape: 'gumdrop', name: 'Gumdrop', note: 'The blob, turned on a lathe.' },\n  { shape: 'sticky', name: 'Sticky note', note: 'A note stuck on the page, corner curling.' },\n  { shape: 'paperclip', name: 'Paperclip', note: 'Office’s own, bent from wire.' },\n  { shape: 'pawn', name: 'Pawn', note: 'The chess coach, in person.' },\n  { shape: 'knight', name: 'Knight', note: 'A horse’s head in blocks, mane in ink.' },\n  { shape: 'bishop', name: 'Bishop', note: 'The mitre, slit and all.' },\n  { shape: 'rook', name: 'Rook', note: 'A tower, face under the battlements.' },\n  { shape: 'queen', name: 'Queen', note: 'A crown of beads.' },\n  { shape: 'king', name: 'King', note: 'The cross on top.' },\n  { shape: 'planet', name: 'Planet', note: 'A ringed planet.' },\n  { shape: 'moon', name: 'Moon', note: 'Craters and all.' },\n  { shape: 'star', name: 'Star', note: 'A star.' },\n  { shape: 'rocket', name: 'Rocket', note: 'A Saturn V, lit.' },\n  { shape: 'lander', name: 'Lander', note: 'Apollo’s lunar module, gold foil and legs.' },\n  { shape: 'astronaut', name: 'Astronaut', note: 'The face on the visor.' },\n  { shape: 'bar', wear: 'flag', name: 'Bar + flag', note: 'Planted, like Apollo 11’s.' },\n  { shape: 'blob', wear: 'antennas', name: 'Blob + antennas', note: 'Sputnik’s four whiskers.' },\n]\nconst MOODS: Mood[] = ['idle', 'happy', 'surprised', 'love', 'confused', 'think']\nconst TRICKS: Trick[] = ['jump', 'wave', 'spin', 'look']\nconst canvases = useTemplateRef\u003CHTMLCanvasElement[]>('canvas')\nconst views: JevvieView[] = []\nconst mood = ref\u003CMood>('idle')\n\nonMounted(async () => {\n  const { mountCharacter } = await import('@cw\u002Fjevvie\u002Fcharacter')\n  for (const [i, c] of (canvases.value ?? []).entries()) views.push(await mountCharacter(c, { colors: jevvieColors, shape: SHAPES[i]!.shape, wear: SHAPES[i]!.wear, reduced: useReducedMotion() }))\n})\nlet step = 0\nuseIntervalFn(() => {\n  step++\n  mood.value = MOODS[step % MOODS.length]!\n  for (const v of views) { v.mood(mood.value); if (step % 2) v.trick(TRICKS[step % TRICKS.length]!) }\n}, 2200, { immediate: !useReducedMotion() })\nonBeforeUnmount(() => views.forEach((v) => v.dispose()))\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003Csection id=\"characters\" class=\"bg-paper py-section\">\n    \u003Cdiv class=\"wrap grid gap-head\">\n      \u003CSinkHead label=\"Characters\" title=\"Who lives in the corner.\" accent=\"the corner.\">The companion’s candidate bodies, and stationery they might wear, going through the same moods together (now: {{ mood }}). Same face, colours and tricks; only the shape and what it wears change.\u003C\u002FSinkHead>\n      \u003Col class=\"cast\">\n        \u003Cli v-for=\"s in SHAPES\" :key=\"s.name\" class=\"cast__one\">\n          \u003Cdiv class=\"cast__stage\">\u003Ccanvas ref=\"canvas\" width=\"64\" height=\"44\" class=\"cast__canvas\" aria-hidden=\"true\" \u002F>\u003C\u002Fdiv>\n          \u003Cp class=\"text-11\">{{ s.name }} · {{ s.note }}\u003C\u002Fp>\n        \u003C\u002Fli>\n      \u003C\u002Fol>\n    \u003C\u002Fdiv>\n  \u003C\u002Fsection>\n\u003C\u002Ftemplate>","\u003Cspan class=\"hljs-tag\">&lt;\u003Cspan class=\"hljs-name\">script\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">setup\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">lang\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;ts&quot;\u003C\u002Fspan>&gt;\u003C\u002Fspan>\u003Cspan class=\"language-javascript\">\n\u003Cspan class=\"hljs-keyword\">import\u003C\u002Fspan> { jevvieColors } \u003Cspan class=\"hljs-keyword\">from\u003C\u002Fspan> \u003Cspan class=\"hljs-string\">&#x27;#core\u002Fdomain\u002Fpalette&#x27;\u003C\u002Fspan>\n\u003Cspan class=\"hljs-keyword\">import\u003C\u002Fspan> type { \u003Cspan class=\"hljs-title class_\">JevvieView\u003C\u002Fspan>, \u003Cspan class=\"hljs-title class_\">Mood\u003C\u002Fspan>, \u003Cspan class=\"hljs-title class_\">Shape\u003C\u002Fspan>, \u003Cspan class=\"hljs-title class_\">Trick\u003C\u002Fspan>, \u003Cspan class=\"hljs-title class_\">Wear\u003C\u002Fspan> } \u003Cspan class=\"hljs-keyword\">from\u003C\u002Fspan> \u003Cspan class=\"hljs-string\">&#x27;@cw\u002Fjevvie\u002Fcharacter&#x27;\u003C\u002Fspan>\n\n\u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">SHAPES\u003C\u002Fspan>: { \u003Cspan class=\"hljs-attr\">shape\u003C\u002Fspan>: \u003Cspan class=\"hljs-title class_\">Shape\u003C\u002Fspan>; wear?: \u003Cspan class=\"hljs-title class_\">Wear\u003C\u002Fspan>; \u003Cspan class=\"hljs-attr\">name\u003C\u002Fspan>: string; \u003Cspan class=\"hljs-attr\">note\u003C\u002Fspan>: string }[] = [\n  { \u003Cspan class=\"hljs-attr\">shape\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;bar&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">name\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;Bar&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">note\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;The logo’s _, got loose. Today’s.&#x27;\u003C\u002Fspan> },\n  { \u003Cspan class=\"hljs-attr\">shape\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;block&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">name\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;Block&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">note\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;A terminal cursor █, come alive.&#x27;\u003C\u002Fspan> },\n  { \u003Cspan class=\"hljs-attr\">shape\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;blob&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">name\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;Blob&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">note\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;Round, soft, easy to love.&#x27;\u003C\u002Fspan> },\n  { \u003Cspan class=\"hljs-attr\">shape\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;bubble&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">name\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;Bubble&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">note\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;A speech bubble that talks back.&#x27;\u003C\u002Fspan> },\n  { \u003Cspan class=\"hljs-attr\">shape\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;page&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">name\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;Page&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">note\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;A sheet from the Trajectory notebook, face doodled on.&#x27;\u003C\u002Fspan> },\n  { \u003Cspan class=\"hljs-attr\">shape\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;clip&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">name\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;Clip&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">note\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;A binder clip: Office had a paperclip, a clipboard has these.&#x27;\u003C\u002Fspan> },\n  { \u003Cspan class=\"hljs-attr\">shape\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;bar&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">wear\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;clip&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">name\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;Bar + clip&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">note\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;The _, clipped to the page.&#x27;\u003C\u002Fspan> },\n  { \u003Cspan class=\"hljs-attr\">shape\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;bar&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">wear\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;pencil&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">name\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;Bar + pencil&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">note\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;A pencil behind the ear, for notes.&#x27;\u003C\u002Fspan> },\n  { \u003Cspan class=\"hljs-attr\">shape\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;block&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">wear\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;pin&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">name\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;Block + pin&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">note\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;Pinned to the board.&#x27;\u003C\u002Fspan> },\n  { \u003Cspan class=\"hljs-attr\">shape\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;page&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">wear\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;clip&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">name\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;Page + clip&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">note\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;The notebook page, on a clipboard.&#x27;\u003C\u002Fspan> },\n  { \u003Cspan class=\"hljs-attr\">shape\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;chamfer&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">name\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;Chamfered bar&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">note\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;The _, one bevel round its edges to catch the light.&#x27;\u003C\u002Fspan> },\n  { \u003Cspan class=\"hljs-attr\">shape\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;capsule&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">name\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;Rounded bar&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">note\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;The _, ends rounded like a pill.&#x27;\u003C\u002Fspan> },\n  { \u003Cspan class=\"hljs-attr\">shape\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;gumdrop&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">name\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;Gumdrop&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">note\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;The blob, turned on a lathe.&#x27;\u003C\u002Fspan> },\n  { \u003Cspan class=\"hljs-attr\">shape\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;sticky&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">name\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;Sticky note&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">note\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;A note stuck on the page, corner curling.&#x27;\u003C\u002Fspan> },\n  { \u003Cspan class=\"hljs-attr\">shape\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;paperclip&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">name\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;Paperclip&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">note\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;Office’s own, bent from wire.&#x27;\u003C\u002Fspan> },\n  { \u003Cspan class=\"hljs-attr\">shape\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;pawn&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">name\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;Pawn&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">note\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;The chess coach, in person.&#x27;\u003C\u002Fspan> },\n  { \u003Cspan class=\"hljs-attr\">shape\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;knight&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">name\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;Knight&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">note\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;A horse’s head in blocks, mane in ink.&#x27;\u003C\u002Fspan> },\n  { \u003Cspan class=\"hljs-attr\">shape\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;bishop&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">name\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;Bishop&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">note\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;The mitre, slit and all.&#x27;\u003C\u002Fspan> },\n  { \u003Cspan class=\"hljs-attr\">shape\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;rook&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">name\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;Rook&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">note\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;A tower, face under the battlements.&#x27;\u003C\u002Fspan> },\n  { \u003Cspan class=\"hljs-attr\">shape\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;queen&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">name\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;Queen&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">note\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;A crown of beads.&#x27;\u003C\u002Fspan> },\n  { \u003Cspan class=\"hljs-attr\">shape\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;king&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">name\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;King&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">note\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;The cross on top.&#x27;\u003C\u002Fspan> },\n  { \u003Cspan class=\"hljs-attr\">shape\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;planet&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">name\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;Planet&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">note\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;A ringed planet.&#x27;\u003C\u002Fspan> },\n  { \u003Cspan class=\"hljs-attr\">shape\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;moon&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">name\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;Moon&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">note\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;Craters and all.&#x27;\u003C\u002Fspan> },\n  { \u003Cspan class=\"hljs-attr\">shape\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;star&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">name\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;Star&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">note\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;A star.&#x27;\u003C\u002Fspan> },\n  { \u003Cspan class=\"hljs-attr\">shape\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;rocket&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">name\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;Rocket&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">note\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;A Saturn V, lit.&#x27;\u003C\u002Fspan> },\n  { \u003Cspan class=\"hljs-attr\">shape\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;lander&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">name\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;Lander&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">note\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;Apollo’s lunar module, gold foil and legs.&#x27;\u003C\u002Fspan> },\n  { \u003Cspan class=\"hljs-attr\">shape\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;astronaut&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">name\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;Astronaut&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">note\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;The face on the visor.&#x27;\u003C\u002Fspan> },\n  { \u003Cspan class=\"hljs-attr\">shape\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;bar&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">wear\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;flag&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">name\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;Bar + flag&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">note\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;Planted, like Apollo 11’s.&#x27;\u003C\u002Fspan> },\n  { \u003Cspan class=\"hljs-attr\">shape\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;blob&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">wear\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;antennas&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">name\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;Blob + antennas&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">note\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;Sputnik’s four whiskers.&#x27;\u003C\u002Fspan> },\n]\n\u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">MOODS\u003C\u002Fspan>: \u003Cspan class=\"hljs-title class_\">Mood\u003C\u002Fspan>[] = [\u003Cspan class=\"hljs-string\">&#x27;idle&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-string\">&#x27;happy&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-string\">&#x27;surprised&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-string\">&#x27;love&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-string\">&#x27;confused&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-string\">&#x27;think&#x27;\u003C\u002Fspan>]\n\u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">TRICKS\u003C\u002Fspan>: \u003Cspan class=\"hljs-title class_\">Trick\u003C\u002Fspan>[] = [\u003Cspan class=\"hljs-string\">&#x27;jump&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-string\">&#x27;wave&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-string\">&#x27;spin&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-string\">&#x27;look&#x27;\u003C\u002Fspan>]\n\u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> canvases = useTemplateRef&lt;\u003Cspan class=\"hljs-title class_\">HTMLCanvasElement\u003C\u002Fspan>[]&gt;(\u003Cspan class=\"hljs-string\">&#x27;canvas&#x27;\u003C\u002Fspan>)\n\u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">views\u003C\u002Fspan>: \u003Cspan class=\"hljs-title class_\">JevvieView\u003C\u002Fspan>[] = []\n\u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> mood = ref&lt;\u003Cspan class=\"hljs-title class_\">Mood\u003C\u002Fspan>&gt;(\u003Cspan class=\"hljs-string\">&#x27;idle&#x27;\u003C\u002Fspan>)\n\n\u003Cspan class=\"hljs-title function_\">onMounted\u003C\u002Fspan>(\u003Cspan class=\"hljs-title function_\">async\u003C\u002Fspan> () =&gt; {\n  \u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> { mountCharacter } = \u003Cspan class=\"hljs-keyword\">await\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">import\u003C\u002Fspan>(\u003Cspan class=\"hljs-string\">&#x27;@cw\u002Fjevvie\u002Fcharacter&#x27;\u003C\u002Fspan>)\n  \u003Cspan class=\"hljs-keyword\">for\u003C\u002Fspan> (\u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> [i, c] \u003Cspan class=\"hljs-title function_\">of\u003C\u002Fspan> (canvases.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan> ?? []).\u003Cspan class=\"hljs-title function_\">entries\u003C\u002Fspan>()) views.\u003Cspan class=\"hljs-title function_\">push\u003C\u002Fspan>(\u003Cspan class=\"hljs-keyword\">await\u003C\u002Fspan> \u003Cspan class=\"hljs-title function_\">mountCharacter\u003C\u002Fspan>(c, { \u003Cspan class=\"hljs-attr\">colors\u003C\u002Fspan>: jevvieColors, \u003Cspan class=\"hljs-attr\">shape\u003C\u002Fspan>: \u003Cspan class=\"hljs-variable constant_\">SHAPES\u003C\u002Fspan>[i]!.\u003Cspan class=\"hljs-property\">shape\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">wear\u003C\u002Fspan>: \u003Cspan class=\"hljs-variable constant_\">SHAPES\u003C\u002Fspan>[i]!.\u003Cspan class=\"hljs-property\">wear\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">reduced\u003C\u002Fspan>: \u003Cspan class=\"hljs-title function_\">useReducedMotion\u003C\u002Fspan>() }))\n})\n\u003Cspan class=\"hljs-keyword\">let\u003C\u002Fspan> step = \u003Cspan class=\"hljs-number\">0\u003C\u002Fspan>\n\u003Cspan class=\"hljs-title function_\">useIntervalFn\u003C\u002Fspan>(\u003Cspan class=\"hljs-function\">() =&gt;\u003C\u002Fspan> {\n  step++\n  mood.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan> = \u003Cspan class=\"hljs-variable constant_\">MOODS\u003C\u002Fspan>[step % \u003Cspan class=\"hljs-variable constant_\">MOODS\u003C\u002Fspan>.\u003Cspan class=\"hljs-property\">length\u003C\u002Fspan>]!\n  \u003Cspan class=\"hljs-keyword\">for\u003C\u002Fspan> (\u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> v \u003Cspan class=\"hljs-keyword\">of\u003C\u002Fspan> views) { v.\u003Cspan class=\"hljs-title function_\">mood\u003C\u002Fspan>(mood.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan>); \u003Cspan class=\"hljs-keyword\">if\u003C\u002Fspan> (step % \u003Cspan class=\"hljs-number\">2\u003C\u002Fspan>) v.\u003Cspan class=\"hljs-title function_\">trick\u003C\u002Fspan>(\u003Cspan class=\"hljs-variable constant_\">TRICKS\u003C\u002Fspan>[step % \u003Cspan class=\"hljs-variable constant_\">TRICKS\u003C\u002Fspan>.\u003Cspan class=\"hljs-property\">length\u003C\u002Fspan>]!) }\n}, \u003Cspan class=\"hljs-number\">2200\u003C\u002Fspan>, { \u003Cspan class=\"hljs-attr\">immediate\u003C\u002Fspan>: !\u003Cspan class=\"hljs-title function_\">useReducedMotion\u003C\u002Fspan>() })\n\u003Cspan class=\"hljs-title function_\">onBeforeUnmount\u003C\u002Fspan>(\u003Cspan class=\"hljs-function\">() =&gt;\u003C\u002Fspan> views.\u003Cspan class=\"hljs-title function_\">forEach\u003C\u002Fspan>(\u003Cspan class=\"hljs-function\">(\u003Cspan class=\"hljs-params\">v\u003C\u002Fspan>) =&gt;\u003C\u002Fspan> v.\u003Cspan class=\"hljs-title function_\">dispose\u003C\u002Fspan>()))\n\u003C\u002Fspan>\u003Cspan class=\"hljs-tag\">&lt;\u002F\u003Cspan class=\"hljs-name\">script\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n\n\u003Cspan class=\"hljs-tag\">&lt;\u003Cspan class=\"hljs-name\">template\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n  \u003Cspan class=\"hljs-tag\">&lt;\u003Cspan class=\"hljs-name\">section\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">id\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;characters&quot;\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">class\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;bg-paper py-section&quot;\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n    \u003Cspan class=\"hljs-tag\">&lt;\u003Cspan class=\"hljs-name\">div\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">class\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;wrap grid gap-head&quot;\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n      \u003Cspan class=\"hljs-tag\">&lt;\u003Cspan class=\"hljs-name\">SinkHead\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">label\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;Characters&quot;\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">title\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;Who lives in the corner.&quot;\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">accent\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;the corner.&quot;\u003C\u002Fspan>&gt;\u003C\u002Fspan>The companion’s candidate bodies, and stationery they might wear, going through the same moods together (now: {{ mood }}). Same face, colours and tricks; only the shape and what it wears change.\u003Cspan class=\"hljs-tag\">&lt;\u002F\u003Cspan class=\"hljs-name\">SinkHead\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n      \u003Cspan class=\"hljs-tag\">&lt;\u003Cspan class=\"hljs-name\">ol\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">class\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;cast&quot;\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n        \u003Cspan class=\"hljs-tag\">&lt;\u003Cspan class=\"hljs-name\">li\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">v-for\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;s in SHAPES&quot;\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">:key\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;s.name&quot;\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">class\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;cast__one&quot;\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n          \u003Cspan class=\"hljs-tag\">&lt;\u003Cspan class=\"hljs-name\">div\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">class\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;cast__stage&quot;\u003C\u002Fspan>&gt;\u003C\u002Fspan>\u003Cspan class=\"hljs-tag\">&lt;\u003Cspan class=\"hljs-name\">canvas\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">ref\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;canvas&quot;\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">width\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;64&quot;\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">height\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;44&quot;\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">class\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;cast__canvas&quot;\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">aria-hidden\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;true&quot;\u003C\u002Fspan> \u002F&gt;\u003C\u002Fspan>\u003Cspan class=\"hljs-tag\">&lt;\u002F\u003Cspan class=\"hljs-name\">div\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n          \u003Cspan class=\"hljs-tag\">&lt;\u003Cspan class=\"hljs-name\">p\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">class\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;text-11&quot;\u003C\u002Fspan>&gt;\u003C\u002Fspan>{{ s.name }} · {{ s.note }}\u003Cspan class=\"hljs-tag\">&lt;\u002F\u003Cspan class=\"hljs-name\">p\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n        \u003Cspan class=\"hljs-tag\">&lt;\u002F\u003Cspan class=\"hljs-name\">li\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n      \u003Cspan class=\"hljs-tag\">&lt;\u002F\u003Cspan class=\"hljs-name\">ol\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n    \u003Cspan class=\"hljs-tag\">&lt;\u002F\u003Cspan class=\"hljs-name\">div\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n  \u003Cspan class=\"hljs-tag\">&lt;\u002F\u003Cspan class=\"hljs-name\">section\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n\u003Cspan class=\"hljs-tag\">&lt;\u002F\u003Cspan class=\"hljs-name\">template\u003C\u002Fspan>&gt;\u003C\u002Fspan>",{"path":222,"lines":223,"code":224,"html":225},"app\u002Fcomponents\u002Fsite\u002FJevvie.vue",450,"\u003Cscript setup lang=\"ts\">\nimport { clamp } from '@vueuse\u002Fcore'\nimport { PhLightbulb } from '@phosphor-icons\u002Fvue'\nimport companion from '~~\u002Fcontent\u002Fcompanion.json'\nimport { jevvieColors, rgb } from '#core\u002Fdomain\u002Fpalette'\nimport { fill, pickLine } from '#core\u002Fdomain\u002Flines'\nimport { actionName, ANY, argCriteria, argQuestions, HELP, NONE, pickOf, queryFrom, QUIET, ranked, suggestionsFor, toolCriteria, under, unsure, wantsAny, type Answer, type Suggestion, type Tip } from '@cw\u002Fjevvie'\nimport type { JevvieView, Mood, Shape, Trick, Wear } from '@cw\u002Fjevvie\u002Fcharacter'\nimport type { Trail } from '@cw\u002Fjevvie\u002Ftrail'\n\nconst route = useRoute()\nconst root = useTemplateRef\u003CHTMLElement>('root')\nconst body = useTemplateRef\u003CHTMLElement>('body')\nconst handle = useTemplateRef\u003CHTMLElement>('handle')\nconst canvas = useTemplateRef\u003CHTMLCanvasElement>('canvas')\nconst trailCanvas = useTemplateRef\u003CHTMLCanvasElement>('trailCanvas')\nconst reduced = useReducedMotion()\nconst { asking: consenting } = useAnalyticsConsent()\nconst { top: atTop, left: atLeft, right: atRight, update: measure } = useElementBounding(root)\nconst { width: screenWidth } = useWindowSize()\nconst leftward = computed(() => screenWidth.value - atLeft.value > atRight.value)\nconst talkWidth = computed(() => `${Math.min(320, Math.max(screenWidth.value - atLeft.value, atRight.value) - 16)}px`)\nlet view: JevvieView | undefined\nlet trail: Trail | null | undefined\n\nlet moodTimer = 0\nfunction feel(m: Mood, ms = 1600) {\n  view?.mood(m)\n  clearTimeout(moodTimer)\n  if (m !== 'sleep' && m !== 'sulk') moodTimer = window.setTimeout(() => view?.mood('idle'), ms)\n}\nfunction random\u003CT>(xs: readonly T[]) { return xs[Math.floor(Math.random() * xs.length)] }\nconst trick = (t?: Trick) => import('@cw\u002Fjevvie\u002Fcharacter').then(({ TRICKS }) => view?.trick(t ?? random(TRICKS)!))\n\ntype Choice = { label: string; run: () => void }\nconst say = ref('')\nconst tip = ref\u003CTip | null>(null)\nconst choices = ref\u003CChoice[]>([])\nconst sure = ref('')\nconst greeting = ref(false)\nconst open = ref(false)\nconst menu = ref(false)\nconst busy = ref(false)\nlet last = ''\nconst line = (lines: readonly string[]) => (last = pickLine(lines, last))\nconst cap = (s: string) => s.charAt(0).toUpperCase() + s.slice(1)\nconst { start: fade, stop: keep } = useTimeoutFn(() => { if (!tip.value && !greeting.value && !choices.value.length) say.value = '' }, 6000, { immediate: false })\nfunction speak(text: string, stay = false, options: Choice[] = [], confidence = '') {\n  say.value = text; choices.value = options; sure.value = confidence\n  keep(); if (!stay) fade()\n}\nconst hush = () => { say.value = ''; tip.value = null; choices.value = []; greeting.value = false }\nconst unasked = () => { if (greeting.value || tip.value) hush() }\nconst { start: outstay } = useTimeoutFn(unasked, 10_000, { immediate: false })\nuseEventListener(window, 'scroll', unasked, { passive: true })\nconst awayFrom = shallowRef\u003CHTMLElement[]>([])\nconst inView = new Set\u003CElement>()\nconst away = ref(!!document.querySelector('[data-jevvie-away]'))\nuseIntersectionObserver(awayFrom, (entries) => {\n  for (const e of entries) { if (e.isIntersecting) inView.add(e.target); else inView.delete(e.target) }\n  away.value = inView.size > 0\n})\nconst findAway = () => { inView.clear(); awayFrom.value = [...document.querySelectorAll\u003CHTMLElement>('[data-jevvie-away]')] }\nuseNuxtApp().hook('page:finish', findAway)\nconst typed = ref('')\nconst { resume: type, pause: typedOut } = useIntervalFn(() => {\n  typed.value = say.value.slice(0, typed.value.length + 2)\n  if (typed.value.length >= say.value.length) typedOut()\n}, 28, { immediate: false })\nwatch(say, (now) => { typed.value = reduced ? now : ''; if (!reduced && now) type() })\n\nlet introduce = false\nonMounted(async () => {\n  findAway()\n  await new Promise((done) => ('requestIdleCallback' in window ? requestIdleCallback(done, { timeout: 3000 }) : setTimeout(done, 1500)))\n  await mountBody()\n  measure()\n  if (!readStore('jevvieMet')) {\n    writeStore('jevvieMet', true)\n    introduce = true\n    const wave = () => setTimeout(() => void trick('wave'), away.value ? 400 : 2500)\n    if (!away.value) wave()\n    else { const stop = watch(away, (a) => { if (!a) { stop(); wave() } }) }\n  }\n})\nonBeforeUnmount(() => { view?.dispose(); trail?.dispose(); clearTimeout(moodTimer) })\n\n\u002F\u002F a new body gets a fresh canvas (the :key), since a WebGL canvas cannot be taken over once its renderer is gone\nconst BODIES: { shape: Shape; wear: Wear; name: string }[] = [\n  { shape: 'bar', wear: 'none', name: 'Bar' }, { shape: 'bar', wear: 'clip', name: 'Bar + clip' }, { shape: 'page', wear: 'clip', name: 'Page' },\n  { shape: 'clip', wear: 'none', name: 'Clip' }, { shape: 'block', wear: 'pin', name: 'Block' }, { shape: 'blob', wear: 'none', name: 'Blob' },\n  { shape: 'pawn', wear: 'none', name: 'Pawn' }, { shape: 'emoji', wear: 'none', name: 'Emoji' }, { shape: 'bubble', wear: 'none', name: 'Bubble' },\n  { shape: 'chamfer', wear: 'clip', name: 'Chamfered bar' }, { shape: 'capsule', wear: 'none', name: 'Rounded bar' }, { shape: 'gumdrop', wear: 'none', name: 'Gumdrop' },\n  { shape: 'sticky', wear: 'pin', name: 'Sticky note' }, { shape: 'paperclip', wear: 'none', name: 'Paperclip' },\n  { shape: 'knight', wear: 'none', name: 'Knight' }, { shape: 'bishop', wear: 'none', name: 'Bishop' }, { shape: 'rook', wear: 'none', name: 'Rook' },\n  { shape: 'queen', wear: 'none', name: 'Queen' }, { shape: 'king', wear: 'none', name: 'King' },\n  { shape: 'planet', wear: 'none', name: 'Planet' }, { shape: 'moon', wear: 'none', name: 'Moon' }, { shape: 'star', wear: 'none', name: 'Star' },\n  { shape: 'rocket', wear: 'none', name: 'Rocket' }, { shape: 'lander', wear: 'none', name: 'Lander' }, { shape: 'astronaut', wear: 'none', name: 'Astronaut' },\n  { shape: 'bar', wear: 'flag', name: 'Bar + flag' },\n]\nconst bodyAt = useStored('jevvieBody', 0, indexBelow(BODIES.length))\nconst picked = ref(false)\nconst bodyShown = computed(() => { const own = BODIES.findIndex((b) => b.shape === route.meta.jevvie); return own >= 0 && !picked.value ? own : bodyAt.value })\nlet mounting = Promise.resolve()\nwatch(bodyShown, () => { mounting = mountBody() })\nasync function mountBody() {\n  view?.dispose(); view = undefined\n  await nextTick()\n  const { mountCharacter } = await import('@cw\u002Fjevvie\u002Fcharacter')\n  const { shape, wear } = BODIES[bodyShown.value]!\n  if (canvas.value) view = await mountCharacter(canvas.value, { reduced, colors: jevvieColors, shape, wear })\n}\nfunction nextBody() {\n  menu.value = false\n  const next = (bodyShown.value + 1) % BODIES.length\n  picked.value = true; bodyAt.value = next\n  void nextTick().then(() => mounting).then(() => { view?.squash(); speak(fill(companion.menu.bodyIs, { body: BODIES[next]!.name })) })\n}\n\nconst bounds = () => new DOMRect(0, 0, innerWidth, innerHeight)\nconst saved = readStore\u003C{ x: number; y: number }>('jevviePlace')\nlet place = saved ?? { x: 0, y: 0 }, moved = false\nconst SWING = 18, FLING = 1.6\nconst swing = ref(0)\nlet grip = { ...place, at: 0 }, flung = false\nuseDraggable(root, handle, {\n  initial: saved,\n  onDrag: (x, y) => {\n    const now = performance.now(), dt = Math.max(16, now - grip.at), dx = x - grip.x, dy = y - grip.y\n    if (now - grip.at > 500) flung = false\n    grip = { x, y, at: now }\n    if (!reduced) swing.value = Math.max(-SWING, Math.min(SWING, (dx \u002F dt) * 10))\n    if (!flung && Math.hypot(dx, dy) \u002F dt > FLING) { flung = true; feel('surprised', 1400); void trick('spin'); speak(line(companion.fling)) }\n  },\n  onMove: (x, y) => {\n    swing.value = 0\n    moved = Math.abs(x - place.x) + Math.abs(y - place.y) > 3\n    place = { x, y }\n    grip = { ...place, at: 0 }\n    measure()\n    if (!moved) return\n    writeStore('jevviePlace', place)\n    view?.squash()\n    if (!flung) { feel('happy', 900); speak(line(companion.drop)) }\n    flung = false\n  },\n})\n\nconst { x: mx, y: my } = useMouse({ type: 'client' })\nwatchThrottled([mx, my], ([x, y]) => {\n  const r = body.value?.getBoundingClientRect()\n  if (r) view?.look(x - (r.left + r.width \u002F 2), y - (r.top + r.height \u002F 2))\n}, { throttle: 50 })\nconst { idle, lastActive } = useIdle(60_000)\nwatch(idle, (asleep) => {\n  if (sulking) return\n  feel(asleep ? 'sleep' : 'idle')\n  if (asleep) speak(line(companion.sleep), true)\n  else if (say.value && companion.sleep.includes(say.value)) speak(line(companion.wake))\n})\nuseIntervalFn(() => {\n  if (!idle.value && !busy.value && !open.value && !sulking && !document.hidden && Math.random() \u003C 0.5) void trick(random(['look', 'stretch', 'tap'] as const))\n}, 17_000)\n\nconst suggestions = computed(() => suggestionsFor(companion.suggest as Suggestion[], siteTools(), route.path, 20))\nconst more = useStored('jevvieMore', false, oneOf(true, false))\nconst groups = computed(() => {\n  const all = [{ name: companion.panel.here, global: false }, { name: companion.panel.anywhere, global: true }]\n    .map(({ name, global }) => ({ name, items: suggestions.value.filter((s) => GLOBAL_TOOLS.has(s.tool) === global) })).filter((g) => g.items.length)\n  if (more.value) return all\n  let left = 3\n  return all.map((g) => { const items = g.items.slice(0, left); left -= items.length; return { ...g, items } }).filter((g) => g.items.length)\n})\nconst hiddenCount = computed(() => suggestions.value.length - groups.value.reduce((n, g) => n + g.items.length, 0))\nfunction openPanel() { hush(); menu.value = false; open.value = true; feel('happy', 900) }\nconst closePanel = () => { open.value = false; hush() }\nfunction suggest(s?: Suggestion) {\n  const pick = s ?? random(suggestions.value)\n  if (pick) void act(pick.tool, pick.arg)\n}\n\nlet pokes: number[] = [], sulking = false\nconst clickLater = useTimeoutFn(poke, 220, { immediate: false })\nfunction click() {\n  if (moved) { moved = false; return }\n  clickLater.start()\n}\nfunction poke() {\n  if (sulking) return\n  view?.squash(0.6)\n  if (!open.value && introduce) {\n    introduce = false; greeting.value = true\n    return speak(companion.greet.text, true, [{ label: companion.greet.button, run: openPanel }])\n  }\n  if (!open.value) return openPanel()\n  const now = Date.now()\n  pokes = [...pokes.filter((t) => now - t \u003C 8000), now]\n  if (pokes.length \u003C 5) { feel(Math.random() \u003C 0.5 ? 'surprised' : 'happy', 700); return speak(line(companion.poke)) }\n  pokes = []; sulking = true; open.value = false\n  feel('sulk'); speak(line(companion.sulk))\n  setTimeout(() => { sulking = false; feel('idle') }, 7000)\n}\nfunction animate() {\n  clickLater.stop()\n  if (sulking) return\n  menu.value = false\n  void trick(); feel('happy', 1200)\n  speak(line(companion.tricks))\n}\nfunction openMenu() { menu.value = !menu.value; if (menu.value) open.value = false }\n\nlet flight: Animation | undefined\nasync function hop(dx: number, dy: number) {\n  const el = body.value\n  if (!el) return false\n  const from = new DOMMatrixReadOnly(getComputedStyle(el).transform)\n  flight?.cancel()\n  const rise = 70 + Math.abs(dy - from.f) \u002F 2\n  const keyframes = Array.from({ length: 9 }, (_, i) => {\n    const t = i \u002F 8\n    return { transform: `translate(${from.e + (dx - from.e) * t}px, ${from.f + (dy - from.f) * t - 4 * rise * t * (1 - t)}px)` }\n  })\n  const run = flight = el.animate(keyframes, { duration: Math.min(700, 420 + Math.hypot(dx - from.e, dy - from.f) * 0.2), easing: 'steps(12, jump-end)', fill: 'forwards' })\n  const canvas = trailCanvas.value\n  if (canvas && trail === undefined) trail = await import('@cw\u002Fjevvie\u002Ftrail').then((m) => m.mountTrail(canvas, rgb('amber')))\n  const mark = () => { const r = el.getBoundingClientRect(); trail?.add(r.left + r.width \u002F 2, r.bottom - 6); if (run.playState === 'running') requestAnimationFrame(mark) }\n  mark()\n  if (!(await run.finished.then(() => true, () => false))) return false\n  el.style.transform = `translate(${dx}px, ${dy}px)`\n  run.cancel()\n  view?.squash()\n  return true\n}\nasync function visit(target: Element | null | undefined) {\n  if (!target || !body.value || !root.value) return\n  if (reduced) { target.animate([{ outline: '2px solid currentColor' }, { outline: '2px solid transparent' }], { duration: 1200, easing: 'steps(1, jump-end)' }); return }\n  let r = target.getBoundingClientRect()\n  if (r.bottom \u003C 0 || r.top > innerHeight) {\n    await new Promise\u003Cvoid>((done) => scrollPageTo(scrollY + r.top + r.height \u002F 2 - innerHeight \u002F 2, done))\n    r = target.getBoundingClientRect()\n  }\n  const home = root.value.getBoundingClientRect(), me = body.value.getBoundingClientRect(), b = bounds()\n  const x = clamp(r.left + Math.min(r.width \u002F 2, 80) - me.width \u002F 2, b.left + 8, b.right - me.width - 8)\n  const y = clamp(r.top - me.height + 8, b.top + 8, b.bottom - me.height - 8)\n  await hop(x - (home.right - me.width), y - (home.bottom - me.height))\n}\nconst goHome = () => { if (!reduced && body.value?.style.transform) void hop(0, 0).then((landed) => { if (landed && body.value) body.value.style.transform = '' }) }\n\nasync function act(name: string, value?: string, alternatives: Choice[] = [], confidence = '') {\n  const tool = siteTools().get(name)\n  if (!tool) { feel('confused'); return speak(line(companion.ask.none)) }\n  const values = tool.arg?.values\n  if (value === ANY) value = values && random(values)?.value\n  const label = values?.find((v) => v.value === value)?.label ?? value\n  const doing = `${cap(tool.doing(label))}.`\n  hush()\n  feel('happy', 3000)\n  speak(doing, alternatives.length > 0, alternatives, confidence)\n  await visit(tool.target?.(value))\n  try {\n    const { result } = await callTool(name, value, 'jevvie')\n    void trick('jump'); feel('love', 1400)\n    if (result && !alternatives.length && name !== 'copy_link') speak(`${doing} ${result}`)\n  } catch { feel('confused', 2200); speak(companion.ask.failed) }\n  setTimeout(goHome, 1400)\n}\n\nconst lastPick = useJevPick()\nconst picks = useJevPicks()\nasync function post(body: { criteria?: Record\u003Cstring, string> } & Record\u003Cstring, unknown>, name = actionName) {\n  const answer = await $fetch\u003CAnswer>('\u002Fapi\u002Fcompanion', { method: 'POST', body: { path: route.path, ...body } })\n  const pick = pickOf(answer, body.criteria ? Object.keys(body.criteria) : tipIds, name)\n  if (pick) { lastPick.value = pick; picks.value = [...picks.value, pick].slice(-8) }\n  return answer\n}\nconst tipIds = (companion.tips as Tip[]).map((t) => t.id)\nconst context = () => ({ recent: recentEvents(), heading: [...document.querySelectorAll('h1, h2')].find((h) => { const r = h.getBoundingClientRect(); return r.bottom > 0 && r.top \u003C innerHeight })?.textContent?.trim() })\nconst SECTIONS = ['work', 'notes', 'lab', 'experiments', 'decks', 'projects']\nfunction think() {\n  busy.value = true\n  feel('think', 20_000)\n  speak(companion.ask.thinking, true)\n}\nasync function ask(request: string) {\n  if (busy.value) return\n  think()\n  try {\n    const tools = [...siteTools().values()].filter((t) => !t.agentOnly && (!t.arg?.values || t.arg.values.length))\n    const first = await post({ kind: 'tool', request, criteria: toolCriteria(tools), args: wantsAny(request) ? {} : argQuestions(tools, request) })\n    if (first.choice === HELP) { feel('happy'); return openPanel() }\n    const tool = siteTools().get(first.choice)\n    if (first.choice === NONE || !tool) { feel('confused', 2200); return speak(line(companion.ask.none)) }\n    if (unsure(first)) {\n      feel('confused', 4000)\n      const options = ranked(first, [NONE, HELP]).slice(0, 3).map(([name]) => ({ label: siteTools().get(name)?.description ?? name, run: () => void resolve(name, request, 1, first.args?.[name]) }))\n      return speak(companion.clarify.question, true, options)\n    }\n    await resolve(tool.name, request, first.probabilities[tool.name], first.args?.[tool.name])\n  } catch (e) {\n    feel('confused', 2200)\n    speak((e as { statusCode?: number }).statusCode === 429 ? companion.ask.busy : companion.ask.failed)\n  } finally { busy.value = false }\n}\nasync function resolve(name: string, request: string, p = 1, asked?: Answer) {\n  const tool = siteTools().get(name)\n  if (!tool) return\n  const percent = (x: number) => fill(companion.clarify.sure, { p: String(Math.round(x * 100)) })\n  if (!tool.arg) return act(name, undefined, [], percent(p))\n  const { values } = tool.arg\n  if (!values) return act(name, queryFrom(request, tool.description, SECTIONS) || request, [], percent(p))\n  if (wantsAny(request)) return act(name, ANY)\n  const options = argCriteria(tool.arg, request)\n  const keys = Object.keys(options)\n  if (keys.length === 1) return act(name, keys[0], [], percent(p))\n  const second = asked?.choice && asked.choice in options ? asked : await post({ kind: 'arg', request, action: tool.description, criteria: options }, (v) => values.find((x) => x.value === v)?.label ?? actionName(v))\n  const runners = ranked(second, [second.choice]).slice(0, 2).map(([value]) => ({ label: options[value] ?? value, run: () => void act(name, value) }))\n  if (unsure(second)) {\n    feel('confused', 4000)\n    return speak(companion.clarify.question, true, [{ label: options[second.choice] ?? second.choice, run: () => void act(name, second.choice) }, ...runners])\n  }\n  await act(name, second.choice, runners, percent(p * (second.probabilities[second.choice] ?? 1)))\n}\n\nonJevvieSay((l) => {\n  if (sulking) return\n  tip.value = null; greeting.value = false\n  feel(l.mood ?? 'happy', 3000)\n  if (l.trick) void trick(l.trick)\n  speak(l.text)\n})\n\nuseEventBus\u003C'call'>('jevvie').on(() => { view?.squash(); void trick('jump'); feel('surprised', 1200); speak(line(companion.ask.rang)) })\n\nonToolCall((call) => {\n  if (call.by !== 'agent') return\n  feel('surprised', 1400)\n  speak(cap(fill(line(call.tool.name.startsWith('jevvie_') ? companion.agentMe : companion.agent), { doing: call.tool.doing(call.label) })))\n  if (!call.tool.agentOnly) void visit(call.tool.target?.(call.value)).then(() => setTimeout(goHome, 1400))\n})\n\nconst tipsOn = useStored('jevvieTips', true, oneOf(true, false))\nconst dismissed = useSessionStorage\u003Cstring[]>('cw:jevvieDismissed', [])\nlet lastTipAt = Date.now(), shown = 0, lastTip = ''\nconst MAX_TIPS = 10\nconst tipGap = () => Math.max(40_000, 120_000 - shown * 15_000)\nconst tipFor = (id: string) => (companion.tips as Tip[]).find((t) => t.id === id)\nfunction offer(next: Tip) {\n  hush(); open.value = false\n  lastTip = next.id; tip.value = next\n  view?.squash(0.5); void trick('wave'); feel('happy', 1400)\n  speak(next.text, true); outstay()\n}\nuseIntervalFn(async () => {\n  const quiet = (Date.now() - lastActive.value) \u002F 1000\n  if (!tipsOn.value || consenting.value || dismissed.value.length >= 3 || shown >= MAX_TIPS || open.value || menu.value || busy.value || say.value || sulking || document.hidden) return\n  if (Date.now() - lastTipAt \u003C tipGap() || quiet \u003C 12 || idle.value) return\n  lastTipAt = Date.now()\n  const scrolled = scrollY \u002F Math.max(1, document.documentElement.scrollHeight - innerHeight)\n  const { choice } = await post({ kind: 'tip', idle: Math.round(quiet), scrolled, dismissed: dismissed.value, lastTip, ...context() }).catch(() => ({ choice: QUIET }))\n  const next = tipFor(choice)\n  if (!next || say.value || open.value) return\n  shown++\n  offer(next)\n}, 30_000)\nconst landed = useSessionStorage\u003Cstring[]>('cw:jevvieLanded', [])\nwatch(() => route.path, (path) => {\n  setTimeout(async () => {\n    if (path === '\u002F' || route.path !== path || landed.value.includes(path) || !tipsOn.value || consenting.value || dismissed.value.length >= 3 || open.value || busy.value || say.value || sulking) return\n    if (!(companion.tips as Tip[]).some((t) => t.only?.some((p) => under(path, p)))) return\n    landed.value = [...landed.value, path]\n    const { choice } = await post({ kind: 'landing', dismissed: dismissed.value, lastTip, ...context() }).catch(() => ({ choice: QUIET }))\n    const next = tipFor(choice)\n    if (next && !say.value && !open.value) offer(next)\n  }, 3500)\n}, { immediate: true })\nfunction answerTip(yes: boolean) {\n  const t = tip.value\n  tip.value = null\n  if (!t) return\n  track('jevvie_tip', { id: t.id, answer: yes ? 'yes' : 'no' })\n  if (yes && t.action) return void act(t.action.tool, t.action.arg)\n  if (yes) return hush()\n  dismissed.value = [...dismissed.value, t.id]\n  feel('sulk'); setTimeout(() => feel('idle'), 1500)\n  speak(companion.dismiss)\n}\nasync function askTip() {\n  if (busy.value) return\n  think()\n  const { choice } = await post({ kind: 'ask', dismissed: dismissed.value, lastTip, ...context() }).catch(() => ({ choice: QUIET }))\n  busy.value = false\n  const next = tipFor(choice)\n  if (!next) { feel('confused', 2000); return speak(companion.ask.failed) }\n  offer(next)\n}\nonKeyStroke('Escape', () => { if (tip.value) answerTip(false) })\nconst hidden = useStored('jevvieHidden', false, oneOf(true, false))\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003Cdiv ref=\"root\" class=\"us\" :class=\"{ 'us--away': away, 'us--below': atTop \u003C 240, 'us--leftward': leftward }\" :style=\"{ '--talk': talkWidth }\">\n    \u003Cdiv class=\"us__talk\">\n      \u003Cul v-if=\"menu\" class=\"us__menu shadow-win mono-label\" :aria-label=\"companion.menu.label\" role=\"menu\">\n        \u003Cli role=\"none\">\u003Cbutton type=\"button\" role=\"menuitem\" class=\"bare read-1\" @click=\"animate\">{{ companion.menu.animate }}\u003C\u002Fbutton>\u003C\u002Fli>\n        \u003Cli role=\"none\">\u003Cbutton type=\"button\" role=\"menuitem\" class=\"bare read-1\" @click=\"tipsOn = !tipsOn; menu = false\">{{ tipsOn ? companion.menu.tipsOn : companion.menu.tipsOff }}\u003C\u002Fbutton>\u003C\u002Fli>\n        \u003Cli role=\"none\">\u003Cbutton type=\"button\" role=\"menuitem\" class=\"bare read-1\" @click=\"nextBody\">{{ companion.menu.body }}: {{ BODIES[bodyShown]!.name }} ►\u003C\u002Fbutton>\u003C\u002Fli>\n        \u003Cli role=\"none\">\u003Cbutton type=\"button\" role=\"menuitem\" class=\"bare read-1\" @click=\"hidden = true\">{{ companion.menu.hide }}\u003C\u002Fbutton>\u003C\u002Fli>\n      \u003C\u002Ful>\n      \u003CWin v-if=\"open\" :title=\"companion.panel.title\" as=\"section\" :label=\"companion.panel.question\" class=\"us__win\" closable @close=\"closePanel\">\n        \u003Cp class=\"us__question\">{{ companion.panel.question }}\u003C\u002Fp>\n        \u003Cdiv v-for=\"g in groups\" :key=\"g.name\" class=\"us__group\">\n          \u003Cp class=\"us__group-name mono-label\">{{ g.name }}\u003C\u002Fp>\n          \u003Cul class=\"us__list\">\n            \u003Cli v-for=\"s in g.items\" :key=\"s.label\">\u003Cbutton type=\"button\" class=\"bare read-1\" :disabled=\"busy\" @click=\"suggest(s)\">{{ s.label }}\u003C\u002Fbutton>\u003C\u002Fli>\n          \u003C\u002Ful>\n        \u003C\u002Fdiv>\n        \u003Cbutton v-if=\"hiddenCount > 0 || more\" type=\"button\" class=\"us__more bare read-1 mono-label\" :aria-expanded=\"more\" @click=\"more = !more\">{{ more ? `${companion.panel.less} ▲` : `${companion.panel.more} (${hiddenCount}) ▼` }}\u003C\u002Fbutton>\n        \u003CTuiPrompt :label=\"companion.ask.label\" :placeholder=\"companion.ask.placeholder\" @submit=\"ask\" \u002F>\n        \u003Cp class=\"us__foot mono-label\">\n          \u003Cbutton type=\"button\" class=\"bare read-1\" :disabled=\"busy\" @click=\"askTip\">\u003CPhLightbulb :size=\"14\" weight=\"bold\" aria-hidden=\"true\" \u002F> {{ companion.panel.tip }}\u003C\u002Fbutton>\n          \u003Cbutton type=\"button\" class=\"bare read-1\" :disabled=\"busy\" @click=\"suggest()\">{{ companion.panel.surprise }} ►\u003C\u002Fbutton>\n          \u003Cbutton type=\"button\" class=\"bare read-1\" :aria-expanded=\"menu\" @click=\"openMenu\">{{ companion.panel.options }}\u003C\u002Fbutton>\n        \u003C\u002Fp>\n      \u003C\u002FWin>\n      \u003Cdiv v-if=\"say\" class=\"us__say shadow-win text-11\" :class=\"{ 'us__say--tip': tip }\" role=\"status\" aria-live=\"polite\">\u003Cdiv class=\"us__panel bg-paper\">\n        \u003Cbutton v-if=\"!tip\" type=\"button\" class=\"us__x bare hit read-1\" :aria-label=\"companion.answers.close\" @click=\"hush()\">×\u003C\u002Fbutton>\n        \u003Cp class=\"us__line\">\n          \u003CPhLightbulb v-if=\"tip\" class=\"us__bulb\" :size=\"14\" weight=\"bold\" aria-hidden=\"true\" \u002F>\n          \u003Cspan class=\"us__text\">\u003Cspan class=\"us__ghost\" aria-hidden=\"true\">{{ say }}█\u003C\u002Fspan>\u003Cspan aria-hidden=\"true\">{{ typed }}\u003CCursor :steady=\"typed.length \u003C say.length\" \u002F>\u003C\u002Fspan>\u003C\u002Fspan>\n          \u003Cspan class=\"visually-hidden\">{{ say }}\u003C\u002Fspan>\n        \u003C\u002Fp>\n        \u003Cp v-if=\"sure\" class=\"us__sure\">{{ sure }}\u003Ctemplate v-if=\"choices.length\"> · {{ companion.clarify.or }}\u003C\u002Ftemplate>\u003C\u002Fp>\n        \u003Cp v-if=\"choices.length\" class=\"us__choices\">\n          \u003Cbutton v-for=\"c in choices\" :key=\"c.label\" type=\"button\" class=\"bare hit read-1\" @click=\"c.run\">{{ c.label }}\u003C\u002Fbutton>\n        \u003C\u002Fp>\n        \u003Cdiv v-if=\"tip\" class=\"us__answers btn-group\">\n          \u003CBtn size=\"sm\" @click=\"answerTip(true)\">{{ tip.action ? companion.answers.yes : companion.answers.thanks }}\u003C\u002FBtn>\n          \u003CBtn size=\"sm\" variant=\"ghost\" @click=\"answerTip(false)\">{{ tip.action ? companion.answers.no : companion.answers.later }}\u003C\u002FBtn>\n        \u003C\u002Fdiv>\n      \u003C\u002Fdiv>\u003C\u002Fdiv>\n    \u003C\u002Fdiv>\n    \u003Cdiv ref=\"body\" class=\"us__body\" :style=\"{ rotate: `${swing}deg` }\">\n      \u003Cdiv ref=\"handle\" class=\"us__handle\" @click=\"click\" @dblclick=\"animate\" @contextmenu.prevent=\"openMenu\" @keydown.enter.prevent=\"poke\">\n        \u003Cspan class=\"win__title visually-hidden\">{{ companion.name }}\u003C\u002Fspan>\n        \u003Ccanvas ref=\"canvas\" :key=\"bodyShown\" class=\"us__canvas\" width=\"64\" height=\"44\" aria-hidden=\"true\" \u002F>\n      \u003C\u002Fdiv>\n    \u003C\u002Fdiv>\n    \u003CTeleport to=\"body\">\u003Ccanvas ref=\"trailCanvas\" class=\"us-trail\" aria-hidden=\"true\" \u002F>\u003C\u002FTeleport>\n  \u003C\u002Fdiv>\n\u003C\u002Ftemplate>","\u003Cspan class=\"hljs-tag\">&lt;\u003Cspan class=\"hljs-name\">script\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">setup\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">lang\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;ts&quot;\u003C\u002Fspan>&gt;\u003C\u002Fspan>\u003Cspan class=\"language-javascript\">\n\u003Cspan class=\"hljs-keyword\">import\u003C\u002Fspan> { clamp } \u003Cspan class=\"hljs-keyword\">from\u003C\u002Fspan> \u003Cspan class=\"hljs-string\">&#x27;@vueuse\u002Fcore&#x27;\u003C\u002Fspan>\n\u003Cspan class=\"hljs-keyword\">import\u003C\u002Fspan> { \u003Cspan class=\"hljs-title class_\">PhLightbulb\u003C\u002Fspan> } \u003Cspan class=\"hljs-keyword\">from\u003C\u002Fspan> \u003Cspan class=\"hljs-string\">&#x27;@phosphor-icons\u002Fvue&#x27;\u003C\u002Fspan>\n\u003Cspan class=\"hljs-keyword\">import\u003C\u002Fspan> companion \u003Cspan class=\"hljs-keyword\">from\u003C\u002Fspan> \u003Cspan class=\"hljs-string\">&#x27;~~\u002Fcontent\u002Fcompanion.json&#x27;\u003C\u002Fspan>\n\u003Cspan class=\"hljs-keyword\">import\u003C\u002Fspan> { jevvieColors, rgb } \u003Cspan class=\"hljs-keyword\">from\u003C\u002Fspan> \u003Cspan class=\"hljs-string\">&#x27;#core\u002Fdomain\u002Fpalette&#x27;\u003C\u002Fspan>\n\u003Cspan class=\"hljs-keyword\">import\u003C\u002Fspan> { fill, pickLine } \u003Cspan class=\"hljs-keyword\">from\u003C\u002Fspan> \u003Cspan class=\"hljs-string\">&#x27;#core\u002Fdomain\u002Flines&#x27;\u003C\u002Fspan>\n\u003Cspan class=\"hljs-keyword\">import\u003C\u002Fspan> { actionName, \u003Cspan class=\"hljs-variable constant_\">ANY\u003C\u002Fspan>, argCriteria, argQuestions, \u003Cspan class=\"hljs-variable constant_\">HELP\u003C\u002Fspan>, \u003Cspan class=\"hljs-variable constant_\">NONE\u003C\u002Fspan>, pickOf, queryFrom, \u003Cspan class=\"hljs-variable constant_\">QUIET\u003C\u002Fspan>, ranked, suggestionsFor, toolCriteria, under, unsure, wantsAny, type \u003Cspan class=\"hljs-title class_\">Answer\u003C\u002Fspan>, type \u003Cspan class=\"hljs-title class_\">Suggestion\u003C\u002Fspan>, type \u003Cspan class=\"hljs-title class_\">Tip\u003C\u002Fspan> } \u003Cspan class=\"hljs-keyword\">from\u003C\u002Fspan> \u003Cspan class=\"hljs-string\">&#x27;@cw\u002Fjevvie&#x27;\u003C\u002Fspan>\n\u003Cspan class=\"hljs-keyword\">import\u003C\u002Fspan> type { \u003Cspan class=\"hljs-title class_\">JevvieView\u003C\u002Fspan>, \u003Cspan class=\"hljs-title class_\">Mood\u003C\u002Fspan>, \u003Cspan class=\"hljs-title class_\">Shape\u003C\u002Fspan>, \u003Cspan class=\"hljs-title class_\">Trick\u003C\u002Fspan>, \u003Cspan class=\"hljs-title class_\">Wear\u003C\u002Fspan> } \u003Cspan class=\"hljs-keyword\">from\u003C\u002Fspan> \u003Cspan class=\"hljs-string\">&#x27;@cw\u002Fjevvie\u002Fcharacter&#x27;\u003C\u002Fspan>\n\u003Cspan class=\"hljs-keyword\">import\u003C\u002Fspan> type { \u003Cspan class=\"hljs-title class_\">Trail\u003C\u002Fspan> } \u003Cspan class=\"hljs-keyword\">from\u003C\u002Fspan> \u003Cspan class=\"hljs-string\">&#x27;@cw\u002Fjevvie\u002Ftrail&#x27;\u003C\u002Fspan>\n\n\u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> route = \u003Cspan class=\"hljs-title function_\">useRoute\u003C\u002Fspan>()\n\u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> root = useTemplateRef&lt;\u003Cspan class=\"hljs-title class_\">HTMLElement\u003C\u002Fspan>&gt;(\u003Cspan class=\"hljs-string\">&#x27;root&#x27;\u003C\u002Fspan>)\n\u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> body = useTemplateRef&lt;\u003Cspan class=\"hljs-title class_\">HTMLElement\u003C\u002Fspan>&gt;(\u003Cspan class=\"hljs-string\">&#x27;body&#x27;\u003C\u002Fspan>)\n\u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> handle = useTemplateRef&lt;\u003Cspan class=\"hljs-title class_\">HTMLElement\u003C\u002Fspan>&gt;(\u003Cspan class=\"hljs-string\">&#x27;handle&#x27;\u003C\u002Fspan>)\n\u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> canvas = useTemplateRef&lt;\u003Cspan class=\"hljs-title class_\">HTMLCanvasElement\u003C\u002Fspan>&gt;(\u003Cspan class=\"hljs-string\">&#x27;canvas&#x27;\u003C\u002Fspan>)\n\u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> trailCanvas = useTemplateRef&lt;\u003Cspan class=\"hljs-title class_\">HTMLCanvasElement\u003C\u002Fspan>&gt;(\u003Cspan class=\"hljs-string\">&#x27;trailCanvas&#x27;\u003C\u002Fspan>)\n\u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> reduced = \u003Cspan class=\"hljs-title function_\">useReducedMotion\u003C\u002Fspan>()\n\u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> { \u003Cspan class=\"hljs-attr\">asking\u003C\u002Fspan>: consenting } = \u003Cspan class=\"hljs-title function_\">useAnalyticsConsent\u003C\u002Fspan>()\n\u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> { \u003Cspan class=\"hljs-attr\">top\u003C\u002Fspan>: atTop, \u003Cspan class=\"hljs-attr\">left\u003C\u002Fspan>: atLeft, \u003Cspan class=\"hljs-attr\">right\u003C\u002Fspan>: atRight, \u003Cspan class=\"hljs-attr\">update\u003C\u002Fspan>: measure } = \u003Cspan class=\"hljs-title function_\">useElementBounding\u003C\u002Fspan>(root)\n\u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> { \u003Cspan class=\"hljs-attr\">width\u003C\u002Fspan>: screenWidth } = \u003Cspan class=\"hljs-title function_\">useWindowSize\u003C\u002Fspan>()\n\u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> leftward = \u003Cspan class=\"hljs-title function_\">computed\u003C\u002Fspan>(\u003Cspan class=\"hljs-function\">() =&gt;\u003C\u002Fspan> screenWidth.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan> - atLeft.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan> &gt; atRight.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan>)\n\u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> talkWidth = \u003Cspan class=\"hljs-title function_\">computed\u003C\u002Fspan>(\u003Cspan class=\"hljs-function\">() =&gt;\u003C\u002Fspan> \u003Cspan class=\"hljs-string\">`\u003Cspan class=\"hljs-subst\">${\u003Cspan class=\"hljs-built_in\">Math\u003C\u002Fspan>.min(\u003Cspan class=\"hljs-number\">320\u003C\u002Fspan>, \u003Cspan class=\"hljs-built_in\">Math\u003C\u002Fspan>.max(screenWidth.value - atLeft.value, atRight.value) - \u003Cspan class=\"hljs-number\">16\u003C\u002Fspan>)}\u003C\u002Fspan>px`\u003C\u002Fspan>)\n\u003Cspan class=\"hljs-keyword\">let\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">view\u003C\u002Fspan>: \u003Cspan class=\"hljs-title class_\">JevvieView\u003C\u002Fspan> | \u003Cspan class=\"hljs-literal\">undefined\u003C\u002Fspan>\n\u003Cspan class=\"hljs-keyword\">let\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">trail\u003C\u002Fspan>: \u003Cspan class=\"hljs-title class_\">Trail\u003C\u002Fspan> | \u003Cspan class=\"hljs-literal\">null\u003C\u002Fspan> | \u003Cspan class=\"hljs-literal\">undefined\u003C\u002Fspan>\n\n\u003Cspan class=\"hljs-keyword\">let\u003C\u002Fspan> moodTimer = \u003Cspan class=\"hljs-number\">0\u003C\u002Fspan>\n\u003Cspan class=\"hljs-keyword\">function\u003C\u002Fspan> \u003Cspan class=\"hljs-title function_\">feel\u003C\u002Fspan>(\u003Cspan class=\"hljs-params\">m: Mood, ms = \u003Cspan class=\"hljs-number\">1600\u003C\u002Fspan>\u003C\u002Fspan>) {\n  view?.\u003Cspan class=\"hljs-title function_\">mood\u003C\u002Fspan>(m)\n  \u003Cspan class=\"hljs-built_in\">clearTimeout\u003C\u002Fspan>(moodTimer)\n  \u003Cspan class=\"hljs-keyword\">if\u003C\u002Fspan> (m !== \u003Cspan class=\"hljs-string\">&#x27;sleep&#x27;\u003C\u002Fspan> &amp;&amp; m !== \u003Cspan class=\"hljs-string\">&#x27;sulk&#x27;\u003C\u002Fspan>) moodTimer = \u003Cspan class=\"hljs-variable language_\">window\u003C\u002Fspan>.\u003Cspan class=\"hljs-built_in\">setTimeout\u003C\u002Fspan>(\u003Cspan class=\"hljs-function\">() =&gt;\u003C\u002Fspan> view?.\u003Cspan class=\"hljs-title function_\">mood\u003C\u002Fspan>(\u003Cspan class=\"hljs-string\">&#x27;idle&#x27;\u003C\u002Fspan>), ms)\n}\n\u003Cspan class=\"hljs-keyword\">function\u003C\u002Fspan> random&lt;T&gt;(\u003Cspan class=\"hljs-attr\">xs\u003C\u002Fspan>: readonly T[]) { \u003Cspan class=\"hljs-keyword\">return\u003C\u002Fspan> xs[\u003Cspan class=\"hljs-title class_\">Math\u003C\u002Fspan>.\u003Cspan class=\"hljs-title function_\">floor\u003C\u002Fspan>(\u003Cspan class=\"hljs-title class_\">Math\u003C\u002Fspan>.\u003Cspan class=\"hljs-title function_\">random\u003C\u002Fspan>() * xs.\u003Cspan class=\"hljs-property\">length\u003C\u002Fspan>)] }\n\u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> \u003Cspan class=\"hljs-title function_\">trick\u003C\u002Fspan> = (\u003Cspan class=\"hljs-params\">t?: Trick\u003C\u002Fspan>) =&gt; \u003Cspan class=\"hljs-keyword\">import\u003C\u002Fspan>(\u003Cspan class=\"hljs-string\">&#x27;@cw\u002Fjevvie\u002Fcharacter&#x27;\u003C\u002Fspan>).\u003Cspan class=\"hljs-title function_\">then\u003C\u002Fspan>(\u003Cspan class=\"hljs-function\">(\u003Cspan class=\"hljs-params\">{ TRICKS }\u003C\u002Fspan>) =&gt;\u003C\u002Fspan> view?.\u003Cspan class=\"hljs-title function_\">trick\u003C\u002Fspan>(t ?? \u003Cspan class=\"hljs-title function_\">random\u003C\u002Fspan>(\u003Cspan class=\"hljs-variable constant_\">TRICKS\u003C\u002Fspan>)!))\n\ntype \u003Cspan class=\"hljs-title class_\">Choice\u003C\u002Fspan> = { \u003Cspan class=\"hljs-attr\">label\u003C\u002Fspan>: string; \u003Cspan class=\"hljs-attr\">run\u003C\u002Fspan>: \u003Cspan class=\"hljs-function\">() =&gt;\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">void\u003C\u002Fspan> }\n\u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> say = \u003Cspan class=\"hljs-title function_\">ref\u003C\u002Fspan>(\u003Cspan class=\"hljs-string\">&#x27;&#x27;\u003C\u002Fspan>)\n\u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> tip = ref&lt;\u003Cspan class=\"hljs-title class_\">Tip\u003C\u002Fspan> | \u003Cspan class=\"hljs-literal\">null\u003C\u002Fspan>&gt;(\u003Cspan class=\"hljs-literal\">null\u003C\u002Fspan>)\n\u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> choices = ref&lt;\u003Cspan class=\"hljs-title class_\">Choice\u003C\u002Fspan>[]&gt;([])\n\u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> sure = \u003Cspan class=\"hljs-title function_\">ref\u003C\u002Fspan>(\u003Cspan class=\"hljs-string\">&#x27;&#x27;\u003C\u002Fspan>)\n\u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> greeting = \u003Cspan class=\"hljs-title function_\">ref\u003C\u002Fspan>(\u003Cspan class=\"hljs-literal\">false\u003C\u002Fspan>)\n\u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> open = \u003Cspan class=\"hljs-title function_\">ref\u003C\u002Fspan>(\u003Cspan class=\"hljs-literal\">false\u003C\u002Fspan>)\n\u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> menu = \u003Cspan class=\"hljs-title function_\">ref\u003C\u002Fspan>(\u003Cspan class=\"hljs-literal\">false\u003C\u002Fspan>)\n\u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> busy = \u003Cspan class=\"hljs-title function_\">ref\u003C\u002Fspan>(\u003Cspan class=\"hljs-literal\">false\u003C\u002Fspan>)\n\u003Cspan class=\"hljs-keyword\">let\u003C\u002Fspan> last = \u003Cspan class=\"hljs-string\">&#x27;&#x27;\u003C\u002Fspan>\n\u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> \u003Cspan class=\"hljs-title function_\">line\u003C\u002Fspan> = (\u003Cspan class=\"hljs-params\">lines: readonly string[]\u003C\u002Fspan>) =&gt; (last = \u003Cspan class=\"hljs-title function_\">pickLine\u003C\u002Fspan>(lines, last))\n\u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> \u003Cspan class=\"hljs-title function_\">cap\u003C\u002Fspan> = (\u003Cspan class=\"hljs-params\">s: string\u003C\u002Fspan>) =&gt; s.\u003Cspan class=\"hljs-title function_\">charAt\u003C\u002Fspan>(\u003Cspan class=\"hljs-number\">0\u003C\u002Fspan>).\u003Cspan class=\"hljs-title function_\">toUpperCase\u003C\u002Fspan>() + s.\u003Cspan class=\"hljs-title function_\">slice\u003C\u002Fspan>(\u003Cspan class=\"hljs-number\">1\u003C\u002Fspan>)\n\u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> { \u003Cspan class=\"hljs-attr\">start\u003C\u002Fspan>: fade, \u003Cspan class=\"hljs-attr\">stop\u003C\u002Fspan>: keep } = \u003Cspan class=\"hljs-title function_\">useTimeoutFn\u003C\u002Fspan>(\u003Cspan class=\"hljs-function\">() =&gt;\u003C\u002Fspan> { \u003Cspan class=\"hljs-keyword\">if\u003C\u002Fspan> (!tip.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan> &amp;&amp; !greeting.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan> &amp;&amp; !choices.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan>.\u003Cspan class=\"hljs-property\">length\u003C\u002Fspan>) say.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan> = \u003Cspan class=\"hljs-string\">&#x27;&#x27;\u003C\u002Fspan> }, \u003Cspan class=\"hljs-number\">6000\u003C\u002Fspan>, { \u003Cspan class=\"hljs-attr\">immediate\u003C\u002Fspan>: \u003Cspan class=\"hljs-literal\">false\u003C\u002Fspan> })\n\u003Cspan class=\"hljs-keyword\">function\u003C\u002Fspan> \u003Cspan class=\"hljs-title function_\">speak\u003C\u002Fspan>(\u003Cspan class=\"hljs-params\">text: string, stay = \u003Cspan class=\"hljs-literal\">false\u003C\u002Fspan>, options: Choice[] = [], confidence = \u003Cspan class=\"hljs-string\">&#x27;&#x27;\u003C\u002Fspan>\u003C\u002Fspan>) {\n  say.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan> = text; choices.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan> = options; sure.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan> = confidence\n  \u003Cspan class=\"hljs-title function_\">keep\u003C\u002Fspan>(); \u003Cspan class=\"hljs-keyword\">if\u003C\u002Fspan> (!stay) \u003Cspan class=\"hljs-title function_\">fade\u003C\u002Fspan>()\n}\n\u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> \u003Cspan class=\"hljs-title function_\">hush\u003C\u002Fspan> = (\u003Cspan class=\"hljs-params\">\u003C\u002Fspan>) =&gt; { say.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan> = \u003Cspan class=\"hljs-string\">&#x27;&#x27;\u003C\u002Fspan>; tip.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan> = \u003Cspan class=\"hljs-literal\">null\u003C\u002Fspan>; choices.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan> = []; greeting.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan> = \u003Cspan class=\"hljs-literal\">false\u003C\u002Fspan> }\n\u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> \u003Cspan class=\"hljs-title function_\">unasked\u003C\u002Fspan> = (\u003Cspan class=\"hljs-params\">\u003C\u002Fspan>) =&gt; { \u003Cspan class=\"hljs-keyword\">if\u003C\u002Fspan> (greeting.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan> || tip.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan>) \u003Cspan class=\"hljs-title function_\">hush\u003C\u002Fspan>() }\n\u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> { \u003Cspan class=\"hljs-attr\">start\u003C\u002Fspan>: outstay } = \u003Cspan class=\"hljs-title function_\">useTimeoutFn\u003C\u002Fspan>(unasked, \u003Cspan class=\"hljs-number\">10_000\u003C\u002Fspan>, { \u003Cspan class=\"hljs-attr\">immediate\u003C\u002Fspan>: \u003Cspan class=\"hljs-literal\">false\u003C\u002Fspan> })\n\u003Cspan class=\"hljs-title function_\">useEventListener\u003C\u002Fspan>(\u003Cspan class=\"hljs-variable language_\">window\u003C\u002Fspan>, \u003Cspan class=\"hljs-string\">&#x27;scroll&#x27;\u003C\u002Fspan>, unasked, { \u003Cspan class=\"hljs-attr\">passive\u003C\u002Fspan>: \u003Cspan class=\"hljs-literal\">true\u003C\u002Fspan> })\n\u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> awayFrom = shallowRef&lt;\u003Cspan class=\"hljs-title class_\">HTMLElement\u003C\u002Fspan>[]&gt;([])\n\u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> inView = \u003Cspan class=\"hljs-keyword\">new\u003C\u002Fspan> \u003Cspan class=\"hljs-title class_\">Set\u003C\u002Fspan>&lt;\u003Cspan class=\"hljs-title class_\">Element\u003C\u002Fspan>&gt;()\n\u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> away = \u003Cspan class=\"hljs-title function_\">ref\u003C\u002Fspan>(!!\u003Cspan class=\"hljs-variable language_\">document\u003C\u002Fspan>.\u003Cspan class=\"hljs-title function_\">querySelector\u003C\u002Fspan>(\u003Cspan class=\"hljs-string\">&#x27;[data-jevvie-away]&#x27;\u003C\u002Fspan>))\n\u003Cspan class=\"hljs-title function_\">useIntersectionObserver\u003C\u002Fspan>(awayFrom, \u003Cspan class=\"hljs-function\">(\u003Cspan class=\"hljs-params\">entries\u003C\u002Fspan>) =&gt;\u003C\u002Fspan> {\n  \u003Cspan class=\"hljs-keyword\">for\u003C\u002Fspan> (\u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> e \u003Cspan class=\"hljs-keyword\">of\u003C\u002Fspan> entries) { \u003Cspan class=\"hljs-keyword\">if\u003C\u002Fspan> (e.\u003Cspan class=\"hljs-property\">isIntersecting\u003C\u002Fspan>) inView.\u003Cspan class=\"hljs-title function_\">add\u003C\u002Fspan>(e.\u003Cspan class=\"hljs-property\">target\u003C\u002Fspan>); \u003Cspan class=\"hljs-keyword\">else\u003C\u002Fspan> inView.\u003Cspan class=\"hljs-title function_\">delete\u003C\u002Fspan>(e.\u003Cspan class=\"hljs-property\">target\u003C\u002Fspan>) }\n  away.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan> = inView.\u003Cspan class=\"hljs-property\">size\u003C\u002Fspan> &gt; \u003Cspan class=\"hljs-number\">0\u003C\u002Fspan>\n})\n\u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> \u003Cspan class=\"hljs-title function_\">findAway\u003C\u002Fspan> = (\u003Cspan class=\"hljs-params\">\u003C\u002Fspan>) =&gt; { inView.\u003Cspan class=\"hljs-title function_\">clear\u003C\u002Fspan>(); awayFrom.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan> = [...\u003Cspan class=\"hljs-variable language_\">document\u003C\u002Fspan>.\u003Cspan class=\"hljs-property\">querySelectorAll\u003C\u002Fspan>&lt;\u003Cspan class=\"hljs-title class_\">HTMLElement\u003C\u002Fspan>&gt;(\u003Cspan class=\"hljs-string\">&#x27;[data-jevvie-away]&#x27;\u003C\u002Fspan>)] }\n\u003Cspan class=\"hljs-title function_\">useNuxtApp\u003C\u002Fspan>().\u003Cspan class=\"hljs-title function_\">hook\u003C\u002Fspan>(\u003Cspan class=\"hljs-string\">&#x27;page:finish&#x27;\u003C\u002Fspan>, findAway)\n\u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> typed = \u003Cspan class=\"hljs-title function_\">ref\u003C\u002Fspan>(\u003Cspan class=\"hljs-string\">&#x27;&#x27;\u003C\u002Fspan>)\n\u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> { \u003Cspan class=\"hljs-attr\">resume\u003C\u002Fspan>: type, \u003Cspan class=\"hljs-attr\">pause\u003C\u002Fspan>: typedOut } = \u003Cspan class=\"hljs-title function_\">useIntervalFn\u003C\u002Fspan>(\u003Cspan class=\"hljs-function\">() =&gt;\u003C\u002Fspan> {\n  typed.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan> = say.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan>.\u003Cspan class=\"hljs-title function_\">slice\u003C\u002Fspan>(\u003Cspan class=\"hljs-number\">0\u003C\u002Fspan>, typed.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan>.\u003Cspan class=\"hljs-property\">length\u003C\u002Fspan> + \u003Cspan class=\"hljs-number\">2\u003C\u002Fspan>)\n  \u003Cspan class=\"hljs-keyword\">if\u003C\u002Fspan> (typed.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan>.\u003Cspan class=\"hljs-property\">length\u003C\u002Fspan> &gt;= say.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan>.\u003Cspan class=\"hljs-property\">length\u003C\u002Fspan>) \u003Cspan class=\"hljs-title function_\">typedOut\u003C\u002Fspan>()\n}, \u003Cspan class=\"hljs-number\">28\u003C\u002Fspan>, { \u003Cspan class=\"hljs-attr\">immediate\u003C\u002Fspan>: \u003Cspan class=\"hljs-literal\">false\u003C\u002Fspan> })\n\u003Cspan class=\"hljs-title function_\">watch\u003C\u002Fspan>(say, \u003Cspan class=\"hljs-function\">(\u003Cspan class=\"hljs-params\">now\u003C\u002Fspan>) =&gt;\u003C\u002Fspan> { typed.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan> = reduced ? now : \u003Cspan class=\"hljs-string\">&#x27;&#x27;\u003C\u002Fspan>; \u003Cspan class=\"hljs-keyword\">if\u003C\u002Fspan> (!reduced &amp;&amp; now) \u003Cspan class=\"hljs-title function_\">type\u003C\u002Fspan>() })\n\n\u003Cspan class=\"hljs-keyword\">let\u003C\u002Fspan> introduce = \u003Cspan class=\"hljs-literal\">false\u003C\u002Fspan>\n\u003Cspan class=\"hljs-title function_\">onMounted\u003C\u002Fspan>(\u003Cspan class=\"hljs-title function_\">async\u003C\u002Fspan> () =&gt; {\n  \u003Cspan class=\"hljs-title function_\">findAway\u003C\u002Fspan>()\n  \u003Cspan class=\"hljs-keyword\">await\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">new\u003C\u002Fspan> \u003Cspan class=\"hljs-title class_\">Promise\u003C\u002Fspan>(\u003Cspan class=\"hljs-function\">(\u003Cspan class=\"hljs-params\">done\u003C\u002Fspan>) =&gt;\u003C\u002Fspan> (\u003Cspan class=\"hljs-string\">&#x27;requestIdleCallback&#x27;\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">in\u003C\u002Fspan> \u003Cspan class=\"hljs-variable language_\">window\u003C\u002Fspan> ? \u003Cspan class=\"hljs-title function_\">requestIdleCallback\u003C\u002Fspan>(done, { \u003Cspan class=\"hljs-attr\">timeout\u003C\u002Fspan>: \u003Cspan class=\"hljs-number\">3000\u003C\u002Fspan> }) : \u003Cspan class=\"hljs-built_in\">setTimeout\u003C\u002Fspan>(done, \u003Cspan class=\"hljs-number\">1500\u003C\u002Fspan>)))\n  \u003Cspan class=\"hljs-keyword\">await\u003C\u002Fspan> \u003Cspan class=\"hljs-title function_\">mountBody\u003C\u002Fspan>()\n  \u003Cspan class=\"hljs-title function_\">measure\u003C\u002Fspan>()\n  \u003Cspan class=\"hljs-keyword\">if\u003C\u002Fspan> (!\u003Cspan class=\"hljs-title function_\">readStore\u003C\u002Fspan>(\u003Cspan class=\"hljs-string\">&#x27;jevvieMet&#x27;\u003C\u002Fspan>)) {\n    \u003Cspan class=\"hljs-title function_\">writeStore\u003C\u002Fspan>(\u003Cspan class=\"hljs-string\">&#x27;jevvieMet&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-literal\">true\u003C\u002Fspan>)\n    introduce = \u003Cspan class=\"hljs-literal\">true\u003C\u002Fspan>\n    \u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> \u003Cspan class=\"hljs-title function_\">wave\u003C\u002Fspan> = (\u003Cspan class=\"hljs-params\">\u003C\u002Fspan>) =&gt; \u003Cspan class=\"hljs-built_in\">setTimeout\u003C\u002Fspan>(\u003Cspan class=\"hljs-function\">() =&gt;\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">void\u003C\u002Fspan> \u003Cspan class=\"hljs-title function_\">trick\u003C\u002Fspan>(\u003Cspan class=\"hljs-string\">&#x27;wave&#x27;\u003C\u002Fspan>), away.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan> ? \u003Cspan class=\"hljs-number\">400\u003C\u002Fspan> : \u003Cspan class=\"hljs-number\">2500\u003C\u002Fspan>)\n    \u003Cspan class=\"hljs-keyword\">if\u003C\u002Fspan> (!away.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan>) \u003Cspan class=\"hljs-title function_\">wave\u003C\u002Fspan>()\n    \u003Cspan class=\"hljs-keyword\">else\u003C\u002Fspan> { \u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> stop = \u003Cspan class=\"hljs-title function_\">watch\u003C\u002Fspan>(away, \u003Cspan class=\"hljs-function\">(\u003Cspan class=\"hljs-params\">a\u003C\u002Fspan>) =&gt;\u003C\u002Fspan> { \u003Cspan class=\"hljs-keyword\">if\u003C\u002Fspan> (!a) { \u003Cspan class=\"hljs-title function_\">stop\u003C\u002Fspan>(); \u003Cspan class=\"hljs-title function_\">wave\u003C\u002Fspan>() } }) }\n  }\n})\n\u003Cspan class=\"hljs-title function_\">onBeforeUnmount\u003C\u002Fspan>(\u003Cspan class=\"hljs-function\">() =&gt;\u003C\u002Fspan> { view?.\u003Cspan class=\"hljs-title function_\">dispose\u003C\u002Fspan>(); trail?.\u003Cspan class=\"hljs-title function_\">dispose\u003C\u002Fspan>(); \u003Cspan class=\"hljs-built_in\">clearTimeout\u003C\u002Fspan>(moodTimer) })\n\n\u003Cspan class=\"hljs-comment\">\u002F\u002F a new body gets a fresh canvas (the :key), since a WebGL canvas cannot be taken over once its renderer is gone\u003C\u002Fspan>\n\u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">BODIES\u003C\u002Fspan>: { \u003Cspan class=\"hljs-attr\">shape\u003C\u002Fspan>: \u003Cspan class=\"hljs-title class_\">Shape\u003C\u002Fspan>; \u003Cspan class=\"hljs-attr\">wear\u003C\u002Fspan>: \u003Cspan class=\"hljs-title class_\">Wear\u003C\u002Fspan>; \u003Cspan class=\"hljs-attr\">name\u003C\u002Fspan>: string }[] = [\n  { \u003Cspan class=\"hljs-attr\">shape\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;bar&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">wear\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;none&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">name\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;Bar&#x27;\u003C\u002Fspan> }, { \u003Cspan class=\"hljs-attr\">shape\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;bar&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">wear\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;clip&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">name\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;Bar + clip&#x27;\u003C\u002Fspan> }, { \u003Cspan class=\"hljs-attr\">shape\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;page&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">wear\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;clip&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">name\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;Page&#x27;\u003C\u002Fspan> },\n  { \u003Cspan class=\"hljs-attr\">shape\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;clip&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">wear\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;none&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">name\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;Clip&#x27;\u003C\u002Fspan> }, { \u003Cspan class=\"hljs-attr\">shape\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;block&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">wear\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;pin&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">name\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;Block&#x27;\u003C\u002Fspan> }, { \u003Cspan class=\"hljs-attr\">shape\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;blob&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">wear\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;none&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">name\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;Blob&#x27;\u003C\u002Fspan> },\n  { \u003Cspan class=\"hljs-attr\">shape\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;pawn&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">wear\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;none&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">name\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;Pawn&#x27;\u003C\u002Fspan> }, { \u003Cspan class=\"hljs-attr\">shape\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;emoji&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">wear\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;none&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">name\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;Emoji&#x27;\u003C\u002Fspan> }, { \u003Cspan class=\"hljs-attr\">shape\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;bubble&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">wear\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;none&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">name\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;Bubble&#x27;\u003C\u002Fspan> },\n  { \u003Cspan class=\"hljs-attr\">shape\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;chamfer&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">wear\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;clip&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">name\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;Chamfered bar&#x27;\u003C\u002Fspan> }, { \u003Cspan class=\"hljs-attr\">shape\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;capsule&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">wear\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;none&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">name\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;Rounded bar&#x27;\u003C\u002Fspan> }, { \u003Cspan class=\"hljs-attr\">shape\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;gumdrop&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">wear\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;none&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">name\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;Gumdrop&#x27;\u003C\u002Fspan> },\n  { \u003Cspan class=\"hljs-attr\">shape\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;sticky&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">wear\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;pin&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">name\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;Sticky note&#x27;\u003C\u002Fspan> }, { \u003Cspan class=\"hljs-attr\">shape\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;paperclip&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">wear\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;none&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">name\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;Paperclip&#x27;\u003C\u002Fspan> },\n  { \u003Cspan class=\"hljs-attr\">shape\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;knight&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">wear\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;none&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">name\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;Knight&#x27;\u003C\u002Fspan> }, { \u003Cspan class=\"hljs-attr\">shape\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;bishop&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">wear\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;none&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">name\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;Bishop&#x27;\u003C\u002Fspan> }, { \u003Cspan class=\"hljs-attr\">shape\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;rook&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">wear\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;none&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">name\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;Rook&#x27;\u003C\u002Fspan> },\n  { \u003Cspan class=\"hljs-attr\">shape\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;queen&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">wear\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;none&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">name\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;Queen&#x27;\u003C\u002Fspan> }, { \u003Cspan class=\"hljs-attr\">shape\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;king&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">wear\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;none&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">name\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;King&#x27;\u003C\u002Fspan> },\n  { \u003Cspan class=\"hljs-attr\">shape\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;planet&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">wear\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;none&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">name\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;Planet&#x27;\u003C\u002Fspan> }, { \u003Cspan class=\"hljs-attr\">shape\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;moon&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">wear\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;none&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">name\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;Moon&#x27;\u003C\u002Fspan> }, { \u003Cspan class=\"hljs-attr\">shape\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;star&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">wear\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;none&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">name\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;Star&#x27;\u003C\u002Fspan> },\n  { \u003Cspan class=\"hljs-attr\">shape\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;rocket&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">wear\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;none&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">name\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;Rocket&#x27;\u003C\u002Fspan> }, { \u003Cspan class=\"hljs-attr\">shape\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;lander&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">wear\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;none&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">name\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;Lander&#x27;\u003C\u002Fspan> }, { \u003Cspan class=\"hljs-attr\">shape\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;astronaut&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">wear\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;none&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">name\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;Astronaut&#x27;\u003C\u002Fspan> },\n  { \u003Cspan class=\"hljs-attr\">shape\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;bar&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">wear\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;flag&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">name\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;Bar + flag&#x27;\u003C\u002Fspan> },\n]\n\u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> bodyAt = \u003Cspan class=\"hljs-title function_\">useStored\u003C\u002Fspan>(\u003Cspan class=\"hljs-string\">&#x27;jevvieBody&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-number\">0\u003C\u002Fspan>, \u003Cspan class=\"hljs-title function_\">indexBelow\u003C\u002Fspan>(\u003Cspan class=\"hljs-variable constant_\">BODIES\u003C\u002Fspan>.\u003Cspan class=\"hljs-property\">length\u003C\u002Fspan>))\n\u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> picked = \u003Cspan class=\"hljs-title function_\">ref\u003C\u002Fspan>(\u003Cspan class=\"hljs-literal\">false\u003C\u002Fspan>)\n\u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> bodyShown = \u003Cspan class=\"hljs-title function_\">computed\u003C\u002Fspan>(\u003Cspan class=\"hljs-function\">() =&gt;\u003C\u002Fspan> { \u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> own = \u003Cspan class=\"hljs-variable constant_\">BODIES\u003C\u002Fspan>.\u003Cspan class=\"hljs-title function_\">findIndex\u003C\u002Fspan>(\u003Cspan class=\"hljs-function\">(\u003Cspan class=\"hljs-params\">b\u003C\u002Fspan>) =&gt;\u003C\u002Fspan> b.\u003Cspan class=\"hljs-property\">shape\u003C\u002Fspan> === route.\u003Cspan class=\"hljs-property\">meta\u003C\u002Fspan>.\u003Cspan class=\"hljs-property\">jevvie\u003C\u002Fspan>); \u003Cspan class=\"hljs-keyword\">return\u003C\u002Fspan> own &gt;= \u003Cspan class=\"hljs-number\">0\u003C\u002Fspan> &amp;&amp; !picked.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan> ? own : bodyAt.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan> })\n\u003Cspan class=\"hljs-keyword\">let\u003C\u002Fspan> mounting = \u003Cspan class=\"hljs-title class_\">Promise\u003C\u002Fspan>.\u003Cspan class=\"hljs-title function_\">resolve\u003C\u002Fspan>()\n\u003Cspan class=\"hljs-title function_\">watch\u003C\u002Fspan>(bodyShown, \u003Cspan class=\"hljs-function\">() =&gt;\u003C\u002Fspan> { mounting = \u003Cspan class=\"hljs-title function_\">mountBody\u003C\u002Fspan>() })\n\u003Cspan class=\"hljs-keyword\">async\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">function\u003C\u002Fspan> \u003Cspan class=\"hljs-title function_\">mountBody\u003C\u002Fspan>(\u003Cspan class=\"hljs-params\">\u003C\u002Fspan>) {\n  view?.\u003Cspan class=\"hljs-title function_\">dispose\u003C\u002Fspan>(); view = \u003Cspan class=\"hljs-literal\">undefined\u003C\u002Fspan>\n  \u003Cspan class=\"hljs-keyword\">await\u003C\u002Fspan> \u003Cspan class=\"hljs-title function_\">nextTick\u003C\u002Fspan>()\n  \u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> { mountCharacter } = \u003Cspan class=\"hljs-keyword\">await\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">import\u003C\u002Fspan>(\u003Cspan class=\"hljs-string\">&#x27;@cw\u002Fjevvie\u002Fcharacter&#x27;\u003C\u002Fspan>)\n  \u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> { shape, wear } = \u003Cspan class=\"hljs-variable constant_\">BODIES\u003C\u002Fspan>[bodyShown.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan>]!\n  \u003Cspan class=\"hljs-keyword\">if\u003C\u002Fspan> (canvas.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan>) view = \u003Cspan class=\"hljs-keyword\">await\u003C\u002Fspan> \u003Cspan class=\"hljs-title function_\">mountCharacter\u003C\u002Fspan>(canvas.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan>, { reduced, \u003Cspan class=\"hljs-attr\">colors\u003C\u002Fspan>: jevvieColors, shape, wear })\n}\n\u003Cspan class=\"hljs-keyword\">function\u003C\u002Fspan> \u003Cspan class=\"hljs-title function_\">nextBody\u003C\u002Fspan>(\u003Cspan class=\"hljs-params\">\u003C\u002Fspan>) {\n  menu.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan> = \u003Cspan class=\"hljs-literal\">false\u003C\u002Fspan>\n  \u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> next = (bodyShown.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan> + \u003Cspan class=\"hljs-number\">1\u003C\u002Fspan>) % \u003Cspan class=\"hljs-variable constant_\">BODIES\u003C\u002Fspan>.\u003Cspan class=\"hljs-property\">length\u003C\u002Fspan>\n  picked.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan> = \u003Cspan class=\"hljs-literal\">true\u003C\u002Fspan>; bodyAt.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan> = next\n  \u003Cspan class=\"hljs-keyword\">void\u003C\u002Fspan> \u003Cspan class=\"hljs-title function_\">nextTick\u003C\u002Fspan>().\u003Cspan class=\"hljs-title function_\">then\u003C\u002Fspan>(\u003Cspan class=\"hljs-function\">() =&gt;\u003C\u002Fspan> mounting).\u003Cspan class=\"hljs-title function_\">then\u003C\u002Fspan>(\u003Cspan class=\"hljs-function\">() =&gt;\u003C\u002Fspan> { view?.\u003Cspan class=\"hljs-title function_\">squash\u003C\u002Fspan>(); \u003Cspan class=\"hljs-title function_\">speak\u003C\u002Fspan>(\u003Cspan class=\"hljs-title function_\">fill\u003C\u002Fspan>(companion.\u003Cspan class=\"hljs-property\">menu\u003C\u002Fspan>.\u003Cspan class=\"hljs-property\">bodyIs\u003C\u002Fspan>, { \u003Cspan class=\"hljs-attr\">body\u003C\u002Fspan>: \u003Cspan class=\"hljs-variable constant_\">BODIES\u003C\u002Fspan>[next]!.\u003Cspan class=\"hljs-property\">name\u003C\u002Fspan> })) })\n}\n\n\u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> \u003Cspan class=\"hljs-title function_\">bounds\u003C\u002Fspan> = (\u003Cspan class=\"hljs-params\">\u003C\u002Fspan>) =&gt; \u003Cspan class=\"hljs-keyword\">new\u003C\u002Fspan> \u003Cspan class=\"hljs-title class_\">DOMRect\u003C\u002Fspan>(\u003Cspan class=\"hljs-number\">0\u003C\u002Fspan>, \u003Cspan class=\"hljs-number\">0\u003C\u002Fspan>, innerWidth, innerHeight)\n\u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> saved = readStore&lt;{ \u003Cspan class=\"hljs-attr\">x\u003C\u002Fspan>: number; \u003Cspan class=\"hljs-attr\">y\u003C\u002Fspan>: number }&gt;(\u003Cspan class=\"hljs-string\">&#x27;jevviePlace&#x27;\u003C\u002Fspan>)\n\u003Cspan class=\"hljs-keyword\">let\u003C\u002Fspan> place = saved ?? { \u003Cspan class=\"hljs-attr\">x\u003C\u002Fspan>: \u003Cspan class=\"hljs-number\">0\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">y\u003C\u002Fspan>: \u003Cspan class=\"hljs-number\">0\u003C\u002Fspan> }, moved = \u003Cspan class=\"hljs-literal\">false\u003C\u002Fspan>\n\u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> \u003Cspan class=\"hljs-variable constant_\">SWING\u003C\u002Fspan> = \u003Cspan class=\"hljs-number\">18\u003C\u002Fspan>, \u003Cspan class=\"hljs-variable constant_\">FLING\u003C\u002Fspan> = \u003Cspan class=\"hljs-number\">1.6\u003C\u002Fspan>\n\u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> swing = \u003Cspan class=\"hljs-title function_\">ref\u003C\u002Fspan>(\u003Cspan class=\"hljs-number\">0\u003C\u002Fspan>)\n\u003Cspan class=\"hljs-keyword\">let\u003C\u002Fspan> grip = { ...place, \u003Cspan class=\"hljs-attr\">at\u003C\u002Fspan>: \u003Cspan class=\"hljs-number\">0\u003C\u002Fspan> }, flung = \u003Cspan class=\"hljs-literal\">false\u003C\u002Fspan>\n\u003Cspan class=\"hljs-title function_\">useDraggable\u003C\u002Fspan>(root, handle, {\n  \u003Cspan class=\"hljs-attr\">initial\u003C\u002Fspan>: saved,\n  \u003Cspan class=\"hljs-attr\">onDrag\u003C\u002Fspan>: \u003Cspan class=\"hljs-function\">(\u003Cspan class=\"hljs-params\">x, y\u003C\u002Fspan>) =&gt;\u003C\u002Fspan> {\n    \u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> now = performance.\u003Cspan class=\"hljs-title function_\">now\u003C\u002Fspan>(), dt = \u003Cspan class=\"hljs-title class_\">Math\u003C\u002Fspan>.\u003Cspan class=\"hljs-title function_\">max\u003C\u002Fspan>(\u003Cspan class=\"hljs-number\">16\u003C\u002Fspan>, now - grip.\u003Cspan class=\"hljs-property\">at\u003C\u002Fspan>), dx = x - grip.\u003Cspan class=\"hljs-property\">x\u003C\u002Fspan>, dy = y - grip.\u003Cspan class=\"hljs-property\">y\u003C\u002Fspan>\n    \u003Cspan class=\"hljs-keyword\">if\u003C\u002Fspan> (now - grip.\u003Cspan class=\"hljs-property\">at\u003C\u002Fspan> &gt; \u003Cspan class=\"hljs-number\">500\u003C\u002Fspan>) flung = \u003Cspan class=\"hljs-literal\">false\u003C\u002Fspan>\n    grip = { x, y, \u003Cspan class=\"hljs-attr\">at\u003C\u002Fspan>: now }\n    \u003Cspan class=\"hljs-keyword\">if\u003C\u002Fspan> (!reduced) swing.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan> = \u003Cspan class=\"hljs-title class_\">Math\u003C\u002Fspan>.\u003Cspan class=\"hljs-title function_\">max\u003C\u002Fspan>(-\u003Cspan class=\"hljs-variable constant_\">SWING\u003C\u002Fspan>, \u003Cspan class=\"hljs-title class_\">Math\u003C\u002Fspan>.\u003Cspan class=\"hljs-title function_\">min\u003C\u002Fspan>(\u003Cspan class=\"hljs-variable constant_\">SWING\u003C\u002Fspan>, (dx \u002F dt) * \u003Cspan class=\"hljs-number\">10\u003C\u002Fspan>))\n    \u003Cspan class=\"hljs-keyword\">if\u003C\u002Fspan> (!flung &amp;&amp; \u003Cspan class=\"hljs-title class_\">Math\u003C\u002Fspan>.\u003Cspan class=\"hljs-title function_\">hypot\u003C\u002Fspan>(dx, dy) \u002F dt &gt; \u003Cspan class=\"hljs-variable constant_\">FLING\u003C\u002Fspan>) { flung = \u003Cspan class=\"hljs-literal\">true\u003C\u002Fspan>; \u003Cspan class=\"hljs-title function_\">feel\u003C\u002Fspan>(\u003Cspan class=\"hljs-string\">&#x27;surprised&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-number\">1400\u003C\u002Fspan>); \u003Cspan class=\"hljs-keyword\">void\u003C\u002Fspan> \u003Cspan class=\"hljs-title function_\">trick\u003C\u002Fspan>(\u003Cspan class=\"hljs-string\">&#x27;spin&#x27;\u003C\u002Fspan>); \u003Cspan class=\"hljs-title function_\">speak\u003C\u002Fspan>(\u003Cspan class=\"hljs-title function_\">line\u003C\u002Fspan>(companion.\u003Cspan class=\"hljs-property\">fling\u003C\u002Fspan>)) }\n  },\n  \u003Cspan class=\"hljs-attr\">onMove\u003C\u002Fspan>: \u003Cspan class=\"hljs-function\">(\u003Cspan class=\"hljs-params\">x, y\u003C\u002Fspan>) =&gt;\u003C\u002Fspan> {\n    swing.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan> = \u003Cspan class=\"hljs-number\">0\u003C\u002Fspan>\n    moved = \u003Cspan class=\"hljs-title class_\">Math\u003C\u002Fspan>.\u003Cspan class=\"hljs-title function_\">abs\u003C\u002Fspan>(x - place.\u003Cspan class=\"hljs-property\">x\u003C\u002Fspan>) + \u003Cspan class=\"hljs-title class_\">Math\u003C\u002Fspan>.\u003Cspan class=\"hljs-title function_\">abs\u003C\u002Fspan>(y - place.\u003Cspan class=\"hljs-property\">y\u003C\u002Fspan>) &gt; \u003Cspan class=\"hljs-number\">3\u003C\u002Fspan>\n    place = { x, y }\n    grip = { ...place, \u003Cspan class=\"hljs-attr\">at\u003C\u002Fspan>: \u003Cspan class=\"hljs-number\">0\u003C\u002Fspan> }\n    \u003Cspan class=\"hljs-title function_\">measure\u003C\u002Fspan>()\n    \u003Cspan class=\"hljs-keyword\">if\u003C\u002Fspan> (!moved) \u003Cspan class=\"hljs-keyword\">return\u003C\u002Fspan>\n    \u003Cspan class=\"hljs-title function_\">writeStore\u003C\u002Fspan>(\u003Cspan class=\"hljs-string\">&#x27;jevviePlace&#x27;\u003C\u002Fspan>, place)\n    view?.\u003Cspan class=\"hljs-title function_\">squash\u003C\u002Fspan>()\n    \u003Cspan class=\"hljs-keyword\">if\u003C\u002Fspan> (!flung) { \u003Cspan class=\"hljs-title function_\">feel\u003C\u002Fspan>(\u003Cspan class=\"hljs-string\">&#x27;happy&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-number\">900\u003C\u002Fspan>); \u003Cspan class=\"hljs-title function_\">speak\u003C\u002Fspan>(\u003Cspan class=\"hljs-title function_\">line\u003C\u002Fspan>(companion.\u003Cspan class=\"hljs-property\">drop\u003C\u002Fspan>)) }\n    flung = \u003Cspan class=\"hljs-literal\">false\u003C\u002Fspan>\n  },\n})\n\n\u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> { \u003Cspan class=\"hljs-attr\">x\u003C\u002Fspan>: mx, \u003Cspan class=\"hljs-attr\">y\u003C\u002Fspan>: my } = \u003Cspan class=\"hljs-title function_\">useMouse\u003C\u002Fspan>({ \u003Cspan class=\"hljs-attr\">type\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;client&#x27;\u003C\u002Fspan> })\n\u003Cspan class=\"hljs-title function_\">watchThrottled\u003C\u002Fspan>([mx, my], \u003Cspan class=\"hljs-function\">(\u003Cspan class=\"hljs-params\">[x, y]\u003C\u002Fspan>) =&gt;\u003C\u002Fspan> {\n  \u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> r = body.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan>?.\u003Cspan class=\"hljs-title function_\">getBoundingClientRect\u003C\u002Fspan>()\n  \u003Cspan class=\"hljs-keyword\">if\u003C\u002Fspan> (r) view?.\u003Cspan class=\"hljs-title function_\">look\u003C\u002Fspan>(x - (r.\u003Cspan class=\"hljs-property\">left\u003C\u002Fspan> + r.\u003Cspan class=\"hljs-property\">width\u003C\u002Fspan> \u002F \u003Cspan class=\"hljs-number\">2\u003C\u002Fspan>), y - (r.\u003Cspan class=\"hljs-property\">top\u003C\u002Fspan> + r.\u003Cspan class=\"hljs-property\">height\u003C\u002Fspan> \u002F \u003Cspan class=\"hljs-number\">2\u003C\u002Fspan>))\n}, { \u003Cspan class=\"hljs-attr\">throttle\u003C\u002Fspan>: \u003Cspan class=\"hljs-number\">50\u003C\u002Fspan> })\n\u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> { idle, lastActive } = \u003Cspan class=\"hljs-title function_\">useIdle\u003C\u002Fspan>(\u003Cspan class=\"hljs-number\">60_000\u003C\u002Fspan>)\n\u003Cspan class=\"hljs-title function_\">watch\u003C\u002Fspan>(idle, \u003Cspan class=\"hljs-function\">(\u003Cspan class=\"hljs-params\">asleep\u003C\u002Fspan>) =&gt;\u003C\u002Fspan> {\n  \u003Cspan class=\"hljs-keyword\">if\u003C\u002Fspan> (sulking) \u003Cspan class=\"hljs-keyword\">return\u003C\u002Fspan>\n  \u003Cspan class=\"hljs-title function_\">feel\u003C\u002Fspan>(asleep ? \u003Cspan class=\"hljs-string\">&#x27;sleep&#x27;\u003C\u002Fspan> : \u003Cspan class=\"hljs-string\">&#x27;idle&#x27;\u003C\u002Fspan>)\n  \u003Cspan class=\"hljs-keyword\">if\u003C\u002Fspan> (asleep) \u003Cspan class=\"hljs-title function_\">speak\u003C\u002Fspan>(\u003Cspan class=\"hljs-title function_\">line\u003C\u002Fspan>(companion.\u003Cspan class=\"hljs-property\">sleep\u003C\u002Fspan>), \u003Cspan class=\"hljs-literal\">true\u003C\u002Fspan>)\n  \u003Cspan class=\"hljs-keyword\">else\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">if\u003C\u002Fspan> (say.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan> &amp;&amp; companion.\u003Cspan class=\"hljs-property\">sleep\u003C\u002Fspan>.\u003Cspan class=\"hljs-title function_\">includes\u003C\u002Fspan>(say.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan>)) \u003Cspan class=\"hljs-title function_\">speak\u003C\u002Fspan>(\u003Cspan class=\"hljs-title function_\">line\u003C\u002Fspan>(companion.\u003Cspan class=\"hljs-property\">wake\u003C\u002Fspan>))\n})\n\u003Cspan class=\"hljs-title function_\">useIntervalFn\u003C\u002Fspan>(\u003Cspan class=\"hljs-function\">() =&gt;\u003C\u002Fspan> {\n  \u003Cspan class=\"hljs-keyword\">if\u003C\u002Fspan> (!idle.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan> &amp;&amp; !busy.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan> &amp;&amp; !open.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan> &amp;&amp; !sulking &amp;&amp; !\u003Cspan class=\"hljs-variable language_\">document\u003C\u002Fspan>.\u003Cspan class=\"hljs-property\">hidden\u003C\u002Fspan> &amp;&amp; \u003Cspan class=\"hljs-title class_\">Math\u003C\u002Fspan>.\u003Cspan class=\"hljs-title function_\">random\u003C\u002Fspan>() &lt; \u003Cspan class=\"hljs-number\">0.5\u003C\u002Fspan>) \u003Cspan class=\"hljs-keyword\">void\u003C\u002Fspan> \u003Cspan class=\"hljs-title function_\">trick\u003C\u002Fspan>(\u003Cspan class=\"hljs-title function_\">random\u003C\u002Fspan>([\u003Cspan class=\"hljs-string\">&#x27;look&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-string\">&#x27;stretch&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-string\">&#x27;tap&#x27;\u003C\u002Fspan>] \u003Cspan class=\"hljs-keyword\">as\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan>))\n}, \u003Cspan class=\"hljs-number\">17_000\u003C\u002Fspan>)\n\n\u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> suggestions = \u003Cspan class=\"hljs-title function_\">computed\u003C\u002Fspan>(\u003Cspan class=\"hljs-function\">() =&gt;\u003C\u002Fspan> \u003Cspan class=\"hljs-title function_\">suggestionsFor\u003C\u002Fspan>(companion.\u003Cspan class=\"hljs-property\">suggest\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">as\u003C\u002Fspan> \u003Cspan class=\"hljs-title class_\">Suggestion\u003C\u002Fspan>[], \u003Cspan class=\"hljs-title function_\">siteTools\u003C\u002Fspan>(), route.\u003Cspan class=\"hljs-property\">path\u003C\u002Fspan>, \u003Cspan class=\"hljs-number\">20\u003C\u002Fspan>))\n\u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> more = \u003Cspan class=\"hljs-title function_\">useStored\u003C\u002Fspan>(\u003Cspan class=\"hljs-string\">&#x27;jevvieMore&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-literal\">false\u003C\u002Fspan>, \u003Cspan class=\"hljs-title function_\">oneOf\u003C\u002Fspan>(\u003Cspan class=\"hljs-literal\">true\u003C\u002Fspan>, \u003Cspan class=\"hljs-literal\">false\u003C\u002Fspan>))\n\u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> groups = \u003Cspan class=\"hljs-title function_\">computed\u003C\u002Fspan>(\u003Cspan class=\"hljs-function\">() =&gt;\u003C\u002Fspan> {\n  \u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> all = [{ \u003Cspan class=\"hljs-attr\">name\u003C\u002Fspan>: companion.\u003Cspan class=\"hljs-property\">panel\u003C\u002Fspan>.\u003Cspan class=\"hljs-property\">here\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">global\u003C\u002Fspan>: \u003Cspan class=\"hljs-literal\">false\u003C\u002Fspan> }, { \u003Cspan class=\"hljs-attr\">name\u003C\u002Fspan>: companion.\u003Cspan class=\"hljs-property\">panel\u003C\u002Fspan>.\u003Cspan class=\"hljs-property\">anywhere\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">global\u003C\u002Fspan>: \u003Cspan class=\"hljs-literal\">true\u003C\u002Fspan> }]\n    .\u003Cspan class=\"hljs-title function_\">map\u003C\u002Fspan>(\u003Cspan class=\"hljs-function\">(\u003Cspan class=\"hljs-params\">{ name, \u003Cspan class=\"hljs-variable language_\">global\u003C\u002Fspan> }\u003C\u002Fspan>) =&gt;\u003C\u002Fspan> ({ name, \u003Cspan class=\"hljs-attr\">items\u003C\u002Fspan>: suggestions.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan>.\u003Cspan class=\"hljs-title function_\">filter\u003C\u002Fspan>(\u003Cspan class=\"hljs-function\">(\u003Cspan class=\"hljs-params\">s\u003C\u002Fspan>) =&gt;\u003C\u002Fspan> \u003Cspan class=\"hljs-variable constant_\">GLOBAL_TOOLS\u003C\u002Fspan>.\u003Cspan class=\"hljs-title function_\">has\u003C\u002Fspan>(s.\u003Cspan class=\"hljs-property\">tool\u003C\u002Fspan>) === \u003Cspan class=\"hljs-variable language_\">global\u003C\u002Fspan>) })).\u003Cspan class=\"hljs-title function_\">filter\u003C\u002Fspan>(\u003Cspan class=\"hljs-function\">(\u003Cspan class=\"hljs-params\">g\u003C\u002Fspan>) =&gt;\u003C\u002Fspan> g.\u003Cspan class=\"hljs-property\">items\u003C\u002Fspan>.\u003Cspan class=\"hljs-property\">length\u003C\u002Fspan>)\n  \u003Cspan class=\"hljs-keyword\">if\u003C\u002Fspan> (more.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan>) \u003Cspan class=\"hljs-keyword\">return\u003C\u002Fspan> all\n  \u003Cspan class=\"hljs-keyword\">let\u003C\u002Fspan> left = \u003Cspan class=\"hljs-number\">3\u003C\u002Fspan>\n  \u003Cspan class=\"hljs-keyword\">return\u003C\u002Fspan> all.\u003Cspan class=\"hljs-title function_\">map\u003C\u002Fspan>(\u003Cspan class=\"hljs-function\">(\u003Cspan class=\"hljs-params\">g\u003C\u002Fspan>) =&gt;\u003C\u002Fspan> { \u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> items = g.\u003Cspan class=\"hljs-property\">items\u003C\u002Fspan>.\u003Cspan class=\"hljs-title function_\">slice\u003C\u002Fspan>(\u003Cspan class=\"hljs-number\">0\u003C\u002Fspan>, left); left -= items.\u003Cspan class=\"hljs-property\">length\u003C\u002Fspan>; \u003Cspan class=\"hljs-keyword\">return\u003C\u002Fspan> { ...g, items } }).\u003Cspan class=\"hljs-title function_\">filter\u003C\u002Fspan>(\u003Cspan class=\"hljs-function\">(\u003Cspan class=\"hljs-params\">g\u003C\u002Fspan>) =&gt;\u003C\u002Fspan> g.\u003Cspan class=\"hljs-property\">items\u003C\u002Fspan>.\u003Cspan class=\"hljs-property\">length\u003C\u002Fspan>)\n})\n\u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> hiddenCount = \u003Cspan class=\"hljs-title function_\">computed\u003C\u002Fspan>(\u003Cspan class=\"hljs-function\">() =&gt;\u003C\u002Fspan> suggestions.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan>.\u003Cspan class=\"hljs-property\">length\u003C\u002Fspan> - groups.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan>.\u003Cspan class=\"hljs-title function_\">reduce\u003C\u002Fspan>(\u003Cspan class=\"hljs-function\">(\u003Cspan class=\"hljs-params\">n, g\u003C\u002Fspan>) =&gt;\u003C\u002Fspan> n + g.\u003Cspan class=\"hljs-property\">items\u003C\u002Fspan>.\u003Cspan class=\"hljs-property\">length\u003C\u002Fspan>, \u003Cspan class=\"hljs-number\">0\u003C\u002Fspan>))\n\u003Cspan class=\"hljs-keyword\">function\u003C\u002Fspan> \u003Cspan class=\"hljs-title function_\">openPanel\u003C\u002Fspan>(\u003Cspan class=\"hljs-params\">\u003C\u002Fspan>) { \u003Cspan class=\"hljs-title function_\">hush\u003C\u002Fspan>(); menu.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan> = \u003Cspan class=\"hljs-literal\">false\u003C\u002Fspan>; open.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan> = \u003Cspan class=\"hljs-literal\">true\u003C\u002Fspan>; \u003Cspan class=\"hljs-title function_\">feel\u003C\u002Fspan>(\u003Cspan class=\"hljs-string\">&#x27;happy&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-number\">900\u003C\u002Fspan>) }\n\u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> \u003Cspan class=\"hljs-title function_\">closePanel\u003C\u002Fspan> = (\u003Cspan class=\"hljs-params\">\u003C\u002Fspan>) =&gt; { open.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan> = \u003Cspan class=\"hljs-literal\">false\u003C\u002Fspan>; \u003Cspan class=\"hljs-title function_\">hush\u003C\u002Fspan>() }\n\u003Cspan class=\"hljs-keyword\">function\u003C\u002Fspan> \u003Cspan class=\"hljs-title function_\">suggest\u003C\u002Fspan>(\u003Cspan class=\"hljs-params\">s?: Suggestion\u003C\u002Fspan>) {\n  \u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> pick = s ?? \u003Cspan class=\"hljs-title function_\">random\u003C\u002Fspan>(suggestions.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan>)\n  \u003Cspan class=\"hljs-keyword\">if\u003C\u002Fspan> (pick) \u003Cspan class=\"hljs-keyword\">void\u003C\u002Fspan> \u003Cspan class=\"hljs-title function_\">act\u003C\u002Fspan>(pick.\u003Cspan class=\"hljs-property\">tool\u003C\u002Fspan>, pick.\u003Cspan class=\"hljs-property\">arg\u003C\u002Fspan>)\n}\n\n\u003Cspan class=\"hljs-keyword\">let\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">pokes\u003C\u002Fspan>: number[] = [], sulking = \u003Cspan class=\"hljs-literal\">false\u003C\u002Fspan>\n\u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> clickLater = \u003Cspan class=\"hljs-title function_\">useTimeoutFn\u003C\u002Fspan>(poke, \u003Cspan class=\"hljs-number\">220\u003C\u002Fspan>, { \u003Cspan class=\"hljs-attr\">immediate\u003C\u002Fspan>: \u003Cspan class=\"hljs-literal\">false\u003C\u002Fspan> })\n\u003Cspan class=\"hljs-keyword\">function\u003C\u002Fspan> \u003Cspan class=\"hljs-title function_\">click\u003C\u002Fspan>(\u003Cspan class=\"hljs-params\">\u003C\u002Fspan>) {\n  \u003Cspan class=\"hljs-keyword\">if\u003C\u002Fspan> (moved) { moved = \u003Cspan class=\"hljs-literal\">false\u003C\u002Fspan>; \u003Cspan class=\"hljs-keyword\">return\u003C\u002Fspan> }\n  clickLater.\u003Cspan class=\"hljs-title function_\">start\u003C\u002Fspan>()\n}\n\u003Cspan class=\"hljs-keyword\">function\u003C\u002Fspan> \u003Cspan class=\"hljs-title function_\">poke\u003C\u002Fspan>(\u003Cspan class=\"hljs-params\">\u003C\u002Fspan>) {\n  \u003Cspan class=\"hljs-keyword\">if\u003C\u002Fspan> (sulking) \u003Cspan class=\"hljs-keyword\">return\u003C\u002Fspan>\n  view?.\u003Cspan class=\"hljs-title function_\">squash\u003C\u002Fspan>(\u003Cspan class=\"hljs-number\">0.6\u003C\u002Fspan>)\n  \u003Cspan class=\"hljs-keyword\">if\u003C\u002Fspan> (!open.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan> &amp;&amp; introduce) {\n    introduce = \u003Cspan class=\"hljs-literal\">false\u003C\u002Fspan>; greeting.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan> = \u003Cspan class=\"hljs-literal\">true\u003C\u002Fspan>\n    \u003Cspan class=\"hljs-keyword\">return\u003C\u002Fspan> \u003Cspan class=\"hljs-title function_\">speak\u003C\u002Fspan>(companion.\u003Cspan class=\"hljs-property\">greet\u003C\u002Fspan>.\u003Cspan class=\"hljs-property\">text\u003C\u002Fspan>, \u003Cspan class=\"hljs-literal\">true\u003C\u002Fspan>, [{ \u003Cspan class=\"hljs-attr\">label\u003C\u002Fspan>: companion.\u003Cspan class=\"hljs-property\">greet\u003C\u002Fspan>.\u003Cspan class=\"hljs-property\">button\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">run\u003C\u002Fspan>: openPanel }])\n  }\n  \u003Cspan class=\"hljs-keyword\">if\u003C\u002Fspan> (!open.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan>) \u003Cspan class=\"hljs-keyword\">return\u003C\u002Fspan> \u003Cspan class=\"hljs-title function_\">openPanel\u003C\u002Fspan>()\n  \u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> now = \u003Cspan class=\"hljs-title class_\">Date\u003C\u002Fspan>.\u003Cspan class=\"hljs-title function_\">now\u003C\u002Fspan>()\n  pokes = [...pokes.\u003Cspan class=\"hljs-title function_\">filter\u003C\u002Fspan>(\u003Cspan class=\"hljs-function\">(\u003Cspan class=\"hljs-params\">t\u003C\u002Fspan>) =&gt;\u003C\u002Fspan> now - t &lt; \u003Cspan class=\"hljs-number\">8000\u003C\u002Fspan>), now]\n  \u003Cspan class=\"hljs-keyword\">if\u003C\u002Fspan> (pokes.\u003Cspan class=\"hljs-property\">length\u003C\u002Fspan> &lt; \u003Cspan class=\"hljs-number\">5\u003C\u002Fspan>) { \u003Cspan class=\"hljs-title function_\">feel\u003C\u002Fspan>(\u003Cspan class=\"hljs-title class_\">Math\u003C\u002Fspan>.\u003Cspan class=\"hljs-title function_\">random\u003C\u002Fspan>() &lt; \u003Cspan class=\"hljs-number\">0.5\u003C\u002Fspan> ? \u003Cspan class=\"hljs-string\">&#x27;surprised&#x27;\u003C\u002Fspan> : \u003Cspan class=\"hljs-string\">&#x27;happy&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-number\">700\u003C\u002Fspan>); \u003Cspan class=\"hljs-keyword\">return\u003C\u002Fspan> \u003Cspan class=\"hljs-title function_\">speak\u003C\u002Fspan>(\u003Cspan class=\"hljs-title function_\">line\u003C\u002Fspan>(companion.\u003Cspan class=\"hljs-property\">poke\u003C\u002Fspan>)) }\n  pokes = []; sulking = \u003Cspan class=\"hljs-literal\">true\u003C\u002Fspan>; open.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan> = \u003Cspan class=\"hljs-literal\">false\u003C\u002Fspan>\n  \u003Cspan class=\"hljs-title function_\">feel\u003C\u002Fspan>(\u003Cspan class=\"hljs-string\">&#x27;sulk&#x27;\u003C\u002Fspan>); \u003Cspan class=\"hljs-title function_\">speak\u003C\u002Fspan>(\u003Cspan class=\"hljs-title function_\">line\u003C\u002Fspan>(companion.\u003Cspan class=\"hljs-property\">sulk\u003C\u002Fspan>))\n  \u003Cspan class=\"hljs-built_in\">setTimeout\u003C\u002Fspan>(\u003Cspan class=\"hljs-function\">() =&gt;\u003C\u002Fspan> { sulking = \u003Cspan class=\"hljs-literal\">false\u003C\u002Fspan>; \u003Cspan class=\"hljs-title function_\">feel\u003C\u002Fspan>(\u003Cspan class=\"hljs-string\">&#x27;idle&#x27;\u003C\u002Fspan>) }, \u003Cspan class=\"hljs-number\">7000\u003C\u002Fspan>)\n}\n\u003Cspan class=\"hljs-keyword\">function\u003C\u002Fspan> \u003Cspan class=\"hljs-title function_\">animate\u003C\u002Fspan>(\u003Cspan class=\"hljs-params\">\u003C\u002Fspan>) {\n  clickLater.\u003Cspan class=\"hljs-title function_\">stop\u003C\u002Fspan>()\n  \u003Cspan class=\"hljs-keyword\">if\u003C\u002Fspan> (sulking) \u003Cspan class=\"hljs-keyword\">return\u003C\u002Fspan>\n  menu.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan> = \u003Cspan class=\"hljs-literal\">false\u003C\u002Fspan>\n  \u003Cspan class=\"hljs-keyword\">void\u003C\u002Fspan> \u003Cspan class=\"hljs-title function_\">trick\u003C\u002Fspan>(); \u003Cspan class=\"hljs-title function_\">feel\u003C\u002Fspan>(\u003Cspan class=\"hljs-string\">&#x27;happy&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-number\">1200\u003C\u002Fspan>)\n  \u003Cspan class=\"hljs-title function_\">speak\u003C\u002Fspan>(\u003Cspan class=\"hljs-title function_\">line\u003C\u002Fspan>(companion.\u003Cspan class=\"hljs-property\">tricks\u003C\u002Fspan>))\n}\n\u003Cspan class=\"hljs-keyword\">function\u003C\u002Fspan> \u003Cspan class=\"hljs-title function_\">openMenu\u003C\u002Fspan>(\u003Cspan class=\"hljs-params\">\u003C\u002Fspan>) { menu.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan> = !menu.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan>; \u003Cspan class=\"hljs-keyword\">if\u003C\u002Fspan> (menu.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan>) open.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan> = \u003Cspan class=\"hljs-literal\">false\u003C\u002Fspan> }\n\n\u003Cspan class=\"hljs-keyword\">let\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">flight\u003C\u002Fspan>: \u003Cspan class=\"hljs-title class_\">Animation\u003C\u002Fspan> | \u003Cspan class=\"hljs-literal\">undefined\u003C\u002Fspan>\n\u003Cspan class=\"hljs-keyword\">async\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">function\u003C\u002Fspan> \u003Cspan class=\"hljs-title function_\">hop\u003C\u002Fspan>(\u003Cspan class=\"hljs-params\">dx: number, dy: number\u003C\u002Fspan>) {\n  \u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> el = body.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan>\n  \u003Cspan class=\"hljs-keyword\">if\u003C\u002Fspan> (!el) \u003Cspan class=\"hljs-keyword\">return\u003C\u002Fspan> \u003Cspan class=\"hljs-literal\">false\u003C\u002Fspan>\n  \u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">from\u003C\u002Fspan> = \u003Cspan class=\"hljs-keyword\">new\u003C\u002Fspan> \u003Cspan class=\"hljs-title class_\">DOMMatrixReadOnly\u003C\u002Fspan>(\u003Cspan class=\"hljs-title function_\">getComputedStyle\u003C\u002Fspan>(el).\u003Cspan class=\"hljs-property\">transform\u003C\u002Fspan>)\n  flight?.\u003Cspan class=\"hljs-title function_\">cancel\u003C\u002Fspan>()\n  \u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> rise = \u003Cspan class=\"hljs-number\">70\u003C\u002Fspan> + \u003Cspan class=\"hljs-title class_\">Math\u003C\u002Fspan>.\u003Cspan class=\"hljs-title function_\">abs\u003C\u002Fspan>(dy - \u003Cspan class=\"hljs-keyword\">from\u003C\u002Fspan>.\u003Cspan class=\"hljs-property\">f\u003C\u002Fspan>) \u002F \u003Cspan class=\"hljs-number\">2\u003C\u002Fspan>\n  \u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> keyframes = \u003Cspan class=\"hljs-title class_\">Array\u003C\u002Fspan>.\u003Cspan class=\"hljs-title function_\">from\u003C\u002Fspan>({ \u003Cspan class=\"hljs-attr\">length\u003C\u002Fspan>: \u003Cspan class=\"hljs-number\">9\u003C\u002Fspan> }, \u003Cspan class=\"hljs-function\">(\u003Cspan class=\"hljs-params\">_, i\u003C\u002Fspan>) =&gt;\u003C\u002Fspan> {\n    \u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> t = i \u002F \u003Cspan class=\"hljs-number\">8\u003C\u002Fspan>\n    \u003Cspan class=\"hljs-keyword\">return\u003C\u002Fspan> { \u003Cspan class=\"hljs-attr\">transform\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">`translate(\u003Cspan class=\"hljs-subst\">${\u003Cspan class=\"hljs-keyword\">from\u003C\u002Fspan>.e + (dx - \u003Cspan class=\"hljs-keyword\">from\u003C\u002Fspan>.e) * t}\u003C\u002Fspan>px, \u003Cspan class=\"hljs-subst\">${\u003Cspan class=\"hljs-keyword\">from\u003C\u002Fspan>.f + (dy - \u003Cspan class=\"hljs-keyword\">from\u003C\u002Fspan>.f) * t - \u003Cspan class=\"hljs-number\">4\u003C\u002Fspan> * rise * t * (\u003Cspan class=\"hljs-number\">1\u003C\u002Fspan> - t)}\u003C\u002Fspan>px)`\u003C\u002Fspan> }\n  })\n  \u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> run = flight = el.\u003Cspan class=\"hljs-title function_\">animate\u003C\u002Fspan>(keyframes, { \u003Cspan class=\"hljs-attr\">duration\u003C\u002Fspan>: \u003Cspan class=\"hljs-title class_\">Math\u003C\u002Fspan>.\u003Cspan class=\"hljs-title function_\">min\u003C\u002Fspan>(\u003Cspan class=\"hljs-number\">700\u003C\u002Fspan>, \u003Cspan class=\"hljs-number\">420\u003C\u002Fspan> + \u003Cspan class=\"hljs-title class_\">Math\u003C\u002Fspan>.\u003Cspan class=\"hljs-title function_\">hypot\u003C\u002Fspan>(dx - \u003Cspan class=\"hljs-keyword\">from\u003C\u002Fspan>.\u003Cspan class=\"hljs-property\">e\u003C\u002Fspan>, dy - \u003Cspan class=\"hljs-keyword\">from\u003C\u002Fspan>.\u003Cspan class=\"hljs-property\">f\u003C\u002Fspan>) * \u003Cspan class=\"hljs-number\">0.2\u003C\u002Fspan>), \u003Cspan class=\"hljs-attr\">easing\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;steps(12, jump-end)&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">fill\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;forwards&#x27;\u003C\u002Fspan> })\n  \u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> canvas = trailCanvas.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan>\n  \u003Cspan class=\"hljs-keyword\">if\u003C\u002Fspan> (canvas &amp;&amp; trail === \u003Cspan class=\"hljs-literal\">undefined\u003C\u002Fspan>) trail = \u003Cspan class=\"hljs-keyword\">await\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">import\u003C\u002Fspan>(\u003Cspan class=\"hljs-string\">&#x27;@cw\u002Fjevvie\u002Ftrail&#x27;\u003C\u002Fspan>).\u003Cspan class=\"hljs-title function_\">then\u003C\u002Fspan>(\u003Cspan class=\"hljs-function\">(\u003Cspan class=\"hljs-params\">m\u003C\u002Fspan>) =&gt;\u003C\u002Fspan> m.\u003Cspan class=\"hljs-title function_\">mountTrail\u003C\u002Fspan>(canvas, \u003Cspan class=\"hljs-title function_\">rgb\u003C\u002Fspan>(\u003Cspan class=\"hljs-string\">&#x27;amber&#x27;\u003C\u002Fspan>)))\n  \u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> \u003Cspan class=\"hljs-title function_\">mark\u003C\u002Fspan> = (\u003Cspan class=\"hljs-params\">\u003C\u002Fspan>) =&gt; { \u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> r = el.\u003Cspan class=\"hljs-title function_\">getBoundingClientRect\u003C\u002Fspan>(); trail?.\u003Cspan class=\"hljs-title function_\">add\u003C\u002Fspan>(r.\u003Cspan class=\"hljs-property\">left\u003C\u002Fspan> + r.\u003Cspan class=\"hljs-property\">width\u003C\u002Fspan> \u002F \u003Cspan class=\"hljs-number\">2\u003C\u002Fspan>, r.\u003Cspan class=\"hljs-property\">bottom\u003C\u002Fspan> - \u003Cspan class=\"hljs-number\">6\u003C\u002Fspan>); \u003Cspan class=\"hljs-keyword\">if\u003C\u002Fspan> (run.\u003Cspan class=\"hljs-property\">playState\u003C\u002Fspan> === \u003Cspan class=\"hljs-string\">&#x27;running&#x27;\u003C\u002Fspan>) \u003Cspan class=\"hljs-title function_\">requestAnimationFrame\u003C\u002Fspan>(mark) }\n  \u003Cspan class=\"hljs-title function_\">mark\u003C\u002Fspan>()\n  \u003Cspan class=\"hljs-keyword\">if\u003C\u002Fspan> (!(\u003Cspan class=\"hljs-keyword\">await\u003C\u002Fspan> run.\u003Cspan class=\"hljs-property\">finished\u003C\u002Fspan>.\u003Cspan class=\"hljs-title function_\">then\u003C\u002Fspan>(\u003Cspan class=\"hljs-function\">() =&gt;\u003C\u002Fspan> \u003Cspan class=\"hljs-literal\">true\u003C\u002Fspan>, \u003Cspan class=\"hljs-function\">() =&gt;\u003C\u002Fspan> \u003Cspan class=\"hljs-literal\">false\u003C\u002Fspan>))) \u003Cspan class=\"hljs-keyword\">return\u003C\u002Fspan> \u003Cspan class=\"hljs-literal\">false\u003C\u002Fspan>\n  el.\u003Cspan class=\"hljs-property\">style\u003C\u002Fspan>.\u003Cspan class=\"hljs-property\">transform\u003C\u002Fspan> = \u003Cspan class=\"hljs-string\">`translate(\u003Cspan class=\"hljs-subst\">${dx}\u003C\u002Fspan>px, \u003Cspan class=\"hljs-subst\">${dy}\u003C\u002Fspan>px)`\u003C\u002Fspan>\n  run.\u003Cspan class=\"hljs-title function_\">cancel\u003C\u002Fspan>()\n  view?.\u003Cspan class=\"hljs-title function_\">squash\u003C\u002Fspan>()\n  \u003Cspan class=\"hljs-keyword\">return\u003C\u002Fspan> \u003Cspan class=\"hljs-literal\">true\u003C\u002Fspan>\n}\n\u003Cspan class=\"hljs-keyword\">async\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">function\u003C\u002Fspan> \u003Cspan class=\"hljs-title function_\">visit\u003C\u002Fspan>(\u003Cspan class=\"hljs-params\">target: Element | \u003Cspan class=\"hljs-literal\">null\u003C\u002Fspan> | \u003Cspan class=\"hljs-literal\">undefined\u003C\u002Fspan>\u003C\u002Fspan>) {\n  \u003Cspan class=\"hljs-keyword\">if\u003C\u002Fspan> (!target || !body.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan> || !root.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan>) \u003Cspan class=\"hljs-keyword\">return\u003C\u002Fspan>\n  \u003Cspan class=\"hljs-keyword\">if\u003C\u002Fspan> (reduced) { target.\u003Cspan class=\"hljs-title function_\">animate\u003C\u002Fspan>([{ \u003Cspan class=\"hljs-attr\">outline\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;2px solid currentColor&#x27;\u003C\u002Fspan> }, { \u003Cspan class=\"hljs-attr\">outline\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;2px solid transparent&#x27;\u003C\u002Fspan> }], { \u003Cspan class=\"hljs-attr\">duration\u003C\u002Fspan>: \u003Cspan class=\"hljs-number\">1200\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">easing\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;steps(1, jump-end)&#x27;\u003C\u002Fspan> }); \u003Cspan class=\"hljs-keyword\">return\u003C\u002Fspan> }\n  \u003Cspan class=\"hljs-keyword\">let\u003C\u002Fspan> r = target.\u003Cspan class=\"hljs-title function_\">getBoundingClientRect\u003C\u002Fspan>()\n  \u003Cspan class=\"hljs-keyword\">if\u003C\u002Fspan> (r.\u003Cspan class=\"hljs-property\">bottom\u003C\u002Fspan> &lt; \u003Cspan class=\"hljs-number\">0\u003C\u002Fspan> || r.\u003Cspan class=\"hljs-property\">top\u003C\u002Fspan> &gt; innerHeight) {\n    \u003Cspan class=\"hljs-keyword\">await\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">new\u003C\u002Fspan> \u003Cspan class=\"hljs-title class_\">Promise\u003C\u002Fspan>&lt;\u003Cspan class=\"hljs-keyword\">void\u003C\u002Fspan>&gt;(\u003Cspan class=\"hljs-function\">(\u003Cspan class=\"hljs-params\">done\u003C\u002Fspan>) =&gt;\u003C\u002Fspan> \u003Cspan class=\"hljs-title function_\">scrollPageTo\u003C\u002Fspan>(scrollY + r.\u003Cspan class=\"hljs-property\">top\u003C\u002Fspan> + r.\u003Cspan class=\"hljs-property\">height\u003C\u002Fspan> \u002F \u003Cspan class=\"hljs-number\">2\u003C\u002Fspan> - innerHeight \u002F \u003Cspan class=\"hljs-number\">2\u003C\u002Fspan>, done))\n    r = target.\u003Cspan class=\"hljs-title function_\">getBoundingClientRect\u003C\u002Fspan>()\n  }\n  \u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> home = root.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan>.\u003Cspan class=\"hljs-title function_\">getBoundingClientRect\u003C\u002Fspan>(), me = body.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan>.\u003Cspan class=\"hljs-title function_\">getBoundingClientRect\u003C\u002Fspan>(), b = \u003Cspan class=\"hljs-title function_\">bounds\u003C\u002Fspan>()\n  \u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> x = \u003Cspan class=\"hljs-title function_\">clamp\u003C\u002Fspan>(r.\u003Cspan class=\"hljs-property\">left\u003C\u002Fspan> + \u003Cspan class=\"hljs-title class_\">Math\u003C\u002Fspan>.\u003Cspan class=\"hljs-title function_\">min\u003C\u002Fspan>(r.\u003Cspan class=\"hljs-property\">width\u003C\u002Fspan> \u002F \u003Cspan class=\"hljs-number\">2\u003C\u002Fspan>, \u003Cspan class=\"hljs-number\">80\u003C\u002Fspan>) - me.\u003Cspan class=\"hljs-property\">width\u003C\u002Fspan> \u002F \u003Cspan class=\"hljs-number\">2\u003C\u002Fspan>, b.\u003Cspan class=\"hljs-property\">left\u003C\u002Fspan> + \u003Cspan class=\"hljs-number\">8\u003C\u002Fspan>, b.\u003Cspan class=\"hljs-property\">right\u003C\u002Fspan> - me.\u003Cspan class=\"hljs-property\">width\u003C\u002Fspan> - \u003Cspan class=\"hljs-number\">8\u003C\u002Fspan>)\n  \u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> y = \u003Cspan class=\"hljs-title function_\">clamp\u003C\u002Fspan>(r.\u003Cspan class=\"hljs-property\">top\u003C\u002Fspan> - me.\u003Cspan class=\"hljs-property\">height\u003C\u002Fspan> + \u003Cspan class=\"hljs-number\">8\u003C\u002Fspan>, b.\u003Cspan class=\"hljs-property\">top\u003C\u002Fspan> + \u003Cspan class=\"hljs-number\">8\u003C\u002Fspan>, b.\u003Cspan class=\"hljs-property\">bottom\u003C\u002Fspan> - me.\u003Cspan class=\"hljs-property\">height\u003C\u002Fspan> - \u003Cspan class=\"hljs-number\">8\u003C\u002Fspan>)\n  \u003Cspan class=\"hljs-keyword\">await\u003C\u002Fspan> \u003Cspan class=\"hljs-title function_\">hop\u003C\u002Fspan>(x - (home.\u003Cspan class=\"hljs-property\">right\u003C\u002Fspan> - me.\u003Cspan class=\"hljs-property\">width\u003C\u002Fspan>), y - (home.\u003Cspan class=\"hljs-property\">bottom\u003C\u002Fspan> - me.\u003Cspan class=\"hljs-property\">height\u003C\u002Fspan>))\n}\n\u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> \u003Cspan class=\"hljs-title function_\">goHome\u003C\u002Fspan> = (\u003Cspan class=\"hljs-params\">\u003C\u002Fspan>) =&gt; { \u003Cspan class=\"hljs-keyword\">if\u003C\u002Fspan> (!reduced &amp;&amp; body.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan>?.\u003Cspan class=\"hljs-property\">style\u003C\u002Fspan>.\u003Cspan class=\"hljs-property\">transform\u003C\u002Fspan>) \u003Cspan class=\"hljs-keyword\">void\u003C\u002Fspan> \u003Cspan class=\"hljs-title function_\">hop\u003C\u002Fspan>(\u003Cspan class=\"hljs-number\">0\u003C\u002Fspan>, \u003Cspan class=\"hljs-number\">0\u003C\u002Fspan>).\u003Cspan class=\"hljs-title function_\">then\u003C\u002Fspan>(\u003Cspan class=\"hljs-function\">(\u003Cspan class=\"hljs-params\">landed\u003C\u002Fspan>) =&gt;\u003C\u002Fspan> { \u003Cspan class=\"hljs-keyword\">if\u003C\u002Fspan> (landed &amp;&amp; body.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan>) body.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan>.\u003Cspan class=\"hljs-property\">style\u003C\u002Fspan>.\u003Cspan class=\"hljs-property\">transform\u003C\u002Fspan> = \u003Cspan class=\"hljs-string\">&#x27;&#x27;\u003C\u002Fspan> }) }\n\n\u003Cspan class=\"hljs-keyword\">async\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">function\u003C\u002Fspan> \u003Cspan class=\"hljs-title function_\">act\u003C\u002Fspan>(\u003Cspan class=\"hljs-params\">name: string, value?: string, alternatives: Choice[] = [], confidence = \u003Cspan class=\"hljs-string\">&#x27;&#x27;\u003C\u002Fspan>\u003C\u002Fspan>) {\n  \u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> tool = \u003Cspan class=\"hljs-title function_\">siteTools\u003C\u002Fspan>().\u003Cspan class=\"hljs-title function_\">get\u003C\u002Fspan>(name)\n  \u003Cspan class=\"hljs-keyword\">if\u003C\u002Fspan> (!tool) { \u003Cspan class=\"hljs-title function_\">feel\u003C\u002Fspan>(\u003Cspan class=\"hljs-string\">&#x27;confused&#x27;\u003C\u002Fspan>); \u003Cspan class=\"hljs-keyword\">return\u003C\u002Fspan> \u003Cspan class=\"hljs-title function_\">speak\u003C\u002Fspan>(\u003Cspan class=\"hljs-title function_\">line\u003C\u002Fspan>(companion.\u003Cspan class=\"hljs-property\">ask\u003C\u002Fspan>.\u003Cspan class=\"hljs-property\">none\u003C\u002Fspan>)) }\n  \u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> values = tool.\u003Cspan class=\"hljs-property\">arg\u003C\u002Fspan>?.\u003Cspan class=\"hljs-property\">values\u003C\u002Fspan>\n  \u003Cspan class=\"hljs-keyword\">if\u003C\u002Fspan> (value === \u003Cspan class=\"hljs-variable constant_\">ANY\u003C\u002Fspan>) value = values &amp;&amp; \u003Cspan class=\"hljs-title function_\">random\u003C\u002Fspan>(values)?.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan>\n  \u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> label = values?.\u003Cspan class=\"hljs-title function_\">find\u003C\u002Fspan>(\u003Cspan class=\"hljs-function\">(\u003Cspan class=\"hljs-params\">v\u003C\u002Fspan>) =&gt;\u003C\u002Fspan> v.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan> === value)?.\u003Cspan class=\"hljs-property\">label\u003C\u002Fspan> ?? value\n  \u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> doing = \u003Cspan class=\"hljs-string\">`\u003Cspan class=\"hljs-subst\">${cap(tool.doing(label))}\u003C\u002Fspan>.`\u003C\u002Fspan>\n  \u003Cspan class=\"hljs-title function_\">hush\u003C\u002Fspan>()\n  \u003Cspan class=\"hljs-title function_\">feel\u003C\u002Fspan>(\u003Cspan class=\"hljs-string\">&#x27;happy&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-number\">3000\u003C\u002Fspan>)\n  \u003Cspan class=\"hljs-title function_\">speak\u003C\u002Fspan>(doing, alternatives.\u003Cspan class=\"hljs-property\">length\u003C\u002Fspan> &gt; \u003Cspan class=\"hljs-number\">0\u003C\u002Fspan>, alternatives, confidence)\n  \u003Cspan class=\"hljs-keyword\">await\u003C\u002Fspan> \u003Cspan class=\"hljs-title function_\">visit\u003C\u002Fspan>(tool.\u003Cspan class=\"hljs-property\">target\u003C\u002Fspan>?.(value))\n  \u003Cspan class=\"hljs-keyword\">try\u003C\u002Fspan> {\n    \u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> { result } = \u003Cspan class=\"hljs-keyword\">await\u003C\u002Fspan> \u003Cspan class=\"hljs-title function_\">callTool\u003C\u002Fspan>(name, value, \u003Cspan class=\"hljs-string\">&#x27;jevvie&#x27;\u003C\u002Fspan>)\n    \u003Cspan class=\"hljs-keyword\">void\u003C\u002Fspan> \u003Cspan class=\"hljs-title function_\">trick\u003C\u002Fspan>(\u003Cspan class=\"hljs-string\">&#x27;jump&#x27;\u003C\u002Fspan>); \u003Cspan class=\"hljs-title function_\">feel\u003C\u002Fspan>(\u003Cspan class=\"hljs-string\">&#x27;love&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-number\">1400\u003C\u002Fspan>)\n    \u003Cspan class=\"hljs-keyword\">if\u003C\u002Fspan> (result &amp;&amp; !alternatives.\u003Cspan class=\"hljs-property\">length\u003C\u002Fspan> &amp;&amp; name !== \u003Cspan class=\"hljs-string\">&#x27;copy_link&#x27;\u003C\u002Fspan>) \u003Cspan class=\"hljs-title function_\">speak\u003C\u002Fspan>(\u003Cspan class=\"hljs-string\">`\u003Cspan class=\"hljs-subst\">${doing}\u003C\u002Fspan> \u003Cspan class=\"hljs-subst\">${result}\u003C\u002Fspan>`\u003C\u002Fspan>)\n  } \u003Cspan class=\"hljs-keyword\">catch\u003C\u002Fspan> { \u003Cspan class=\"hljs-title function_\">feel\u003C\u002Fspan>(\u003Cspan class=\"hljs-string\">&#x27;confused&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-number\">2200\u003C\u002Fspan>); \u003Cspan class=\"hljs-title function_\">speak\u003C\u002Fspan>(companion.\u003Cspan class=\"hljs-property\">ask\u003C\u002Fspan>.\u003Cspan class=\"hljs-property\">failed\u003C\u002Fspan>) }\n  \u003Cspan class=\"hljs-built_in\">setTimeout\u003C\u002Fspan>(goHome, \u003Cspan class=\"hljs-number\">1400\u003C\u002Fspan>)\n}\n\n\u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> lastPick = \u003Cspan class=\"hljs-title function_\">useJevPick\u003C\u002Fspan>()\n\u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> picks = \u003Cspan class=\"hljs-title function_\">useJevPicks\u003C\u002Fspan>()\n\u003Cspan class=\"hljs-keyword\">async\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">function\u003C\u002Fspan> \u003Cspan class=\"hljs-title function_\">post\u003C\u002Fspan>(\u003Cspan class=\"hljs-params\">body: { criteria?: Record&lt;string, string&gt; } &amp; Record&lt;string, unknown&gt;, name = actionName\u003C\u002Fspan>) {\n  \u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> answer = \u003Cspan class=\"hljs-keyword\">await\u003C\u002Fspan> $fetch&lt;\u003Cspan class=\"hljs-title class_\">Answer\u003C\u002Fspan>&gt;(\u003Cspan class=\"hljs-string\">&#x27;\u002Fapi\u002Fcompanion&#x27;\u003C\u002Fspan>, { \u003Cspan class=\"hljs-attr\">method\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;POST&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">body\u003C\u002Fspan>: { \u003Cspan class=\"hljs-attr\">path\u003C\u002Fspan>: route.\u003Cspan class=\"hljs-property\">path\u003C\u002Fspan>, ...body } })\n  \u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> pick = \u003Cspan class=\"hljs-title function_\">pickOf\u003C\u002Fspan>(answer, body.\u003Cspan class=\"hljs-property\">criteria\u003C\u002Fspan> ? \u003Cspan class=\"hljs-title class_\">Object\u003C\u002Fspan>.\u003Cspan class=\"hljs-title function_\">keys\u003C\u002Fspan>(body.\u003Cspan class=\"hljs-property\">criteria\u003C\u002Fspan>) : tipIds, name)\n  \u003Cspan class=\"hljs-keyword\">if\u003C\u002Fspan> (pick) { lastPick.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan> = pick; picks.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan> = [...picks.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan>, pick].\u003Cspan class=\"hljs-title function_\">slice\u003C\u002Fspan>(-\u003Cspan class=\"hljs-number\">8\u003C\u002Fspan>) }\n  \u003Cspan class=\"hljs-keyword\">return\u003C\u002Fspan> answer\n}\n\u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> tipIds = (companion.\u003Cspan class=\"hljs-property\">tips\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">as\u003C\u002Fspan> \u003Cspan class=\"hljs-title class_\">Tip\u003C\u002Fspan>[]).\u003Cspan class=\"hljs-title function_\">map\u003C\u002Fspan>(\u003Cspan class=\"hljs-function\">(\u003Cspan class=\"hljs-params\">t\u003C\u002Fspan>) =&gt;\u003C\u002Fspan> t.\u003Cspan class=\"hljs-property\">id\u003C\u002Fspan>)\n\u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> \u003Cspan class=\"hljs-title function_\">context\u003C\u002Fspan> = (\u003Cspan class=\"hljs-params\">\u003C\u002Fspan>) =&gt; ({ \u003Cspan class=\"hljs-attr\">recent\u003C\u002Fspan>: \u003Cspan class=\"hljs-title function_\">recentEvents\u003C\u002Fspan>(), \u003Cspan class=\"hljs-attr\">heading\u003C\u002Fspan>: [...\u003Cspan class=\"hljs-variable language_\">document\u003C\u002Fspan>.\u003Cspan class=\"hljs-title function_\">querySelectorAll\u003C\u002Fspan>(\u003Cspan class=\"hljs-string\">&#x27;h1, h2&#x27;\u003C\u002Fspan>)].\u003Cspan class=\"hljs-title function_\">find\u003C\u002Fspan>(\u003Cspan class=\"hljs-function\">(\u003Cspan class=\"hljs-params\">h\u003C\u002Fspan>) =&gt;\u003C\u002Fspan> { \u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> r = h.\u003Cspan class=\"hljs-title function_\">getBoundingClientRect\u003C\u002Fspan>(); \u003Cspan class=\"hljs-keyword\">return\u003C\u002Fspan> r.\u003Cspan class=\"hljs-property\">bottom\u003C\u002Fspan> &gt; \u003Cspan class=\"hljs-number\">0\u003C\u002Fspan> &amp;&amp; r.\u003Cspan class=\"hljs-property\">top\u003C\u002Fspan> &lt; innerHeight })?.\u003Cspan class=\"hljs-property\">textContent\u003C\u002Fspan>?.\u003Cspan class=\"hljs-title function_\">trim\u003C\u002Fspan>() })\n\u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> \u003Cspan class=\"hljs-variable constant_\">SECTIONS\u003C\u002Fspan> = [\u003Cspan class=\"hljs-string\">&#x27;work&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-string\">&#x27;notes&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-string\">&#x27;lab&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-string\">&#x27;experiments&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-string\">&#x27;decks&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-string\">&#x27;projects&#x27;\u003C\u002Fspan>]\n\u003Cspan class=\"hljs-keyword\">function\u003C\u002Fspan> \u003Cspan class=\"hljs-title function_\">think\u003C\u002Fspan>(\u003Cspan class=\"hljs-params\">\u003C\u002Fspan>) {\n  busy.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan> = \u003Cspan class=\"hljs-literal\">true\u003C\u002Fspan>\n  \u003Cspan class=\"hljs-title function_\">feel\u003C\u002Fspan>(\u003Cspan class=\"hljs-string\">&#x27;think&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-number\">20_000\u003C\u002Fspan>)\n  \u003Cspan class=\"hljs-title function_\">speak\u003C\u002Fspan>(companion.\u003Cspan class=\"hljs-property\">ask\u003C\u002Fspan>.\u003Cspan class=\"hljs-property\">thinking\u003C\u002Fspan>, \u003Cspan class=\"hljs-literal\">true\u003C\u002Fspan>)\n}\n\u003Cspan class=\"hljs-keyword\">async\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">function\u003C\u002Fspan> \u003Cspan class=\"hljs-title function_\">ask\u003C\u002Fspan>(\u003Cspan class=\"hljs-params\">request: string\u003C\u002Fspan>) {\n  \u003Cspan class=\"hljs-keyword\">if\u003C\u002Fspan> (busy.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan>) \u003Cspan class=\"hljs-keyword\">return\u003C\u002Fspan>\n  \u003Cspan class=\"hljs-title function_\">think\u003C\u002Fspan>()\n  \u003Cspan class=\"hljs-keyword\">try\u003C\u002Fspan> {\n    \u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> tools = [...\u003Cspan class=\"hljs-title function_\">siteTools\u003C\u002Fspan>().\u003Cspan class=\"hljs-title function_\">values\u003C\u002Fspan>()].\u003Cspan class=\"hljs-title function_\">filter\u003C\u002Fspan>(\u003Cspan class=\"hljs-function\">(\u003Cspan class=\"hljs-params\">t\u003C\u002Fspan>) =&gt;\u003C\u002Fspan> !t.\u003Cspan class=\"hljs-property\">agentOnly\u003C\u002Fspan> &amp;&amp; (!t.\u003Cspan class=\"hljs-property\">arg\u003C\u002Fspan>?.\u003Cspan class=\"hljs-property\">values\u003C\u002Fspan> || t.\u003Cspan class=\"hljs-property\">arg\u003C\u002Fspan>.\u003Cspan class=\"hljs-property\">values\u003C\u002Fspan>.\u003Cspan class=\"hljs-property\">length\u003C\u002Fspan>))\n    \u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> first = \u003Cspan class=\"hljs-keyword\">await\u003C\u002Fspan> \u003Cspan class=\"hljs-title function_\">post\u003C\u002Fspan>({ \u003Cspan class=\"hljs-attr\">kind\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;tool&#x27;\u003C\u002Fspan>, request, \u003Cspan class=\"hljs-attr\">criteria\u003C\u002Fspan>: \u003Cspan class=\"hljs-title function_\">toolCriteria\u003C\u002Fspan>(tools), \u003Cspan class=\"hljs-attr\">args\u003C\u002Fspan>: \u003Cspan class=\"hljs-title function_\">wantsAny\u003C\u002Fspan>(request) ? {} : \u003Cspan class=\"hljs-title function_\">argQuestions\u003C\u002Fspan>(tools, request) })\n    \u003Cspan class=\"hljs-keyword\">if\u003C\u002Fspan> (first.\u003Cspan class=\"hljs-property\">choice\u003C\u002Fspan> === \u003Cspan class=\"hljs-variable constant_\">HELP\u003C\u002Fspan>) { \u003Cspan class=\"hljs-title function_\">feel\u003C\u002Fspan>(\u003Cspan class=\"hljs-string\">&#x27;happy&#x27;\u003C\u002Fspan>); \u003Cspan class=\"hljs-keyword\">return\u003C\u002Fspan> \u003Cspan class=\"hljs-title function_\">openPanel\u003C\u002Fspan>() }\n    \u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> tool = \u003Cspan class=\"hljs-title function_\">siteTools\u003C\u002Fspan>().\u003Cspan class=\"hljs-title function_\">get\u003C\u002Fspan>(first.\u003Cspan class=\"hljs-property\">choice\u003C\u002Fspan>)\n    \u003Cspan class=\"hljs-keyword\">if\u003C\u002Fspan> (first.\u003Cspan class=\"hljs-property\">choice\u003C\u002Fspan> === \u003Cspan class=\"hljs-variable constant_\">NONE\u003C\u002Fspan> || !tool) { \u003Cspan class=\"hljs-title function_\">feel\u003C\u002Fspan>(\u003Cspan class=\"hljs-string\">&#x27;confused&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-number\">2200\u003C\u002Fspan>); \u003Cspan class=\"hljs-keyword\">return\u003C\u002Fspan> \u003Cspan class=\"hljs-title function_\">speak\u003C\u002Fspan>(\u003Cspan class=\"hljs-title function_\">line\u003C\u002Fspan>(companion.\u003Cspan class=\"hljs-property\">ask\u003C\u002Fspan>.\u003Cspan class=\"hljs-property\">none\u003C\u002Fspan>)) }\n    \u003Cspan class=\"hljs-keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"hljs-title function_\">unsure\u003C\u002Fspan>(first)) {\n      \u003Cspan class=\"hljs-title function_\">feel\u003C\u002Fspan>(\u003Cspan class=\"hljs-string\">&#x27;confused&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-number\">4000\u003C\u002Fspan>)\n      \u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> options = \u003Cspan class=\"hljs-title function_\">ranked\u003C\u002Fspan>(first, [\u003Cspan class=\"hljs-variable constant_\">NONE\u003C\u002Fspan>, \u003Cspan class=\"hljs-variable constant_\">HELP\u003C\u002Fspan>]).\u003Cspan class=\"hljs-title function_\">slice\u003C\u002Fspan>(\u003Cspan class=\"hljs-number\">0\u003C\u002Fspan>, \u003Cspan class=\"hljs-number\">3\u003C\u002Fspan>).\u003Cspan class=\"hljs-title function_\">map\u003C\u002Fspan>(\u003Cspan class=\"hljs-function\">(\u003Cspan class=\"hljs-params\">[name]\u003C\u002Fspan>) =&gt;\u003C\u002Fspan> ({ \u003Cspan class=\"hljs-attr\">label\u003C\u002Fspan>: \u003Cspan class=\"hljs-title function_\">siteTools\u003C\u002Fspan>().\u003Cspan class=\"hljs-title function_\">get\u003C\u002Fspan>(name)?.\u003Cspan class=\"hljs-property\">description\u003C\u002Fspan> ?? name, \u003Cspan class=\"hljs-attr\">run\u003C\u002Fspan>: \u003Cspan class=\"hljs-function\">() =&gt;\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">void\u003C\u002Fspan> \u003Cspan class=\"hljs-title function_\">resolve\u003C\u002Fspan>(name, request, \u003Cspan class=\"hljs-number\">1\u003C\u002Fspan>, first.\u003Cspan class=\"hljs-property\">args\u003C\u002Fspan>?.[name]) }))\n      \u003Cspan class=\"hljs-keyword\">return\u003C\u002Fspan> \u003Cspan class=\"hljs-title function_\">speak\u003C\u002Fspan>(companion.\u003Cspan class=\"hljs-property\">clarify\u003C\u002Fspan>.\u003Cspan class=\"hljs-property\">question\u003C\u002Fspan>, \u003Cspan class=\"hljs-literal\">true\u003C\u002Fspan>, options)\n    }\n    \u003Cspan class=\"hljs-keyword\">await\u003C\u002Fspan> \u003Cspan class=\"hljs-title function_\">resolve\u003C\u002Fspan>(tool.\u003Cspan class=\"hljs-property\">name\u003C\u002Fspan>, request, first.\u003Cspan class=\"hljs-property\">probabilities\u003C\u002Fspan>[tool.\u003Cspan class=\"hljs-property\">name\u003C\u002Fspan>], first.\u003Cspan class=\"hljs-property\">args\u003C\u002Fspan>?.[tool.\u003Cspan class=\"hljs-property\">name\u003C\u002Fspan>])\n  } \u003Cspan class=\"hljs-keyword\">catch\u003C\u002Fspan> (e) {\n    \u003Cspan class=\"hljs-title function_\">feel\u003C\u002Fspan>(\u003Cspan class=\"hljs-string\">&#x27;confused&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-number\">2200\u003C\u002Fspan>)\n    \u003Cspan class=\"hljs-title function_\">speak\u003C\u002Fspan>((e \u003Cspan class=\"hljs-keyword\">as\u003C\u002Fspan> { statusCode?: number }).\u003Cspan class=\"hljs-property\">statusCode\u003C\u002Fspan> === \u003Cspan class=\"hljs-number\">429\u003C\u002Fspan> ? companion.\u003Cspan class=\"hljs-property\">ask\u003C\u002Fspan>.\u003Cspan class=\"hljs-property\">busy\u003C\u002Fspan> : companion.\u003Cspan class=\"hljs-property\">ask\u003C\u002Fspan>.\u003Cspan class=\"hljs-property\">failed\u003C\u002Fspan>)\n  } \u003Cspan class=\"hljs-keyword\">finally\u003C\u002Fspan> { busy.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan> = \u003Cspan class=\"hljs-literal\">false\u003C\u002Fspan> }\n}\n\u003Cspan class=\"hljs-keyword\">async\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">function\u003C\u002Fspan> \u003Cspan class=\"hljs-title function_\">resolve\u003C\u002Fspan>(\u003Cspan class=\"hljs-params\">name: string, request: string, p = \u003Cspan class=\"hljs-number\">1\u003C\u002Fspan>, asked?: Answer\u003C\u002Fspan>) {\n  \u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> tool = \u003Cspan class=\"hljs-title function_\">siteTools\u003C\u002Fspan>().\u003Cspan class=\"hljs-title function_\">get\u003C\u002Fspan>(name)\n  \u003Cspan class=\"hljs-keyword\">if\u003C\u002Fspan> (!tool) \u003Cspan class=\"hljs-keyword\">return\u003C\u002Fspan>\n  \u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> \u003Cspan class=\"hljs-title function_\">percent\u003C\u002Fspan> = (\u003Cspan class=\"hljs-params\">x: number\u003C\u002Fspan>) =&gt; \u003Cspan class=\"hljs-title function_\">fill\u003C\u002Fspan>(companion.\u003Cspan class=\"hljs-property\">clarify\u003C\u002Fspan>.\u003Cspan class=\"hljs-property\">sure\u003C\u002Fspan>, { \u003Cspan class=\"hljs-attr\">p\u003C\u002Fspan>: \u003Cspan class=\"hljs-title class_\">String\u003C\u002Fspan>(\u003Cspan class=\"hljs-title class_\">Math\u003C\u002Fspan>.\u003Cspan class=\"hljs-title function_\">round\u003C\u002Fspan>(x * \u003Cspan class=\"hljs-number\">100\u003C\u002Fspan>)) })\n  \u003Cspan class=\"hljs-keyword\">if\u003C\u002Fspan> (!tool.\u003Cspan class=\"hljs-property\">arg\u003C\u002Fspan>) \u003Cspan class=\"hljs-keyword\">return\u003C\u002Fspan> \u003Cspan class=\"hljs-title function_\">act\u003C\u002Fspan>(name, \u003Cspan class=\"hljs-literal\">undefined\u003C\u002Fspan>, [], \u003Cspan class=\"hljs-title function_\">percent\u003C\u002Fspan>(p))\n  \u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> { values } = tool.\u003Cspan class=\"hljs-property\">arg\u003C\u002Fspan>\n  \u003Cspan class=\"hljs-keyword\">if\u003C\u002Fspan> (!values) \u003Cspan class=\"hljs-keyword\">return\u003C\u002Fspan> \u003Cspan class=\"hljs-title function_\">act\u003C\u002Fspan>(name, \u003Cspan class=\"hljs-title function_\">queryFrom\u003C\u002Fspan>(request, tool.\u003Cspan class=\"hljs-property\">description\u003C\u002Fspan>, \u003Cspan class=\"hljs-variable constant_\">SECTIONS\u003C\u002Fspan>) || request, [], \u003Cspan class=\"hljs-title function_\">percent\u003C\u002Fspan>(p))\n  \u003Cspan class=\"hljs-keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"hljs-title function_\">wantsAny\u003C\u002Fspan>(request)) \u003Cspan class=\"hljs-keyword\">return\u003C\u002Fspan> \u003Cspan class=\"hljs-title function_\">act\u003C\u002Fspan>(name, \u003Cspan class=\"hljs-variable constant_\">ANY\u003C\u002Fspan>)\n  \u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> options = \u003Cspan class=\"hljs-title function_\">argCriteria\u003C\u002Fspan>(tool.\u003Cspan class=\"hljs-property\">arg\u003C\u002Fspan>, request)\n  \u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> keys = \u003Cspan class=\"hljs-title class_\">Object\u003C\u002Fspan>.\u003Cspan class=\"hljs-title function_\">keys\u003C\u002Fspan>(options)\n  \u003Cspan class=\"hljs-keyword\">if\u003C\u002Fspan> (keys.\u003Cspan class=\"hljs-property\">length\u003C\u002Fspan> === \u003Cspan class=\"hljs-number\">1\u003C\u002Fspan>) \u003Cspan class=\"hljs-keyword\">return\u003C\u002Fspan> \u003Cspan class=\"hljs-title function_\">act\u003C\u002Fspan>(name, keys[\u003Cspan class=\"hljs-number\">0\u003C\u002Fspan>], [], \u003Cspan class=\"hljs-title function_\">percent\u003C\u002Fspan>(p))\n  \u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> second = asked?.\u003Cspan class=\"hljs-property\">choice\u003C\u002Fspan> &amp;&amp; asked.\u003Cspan class=\"hljs-property\">choice\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">in\u003C\u002Fspan> options ? asked : \u003Cspan class=\"hljs-keyword\">await\u003C\u002Fspan> \u003Cspan class=\"hljs-title function_\">post\u003C\u002Fspan>({ \u003Cspan class=\"hljs-attr\">kind\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;arg&#x27;\u003C\u002Fspan>, request, \u003Cspan class=\"hljs-attr\">action\u003C\u002Fspan>: tool.\u003Cspan class=\"hljs-property\">description\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">criteria\u003C\u002Fspan>: options }, \u003Cspan class=\"hljs-function\">(\u003Cspan class=\"hljs-params\">v\u003C\u002Fspan>) =&gt;\u003C\u002Fspan> values.\u003Cspan class=\"hljs-title function_\">find\u003C\u002Fspan>(\u003Cspan class=\"hljs-function\">(\u003Cspan class=\"hljs-params\">x\u003C\u002Fspan>) =&gt;\u003C\u002Fspan> x.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan> === v)?.\u003Cspan class=\"hljs-property\">label\u003C\u002Fspan> ?? \u003Cspan class=\"hljs-title function_\">actionName\u003C\u002Fspan>(v))\n  \u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> runners = \u003Cspan class=\"hljs-title function_\">ranked\u003C\u002Fspan>(second, [second.\u003Cspan class=\"hljs-property\">choice\u003C\u002Fspan>]).\u003Cspan class=\"hljs-title function_\">slice\u003C\u002Fspan>(\u003Cspan class=\"hljs-number\">0\u003C\u002Fspan>, \u003Cspan class=\"hljs-number\">2\u003C\u002Fspan>).\u003Cspan class=\"hljs-title function_\">map\u003C\u002Fspan>(\u003Cspan class=\"hljs-function\">(\u003Cspan class=\"hljs-params\">[value]\u003C\u002Fspan>) =&gt;\u003C\u002Fspan> ({ \u003Cspan class=\"hljs-attr\">label\u003C\u002Fspan>: options[value] ?? value, \u003Cspan class=\"hljs-attr\">run\u003C\u002Fspan>: \u003Cspan class=\"hljs-function\">() =&gt;\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">void\u003C\u002Fspan> \u003Cspan class=\"hljs-title function_\">act\u003C\u002Fspan>(name, value) }))\n  \u003Cspan class=\"hljs-keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"hljs-title function_\">unsure\u003C\u002Fspan>(second)) {\n    \u003Cspan class=\"hljs-title function_\">feel\u003C\u002Fspan>(\u003Cspan class=\"hljs-string\">&#x27;confused&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-number\">4000\u003C\u002Fspan>)\n    \u003Cspan class=\"hljs-keyword\">return\u003C\u002Fspan> \u003Cspan class=\"hljs-title function_\">speak\u003C\u002Fspan>(companion.\u003Cspan class=\"hljs-property\">clarify\u003C\u002Fspan>.\u003Cspan class=\"hljs-property\">question\u003C\u002Fspan>, \u003Cspan class=\"hljs-literal\">true\u003C\u002Fspan>, [{ \u003Cspan class=\"hljs-attr\">label\u003C\u002Fspan>: options[second.\u003Cspan class=\"hljs-property\">choice\u003C\u002Fspan>] ?? second.\u003Cspan class=\"hljs-property\">choice\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">run\u003C\u002Fspan>: \u003Cspan class=\"hljs-function\">() =&gt;\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">void\u003C\u002Fspan> \u003Cspan class=\"hljs-title function_\">act\u003C\u002Fspan>(name, second.\u003Cspan class=\"hljs-property\">choice\u003C\u002Fspan>) }, ...runners])\n  }\n  \u003Cspan class=\"hljs-keyword\">await\u003C\u002Fspan> \u003Cspan class=\"hljs-title function_\">act\u003C\u002Fspan>(name, second.\u003Cspan class=\"hljs-property\">choice\u003C\u002Fspan>, runners, \u003Cspan class=\"hljs-title function_\">percent\u003C\u002Fspan>(p * (second.\u003Cspan class=\"hljs-property\">probabilities\u003C\u002Fspan>[second.\u003Cspan class=\"hljs-property\">choice\u003C\u002Fspan>] ?? \u003Cspan class=\"hljs-number\">1\u003C\u002Fspan>)))\n}\n\n\u003Cspan class=\"hljs-title function_\">onJevvieSay\u003C\u002Fspan>(\u003Cspan class=\"hljs-function\">(\u003Cspan class=\"hljs-params\">l\u003C\u002Fspan>) =&gt;\u003C\u002Fspan> {\n  \u003Cspan class=\"hljs-keyword\">if\u003C\u002Fspan> (sulking) \u003Cspan class=\"hljs-keyword\">return\u003C\u002Fspan>\n  tip.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan> = \u003Cspan class=\"hljs-literal\">null\u003C\u002Fspan>; greeting.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan> = \u003Cspan class=\"hljs-literal\">false\u003C\u002Fspan>\n  \u003Cspan class=\"hljs-title function_\">feel\u003C\u002Fspan>(l.\u003Cspan class=\"hljs-property\">mood\u003C\u002Fspan> ?? \u003Cspan class=\"hljs-string\">&#x27;happy&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-number\">3000\u003C\u002Fspan>)\n  \u003Cspan class=\"hljs-keyword\">if\u003C\u002Fspan> (l.\u003Cspan class=\"hljs-property\">trick\u003C\u002Fspan>) \u003Cspan class=\"hljs-keyword\">void\u003C\u002Fspan> \u003Cspan class=\"hljs-title function_\">trick\u003C\u002Fspan>(l.\u003Cspan class=\"hljs-property\">trick\u003C\u002Fspan>)\n  \u003Cspan class=\"hljs-title function_\">speak\u003C\u002Fspan>(l.\u003Cspan class=\"hljs-property\">text\u003C\u002Fspan>)\n})\n\nuseEventBus&lt;\u003Cspan class=\"hljs-string\">&#x27;call&#x27;\u003C\u002Fspan>&gt;(\u003Cspan class=\"hljs-string\">&#x27;jevvie&#x27;\u003C\u002Fspan>).\u003Cspan class=\"hljs-title function_\">on\u003C\u002Fspan>(\u003Cspan class=\"hljs-function\">() =&gt;\u003C\u002Fspan> { view?.\u003Cspan class=\"hljs-title function_\">squash\u003C\u002Fspan>(); \u003Cspan class=\"hljs-keyword\">void\u003C\u002Fspan> \u003Cspan class=\"hljs-title function_\">trick\u003C\u002Fspan>(\u003Cspan class=\"hljs-string\">&#x27;jump&#x27;\u003C\u002Fspan>); \u003Cspan class=\"hljs-title function_\">feel\u003C\u002Fspan>(\u003Cspan class=\"hljs-string\">&#x27;surprised&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-number\">1200\u003C\u002Fspan>); \u003Cspan class=\"hljs-title function_\">speak\u003C\u002Fspan>(\u003Cspan class=\"hljs-title function_\">line\u003C\u002Fspan>(companion.\u003Cspan class=\"hljs-property\">ask\u003C\u002Fspan>.\u003Cspan class=\"hljs-property\">rang\u003C\u002Fspan>)) })\n\n\u003Cspan class=\"hljs-title function_\">onToolCall\u003C\u002Fspan>(\u003Cspan class=\"hljs-function\">(\u003Cspan class=\"hljs-params\">call\u003C\u002Fspan>) =&gt;\u003C\u002Fspan> {\n  \u003Cspan class=\"hljs-keyword\">if\u003C\u002Fspan> (call.\u003Cspan class=\"hljs-property\">by\u003C\u002Fspan> !== \u003Cspan class=\"hljs-string\">&#x27;agent&#x27;\u003C\u002Fspan>) \u003Cspan class=\"hljs-keyword\">return\u003C\u002Fspan>\n  \u003Cspan class=\"hljs-title function_\">feel\u003C\u002Fspan>(\u003Cspan class=\"hljs-string\">&#x27;surprised&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-number\">1400\u003C\u002Fspan>)\n  \u003Cspan class=\"hljs-title function_\">speak\u003C\u002Fspan>(\u003Cspan class=\"hljs-title function_\">cap\u003C\u002Fspan>(\u003Cspan class=\"hljs-title function_\">fill\u003C\u002Fspan>(\u003Cspan class=\"hljs-title function_\">line\u003C\u002Fspan>(call.\u003Cspan class=\"hljs-property\">tool\u003C\u002Fspan>.\u003Cspan class=\"hljs-property\">name\u003C\u002Fspan>.\u003Cspan class=\"hljs-title function_\">startsWith\u003C\u002Fspan>(\u003Cspan class=\"hljs-string\">&#x27;jevvie_&#x27;\u003C\u002Fspan>) ? companion.\u003Cspan class=\"hljs-property\">agentMe\u003C\u002Fspan> : companion.\u003Cspan class=\"hljs-property\">agent\u003C\u002Fspan>), { \u003Cspan class=\"hljs-attr\">doing\u003C\u002Fspan>: call.\u003Cspan class=\"hljs-property\">tool\u003C\u002Fspan>.\u003Cspan class=\"hljs-title function_\">doing\u003C\u002Fspan>(call.\u003Cspan class=\"hljs-property\">label\u003C\u002Fspan>) })))\n  \u003Cspan class=\"hljs-keyword\">if\u003C\u002Fspan> (!call.\u003Cspan class=\"hljs-property\">tool\u003C\u002Fspan>.\u003Cspan class=\"hljs-property\">agentOnly\u003C\u002Fspan>) \u003Cspan class=\"hljs-keyword\">void\u003C\u002Fspan> \u003Cspan class=\"hljs-title function_\">visit\u003C\u002Fspan>(call.\u003Cspan class=\"hljs-property\">tool\u003C\u002Fspan>.\u003Cspan class=\"hljs-property\">target\u003C\u002Fspan>?.(call.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan>)).\u003Cspan class=\"hljs-title function_\">then\u003C\u002Fspan>(\u003Cspan class=\"hljs-function\">() =&gt;\u003C\u002Fspan> \u003Cspan class=\"hljs-built_in\">setTimeout\u003C\u002Fspan>(goHome, \u003Cspan class=\"hljs-number\">1400\u003C\u002Fspan>))\n})\n\n\u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> tipsOn = \u003Cspan class=\"hljs-title function_\">useStored\u003C\u002Fspan>(\u003Cspan class=\"hljs-string\">&#x27;jevvieTips&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-literal\">true\u003C\u002Fspan>, \u003Cspan class=\"hljs-title function_\">oneOf\u003C\u002Fspan>(\u003Cspan class=\"hljs-literal\">true\u003C\u002Fspan>, \u003Cspan class=\"hljs-literal\">false\u003C\u002Fspan>))\n\u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> dismissed = useSessionStorage&lt;string[]&gt;(\u003Cspan class=\"hljs-string\">&#x27;cw:jevvieDismissed&#x27;\u003C\u002Fspan>, [])\n\u003Cspan class=\"hljs-keyword\">let\u003C\u002Fspan> lastTipAt = \u003Cspan class=\"hljs-title class_\">Date\u003C\u002Fspan>.\u003Cspan class=\"hljs-title function_\">now\u003C\u002Fspan>(), shown = \u003Cspan class=\"hljs-number\">0\u003C\u002Fspan>, lastTip = \u003Cspan class=\"hljs-string\">&#x27;&#x27;\u003C\u002Fspan>\n\u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> \u003Cspan class=\"hljs-variable constant_\">MAX_TIPS\u003C\u002Fspan> = \u003Cspan class=\"hljs-number\">10\u003C\u002Fspan>\n\u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> \u003Cspan class=\"hljs-title function_\">tipGap\u003C\u002Fspan> = (\u003Cspan class=\"hljs-params\">\u003C\u002Fspan>) =&gt; \u003Cspan class=\"hljs-title class_\">Math\u003C\u002Fspan>.\u003Cspan class=\"hljs-title function_\">max\u003C\u002Fspan>(\u003Cspan class=\"hljs-number\">40_000\u003C\u002Fspan>, \u003Cspan class=\"hljs-number\">120_000\u003C\u002Fspan> - shown * \u003Cspan class=\"hljs-number\">15_000\u003C\u002Fspan>)\n\u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> \u003Cspan class=\"hljs-title function_\">tipFor\u003C\u002Fspan> = (\u003Cspan class=\"hljs-params\">id: string\u003C\u002Fspan>) =&gt; (companion.\u003Cspan class=\"hljs-property\">tips\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">as\u003C\u002Fspan> \u003Cspan class=\"hljs-title class_\">Tip\u003C\u002Fspan>[]).\u003Cspan class=\"hljs-title function_\">find\u003C\u002Fspan>(\u003Cspan class=\"hljs-function\">(\u003Cspan class=\"hljs-params\">t\u003C\u002Fspan>) =&gt;\u003C\u002Fspan> t.\u003Cspan class=\"hljs-property\">id\u003C\u002Fspan> === id)\n\u003Cspan class=\"hljs-keyword\">function\u003C\u002Fspan> \u003Cspan class=\"hljs-title function_\">offer\u003C\u002Fspan>(\u003Cspan class=\"hljs-params\">next: Tip\u003C\u002Fspan>) {\n  \u003Cspan class=\"hljs-title function_\">hush\u003C\u002Fspan>(); open.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan> = \u003Cspan class=\"hljs-literal\">false\u003C\u002Fspan>\n  lastTip = next.\u003Cspan class=\"hljs-property\">id\u003C\u002Fspan>; tip.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan> = next\n  view?.\u003Cspan class=\"hljs-title function_\">squash\u003C\u002Fspan>(\u003Cspan class=\"hljs-number\">0.5\u003C\u002Fspan>); \u003Cspan class=\"hljs-keyword\">void\u003C\u002Fspan> \u003Cspan class=\"hljs-title function_\">trick\u003C\u002Fspan>(\u003Cspan class=\"hljs-string\">&#x27;wave&#x27;\u003C\u002Fspan>); \u003Cspan class=\"hljs-title function_\">feel\u003C\u002Fspan>(\u003Cspan class=\"hljs-string\">&#x27;happy&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-number\">1400\u003C\u002Fspan>)\n  \u003Cspan class=\"hljs-title function_\">speak\u003C\u002Fspan>(next.\u003Cspan class=\"hljs-property\">text\u003C\u002Fspan>, \u003Cspan class=\"hljs-literal\">true\u003C\u002Fspan>); \u003Cspan class=\"hljs-title function_\">outstay\u003C\u002Fspan>()\n}\n\u003Cspan class=\"hljs-title function_\">useIntervalFn\u003C\u002Fspan>(\u003Cspan class=\"hljs-title function_\">async\u003C\u002Fspan> () =&gt; {\n  \u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> quiet = (\u003Cspan class=\"hljs-title class_\">Date\u003C\u002Fspan>.\u003Cspan class=\"hljs-title function_\">now\u003C\u002Fspan>() - lastActive.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan>) \u002F \u003Cspan class=\"hljs-number\">1000\u003C\u002Fspan>\n  \u003Cspan class=\"hljs-keyword\">if\u003C\u002Fspan> (!tipsOn.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan> || consenting.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan> || dismissed.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan>.\u003Cspan class=\"hljs-property\">length\u003C\u002Fspan> &gt;= \u003Cspan class=\"hljs-number\">3\u003C\u002Fspan> || shown &gt;= \u003Cspan class=\"hljs-variable constant_\">MAX_TIPS\u003C\u002Fspan> || open.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan> || menu.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan> || busy.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan> || say.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan> || sulking || \u003Cspan class=\"hljs-variable language_\">document\u003C\u002Fspan>.\u003Cspan class=\"hljs-property\">hidden\u003C\u002Fspan>) \u003Cspan class=\"hljs-keyword\">return\u003C\u002Fspan>\n  \u003Cspan class=\"hljs-keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"hljs-title class_\">Date\u003C\u002Fspan>.\u003Cspan class=\"hljs-title function_\">now\u003C\u002Fspan>() - lastTipAt &lt; \u003Cspan class=\"hljs-title function_\">tipGap\u003C\u002Fspan>() || quiet &lt; \u003Cspan class=\"hljs-number\">12\u003C\u002Fspan> || idle.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan>) \u003Cspan class=\"hljs-keyword\">return\u003C\u002Fspan>\n  lastTipAt = \u003Cspan class=\"hljs-title class_\">Date\u003C\u002Fspan>.\u003Cspan class=\"hljs-title function_\">now\u003C\u002Fspan>()\n  \u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> scrolled = scrollY \u002F \u003Cspan class=\"hljs-title class_\">Math\u003C\u002Fspan>.\u003Cspan class=\"hljs-title function_\">max\u003C\u002Fspan>(\u003Cspan class=\"hljs-number\">1\u003C\u002Fspan>, \u003Cspan class=\"hljs-variable language_\">document\u003C\u002Fspan>.\u003Cspan class=\"hljs-property\">documentElement\u003C\u002Fspan>.\u003Cspan class=\"hljs-property\">scrollHeight\u003C\u002Fspan> - innerHeight)\n  \u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> { choice } = \u003Cspan class=\"hljs-keyword\">await\u003C\u002Fspan> \u003Cspan class=\"hljs-title function_\">post\u003C\u002Fspan>({ \u003Cspan class=\"hljs-attr\">kind\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;tip&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">idle\u003C\u002Fspan>: \u003Cspan class=\"hljs-title class_\">Math\u003C\u002Fspan>.\u003Cspan class=\"hljs-title function_\">round\u003C\u002Fspan>(quiet), scrolled, \u003Cspan class=\"hljs-attr\">dismissed\u003C\u002Fspan>: dismissed.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan>, lastTip, ...\u003Cspan class=\"hljs-title function_\">context\u003C\u002Fspan>() }).\u003Cspan class=\"hljs-title function_\">catch\u003C\u002Fspan>(\u003Cspan class=\"hljs-function\">() =&gt;\u003C\u002Fspan> ({ \u003Cspan class=\"hljs-attr\">choice\u003C\u002Fspan>: \u003Cspan class=\"hljs-variable constant_\">QUIET\u003C\u002Fspan> }))\n  \u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> next = \u003Cspan class=\"hljs-title function_\">tipFor\u003C\u002Fspan>(choice)\n  \u003Cspan class=\"hljs-keyword\">if\u003C\u002Fspan> (!next || say.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan> || open.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan>) \u003Cspan class=\"hljs-keyword\">return\u003C\u002Fspan>\n  shown++\n  \u003Cspan class=\"hljs-title function_\">offer\u003C\u002Fspan>(next)\n}, \u003Cspan class=\"hljs-number\">30_000\u003C\u002Fspan>)\n\u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> landed = useSessionStorage&lt;string[]&gt;(\u003Cspan class=\"hljs-string\">&#x27;cw:jevvieLanded&#x27;\u003C\u002Fspan>, [])\n\u003Cspan class=\"hljs-title function_\">watch\u003C\u002Fspan>(\u003Cspan class=\"hljs-function\">() =&gt;\u003C\u002Fspan> route.\u003Cspan class=\"hljs-property\">path\u003C\u002Fspan>, \u003Cspan class=\"hljs-function\">(\u003Cspan class=\"hljs-params\">path\u003C\u002Fspan>) =&gt;\u003C\u002Fspan> {\n  \u003Cspan class=\"hljs-built_in\">setTimeout\u003C\u002Fspan>(\u003Cspan class=\"hljs-title function_\">async\u003C\u002Fspan> () =&gt; {\n    \u003Cspan class=\"hljs-keyword\">if\u003C\u002Fspan> (path === \u003Cspan class=\"hljs-string\">&#x27;\u002F&#x27;\u003C\u002Fspan> || route.\u003Cspan class=\"hljs-property\">path\u003C\u002Fspan> !== path || landed.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan>.\u003Cspan class=\"hljs-title function_\">includes\u003C\u002Fspan>(path) || !tipsOn.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan> || consenting.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan> || dismissed.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan>.\u003Cspan class=\"hljs-property\">length\u003C\u002Fspan> &gt;= \u003Cspan class=\"hljs-number\">3\u003C\u002Fspan> || open.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan> || busy.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan> || say.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan> || sulking) \u003Cspan class=\"hljs-keyword\">return\u003C\u002Fspan>\n    \u003Cspan class=\"hljs-keyword\">if\u003C\u002Fspan> (!(companion.\u003Cspan class=\"hljs-property\">tips\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">as\u003C\u002Fspan> \u003Cspan class=\"hljs-title class_\">Tip\u003C\u002Fspan>[]).\u003Cspan class=\"hljs-title function_\">some\u003C\u002Fspan>(\u003Cspan class=\"hljs-function\">(\u003Cspan class=\"hljs-params\">t\u003C\u002Fspan>) =&gt;\u003C\u002Fspan> t.\u003Cspan class=\"hljs-property\">only\u003C\u002Fspan>?.\u003Cspan class=\"hljs-title function_\">some\u003C\u002Fspan>(\u003Cspan class=\"hljs-function\">(\u003Cspan class=\"hljs-params\">p\u003C\u002Fspan>) =&gt;\u003C\u002Fspan> \u003Cspan class=\"hljs-title function_\">under\u003C\u002Fspan>(path, p)))) \u003Cspan class=\"hljs-keyword\">return\u003C\u002Fspan>\n    landed.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan> = [...landed.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan>, path]\n    \u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> { choice } = \u003Cspan class=\"hljs-keyword\">await\u003C\u002Fspan> \u003Cspan class=\"hljs-title function_\">post\u003C\u002Fspan>({ \u003Cspan class=\"hljs-attr\">kind\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;landing&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">dismissed\u003C\u002Fspan>: dismissed.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan>, lastTip, ...\u003Cspan class=\"hljs-title function_\">context\u003C\u002Fspan>() }).\u003Cspan class=\"hljs-title function_\">catch\u003C\u002Fspan>(\u003Cspan class=\"hljs-function\">() =&gt;\u003C\u002Fspan> ({ \u003Cspan class=\"hljs-attr\">choice\u003C\u002Fspan>: \u003Cspan class=\"hljs-variable constant_\">QUIET\u003C\u002Fspan> }))\n    \u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> next = \u003Cspan class=\"hljs-title function_\">tipFor\u003C\u002Fspan>(choice)\n    \u003Cspan class=\"hljs-keyword\">if\u003C\u002Fspan> (next &amp;&amp; !say.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan> &amp;&amp; !open.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan>) \u003Cspan class=\"hljs-title function_\">offer\u003C\u002Fspan>(next)\n  }, \u003Cspan class=\"hljs-number\">3500\u003C\u002Fspan>)\n}, { \u003Cspan class=\"hljs-attr\">immediate\u003C\u002Fspan>: \u003Cspan class=\"hljs-literal\">true\u003C\u002Fspan> })\n\u003Cspan class=\"hljs-keyword\">function\u003C\u002Fspan> \u003Cspan class=\"hljs-title function_\">answerTip\u003C\u002Fspan>(\u003Cspan class=\"hljs-params\">yes: boolean\u003C\u002Fspan>) {\n  \u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> t = tip.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan>\n  tip.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan> = \u003Cspan class=\"hljs-literal\">null\u003C\u002Fspan>\n  \u003Cspan class=\"hljs-keyword\">if\u003C\u002Fspan> (!t) \u003Cspan class=\"hljs-keyword\">return\u003C\u002Fspan>\n  \u003Cspan class=\"hljs-title function_\">track\u003C\u002Fspan>(\u003Cspan class=\"hljs-string\">&#x27;jevvie_tip&#x27;\u003C\u002Fspan>, { \u003Cspan class=\"hljs-attr\">id\u003C\u002Fspan>: t.\u003Cspan class=\"hljs-property\">id\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">answer\u003C\u002Fspan>: yes ? \u003Cspan class=\"hljs-string\">&#x27;yes&#x27;\u003C\u002Fspan> : \u003Cspan class=\"hljs-string\">&#x27;no&#x27;\u003C\u002Fspan> })\n  \u003Cspan class=\"hljs-keyword\">if\u003C\u002Fspan> (yes &amp;&amp; t.\u003Cspan class=\"hljs-property\">action\u003C\u002Fspan>) \u003Cspan class=\"hljs-keyword\">return\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">void\u003C\u002Fspan> \u003Cspan class=\"hljs-title function_\">act\u003C\u002Fspan>(t.\u003Cspan class=\"hljs-property\">action\u003C\u002Fspan>.\u003Cspan class=\"hljs-property\">tool\u003C\u002Fspan>, t.\u003Cspan class=\"hljs-property\">action\u003C\u002Fspan>.\u003Cspan class=\"hljs-property\">arg\u003C\u002Fspan>)\n  \u003Cspan class=\"hljs-keyword\">if\u003C\u002Fspan> (yes) \u003Cspan class=\"hljs-keyword\">return\u003C\u002Fspan> \u003Cspan class=\"hljs-title function_\">hush\u003C\u002Fspan>()\n  dismissed.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan> = [...dismissed.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan>, t.\u003Cspan class=\"hljs-property\">id\u003C\u002Fspan>]\n  \u003Cspan class=\"hljs-title function_\">feel\u003C\u002Fspan>(\u003Cspan class=\"hljs-string\">&#x27;sulk&#x27;\u003C\u002Fspan>); \u003Cspan class=\"hljs-built_in\">setTimeout\u003C\u002Fspan>(\u003Cspan class=\"hljs-function\">() =&gt;\u003C\u002Fspan> \u003Cspan class=\"hljs-title function_\">feel\u003C\u002Fspan>(\u003Cspan class=\"hljs-string\">&#x27;idle&#x27;\u003C\u002Fspan>), \u003Cspan class=\"hljs-number\">1500\u003C\u002Fspan>)\n  \u003Cspan class=\"hljs-title function_\">speak\u003C\u002Fspan>(companion.\u003Cspan class=\"hljs-property\">dismiss\u003C\u002Fspan>)\n}\n\u003Cspan class=\"hljs-keyword\">async\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">function\u003C\u002Fspan> \u003Cspan class=\"hljs-title function_\">askTip\u003C\u002Fspan>(\u003Cspan class=\"hljs-params\">\u003C\u002Fspan>) {\n  \u003Cspan class=\"hljs-keyword\">if\u003C\u002Fspan> (busy.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan>) \u003Cspan class=\"hljs-keyword\">return\u003C\u002Fspan>\n  \u003Cspan class=\"hljs-title function_\">think\u003C\u002Fspan>()\n  \u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> { choice } = \u003Cspan class=\"hljs-keyword\">await\u003C\u002Fspan> \u003Cspan class=\"hljs-title function_\">post\u003C\u002Fspan>({ \u003Cspan class=\"hljs-attr\">kind\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;ask&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">dismissed\u003C\u002Fspan>: dismissed.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan>, lastTip, ...\u003Cspan class=\"hljs-title function_\">context\u003C\u002Fspan>() }).\u003Cspan class=\"hljs-title function_\">catch\u003C\u002Fspan>(\u003Cspan class=\"hljs-function\">() =&gt;\u003C\u002Fspan> ({ \u003Cspan class=\"hljs-attr\">choice\u003C\u002Fspan>: \u003Cspan class=\"hljs-variable constant_\">QUIET\u003C\u002Fspan> }))\n  busy.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan> = \u003Cspan class=\"hljs-literal\">false\u003C\u002Fspan>\n  \u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> next = \u003Cspan class=\"hljs-title function_\">tipFor\u003C\u002Fspan>(choice)\n  \u003Cspan class=\"hljs-keyword\">if\u003C\u002Fspan> (!next) { \u003Cspan class=\"hljs-title function_\">feel\u003C\u002Fspan>(\u003Cspan class=\"hljs-string\">&#x27;confused&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-number\">2000\u003C\u002Fspan>); \u003Cspan class=\"hljs-keyword\">return\u003C\u002Fspan> \u003Cspan class=\"hljs-title function_\">speak\u003C\u002Fspan>(companion.\u003Cspan class=\"hljs-property\">ask\u003C\u002Fspan>.\u003Cspan class=\"hljs-property\">failed\u003C\u002Fspan>) }\n  \u003Cspan class=\"hljs-title function_\">offer\u003C\u002Fspan>(next)\n}\n\u003Cspan class=\"hljs-title function_\">onKeyStroke\u003C\u002Fspan>(\u003Cspan class=\"hljs-string\">&#x27;Escape&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-function\">() =&gt;\u003C\u002Fspan> { \u003Cspan class=\"hljs-keyword\">if\u003C\u002Fspan> (tip.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan>) \u003Cspan class=\"hljs-title function_\">answerTip\u003C\u002Fspan>(\u003Cspan class=\"hljs-literal\">false\u003C\u002Fspan>) })\n\u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> hidden = \u003Cspan class=\"hljs-title function_\">useStored\u003C\u002Fspan>(\u003Cspan class=\"hljs-string\">&#x27;jevvieHidden&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-literal\">false\u003C\u002Fspan>, \u003Cspan class=\"hljs-title function_\">oneOf\u003C\u002Fspan>(\u003Cspan class=\"hljs-literal\">true\u003C\u002Fspan>, \u003Cspan class=\"hljs-literal\">false\u003C\u002Fspan>))\n\u003C\u002Fspan>\u003Cspan class=\"hljs-tag\">&lt;\u002F\u003Cspan class=\"hljs-name\">script\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n\n\u003Cspan class=\"hljs-tag\">&lt;\u003Cspan class=\"hljs-name\">template\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n  \u003Cspan class=\"hljs-tag\">&lt;\u003Cspan class=\"hljs-name\">div\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">ref\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;root&quot;\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">class\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;us&quot;\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">:class\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;{ &#x27;us--away&#x27;: away, &#x27;us--below&#x27;: atTop &lt; 240, &#x27;us--leftward&#x27;: leftward }&quot;\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">:style\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;{ &#x27;--talk&#x27;: talkWidth }&quot;\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n    \u003Cspan class=\"hljs-tag\">&lt;\u003Cspan class=\"hljs-name\">div\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">class\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;us__talk&quot;\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n      \u003Cspan class=\"hljs-tag\">&lt;\u003Cspan class=\"hljs-name\">ul\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">v-if\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;menu&quot;\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">class\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;us__menu shadow-win mono-label&quot;\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">:aria-label\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;companion.menu.label&quot;\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">role\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;menu&quot;\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n        \u003Cspan class=\"hljs-tag\">&lt;\u003Cspan class=\"hljs-name\">li\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">role\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;none&quot;\u003C\u002Fspan>&gt;\u003C\u002Fspan>\u003Cspan class=\"hljs-tag\">&lt;\u003Cspan class=\"hljs-name\">button\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">type\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;button&quot;\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">role\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;menuitem&quot;\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">class\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;bare read-1&quot;\u003C\u002Fspan> @\u003Cspan class=\"hljs-attr\">click\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;animate&quot;\u003C\u002Fspan>&gt;\u003C\u002Fspan>{{ companion.menu.animate }}\u003Cspan class=\"hljs-tag\">&lt;\u002F\u003Cspan class=\"hljs-name\">button\u003C\u002Fspan>&gt;\u003C\u002Fspan>\u003Cspan class=\"hljs-tag\">&lt;\u002F\u003Cspan class=\"hljs-name\">li\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n        \u003Cspan class=\"hljs-tag\">&lt;\u003Cspan class=\"hljs-name\">li\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">role\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;none&quot;\u003C\u002Fspan>&gt;\u003C\u002Fspan>\u003Cspan class=\"hljs-tag\">&lt;\u003Cspan class=\"hljs-name\">button\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">type\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;button&quot;\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">role\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;menuitem&quot;\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">class\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;bare read-1&quot;\u003C\u002Fspan> @\u003Cspan class=\"hljs-attr\">click\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;tipsOn = !tipsOn; menu = false&quot;\u003C\u002Fspan>&gt;\u003C\u002Fspan>{{ tipsOn ? companion.menu.tipsOn : companion.menu.tipsOff }}\u003Cspan class=\"hljs-tag\">&lt;\u002F\u003Cspan class=\"hljs-name\">button\u003C\u002Fspan>&gt;\u003C\u002Fspan>\u003Cspan class=\"hljs-tag\">&lt;\u002F\u003Cspan class=\"hljs-name\">li\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n        \u003Cspan class=\"hljs-tag\">&lt;\u003Cspan class=\"hljs-name\">li\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">role\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;none&quot;\u003C\u002Fspan>&gt;\u003C\u002Fspan>\u003Cspan class=\"hljs-tag\">&lt;\u003Cspan class=\"hljs-name\">button\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">type\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;button&quot;\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">role\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;menuitem&quot;\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">class\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;bare read-1&quot;\u003C\u002Fspan> @\u003Cspan class=\"hljs-attr\">click\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;nextBody&quot;\u003C\u002Fspan>&gt;\u003C\u002Fspan>{{ companion.menu.body }}: {{ BODIES[bodyShown]!.name }} ►\u003Cspan class=\"hljs-tag\">&lt;\u002F\u003Cspan class=\"hljs-name\">button\u003C\u002Fspan>&gt;\u003C\u002Fspan>\u003Cspan class=\"hljs-tag\">&lt;\u002F\u003Cspan class=\"hljs-name\">li\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n        \u003Cspan class=\"hljs-tag\">&lt;\u003Cspan class=\"hljs-name\">li\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">role\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;none&quot;\u003C\u002Fspan>&gt;\u003C\u002Fspan>\u003Cspan class=\"hljs-tag\">&lt;\u003Cspan class=\"hljs-name\">button\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">type\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;button&quot;\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">role\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;menuitem&quot;\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">class\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;bare read-1&quot;\u003C\u002Fspan> @\u003Cspan class=\"hljs-attr\">click\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;hidden = true&quot;\u003C\u002Fspan>&gt;\u003C\u002Fspan>{{ companion.menu.hide }}\u003Cspan class=\"hljs-tag\">&lt;\u002F\u003Cspan class=\"hljs-name\">button\u003C\u002Fspan>&gt;\u003C\u002Fspan>\u003Cspan class=\"hljs-tag\">&lt;\u002F\u003Cspan class=\"hljs-name\">li\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n      \u003Cspan class=\"hljs-tag\">&lt;\u002F\u003Cspan class=\"hljs-name\">ul\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n      \u003Cspan class=\"hljs-tag\">&lt;\u003Cspan class=\"hljs-name\">Win\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">v-if\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;open&quot;\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">:title\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;companion.panel.title&quot;\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">as\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;section&quot;\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">:label\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;companion.panel.question&quot;\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">class\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;us__win&quot;\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">closable\u003C\u002Fspan> @\u003Cspan class=\"hljs-attr\">close\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;closePanel&quot;\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n        \u003Cspan class=\"hljs-tag\">&lt;\u003Cspan class=\"hljs-name\">p\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">class\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;us__question&quot;\u003C\u002Fspan>&gt;\u003C\u002Fspan>{{ companion.panel.question }}\u003Cspan class=\"hljs-tag\">&lt;\u002F\u003Cspan class=\"hljs-name\">p\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n        \u003Cspan class=\"hljs-tag\">&lt;\u003Cspan class=\"hljs-name\">div\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">v-for\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;g in groups&quot;\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">:key\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;g.name&quot;\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">class\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;us__group&quot;\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n          \u003Cspan class=\"hljs-tag\">&lt;\u003Cspan class=\"hljs-name\">p\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">class\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;us__group-name mono-label&quot;\u003C\u002Fspan>&gt;\u003C\u002Fspan>{{ g.name }}\u003Cspan class=\"hljs-tag\">&lt;\u002F\u003Cspan class=\"hljs-name\">p\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n          \u003Cspan class=\"hljs-tag\">&lt;\u003Cspan class=\"hljs-name\">ul\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">class\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;us__list&quot;\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n            \u003Cspan class=\"hljs-tag\">&lt;\u003Cspan class=\"hljs-name\">li\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">v-for\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;s in g.items&quot;\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">:key\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;s.label&quot;\u003C\u002Fspan>&gt;\u003C\u002Fspan>\u003Cspan class=\"hljs-tag\">&lt;\u003Cspan class=\"hljs-name\">button\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">type\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;button&quot;\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">class\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;bare read-1&quot;\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">:disabled\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;busy&quot;\u003C\u002Fspan> @\u003Cspan class=\"hljs-attr\">click\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;suggest(s)&quot;\u003C\u002Fspan>&gt;\u003C\u002Fspan>{{ s.label }}\u003Cspan class=\"hljs-tag\">&lt;\u002F\u003Cspan class=\"hljs-name\">button\u003C\u002Fspan>&gt;\u003C\u002Fspan>\u003Cspan class=\"hljs-tag\">&lt;\u002F\u003Cspan class=\"hljs-name\">li\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n          \u003Cspan class=\"hljs-tag\">&lt;\u002F\u003Cspan class=\"hljs-name\">ul\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n        \u003Cspan class=\"hljs-tag\">&lt;\u002F\u003Cspan class=\"hljs-name\">div\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n        \u003Cspan class=\"hljs-tag\">&lt;\u003Cspan class=\"hljs-name\">button\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">v-if\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;hiddenCount &gt; 0 || more&quot;\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">type\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;button&quot;\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">class\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;us__more bare read-1 mono-label&quot;\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">:aria-expanded\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;more&quot;\u003C\u002Fspan> @\u003Cspan class=\"hljs-attr\">click\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;more = !more&quot;\u003C\u002Fspan>&gt;\u003C\u002Fspan>{{ more ? `${companion.panel.less} ▲` : `${companion.panel.more} (${hiddenCount}) ▼` }}\u003Cspan class=\"hljs-tag\">&lt;\u002F\u003Cspan class=\"hljs-name\">button\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n        \u003Cspan class=\"hljs-tag\">&lt;\u003Cspan class=\"hljs-name\">TuiPrompt\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">:label\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;companion.ask.label&quot;\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">:placeholder\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;companion.ask.placeholder&quot;\u003C\u002Fspan> @\u003Cspan class=\"hljs-attr\">submit\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;ask&quot;\u003C\u002Fspan> \u002F&gt;\u003C\u002Fspan>\n        \u003Cspan class=\"hljs-tag\">&lt;\u003Cspan class=\"hljs-name\">p\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">class\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;us__foot mono-label&quot;\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n          \u003Cspan class=\"hljs-tag\">&lt;\u003Cspan class=\"hljs-name\">button\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">type\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;button&quot;\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">class\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;bare read-1&quot;\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">:disabled\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;busy&quot;\u003C\u002Fspan> @\u003Cspan class=\"hljs-attr\">click\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;askTip&quot;\u003C\u002Fspan>&gt;\u003C\u002Fspan>\u003Cspan class=\"hljs-tag\">&lt;\u003Cspan class=\"hljs-name\">PhLightbulb\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">:size\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;14&quot;\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">weight\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;bold&quot;\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">aria-hidden\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;true&quot;\u003C\u002Fspan> \u002F&gt;\u003C\u002Fspan> {{ companion.panel.tip }}\u003Cspan class=\"hljs-tag\">&lt;\u002F\u003Cspan class=\"hljs-name\">button\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n          \u003Cspan class=\"hljs-tag\">&lt;\u003Cspan class=\"hljs-name\">button\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">type\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;button&quot;\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">class\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;bare read-1&quot;\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">:disabled\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;busy&quot;\u003C\u002Fspan> @\u003Cspan class=\"hljs-attr\">click\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;suggest()&quot;\u003C\u002Fspan>&gt;\u003C\u002Fspan>{{ companion.panel.surprise }} ►\u003Cspan class=\"hljs-tag\">&lt;\u002F\u003Cspan class=\"hljs-name\">button\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n          \u003Cspan class=\"hljs-tag\">&lt;\u003Cspan class=\"hljs-name\">button\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">type\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;button&quot;\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">class\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;bare read-1&quot;\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">:aria-expanded\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;menu&quot;\u003C\u002Fspan> @\u003Cspan class=\"hljs-attr\">click\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;openMenu&quot;\u003C\u002Fspan>&gt;\u003C\u002Fspan>{{ companion.panel.options }}\u003Cspan class=\"hljs-tag\">&lt;\u002F\u003Cspan class=\"hljs-name\">button\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n        \u003Cspan class=\"hljs-tag\">&lt;\u002F\u003Cspan class=\"hljs-name\">p\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n      \u003Cspan class=\"hljs-tag\">&lt;\u002F\u003Cspan class=\"hljs-name\">Win\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n      \u003Cspan class=\"hljs-tag\">&lt;\u003Cspan class=\"hljs-name\">div\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">v-if\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;say&quot;\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">class\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;us__say shadow-win text-11&quot;\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">:class\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;{ &#x27;us__say--tip&#x27;: tip }&quot;\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">role\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;status&quot;\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">aria-live\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;polite&quot;\u003C\u002Fspan>&gt;\u003C\u002Fspan>\u003Cspan class=\"hljs-tag\">&lt;\u003Cspan class=\"hljs-name\">div\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">class\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;us__panel bg-paper&quot;\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n        \u003Cspan class=\"hljs-tag\">&lt;\u003Cspan class=\"hljs-name\">button\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">v-if\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;!tip&quot;\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">type\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;button&quot;\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">class\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;us__x bare hit read-1&quot;\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">:aria-label\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;companion.answers.close&quot;\u003C\u002Fspan> @\u003Cspan class=\"hljs-attr\">click\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;hush()&quot;\u003C\u002Fspan>&gt;\u003C\u002Fspan>×\u003Cspan class=\"hljs-tag\">&lt;\u002F\u003Cspan class=\"hljs-name\">button\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n        \u003Cspan class=\"hljs-tag\">&lt;\u003Cspan class=\"hljs-name\">p\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">class\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;us__line&quot;\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n          \u003Cspan class=\"hljs-tag\">&lt;\u003Cspan class=\"hljs-name\">PhLightbulb\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">v-if\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;tip&quot;\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">class\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;us__bulb&quot;\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">:size\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;14&quot;\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">weight\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;bold&quot;\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">aria-hidden\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;true&quot;\u003C\u002Fspan> \u002F&gt;\u003C\u002Fspan>\n          \u003Cspan class=\"hljs-tag\">&lt;\u003Cspan class=\"hljs-name\">span\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">class\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;us__text&quot;\u003C\u002Fspan>&gt;\u003C\u002Fspan>\u003Cspan class=\"hljs-tag\">&lt;\u003Cspan class=\"hljs-name\">span\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">class\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;us__ghost&quot;\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">aria-hidden\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;true&quot;\u003C\u002Fspan>&gt;\u003C\u002Fspan>{{ say }}█\u003Cspan class=\"hljs-tag\">&lt;\u002F\u003Cspan class=\"hljs-name\">span\u003C\u002Fspan>&gt;\u003C\u002Fspan>\u003Cspan class=\"hljs-tag\">&lt;\u003Cspan class=\"hljs-name\">span\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">aria-hidden\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;true&quot;\u003C\u002Fspan>&gt;\u003C\u002Fspan>{{ typed }}\u003Cspan class=\"hljs-tag\">&lt;\u003Cspan class=\"hljs-name\">Cursor\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">:steady\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;typed.length &lt; say.length&quot;\u003C\u002Fspan> \u002F&gt;\u003C\u002Fspan>\u003Cspan class=\"hljs-tag\">&lt;\u002F\u003Cspan class=\"hljs-name\">span\u003C\u002Fspan>&gt;\u003C\u002Fspan>\u003Cspan class=\"hljs-tag\">&lt;\u002F\u003Cspan class=\"hljs-name\">span\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n          \u003Cspan class=\"hljs-tag\">&lt;\u003Cspan class=\"hljs-name\">span\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">class\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;visually-hidden&quot;\u003C\u002Fspan>&gt;\u003C\u002Fspan>{{ say }}\u003Cspan class=\"hljs-tag\">&lt;\u002F\u003Cspan class=\"hljs-name\">span\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n        \u003Cspan class=\"hljs-tag\">&lt;\u002F\u003Cspan class=\"hljs-name\">p\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n        \u003Cspan class=\"hljs-tag\">&lt;\u003Cspan class=\"hljs-name\">p\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">v-if\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;sure&quot;\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">class\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;us__sure&quot;\u003C\u002Fspan>&gt;\u003C\u002Fspan>{{ sure }}\u003Cspan class=\"hljs-tag\">&lt;\u003Cspan class=\"hljs-name\">template\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">v-if\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;choices.length&quot;\u003C\u002Fspan>&gt;\u003C\u002Fspan> · {{ companion.clarify.or }}\u003Cspan class=\"hljs-tag\">&lt;\u002F\u003Cspan class=\"hljs-name\">template\u003C\u002Fspan>&gt;\u003C\u002Fspan>\u003Cspan class=\"hljs-tag\">&lt;\u002F\u003Cspan class=\"hljs-name\">p\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n        \u003Cspan class=\"hljs-tag\">&lt;\u003Cspan class=\"hljs-name\">p\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">v-if\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;choices.length&quot;\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">class\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;us__choices&quot;\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n          \u003Cspan class=\"hljs-tag\">&lt;\u003Cspan class=\"hljs-name\">button\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">v-for\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;c in choices&quot;\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">:key\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;c.label&quot;\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">type\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;button&quot;\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">class\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;bare hit read-1&quot;\u003C\u002Fspan> @\u003Cspan class=\"hljs-attr\">click\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;c.run&quot;\u003C\u002Fspan>&gt;\u003C\u002Fspan>{{ c.label }}\u003Cspan class=\"hljs-tag\">&lt;\u002F\u003Cspan class=\"hljs-name\">button\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n        \u003Cspan class=\"hljs-tag\">&lt;\u002F\u003Cspan class=\"hljs-name\">p\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n        \u003Cspan class=\"hljs-tag\">&lt;\u003Cspan class=\"hljs-name\">div\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">v-if\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;tip&quot;\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">class\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;us__answers btn-group&quot;\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n          \u003Cspan class=\"hljs-tag\">&lt;\u003Cspan class=\"hljs-name\">Btn\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">size\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;sm&quot;\u003C\u002Fspan> @\u003Cspan class=\"hljs-attr\">click\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;answerTip(true)&quot;\u003C\u002Fspan>&gt;\u003C\u002Fspan>{{ tip.action ? companion.answers.yes : companion.answers.thanks }}\u003Cspan class=\"hljs-tag\">&lt;\u002F\u003Cspan class=\"hljs-name\">Btn\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n          \u003Cspan class=\"hljs-tag\">&lt;\u003Cspan class=\"hljs-name\">Btn\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">size\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;sm&quot;\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">variant\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;ghost&quot;\u003C\u002Fspan> @\u003Cspan class=\"hljs-attr\">click\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;answerTip(false)&quot;\u003C\u002Fspan>&gt;\u003C\u002Fspan>{{ tip.action ? companion.answers.no : companion.answers.later }}\u003Cspan class=\"hljs-tag\">&lt;\u002F\u003Cspan class=\"hljs-name\">Btn\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n        \u003Cspan class=\"hljs-tag\">&lt;\u002F\u003Cspan class=\"hljs-name\">div\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n      \u003Cspan class=\"hljs-tag\">&lt;\u002F\u003Cspan class=\"hljs-name\">div\u003C\u002Fspan>&gt;\u003C\u002Fspan>\u003Cspan class=\"hljs-tag\">&lt;\u002F\u003Cspan class=\"hljs-name\">div\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n    \u003Cspan class=\"hljs-tag\">&lt;\u002F\u003Cspan class=\"hljs-name\">div\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n    \u003Cspan class=\"hljs-tag\">&lt;\u003Cspan class=\"hljs-name\">div\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">ref\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;body&quot;\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">class\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;us__body&quot;\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">:style\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;{ rotate: `${swing}deg` }&quot;\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n      \u003Cspan class=\"hljs-tag\">&lt;\u003Cspan class=\"hljs-name\">div\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">ref\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;handle&quot;\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">class\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;us__handle&quot;\u003C\u002Fspan> @\u003Cspan class=\"hljs-attr\">click\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;click&quot;\u003C\u002Fspan> @\u003Cspan class=\"hljs-attr\">dblclick\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;animate&quot;\u003C\u002Fspan> @\u003Cspan class=\"hljs-attr\">contextmenu.prevent\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;openMenu&quot;\u003C\u002Fspan> @\u003Cspan class=\"hljs-attr\">keydown.enter.prevent\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;poke&quot;\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n        \u003Cspan class=\"hljs-tag\">&lt;\u003Cspan class=\"hljs-name\">span\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">class\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;win__title visually-hidden&quot;\u003C\u002Fspan>&gt;\u003C\u002Fspan>{{ companion.name }}\u003Cspan class=\"hljs-tag\">&lt;\u002F\u003Cspan class=\"hljs-name\">span\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n        \u003Cspan class=\"hljs-tag\">&lt;\u003Cspan class=\"hljs-name\">canvas\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">ref\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;canvas&quot;\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">:key\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;bodyShown&quot;\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">class\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;us__canvas&quot;\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">width\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;64&quot;\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">height\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;44&quot;\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">aria-hidden\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;true&quot;\u003C\u002Fspan> \u002F&gt;\u003C\u002Fspan>\n      \u003Cspan class=\"hljs-tag\">&lt;\u002F\u003Cspan class=\"hljs-name\">div\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n    \u003Cspan class=\"hljs-tag\">&lt;\u002F\u003Cspan class=\"hljs-name\">div\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n    \u003Cspan class=\"hljs-tag\">&lt;\u003Cspan class=\"hljs-name\">Teleport\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">to\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;body&quot;\u003C\u002Fspan>&gt;\u003C\u002Fspan>\u003Cspan class=\"hljs-tag\">&lt;\u003Cspan class=\"hljs-name\">canvas\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">ref\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;trailCanvas&quot;\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">class\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;us-trail&quot;\u003C\u002Fspan> \u003Cspan class=\"hljs-attr\">aria-hidden\u003C\u002Fspan>=\u003Cspan class=\"hljs-string\">&quot;true&quot;\u003C\u002Fspan> \u002F&gt;\u003C\u002Fspan>\u003Cspan class=\"hljs-tag\">&lt;\u002F\u003Cspan class=\"hljs-name\">Teleport\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n  \u003Cspan class=\"hljs-tag\">&lt;\u002F\u003Cspan class=\"hljs-name\">div\u003C\u002Fspan>&gt;\u003C\u002Fspan>\n\u003Cspan class=\"hljs-tag\">&lt;\u002F\u003Cspan class=\"hljs-name\">template\u003C\u002Fspan>&gt;\u003C\u002Fspan>",{"path":227,"lines":228,"code":229,"html":230},"app\u002Fcomposables\u002FuseJevPick.ts",5,"import type { JevPick } from '@cw\u002Fjevvie'\n\n\u002F** Jev's picks stay in this tab's memory: never sent anywhere or stored. *\u002F\nexport const useJevPick = () => useState\u003CJevPick | null>('jev-pick', () => null)\nexport const useJevPicks = () => useState\u003CJevPick[]>('jev-picks', () => [])","\u003Cspan class=\"hljs-keyword\">import\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">type\u003C\u002Fspan> { \u003Cspan class=\"hljs-title class_\">JevPick\u003C\u002Fspan> } \u003Cspan class=\"hljs-keyword\">from\u003C\u002Fspan> \u003Cspan class=\"hljs-string\">&#x27;@cw\u002Fjevvie&#x27;\u003C\u002Fspan>\n\n\u003Cspan class=\"hljs-comment\">\u002F** Jev&#x27;s picks stay in this tab&#x27;s memory: never sent anywhere or stored. *\u002F\u003C\u002Fspan>\n\u003Cspan class=\"hljs-keyword\">export\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> \u003Cspan class=\"hljs-title function_\">useJevPick\u003C\u002Fspan> = (\u003Cspan class=\"hljs-params\">\u003C\u002Fspan>) =&gt; useState&lt;\u003Cspan class=\"hljs-title class_\">JevPick\u003C\u002Fspan> | \u003Cspan class=\"hljs-literal\">null\u003C\u002Fspan>&gt;(\u003Cspan class=\"hljs-string\">&#x27;jev-pick&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-function\">() =&gt;\u003C\u002Fspan> \u003Cspan class=\"hljs-literal\">null\u003C\u002Fspan>)\n\u003Cspan class=\"hljs-keyword\">export\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> \u003Cspan class=\"hljs-title function_\">useJevPicks\u003C\u002Fspan> = (\u003Cspan class=\"hljs-params\">\u003C\u002Fspan>) =&gt; useState&lt;\u003Cspan class=\"hljs-title class_\">JevPick\u003C\u002Fspan>[]&gt;(\u003Cspan class=\"hljs-string\">&#x27;jev-picks&#x27;\u003C\u002Fspan>, \u003Cspan class=\"hljs-function\">() =&gt;\u003C\u002Fspan> [])",{"path":232,"lines":233,"code":234,"html":235},"app\u002Fcomposables\u002FuseJevvie.ts",7,"import type { Mood, Trick } from '@cw\u002Fjevvie\u002Fcharacter'\n\nexport type JevvieLine = { text: string; mood?: Mood; trick?: Trick }\nconst bus = useEventBus\u003CJevvieLine>('jevvie-say')\n\nexport const jevvieSay = (line: JevvieLine) => bus.emit(line)\nexport const onJevvieSay = (fn: (line: JevvieLine) => void) => bus.on(fn)","\u003Cspan class=\"hljs-keyword\">import\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">type\u003C\u002Fspan> { \u003Cspan class=\"hljs-title class_\">Mood\u003C\u002Fspan>, \u003Cspan class=\"hljs-title class_\">Trick\u003C\u002Fspan> } \u003Cspan class=\"hljs-keyword\">from\u003C\u002Fspan> \u003Cspan class=\"hljs-string\">&#x27;@cw\u002Fjevvie\u002Fcharacter&#x27;\u003C\u002Fspan>\n\n\u003Cspan class=\"hljs-keyword\">export\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">type\u003C\u002Fspan> \u003Cspan class=\"hljs-title class_\">JevvieLine\u003C\u002Fspan> = { \u003Cspan class=\"hljs-attr\">text\u003C\u002Fspan>: \u003Cspan class=\"hljs-built_in\">string\u003C\u002Fspan>; \u003Cspan class=\"hljs-attr\">mood\u003C\u002Fspan>?: \u003Cspan class=\"hljs-title class_\">Mood\u003C\u002Fspan>; \u003Cspan class=\"hljs-attr\">trick\u003C\u002Fspan>?: \u003Cspan class=\"hljs-title class_\">Trick\u003C\u002Fspan> }\n\u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> bus = useEventBus&lt;\u003Cspan class=\"hljs-title class_\">JevvieLine\u003C\u002Fspan>&gt;(\u003Cspan class=\"hljs-string\">&#x27;jevvie-say&#x27;\u003C\u002Fspan>)\n\n\u003Cspan class=\"hljs-keyword\">export\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> \u003Cspan class=\"hljs-title function_\">jevvieSay\u003C\u002Fspan> = (\u003Cspan class=\"hljs-params\">\u003Cspan class=\"hljs-attr\">line\u003C\u002Fspan>: \u003Cspan class=\"hljs-title class_\">JevvieLine\u003C\u002Fspan>\u003C\u002Fspan>) =&gt; bus.\u003Cspan class=\"hljs-title function_\">emit\u003C\u002Fspan>(line)\n\u003Cspan class=\"hljs-keyword\">export\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> \u003Cspan class=\"hljs-title function_\">onJevvieSay\u003C\u002Fspan> = (\u003Cspan class=\"hljs-params\">\u003Cspan class=\"hljs-attr\">fn\u003C\u002Fspan>: (line: JevvieLine) =&gt; \u003Cspan class=\"hljs-built_in\">void\u003C\u002Fspan>\u003C\u002Fspan>) =&gt; bus.\u003Cspan class=\"hljs-title function_\">on\u003C\u002Fspan>(fn)",{"path":237,"lines":238,"code":239,"html":240},"app\u002Fcomposables\u002FuseSiteTools.ts",34,"import type { ToolInfo } from '@cw\u002Fjevvie'\n\nexport type SiteTool = ToolInfo & {\n  doing: (label?: string) => string\n  target?: (value?: string) => Element | null | undefined\n  run: (value?: string) => unknown\n  readOnly?: boolean\n  agentOnly?: boolean\n}\nexport type ToolCall = { tool: SiteTool; value?: string; label?: string; by: 'agent' | 'jevvie' }\n\nconst tools = shallowReactive(new Map\u003Cstring, SiteTool>())\nconst bus = useEventBus\u003CToolCall>('site-tool')\n\nexport function useSiteTool(tool: () => SiteTool) {\n  if (import.meta.server) return\n  const name = tool().name\n  watchEffect(() => { tools.set(name, tool()) })\n  onScopeDispose(() => { tools.delete(name) })\n}\n\nexport const siteTools = () => tools\nexport const onToolCall = (fn: (call: ToolCall) => void) => bus.on(fn)\n\nexport async function callTool(name: string, value: string | undefined, by: ToolCall['by']) {\n  const tool = tools.get(name)\n  if (!tool) throw new Error(`No action called ${name} here`)\n  const values = tool.arg?.values\n  if (values && !values.some((v) => v.value === value)) throw new Error(`${name} takes one of: ${values.slice(0, 30).map((v) => v.value).join(', ')}`)\n  const label = values?.find((v) => v.value === value)?.label ?? value\n  bus.emit({ tool, value, label, by })\n  const result = await tool.run(value)\n  return { doing: tool.doing(label), result: typeof result === 'string' ? result : undefined }\n}","\u003Cspan class=\"hljs-keyword\">import\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">type\u003C\u002Fspan> { \u003Cspan class=\"hljs-title class_\">ToolInfo\u003C\u002Fspan> } \u003Cspan class=\"hljs-keyword\">from\u003C\u002Fspan> \u003Cspan class=\"hljs-string\">&#x27;@cw\u002Fjevvie&#x27;\u003C\u002Fspan>\n\n\u003Cspan class=\"hljs-keyword\">export\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">type\u003C\u002Fspan> \u003Cspan class=\"hljs-title class_\">SiteTool\u003C\u002Fspan> = \u003Cspan class=\"hljs-title class_\">ToolInfo\u003C\u002Fspan> &amp; {\n  \u003Cspan class=\"hljs-attr\">doing\u003C\u002Fspan>: \u003Cspan class=\"hljs-function\">(\u003Cspan class=\"hljs-params\">\u003Cspan class=\"hljs-attr\">label\u003C\u002Fspan>?: \u003Cspan class=\"hljs-built_in\">string\u003C\u002Fspan>\u003C\u002Fspan>) =&gt;\u003C\u002Fspan> \u003Cspan class=\"hljs-built_in\">string\u003C\u002Fspan>\n  \u003Cspan class=\"hljs-attr\">target\u003C\u002Fspan>?: \u003Cspan class=\"hljs-function\">(\u003Cspan class=\"hljs-params\">\u003Cspan class=\"hljs-attr\">value\u003C\u002Fspan>?: \u003Cspan class=\"hljs-built_in\">string\u003C\u002Fspan>\u003C\u002Fspan>) =&gt;\u003C\u002Fspan> \u003Cspan class=\"hljs-title class_\">Element\u003C\u002Fspan> | \u003Cspan class=\"hljs-literal\">null\u003C\u002Fspan> | \u003Cspan class=\"hljs-literal\">undefined\u003C\u002Fspan>\n  \u003Cspan class=\"hljs-attr\">run\u003C\u002Fspan>: \u003Cspan class=\"hljs-function\">(\u003Cspan class=\"hljs-params\">\u003Cspan class=\"hljs-attr\">value\u003C\u002Fspan>?: \u003Cspan class=\"hljs-built_in\">string\u003C\u002Fspan>\u003C\u002Fspan>) =&gt;\u003C\u002Fspan> \u003Cspan class=\"hljs-built_in\">unknown\u003C\u002Fspan>\n  \u003Cspan class=\"hljs-attr\">readOnly\u003C\u002Fspan>?: \u003Cspan class=\"hljs-built_in\">boolean\u003C\u002Fspan>\n  \u003Cspan class=\"hljs-attr\">agentOnly\u003C\u002Fspan>?: \u003Cspan class=\"hljs-built_in\">boolean\u003C\u002Fspan>\n}\n\u003Cspan class=\"hljs-keyword\">export\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">type\u003C\u002Fspan> \u003Cspan class=\"hljs-title class_\">ToolCall\u003C\u002Fspan> = { \u003Cspan class=\"hljs-attr\">tool\u003C\u002Fspan>: \u003Cspan class=\"hljs-title class_\">SiteTool\u003C\u002Fspan>; \u003Cspan class=\"hljs-attr\">value\u003C\u002Fspan>?: \u003Cspan class=\"hljs-built_in\">string\u003C\u002Fspan>; \u003Cspan class=\"hljs-attr\">label\u003C\u002Fspan>?: \u003Cspan class=\"hljs-built_in\">string\u003C\u002Fspan>; \u003Cspan class=\"hljs-attr\">by\u003C\u002Fspan>: \u003Cspan class=\"hljs-string\">&#x27;agent&#x27;\u003C\u002Fspan> | \u003Cspan class=\"hljs-string\">&#x27;jevvie&#x27;\u003C\u002Fspan> }\n\n\u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> tools = \u003Cspan class=\"hljs-title function_\">shallowReactive\u003C\u002Fspan>(\u003Cspan class=\"hljs-keyword\">new\u003C\u002Fspan> \u003Cspan class=\"hljs-title class_\">Map\u003C\u002Fspan>&lt;\u003Cspan class=\"hljs-built_in\">string\u003C\u002Fspan>, \u003Cspan class=\"hljs-title class_\">SiteTool\u003C\u002Fspan>&gt;())\n\u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> bus = useEventBus&lt;\u003Cspan class=\"hljs-title class_\">ToolCall\u003C\u002Fspan>&gt;(\u003Cspan class=\"hljs-string\">&#x27;site-tool&#x27;\u003C\u002Fspan>)\n\n\u003Cspan class=\"hljs-keyword\">export\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">function\u003C\u002Fspan> \u003Cspan class=\"hljs-title function_\">useSiteTool\u003C\u002Fspan>(\u003Cspan class=\"hljs-params\">\u003Cspan class=\"hljs-attr\">tool\u003C\u002Fspan>: () =&gt; \u003Cspan class=\"hljs-title class_\">SiteTool\u003C\u002Fspan>\u003C\u002Fspan>) {\n  \u003Cspan class=\"hljs-keyword\">if\u003C\u002Fspan> (\u003Cspan class=\"hljs-keyword\">import\u003C\u002Fspan>.\u003Cspan class=\"hljs-property\">meta\u003C\u002Fspan>.\u003Cspan class=\"hljs-property\">server\u003C\u002Fspan>) \u003Cspan class=\"hljs-keyword\">return\u003C\u002Fspan>\n  \u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> name = \u003Cspan class=\"hljs-title function_\">tool\u003C\u002Fspan>().\u003Cspan class=\"hljs-property\">name\u003C\u002Fspan>\n  \u003Cspan class=\"hljs-title function_\">watchEffect\u003C\u002Fspan>(\u003Cspan class=\"hljs-function\">() =&gt;\u003C\u002Fspan> { tools.\u003Cspan class=\"hljs-title function_\">set\u003C\u002Fspan>(name, \u003Cspan class=\"hljs-title function_\">tool\u003C\u002Fspan>()) })\n  \u003Cspan class=\"hljs-title function_\">onScopeDispose\u003C\u002Fspan>(\u003Cspan class=\"hljs-function\">() =&gt;\u003C\u002Fspan> { tools.\u003Cspan class=\"hljs-title function_\">delete\u003C\u002Fspan>(name) })\n}\n\n\u003Cspan class=\"hljs-keyword\">export\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> \u003Cspan class=\"hljs-title function_\">siteTools\u003C\u002Fspan> = (\u003Cspan class=\"hljs-params\">\u003C\u002Fspan>) =&gt; tools\n\u003Cspan class=\"hljs-keyword\">export\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> \u003Cspan class=\"hljs-title function_\">onToolCall\u003C\u002Fspan> = (\u003Cspan class=\"hljs-params\">\u003Cspan class=\"hljs-attr\">fn\u003C\u002Fspan>: (call: ToolCall) =&gt; \u003Cspan class=\"hljs-built_in\">void\u003C\u002Fspan>\u003C\u002Fspan>) =&gt; bus.\u003Cspan class=\"hljs-title function_\">on\u003C\u002Fspan>(fn)\n\n\u003Cspan class=\"hljs-keyword\">export\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">async\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">function\u003C\u002Fspan> \u003Cspan class=\"hljs-title function_\">callTool\u003C\u002Fspan>(\u003Cspan class=\"hljs-params\">\u003Cspan class=\"hljs-attr\">name\u003C\u002Fspan>: \u003Cspan class=\"hljs-built_in\">string\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">value\u003C\u002Fspan>: \u003Cspan class=\"hljs-built_in\">string\u003C\u002Fspan> | \u003Cspan class=\"hljs-literal\">undefined\u003C\u002Fspan>, \u003Cspan class=\"hljs-attr\">by\u003C\u002Fspan>: \u003Cspan class=\"hljs-title class_\">ToolCall\u003C\u002Fspan>[\u003Cspan class=\"hljs-string\">&#x27;by&#x27;\u003C\u002Fspan>]\u003C\u002Fspan>) {\n  \u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> tool = tools.\u003Cspan class=\"hljs-title function_\">get\u003C\u002Fspan>(name)\n  \u003Cspan class=\"hljs-keyword\">if\u003C\u002Fspan> (!tool) \u003Cspan class=\"hljs-keyword\">throw\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">new\u003C\u002Fspan> \u003Cspan class=\"hljs-title class_\">Error\u003C\u002Fspan>(\u003Cspan class=\"hljs-string\">`No action called \u003Cspan class=\"hljs-subst\">${name}\u003C\u002Fspan> here`\u003C\u002Fspan>)\n  \u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> values = tool.\u003Cspan class=\"hljs-property\">arg\u003C\u002Fspan>?.\u003Cspan class=\"hljs-property\">values\u003C\u002Fspan>\n  \u003Cspan class=\"hljs-keyword\">if\u003C\u002Fspan> (values &amp;&amp; !values.\u003Cspan class=\"hljs-title function_\">some\u003C\u002Fspan>(\u003Cspan class=\"hljs-function\">(\u003Cspan class=\"hljs-params\">v\u003C\u002Fspan>) =&gt;\u003C\u002Fspan> v.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan> === value)) \u003Cspan class=\"hljs-keyword\">throw\u003C\u002Fspan> \u003Cspan class=\"hljs-keyword\">new\u003C\u002Fspan> \u003Cspan class=\"hljs-title class_\">Error\u003C\u002Fspan>(\u003Cspan class=\"hljs-string\">`\u003Cspan class=\"hljs-subst\">${name}\u003C\u002Fspan> takes one of: \u003Cspan class=\"hljs-subst\">${values.slice(\u003Cspan class=\"hljs-number\">0\u003C\u002Fspan>, \u003Cspan class=\"hljs-number\">30\u003C\u002Fspan>).map((v) =&gt; v.value).join(\u003Cspan class=\"hljs-string\">&#x27;, &#x27;\u003C\u002Fspan>)}\u003C\u002Fspan>`\u003C\u002Fspan>)\n  \u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> label = values?.\u003Cspan class=\"hljs-title function_\">find\u003C\u002Fspan>(\u003Cspan class=\"hljs-function\">(\u003Cspan class=\"hljs-params\">v\u003C\u002Fspan>) =&gt;\u003C\u002Fspan> v.\u003Cspan class=\"hljs-property\">value\u003C\u002Fspan> === value)?.\u003Cspan class=\"hljs-property\">label\u003C\u002Fspan> ?? value\n  bus.\u003Cspan class=\"hljs-title function_\">emit\u003C\u002Fspan>({ tool, value, label, by })\n  \u003Cspan class=\"hljs-keyword\">const\u003C\u002Fspan> result = \u003Cspan class=\"hljs-keyword\">await\u003C\u002Fspan> tool.\u003Cspan class=\"hljs-title function_\">run\u003C\u002Fspan>(value)\n  \u003Cspan class=\"hljs-keyword\">return\u003C\u002Fspan> { \u003Cspan class=\"hljs-attr\">doing\u003C\u002Fspan>: tool.\u003Cspan class=\"hljs-title function_\">doing\u003C\u002Fspan>(label), \u003Cspan class=\"hljs-attr\">result\u003C\u002Fspan>: \u003Cspan class=\"hljs-keyword\">typeof\u003C\u002Fspan> result === \u003Cspan class=\"hljs-string\">&#x27;string&#x27;\u003C\u002Fspan> ? result : \u003Cspan class=\"hljs-literal\">undefined\u003C\u002Fspan> }\n}",1792054520343]