summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpolwex <polwex@sortug.com>2025-09-11 01:48:14 +0700
committerpolwex <polwex@sortug.com>2025-09-11 01:48:14 +0700
commitb1d68ac307ed87d63e83820cbdf843fff0fd9f7f (patch)
treed6a684a70a80509e68ff667b842aa4e4c091906f
init
-rw-r--r--.claude/settings.local.json10
-rw-r--r--.gitignore1
-rw-r--r--desk/NOTES.md39
-rw-r--r--desk/app/nostril.hoon204
-rw-r--r--desk/desk.bill2
-rw-r--r--desk/desk.docket-011
-rw-r--r--desk/desk.ship1
-rw-r--r--desk/lib/dbug.hoon155
-rw-r--r--desk/lib/docket.hoon223
-rw-r--r--desk/lib/json/common.hoon29
-rw-r--r--desk/lib/json/nostr.hoon116
-rw-r--r--desk/lib/json/nostril.hoon113
-rw-r--r--desk/lib/json/trill.hoon191
-rw-r--r--desk/lib/markdown.hoon1711
-rw-r--r--desk/lib/nostr.hoon29
-rw-r--r--desk/lib/nostril.hoon28
-rw-r--r--desk/lib/nostril/mutations.hoon117
-rw-r--r--desk/lib/server.hoon159
-rw-r--r--desk/lib/shim.hoon23
l---------desk/lib/sortug.hoon1
-rw-r--r--desk/lib/strand.hoon1
-rw-r--r--desk/lib/strandio.hoon965
-rw-r--r--desk/lib/trill/post.hoon377
-rw-r--r--desk/mar/bill.hoon34
-rw-r--r--desk/mar/css.hoon25
-rw-r--r--desk/mar/docket-0.hoon25
-rw-r--r--desk/mar/hoon.hoon36
-rw-r--r--desk/mar/ico.hoon12
-rw-r--r--desk/mar/js.hoon25
-rw-r--r--desk/mar/kelvin.hoon28
-rw-r--r--desk/mar/mime.hoon32
-rw-r--r--desk/mar/noun.hoon22
-rw-r--r--desk/mar/png.hoon12
-rw-r--r--desk/mar/ship.hoon20
-rw-r--r--desk/mar/svg.hoon12
-rw-r--r--desk/mar/webmanifest.hoon12
-rw-r--r--desk/sur/docket.hoon82
-rw-r--r--desk/sur/markdown.hoon157
-rw-r--r--desk/sur/nostr.hoon47
-rw-r--r--desk/sur/nostril.hoon54
-rw-r--r--desk/sur/spider.hoon27
-rw-r--r--desk/sur/trill/feed.hoon16
-rw-r--r--desk/sur/trill/gate.hoon26
-rw-r--r--desk/sur/trill/post.hoon121
-rw-r--r--desk/sys.kelvin1
-rw-r--r--desk/ted/fetch.hoon24
-rw-r--r--desk/web/assets/apple-touch-icon.pngbin0 -> 18464 bytes
-rw-r--r--desk/web/assets/favicon-16x16.pngbin0 -> 863 bytes
-rw-r--r--desk/web/assets/favicon-32x32.pngbin0 -> 2066 bytes
-rw-r--r--desk/web/assets/favicon.icobin0 -> 15406 bytes
-rw-r--r--desk/web/assets/script.js0
-rw-r--r--desk/web/assets/site.webmanifest1
-rw-r--r--desk/web/assets/spinner.svg1
-rw-r--r--desk/web/assets/style.css415
-rw-r--r--desk/web/components/components.hoon3
-rw-r--r--desk/web/components/navbar.hoon54
-rw-r--r--desk/web/components/post-text.hoon134
-rw-r--r--desk/web/components/sigil/sigil.hoon227
-rw-r--r--desk/web/components/sigil/symbols.hoon14332
-rw-r--r--desk/web/layout.hoon24
-rw-r--r--desk/web/pages/index.hoon15
-rw-r--r--desk/web/router.hoon43
-rw-r--r--front/.gitignore34
-rw-r--r--front/README.md69
-rw-r--r--front/bun.lock556
-rw-r--r--front/eslint.config.js23
-rw-r--r--front/index.html16
-rw-r--r--front/package.json37
-rw-r--r--front/public/favicon.svg22
l---------front/public/fonts/Inter1
l---------front/public/fonts/Source_Code_Pro1
-rw-r--r--front/public/nostril-icon.pngbin0 -> 764000 bytes
-rw-r--r--front/src/App.tsx43
-rw-r--r--front/src/Router.tsx29
-rw-r--r--front/src/assets/crowspinner.gifbin0 -> 83062 bytes
-rw-r--r--front/src/assets/icons/bell.svg3
-rw-r--r--front/src/assets/icons/comet.svg23
-rw-r--r--front/src/assets/icons/copy.svg5
-rw-r--r--front/src/assets/icons/crow.svg29
-rw-r--r--front/src/assets/icons/emoji.svg5
-rw-r--r--front/src/assets/icons/home.svg3
-rw-r--r--front/src/assets/icons/key.pngbin0 -> 16383 bytes
-rw-r--r--front/src/assets/icons/key.svg5
-rw-r--r--front/src/assets/icons/logo.pngbin0 -> 33892 bytes
-rw-r--r--front/src/assets/icons/logo.svg8
-rw-r--r--front/src/assets/icons/messages.svg8
-rw-r--r--front/src/assets/icons/nostr.svg3
-rw-r--r--front/src/assets/icons/pals.svg3
-rw-r--r--front/src/assets/icons/profile.svg3
-rw-r--r--front/src/assets/icons/quote.svg3
-rw-r--r--front/src/assets/icons/radio.svg3
-rw-r--r--front/src/assets/icons/reply.svg3
-rw-r--r--front/src/assets/icons/rt.svg3
-rw-r--r--front/src/assets/icons/rumors.svg3
-rw-r--r--front/src/assets/icons/settings.svg3
-rw-r--r--front/src/assets/icons/youtube.svg1
-rw-r--r--front/src/assets/reacts/chad.pngbin0 -> 20099 bytes
-rw-r--r--front/src/assets/reacts/cringe.pngbin0 -> 21923 bytes
-rw-r--r--front/src/assets/reacts/cry.pngbin0 -> 18471 bytes
-rw-r--r--front/src/assets/reacts/doom.pngbin0 -> 14749 bytes
-rw-r--r--front/src/assets/reacts/facepalm.pngbin0 -> 188497 bytes
-rw-r--r--front/src/assets/reacts/galaxy.pngbin0 -> 43137 bytes
-rw-r--r--front/src/assets/reacts/gigachad.pngbin0 -> 19087 bytes
-rw-r--r--front/src/assets/reacts/pepechin.pngbin0 -> 22389 bytes
-rw-r--r--front/src/assets/reacts/pepeeyes.pngbin0 -> 18480 bytes
-rw-r--r--front/src/assets/reacts/pepegmi.pngbin0 -> 23024 bytes
-rw-r--r--front/src/assets/reacts/pepesad.pngbin0 -> 18323 bytes
-rw-r--r--front/src/assets/reacts/pika.pngbin0 -> 11475 bytes
-rw-r--r--front/src/assets/reacts/pink.pngbin0 -> 26288 bytes
-rw-r--r--front/src/assets/reacts/soy.pngbin0 -> 12655 bytes
-rw-r--r--front/src/assets/reacts/yeschad.pngbin0 -> 29394 bytes
-rw-r--r--front/src/assets/triangles.svg18
-rw-r--r--front/src/components/Avatar.tsx59
-rw-r--r--front/src/components/Sigil.tsx50
-rw-r--r--front/src/components/feed/Body.tsx174
-rw-r--r--front/src/components/feed/Card.tsx9
-rw-r--r--front/src/components/feed/Composer.tsx52
-rw-r--r--front/src/components/feed/External.tsx41
-rw-r--r--front/src/components/feed/Footer.tsx237
-rw-r--r--front/src/components/feed/Header.tsx33
-rw-r--r--front/src/components/feed/Media.tsx35
-rw-r--r--front/src/components/feed/NostrIcon.tsx22
-rw-r--r--front/src/components/feed/Post.tsx79
-rw-r--r--front/src/components/feed/PostData.tsx160
-rw-r--r--front/src/components/feed/PostList.tsx32
-rw-r--r--front/src/components/feed/Quote.tsx37
-rw-r--r--front/src/components/feed/RP.tsx47
-rw-r--r--front/src/components/feed/Reactions.tsx118
-rw-r--r--front/src/components/feed/StatsModal.tsx106
-rw-r--r--front/src/components/layout/Sidebar.tsx81
-rw-r--r--front/src/components/modals/Modal.tsx72
-rw-r--r--front/src/components/modals/ShipModal.tsx45
-rw-r--r--front/src/components/snippets/Snippets.tsx395
-rw-r--r--front/src/logic/api.ts15
-rw-r--r--front/src/logic/bunts.ts51
-rw-r--r--front/src/logic/constants.ts36
-rw-r--r--front/src/logic/emojis.json3613
-rw-r--r--front/src/logic/nostril.ts36
-rw-r--r--front/src/logic/requests/nostril.ts139
-rw-r--r--front/src/logic/utils.ts459
-rw-r--r--front/src/main.tsx9
-rw-r--r--front/src/pages/Feed.tsx104
-rw-r--r--front/src/pages/Settings.tsx92
-rw-r--r--front/src/pages/User.tsx18
-rw-r--r--front/src/state/state.ts64
-rw-r--r--front/src/styles/ThemeProvider.tsx302
-rw-r--r--front/src/styles/ThemeSwitcher.css249
-rw-r--r--front/src/styles/ThemeSwitcher.tsx131
-rw-r--r--front/src/styles/styles.css438
-rw-r--r--front/src/styles/trill.css612
-rw-r--r--front/src/types/nostr.ts11
-rw-r--r--front/src/types/nostril.ts6
-rw-r--r--front/src/types/trill.ts420
-rw-r--r--front/src/types/twatter.ts336
-rw-r--r--front/src/types/ui.ts49
-rw-r--r--front/src/types/urbit.ts8
-rw-r--r--front/src/vite-env.d.ts1
-rw-r--r--front/tsconfig.app.json30
-rw-r--r--front/tsconfig.json7
-rw-r--r--front/tsconfig.node.json25
-rw-r--r--front/vite.config.ts13
m---------wss-shim0
162 files changed, 30729 insertions, 0 deletions
diff --git a/.claude/settings.local.json b/.claude/settings.local.json
new file mode 100644
index 0000000..0f2b89c
--- /dev/null
+++ b/.claude/settings.local.json
@@ -0,0 +1,10 @@
+{
+ "permissions": {
+ "allow": [
+ "Bash(tsc --noEmit)",
+ "Bash(npx tsc:*)"
+ ],
+ "deny": [],
+ "ask": []
+ }
+} \ No newline at end of file
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..9f95f45
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+oldfront
diff --git a/desk/NOTES.md b/desk/NOTES.md
new file mode 100644
index 0000000..730a478
--- /dev/null
+++ b/desk/NOTES.md
@@ -0,0 +1,39 @@
+# NIPS to implement
+
+
+- NIP-2 for follow lists
+- NIP-25 for reactions (with content), kind 7. kind 17 with content
+
+- NIP-17 for private DMs
+https://github.com/nostr-protocol/nips/blob/master/17.md
+
+- NIP-10 for mentions and replies ("marked e tags")
+
+- NIP-18 for Quotes and RTs
+
+- NIP-57 lightning zaps
+
+- NIP-51 lists?
+- NIP-22 replies?
+# Relay discovery
+
+https://nostr.watch/
+
+# Tag specs
+https://nostr-nips.com/#standardized-tags
+
+- 'e' for event,
+- 'p' for people,
+- 't' for hashtag
+- 'r' for relays
+- 'd' for identifier # wtf?
+- 'm' for mime type
+- 'a' for event coordinates
+- 'g' for geohash
+
+
+# TODO
+
+- Default keypair that of groundwire comet?
+
+lol forget the frontend make it work for Primal
diff --git a/desk/app/nostril.hoon b/desk/app/nostril.hoon
new file mode 100644
index 0000000..51f9965
--- /dev/null
+++ b/desk/app/nostril.hoon
@@ -0,0 +1,204 @@
+/- sur=nostril, nsur=nostr
+/+ lib=nostril, nlib=nostr, sr=sortug,
+ shim, dbug, muta=nostril-mutations, jsonlib=json-nostril,
+ trill=trill-post
+/= web /web/router
+|%
++$ versioned-state $%(state-0:sur)
+--
+=| versioned-state
+=* state -
+%- agent:dbug
+^- agent:gall
+|_ =bowl:gall
++* this .
+ rout ~(. router:web [state bowl])
+ cards ~(. cards:lib bowl)
+ mutat ~(. muta [state bowl])
+++ on-init
+ ^- (quip card:agent:gall agent:gall)
+ :_ this(state default:sur)
+ :~ shim-binding:cards
+ ==
+::
+++ on-save
+ ^- vase
+ !>(state)
+::
+++ on-load
+ |~ old-state=vase
+ ^- (quip card:agent:gall agent:gall)
+ =/ old-state !<(versioned-state old-state)
+ ?- -.old-state
+ %0 `this(state old-state)
+ ==
+::
+++ on-poke
+ |~ [=mark =vase]
+ ^- (quip card:agent:gall agent:gall)
+ ~& >> on-poke-nostril=mark
+ |^
+ ?+ mark `this
+ %noun debug
+ %json on-ui
+ %handle-http-request serve
+ ==
+ :: handling shim events
+ ++ serve
+ =/ order !<(order:web vase)
+ :: ~& request.req.order
+ ?: .=(url.request.req.order '/nostr-shim')
+ =/ msg (handle:shim order)
+ ?~ msg `this
+ ~& "msg processed"
+ =/ relay (~(get by relays) url.u.msg)
+ =/ nevents=(list event:nsur) ?~ relay [event.u.msg ~] [event.u.msg u.relay]
+ =/ nevents2 (scag 100 nevents)
+ =. relays (~(put by relays) url.u.msg nevents2)
+ =/ response (ebail:rout id.order)
+ [response this]
+
+ ::
+ :_ this (rout:rout order)
+
+ ::
+ ++ on-ui
+ =/ jon=json !<(json vase)
+ ~& > on-ui-jon=jon
+ =/ upoke=(unit poke:ui:sur) (ui:de:jsonlib jon)
+ ?~ upoke ~& bad-ui-poke=jon `this
+ ?- -.u.upoke
+ %fols (handle-fols +.u.upoke)
+ %prof (handle-prof +.u.upoke)
+ %keys (handle-keys +.u.upoke)
+ %post (handle-post +.u.upoke)
+ %rela (handle-rela +.u.upoke)
+ ==
+ ++ handle-post |= poke=post-poke:ui:sur
+ ?- -.poke
+ %add
+ =/ sp (build-sp:trill our.bowl our.bowl content.poke)
+ =/ p (build-post:trill now.bowl pubkey.poke sp)
+ =. state (add-to-feed:mutat p)
+ `this
+ %rt `this
+ %del `this
+ ==
+ ++ handle-fols |= poke=fols-poke:ui:sur
+ `this
+ ++ handle-prof |= poke=prof-poke:ui:sur
+ ?- -.poke
+ %add
+ =. profiles (~(put by profiles) +<.poke +>.poke)
+ `this
+ %del
+ =. profiles (~(del by profiles) +.poke)
+ `this
+ ==
+ ++ handle-keys |= poke=keys-poke:ui:sur
+ ?- -.poke
+ %add
+ =/ ks (gen-keys:nlib eny.bowl)
+ =. keys (~(put by keys) -.ks +.ks)
+ ~& new-keys=keys
+ `this
+ %del
+ =. profiles (~(del by profiles) +.poke)
+ `this
+ ==
+ ++ handle-rela |= poke=relay-poke:ui:sur
+ ?- -.poke
+ %send
+ =/ upoast (get-poast:mutat host.poke id.poke)
+ ?~ upoast `this
+ :_ this :_ ~
+ =/ keylist ~(tap by keys)
+ =/ key (snag 0 keylist)
+ =/ event (post-to-event:lib key eny.bowl u.upoast)
+ =/ =req:shim:nsur [%post event relays.poke]
+ (send:shim dap.bowl req)
+ ==
+
+ ::
+ ++ debug
+ =/ noun !<(* vase)
+ ?+ -.noun `this
+ %wtf
+ =/ lol=(unit @) ~
+ =/ l ~| "wtf" (need lol)
+ `this
+ %genkey
+ =/ keys (gen-keys:nlib eny.bowl)
+ ~& keys=keys
+ `this
+ %printkey
+ =/ keylist ~(tap by keys)
+ =/ key (snag 0 keylist)
+ ~& pub=(scow:sr %ux -.key)
+ ~& priv=(scow:sr %ux +.key)
+ `this
+ %feed
+ =/ lol debug-own-feed:mutat
+ `this
+ %rt :: relay test
+ :_ this :_ ~
+ :: khan
+ =/ =req:shim:nsur :- %get
+ %+ turn ~(tap by relays)
+ |= [url=@t *]
+ =/ kinds ~[0 1 6 7]
+ =/ =filter:nsur [~ ~ kinds ~ ~ ~ `5]
+ [url ~[filter]]
+ (send:shim dap.bowl req)
+ ::
+ %rt2
+ =/ rls ~(tap by relays)
+ =/ lol
+ |- ?~ rls ~
+ =/ rl i.rls
+ ~& > relay=[-.rl (lent +.rl)]
+ $(rls t.rls)
+ `this
+ ==
+ ::
+ --
+::
+++ on-watch
+|= =(pole knot)
+ ?> .=(our.bowl src.bowl)
+ ?+ pole !!
+ [%ui ~]
+ :_ this
+ =/ jon (state:en:jsonlib state)
+ [%give %fact ~ [%json !>(jon)]]^~
+ ==
+::
+++ on-leave
+ |~ =(pole knot)
+ ^- (quip card:agent:gall agent:gall)
+ `this
+::
+++ on-peek
+ |~ =(pole knot)
+ ^- (unit (unit cage))
+ ~& > on-peek=pole
+ ?+ pole ~
+ [%j %feed rest=*] ~
+ [%j %post rest=*] ~
+ ==
+::
+++ on-agent
+ |~ [wire sign:agent:gall]
+ ^- (quip card:agent:gall agent:gall)
+ `this
+::
+++ on-arvo
+ |~ [wire =sign-arvo]
+ ^- (quip card:agent:gall agent:gall)
+ `this
+::
+++ on-fail
+ |~ [term tang]
+ ^- (quip card:agent:gall agent:gall)
+ `this
+--
diff --git a/desk/desk.bill b/desk/desk.bill
new file mode 100644
index 0000000..9611612
--- /dev/null
+++ b/desk/desk.bill
@@ -0,0 +1,2 @@
+:~ %nostril
+==
diff --git a/desk/desk.docket-0 b/desk/desk.docket-0
new file mode 100644
index 0000000..1eee1d5
--- /dev/null
+++ b/desk/desk.docket-0
@@ -0,0 +1,11 @@
+:~
+ title+'Nostrill'
+ info+'Pater Nostr'
+ color+0xff.d400
+ version+[0 1 0]
+ website+'https://sortug.com'
+ license+'© 2025 ~sortug. All rights reserved.'
+ image+'https://s3.sortug.com/img/nostril-icon.png'
+ base+'nostril'
+ glob-http+['https://s3.sortug.com/globs/glob-0v1.862v7.o85ao.krj6r.v1dgc.ek27l.glob' 0v1.862v7.o85ao.krj6r.v1dgc.ek27l]
+==
diff --git a/desk/desk.ship b/desk/desk.ship
new file mode 100644
index 0000000..56a71f3
--- /dev/null
+++ b/desk/desk.ship
@@ -0,0 +1 @@
+~polwex
diff --git a/desk/lib/dbug.hoon b/desk/lib/dbug.hoon
new file mode 100644
index 0000000..ce98619
--- /dev/null
+++ b/desk/lib/dbug.hoon
@@ -0,0 +1,155 @@
+:: dbug: agent wrapper for generic debugging tools
+::
+:: usage: %-(agent:dbug your-agent)
+::
+|%
++$ poke
+ $% [%bowl ~]
+ [%state grab=cord]
+ [%incoming =about]
+ [%outgoing =about]
+ ==
+::
++$ about
+ $@ ~
+ $% [%ship =ship]
+ [%path =path]
+ [%wire =wire]
+ [%term =term]
+ ==
+::
+++ agent
+ |= =agent:gall
+ ^- agent:gall
+ !.
+ |_ =bowl:gall
+ +* this .
+ ag ~(. agent bowl)
+ ::
+ ++ on-poke
+ |= [=mark =vase]
+ ^- (quip card:agent:gall agent:gall)
+ ?. ?=(%dbug mark)
+ =^ cards agent (on-poke:ag mark vase)
+ [cards this]
+ =/ dbug
+ !<(poke vase)
+ =; =tang
+ ((%*(. slog pri 1) tang) [~ this])
+ ?- -.dbug
+ %bowl [(sell !>(bowl))]~
+ ::
+ %state
+ =? grab.dbug =('' grab.dbug) '-'
+ =; product=^vase
+ [(sell product)]~
+ =/ state=^vase
+ :: if the underlying app has implemented a /dbug/state scry endpoint,
+ :: use that vase in place of +on-save's.
+ ::
+ =/ result=(each ^vase tang)
+ (mule |.(q:(need (need (on-peek:ag /x/dbug/state)))))
+ ?:(?=(%& -.result) p.result on-save:ag)
+ %+ slap
+ (slop state !>([bowl=bowl ..zuse]))
+ (ream grab.dbug)
+ ::
+ %incoming
+ =; =tang
+ ?^ tang tang
+ [%leaf "no matching subscriptions"]~
+ %+ murn
+ %+ sort ~(tap by sup.bowl)
+ |= [[* a=[=ship =path]] [* b=[=ship =path]]]
+ (aor [path ship]:a [path ship]:b)
+ |= [=duct [=ship =path]]
+ ^- (unit tank)
+ =; relevant=?
+ ?. relevant ~
+ `>[path=path from=ship duct=duct]<
+ ?: ?=(~ about.dbug) &
+ ?- -.about.dbug
+ %ship =(ship ship.about.dbug)
+ %path ?=(^ (find path.about.dbug path))
+ %wire %+ lien duct
+ |=(=wire ?=(^ (find wire.about.dbug wire)))
+ %term !!
+ ==
+ ::
+ %outgoing
+ =; =tang
+ ?^ tang tang
+ [%leaf "no matching subscriptions"]~
+ %+ murn
+ %+ sort ~(tap by wex.bowl)
+ |= [[[a=wire *] *] [[b=wire *] *]]
+ (aor a b)
+ |= [[=wire =ship =term] [acked=? =path]]
+ ^- (unit tank)
+ =; relevant=?
+ ?. relevant ~
+ `>[wire=wire agnt=[ship term] path=path ackd=acked]<
+ ?: ?=(~ about.dbug) &
+ ?- -.about.dbug
+ %ship =(ship ship.about.dbug)
+ %path ?=(^ (find path.about.dbug path))
+ %wire ?=(^ (find wire.about.dbug wire))
+ %term =(term term.about.dbug)
+ ==
+ ==
+ ::
+ ++ on-peek
+ |= =path
+ ^- (unit (unit cage))
+ ?. ?=([@ %dbug *] path)
+ (on-peek:ag path)
+ ?+ path [~ ~]
+ [%u %dbug ~] ``noun+!>(&)
+ [%x %dbug %state ~] ``noun+!>(on-save:ag)
+ [%x %dbug %subscriptions ~] ``noun+!>([wex sup]:bowl)
+ ==
+ ::
+ ++ on-init
+ ^- (quip card:agent:gall agent:gall)
+ =^ cards agent on-init:ag
+ [cards this]
+ ::
+ ++ on-save on-save:ag
+ ::
+ ++ on-load
+ |= old-state=vase
+ ^- (quip card:agent:gall agent:gall)
+ =^ cards agent (on-load:ag old-state)
+ [cards this]
+ ::
+ ++ on-watch
+ |= =path
+ ^- (quip card:agent:gall agent:gall)
+ =^ cards agent (on-watch:ag path)
+ [cards this]
+ ::
+ ++ on-leave
+ |= =path
+ ^- (quip card:agent:gall agent:gall)
+ =^ cards agent (on-leave:ag path)
+ [cards this]
+ ::
+ ++ on-agent
+ |= [=wire =sign:agent:gall]
+ ^- (quip card:agent:gall agent:gall)
+ =^ cards agent (on-agent:ag wire sign)
+ [cards this]
+ ::
+ ++ on-arvo
+ |= [=wire =sign-arvo]
+ ^- (quip card:agent:gall agent:gall)
+ =^ cards agent (on-arvo:ag wire sign-arvo)
+ [cards this]
+ ::
+ ++ on-fail
+ |= [=term =tang]
+ ^- (quip card:agent:gall agent:gall)
+ =^ cards agent (on-fail:ag term tang)
+ [cards this]
+ --
+--
diff --git a/desk/lib/docket.hoon b/desk/lib/docket.hoon
new file mode 100644
index 0000000..ef39b7f
--- /dev/null
+++ b/desk/lib/docket.hoon
@@ -0,0 +1,223 @@
+/- *docket
+|%
+::
+++ mime
+ |%
+ +$ draft
+ $: title=(unit @t)
+ info=(unit @t)
+ color=(unit @ux)
+ glob-http=(unit [=url hash=@uvH])
+ glob-ames=(unit [=ship hash=@uvH])
+ base=(unit term)
+ site=(unit path)
+ image=(unit url)
+ version=(unit version)
+ website=(unit url)
+ license=(unit cord)
+ ==
+ ::
+ ++ finalize
+ |= =draft
+ ^- (unit docket)
+ ?~ title.draft ~
+ ?~ info.draft ~
+ ?~ color.draft ~
+ ?~ version.draft ~
+ ?~ website.draft ~
+ ?~ license.draft ~
+ =/ href=(unit href)
+ ?^ site.draft `[%site u.site.draft]
+ ?~ base.draft ~
+ ?^ glob-http.draft
+ `[%glob u.base hash.u.glob-http %http url.u.glob-http]:draft
+ ?~ glob-ames.draft
+ ~
+ `[%glob u.base hash.u.glob-ames %ames ship.u.glob-ames]:draft
+ ?~ href ~
+ =, draft
+ :- ~
+ :* %1
+ u.title
+ u.info
+ u.color
+ u.href
+ image
+ u.version
+ u.website
+ u.license
+ ==
+ ::
+ ++ from-clauses
+ =| =draft
+ |= cls=(list clause)
+ ^- (unit docket)
+ =* loop $
+ ?~ cls (finalize draft)
+ =* clause i.cls
+ =. draft
+ ?- -.clause
+ %title draft(title `title.clause)
+ %info draft(info `info.clause)
+ %color draft(color `color.clause)
+ %glob-http draft(glob-http `[url hash]:clause)
+ %glob-ames draft(glob-ames `[ship hash]:clause)
+ %base draft(base `base.clause)
+ %site draft(site `path.clause)
+ %image draft(image `url.clause)
+ %version draft(version `version.clause)
+ %website draft(website `website.clause)
+ %license draft(license `license.clause)
+ ==
+ loop(cls t.cls)
+ ::
+ ++ to-clauses
+ |= d=docket
+ ^- (list clause)
+ %- zing
+ :~ :~ title+title.d
+ info+info.d
+ color+color.d
+ version+version.d
+ website+website.d
+ license+license.d
+ ==
+ ?~ image.d ~ ~[image+u.image.d]
+ ?: ?=(%site -.href.d) ~[site+path.href.d]
+ =/ ref=glob-reference glob-reference.href.d
+ :~ base+base.href.d
+ ?- -.location.ref
+ %http [%glob-http url.location.ref hash.ref]
+ %ames [%glob-ames ship.location.ref hash.ref]
+ == == ==
+ ::
+ ++ spit-clause
+ |= =clause
+ ^- tape
+ %+ weld " {(trip -.clause)}+"
+ ?+ -.clause "'{(trip +.clause)}'"
+ %color (scow %ux color.clause)
+ %site (spud path.clause)
+ ::
+ %glob-http
+ "['{(trip url.clause)}' {(scow %uv hash.clause)}]"
+ ::
+ %glob-ames
+ "[{(scow %p ship.clause)} {(scow %uv hash.clause)}]"
+ ::
+ %version
+ =, version.clause
+ "[{(scow %ud major)} {(scow %ud minor)} {(scow %ud patch)}]"
+ ==
+ ::
+ ++ spit-docket
+ |= dock=docket
+ ^- tape
+ ;: welp
+ ":~\0a"
+ `tape`(zing (join "\0a" (turn (to-clauses dock) spit-clause)))
+ "\0a=="
+ ==
+ --
+::
+++ enjs
+ =, enjs:format
+ |%
+ ::
+ ++ charge-update
+ |= u=^charge-update
+ ^- json
+ %+ frond -.u
+ ^- json
+ ?- -.u
+ %del-charge s+desk.u
+ ::
+ %initial
+ %- pairs
+ %+ turn ~(tap by initial.u)
+ |=([=desk c=^charge] [desk (charge c)])
+ ::
+ %add-charge
+ %- pairs
+ :~ desk+s+desk.u
+ charge+(charge charge.u)
+ ==
+ ==
+ ::
+ ++ num
+ |= a=@u
+ ^- ^tape
+ =/ p=json (numb a)
+ ?> ?=(%n -.p)
+ (trip p.p)
+ ::
+ ++ version
+ |= v=^version
+ ^- json
+ :- %s
+ %- crip
+ "{(num major.v)}.{(num minor.v)}.{(num patch.v)}"
+ ::
+ ++ merge
+ |= [a=json b=json]
+ ^- json
+ ?> &(?=(%o -.a) ?=(%o -.b))
+ [%o (~(uni by p.a) p.b)]
+ ::
+ ++ href
+ |= h=^href
+ %+ frond -.h
+ ?- -.h
+ %site s+(spat path.h)
+ %glob
+ %- pairs
+ :~ base+s+base.h
+ glob-reference+(glob-reference glob-reference.h)
+ ==
+ ==
+ ::
+ ++ glob-reference
+ |= ref=^glob-reference
+ %- pairs
+ :~ hash+s+(scot %uv hash.ref)
+ location+(glob-location location.ref)
+ ==
+ ::
+ ++ glob-location
+ |= loc=^glob-location
+ ^- json
+ %+ frond -.loc
+ ?- -.loc
+ %http s+url.loc
+ %ames s+(scot %p ship.loc)
+ ==
+ ::
+ ++ charge
+ |= c=^charge
+ %+ merge (docket docket.c)
+ %- pairs
+ :~ chad+(chad chad.c)
+ ==
+ ::
+ ++ docket
+ |= d=^docket
+ ^- json
+ %- pairs
+ :~ title+s+title.d
+ info+s+info.d
+ color+s+(scot %ux color.d)
+ href+(href href.d)
+ image+?~(image.d ~ s+u.image.d)
+ version+(version version.d)
+ license+s+license.d
+ website+s+website.d
+ ==
+ ::
+ ++ chad
+ |= c=^chad
+ %+ frond -.c
+ ?+ -.c ~
+ %hung s+err.c
+ ==
+ --
+--
diff --git a/desk/lib/json/common.hoon b/desk/lib/json/common.hoon
new file mode 100644
index 0000000..64d4b03
--- /dev/null
+++ b/desk/lib/json/common.hoon
@@ -0,0 +1,29 @@
+/+ sr=sortug
+|%
+++ en
+=, enjs:format
+ |%
+ ++ cord |= s=@t ^- json s+s
+ ++ hex |= h=@ux ^- json
+ [%s (crip (scow:sr %ux h))]
+ ++ b64 |= h=@uv ^- json
+ [%s (crip (scow:sr %uv h))]
+ ++ ud |= n=@ ^- json
+ [%s (crip (scow:sr %ud n))]
+ ++ patp |= p=@p ^- json
+ [%s (scot %p p)]
+ --
+++ de
+=, dejs-soft:format
+ |%
+ ++ hex |= jon=json ^- (unit @ux)
+ ?. ?=(%s -.jon) ~
+ =/ atom=(unit @) (slaw:sr %ux p.jon)
+ ?~ atom ~
+ atom
+ ++ se |= aur=@tas |= jon=json
+ ?. ?=(%s -.jon) ~
+ (slaw aur p.jon)
+ --
+
+--
diff --git a/desk/lib/json/nostr.hoon b/desk/lib/json/nostr.hoon
new file mode 100644
index 0000000..aa5952a
--- /dev/null
+++ b/desk/lib/json/nostr.hoon
@@ -0,0 +1,116 @@
+/- sur=nostr
+/+ common=json-common, sr=sortug
+|%
+++ en
+=, enjs:format
+ |%
+ :: shim comms
+ ++ req |= =req:shim:sur ^- json
+ %+ frond -.req
+ ?- -.req
+ %get (get +.req)
+ %post (post +.req)
+ ==
+ ++ get |= rs=get:shim:sur
+ :- %a %+ turn rs |= [r=@t fs=(list filter:sur)]
+ %: pairs
+ relay+s+r
+ filters+a+(turn fs filter)
+ ~
+ ==
+ ::
+ ++ post |= p=post:shim:sur
+ %: pairs
+ event+(event event.p)
+ relays+a+(turn relays.p cord:en:common)
+ ~
+ ==
+ ::
+ ++ raw-event |= raw-event:sur
+ :: WTF nostr doesn't want the prefix on the pubkey
+ =/ pubkeyt (scow:sr %ux pubkey)
+ ?~ pubkeyt !!
+ =/ pubkeyj [%s (crip t.pubkeyt)]
+ :- %a :~
+ [%n '0']
+ pubkeyj
+ (numb created-at)
+ (numb kind)
+ a+(turn tags tag)
+ s+content
+ ==
+ ++ event
+ |= e=event:sur ^- json
+ =/ pubkeyt (scow:sr %ux pubkey.e)
+ ?~ pubkeyt !!
+ =/ pubkeyj [%s (crip t.pubkeyt)]
+ %: pairs
+ id+(hex:en:common id.e)
+ :: pubkey+(hex:en:common pubkey.e)
+ pubkey+pubkeyj
+ sig+(hex:en:common sig.e)
+ ['created_at' (numb created-at.e)]
+ kind+(numb kind.e)
+ content+s+content.e
+ tags+a+(turn tags.e tag)
+ ~
+ ==
+ ++ tag
+ |= t=tag:sur ^- json [%a (turn t cord:en:common)]
+ :: :- s+key.t
+ :: :- s+value.t
+ :: (turn rest.t |=(tt=@t s+tt))
+ ::
+ ++ filter
+ |= f=filter:sur ^- json
+ =| l=(list [key=@t jon=json])
+ =. l ?~ ids.f l :_ l ['ids' [%a (turn ids.f hex:en:common)]]
+ =. l ?~ authors.f l :_ l ['authors' [%a (turn authors.f hex:en:common)]]
+ =. l ?~ kinds.f l :_ l ['kinds' [%a (turn kinds.f numb)]]
+ =. l ?~ since.f l :_ l ['since' (numb u.since.f)]
+ =. l ?~ until.f l :_ l ['until' (numb u.until.f)]
+ =. l ?~ limit.f l :_ l ['limit' (numb u.limit.f)]
+ %- pairs l
+ ++ user-meta
+ |= meta=user-meta:sur
+ =/ other %+ turn ~(tap by other.meta) |= [key=@t val=@t]
+ [key %s val]
+ %: pairs
+ name+s+name.meta
+ picture+s+picture.meta
+ about+s+about.meta
+ other
+ ==
+ --
+++ de
+=, dejs-soft:format
+ |%
+ :: shim
+ ++ msg
+ %- ot :~
+ relay+so
+ event+event
+ ==
+ ++ event
+ %- ot :~
+ id+hex:de:common
+ pubkey+hex:de:common
+ ['created_at' ni]
+ kind+ni
+ tags+(ar (ar so))
+ content+so
+ sig+hex:de:common
+ ==
+ ++ user-meta |= jon=json
+ ^- (unit user-meta:sur)
+ =/ all ((om so) jon)
+ ?~ all ~
+ =/ base=(unit [name=@t about=@t picture=@t]) %. jon %- ot :~
+ name+so
+ about+so
+ picture+so
+ ==
+ ?~ base ~
+ `[name.u.base about.u.base picture.u.base u.all]
+ --
+--
diff --git a/desk/lib/json/nostril.hoon b/desk/lib/json/nostril.hoon
new file mode 100644
index 0000000..16792a9
--- /dev/null
+++ b/desk/lib/json/nostril.hoon
@@ -0,0 +1,113 @@
+/- sur=nostril, nsur=nostr, feed=trill-feed
+/+ sr=sortug, common=json-common, trill=json-trill, nostr=json-nostr
+|%
+++ en
+=, enjs:format
+|%
+ :: UI comms
+ ++ state |= state-0:sur ^- json
+ %: pairs
+ relays+(en-relays relays)
+ keys+a+(turn ~(tap in ~(key by keys)) hex:en:common)
+ profiles+(en-profiles profiles)
+ feed+(feed-with-cursor:en:trill feed ~ ~)
+ following+(enfollowing following)
+ ['followGraph' (engraph follow-graph)]
+ ~
+ ==
+ ++ en-relays
+ |= r=(map @t (list event:nsur)) ^- json
+ %- pairs %+ turn ~(tap by r)
+ |= [url=@t events=(list event:nsur)]
+ :- url :- %a %+ turn events event:en:nostr
+ ++ en-profiles |= m=(map @ux user-meta:nsur)
+ %- pairs
+ %+ turn ~(tap by m) |= [key=@ux p=user-meta:nsur]
+ :- (crip (scow:sr %ux key)) (user-meta:en:nostr p)
+
+ ++ enfollowing
+ |= m=(map @ux feed:feed)
+ ^- json
+ %- pairs %+ turn ~(tap by m) |= [key=@ux f=feed:feed]
+ :- (crip (scow:sr %ux key)) (feed:en:trill f)
+
+ ++ engraph
+ |= m=(map @ux (set follow:sur))
+ ^- json
+ %- pairs %+ turn ~(tap by m) |= [key=@ux s=(set follow:sur)]
+ :- (crip (scow:sr %ux key))
+ :- %a %+ turn ~(tap in s) |= f=follow:sur
+ %- pairs
+ :~ pubkey+(hex:en:common pubkey.f)
+ name+s+name.f
+ :- %relay ?~ relay.f ~ s+u.relay.f
+ ==
+
+
+ --
+++ de
+=, dejs-soft:format
+|%
+ :: ui
+++ ui
+ %- of :~
+ fols+ui-fols
+ prof+ui-prof
+ keys+ui-keys
+ post+ui-post
+ rela+ui-relay
+ ==
+++ ui-fols
+ %- of :~
+ add+hex:de:common
+ del+hex:de:common
+ ==
+++ ui-prof
+ %- of :~
+ add+add-prof
+ del+hex:de:common
+ ==
+++ add-prof %- ot :~
+ pubkey+hex:de:common
+ meta+user-meta:de:nostr
+==
+++ ui-keys
+ %- of :~
+ add+ul
+ del+hex:de:common
+ ==
+++ ui-post
+ %- of :~
+ add+de-post
+ rt+de-rt
+ del+hex:de:common
+ ==
+++ de-post
+ %- ot :~
+ pubkey+hex:de:common
+ content+so
+ ==
+++ de-rt
+ %- ot :~
+ id+hex:de:common
+ pubkey+hex:de:common
+ relay+so
+ ==
+++ ui-relay
+ %- of :~
+ send+de-relay
+ ==
+++ de-relay %- ot :~
+ host+(se:de:common %p)
+ id+de-atom-id
+ relays+(ar so)
+ ==
+++ de-atom-id
+ |= jon=json
+ ?. ?=([%s @t] jon) ~
+ (rush p.jon dem)
+
+ --
+
+--
+
diff --git a/desk/lib/json/trill.hoon b/desk/lib/json/trill.hoon
new file mode 100644
index 0000000..efa4ffc
--- /dev/null
+++ b/desk/lib/json/trill.hoon
@@ -0,0 +1,191 @@
+/- feed=trill-feed, post=trill-post
+/+ common=json-common, sr=sortug
+|%
+++ en
+=, enjs:format
+ |%
+ ++ feed-with-cursor
+ |= [f=feed:^feed start=(unit @da) end=(unit @da)] ^- json
+ %: pairs
+ feed+(feed f)
+ start+(cursor start)
+ end+(cursor end)
+ ~
+ ==
+ ++ cursor |= c=(unit @da)
+ ?~ c ~ (time u.c)
+ ++ feed
+ |= f=feed:^feed ^- json
+ %- pairs
+ %+ turn (tap:orm:^feed f)
+ |= [post-id=@da p=post:post]
+ ^- [@ta json]
+ :- (crip (scow:sr %ud `@ud`post-id))
+ (poast p)
+
+ ++ poast
+ |= p=post:post ^- json
+ %- pairs
+ :~ id+(ud:en:common id.p)
+ host+(patp:en:common host.p)
+ author+(patp:en:common author.p)
+ thread+(ud:en:common thread.p)
+ parent+?~(parent.p ~ (ud:en:common u.parent.p))
+ contents+(content contents.p)
+ hash+(b64:en:common hash.p)
+ engagement+(engagement engagement.p)
+ children+a+(turn ~(tap in children.p) ud:en:common)
+ time+(time id.p)
+ ==
+
+ ++ content
+ |= cm=content-map:post ^- json
+ =/ last (pry:corm:post cm)
+ ?~ last ~
+ =/ blocks=content-list:post +.u.last
+ :- %a %+ turn blocks en-block
+ ++ en-block
+ |= b=block:post ^- json
+ %+ frond -.b
+ ?- -.b
+ %paragraph a+(turn p.b inline)
+ %blockquote a+(turn p.b inline)
+ %table a+(turn rows.b table-row)
+ %heading (heading +.b)
+ %list (ilist +.b)
+ %media (media media.b)
+ %codeblock (codespan +.b)
+ %eval s+hoon.b
+ %ref (en-ref +.b)
+ %json (external +.b)
+ %poll ~
+ ==
+ ++ table-row
+ |= l=(list content-list:post)
+ :- %a %+ turn l
+ |= b=content-list:post
+ :- %a %+ turn b en-block
+ ++ heading
+ |= [p=cord q=@]
+ %- pairs
+ :~ text+s+p
+ num+(numb q)
+ ==
+ ++ ilist
+ |= [p=(list inline:post) q=?]
+ %- pairs
+ :~ text+a+(turn p inline)
+ ordered+b+q
+ ==
+ ++ media
+ |= =media:post
+ %+ frond -.media
+ ?- -.media
+ %images a+(turn p.media string)
+ %video s+p.media
+ %audio s+p.media
+ ==
+ ++ string
+ |= c=cord s+c
+ ++ en-ref :: TODO should the backend fetch this shit
+ |= [type=term s=@p p=^path]
+ %- pairs
+ :~ type+s+type
+ ship+(patp:en:common s)
+ path+(path p)
+ ==
+ ++ external
+ |= [p=term q=cord]
+ %- pairs
+ :~ origin+s+p
+ content+s+q
+ ==
+ ++ inline
+ |= i=inline:post ^- json
+ %+ frond -.i
+ ?+ -.i s+p.i
+ %ship (patp:en:common p.i)
+ %link (link +.i)
+ %ruby (ruby +.i)
+ %break ~
+ ==
+ ++ ruby
+ |= [p=@t q=@t]
+ %- pairs
+ :~ text+s+p
+ ruby+s+q
+ ==
+ ++ codespan
+ |= [code=cord lang=cord]
+ %- pairs
+ :~ code+s+code
+ lang+s+lang
+ ==
+ ++ link
+ |= [href=cord show=cord]
+ %- pairs
+ :~ href+s+href
+ show+s+show
+ ==
+
+ ++ engagement
+ |= =engagement:post ^- json
+ %- pairs
+ :~ reacts+(reacts reacts.engagement)
+ quoted+a+(turn ~(tap in quoted.engagement) signed-pid)
+ shared+a+(turn ~(tap in shared.engagement) signed-pid)
+ ==
+ ++ reacts
+ |= rs=(map @p [react:post signature:post])
+ ^- json
+ %- pairs
+ %+ turn ~(val by rs)
+ |= [r=react:post s=signature:post]
+ ^- [@ta json]
+ :- (scot %p q.s)
+ s+r
+ ++ signed-pid
+ |= =signed-pid:post
+ ^- json
+ %- pairs
+ :~ ship+(patp:en:common q.signature.signed-pid)
+ pid+(pid pid.signed-pid)
+ ==
+ ++ time-pid
+ |= [t=@da s=@p =id:post]
+ %- pairs
+ :~ id+(ud:en:common id)
+ ship+(patp:en:common s)
+ time+(time t)
+ ==
+ ++ time-ship
+ |= [t=@da s=@p] ^- json
+ %- pairs
+ :~ ship+(patp:en:common s)
+ time+(time t)
+ ==
+ ++ mention
+ |= [t=@da s=@p p=pid:post] ^- json
+ %- pairs
+ :~ pid+(pid p)
+ ship+(patp:en:common s)
+ time+(time t)
+ ==
+ ++ react
+ |= [t=@da s=@p p=pid:post react=@t] ^- json
+ %- pairs
+ :~ pid+(pid p)
+ ship+(patp:en:common s)
+ react+s+react
+ time+(time t)
+ ==
+ ++ pid
+ |= =pid:post
+ %- pairs
+ :~ ship+(patp:en:common ship.pid)
+ id+(ud:en:common id.pid)
+ ==
+ ::
+ ::
+ --
+--
diff --git a/desk/lib/markdown.hoon b/desk/lib/markdown.hoon
new file mode 100644
index 0000000..67ee3ad
--- /dev/null
+++ b/desk/lib/markdown.hoon
@@ -0,0 +1,1711 @@
+/- m=markdown
+::
+
+=> |%
+ :: Set label for collapsed / shortcut reference links
+ ++ backfill-ref-link
+ |= [a=link:inline:m]
+ ^- link:inline:m
+ =/ t target.a
+ ?+ -.t a :: only reference links
+ %ref
+ ?: =(%full type.t) a :: only collapsed / shortcut links
+ =/ node=element:inline.m (head contents.a)
+ ?+ -.node a :: ...and it's a %text node
+ %text
+ %_ a
+ target %_ t
+ label text.node
+ ==
+ ==
+ ==
+ ==
+ ::
+ ++ whitespace (mask " \09\0d\0a") :: whitespace: space, tab, or newline
+ ::
+ ++ all-link-ref-definitions :: Recursively get link ref definitions
+ =< process-nodes
+ |%
+ ++ process-nodes
+ |= [nodes=markdown:m]
+ ^- (map @t urlt:ln:m)
+ ?~ nodes ~
+ %- %~(uni by (process-node (head nodes)))
+ $(nodes +.nodes)
+ ::
+ ++ process-nodeses
+ |= [nodeses=(list markdown:m)]
+ ^- (map @t urlt:ln:m)
+ ?~ nodeses ~
+ %- %~(uni by (process-nodes (head nodeses)))
+ $(nodeses +.nodeses)
+ ::
+ ++ process-node
+ |= [node=node:markdown:m]
+ ^- (map @t urlt:ln:m)
+ =/ result *(map @t urlt:ln:m)
+ ?- -.node
+ %leaf :: Leaf node: check if it's a link ref def
+ =/ leaf=node:leaf:m +.node
+ ?+ -.leaf result
+ %link-ref-definition (~(put by result) label.leaf urlt.leaf)
+ ==
+ ::
+ %container
+ =/ container=node:container:m +.node
+ ?- -.container
+ %block-quote (process-nodes markdown.container)
+ %ol (process-nodeses contents.container)
+ %ul (process-nodeses contents.container)
+ %tl (process-nodeses (turn contents.container |=([is-checked=? =markdown:m] markdown)))
+ ==
+ ==
+ --
+ --
+|%
+ ::
+ :: Parse to and from Markdown text format
+ ++ md
+ |%
+ ++ de :: de:md Deserialize (parse)
+ |%
+ ++ escaped
+ |= [char=@t]
+ (cold char (jest (crip (snoc "\\" char))))
+ ::
+ ++ newline
+ %+ cold '\0a' :: EOL, with or without carriage return '\0d'
+ ;~(pfix ;~(pose (just '\0d') (easy ~)) (just '\0a'))
+ ++ line-end :: Either EOL or EOF
+ %+ cold '\0a'
+ ;~(pose newline (full (easy ~)))
+ ::
+ ++ ln :: Links and urls
+ |%
+ ++ url
+ =< %+ cook |=(a=url:ln:m a) :: Cast
+ ;~(pose with-triangles without-triangles)
+ |%
+ ++ with-triangles
+ ;~ plug
+ %+ cook crip
+ %+ ifix [gal gar]
+ %- star
+ ;~ pose
+ (escaped '<')
+ (escaped '>')
+ ;~(less gal gar line-end prn) :: Anything except '<', '>' or newline
+ ==
+ (easy %.y) :: "yes triangles"
+ ==
+ ++ without-triangles
+ ;~ plug
+ %+ cook crip
+ ;~ less
+ gal :: Doesn't start with '<'
+ %- plus :: Non-empty
+ ;~ less
+ whitespace :: No whitespace allowed
+ ;~ pose
+ (escaped '(')
+ (escaped ')')
+ ;~(less pal par line-end prn) :: Anything except '(', ')' or newline
+ ==
+ ==
+ ==
+ (easy %.n) :: "no triangles"
+ ==
+ --
+ ::
+ ++ urlt
+ %+ cook |=(a=urlt:ln:m a) :: Cast
+ ;~ plug
+ url
+ %- punt :: Optional title-text
+ ;~ pfix (plus whitespace) :: Separated by some whitespace
+ %+ cook crip ;~ pose :: Enclosed in single quote, double quote, or '(...)'
+ (ifix [soq soq] (star ;~(pose (escaped '\'') ;~(less soq prn))))
+ (ifix [doq doq] (star ;~(pose (escaped '"') ;~(less doq prn))))
+ (ifix [pal par] (star ;~(pose (escaped '(') (escaped ')') ;~(less pal par prn))))
+ ==
+ ==
+ ==
+ ::
+ :: Labels are used in inline link targets and in a block-level element (labeled link references)
+ ++ label
+ %+ cook crip
+ %+ ifix [sel ser] :: Enclosed in '[...]'
+ %+ ifix :- (star whitespace) :: Strip leading and trailing whitespapce
+ (star whitespace)
+ %- plus ;~ pose :: Non-empty
+ (escaped '[')
+ (escaped ']')
+ ;~(less sel ser prn) :: Anything except '[', ']' (must be escaped)
+ ==
+ ::
+ ++ target :: Link target, either reference or direct
+ =< %+ cook |=(a=target:ln:m a)
+ ;~(pose target-direct target-ref)
+ |%
+ ++ target-direct
+ %+ cook |=(a=target:ln:m a)
+ %+ stag %direct
+ %+ ifix [pal par] :: Direct links are enclosed in '(...)'
+ %+ ifix :- (star whitespace) :: Strip leading and trailing whitespace
+ (star whitespace)
+ urlt :: Just the target
+ ++ target-ref
+ %+ cook |=(a=target:ln:m a)
+ %+ stag %ref
+ ;~ pose
+ %+ stag %full label
+ %+ stag %collapsed (cold '' (jest '[]'))
+ %+ stag %shortcut (easy '')
+ ==
+ --
+ --
+ ++ inline :: Inline elements
+ |%
+ ++ contents (cook |=(a=contents:inline:m a) (star element)) :: Element sequence
+ ++ element :: Any element
+ %+ cook |=(a=element:inline:m a)
+ ;~ pose
+ escape
+ entity
+ strong
+ emphasis
+ code
+ link
+ image
+ autolink
+ text
+ softbrk
+ hardbrk
+ ==
+ ::
+ ++ text
+ %+ knee *text:inline:m |. ~+ :: recurse
+ %+ cook |=(a=text:inline:m a)
+ %+ stag %text
+ %+ cook crip
+ %- plus :: At least one character
+ ;~ less :: ...which doesn't match any other inline rule
+ escape
+ entity
+ link
+ image
+ autolink
+ emphasis
+ strong
+ code
+ softbrk
+ hardbrk
+ :: ...etc
+ prn
+ ==
+ ::
+ ++ escape
+ %+ cook |=(a=escape:inline:m a)
+ %+ stag %escape
+ ;~ pose
+ :: \!\"\#\$\%\&\'\(\)\*\+\,\-\.\/\:\;\<\=\>\?\@\[\\\]\^\_\`\{\|\}\~
+ (escaped '[') (escaped ']') (escaped '(') (escaped ')')
+ (escaped '!') (escaped '*') (escaped '*') (escaped '_')
+ (escaped '&') (escaped '\\')
+ :: etc
+ ==
+ ++ entity
+ %+ cook |=(a=entity:inline:m a)
+ %+ stag %entity
+ %+ ifix [pam mic]
+ %+ cook crip
+ ;~ pose
+ ;~(plug hax (stun [1 7] nud)) :: '#' and one to seven digits
+ (plus alf) :: Named entity
+ ==
+ ::
+ ++ softbrk :: Newline
+ %+ cook |=(a=softbrk:inline:m a)
+ %+ stag %soft-line-break
+ (cold ~ newline)
+ ::
+ ++ hardbrk
+ %+ cook |=(a=hardbrk:inline:m a)
+ %+ stag %line-break
+ %+ cold ~
+ ;~ pose
+ ;~(plug (jest ' ') (star ace) newline) :: Two or more spaces before a newline
+ ;~(plug (just '\\') newline) :: An escaped newline
+ ==
+ ++ link
+ %+ knee *link:inline:m |. ~+ :: recurse
+ %+ cook backfill-ref-link
+ %+ stag %link
+ ;~ plug
+ %+ ifix [sel ser] :: Display text is wrapped in '[...]'
+ %- star ;~ pose :: Display text can contain various contents
+ escape
+ entity
+ emphasis
+ strong
+ code
+ image
+ :: Text: =>
+ %+ knee *text:inline:m |. ~+ :: recurse
+ %+ cook |=(a=text:inline:m a)
+ %+ stag %text
+ %+ cook crip
+ %- plus :: At least one character
+ ;~ less :: ...which doesn't match any other inline rule
+ escape
+ entity
+ emphasis
+ strong
+ code
+ ser :: No closing ']'
+ prn
+ ==
+ ==
+ target:ln
+ ==
+ ::
+ ++ image
+ %+ cook |=(a=image:inline:m a)
+ %+ stag %image
+ ;~ plug
+ %+ ifix [(jest '![') (just ']')] :: alt-text is wrapped in '![...]'
+ %+ cook crip
+ %- star ;~ pose
+ (escaped ']')
+ ;~(less ser prn)
+ ==
+ target:ln
+ ==
+ ::
+ ++ autolink
+ %+ cook |=(a=autolink:inline:m a)
+ %+ stag %autolink
+ %+ ifix [gal gar] :: Enclosed in '<...>'
+ %+ cook crip
+ %- star ;~ pose
+ ;~(less ace gar prn) :: Spaces are not allowed; neither are backslash-escapes
+ ==
+ ::
+ ++ emphasis
+ %+ knee *emphasis:inline:m |. ~+ :: recurse
+ %+ cook |=(a=emphasis:inline:m a)
+ %+ stag %emphasis
+ ;~ pose
+ %+ ifix [tar tar]
+ ;~ plug
+ (easy '*')
+ %- plus ;~ pose :: Display text can contain various contents
+ escape
+ entity
+ strong
+ link
+ autolink
+ code
+ image
+ link
+ softbrk
+ hardbrk
+ %+ knee *text:inline:m |. ~+ :: recurse
+ %+ cook |=(a=text:inline:m a)
+ %+ stag %text
+ %+ cook crip
+ %- plus :: At least one character
+ ;~ less :: ...which doesn't match any other inline rule
+ escape
+ entity
+ strong
+ link
+ autolink
+ code
+ image
+ link
+ softbrk
+ hardbrk
+ ::
+ tar :: If a '*', then it's the end of the `emphasis`
+ ::
+ prn
+ ==
+ ==
+ ==
+ %+ ifix [cab cab]
+ ;~ plug
+ (easy '_')
+ %- plus ;~ pose :: Display text can contain various contents
+ escape
+ entity
+ strong
+ link
+ autolink
+ code
+ image
+ link
+ softbrk
+ hardbrk
+ %+ knee *text:inline:m |. ~+ :: recurse
+ %+ cook |=(a=text:inline:m a)
+ %+ stag %text
+ %+ cook crip
+ %- plus :: At least one character
+ ;~ less :: ...which doesn't match any other inline rule
+ escape
+ entity
+ strong
+ link
+ autolink
+ code
+ image
+ link
+ softbrk
+ hardbrk
+ ::
+ cab :: If a '*', then it's the end of the `emphasis`
+ ::
+ prn
+ ==
+ ==
+ ==
+ ==
+ ::
+ ++ strong
+ %+ knee *strong:inline:m |. ~+ :: recurse
+ %+ cook |=(a=strong:inline:m a)
+ %+ stag %strong
+ ;~ pose
+ %+ ifix [(jest '**') (jest '**')]
+ ;~ plug
+ (easy '*')
+ %- plus ;~ pose :: Display text can contain various contents
+ escape
+ emphasis
+ link
+ autolink
+ code
+ image
+ link
+ softbrk
+ hardbrk
+ %+ knee *text:inline:m |. ~+ :: recurse
+ %+ cook |=(a=text:inline:m a)
+ %+ stag %text
+ %+ cook crip
+ %- plus :: At least one character
+ ;~ less :: ...which doesn't match any other inline rule
+ escape
+ emphasis
+ link
+ autolink
+ code
+ image
+ link
+ softbrk
+ hardbrk
+ :: ...etc
+ (jest '**') :: If a '**', then it's the end of the `emphasis`
+ prn
+ ==
+ ==
+ ==
+ %+ ifix [(jest '__') (jest '__')]
+ ;~ plug (easy '_')
+ %- plus ;~ pose :: Display text can contain various contents
+ escape
+ emphasis
+ link
+ autolink
+ code
+ image
+ link
+ softbrk
+ hardbrk
+ %+ knee *text:inline:m |. ~+ :: recurse
+ %+ cook |=(a=text:inline:m a)
+ %+ stag %text
+ %+ cook crip
+ %- plus :: At least one character
+ ;~ less :: ...which doesn't match any other inline rule
+ escape
+ emphasis
+ link
+ autolink
+ code
+ image
+ link
+ softbrk
+ hardbrk
+ ::
+ (jest '__') :: If a '**', then it's the end of the `emphasis`
+ prn
+ ==
+ ==
+ ==
+ ==
+ ::
+ ++ code
+ =< %+ cook |=(a=code:inline:m a)
+ %+ stag %code-span
+ inner-parser
+ |%
+ ++ inner-parser
+ |= =nail
+ =/ vex ((plus tic) nail) :: Read the first backtick string
+ ?~ q.vex vex :: If no vex is found, fail
+ =/ tic-sequence ^- tape p:(need q.vex)
+ %.
+ q:(need q.vex)
+ %+ cook |= [a=tape] :: Attach the backtick length to it
+ [(lent tic-sequence) (crip a)]
+ ;~ sfix
+ %+ cook
+ |= [a=(list tape)]
+ ^- tape
+ (zing a)
+ %- star ;~ pose
+ %+ cook trip ;~(less tic prn) :: Any character other than a backtick
+ %+ sear :: A backtick string that doesn't match the opener
+ |= [a=tape]
+ ^- (unit tape)
+ ?: =((lent a) (lent tic-sequence))
+ ~
+ `a
+ (plus tic)
+ ==
+ (jest (crip tic-sequence)) :: Followed by a closing backtick string
+ ==
+ --
+ --
+ ::
+ ++ leaf
+ |%
+ ++ node
+ %+ cook |=(a=node:leaf:m a)
+ ;~ pose
+ blank-line
+ heading
+ break
+ codeblk-indent
+ codeblk-fenced
+ link-ref-def
+ :: ...etc
+ table
+ paragraph
+ ==
+ ++ blank-line
+ %+ cook |=(a=blank-line:leaf:m a)
+ %+ stag %blank-line
+ (cold ~ newline)
+ ++ heading
+ =< %+ cook |=(a=heading:leaf:m a)
+ %+ stag %heading
+ ;~(pose atx setext)
+ |%
+ ++ atx
+ =/ atx-eol ;~ plug
+ (star ace)
+ (star hax)
+ (star ace)
+ line-end
+ ==
+
+ %+ stag %atx
+ %+ cook :: Parse heading inline content
+ |= [level=@ text=tape]
+ [level (scan text contents:inline)]
+ ;~ pfix
+ (stun [0 3] ace) :: Ignore up to 3 leading spaces
+ ;~ plug
+ (cook |=(a=tape (lent a)) (stun [1 6] hax)) :: Heading level
+ %+ ifix [(plus ace) atx-eol] :: One leading space is required; rest is ignored
+ %- star
+ ;~(less atx-eol prn) :: Trailing haxes/spaces are ignored
+ ==
+ ==
+ ++ setext
+ %+ stag %setext
+ %+ cook
+ |= [text=tape level=@]
+ [level (scan text contents:inline)]
+ ;~ plug :: Wow this is a mess
+ %+ ifix [(stun [0 3] ace) (star ace)] :: Strip up to 3 spaces, and trailing space
+ (star ;~(less ;~(pfix (star ace) newline) prn)) :: Any text...
+ ;~ pfix
+ newline :: ...followed by newline...
+ (stun [0 3] ace) :: ...up to 3 spaces (stripped)...
+ ;~ sfix
+ ;~ pose :: ...and an underline
+ (cold 1 (plus (just '-'))) :: Underlined by '-' means heading lvl 1
+ (cold 2 (plus (just '='))) :: Underlined by '=' means heading lvl 2
+ ==
+ (star ace)
+ ==
+ ==
+ ==
+ --
+ ++ break
+ %+ cook |=(a=break:leaf:m a)
+ %+ stag %break
+ %+ cook
+ |= [first-2=@t trailing=tape]
+ [(head trailing) (add 2 (lent trailing))]
+ %+ ifix :- (stun [0 3] ace) :: Strip indent and trailing space
+ ;~ plug
+ (star (mask " \09"))
+ newline :: No other chars allowed on the line
+ ==
+ ;~ pose
+ ;~(plug (jest '**') (plus tar)) :: At least 3, but can be more
+ ;~(plug (jest '--') (plus hep))
+ ;~(plug (jest '__') (plus cab))
+ ==
+ ::
+ ++ codeblk-indent
+ %+ cook |=(a=codeblk-indent:leaf:m a)
+ %+ stag %indent-codeblock
+ %+ cook |=(a=(list tape) (crip (zing a)))
+ %- plus :: 1 or more lines
+ ;~ pfix
+ (jest ' ') :: 4 leading spaces
+ %+ cook snoc ;~ plug
+ (star ;~(less line-end prn))
+ line-end
+ ==
+ ==
+ ::
+ ++ codeblk-fenced
+ =+ |%
+ :: Returns a 3-tuple:
+ :: - indent size
+ :: - char type
+ :: - fence length
+ ++ code-fence
+ ;~ plug
+ %+ cook |=(a=tape (lent a)) (stun [0 3] ace)
+ %+ cook |=(a=tape [(head a) (lent a)]) :: Get code fence char and length
+ ;~ pose
+ (stun [3 999.999.999] sig)
+ (stun [3 999.999.999] tic)
+ ==
+ ==
+ ::
+ ++ info-string
+ %+ cook crip
+ %+ ifix [(star ace) line-end] :: Strip leading whitespace
+ (star ;~(less line-end tic prn)) :: No backticks in a code fence
+ --
+ |* =nail
+ :: Get the marker and indent size
+ =/ vex (code-fence nail)
+ ?~ q.vex vex :: If no match found, fail
+ =/ [indent=@ char=@t len=@] p:(need q.vex)
+ =/ closing-fence
+ ;~ plug
+ (star ace)
+ (stun [len 999.999.999] (just char)) :: Closing fence must be at least as long as opener
+ (star ace) :: ...and cannot have any following text except space
+ line-end
+ ==
+ :: Read the rest of the list item block
+ %.
+ q:(need q.vex)
+ %+ cook |=(a=codeblk-fenced:leaf:m a)
+ %+ stag %fenced-codeblock
+ ;~ plug
+ %+ cook |=(a=@t a) (easy char)
+ (easy len)
+ %+ cook |=(a=@t a) info-string
+ (easy indent)
+ %+ cook |=(a=(list tape) (crip (zing a)))
+ ;~ sfix
+ %- star :: Any amount of lines
+ ;~ less closing-fence :: ...until the closing code fence
+ ;~ pfix (stun [0 indent] ace) :: Strip indent up to that of the opening fence
+ %+ cook |=(a=tape a)
+ ;~ pose :: Avoid infinite loop at EOF
+ %+ cook trip newline :: A line is either a blank line...
+ %+ cook snoc
+ ;~ plug :: Or a non-blank line
+ (plus ;~(less line-end prn))
+ line-end
+ ==
+ ==
+ ==
+ ==
+ ;~(pose closing-fence (full (easy ~)))
+ ==
+ ==
+ ::
+ ++ link-ref-def
+ %+ cook |=(a=link-ref-def:leaf:m a)
+ %+ stag %link-ref-definition
+ %+ ifix [(stun [0 3] ace) line-end] :: Strip leading space
+ ;~ plug
+ ;~(sfix label:ln col) :: Label (enclosed in "[...]"), followed by col ":"
+ ;~ pfix :: Optional whitespace, including up to 1 newline
+ (star ace)
+ (stun [0 1] newline)
+ (star ace)
+ urlt:ln
+ ==
+ ==
+ ::
+ ++ paragraph
+ %+ cook |=(a=paragraph:leaf:m a)
+ %+ stag %paragraph
+ %+ cook :: Reparse the paragraph text as elements
+ |= [a=(list tape)]
+ (scan (zing a) contents:inline)
+ %- plus :: Read lines until a non-paragraph object is found
+ ;~ less
+ heading
+ break
+ block-quote-line:container :: Block quotes can interrupt paragraphs
+ %+ cook snoc ;~ plug
+ %- plus ;~(less line-end prn) :: Lines must be non-empty
+ line-end
+ ==
+ ==
+ ::
+ ++ table
+ => |%
+ +$ cell-t [len=@ =contents:inline:m]
+ ++ row
+ ;~ pfix bar :: A bar in front...
+ %- star
+ %+ cook :: compute the length and parse inlines
+ |= [pfx=@ stuff=tape sfx=@]
+ [;:(add pfx (lent stuff) sfx) (scan stuff contents:inline)] :: inline elements...
+ ;~ plug
+ (cook lent (star ace))
+ (star ;~(less newline ;~(plug (star ace) bar) prn))
+ (cook lent ;~(sfix (star ace) bar))
+ ==
+ ==
+ ++ delimiter-row
+ ;~ pfix bar :: A bar in front...
+ %- star
+ %+ cook
+ |= [pfx=@ lal=? heps=@ ral=? sfx=@]
+ :- ;:(add pfx ?:(ral 1 0) heps ?:(lal 1 0) sfx)
+ ?:(ral ?:(lal %c %r) ?:(lal %l %n))
+ ;~ plug
+ (cook lent (star ace)) :: Delimiter: leading space...
+ (cook |=(a=tape .?(a)) (stun [0 1] col)) :: maybe a ':'...
+ (cook lent (plus hep)) :: a bunch of '-'...
+ (cook |=(a=tape .?(a)) (stun [0 1] col)) :: maybe another ':'...
+ (cook lent ;~(sfix (star ace) bar)) :: ..and a bar as a terminator
+ ==
+ ==
+ --
+ |* =nail :: Make it a (redundant) gate so I can use `=>` to add a helper core
+ %. nail :: apply the following parser
+ %+ cook
+ |= [hdr=(list cell-t) del=(list [len=@ al=?(%c %r %l %n)]) bdy=(list (list cell-t))]
+ ^- table:leaf:m
+ =/ widths=(list @) (turn del |=([len=@ al=*] len))
+ =/ rows=(list (list cell-t)) (snoc bdy hdr) :: since they're the same data type
+ =/ computed-widths
+ |-
+ ?~ rows widths
+ %= $
+ rows (tail rows)
+ widths =/ row=(list cell-t) (head rows)
+ |-
+ ?~ row ~
+ :- (max (head widths) len:(head row))
+ %= $
+ widths (tail widths)
+ row (tail row)
+ ==
+ ==
+ :* %table
+ computed-widths
+ (turn hdr |=(cell=cell-t contents.cell))
+ (turn del |=([len=@ al=?(%c %r %l %n)] al))
+ (turn bdy |=(row=(list cell-t) (turn row |=(cell=cell-t contents.cell))))
+ ==
+ ;~ plug
+ ;~(sfix row line-end)
+ ;~(sfix delimiter-row line-end)
+ (star ;~(sfix row line-end))
+ ==
+ --
+ ::
+ ++ container
+ =+ |%
+ ::
+ ++ line :: Read a line of plain text
+ %+ cook |=([a=tape b=tape c=tape] ;:(weld a b c))
+ ;~ plug
+ (star ;~(less line-end prn))
+ (cook trip line-end)
+ (star newline) :: Can have blank lines in a list item
+ ==
+ ++ block-quote-marker
+ ;~ plug :: Single char '>'
+ (stun [0 3] ace) :: Indented up to 3 spaces
+ gar
+ (stun [0 1] ace) :: Optionally followed by a space
+ ==
+ ++ block-quote-line
+ %+ cook snoc
+ ;~ plug :: Single line...
+ ;~ pfix block-quote-marker :: ...starting with ">..."
+ (star ;~(less line-end prn)) :: can be empty
+ ==
+ line-end
+ ==
+ ::
+ +$ ul-marker-t [indent=@ char=@t len=@]
+ ++ ul-marker
+ %+ cook :: Compute the length of the whole thing
+ |= [prefix=tape bullet=@t suffix=tape]
+ ^- ul-marker-t
+ :* (lent prefix)
+ bullet
+ ;:(add 1 (lent prefix) (lent suffix))
+ ==
+ ;~ plug
+ (stun [0 3] ace)
+ ;~(pose hep lus tar) :: Bullet char
+ (stun [1 4] ace)
+ ==
+ ::
+ :: Produces a 3-tuple:
+ :: - bullet char (*, +, or -)
+ :: - indent level (number of spaces before the bullet)
+ :: - item contents (markdown)
+ +$ ul-item-t [char=@t indent=@ =markdown:m]
+ ++ ul-item
+ |* =nail
+ :: Get the marker and indent size
+ =/ vex (ul-marker nail)
+ ?~ q.vex vex :: If no match found, fail
+ =/ mrkr=ul-marker-t p:(need q.vex)
+ :: Read the rest of the list item block
+ %.
+ q:(need q.vex)
+ %+ cook
+ |= [a=(list tape)]
+ ^- ul-item-t
+ :* char.mrkr
+ indent.mrkr
+ (scan (zing a) markdown)
+ ==
+ ;~ plug
+ line :: First line
+ %- star ;~ pfix :: Subsequent lines must have the same indent
+ (stun [len.mrkr len.mrkr] ace) :: the indent
+ line :: the line
+ ==
+ ==
+ ::
+ +$ ol-marker-t [indent=@ char=@t number=@ len=@]
+ ++ ol-marker
+ %+ cook :: Compute the length of the whole thing
+ |= [prefix=tape number=@ char=@t suffix=tape]
+ ^- ol-marker-t
+ :* (lent prefix)
+ char
+ number
+ ;:(add 1 (lent (a-co:co number)) (lent prefix) (lent suffix))
+ ==
+ ;~ plug
+ (stun [0 3] ace)
+ dem
+ ;~(pose dot par) :: Bullet char
+ (stun [1 4] ace)
+ ==
+ ::
+ :: Produces a 4-tuple:
+ :: - delimiter char: either dot '.' or par ')'
+ :: - list item number
+ :: - indent level (number of spaces before the number)
+ :: - item contents (markdown)
+ +$ ol-item-t [char=@t number=@ indent=@ =markdown:m]
+ ++ ol-item
+ |* =nail
+ ::^- edge
+ :: Get the marker and indent size
+ =/ vex (ol-marker nail)
+ ?~ q.vex vex :: If no match found, fail
+ =/ mrkr=ol-marker-t p:(need q.vex)
+ :: Read the rest of the list item block
+ %.
+ q:(need q.vex)
+ %+ cook
+ |= [a=(list tape)]
+ ^- ol-item-t
+ :* char.mrkr
+ number.mrkr
+ indent.mrkr
+ (scan (zing a) markdown)
+ ==
+ ;~ plug
+ line :: First line
+ %- star ;~ pfix :: Subsequent lines must have the same indent
+ (stun [len.mrkr len.mrkr] ace) :: the indent
+ line :: the line
+ ==
+ ==
+ ::
+ ++ tl-checkbox
+ ;~ pose
+ %+ cold %.y (jest '[x]')
+ %+ cold %.n (jest '[ ]')
+ ==
+ ::
+ :: Produces a 4-tuple:
+ :: - bullet char (*, +, or -)
+ :: - indent level (number of spaces before the bullet)
+ :: - is-checked
+ :: - item contents (markdown)
+ +$ tl-item-t [char=@t indent=@ is-checked=? =markdown:m]
+ ++ tl-item
+ |* =nail
+ :: Get the marker and indent size
+ =/ vex (;~(plug ul-marker ;~(sfix tl-checkbox ace)) nail)
+ ?~ q.vex vex :: If no match found, fail
+ =/ [mrkr=ul-marker-t is-checked=?] p:(need q.vex)
+ :: Read the rest of the list item block
+ %.
+ q:(need q.vex)
+ %+ cook
+ |= [a=(list tape)]
+ ^- tl-item-t
+ :* char.mrkr
+ indent.mrkr
+ is-checked
+ (scan (zing a) markdown)
+ ==
+ ;~ plug
+ line :: First line
+ %- star ;~ pfix :: Subsequent lines must have the same indent
+ (stun [len.mrkr len.mrkr] ace) :: the indent
+ line :: the line
+ ==
+ ==
+ --
+ |%
+ ++ node
+ %+ cook |=(a=node:container:m a)
+ ;~ pose
+ block-quote
+ tl
+ ul
+ ol
+ ==
+ ::
+ ++ block-quote
+ %+ cook |=(a=block-quote:container:m a)
+ %+ stag %block-quote
+ %+ cook |= [a=(list tape)]
+ (scan (zing a) markdown)
+ ;~ plug
+ block-quote-line
+ %- star :: At least one line
+ ;~ pose
+ block-quote-line
+ %+ cook zing %- plus :: Paragraph continuation (copied from `paragraph` above)
+ ;~ less :: ...basically just text that doesn't matchZ anything else
+ heading:leaf
+ break:leaf
+ :: ol
+ :: ul
+ block-quote-marker :: Can't start with ">"
+ line-end :: Can't be blank
+ %+ cook snoc ;~ plug
+ %- star ;~(less line-end prn)
+ line-end
+ ==
+ ==
+ ==
+ ==
+ ::
+ ++ ul
+ |* =nail
+ :: Start by finding the type of the first bullet (indent level and bullet char)
+ =/ vex (ul-item nail)
+ ?~ q.vex vex :: Fail if it doesn't match a list item
+ =/ first-item=ul-item-t p:(need q.vex)
+ :: Check for more list items
+ %.
+ q:(need q.vex)
+ %+ cook |=(a=ul:container:m a)
+ %+ stag %ul
+ ;~ plug :: Give the first item, first
+ (easy indent.first-item)
+ (easy char.first-item)
+ (easy markdown.first-item)
+ %- star
+ %+ sear :: Reject items that don't have the same bullet char
+ |= [item=ul-item-t]
+ ^- (unit markdown:m)
+ ?. =(char.item char.first-item)
+ ~
+ `markdown.item
+ ul-item
+ ==
+ ::
+ ++ ol
+ |* =nail
+ :: Start by finding the first number, char, and indent level
+ =/ vex (ol-item nail)
+ ?~ q.vex vex :: Fail if it doesn't match a list item
+ =/ first-item=ol-item-t p:(need q.vex)
+ :: Check for more list items
+ %.
+ q:(need q.vex)
+ %+ cook |=(a=ol:container:m a)
+ %+ stag %ol
+ ;~ plug :: Give the first item, first
+ (easy indent.first-item)
+ (easy char.first-item)
+ (easy number.first-item)
+ (easy markdown.first-item)
+ %- star
+ %+ sear :: Reject items that don't have the same delimiter
+ |= [item=ol-item-t]
+ ^- (unit markdown:m)
+ ?. =(char.item char.first-item)
+ ~
+ `markdown.item
+ ol-item
+ ==
+ ::
+ ++ tl
+ |* =nail
+ :: Start by finding the type of the first bullet (indent level and bullet char)
+ =/ vex (tl-item nail)
+ ?~ q.vex vex :: Fail if it doesn't match a list item
+ =/ first-item=tl-item-t p:(need q.vex)
+ :: Check for more list items
+ %.
+ q:(need q.vex)
+ %+ cook |=(a=tl:container:m a)
+ %+ stag %tl
+ ;~ plug :: Give the first item, first
+ (easy indent.first-item)
+ (easy char.first-item)
+ (easy [is-checked.first-item markdown.first-item])
+ %- star
+ %+ sear :: Reject items that don't have the same bullet char
+ |= [item=tl-item-t]
+ ^- (unit [is-checked=? markdown:m])
+ ?. =(char.item char.first-item)
+ ~
+ `[is-checked.item markdown.item]
+ tl-item
+ ==
+ --
+ ::
+ ++ markdown
+ %+ cook |=(a=markdown:m a)
+ %- star ;~ pose
+ (stag %container node:container)
+ (stag %leaf node:leaf)
+ ==
+ --
+ ::
+ :: Enserialize (write out as text)
+ ++ en
+ |%
+ ++ escape-chars
+ |= [text=@t chars=(list @t)]
+ ^- tape
+ %+ rash text
+ %+ cook
+ |=(a=(list tape) `tape`(zing a))
+ %- star ;~ pose
+ (cook |=(a=@t `tape`~['\\' a]) (mask chars))
+ (cook trip prn)
+ ==
+ ::
+ ++ ln
+ |%
+ ++ url
+ =< |= [u=url:ln:m]
+ ^- tape
+ ?: has-triangle-brackets.u
+ (with-triangles text.u)
+ (without-triangles text.u)
+ |%
+ ++ with-triangles
+ |= [text=@t]
+ ;: weld
+ "<" :: Put it inside triangle brackets
+ (escape-chars text "<>") :: Escape triangle brackets in the text
+ ">"
+ ==
+ ++ without-triangles
+ |= [text=@t]
+ (escape-chars text "()") :: Escape all parentheses '(' and ')'
+ --
+ ++ urlt
+ |= [u=urlt:ln:m]
+ ^- tape
+ ?~ title-text.u :: If there's no title text, then it's just an url
+ (url url.u)
+ ;:(weld (url url.u) " \"" (escape-chars (need title-text.u) "\"") "\"")
+ ++ label
+ |= [text=@t]
+ ^- tape
+ ;:(weld "[" (escape-chars text "[]") "]")
+ ++ target
+ |= [t=target:ln:m]
+ ^- tape
+ ?- -.t
+ %direct ;:(weld "(" (urlt urlt.t) ")") :: Wrap in parentheses
+ ::
+ %ref ?- type.t
+ %full (label label.t)
+ %collapsed "[]"
+ %shortcut ""
+ ==
+ ==
+ --
+ ::
+ ++ inline
+ |%
+ ++ contents
+ |= [=contents:inline:m]
+ ^- tape
+ %- zing %+ turn contents element
+ ++ element
+ |= [e=element:inline:m]
+ ?+ -.e !!
+ %text (text e)
+ %link (link e)
+ %escape (escape e)
+ %entity (entity e)
+ %code-span (code e)
+ %strong (strong e)
+ %emphasis (emphasis e)
+ %soft-line-break (softbrk e)
+ %line-break (hardbrk e)
+ %image (image e)
+ %autolink (autolink e)
+ :: ...etc
+ ==
+ ++ text
+ |= [t=text:inline:m]
+ ^- tape
+ (trip text.t) :: So easy!
+ ::
+ ++ entity
+ |= [e=entity:inline:m]
+ ^- tape
+ ;:(weld "&" (trip code.e) ";")
+ ::
+ ++ link
+ |= [l=link:inline:m]
+ ^- tape
+ ;: weld
+ "["
+ (contents contents.l)
+ "]"
+ (target:ln target.l)
+ ==
+ ::
+ ++ image
+ |= [i=image:inline:m]
+ ^- tape
+ ;: weld
+ "!["
+ (escape-chars alt-text.i "]")
+ "]"
+ (target:ln target.i)
+ ==
+ ::
+ ++ autolink
+ |= [a=autolink:inline:m]
+ ^- tape
+ ;: weld
+ "<"
+ (trip text.a)
+ ">"
+ ==
+ ::
+ ++ escape
+ |= [e=escape:inline:m]
+ ^- tape
+ (snoc "\\" char.e) :: Could use `escape-chars` but why bother-- this is shorter
+ ::
+ ++ softbrk
+ |= [s=softbrk:inline:m]
+ ^- tape
+ "\0a"
+ ++ hardbrk
+ |= [h=hardbrk:inline:m]
+ ^- tape
+ "\\\0a"
+ ++ code
+ |= [c=code:inline:m]
+ ^- tape
+ ;:(weld (reap num-backticks.c '`') (trip text.c) (reap num-backticks.c '`'))
+ ::
+ ++ strong
+ |= [s=strong:inline:m]
+ ^- tape
+ ;: weld
+ (reap 2 emphasis-char.s)
+ (contents contents.s)
+ (reap 2 emphasis-char.s)
+ ==
+ ::
+ ++ emphasis
+ |= [e=emphasis:inline:m]
+ ^- tape
+ ;: weld
+ (trip emphasis-char.e)
+ (contents contents.e)
+ (trip emphasis-char.e)
+ ==
+ --
+ ::
+ ++ leaf
+ |%
+ ++ node
+ |= [n=node:leaf:m]
+ ?+ -.n !!
+ %blank-line (blank-line n)
+ %break (break n)
+ %heading (heading n)
+ %indent-codeblock (codeblk-indent n)
+ %fenced-codeblock (codeblk-fenced n)
+ %link-ref-definition (link-ref-def n)
+ %paragraph (paragraph n)
+ %table (table n)
+ :: ...etc
+ ==
+
+ ++ blank-line
+ |= [b=blank-line:leaf:m]
+ ^- tape
+ "\0a"
+ ::
+ ++ break
+ |= [b=break:leaf:m]
+ ^- tape
+ (weld (reap char-count.b char.b) "\0a")
+ ::
+ ++ heading
+ |= [h=heading:leaf:m]
+ ^- tape
+ ?- style.h
+ %atx
+ ;:(weld (reap level.h '#') " " (contents:inline contents.h) "\0a")
+ %setext
+ =/ line (contents:inline contents.h)
+ ;:(weld line "\0a" (reap (lent line) ?:(=(level.h 1) '-' '=')) "\0a")
+ ==
+ ::
+ ++ codeblk-indent
+ |= [c=codeblk-indent:leaf:m]
+ ^- tape
+ %+ rash text.c
+ %+ cook
+ |= [a=(list tape)]
+ ^- tape
+ %- zing %+ turn a |=(t=tape (weld " " t))
+ %- plus %+ cook snoc ;~(plug (star ;~(less (just '\0a') prn)) (just '\0a'))
+ ::
+ ++ codeblk-fenced
+ |= [c=codeblk-fenced:leaf:m]
+ ^- tape
+ ;: weld
+ (reap indent-level.c ' ')
+ (reap char-count.c char.c)
+ (trip info-string.c)
+ "\0a"
+ ^- tape %+ rash text.c
+ %+ cook zing %- star :: Many lines
+ %+ cook |= [a=tape newline=@t] :: Prepend each line with "> "
+ ^- tape
+ ;: weld
+ ?~(a "" (reap indent-level.c ' ')) :: If the line is blank, no indent
+ a
+ "\0a"
+ ==
+ ;~ plug :: Break into lines
+ (star ;~(less (just '\0a') prn))
+ (just '\0a')
+ ==
+ (reap indent-level.c ' ')
+ (reap char-count.c char.c)
+ "\0a"
+ ==
+ ::
+ ++ link-ref-def
+ |= [l=link-ref-def:leaf:m]
+ ^- tape
+ ;: weld
+ "["
+ (trip label.l)
+ "]: "
+ (urlt:ln urlt.l)
+ "\0a"
+ ==
+ ::
+ ++ table
+ => |%
+ ++ cell
+ |= [width=@ c=contents:inline:m]
+ ^- tape
+ =/ contents-txt (contents:inline c)
+ ;: weld
+ " "
+ contents-txt
+ (reap (sub width (add 1 (lent contents-txt))) ' ')
+ "|"
+ ==
+ ++ row
+ |= [widths=(list @) cells=(list contents:inline:m)]
+ ^- tape
+ ;: weld
+ "|"
+ |-
+ ^- tape
+ ?~ widths ~
+ %+ weld
+ (cell (head widths) (head cells))
+ $(widths (tail widths), cells (tail cells))
+ "\0a"
+ ==
+ ++ delimiter-row
+ |= [widths=(list @) align=(list ?(%l %c %r %n))]
+ ^- tape
+ ;: weld
+ "|"
+ |-
+ ^- tape
+ ?~ align ~
+ ;: weld
+ " "
+ ?- (head align)
+ %l (weld ":" (reap ;:(sub (head widths) 3) '-'))
+ %r (weld (reap ;:(sub (head widths) 3) '-') ":")
+ %c ;:(weld ":" (reap ;:(sub (head widths) 4) '-') ":")
+ %n (reap ;:(sub (head widths) 2) '-')
+ ==
+ " |"
+ $(align (tail align), widths (tail widths))
+ ==
+ "\0a"
+ ==
+ --
+ |= [t=table:leaf:m]
+ ^- tape
+ ;: weld
+ (row widths.t head.t)
+ (delimiter-row widths.t align.t)
+ =/ rows rows.t
+ |-
+ ^- tape
+ ?~ rows ~
+ %+ weld (row widths.t (head rows)) $(rows (tail rows))
+ ==
+ ::
+ ++ paragraph
+ |= [p=paragraph:leaf:m]
+ ^- tape
+ (contents:inline contents.p)
+ --
+ ::
+ ++ container
+ => |%
+ ++ line
+ %+ cook snoc
+ ;~ plug
+ (star ;~(less (just '\0a') prn))
+ (just '\0a')
+ ==
+ --
+ |%
+ ++ node
+ |= [n=node:container:m]
+ ?- -.n
+ %block-quote (block-quote n)
+ %ul (ul n)
+ %ol (ol n)
+ %tl (tl n)
+ ==
+ ::
+ ++ block-quote
+ |= [b=block-quote:container:m]
+ ^- tape
+ %+ scan (markdown markdown.b) :: First, render the contents
+ %+ cook zing %- plus :: Many lines
+ %+ cook |= [a=tape newline=@t] :: Prepend each line with "> "
+ ^- tape
+ ;: weld
+ ">"
+ ?~(a "" " ") :: If the line is blank, no trailing space
+ a
+ "\0a"
+ ==
+ ;~ plug :: Break into lines
+ (star ;~(less (just '\0a') prn))
+ (just '\0a')
+ ==
+ ::
+ ++ ul
+ |= [u=ul:container:m]
+ ^- tape
+ %- zing %+ turn contents.u :: Each bullet point...
+ |= [item=markdown:m]
+ ^- tape
+ %+ scan (markdown item) :: First, render bullet point contents
+ %+ cook zing
+ ;~ plug
+ %+ cook |= [a=tape] :: Prepend 1st line with indent + bullet char
+ ;: weld
+ (reap indent-level.u ' ')
+ (trip marker-char.u)
+ " "
+ a
+ ==
+ line :: first line
+ %- star
+ %+ cook |= [a=tape] :: Subsequent lines just get indent
+ ?: ?|(=("" a) =("\0a" a)) a
+ ;: weld
+ (reap indent-level.u ' ')
+ " " :: 2 spaces, to make it even with the 1st line
+ a
+ ==
+ line :: second and thereafter lines
+ ==
+ ++ tl
+ |= [t=tl:container:m]
+ ^- tape
+ %- zing %+ turn contents.t :: Each bullet point...
+ |= [is-checked=? item=markdown:m]
+ ^- tape
+ %+ scan (markdown item) :: First, render bullet point contents
+ %+ cook zing
+ ;~ plug
+ %+ cook |= [a=tape] :: Prepend 1st line with indent, bullet char, checkbox
+ ;: weld
+ (reap indent-level.t ' ')
+ (trip marker-char.t)
+ " ["
+ ?:(is-checked "x" " ")
+ "] "
+ a
+ ==
+ line :: first line
+ %- star
+ %+ cook |= [a=tape] :: Subsequent lines just get indent
+ ?: ?|(=("" a) =("\0a" a)) a
+ ;: weld
+ (reap indent-level.t ' ')
+ " " :: 2 spaces, to make it even with the 1st line
+ a
+ ==
+ line :: second and thereafter lines
+ ==
+ ::
+ ++ ol
+ |= [o=ol:container:m]
+ ^- tape
+ %- zing %+ turn contents.o :: Each item...
+ |= [item=markdown:m]
+ ^- tape
+ %+ scan (markdown item) :: First, render item contents
+ %+ cook zing
+ ;~ plug
+ %+ cook |= [a=tape] :: Prepend 1st line with indent + item number
+ ;: weld
+ (reap indent-level.o ' ')
+ (a-co:co start-num.o)
+ (trip marker-char.o)
+ " "
+ a
+ ==
+ line :: first line
+ %- star
+ %+ cook |= [a=tape] :: Subsequent lines just get indent
+ ?: ?|(=("" a) =("\0a" a)) a
+ ;: weld
+ (reap indent-level.o ' ')
+ (reap (lent (a-co:co start-num.o)) ' ')
+ " " :: 2 spaces, to make it even with the 1st line
+ a
+ ==
+ line :: second and thereafter lines
+ ==
+ --
+ ::
+ ++ markdown
+ |= [a=markdown:m]
+ ^- tape
+ %- zing %+ turn a |= [item=node:markdown:m]
+ ?- -.item
+ %leaf (node:leaf +.item)
+ %container (node:container +.item)
+ ==
+ --
+ --
+ ::
+ :: Enserialize as Sail (manx and marl)
+ ++ sail-en
+ =<
+ |= [document=markdown:m]
+ =/ link-ref-defs (all-link-ref-definitions document)
+ ^- manx
+ ;div
+ ;* (~(markdown sail-en link-ref-defs) document)
+ ==
+ ::
+ |_ [reference-links=(map @t urlt:ln:m)]
+ ++ inline
+ |%
+ ++ contents
+ |= [=contents:inline:m]
+ ^- marl
+ %+ turn contents element
+ ++ element
+ |= [e=element:inline:m]
+ ^- manx
+ ?+ -.e !!
+ %text (text e)
+ %link (link e)
+ %code-span (code e)
+ %escape (escape e)
+ %entity (entity e)
+ %strong (strong e)
+ %emphasis (emphasis e)
+ %soft-line-break (softbrk e)
+ %line-break (hardbrk e)
+ %image (image e)
+ %autolink (autolink e)
+ :: ...etc
+ ==
+ ++ text
+ |= [t=text:inline:m]
+ ^- manx
+ [[%$ [%$ (trip text.t)] ~] ~] :: Magic; look up the structure of a `manx` if you want
+ ++ escape
+ |= [e=escape:inline:m]
+ ^- manx
+ [[%$ [%$ (trip char.e)] ~] ~] :: Magic; look up the structure of a `manx` if you want
+ ++ entity
+ |= [e=entity:inline:m]
+ ^- manx
+ =/ fulltext (crip ;:(weld "&" (trip code.e) ";"))
+ [[%$ [%$ `tape`[fulltext ~]] ~] ~] :: We do a little sneaky
+ ++ softbrk
+ |= [s=softbrk:inline:m]
+ ^- manx
+ (text [%text ' '])
+ ++ hardbrk
+ |= [h=hardbrk:inline:m]
+ ^- manx
+ ;br;
+ ++ code
+ |= [c=code:inline:m]
+ ^- manx
+ ;code: {(trip text.c)}
+ ++ link
+ |= [l=link:inline:m]
+ ^- manx
+ =/ target target.l
+ =/ urlt ?- -.target
+ %direct urlt.target :: Direct link; use it
+ %ref :: Ref link; look it up
+ ~| "reflink not found: {<label.target>}"
+ (~(got by reference-links) label.target)
+ ==
+ ;a(href (trip text.url.urlt), title (trip (fall title-text.urlt '')))
+ ;* (contents contents.l)
+ ==
+ ++ image
+ |= [i=image:inline:m]
+ ^- manx
+ =/ target target.i
+ =/ urlt ?- -.target
+ %direct urlt.target :: Direct link; use it
+ %ref :: Ref link; look it up
+ ~| "reflink not found: {<label.target>}"
+ (~(got by reference-links) label.target)
+ ==
+ ;img(src (trip text.url.urlt), alt (trip alt-text.i));
+ ++ autolink
+ |= [a=autolink:inline:m]
+ ^- manx
+ ;a(href (trip text.a)): {(trip text.a)}
+ ++ emphasis
+ |= [e=emphasis:inline:m]
+ ^- manx
+ ;em
+ ;* (contents contents.e)
+ ==
+ ++ strong
+ |= [s=strong:inline:m]
+ ^- manx
+ ;strong
+ ;* (contents contents.s)
+ ==
+ --
+ ++ leaf
+ |%
+ ++ node
+ |= [n=node:leaf:m]
+ ^- manx
+ ?+ -.n !!
+ %blank-line (blank-line n)
+ %break (break n)
+ %heading (heading n)
+ %indent-codeblock (codeblk-indent n)
+ %fenced-codeblock (codeblk-fenced n)
+ %table (table n)
+ %paragraph (paragraph n)
+ %link-ref-definition (text:inline [%text ' ']) :: Link ref definitions don't render as anything
+ :: ...etc
+ ==
+ ++ heading
+ |= [h=heading:leaf:m]
+ ^- manx
+ :-
+ :_ ~ ?+ level.h !! :: Tag and attributes; attrs are empty (~)
+ %1 %h1
+ %2 %h2
+ %3 %h3
+ %4 %h4
+ %5 %h5
+ %6 %h6
+ ==
+ (contents:inline contents.h)
+ ++ blank-line
+ |= [b=blank-line:leaf:m]
+ ^- manx
+ (text:inline [%text ' '])
+ ++ break
+ |= [b=break:leaf:m]
+ ^- manx
+ ;hr;
+ ++ codeblk-indent
+ |= [c=codeblk-indent:leaf:m]
+ ^- manx
+ ;pre
+ ;code: {(trip text.c)}
+ ==
+ ++ codeblk-fenced
+ |= [c=codeblk-fenced:leaf:m]
+ ^- manx
+ ;pre
+ ;+ ?: =(info-string.c '')
+ ;code: {(trip text.c)}
+ ;code(class (weld "language-" (trip info-string.c))): {(trip text.c)}
+ ==
+ ++ table
+ |= [t=table:leaf:m]
+ ^- manx
+ ;table
+ ;thead
+ ;tr
+ ;* =/ hdr head.t
+ =/ align align.t
+ |-
+ ?~ hdr ~
+ :- ;th(align ?-((head align) %c "center", %r "right", %l "left", %n ""))
+ ;* (contents:inline (head hdr))
+ ==
+ $(hdr (tail hdr), align (tail align))
+
+ ==
+ ==
+ ;tbody
+ ;* %+ turn rows.t
+ |= [r=(list contents:inline:m)]
+ ^- manx
+ ;tr
+ ;* =/ row r
+ =/ align align.t
+ |-
+ ?~ row ~
+ :- ;td(align ?-((head align) %c "center", %r "right", %l "left", %n ""))
+ ;* (contents:inline (head row))
+ ==
+ $(row (tail row), align (tail align))
+ ==
+ ==
+ ==
+ ++ paragraph
+ |= [p=paragraph:leaf:m]
+ ^- manx
+ ;p
+ ;* (contents:inline contents.p)
+ ==
+ --
+ ::
+ ++ container
+ |%
+ ++ node
+ |= [n=node:container:m]
+ ^- manx
+ ?- -.n
+ %block-quote (block-quote n)
+ %ul (ul n)
+ %ol (ol n)
+ %tl (tl n)
+ ==
+ ::
+ ++ block-quote
+ |= [b=block-quote:container:m]
+ ^- manx
+ ;blockquote
+ ;* (~(. markdown reference-links) markdown.b)
+ ==
+ ::
+ ++ ul
+ |= [u=ul:container:m]
+ ^- manx
+ ;ul
+ ;* %+ turn contents.u |= [a=markdown:m]
+ ^- manx
+ ;li
+ ;* (~(. markdown reference-links) a)
+ ==
+ ==
+ ::
+ ++ ol
+ |= [o=ol:container:m]
+ ^- manx
+ ;ol(start (a-co:co start-num.o))
+ ;* %+ turn contents.o |= [a=markdown:m]
+ ^- manx
+ ;li
+ ;* (~(. markdown reference-links) a)
+ ==
+ ==
+ ++ tl
+ |= [t=tl:container:m]
+ ^- manx
+ ;ul.task-list
+ ;* %+ turn contents.t |= [is-checked=? a=markdown:m]
+ ^- manx
+ ;li
+ ;+ ?: is-checked
+ ;input(type "checkbox", checked "true");
+ ;input(type "checkbox");
+ ;* (~(. markdown reference-links) a)
+ ==
+ ==
+ --
+ ::
+ ++ markdown
+ |= [a=markdown:m]
+ ^- marl
+ %+ turn a |= [item=node:markdown:m]
+ ?- -.item
+ %leaf (node:leaf +.item)
+ %container (node:container +.item)
+ ==
+ --
+--
diff --git a/desk/lib/nostr.hoon b/desk/lib/nostr.hoon
new file mode 100644
index 0000000..c05b0eb
--- /dev/null
+++ b/desk/lib/nostr.hoon
@@ -0,0 +1,29 @@
+/- sur=nostr
+/+ js=json-nostr
+|%
+++ gen-keys |= eny=@ ^- keys:sur
+ =, secp256k1:secp:crypto
+ =/ privkey
+ |-
+ =/ k (~(rad og eny) (bex 256))
+ ?. (lth k n.t) $ k
+
+ =/ pubkey (priv-to-pub privkey)
+ =/ pub (compress-point pubkey)
+ :: =/ pub (serialize-point pubkey)
+ [pub=pub priv=privkey]
+::
+++ hash-event |= raw=raw-event:sur ^- @ux
+ =/ jon (raw-event:en:js raw)
+ =/ jstring (en:json:html jon)
+ (swp 3 (shax jstring))
+
+++ raws
+ |= [eny=@ bits=@]
+ ^- [@ @]
+ [- +>-]:(~(raws og eny) bits)
+
+++ sign-event |= [priv=@ux hash=@ux eny=@]
+ =^ sed eny (raws eny 256)
+ (sign:schnorr:secp256k1:secp:crypto priv hash sed)
+--
diff --git a/desk/lib/nostril.hoon b/desk/lib/nostril.hoon
new file mode 100644
index 0000000..48d4eb7
--- /dev/null
+++ b/desk/lib/nostril.hoon
@@ -0,0 +1,28 @@
+/- post=trill-post, nsur=nostr
+/+ trill=trill-post, nostr, sr=sortug
+|%
+::
+++ post-to-event |= [=keys:nsur eny=@ p=post:post] ^- event:nsur
+ =/ cl (latest-post-content:trill contents.p)
+ =/ string (crip (content-list-to-md:trill cl))
+ =/ ts (to-unix-secs:jikan:sr id.p)
+ =/ raw=raw-event:nsur [pub.keys ts 1 ~ string]
+ =/ event-id (hash-event:nostr raw)
+ =/ signature (sign-event:nostr priv.keys event-id eny)
+ ~& hash-and-signed=[event-id signature]
+ =/ =event:nsur :*
+ event-id
+ pub.keys
+ created-at.raw
+ kind.raw
+ tags.raw
+ content.raw
+ signature
+ ==
+ event
+++ cards
+|_ =bowl:gall
+ ++ shim-binding ^- card:agent:gall
+ [%pass /binding %arvo %e %connect [~ /nostr-shim] dap.bowl]
+ --
+--
diff --git a/desk/lib/nostril/mutations.hoon b/desk/lib/nostril/mutations.hoon
new file mode 100644
index 0000000..f7de23b
--- /dev/null
+++ b/desk/lib/nostril/mutations.hoon
@@ -0,0 +1,117 @@
+/- sur=nostril, nsur=nostr,
+ post=trill-post, gate=trill-gate, feed=trill-feed
+
+/+ appjs=json-nostril,
+ njs=json-nostr,
+ postlib=nostril-post,
+ sr=sortug
+
+|_ [=state:sur =bowl:gall]
+++ debug-own-feed
+ =/ postlist (tap:orm:feed feed.state)
+ =/ lol
+ |- ?~ postlist ~
+ ~& >> poast=+.i.postlist
+ $(postlist t.postlist)
+ ~
+:: TODO not a mutation but fuck it
+++ get-poast |= [host=@p id=@] ^- (unit post:post)
+ =/ poast ?: .=(host our.bowl)
+ (get:orm:feed feed.state id)
+ ~
+ poast
+
+:: state
+++ add-to-feed |= p=post:post
+ =. feed.state (put:orm:feed feed.state id.p p)
+ state
+:: events
+++ process-events ^- (quip card _state)
+ :: =/ l events.state
+ :: =| cards=(list card:agent:gall)
+ :: |- ?~ l [cards state]
+ :: =/ n (event-parsing i.l)
+ :: $(cards -.n, state +.n, l t.l)
+ :: TODO
+ `state
+
+++ event-parsing
+ |= =event:nsur
+ ^- (quip card _state)
+ |^
+:: https://nostrdata.github.io/kinds/
+ ?: .=(kind.event 0) :: user metadata
+ parse-metadata
+ ?: .=(kind.event 1) :: apparently a poast
+ parse-poast
+ ?: .=(kind.event 3) :: follow list
+ parse-follow
+ :: ?: .=(kind.event 5) :: delete
+ ?: .=(kind.event 6) :: RT
+ parse-follow
+ ?: .=(kind.event 7) :: Reaction
+ parse-follow
+
+ `state
+
+ ++ parse-metadata
+ ^- (quip card _state)
+ =/ jstring content.event
+ =/ ujon (de:json:html jstring)
+ ?~ ujon !!
+ =/ umeta (user-meta:de:njs u.ujon)
+ ?~ umeta `state
+ =. profiles.state (~(put by profiles.state) pubkey.event u.umeta)
+ `state
+
+
+ ++ parse-poast
+ ^- (quip card _state)
+ =/ fid (~(get by following.state) pubkey.event)
+ ?~ fid `state :: don't save post if we don't follow the fucker
+
+ =/ cl (tokenize:postlib content.event)
+
+ =/ ts (from-unix:jikan:sr created-at.event)
+ :: TODO wtf
+ =/ cm=content-map:post (init-content-map:postlib cl ts)
+
+ =/ p=post:post :*
+ id=ts
+ host=`@p`pubkey.event
+ author=`@p`pubkey.event
+ thread=ts
+ parent=~
+ children=~
+ contents=cm
+ read=*lock:gate
+ write=*lock:gate
+ *engagement:post
+ 0v0
+ *signature:post
+ tags=~
+ ==
+ =/ nfid (put:orm:feed u.fid ts p)
+ =. following.state (~(put by following.state) pubkey.event nfid)
+ `state
+
+
+ ++ parse-follow
+ ^- (quip card _state)
+ =/ following (~(get by follow-graph.state) pubkey.event)
+ =/ follow-set ?~ following *(set follow:sur) u.following
+ |- ?~ tags.event `state
+ =/ t=tag:nsur i.tags.event
+ :: ?. .=('p' key.t) $(tags.event t.tags.event)
+ :: =/ pubkeys value.t
+ :: =/ pubkey (slaw:sr %ux pubkeys)
+ :: ?~ pubkey ~& "parsing hex error" $(tags.event t.tags.event)
+ :: =/ relay (snag 0 rest.t)
+ :: =/ rel ?: .=(relay '') ~ (some relay)
+ :: =/ nickname (snag 1 rest.t)
+ :: =/ meta=follow:sur [u.pubkey nickname rel]
+ :: =. follow-set (~(put in follow-set) meta)
+ :: =. follow-graph.state (~(put by follow-graph.state) pubkey.event follow-set)
+ $(tags.event t.tags.event)
+ --
+--
diff --git a/desk/lib/server.hoon b/desk/lib/server.hoon
new file mode 100644
index 0000000..f5cf8f0
--- /dev/null
+++ b/desk/lib/server.hoon
@@ -0,0 +1,159 @@
+=, eyre
+|%
++$ request-line
+ $: [ext=(unit @ta) site=(list @t)]
+ args=(list [key=@t value=@t])
+ ==
+:: +parse-request-line: take a cord and parse out a url
+::
+++ parse-request-line
+ |= url=@t
+ ^- request-line
+ (fall (rush url ;~(plug apat:de-purl:html yque:de-purl:html)) [[~ ~] ~])
+::
+++ manx-to-octs
+ |= man=manx
+ ^- octs
+ (as-octt:mimes:html (en-xml:html man))
+::
+++ json-to-octs
+ |= jon=json
+ ^- octs
+ (as-octs:mimes:html (en:json:html jon))
+::
+++ app
+ |%
+ ::
+ :: +require-authorization:
+ :: redirect to the login page when unauthenticated
+ :: otherwise call handler on inbound request
+ ::
+ ++ require-authorization
+ |= $: =inbound-request:eyre
+ handler=$-(inbound-request:eyre simple-payload:http)
+ ==
+ ^- simple-payload:http
+ ::
+ ?: authenticated.inbound-request
+ ~! this
+ ~! +:*handler
+ (handler inbound-request)
+ ::
+ =- [[307 ['location' -]~] ~]
+ %^ cat 3
+ '/~/login?redirect='
+ url.request.inbound-request
+ ::
+ :: +require-authorization-simple:
+ :: redirect to the login page when unauthenticated
+ :: otherwise pass through simple-paylod
+ ::
+ ++ require-authorization-simple
+ |= [=inbound-request:eyre =simple-payload:http]
+ ^- simple-payload:http
+ ::
+ ?: authenticated.inbound-request
+ ~! this
+ simple-payload
+ ::
+ =- [[307 ['location' -]~] ~]
+ %^ cat 3
+ '/~/login?redirect='
+ url.request.inbound-request
+ ::
+ ++ give-simple-payload
+ |= [eyre-id=@ta =simple-payload:http]
+ ^- (list card:agent:gall)
+ =/ header-cage
+ [%http-response-header !>(response-header.simple-payload)]
+ =/ data-cage
+ [%http-response-data !>(data.simple-payload)]
+ :~ [%give %fact ~[/http-response/[eyre-id]] header-cage]
+ [%give %fact ~[/http-response/[eyre-id]] data-cage]
+ [%give %kick ~[/http-response/[eyre-id]] ~]
+ ==
+ --
+++ gen
+ |%
+ ::
+ ++ max-1-da ['cache-control' 'max-age=86400']
+ ++ max-1-wk ['cache-control' 'max-age=604800']
+ ::
+ ++ html-response
+ =| cache=?
+ |= =octs
+ ^- simple-payload:http
+ :_ `octs
+ [200 [['content-type' 'text/html'] ?:(cache [max-1-wk ~] ~)]]
+ ::
+ ++ css-response
+ =| cache=?
+ |= =octs
+ ^- simple-payload:http
+ :_ `octs
+ [200 [['content-type' 'text/css'] ?:(cache [max-1-wk ~] ~)]]
+ ::
+ ++ js-response
+ =| cache=?
+ |= =octs
+ ^- simple-payload:http
+ :_ `octs
+ [200 [['content-type' 'text/javascript'] ?:(cache [max-1-wk ~] ~)]]
+ ::
+ ++ png-response
+ =| cache=?
+ |= =octs
+ ^- simple-payload:http
+ :_ `octs
+ [200 [['content-type' 'image/png'] ?:(cache [max-1-wk ~] ~)]]
+ ::
+ ++ svg-response
+ =| cache=?
+ |= =octs
+ ^- simple-payload:http
+ :_ `octs
+ [200 [['content-type' 'image/svg+xml'] ?:(cache [max-1-wk ~] ~)]]
+ ::
+ ++ ico-response
+ |= =octs
+ ^- simple-payload:http
+ [[200 [['content-type' 'image/x-icon'] max-1-wk ~]] `octs]
+ ::
+ ++ woff2-response
+ =| cache=?
+ |= =octs
+ ^- simple-payload:http
+ [[200 [['content-type' 'font/woff2'] max-1-wk ~]] `octs]
+ ::
+ ++ json-response
+ =| cache=_|
+ |= =json
+ ^- simple-payload:http
+ :_ `(json-to-octs json)
+ [200 [['content-type' 'application/json'] ?:(cache [max-1-da ~] ~)]]
+ ::
+ ++ manx-response
+ =| cache=_|
+ |= man=manx
+ ^- simple-payload:http
+ :_ `(manx-to-octs man)
+ [200 [['content-type' 'text/html'] ?:(cache [max-1-da ~] ~)]]
+ ::
+ ++ not-found
+ ^- simple-payload:http
+ [[404 ~] ~]
+ ::
+ ++ login-redirect
+ |= =request:http
+ ^- simple-payload:http
+ =- [[307 ['location' -]~] ~]
+ %^ cat 3
+ '/~/login?redirect='
+ url.request
+ ::
+ ++ redirect
+ |= redirect=cord
+ ^- simple-payload:http
+ [[307 ['location' redirect]~] ~]
+ --
+--
diff --git a/desk/lib/shim.hoon b/desk/lib/shim.hoon
new file mode 100644
index 0000000..be95b70
--- /dev/null
+++ b/desk/lib/shim.hoon
@@ -0,0 +1,23 @@
+/- sur=nostr
+/+ js=json-nostr
+/= web /web/router
+|%
+
+++ handle
+ |= [eyre-id=@ta req=inbound-request:eyre]
+ ^- (unit [url=@ event=event:sur])
+ ?~ body.request.req ~
+ =/ jstring q.u.body.request.req
+ =/ ures (de:json:html jstring)
+ ?~ ures ~
+ (msg:de:js u.ures)
+++ send
+ |= [desk=@tas =req:shim:sur] ^- card:agent:gall
+ =/ req-body (req:en:js req)
+ =/ headers :~
+ [key='content-type' value='application/json']
+ ==
+ =/ =request:http [%'POST' url:shim:sur headers `(json-body:web req-body)]
+ =/ pat /shim
+ [%pass (weld /ws pat) %arvo %k %fard desk %fetch %noun !>(request)]
+--
diff --git a/desk/lib/sortug.hoon b/desk/lib/sortug.hoon
new file mode 120000
index 0000000..dad4203
--- /dev/null
+++ b/desk/lib/sortug.hoon
@@ -0,0 +1 @@
+/home/y/code/urbit/sortug/lib/sortug.hoon \ No newline at end of file
diff --git a/desk/lib/strand.hoon b/desk/lib/strand.hoon
new file mode 100644
index 0000000..b0db35b
--- /dev/null
+++ b/desk/lib/strand.hoon
@@ -0,0 +1 @@
+rand
diff --git a/desk/lib/strandio.hoon b/desk/lib/strandio.hoon
new file mode 100644
index 0000000..48f6e0d
--- /dev/null
+++ b/desk/lib/strandio.hoon
@@ -0,0 +1,965 @@
+/- spider
+/+ libstrand=strand
+=, strand=strand:libstrand
+=, strand-fail=strand-fail:libstrand
+|%
+++ send-raw-cards
+ |= cards=(list =card:agent:gall)
+ =/ m (strand ,~)
+ ^- form:m
+ |= strand-input:strand
+ [cards %done ~]
+::
+++ send-raw-card
+ |= =card:agent:gall
+ =/ m (strand ,~)
+ ^- form:m
+ (send-raw-cards card ~)
+::
+++ ignore
+ |= tin=strand-input:strand
+ `[%fail %ignore ~]
+::
+++ get-bowl
+ =/ m (strand ,bowl:strand)
+ ^- form:m
+ |= tin=strand-input:strand
+ `[%done bowl.tin]
+::
+++ get-beak
+ =/ m (strand ,beak)
+ ^- form:m
+ |= tin=strand-input:strand
+ `[%done [our q.byk da+now]:bowl.tin]
+::
+++ get-time
+ =/ m (strand ,@da)
+ ^- form:m
+ |= tin=strand-input:strand
+ `[%done now.bowl.tin]
+::
+++ get-our
+ =/ m (strand ,ship)
+ ^- form:m
+ |= tin=strand-input:strand
+ `[%done our.bowl.tin]
+::
+++ get-entropy
+ =/ m (strand ,@uvJ)
+ ^- form:m
+ |= tin=strand-input:strand
+ `[%done eny.bowl.tin]
+::
+:: Convert skips to %ignore failures.
+::
+:: This tells the main loop to try the next handler.
+::
+++ handle
+ |* a=mold
+ =/ m (strand ,a)
+ |= =form:m
+ ^- form:m
+ |= tin=strand-input:strand
+ =/ res (form tin)
+ =? next.res ?=(%skip -.next.res)
+ [%fail %ignore ~]
+ res
+::
+:: Wait for a poke with a particular mark
+::
+++ take-poke
+ |= =mark
+ =/ m (strand ,vase)
+ ^- form:m
+ |= tin=strand-input:strand
+ ?+ in.tin `[%skip ~]
+ ~
+ `[%wait ~]
+ ::
+ [~ %poke @ *]
+ ?. =(mark p.cage.u.in.tin)
+ `[%skip ~]
+ `[%done q.cage.u.in.tin]
+ ==
+::
+++ take-sign-arvo
+ =/ m (strand ,[wire sign-arvo])
+ ^- form:m
+ |= tin=strand-input:strand
+ ?+ in.tin `[%skip ~]
+ ~
+ `[%wait ~]
+ ::
+ [~ %sign *]
+ `[%done [wire sign-arvo]:u.in.tin]
+ ==
+::
+:: Wait for a subscription update on a wire
+::
+++ take-fact-prefix
+ |= =wire
+ =/ m (strand ,[path cage])
+ ^- form:m
+ |= tin=strand-input:strand
+ ?+ in.tin `[%skip ~]
+ ~ `[%wait ~]
+ [~ %agent * %fact *]
+ ?. =(watch+wire (scag +((lent wire)) wire.u.in.tin))
+ `[%skip ~]
+ `[%done (slag (lent wire) wire.u.in.tin) cage.sign.u.in.tin]
+ ==
+::
+:: Wait for a subscription update on a wire
+::
+++ take-fact
+ |= =wire
+ =/ m (strand ,cage)
+ ^- form:m
+ |= tin=strand-input:strand
+ ?+ in.tin `[%skip ~]
+ ~ `[%wait ~]
+ [~ %agent * %fact *]
+ ?. =(watch+wire wire.u.in.tin)
+ `[%skip ~]
+ `[%done cage.sign.u.in.tin]
+ ==
+::
+:: Wait for a subscription close
+::
+++ take-kick
+ |= =wire
+ =/ m (strand ,~)
+ ^- form:m
+ |= tin=strand-input:strand
+ ?+ in.tin `[%skip ~]
+ ~ `[%wait ~]
+ [~ %agent * %kick *]
+ ?. =(watch+wire wire.u.in.tin)
+ `[%skip ~]
+ `[%done ~]
+ ==
+::
+++ echo
+ =/ m (strand ,~)
+ ^- form:m
+ %- (main-loop ,~)
+ :~ |= ~
+ ^- form:m
+ ;< =vase bind:m ((handle ,vase) (take-poke %echo))
+ =/ message=tape !<(tape vase)
+ %- (slog leaf+"{message}..." ~)
+ ;< ~ bind:m (sleep ~s2)
+ %- (slog leaf+"{message}.." ~)
+ (pure:m ~)
+ ::
+ |= ~
+ ^- form:m
+ ;< =vase bind:m ((handle ,vase) (take-poke %over))
+ %- (slog leaf+"over..." ~)
+ (pure:m ~)
+ ==
+::
+++ take-watch
+ =/ m (strand ,path)
+ |= tin=strand-input:strand
+ ?+ in.tin `[%skip ~]
+ ~ `[%wait ~]
+ [~ %watch *]
+ `[%done path.u.in.tin]
+ ==
+::
+++ take-wake
+ |= until=(unit @da)
+ =/ m (strand ,~)
+ ^- form:m
+ |= tin=strand-input:strand
+ ?+ in.tin `[%skip ~]
+ ~ `[%wait ~]
+ [~ %sign [%wait @ ~] %behn %wake *]
+ ?. |(?=(~ until) =(`u.until (slaw %da i.t.wire.u.in.tin)))
+ `[%skip ~]
+ ?~ error.sign-arvo.u.in.tin
+ `[%done ~]
+ `[%fail %timer-error u.error.sign-arvo.u.in.tin]
+ ==
+::
+++ take-tune
+ |= =wire
+ =/ m (strand ,[spar:ames (unit roar:ames)])
+ ^- form:m
+ |= tin=strand-input:strand
+ ?+ in.tin `[%skip ~]
+ ~ `[%wait ~]
+ ::
+ [~ %sign * %ames %tune ^ *]
+ ?. =(wire wire.u.in.tin)
+ `[%skip ~]
+ `[%done +>.sign-arvo.u.in.tin]
+ ==
+::
+++ take-whey
+ |= =wire
+ =/ m (strand ,[spar:ames fragment-size=@ud num-fragments=@ud])
+ ^- form:m
+ |= tin=strand-input:strand
+ ?+ in.tin `[%skip ~]
+ ~ `[%wait ~]
+ ::
+ [~ %sign * %ames %sage sage=*]
+ ?. =(wire wire.u.in.tin)
+ `[%skip ~]
+ =/ =sage:mess:ames sage.sign-arvo.u.in.tin
+ :^ ~ %done spar=p.sage
+ ?~ q.sage
+ [boq=13 tot=0]
+ =< [boq tot]
+ ;;([%whey boq=@ud tot=@ud] q.sage)
+ ==
+::
+++ take-sage
+ |= =wire
+ =/ m (strand ,sage:mess:ames)
+ ^- form:m
+ |= tin=strand-input:strand
+ ?+ in.tin `[%skip ~]
+ ~ `[%wait ~]
+ ::
+ [~ %sign * %ames %sage sage=*]
+ ?. =(wire wire.u.in.tin)
+ `[%skip ~]
+ `[%done sage.sign-arvo.u.in.tin]
+ ==
+::
+++ take-message
+ => |% +$ out $% [%sage sage:mess:ames]
+ [%tune spar:ames (unit roar:ames)]
+ [%page spar:ames (unit (unit page))]
+ ==
+ --
+ |= =wire
+ =/ m (strand ,out)
+ ^- form:m
+ |= tin=strand-input:strand
+ ?+ in.tin `[%skip ~]
+ ~ `[%wait ~]
+ ::
+ [~ %sign * %ames %sage sage=*]
+ ?. =(wire wire.u.in.tin)
+ `[%skip ~]
+ `[%done %sage sage.sign-arvo.u.in.tin]
+ ::
+ [~ %sign * %ames %tune ^ *]
+ ?. =(wire wire.u.in.tin)
+ `[%skip ~]
+ `[%done %tune +>.sign-arvo.u.in.tin]
+ ::
+ [~ %sign * %ames %near ^ *]
+ ?. =(wire wire.u.in.tin)
+ `[%skip ~]
+ `[%done %page +>.sign-arvo.u.in.tin]
+ ==
+::
+++ take-near
+ |= =wire
+ =/ m (strand ,[spar:ames (unit (unit page))])
+ ^- form:m
+ |= tin=strand-input:strand
+ ?+ in.tin `[%skip ~]
+ ~ `[%wait ~]
+ ::
+ [~ %sign * %ames %near ^ *]
+ ?. =(wire wire.u.in.tin)
+ `[%skip ~]
+ `[%done +>.sign-arvo.u.in.tin]
+ ==
+::
+++ take-poke-ack
+ |= =wire
+ =/ m (strand ,~)
+ ^- form:m
+ |= tin=strand-input:strand
+ ?+ in.tin `[%skip ~]
+ ~ `[%wait ~]
+ [~ %agent * %poke-ack *]
+ ?. =(wire wire.u.in.tin)
+ `[%skip ~]
+ ?~ p.sign.u.in.tin
+ `[%done ~]
+ `[%fail %poke-fail u.p.sign.u.in.tin]
+ ==
+::
+++ take-watch-ack
+ |= =wire
+ =/ m (strand ,~)
+ ^- form:m
+ |= tin=strand-input:strand
+ ?+ in.tin `[%skip ~]
+ ~ `[%wait ~]
+ [~ %agent * %watch-ack *]
+ ?. =(watch+wire wire.u.in.tin)
+ `[%skip ~]
+ ?~ p.sign.u.in.tin
+ `[%done ~]
+ `[%fail %watch-ack-fail u.p.sign.u.in.tin]
+ ==
+::
+++ poke
+ |= [=dock =cage]
+ =/ m (strand ,~)
+ ^- form:m
+ =/ =card:agent:gall [%pass /poke %agent dock %poke cage]
+ ;< ~ bind:m (send-raw-card card)
+ (take-poke-ack /poke)
+::
+++ raw-poke
+ |= [=dock =cage]
+ =/ m (strand ,~)
+ ^- form:m
+ =/ =card:agent:gall [%pass /poke %agent dock %poke cage]
+ ;< ~ bind:m (send-raw-card card)
+ =/ m (strand ,~)
+ ^- form:m
+ |= tin=strand-input:strand
+ ?+ in.tin `[%skip ~]
+ ~
+ `[%wait ~]
+ ::
+ [~ %agent * %poke-ack *]
+ ?. =(/poke wire.u.in.tin)
+ `[%skip ~]
+ `[%done ~]
+ ==
+::
+++ raw-poke-our
+ |= [app=term =cage]
+ =/ m (strand ,~)
+ ^- form:m
+ ;< =bowl:spider bind:m get-bowl
+ (raw-poke [our.bowl app] cage)
+::
+++ poke-our
+ |= [=term =cage]
+ =/ m (strand ,~)
+ ^- form:m
+ ;< our=@p bind:m get-our
+ (poke [our term] cage)
+::
+++ watch
+ |= [=wire =dock =path]
+ =/ m (strand ,~)
+ ^- form:m
+ =/ =card:agent:gall [%pass watch+wire %agent dock %watch path]
+ ;< ~ bind:m (send-raw-card card)
+ (take-watch-ack wire)
+::
+++ watch-one
+ |= [=wire =dock =path]
+ =/ m (strand ,cage)
+ ^- form:m
+ ;< ~ bind:m (watch wire dock path)
+ ;< =cage bind:m (take-fact wire)
+ ;< ~ bind:m (take-kick wire)
+ (pure:m cage)
+::
+++ watch-our
+ |= [=wire =term =path]
+ =/ m (strand ,~)
+ ^- form:m
+ ;< our=@p bind:m get-our
+ (watch wire [our term] path)
+::
+++ scry
+ |* [=mold =path]
+ =/ m (strand ,mold)
+ ^- form:m
+ ?> ?=(^ path)
+ ?> ?=(^ t.path)
+ ;< =bowl:spider bind:m get-bowl
+ %- pure:m
+ .^(mold i.path (scot %p our.bowl) i.t.path (scot %da now.bowl) t.t.path)
+::
+++ leave
+ |= [=wire =dock]
+ =/ m (strand ,~)
+ ^- form:m
+ =/ =card:agent:gall [%pass watch+wire %agent dock %leave ~]
+ (send-raw-card card)
+::
+++ leave-our
+ |= [=wire =term]
+ =/ m (strand ,~)
+ ^- form:m
+ ;< our=@p bind:m get-our
+ (leave wire [our term])
+::
+++ rewatch
+ |= [=wire =dock =path]
+ =/ m (strand ,~)
+ ;< ~ bind:m ((handle ,~) (take-kick wire))
+ ;< ~ bind:m (flog-text "rewatching {<dock>} {<path>}")
+ ;< ~ bind:m (watch wire dock path)
+ (pure:m ~)
+::
+++ wait
+ |= until=@da
+ =/ m (strand ,~)
+ ^- form:m
+ ;< ~ bind:m (send-wait until)
+ (take-wake `until)
+::
+++ mass
+ =/ m (strand ,(list quac:dill))
+ ^- form:m
+ =/ =card:agent:gall [%pass /mass %arvo %d %mass ~]
+ ;< ~ bind:m (send-raw-card card)
+ ;< quz=(list quac:dill) bind:m take-meme
+ (pure:m quz)
+::
+++ take-meme
+ =/ m (strand ,(list quac:dill))
+ ^- form:m
+ |= tin=strand-input:strand
+ ?+ in.tin `[%skip ~]
+ ~ `[%wait ~]
+ [~ %sign [%mass ~] %dill %meme *]
+ `[%done p.sign-arvo.u.in.tin]
+ ==
+::
+++ keen
+ |= [=wire =spar:ames sec=(unit [@ @])]
+ =/ m (strand ,~)
+ ^- form:m
+ (send-raw-card %pass wire %arvo %a %keen sec spar)
+::
+++ chum
+ |= [=wire =spar:ames]
+ =/ m (strand ,~)
+ ^- form:m
+ (send-raw-card %pass wire %arvo %a %chum spar)
+::
+++ keen-shut
+ |= [=wire =spar:ames]
+ =/ m (strand ,~)
+ ^- form:m
+ (send-raw-card %pass wire %keen & spar)
+::
+++ yawn
+ |= [=wire =spar:ames]
+ =/ m (strand ,~)
+ ^- form:m
+ (send-raw-card %pass wire %arvo %a %yawn spar)
+::
+++ whey
+ |= [=wire boq=@ud =spar:ames]
+ =/ m (strand ,~)
+ ^- form:m
+ :: encrypted using %chum namespace
+ ::
+ ;< our=@p bind:m get-our
+ =. path.spar
+ [%a %x '1' %$ %whey (scot %ud boq) (scot %p our) path.spar]
+ (chum wire spar)
+::
+++ meta
+ |= [=wire =spar:ames]
+ =/ m (strand ,~)
+ ^- form:m
+ ?+ path.spar !!
+ $% [%ames bone=@ ?(%clos %cork %next %last %curr) ~]
+ [%flow bone=@ =dire:ames ~]
+ [%flow bone=@ =dire:ames ?(%clos %cork %line %lods %next %last) ~]
+ :: XX rewrite in terms of %whey namespace
+ ::
+ [%flow bone=@ =dire:ames %whey boq=@ ~]
+ [%flow bone=@ =dire:ames seq=@ %naxp ~]
+ ==
+ :: encrypted using %chum namespace
+ ::
+ ;< our=@p bind:m get-our
+ %- send-raw-card
+ :* %pass wire %arvo %a %chum
+ spar(path [%a %x '1' %$ %meta (scot %p our) path.spar])
+ ==
+ ==
+::
+++ sleep
+ |= for=@dr
+ =/ m (strand ,~)
+ ^- form:m
+ ;< now=@da bind:m get-time
+ (wait (add now for))
+::
+++ send-wait
+ |= until=@da
+ =/ m (strand ,~)
+ ^- form:m
+ =/ =card:agent:gall
+ [%pass /wait/(scot %da until) %arvo %b %wait until]
+ (send-raw-card card)
+::
+++ map-err
+ |* computation-result=mold
+ =/ m (strand ,computation-result)
+ |= [f=$-([term tang] [term tang]) computation=form:m]
+ ^- form:m
+ |= tin=strand-input:strand
+ =* loop $
+ =/ c-res (computation tin)
+ ?: ?=(%cont -.next.c-res)
+ c-res(self.next ..loop(computation self.next.c-res))
+ ?. ?=(%fail -.next.c-res)
+ c-res
+ c-res(err.next (f err.next.c-res))
+::
+++ set-timeout
+ |* computation-result=mold
+ =/ m (strand ,computation-result)
+ |= [time=@dr computation=form:m]
+ ^- form:m
+ ;< now=@da bind:m get-time
+ =/ when (add now time)
+ =/ =card:agent:gall
+ [%pass /timeout/(scot %da when) %arvo %b %wait when]
+ ;< ~ bind:m (send-raw-card card)
+ |= tin=strand-input:strand
+ =* loop $
+ ?: ?& ?=([~ %sign [%timeout @ ~] %behn %wake *] in.tin)
+ =((scot %da when) i.t.wire.u.in.tin)
+ ==
+ `[%fail %timeout ~]
+ =/ c-res (computation tin)
+ ?: ?=(%cont -.next.c-res)
+ c-res(self.next ..loop(computation self.next.c-res))
+ ?: ?=(%done -.next.c-res)
+ =/ =card:agent:gall
+ [%pass /timeout/(scot %da when) %arvo %b %rest when]
+ c-res(cards [card cards.c-res])
+ c-res
+::
+++ send-request
+ |= =request:http
+ =/ m (strand ,~)
+ ^- form:m
+ (send-raw-card %pass /request %arvo %i %request request *outbound-config:iris)
+::
+++ send-cancel-request
+ =/ m (strand ,~)
+ ^- form:m
+ (send-raw-card %pass /request %arvo %i %cancel-request ~)
+::
+++ take-client-response
+ =/ m (strand ,client-response:iris)
+ ^- form:m
+ |= tin=strand-input:strand
+ ?+ in.tin `[%skip ~]
+ ~ `[%wait ~]
+ ::
+ [~ %sign [%request ~] %iris %http-response %cancel *]
+ ::NOTE iris does not (yet?) retry after cancel, so it means failure
+ :- ~
+ :+ %fail
+ %http-request-cancelled
+ ['http request was cancelled by the runtime']~
+ ::
+ [~ %sign [%request ~] %iris %http-response %finished *]
+ `[%done client-response.sign-arvo.u.in.tin]
+ ==
+::
+:: Wait until we get an HTTP response or cancelation and unset contract
+::
+++ take-maybe-sigh
+ =/ m (strand ,(unit httr:eyre))
+ ^- form:m
+ ;< rep=(unit client-response:iris) bind:m
+ take-maybe-response
+ ?~ rep
+ (pure:m ~)
+ :: XX s/b impossible
+ ::
+ ?. ?=(%finished -.u.rep)
+ (pure:m ~)
+ (pure:m (some (to-httr:iris +.u.rep)))
+::
+++ take-maybe-response
+ =/ m (strand ,(unit client-response:iris))
+ ^- form:m
+ |= tin=strand-input:strand
+ ?+ in.tin `[%skip ~]
+ ~ `[%wait ~]
+ [~ %sign [%request ~] %iris %http-response %cancel *]
+ `[%done ~]
+ [~ %sign [%request ~] %iris %http-response %finished *]
+ `[%done `client-response.sign-arvo.u.in.tin]
+ ==
+::
+++ extract-body
+ |= =client-response:iris
+ =/ m (strand ,cord)
+ ^- form:m
+ ?> ?=(%finished -.client-response)
+ %- pure:m
+ ?~ full-file.client-response ''
+ q.data.u.full-file.client-response
+::
+++ fetch-cord
+ |= url=tape
+ =/ m (strand ,cord)
+ ^- form:m
+ =/ =request:http [%'GET' (crip url) ~ ~]
+ ;< ~ bind:m (send-request request)
+ ;< =client-response:iris bind:m take-client-response
+ (extract-body client-response)
+::
+++ fetch-json
+ |= url=tape
+ =/ m (strand ,json)
+ ^- form:m
+ ;< =cord bind:m (fetch-cord url)
+ =/ json=(unit json) (de:json:html cord)
+ ?~ json
+ (strand-fail %json-parse-error ~)
+ (pure:m u.json)
+::
+++ hiss-request
+ |= =hiss:eyre
+ =/ m (strand ,(unit httr:eyre))
+ ^- form:m
+ ;< ~ bind:m (send-request (hiss-to-request:html hiss))
+ take-maybe-sigh
+::
+:: +build-file: build the source file at the specified $beam
+::
+++ build-file
+ |= [[=ship =desk =case] =spur]
+ =* arg +<
+ =/ m (strand ,(unit vase))
+ ^- form:m
+ ;< =riot:clay bind:m
+ (warp ship desk ~ %sing %a case spur)
+ ?~ riot
+ (pure:m ~)
+ ?> =(%vase p.r.u.riot)
+ (pure:m (some !<(vase q.r.u.riot)))
+::
+++ build-file-hard
+ |= [[=ship =desk =case] =spur]
+ =* arg +<
+ =/ m (strand ,vase)
+ ^- form:m
+ ;< =riot:clay
+ bind:m
+ (warp ship desk ~ %sing %a case spur)
+ ?> ?=(^ riot)
+ ?> ?=(%vase p.r.u.riot)
+ (pure:m !<(vase q.r.u.riot))
+:: +build-mark: build a mark definition to a $dais
+::
+++ build-mark
+ |= [[=ship =desk =case] mak=mark]
+ =* arg +<
+ =/ m (strand ,dais:clay)
+ ^- form:m
+ ;< =riot:clay bind:m
+ (warp ship desk ~ %sing %b case /[mak])
+ ?~ riot
+ (strand-fail %build-mark >arg< ~)
+ ?> =(%dais p.r.u.riot)
+ (pure:m !<(dais:clay q.r.u.riot))
+:: +build-tube: build a mark conversion gate ($tube)
+::
+++ build-tube
+ |= [[=ship =desk =case] =mars:clay]
+ =* arg +<
+ =/ m (strand ,tube:clay)
+ ^- form:m
+ ;< =riot:clay bind:m
+ (warp ship desk ~ %sing %c case /[a.mars]/[b.mars])
+ ?~ riot
+ (strand-fail %build-tube >arg< ~)
+ ?> =(%tube p.r.u.riot)
+ (pure:m !<(tube:clay q.r.u.riot))
+::
+:: +build-nave: build a mark definition to a $nave
+::
+++ build-nave
+ |= [[=ship =desk =case] mak=mark]
+ =* arg +<
+ =/ m (strand ,vase)
+ ^- form:m
+ ;< =riot:clay bind:m
+ (warp ship desk ~ %sing %e case /[mak])
+ ?~ riot
+ (strand-fail %build-nave >arg< ~)
+ ?> =(%nave p.r.u.riot)
+ (pure:m q.r.u.riot)
+:: +build-cast: build a mark conversion gate (static)
+::
+++ build-cast
+ |= [[=ship =desk =case] =mars:clay]
+ =* arg +<
+ =/ m (strand ,vase)
+ ^- form:m
+ ;< =riot:clay bind:m
+ (warp ship desk ~ %sing %f case /[a.mars]/[b.mars])
+ ?~ riot
+ (strand-fail %build-cast >arg< ~)
+ ?> =(%cast p.r.u.riot)
+ (pure:m q.r.u.riot)
+::
+:: Read from Clay
+::
+++ warp
+ |= [=ship =riff:clay]
+ =/ m (strand ,riot:clay)
+ ;< ~ bind:m (send-raw-card %pass /warp %arvo %c %warp ship riff)
+ (take-writ /warp)
+::
+++ read-file
+ |= [[=ship =desk =case] =spur]
+ =* arg +<
+ =/ m (strand ,cage)
+ ;< =riot:clay bind:m (warp ship desk ~ %sing %x case spur)
+ ?~ riot
+ (strand-fail %read-file >arg< ~)
+ (pure:m r.u.riot)
+::
+++ check-for-file
+ |= [[=ship =desk =case] =spur]
+ =/ m (strand ,?)
+ ;< =riot:clay bind:m (warp ship desk ~ %sing %u case spur)
+ ?> ?=(^ riot)
+ (pure:m !<(? q.r.u.riot))
+::
+++ list-tree
+ |= [[=ship =desk =case] =spur]
+ =* arg +<
+ =/ m (strand ,(list path))
+ ;< =riot:clay bind:m (warp ship desk ~ %sing %t case spur)
+ ?~ riot
+ (strand-fail %list-tree >arg< ~)
+ (pure:m !<((list path) q.r.u.riot))
+::
+++ list-desk
+ |= [[=ship =desk =case] =spur]
+ =* arg +<
+ =/ m (strand arch)
+ ;< =riot:clay bind:m (warp ship desk ~ %sing %y case spur)
+ ?~ riot
+ (strand-fail %list-desk >arg< ~)
+ (pure:m !<(arch q.r.u.riot))
+:: Take Clay read result
+::
+++ take-writ
+ |= =wire
+ =/ m (strand ,riot:clay)
+ ^- form:m
+ |= tin=strand-input:strand
+ ?+ in.tin `[%skip ~]
+ ~ `[%wait ~]
+ [~ %sign * ?(%behn %clay) %writ *]
+ ?. =(wire wire.u.in.tin)
+ `[%skip ~]
+ `[%done +>.sign-arvo.u.in.tin]
+ ==
+:: +check-online: require that peer respond before timeout
+::
+++ check-online
+ |= [who=ship lag=@dr]
+ =/ m (strand ,~)
+ ^- form:m
+ %+ (map-err ,~) |=(* [%offline *tang])
+ %+ (set-timeout ,~) lag
+ ;< ~ bind:m
+ (poke [who %hood] %helm-hi !>(~))
+ (pure:m ~)
+::
+++ eval-hoon
+ |= [gen=hoon bez=(list beam)]
+ =/ m (strand ,vase)
+ ^- form:m
+ =/ sut=vase !>(..zuse)
+ |-
+ ?~ bez
+ (pure:m (slap sut gen))
+ ;< vax=vase bind:m (build-file-hard i.bez)
+ $(bez t.bez, sut (slop vax sut))
+::
+++ send-thread
+ |= [=bear:khan =shed:khan =wire]
+ =/ m (strand ,~)
+ ^- form:m
+ (send-raw-card %pass wire %arvo %k %lard bear shed)
+::
+:: Queue on skip, try next on fail %ignore
+::
+++ main-loop
+ |* a=mold
+ =/ m (strand ,~)
+ =/ m-a (strand ,a)
+ =| queue=(qeu (unit input:strand))
+ =| active=(unit [in=(unit input:strand) =form:m-a forms=(list $-(a form:m-a))])
+ =| state=a
+ |= forms=(lest $-(a form:m-a))
+ ^- form:m
+ |= tin=strand-input:strand
+ =* top `form:m`..$
+ =. queue (~(put to queue) in.tin)
+ |^ (continue bowl.tin)
+ ::
+ ++ continue
+ |= =bowl:strand
+ ^- output:m
+ ?> =(~ active)
+ ?: =(~ queue)
+ `[%cont top]
+ =^ in=(unit input:strand) queue ~(get to queue)
+ ^- output:m
+ =. active `[in (i.forms state) t.forms]
+ ^- output:m
+ (run bowl in)
+ ::
+ ++ run
+ ^- form:m
+ |= tin=strand-input:strand
+ ^- output:m
+ ?> ?=(^ active)
+ =/ res (form.u.active tin)
+ =/ =output:m
+ ?- -.next.res
+ %wait `[%wait ~]
+ %skip `[%cont ..$(queue (~(put to queue) in.tin))]
+ %cont `[%cont ..$(active `[in.u.active self.next.res forms.u.active])]
+ %done (continue(active ~, state value.next.res) bowl.tin)
+ %fail
+ ?: &(?=(^ forms.u.active) ?=(%ignore p.err.next.res))
+ %= $
+ active `[in.u.active (i.forms.u.active state) t.forms.u.active]
+ in.tin in.u.active
+ ==
+ `[%fail err.next.res]
+ ==
+ [(weld cards.res cards.output) next.output]
+ --
+::
+++ retry
+ |* result=mold
+ |= [crash-after=(unit @ud) computation=_*form:(strand (unit result))]
+ =/ m (strand ,result)
+ =| try=@ud
+ |- ^- form:m
+ =* loop $
+ ?: =(crash-after `try)
+ (strand-fail %retry-too-many ~)
+ ;< ~ bind:m (backoff try ~m1)
+ ;< res=(unit result) bind:m computation
+ ?^ res
+ (pure:m u.res)
+ loop(try +(try))
+::
+++ backoff
+ |= [try=@ud limit=@dr]
+ =/ m (strand ,~)
+ ^- form:m
+ ;< eny=@uvJ bind:m get-entropy
+ %- sleep
+ %+ min limit
+ ?: =(0 try) ~s0
+ %+ add
+ (mul ~s1 (bex (dec try)))
+ (mul ~s0..0001 (~(rad og eny) 1.000))
+::
+:: ----
+::
+:: Output
+::
+++ flog
+ |= =flog:dill
+ =/ m (strand ,~)
+ ^- form:m
+ (send-raw-card %pass / %arvo %d %flog flog)
+::
+++ flog-text
+ |= =tape
+ =/ m (strand ,~)
+ ^- form:m
+ (flog %text tape)
+::
+++ flog-tang
+ |= =tang
+ =/ m (strand ,~)
+ ^- form:m
+ =/ =wall
+ (zing (turn (flop tang) (cury wash [0 80])))
+ |- ^- form:m
+ =* loop $
+ ?~ wall
+ (pure:m ~)
+ ;< ~ bind:m (flog-text i.wall)
+ loop(wall t.wall)
+::
+++ trace
+ |= =tang
+ =/ m (strand ,~)
+ ^- form:m
+ (pure:m ((slog tang) ~))
+::
+++ app-message
+ |= [app=term =cord =tang]
+ =/ m (strand ,~)
+ ^- form:m
+ =/ msg=tape :(weld (trip app) ": " (trip cord))
+ ;< ~ bind:m (flog-text msg)
+ (flog-tang tang)
+::
+:: ----
+::
+:: Handle domains
+::
+++ install-domain
+ |= =turf
+ =/ m (strand ,~)
+ ^- form:m
+ (send-raw-card %pass / %arvo %e %rule %turf %put turf)
+::
+:: ----
+::
+:: Threads
+::
+++ start-thread
+ |= file=term
+ =/ m (strand ,tid:spider)
+ ;< =bowl:spider bind:m get-bowl
+ (start-thread-with-args byk.bowl file *vase)
+::
+++ start-thread-with-args
+ |= [=beak file=term args=vase]
+ =/ m (strand ,tid:spider)
+ ^- form:m
+ ;< =bowl:spider bind:m get-bowl
+ =/ tid
+ (scot %ta (cat 3 (cat 3 'strand_' file) (scot %uv (sham file eny.bowl))))
+ =/ poke-vase !>(`start-args:spider`[`tid.bowl `tid beak file args])
+ ;< ~ bind:m (poke-our %spider %spider-start poke-vase)
+ ;< ~ bind:m (sleep ~s0) :: wait for thread to start
+ (pure:m tid)
+::
++$ thread-result
+ (each vase [term tang])
+::
+++ await-thread
+ |= [file=term args=vase]
+ =/ m (strand ,thread-result)
+ ^- form:m
+ ;< =bowl:spider bind:m get-bowl
+ =/ tid (scot %ta (cat 3 'strand_' (scot %uv (sham file eny.bowl))))
+ =/ poke-vase !>(`start-args:spider`[`tid.bowl `tid byk.bowl file args])
+ ;< ~ bind:m (watch-our /awaiting/[tid] %spider /thread-result/[tid])
+ ;< ~ bind:m (poke-our %spider %spider-start poke-vase)
+ ;< ~ bind:m (sleep ~s0) :: wait for thread to start
+ ;< =cage bind:m (take-fact /awaiting/[tid])
+ ;< ~ bind:m (take-kick /awaiting/[tid])
+ ?+ p.cage ~|([%strange-thread-result p.cage file tid] !!)
+ %thread-done (pure:m %& q.cage)
+ %thread-fail (pure:m %| !<([term tang] q.cage))
+ ==
+--
diff --git a/desk/lib/trill/post.hoon b/desk/lib/trill/post.hoon
new file mode 100644
index 0000000..5bed037
--- /dev/null
+++ b/desk/lib/trill/post.hoon
@@ -0,0 +1,377 @@
+/- tp=trill-post, md=markdown
+/+ sr=sortug, mdlib=markdown
+|%
+++ build-sp
+ |= [host=@p author=@p input=@t]
+ ^- sent-post:tp
+ =/ cl (tokenise input)
+ ~| "parsing error!!"
+ ?: ?=(%| -.cl) !!
+ =| sp=sent-post:tp
+ %= sp
+ host host
+ author author
+ contents +.cl
+ ==
+++ build-post
+ |= [now=@da pubkey=@ux sp=sent-post:tp]
+ ^- post:tp
+ =/ cm (init-content-map contents.sp now)
+ =/ thread ?~ thread.sp now u.thread.sp
+ =/ =post:tp
+ :* id=now
+ host.sp
+ author.sp
+ thread
+ parent.sp
+ ~
+ cm
+ read.sp
+ write.sp
+ *engagement:tp
+ `@uvH`pubkey
+ *signature:tp
+ ~
+ ==
+ post
+:: new! using wispem's lib
+++ tokenise
+|= t=@t ^- (each content-list:tp @t)
+ =/ parsed (rush t markdown:de:md:mdlib)
+ ?~ parsed [%| 'parsing error']
+ :- %&
+ %+ turn u.parsed de-node
+++ de-node |= =node:markdown:md ^- block:tp
+ ?~ node [%paragraph ~]
+ ?- -.node
+ %leaf (de-leaf +.node)
+ %container (de-cont +.node)
+ ==
+
+++ de-leaf |= =node:leaf:markdown:md ^- block:tp
+ ?~ node [%paragraph ~]
+ ?- -.node
+ %heading (de-heading node)
+ %break [%paragraph :~([%break ~])]
+ %indent-codeblock [%codeblock text.node '']
+ %fenced-codeblock [%codeblock text.node info-string.node]
+ %html [%codeblock text.node 'html']
+ %link-ref-definition [%paragraph :~([%link '' label.node])]
+ %paragraph [%paragraph (de-inline contents.node)]
+ %blank-line [%paragraph :~([%break ~])]
+ %table [%paragraph :~([%break ~])] :: TODO
+ ==
+++ de-heading |= h=heading:leaf:markdown:md
+ :+ %heading (flatten-inline contents.h)
+ ?: .=(1 level.h) %h1
+ ?: .=(2 level.h) %h2
+ ?: .=(3 level.h) %h3
+ ?: .=(4 level.h) %h4
+ ?: .=(5 level.h) %h5 %h6
+++ de-inline |= inls=contents:inline:md
+ =| res=(list inline:tp)
+ |- ?~ inls (flop res)
+ =/ inl i.inls
+ =/ r=inline:tp ?- -.inl
+ %escape [%codespan char.inl]
+ %entity [%codespan code.inl]
+ %code-span [%codespan text.inl]
+ %line-break [%break ~]
+ %soft-line-break [%break ~]
+ %text [%text text.inl]
+ %emphasis (de-strong +.inl)
+ %strong (de-strong +.inl)
+ %link [%link (de-target target.inl) (flatten-inline contents.inl)]
+ %image [%link (de-target target.inl) (de-target target.inl)]
+ :: %image [%img (de-target target.inl) alt-text.inl]
+ %autolink [%text '']
+ %html [%codespan text.inl]
+ ==
+ $(inls t.inls, res [r res])
+++ de-strong |= [char=@t inls=contents:inline:md]
+?: .=('_' char) [%italic (flatten-inline inls)]
+ [%bold (flatten-inline inls)]
+++ de-target |= tar=target:ln:md
+:: TODO lotsa stuff here
+ ?- -.tar
+ %direct text.url.urlt.tar
+ %ref label.tar
+ ==
+++ flatten-inline |= inls=contents:inline:md ^- @t
+ =/ res ""
+ |- ?~ inls (crip res)
+ =/ inl i.inls
+ =/ r ?+ -.inl ""
+ %escape (trip char.inl)
+ %entity (trip code.inl)
+ %code-span (trip text.inl)
+ %text (trip text.inl)
+ %emphasis (trip (flatten-inline contents.inl))
+ %strong (trip (flatten-inline contents.inl))
+ %link (trip (flatten-inline contents.inl))
+ %image (trip (de-target target.inl))
+ %html (trip text.inl)
+ ==
+ $(inls t.inls, res "{res} {r}")
+++ de-cont |= =node:container:markdown:md ^- block:tp
+ ?~ node [%paragraph ~]
+ ?- -.node
+ %block-quote [%blockquote (denest +.node)]
+ %ol [%list (de-list contents.node) .y]
+ %ul [%list (de-list contents.node) .n]
+ %tl [%paragraph ~]
+ ==
+++ de-list |= lmd=(list markdown:md) ^- (list inline:tp)
+:: TODO
+~
+ :: =| res=(list li:tp)
+ :: |- ?~ lmd (flop res)
+ :: =/ nodelist i.lmd
+ :: =/ blocks=(list block:tp)
+ :: %+ turn nodelist de-node
+ :: $(lmd t.lmd, res [blocks res])
+
+++ denest |= mde=markdown:md ^- paragraph:tp
+ =| res=paragraph:tp
+ |- ?~ mde (flop res)
+ =/ block (de-node i.mde)
+ =/ r=paragraph:tp (break-block block)
+ =/ nr (weld res r)
+ $(mde t.mde, res nr)
+
+++ break-block |= =block:tp ^- paragraph:tp
+?+ -.block ~
+ %paragraph p.block
+ %blockquote p.block
+ %heading :~([%text p.block])
+ %codeblock :~([%text code.block])
+ %eval :~([%text hoon.block])
+ :: %list (break-list p.block)
+==
+++ break-list |= lis=(list li:tp) ^- paragraph:tp
+ =| res=paragraph:tp
+ |- ?~ lis (flop res)
+ =/ par (ibreak-list i.lis)
+ =/ nr (weld res par)
+ $(lis t.lis, res nr)
+++ ibreak-list |= blocks=(list block:tp) ^- paragraph:tp
+ =| res=paragraph:tp
+ |- ?~ blocks (flop res)
+ =/ par (break-block i.blocks)
+ =/ nr (weld res par)
+ $(blocks t.blocks, res nr)
+
+:: tape -> post:trill, parsing user input from Sail
++$ heading $?(%h1 %h2 %h3 %h4 %h5 %h6)
+
+++ parse :: Markdown parser. Actually udon parser but it'll do
+ |= s=tape ^- (unit marl:hoot) :: finally
+ :: Annoying it requires a line break but then parses it as a space wtf
+ =, vast
+ (rust s cram:(sail .y))
+++ tokenize
+|= s=@t ^- content-list:tp
+ =/ t (weld (trip s) "\0a")
+ =/ parsed (parse t)
+ :: =/ parsed2 (parse:md t)
+ :: ~& > diary-parser=parsed2
+ :: \0a can't be followed by a space. ever. those are the rules
+ ?~ parsed ~& error-parsing-markdown=t ~
+ (marl-to-cl u.parsed)
+++ marl-to-cl
+|= =marl:hoot ^- content-list:tp
+ %- flop
+ %+ roll marl
+ |= [=tuna:hoot acc=content-list:tp]
+ :: man this is an annoying type if I ever saw one
+ ?@ -.tuna acc
+ =/ blk (manx-to-block tuna)
+ ?~ blk acc :_ acc u.blk
+++ manx-to-block
+ |= =manx:hoot ^- (unit block:tp)
+ ?+ n.g.manx ~
+ :: TODO
+ :: heading %- some [%heading (phead n.g.manx c.manx)]
+ %p %- some [%paragraph (inline-list c.manx)]
+ %blockquote %- some [%blockquote (inline-list c.manx)]
+ %pre %- some [%codeblock (pre c.manx)]
+ %hr %- some [%paragraph ~[[%break ~]]]
+ %ul %- some [%list (inline-list c.manx) .n]
+ %ol %- some [%list (inline-list c.manx) .y]
+ :: %table %- some (table-rows c.manx)
+ ==
+:: ++ list-items
+:: |= =marl:hoot ^- (list li:tp)
+:: %- flop
+:: %+ roll marl |= [=tuna:hoot acc=(list li:tp)]
+:: ?@ -.tuna acc
+:: ?. ?=(%li n.g.tuna) acc :_ acc (marl-to-cl c.tuna)
+:: ++ phead
+:: |= [h=heading c=marl:hoot] ^- [p=cord q=heading]
+:: :- (get-tag-text c) h
+++ inline-list
+ |= c=marl:hoot ^- (list inline:tp)
+ %- flop
+ %+ roll c
+ |= [=tuna:hoot acc=(list inline:tp)]
+ ?@ -.tuna acc :_ acc (inline tuna)
+ ++ inline
+ |= =manx:hoot ^- inline:tp
+ ?: ?=(%$ n.g.manx) [%text (get-attrs-text a.g.manx)]
+ =/ text=@t (get-tag-text c.manx)
+ ?+ n.g.manx [%text text]
+ %i [%italic text]
+ %b [%bold text]
+ %code [%codespan text]
+ %br [%break ~]
+ %a :+ %link (get-attrs-text a.g.manx) (get-tag-text c.manx)
+ %img :+ %link (get-attr-text a.g.manx %src) (get-attr-text a.g.manx %alt)
+ ==
+::
+++ reduce-block
+|= c=marl:hoot ^- @t
+ %+ roll c
+ |= [=tuna:hoot acc=@t]
+ ?@ -.tuna acc
+ ?+ n.g.tuna acc
+ %p (get-tag-text c.tuna)
+ ==
+++ get-attr-text
+|= [a=mart:hoot attr=@tas] ^- @t
+ %- crip %- flop
+ %+ roll a
+ |= [[n=mane v=(list beer:hoot)] acc=tape]
+ ?. .=(attr n) acc
+ %+ roll v
+ |= [b=beer:hoot acc=tape]
+ ?^ b acc [b acc]
+++ get-attrs-text :: this assumes we don't care about which attr, which we usually don't
+|= a=mart:hoot ^- @t
+ :: ?: (gte (lent a) 1)
+ %- crip %- flop
+ %+ roll a
+ |= [[n=mane v=(list beer:hoot)] acc=tape]
+ %+ roll v
+ |= [b=beer:hoot acc=tape]
+ ?^ b acc [b acc]
+++ get-tag-text
+|= c=marl:hoot ^- @t
+:: there's only really one child in these things
+ %+ roll c
+ |= [=tuna:hoot acc=@t]
+ ?@ -.tuna acc
+ %- crip
+ %- flop
+ %+ roll a.g.tuna
+ |= [[n=mane v=(list beer:hoot)] acc=tape]
+ %+ roll v
+ |= [b=beer:hoot acc=tape]
+ ?^ b acc [b acc]
+
+++ pre
+ |= c=marl:hoot ^- [cord cord]
+ :_ '' :: lang not supported, duh
+ %+ roll c
+ |= [=tuna:hoot acc=@t]
+ ?@ -.tuna acc
+ (get-attrs-text a.g.tuna)
+
+++ parse-tags
+|= t=@t ^- (unit (set @t))
+ =/ lst (rush t (csplit:sr com))
+ ?~ lst ~ (some (sy u.lst))
+:: post:trill -> (markdown) tape for display on sail
+++ block-to-md
+|= b=block:tp ^- tape
+ ?+ -.b ""
+%paragraph
+ %^ foldi:sr p.b "" |= [in=@ud i=inline:tp acc=tape]
+ =/ il (inline-to-tape i)
+ ?: .=(+(in) (lent p.b))
+ "{acc}{il}"
+ "{acc}{il} "
+%blockquote
+ %+ weld "> "
+ %^ foldi:sr p.b "" |= [in=@ud i=inline:tp acc=tape]
+ =/ il (inline-to-tape i)
+ ?: .=(+(in) (lent p.b))
+ "{acc}{il}"
+ "{acc}{il} "
+%list
+ %^ foldi:sr p.b "" |= [in=@ud i=inline:tp acc=tape]
+ =/ li-tape (inline-to-tape i)
+ =/ line ?: ordered.b
+ "{<+(in)>}. {li-tape}"
+ "- {li-tape}"
+ ?: .=(+(in) (lent p.b))
+ "{acc}{line}"
+ "{acc}{line}\0a"
+%media
+ ?+ -.media.b "![{(trip p.media.b)}]({(trip p.media.b)})"
+ :: TODO
+%images
+ :: %^ foldi:sr p.media.b "" |= [i=@ud [url=@t caption=@t] acc=tape]
+ :: =/ line "![{(trip caption)}]({(trip url)})"
+ :: ?: .=(+(i) (lent p.media.b))
+ :: "{acc}{line}"
+ :: "{acc}{line}\0a"
+ ""
+ ==
+%codeblock
+ """
+ ```
+ {(trip code.b)}
+ ```
+ """
+%heading =/ dashes=tape ?- q.b
+ %h1 "# "
+ %h2 "## "
+ %h3 "### "
+ %h4 "#### "
+ %h5 "##### "
+ %h6 "###### "
+ == "{dashes}{(trip p.b)}"
+:: %tasklist "" ::TODO
+ ::
+ :: %table acc
+ :: %eval acc
+ :: %ref acc
+ :: %json acc
+ ==
+++ latest-post-content
+|= cm=content-map:tp ^- content-list:tp
+ =/ last (pry:corm:tp cm)
+ ?~ last ~
+ +.u.last
+
+++ content-list-to-md
+|= =content-list:tp ^- tape
+ %^ foldi:sr content-list "" |= [i=@ud b=block:tp acc=tape]
+ =/ block-tape (block-to-md b)
+ ?: .=(+(i) (lent content-list))
+ "{acc}{block-tape}"
+ "{acc}{block-tape}\0a\0a"
+++ inline-to-tape
+|= i=inline:tp ^- tape
+ ?+ -.i ""
+ %text (trip p.i)
+ %italic "_{(trip p.i)}_"
+ %bold "*{(trip p.i)}*"
+ %strike "~~{(trip p.i)}~~"
+ %ship (scow %p p.i)
+ %codespan "`{(trip p.i)}`"
+ %link "[{(trip show.i)}]({(trip href.i)})"
+ :: %img "![{(trip alt.i)}]({(trip src.i)})"
+ %break "\0a"
+ ==
+++ tags-to-tape
+|= t=(set @t) ^- tape
+ %^ foldi:sr ~(tap in t) "" |= [i=@ud c=@t acc=tape]
+ ?: .=(+(i) ~(wyt in t))
+ "{acc}{(trip c)}"
+ "{acc}{(trip c)},"
+
+++ init-content-map |= [cl=content-list:tp date=@da] ^- content-map:tp
+ (put:corm:tp *content-map:tp date cl)
+
+--
diff --git a/desk/mar/bill.hoon b/desk/mar/bill.hoon
new file mode 100644
index 0000000..76cef34
--- /dev/null
+++ b/desk/mar/bill.hoon
@@ -0,0 +1,34 @@
+|_ bil=(list dude:gall)
+++ grow
+ |%
+ ++ mime `^mime`[/text/x-bill (as-octs:mimes:html hoon)]
+ ++ noun bil
+ ++ hoon
+ ^- @t
+ |^ (crip (of-wall:format (wrap-lines (spit-duz bil))))
+ ::
+ ++ wrap-lines
+ |= taz=wall
+ ^- wall
+ ?~ taz ["~"]~
+ :- (weld ":~ " i.taz)
+ %- snoc :_ "=="
+ (turn t.taz |=(t=tape (weld " " t)))
+ ::
+ ++ spit-duz
+ |= duz=(list dude:gall)
+ ^- wall
+ (turn duz |=(=dude:gall ['%' (trip dude)]))
+ --
+ ++ txt (to-wain:format hoon)
+ --
+++ grab
+ |%
+ ++ noun (list dude:gall)
+ ++ mime
+ |= [=mite len=@ud tex=@]
+ ~_ tex
+ !<((list dude:gall) (slap !>(~) (ream tex)))
+ --
+++ grad %noun
+--
diff --git a/desk/mar/css.hoon b/desk/mar/css.hoon
new file mode 100644
index 0000000..1a87081
--- /dev/null
+++ b/desk/mar/css.hoon
@@ -0,0 +1,25 @@
+::
+:::: /hoon/css/mar
+ ::
+/? 310
+=, eyre
+=, mimes:html
+|_ mud=@t
+++ grow :: convert to
+ |%
+ ++ mime [/text/css (as-octs mud)] :: convert to %mime
+ ++ hymn :: convert to %hymn
+ |^ html
+ ++ style ;style
+ ;- (trip mud)
+ ==
+ ++ html ;html:(head:"{style}" body)
+ --
+ --
+++ grab
+ |% :: convert from
+ ++ mime |=([p=mite q=octs] (@t q.q))
+ ++ noun @t :: clam from %noun
+ --
+++ grad %mime
+--
diff --git a/desk/mar/docket-0.hoon b/desk/mar/docket-0.hoon
new file mode 100644
index 0000000..c3b253b
--- /dev/null
+++ b/desk/mar/docket-0.hoon
@@ -0,0 +1,25 @@
+/+ dock=docket
+|_ =docket:dock
+++ grow
+ |%
+ ++ mime
+ ^- ^mime
+ [/text/x-docket (as-octt:mimes:html (spit-docket:mime:dock docket))]
+ ++ noun docket
+ ++ json (docket:enjs:dock docket)
+ --
+++ grab
+ |%
+ ::
+ ++ mime
+ |= [=mite len=@ud tex=@]
+ ^- docket:dock
+ %- need
+ %- from-clauses:mime:dock
+ !<((list clause:dock) (slap !>(~) (ream tex)))
+
+ ::
+ ++ noun docket:dock
+ --
+++ grad %noun
+--
diff --git a/desk/mar/hoon.hoon b/desk/mar/hoon.hoon
new file mode 100644
index 0000000..428e105
--- /dev/null
+++ b/desk/mar/hoon.hoon
@@ -0,0 +1,36 @@
+:::: /hoon/hoon/mar
+ ::
+/? 310
+::
+=, eyre
+|_ own=@t
+::
+++ grow :: convert to
+ |%
+ ++ mime `^mime`[/text/x-hoon (as-octs:mimes:html own)] :: convert to %mime
+ ++ hymn
+ ;html
+ ;head
+ ;title:"Source"
+ ;script@"//cdnjs.cloudflare.com/ajax/libs/codemirror/4.3.0/codemirror.js";
+ ;script@"/lib/syntax/hoon.js";
+ ;link(rel "stylesheet", href "//cdnjs.cloudflare.com/ajax/libs/".
+ "codemirror/4.3.0/codemirror.min.css");
+ ;link/"/lib/syntax/codemirror.css"(rel "stylesheet");
+ ==
+ ;body
+ ;textarea#src:"{(trip own)}"
+ ;script:'CodeMirror.fromTextArea(src, {lineNumbers:true, readOnly:true})'
+ ==
+ ==
+ ++ txt
+ (to-wain:format own)
+ --
+++ grab
+ |% :: convert from
+ ++ mime |=([p=mite q=octs] q.q)
+ ++ noun @t :: clam from %noun
+ ++ txt of-wain:format
+ --
+++ grad %txt
+--
diff --git a/desk/mar/ico.hoon b/desk/mar/ico.hoon
new file mode 100644
index 0000000..e862b9b
--- /dev/null
+++ b/desk/mar/ico.hoon
@@ -0,0 +1,12 @@
+|_ dat=@
+++ grow
+ |%
+ ++ mime [/image/x-icon (as-octs:mimes:html dat)]
+ --
+++ grab
+ |%
+ ++ mime |=([p=mite q=octs] q.q)
+ ++ noun @
+ --
+++ grad %mime
+--
diff --git a/desk/mar/js.hoon b/desk/mar/js.hoon
new file mode 100644
index 0000000..fe010d9
--- /dev/null
+++ b/desk/mar/js.hoon
@@ -0,0 +1,25 @@
+::
+:::: /hoon/js/mar
+ ::
+/? 310
+::
+=, eyre
+|_ mud=@
+++ grow
+ |%
+ ++ mime [/application/javascript (as-octs:mimes:html (@t mud))]
+ ++ hymn :: convert to %hymn
+ |^ html
+ ++ script ;script
+ ;- (trip (@t mud))
+ ==
+ ++ html ;html:(head:"{script}" body)
+ --
+ --
+++ grab
+ |% :: convert from
+ ++ mime |=([p=mite q=octs] (@t q.q))
+ ++ noun cord :: clam from %noun
+ --
+++ grad %mime
+--
diff --git a/desk/mar/kelvin.hoon b/desk/mar/kelvin.hoon
new file mode 100644
index 0000000..7f1b409
--- /dev/null
+++ b/desk/mar/kelvin.hoon
@@ -0,0 +1,28 @@
+|_ kal=waft:clay
+++ grow
+ |%
+ ++ mime `^mime`[/text/x-kelvin (as-octs:mimes:html hoon)]
+ ++ noun kal
+ ++ hoon
+ %+ rap 3
+ %+ turn
+ %+ sort
+ ~(tap in (waft-to-wefts:clay kal))
+ |= [a=weft b=weft]
+ ?: =(lal.a lal.b)
+ (gte num.a num.b)
+ (gte lal.a lal.b)
+ |= =weft
+ (rap 3 '[%' (scot %tas lal.weft) ' ' (scot %ud num.weft) ']\0a' ~)
+ ::
+ ++ txt (to-wain:format hoon)
+ --
+++ grab
+ |%
+ ++ noun waft:clay
+ ++ mime
+ |= [=mite len=@ud tex=@]
+ (cord-to-waft:clay tex)
+ --
+++ grad %noun
+--
diff --git a/desk/mar/mime.hoon b/desk/mar/mime.hoon
new file mode 100644
index 0000000..83b4dae
--- /dev/null
+++ b/desk/mar/mime.hoon
@@ -0,0 +1,32 @@
+::
+:::: /hoon/mime/mar
+ ::
+/? 310
+::
+|_ own=mime
+++ grow
+ ^?
+ |%
+ ++ jam `@`q.q.own
+ --
+::
+++ grab :: convert from
+ ^?
+ |%
+ ++ noun mime :: clam from %noun
+ ++ tape
+ |=(a=_"" [/application/x-urb-unknown (as-octt:mimes:html a)])
+ --
+++ grad
+ ^?
+ |%
+ ++ form %mime
+ ++ diff |=(mime +<)
+ ++ pact |=(mime +<)
+ ++ join |=([mime mime] `(unit mime)`~)
+ ++ mash
+ |= [[ship desk mime] [ship desk mime]]
+ ^- mime
+ ~|(%mime-mash !!)
+ --
+--
diff --git a/desk/mar/noun.hoon b/desk/mar/noun.hoon
new file mode 100644
index 0000000..ff5443e
--- /dev/null
+++ b/desk/mar/noun.hoon
@@ -0,0 +1,22 @@
+::
+:::: /hoon/noun/mar
+ ::
+/? 310
+!:
+:::: A minimal noun mark
+|_ non=*
+++ grab |%
+ ++ noun *
+ --
+++ grow |%
+ ++ mime [/application/x-urb-jam (as-octs:mimes:html (jam non))]
+ --
+++ grad
+ |%
+ ++ form %noun
+ ++ diff |=(* +<)
+ ++ pact |=(* +<)
+ ++ join |=([* *] *(unit *))
+ ++ mash |=([[ship desk *] [ship desk *]] `*`~|(%noun-mash !!))
+ --
+--
diff --git a/desk/mar/png.hoon b/desk/mar/png.hoon
new file mode 100644
index 0000000..6a60a6a
--- /dev/null
+++ b/desk/mar/png.hoon
@@ -0,0 +1,12 @@
+|_ dat=@
+++ grow
+ |%
+ ++ mime [/image/png (as-octs:mimes:html dat)]
+ --
+++ grab
+ |%
+ ++ mime |=([p=mite q=octs] q.q)
+ ++ noun @
+ --
+++ grad %mime
+--
diff --git a/desk/mar/ship.hoon b/desk/mar/ship.hoon
new file mode 100644
index 0000000..176bcad
--- /dev/null
+++ b/desk/mar/ship.hoon
@@ -0,0 +1,20 @@
+|_ s=ship
+++ grad %noun
+++ grow
+ |%
+ ++ noun s
+ ++ json s+(scot %p s)
+ ++ mime
+ ^- ^mime
+ [/text/x-ship (as-octt:mimes:html (scow %p s))]
+
+ --
+++ grab
+ |%
+ ++ noun ship
+ ++ json (su:dejs:format ;~(pfix sig fed:ag))
+ ++ mime
+ |= [=mite len=@ tex=@]
+ (slav %p (snag 0 (to-wain:format tex)))
+ --
+--
diff --git a/desk/mar/svg.hoon b/desk/mar/svg.hoon
new file mode 100644
index 0000000..2911e49
--- /dev/null
+++ b/desk/mar/svg.hoon
@@ -0,0 +1,12 @@
+|_ dat=@
+++ grow
+ |%
+ ++ mime [/image/'svg+xml' (as-octs:mimes:html dat)]
+ --
+++ grab
+ |%
+ ++ mime |=([p=mite q=octs] q.q)
+ ++ noun @
+ --
+++ grad %mime
+--
diff --git a/desk/mar/webmanifest.hoon b/desk/mar/webmanifest.hoon
new file mode 100644
index 0000000..6a60a6a
--- /dev/null
+++ b/desk/mar/webmanifest.hoon
@@ -0,0 +1,12 @@
+|_ dat=@
+++ grow
+ |%
+ ++ mime [/image/png (as-octs:mimes:html dat)]
+ --
+++ grab
+ |%
+ ++ mime |=([p=mite q=octs] q.q)
+ ++ noun @
+ --
+++ grad %mime
+--
diff --git a/desk/sur/docket.hoon b/desk/sur/docket.hoon
new file mode 100644
index 0000000..091c8c9
--- /dev/null
+++ b/desk/sur/docket.hoon
@@ -0,0 +1,82 @@
+|%
+::
++$ version
+ [major=@ud minor=@ud patch=@ud]
+::
++$ glob (map path mime)
+::
++$ url cord
+:: $glob-location: How to retrieve a glob
+::
++$ glob-reference
+ [hash=@uvH location=glob-location]
+::
++$ glob-location
+ $% [%http =url]
+ [%ames =ship]
+ ==
+:: $href: Where a tile links to
+::
++$ href
+ $% [%glob base=term =glob-reference]
+ [%site =path]
+ ==
+:: $chad: State of a docket
+::
++$ chad
+ $~ [%install ~]
+ $% :: Done
+ [%glob =glob]
+ [%site ~]
+ :: Waiting
+ [%install ~]
+ [%suspend glob=(unit glob)]
+ :: Error
+ [%hung err=cord]
+ ==
+::
+:: $charge: A realized $docket
+::
++$ charge
+ $: =docket
+ =chad
+ ==
+::
+:: $clause: A key and value, as part of a docket
+::
+:: Only used to parse $docket
+::
++$ clause
+ $% [%title title=@t]
+ [%info info=@t]
+ [%color color=@ux]
+ [%glob-http url=cord hash=@uvH]
+ [%glob-ames =ship hash=@uvH]
+ [%image =url]
+ [%site =path]
+ [%base base=term]
+ [%version =version]
+ [%website website=url]
+ [%license license=cord]
+ ==
+::
+:: $docket: A description of JS bundles for a desk
+::
++$ docket
+ $: %1
+ title=@t
+ info=@t
+ color=@ux
+ =href
+ image=(unit url)
+ =version
+ website=url
+ license=cord
+ ==
+::
++$ charge-update
+ $% [%initial initial=(map desk charge)]
+ [%add-charge =desk =charge]
+ [%del-charge =desk]
+ ==
+--
diff --git a/desk/sur/markdown.hoon b/desk/sur/markdown.hoon
new file mode 100644
index 0000000..baf266e
--- /dev/null
+++ b/desk/sur/markdown.hoon
@@ -0,0 +1,157 @@
+=> |%
+ ++ ln
+ |%
+ ::
+ :: Url: optionally enclosed in triangle brackets
+ :: A link destination consists of either
+ :: - a sequence of zero or more characters between an opening < and a closing > that
+ :: contains no line breaks or unescaped < or > characters, or
+ :: - a nonempty sequence of characters that does not start with <, does not include
+ :: ASCII space or control characters, and includes parentheses only if (a) they are
+ :: backslash-escaped or (b) they are part of a balanced pair of unescaped parentheses.
+ :: (Implementations may impose limits on parentheses nesting to avoid performance
+ :: issues, but at least three levels of nesting should be supported.)
+ +$ url [text=@t has-triangle-brackets=?]
+ ::
+ :: Url with optional title-text
+ +$ urlt [=url title-text=(unit @t)]
+ ::
+ :: Link target: the part of a link after the display text. can be direct or reference
+ :: A reference link is in square brackets, and refers to a named link elsewhere.
+ :: - full => [Display][foo]
+ :: - collapsed => [Display][]
+ :: - shortcut => [Display]
+ :: Collapsed and shortcut links have a `label` equal to the display text.
+ +$ target $% [%direct =urlt]
+ [%ref type=?(%full %collapsed %shortcut) label=@t]
+ ==
+ --
+ --
+::
+|%
+ ::
+ :: Markdown document or fragment: a list of nodes
+ ++ markdown =< $+ markdown
+ (list node)
+ |%
+ +$ node $+ markdown-node
+ $@ ~ :: `$@ ~` is magic that makes recursive structures work
+ $% [%leaf node:leaf]
+ [%container node:container]
+ ==
+ --
+ ::
+ ++ inline
+ |%
+ :: A single inline element
+ ++ element $+ inline-element
+ $@ ~
+ $%(escape entity code hardbrk softbrk text emphasis strong link image autolink html)
+ ::
+ :: Any amount of elements
+ ++ contents (list element)
+ ::
+ :: -----------------------
+ :: List of inline elements
+ :: -----------------------
+ ::
+ :: Backslash-escaped character
+ +$ escape [%escape char=@t]
+ ::
+ :: HTML-entity
+ +$ entity [%entity code=@t]
+ ::
+ :: Code span (inline code). Interpreted literally, cannot have nested elements.
+ :: Can be enclosed by any amount of backticks on each side, >= 1. Must be balanced.
+ +$ code [%code-span num-backticks=@ text=@t]
+ ::
+ :: Line break
+ +$ hardbrk [%line-break ~]
+ ::
+ :: Soft line break: a newline in the source code, will be rendered as a single space
+ +$ softbrk [%soft-line-break ~]
+ ::
+ :: Text: Just text
+ +$ text [%text text=@t]
+ ::
+ :: Emphasis and strong emphasis
+ :: Can use either tar "*" or cab "_" as the emphasis character.
+ :: Can have nested inline elements.
+ +$ emphasis [%emphasis emphasis-char=@t =contents]
+ +$ strong [%strong emphasis-char=@t =contents]
+ ::
+ :: Link
+ +$ link [%link =contents =target:ln]
+ ::
+ :: Images
+ +$ image [%image alt-text=@t =target:ln]
+ ::
+ :: Autolink: a link that's just itself, surrounded by "<...>"
+ +$ autolink [%autolink text=@t]
+ ::
+ :: HTML
+ +$ html [%html text=@t]
+ --
+ ::
+ :: Leaf nodes: non-nested (i.e., terminal) nodes
+ ++ leaf
+ |%
+ ++ node $+ leaf-node
+ $@ ~
+ $%(heading break codeblk-indent codeblk-fenced html link-ref-def table paragraph blank-line)
+ ::
+ :: Heading, either setext or ATX style
+ +$ heading [%heading style=?(%setext %atx) level=@ =contents:inline]
+ ::
+ :: Thematic break (horizontal line)
+ :: Consists of at least 3 repetitions of either hep '-', cab '_', or tar '*'
+ +$ break [%break char=@t char-count=@]
+ ::
+ :: Indentation-based code block: indented 4 spaces. Can include newlines and blank lines.
+ +$ codeblk-indent [%indent-codeblock text=@t]
+ ::
+ :: Fenced code block: begins and ends with 3+ repetitions of tic (`) or sig (~).
+ :: Can be indented up to 3 spaces.
+ +$ codeblk-fenced [%fenced-codeblock char=@t char-count=@ info-string=@t indent-level=@ text=@t]
+ ::
+ :: HTML
+ +$ html [%html text=@t]
+ ::
+ :: Link reference definition (defines a named link which can be referenced elsewhere)
+ +$ link-ref-def [%link-ref-definition label=@t =urlt:ln]
+ ::
+ :: Paragraph
+ +$ paragraph [%paragraph =contents:inline]
+ ::
+ :: Blank lines (not rendered, but lets user control aethetic layout of the source code)
+ +$ blank-line [%blank-line ~]
+ ::
+ :: Table (alignments: [l]eft, [r]ight, [c]enter, [n]one)
+ +$ table [%table widths=(list @) head=(list contents:inline) align=(list ?(%l %c %r %n)) rows=(list (list contents:inline))]
+ --
+ ::
+ :: Container node: can contain other nodes (either container or leaf).
+ ++ container
+ |%
+ ++ node $+ container-node
+ $@ ~
+ $%(block-quote ol ul tl)
+ ::
+ :: Block quote. Can be nested.
+ +$ block-quote [%block-quote =markdown]
+ ::
+ :: Ordered list: numbered based on first list item marker.
+ :: Marker char can be either dot '1. asdf' or par '1) asdf'
+ :: Can be indented up to 3 spaces
+ +$ ol [%ol indent-level=@ marker-char=@t start-num=@ contents=(list markdown)] :: is-tight=?
+ ::
+ :: Unordered list: bullet point list
+ :: Marker char can be either hep (-), lus (+) or tar (*)
+ :: Can be indented up to 3 spaces
+ +$ ul [%ul indent-level=@ marker-char=@t contents=(list markdown)] :: is-tight=?
+ ::
+ :: Task list: unordered list of tasks
+ :: Can be indented up to 3 spaces
+ +$ tl [%tl indent-level=@ marker-char=@t contents=(list [is-checked=? =markdown])] :: is-tight=?
+ --
+--
diff --git a/desk/sur/nostr.hoon b/desk/sur/nostr.hoon
new file mode 100644
index 0000000..78c00ab
--- /dev/null
+++ b/desk/sur/nostr.hoon
@@ -0,0 +1,47 @@
+|%
++$ keys [pub=@ priv=@]
++$ event
+$: id=@ux :: 32bytes
+ pubkey=@ux :: 32bytes
+ created-at=@ud :: seconds
+ kind=@ud
+ tags=(list tag)
+ content=@t
+ sig=@ux :: 64bytes
+==
++$ raw-event
+$: pubkey=@ux :: 32bytes
+ created-at=@ud :: seconds
+ kind=@ud
+ tags=(list tag)
+ content=@t
+==
++$ tag (list @t)
+:: $: key=@t
+:: value=@t
+:: rest=(list @t)
+:: ==
++$ user-meta :: NIP-1
+$: name=@t
+ about=@t
+ picture=@t
+ other=(map @t @t)
+==
+:: Relay comms
++$ filter
+$: ids=(list @ux)
+ authors=(list @ux)
+ kinds=(list @ud)
+ tag=(unit [key=@ values=(list @t)])
+ since=(unit @ud)
+ until=(unit @ud)
+ limit=(unit @ud)
+==
+++ shim
+ |%
+ ++ url 'http://localhost:8888/shim'
+ +$ get (list [relay=@t filters=(list filter)])
+ +$ post [=event relays=(list @t)]
+ +$ req $%([%get get] [%post post])
+ --
+--
diff --git a/desk/sur/nostril.hoon b/desk/sur/nostril.hoon
new file mode 100644
index 0000000..a1cc5ee
--- /dev/null
+++ b/desk/sur/nostril.hoon
@@ -0,0 +1,54 @@
+/- trill=trill-feed, nostr
+|%
++$ state state-0
++$ state-0
+ $: %0
+ :: nostr config
+ relays=(map @t (list event:nostr))
+ keys=(map @ux @ux) :: pubkey to privkey
+ :: own feed
+ feed=feed:trill
+ profiles=(map @ux user-meta:nostr)
+ following=(map @ux =feed:trill)
+ follow-graph=(map @ux (set follow))
+ :: TODO global feed somehow?
+
+ ==
++$ follow [pubkey=@ux name=@t relay=(unit @t)]
+++ default ^- state-0
+ =/ s *state-0
+ =/ l ~[['wss://relay.damus.io' ~] ['wss://nos.lol' ~]]
+ s(relays (malt l))
+
+++ ui
+ |%
+ +$ poke
+ $% [%fols fols-poke]
+ [%post post-poke]
+ :: [%reac reac-poke]
+ [%prof prof-poke]
+ [%keys keys-poke]
+ [%rela relay-poke]
+ ==
+ +$ post-poke
+ $% [%add pubkey=@ux content=@t]
+ [%rt id=@ux pubkey=@ux relay=@t] :: NIP-18
+ [%del pubkey=@ux]
+ ==
+ +$ fols-poke
+ $% [%add pubkey=@ux]
+ [%del pubkey=@ux]
+ ==
+ +$ prof-poke
+ $% [%add pubkey=@ux meta=user-meta:nostr]
+ [%del pubkey=@ux]
+ ==
+ +$ keys-poke
+ $% [%add ~]
+ [%del pubkey=@ux]
+ ==
+ +$ relay-poke
+ $% [%send host=@p id=@ relays=(list @t)]
+ ==
+ --
+--
diff --git a/desk/sur/spider.hoon b/desk/sur/spider.hoon
new file mode 100644
index 0000000..7c21268
--- /dev/null
+++ b/desk/sur/spider.hoon
@@ -0,0 +1,27 @@
+/+ libstrand=strand
+=, strand=strand:libstrand
+|%
++$ thread $-(vase shed:khan)
++$ input [=tid =cage]
++$ tid tid:strand
++$ bowl bowl:strand
++$ http-error
+ $? %bad-request :: 400
+ %forbidden :: 403
+ %nonexistent :: 404
+ %offline :: 504
+ ==
++$ start-args
+ $: parent=(unit tid)
+ use=(unit tid)
+ =beak
+ file=term
+ =vase
+ ==
++$ inline-args
+ $: parent=(unit tid)
+ use=(unit tid)
+ =beak
+ =shed:khan
+ ==
+--
diff --git a/desk/sur/trill/feed.hoon b/desk/sur/trill/feed.hoon
new file mode 100644
index 0000000..be7abb5
--- /dev/null
+++ b/desk/sur/trill/feed.hoon
@@ -0,0 +1,16 @@
+/- post=trill-post
+|%
++$ feeds (map ship feed)
++$ feed ((mop id:post post:post) gth)
++$ index (map @t (set pid:post))
+++ orm ((on id:post post:post) gth)
++$ full-graph ((mop id:post full-node:post) gth)
+++ form ((on id:post full-node:post) gth)
++$ global ((mop pid:post post:post) ggth)
+++ ggth |=([[ship a=time] [ship b=time]] (gth a b))
+++ gorm ((on pid:post post:post) ggth)
+
++$ cursor (unit @da)
++$ fc [=feed:feed start=cursor end=cursor]
++$ gc [mix=global:feed start=cursor end=cursor]
+--
diff --git a/desk/sur/trill/gate.hoon b/desk/sur/trill/gate.hoon
new file mode 100644
index 0000000..ddc0adb
--- /dev/null
+++ b/desk/sur/trill/gate.hoon
@@ -0,0 +1,26 @@
+|%
++$ gate
+$: =lock
+ begs=(set @p) :: follow requests
+ post-begs=(set post-beg) :: read requests for specific posts
+ :: TODO include whole thread?
+ mute=lock :: mute list to prevent request spamming
+ backlog=$~(50 @) :: size of backlog sent to followers by default
+==
++$ post-beg [=ship id=@da]
+
++$ lock
+$: rank=[caveats=(set rank:title) locked=_| public=?]
+ luk=[caveats=(set ship) locked=_| public=?]
+ ship=[caveats=(set ship) locked=_| public=?]
+ tags=[caveats=(set @t) locked=_| public=?]
+ custom=[fn=(unit $-(@p ?)) public=?]
+==
++$ change
+$% [%set-rank set=(set rank:title) locked=? public=?]
+ [%set-luk set=(set ship) locked=? public=?]
+ [%set-ship set=(set ship) locked=? public=?]
+ [%set-tags set=(set @t) locked=? public=?]
+ [%set-custom term] :: Handle this and set in hoon
+==
+--
diff --git a/desk/sur/trill/post.hoon b/desk/sur/trill/post.hoon
new file mode 100644
index 0000000..97912ce
--- /dev/null
+++ b/desk/sur/trill/post.hoon
@@ -0,0 +1,121 @@
+/- gate=trill-gate
+|%
++$ id @da
++$ pid [=ship =id]
+:: anon post type?
++$ tag @t
++$ post
+ $: =id
+ host=ship
+ author=ship
+ thread=id
+ parent=(unit id)
+ children=(set id)
+ contents=content-map
+ read=lock:gate
+ write=lock:gate
+ =engagement
+ =hash :: We'll reuse this for the Nostr pubkey
+ =signature
+ tags=(set tag) ::TODO make sure it's not infinite
+ ==
++$ sent-post
+ $: host=ship
+ author=ship
+ thread=(unit id)
+ parent=(unit id)
+ contents=content-list
+ read=lock:gate
+ write=lock:gate
+ tags=(set tag)
+ ==
++$ full-node
+ $: =id
+ host=ship
+ author=ship
+ thread=id
+ parent=(unit id)
+ children=internal-graph
+ contents=content-map
+ read=lock:gate
+ write=lock:gate
+ =engagement
+ =hash
+ =signature
+ tags=(set tag)
+ ==
+:: recursive types crash
++$ internal-graph
+ $~ [%empty ~]
+ $% [%full p=full-graph]
+ [%empty ~]
+ ==
++$ full-graph ((mop id full-node) gth)
+++ form ((on id full-node) gth)
+:: from post:graph-store
+:: +sham (half sha-256) hash of +validated-portion
++$ hash @uvH
+::
++$ signature [p=@uvH q=ship r=life]
++$ engagement
+ $:
+ =reacts
+ quoted=(set signed-pid)
+ shared=(set signed-pid)
+ ==
++$ signed-pid [=signature =pid]
++$ react @t
++$ reacts (map ship signed-react-2)
++$ signed-react [=pid author=ship =react =signature]
++$ signed-react-2 [p=react q=signature]
+
+
++$ content-map ((mop time content-list) gth)
+++ corm ((on time content-list) gth)
+:: +$ content-list contents:contents-1
++$ content-list contents
++$ li content-list
++$ contents (list block)
++$ paragraph (list inline)
++$ heading $?(%h1 %h2 %h3 %h4 %h5 %h6)
++$ block
+ $% [%paragraph p=(list inline)]
+ [%blockquote p=(list inline)]
+ [%table rows=(list (list contents))]
+ [%heading p=cord q=heading]
+ [%list p=(list inline) ordered=?]
+ [%media =media]
+ [%codeblock code=cord lang=cord]
+ [%eval hoon=cord]
+ ::
+ [%ref type=term =ship =path]
+ ::
+ [%json origin=term content=@t]
+ :: TODO get rid of this. should be a ref
+ [%poll id=@da]
+ ==
++$ poll-opt [option=cord votes=@]
++$ media
+ $% [%images p=(list cord)]
+ [%video p=cord]
+ [%audio p=cord]
+ ==
++$ inline
+ $% [%text p=cord]
+ [%italic p=cord]
+ [%bold p=cord]
+ [%strike p=cord]
+ [%codespan p=cord]
+ [%link href=cord show=cord]
+ [%break ~]
+ :: not strictly markdown
+ [%underline p=cord]
+ [%sup p=cord]
+ [%sub p=cord]
+ [%ruby p=cord q=cord]
+ :: custom types
+ [%ship p=ship]
+ :: TODO
+ :: [%date p=@da]
+ ==
+--
diff --git a/desk/sys.kelvin b/desk/sys.kelvin
new file mode 100644
index 0000000..1ec239e
--- /dev/null
+++ b/desk/sys.kelvin
@@ -0,0 +1 @@
+[%zuse 410]
diff --git a/desk/ted/fetch.hoon b/desk/ted/fetch.hoon
new file mode 100644
index 0000000..6444ca7
--- /dev/null
+++ b/desk/ted/fetch.hoon
@@ -0,0 +1,24 @@
+/- spider
+/+ strandio
+=, strand=strand:spider
+=, dejs-soft:format
+=, strand-fail=strand-fail:libstrand:spider
+^- thread:spider
+|= arg=vase
+ =/ request ;;(request:http q.arg)
+ ~& req=request
+ =/ m (strand ,vase) ^- form:m
+ :: =/ m (strand ,json) ^- form:m
+ ;< ~ bind:m (send-request:strandio request)
+ ;< res=client-response:iris bind:m take-client-response:strandio
+ ?. ?=(%finished -.res) (strand-fail:strand %no-body ~)
+ :: =/ headers headers.response-header.res
+ :: =/ redirect (get-header:http 'location' headers)
+ :: ?^ redirect (pure:m [%| u.redirect])
+
+ ::
+ ?~ full-file.res (strand-fail:strand %no-body ~)
+ =/ body=@t q.data.u.full-file.res
+ :: ~& resbody=body
+ =/ json [%s body]
+ (pure:m !>(json))
diff --git a/desk/web/assets/apple-touch-icon.png b/desk/web/assets/apple-touch-icon.png
new file mode 100644
index 0000000..f77c873
--- /dev/null
+++ b/desk/web/assets/apple-touch-icon.png
Binary files differ
diff --git a/desk/web/assets/favicon-16x16.png b/desk/web/assets/favicon-16x16.png
new file mode 100644
index 0000000..6ab2451
--- /dev/null
+++ b/desk/web/assets/favicon-16x16.png
Binary files differ
diff --git a/desk/web/assets/favicon-32x32.png b/desk/web/assets/favicon-32x32.png
new file mode 100644
index 0000000..b81291b
--- /dev/null
+++ b/desk/web/assets/favicon-32x32.png
Binary files differ
diff --git a/desk/web/assets/favicon.ico b/desk/web/assets/favicon.ico
new file mode 100644
index 0000000..0369d8a
--- /dev/null
+++ b/desk/web/assets/favicon.ico
Binary files differ
diff --git a/desk/web/assets/script.js b/desk/web/assets/script.js
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/desk/web/assets/script.js
diff --git a/desk/web/assets/site.webmanifest b/desk/web/assets/site.webmanifest
new file mode 100644
index 0000000..45dc8a2
--- /dev/null
+++ b/desk/web/assets/site.webmanifest
@@ -0,0 +1 @@
+{"name":"","short_name":"","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"} \ No newline at end of file
diff --git a/desk/web/assets/spinner.svg b/desk/web/assets/spinner.svg
new file mode 100644
index 0000000..a6763ca
--- /dev/null
+++ b/desk/web/assets/spinner.svg
@@ -0,0 +1 @@
+<svg width="24" height="24" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><style>.spinner_0XTQ{transform-origin:center;animation:spinner_y6GP .75s linear infinite}@keyframes spinner_y6GP{100%{transform:rotate(360deg)}}</style><path class="spinner_0XTQ" d="M12,23a9.63,9.63,0,0,1-8-9.5,9.51,9.51,0,0,1,6.79-9.1A1.66,1.66,0,0,0,12,2.81h0a1.67,1.67,0,0,0-1.94-1.64A11,11,0,0,0,12,23Z"/></svg> \ No newline at end of file
diff --git a/desk/web/assets/style.css b/desk/web/assets/style.css
new file mode 100644
index 0000000..9b8f0e5
--- /dev/null
+++ b/desk/web/assets/style.css
@@ -0,0 +1,415 @@
+@font-face {
+ font-family: Urbit Sans;
+ src: url(https://media.urbit.org/fonts/UrbitSans/UrbitSansVFWeb-Regular.woff2) format("woff2");
+ font-weight: 100 700;
+ font-style: normal
+}
+
+@font-face {
+ font-family: "Urbit Serif Italic";
+ src: url(https://media.urbit.org/fonts/UrbitSerifItalic/UrbitSerifItalic-UltraThin.otf);
+ font-weight: 100;
+ font-style: normal
+}
+
+@font-face {
+ font-family: "Urbit Serif Italic";
+ src: url(https://media.urbit.org/fonts/UrbitSerifItalic/UrbitSerifItalic-Thin.otf);
+ font-weight: 200;
+ font-style: normal
+}
+
+@font-face {
+ font-family: "Urbit Serif Italic";
+ src: url(https://media.urbit.org/fonts/UrbitSerifItalic/UrbitSerifItalic-Light.otf);
+ font-weight: 300;
+ font-style: normal
+}
+
+@font-face {
+ font-family: "Urbit Serif Italic";
+ src: url(https://media.urbit.org/fonts/UrbitSerifItalic/UrbitSerifItalic-Regular.otf);
+ font-weight: 400;
+ font-style: normal
+}
+
+@font-face {
+ font-family: "Urbit Serif Italic";
+ src: url(https://media.urbit.org/fonts/UrbitSerifItalic/UrbitSerifItalic-Medium.otf);
+ font-weight: 500;
+ font-style: normal
+}
+
+@font-face {
+ font-family: "Urbit Serif Italic";
+ src: url(https://media.urbit.org/fonts/UrbitSerifItalic/UrbitSerifItalic-SemiBold.otf);
+ font-weight: 600;
+ font-style: normal
+}
+
+@font-face {
+ font-family: "Urbit Serif Italic";
+ src: url(https://media.urbit.org/fonts/UrbitSerifItalic/UrbitSerifItalic-Bold.otf);
+ font-weight: 700;
+ font-style: normal
+}
+
+body,
+html {
+ font-family: Urbit Sans
+}
+
+/* urbit intranav color scheme */
+.wit {
+ --muted: #14140F;
+ --primary: #F8FAF8;
+}
+/* fdn intranav color scheme */
+.mos {
+ --muted: #5A5A55;
+ --primary: #C3CDC3;
+}
+/* roadmap intranav color scheme */
+.mos-light {
+ --muted: #A3ABA3;
+ --primary: #54544F;
+}
+/* docs intranav color scheme */
+.blu {
+ --muted: #5A5A6E;
+ --primary: #A0DCE6;
+}
+/* network explorer intranav color scheme */
+.gry {
+ --muted: #141A14;
+ --primary: #C8C8C8
+}
+
+/* utility */
+.f {
+ display: flex;
+}
+
+.fs {
+ display: flex;
+ justify-content: space-between;
+}
+
+.g1 {
+ gap: 0.5rem;
+}
+
+.g2 {
+ gap: 1rem;
+}
+.cp{
+ cursor: pointer;
+}
+.tc{
+ text-align:center;
+}
+
+/* base */
+
+:root {
+ --black: #141A14;
+ --white: #FFFFFF;
+ --primary: #FFF450;
+ --muted: #B9B13D;
+}
+
+
+body {
+ background-color: var(--primary);
+ color: var(--black);
+ margin: 0;
+ padding: 0;
+ min-height: 100vh;
+ display: flex;
+ flex-direction: column;
+}
+
+a {
+ color: inherit;
+ text-decoration: none;
+}
+
+/* nav */
+#topnav {
+ height: 63px;
+
+ & #login-div {
+ display: flex;
+ align-items: center;
+ text-decoration: underline;
+ margin-right: 2rem;
+ font-size: 18px;
+ line-height: 24.12px;
+ /* font-weight: 600; */
+ }
+}
+
+#nav-main {
+ background-color: var(--black);
+ color: var(--primary);
+ cursor: pointer;
+ font-size: 18px;
+ line-height: 24.12px;
+ /* font-weight: 600; */
+ text-align: center;
+ display: flex;
+ align-items: center;
+ gap: 1rem;
+ padding: 0 1rem;
+}
+
+#nav-links {
+ display: flex;
+ align-items: center;
+ font-size: 18px;
+ line-height: 24.12px;
+ /* font-weight: 600; */
+ text-align: center;
+ gap: 1rem;
+
+ & a {
+ opacity: 0.5;
+ }
+
+ & .active {
+ opacity: 1
+ }
+}
+
+
+/* index */
+main {
+ padding: 1rem 2rem;
+ flex-grow: 1;
+ overflow: auto;
+}
+
+#index-top {
+ margin-bottom: 1.5rem;
+ font-size: 1.4rem;
+ font-weight: 600;
+
+ div {
+ opacity: 0.5;
+ cursor: pointer;
+ }
+
+ & .active {
+ opacity: 1;
+ }
+}
+
+.thread-preview {
+ padding: 0.5rem 0;
+
+ border-bottom: 2px solid black;
+
+ &:first-child {
+ border-top: 2px solid black;
+ }
+
+ & .num {
+ font-size: 1.5rem;
+ }
+
+ & a {
+ text-decoration: none;
+ }
+ & .preview{
+ max-width: 100%;
+ }
+ & .title {
+ font-weight: 600;
+ font-size: 25px;
+ line-height: 33px;
+ }
+ & .title-text{
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ }
+
+ & .out-link {
+ font-weight: 600;
+ font-size: 20px;
+
+ & .arrow {
+ margin-left: 0.3rem;
+ font-size: 1.3rem;
+ }
+ }
+
+ & .meta {
+ opacity: 0.5;
+ & .upvote-button, & .downvote-button{
+
+ }
+ }
+
+}
+
+.moar {
+ text-decoration: underline;
+ font-size: 20px;
+ margin-top: 1rem;
+ display: block;
+}
+
+.white{
+ background-color: var(--white);
+}
+/* thread page */
+#thread-main{
+ background-color: var(--white);
+ & h1{
+ margin-top: 0.3rem;
+ }
+ & ul{
+ display: block;
+ list-style-image: none;
+ list-style-position: outside;
+ list-style-type: none;
+ padding: 0;
+ & li{
+ margin-bottom: 1rem;
+ }
+ }
+ & .nested{
+ padding-left: 2rem !important;
+ }
+ & .comment{
+ & img{
+ max-width: 60%;
+ display: block;
+ margin: 1rem auto;
+ }
+ & .comment-proper{
+ margin-top: 0.5rem;
+ }
+ & .content{
+ font-weight: 600;
+ margin: 1rem 0;
+ & p{
+ margin: 0.2rem 0;
+ }
+ }
+ }
+}
+.red{
+ color: red;
+}
+.green {
+ color: green;
+}
+.tally{
+ font-weight: 600;
+}
+.uln{
+ text-decoration: underline;
+ cursor: pointer;
+}
+.return-link{
+ display: block;
+ margin-bottom: 2rem;
+}
+#og{
+ border: 1px solid var(--black);
+ border-radius: 0.5rem;
+ & img{
+ width: 100%;
+ max-height: 500px;
+ }
+}
+#link-url{
+ padding: 0.5rem 1rem;
+}
+#thread-composer{
+ & input{
+ display: block;
+ height: 2rem;
+ width: 100%;
+ margin: 1rem 0;
+ }
+}
+#comment-composer{
+ margin-top: 3rem;
+ margin-bottom: 1rem;
+
+ padding: 0.5rem 1rem;
+ border: 1px solid var(--black);
+ border-radius: 0.5rem;
+}
+#composer-proper{
+ margin: 1rem;
+ padding: 1rem;
+ & textarea{
+ width: 100%;
+ height: 200px;
+ margin-bottom: 0.5rem;
+ resize: none;
+ }
+}
+#login-page{
+ & form{
+ display: block;
+ width: 50%;
+ margin: 2rem auto;
+
+ & input{
+ display: block;
+ width: 30ch;
+ padding: 0.4rem;
+ height: 2rem;
+ margin: 2rem auto;
+ }
+ & button{
+ display: block;
+ margin: auto;
+ font-size: 1.2rem;
+ }
+ }
+}
+#sigil-img{
+ margin: 1rem auto !important;
+}
+#user-page{
+ & *{
+ margin: auto;
+ }
+ & #main{
+ width: 50%;
+ }
+}
+#logout{
+ display: block;
+ margin: 2rem auto;
+ font-size: 1.2rem;
+}
+button, .button{
+ border: 1px solid var(--black);
+ background: none;
+ padding: 0.5rem;
+ width: max-content;
+}
+
+.footer {
+ /* height: 63px; */
+ /* display: flex; */
+ /* position: fixed; */
+ left: 0;
+ bottom: 0;
+ /* width: 100%; */
+ background-color: none;
+ padding: 0.5rem;
+ color: #141A14;
+ text-align: right;
+ margin-right: 2rem;
+ font-size: 20px;
+ line-height: 23px;
+ font-weight: 600;
+}
diff --git a/desk/web/components/components.hoon b/desk/web/components/components.hoon
new file mode 100644
index 0000000..ced005e
--- /dev/null
+++ b/desk/web/components/components.hoon
@@ -0,0 +1,3 @@
+|%
+++ lol %lol
+--
diff --git a/desk/web/components/navbar.hoon b/desk/web/components/navbar.hoon
new file mode 100644
index 0000000..46b93d4
--- /dev/null
+++ b/desk/web/components/navbar.hoon
@@ -0,0 +1,54 @@
+/- sur=nostril
+/= sig /web/components/sigil/sigil
+::
+|_ [=state:sur =bowl:gall]
+++ new-post-link
+ ;+ ;a/"/nostril/add":"new post"
+++ sigil
+ :: ;+ (sig(size 48) src.bowl)
+ :: =/ =ship
+ :: ?+ (clan:title (~(gut by sessions.state) src.bowl (dec (bex 128))))
+ :: !!
+ :: %czar ?:((gte (bex 64) src.bowl) src.bowl (~(got by sessions.state) src.bowl))
+ :: %king ?:((gte (bex 64) src.bowl) src.bowl (~(got by sessions.state) src.bowl))
+ :: %duke ?:((gte (bex 64) src.bowl) src.bowl (~(got by sessions.state) src.bowl))
+ :: %earl ?:((gte (bex 64) src.bowl) src.bowl (~(got by sessions.state) src.bowl))
+ :: ==
+ =/ ship src.bowl
+ =/ p (scow %p ship)
+ ;div.f.g2
+ ;* new-post-link
+ ;a/"/forum/usr/{p}":"{p}"
+ ==
+++ $
+ ;nav#topnav.fs.g2
+ ;div.f.g2
+ ;div#nav-main.fs
+ ;a/"https://urbitsystems.tech/"(class "lg:relative flex h-full items-center bg-black w-1/2 lg:w-[14.5rem] xl:w-64 type-ui"):"~ Technical Journal"
+ ;div#nav-dropdown:"↓"
+ ==
+ ;div#nav-links
+ ;a/"https://urbitsystems.tech/information":"Information"
+ ;a.active/"/forum":"Forum"
+ ==
+ ==
+ ;div#login-div
+ ;+ sigil
+ ==
+ ;script:"{script}"
+ ==
+++ script
+ ^~
+ %- trip
+'''
+ async function setSigil(){
+ console.log("setting sigil")
+ const div = document.getElementById("login-div");
+ const res = await fetch("/forum/f/sigil");
+ const t = await res.text();
+ console.log("sigil", t);
+ if (t) div.innerHTML = t;
+ }
+ setSigil();
+'''
+--
diff --git a/desk/web/components/post-text.hoon b/desk/web/components/post-text.hoon
new file mode 100644
index 0000000..f4b574f
--- /dev/null
+++ b/desk/web/components/post-text.hoon
@@ -0,0 +1,134 @@
+/- tp=post
+/+ sr=sortug
+|%
+++ content
+ |= c=content-list:tp
+ ^- marl
+ (turn c block)
+::
+++ block
+ |= b=block:tp
+ ^- manx
+ ?+ -.b ;p;
+ %paragraph (pg +.b)
+ %blockquote (bq +.b)
+ %heading (heading +.b)
+ %list (htmlist +.b)
+ %media (media +.b)
+ %codeblock (codeblock +.b)
+ %eval (eval +.b)
+ ==
+++ eval
+ |= txt=@t
+ ^- manx
+ :: +ream can crash if the cord is wrong, so soften instead
+ =/ uhoon (rush txt vest)
+ ?~ uhoon ;p:"The hoon you tried to run ({(trip txt)}) is invalid."
+ =/ run (mule |.((slap !>(..zuse) u.uhoon)))
+ ?: ?=(%.n -.run) :: if virtualization fails get a (list tank)
+ ;p
+ ;span:"Evaluation of {(trip txt)} failed:"
+ ;br;
+ ;* %+ turn p.run |= t=tank ;span:"{~(ram re t)}"
+ ==
+ ;p:"{(text p.run)}"
+++ pg
+ |= l=(list inline:tp)
+ ^- manx
+ ;p
+ ;* %+ turn l inline
+ ==
+++ bq
+ |= l=(list inline:tp)
+ ^- manx
+ ;blockquote
+ ;* %+ turn l inline
+ ==
+++ htmlist
+ |= [l=(list content-list:tp) ordered=?]
+ ?: ordered
+ ;ol
+ ;* %+ turn l li
+ ==
+ ;ul
+ ;* %+ turn l li
+ ==
+++ li
+ |= l=content-list:tp ^- manx
+ ;li
+ ;* (turn l block)
+ ==
+++ media
+ |= m=media:tp
+ ^- manx
+ ?- -.m
+ %video ;video@"{(trip p.m)}";
+ %audio ;audio@"{(trip p.m)}";
+ %images ;div.images
+ ;* %+ turn p.m
+ |= [url=@t caption=@t]
+ ;img@"{(trip url)}"(alt (trip caption));
+ ==
+ ==
+++ codeblock
+ |= [code=@t lang=@t] :: TODO lang suff
+ ;pre
+ ;code:"{(trip code)}"
+ ==
+++ heading
+ |= [pp=@t q=@]
+ ^- manx
+ =/ p (trip pp)
+ ?: .=(1 q) ;h1:"{p}"
+ ?: .=(2 q) ;h2:"{p}"
+ ?: .=(3 q) ;h3:"{p}"
+ ?: .=(4 q) ;h4:"{p}"
+ ?: .=(5 q) ;h5:"{p}"
+ ?: .=(6 q) ;h6:"{p}"
+ ;p:""
+++ inline
+ |= l=inline:tp
+ ^- manx
+ ?+ -.l ;span;
+ %text (parse-text p.l)
+ %italic ;i:"{(trip p.l)}"
+ %bold ;strong:"{(trip p.l)}"
+ :: %strike ;del:"{(trip p.l)}"
+ %ship ;span.ship:"{(trip (scot %p p.l))}"
+ %codespan ;code:"{(trip p.l)}"
+ %break ;br;
+ %img ;a/"{(trip src.l)}"
+ ;img@"{(trip src.l)}"(alt (trip alt.l));
+ ==
+ %link ?. (is-image:parsing:sr href.l)
+ ;a/"{(trip href.l)}"(target "_blank"):"{(trip show.l)}"
+ ;a/"{(trip href.l)}"
+ =target "_blank"
+ ;img@"{(trip href.l)}"(alt (trip show.l));
+ ==
+ ==
+++ parse-text
+ |= txt=@t
+ ^- manx
+ =/ tpe (trip txt)
+ =/ youtube (rush txt youtube:parsing:sr)
+ ?^ youtube
+ :: ;a/"{tpe}"
+ :: ;img@"https://i.ytimg.com/vi/{u.youtube}/hqdefault.jpg";
+ :: ==
+ ;iframe.youtube-frame@"https://www.youtube.com/embed/{u.youtube}";
+ =/ twatter-status (rush txt twatter:parsing:sr)
+ ?^ twatter-status
+ ;div :: goddamn twatter embeds insert themselves as last child
+ ;a.parsed-twatter(status u.twatter-status):"{tpe}"
+ ==
+ =/ trimmed (rush txt trim:parsing:sr)
+ ?~ trimmed ~& parsing-error=txt ;span.parsing-error;
+ =/ link=(unit purl:eyre) (rust u.trimmed link:parsing:sr)
+ ?^ link
+ ?^ p.q.u.link
+ ?: (is-img:parsing:sr u.p.q.u.link) ;img@"{u.trimmed}";
+ ;a.parsed-link/"{tpe}"(target "_blank"):"{tpe}" :: normal link
+ ;a.parsed-link/"{tpe}"(target "_blank"):"{tpe}" :: normal link
+ ;span:"{tpe}"
+--
diff --git a/desk/web/components/sigil/sigil.hoon b/desk/web/components/sigil/sigil.hoon
new file mode 100644
index 0000000..cee33a0
--- /dev/null
+++ b/desk/web/components/sigil/sigil.hoon
@@ -0,0 +1,227 @@
+:: sigil: @p svg generation
+::
+:: usage: do a named import, then invoke as a function:
+:: (sigil ~zod)
+::
+:: optionally modify configuration parameters:
+:: %. ~paldev
+:: %_ sigil
+:: size 25
+:: fg "black"
+:: bg "#2aa779"
+:: margin |
+:: icon &
+:: ==
+::
+::NOTE svg construction logic is coupled to the symbols definitions.
+:: the symbols' elements assume they live in a space of 128x128.
+:: what we do here is assume an svg _canvas_ of 128x128, draw the
+:: symbols at their original sizes, and then scale them down to fit.
+::
+/= sigil-symbols /web/components/sigil/symbols
+::
+:: config
+::
+=/ fg=tape "white"
+=/ bg=tape "black"
+=/ size=@ud 128
+=/ margin=? &
+=/ icon=? |
+::
+::
+~% %sigil ..part ~
+=/ who=ship ~zod
+=/ syc=@ud 1
+|^ |= =ship
+ ^- manx
+ ::
+ =. who ship
+ =/ syz (simp who)
+ =. syc (lent syz)
+ :: shift the sigil to account for the margin
+ :: scale the sigil to account for the amount of symbols
+ ::
+ =/ sire=@rd (sun:rd size)
+ =/ tr=tape
+ ::TODO render transform inside +sigil:svg?
+ %+ transform:svg
+ ?. margin ~
+ =+ grid:pos
+ `[(gird:pos x) (gird:pos y)]
+ `span:pos
+ ::
+ =/ sw=@rd ::TODO
+ ?: icon .~0.8 ::TODO scale with size?
+ (add:rd .~0.33 (div:rd sire .~128))
+ ::
+ %- outer:svg
+ %+ sigil:svg
+ [tr sw]
+ (symbols:svg syz)
+::
+++ pos
+ |%
+ ++ span :: symbol scale (relative to full canvas)
+ ^- @rd
+ ::TODO accounting for margin here feels a bit ugly?
+ ?+ (max grid) !!
+ %1 ?:(margin .~0.4 .~1)
+ %2 ?:(margin .~0.4 .~0.5)
+ %4 ?:(margin .~0.2 .~0.25)
+ ==
+ ::
+ ++ grid :: size in symbols
+ ^- [x=@ud y=@ud]
+ ?+ syc !!
+ %16 [4 4]
+ %8 [4 4]
+ %4 [2 2]
+ %2 [2 1]
+ %1 [1 1]
+ ==
+ ::
+ ++ gird :: calculate margin
+ |= n=@ud
+ ^- @rd
+ =- (div:rd - .~2) :: / both sides
+ %+ sub:rd .~128 :: canvas size -
+ %+ mul:rd (sun:rd n) :: symbols *
+ %+ mul:rd span:pos :: symbol scale *
+ .~128 :: symbol size
+ ::
+ ++ plan :: as position on symbol grid
+ |= i=@ud
+ ^- [x=@ud y=@ud]
+ ?+ [syc i] !!
+ [%16 *] [(mod i 4) (div i 4)]
+ ::
+ [%8 %0] [0 0]
+ [%8 %1] [3 0]
+ [%8 %2] [0 3]
+ [%8 %3] [3 3]
+ [%8 %4] [1 1]
+ [%8 %5] [2 1]
+ [%8 %6] [1 2]
+ [%8 %7] [2 2]
+ ::
+ [%4 *] [(mod i 2) (div i 2)]
+ [%2 *] [i 0]
+ [%1 *] [0 0]
+ ==
+ --
+::
+++ svg
+ |%
+ ++ outer
+ |= inner=manx
+ ^- manx
+ =/ s=tape ((d-co:co 1) size)
+ ;svg
+ =style "display: block; width: {s}px; height: {s}px;" :: prevent bottom margin on svg tag
+ =width s
+ =height s
+ =viewBox "0 0 128 128"
+ =version "1.1"
+ =xmlns "http://www.w3.org/2000/svg"
+ ::TODO additional attributes from config arg?
+ ;rect
+ =fill bg
+ =width "128"
+ =height "128";
+ ;+ inner
+ ==
+ ::
+ ::TODO should it be possible to get these svg elements out of this lib?
+ ++ sigil
+ |= [[tr=tape sw=@rd] symbols=(list manx)]
+ ^- manx
+ ;g
+ =transform tr
+ =stroke-width (say-rd sw)
+ =stroke-linecap "square"
+ =fill fg
+ =stroke bg
+ ::NOTE unfortunately, vector-effect cannot be inherited,
+ :: so it gets inlined in the symbol elements instead
+ :: =vector-effect "non-scaling-stroke"
+ ;* symbols
+ ==
+ ::
+ ++ symbols
+ |= noms=(list @t)
+ ^- (list manx)
+ =| i=@ud
+ =/ l=@ud (lent noms)
+ |-
+ ?~ noms ~
+ :_ $(noms t.noms, i +(i))
+ ::TODO exclude if both 0
+ =+ (plan:pos i)
+ ;g(transform (transform `[(sun:rd (mul x 128)) (sun:rd (mul y 128))] ~))
+ ;* =+ ((symbol i.noms) fg bg)
+ ?.(icon - (scag 1 -))
+ ==
+ ::
+ ++ symbol ~(got by sigil-symbols)
+ ::
+ ++ transform ::TODO take manx instead so we can omit attr entirely?
+ |= [translate=(unit [x=@rd y=@rd]) scale=(unit @rd)]
+ ^- tape
+ %- zing
+ ^- (list tape)
+ ::TODO make cleaner
+ =- ?: ?=(?(~ [* ~]) -) -
+ (join " " `(list tape)`-)
+ ^- (list tape)
+ :~ ?~ translate ~
+ ?: =([0 0] u.translate) ~
+ "translate({(say-rd x.u.translate)} {(say-rd y.u.translate)})"
+ ::
+ ?~ scale ~
+ "scale({(say-rd u.scale)})"
+ ==
+ --
+::
+++ simp
+ |= =ship
+ ^- (list @t)
+ :: split into phonemes
+ ::
+ =/ noms=(list @t)
+ =/ nom=@t
+ (rsh 3 (scot %p ship))
+ |- ?~ nom ~
+ |- ?: =('-' (end 3 nom))
+ $(nom (rsh 3 nom))
+ :- (end 3^3 nom)
+ ^$(nom (rsh 3^3 nom))
+ :: fill leading empties with 'zod'
+ ::
+ =/ left=@ud
+ =- (sub - (lent noms))
+ %- bex
+ ?- (clan:title ship)
+ %czar 0
+ %king 1
+ %duke 2
+ %earl 3
+ %pawn 4
+ ==
+ |-
+ ?: =(0 left) noms
+ $(noms ['zod' noms], left (dec left))
+::
+++ rd ~(. ^rd %n)
+++ say-rd
+ |= n=@rd
+ ^- tape
+ =/ =dn (drg:rd n)
+ ?> ?=(%d -.dn)
+ =/ [s=? m=@ud] (old:si e.dn)
+ =/ x=@ud (pow 10 m)
+ %+ weld
+ %- (d-co:co 1)
+ ?:(s (mul a.dn x) (div a.dn x))
+ ?: s ~
+ ['.' ((d-co:co m) (mod a.dn x))]
+--
diff --git a/desk/web/components/sigil/symbols.hoon b/desk/web/components/sigil/symbols.hoon
new file mode 100644
index 0000000..1131612
--- /dev/null
+++ b/desk/web/components/sigil/symbols.hoon
@@ -0,0 +1,14332 @@
+:: sigil-symbols: svg symbols for phonemes, for use in /lib/sigil
+::
+:: the map is keyed by phoneme cords and contains functions for
+:: generating lists of manxes based on fore- and background colors,
+:: intended to be wrapped up in an svg <g> for further processing.
+::
+:: shapes and default attributes sourced from:
+:: https://github.com/urbit/sigil-js/blob/fdea06f/src/index.json
+::
+::NOTE to reduce svg size, we exclude certain common/shared attributes.
+:: we expect the /lib/sigil to wrap these elements in a <g> which sets
+:: those attributes, letting them be inherited. they are as follows:
+:: =fill fg
+:: =stroke bg
+:: =stroke-linecap "square"
+:: =stroke-width
+:: we assume the defaults specified above, and only include those
+:: attributes below if they deviate from those. (this includes adding
+:: stroke="none" for elements whose original specification did not
+:: include a stroke.)
+:: unfortunately, the vector-effect attribute cannot be inherted by <g>
+:: children, so we have to inline it for every element here.
+:: for ease of change, we leave excluded attributes as comments here.
+::
+^~
+%- ~(gas by *(map cord $-([fg=tape bg=tape] (list manx))))
+:~
+ :- 'bac'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M0 0C0 70.6925 57.3075 128 128 128V0H0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "-0.0029152"
+ =x2 "127.983"
+ =y2 "127.986"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ;circle
+ =cx "16"
+ =cy "112"
+ =r "11.5"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ ;circle
+ =cx "16"
+ =cy "112"
+ =r "9"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ :: =stroke-width "2"
+ ==
+::
+ :- 'bal'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M0.0541 0C70.7217 0.0292317 128 57.3256 128 128C57.3177 128 0.0164917 70.7089 7.62806e-06 0.0305091C7.62851e-06 0.0203397 -4.44317e-10 0.01017 0 0H0.0541Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;circle
+ =cx "32"
+ =cy "32"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "32"
+ =cy "32"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ;line
+ =x1 "0.5"
+ =y1 "-0.5"
+ =x2 "181.5"
+ =y2 "-0.5"
+ =transform "matrix(-0.707107 0.707107 0.707107 0.707107 128.71 0)"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;line
+ =x1 "128"
+ =y1 "32.0072"
+ =x2 "32.7071"
+ =y2 "127.3"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;line
+ =x1 "128"
+ =y1 "64.0072"
+ =x2 "64.7071"
+ =y2 "127.3"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;line
+ =x1 "128"
+ =y1 "96.0072"
+ =x2 "96.7071"
+ =y2 "127.3"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ==
+::
+ :- 'ban'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M0 0C0 70.6925 57.3075 128 128 128V0H0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M128 0C128 70.6924 70.6924 128 -1.52588e-05 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'bar'
+ |= [fg=tape bg=tape]
+ :~ ;circle
+ =cx "64"
+ =cy "64"
+ =r "64"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M-0.00292969 0L127.997 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "16"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;circle
+ =cx "32"
+ =cy "32"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "32"
+ =cy "32"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'bat'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M0 0C0 70.6925 57.3075 128 128 128V0H0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M128 0C128 35.3462 99.3462 64 64 64C28.6538 64 0 35.3462 0 0"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'bec'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M128 128C128 57.3076 70.6925 6.18013e-06 1.11901e-05 0L0 128L128 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M-0.00280762 0L127.997 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;path
+ =fill-rule "evenodd"
+ =clip-rule "evenodd"
+ =stroke "none"
+ =d "M80 64C80 72.8366 72.8366 80 64 80C55.1634 80 48 72.8366 48 64C48 55.1634 55.1634 48 64 48C72.8366 48 80 55.1634 80 64ZM64 72C68.4183 72 72 68.4183 72 64C72 59.5817 68.4183 56 64 56C59.5817 56 56 59.5817 56 64C56 68.4183 59.5817 72 64 72Z"
+ =fill bg;
+ ==
+::
+ :- 'bel'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M0 127.946C0.0292286 57.2783 57.3256 3.08928e-06 128 0C128 70.6823 70.7089 127.984 0.0305092 128C0.0203397 128 0.01017 128 2.36469e-09 128L0 127.946Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "32"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'ben'
+ |= [fg=tape bg=tape]
+ :~ ;rect
+ =width "128"
+ =height "128"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "8"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;circle
+ =cx "32"
+ =cy "64"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "32"
+ =cy "64"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'bep'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M128 0C57.3075 8.42999e-07 -8.42999e-07 57.3075 0 128H128V0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M128 64C92.6538 64 64 92.6538 64 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'ber'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M64 128H0L5.59506e-06 0L64 5.59506e-06C99.3462 8.68512e-06 128 28.6538 128 64C128 99.3462 99.3462 128 64 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M96 0L96 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'bes'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M128 128C128 57.3076 70.6925 6.18013e-06 1.11901e-05 0L0 128L128 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M64 128C64 92.6538 35.3462 64 0 64"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M-0.00280762 0L127.997 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ==
+::
+ :- 'bet'
+ |= [fg=tape bg=tape]
+ :~ ;circle
+ =cx "64"
+ =cy "64"
+ =r "64"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "16.0036"
+ =y1 "15.9965"
+ =x2 "48.0036"
+ =y2 "47.9965"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'bex'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M64 128H0L5.59506e-06 0L64 5.59506e-06C99.3462 8.68512e-06 128 28.6538 128 64C128 99.3462 99.3462 128 64 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "16.0036"
+ =y1 "15.9965"
+ =x2 "48.0036"
+ =y2 "47.9965"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =fill-rule "evenodd"
+ =clip-rule "evenodd"
+ =stroke "none"
+ =d "M80 64C80 72.8366 72.8366 80 64 80C55.1634 80 48 72.8366 48 64C48 55.1634 55.1634 48 64 48C72.8366 48 80 55.1634 80 64ZM64 72C68.4183 72 72 68.4183 72 64C72 59.5817 68.4183 56 64 56C59.5817 56 56 59.5817 56 64C56 68.4183 59.5817 72 64 72Z"
+ =fill bg;
+ ==
+::
+ :- 'bic'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M0 0C0 70.6925 57.3075 128 128 128V0H0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M128 96C74.9807 96 32 53.0193 32 -4.19629e-06"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'bid'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M0 0C0 70.6925 57.3075 128 128 128V0H0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M32 0C32 70.6925 74.9807 128 128 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M128 64L0 64"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'bil'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M64 0H128V128H64C28.6538 128 0 99.3462 0 64C0 28.6538 28.6538 0 64 0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "80.0035"
+ =y1 "79.9965"
+ =x2 "112.004"
+ =y2 "111.997"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =fill-rule "evenodd"
+ =clip-rule "evenodd"
+ =stroke "none"
+ =d "M80 64C80 72.8366 72.8366 80 64 80C55.1634 80 48 72.8366 48 64C48 55.1634 55.1634 48 64 48C72.8366 48 80 55.1634 80 64ZM64 72C68.4183 72 72 68.4183 72 64C72 59.5817 68.4183 56 64 56C59.5817 56 56 59.5817 56 64C56 68.4183 59.5817 72 64 72Z"
+ =fill bg;
+ ==
+::
+ :- 'bin'
+ |= [fg=tape bg=tape]
+ :~ ;rect
+ =width "128"
+ =height "128"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ==
+::
+ :- 'bis'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M0 0C0 70.6925 57.3075 128 128 128V0H0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "128"
+ =y1 "64"
+ =x2 "-8.87604e-09"
+ =y2 "64"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;line
+ =x1 "128"
+ =y1 "96"
+ =x2 "-8.87604e-09"
+ =y2 "96"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;line
+ =x1 "128"
+ =y1 "32"
+ =x2 "-8.87604e-09"
+ =y2 "32"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'bit'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M0.0541 0C70.7217 0.0292317 128 57.3256 128 128C57.3177 128 0.0164917 70.7089 7.62806e-06 0.0305091C7.62851e-06 0.0203397 -4.44317e-10 0.01017 0 0H0.0541Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M128 0L0 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'bol'
+ |= [fg=tape bg=tape]
+ :~ ;circle
+ =cx "64"
+ =cy "64"
+ =r "64"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "48"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;line
+ =x1 "128"
+ =y1 "64"
+ =x2 "-4.37114e-08"
+ =y2 "64"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'bon'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M128 0C57.3075 8.42999e-07 -8.42999e-07 57.3075 0 128H128V0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M128 128C92.6538 128 64 99.3462 64 64C64 28.6538 92.6538 4.215e-07 128 0"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'bor'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M64 0H128V128H64C28.6538 128 0 99.3462 0 64C0 28.6538 28.6538 0 64 0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "-0.0029152"
+ =x2 "127.983"
+ =y2 "127.986"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;path
+ =d "M0 128C4.63574e-06 92.6489 14.3309 60.6449 37.5 37.4807"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M32 128C32 101.492 42.7436 77.4939 60.1138 60.1217"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M64 128C64 110.328 71.1626 94.3287 82.7432 82.7471"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M95.6284 128C95.6284 119.164 99.2097 111.164 105 105.374"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'bos'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M0 0C0 70.6925 57.3075 128 128 128V0H0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "-0.0029152"
+ =x2 "127.983"
+ =y2 "127.986"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;circle
+ =cx "32"
+ =cy "32"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "32"
+ =cy "32"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'bot'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M64 0H128V128H64C28.6538 128 0 99.3462 0 64C0 28.6538 28.6538 0 64 0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "32"
+ =y1 "2.18557e-08"
+ =x2 "32"
+ =y2 "128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;circle
+ =cx "32"
+ =cy "96"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "32"
+ =cy "96"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ;circle
+ =cx "32"
+ =cy "32"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "32"
+ =cy "32"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'bud'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M128 128C128 57.3076 70.6925 6.18013e-06 1.11901e-05 0L0 128L128 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M16 64C16 90.5097 37.4903 112 64 112"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;circle
+ =cx "16"
+ =cy "64"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "16"
+ =cy "64"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'bur'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M5.59506e-06 128C70.6925 128 128 70.6925 128 0L0 5.59506e-06L5.59506e-06 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M7.37542e-06 -3.56072e-06C1.19529e-06 70.6924 57.3075 128 128 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M128 0L0 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ==
+::
+ :- 'bus'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M128 128C128 57.3076 70.6925 6.18013e-06 1.11901e-05 0L0 128L128 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M32 128C32 110.327 17.6731 96 0 96"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M-0.00292969 0L127.997 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ==
+::
+ :- 'byl'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M5.59506e-06 128C70.6925 128 128 70.6925 128 0L0 5.59506e-06L5.59506e-06 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;circle
+ =cx "16"
+ =cy "112"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "16"
+ =cy "112"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ;path
+ =d "M-0.00280762 0L127.997 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;path
+ =d "M22.1288 22.6299C16.0075 28.7511 8.0234 31.874 0.00134547 31.9986M44.7562 45.2573C32.3866 57.6269 16.2133 63.8747 0.00134277 64.0005M67.3836 67.8847C48.7656 86.5027 24.403 95.8749 0.00134412 96.0012"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'byn'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M5.59506e-06 128C70.6925 128 128 70.6925 128 0L0 5.59506e-06L5.59506e-06 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M128 0C128 35.3511 113.669 67.3551 90.5 90.5193"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M96 0C96 26.5077 85.2564 50.5061 67.8862 67.8783"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M64 0C64 17.6721 56.8374 33.6713 45.2568 45.2529"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M32.3716 0C32.3716 8.83603 28.7903 16.8356 23 22.6264"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'byr'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M0 127.946C0.0292286 57.2783 57.3256 3.08928e-06 128 0C128 70.6823 70.7089 127.984 0.0305092 128C0.0203397 128 0.01017 128 2.36469e-09 128L0 127.946Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M-0.00280762 0L127.997 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;circle
+ =cx "48"
+ =cy "80"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "48"
+ =cy "80"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'byt'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M64 128H0L5.59506e-06 0L64 5.59506e-06C99.3462 8.68512e-06 128 28.6538 128 64C128 99.3462 99.3462 128 64 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "48"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M128 64L0 64"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M32 0L32 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'dab'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M0 0C0 70.6925 57.3075 128 128 128V0H0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =y1 "-0.5"
+ =x2 "45.2548"
+ =y2 "-0.5"
+ =transform "matrix(0.707107 -0.707107 -0.707107 -0.707107 79.65 47.6499)"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;circle
+ =cx "16"
+ =cy "112"
+ =r "11.5"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ ;circle
+ =cx "16"
+ =cy "112"
+ =r "9"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ :: =stroke-width "2"
+ ==
+::
+ :- 'dac'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M0 0C0 70.6925 57.3075 128 128 128V0H0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M128 0L0 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;path
+ =d "M64 0L64 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M128 64L-5.96046e-08 64"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'dal'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M0.0541 0C70.7217 0.0292317 128 57.3256 128 128C57.3177 128 0.0164917 70.7089 7.62806e-06 0.0305091C7.62851e-06 0.0203397 -4.44317e-10 0.01017 0 0H0.0541Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "-0.0029152"
+ =x2 "63.29"
+ =y2 "63.2929"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;line
+ =x1 "0.5"
+ =y1 "-0.5"
+ =x2 "181.5"
+ =y2 "-0.5"
+ =transform "matrix(-0.707107 0.707107 0.707107 0.707107 128.71 0)"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;line
+ =x1 "128"
+ =y1 "32.0072"
+ =x2 "32.7071"
+ =y2 "127.3"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;line
+ =x1 "128"
+ =y1 "64.0072"
+ =x2 "64.7071"
+ =y2 "127.3"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;line
+ =x1 "128"
+ =y1 "96.0072"
+ =x2 "96.7071"
+ =y2 "127.3"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ==
+::
+ :- 'dan'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M64 0H128V128H64C28.6538 128 0 99.3462 0 64C0 28.6538 28.6538 0 64 0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "64"
+ =y1 "2.18557e-08"
+ =x2 "64"
+ =y2 "128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;line
+ =x1 "96"
+ =y1 "2.18557e-08"
+ =x2 "96"
+ =y2 "128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "16"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'dap'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M0 0C0 70.6925 57.3075 128 128 128V0H0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "80.0035"
+ =y1 "79.9964"
+ =x2 "112.004"
+ =y2 "111.996"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'dar'
+ |= [fg=tape bg=tape]
+ :~ ;circle
+ =cx "64"
+ =cy "64"
+ =r "64"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;circle
+ =cx "32"
+ =cy "96"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "32"
+ =cy "96"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ;path
+ =d "M86.6274 86.6274C99.1242 74.1307 99.1242 53.8694 86.6274 41.3726C74.1306 28.8758 53.8694 28.8758 41.3726 41.3726"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M75.3137 75.3137C81.5621 69.0653 81.5621 58.9347 75.3137 52.6863C69.0653 46.4379 58.9347 46.4379 52.6863 52.6863"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M97.9411 97.9411C116.686 79.1959 116.686 48.804 97.9411 30.0589C79.196 11.3137 48.804 11.3137 30.0589 30.0589"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M-0.00292969 0L127.997 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ==
+::
+ :- 'das'
+ |= [fg=tape bg=tape]
+ :~ ;rect
+ =width "128"
+ =height "128"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "64"
+ =y1 "2.18557e-08"
+ =x2 "64"
+ =y2 "128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =fill-rule "evenodd"
+ =clip-rule "evenodd"
+ =stroke "none"
+ =d "M80 64C80 72.8366 72.8366 80 64 80C55.1634 80 48 72.8366 48 64C48 55.1634 55.1634 48 64 48C72.8366 48 80 55.1634 80 64ZM64 72C68.4183 72 72 68.4183 72 64C72 59.5817 68.4183 56 64 56C59.5817 56 56 59.5817 56 64C56 68.4183 59.5817 72 64 72Z"
+ =fill bg;
+ ==
+::
+ :- 'dat'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M0 0C0 70.6925 57.3075 128 128 128V0H0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M128 128C92.6538 128 64 99.3462 64 64C64 28.6538 92.6538 -1.54503e-06 128 0"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'dav'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M64 0H128V128H64C28.6538 128 0 99.3462 0 64C0 28.6538 28.6538 0 64 0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M128 64L0 64"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M96 64C96 46.3269 81.6731 32 64 32"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;circle
+ =cx "96"
+ =cy "64"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "96"
+ =cy "64"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'deb'
+ |= [fg=tape bg=tape]
+ :~ ;rect
+ =width "128"
+ =height "128"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M64 -6.35781e-07C64 35.3462 35.3462 64 0 64"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'dec'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M128 128C128 57.3076 70.6925 6.18013e-06 1.11901e-05 0L0 128L128 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ;circle
+ =cx "112"
+ =cy "16"
+ =r "11.5"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ ;circle
+ =cx "112"
+ =cy "16"
+ =r "9"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ :: =stroke-width "2"
+ ==
+::
+ :- 'def'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M0.0541 0C70.7217 0.0292317 128 57.3256 128 128C57.3177 128 0.0164917 70.7089 7.62806e-06 0.0305091C7.62851e-06 0.0203397 -4.44317e-10 0.01017 0 0H0.0541Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M0 128L128 0"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;path
+ =d "M0 94L94 0"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;path
+ =d "M0 64L64 0"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;path
+ =d "M0 32L32 0"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;circle
+ =cx "16"
+ =cy "112"
+ =r "11.5"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ ;circle
+ =cx "16"
+ =cy "112"
+ =r "9"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ :: =stroke-width "2"
+ ==
+::
+ :- 'deg'
+ |= [fg=tape bg=tape]
+ :~ ;rect
+ =width "128"
+ =height "128"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M64 128C64 92.6538 35.3462 64 0 64"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'del'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M0 127.946C0.0292286 57.2783 57.3256 3.08928e-06 128 0C128 70.6823 70.7089 127.984 0.0305092 128C0.0203397 128 0.01017 128 2.36469e-09 128L0 127.946Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;circle
+ =cx "32"
+ =cy "96"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "32"
+ =cy "96"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'dem'
+ |= [fg=tape bg=tape]
+ :~ ;circle
+ =cx "64"
+ =cy "64"
+ =r "64"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M-0.00292969 0L127.997 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;path
+ =d "M64 -6.35781e-07C64 35.3462 35.3462 64 0 64"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;circle
+ =cx "32"
+ =cy "32"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "32"
+ =cy "32"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'den'
+ |= [fg=tape bg=tape]
+ :~ ;rect
+ =width "128"
+ =height "128"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M1.52575e-06 96C53.0193 96 96 53.0193 96 0"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M-0.00280762 0L127.997 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ==
+::
+ :- 'dep'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M128 0C57.3075 8.42999e-07 -8.42999e-07 57.3075 0 128H128V0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M32 128C32 101.492 42.7436 77.4939 60.1138 60.1216"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M64 128C64 110.328 71.1626 94.3287 82.7432 82.7471"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M95.6284 128C95.6284 119.164 99.2097 111.164 105 105.374"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'der'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M0 64L5.59506e-06 0L128 1.11901e-05V64C128 99.3462 99.3462 128 64 128C28.6538 128 -4.6351e-06 99.3462 0 64Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M96 128L96 0"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'des'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M128 0C57.3075 8.42999e-07 -8.42999e-07 57.3075 0 128H128V0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M96 0L96 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'det'
+ |= [fg=tape bg=tape]
+ :~ ;circle
+ =cx "64"
+ =cy "64"
+ =r "64"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "15.9964"
+ =y1 "111.996"
+ =x2 "47.9964"
+ =y2 "79.9964"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'dev'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M64 128H0L5.59506e-06 0L64 5.59506e-06C99.3462 8.68512e-06 128 28.6538 128 64C128 99.3462 99.3462 128 64 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "96.5"
+ =y1 "3.07317e-08"
+ =x2 "96.5"
+ =y2 "128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;line
+ =x1 "32.5"
+ =y1 "3.07317e-08"
+ =x2 "32.5"
+ =y2 "128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'dex'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M64 128H0L5.59506e-06 0L64 5.59506e-06C99.3462 8.68512e-06 128 28.6538 128 64C128 99.3462 99.3462 128 64 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "64"
+ =y1 "2.18557e-08"
+ =x2 "64"
+ =y2 "128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =fill-rule "evenodd"
+ =clip-rule "evenodd"
+ =stroke "none"
+ =d "M80 64C80 72.8366 72.8366 80 64 80C55.1634 80 48 72.8366 48 64C48 55.1634 55.1634 48 64 48C72.8366 48 80 55.1634 80 64ZM64 72C68.4183 72 72 68.4183 72 64C72 59.5817 68.4183 56 64 56C59.5817 56 56 59.5817 56 64C56 68.4183 59.5817 72 64 72Z"
+ =fill bg;
+ ==
+::
+ :- 'dib'
+ |= [fg=tape bg=tape]
+ :~ ;circle
+ =cx "64"
+ =cy "64"
+ =r "64"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "8.74228e-08"
+ =y1 "64"
+ =x2 "128"
+ =y2 "64"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;line
+ =x1 "5.25874e-08"
+ =y1 "32"
+ =x2 "128"
+ =y2 "32"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;circle
+ =cx "64"
+ =cy "32"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "64"
+ =cy "32"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'dif'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M0 0C0 70.6925 57.3075 128 128 128V0H0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M60.1244 67.3837C41.5063 48.7657 32.1342 24.4031 32.0079 0.00145601M82.7518 44.7563C70.3822 32.3867 64.1344 16.2134 64.0086 0.00145196M105.379 22.1289C99.258 16.0077 96.1351 8.02351 96.0105 0.00145196"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;line
+ =x1 "0.5"
+ =y1 "-0.5"
+ =x2 "181.5"
+ =y2 "-0.5"
+ =transform "matrix(-0.707107 0.707107 0.707107 0.707107 128.71 0)"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;circle
+ =cx "16"
+ =cy "16"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "16"
+ =cy "16"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ;circle
+ =cx "16"
+ =cy "112"
+ =r "11.5"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ ;circle
+ =cx "16"
+ =cy "112"
+ =r "9"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ :: =stroke-width "2"
+ ==
+::
+ :- 'dig'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M64 0H128V128H64C28.6538 128 0 99.3462 0 64C0 28.6538 28.6538 0 64 0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "64.5"
+ =y1 "-0.5"
+ =x2 "64.5"
+ =y2 "127.5"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;line
+ =x1 "16.0035"
+ =y1 "15.9965"
+ =x2 "48.0035"
+ =y2 "47.9965"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "16"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'dil'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M64 0H128V128H64C28.6538 128 0 99.3462 0 64C0 28.6538 28.6538 0 64 0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "80.0036"
+ =y1 "79.9964"
+ =x2 "112.004"
+ =y2 "111.996"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;line
+ =x1 "0.5"
+ =y1 "-0.5"
+ =x2 "181.5"
+ =y2 "-0.5"
+ =transform "matrix(-0.707107 0.707107 0.707107 0.707107 128.71 0)"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ==
+::
+ :- 'din'
+ |= [fg=tape bg=tape]
+ :~ ;rect
+ =width "128"
+ =height "128"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "96"
+ =y1 "2.18557e-08"
+ =x2 "96"
+ =y2 "128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'dir'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M0 0C0 70.6925 57.3075 128 128 128V0H0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M96 64C96 81.6731 81.6731 96 64 96"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;line
+ =x1 "16.0035"
+ =y1 "15.9965"
+ =x2 "48.0035"
+ =y2 "47.9965"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "16"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'dis'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M128 0C57.3075 8.42999e-07 -8.42999e-07 57.3075 0 128H128V0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M-0.0029152 0L127.997 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;circle
+ =cx "96"
+ =cy "32"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "96"
+ =cy "32"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ;circle
+ =cx "32"
+ =cy "96"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "32"
+ =cy "96"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'div'
+ |= [fg=tape bg=tape]
+ :~ ;rect
+ =width "128"
+ =height "128"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M64 0L64 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M-4.19629e-06 96C70.6924 96 128 53.0193 128 5.59506e-06"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M-2.79753e-06 64C70.6924 64 128 35.3462 128 5.59506e-06"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'doc'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M0 127.946C0.0292286 57.2783 57.3256 3.08928e-06 128 0C128 70.6823 70.7089 127.984 0.0305092 128C0.0203397 128 0.01017 128 2.36469e-09 128L0 127.946Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M127.997 0L-0.00291443 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "16"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M86.6274 41.3726C74.1306 28.8758 53.8694 28.8758 41.3726 41.3726C28.8758 53.8694 28.8758 74.1306 41.3726 86.6274"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'dol'
+ |= [fg=tape bg=tape]
+ :~ ;circle
+ =cx "64"
+ =cy "64"
+ =r "64"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M128 64L0 64"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M-4.19629e-06 16C26.5097 16 48 37.4903 48 64C48 90.5097 26.5097 112 0 112"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'don'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M128 0C57.3075 8.42999e-07 -8.42999e-07 57.3075 0 128H128V0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M-3.8147e-06 128C-7.24632e-07 92.6538 28.6538 64 64 64C99.3462 64 128 92.6538 128 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'dop'
+ |= [fg=tape bg=tape]
+ :~ ;circle
+ =cx "64"
+ =cy "64"
+ =r "64"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M64 112C90.5097 112 112 90.5097 112 64C112 37.4903 90.5097 16 64 16"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M128 64L0 64"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'dor'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M64 0H128V128H64C28.6538 128 0 99.3462 0 64C0 28.6538 28.6538 0 64 0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =y1 "63.5"
+ =x2 "128"
+ =y2 "63.5"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'dos'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M0 0C0 70.6925 57.3075 128 128 128V0H0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "-0.0029152"
+ =x2 "127.983"
+ =y2 "127.986"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;path
+ =d "M86.6274 86.6274C99.1242 74.1306 99.1242 53.8693 86.6274 41.3725C74.1306 28.8758 53.8694 28.8758 41.3726 41.3725"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'dot'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M64 0H128V128H64C28.6538 128 0 99.3462 0 64C0 28.6538 28.6538 0 64 0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'dov'
+ |= [fg=tape bg=tape]
+ :~ ;rect
+ =width "128"
+ =height "128"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M128 0L0 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;path
+ =d "M-0.701724 31.9914C25.6281 31.9914 49.4822 42.5913 66.8261 59.7565M-0.701723 63.9914C16.7916 63.9914 32.6456 71.0098 44.1982 82.3844M-0.701722 95.9914C7.955 95.9914 15.8089 99.4288 21.5694 105.013"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M0 0C35.3511 0 67.3551 14.3309 90.5193 37.5"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'doz'
+ |= [fg=tape bg=tape]
+ :~ ;circle
+ =cx "64"
+ =cy "64"
+ =r "64"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M128 128L0 0"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;path
+ =d "M30.0589 30.0589C48.804 11.3137 79.196 11.3137 97.9411 30.0589C116.686 48.804 116.686 79.196 97.9411 97.9411"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M52.6863 52.6863C58.9347 46.4379 69.0653 46.4379 75.3137 52.6863C81.5621 58.9347 81.5621 69.0653 75.3137 75.3137"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M41.3726 41.3726C53.8694 28.8758 74.1306 28.8758 86.6274 41.3726C99.1242 53.8694 99.1242 74.1306 86.6274 86.6274"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'duc'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M128 128C128 57.3076 70.6925 6.18013e-06 1.11901e-05 0L0 128L128 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M128 64L0 64"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M128 32L0 32"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;circle
+ =cx "32"
+ =cy "32"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "32"
+ =cy "32"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'dul'
+ |= [fg=tape bg=tape]
+ :~ ;circle
+ =cx "64"
+ =cy "64"
+ =r "64"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M64 16C90.5097 16 112 37.4903 112 64"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M64 64L64 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'dun'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M64 128H0L5.59506e-06 0L64 5.59506e-06C99.3462 8.68512e-06 128 28.6538 128 64C128 99.3462 99.3462 128 64 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M112 64C112 37.4903 90.5097 16 64 16"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'dur'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M0 64L5.59506e-06 0L128 1.11901e-05V64C128 99.3462 99.3462 128 64 128C28.6538 128 -4.6351e-06 99.3462 0 64Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ==
+::
+ :- 'dus'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M128 128C128 57.3076 70.6925 6.18013e-06 1.11901e-05 0L0 128L128 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M32 -3.05151e-06C32 53.0193 74.9807 96 128 96"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M128 0L0 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ==
+::
+ :- 'dut'
+ |= [fg=tape bg=tape]
+ :~ ;rect
+ =width "128"
+ =height "128"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;circle
+ =cx "96"
+ =cy "96"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "96"
+ =cy "96"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'dux'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M5.59506e-06 128C70.6925 128 128 70.6925 128 0L0 5.59506e-06L5.59506e-06 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M-2.79795e-06 -3.55988e-06C70.6924 -4.40288e-06 128 57.3075 128 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'dyl'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M128 128C128 57.3076 70.6925 6.18013e-06 1.11901e-05 0L0 128L128 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M2.03434e-06 128C70.6924 128 128 70.6925 128 0"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'dyn'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M5.59506e-06 128C70.6925 128 128 70.6925 128 0L0 5.59506e-06L5.59506e-06 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M128 32L0 32"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'dyr'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M0 127.946C0.0292286 57.2783 57.3256 3.08928e-06 128 0C128 70.6823 70.7089 127.984 0.0305092 128C0.0203397 128 0.01017 128 2.36469e-09 128L0 127.946Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M-0.00292969 0L127.997 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;circle
+ =cx "96"
+ =cy "32"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "96"
+ =cy "32"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ;circle
+ =cx "32"
+ =cy "96"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "32"
+ =cy "96"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'dys'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M128 128C128 57.3076 70.6925 6.18013e-06 1.11901e-05 0L0 128L128 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M-3.8147e-06 1.11901e-05C-7.24633e-07 35.3462 28.6538 64 64 64C99.3462 64 128 35.3462 128 0"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'dyt'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M64 128H0L5.59506e-06 0L64 5.59506e-06C99.3462 8.68512e-06 128 28.6538 128 64C128 99.3462 99.3462 128 64 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "32"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M128 64L0 64"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;circle
+ =cx "32"
+ =cy "64"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "32"
+ =cy "64"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'fab'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M0 0C0 70.6925 57.3075 128 128 128V0H0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M128 0L0 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ;circle
+ =cx "16"
+ =cy "112"
+ =r "11.5"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ ;circle
+ =cx "16"
+ =cy "112"
+ =r "9"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ :: =stroke-width "2"
+ ==
+::
+ :- 'fad'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M5.59506e-06 128C70.6925 128 128 70.6925 128 0L0 5.59506e-06L5.59506e-06 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;circle
+ =cx "96"
+ =cy "32"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "96"
+ =cy "32"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ;circle
+ =cx "32"
+ =cy "96"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "32"
+ =cy "96"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'fal'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M0 127.946C0.0292286 57.2783 57.3256 3.08928e-06 128 0C128 70.6823 70.7089 127.984 0.0305092 128C0.0203397 128 0.01017 128 2.36469e-09 128L0 127.946Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M0 128L128 0"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;path
+ =d "M0 0C35.3511 0 67.3551 14.3309 90.5193 37.5"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M0 32C26.5077 32 50.5061 42.7436 67.8783 60.1138"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M0 64C17.6721 64 33.6713 71.1626 45.2529 82.7432"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M0 95.6284C8.83603 95.6284 16.8356 99.2097 22.6264 105"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'fam'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M64 0H128V128H64C28.6538 128 0 99.3462 0 64C0 28.6538 28.6538 0 64 0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "128"
+ =y1 "64"
+ =x2 "-4.37114e-08"
+ =y2 "64"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;line
+ =x1 "64"
+ =y1 "2.18557e-08"
+ =x2 "64"
+ =y2 "128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'fan'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M64 0H128V128H64C28.6538 128 0 99.3462 0 64C0 28.6538 28.6538 0 64 0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M128 0L0 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;path
+ =d "M64 0L64 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M-0.00292969 0L127.997 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ==
+::
+ :- 'fas'
+ |= [fg=tape bg=tape]
+ :~ ;rect
+ =width "128"
+ =height "128"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "32"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;circle
+ =cx "96"
+ =cy "64"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "96"
+ =cy "64"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'feb'
+ |= [fg=tape bg=tape]
+ :~ ;rect
+ =width "128"
+ =height "128"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M7.37542e-06 -3.56072e-06C1.19529e-06 70.6924 57.3075 128 128 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'fed'
+ |= [fg=tape bg=tape]
+ :~ ;circle
+ =cx "64"
+ =cy "64"
+ =r "64"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M128 32L0 32"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'fel'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M0 127.946C0.0292286 57.2783 57.3256 3.08928e-06 128 0C128 70.6823 70.7089 127.984 0.0305092 128C0.0203397 128 0.01017 128 2.36469e-09 128L0 127.946Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =y1 "-0.5"
+ =x2 "45.2548"
+ =y2 "-0.5"
+ =transform "matrix(0.707107 -0.707107 -0.707107 -0.707107 79.65 47.6499)"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'fen'
+ |= [fg=tape bg=tape]
+ :~ ;rect
+ =width "128"
+ =height "128"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M-0.00280762 0L127.997 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;path
+ =d "M0 128C4.63574e-06 92.6489 14.3309 60.6449 37.5 37.4807"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M32 128C32 101.492 42.7436 77.4939 60.1138 60.1217"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M64 128C64 110.328 71.1626 94.3287 82.7432 82.7471"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M95.6284 128C95.6284 119.164 99.2097 111.164 105 105.374"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'fep'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M128 128C128 57.3076 70.6925 6.18013e-06 1.11901e-05 0L0 128L128 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M128 0L0 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ==
+::
+ :- 'fer'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M64 128H0L5.59506e-06 0L64 5.59506e-06C99.3462 8.68512e-06 128 28.6538 128 64C128 99.3462 99.3462 128 64 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M64 0L64 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'fes'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M128 0C57.3075 8.42999e-07 -8.42999e-07 57.3075 0 128H128V0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M32 0L32 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'fet'
+ |= [fg=tape bg=tape]
+ :~ ;circle
+ =cx "64"
+ =cy "64"
+ =r "64"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M128 0L0 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ==
+::
+ :- 'fex'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M64 128H0L5.59506e-06 0L64 5.59506e-06C99.3462 8.68512e-06 128 28.6538 128 64C128 99.3462 99.3462 128 64 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =y1 "-0.5"
+ =x2 "45.2548"
+ =y2 "-0.5"
+ =transform "matrix(0.707107 -0.707107 -0.707107 -0.707107 79.6499 47.6499)"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =fill-rule "evenodd"
+ =clip-rule "evenodd"
+ =stroke "none"
+ =d "M80 64C80 72.8366 72.8366 80 64 80C55.1634 80 48 72.8366 48 64C48 55.1634 55.1634 48 64 48C72.8366 48 80 55.1634 80 64ZM64 72C68.4183 72 72 68.4183 72 64C72 59.5817 68.4183 56 64 56C59.5817 56 56 59.5817 56 64C56 68.4183 59.5817 72 64 72Z"
+ =fill bg;
+ ==
+::
+ :- 'fid'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M0 0C0 70.6925 57.3075 128 128 128V0H0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M-0.00291443 0L127.997 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;circle
+ =cx "96"
+ =cy "96"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "96"
+ =cy "96"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ;circle
+ =cx "32"
+ =cy "32"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "32"
+ =cy "32"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'fig'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M64 0H128V128H64C28.6538 128 0 99.3462 0 64C0 28.6538 28.6538 0 64 0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M64 0L64 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "32"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "16"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'fil'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M64 0H128V128H64C28.6538 128 0 99.3462 0 64C0 28.6538 28.6538 0 64 0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "128"
+ =y1 "64"
+ =x2 "-4.37114e-08"
+ =y2 "64"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;line
+ =x1 "64"
+ =y1 "2.18557e-08"
+ =x2 "64"
+ =y2 "128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;line
+ =x1 "32"
+ =y1 "2.18557e-08"
+ =x2 "32"
+ =y2 "128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'fin'
+ |= [fg=tape bg=tape]
+ :~ ;rect
+ =width "128"
+ =height "128"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "98"
+ =y1 "2.18557e-08"
+ =x2 "98"
+ =y2 "128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'fip'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M64 0H128V128H64C28.6538 128 0 99.3462 0 64C0 28.6538 28.6538 0 64 0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "32"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;line
+ =x1 "-0.0029152"
+ =x2 "127.983"
+ =y2 "127.986"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;circle
+ =cx "64"
+ =cy "96"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "64"
+ =cy "96"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'fir'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M0 0C0 70.6925 57.3075 128 128 128V0H0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =y1 "-0.5"
+ =x2 "45.2548"
+ =y2 "-0.5"
+ =transform "matrix(0.707107 -0.707107 -0.707107 -0.707107 79.65 47.6499)"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;line
+ =x1 "80.0036"
+ =y1 "79.9965"
+ =x2 "112.004"
+ =y2 "111.997"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;line
+ =x1 "16.0035"
+ =y1 "15.9965"
+ =x2 "48.0035"
+ =y2 "47.9965"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'fit'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M0.0541 0C70.7217 0.0292317 128 57.3256 128 128C57.3177 128 0.0164917 70.7089 7.62806e-06 0.0305091C7.62851e-06 0.0203397 -4.44317e-10 0.01017 0 0H0.0541Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "0.5"
+ =y1 "-0.5"
+ =x2 "181.5"
+ =y2 "-0.5"
+ =transform "matrix(-0.707107 0.707107 0.707107 0.707107 128.71 0)"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ==
+::
+ :- 'fod'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M64 0H128V128H64C28.6538 128 0 99.3462 0 64C0 28.6538 28.6538 0 64 0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =fill-rule "evenodd"
+ =clip-rule "evenodd"
+ =stroke "none"
+ =d "M80 64C80 72.8366 72.8366 80 64 80C55.1634 80 48 72.8366 48 64C48 55.1634 55.1634 48 64 48C72.8366 48 80 55.1634 80 64ZM64 72C68.4183 72 72 68.4183 72 64C72 59.5817 68.4183 56 64 56C59.5817 56 56 59.5817 56 64C56 68.4183 59.5817 72 64 72Z"
+ =fill bg;
+ ==
+::
+ :- 'fog'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M128 0C57.3075 8.42999e-07 -8.42999e-07 57.3075 0 128H128V0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M-0.00292969 0L127.997 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;path
+ =d "M86.6274 86.6274C99.1242 74.1306 99.1242 53.8694 86.6274 41.3726C74.1306 28.8758 53.8694 28.8758 41.3726 41.3726"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "16"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'fol'
+ |= [fg=tape bg=tape]
+ :~ ;circle
+ =cx "64"
+ =cy "64"
+ =r "64"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "16"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;line
+ =x1 "128"
+ =y1 "64"
+ =x2 "-4.37114e-08"
+ =y2 "64"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'fon'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M128 0C57.3075 8.42999e-07 -8.42999e-07 57.3075 0 128H128V0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "-0.0029152"
+ =x2 "127.983"
+ =y2 "127.986"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ==
+::
+ :- 'fop'
+ |= [fg=tape bg=tape]
+ :~ ;circle
+ =cx "64"
+ =cy "64"
+ =r "64"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "-0.0029152"
+ =x2 "127.983"
+ =y2 "127.986"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;path
+ =d "M16 64C16 90.5097 37.4903 112 64 112"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;circle
+ =cx "16"
+ =cy "64"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "16"
+ =cy "64"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'for'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M64 0H128V128H64C28.6538 128 0 99.3462 0 64C0 28.6538 28.6538 0 64 0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "96"
+ =y1 "2.18557e-08"
+ =x2 "96"
+ =y2 "128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'fos'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M5.59506e-06 128C70.6925 128 128 70.6925 128 0L0 5.59506e-06L5.59506e-06 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "-0.0029152"
+ =x2 "127.983"
+ =y2 "127.986"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;path
+ =d "M96 0C96 53.0193 53.0193 96 0 96"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M64 0C64 35.3462 35.3462 64 0 64"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M32 0C32 17.6731 17.6731 32 0 32"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'fot'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M64 0H128V128H64C28.6538 128 0 99.3462 0 64C0 28.6538 28.6538 0 64 0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "15.9964"
+ =y1 "111.997"
+ =x2 "47.9964"
+ =y2 "79.9965"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'ful'
+ |= [fg=tape bg=tape]
+ :~ ;circle
+ =cx "64"
+ =cy "64"
+ =r "64"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M64 96C81.6731 96 96 81.6731 96 64C96 46.3269 81.6731 32 64 32"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'fun'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M128 64V128H0L2.79753e-06 64C4.34256e-06 28.6538 28.6538 -1.54503e-06 64 0C99.3462 1.54503e-06 128 28.6538 128 64Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "15.9964"
+ =y1 "111.997"
+ =x2 "47.9964"
+ =y2 "79.9965"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M-0.00280762 0L127.997 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;circle
+ =cx "16"
+ =cy "112"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "16"
+ =cy "112"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'fur'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M5.59506e-06 128C70.6925 128 128 70.6925 128 0L0 5.59506e-06L5.59506e-06 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M128 0L0 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;path
+ =d "M86.8823 41.6275C74.3855 29.1307 54.1242 29.1307 41.6274 41.6275C29.1307 54.1243 29.1307 74.3855 41.6274 86.8823"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "16"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'fus'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M128 128C128 57.3076 70.6925 6.18013e-06 1.11901e-05 0L0 128L128 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M128 0L0 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;path
+ =d "M32 128C32 110.327 17.6731 96 0 96"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'fyl'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M5.59506e-06 128C70.6925 128 128 70.6925 128 0L0 5.59506e-06L5.59506e-06 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M22.1288 22.6299C16.0075 28.7511 8.0234 31.874 0.00134547 31.9986M44.7562 45.2573C32.3866 57.6269 16.2133 63.8747 0.00134277 64.0005M67.3836 67.8847C48.7656 86.5027 24.403 95.8749 0.00134412 96.0012"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M-0.00280762 0L127.997 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ==
+::
+ :- 'fyn'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M5.59506e-06 128C70.6925 128 128 70.6925 128 0L0 5.59506e-06L5.59506e-06 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M128 0L0 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ==
+::
+ :- 'fyr'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M0 127.946C0.0292286 57.2783 57.3256 3.08928e-06 128 0C128 70.6823 70.7089 127.984 0.0305092 128C0.0203397 128 0.01017 128 2.36469e-09 128L0 127.946Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M-0.00268555 0L127.997 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;line
+ =y1 "-0.5"
+ =x2 "45.2548"
+ =y2 "-0.5"
+ =transform "matrix(0.707107 -0.707107 -0.707107 -0.707107 79.6499 47.6499)"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'hab'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M0 0C0 70.6925 57.3075 128 128 128V0H0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "0.5"
+ =y1 "-0.5"
+ =x2 "181.5"
+ =y2 "-0.5"
+ =transform "matrix(-0.707107 0.707107 0.707107 0.707107 128.71 0)"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;path
+ =d "M60.1244 67.3837C41.5063 48.7657 32.1342 24.4031 32.0079 0.00145601M82.7518 44.7563C70.3822 32.3867 64.1344 16.2134 64.0086 0.00145196M105.379 22.1289C99.258 16.0077 96.1351 8.02351 96.0105 0.00145196"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;circle
+ =cx "16"
+ =cy "112"
+ =r "11.5"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ ;circle
+ =cx "16"
+ =cy "112"
+ =r "9"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ :: =stroke-width "2"
+ ==
+::
+ :- 'hac'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M0 0C0 70.6925 57.3075 128 128 128V0H0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "0.5"
+ =y1 "-0.5"
+ =x2 "181.5"
+ =y2 "-0.5"
+ =transform "matrix(-0.707107 0.707107 0.707107 0.707107 128.71 0)"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "32"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'had'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M5.59506e-06 128C70.6925 128 128 70.6925 128 0L0 5.59506e-06L5.59506e-06 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;circle
+ =cx "32"
+ =cy "32"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "32"
+ =cy "32"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'hal'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M0 127.946C0.0292286 57.2783 57.3256 3.08928e-06 128 0C128 70.6823 70.7089 127.984 0.0305092 128C0.0203397 128 0.01017 128 2.36469e-09 128L0 127.946Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "64.5"
+ =y1 "-0.5"
+ =x2 "64.5"
+ =y2 "127.5"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M16 64C16 90.5097 37.4903 112 64 112"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M112 64C112 37.4903 90.5097 16 64 16"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'han'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M5.59506e-06 128C70.6925 128 128 70.6925 128 0L0 5.59506e-06L5.59506e-06 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ==
+::
+ :- 'hap'
+ |= [fg=tape bg=tape]
+ :~ ;circle
+ =cx "64"
+ =cy "64"
+ =r "64"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "32"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "48"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M-0.00292969 0L127.997 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'har'
+ |= [fg=tape bg=tape]
+ :~ ;circle
+ =cx "64"
+ =cy "64"
+ =r "64"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "64"
+ =y1 "2.18557e-08"
+ =x2 "64"
+ =y2 "128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "16"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'has'
+ |= [fg=tape bg=tape]
+ :~ ;rect
+ =width "128"
+ =height "128"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "32"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;circle
+ =cx "64"
+ =cy "32"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "64"
+ =cy "32"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ;circle
+ =cx "32"
+ =cy "64"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "32"
+ =cy "64"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'hat'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M0 0C0 70.6925 57.3075 128 128 128V0H0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;circle
+ =cx "16"
+ =cy "16"
+ =r "8"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;line
+ =x1 "0.5"
+ =y1 "-0.5"
+ =x2 "181.5"
+ =y2 "-0.5"
+ =transform "matrix(-0.707107 0.707107 0.707107 0.707107 128.71 0)"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;path
+ =fill-rule "evenodd"
+ =clip-rule "evenodd"
+ =stroke "none"
+ =d "M48 32C48 40.8366 40.8366 48 32 48C23.1634 48 16 40.8366 16 32C16 23.1634 23.1634 16 32 16C40.8366 16 48 23.1634 48 32ZM32 40C36.4183 40 40 36.4183 40 32C40 27.5817 36.4183 24 32 24C27.5817 24 24 27.5817 24 32C24 36.4183 27.5817 40 32 40Z"
+ =fill bg;
+ ==
+::
+ :- 'hav'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M0 0C0 70.6925 57.3075 128 128 128V0H0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "96"
+ =y1 "2.18557e-08"
+ =x2 "96"
+ =y2 "128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'heb'
+ |= [fg=tape bg=tape]
+ :~ ;rect
+ =width "128"
+ =height "128"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M2.03434e-06 128C70.6924 128 128 70.6925 128 0"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'hec'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M128 128C128 57.3076 70.6925 6.18013e-06 1.11901e-05 0L0 128L128 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;circle
+ =cx "32"
+ =cy "32"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "32"
+ =cy "32"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ;circle
+ =cx "32"
+ =cy "96"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "32"
+ =cy "96"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ;circle
+ =cx "96"
+ =cy "96"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "96"
+ =cy "96"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'hep'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M128 128C128 57.3076 70.6925 6.18013e-06 1.11901e-05 0L0 128L128 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "-0.00285417"
+ =x2 "127.983"
+ =y2 "127.986"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;path
+ =d "M-0.00292969 0L127.997 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ==
+::
+ :- 'hes'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M128 0C57.3075 8.42999e-07 -8.42999e-07 57.3075 0 128H128V0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M32 0L32 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =fill-rule "evenodd"
+ =clip-rule "evenodd"
+ =stroke "none"
+ =d "M48 96C48 104.837 40.8366 112 32 112C23.1634 112 16 104.837 16 96C16 87.1634 23.1634 80 32 80C40.8366 80 48 87.1634 48 96ZM32 104C36.4183 104 40 100.418 40 96C40 91.5817 36.4183 88 32 88C27.5817 88 24 91.5817 24 96C24 100.418 27.5817 104 32 104Z"
+ =fill bg;
+ ==
+::
+ :- 'het'
+ |= [fg=tape bg=tape]
+ :~ ;circle
+ =cx "64"
+ =cy "64"
+ =r "64"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M96 128L96 0"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'hex'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M64 128H0L5.59506e-06 0L64 5.59506e-06C99.3462 8.68512e-06 128 28.6538 128 64C128 99.3462 99.3462 128 64 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M128 0L0 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;path
+ =fill-rule "evenodd"
+ =clip-rule "evenodd"
+ =stroke "none"
+ =d "M80 64C80 72.8366 72.8366 80 64 80C55.1634 80 48 72.8366 48 64C48 55.1634 55.1634 48 64 48C72.8366 48 80 55.1634 80 64ZM64 72C68.4183 72 72 68.4183 72 64C72 59.5817 68.4183 56 64 56C59.5817 56 56 59.5817 56 64C56 68.4183 59.5817 72 64 72Z"
+ =fill bg;
+ ==
+::
+ :- 'hid'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M0 0C0 70.6925 57.3075 128 128 128V0H0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M-0.00292969 0L127.997 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;path
+ =d "M2.03434e-06 128C70.6924 128 128 70.6925 128 0"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M1.52575e-06 96C53.0193 96 96 53.0193 96 0"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M1.01717e-06 64C35.3462 64 64 35.3462 64 0"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M5.08584e-07 32C17.6731 32 32 17.6731 32 0"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'hil'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M64 0H128V128H64C28.6538 128 0 99.3462 0 64C0 28.6538 28.6538 0 64 0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "8.74228e-08"
+ =y1 "64"
+ =x2 "128"
+ =y2 "64"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;line
+ =x1 "64"
+ =y1 "2.18557e-08"
+ =x2 "64"
+ =y2 "128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'hin'
+ |= [fg=tape bg=tape]
+ :~ ;rect
+ =width "128"
+ =height "128"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "32"
+ =y1 "2.18557e-08"
+ =x2 "32"
+ =y2 "128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =fill-rule "evenodd"
+ =clip-rule "evenodd"
+ =stroke "none"
+ =d "M48 64C48 72.8366 40.8366 80 32 80C23.1634 80 16 72.8366 16 64C16 55.1634 23.1634 48 32 48C40.8366 48 48 55.1634 48 64ZM32 72C36.4183 72 40 68.4183 40 64C40 59.5817 36.4183 56 32 56C27.5817 56 24 59.5817 24 64C24 68.4183 27.5817 72 32 72Z"
+ =fill bg;
+ ==
+::
+ :- 'hob'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M128 64V128H0L2.79753e-06 64C4.34256e-06 28.6538 28.6538 -1.54503e-06 64 0C99.3462 1.54503e-06 128 28.6538 128 64Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "128"
+ =y1 "64"
+ =x2 "-4.37114e-08"
+ =y2 "64"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'hoc'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M64 0H128V128H64C28.6538 128 0 99.3462 0 64C0 28.6538 28.6538 0 64 0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =y1 "-0.5"
+ =x2 "45.2548"
+ =y2 "-0.5"
+ =transform "matrix(0.707107 -0.707107 -0.707107 -0.707107 79.65 47.6499)"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'hod'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M64 0H128V128H64C28.6538 128 0 99.3462 0 64C0 28.6538 28.6538 0 64 0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M32 0L32 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'hol'
+ |= [fg=tape bg=tape]
+ :~ ;circle
+ =cx "64"
+ =cy "64"
+ =r "64"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "128"
+ =y1 "64"
+ =x2 "-4.37114e-08"
+ =y2 "64"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "16"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;circle
+ =cx "64"
+ =cy "96"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "64"
+ =cy "96"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'hop'
+ |= [fg=tape bg=tape]
+ :~ ;circle
+ =cx "64"
+ =cy "64"
+ =r "64"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M128 64L0 64"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M64 96C81.6731 96 96 81.6731 96 64C96 46.3269 81.6731 32 64 32"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'hos'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M0 0C0 70.6925 57.3075 128 128 128V0H0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "80.0036"
+ =y1 "79.9965"
+ =x2 "112.004"
+ =y2 "111.997"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;line
+ =x1 "16.0036"
+ =y1 "15.9965"
+ =x2 "48.0036"
+ =y2 "47.9965"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;circle
+ =cx "48"
+ =cy "48"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "48"
+ =cy "48"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ;circle
+ =cx "80"
+ =cy "47"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "80"
+ =cy "47"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ;circle
+ =cx "80"
+ =cy "81"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "80"
+ =cy "81"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ;circle
+ =cx "48"
+ =cy "80"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "48"
+ =cy "80"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'hul'
+ |= [fg=tape bg=tape]
+ :~ ;circle
+ =cx "64"
+ =cy "64"
+ =r "64"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "32"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;circle
+ =cx "48"
+ =cy "64"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "48"
+ =cy "64"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'hus'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M128 128C128 57.3076 70.6925 6.18013e-06 1.11901e-05 0L0 128L128 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M-0.00292969 0L127.997 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;path
+ =d "M64 96C46.3269 96 32 81.6731 32 64"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'hut'
+ |= [fg=tape bg=tape]
+ :~ ;rect
+ =width "128"
+ =height "128"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "48"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;circle
+ =cx "32"
+ =cy "32"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "32"
+ =cy "32"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ;circle
+ =cx "96"
+ =cy "96"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "96"
+ =cy "96"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'lab'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M128 0C57.3075 8.42999e-07 -8.42999e-07 57.3075 0 128H128V0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "-0.0029152"
+ =x2 "127.983"
+ =y2 "127.986"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;line
+ =y1 "-0.5"
+ =x2 "45.2548"
+ =y2 "-0.5"
+ =transform "matrix(0.707107 -0.707107 -0.707107 -0.707107 79.65 47.6499)"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;line
+ =x1 "15.9964"
+ =y1 "111.997"
+ =x2 "47.9964"
+ =y2 "79.9965"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'lac'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M0 0C0 70.6925 57.3075 128 128 128V0H0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M64 -9.40976e-06C64 70.6924 92.6538 128 128 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M32 -7.63193e-07C32 70.6924 74.9807 128 128 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M128 64L0 64"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'lad'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M128 0C57.3075 8.42999e-07 -8.42999e-07 57.3075 0 128H128V0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "95.35"
+ =y1 "32.7071"
+ =x2 "32.0571"
+ =y2 "96"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;circle
+ =cx "96"
+ =cy "32"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "96"
+ =cy "32"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ;circle
+ =cx "32"
+ =cy "96"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "32"
+ =cy "96"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'lag'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M64 0H128V128H64C28.6538 128 0 99.3462 0 64C0 28.6538 28.6538 0 64 0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M64 112C90.5097 112 112 90.5097 112 64"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'lan'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M64 0H128V128H64C28.6538 128 0 99.3462 0 64C0 28.6538 28.6538 0 64 0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "64"
+ =y1 "2.18557e-08"
+ =x2 "64"
+ =y2 "128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;line
+ =x1 "32"
+ =y1 "2.18557e-08"
+ =x2 "32"
+ =y2 "128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "16"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'lap'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M0 0C0 70.6925 57.3075 128 128 128V0H0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M112 64C112 37.4903 90.5097 16 64 16"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;circle
+ =cx "112"
+ =cy "64"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "112"
+ =cy "64"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'lar'
+ |= [fg=tape bg=tape]
+ :~ ;circle
+ =cx "64"
+ =cy "64"
+ =r "64"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "2.78181e-08"
+ =y1 "64"
+ =x2 "128"
+ =y2 "64"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "16"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;circle
+ =cx "64"
+ =cy "96"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "64"
+ =cy "96"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ;circle
+ =cx "64"
+ =cy "32"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "64"
+ =cy "32"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'las'
+ |= [fg=tape bg=tape]
+ :~ ;rect
+ =width "128"
+ =height "128"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "48"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;circle
+ =cx "16"
+ =cy "64"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "16"
+ =cy "64"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'lat'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M0 0C0 70.6925 57.3075 128 128 128V0H0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M2.03434e-06 128C70.6924 128 128 70.6925 128 0"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M1.52575e-06 96C53.0193 96 96 53.0193 96 0"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M1.01717e-06 64C35.3462 64 64 35.3462 64 0"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M5.08584e-07 32C17.6731 32 32 17.6731 32 0"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'lav'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M128 0C57.3075 8.42999e-07 -8.42999e-07 57.3075 0 128H128V0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M128 128C92.6489 128 60.6449 113.669 37.4807 90.5"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M128 96C101.492 96 77.4939 85.2564 60.1217 67.8862"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M128 64C110.328 64 94.3287 56.8374 82.7471 45.2568"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M128 32.3716C119.164 32.3716 111.164 28.7903 105.374 23"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'leb'
+ |= [fg=tape bg=tape]
+ :~ ;rect
+ =width "128"
+ =height "128"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M-1.64036e-05 32C53.0193 32 96 74.9807 96 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'lec'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M128 128C128 57.3076 70.6925 6.18013e-06 1.11901e-05 0L0 128L128 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M-0.00292969 0L127.997 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'led'
+ |= [fg=tape bg=tape]
+ :~ ;circle
+ =cx "64"
+ =cy "64"
+ =r "64"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;circle
+ =cx "64"
+ =cy "32"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "64"
+ =cy "32"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'leg'
+ |= [fg=tape bg=tape]
+ :~ ;rect
+ =width "128"
+ =height "128"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M7.63192e-07 32C17.6731 32 32 46.3269 32 64C32 81.6731 17.6731 96 0 96"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'len'
+ |= [fg=tape bg=tape]
+ :~ ;rect
+ =width "128"
+ =height "128"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "48"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;circle
+ =cx "64"
+ =cy "96"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "64"
+ =cy "96"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'lep'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M128 0C57.3075 8.42999e-07 -8.42999e-07 57.3075 0 128H128V0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M128 96C110.327 96 96 110.327 96 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'ler'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M64 128H0L5.59506e-06 0L64 5.59506e-06C99.3462 8.68512e-06 128 28.6538 128 64C128 99.3462 99.3462 128 64 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M32 0L32 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;circle
+ =cx "32"
+ =cy "32"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "32"
+ =cy "32"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'let'
+ |= [fg=tape bg=tape]
+ :~ ;circle
+ =cx "64"
+ =cy "64"
+ =r "64"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M64 0L64 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'lev'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M64 128H0L5.59506e-06 0L64 5.59506e-06C99.3462 8.68512e-06 128 28.6538 128 64C128 99.3462 99.3462 128 64 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;circle
+ =cx "32"
+ =cy "32"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "32"
+ =cy "32"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'lex'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M64 128H0L5.59506e-06 0L64 5.59506e-06C99.3462 8.68512e-06 128 28.6538 128 64C128 99.3462 99.3462 128 64 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M-0.00292969 0L127.997 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;line
+ =x1 "15.9965"
+ =y1 "111.997"
+ =x2 "47.9965"
+ =y2 "79.9965"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =fill-rule "evenodd"
+ =clip-rule "evenodd"
+ =stroke "none"
+ =d "M80 64C80 72.8366 72.8366 80 64 80C55.1634 80 48 72.8366 48 64C48 55.1634 55.1634 48 64 48C72.8366 48 80 55.1634 80 64ZM64 72C68.4183 72 72 68.4183 72 64C72 59.5817 68.4183 56 64 56C59.5817 56 56 59.5817 56 64C56 68.4183 59.5817 72 64 72Z"
+ =fill bg;
+ ==
+::
+ :- 'lib'
+ |= [fg=tape bg=tape]
+ :~ ;circle
+ =cx "64"
+ =cy "64"
+ =r "64"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M128 64C92.6538 64 64 92.6538 64 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M128 64L0 64"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'lid'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M0 0C0 70.6925 57.3075 128 128 128V0H0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "16.0036"
+ =y1 "15.9965"
+ =x2 "48.0036"
+ =y2 "47.9965"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M128 0L0 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ==
+::
+ :- 'lig'
+ |= [fg=tape bg=tape]
+ :~ ;circle
+ =cx "64"
+ =cy "64"
+ =r "64"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "48"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'lin'
+ |= [fg=tape bg=tape]
+ :~ ;rect
+ =width "128"
+ =height "128"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "64"
+ =y1 "128"
+ =x2 "64"
+ =y2 "-6.55671e-08"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;circle
+ =cx "80"
+ =cy "64"
+ =r "8"
+ =fill bg
+ =stroke "none";
+ ==
+::
+ :- 'lis'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M128 128C128 57.3076 70.6925 6.18013e-06 1.11901e-05 0L0 128L128 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M128 64L0 64"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M-4.70488e-06 64C35.3462 64 64 35.3462 64 0"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'lit'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M0.0541 0C70.7217 0.0292317 128 57.3256 128 128C57.3177 128 0.0164917 70.7089 7.62806e-06 0.0305091C7.62851e-06 0.0203397 -4.44317e-10 0.01017 0 0H0.0541Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M-0.00286865 0L127.997 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;path
+ =d "M128 0C128 35.3511 113.669 67.3551 90.5 90.5193"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M96 0C96 26.5077 85.2564 50.5061 67.8862 67.8783"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M64 0C64 17.6721 56.8374 33.6713 45.2568 45.2529"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M32.3716 0C32.3716 8.83603 28.7903 16.8356 23 22.6264"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'liv'
+ |= [fg=tape bg=tape]
+ :~ ;rect
+ =width "128"
+ =height "128"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M-5.21346e-06 32C70.6924 32 128 17.6731 128 0"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M3.4331e-06 96C70.6924 96 128 53.0193 128 0"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M64 0L64 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'loc'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M0.0541 0C70.7217 0.0292317 128 57.3256 128 128C57.3177 128 0.0164917 70.7089 7.62806e-06 0.0305091C7.62851e-06 0.0203397 -4.44317e-10 0.01017 0 0H0.0541Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M128 96C74.9807 96 32 53.0193 32 -4.19629e-06"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'lod'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M64 0H128V128H64C28.6538 128 0 99.3462 0 64C0 28.6538 28.6538 0 64 0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M16 64C16 90.5097 37.4903 112 64 112"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'lom'
+ |= [fg=tape bg=tape]
+ :~ ;rect
+ =width "128"
+ =height "128"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;circle
+ =cx "32"
+ =cy "32"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "32"
+ =cy "32"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ;circle
+ =cx "96"
+ =cy "32"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "96"
+ =cy "32"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ;circle
+ =cx "96"
+ =cy "96"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "96"
+ =cy "96"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'lon'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M128 0C57.3075 8.42999e-07 -8.42999e-07 57.3075 0 128H128V0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M2.03434e-06 128C70.6924 128 128 70.6925 128 0"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M1.52575e-06 96C53.0193 96 96 53.0193 96 0"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M1.01717e-06 64C35.3462 64 64 35.3462 64 0"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M5.08584e-07 32C17.6731 32 32 17.6731 32 0"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'lop'
+ |= [fg=tape bg=tape]
+ :~ ;circle
+ =cx "64"
+ =cy "64"
+ =r "64"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "128"
+ =y1 "64"
+ =x2 "-8.87604e-09"
+ =y2 "64"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;line
+ =x1 "128"
+ =y1 "32"
+ =x2 "-8.87604e-09"
+ =y2 "32"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'lor'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M64 0H128V128H64C28.6538 128 0 99.3462 0 64C0 28.6538 28.6538 0 64 0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "64"
+ =y1 "2.18557e-08"
+ =x2 "64"
+ =y2 "128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'los'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M0 0C0 70.6925 57.3075 128 128 128V0H0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "-0.0029152"
+ =x2 "127.983"
+ =y2 "127.986"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;circle
+ =cx "96"
+ =cy "96"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "96"
+ =cy "96"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'luc'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M128 128C128 57.3076 70.6925 6.18013e-06 1.11901e-05 0L0 128L128 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "128"
+ =y1 "64"
+ =x2 "-8.87604e-09"
+ =y2 "64"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M128 64L0 64"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M128 96L0 96"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'lud'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M128 128C128 57.3076 70.6925 6.18013e-06 1.11901e-05 0L0 128L128 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M128 64L0 64"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M32 0L32 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M64 0L64 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M96 0L96 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'lug'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M64 128H0L5.59506e-06 -7.62939e-06L64 -2.03434e-06C99.3462 1.05573e-06 128 28.6538 128 64C128 99.3462 99.3462 128 64 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ==
+::
+ :- 'lun'
+ |= [fg=tape bg=tape]
+ :~ ;circle
+ =cx "64"
+ =cy "64"
+ =r "64"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "32"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'lup'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M64 128H0L5.59506e-06 -7.62939e-06L64 -2.03434e-06C99.3462 1.05573e-06 128 28.6538 128 64C128 99.3462 99.3462 128 64 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M64 16C90.5097 16 112 37.4903 112 64C112 90.5097 90.5097 112 64 112"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;line
+ =x1 "128"
+ =y1 "64"
+ =x2 "-8.87604e-09"
+ =y2 "64"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'lur'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M128 128C128 57.3076 70.6925 6.18013e-06 1.11901e-05 0L0 128L128 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M64 0L64 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M96 0L96 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M32 0L32 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'lus'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M128 128C128 57.3076 70.6925 6.18013e-06 1.11901e-05 0L0 128L128 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M128 0L0 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;circle
+ =cx "96"
+ =cy "96"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "96"
+ =cy "96"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'lut'
+ |= [fg=tape bg=tape]
+ :~ ;rect
+ =width "128"
+ =height "128"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;circle
+ =cx "32"
+ =cy "64"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "32"
+ =cy "64"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'lux'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M5.59506e-06 128C70.6925 128 128 70.6925 128 0L0 5.59506e-06L5.59506e-06 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =fill-rule "evenodd"
+ =clip-rule "evenodd"
+ =stroke "none"
+ =d "M80 64C80 72.8366 72.8366 80 64 80C55.1634 80 48 72.8366 48 64C48 55.1634 55.1634 48 64 48C72.8366 48 80 55.1634 80 64ZM64 72C68.4183 72 72 68.4183 72 64C72 59.5817 68.4183 56 64 56C59.5817 56 56 59.5817 56 64C56 68.4183 59.5817 72 64 72Z"
+ =fill bg;
+ ==
+::
+ :- 'lyd'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M0.0541 0C70.7217 0.0292317 128 57.3256 128 128C57.3177 128 0.0164917 70.7089 7.62806e-06 0.0305091C7.62851e-06 0.0203397 -4.44317e-10 0.01017 0 0H0.0541Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M-0.00280762 0L127.997 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "32"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;circle
+ =cx "64"
+ =cy "32"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "64"
+ =cy "32"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'lyn'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M5.59506e-06 128C70.6925 128 128 70.6925 128 0L0 5.59506e-06L5.59506e-06 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M32 0L32 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'lyr'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M0 127.946C0.0292286 57.2783 57.3256 3.08928e-06 128 0C128 70.6823 70.7089 127.984 0.0305092 128C0.0203397 128 0.01017 128 2.36469e-09 128L0 127.946Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M-0.00268555 0L127.997 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;circle
+ =cx "80"
+ =cy "48"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "80"
+ =cy "48"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'lys'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M128 128C128 57.3076 70.6925 6.18013e-06 1.11901e-05 0L0 128L128 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ;circle
+ =cx "16"
+ =cy "112"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "16"
+ =cy "112"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'lyt'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M64 128H0L5.59506e-06 0L64 5.59506e-06C99.3462 8.68512e-06 128 28.6538 128 64C128 99.3462 99.3462 128 64 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M128 0L0 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;line
+ =x1 "80.0035"
+ =y1 "79.9965"
+ =x2 "112.003"
+ =y2 "111.997"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "16"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'lyx'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M5.59506e-06 128C70.6925 128 128 70.6925 128 0L0 5.59506e-06L5.59506e-06 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M-0.00292969 0L127.997 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;circle
+ =cx "32"
+ =cy "32"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "32"
+ =cy "32"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'mac'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M0 0C0 70.6925 57.3075 128 128 128V0H0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;circle
+ =cx "16"
+ =cy "112"
+ =r "11.5"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ ;circle
+ =cx "16"
+ =cy "112"
+ =r "9"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ :: =stroke-width "2"
+ ==
+::
+ :- 'mag'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M64 0H128V128H64C28.6538 128 0 99.3462 0 64C0 28.6538 28.6538 0 64 0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "32"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M128 64L0 64"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;circle
+ =cx "64"
+ =cy "96"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "64"
+ =cy "96"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'mal'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M0.0541 0C70.7217 0.0292317 128 57.3256 128 128C57.3177 128 0.0164917 70.7089 7.62806e-06 0.0305091C7.62851e-06 0.0203397 -4.44317e-10 0.01017 0 0H0.0541Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "80.0035"
+ =y1 "79.9964"
+ =x2 "112.004"
+ =y2 "111.996"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;circle
+ =cx "16"
+ =cy "112"
+ =r "11.5"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ ;circle
+ =cx "16"
+ =cy "112"
+ =r "9"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ :: =stroke-width "2"
+ ==
+::
+ :- 'map'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M128 0C57.3075 8.42999e-07 -8.42999e-07 57.3075 0 128H128V0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "80.0036"
+ =y1 "79.9965"
+ =x2 "112.004"
+ =y2 "111.997"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'mar'
+ |= [fg=tape bg=tape]
+ :~ ;circle
+ =cx "64"
+ =cy "64"
+ =r "64"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M-0.0029152 0L127.997 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;path
+ =d "M64 64L64 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M86.6274 86.6274C99.1242 74.1307 99.1242 53.8694 86.6274 41.3726C74.1306 28.8758 53.8694 28.8758 41.3726 41.3726"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M75.3137 75.3137C81.5621 69.0653 81.5621 58.9347 75.3137 52.6863C69.0653 46.4379 58.9347 46.4379 52.6863 52.6863"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M97.9411 97.9411C116.686 79.1959 116.686 48.804 97.9411 30.0589C79.196 11.3137 48.804 11.3137 30.0589 30.0589"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'mas'
+ |= [fg=tape bg=tape]
+ :~ ;rect
+ =width "128"
+ =height "128"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "32"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =fill-rule "evenodd"
+ =clip-rule "evenodd"
+ =stroke "none"
+ =d "M80 64C80 72.8366 72.8366 80 64 80C55.1634 80 48 72.8366 48 64C48 55.1634 55.1634 48 64 48C72.8366 48 80 55.1634 80 64ZM64 72C68.4183 72 72 68.4183 72 64C72 59.5817 68.4183 56 64 56C59.5817 56 56 59.5817 56 64C56 68.4183 59.5817 72 64 72Z"
+ =fill bg;
+ ==
+::
+ :- 'mat'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M0 0C0 70.6925 57.3075 128 128 128V0H0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M128 32C110.327 32 96 17.6731 96 0"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'meb'
+ |= [fg=tape bg=tape]
+ :~ ;rect
+ =width "128"
+ =height "128"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M32 -3.05151e-06C32 53.0193 74.9807 96 128 96"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'mec'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M128 128C128 57.3076 70.6925 6.18013e-06 1.11901e-05 0L0 128L128 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "80.0035"
+ =y1 "79.9965"
+ =x2 "112.003"
+ =y2 "111.997"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'med'
+ |= [fg=tape bg=tape]
+ :~ ;circle
+ =cx "64"
+ =cy "64"
+ =r "64"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;circle
+ =cx "96"
+ =cy "64"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "96"
+ =cy "64"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'meg'
+ |= [fg=tape bg=tape]
+ :~ ;rect
+ =width "128"
+ =height "128"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M128 64C92.6538 64 64 92.6538 64 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'mel'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M0 127.946C0.0292286 57.2783 57.3256 3.08928e-06 128 0C128 70.6823 70.7089 127.984 0.0305092 128C0.0203397 128 0.01017 128 2.36469e-09 128L0 127.946Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "15.9964"
+ =y1 "111.997"
+ =x2 "47.9964"
+ =y2 "79.9965"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'mep'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M128 0C57.3075 8.42999e-07 -8.42999e-07 57.3075 0 128H128V0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M128 64L0 64"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M128 96L0 96"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M128 32L0 32"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'mer'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M64 128H0L5.59506e-06 0L64 5.59506e-06C99.3462 8.68512e-06 128 28.6538 128 64C128 99.3462 99.3462 128 64 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M32 0L32 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'mes'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M128 128C128 57.3076 70.6925 6.18013e-06 1.11901e-05 0L0 128L128 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M-0.00280762 0L127.997 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;line
+ =x1 "15.9964"
+ =y1 "111.996"
+ =x2 "47.9964"
+ =y2 "79.9964"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'met'
+ |= [fg=tape bg=tape]
+ :~ ;circle
+ =cx "64"
+ =cy "64"
+ =r "64"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M32 128L32 0"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'mev'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M64 128H0L5.59506e-06 0L64 5.59506e-06C99.3462 8.68512e-06 128 28.6538 128 64C128 99.3462 99.3462 128 64 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "16"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'mex'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M64 128H0L5.59506e-06 0L64 5.59506e-06C99.3462 8.68512e-06 128 28.6538 128 64C128 99.3462 99.3462 128 64 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M-0.00292969 0L127.997 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;path
+ =fill-rule "evenodd"
+ =clip-rule "evenodd"
+ =stroke "none"
+ =d "M80 64C80 72.8366 72.8366 80 64 80C55.1634 80 48 72.8366 48 64C48 55.1634 55.1634 48 64 48C72.8366 48 80 55.1634 80 64ZM64 72C68.4183 72 72 68.4183 72 64C72 59.5817 68.4183 56 64 56C59.5817 56 56 59.5817 56 64C56 68.4183 59.5817 72 64 72Z"
+ =fill bg;
+ ==
+::
+ :- 'mic'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M128 128C128 57.3076 70.6925 6.18013e-06 1.11901e-05 0L0 128L128 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M-2.09815e-06 80C26.5097 80 48 101.49 48 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'mid'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M0 0C0 70.6925 57.3075 128 128 128V0H0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "128"
+ =y1 "64"
+ =x2 "-4.37114e-08"
+ =y2 "64"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M128 64C92.6538 64 64 92.6538 64 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'mig'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M64 0H128V128H64C28.6538 128 0 99.3462 0 64C0 28.6538 28.6538 0 64 0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "64"
+ =y1 "2.18557e-08"
+ =x2 "64"
+ =y2 "128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;line
+ =x1 "80.0036"
+ =y1 "79.9965"
+ =x2 "112.004"
+ =y2 "111.997"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "16"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'mil'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M64 0H128V128H64C28.6538 128 0 99.3462 0 64C0 28.6538 28.6538 0 64 0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "128"
+ =y1 "64"
+ =x2 "-4.37114e-08"
+ =y2 "64"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;line
+ =x1 "128"
+ =y1 "32"
+ =x2 "-4.37114e-08"
+ =y2 "32"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;line
+ =x1 "128"
+ =y1 "96"
+ =x2 "-4.37114e-08"
+ =y2 "96"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'min'
+ |= [fg=tape bg=tape]
+ :~ ;rect
+ =width "128"
+ =height "128"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "-0.0029152"
+ =x2 "127.983"
+ =y2 "127.986"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ==
+::
+ :- 'mip'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M128 0C57.3075 8.42999e-07 -8.42999e-07 57.3075 0 128H128V0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "64"
+ =y1 "2.18557e-08"
+ =x2 "64"
+ =y2 "128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M128 128C92.6538 128 64 99.3462 64 64C64 28.6538 92.6538 4.215e-07 128 0"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "16"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'mir'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M0 0C0 70.6925 57.3075 128 128 128V0H0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "16.0036"
+ =y1 "15.9964"
+ =x2 "48.0036"
+ =y2 "47.9964"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M96 64C96 46.3269 81.6731 32 64 32"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "16"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'mis'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M128 0C57.3075 8.42999e-07 -8.42999e-07 57.3075 0 128H128V0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M128 64C92.6538 64 64 92.6538 64 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M-0.00286865 0L127.997 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ==
+::
+ :- 'mit'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M0.0541 0C70.7217 0.0292317 128 57.3256 128 128C57.3177 128 0.0164917 70.7089 7.62806e-06 0.0305091C7.62851e-06 0.0203397 -4.44317e-10 0.01017 0 0H0.0541Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "0.5"
+ =y1 "-0.5"
+ =x2 "181.5"
+ =y2 "-0.5"
+ =transform "matrix(-0.707107 0.707107 0.707107 0.707107 128.71 0)"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;circle
+ =cx "32"
+ =cy "32"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "32"
+ =cy "32"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'moc'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M0.0541 0C70.7217 0.0292317 128 57.3256 128 128C57.3177 128 0.0164917 70.7089 7.62806e-06 0.0305091C7.62851e-06 0.0203397 -4.44317e-10 0.01017 0 0H0.0541Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M128 64L0 64"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M128 96L0 96"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M128 32L0 32"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'mod'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M64 0H128V128H64C28.6538 128 0 99.3462 0 64C0 28.6538 28.6538 0 64 0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M0 96L128 96"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;line
+ =x1 "16.0035"
+ =y1 "15.9965"
+ =x2 "48.0035"
+ =y2 "47.9965"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'mog'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M128 0C57.3075 8.42999e-07 -8.42999e-07 57.3075 0 128H128V0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "-0.0029152"
+ =x2 "127.983"
+ =y2 "127.986"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "32"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "16"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'mol'
+ |= [fg=tape bg=tape]
+ :~ ;circle
+ =cx "64"
+ =cy "64"
+ =r "64"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "128"
+ =y1 "64"
+ =x2 "-4.37114e-08"
+ =y2 "64"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M112 64C112 90.5097 90.5097 112 64 112C37.4903 112 16 90.5097 16 64"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M112 0C112 26.5097 90.5097 48 64 48C37.4903 48 16 26.5097 16 0"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'mon'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M128 0C57.3075 8.42999e-07 -8.42999e-07 57.3075 0 128H128V0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =fill-rule "evenodd"
+ =clip-rule "evenodd"
+ =stroke "none"
+ =d "M80 64C80 72.8366 72.8366 80 64 80C55.1634 80 48 72.8366 48 64C48 55.1634 55.1634 48 64 48C72.8366 48 80 55.1634 80 64ZM64 72C68.4183 72 72 68.4183 72 64C72 59.5817 68.4183 56 64 56C59.5817 56 56 59.5817 56 64C56 68.4183 59.5817 72 64 72Z"
+ =fill bg;
+ ==
+::
+ :- 'mop'
+ |= [fg=tape bg=tape]
+ :~ ;circle
+ =cx "64"
+ =cy "64"
+ =r "64"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "-0.0029152"
+ =x2 "127.983"
+ =y2 "127.986"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "32"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;circle
+ =cx "32"
+ =cy "64"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "32"
+ =cy "64"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'mor'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M64 0H128V128H64C28.6538 128 0 99.3462 0 64C0 28.6538 28.6538 0 64 0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "16.0035"
+ =y1 "15.9964"
+ =x2 "48.0035"
+ =y2 "47.9964"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;line
+ =x1 "15.9964"
+ =y1 "111.996"
+ =x2 "47.9964"
+ =y2 "79.9964"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'mos'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M0 0C0 70.6925 57.3075 128 128 128V0H0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "0.5"
+ =y1 "-0.5"
+ =x2 "181.5"
+ =y2 "-0.5"
+ =transform "matrix(-0.707107 0.707107 0.707107 0.707107 128.71 0)"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;circle
+ =cx "96"
+ =cy "32"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "96"
+ =cy "32"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'mot'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M64 0H128V128H64C28.6538 128 0 99.3462 0 64C0 28.6538 28.6538 0 64 0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M128 96C110.327 96 96 81.6731 96 64C96 46.3269 110.327 32 128 32"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'mud'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M128 128C128 57.3076 70.6925 6.18013e-06 1.11901e-05 0L0 128L128 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M-0.00292969 0L127.997 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;circle
+ =cx "80"
+ =cy "80"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "80"
+ =cy "80"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'mug'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M64 128H0L5.59506e-06 0L64 5.59506e-06C99.3462 8.68512e-06 128 28.6538 128 64C128 99.3462 99.3462 128 64 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M64 96C81.6731 96 96 81.6731 96 64C96 46.3269 81.6731 32 64 32"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'mul'
+ |= [fg=tape bg=tape]
+ :~ ;circle
+ =cx "64"
+ =cy "64"
+ =r "64"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "80.0035"
+ =y1 "79.9964"
+ =x2 "112.003"
+ =y2 "111.996"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M112 64C112 37.4903 90.5097 16 64 16"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'mun'
+ |= [fg=tape bg=tape]
+ :~ ;circle
+ =cx "64"
+ =cy "64"
+ =r "64"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M128 64C92.6538 64 64 35.3462 64 0"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'mur'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M128 128C128 57.3076 70.6925 6.18013e-06 1.11901e-05 0L0 128L128 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M128 64L0 64"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ;circle
+ =cx "32"
+ =cy "64"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "32"
+ =cy "64"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'mus'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M128 128C128 57.3076 70.6925 6.18013e-06 1.11901e-05 0L0 128L128 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "0.5"
+ =y1 "-0.5"
+ =x2 "181.5"
+ =y2 "-0.5"
+ =transform "matrix(-0.707107 0.707107 0.707107 0.707107 128.71 0)"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;path
+ =d "M96 128C96 74.9807 53.0193 32 0 32"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'mut'
+ |= [fg=tape bg=tape]
+ :~ ;rect
+ =width "128"
+ =height "128"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;circle
+ =cx "96"
+ =cy "32"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "96"
+ =cy "32"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'myl'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M5.59506e-06 128C70.6925 128 128 70.6925 128 0L0 5.59506e-06L5.59506e-06 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "16.0035"
+ =y1 "15.9965"
+ =x2 "48.0035"
+ =y2 "47.9965"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;circle
+ =cx "16"
+ =cy "16"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "16"
+ =cy "16"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'myn'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M5.59506e-06 128C70.6925 128 128 70.6925 128 0L0 5.59506e-06L5.59506e-06 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M128 1.52638e-06C57.3076 -7.74381e-06 9.2702e-06 57.3075 0 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M128 32C74.9807 32 32 74.9807 32 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M128 64C92.6538 64 64 92.6538 64 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M128 96C110.327 96 96 110.327 96 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'myr'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M0 127.946C0.0292286 57.2783 57.3256 3.08928e-06 128 0C128 70.6823 70.7089 127.984 0.0305092 128C0.0203397 128 0.01017 128 2.36469e-09 128L0 127.946Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M-0.00292969 0L127.997 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;circle
+ =cx "32"
+ =cy "96"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "32"
+ =cy "96"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'nac'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M0 0C0 70.6925 57.3075 128 128 128V0H0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "16"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;circle
+ =cx "16"
+ =cy "112"
+ =r "11.5"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ ;circle
+ =cx "16"
+ =cy "112"
+ =r "9"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ :: =stroke-width "2"
+ ==
+::
+ :- 'nal'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M0.0541 0C70.7217 0.0292317 128 57.3256 128 128C57.3177 128 0.0164917 70.7089 7.62806e-06 0.0305091C7.62851e-06 0.0203397 -4.44317e-10 0.01017 0 0H0.0541Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "-0.0029152"
+ =x2 "127.983"
+ =y2 "127.986"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;path
+ =d "M2.82114e-06 110C60.7513 110 110 60.7513 110 0"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M-5.09828e-06 73C40.3168 73 73 40.3168 73 0"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M-6.63647e-07 37C20.4345 37 37 20.4345 37 0"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'nam'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M64 0H128V128H64C28.6538 128 0 99.3462 0 64C0 28.6538 28.6538 0 64 0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "8.74228e-08"
+ =y1 "64"
+ =x2 "128"
+ =y2 "64"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ;circle
+ =cx "112"
+ =cy "64"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "112"
+ =cy "64"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'nap'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M128 0C57.3075 8.42999e-07 -8.42999e-07 57.3075 0 128H128V0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "64"
+ =y1 "2.18557e-08"
+ =x2 "64"
+ =y2 "128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;circle
+ =cx "96"
+ =cy "32"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "96"
+ =cy "32"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ;circle
+ =cx "96"
+ =cy "96"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "96"
+ =cy "96"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'nar'
+ |= [fg=tape bg=tape]
+ :~ ;circle
+ =cx "64"
+ =cy "64"
+ =r "64"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "32"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "8"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'nat'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M0 0C0 70.6925 57.3075 128 128 128V0H0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M-1.52588e-05 128C-9.07866e-06 57.3075 57.3076 1.44926e-06 128 7.62939e-06"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'nav'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M0 0C0 70.6925 57.3075 128 128 128V0H0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M128 96C101.492 96 77.4939 85.2564 60.1217 67.8862"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M128 64C110.328 64 94.3287 56.8374 82.7471 45.2568"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M128 32.3716C119.164 32.3716 111.164 28.7903 105.374 23"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'neb'
+ |= [fg=tape bg=tape]
+ :~ ;rect
+ =width "128"
+ =height "128"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M128 32C74.9807 32 32 74.9807 32 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'nec'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M128 128C128 57.3076 70.6925 6.18013e-06 1.11901e-05 0L0 128L128 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;circle
+ =cx "32"
+ =cy "32"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "32"
+ =cy "32"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ;circle
+ =cx "96"
+ =cy "96"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "96"
+ =cy "96"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ;path
+ =d "M64 0L64 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'ned'
+ |= [fg=tape bg=tape]
+ :~ ;circle
+ =cx "64"
+ =cy "64"
+ =r "64"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'nel'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M0 127.946C0.0292286 57.2783 57.3256 3.08928e-06 128 0C128 70.6823 70.7089 127.984 0.0305092 128C0.0203397 128 0.01017 128 2.36469e-09 128L0 127.946Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M-0.00268555 0L127.997 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;path
+ =d "M96 1.90735e-06C96 53.0193 53.0193 96 0 96"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'nem'
+ |= [fg=tape bg=tape]
+ :~ ;circle
+ =cx "64"
+ =cy "64"
+ =r "64"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M-0.00292969 0L127.997 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;path
+ =d "M128 64C92.6538 64 64 92.6538 64 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;circle
+ =cx "32"
+ =cy "32"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "32"
+ =cy "32"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'nep'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M128 128C128 57.3076 70.6925 6.18013e-06 1.11901e-05 0L0 128L128 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M128 128C57.3076 128 3.09007e-06 70.6925 0 0"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M128 96C74.9807 96 32 53.0193 32 0"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M128 64C92.6538 64 64 35.3462 64 0"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M128 32C110.327 32 96 17.6731 96 0"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'ner'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M64 128H0L5.59506e-06 0L64 5.59506e-06C99.3462 8.68512e-06 128 28.6538 128 64C128 99.3462 99.3462 128 64 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M64 0L64 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;line
+ =x1 "15.9965"
+ =y1 "111.997"
+ =x2 "47.9965"
+ =y2 "79.9965"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'nes'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M128 0C57.3075 8.42999e-07 -8.42999e-07 57.3075 0 128H128V0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M64 0L64 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'net'
+ |= [fg=tape bg=tape]
+ :~ ;circle
+ =cx "64"
+ =cy "64"
+ =r "64"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M64 64L64 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'nev'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M64 128H0L5.59506e-06 0L64 5.59506e-06C99.3462 8.68512e-06 128 28.6538 128 64C128 99.3462 99.3462 128 64 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "16"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;circle
+ =cx "32"
+ =cy "32"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "32"
+ =cy "32"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'nex'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M64 128H0L5.59506e-06 -7.62939e-06L64 -2.03434e-06C99.3462 1.05573e-06 128 28.6538 128 64C128 99.3462 99.3462 128 64 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "80.0035"
+ =y1 "79.9964"
+ =x2 "112.003"
+ =y2 "111.996"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =fill-rule "evenodd"
+ =clip-rule "evenodd"
+ =stroke "none"
+ =d "M80 64C80 72.8366 72.8366 80 64 80C55.1634 80 48 72.8366 48 64C48 55.1634 55.1634 48 64 48C72.8366 48 80 55.1634 80 64ZM64 72C68.4183 72 72 68.4183 72 64C72 59.5817 68.4183 56 64 56C59.5817 56 56 59.5817 56 64C56 68.4183 59.5817 72 64 72Z"
+ =fill bg;
+ ==
+::
+ :- 'nib'
+ |= [fg=tape bg=tape]
+ :~ ;circle
+ =cx "64"
+ =cy "64"
+ =r "64"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M128 64L0 64"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M128 96L0 96"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'nid'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M0 0C0 70.6925 57.3075 128 128 128V0H0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M128 64L0 64"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M128 128C92.6538 128 64 70.6925 64 7.63192e-07"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'nil'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M64 0H128V128H64C28.6538 128 0 99.3462 0 64C0 28.6538 28.6538 0 64 0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "128"
+ =y1 "64"
+ =x2 "-8.87604e-09"
+ =y2 "64"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;line
+ =x1 "128"
+ =y1 "32"
+ =x2 "-8.87604e-09"
+ =y2 "32"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'nim'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M128 64V128H0L2.79753e-06 64C4.34256e-06 28.6538 28.6538 -1.54503e-06 64 0C99.3462 1.54503e-06 128 28.6538 128 64Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "64"
+ =y1 "2.18557e-08"
+ =x2 "64"
+ =y2 "128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'nis'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M128 0C57.3075 8.42999e-07 -8.42999e-07 57.3075 0 128H128V0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M128 32C74.9807 32 32 74.9807 32 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M-0.00285435 0L127.997 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ==
+::
+ :- 'noc'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M64 0H128V128H64C28.6538 128 0 99.3462 0 64C0 28.6538 28.6538 0 64 0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "64"
+ =y1 "2.18557e-08"
+ =x2 "64"
+ =y2 "128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'nod'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M64 0H128V128H64C28.6538 128 0 99.3462 0 64C0 28.6538 28.6538 0 64 0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;circle
+ =cx "32"
+ =cy "64"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "32"
+ =cy "64"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ;circle
+ =cx "96"
+ =cy "64"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "96"
+ =cy "64"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'nol'
+ |= [fg=tape bg=tape]
+ :~ ;circle
+ =cx "64"
+ =cy "64"
+ =r "64"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "128"
+ =y1 "64"
+ =x2 "1.51277e-05"
+ =y2 "64"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;circle
+ =cx "64"
+ =cy "96"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "64"
+ =cy "96"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'nom'
+ |= [fg=tape bg=tape]
+ :~ ;rect
+ =width "128"
+ =height "128"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;circle
+ =cx "32"
+ =cy "96"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "32"
+ =cy "96"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ;circle
+ =cx "96"
+ =cy "96"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "96"
+ =cy "96"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ;circle
+ =cx "96"
+ =cy "32"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "96"
+ =cy "32"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'nop'
+ |= [fg=tape bg=tape]
+ :~ ;circle
+ =cx "64"
+ =cy "64"
+ =r "64"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "-0.0029152"
+ =x2 "127.983"
+ =y2 "127.986"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;line
+ =y1 "-0.5"
+ =x2 "45.2548"
+ =y2 "-0.5"
+ =transform "matrix(0.707107 -0.707107 -0.707107 -0.707107 79.65 47.65)"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'nor'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M64 0H128V128H64C28.6538 128 0 99.3462 0 64C0 28.6538 28.6538 0 64 0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M64 96C46.3269 96 32 81.6731 32 64"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'nos'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M0 0C0 70.6925 57.3075 128 128 128V0H0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "0.5"
+ =y1 "-0.5"
+ =x2 "181.5"
+ =y2 "-0.5"
+ =transform "matrix(-0.707107 0.707107 0.707107 0.707107 128.71 0)"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;circle
+ =cx "32"
+ =cy "32"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "32"
+ =cy "32"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'nov'
+ |= [fg=tape bg=tape]
+ :~ ;rect
+ =width "128"
+ =height "128"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "-0.0029152"
+ =x2 "127.983"
+ =y2 "127.986"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;path
+ =d "M2.03434e-06 128C70.6924 128 128 70.6925 128 0"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M1.52575e-06 96C53.0193 96 96 53.0193 96 0"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M1.01717e-06 64C35.3462 64 64 35.3462 64 0"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M5.08584e-07 32C17.6731 32 32 17.6731 32 0"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'nub'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M128 128C128 57.3076 70.6925 6.18013e-06 1.11901e-05 0L0 128L128 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M128 64L0 64"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'nul'
+ |= [fg=tape bg=tape]
+ :~ ;circle
+ =cx "64"
+ =cy "64"
+ =r "64"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "32"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;circle
+ =cx "32"
+ =cy "64"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "32"
+ =cy "64"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'num'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M128 128C128 57.3076 70.6925 6.18013e-06 1.11901e-05 0L0 128L128 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M128 0L0 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;circle
+ =cx "32"
+ =cy "32"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "32"
+ =cy "32"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ;circle
+ =cx "96"
+ =cy "96"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "96"
+ =cy "96"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'nup'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M64 128H0L5.59506e-06 -7.62939e-06L64 -2.03434e-06C99.3462 1.05573e-06 128 28.6538 128 64C128 99.3462 99.3462 128 64 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M64 16C90.5097 16 112 37.4903 112 64C112 90.5097 90.5097 112 64 112"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'nus'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M128 128C128 57.3076 70.6925 6.18013e-06 1.11901e-05 0L0 128L128 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M-0.00280762 0L127.997 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;path
+ =d "M0.000105172 128C35.3582 128 67.3679 113.664 90.5332 90.4863"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;circle
+ =cx "31"
+ =cy "32"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "31"
+ =cy "32"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'nut'
+ |= [fg=tape bg=tape]
+ :~ ;rect
+ =width "128"
+ =height "128"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "80.0035"
+ =y1 "79.9964"
+ =x2 "112.003"
+ =y2 "111.996"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;line
+ =y1 "-0.5"
+ =x2 "45.2548"
+ =y2 "-0.5"
+ =transform "matrix(0.707107 -0.707107 -0.707107 -0.707107 79.6499 47.6499)"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;circle
+ =cx "96"
+ =cy "96"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "96"
+ =cy "96"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'nux'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M128 128C128 57.3076 70.6925 6.18013e-06 1.11901e-05 0L0 128L128 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M128 64L0 64"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M128 96L0 96"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M128 32L0 32"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'nyd'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M0.0541 0C70.7217 0.0292317 128 57.3256 128 128C57.3177 128 0.0164917 70.7089 7.62806e-06 0.0305091C7.62851e-06 0.0203397 -4.44317e-10 0.01017 0 0H0.0541Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M-0.00292969 0L127.997 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "32"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "16"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'nyl'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M128 128C128 57.3076 70.6925 6.18013e-06 1.11901e-05 0L0 128L128 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M-0.00292969 0L127.997 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;path
+ =d "M0 128C4.63574e-06 92.6489 14.3309 60.6449 37.5 37.4807"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M32 128C32 101.492 42.7436 77.4939 60.1138 60.1217"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M64 128C64 110.328 71.1626 94.3287 82.7432 82.7471"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M95.6284 128C95.6284 119.164 99.2097 111.164 105 105.374"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'nym'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M5.59506e-06 128C70.6925 128 128 70.6925 128 0L0 5.59506e-06L5.59506e-06 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M64 0L64 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M96 0L96 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M32 0L32 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'nyr'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M0 127.946C0.0292286 57.2783 57.3256 3.08928e-06 128 0C128 70.6823 70.7089 127.984 0.0305092 128C0.0203397 128 0.01017 128 2.36469e-09 128L0 127.946Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M-0.00268555 0L127.997 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;path
+ =d "M95.9984 0C95.9984 26.3298 85.3985 50.1839 68.2332 67.5278M63.9983 0C63.9983 17.4933 56.9799 33.3473 45.6054 44.8999M31.9983 0C31.9983 8.65672 28.5609 16.5106 22.9766 22.2711"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'nys'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M128 128C128 57.3076 70.6925 6.18013e-06 1.11901e-05 0L0 128L128 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;circle
+ =cx "16"
+ =cy "112"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "16"
+ =cy "112"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'nyt'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M64 128H0L5.59506e-06 0L64 5.59506e-06C99.3462 8.68512e-06 128 28.6538 128 64C128 99.3462 99.3462 128 64 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M128 64L0 64"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M64 32C81.6731 32 96 46.3269 96 64"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M64 16C90.5097 16 112 37.4903 112 64"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'nyx'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M5.59506e-06 128C70.6925 128 128 70.6925 128 0L0 5.59506e-06L5.59506e-06 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M-0.00292969 0L127.997 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;path
+ =fill-rule "evenodd"
+ =clip-rule "evenodd"
+ =stroke "none"
+ =d "M80 64C80 72.8366 72.8366 80 64 80C55.1634 80 48 72.8366 48 64C48 55.1634 55.1634 48 64 48C72.8366 48 80 55.1634 80 64ZM64 72C68.4183 72 72 68.4183 72 64C72 59.5817 68.4183 56 64 56C59.5817 56 56 59.5817 56 64C56 68.4183 59.5817 72 64 72Z"
+ =fill bg;
+ ==
+::
+ :- 'pac'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M0 0C0 70.6925 57.3075 128 128 128V0H0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M128 0L0 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "16"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;circle
+ =cx "64"
+ =cy "32"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "64"
+ =cy "32"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'pad'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M0 0C0 70.6925 57.3075 128 128 128V0H0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;circle
+ =cx "96"
+ =cy "32"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "96"
+ =cy "32"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'pag'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M64 0H128V128H64C28.6538 128 0 99.3462 0 64C0 28.6538 28.6538 0 64 0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "15.9964"
+ =y1 "111.997"
+ =x2 "47.9964"
+ =y2 "79.9965"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'pal'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M0.0541 0C70.7217 0.0292317 128 57.3256 128 128C57.3177 128 0.0164917 70.7089 7.62806e-06 0.0305091C7.62851e-06 0.0203397 -4.44317e-10 0.01017 0 0H0.0541Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M128 0L0 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;path
+ =d "M128 96C101.492 96 77.4939 85.2564 60.1217 67.8862"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M128 64C110.328 64 94.3287 56.8374 82.7471 45.2568"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M128 32.3716C119.164 32.3716 111.164 28.7903 105.374 23"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'pan'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M0 0C0 70.6925 57.3075 128 128 128V0H0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "0.5"
+ =y1 "-0.5"
+ =x2 "181.5"
+ =y2 "-0.5"
+ =transform "matrix(-0.707107 0.707107 0.707107 0.707107 128.71 0)"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;path
+ =d "M41.3726 86.6274C28.8758 74.1306 28.8758 53.8693 41.3726 41.3725C53.8694 28.8758 74.1306 28.8758 86.6274 41.3725"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'par'
+ |= [fg=tape bg=tape]
+ :~ ;circle
+ =cx "64"
+ =cy "64"
+ =r "64"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "0.5"
+ =y1 "-0.5"
+ =x2 "181.5"
+ =y2 "-0.5"
+ =transform "matrix(-0.707107 0.707107 0.707107 0.707107 128.693 0)"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "16"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'pas'
+ |= [fg=tape bg=tape]
+ :~ ;rect
+ =width "128"
+ =height "128"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M32 0L32 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M64 0L64 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M96 0L96 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'pat'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M0 0C0 70.6925 57.3075 128 128 128V0H0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M32 -2.67054e-06C32 53.0193 74.9807 96 128 96"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M64 -1.78036e-06C64 35.3462 92.6538 64 128 64"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M96 -8.9018e-07C96 17.6731 110.327 32 128 32"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'pec'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M128 128C128 57.3076 70.6925 6.18013e-06 1.11901e-05 0L0 128L128 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M128 0L0 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'ped'
+ |= [fg=tape bg=tape]
+ :~ ;circle
+ =cx "64"
+ =cy "64"
+ =r "64"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;circle
+ =cx "32"
+ =cy "64"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "32"
+ =cy "64"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'peg'
+ |= [fg=tape bg=tape]
+ :~ ;rect
+ =width "128"
+ =height "128"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M96 0C96 17.6731 81.6731 32 64 32C46.3269 32 32 17.6731 32 0"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'pel'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M0 127.946C0.0292286 57.2783 57.3256 3.08928e-06 128 0C128 70.6823 70.7089 127.984 0.0305092 128C0.0203397 128 0.01017 128 2.36469e-09 128L0 127.946Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "32"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M112 64C112 37.4903 90.5097 16 64 16"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'pem'
+ |= [fg=tape bg=tape]
+ :~ ;circle
+ =cx "64"
+ =cy "64"
+ =r "64"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M-0.00280762 0L127.997 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;path
+ =d "M64 128C64 92.6538 35.3462 64 0 64"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'pen'
+ |= [fg=tape bg=tape]
+ :~ ;rect
+ =width "128"
+ =height "128"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M96 0C96 17.6731 81.6731 32 64 32C46.3269 32 32 17.6731 32 0"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M-0.00292969 0L127.997 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ==
+::
+ :- 'per'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M0 64L5.59506e-06 0L128 1.11901e-05V64C128 99.3462 99.3462 128 64 128C28.6538 128 -4.6351e-06 99.3462 0 64Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M64 0L64 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'pes'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M128 0C57.3075 8.42999e-07 -8.42999e-07 57.3075 0 128H128V0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M64 112C90.5097 112 112 90.5097 112 64"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;line
+ =x1 "-0.00285417"
+ =x2 "127.983"
+ =y2 "127.986"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ==
+::
+ :- 'pet'
+ |= [fg=tape bg=tape]
+ :~ ;circle
+ =cx "64"
+ =cy "64"
+ =r "64"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "80.0035"
+ =y1 "79.9964"
+ =x2 "112.003"
+ =y2 "111.996"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'pex'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M64 128H0L5.59506e-06 0L64 5.59506e-06C99.3462 8.68512e-06 128 28.6538 128 64C128 99.3462 99.3462 128 64 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "32"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =fill-rule "evenodd"
+ =clip-rule "evenodd"
+ =stroke "none"
+ =d "M80 64C80 72.8366 72.8366 80 64 80C55.1634 80 48 72.8366 48 64C48 55.1634 55.1634 48 64 48C72.8366 48 80 55.1634 80 64ZM64 72C68.4183 72 72 68.4183 72 64C72 59.5817 68.4183 56 64 56C59.5817 56 56 59.5817 56 64C56 68.4183 59.5817 72 64 72Z"
+ =fill bg;
+ ==
+::
+ :- 'pic'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M128 128C128 57.3076 70.6925 6.18013e-06 1.11901e-05 0L0 128L128 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M96 128C96 74.9807 53.0193 32 0 32"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M64 128C64 92.6538 35.3462 64 0 64"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M32 128C32 110.327 17.6731 96 0 96"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'pid'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M0 0C0 70.6925 57.3075 128 128 128V0H0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "-0.0029152"
+ =x2 "127.983"
+ =y2 "127.986"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;circle
+ =cx "16"
+ =cy "112"
+ =r "11.5"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ ;circle
+ =cx "16"
+ =cy "112"
+ =r "9"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ :: =stroke-width "2"
+ ==
+::
+ :- 'pil'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M64 0H128V128H64C28.6538 128 0 99.3462 0 64C0 28.6538 28.6538 0 64 0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "0.5"
+ =y1 "-0.5"
+ =x2 "181.5"
+ =y2 "-0.5"
+ =transform "matrix(-0.707107 0.707107 0.707107 0.707107 128.71 0)"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;circle
+ =cx "96"
+ =cy "96"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "96"
+ =cy "96"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'pin'
+ |= [fg=tape bg=tape]
+ :~ ;rect
+ =width "128"
+ =height "128"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M32 0L32 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;circle
+ =cx "32"
+ =cy "32"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "32"
+ =cy "32"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'pit'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M0.0541 0C70.7217 0.0292317 128 57.3256 128 128C57.3177 128 0.0164917 70.7089 7.62806e-06 0.0305091C7.62851e-06 0.0203397 -4.44317e-10 0.01017 0 0H0.0541Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "0.5"
+ =y1 "-0.5"
+ =x2 "181.5"
+ =y2 "-0.5"
+ =transform "matrix(-0.707107 0.707107 0.707107 0.707107 128.71 0)"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;circle
+ =cx "16"
+ =cy "112"
+ =r "11.5"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ ;circle
+ =cx "16"
+ =cy "112"
+ =r "9"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ :: =stroke-width "2"
+ ==
+::
+ :- 'poc'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M0.0541 0C70.7217 0.0292317 128 57.3256 128 128C57.3177 128 0.0164917 70.7089 7.62806e-06 0.0305091C7.62851e-06 0.0203397 -4.44317e-10 0.01017 0 0H0.0541Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "64.5"
+ =y1 "-0.5"
+ =x2 "64.5"
+ =y2 "127.5"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;line
+ =x1 "96.5"
+ =y1 "-0.5"
+ =x2 "96.5"
+ =y2 "127.5"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;line
+ =x1 "32.5"
+ =y1 "-0.5"
+ =x2 "32.5"
+ =y2 "127.5"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'pod'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M64 0H128V128H64C28.6538 128 0 99.3462 0 64C0 28.6538 28.6538 0 64 0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "128"
+ =y1 "96"
+ =x2 "-8.87604e-09"
+ =y2 "96"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'pol'
+ |= [fg=tape bg=tape]
+ :~ ;circle
+ =cx "64"
+ =cy "64"
+ =r "64"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "48"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;line
+ =x1 "128"
+ =y1 "32"
+ =x2 "-8.87604e-09"
+ =y2 "32"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'pon'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M128 0C57.3075 8.42999e-07 -8.42999e-07 57.3075 0 128H128V0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ==
+::
+ :- 'pos'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M0 0C0 70.6925 57.3075 128 128 128V0H0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "-0.0029152"
+ =x2 "127.983"
+ =y2 "127.986"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;circle
+ =cx "96"
+ =cy "32"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "96"
+ =cy "32"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'pub'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M128 128C128 57.3076 70.6925 6.18013e-06 1.11901e-05 0L0 128L128 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M32 0L32 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'pun'
+ |= [fg=tape bg=tape]
+ :~ ;circle
+ =cx "64"
+ =cy "64"
+ =r "64"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M112 64C112 37.4903 90.5097 16 64 16"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M96 64C96 46.3269 81.6731 32 64 32"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M80 64C80 55.1634 72.8366 48 64 48"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'pur'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M5.59506e-06 128C70.6925 128 128 70.6925 128 0L0 5.59506e-06L5.59506e-06 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M-0.00292969 0L127.997 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;path
+ =d "M3.73284e-05 64C17.6633 64 33.6554 56.8445 45.2356 45.2741"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'put'
+ |= [fg=tape bg=tape]
+ :~ ;rect
+ =width "128"
+ =height "128"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;circle
+ =cx "32"
+ =cy "96"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "32"
+ =cy "96"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'pyl'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M128 128C128 57.3076 70.6925 6.18013e-06 1.11901e-05 0L0 128L128 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M-5.59506e-06 128C35.3462 128 64 99.3462 64 64C64 28.6538 35.3462 1.54503e-06 0 0"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'pyx'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M5.59506e-06 128C70.6925 128 128 70.6925 128 0L0 5.59506e-06L5.59506e-06 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M-0.00292969 0L127.997 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;circle
+ =cx "96"
+ =cy "32"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "96"
+ =cy "32"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'rab'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M128 0C57.3075 8.42999e-07 -8.42999e-07 57.3075 0 128H128V0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M-0.00292969 0L127.997 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;line
+ =x1 "15.9965"
+ =y1 "111.997"
+ =x2 "47.9964"
+ =y2 "79.9965"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'rac'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M0.0541 0C70.7217 0.0292317 128 57.3256 128 128C57.3177 128 0.0164917 70.7089 7.62806e-06 0.0305091C7.62851e-06 0.0203397 -4.44317e-10 0.01017 0 0H0.0541Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;circle
+ =cx "16"
+ =cy "112"
+ =r "11.5"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ ;circle
+ =cx "16"
+ =cy "112"
+ =r "9"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ :: =stroke-width "2"
+ ==
+::
+ :- 'rad'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M128 128C128 57.3076 70.6925 6.18013e-06 1.11901e-05 0L0 128L128 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;circle
+ =cx "32"
+ =cy "96"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "32"
+ =cy "96"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'rag'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M64 0H128V128H64C28.6538 128 0 99.3462 0 64C0 28.6538 28.6538 0 64 0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "16.0036"
+ =y1 "15.9965"
+ =x2 "48.0036"
+ =y2 "47.9965"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'ral'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M0.0541 0C70.7217 0.0292317 128 57.3256 128 128C57.3177 128 0.0164917 70.7089 7.62806e-06 0.0305091C7.62851e-06 0.0203397 -4.44317e-10 0.01017 0 0H0.0541Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "32"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "16"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'ram'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M64 0H128V128H64C28.6538 128 0 99.3462 0 64C0 28.6538 28.6538 0 64 0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "64"
+ =y1 "2.18557e-08"
+ =x2 "64"
+ =y2 "128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =fill-rule "evenodd"
+ =clip-rule "evenodd"
+ =stroke "none"
+ =d "M80 64C80 72.8366 72.8366 80 64 80C55.1634 80 48 72.8366 48 64C48 55.1634 55.1634 48 64 48C72.8366 48 80 55.1634 80 64ZM64 72C68.4183 72 72 68.4183 72 64C72 59.5817 68.4183 56 64 56C59.5817 56 56 59.5817 56 64C56 68.4183 59.5817 72 64 72Z"
+ =fill bg;
+ ==
+::
+ :- 'ran'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M64 0H128V128H64C28.6538 128 0 99.3462 0 64C0 28.6538 28.6538 0 64 0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M64 0L64 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M-0.00291443 0L127.997 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "16"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'rap'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M0 0C0 70.6925 57.3075 128 128 128V0H0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "64"
+ =y1 "-1.29797e-08"
+ =x2 "64"
+ =y2 "128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;circle
+ =cx "96"
+ =cy "64"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "96"
+ =cy "64"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'rav'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M0 0C0 70.6925 57.3075 128 128 128V0H0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M128 32L0 32"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'reb'
+ |= [fg=tape bg=tape]
+ :~ ;rect
+ =width "128"
+ =height "128"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M128 -9.40976e-06C57.3075 -6.31969e-06 -3.09007e-06 57.3075 0 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'rec'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M128 128C128 57.3076 70.6925 6.18013e-06 1.11901e-05 0L0 128L128 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;circle
+ =cx "32"
+ =cy "96"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "32"
+ =cy "96"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ;circle
+ =cx "96"
+ =cy "96"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "96"
+ =cy "96"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'red'
+ |= [fg=tape bg=tape]
+ :~ ;circle
+ =cx "64"
+ =cy "64"
+ =r "64"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;circle
+ =cx "64"
+ =cy "96"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "64"
+ =cy "96"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'ref'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M0.0541 0C70.7217 0.0292317 128 57.3256 128 128C57.3177 128 0.0164917 70.7089 7.62806e-06 0.0305091C7.62851e-06 0.0203397 -4.44317e-10 0.01017 0 0H0.0541Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M-0.00292969 0L127.997 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;circle
+ =cx "16"
+ =cy "112"
+ =r "11.5"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ ;circle
+ =cx "16"
+ =cy "112"
+ =r "9"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ :: =stroke-width "2"
+ ==
+::
+ :- 'reg'
+ |= [fg=tape bg=tape]
+ :~ ;rect
+ =width "128"
+ =height "128"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M128 96C110.327 96 96 81.6731 96 64C96 46.3269 110.327 32 128 32"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'rel'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M0 127.946C0.0292286 57.2783 57.3256 3.08928e-06 128 0C128 70.6823 70.7089 127.984 0.0305092 128C0.0203397 128 0.01017 128 2.36469e-09 128L0 127.946Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M128 64L0 64"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M128 96L0 96"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M128 32L0 32"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'rem'
+ |= [fg=tape bg=tape]
+ :~ ;circle
+ =cx "64"
+ =cy "64"
+ =r "64"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M-0.00292969 0L127.997 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;path
+ =d "M128 64C92.6538 64 64 35.3462 64 0"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'ren'
+ |= [fg=tape bg=tape]
+ :~ ;rect
+ =width "128"
+ =height "128"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "80.0035"
+ =y1 "79.9965"
+ =x2 "112.003"
+ =y2 "111.997"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "16"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'rep'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M128 0C57.3075 8.42999e-07 -8.42999e-07 57.3075 0 128H128V0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M32 128C32 74.9807 74.9807 32 128 32"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'res'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M128 0C57.3075 8.42999e-07 -8.42999e-07 57.3075 0 128H128V0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "80.0035"
+ =y1 "79.9965"
+ =x2 "112.003"
+ =y2 "111.997"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'ret'
+ |= [fg=tape bg=tape]
+ :~ ;circle
+ =cx "64"
+ =cy "64"
+ =r "64"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M128 64L0 64"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'rev'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M64 128H0L5.59506e-06 0L64 5.59506e-06C99.3462 8.68512e-06 128 28.6538 128 64C128 99.3462 99.3462 128 64 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "15.9965"
+ =y1 "111.997"
+ =x2 "53.9965"
+ =y2 "73.9965"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;circle
+ =cx "16"
+ =cy "112"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "16"
+ =cy "112"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ;path
+ =fill-rule "evenodd"
+ =clip-rule "evenodd"
+ =stroke "none"
+ =d "M80 64C80 72.8366 72.8366 80 64 80C55.1634 80 48 72.8366 48 64C48 55.1634 55.1634 48 64 48C72.8366 48 80 55.1634 80 64ZM64 72C68.4183 72 72 68.4183 72 64C72 59.5817 68.4183 56 64 56C59.5817 56 56 59.5817 56 64C56 68.4183 59.5817 72 64 72Z"
+ =fill bg;
+ ==
+::
+ :- 'rex'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M64 128H0L5.59506e-06 0L64 5.59506e-06C99.3462 8.68512e-06 128 28.6538 128 64C128 99.3462 99.3462 128 64 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M128 64L0 64"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =fill-rule "evenodd"
+ =clip-rule "evenodd"
+ =stroke "none"
+ =d "M80 64C80 72.8366 72.8366 80 64 80C55.1634 80 48 72.8366 48 64C48 55.1634 55.1634 48 64 48C72.8366 48 80 55.1634 80 64ZM64 72C68.4183 72 72 68.4183 72 64C72 59.5817 68.4183 56 64 56C59.5817 56 56 59.5817 56 64C56 68.4183 59.5817 72 64 72Z"
+ =fill bg;
+ ==
+::
+ :- 'rib'
+ |= [fg=tape bg=tape]
+ :~ ;circle
+ =cx "64"
+ =cy "64"
+ =r "64"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "8.74228e-08"
+ =y1 "64"
+ =x2 "128"
+ =y2 "64"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;line
+ =x1 "64"
+ =y1 "2.18557e-08"
+ =x2 "64"
+ =y2 "128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'ric'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M128 128C128 57.3076 70.6925 6.18013e-06 1.11901e-05 0L0 128L128 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M96 128C96 74.9807 53.0193 32 0 32"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'rid'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M0 0C0 70.6925 57.3075 128 128 128V0H0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M64 0L64 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M96 0L96 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'rig'
+ |= [fg=tape bg=tape]
+ :~ ;circle
+ =cx "64"
+ =cy "64"
+ =r "64"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;circle
+ =cx "64"
+ =cy "32"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "64"
+ =cy "32"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ;circle
+ =cx "64"
+ =cy "96"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "64"
+ =cy "96"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'ril'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M64 0H128V128H64C28.6538 128 0 99.3462 0 64C0 28.6538 28.6538 0 64 0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "0.5"
+ =y1 "-0.5"
+ =x2 "181.5"
+ =y2 "-0.5"
+ =transform "matrix(-0.707107 0.707107 0.707107 0.707107 128.693 0)"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;circle
+ =cx "96"
+ =cy "32"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "96"
+ =cy "32"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'rin'
+ |= [fg=tape bg=tape]
+ :~ ;rect
+ =width "128"
+ =height "128"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "64"
+ =y1 "2.18557e-08"
+ =x2 "64"
+ =y2 "128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;line
+ =x1 "32"
+ =y1 "2.18557e-08"
+ =x2 "32"
+ =y2 "128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'rip'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M64 0H128V128H64C28.6538 128 0 99.3462 0 64C0 28.6538 28.6538 0 64 0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M-0.00292969 0L127.997 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;path
+ =d "M96 64C96 46.3269 81.6731 32 64 32"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;circle
+ =cx "96"
+ =cy "64"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "96"
+ =cy "64"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'ris'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M128 0C57.3075 8.42999e-07 -8.42999e-07 57.3075 0 128H128V0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "-0.0029152"
+ =x2 "127.983"
+ =y2 "127.986"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;path
+ =d "M128 0C128 35.3511 113.669 67.3551 90.5 90.5193"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M96 0C96 26.5077 85.2564 50.5061 67.8862 67.8783"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M64 0C64 17.6721 56.8374 33.6713 45.2568 45.2529"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M32.3716 0C32.3716 8.83603 28.7903 16.8356 23 22.6264"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'rit'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M0.0541 0C70.7217 0.0292317 128 57.3256 128 128C57.3177 128 0.0164917 70.7089 7.62806e-06 0.0305091C7.62851e-06 0.0203397 -4.44317e-10 0.01017 0 0H0.0541Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "0.5"
+ =y1 "-0.5"
+ =x2 "181.5"
+ =y2 "-0.5"
+ =transform "matrix(-0.707107 0.707107 0.707107 0.707107 128.71 0)"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;path
+ =fill-rule "evenodd"
+ =clip-rule "evenodd"
+ =stroke "none"
+ =d "M80 64C80 72.8366 72.8366 80 64 80C55.1634 80 48 72.8366 48 64C48 55.1634 55.1634 48 64 48C72.8366 48 80 55.1634 80 64ZM64 72C68.4183 72 72 68.4183 72 64C72 59.5817 68.4183 56 64 56C59.5817 56 56 59.5817 56 64C56 68.4183 59.5817 72 64 72Z"
+ =fill bg;
+ ==
+::
+ :- 'riv'
+ |= [fg=tape bg=tape]
+ :~ ;rect
+ =width "128"
+ =height "128"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "32"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;line
+ =x1 "64"
+ =y1 "2.18557e-08"
+ =x2 "64"
+ =y2 "128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "48"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'roc'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M0.0541 0C70.7217 0.0292317 128 57.3256 128 128C57.3177 128 0.0164917 70.7089 7.62806e-06 0.0305091C7.62851e-06 0.0203397 -4.44317e-10 0.01017 0 0H0.0541Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ;circle
+ =cx "16"
+ =cy "112"
+ =r "11.5"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ ;circle
+ =cx "16"
+ =cy "112"
+ =r "9"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ :: =stroke-width "2"
+ ;circle
+ =cx "112"
+ =cy "16"
+ =r "11.5"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ ;circle
+ =cx "112"
+ =cy "16"
+ =r "9"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ :: =stroke-width "2"
+ ==
+::
+ :- 'rol'
+ |= [fg=tape bg=tape]
+ :~ ;circle
+ =cx "64"
+ =cy "64"
+ =r "64"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M128 64L0 64"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M64 16C90.5097 16 112 37.4903 112 64C112 90.5097 90.5097 112 64 112"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'ron'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M128 0C57.3075 8.42999e-07 -8.42999e-07 57.3075 0 128H128V0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M128 0C128 70.6924 70.6925 128 0 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'rop'
+ |= [fg=tape bg=tape]
+ :~ ;circle
+ =cx "64"
+ =cy "64"
+ =r "64"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M-0.00292969 0L127.997 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;path
+ =d "M112 64C112 37.4903 90.5097 16 64 16"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'ros'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M0 0C0 70.6925 57.3075 128 128 128V0H0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "0.5"
+ =y1 "-0.5"
+ =x2 "181.5"
+ =y2 "-0.5"
+ =transform "matrix(-0.707107 0.707107 0.707107 0.707107 128.71 0)"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;circle
+ =cx "96"
+ =cy "96"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "96"
+ =cy "96"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'rov'
+ |= [fg=tape bg=tape]
+ :~ ;rect
+ =width "128"
+ =height "128"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "-0.0029152"
+ =x2 "127.983"
+ =y2 "127.986"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;path
+ =d "M128 0C128 35.3511 113.669 67.3551 90.5 90.5193"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M96 0C96 26.5077 85.2564 50.5061 67.8862 67.8783"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M64 0C64 17.6721 56.8374 33.6713 45.2568 45.2529"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M32.3716 0C32.3716 8.83603 28.7903 16.8356 23 22.6264"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'ruc'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M128 128C128 57.3076 70.6925 6.18013e-06 1.11901e-05 0L0 128L128 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M128 64L0 64"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M128 32L0 32"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'rud'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M128 128C128 57.3076 70.6925 6.18013e-06 1.11901e-05 0L0 128L128 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M128 64L0 64"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M32 0L32 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M64 0L64 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'rul'
+ |= [fg=tape bg=tape]
+ :~ ;circle
+ =cx "64"
+ =cy "64"
+ =r "64"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "80.0035"
+ =y1 "79.9964"
+ =x2 "112.003"
+ =y2 "111.996"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =fill-rule "evenodd"
+ =clip-rule "evenodd"
+ =stroke "none"
+ =d "M80 64C80 72.8366 72.8366 80 64 80C55.1634 80 48 72.8366 48 64C48 55.1634 55.1634 48 64 48C72.8366 48 80 55.1634 80 64ZM64 72C68.4183 72 72 68.4183 72 64C72 59.5817 68.4183 56 64 56C59.5817 56 56 59.5817 56 64C56 68.4183 59.5817 72 64 72Z"
+ =fill bg;
+ ==
+::
+ :- 'rum'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M5.59506e-06 128C70.6925 128 128 70.6925 128 0L0 5.59506e-06L5.59506e-06 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M5.08584e-07 32C17.6731 32 32 17.6731 32 0"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'run'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M64 128H0L5.59506e-06 0L64 5.59506e-06C99.3462 8.68512e-06 128 28.6538 128 64C128 99.3462 99.3462 128 64 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M64 0L64 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M96 0L96 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M32 0L32 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'rup'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M64 128H0L5.59506e-06 0L64 5.59506e-06C99.3462 8.68512e-06 128 28.6538 128 64C128 99.3462 99.3462 128 64 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M64 0L64 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M64 112C90.5097 112 112 90.5097 112 64C112 37.4903 90.5097 16 64 16"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "32"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'rus'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M128 128C128 57.3076 70.6925 6.18013e-06 1.11901e-05 0L0 128L128 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M128 0L0 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;path
+ =d "M64 128C64 92.6538 35.3462 64 0 64"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'rut'
+ |= [fg=tape bg=tape]
+ :~ ;rect
+ =width "128"
+ =height "128"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;circle
+ =cx "32"
+ =cy "32"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "32"
+ =cy "32"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'rux'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M128 128C128 57.3076 70.6925 6.18013e-06 1.11901e-05 0L0 128L128 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M128 64L0 64"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M32 64C32 81.6731 46.3269 96 64 96"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'ryc'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M128 128C128 57.3076 70.6925 6.18013e-06 1.11901e-05 0L0 128L128 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M128 96L0 96"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'ryd'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M0.0541 0C70.7217 0.0292317 128 57.3256 128 128C57.3177 128 0.0164917 70.7089 7.62806e-06 0.0305091C7.62851e-06 0.0203397 -4.44317e-10 0.01017 0 0H0.0541Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M-0.00280762 0L127.997 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;path
+ =d "M96 64C96 81.6731 81.6731 96 64 96"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'ryg'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M5.59506e-06 128C70.6925 128 128 70.6925 128 0L0 5.59506e-06L5.59506e-06 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M-2.79795e-06 -3.55988e-06C70.6924 -4.40288e-06 128 57.3075 128 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;line
+ =x1 "16.0035"
+ =y1 "15.9965"
+ =x2 "48.0035"
+ =y2 "47.9965"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'ryl'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M0 0C0 70.6925 57.3075 128 128 128V0H0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M128 0L0 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;path
+ =d "M128 128C92.6489 128 60.6449 113.669 37.4807 90.5"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M128 96C101.492 96 77.4939 85.2564 60.1217 67.8862"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M128 64C110.328 64 94.3287 56.8374 82.7471 45.2568"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M128 32.3716C119.164 32.3716 111.164 28.7903 105.374 23"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'rym'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M5.59506e-06 128C70.6925 128 128 70.6925 128 0L0 5.59506e-06L5.59506e-06 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M128 96L0 96"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'ryn'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M5.59506e-06 128C70.6925 128 128 70.6925 128 0L0 5.59506e-06L5.59506e-06 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M128 128C57.3075 128 -3.09007e-06 70.6925 0 0"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'ryp'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M5.59506e-06 128C70.6925 128 128 70.6925 128 0L0 5.59506e-06L5.59506e-06 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M-0.00292969 0L127.997 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ==
+::
+ :- 'rys'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M128 128C128 57.3076 70.6925 6.18013e-06 1.11901e-05 0L0 128L128 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M1.52575e-06 96C53.0193 96 96 53.0193 96 0"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'ryt'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M64 128H0L5.59506e-06 -7.62939e-06L64 -2.03434e-06C99.3462 1.05573e-06 128 28.6538 128 64C128 99.3462 99.3462 128 64 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "16"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "48"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M128 0L0 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ==
+::
+ :- 'ryx'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M5.59506e-06 128C70.6925 128 128 70.6925 128 0L0 5.59506e-06L5.59506e-06 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "0.5"
+ =y1 "-0.5"
+ =x2 "181.5"
+ =y2 "-0.5"
+ =transform "matrix(-0.707107 0.707107 0.707107 0.707107 128.71 0)"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;path
+ =d "M128 0L0 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "16"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'sab'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M0 0C0 70.6925 57.3075 128 128 128V0H0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M-0.00292969 0L127.997 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;line
+ =y1 "-0.5"
+ =x2 "45.2548"
+ =y2 "-0.5"
+ =transform "matrix(0.707107 -0.707107 -0.707107 -0.707107 79.65 47.65)"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;circle
+ =cx "16"
+ =cy "112"
+ =r "11.5"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ ;circle
+ =cx "16"
+ =cy "112"
+ =r "9"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ :: =stroke-width "2"
+ ==
+::
+ :- 'sal'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M0.0541 0C70.7217 0.0292317 128 57.3256 128 128C57.3177 128 0.0164917 70.7089 7.62806e-06 0.0305091C7.62851e-06 0.0203397 -4.44317e-10 0.01017 0 0H0.0541Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M0 128L128 0"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;path
+ =d "M-0.701724 31.9914C25.6281 31.9914 49.4822 42.5913 66.8261 59.7565M-0.701723 63.9914C16.7916 63.9914 32.6456 71.0098 44.1982 82.3844M-0.701722 95.9914C7.955 95.9914 15.8089 99.4288 21.5694 105.013"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'sam'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M64 0H128V128H64C28.6538 128 0 99.3462 0 64C0 28.6538 28.6538 0 64 0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "48"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M64 0L64 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =fill-rule "evenodd"
+ =clip-rule "evenodd"
+ =stroke "none"
+ =d "M80 64C80 72.8366 72.8366 80 64 80C55.1634 80 48 72.8366 48 64C48 55.1634 55.1634 48 64 48C72.8366 48 80 55.1634 80 64ZM64 72C68.4183 72 72 68.4183 72 64C72 59.5817 68.4183 56 64 56C59.5817 56 56 59.5817 56 64C56 68.4183 59.5817 72 64 72Z"
+ =fill bg;
+ ==
+::
+ :- 'san'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M0 0C0 70.6925 57.3075 128 128 128V0H0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "-0.0029152"
+ =x2 "127.983"
+ =y2 "127.986"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ==
+::
+ :- 'sap'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M0 0C0 70.6925 57.3075 128 128 128V0H0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "128"
+ =y1 "64"
+ =x2 "-4.37114e-08"
+ =y2 "64"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;circle
+ =cx "96"
+ =cy "64"
+ =r "8"
+ =fill bg
+ =stroke "none";
+ ==
+::
+ :- 'sar'
+ |= [fg=tape bg=tape]
+ :~ ;circle
+ =cx "64"
+ =cy "64"
+ =r "64"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "48"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "48"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;line
+ =x1 "64"
+ =y1 "2.18557e-08"
+ =x2 "64"
+ =y2 "128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'sat'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M0 0C0 70.6925 57.3075 128 128 128V0H0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M128 128C128 57.3076 70.6925 0 0 0"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'sav'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M64 0H128V128H64C28.6538 128 0 99.3462 0 64C0 28.6538 28.6538 0 64 0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "0.5"
+ =y1 "-0.5"
+ =x2 "181.5"
+ =y2 "-0.5"
+ =transform "matrix(-0.707107 0.707107 0.707107 0.707107 128.71 0)"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;path
+ =d "M96 64C96 46.3269 81.6731 32 64 32"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;circle
+ =cx "64"
+ =cy "32"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "64"
+ =cy "32"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'seb'
+ |= [fg=tape bg=tape]
+ :~ ;rect
+ =width "128"
+ =height "128"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M128 64C92.6538 64 64 35.3462 64 0"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'sec'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M128 128C128 57.3076 70.6925 6.18013e-06 1.11901e-05 0L0 128L128 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;circle
+ =cx "32"
+ =cy "32"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "32"
+ =cy "32"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'sed'
+ |= [fg=tape bg=tape]
+ :~ ;circle
+ =cx "64"
+ =cy "64"
+ =r "64"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ;circle
+ =cx "96"
+ =cy "64"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "96"
+ =cy "64"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'sef'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M0.0541 0C70.7217 0.0292317 128 57.3256 128 128C57.3177 128 0.0164917 70.7089 7.62806e-06 0.0305091C7.62851e-06 0.0203397 -4.44317e-10 0.01017 0 0H0.0541Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ;circle
+ =cx "16"
+ =cy "112"
+ =r "11.5"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ ;circle
+ =cx "16"
+ =cy "112"
+ =r "9"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ :: =stroke-width "2"
+ ==
+::
+ :- 'seg'
+ |= [fg=tape bg=tape]
+ :~ ;rect
+ =width "128"
+ =height "128"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M32 128C32 110.327 46.3269 96 64 96C81.6731 96 96 110.327 96 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'sel'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M0 127.946C0.0292286 57.2783 57.3256 3.08928e-06 128 0C128 70.6823 70.7089 127.984 0.0305092 128C0.0203397 128 0.01017 128 2.36469e-09 128L0 127.946Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "8"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'sem'
+ |= [fg=tape bg=tape]
+ :~ ;circle
+ =cx "64"
+ =cy "64"
+ =r "64"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M1.01717e-06 64C35.3462 64 64 35.3462 64 0"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M-0.00292969 0L127.997 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ==
+::
+ :- 'sen'
+ |= [fg=tape bg=tape]
+ :~ ;rect
+ =width "128"
+ =height "128"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M64 0L64 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M96 128C96 110.327 81.6731 96 64 96C46.3269 96 32 110.327 32 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'sep'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M128 0C57.3075 8.42999e-07 -8.42999e-07 57.3075 0 128H128V0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M64 128L64 0"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M32 128L32 0"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M96 128L96 0"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'ser'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M0 64L5.59506e-06 0L128 1.11901e-05V64C128 99.3462 99.3462 128 64 128C28.6538 128 -4.6351e-06 99.3462 0 64Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M32 0L32 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'set'
+ |= [fg=tape bg=tape]
+ :~ ;circle
+ =cx "64"
+ =cy "64"
+ =r "64"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M64 64L128 64"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'sev'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M64 128H0L5.59506e-06 0L64 5.59506e-06C99.3462 8.68512e-06 128 28.6538 128 64C128 99.3462 99.3462 128 64 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "48"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'sib'
+ |= [fg=tape bg=tape]
+ :~ ;circle
+ =cx "64"
+ =cy "64"
+ =r "64"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M128 0L0 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;path
+ =d "M64 9.40976e-06C64 35.3462 92.6538 64 128 64"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'sic'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M0 0C0 70.6925 57.3075 128 128 128V0H0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M128 0L0 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ==
+::
+ :- 'sid'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M0 0C0 70.6925 57.3075 128 128 128V0H0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M128 64L0 64"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M128 128C110.327 128 96 113.673 96 96C96 78.3269 110.327 64 128 64"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'sig'
+ |= [fg=tape bg=tape]
+ :~ ;circle
+ =cx "64"
+ =cy "64"
+ =r "64"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;circle
+ =cx "32"
+ =cy "64"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "32"
+ =cy "64"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ;circle
+ =cx "96"
+ =cy "64"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "96"
+ =cy "64"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'sil'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M64 0H128V128H64C28.6538 128 0 99.3462 0 64C0 28.6538 28.6538 0 64 0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "16.0036"
+ =y1 "15.9965"
+ =x2 "48.0036"
+ =y2 "47.9965"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M128 0L0 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ==
+::
+ :- 'sim'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M128 64V128H0L2.79753e-06 64C4.34256e-06 28.6538 28.6538 -1.54503e-06 64 0C99.3462 1.54503e-06 128 28.6538 128 64Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M64 0L64 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M32 0L32 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'sip'
+ |= [fg=tape bg=tape]
+ :~ ;rect
+ =width "128"
+ =height "128"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M64 0L64 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M16 64C16 37.4903 37.4903 16 64 16"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;circle
+ =cx "16"
+ =cy "64"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "16"
+ =cy "64"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'sit'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M0.0541 0C70.7217 0.0292317 128 57.3256 128 128C57.3177 128 0.0164917 70.7089 7.62806e-06 0.0305091C7.62851e-06 0.0203397 -4.44317e-10 0.01017 0 0H0.0541Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =fill-rule "evenodd"
+ =clip-rule "evenodd"
+ =stroke "none"
+ =d "M80 64C80 72.8366 72.8366 80 64 80C55.1634 80 48 72.8366 48 64C48 55.1634 55.1634 48 64 48C72.8366 48 80 55.1634 80 64ZM64 72C68.4183 72 72 68.4183 72 64C72 59.5817 68.4183 56 64 56C59.5817 56 56 59.5817 56 64C56 68.4183 59.5817 72 64 72Z"
+ =fill bg;
+ ==
+::
+ :- 'siv'
+ |= [fg=tape bg=tape]
+ :~ ;rect
+ =width "128"
+ =height "128"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M64 0L64 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M128 96L0 96"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'soc'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M0 127.946C0.0292286 57.2783 57.3256 3.08928e-06 128 0C128 70.6823 70.7089 127.984 0.0305092 128C0.0203397 128 0.01017 128 2.36469e-09 128L0 127.946Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "64"
+ =y1 "2.18557e-08"
+ =x2 "64"
+ =y2 "128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "16"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;circle
+ =cx "16"
+ =cy "16"
+ =r "11.5"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ ;circle
+ =cx "16"
+ =cy "16"
+ =r "9"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ :: =stroke-width "2"
+ ==
+::
+ :- 'sog'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M128 0C57.3075 8.42999e-07 -8.42999e-07 57.3075 0 128H128V0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M128 0L0 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;path
+ =d "M64 96C81.6731 96 96 81.6731 96 64C96 46.3269 81.6731 32 64 32"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "16"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'sol'
+ |= [fg=tape bg=tape]
+ :~ ;circle
+ =cx "64"
+ =cy "64"
+ =r "64"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "32"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M128 64L-5.96046e-08 64"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'som'
+ |= [fg=tape bg=tape]
+ :~ ;rect
+ =width "128"
+ =height "128"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;circle
+ =cx "96"
+ =cy "96"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "96"
+ =cy "96"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ;circle
+ =cx "32"
+ =cy "96"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "32"
+ =cy "96"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ;circle
+ =cx "32"
+ =cy "32"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "32"
+ =cy "32"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'son'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M128 0C57.3075 8.42999e-07 -8.42999e-07 57.3075 0 128H128V0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "127.553"
+ =y1 "128.224"
+ =x2 "63.5528"
+ =y2 "0.223598"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'sop'
+ |= [fg=tape bg=tape]
+ :~ ;circle
+ =cx "64"
+ =cy "64"
+ =r "64"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "32"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M-0.00292969 0L127.997 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;circle
+ =cx "64"
+ =cy "32"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "64"
+ =cy "32"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'sor'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M64 0H128V128H64C28.6538 128 0 99.3462 0 64C0 28.6538 28.6538 0 64 0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M-0.00292969 0L127.997 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;path
+ =d "M128 0C128 35.3511 113.669 67.3551 90.5 90.5193"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M96 0C96 26.5077 85.2564 50.5061 67.8862 67.8783"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M64 0C64 17.6721 56.8374 33.6713 45.2568 45.2529"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M32.3716 0C32.3716 8.83603 28.7903 16.8356 23 22.6264"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'sov'
+ |= [fg=tape bg=tape]
+ :~ ;rect
+ =width "128"
+ =height "128"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M0 128L128 0"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;path
+ =d "M128 128C92.6489 128 60.6449 113.669 37.4807 90.5"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M128 96C101.492 96 77.4939 85.2564 60.1217 67.8862"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M128 64C110.328 64 94.3287 56.8374 82.7471 45.2568"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M128 32.3716C119.164 32.3716 111.164 28.7903 105.374 23"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'sub'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M128 128C128 57.3076 70.6925 6.18013e-06 1.11901e-05 0L0 128L128 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M64 0L64 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'sud'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M128 128C128 57.3076 70.6925 6.18013e-06 1.11901e-05 0L0 128L128 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "128"
+ =y1 "64"
+ =x2 "-8.87604e-09"
+ =y2 "64"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M128 64L0 64"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =fill-rule "evenodd"
+ =clip-rule "evenodd"
+ =stroke "none"
+ =d "M80 64C80 72.8366 72.8366 80 64 80C55.1634 80 48 72.8366 48 64C48 55.1634 55.1634 48 64 48C72.8366 48 80 55.1634 80 64ZM64 72C68.4183 72 72 68.4183 72 64C72 59.5817 68.4183 56 64 56C59.5817 56 56 59.5817 56 64C56 68.4183 59.5817 72 64 72Z"
+ =fill bg;
+ ==
+::
+ :- 'sug'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M64 128H0L5.59506e-06 0L64 5.59506e-06C99.3462 8.68512e-06 128 28.6538 128 64C128 99.3462 99.3462 128 64 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;circle
+ =cx "16"
+ =cy "64"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "16"
+ =cy "64"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ;circle
+ =cx "80"
+ =cy "64"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "80"
+ =cy "64"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'sul'
+ |= [fg=tape bg=tape]
+ :~ ;circle
+ =cx "64"
+ =cy "64"
+ =r "64"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M64 96C46.3269 96 32 81.6731 32 64C32 46.3269 46.3269 32 64 32"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'sum'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M5.59506e-06 128C70.6925 128 128 70.6925 128 0L0 5.59506e-06L5.59506e-06 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M1.01717e-06 64C35.3462 64 64 35.3462 64 0"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'sun'
+ |= [fg=tape bg=tape]
+ :~ ;circle
+ =cx "64"
+ =cy "64"
+ =r "64"
+ :: =fill fg
+ =stroke "none";
+ ;circle
+ =cx "80"
+ =cy "80"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "80"
+ =cy "80"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ;circle
+ =cx "80"
+ =cy "48"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "80"
+ =cy "48"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ;circle
+ =cx "48"
+ =cy "48"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "48"
+ =cy "48"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ;circle
+ =cx "48"
+ =cy "80"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "48"
+ =cy "80"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'sup'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M64 128H0L5.59506e-06 0L64 5.59506e-06C99.3462 8.68512e-06 128 28.6538 128 64C128 99.3462 99.3462 128 64 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M64 112C90.5097 112 112 90.5097 112 64C112 37.4903 90.5097 16 64 16"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M128 64L0 64"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'sur'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M128 128C128 57.3076 70.6925 6.18013e-06 1.11901e-05 0L0 128L128 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M-0.00292969 0L127.997 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;path
+ =d "M3.73284e-05 64.0001C17.6633 64.0001 33.6554 56.8446 45.2356 45.2742"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M0.000105172 128C35.3582 128 67.3679 113.664 90.5332 90.4863"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'sut'
+ |= [fg=tape bg=tape]
+ :~ ;rect
+ =width "128"
+ =height "128"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;circle
+ =cx "32"
+ =cy "32"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "32"
+ =cy "32"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ;circle
+ =cx "96"
+ =cy "96"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "96"
+ =cy "96"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'syd'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M0.0541 0C70.7217 0.0292317 128 57.3256 128 128C57.3177 128 0.0164917 70.7089 7.62806e-06 0.0305091C7.62851e-06 0.0203397 -4.44317e-10 0.01017 0 0H0.0541Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M64 16C37.4903 16 16 37.4903 16 64"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M-0.00292969 0L127.997 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ==
+::
+ :- 'syl'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M5.59506e-06 128C70.6925 128 128 70.6925 128 0L0 5.59506e-06L5.59506e-06 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M-0.00292969 0L127.997 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;circle
+ =cx "32"
+ =cy "96"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "32"
+ =cy "96"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ;circle
+ =cx "96"
+ =cy "32"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "96"
+ =cy "32"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'sym'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M5.59506e-06 128C70.6925 128 128 70.6925 128 0L0 5.59506e-06L5.59506e-06 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "96.5"
+ =y1 "3.07317e-08"
+ =x2 "96.5"
+ =y2 "128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'syn'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M5.59506e-06 128C70.6925 128 128 70.6925 128 0L0 5.59506e-06L5.59506e-06 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M0 0C35.3511 0 67.3551 14.3309 90.5193 37.5"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M0 32C26.5077 32 50.5061 42.7436 67.8783 60.1138"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M0 64C17.6721 64 33.6713 71.1626 45.2529 82.7432"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M0 95.6284C8.83603 95.6284 16.8356 99.2097 22.6264 105"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'syp'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M5.59506e-06 128C70.6925 128 128 70.6925 128 0L0 5.59506e-06L5.59506e-06 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M-0.00280762 0L127.997 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;path
+ =d "M1.01717e-06 64C35.3462 64 64 35.3462 64 0"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'syr'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M0 127.946C0.0292286 57.2783 57.3256 3.08928e-06 128 0C128 70.6823 70.7089 127.984 0.0305092 128C0.0203397 128 0.01017 128 2.36469e-09 128L0 127.946Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M-0.00292969 0L127.997 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;circle
+ =cx "96"
+ =cy "32"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "96"
+ =cy "32"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'syt'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M64 128H0L5.59506e-06 0L64 5.59506e-06C99.3462 8.68512e-06 128 28.6538 128 64C128 99.3462 99.3462 128 64 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "32"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "48"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M128 0L0 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ==
+::
+ :- 'syx'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M5.59506e-06 128C70.6925 128 128 70.6925 128 0L0 5.59506e-06L5.59506e-06 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M0 128C4.63574e-06 92.6488 14.3309 60.6449 37.5 37.4807"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M32 128C32 101.492 42.7436 77.4939 60.1138 60.1216"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M64 128C64 110.328 71.1626 94.3287 82.7432 82.7471"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M95.6284 128C95.6284 119.164 99.2097 111.164 105 105.374"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M-0.00280762 0L127.997 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ==
+::
+ :- 'tab'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M0 0C0 70.6925 57.3075 128 128 128V0H0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "8"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;line
+ =x1 "-0.0029152"
+ =x2 "127.983"
+ =y2 "127.986"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;circle
+ =cx "16"
+ =cy "112"
+ =r "11.5"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ ;circle
+ =cx "16"
+ =cy "112"
+ =r "9"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ :: =stroke-width "2"
+ ==
+::
+ :- 'tac'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M0 0C0 70.6925 57.3075 128 128 128V0H0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M128 0L0 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;circle
+ =cx "64"
+ =cy "32"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "64"
+ =cy "32"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ;circle
+ =cx "96"
+ =cy "64"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "96"
+ =cy "64"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'tad'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M0 0C0 70.6925 57.3075 128 128 128V0H0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;circle
+ =cx "32"
+ =cy "32"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "32"
+ =cy "32"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ;circle
+ =cx "96"
+ =cy "96"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "96"
+ =cy "96"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'tag'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M64 0H128V128H64C28.6538 128 0 99.3462 0 64C0 28.6538 28.6538 0 64 0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "80.0036"
+ =y1 "79.9964"
+ =x2 "112.004"
+ =y2 "111.996"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'tal'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M0.0541 0C70.7217 0.0292317 128 57.3256 128 128C57.3177 128 0.0164917 70.7089 7.62806e-06 0.0305091C7.62851e-06 0.0203397 -4.44317e-10 0.01017 0 0H0.0541Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "0.5"
+ =y1 "-0.5"
+ =x2 "181.5"
+ =y2 "-0.5"
+ =transform "matrix(-0.707107 0.707107 0.707107 0.707107 128.71 0)"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;path
+ =d "M96 128C96 74.9807 53.0193 32 0 32"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'tam'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M64 0H128V128H64C28.6538 128 0 99.3462 0 64C0 28.6538 28.6538 0 64 0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "128"
+ =y1 "96"
+ =x2 "-8.87604e-09"
+ =y2 "96"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;line
+ =x1 "128"
+ =y1 "32"
+ =x2 "-8.87604e-09"
+ =y2 "32"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'tan'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M0 0C0 70.6925 57.3075 128 128 128V0H0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M96 128C96 74.9807 53.0193 32 0 32"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M64 128C64 92.6538 35.3462 64 0 64"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M48 128C48 101.49 26.5097 80 0 80"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M32 128C32 110.327 17.6731 96 0 96"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M16 128C16 119.163 8.83656 112 0 112"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M128 128C128 57.3075 70.6925 0 0 0"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'tap'
+ |= [fg=tape bg=tape]
+ :~ ;circle
+ =cx "64"
+ =cy "64"
+ =r "64"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "48"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;line
+ =x1 "128"
+ =y1 "64"
+ =x2 "-8.87604e-09"
+ =y2 "64"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M64 32C81.6731 32 96 46.3269 96 64C96 81.6731 81.6731 96 64 96"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'tar'
+ |= [fg=tape bg=tape]
+ :~ ;circle
+ =cx "64"
+ =cy "64"
+ =r "64"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "48"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;circle
+ =cx "16"
+ =cy "64"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "16"
+ =cy "64"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'tas'
+ |= [fg=tape bg=tape]
+ :~ ;rect
+ =width "128"
+ =height "128"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M64 0L64 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M64 32C81.6731 32 96 46.3269 96 64C96 81.6731 81.6731 96 64 96"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'teb'
+ |= [fg=tape bg=tape]
+ :~ ;rect
+ =width "128"
+ =height "128"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M1.52575e-06 96C53.0193 96 96 53.0193 96 0"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'tec'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M128 128C128 57.3076 70.6925 6.18013e-06 1.11901e-05 0L0 128L128 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "80.0035"
+ =y1 "79.9965"
+ =x2 "112.003"
+ =y2 "111.997"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =fill-rule "evenodd"
+ =clip-rule "evenodd"
+ =stroke "none"
+ =d "M80 64C80 72.8366 72.8366 80 64 80C55.1634 80 48 72.8366 48 64C48 55.1634 55.1634 48 64 48C72.8366 48 80 55.1634 80 64ZM64 72C68.4183 72 72 68.4183 72 64C72 59.5817 68.4183 56 64 56C59.5817 56 56 59.5817 56 64C56 68.4183 59.5817 72 64 72Z"
+ =fill bg;
+ ==
+::
+ :- 'ted'
+ |= [fg=tape bg=tape]
+ :~ ;circle
+ =cx "64"
+ =cy "64"
+ =r "64"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;circle
+ =cx "32"
+ =cy "96"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "32"
+ =cy "96"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'teg'
+ |= [fg=tape bg=tape]
+ :~ ;rect
+ =width "128"
+ =height "128"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M128 80C119.163 80 112 72.8366 112 64C112 55.1634 119.163 48 128 48"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'tel'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M0 127.946C0.0292286 57.2783 57.3256 3.08928e-06 128 0C128 70.6823 70.7089 127.984 0.0305092 128C0.0203397 128 0.01017 128 2.36469e-09 128L0 127.946Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;circle
+ =cx "15"
+ =cy "112"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "15"
+ =cy "112"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ;path
+ =d "M0 0L127.986 127.986"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;path
+ =d "M32 0L128 96"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;path
+ =d "M64 0L128 64"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;path
+ =d "M96 0L128 32"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ==
+::
+ :- 'tem'
+ |= [fg=tape bg=tape]
+ :~ ;circle
+ =cx "64"
+ =cy "64"
+ =r "64"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M128 64C92.6538 64 64 92.6538 64 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;line
+ =x1 "-0.00285417"
+ =x2 "127.983"
+ =y2 "127.986"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ==
+::
+ :- 'ten'
+ |= [fg=tape bg=tape]
+ :~ ;rect
+ =width "128"
+ =height "128"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;circle
+ =cx "48"
+ =cy "48"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "48"
+ =cy "48"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ;circle
+ =cx "80"
+ =cy "48"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "80"
+ =cy "48"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ;circle
+ =cx "80"
+ =cy "80"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "80"
+ =cy "80"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ;circle
+ =cx "48"
+ =cy "80"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "48"
+ =cy "80"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'tep'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M128 0C57.3075 8.42999e-07 -8.42999e-07 57.3075 0 128H128V0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M1.14479e-06 96C53.0193 96 96 53.0193 96 0"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'ter'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M0 64L5.59506e-06 0L128 1.11901e-05V64C128 99.3462 99.3462 128 64 128C28.6538 128 -4.6351e-06 99.3462 0 64Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "96.5"
+ =y1 "3.07317e-08"
+ =x2 "96.5"
+ =y2 "128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M1.01717e-06 64C35.3462 64 64 35.3462 64 0"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'tes'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M128 0C57.3075 8.42999e-07 -8.42999e-07 57.3075 0 128H128V0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M64 0L64 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M128 64L0 64"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'tev'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M64 128H0L5.59506e-06 0L64 5.59506e-06C99.3462 8.68512e-06 128 28.6538 128 64C128 99.3462 99.3462 128 64 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "32"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'tex'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M64 128H0L5.59506e-06 0L64 5.59506e-06C99.3462 8.68512e-06 128 28.6538 128 64C128 99.3462 99.3462 128 64 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "15.9965"
+ =y1 "111.997"
+ =x2 "47.9965"
+ =y2 "79.9965"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =fill-rule "evenodd"
+ =clip-rule "evenodd"
+ =stroke "none"
+ =d "M80 64C80 72.8366 72.8366 80 64 80C55.1634 80 48 72.8366 48 64C48 55.1634 55.1634 48 64 48C72.8366 48 80 55.1634 80 64ZM64 72C68.4183 72 72 68.4183 72 64C72 59.5817 68.4183 56 64 56C59.5817 56 56 59.5817 56 64C56 68.4183 59.5817 72 64 72Z"
+ =fill bg;
+ ==
+::
+ :- 'tic'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M0 0C0 70.6925 57.3075 128 128 128V0H0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M128 32C110.327 32 96 17.6731 96 -1.39876e-06"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "32"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'tid'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M0 0C0 70.6925 57.3075 128 128 128V0H0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "64"
+ =y1 "2.18557e-08"
+ =x2 "64"
+ =y2 "128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;line
+ =x1 "96"
+ =y1 "2.18557e-08"
+ =x2 "96"
+ =y2 "128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =fill-rule "evenodd"
+ =clip-rule "evenodd"
+ =stroke "none"
+ =d "M112 32C112 40.8366 104.837 48 96 48C87.1634 48 80 40.8366 80 32C80 23.1634 87.1634 16 96 16C104.837 16 112 23.1634 112 32ZM96 40C100.418 40 104 36.4183 104 32C104 27.5817 100.418 24 96 24C91.5817 24 88 27.5817 88 32C88 36.4183 91.5817 40 96 40Z"
+ =fill bg;
+ ==
+::
+ :- 'til'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M64 0H128V128H64C28.6538 128 0 99.3462 0 64C0 28.6538 28.6538 0 64 0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "80.0036"
+ =y1 "79.9965"
+ =x2 "112.004"
+ =y2 "111.997"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'tim'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M128 64V128H0L2.79753e-06 64C4.34256e-06 28.6538 28.6538 -1.54503e-06 64 0C99.3462 1.54503e-06 128 28.6538 128 64Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M-0.00291443 0L127.997 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ==
+::
+ :- 'tin'
+ |= [fg=tape bg=tape]
+ :~ ;rect
+ =width "128"
+ =height "128"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "32"
+ =y1 "2.18557e-08"
+ =x2 "32"
+ =y2 "128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'tip'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M128 0C57.3075 8.42999e-07 -8.42999e-07 57.3075 0 128H128V0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M64 0L64 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =fill-rule "evenodd"
+ =clip-rule "evenodd"
+ =stroke "none"
+ =d "M80 64C80 72.8366 72.8366 80 64 80C55.1634 80 48 72.8366 48 64C48 55.1634 55.1634 48 64 48C72.8366 48 80 55.1634 80 64ZM64 72C68.4183 72 72 68.4183 72 64C72 59.5817 68.4183 56 64 56C59.5817 56 56 59.5817 56 64C56 68.4183 59.5817 72 64 72Z"
+ =fill bg;
+ ==
+::
+ :- 'tir'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M0 0C0 70.6925 57.3075 128 128 128V0H0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "-0.0029152"
+ =x2 "127.983"
+ =y2 "127.986"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "16"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "32"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'tob'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M128 64V128H0L2.79753e-06 64C4.34256e-06 28.6538 28.6538 -1.54503e-06 64 0C99.3462 1.54503e-06 128 28.6538 128 64Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M128 96L0 96"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'toc'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M0.0541 0C70.7217 0.0292317 128 57.3256 128 128C57.3177 128 0.0164917 70.7089 7.62806e-06 0.0305091C7.62851e-06 0.0203397 -4.44317e-10 0.01017 0 0H0.0541Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "128"
+ =y1 "96"
+ =x2 "-8.87604e-09"
+ =y2 "96"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "16"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'tod'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M64 0H128V128H64C28.6538 128 0 99.3462 0 64C0 28.6538 28.6538 0 64 0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;circle
+ =cx "64"
+ =cy "96"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "64"
+ =cy "96"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ;circle
+ =cx "64"
+ =cy "32"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "64"
+ =cy "32"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'tog'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M128 0C57.3075 8.42999e-07 -8.42999e-07 57.3075 0 128H128V0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M64 96C46.3269 96 32 81.6731 32 64"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "16"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M128 0L0 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ==
+::
+ :- 'tol'
+ |= [fg=tape bg=tape]
+ :~ ;circle
+ =cx "64"
+ =cy "64"
+ =r "64"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "128"
+ =y1 "64"
+ =x2 "-4.37114e-08"
+ =y2 "64"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M16 128C16 101.49 37.4903 80 64 80C90.5097 80 112 101.49 112 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'tom'
+ |= [fg=tape bg=tape]
+ :~ ;rect
+ =width "128"
+ =height "128"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;circle
+ =cx "32"
+ =cy "32"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "32"
+ =cy "32"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ;circle
+ =cx "96"
+ =cy "32"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "96"
+ =cy "32"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ;circle
+ =cx "32"
+ =cy "96"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "32"
+ =cy "96"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'ton'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M128 0C57.3075 8.42999e-07 -8.42999e-07 57.3075 0 128H128V0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M128 32C74.9807 32 32 74.9807 32 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M128 64C92.6538 64 64 92.6538 64 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M128 96C110.327 96 96 110.327 96 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'top'
+ |= [fg=tape bg=tape]
+ :~ ;circle
+ =cx "64"
+ =cy "64"
+ =r "64"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "-0.0029152"
+ =x2 "127.983"
+ =y2 "127.986"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "32"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "16"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'tor'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M64 0H128V128H64C28.6538 128 0 99.3462 0 64C0 28.6538 28.6538 0 64 0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "32"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'tuc'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M128 128C128 57.3076 70.6925 6.18013e-06 1.11901e-05 0L0 128L128 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M128 64L0 64"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M128 96L0 96"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;circle
+ =cx "96"
+ =cy "96"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "96"
+ =cy "96"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ;circle
+ =cx "32"
+ =cy "64"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "32"
+ =cy "64"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'tud'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M128 128C128 57.3076 70.6925 6.18013e-06 1.11901e-05 0L0 128L128 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M128 64L0 64"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;circle
+ =cx "32"
+ =cy "64"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "32"
+ =cy "64"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'tug'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M64 128H0L5.59506e-06 0L64 5.59506e-06C99.3462 8.68512e-06 128 28.6538 128 64C128 99.3462 99.3462 128 64 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M128 64L0 64"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M128 32L0 32"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'tul'
+ |= [fg=tape bg=tape]
+ :~ ;circle
+ =cx "64"
+ =cy "64"
+ =r "64"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =fill-rule "evenodd"
+ =clip-rule "evenodd"
+ =stroke "none"
+ =d "M80 64C80 72.8366 72.8366 80 64 80C55.1634 80 48 72.8366 48 64C48 55.1634 55.1634 48 64 48C72.8366 48 80 55.1634 80 64ZM64 72C68.4183 72 72 68.4183 72 64C72 59.5817 68.4183 56 64 56C59.5817 56 56 59.5817 56 64C56 68.4183 59.5817 72 64 72Z"
+ =fill bg;
+ ==
+::
+ :- 'tun'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M128 64V128H0L2.79753e-06 64C4.34256e-06 28.6538 28.6538 -1.54503e-06 64 0C99.3462 1.54503e-06 128 28.6538 128 64Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M-0.00292969 0L127.997 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "48"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'tus'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M128 128C128 57.3076 70.6925 6.18013e-06 1.11901e-05 0L0 128L128 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M128 0L0 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;circle
+ =cx "32"
+ =cy "32"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "32"
+ =cy "32"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'tux'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M128 128C128 57.3076 70.6925 6.18013e-06 1.11901e-05 0L0 128L128 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M128 64L0 64"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;circle
+ =cx "64"
+ =cy "96"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "64"
+ =cy "96"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'tyc'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M128 128C128 57.3076 70.6925 6.18013e-06 1.11901e-05 0L0 128L128 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =fill-rule "evenodd"
+ =clip-rule "evenodd"
+ =stroke "none"
+ =d "M80 64C80 72.8366 72.8366 80 64 80C55.1634 80 48 72.8366 48 64C48 55.1634 55.1634 48 64 48C72.8366 48 80 55.1634 80 64ZM64 72C68.4183 72 72 68.4183 72 64C72 59.5817 68.4183 56 64 56C59.5817 56 56 59.5817 56 64C56 68.4183 59.5817 72 64 72Z"
+ =fill bg;
+ ==
+::
+ :- 'tyd'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M0.0541 0C70.7217 0.0292317 128 57.3256 128 128C57.3177 128 0.0164917 70.7089 7.62806e-06 0.0305091C7.62851e-06 0.0203397 -4.44317e-10 0.01017 0 0H0.0541Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M-0.00280762 0L127.997 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;line
+ =y1 "-0.5"
+ =x2 "45.2548"
+ =y2 "-0.5"
+ =transform "matrix(0.707107 -0.707107 -0.707107 -0.707107 79.65 47.6499)"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;line
+ =x1 "15.9964"
+ =y1 "111.997"
+ =x2 "47.9964"
+ =y2 "79.9965"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'tyl'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M128 128C128 57.3076 70.6925 6.18013e-06 1.11901e-05 0L0 128L128 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M7.37542e-06 -3.56072e-06C1.19529e-06 70.6924 57.3075 128 128 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'tyn'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M5.59506e-06 128C70.6925 128 128 70.6925 128 0L0 5.59506e-06L5.59506e-06 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M128 -2.28831e-06C57.3076 -3.13131e-06 8.42999e-07 57.3075 0 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'typ'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M5.59506e-06 128C70.6925 128 128 70.6925 128 0L0 5.59506e-06L5.59506e-06 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M-0.00292969 0L127.997 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;path
+ =d "M96 1.90735e-06C96 53.0193 53.0193 96 0 96"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'tyr'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M0 127.946C0.0292286 57.2783 57.3256 3.08928e-06 128 0C128 70.6823 70.7089 127.984 0.0305092 128C0.0203397 128 0.01017 128 2.36469e-09 128L0 127.946Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M0 0L128 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;path
+ =d "M128 64C92.6538 64 64 35.3462 64 0"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M0 64C35.3462 64 64 92.6538 64 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'tyv'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M0 127.946C0.0292286 57.2783 57.3256 3.08928e-06 128 0C128 70.6823 70.7089 127.984 0.0305092 128C0.0203397 128 0.01017 128 2.36469e-09 128L0 127.946Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M256 0L128 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "32"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;circle
+ =cx "96"
+ =cy "32"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "96"
+ =cy "32"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ;circle
+ =cx "32"
+ =cy "96"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "32"
+ =cy "96"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'wac'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M0 0C0 70.6925 57.3075 128 128 128V0H0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M128 64L0 64"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ;circle
+ =cx "16"
+ =cy "112"
+ =r "11.5"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ ;circle
+ =cx "16"
+ =cy "112"
+ =r "9"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ :: =stroke-width "2"
+ ==
+::
+ :- 'wal'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M0 127.946C0.0292286 57.2783 57.3256 3.08928e-06 128 0C128 70.6823 70.7089 127.984 0.0305092 128C0.0203397 128 0.01017 128 2.36469e-09 128L0 127.946Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "64.5"
+ =y1 "-0.5"
+ =x2 "64.5"
+ =y2 "127.5"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;line
+ =x1 "32"
+ =y1 "2.18557e-08"
+ =x2 "32"
+ =y2 "128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'wan'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M0 0C0 70.6925 57.3075 128 128 128V0H0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M0 0C0 70.6925 57.3075 128 128 128V0H0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ==
+::
+ :- 'wat'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M0 0C0 70.6925 57.3075 128 128 128V0H0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =fill-rule "evenodd"
+ =clip-rule "evenodd"
+ =stroke "none"
+ =d "M80 64C80 72.8366 72.8366 80 64 80C55.1634 80 48 72.8366 48 64C48 55.1634 55.1634 48 64 48C72.8366 48 80 55.1634 80 64ZM64 72C68.4183 72 72 68.4183 72 64C72 59.5817 68.4183 56 64 56C59.5817 56 56 59.5817 56 64C56 68.4183 59.5817 72 64 72Z"
+ =fill bg;
+ ==
+::
+ :- 'web'
+ |= [fg=tape bg=tape]
+ :~ ;rect
+ =width "128"
+ =height "128"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M128 128C128 57.3075 70.6925 0 0 0"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'wed'
+ |= [fg=tape bg=tape]
+ :~ ;circle
+ =cx "64"
+ =cy "64"
+ =r "64"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;circle
+ =cx "32"
+ =cy "32"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "32"
+ =cy "32"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'weg'
+ |= [fg=tape bg=tape]
+ :~ ;rect
+ =width "128"
+ =height "128"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M79.5254 0C79.5254 8.83656 72.3619 16 63.5254 16C54.6888 16 47.5254 8.83656 47.5254 0"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'wel'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M0 127.946C0.0292286 57.2783 57.3256 3.08928e-06 128 0C128 70.6823 70.7089 127.984 0.0305092 128C0.0203397 128 0.01017 128 2.36469e-09 128L0 127.946Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M128 32C74.9807 32 32 74.9807 32 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M128 64C92.6538 64 64 92.6538 64 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M128 96C110.327 96 96 110.327 96 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'wen'
+ |= [fg=tape bg=tape]
+ :~ ;rect
+ =width "128"
+ =height "128"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M1.01717e-06 64C35.3462 64 64 35.3462 64 0"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M-0.00292969 0L127.997 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ==
+::
+ :- 'wep'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M128 0C57.3075 8.42999e-07 -8.42999e-07 57.3075 0 128H128V0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;circle
+ =cx "96"
+ =cy "96"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "96"
+ =cy "96"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'wer'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M0 64L5.59506e-06 0L128 1.11901e-05V64C128 99.3462 99.3462 128 64 128C28.6538 128 -4.6351e-06 99.3462 0 64Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M32 0L32 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;circle
+ =cx "32"
+ =cy "32"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "32"
+ =cy "32"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'wes'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M128 0C57.3075 8.42999e-07 -8.42999e-07 57.3075 0 128H128V0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "80.0035"
+ =y1 "79.9965"
+ =x2 "112.003"
+ =y2 "111.997"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;circle
+ =cx "112"
+ =cy "112"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "112"
+ =cy "112"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'wet'
+ |= [fg=tape bg=tape]
+ :~ ;circle
+ =cx "64"
+ =cy "64"
+ =r "64"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M64 64H0"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'wex'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M64 128H0L5.59506e-06 0L64 5.59506e-06C99.3462 8.68512e-06 128 28.6538 128 64C128 99.3462 99.3462 128 64 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =fill-rule "evenodd"
+ =clip-rule "evenodd"
+ =stroke "none"
+ =d "M80 64C80 72.8366 72.8366 80 64 80C55.1634 80 48 72.8366 48 64C48 55.1634 55.1634 48 64 48C72.8366 48 80 55.1634 80 64ZM64 72C68.4183 72 72 68.4183 72 64C72 59.5817 68.4183 56 64 56C59.5817 56 56 59.5817 56 64C56 68.4183 59.5817 72 64 72Z"
+ =fill bg;
+ ==
+::
+ :- 'wic'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M128 0C57.3075 8.42999e-07 -8.42999e-07 57.3075 0 128H128V0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;circle
+ =cx "96"
+ =cy "32"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "96"
+ =cy "32"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ;circle
+ =cx "32"
+ =cy "96"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "32"
+ =cy "96"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'wid'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M0 0C0 70.6925 57.3075 128 128 128V0H0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "48.0035"
+ =y1 "80.0036"
+ =x2 "16.0035"
+ =y2 "112.004"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =fill-rule "evenodd"
+ =clip-rule "evenodd"
+ =stroke "none"
+ =d "M80 64C80 72.8366 72.8366 80 64 80C55.1634 80 48 72.8366 48 64C48 55.1634 55.1634 48 64 48C72.8366 48 80 55.1634 80 64ZM64 72C68.4183 72 72 68.4183 72 64C72 59.5817 68.4183 56 64 56C59.5817 56 56 59.5817 56 64C56 68.4183 59.5817 72 64 72Z"
+ =fill bg;
+ ==
+::
+ :- 'win'
+ |= [fg=tape bg=tape]
+ :~ ;rect
+ =width "128"
+ =height "128"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "64"
+ =y1 "2.18557e-08"
+ =x2 "64"
+ =y2 "128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'wis'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M0 0C0 70.6925 57.3075 128 128 128V0H0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M128 64L0 64"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M128 32L0 32"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'wit'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M0 127.946C0.0292286 57.2783 57.3256 3.08928e-06 128 0C128 70.6823 70.7089 127.984 0.0305092 128C0.0203397 128 0.01017 128 2.36469e-09 128L0 127.946Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =x1 "64"
+ =y1 "2.18557e-08"
+ =x2 "64"
+ =y2 "128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;line
+ =x1 "32"
+ =y1 "2.18557e-08"
+ =x2 "32"
+ =y2 "128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;line
+ =x1 "96"
+ =y1 "2.18557e-08"
+ =x2 "96"
+ =y2 "128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'wol'
+ |= [fg=tape bg=tape]
+ :~ ;circle
+ =cx "64"
+ =cy "64"
+ =r "64"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M0 64L128 64"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M128 96C110.327 96 96 81.6731 96 64C96 46.3269 110.327 32 128 32"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'wor'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M64 0H128V128H64C28.6538 128 0 99.3462 0 64C0 28.6538 28.6538 0 64 0Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;line
+ =y1 "-0.5"
+ =x2 "45.2548"
+ =y2 "-0.5"
+ =transform "matrix(0.707107 -0.707107 -0.707107 -0.707107 79.65 47.65)"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;line
+ =x1 "-0.0029152"
+ =x2 "127.983"
+ =y2 "127.986"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;path
+ =d "M64 96C46.3269 96 32 81.6731 32 64"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'wyc'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M128 128C128 57.3076 70.6925 6.18013e-06 1.11901e-05 0L0 128L128 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ==
+::
+ :- 'wyd'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M0.0541 0C70.7217 0.0292317 128 57.3256 128 128C57.3177 128 0.0164917 70.7089 7.62806e-06 0.0305091C7.62851e-06 0.0203397 -4.44317e-10 0.01017 0 0H0.0541Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M-0.00292969 0L127.997 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;path
+ =d "M32 64C32 46.3269 46.3269 32 64 32"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;circle
+ =cx "32"
+ =cy "64"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "32"
+ =cy "64"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'wyl'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M128 128C128 57.3076 70.6925 6.18013e-06 1.11901e-05 0L0 128L128 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M-3.8147e-06 128C-7.24633e-07 92.6538 28.6538 64 64 64C99.3462 64 128 92.6538 128 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'wyn'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M5.59506e-06 128C70.6925 128 128 70.6925 128 0L0 5.59506e-06L5.59506e-06 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M1.52575e-06 96C53.0193 96 96 53.0193 96 0"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M1.01717e-06 64C35.3462 64 64 35.3462 64 0"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;path
+ =d "M5.08584e-07 32C17.6731 32 32 17.6731 32 0"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ==
+::
+ :- 'wyt'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M64 128H0L5.59506e-06 0L64 5.59506e-06C99.3462 8.68512e-06 128 28.6538 128 64C128 99.3462 99.3462 128 64 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M128 0L0 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;circle
+ =cx "64"
+ =cy "64"
+ =r "48"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ =fill "none";
+ ;circle
+ =cx "16"
+ =cy "64"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "16"
+ =cy "64"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'wyx'
+ |= [fg=tape bg=tape]
+ :~ ;path
+ =d "M5.59506e-06 128C70.6925 128 128 70.6925 128 0L0 5.59506e-06L5.59506e-06 128Z"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ;path
+ =d "M-0.00292969 0L127.997 128"
+ =vector-effect "non-scaling-stroke"
+ :: =stroke bg
+ :: =stroke-linecap "square"
+ =fill "none";
+ ;circle
+ =cx "32"
+ =cy "96"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "32"
+ =cy "96"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ;circle
+ =cx "32"
+ =cy "32"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "32"
+ =cy "32"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ;circle
+ =cx "96"
+ =cy "32"
+ =r "11.5"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke"
+ =stroke fg;
+ ;circle
+ =cx "96"
+ =cy "32"
+ =r "9"
+ =fill bg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "2"
+ ==
+::
+ :- 'zod'
+ |= [fg=tape bg=tape]
+ :~ ;circle
+ =cx "64"
+ =cy "64"
+ =r "64"
+ :: =fill fg
+ =vector-effect "non-scaling-stroke";
+ :: =stroke bg
+ :: =stroke-width "0.5"
+ ==
+== \ No newline at end of file
diff --git a/desk/web/layout.hoon b/desk/web/layout.hoon
new file mode 100644
index 0000000..213046d
--- /dev/null
+++ b/desk/web/layout.hoon
@@ -0,0 +1,24 @@
+|_ children=marl
+++ $
+ ;html
+ ;head
+ ;meta(charset "utf-8");
+ ;meta(name "viewport", content "width=device-width, initial-scale=1, shrink-to-fit=no");
+ ;title:"Nostril"
+ ;link/"/forum/imgs/favicon.ico"(rel "icon", type "image/png");
+ ;link/"/forum/imgs/favicon-32x32.png"(rel "icon", type "image/png", sizes "32x32");
+ ;link/"/forum/imgs/favicon-16x16.png"(rel "icon", type "image/png", sizes "16x16");
+ ;link/"/forum/imgs/apple-touch-icon.png"(rel "apple-touch-icon", type "image/png", sizes "180x180");
+ ;link/"/forum/site.webmanifest"(rel "manifest");
+ ;link/"/forum/style.css"(rel "stylesheet");
+ ==
+ ;body
+ ;* children
+ ;div.footer
+ ; Hosted on
+ ;a/"https://urbit.org/get-started": ~Urbit
+ ; .
+ ==
+ ==
+ ==
+--
diff --git a/desk/web/pages/index.hoon b/desk/web/pages/index.hoon
new file mode 100644
index 0000000..f385df7
--- /dev/null
+++ b/desk/web/pages/index.hoon
@@ -0,0 +1,15 @@
+/- sur=nostril
+/= comps /web/components/components
+|_ [=state-0:sur =bowl:gall]
+++ $
+ ^- manx
+ ;main
+ ;div#index-top.f.g1
+ ;div:"Popular"
+ ;div.active:"Latest"
+ ==
+ ;div.thread-list
+ ;p:"Hey"
+ ==
+ ==
+--
diff --git a/desk/web/router.hoon b/desk/web/router.hoon
new file mode 100644
index 0000000..0782b7d
--- /dev/null
+++ b/desk/web/router.hoon
@@ -0,0 +1,43 @@
+/- sur=nostril
+/+ lib=nostril, sr=sortug
+/+ server
+:: pages and components
+/= layout /web/layout
+/= navbar /web/components/navbar
+/= index /web/pages/index
+:: assets
+/* css %css /web/assets/style/css
+/* spinner %noun /web/assets/spinner/svg
+/* favicon %noun /web/assets/favicon/ico
+/* favicon1 %noun /web/assets/favicon-32x32/png
+/* favicon2 %noun /web/assets/favicon-16x16/png
+::
+|%
++$ order [id=@ta req=inbound-request:eyre]
+++ json-body json-to-octs:server
+++ ebail |= id=@t %- give-simple-payload:app:server [id pbail]
+++ pbail
+ %- html-response:gen:server
+ %- manx-to-octs:server
+ manx-bail
+++ manx-bail ^- manx ;div:"404"
+++ manx-payload
+ |= =manx
+ ^- simple-payload:http
+ %- html-response:gen:server
+ %- manx-to-octs:server manx
+:: main
+++ router
+ |_ [=state:sur =bowl:gall]
+ ++ rout
+ |= =order
+ ^- (list card:agent:gall)
+ =/ rl (parse-request-line:server url.request.req.order)
+ =. site.rl ?~ site.rl ~ t.site.rl
+ =/ met method.request.req.order
+ =/ fpath=(pole knot) [met site.rl]
+ |^
+ ~
+ --
+ --
+--
diff --git a/front/.gitignore b/front/.gitignore
new file mode 100644
index 0000000..247c9a3
--- /dev/null
+++ b/front/.gitignore
@@ -0,0 +1,34 @@
+# Logs
+logs
+*.log
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+pnpm-debug.log*
+lerna-debug.log*
+
+node_modules
+dist
+dist-ssr
+*.local
+
+# Editor directories and files
+.vscode/*
+!.vscode/extensions.json
+.idea
+.DS_Store
+*.suo
+*.ntvs*
+*.njsproj
+*.sln
+*.sw?
+
+# Devenv
+.devenv*
+devenv.local.nix
+
+# direnv
+.direnv
+
+# pre-commit
+.pre-commit-config.yaml
diff --git a/front/README.md b/front/README.md
new file mode 100644
index 0000000..7959ce4
--- /dev/null
+++ b/front/README.md
@@ -0,0 +1,69 @@
+# React + TypeScript + Vite
+
+This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.
+
+Currently, two official plugins are available:
+
+- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react) uses [Babel](https://babeljs.io/) for Fast Refresh
+- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh
+
+## Expanding the ESLint configuration
+
+If you are developing a production application, we recommend updating the configuration to enable type-aware lint rules:
+
+```js
+export default tseslint.config([
+ globalIgnores(['dist']),
+ {
+ files: ['**/*.{ts,tsx}'],
+ extends: [
+ // Other configs...
+
+ // Remove tseslint.configs.recommended and replace with this
+ ...tseslint.configs.recommendedTypeChecked,
+ // Alternatively, use this for stricter rules
+ ...tseslint.configs.strictTypeChecked,
+ // Optionally, add this for stylistic rules
+ ...tseslint.configs.stylisticTypeChecked,
+
+ // Other configs...
+ ],
+ languageOptions: {
+ parserOptions: {
+ project: ['./tsconfig.node.json', './tsconfig.app.json'],
+ tsconfigRootDir: import.meta.dirname,
+ },
+ // other options...
+ },
+ },
+])
+```
+
+You can also install [eslint-plugin-react-x](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-x) and [eslint-plugin-react-dom](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-dom) for React-specific lint rules:
+
+```js
+// eslint.config.js
+import reactX from 'eslint-plugin-react-x'
+import reactDom from 'eslint-plugin-react-dom'
+
+export default tseslint.config([
+ globalIgnores(['dist']),
+ {
+ files: ['**/*.{ts,tsx}'],
+ extends: [
+ // Other configs...
+ // Enable lint rules for React
+ reactX.configs['recommended-typescript'],
+ // Enable lint rules for React DOM
+ reactDom.configs.recommended,
+ ],
+ languageOptions: {
+ parserOptions: {
+ project: ['./tsconfig.node.json', './tsconfig.app.json'],
+ tsconfigRootDir: import.meta.dirname,
+ },
+ // other options...
+ },
+ },
+])
+```
diff --git a/front/bun.lock b/front/bun.lock
new file mode 100644
index 0000000..acffc6f
--- /dev/null
+++ b/front/bun.lock
@@ -0,0 +1,556 @@
+{
+ "lockfileVersion": 1,
+ "workspaces": {
+ "": {
+ "name": "front",
+ "dependencies": {
+ "@tanstack/react-query": "^5.85.9",
+ "any-ascii": "^0.3.3",
+ "react": "^19.1.1",
+ "react-dom": "^19.1.1",
+ "react-hot-toast": "^2.6.0",
+ "urbit-api": "file:../../../urbit/bun/http-api",
+ "urbit-ob": "file:../../../urbit/bun/urbit-ob",
+ "urbit-sigils": "file:../../../urbit/bun/sigil-ts",
+ "wouter": "^3.7.1",
+ "zustand": "^5.0.8",
+ },
+ "devDependencies": {
+ "@eslint/js": "^9.33.0",
+ "@types/react": "^19.1.10",
+ "@types/react-dom": "^19.1.7",
+ "@vitejs/plugin-react": "^5.0.0",
+ "eslint": "^9.33.0",
+ "eslint-plugin-react-hooks": "^5.2.0",
+ "eslint-plugin-react-refresh": "^0.4.20",
+ "globals": "^16.3.0",
+ "typescript": "~5.8.3",
+ "typescript-eslint": "^8.39.1",
+ "vite": "^7.1.2",
+ },
+ },
+ },
+ "packages": {
+ "@ampproject/remapping": ["@ampproject/remapping@2.3.0", "", { "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw=="],
+
+ "@babel/code-frame": ["@babel/code-frame@7.27.1", "", { "dependencies": { "@babel/helper-validator-identifier": "^7.27.1", "js-tokens": "^4.0.0", "picocolors": "^1.1.1" } }, "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg=="],
+
+ "@babel/compat-data": ["@babel/compat-data@7.28.0", "", {}, "sha512-60X7qkglvrap8mn1lh2ebxXdZYtUcpd7gsmy9kLaBJ4i/WdY8PqTSdxyA8qraikqKQK5C1KRBKXqznrVapyNaw=="],
+
+ "@babel/core": ["@babel/core@7.28.3", "", { "dependencies": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.27.1", "@babel/generator": "^7.28.3", "@babel/helper-compilation-targets": "^7.27.2", "@babel/helper-module-transforms": "^7.28.3", "@babel/helpers": "^7.28.3", "@babel/parser": "^7.28.3", "@babel/template": "^7.27.2", "@babel/traverse": "^7.28.3", "@babel/types": "^7.28.2", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", "json5": "^2.2.3", "semver": "^6.3.1" } }, "sha512-yDBHV9kQNcr2/sUr9jghVyz9C3Y5G2zUM2H2lo+9mKv4sFgbA8s8Z9t8D1jiTkGoO/NoIfKMyKWr4s6CN23ZwQ=="],
+
+ "@babel/generator": ["@babel/generator@7.28.3", "", { "dependencies": { "@babel/parser": "^7.28.3", "@babel/types": "^7.28.2", "@jridgewell/gen-mapping": "^0.3.12", "@jridgewell/trace-mapping": "^0.3.28", "jsesc": "^3.0.2" } }, "sha512-3lSpxGgvnmZznmBkCRnVREPUFJv2wrv9iAoFDvADJc0ypmdOxdUtcLeBgBJ6zE0PMeTKnxeQzyk0xTBq4Ep7zw=="],
+
+ "@babel/helper-compilation-targets": ["@babel/helper-compilation-targets@7.27.2", "", { "dependencies": { "@babel/compat-data": "^7.27.2", "@babel/helper-validator-option": "^7.27.1", "browserslist": "^4.24.0", "lru-cache": "^5.1.1", "semver": "^6.3.1" } }, "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ=="],
+
+ "@babel/helper-globals": ["@babel/helper-globals@7.28.0", "", {}, "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw=="],
+
+ "@babel/helper-module-imports": ["@babel/helper-module-imports@7.27.1", "", { "dependencies": { "@babel/traverse": "^7.27.1", "@babel/types": "^7.27.1" } }, "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w=="],
+
+ "@babel/helper-module-transforms": ["@babel/helper-module-transforms@7.28.3", "", { "dependencies": { "@babel/helper-module-imports": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1", "@babel/traverse": "^7.28.3" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw=="],
+
+ "@babel/helper-plugin-utils": ["@babel/helper-plugin-utils@7.27.1", "", {}, "sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw=="],
+
+ "@babel/helper-string-parser": ["@babel/helper-string-parser@7.27.1", "", {}, "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA=="],
+
+ "@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.27.1", "", {}, "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow=="],
+
+ "@babel/helper-validator-option": ["@babel/helper-validator-option@7.27.1", "", {}, "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg=="],
+
+ "@babel/helpers": ["@babel/helpers@7.28.3", "", { "dependencies": { "@babel/template": "^7.27.2", "@babel/types": "^7.28.2" } }, "sha512-PTNtvUQihsAsDHMOP5pfobP8C6CM4JWXmP8DrEIt46c3r2bf87Ua1zoqevsMo9g+tWDwgWrFP5EIxuBx5RudAw=="],
+
+ "@babel/parser": ["@babel/parser@7.28.3", "", { "dependencies": { "@babel/types": "^7.28.2" }, "bin": "./bin/babel-parser.js" }, "sha512-7+Ey1mAgYqFAx2h0RuoxcQT5+MlG3GTV0TQrgr7/ZliKsm/MNDxVVutlWaziMq7wJNAz8MTqz55XLpWvva6StA=="],
+
+ "@babel/plugin-transform-react-jsx-self": ["@babel/plugin-transform-react-jsx-self@7.27.1", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw=="],
+
+ "@babel/plugin-transform-react-jsx-source": ["@babel/plugin-transform-react-jsx-source@7.27.1", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw=="],
+
+ "@babel/template": ["@babel/template@7.27.2", "", { "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/parser": "^7.27.2", "@babel/types": "^7.27.1" } }, "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw=="],
+
+ "@babel/traverse": ["@babel/traverse@7.28.3", "", { "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/generator": "^7.28.3", "@babel/helper-globals": "^7.28.0", "@babel/parser": "^7.28.3", "@babel/template": "^7.27.2", "@babel/types": "^7.28.2", "debug": "^4.3.1" } }, "sha512-7w4kZYHneL3A6NP2nxzHvT3HCZ7puDZZjFMqDpBPECub79sTtSO5CGXDkKrTQq8ksAwfD/XI2MRFX23njdDaIQ=="],
+
+ "@babel/types": ["@babel/types@7.28.2", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1" } }, "sha512-ruv7Ae4J5dUYULmeXw1gmb7rYRz57OWCPM57pHojnLq/3Z1CK2lNSLTCVjxVk1F/TZHwOZZrOWi0ur95BbLxNQ=="],
+
+ "@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.25.9", "", { "os": "aix", "cpu": "ppc64" }, "sha512-OaGtL73Jck6pBKjNIe24BnFE6agGl+6KxDtTfHhy1HmhthfKouEcOhqpSL64K4/0WCtbKFLOdzD/44cJ4k9opA=="],
+
+ "@esbuild/android-arm": ["@esbuild/android-arm@0.25.9", "", { "os": "android", "cpu": "arm" }, "sha512-5WNI1DaMtxQ7t7B6xa572XMXpHAaI/9Hnhk8lcxF4zVN4xstUgTlvuGDorBguKEnZO70qwEcLpfifMLoxiPqHQ=="],
+
+ "@esbuild/android-arm64": ["@esbuild/android-arm64@0.25.9", "", { "os": "android", "cpu": "arm64" }, "sha512-IDrddSmpSv51ftWslJMvl3Q2ZT98fUSL2/rlUXuVqRXHCs5EUF1/f+jbjF5+NG9UffUDMCiTyh8iec7u8RlTLg=="],
+
+ "@esbuild/android-x64": ["@esbuild/android-x64@0.25.9", "", { "os": "android", "cpu": "x64" }, "sha512-I853iMZ1hWZdNllhVZKm34f4wErd4lMyeV7BLzEExGEIZYsOzqDWDf+y082izYUE8gtJnYHdeDpN/6tUdwvfiw=="],
+
+ "@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.25.9", "", { "os": "darwin", "cpu": "arm64" }, "sha512-XIpIDMAjOELi/9PB30vEbVMs3GV1v2zkkPnuyRRURbhqjyzIINwj+nbQATh4H9GxUgH1kFsEyQMxwiLFKUS6Rg=="],
+
+ "@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.25.9", "", { "os": "darwin", "cpu": "x64" }, "sha512-jhHfBzjYTA1IQu8VyrjCX4ApJDnH+ez+IYVEoJHeqJm9VhG9Dh2BYaJritkYK3vMaXrf7Ogr/0MQ8/MeIefsPQ=="],
+
+ "@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.25.9", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-z93DmbnY6fX9+KdD4Ue/H6sYs+bhFQJNCPZsi4XWJoYblUqT06MQUdBCpcSfuiN72AbqeBFu5LVQTjfXDE2A6Q=="],
+
+ "@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.25.9", "", { "os": "freebsd", "cpu": "x64" }, "sha512-mrKX6H/vOyo5v71YfXWJxLVxgy1kyt1MQaD8wZJgJfG4gq4DpQGpgTB74e5yBeQdyMTbgxp0YtNj7NuHN0PoZg=="],
+
+ "@esbuild/linux-arm": ["@esbuild/linux-arm@0.25.9", "", { "os": "linux", "cpu": "arm" }, "sha512-HBU2Xv78SMgaydBmdor38lg8YDnFKSARg1Q6AT0/y2ezUAKiZvc211RDFHlEZRFNRVhcMamiToo7bDx3VEOYQw=="],
+
+ "@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.25.9", "", { "os": "linux", "cpu": "arm64" }, "sha512-BlB7bIcLT3G26urh5Dmse7fiLmLXnRlopw4s8DalgZ8ef79Jj4aUcYbk90g8iCa2467HX8SAIidbL7gsqXHdRw=="],
+
+ "@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.25.9", "", { "os": "linux", "cpu": "ia32" }, "sha512-e7S3MOJPZGp2QW6AK6+Ly81rC7oOSerQ+P8L0ta4FhVi+/j/v2yZzx5CqqDaWjtPFfYz21Vi1S0auHrap3Ma3A=="],
+
+ "@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.25.9", "", { "os": "linux", "cpu": "none" }, "sha512-Sbe10Bnn0oUAB2AalYztvGcK+o6YFFA/9829PhOCUS9vkJElXGdphz0A3DbMdP8gmKkqPmPcMJmJOrI3VYB1JQ=="],
+
+ "@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.25.9", "", { "os": "linux", "cpu": "none" }, "sha512-YcM5br0mVyZw2jcQeLIkhWtKPeVfAerES5PvOzaDxVtIyZ2NUBZKNLjC5z3/fUlDgT6w89VsxP2qzNipOaaDyA=="],
+
+ "@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.25.9", "", { "os": "linux", "cpu": "ppc64" }, "sha512-++0HQvasdo20JytyDpFvQtNrEsAgNG2CY1CLMwGXfFTKGBGQT3bOeLSYE2l1fYdvML5KUuwn9Z8L1EWe2tzs1w=="],
+
+ "@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.25.9", "", { "os": "linux", "cpu": "none" }, "sha512-uNIBa279Y3fkjV+2cUjx36xkx7eSjb8IvnL01eXUKXez/CBHNRw5ekCGMPM0BcmqBxBcdgUWuUXmVWwm4CH9kg=="],
+
+ "@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.25.9", "", { "os": "linux", "cpu": "s390x" }, "sha512-Mfiphvp3MjC/lctb+7D287Xw1DGzqJPb/J2aHHcHxflUo+8tmN/6d4k6I2yFR7BVo5/g7x2Monq4+Yew0EHRIA=="],
+
+ "@esbuild/linux-x64": ["@esbuild/linux-x64@0.25.9", "", { "os": "linux", "cpu": "x64" }, "sha512-iSwByxzRe48YVkmpbgoxVzn76BXjlYFXC7NvLYq+b+kDjyyk30J0JY47DIn8z1MO3K0oSl9fZoRmZPQI4Hklzg=="],
+
+ "@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.25.9", "", { "os": "none", "cpu": "arm64" }, "sha512-9jNJl6FqaUG+COdQMjSCGW4QiMHH88xWbvZ+kRVblZsWrkXlABuGdFJ1E9L7HK+T0Yqd4akKNa/lO0+jDxQD4Q=="],
+
+ "@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.25.9", "", { "os": "none", "cpu": "x64" }, "sha512-RLLdkflmqRG8KanPGOU7Rpg829ZHu8nFy5Pqdi9U01VYtG9Y0zOG6Vr2z4/S+/3zIyOxiK6cCeYNWOFR9QP87g=="],
+
+ "@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.25.9", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-YaFBlPGeDasft5IIM+CQAhJAqS3St3nJzDEgsgFixcfZeyGPCd6eJBWzke5piZuZ7CtL656eOSYKk4Ls2C0FRQ=="],
+
+ "@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.25.9", "", { "os": "openbsd", "cpu": "x64" }, "sha512-1MkgTCuvMGWuqVtAvkpkXFmtL8XhWy+j4jaSO2wxfJtilVCi0ZE37b8uOdMItIHz4I6z1bWWtEX4CJwcKYLcuA=="],
+
+ "@esbuild/openharmony-arm64": ["@esbuild/openharmony-arm64@0.25.9", "", { "os": "none", "cpu": "arm64" }, "sha512-4Xd0xNiMVXKh6Fa7HEJQbrpP3m3DDn43jKxMjxLLRjWnRsfxjORYJlXPO4JNcXtOyfajXorRKY9NkOpTHptErg=="],
+
+ "@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.25.9", "", { "os": "sunos", "cpu": "x64" }, "sha512-WjH4s6hzo00nNezhp3wFIAfmGZ8U7KtrJNlFMRKxiI9mxEK1scOMAaa9i4crUtu+tBr+0IN6JCuAcSBJZfnphw=="],
+
+ "@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.25.9", "", { "os": "win32", "cpu": "arm64" }, "sha512-mGFrVJHmZiRqmP8xFOc6b84/7xa5y5YvR1x8djzXpJBSv/UsNK6aqec+6JDjConTgvvQefdGhFDAs2DLAds6gQ=="],
+
+ "@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.25.9", "", { "os": "win32", "cpu": "ia32" }, "sha512-b33gLVU2k11nVx1OhX3C8QQP6UHQK4ZtN56oFWvVXvz2VkDoe6fbG8TOgHFxEvqeqohmRnIHe5A1+HADk4OQww=="],
+
+ "@esbuild/win32-x64": ["@esbuild/win32-x64@0.25.9", "", { "os": "win32", "cpu": "x64" }, "sha512-PPOl1mi6lpLNQxnGoyAfschAodRFYXJ+9fs6WHXz7CSWKbOqiMZsubC+BQsVKuul+3vKLuwTHsS2c2y9EoKwxQ=="],
+
+ "@eslint-community/eslint-utils": ["@eslint-community/eslint-utils@4.8.0", "", { "dependencies": { "eslint-visitor-keys": "^3.4.3" }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, "sha512-MJQFqrZgcW0UNYLGOuQpey/oTN59vyWwplvCGZztn1cKz9agZPPYpJB7h2OMmuu7VLqkvEjN8feFZJmxNF9D+Q=="],
+
+ "@eslint-community/regexpp": ["@eslint-community/regexpp@4.12.1", "", {}, "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ=="],
+
+ "@eslint/config-array": ["@eslint/config-array@0.21.0", "", { "dependencies": { "@eslint/object-schema": "^2.1.6", "debug": "^4.3.1", "minimatch": "^3.1.2" } }, "sha512-ENIdc4iLu0d93HeYirvKmrzshzofPw6VkZRKQGe9Nv46ZnWUzcF1xV01dcvEg/1wXUR61OmmlSfyeyO7EvjLxQ=="],
+
+ "@eslint/config-helpers": ["@eslint/config-helpers@0.3.1", "", {}, "sha512-xR93k9WhrDYpXHORXpxVL5oHj3Era7wo6k/Wd8/IsQNnZUTzkGS29lyn3nAT05v6ltUuTFVCCYDEGfy2Or/sPA=="],
+
+ "@eslint/core": ["@eslint/core@0.15.2", "", { "dependencies": { "@types/json-schema": "^7.0.15" } }, "sha512-78Md3/Rrxh83gCxoUc0EiciuOHsIITzLy53m3d9UyiW8y9Dj2D29FeETqyKA+BRK76tnTp6RXWb3pCay8Oyomg=="],
+
+ "@eslint/eslintrc": ["@eslint/eslintrc@3.3.1", "", { "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", "espree": "^10.0.1", "globals": "^14.0.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", "js-yaml": "^4.1.0", "minimatch": "^3.1.2", "strip-json-comments": "^3.1.1" } }, "sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ=="],
+
+ "@eslint/js": ["@eslint/js@9.34.0", "", {}, "sha512-EoyvqQnBNsV1CWaEJ559rxXL4c8V92gxirbawSmVUOWXlsRxxQXl6LmCpdUblgxgSkDIqKnhzba2SjRTI/A5Rw=="],
+
+ "@eslint/object-schema": ["@eslint/object-schema@2.1.6", "", {}, "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA=="],
+
+ "@eslint/plugin-kit": ["@eslint/plugin-kit@0.3.5", "", { "dependencies": { "@eslint/core": "^0.15.2", "levn": "^0.4.1" } }, "sha512-Z5kJ+wU3oA7MMIqVR9tyZRtjYPr4OC004Q4Rw7pgOKUOKkJfZ3O24nz3WYfGRpMDNmcOi3TwQOmgm7B7Tpii0w=="],
+
+ "@humanfs/core": ["@humanfs/core@0.19.1", "", {}, "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA=="],
+
+ "@humanfs/node": ["@humanfs/node@0.16.6", "", { "dependencies": { "@humanfs/core": "^0.19.1", "@humanwhocodes/retry": "^0.3.0" } }, "sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw=="],
+
+ "@humanwhocodes/module-importer": ["@humanwhocodes/module-importer@1.0.1", "", {}, "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA=="],
+
+ "@humanwhocodes/retry": ["@humanwhocodes/retry@0.4.3", "", {}, "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ=="],
+
+ "@jridgewell/gen-mapping": ["@jridgewell/gen-mapping@0.3.13", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA=="],
+
+ "@jridgewell/resolve-uri": ["@jridgewell/resolve-uri@3.1.2", "", {}, "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw=="],
+
+ "@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.5", "", {}, "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og=="],
+
+ "@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.30", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-GQ7Nw5G2lTu/BtHTKfXhKHok2WGetd4XYcVKGx00SjAk8GMwgJM3zr6zORiPGuOE+/vkc90KtTosSSvaCjKb2Q=="],
+
+ "@nodelib/fs.scandir": ["@nodelib/fs.scandir@2.1.5", "", { "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" } }, "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g=="],
+
+ "@nodelib/fs.stat": ["@nodelib/fs.stat@2.0.5", "", {}, "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A=="],
+
+ "@nodelib/fs.walk": ["@nodelib/fs.walk@1.2.8", "", { "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" } }, "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg=="],
+
+ "@rolldown/pluginutils": ["@rolldown/pluginutils@1.0.0-beta.34", "", {}, "sha512-LyAREkZHP5pMom7c24meKmJCdhf2hEyvam2q0unr3or9ydwDL+DJ8chTF6Av/RFPb3rH8UFBdMzO5MxTZW97oA=="],
+
+ "@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.50.0", "", { "os": "android", "cpu": "arm" }, "sha512-lVgpeQyy4fWN5QYebtW4buT/4kn4p4IJ+kDNB4uYNT5b8c8DLJDg6titg20NIg7E8RWwdWZORW6vUFfrLyG3KQ=="],
+
+ "@rollup/rollup-android-arm64": ["@rollup/rollup-android-arm64@4.50.0", "", { "os": "android", "cpu": "arm64" }, "sha512-2O73dR4Dc9bp+wSYhviP6sDziurB5/HCym7xILKifWdE9UsOe2FtNcM+I4xZjKrfLJnq5UR8k9riB87gauiQtw=="],
+
+ "@rollup/rollup-darwin-arm64": ["@rollup/rollup-darwin-arm64@4.50.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-vwSXQN8T4sKf1RHr1F0s98Pf8UPz7pS6P3LG9NSmuw0TVh7EmaE+5Ny7hJOZ0M2yuTctEsHHRTMi2wuHkdS6Hg=="],
+
+ "@rollup/rollup-darwin-x64": ["@rollup/rollup-darwin-x64@4.50.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-cQp/WG8HE7BCGyFVuzUg0FNmupxC+EPZEwWu2FCGGw5WDT1o2/YlENbm5e9SMvfDFR6FRhVCBePLqj0o8MN7Vw=="],
+
+ "@rollup/rollup-freebsd-arm64": ["@rollup/rollup-freebsd-arm64@4.50.0", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-UR1uTJFU/p801DvvBbtDD7z9mQL8J80xB0bR7DqW7UGQHRm/OaKzp4is7sQSdbt2pjjSS72eAtRh43hNduTnnQ=="],
+
+ "@rollup/rollup-freebsd-x64": ["@rollup/rollup-freebsd-x64@4.50.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-G/DKyS6PK0dD0+VEzH/6n/hWDNPDZSMBmqsElWnCRGrYOb2jC0VSupp7UAHHQ4+QILwkxSMaYIbQ72dktp8pKA=="],
+
+ "@rollup/rollup-linux-arm-gnueabihf": ["@rollup/rollup-linux-arm-gnueabihf@4.50.0", "", { "os": "linux", "cpu": "arm" }, "sha512-u72Mzc6jyJwKjJbZZcIYmd9bumJu7KNmHYdue43vT1rXPm2rITwmPWF0mmPzLm9/vJWxIRbao/jrQmxTO0Sm9w=="],
+
+ "@rollup/rollup-linux-arm-musleabihf": ["@rollup/rollup-linux-arm-musleabihf@4.50.0", "", { "os": "linux", "cpu": "arm" }, "sha512-S4UefYdV0tnynDJV1mdkNawp0E5Qm2MtSs330IyHgaccOFrwqsvgigUD29uT+B/70PDY1eQ3t40+xf6wIvXJyg=="],
+
+ "@rollup/rollup-linux-arm64-gnu": ["@rollup/rollup-linux-arm64-gnu@4.50.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-1EhkSvUQXJsIhk4msxP5nNAUWoB4MFDHhtc4gAYvnqoHlaL9V3F37pNHabndawsfy/Tp7BPiy/aSa6XBYbaD1g=="],
+
+ "@rollup/rollup-linux-arm64-musl": ["@rollup/rollup-linux-arm64-musl@4.50.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-EtBDIZuDtVg75xIPIK1l5vCXNNCIRM0OBPUG+tbApDuJAy9mKago6QxX+tfMzbCI6tXEhMuZuN1+CU8iDW+0UQ=="],
+
+ "@rollup/rollup-linux-loongarch64-gnu": ["@rollup/rollup-linux-loongarch64-gnu@4.50.0", "", { "os": "linux", "cpu": "none" }, "sha512-BGYSwJdMP0hT5CCmljuSNx7+k+0upweM2M4YGfFBjnFSZMHOLYR0gEEj/dxyYJ6Zc6AiSeaBY8dWOa11GF/ppQ=="],
+
+ "@rollup/rollup-linux-ppc64-gnu": ["@rollup/rollup-linux-ppc64-gnu@4.50.0", "", { "os": "linux", "cpu": "ppc64" }, "sha512-I1gSMzkVe1KzAxKAroCJL30hA4DqSi+wGc5gviD0y3IL/VkvcnAqwBf4RHXHyvH66YVHxpKO8ojrgc4SrWAnLg=="],
+
+ "@rollup/rollup-linux-riscv64-gnu": ["@rollup/rollup-linux-riscv64-gnu@4.50.0", "", { "os": "linux", "cpu": "none" }, "sha512-bSbWlY3jZo7molh4tc5dKfeSxkqnf48UsLqYbUhnkdnfgZjgufLS/NTA8PcP/dnvct5CCdNkABJ56CbclMRYCA=="],
+
+ "@rollup/rollup-linux-riscv64-musl": ["@rollup/rollup-linux-riscv64-musl@4.50.0", "", { "os": "linux", "cpu": "none" }, "sha512-LSXSGumSURzEQLT2e4sFqFOv3LWZsEF8FK7AAv9zHZNDdMnUPYH3t8ZlaeYYZyTXnsob3htwTKeWtBIkPV27iQ=="],
+
+ "@rollup/rollup-linux-s390x-gnu": ["@rollup/rollup-linux-s390x-gnu@4.50.0", "", { "os": "linux", "cpu": "s390x" }, "sha512-CxRKyakfDrsLXiCyucVfVWVoaPA4oFSpPpDwlMcDFQvrv3XY6KEzMtMZrA+e/goC8xxp2WSOxHQubP8fPmmjOQ=="],
+
+ "@rollup/rollup-linux-x64-gnu": ["@rollup/rollup-linux-x64-gnu@4.50.0", "", { "os": "linux", "cpu": "x64" }, "sha512-8PrJJA7/VU8ToHVEPu14FzuSAqVKyo5gg/J8xUerMbyNkWkO9j2ExBho/68RnJsMGNJq4zH114iAttgm7BZVkA=="],
+
+ "@rollup/rollup-linux-x64-musl": ["@rollup/rollup-linux-x64-musl@4.50.0", "", { "os": "linux", "cpu": "x64" }, "sha512-SkE6YQp+CzpyOrbw7Oc4MgXFvTw2UIBElvAvLCo230pyxOLmYwRPwZ/L5lBe/VW/qT1ZgND9wJfOsdy0XptRvw=="],
+
+ "@rollup/rollup-openharmony-arm64": ["@rollup/rollup-openharmony-arm64@4.50.0", "", { "os": "none", "cpu": "arm64" }, "sha512-PZkNLPfvXeIOgJWA804zjSFH7fARBBCpCXxgkGDRjjAhRLOR8o0IGS01ykh5GYfod4c2yiiREuDM8iZ+pVsT+Q=="],
+
+ "@rollup/rollup-win32-arm64-msvc": ["@rollup/rollup-win32-arm64-msvc@4.50.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-q7cIIdFvWQoaCbLDUyUc8YfR3Jh2xx3unO8Dn6/TTogKjfwrax9SyfmGGK6cQhKtjePI7jRfd7iRYcxYs93esg=="],
+
+ "@rollup/rollup-win32-ia32-msvc": ["@rollup/rollup-win32-ia32-msvc@4.50.0", "", { "os": "win32", "cpu": "ia32" }, "sha512-XzNOVg/YnDOmFdDKcxxK410PrcbcqZkBmz+0FicpW5jtjKQxcW1BZJEQOF0NJa6JO7CZhett8GEtRN/wYLYJuw=="],
+
+ "@rollup/rollup-win32-x64-msvc": ["@rollup/rollup-win32-x64-msvc@4.50.0", "", { "os": "win32", "cpu": "x64" }, "sha512-xMmiWRR8sp72Zqwjgtf3QbZfF1wdh8X2ABu3EaozvZcyHJeU0r+XAnXdKgs4cCAp6ORoYoCygipYP1mjmbjrsg=="],
+
+ "@tanstack/query-core": ["@tanstack/query-core@5.85.9", "", {}, "sha512-5fxb9vwyftYE6KFLhhhDyLr8NO75+Wpu7pmTo+TkwKmMX2oxZDoLwcqGP8ItKSpUMwk3urWgQDZfyWr5Jm9LsQ=="],
+
+ "@tanstack/react-query": ["@tanstack/react-query@5.85.9", "", { "dependencies": { "@tanstack/query-core": "5.85.9" }, "peerDependencies": { "react": "^18 || ^19" } }, "sha512-2T5zgSpcOZXGkH/UObIbIkGmUPQqZqn7esVQFXLOze622h4spgWf5jmvrqAo9dnI13/hyMcNsF1jsoDcb59nJQ=="],
+
+ "@types/babel__core": ["@types/babel__core@7.20.5", "", { "dependencies": { "@babel/parser": "^7.20.7", "@babel/types": "^7.20.7", "@types/babel__generator": "*", "@types/babel__template": "*", "@types/babel__traverse": "*" } }, "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA=="],
+
+ "@types/babel__generator": ["@types/babel__generator@7.27.0", "", { "dependencies": { "@babel/types": "^7.0.0" } }, "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg=="],
+
+ "@types/babel__template": ["@types/babel__template@7.4.4", "", { "dependencies": { "@babel/parser": "^7.1.0", "@babel/types": "^7.0.0" } }, "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A=="],
+
+ "@types/babel__traverse": ["@types/babel__traverse@7.28.0", "", { "dependencies": { "@babel/types": "^7.28.2" } }, "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q=="],
+
+ "@types/bun": ["@types/bun@1.2.21", "", { "dependencies": { "bun-types": "1.2.21" } }, "sha512-NiDnvEqmbfQ6dmZ3EeUO577s4P5bf4HCTXtI6trMc6f6RzirY5IrF3aIookuSpyslFzrnvv2lmEWv5HyC1X79A=="],
+
+ "@types/estree": ["@types/estree@1.0.8", "", {}, "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w=="],
+
+ "@types/invariant": ["@types/invariant@2.2.37", "", {}, "sha512-IwpIMieE55oGWiXkQPSBY1nw1nFs6bsKXTFskNY8sdS17K24vyEBRQZEwlRS7ZmXCWnJcQtbxWzly+cODWGs2A=="],
+
+ "@types/json-schema": ["@types/json-schema@7.0.15", "", {}, "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA=="],
+
+ "@types/node": ["@types/node@24.3.0", "", { "dependencies": { "undici-types": "~7.10.0" } }, "sha512-aPTXCrfwnDLj4VvXrm+UUCQjNEvJgNA8s5F1cvwQU+3KNltTOkBm1j30uNLyqqPNe7gE3KFzImYoZEfLhp4Yow=="],
+
+ "@types/react": ["@types/react@19.1.12", "", { "dependencies": { "csstype": "^3.0.2" } }, "sha512-cMoR+FoAf/Jyq6+Df2/Z41jISvGZZ2eTlnsaJRptmZ76Caldwy1odD4xTr/gNV9VLj0AWgg/nmkevIyUfIIq5w=="],
+
+ "@types/react-dom": ["@types/react-dom@19.1.9", "", { "peerDependencies": { "@types/react": "^19.0.0" } }, "sha512-qXRuZaOsAdXKFyOhRBg6Lqqc0yay13vN7KrIg4L7N4aaHN68ma9OK3NE1BoDFgFOTfM7zg+3/8+2n8rLUH3OKQ=="],
+
+ "@typescript-eslint/eslint-plugin": ["@typescript-eslint/eslint-plugin@8.42.0", "", { "dependencies": { "@eslint-community/regexpp": "^4.10.0", "@typescript-eslint/scope-manager": "8.42.0", "@typescript-eslint/type-utils": "8.42.0", "@typescript-eslint/utils": "8.42.0", "@typescript-eslint/visitor-keys": "8.42.0", "graphemer": "^1.4.0", "ignore": "^7.0.0", "natural-compare": "^1.4.0", "ts-api-utils": "^2.1.0" }, "peerDependencies": { "@typescript-eslint/parser": "^8.42.0", "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-Aq2dPqsQkxHOLfb2OPv43RnIvfj05nw8v/6n3B2NABIPpHnjQnaLo9QGMTvml+tv4korl/Cjfrb/BYhoL8UUTQ=="],
+
+ "@typescript-eslint/parser": ["@typescript-eslint/parser@8.42.0", "", { "dependencies": { "@typescript-eslint/scope-manager": "8.42.0", "@typescript-eslint/types": "8.42.0", "@typescript-eslint/typescript-estree": "8.42.0", "@typescript-eslint/visitor-keys": "8.42.0", "debug": "^4.3.4" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-r1XG74QgShUgXph1BYseJ+KZd17bKQib/yF3SR+demvytiRXrwd12Blnz5eYGm8tXaeRdd4x88MlfwldHoudGg=="],
+
+ "@typescript-eslint/project-service": ["@typescript-eslint/project-service@8.42.0", "", { "dependencies": { "@typescript-eslint/tsconfig-utils": "^8.42.0", "@typescript-eslint/types": "^8.42.0", "debug": "^4.3.4" }, "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-vfVpLHAhbPjilrabtOSNcUDmBboQNrJUiNAGoImkZKnMjs2TIcWG33s4Ds0wY3/50aZmTMqJa6PiwkwezaAklg=="],
+
+ "@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@8.42.0", "", { "dependencies": { "@typescript-eslint/types": "8.42.0", "@typescript-eslint/visitor-keys": "8.42.0" } }, "sha512-51+x9o78NBAVgQzOPd17DkNTnIzJ8T/O2dmMBLoK9qbY0Gm52XJcdJcCl18ExBMiHo6jPMErUQWUv5RLE51zJw=="],
+
+ "@typescript-eslint/tsconfig-utils": ["@typescript-eslint/tsconfig-utils@8.42.0", "", { "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-kHeFUOdwAJfUmYKjR3CLgZSglGHjbNTi1H8sTYRYV2xX6eNz4RyJ2LIgsDLKf8Yi0/GL1WZAC/DgZBeBft8QAQ=="],
+
+ "@typescript-eslint/type-utils": ["@typescript-eslint/type-utils@8.42.0", "", { "dependencies": { "@typescript-eslint/types": "8.42.0", "@typescript-eslint/typescript-estree": "8.42.0", "@typescript-eslint/utils": "8.42.0", "debug": "^4.3.4", "ts-api-utils": "^2.1.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-9KChw92sbPTYVFw3JLRH1ockhyR3zqqn9lQXol3/YbI6jVxzWoGcT3AsAW0mu1MY0gYtsXnUGV/AKpkAj5tVlQ=="],
+
+ "@typescript-eslint/types": ["@typescript-eslint/types@8.42.0", "", {}, "sha512-LdtAWMiFmbRLNP7JNeY0SqEtJvGMYSzfiWBSmx+VSZ1CH+1zyl8Mmw1TT39OrtsRvIYShjJWzTDMPWZJCpwBlw=="],
+
+ "@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@8.42.0", "", { "dependencies": { "@typescript-eslint/project-service": "8.42.0", "@typescript-eslint/tsconfig-utils": "8.42.0", "@typescript-eslint/types": "8.42.0", "@typescript-eslint/visitor-keys": "8.42.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", "minimatch": "^9.0.4", "semver": "^7.6.0", "ts-api-utils": "^2.1.0" }, "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-ku/uYtT4QXY8sl9EDJETD27o3Ewdi72hcXg1ah/kkUgBvAYHLwj2ofswFFNXS+FL5G+AGkxBtvGt8pFBHKlHsQ=="],
+
+ "@typescript-eslint/utils": ["@typescript-eslint/utils@8.42.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.7.0", "@typescript-eslint/scope-manager": "8.42.0", "@typescript-eslint/types": "8.42.0", "@typescript-eslint/typescript-estree": "8.42.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-JnIzu7H3RH5BrKC4NoZqRfmjqCIS1u3hGZltDYJgkVdqAezl4L9d1ZLw+36huCujtSBSAirGINF/S4UxOcR+/g=="],
+
+ "@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.42.0", "", { "dependencies": { "@typescript-eslint/types": "8.42.0", "eslint-visitor-keys": "^4.2.1" } }, "sha512-3WbiuzoEowaEn8RSnhJBrxSwX8ULYE9CXaPepS2C2W3NSA5NNIvBaslpBSBElPq0UGr0xVJlXFWOAKIkyylydQ=="],
+
+ "@vitejs/plugin-react": ["@vitejs/plugin-react@5.0.2", "", { "dependencies": { "@babel/core": "^7.28.3", "@babel/plugin-transform-react-jsx-self": "^7.27.1", "@babel/plugin-transform-react-jsx-source": "^7.27.1", "@rolldown/pluginutils": "1.0.0-beta.34", "@types/babel__core": "^7.20.5", "react-refresh": "^0.17.0" }, "peerDependencies": { "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0" } }, "sha512-tmyFgixPZCx2+e6VO9TNITWcCQl8+Nl/E8YbAyPVv85QCc7/A3JrdfG2A8gIzvVhWuzMOVrFW1aReaNxrI6tbw=="],
+
+ "acorn": ["acorn@8.15.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg=="],
+
+ "acorn-jsx": ["acorn-jsx@5.3.2", "", { "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ=="],
+
+ "ajv": ["ajv@6.12.6", "", { "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" } }, "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g=="],
+
+ "ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="],
+
+ "any-ascii": ["any-ascii@0.3.3", "", {}, "sha512-8hm+zPrc1VnlxD5eRgMo9F9k2wEMZhbZVLKwA/sPKIt6ywuz7bI9uV/yb27uvc8fv8q6Wl2piJT51q1saKX0Jw=="],
+
+ "argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="],
+
+ "balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="],
+
+ "brace-expansion": ["brace-expansion@1.1.12", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg=="],
+
+ "braces": ["braces@3.0.3", "", { "dependencies": { "fill-range": "^7.1.1" } }, "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA=="],
+
+ "browserslist": ["browserslist@4.25.4", "", { "dependencies": { "caniuse-lite": "^1.0.30001737", "electron-to-chromium": "^1.5.211", "node-releases": "^2.0.19", "update-browserslist-db": "^1.1.3" }, "bin": { "browserslist": "cli.js" } }, "sha512-4jYpcjabC606xJ3kw2QwGEZKX0Aw7sgQdZCvIK9dhVSPh76BKo+C+btT1RRofH7B+8iNpEbgGNVWiLki5q93yg=="],
+
+ "bun-types": ["bun-types@1.2.21", "", { "dependencies": { "@types/node": "*" }, "peerDependencies": { "@types/react": "^19" } }, "sha512-sa2Tj77Ijc/NTLS0/Odjq/qngmEPZfbfnOERi0KRUYhT9R8M4VBioWVmMWE5GrYbKMc+5lVybXygLdibHaqVqw=="],
+
+ "callsites": ["callsites@3.1.0", "", {}, "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ=="],
+
+ "caniuse-lite": ["caniuse-lite@1.0.30001739", "", {}, "sha512-y+j60d6ulelrNSwpPyrHdl+9mJnQzHBr08xm48Qno0nSk4h3Qojh+ziv2qE6rXf4k3tadF4o1J/1tAbVm1NtnA=="],
+
+ "chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="],
+
+ "color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="],
+
+ "color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="],
+
+ "concat-map": ["concat-map@0.0.1", "", {}, "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="],
+
+ "convert-source-map": ["convert-source-map@2.0.0", "", {}, "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg=="],
+
+ "cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="],
+
+ "csstype": ["csstype@3.1.3", "", {}, "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="],
+
+ "debug": ["debug@4.4.1", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ=="],
+
+ "deep-is": ["deep-is@0.1.4", "", {}, "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ=="],
+
+ "deep-rename-keys": ["deep-rename-keys@0.2.1", "", { "dependencies": { "kind-of": "^3.0.2", "rename-keys": "^1.1.2" } }, "sha512-RHd9ABw4Fvk+gYDWqwOftG849x0bYOySl/RgX0tLI9i27ZIeSO91mLZJEp7oPHOMFqHvpgu21YptmDt0FYD/0A=="],
+
+ "electron-to-chromium": ["electron-to-chromium@1.5.213", "", {}, "sha512-xr9eRzSLNa4neDO0xVFrkXu3vyIzG4Ay08dApecw42Z1NbmCt+keEpXdvlYGVe0wtvY5dhW0Ay0lY0IOfsCg0Q=="],
+
+ "esbuild": ["esbuild@0.25.9", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.25.9", "@esbuild/android-arm": "0.25.9", "@esbuild/android-arm64": "0.25.9", "@esbuild/android-x64": "0.25.9", "@esbuild/darwin-arm64": "0.25.9", "@esbuild/darwin-x64": "0.25.9", "@esbuild/freebsd-arm64": "0.25.9", "@esbuild/freebsd-x64": "0.25.9", "@esbuild/linux-arm": "0.25.9", "@esbuild/linux-arm64": "0.25.9", "@esbuild/linux-ia32": "0.25.9", "@esbuild/linux-loong64": "0.25.9", "@esbuild/linux-mips64el": "0.25.9", "@esbuild/linux-ppc64": "0.25.9", "@esbuild/linux-riscv64": "0.25.9", "@esbuild/linux-s390x": "0.25.9", "@esbuild/linux-x64": "0.25.9", "@esbuild/netbsd-arm64": "0.25.9", "@esbuild/netbsd-x64": "0.25.9", "@esbuild/openbsd-arm64": "0.25.9", "@esbuild/openbsd-x64": "0.25.9", "@esbuild/openharmony-arm64": "0.25.9", "@esbuild/sunos-x64": "0.25.9", "@esbuild/win32-arm64": "0.25.9", "@esbuild/win32-ia32": "0.25.9", "@esbuild/win32-x64": "0.25.9" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-CRbODhYyQx3qp7ZEwzxOk4JBqmD/seJrzPa/cGjY1VtIn5E09Oi9/dB4JwctnfZ8Q8iT7rioVv5k/FNT/uf54g=="],
+
+ "escalade": ["escalade@3.2.0", "", {}, "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA=="],
+
+ "escape-string-regexp": ["escape-string-regexp@4.0.0", "", {}, "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA=="],
+
+ "eslint": ["eslint@9.34.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.12.1", "@eslint/config-array": "^0.21.0", "@eslint/config-helpers": "^0.3.1", "@eslint/core": "^0.15.2", "@eslint/eslintrc": "^3.3.1", "@eslint/js": "9.34.0", "@eslint/plugin-kit": "^0.3.5", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", "@types/estree": "^1.0.6", "@types/json-schema": "^7.0.15", "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.6", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", "eslint-scope": "^8.4.0", "eslint-visitor-keys": "^4.2.1", "espree": "^10.4.0", "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^8.0.0", "find-up": "^5.0.0", "glob-parent": "^6.0.2", "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "json-stable-stringify-without-jsonify": "^1.0.1", "lodash.merge": "^4.6.2", "minimatch": "^3.1.2", "natural-compare": "^1.4.0", "optionator": "^0.9.3" }, "peerDependencies": { "jiti": "*" }, "optionalPeers": ["jiti"], "bin": { "eslint": "bin/eslint.js" } }, "sha512-RNCHRX5EwdrESy3Jc9o8ie8Bog+PeYvvSR8sDGoZxNFTvZ4dlxUB3WzQ3bQMztFrSRODGrLLj8g6OFuGY/aiQg=="],
+
+ "eslint-plugin-react-hooks": ["eslint-plugin-react-hooks@5.2.0", "", { "peerDependencies": { "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0" } }, "sha512-+f15FfK64YQwZdJNELETdn5ibXEUQmW1DZL6KXhNnc2heoy/sg9VJJeT7n8TlMWouzWqSWavFkIhHyIbIAEapg=="],
+
+ "eslint-plugin-react-refresh": ["eslint-plugin-react-refresh@0.4.20", "", { "peerDependencies": { "eslint": ">=8.40" } }, "sha512-XpbHQ2q5gUF8BGOX4dHe+71qoirYMhApEPZ7sfhF/dNnOF1UXnCMGZf79SFTBO7Bz5YEIT4TMieSlJBWhP9WBA=="],
+
+ "eslint-scope": ["eslint-scope@8.4.0", "", { "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" } }, "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg=="],
+
+ "eslint-visitor-keys": ["eslint-visitor-keys@4.2.1", "", {}, "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ=="],
+
+ "espree": ["espree@10.4.0", "", { "dependencies": { "acorn": "^8.15.0", "acorn-jsx": "^5.3.2", "eslint-visitor-keys": "^4.2.1" } }, "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ=="],
+
+ "esquery": ["esquery@1.6.0", "", { "dependencies": { "estraverse": "^5.1.0" } }, "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg=="],
+
+ "esrecurse": ["esrecurse@4.3.0", "", { "dependencies": { "estraverse": "^5.2.0" } }, "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag=="],
+
+ "estraverse": ["estraverse@5.3.0", "", {}, "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA=="],
+
+ "esutils": ["esutils@2.0.3", "", {}, "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g=="],
+
+ "eventemitter3": ["eventemitter3@2.0.3", "", {}, "sha512-jLN68Dx5kyFHaePoXWPsCGW5qdyZQtLYHkxkg02/Mz6g0kYpDx4FyP6XfArhQdlOC4b8Mv+EMxPo/8La7Tzghg=="],
+
+ "fast-deep-equal": ["fast-deep-equal@3.1.3", "", {}, "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="],
+
+ "fast-glob": ["fast-glob@3.3.3", "", { "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.2", "merge2": "^1.3.0", "micromatch": "^4.0.8" } }, "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg=="],
+
+ "fast-json-stable-stringify": ["fast-json-stable-stringify@2.1.0", "", {}, "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw=="],
+
+ "fast-levenshtein": ["fast-levenshtein@2.0.6", "", {}, "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw=="],
+
+ "fastq": ["fastq@1.19.1", "", { "dependencies": { "reusify": "^1.0.4" } }, "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ=="],
+
+ "fdir": ["fdir@6.5.0", "", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg=="],
+
+ "file-entry-cache": ["file-entry-cache@8.0.0", "", { "dependencies": { "flat-cache": "^4.0.0" } }, "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ=="],
+
+ "fill-range": ["fill-range@7.1.1", "", { "dependencies": { "to-regex-range": "^5.0.1" } }, "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg=="],
+
+ "find-up": ["find-up@5.0.0", "", { "dependencies": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" } }, "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng=="],
+
+ "flat-cache": ["flat-cache@4.0.1", "", { "dependencies": { "flatted": "^3.2.9", "keyv": "^4.5.4" } }, "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw=="],
+
+ "flatted": ["flatted@3.3.3", "", {}, "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg=="],
+
+ "fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="],
+
+ "gensync": ["gensync@1.0.0-beta.2", "", {}, "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg=="],
+
+ "glob-parent": ["glob-parent@6.0.2", "", { "dependencies": { "is-glob": "^4.0.3" } }, "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A=="],
+
+ "globals": ["globals@16.3.0", "", {}, "sha512-bqWEnJ1Nt3neqx2q5SFfGS8r/ahumIakg3HcwtNlrVlwXIeNumWn/c7Pn/wKzGhf6SaW6H6uWXLqC30STCMchQ=="],
+
+ "goober": ["goober@2.1.16", "", { "peerDependencies": { "csstype": "^3.0.10" } }, "sha512-erjk19y1U33+XAMe1VTvIONHYoSqE4iS7BYUZfHaqeohLmnC0FdxEh7rQU+6MZ4OajItzjZFSRtVANrQwNq6/g=="],
+
+ "graphemer": ["graphemer@1.4.0", "", {}, "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag=="],
+
+ "has-flag": ["has-flag@4.0.0", "", {}, "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="],
+
+ "ignore": ["ignore@5.3.2", "", {}, "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g=="],
+
+ "import-fresh": ["import-fresh@3.3.1", "", { "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" } }, "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ=="],
+
+ "imurmurhash": ["imurmurhash@0.1.4", "", {}, "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA=="],
+
+ "invariant": ["invariant@2.2.4", "", { "dependencies": { "loose-envify": "^1.0.0" } }, "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA=="],
+
+ "is-buffer": ["is-buffer@1.1.6", "", {}, "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w=="],
+
+ "is-extglob": ["is-extglob@2.1.1", "", {}, "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ=="],
+
+ "is-glob": ["is-glob@4.0.3", "", { "dependencies": { "is-extglob": "^2.1.1" } }, "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg=="],
+
+ "is-number": ["is-number@7.0.0", "", {}, "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="],
+
+ "isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="],
+
+ "js-tokens": ["js-tokens@4.0.0", "", {}, "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="],
+
+ "js-yaml": ["js-yaml@4.1.0", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA=="],
+
+ "jsesc": ["jsesc@3.1.0", "", { "bin": { "jsesc": "bin/jsesc" } }, "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA=="],
+
+ "json-buffer": ["json-buffer@3.0.1", "", {}, "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ=="],
+
+ "json-schema-traverse": ["json-schema-traverse@0.4.1", "", {}, "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="],
+
+ "json-stable-stringify-without-jsonify": ["json-stable-stringify-without-jsonify@1.0.1", "", {}, "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw=="],
+
+ "json5": ["json5@2.2.3", "", { "bin": { "json5": "lib/cli.js" } }, "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg=="],
+
+ "keyv": ["keyv@4.5.4", "", { "dependencies": { "json-buffer": "3.0.1" } }, "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw=="],
+
+ "kind-of": ["kind-of@3.2.2", "", { "dependencies": { "is-buffer": "^1.1.5" } }, "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ=="],
+
+ "levn": ["levn@0.4.1", "", { "dependencies": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" } }, "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ=="],
+
+ "locate-path": ["locate-path@6.0.0", "", { "dependencies": { "p-locate": "^5.0.0" } }, "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw=="],
+
+ "lodash.merge": ["lodash.merge@4.6.2", "", {}, "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ=="],
+
+ "loose-envify": ["loose-envify@1.4.0", "", { "dependencies": { "js-tokens": "^3.0.0 || ^4.0.0" }, "bin": { "loose-envify": "cli.js" } }, "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q=="],
+
+ "lru-cache": ["lru-cache@5.1.1", "", { "dependencies": { "yallist": "^3.0.2" } }, "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w=="],
+
+ "merge2": ["merge2@1.4.1", "", {}, "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg=="],
+
+ "micromatch": ["micromatch@4.0.8", "", { "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" } }, "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA=="],
+
+ "minimatch": ["minimatch@3.1.2", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="],
+
+ "mitt": ["mitt@3.0.1", "", {}, "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw=="],
+
+ "ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="],
+
+ "nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="],
+
+ "natural-compare": ["natural-compare@1.4.0", "", {}, "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw=="],
+
+ "node-releases": ["node-releases@2.0.19", "", {}, "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw=="],
+
+ "optionator": ["optionator@0.9.4", "", { "dependencies": { "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", "levn": "^0.4.1", "prelude-ls": "^1.2.1", "type-check": "^0.4.0", "word-wrap": "^1.2.5" } }, "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g=="],
+
+ "p-limit": ["p-limit@3.1.0", "", { "dependencies": { "yocto-queue": "^0.1.0" } }, "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ=="],
+
+ "p-locate": ["p-locate@5.0.0", "", { "dependencies": { "p-limit": "^3.0.2" } }, "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw=="],
+
+ "parent-module": ["parent-module@1.0.1", "", { "dependencies": { "callsites": "^3.0.0" } }, "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g=="],
+
+ "path-exists": ["path-exists@4.0.0", "", {}, "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w=="],
+
+ "path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="],
+
+ "picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="],
+
+ "picomatch": ["picomatch@4.0.3", "", {}, "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q=="],
+
+ "postcss": ["postcss@8.5.6", "", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg=="],
+
+ "prelude-ls": ["prelude-ls@1.2.1", "", {}, "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g=="],
+
+ "punycode": ["punycode@2.3.1", "", {}, "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg=="],
+
+ "queue-microtask": ["queue-microtask@1.2.3", "", {}, "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A=="],
+
+ "react": ["react@19.1.1", "", {}, "sha512-w8nqGImo45dmMIfljjMwOGtbmC/mk4CMYhWIicdSflH91J9TyCyczcPFXJzrZ/ZXcgGRFeP6BU0BEJTw6tZdfQ=="],
+
+ "react-dom": ["react-dom@19.1.1", "", { "dependencies": { "scheduler": "^0.26.0" }, "peerDependencies": { "react": "^19.1.1" } }, "sha512-Dlq/5LAZgF0Gaz6yiqZCf6VCcZs1ghAJyrsu84Q/GT0gV+mCxbfmKNoGRKBYMJ8IEdGPqu49YWXD02GCknEDkw=="],
+
+ "react-hot-toast": ["react-hot-toast@2.6.0", "", { "dependencies": { "csstype": "^3.1.3", "goober": "^2.1.16" }, "peerDependencies": { "react": ">=16", "react-dom": ">=16" } }, "sha512-bH+2EBMZ4sdyou/DPrfgIouFpcRLCJ+HoCA32UoAYHn6T3Ur5yfcDCeSr5mwldl6pFOsiocmrXMuoCJ1vV8bWg=="],
+
+ "react-refresh": ["react-refresh@0.17.0", "", {}, "sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ=="],
+
+ "regexparam": ["regexparam@3.0.0", "", {}, "sha512-RSYAtP31mvYLkAHrOlh25pCNQ5hWnT106VukGaaFfuJrZFkGRX5GhUAdPqpSDXxOhA2c4akmRuplv1mRqnBn6Q=="],
+
+ "rename-keys": ["rename-keys@1.2.0", "", {}, "sha512-U7XpAktpbSgHTRSNRrjKSrjYkZKuhUukfoBlXWXUExCAqhzh1TU3BDRAfJmarcl5voKS+pbKU9MvyLWKZ4UEEg=="],
+
+ "resolve-from": ["resolve-from@4.0.0", "", {}, "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g=="],
+
+ "reusify": ["reusify@1.1.0", "", {}, "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw=="],
+
+ "rollup": ["rollup@4.50.0", "", { "dependencies": { "@types/estree": "1.0.8" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.50.0", "@rollup/rollup-android-arm64": "4.50.0", "@rollup/rollup-darwin-arm64": "4.50.0", "@rollup/rollup-darwin-x64": "4.50.0", "@rollup/rollup-freebsd-arm64": "4.50.0", "@rollup/rollup-freebsd-x64": "4.50.0", "@rollup/rollup-linux-arm-gnueabihf": "4.50.0", "@rollup/rollup-linux-arm-musleabihf": "4.50.0", "@rollup/rollup-linux-arm64-gnu": "4.50.0", "@rollup/rollup-linux-arm64-musl": "4.50.0", "@rollup/rollup-linux-loongarch64-gnu": "4.50.0", "@rollup/rollup-linux-ppc64-gnu": "4.50.0", "@rollup/rollup-linux-riscv64-gnu": "4.50.0", "@rollup/rollup-linux-riscv64-musl": "4.50.0", "@rollup/rollup-linux-s390x-gnu": "4.50.0", "@rollup/rollup-linux-x64-gnu": "4.50.0", "@rollup/rollup-linux-x64-musl": "4.50.0", "@rollup/rollup-openharmony-arm64": "4.50.0", "@rollup/rollup-win32-arm64-msvc": "4.50.0", "@rollup/rollup-win32-ia32-msvc": "4.50.0", "@rollup/rollup-win32-x64-msvc": "4.50.0", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-/Zl4D8zPifNmyGzJS+3kVoyXeDeT/GrsJM94sACNg9RtUE0hrHa1bNPtRSrfHTMH5HjRzce6K7rlTh3Khiw+pw=="],
+
+ "run-parallel": ["run-parallel@1.2.0", "", { "dependencies": { "queue-microtask": "^1.2.2" } }, "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA=="],
+
+ "scheduler": ["scheduler@0.26.0", "", {}, "sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA=="],
+
+ "semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="],
+
+ "shebang-command": ["shebang-command@2.0.0", "", { "dependencies": { "shebang-regex": "^3.0.0" } }, "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="],
+
+ "shebang-regex": ["shebang-regex@3.0.0", "", {}, "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="],
+
+ "source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="],
+
+ "strip-json-comments": ["strip-json-comments@3.1.1", "", {}, "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig=="],
+
+ "supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="],
+
+ "svgson": ["svgson@5.3.1", "", { "dependencies": { "deep-rename-keys": "^0.2.1", "xml-reader": "2.4.3" } }, "sha512-qdPgvUNWb40gWktBJnbJRelWcPzkLed/ShhnRsjbayXz8OtdPOzbil9jtiZdrYvSDumAz/VNQr6JaNfPx/gvPA=="],
+
+ "tinyglobby": ["tinyglobby@0.2.14", "", { "dependencies": { "fdir": "^6.4.4", "picomatch": "^4.0.2" } }, "sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ=="],
+
+ "to-regex-range": ["to-regex-range@5.0.1", "", { "dependencies": { "is-number": "^7.0.0" } }, "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ=="],
+
+ "transformation-matrix": ["transformation-matrix@3.1.0", "", {}, "sha512-oYubRWTi2tYFHAL2J8DLvPIqIYcYZ0fSOi2vmSy042Ho4jBW2ce6VP7QfD44t65WQz6bw5w1Pk22J7lcUpaTKA=="],
+
+ "ts-api-utils": ["ts-api-utils@2.1.0", "", { "peerDependencies": { "typescript": ">=4.8.4" } }, "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ=="],
+
+ "type-check": ["type-check@0.4.0", "", { "dependencies": { "prelude-ls": "^1.2.1" } }, "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew=="],
+
+ "typescript": ["typescript@5.8.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ=="],
+
+ "typescript-eslint": ["typescript-eslint@8.42.0", "", { "dependencies": { "@typescript-eslint/eslint-plugin": "8.42.0", "@typescript-eslint/parser": "8.42.0", "@typescript-eslint/typescript-estree": "8.42.0", "@typescript-eslint/utils": "8.42.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-ozR/rQn+aQXQxh1YgbCzQWDFrsi9mcg+1PM3l/z5o1+20P7suOIaNg515bpr/OYt6FObz/NHcBstydDLHWeEKg=="],
+
+ "undici-types": ["undici-types@7.10.0", "", {}, "sha512-t5Fy/nfn+14LuOc2KNYg75vZqClpAiqscVvMygNnlsHBFpSXdJaYtXMcdNLpl/Qvc3P2cB3s6lOV51nqsFq4ag=="],
+
+ "update-browserslist-db": ["update-browserslist-db@1.1.3", "", { "dependencies": { "escalade": "^3.2.0", "picocolors": "^1.1.1" }, "peerDependencies": { "browserslist": ">= 4.21.0" }, "bin": { "update-browserslist-db": "cli.js" } }, "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw=="],
+
+ "urbit-api": ["@urbit/http-api@file:../../../urbit/bun/http-api", { "devDependencies": { "@types/bun": "latest", "typescript": "^5" } }],
+
+ "urbit-ob": ["urbit-ob-ts@file:../../../urbit/bun/urbit-ob", { "devDependencies": { "@types/bun": "latest" }, "peerDependencies": { "typescript": "^5" } }],
+
+ "urbit-sigils": ["sigil-ts@file:../../../urbit/bun/sigil-ts", { "dependencies": { "invariant": "^2.2.4", "react": "^19.1.0", "svgson": "^5.3.1", "transformation-matrix": "^3.0.0" }, "devDependencies": { "@types/bun": "latest", "@types/invariant": "^2.2.37", "@types/react": "^19.1.2" }, "peerDependencies": { "typescript": "^5" } }],
+
+ "uri-js": ["uri-js@4.4.1", "", { "dependencies": { "punycode": "^2.1.0" } }, "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg=="],
+
+ "use-sync-external-store": ["use-sync-external-store@1.5.0", "", { "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-Rb46I4cGGVBmjamjphe8L/UnvJD+uPPtTkNvX5mZgqdbavhI4EbgIWJiIHXJ8bc/i9EQGPRh4DwEURJ552Do0A=="],
+
+ "vite": ["vite@7.1.4", "", { "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.5.0", "picomatch": "^4.0.3", "postcss": "^8.5.6", "rollup": "^4.43.0", "tinyglobby": "^0.2.14" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "jiti": ">=1.21.0", "less": "^4.0.0", "lightningcss": "^1.21.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-X5QFK4SGynAeeIt+A7ZWnApdUyHYm+pzv/8/A57LqSGcI88U6R6ipOs3uCesdc6yl7nl+zNO0t8LmqAdXcQihw=="],
+
+ "which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "./bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="],
+
+ "word-wrap": ["word-wrap@1.2.5", "", {}, "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA=="],
+
+ "wouter": ["wouter@3.7.1", "", { "dependencies": { "mitt": "^3.0.1", "regexparam": "^3.0.0", "use-sync-external-store": "^1.0.0" }, "peerDependencies": { "react": ">=16.8.0" } }, "sha512-od5LGmndSUzntZkE2R5CHhoiJ7YMuTIbiXsa0Anytc2RATekgv4sfWRAxLEULBrp7ADzinWQw8g470lkT8+fOw=="],
+
+ "xml-lexer": ["xml-lexer@0.2.2", "", { "dependencies": { "eventemitter3": "^2.0.0" } }, "sha512-G0i98epIwiUEiKmMcavmVdhtymW+pCAohMRgybyIME9ygfVu8QheIi+YoQh3ngiThsT0SQzJT4R0sKDEv8Ou0w=="],
+
+ "xml-reader": ["xml-reader@2.4.3", "", { "dependencies": { "eventemitter3": "^2.0.0", "xml-lexer": "^0.2.2" } }, "sha512-xWldrIxjeAMAu6+HSf9t50ot1uL5M+BtOidRCWHXIeewvSeIpscWCsp4Zxjk8kHHhdqFBrfK8U0EJeCcnyQ/gA=="],
+
+ "yallist": ["yallist@3.1.1", "", {}, "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="],
+
+ "yocto-queue": ["yocto-queue@0.1.0", "", {}, "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q=="],
+
+ "zustand": ["zustand@5.0.8", "", { "peerDependencies": { "@types/react": ">=18.0.0", "immer": ">=9.0.6", "react": ">=18.0.0", "use-sync-external-store": ">=1.2.0" }, "optionalPeers": ["@types/react", "immer", "react", "use-sync-external-store"] }, "sha512-gyPKpIaxY9XcO2vSMrLbiER7QMAMGOQZVRdJ6Zi782jkbzZygq5GI9nG8g+sMgitRtndwaBSl7uiqC49o1SSiw=="],
+
+ "@eslint-community/eslint-utils/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="],
+
+ "@eslint/eslintrc/globals": ["globals@14.0.0", "", {}, "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ=="],
+
+ "@humanfs/node/@humanwhocodes/retry": ["@humanwhocodes/retry@0.3.1", "", {}, "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA=="],
+
+ "@typescript-eslint/eslint-plugin/ignore": ["ignore@7.0.5", "", {}, "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg=="],
+
+ "@typescript-eslint/typescript-estree/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="],
+
+ "@typescript-eslint/typescript-estree/semver": ["semver@7.7.2", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA=="],
+
+ "fast-glob/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="],
+
+ "micromatch/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="],
+
+ "@typescript-eslint/typescript-estree/minimatch/brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="],
+ }
+}
diff --git a/front/eslint.config.js b/front/eslint.config.js
new file mode 100644
index 0000000..d94e7de
--- /dev/null
+++ b/front/eslint.config.js
@@ -0,0 +1,23 @@
+import js from '@eslint/js'
+import globals from 'globals'
+import reactHooks from 'eslint-plugin-react-hooks'
+import reactRefresh from 'eslint-plugin-react-refresh'
+import tseslint from 'typescript-eslint'
+import { globalIgnores } from 'eslint/config'
+
+export default tseslint.config([
+ globalIgnores(['dist']),
+ {
+ files: ['**/*.{ts,tsx}'],
+ extends: [
+ js.configs.recommended,
+ tseslint.configs.recommended,
+ reactHooks.configs['recommended-latest'],
+ reactRefresh.configs.vite,
+ ],
+ languageOptions: {
+ ecmaVersion: 2020,
+ globals: globals.browser,
+ },
+ },
+])
diff --git a/front/index.html b/front/index.html
new file mode 100644
index 0000000..94cc361
--- /dev/null
+++ b/front/index.html
@@ -0,0 +1,16 @@
+<!doctype html>
+<html lang="en">
+
+<head>
+ <meta charset="UTF-8" />
+ <link rel="icon" type="image/svg+xml" href="/favicon.svg" />
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+ <title>Nostrill</title>
+</head>
+
+<body>
+ <div id="root"></div>
+ <script type="module" src="/src/main.tsx"></script>
+</body>
+
+</html> \ No newline at end of file
diff --git a/front/package.json b/front/package.json
new file mode 100644
index 0000000..35395a9
--- /dev/null
+++ b/front/package.json
@@ -0,0 +1,37 @@
+{
+ "name": "front",
+ "private": true,
+ "version": "0.0.0",
+ "type": "module",
+ "scripts": {
+ "dev": "vite",
+ "build": "tsc -b && vite build",
+ "lint": "eslint .",
+ "preview": "vite preview"
+ },
+ "dependencies": {
+ "@tanstack/react-query": "^5.85.9",
+ "any-ascii": "^0.3.3",
+ "react": "^19.1.1",
+ "react-dom": "^19.1.1",
+ "react-hot-toast": "^2.6.0",
+ "urbit-api": "file:../../../urbit/bun/http-api",
+ "urbit-ob": "file:../../../urbit/bun/urbit-ob",
+ "urbit-sigils": "file:../../../urbit/bun/sigil-ts",
+ "wouter": "^3.7.1",
+ "zustand": "^5.0.8"
+ },
+ "devDependencies": {
+ "@eslint/js": "^9.33.0",
+ "@types/react": "^19.1.10",
+ "@types/react-dom": "^19.1.7",
+ "@vitejs/plugin-react": "^5.0.0",
+ "eslint": "^9.33.0",
+ "eslint-plugin-react-hooks": "^5.2.0",
+ "eslint-plugin-react-refresh": "^0.4.20",
+ "globals": "^16.3.0",
+ "typescript": "~5.8.3",
+ "typescript-eslint": "^8.39.1",
+ "vite": "^7.1.2"
+ }
+}
diff --git a/front/public/favicon.svg b/front/public/favicon.svg
new file mode 100644
index 0000000..790198c
--- /dev/null
+++ b/front/public/favicon.svg
@@ -0,0 +1,22 @@
+<svg
+xmlns="http://www.w3.org/2000/svg"
+xmlns:xlink="http://www.w3.org/1999/xlink"
+aria-hidden="true"
+role="img"
+class="iconify iconify--fa-solid"
+width="40"
+height="32"
+preserveAspectRatio="xMidYMid meet"
+viewBox="0 0 640 512">
+ <style>
+ path {
+ fill: #000;
+ }
+ @media (prefers-color-scheme: dark) {
+ path {
+ fill: #fff;
+ }
+ }
+</style>
+
+<path d="M544 32h-16.36C513.04 12.68 490.09 0 464 0c-44.18 0-80 35.82-80 80v20.98L12.09 393.57A30.216 30.216 0 0 0 0 417.74c0 22.46 23.64 37.07 43.73 27.03L165.27 384h96.49l44.41 120.1c2.27 6.23 9.15 9.44 15.38 7.17l22.55-8.21c6.23-2.27 9.44-9.15 7.17-15.38L312.94 384H352c1.91 0 3.76-.23 5.66-.29l44.51 120.38c2.27 6.23 9.15 9.44 15.38 7.17l22.55-8.21c6.23-2.27 9.44-9.15 7.17-15.38l-41.24-111.53C485.74 352.8 544 279.26 544 192v-80l96-16c0-35.35-42.98-64-96-64zm-80 72c-13.25 0-24-10.75-24-24c0-13.26 10.75-24 24-24s24 10.74 24 24c0 13.25-10.75 24-24 24z" fill="currentColor"></path></svg>
diff --git a/front/public/fonts/Inter b/front/public/fonts/Inter
new file mode 120000
index 0000000..7a1c26c
--- /dev/null
+++ b/front/public/fonts/Inter
@@ -0,0 +1 @@
+/home/y/code/fonts/Inter \ No newline at end of file
diff --git a/front/public/fonts/Source_Code_Pro b/front/public/fonts/Source_Code_Pro
new file mode 120000
index 0000000..ab04caf
--- /dev/null
+++ b/front/public/fonts/Source_Code_Pro
@@ -0,0 +1 @@
+/home/y/code/fonts/Source_Code_Pro \ No newline at end of file
diff --git a/front/public/nostril-icon.png b/front/public/nostril-icon.png
new file mode 100644
index 0000000..73be722
--- /dev/null
+++ b/front/public/nostril-icon.png
Binary files differ
diff --git a/front/src/App.tsx b/front/src/App.tsx
new file mode 100644
index 0000000..60ca66a
--- /dev/null
+++ b/front/src/App.tsx
@@ -0,0 +1,43 @@
+import { useEffect, useState } from "react";
+import useLocalState from "@/state/state";
+import Router from "./Router";
+import "@/styles/styles.css";
+import { ThemeProvider } from "@/styles/ThemeProvider";
+import spinner from "@/assets/crowspinner.gif";
+
+import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
+import { Toaster } from "react-hot-toast";
+const queryClient = new QueryClient();
+
+// const isMobile = MOBILE_BROWSER_REGEX.test(navigator.userAgent);
+
+function App() {
+ const [loading, setLoading] = useState(true);
+ console.log("NOSTRIL INIT");
+ const { init, modal } = useLocalState();
+ useEffect(() => {
+ init().then((_res: any) => {
+ setLoading(false);
+ });
+ }, []);
+ if (loading)
+ return (
+ <div className="global-center">
+ <img id="global-spinner" src={spinner} alt="" />
+ <h3 style={{ textAlign: "center" }}>Syncing with your Urbit...</h3>
+ </div>
+ );
+ else
+ return (
+ <ThemeProvider>
+ <QueryClientProvider client={queryClient}>
+ {/* {isMobile ? <MobileUI /> : <DesktopUI />} */}
+ <Router />
+ {modal && modal}
+ <Toaster position="top-center" />
+ </QueryClientProvider>
+ </ThemeProvider>
+ );
+}
+
+export default App;
diff --git a/front/src/Router.tsx b/front/src/Router.tsx
new file mode 100644
index 0000000..b7b033e
--- /dev/null
+++ b/front/src/Router.tsx
@@ -0,0 +1,29 @@
+import Sidebar from "@/components/layout/Sidebar";
+
+// new
+import Feed from "@/pages/Feed";
+import Settings from "@/pages/Settings";
+import { Switch, Router, Redirect, Route } from "wouter";
+
+export default function r() {
+ return (
+ <Switch>
+ <Router base="/apps/nostril">
+ <Sidebar />
+ <main>
+ <Route path="/" component={toGlobal} />
+ <Route path="/sets" component={Settings} />
+ <Route path="/feed/:taip" component={Feed} />
+ </main>
+ </Router>
+ <Route component={P404} />
+ </Switch>
+ );
+}
+function toGlobal() {
+ return <Redirect to="/feed/nostr" />;
+}
+
+export function P404() {
+ return <h1 className="x-center">404</h1>;
+}
diff --git a/front/src/assets/crowspinner.gif b/front/src/assets/crowspinner.gif
new file mode 100644
index 0000000..d0033d3
--- /dev/null
+++ b/front/src/assets/crowspinner.gif
Binary files differ
diff --git a/front/src/assets/icons/bell.svg b/front/src/assets/icons/bell.svg
new file mode 100644
index 0000000..98e88cd
--- /dev/null
+++ b/front/src/assets/icons/bell.svg
@@ -0,0 +1,3 @@
+<svg width="18" height="21" viewBox="0 0 18 21" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M5.96822 18.0949C6.16344 18.7472 6.56388 19.3192 7.11007 19.7259C7.65625 20.1326 8.31904 20.3522 9 20.3522C9.68095 20.3522 10.3437 20.1326 10.8899 19.7259C11.4361 19.3192 11.8365 18.7472 12.0318 18.0949H5.96822ZM0.867065 17.1912H17.1329V14.4802L15.3256 11.7693V7.25097C15.3256 6.42027 15.162 5.59772 14.8441 4.83026C14.5262 4.0628 14.0603 3.36547 13.4729 2.77808C12.8855 2.1907 12.1882 1.72475 11.4207 1.40686C10.6532 1.08897 9.83069 0.925354 9 0.925354C8.1693 0.925354 7.34675 1.08897 6.57929 1.40686C5.81183 1.72475 5.1145 2.1907 4.52711 2.77808C3.93972 3.36547 3.47378 4.0628 3.15589 4.83026C2.838 5.59772 2.67438 6.42027 2.67438 7.25097V11.7693L0.867065 14.4802V17.1912Z" fill="#111111"/>
+</svg>
diff --git a/front/src/assets/icons/comet.svg b/front/src/assets/icons/comet.svg
new file mode 100644
index 0000000..2d5c3f5
--- /dev/null
+++ b/front/src/assets/icons/comet.svg
@@ -0,0 +1,23 @@
+<svg version="1.1" id="_x32_" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="512px" height="512px" viewBox="0 0 512 512" style="width: 256px; height: 256px; opacity: 1;" xml:space="preserve">
+<g>
+ <path class="st0" d="M503.694,7.871c1.344-2.047,1.047-4.781-0.734-6.453c-1.781-1.703-4.5-1.891-6.484-0.438l-98.547,71.344
+ c-1.891,1.359-4.484,1.266-6.266-0.25s-2.313-4.047-1.266-6.141l10.844-21.656c1.031-2.047,0.547-4.547-1.156-6.063
+ c-1.719-1.531-4.25-1.719-6.172-0.469L83.006,230.137c-3.156,1.813-6.297,3.688-9.328,5.75l-0.25,0.156l0.016,0.016
+ c-7.625,5.219-14.922,11.125-21.688,17.891c-59.047,59.031-59.047,154.75-0.016,213.766
+ c29.531,29.516,68.219,44.281,106.906,44.281s77.359-14.766,106.891-44.281c6.766-6.766,12.656-14.047,17.875-21.672v0.016
+ l0.109-0.172c1.844-2.703,3.516-5.484,5.172-8.281l188.375-302.078c1.203-1.844,1.094-4.25-0.281-5.953
+ c-1.375-1.734-3.688-2.375-5.75-1.594l-46.829,17.563c-2.063,0.75-4.375,0.125-5.75-1.594s-1.484-4.125-0.266-5.953L503.694,7.871z
+ M158.647,464.73c-27.766,0-53.859-10.797-73.484-30.438c-40.5-40.5-40.5-106.406,0-146.922
+ c6.813-6.797,14.422-12.469,22.578-17.063c7.406-4.172,15.297-7.391,23.5-9.641c0.766-0.203,1.547-0.375,2.344-0.578
+ c3.172-0.797,6.406-1.422,9.672-1.906c1.031-0.156,2.047-0.328,3.078-0.453c4.047-0.484,8.156-0.797,12.313-0.797
+ c27.75,0,53.828,10.813,73.453,30.438c2.344,2.328,4.516,4.781,6.578,7.281c0.688,0.813,1.297,1.672,1.938,2.5
+ c1.344,1.734,2.641,3.469,3.859,5.25c0.703,1.031,1.359,2.063,2.016,3.109c1.047,1.656,2.047,3.344,3,5.063
+ c0.609,1.109,1.219,2.234,1.797,3.359c0.859,1.719,1.656,3.484,2.422,5.234c0.5,1.141,1.031,2.266,1.484,3.422
+ c0.813,2.063,1.516,4.172,2.188,6.266c0.656,2.031,1.219,4.063,1.75,6.125c0.391,1.563,0.813,3.109,1.141,4.688
+ c0.344,1.703,0.609,3.438,0.875,5.156c0.188,1.219,0.375,2.438,0.516,3.656c0.219,1.875,0.391,3.75,0.5,5.625
+ c0.063,1.016,0.109,2.047,0.156,3.063c0.063,2.047,0.109,4.094,0.047,6.141c-0.016,0.656-0.063,1.328-0.094,1.984
+ c-0.453,10.406-2.438,20.766-6,30.688c-0.063,0.219-0.141,0.438-0.219,0.641c-0.891,2.422-1.875,4.813-2.938,7.188
+ c-0.125,0.266-0.266,0.563-0.391,0.828c-1.125,2.406-2.313,4.781-3.609,7.094c-4.547,8.078-10.141,15.703-17,22.563
+ C212.475,453.934,186.397,464.73,158.647,464.73z"></path>
+</g>
+</svg>
diff --git a/front/src/assets/icons/copy.svg b/front/src/assets/icons/copy.svg
new file mode 100644
index 0000000..714e9f5
--- /dev/null
+++ b/front/src/assets/icons/copy.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
+<svg width="800px" height="800px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
+<rect x="6.5" y="6.5" width="9" height="13" rx="1.5" stroke="#000000"/>
+<path d="M8.5 6C8.5 5.17157 9.17157 4.5 10 4.5H16C16.8284 4.5 17.5 5.17157 17.5 6V16C17.5 16.8284 16.8284 17.5 16 17.5" stroke="#000000"/>
+</svg> \ No newline at end of file
diff --git a/front/src/assets/icons/crow.svg b/front/src/assets/icons/crow.svg
new file mode 100644
index 0000000..e967970
--- /dev/null
+++ b/front/src/assets/icons/crow.svg
@@ -0,0 +1,29 @@
+<svg
+xmlns="http://www.w3.org/2000/svg"
+xmlns:xlink="http://www.w3.org/1999/xlink"
+aria-hidden="true"
+role="img"
+class="iconify iconify--fa-solid"
+width="40"
+height="32"
+preserveAspectRatio="xMidYMid meet"
+viewBox="0 0 640 512">
+ <style>
+ path {
+ fill: #000;
+ }
+ @media (prefers-color-scheme: dark) {
+ path {
+ <!-- fill: #fff; -->
+ fill: linear-gradient(
+ 90deg,
+ rgba(168, 221, 228, 0.2) 0%,
+ rgba(150, 221, 233, 0.2) 52%,
+ rgba(0, 209, 255, 0.2) 100%
+ );
+ }
+ }
+</style>
+
+<path d="M544 32h-16.36C513.04 12.68 490.09 0 464 0c-44.18 0-80 35.82-80 80v20.98L12.09 393.57A30.216 30.216 0 0 0 0 417.74c0 22.46 23.64 37.07 43.73 27.03L165.27 384h96.49l44.41 120.1c2.27 6.23 9.15 9.44 15.38 7.17l22.55-8.21c6.23-2.27 9.44-9.15 7.17-15.38L312.94 384H352c1.91 0 3.76-.23 5.66-.29l44.51 120.38c2.27 6.23 9.15 9.44 15.38 7.17l22.55-8.21c6.23-2.27 9.44-9.15 7.17-15.38l-41.24-111.53C485.74 352.8 544 279.26 544 192v-80l96-16c0-35.35-42.98-64-96-64zm-80 72c-13.25 0-24-10.75-24-24c0-13.26 10.75-24 24-24s24 10.74 24 24c0 13.25-10.75 24-24 24z" fill="currentColor"></path></svg>
+
diff --git a/front/src/assets/icons/emoji.svg b/front/src/assets/icons/emoji.svg
new file mode 100644
index 0000000..7a957fd
--- /dev/null
+++ b/front/src/assets/icons/emoji.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
+<svg width="800px" height="800px" viewBox="-3 -3 24 24"
+ xmlns="http://www.w3.org/2000/svg">
+ <path fill="#000000" fill-rule="evenodd" d="M255,160 L256,160 C256,162.209139 254.209139,164 252,164 C249.790861,164 248,162.209139 248,160 L249,160 C249,161.656854 250.343146,163 252,163 C253.656854,163 255,161.656854 255,160 Z M252,168 C256.970563,168 261,163.970563 261,159 C261,154.029437 256.970563,150 252,150 C247.029437,150 243,154.029437 243,159 C243,163.970563 247.029437,168 252,168 Z M252,167 C256.418278,167 260,163.418278 260,159 C260,154.581722 256.418278,151 252,151 C247.581722,151 244,154.581722 244,159 C244,163.418278 247.581722,167 252,167 Z M249,158 C249.552285,158 250,157.552285 250,157 C250,156.447715 249.552285,156 249,156 C248.447715,156 248,156.447715 248,157 C248,157.552285 248.447715,158 249,158 Z M255,158 C255.552285,158 256,157.552285 256,157 C256,156.447715 255.552285,156 255,156 C254.447715,156 254,156.447715 254,157 C254,157.552285 254.447715,158 255,158 Z" transform="translate(-243 -150)"/>
+</svg> \ No newline at end of file
diff --git a/front/src/assets/icons/home.svg b/front/src/assets/icons/home.svg
new file mode 100644
index 0000000..64d7984
--- /dev/null
+++ b/front/src/assets/icons/home.svg
@@ -0,0 +1,3 @@
+<svg width="20" height="21" viewBox="0 0 20 21" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M19.743 10.9698L10.743 0.96979C10.364 0.54779 9.63599 0.54779 9.25699 0.96979L0.256994 10.9698C0.127674 11.1135 0.0427905 11.2916 0.0126187 11.4826C-0.017553 11.6736 0.00828102 11.8692 0.0869934 12.0458C0.246993 12.4068 0.604993 12.6388 0.999994 12.6388H2.99999V19.6388C2.99999 19.904 3.10535 20.1584 3.29289 20.3459C3.48042 20.5334 3.73478 20.6388 3.99999 20.6388H6.99999C7.26521 20.6388 7.51956 20.5334 7.7071 20.3459C7.89464 20.1584 7.99999 19.904 7.99999 19.6388V15.6388H12V19.6388C12 19.904 12.1054 20.1584 12.2929 20.3459C12.4804 20.5334 12.7348 20.6388 13 20.6388H16C16.2652 20.6388 16.5196 20.5334 16.7071 20.3459C16.8946 20.1584 17 19.904 17 19.6388V12.6388H19C19.1937 12.6396 19.3834 12.5841 19.546 12.4789C19.7087 12.3738 19.8372 12.2236 19.916 12.0467C19.9947 11.8698 20.0203 11.6737 19.9896 11.4825C19.9589 11.2913 19.8732 11.1131 19.743 10.9698Z" fill="black"/>
+</svg>
diff --git a/front/src/assets/icons/key.png b/front/src/assets/icons/key.png
new file mode 100644
index 0000000..2efe10b
--- /dev/null
+++ b/front/src/assets/icons/key.png
Binary files differ
diff --git a/front/src/assets/icons/key.svg b/front/src/assets/icons/key.svg
new file mode 100644
index 0000000..c2ac4b9
--- /dev/null
+++ b/front/src/assets/icons/key.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20">
+ <title>key</title>
+ <path d="M15 6a1.54 1.54 0 0 1-1.5-1.5 1.5 1.5 0 0 1 3 0A1.54 1.54 0 0 1 15 6zm-1.5-5A5.55 5.55 0 0 0 8 6.5a6.81 6.81 0 0 0 .7 2.8L1 17v2h4v-2h2v-2h2l3.2-3.2a5.85 5.85 0 0 0 1.3.2A5.55 5.55 0 0 0 19 6.5 5.55 5.55 0 0 0 13.5 1z"/>
+</svg>
diff --git a/front/src/assets/icons/logo.png b/front/src/assets/icons/logo.png
new file mode 100644
index 0000000..fdb3f22
--- /dev/null
+++ b/front/src/assets/icons/logo.png
Binary files differ
diff --git a/front/src/assets/icons/logo.svg b/front/src/assets/icons/logo.svg
new file mode 100644
index 0000000..7cbac7c
--- /dev/null
+++ b/front/src/assets/icons/logo.svg
@@ -0,0 +1,8 @@
+
+<svg width="512" height="512" viewBox="0 0 512 512" fill="none" xmlns="http://www.w3.org/2000/svg">
+<rect width="512" height="512" fill="#FBC917"/>
+<circle cx="243.919" cy="230.964" r="93.6337" fill="#F2F2F2"/>
+<path fill-rule="evenodd" clip-rule="evenodd" d="M286.864 217.687C280.478 224.095 275.619 235.177 275.619 241.105C275.619 258.196 254.334 275.749 227.149 300.24C168.195 349.594 174.912 352.009 195.507 343.446C198.439 342.227 204.883 338.748 206.382 338.748C207.881 338.748 160.103 367.905 165.093 370.063C170.091 369.978 228.767 344.936 237.613 338.729C254.826 326.655 265.055 325.162 268.152 331.525C269.767 334.843 267.568 336.52 267.202 341.159C266.627 348.449 268.715 350.068 275.079 350.068C280.407 348.92 285.397 340.62 288.209 336.47C291.669 331.361 299.546 323.724 309.092 315.216C323.222 304.015 326.84 293.677 323.222 266.107C324.834 242.962 328.757 238.648 343.382 231.645C362.164 224.408 369.59 221.114 350.792 217.687C346.228 216.855 329.961 215.088 323.222 214.241C317.199 213.485 316.816 208.727 306.335 208.727C295.449 210.58 292.197 212.337 286.864 217.687Z" fill="#111111"/>
+<path fill-rule="evenodd" clip-rule="evenodd" d="M284.32 375.939L267.423 353.07C266.391 351.674 266.378 349.771 267.39 348.361L282.518 327.285L289.017 331.95L275.588 350.659L290.755 371.185L284.32 375.939Z" fill="#111111"/>
+<path fill-rule="evenodd" clip-rule="evenodd" d="M273.729 374.67L273.073 372.258C271.741 372.619 270.954 373.993 271.316 375.325C271.677 376.652 273.04 377.438 274.367 377.087L274.371 377.086C274.383 377.083 274.41 377.077 274.454 377.067C274.542 377.047 274.698 377.015 274.928 376.973C275.39 376.89 276.151 376.773 277.274 376.652C279.521 376.412 283.207 376.163 288.833 376.163C294.458 376.163 298.379 376.411 300.869 376.655C302.114 376.776 303.001 376.896 303.564 376.983C303.845 377.027 304.045 377.062 304.168 377.085C304.23 377.096 304.272 377.105 304.296 377.11L304.316 377.114M304.314 377.113L304.318 377.114C305.665 377.404 306.993 376.55 307.287 375.203C307.582 373.854 306.727 372.522 305.378 372.228L304.845 374.67C305.378 372.228 305.377 372.227 305.377 372.227L305.372 372.226L305.365 372.225L305.345 372.221L305.284 372.208C305.235 372.198 305.167 372.185 305.08 372.169C304.907 372.137 304.657 372.093 304.328 372.042C303.668 371.94 302.689 371.809 301.355 371.678C298.689 371.418 294.604 371.163 288.833 371.163C283.064 371.163 279.197 371.418 276.741 371.681C275.513 371.812 274.634 371.946 274.044 372.052C273.749 372.105 273.526 372.151 273.367 372.187C273.287 372.204 273.224 372.219 273.175 372.231C273.151 372.237 273.13 372.243 273.113 372.247L273.091 372.253L273.081 372.255L273.077 372.257L273.075 372.257C273.075 372.257 273.073 372.258 273.729 374.67" fill="#111111"/>
+</svg>
diff --git a/front/src/assets/icons/messages.svg b/front/src/assets/icons/messages.svg
new file mode 100644
index 0000000..8a0b9c3
--- /dev/null
+++ b/front/src/assets/icons/messages.svg
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20">
+ <title>
+ message
+ </title>
+ <path d="M0 8v8a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2V8l-10 4z"/>
+ <path d="M18 2H2a2 2 0 0 0-2 2v2l10 4 10-4V4a2 2 0 0 0-2-2z"/>
+</svg>
diff --git a/front/src/assets/icons/nostr.svg b/front/src/assets/icons/nostr.svg
new file mode 100644
index 0000000..80760a8
--- /dev/null
+++ b/front/src/assets/icons/nostr.svg
@@ -0,0 +1,3 @@
+<svg width="620" height="620" viewBox="0 0 620 620" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M457.468 262.483C469.349 344.787 384.156 362.202 335.143 360.68C331.996 360.582 329.03 362.114 327.171 364.655C322.101 371.586 313.996 380.549 307.739 380.549C300.712 380.549 294.388 394.063 291.504 402.47C291.201 403.353 292.069 404.167 292.957 403.879C370.58 378.675 401.039 370.03 414.161 372.46C424.754 374.421 444.567 409.885 453.149 427.372C431.816 428.598 424.705 409.476 419.801 406.044C415.877 403.299 414.406 415.85 414.161 422.469C409.502 420.018 403.617 416.586 403.126 406.044C402.636 395.503 397.241 398.2 393.073 398.69C388.904 399.18 324.904 419.772 315.341 422.469C305.778 425.166 294.743 428.843 285.671 435.216C270.467 442.571 260.659 437.423 257.962 424.92C255.804 414.918 269.814 384.145 277.088 370.008C268.097 373.358 249.428 380.157 246.682 380.549C244.019 380.93 210.235 407.011 192.169 421.181C191.115 422.008 190.437 423.219 190.194 424.536C187.304 440.241 178.078 444.637 162.084 452.867C149.214 459.49 104.263 528.566 81.1495 565.856C79.5513 568.434 77.2056 570.416 74.6869 572.106C60.0054 581.962 45.053 607.044 38.9885 619.32C30.3571 594.413 41.6041 572.988 48.3065 565.388C45.364 562.839 38.5798 564.326 35.5556 565.388C43.8927 536.706 73.0728 536.706 72.0919 536.706C77.4866 532.048 140.751 441.59 142.222 437.423C143.682 433.289 141.28 413.957 173.077 403.358C173.582 403.189 174.083 402.959 174.53 402.672C199.302 386.75 217.885 361.084 224.123 350.151C191.05 347.877 153.177 329.438 133.375 317.595C129.106 315.042 124.579 312.82 119.636 312.261C92.5231 309.192 65.3757 326.536 54.4368 336.423C49.9249 330.148 55.0089 311.909 58.1149 303.574C47.1295 302.005 30.9783 317.956 24.2759 326.127C17.0176 314.753 23.3768 294.422 27.4636 285.678C12.9471 286.071 3.106 292.706 0 295.975C12.0153 206.497 103.921 232.52 104.95 233.708C100.046 228.609 100.455 221.941 101.272 219.244C156.935 220.715 182.927 211.4 199.356 201.839C328.828 129.522 384.613 173.893 405.211 185.047C425.808 196.201 463.203 200.736 489.073 190.44C519.969 176.467 515.318 140.449 509.057 126.702C502.192 111.626 463.448 90.7882 449.716 64.4356C435.985 38.0831 447.95 6.03652 463.858 1.56985C479.014 -2.68593 489.838 2.26516 498.145 9.7683C503.684 14.7705 519.234 18.3484 525.732 20.6772C532.23 23.0061 543.019 26.0704 542.406 27.909C541.793 29.7476 531.39 29.5022 529.778 29.5022C526.467 29.5022 522.544 29.9925 526.467 31.8311C531.068 33.6968 538.013 36.4085 541.338 38.1936C541.77 38.4256 541.681 39.03 541.207 39.1574C518.642 45.2302 498.494 32.6994 483.555 47.1526C468.352 61.8612 500.72 73.1378 517.395 90.7882C534.069 108.439 551.234 129.521 537.502 177.569C526.871 214.767 482.316 246.393 459.302 258.764C457.979 259.476 457.253 260.996 457.468 262.483Z" fill="black"/>
+</svg>
diff --git a/front/src/assets/icons/pals.svg b/front/src/assets/icons/pals.svg
new file mode 100644
index 0000000..04b17a3
--- /dev/null
+++ b/front/src/assets/icons/pals.svg
@@ -0,0 +1,3 @@
+<svg width="24" height="17" viewBox="0 0 24 17" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M7.2 8.63879C9.52125 8.63879 11.4 6.77961 11.4 4.48254C11.4 2.18547 9.52125 0.326294 7.2 0.326294C4.87875 0.326294 3 2.18547 3 4.48254C3 6.77961 4.87875 8.63879 7.2 8.63879ZM10.08 9.82629H9.76875C8.98875 10.1974 8.1225 10.42 7.2 10.42C6.2775 10.42 5.415 10.1974 4.63125 9.82629H4.32C1.935 9.82629 0 11.7411 0 14.1013V15.17C0 16.1534 0.80625 16.9513 1.8 16.9513H12.6C13.5938 16.9513 14.4 16.1534 14.4 15.17V14.1013C14.4 11.7411 12.465 9.82629 10.08 9.82629ZM18 8.63879C19.9875 8.63879 21.6 7.04309 21.6 5.07629C21.6 3.1095 19.9875 1.51379 18 1.51379C16.0125 1.51379 14.4 3.1095 14.4 5.07629C14.4 7.04309 16.0125 8.63879 18 8.63879ZM19.8 9.82629H19.6575C19.1363 10.0044 18.585 10.1232 18 10.1232C17.415 10.1232 16.8638 10.0044 16.3425 9.82629H16.2C15.435 9.82629 14.73 10.0452 14.1112 10.3978C15.0262 11.3738 15.6 12.6689 15.6 14.1013V15.5263C15.6 15.6079 15.5813 15.6859 15.5775 15.7638H22.2C23.1938 15.7638 24 14.9659 24 13.9825C24 11.6855 22.1213 9.82629 19.8 9.82629Z" fill="black"/>
+</svg>
diff --git a/front/src/assets/icons/profile.svg b/front/src/assets/icons/profile.svg
new file mode 100644
index 0000000..f94e63d
--- /dev/null
+++ b/front/src/assets/icons/profile.svg
@@ -0,0 +1,3 @@
+<svg width="18" height="19" viewBox="0 0 18 19" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path fill-rule="evenodd" clip-rule="evenodd" d="M5 4.63879C5 3.57793 5.42143 2.56051 6.17157 1.81037C6.92172 1.06022 7.93913 0.638794 9 0.638794C10.0609 0.638794 11.0783 1.06022 11.8284 1.81037C12.5786 2.56051 13 3.57793 13 4.63879C13 5.69966 12.5786 6.71708 11.8284 7.46722C11.0783 8.21737 10.0609 8.63879 9 8.63879C7.93913 8.63879 6.92172 8.21737 6.17157 7.46722C5.42143 6.71708 5 5.69966 5 4.63879ZM5 10.6388C3.67392 10.6388 2.40215 11.1656 1.46447 12.1033C0.526784 13.0409 0 14.3127 0 15.6388C0 16.4344 0.316071 17.1975 0.87868 17.7601C1.44129 18.3227 2.20435 18.6388 3 18.6388H15C15.7956 18.6388 16.5587 18.3227 17.1213 17.7601C17.6839 17.1975 18 16.4344 18 15.6388C18 14.3127 17.4732 13.0409 16.5355 12.1033C15.5979 11.1656 14.3261 10.6388 13 10.6388H5Z" fill="black"/>
+</svg>
diff --git a/front/src/assets/icons/quote.svg b/front/src/assets/icons/quote.svg
new file mode 100644
index 0000000..5b847e3
--- /dev/null
+++ b/front/src/assets/icons/quote.svg
@@ -0,0 +1,3 @@
+<svg width="14" height="15" viewBox="0 0 14 15" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M4.26338 0.906933C4.3437 0.846697 4.43509 0.80287 4.53234 0.777954C4.62959 0.753038 4.7308 0.747522 4.83019 0.761719C4.92957 0.775917 5.02519 0.809551 5.11157 0.860701C5.19796 0.911851 5.27342 0.979516 5.33366 1.05983C5.3939 1.14015 5.43772 1.23154 5.46264 1.32879C5.48756 1.42604 5.49307 1.52725 5.47887 1.62664C5.46468 1.72602 5.43104 1.82164 5.37989 1.90802C5.32874 1.99441 5.26108 2.06987 5.18076 2.13011C3.98511 3.02685 3.30013 3.89913 2.90795 4.66056C3.44643 4.52194 4.01472 4.55453 4.53382 4.75379C5.05293 4.95305 5.49707 5.30908 5.8045 5.7724C6.11193 6.23571 6.26738 6.7833 6.24925 7.33904C6.23112 7.89478 6.0403 8.43106 5.70332 8.87335C5.36634 9.31565 4.89994 9.64197 4.36895 9.80697C3.83796 9.97196 3.26876 9.96744 2.74046 9.79402C2.21216 9.6206 1.75101 9.2869 1.4211 8.83931C1.0912 8.39172 0.908937 7.85246 0.899644 7.2965C0.802772 6.35768 0.936068 5.40939 1.288 4.53365C1.7444 3.38234 2.63655 2.12705 4.26338 0.906933ZM11.1438 0.906933C11.2241 0.846697 11.3155 0.80287 11.4127 0.777954C11.51 0.753038 11.6112 0.747522 11.7106 0.761719C11.8099 0.775917 11.9056 0.809551 11.9919 0.860701C12.0783 0.911851 12.1538 0.979516 12.214 1.05983C12.2743 1.14015 12.3181 1.23154 12.343 1.32879C12.3679 1.42604 12.3734 1.52725 12.3592 1.62664C12.345 1.72602 12.3114 1.82164 12.2603 1.90802C12.2091 1.99441 12.1415 2.06987 12.0611 2.13011C10.8655 3.02685 10.1805 3.89913 9.78832 4.66056C10.3268 4.52194 10.8951 4.55453 11.4142 4.75379C11.9333 4.95305 12.3774 5.30908 12.6849 5.7724C12.9923 6.23571 13.1478 6.7833 13.1296 7.33904C13.1115 7.89478 12.9207 8.43106 12.5837 8.87335C12.2467 9.31565 11.7803 9.64197 11.2493 9.80697C10.7183 9.97196 10.1491 9.96744 9.62083 9.79402C9.09253 9.6206 8.63138 9.2869 8.30148 8.83931C7.97157 8.39172 7.78931 7.85246 7.78002 7.2965C7.68314 6.35768 7.81644 5.40939 8.16837 4.53365C8.62554 3.38234 9.51693 2.12705 11.1438 0.906933Z" fill="#757678"/>
+</svg>
diff --git a/front/src/assets/icons/radio.svg b/front/src/assets/icons/radio.svg
new file mode 100644
index 0000000..5c98c15
--- /dev/null
+++ b/front/src/assets/icons/radio.svg
@@ -0,0 +1,3 @@
+<svg width="20" height="22" viewBox="0 0 20 22" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M1.24 5.78879C0.51 6.06879 0 6.80879 0 7.63879V19.6388C0 20.7388 0.9 21.6388 2 21.6388H18C18.5304 21.6388 19.0391 21.4281 19.4142 21.053C19.7893 20.6779 20 20.1692 20 19.6388V7.63879C20 6.53879 19.1 5.63879 18 5.63879H6.3L13.73 2.63879C14.19 2.44879 14.41 1.92879 14.22 1.46879C14.1757 1.35955 14.1102 1.26015 14.0273 1.17632C13.9444 1.09249 13.8457 1.02589 13.737 0.980346C13.6282 0.934803 13.5115 0.911219 13.3936 0.910952C13.2757 0.910685 13.159 0.93374 13.05 0.97879L1.24 5.78879ZM5 19.6388C3.34 19.6388 2 18.2988 2 16.6388C2 14.9788 3.34 13.6388 5 13.6388C6.66 13.6388 8 14.9788 8 16.6388C8 18.2988 6.66 19.6388 5 19.6388ZM18 11.6388H16V10.6388C16 10.0888 15.55 9.63879 15 9.63879C14.45 9.63879 14 10.0888 14 10.6388V11.6388H2V8.63879C2 8.08879 2.45 7.63879 3 7.63879H17C17.55 7.63879 18 8.08879 18 8.63879V11.6388Z" fill="black"/>
+</svg>
diff --git a/front/src/assets/icons/reply.svg b/front/src/assets/icons/reply.svg
new file mode 100644
index 0000000..db86cfd
--- /dev/null
+++ b/front/src/assets/icons/reply.svg
@@ -0,0 +1,3 @@
+<svg width="19" height="21" viewBox="0 0 19 21" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M9.25452 13.4142L4.66867 18V13.4142H2.83434C1.82545 13.4142 1 12.5887 1 11.5798V3.3253C1 2.31642 1.82545 1.49097 2.83434 1.49097H15.6747C16.6836 1.49097 17.509 2.31642 17.509 3.3253V11.5798C17.509 12.5887 16.6836 13.4142 15.6747 13.4142H9.25452Z" stroke="#757678" stroke-width="2"/>
+</svg>
diff --git a/front/src/assets/icons/rt.svg b/front/src/assets/icons/rt.svg
new file mode 100644
index 0000000..43b4a36
--- /dev/null
+++ b/front/src/assets/icons/rt.svg
@@ -0,0 +1,3 @@
+<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M1.998 9.98763C1.998 10.4097 2.04387 10.8256 2.13562 11.2354C2.22736 11.6452 2.36193 12.0428 2.5393 12.4281C2.71668 12.8134 2.93076 13.1743 3.18153 13.5107C3.4323 13.8471 3.56262 13.9511 3.89291 14.2263L3.05802 15.0612C2.6788 14.7248 2.5026 14.5597 2.20901 14.1621C1.91543 13.7645 1.66465 13.3394 1.45669 12.8868C1.24873 12.4342 1.09276 11.9663 0.988783 11.4831C0.884803 10.9999 0.829755 10.5014 0.823639 9.98763C0.823639 9.33928 0.906211 8.71541 1.07136 8.11599C1.2365 7.51658 1.47504 6.95693 1.78698 6.43703C2.09892 5.91713 2.46591 5.44005 2.88794 5.00578C3.30998 4.57151 3.784 4.20452 4.31002 3.90482C4.83603 3.60511 5.39874 3.36963 5.99816 3.19837C6.59757 3.02711 7.22145 2.94148 7.86979 2.94148H13.7966L12.3012 1.44601L13.1269 0.620285L16.0353 3.52866L13.1269 6.43703L12.3012 5.61131L13.7966 4.11584H7.86979C7.33154 4.11584 6.81164 4.18618 6.31009 4.32685C5.80855 4.46753 5.34064 4.66326 4.90637 4.91403C4.4721 5.16481 4.07759 5.47063 3.72284 5.8315C3.36808 6.19237 3.06226 6.58994 2.80537 7.02421C2.54848 7.45848 2.34969 7.92638 2.20901 8.42793C2.06834 8.92948 1.998 9.44938 1.998 9.98763ZM17.4011 4.89568C17.7803 5.22596 17.9344 5.41558 18.228 5.81315C18.5216 6.21072 18.7724 6.63581 18.9803 7.08843C19.1883 7.54105 19.3443 8.01202 19.4482 8.50133C19.5522 8.99065 19.6073 9.48608 19.6134 9.98763C19.6134 10.636 19.5308 11.2599 19.3657 11.8593C19.2005 12.4587 18.962 13.0183 18.65 13.5382C18.3381 14.0581 17.9711 14.5352 17.5491 14.9695C17.127 15.4037 16.653 15.7707 16.127 16.0704C15.601 16.3701 15.0383 16.6056 14.4389 16.7769C13.8394 16.9481 13.2156 17.0338 12.5672 17.0338H6.64038L8.13586 18.5293L7.31013 19.355L4.40176 16.4466L7.31013 13.5382L8.13586 14.3639L6.64038 15.8594H12.5672C13.1055 15.8594 13.6254 15.7891 14.1269 15.6484C14.6285 15.5077 15.0964 15.312 15.5306 15.0612C15.9649 14.8104 16.3594 14.5046 16.7142 14.1438C17.0689 13.7829 17.3748 13.3853 17.6316 12.951C17.8885 12.5168 18.0873 12.0489 18.228 11.5473C18.3687 11.0458 18.439 10.5259 18.439 9.98763C18.439 9.55948 18.3931 9.1405 18.3014 8.7307C18.2096 8.3209 18.0781 7.92333 17.9069 7.53799C17.7356 7.15265 17.5215 6.79484 17.2647 6.46455C17.0078 6.13426 16.8996 5.9997 16.5754 5.71222L17.4011 4.89568Z" fill="#757678" stroke="#757678" stroke-width="0.5" stroke-linejoin="round"/>
+</svg>
diff --git a/front/src/assets/icons/rumors.svg b/front/src/assets/icons/rumors.svg
new file mode 100644
index 0000000..2df5165
--- /dev/null
+++ b/front/src/assets/icons/rumors.svg
@@ -0,0 +1,3 @@
+<svg width="22" height="14" viewBox="0 0 22 14" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M11.022 0.263794C-3.5008 0.263794 -0.710755 13.0138 5.82254 13.0138C7.13176 13.0138 8.36453 12.3268 9.15038 11.1591L9.99465 9.90432C10.5085 9.14098 11.5359 9.14098 12.0497 9.90432L12.894 11.1591C13.6795 12.3268 14.9123 13.0138 16.2215 13.0138C22.4513 13.0138 25.7578 0.263794 11.022 0.263794ZM6.53753 8.37731C5.19024 8.37731 4.31415 7.52532 3.9099 7.01432C3.73829 6.7975 3.73829 6.48008 3.9099 6.26293C4.31415 5.75161 5.18992 4.89995 6.53753 4.89995C7.88514 4.89995 8.7609 5.75194 9.16515 6.26293C9.33676 6.47975 9.33676 6.79717 9.16515 7.01432C8.7609 7.52565 7.88481 8.37731 6.53753 8.37731ZM15.4625 8.37731C14.1152 8.37731 13.2392 7.52532 12.8349 7.01432C12.6633 6.7975 12.6633 6.48008 12.8349 6.26293C13.2392 5.75161 14.1149 4.89995 15.4625 4.89995C16.8101 4.89995 17.6859 5.75194 18.0902 6.26293C18.2618 6.47975 18.2618 6.79717 18.0902 7.01432C17.6859 7.52565 16.8098 8.37731 15.4625 8.37731Z" fill="black"/>
+</svg>
diff --git a/front/src/assets/icons/settings.svg b/front/src/assets/icons/settings.svg
new file mode 100644
index 0000000..5c5e400
--- /dev/null
+++ b/front/src/assets/icons/settings.svg
@@ -0,0 +1,3 @@
+<svg width="20" height="21" viewBox="0 0 20 21" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M10.012 0.888794C10.746 0.896794 11.477 0.981794 12.194 1.14179C12.3465 1.17584 12.4846 1.2567 12.5889 1.37305C12.6933 1.48941 12.7587 1.63546 12.776 1.79079L12.946 3.31779C12.97 3.53308 13.0442 3.73972 13.1626 3.9211C13.281 4.10248 13.4404 4.25352 13.6278 4.36208C13.8153 4.47064 14.0256 4.53369 14.2419 4.54614C14.4581 4.5586 14.6743 4.52012 14.873 4.43379L16.273 3.81879C16.4152 3.75614 16.5734 3.73924 16.7257 3.77041C16.878 3.80158 17.0168 3.87929 17.123 3.99279C18.135 5.07395 18.8889 6.37042 19.328 7.78479C19.3738 7.93353 19.3723 8.09286 19.3236 8.24068C19.2748 8.38851 19.1813 8.51751 19.056 8.60979L17.815 9.52579C17.6401 9.65396 17.4979 9.82152 17.3999 10.0149C17.3019 10.2083 17.2508 10.422 17.2508 10.6388C17.2508 10.8556 17.3019 11.0693 17.3999 11.2627C17.4979 11.4561 17.6401 11.6236 17.815 11.7518L19.058 12.6668C19.1835 12.7591 19.2772 12.8883 19.3259 13.0363C19.3747 13.1844 19.3761 13.3439 19.33 13.4928C18.8912 14.9071 18.1377 16.2035 17.126 17.2848C17.02 17.3983 16.8814 17.476 16.7293 17.5074C16.5772 17.5387 16.4192 17.5221 16.277 17.4598L14.871 16.8428C14.6726 16.7558 14.4565 16.7167 14.2402 16.7288C14.0238 16.7408 13.8134 16.8036 13.6259 16.9121C13.4383 17.0205 13.279 17.1716 13.1607 17.3531C13.0424 17.5346 12.9685 17.7414 12.945 17.9568L12.775 19.4828C12.758 19.6363 12.694 19.7808 12.5918 19.8966C12.4896 20.0124 12.3542 20.0939 12.204 20.1298C10.7556 20.4751 9.24634 20.4751 7.79797 20.1298C7.64757 20.094 7.5119 20.0127 7.4095 19.8969C7.30711 19.7811 7.24301 19.6364 7.22597 19.4828L7.05697 17.9588C7.03242 17.7441 6.95787 17.5382 6.83931 17.3575C6.72074 17.1768 6.56146 17.0265 6.37426 16.9186C6.18707 16.8106 5.97716 16.7481 5.76141 16.736C5.54566 16.7238 5.33008 16.7625 5.13197 16.8488L3.72597 17.4648C3.58363 17.5273 3.42537 17.5441 3.27309 17.5127C3.12081 17.4814 2.98204 17.4035 2.87597 17.2898C1.8641 16.2073 1.11088 14.9094 0.672971 13.4938C0.626868 13.3449 0.628288 13.1854 0.677034 13.0373C0.72578 12.8893 0.819431 12.7601 0.944971 12.6678L2.18797 11.7518C2.36282 11.6236 2.50501 11.4561 2.60302 11.2627C2.70103 11.0693 2.75211 10.8556 2.75211 10.6388C2.75211 10.422 2.70103 10.2083 2.60302 10.0149C2.50501 9.82152 2.36282 9.65396 2.18797 9.52579L0.944971 8.61179C0.819431 8.51944 0.72578 8.39027 0.677034 8.24224C0.628288 8.09421 0.626868 7.93467 0.672971 7.78579C1.11201 6.37142 1.8659 5.07495 2.87797 3.99379C2.98416 3.88029 3.12298 3.80258 3.27526 3.77141C3.42753 3.74024 3.58573 3.75714 3.72797 3.81979L5.12797 4.43479C5.32699 4.52107 5.54347 4.55946 5.76002 4.54688C5.97657 4.53431 6.18715 4.47112 6.37484 4.36239C6.56254 4.25366 6.72212 4.10243 6.84076 3.92084C6.9594 3.73924 7.0338 3.53236 7.05797 3.31679L7.22797 1.79079C7.24513 1.63515 7.31058 1.48878 7.41513 1.37221C7.51968 1.25564 7.6581 1.17472 7.81097 1.14079C8.52697 0.982127 9.26064 0.898127 10.012 0.888794ZM9.99997 7.63879C9.20432 7.63879 8.44126 7.95486 7.87865 8.51747C7.31604 9.08008 6.99997 9.84314 6.99997 10.6388C6.99997 11.4344 7.31604 12.1975 7.87865 12.7601C8.44126 13.3227 9.20432 13.6388 9.99997 13.6388C10.7956 13.6388 11.5587 13.3227 12.1213 12.7601C12.6839 12.1975 13 11.4344 13 10.6388C13 9.84314 12.6839 9.08008 12.1213 8.51747C11.5587 7.95486 10.7956 7.63879 9.99997 7.63879Z" fill="black"/>
+</svg>
diff --git a/front/src/assets/icons/youtube.svg b/front/src/assets/icons/youtube.svg
new file mode 100644
index 0000000..46d7db9
--- /dev/null
+++ b/front/src/assets/icons/youtube.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" height="800" width="1200" viewBox="-35.20005 -41.33325 305.0671 247.9995"><path d="M229.763 25.817c-2.699-10.162-10.65-18.165-20.748-20.881C190.716 0 117.333 0 117.333 0S43.951 0 25.651 4.936C15.553 7.652 7.6 15.655 4.903 25.817 0 44.236 0 82.667 0 82.667s0 38.429 4.903 56.85C7.6 149.68 15.553 157.681 25.65 160.4c18.3 4.934 91.682 4.934 91.682 4.934s73.383 0 91.682-4.934c10.098-2.718 18.049-10.72 20.748-20.882 4.904-18.421 4.904-56.85 4.904-56.85s0-38.431-4.904-56.85" fill="red"/><path d="M93.333 117.559l61.333-34.89-61.333-34.894z" fill="#fff"/></svg> \ No newline at end of file
diff --git a/front/src/assets/reacts/chad.png b/front/src/assets/reacts/chad.png
new file mode 100644
index 0000000..51cfa0d
--- /dev/null
+++ b/front/src/assets/reacts/chad.png
Binary files differ
diff --git a/front/src/assets/reacts/cringe.png b/front/src/assets/reacts/cringe.png
new file mode 100644
index 0000000..d39a50c
--- /dev/null
+++ b/front/src/assets/reacts/cringe.png
Binary files differ
diff --git a/front/src/assets/reacts/cry.png b/front/src/assets/reacts/cry.png
new file mode 100644
index 0000000..f70fb28
--- /dev/null
+++ b/front/src/assets/reacts/cry.png
Binary files differ
diff --git a/front/src/assets/reacts/doom.png b/front/src/assets/reacts/doom.png
new file mode 100644
index 0000000..e6df1f4
--- /dev/null
+++ b/front/src/assets/reacts/doom.png
Binary files differ
diff --git a/front/src/assets/reacts/facepalm.png b/front/src/assets/reacts/facepalm.png
new file mode 100644
index 0000000..a03def9
--- /dev/null
+++ b/front/src/assets/reacts/facepalm.png
Binary files differ
diff --git a/front/src/assets/reacts/galaxy.png b/front/src/assets/reacts/galaxy.png
new file mode 100644
index 0000000..3c496d3
--- /dev/null
+++ b/front/src/assets/reacts/galaxy.png
Binary files differ
diff --git a/front/src/assets/reacts/gigachad.png b/front/src/assets/reacts/gigachad.png
new file mode 100644
index 0000000..5f3c2e1
--- /dev/null
+++ b/front/src/assets/reacts/gigachad.png
Binary files differ
diff --git a/front/src/assets/reacts/pepechin.png b/front/src/assets/reacts/pepechin.png
new file mode 100644
index 0000000..dafd907
--- /dev/null
+++ b/front/src/assets/reacts/pepechin.png
Binary files differ
diff --git a/front/src/assets/reacts/pepeeyes.png b/front/src/assets/reacts/pepeeyes.png
new file mode 100644
index 0000000..e57d5e6
--- /dev/null
+++ b/front/src/assets/reacts/pepeeyes.png
Binary files differ
diff --git a/front/src/assets/reacts/pepegmi.png b/front/src/assets/reacts/pepegmi.png
new file mode 100644
index 0000000..7c3cae4
--- /dev/null
+++ b/front/src/assets/reacts/pepegmi.png
Binary files differ
diff --git a/front/src/assets/reacts/pepesad.png b/front/src/assets/reacts/pepesad.png
new file mode 100644
index 0000000..51891fd
--- /dev/null
+++ b/front/src/assets/reacts/pepesad.png
Binary files differ
diff --git a/front/src/assets/reacts/pika.png b/front/src/assets/reacts/pika.png
new file mode 100644
index 0000000..791594b
--- /dev/null
+++ b/front/src/assets/reacts/pika.png
Binary files differ
diff --git a/front/src/assets/reacts/pink.png b/front/src/assets/reacts/pink.png
new file mode 100644
index 0000000..59fdc6a
--- /dev/null
+++ b/front/src/assets/reacts/pink.png
Binary files differ
diff --git a/front/src/assets/reacts/soy.png b/front/src/assets/reacts/soy.png
new file mode 100644
index 0000000..33dbe33
--- /dev/null
+++ b/front/src/assets/reacts/soy.png
Binary files differ
diff --git a/front/src/assets/reacts/yeschad.png b/front/src/assets/reacts/yeschad.png
new file mode 100644
index 0000000..e001332
--- /dev/null
+++ b/front/src/assets/reacts/yeschad.png
Binary files differ
diff --git a/front/src/assets/triangles.svg b/front/src/assets/triangles.svg
new file mode 100644
index 0000000..0b45c01
--- /dev/null
+++ b/front/src/assets/triangles.svg
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" style="margin: auto; background: none; display: block; shape-rendering: auto;" width="200px" height="200px" viewBox="0 0 100 100" preserveAspectRatio="xMidYMid">
+<g transform="translate(50 42)">
+ <g transform="scale(0.8)">
+ <g transform="translate(-50 -50)">
+ <polygon fill="#9f1515" points="72.5 50 50 11 27.5 50 50 50">
+ <animateTransform attributeName="transform" type="rotate" repeatCount="indefinite" dur="1s" values="0 50 38.5;360 50 38.5" keyTimes="0;1"></animateTransform>
+ </polygon>
+ <polygon fill="#f5e116" points="5 89 50 89 27.5 50">
+ <animateTransform attributeName="transform" type="rotate" repeatCount="indefinite" dur="1s" values="0 27.5 77.5;360 27.5 77.5" keyTimes="0;1"></animateTransform>
+ </polygon>
+ <polygon fill="#04284d" points="72.5 50 50 89 95 89">
+ <animateTransform attributeName="transform" type="rotate" repeatCount="indefinite" dur="1s" values="0 72.5 77.5;360 72 77.5" keyTimes="0;1"></animateTransform>
+ </polygon>
+ </g>
+ </g>
+</g>
+<!-- [ldio] generated by https://loading.io/ --></svg> \ No newline at end of file
diff --git a/front/src/components/Avatar.tsx b/front/src/components/Avatar.tsx
new file mode 100644
index 0000000..35b4386
--- /dev/null
+++ b/front/src/components/Avatar.tsx
@@ -0,0 +1,59 @@
+import useLocalState from "@/state/state";
+import type { Ship } from "@/types/urbit";
+import Sigil from "./Sigil";
+import ShipModal from "./modals/ShipModal";
+
+export default function ({
+ p,
+ size,
+ color,
+ noClickOnName,
+}: {
+ p: Ship;
+ size: number;
+ color?: string;
+ noClickOnName?: boolean;
+}) {
+ const { setModal } = useLocalState();
+ // TODO revisit this when %whom updates
+ const avatar = (
+ <div className="avatar-w sigil cp" role="link" onClick={openModal}>
+ <Sigil patp={p} size={size} color={color} />
+ </div>
+ );
+ const tooLong = (s: string) => (s.length > 15 ? " too-long" : "");
+ function openModal(e: React.MouseEvent) {
+ if (noClickOnName) return;
+ e.stopPropagation();
+ setModal(<ShipModal ship={p} />);
+ }
+ const name = (
+ <div className="name cp" role="link" onMouseUp={openModal}>
+ <p className={"p-only" + tooLong(p)}>{p.length > 28 ? "Anon" : p}</p>
+ </div>
+ );
+ return (
+ <div className="ship-avatar">
+ {avatar}
+ {name}
+ </div>
+ );
+}
+
+export function SigilOnly({ p, size, color }: any) {
+ const { setModal } = useLocalState();
+ function openModal(e: React.MouseEvent) {
+ e.stopPropagation();
+ setModal(<ShipModal ship={p} />);
+ }
+ return (
+ <div
+ className="avatar-w sigil cp"
+ role="link"
+ onClick={openModal}
+ onMouseUp={openModal}
+ >
+ <Sigil patp={p} size={size} color={color} />
+ </div>
+ );
+}
diff --git a/front/src/components/Sigil.tsx b/front/src/components/Sigil.tsx
new file mode 100644
index 0000000..4978a72
--- /dev/null
+++ b/front/src/components/Sigil.tsx
@@ -0,0 +1,50 @@
+import comet from "@/assets/icons/comet.svg";
+import { auraToHex } from "@/logic/utils";
+import { isValidPatp } from "urbit-ob";
+import { sigil } from "urbit-sigils";
+import { reactRenderer } from "urbit-sigils";
+
+interface SigilProps {
+ patp: string;
+ size: number;
+ color?: string;
+}
+
+const Sigil = (props: SigilProps) => {
+ const color = props.color ? auraToHex(props.color) : "black";
+ if (!isValidPatp(props.patp)) return <div className="sigil bad-sigil">X</div>;
+ else if (props.patp.length > 28)
+ return (
+ <img
+ className="comet-icon"
+ src={comet}
+ alt=""
+ style={{ width: `${props.size}px`, height: `${props.size}px` }}
+ />
+ );
+ else if (props.patp.length > 15)
+ // moons
+ return (
+ <>
+ {sigil({
+ patp: props.patp.substring(props.patp.length - 13),
+ renderer: reactRenderer,
+ size: props.size,
+ colors: ["grey", "white"],
+ })}
+ </>
+ );
+ else
+ return (
+ <>
+ {sigil({
+ patp: props.patp,
+ renderer: reactRenderer,
+ size: props.size,
+ colors: [color, "white"],
+ })}
+ </>
+ );
+};
+
+export default Sigil;
diff --git a/front/src/components/feed/Body.tsx b/front/src/components/feed/Body.tsx
new file mode 100644
index 0000000..2f11962
--- /dev/null
+++ b/front/src/components/feed/Body.tsx
@@ -0,0 +1,174 @@
+import type {
+ // TODO ref backend fetching!!
+ Reference,
+ Block,
+ Inline,
+ Media as MediaType,
+ ExternalContent,
+} from "@/types/trill";
+import crow from "@/assets/icons/crow.svg";
+import type { PostProps } from "./Post";
+import Media from "./Media";
+import JSONContent, { YoutubeSnippet } from "./External";
+import { useLocation } from "wouter";
+import Quote from "./Quote";
+import PostData from "./PostData";
+import Card from "./Card.tsx";
+import type { Ship } from "@/types/urbit.ts";
+
+function Body(props: PostProps) {
+ const text = props.poast.contents.filter((c) => {
+ return (
+ "paragraph" in c ||
+ "blockquote" in c ||
+ "heading" in c ||
+ "codeblock" in c ||
+ "list" in c
+ );
+ });
+
+ const media: MediaType[] = props.poast.contents.filter(
+ (c): c is MediaType => "media" in c,
+ );
+
+ const refs = props.poast.contents.filter((c): c is Reference => "ref" in c);
+ const json = props.poast.contents.filter(
+ (c): c is ExternalContent => "json" in c,
+ );
+
+ return (
+ <div className="trill-post-body body">
+ <div className="body-text">
+ {text.map((b, i) => (
+ <TextBlock key={JSON.stringify(b) + i} block={b} />
+ ))}
+ </div>
+ {media.length > 0 && <Media media={media} />}
+ {refs.map((r, i) => (
+ <Ref r={r} nest={props.nest || 0} key={JSON.stringify(r) + i} />
+ ))}
+ <JSONContent content={json} />
+ </div>
+ );
+}
+export default Body;
+
+function TextBlock({ block }: { block: Block }) {
+ const key = JSON.stringify(block);
+ return "paragraph" in block ? (
+ <div className="trill-post-paragraph">
+ {block.paragraph.map((i, ind) => (
+ <Inlin key={key + ind} i={i} />
+ ))}
+ </div>
+ ) : "blockquote" in block ? (
+ <blockquote>
+ {block.blockquote.map((i, ind) => (
+ <Inlin key={key + ind} i={i} />
+ ))}
+ </blockquote>
+ ) : "heading" in block ? (
+ <Heading string={block.heading.text} num={block.heading.num} />
+ ) : "codeblock" in block ? (
+ <pre>
+ <code className={`language-${block.codeblock.lang}`}>
+ {block.codeblock.code}
+ </code>
+ </pre>
+ ) : "list" in block ? (
+ block.list.ordered ? (
+ <ol>
+ {block.list.text.map((i, ind) => (
+ <li key={JSON.stringify(i) + ind}>
+ <Inlin key={key + ind} i={i} />
+ </li>
+ ))}
+ </ol>
+ ) : (
+ <ul>
+ {block.list.text.map((i, ind) => (
+ <li key={JSON.stringify(i) + ind}>
+ <Inlin key={JSON.stringify(i) + ind} i={i} />
+ </li>
+ ))}
+ </ul>
+ )
+ ) : null;
+}
+function Inlin({ i }: { i: Inline }) {
+ const [_, navigate] = useLocation();
+ function gotoShip(e: React.MouseEvent, ship: Ship) {
+ e.stopPropagation();
+ navigate(`/feed/${ship}`);
+ }
+ return "text" in i ? (
+ <span>{i.text}</span>
+ ) : "italic" in i ? (
+ <i>{i.italic}</i>
+ ) : "bold" in i ? (
+ <strong>{i.bold}</strong>
+ ) : "strike" in i ? (
+ <span>{i.strike}</span>
+ ) : "underline" in i ? (
+ <span>{i.underline}</span>
+ ) : "sup" in i ? (
+ <sup>{i.sup}</sup>
+ ) : "sub" in i ? (
+ <sub>{i.sub}</sub>
+ ) : "ship" in i ? (
+ <span
+ className="mention"
+ role="link"
+ onMouseUp={(e) => gotoShip(e, i.ship)}
+ >
+ {i.ship}
+ </span>
+ ) : "codespan" in i ? (
+ <code>{i.codespan}</code>
+ ) : "link" in i ? (
+ <LinkParser {...i.link} />
+ ) : "break" in i ? (
+ <br />
+ ) : null;
+}
+
+function LinkParser({ href, show }: { href: string; show: string }) {
+ const YOUTUBE_REGEX_1 = /(youtube\.com\/watch\?v=)(\w+)/;
+ const YOUTUBE_REGEX_2 = /(youtu\.be\/)([a-zA-Z0-9-_]+)/;
+ const m1 = href.match(YOUTUBE_REGEX_1);
+ const m2 = href.match(YOUTUBE_REGEX_2);
+ const ytb = m1 && m1[2] ? m1[2] : m2 && m2[2] ? m2[2] : "";
+ return ytb ? (
+ <YoutubeSnippet href={href} id={ytb} />
+ ) : (
+ <a href={href}>{show}</a>
+ );
+}
+function Heading({ string, num }: { string: string; num: number }) {
+ return num === 1 ? (
+ <h1>{string}</h1>
+ ) : num === 2 ? (
+ <h2>{string}</h2>
+ ) : num === 3 ? (
+ <h3>{string}</h3>
+ ) : num === 4 ? (
+ <h4>{string}</h4>
+ ) : num === 5 ? (
+ <h5>{string}</h5>
+ ) : num === 6 ? (
+ <h6>{string}</h6>
+ ) : null;
+}
+
+function Ref({ r, nest }: { r: Reference; nest: number }) {
+ if (r.ref.type === "nostril") {
+ const comp = PostData({
+ host: r.ref.ship,
+ id: r.ref.path.slice(1),
+ nest: nest + 1,
+ className: "quote-in-post",
+ })(Quote);
+ return <Card logo={crow}>{comp}</Card>;
+ }
+ return <></>;
+}
diff --git a/front/src/components/feed/Card.tsx b/front/src/components/feed/Card.tsx
new file mode 100644
index 0000000..37f4911
--- /dev/null
+++ b/front/src/components/feed/Card.tsx
@@ -0,0 +1,9 @@
+export default function ({ children, logo, cn}: { cn?: string; logo: string; children: any }) {
+ const className = "trill-post-card" + (cn ? ` ${cn}`: "")
+ return (
+ <div className={className}>
+ <img src={logo} alt="" className="trill-post-card-logo" />
+ {children}
+ </div>
+ );
+}
diff --git a/front/src/components/feed/Composer.tsx b/front/src/components/feed/Composer.tsx
new file mode 100644
index 0000000..27da392
--- /dev/null
+++ b/front/src/components/feed/Composer.tsx
@@ -0,0 +1,52 @@
+import { openLock } from "@/logic/bunts";
+import { HASHTAGS_REGEX } from "@/logic/constants";
+import useLocalState from "@/state/state";
+import type { Poast, SentPoast } from "@/types/trill";
+import Sigil from "@/components/Sigil";
+import { useState } from "react";
+
+function Composer({
+ isAnon,
+ replying,
+}: {
+ isAnon?: boolean;
+ replying?: Poast;
+}) {
+ const { api, keys } = useLocalState();
+ const our = api!.airlock.our!;
+ const [input, setInput] = useState(replying ? `${replying}: ` : "");
+ async function poast() {
+ // TODO
+ // const parent = replying ? replying : null;
+ // const tokens = tokenize(input);
+ // const post: SentPoast = {
+ // host: parent ? parent.host : our,
+ // author: our,
+ // thread: parent ? parent.thread : null,
+ // parent: parent ? parent.id : null,
+ // contents: input,
+ // read: openLock,
+ // write: openLock,
+ // tags: input.match(HASHTAGS_REGEX) || [],
+ // };
+ // TODO make it user choosable
+ const pubkey = keys[0]!;
+ await api!.addPost(pubkey, input);
+ }
+ const placeHolder = isAnon ? "> be me" : "What's going on in Urbit";
+ return (
+ <div id="composer">
+ <div className="sigil">
+ <Sigil patp={our} size={48} />
+ </div>
+ <input
+ value={input}
+ onInput={(e) => setInput(e.currentTarget.value)}
+ placeholder={placeHolder}
+ />
+ <button onClick={poast}>Post</button>
+ </div>
+ );
+}
+
+export default Composer;
diff --git a/front/src/components/feed/External.tsx b/front/src/components/feed/External.tsx
new file mode 100644
index 0000000..0ea1500
--- /dev/null
+++ b/front/src/components/feed/External.tsx
@@ -0,0 +1,41 @@
+import type { ExternalContent } from "@/types/trill";
+import youtube from "@/assets/icons/youtube.svg";
+import Card from "./Card";
+
+interface JSONProps {
+ content: ExternalContent[];
+}
+
+function JSONContent({ content }: JSONProps) {
+ return (
+ <>
+ {content.map((c, i) => {
+ if (!JSON.parse(c.json.content)) return <p key={i}>Error</p>;
+ else
+ return (
+ <p
+ key={JSON.stringify(c.json)}
+ className="external-content-warning"
+ >
+ External content from "{c.json.origin}", use
+ <a href="https://urbit.org/applications/~sortug/ufa">UFA</a>
+ to display.
+ </p>
+ );
+ })}
+ </>
+ );
+}
+export default JSONContent;
+
+export function YoutubeSnippet({ href, id }: { href: string; id: string }) {
+ const thumbnail = `https://i.ytimg.com/vi/${id}/hqdefault.jpg`;
+ // todo styiling
+ return (
+ <Card logo={youtube} cn="youtube-thumbnail">
+ <a href={href}>
+ <img src={thumbnail} alt="" />
+ </a>
+ </Card>
+ );
+}
diff --git a/front/src/components/feed/Footer.tsx b/front/src/components/feed/Footer.tsx
new file mode 100644
index 0000000..938a8c7
--- /dev/null
+++ b/front/src/components/feed/Footer.tsx
@@ -0,0 +1,237 @@
+import type { PostProps } from "./Post";
+import reply from "@/assets/icons/reply.svg";
+import quote from "@/assets/icons/quote.svg";
+import repost from "@/assets/icons/rt.svg";
+import { useState } from "react";
+import useLocalState from "@/state/state";
+import { useLocation } from "wouter";
+import { displayCount } from "@/logic/utils";
+import { TrillReactModal, stringToReact } from "./Reactions";
+import toast from "react-hot-toast";
+import NostrIcon from "./NostrIcon";
+function Footer({ poast, refetch }: PostProps) {
+ const [_showMenu, setShowMenu] = useState(false);
+ const [location, navigate] = useLocation();
+ const [reposting, _setReposting] = useState(false);
+ const { api, setComposerData, setModal } = useLocalState();
+ const our = api!.airlock.our!;
+ function doReply(e: React.MouseEvent) {
+ e.stopPropagation();
+ setComposerData({ type: "reply", post: { service: "trill", post: poast } });
+ navigate("/composer");
+ }
+ function doQuote(e: React.MouseEvent) {
+ e.stopPropagation();
+ setComposerData({
+ type: "quote",
+ post: { service: "trill", post: poast },
+ });
+ navigate("/composer");
+ }
+ const childrenCount = poast.children
+ ? poast.children.length
+ ? poast.children.length
+ : Object.keys(poast.children).length
+ : 0;
+ const myRP = poast.engagement.shared.find((r) => r.pid.ship === our);
+ async function cancelRP(e: React.MouseEvent) {
+ e.stopPropagation();
+ const r = await api!.deletePost(our);
+ if (r) toast.success("Repost deleted");
+ refetch();
+ if (location.includes(poast.id)) navigate("/");
+ }
+ async function sendRP(e: React.MouseEvent) {
+ // TODO update backend because contents are only markdown now
+ e.stopPropagation();
+ // const c = [
+ // {
+ // ref: {
+ // type: "trill",
+ // ship: poast.host,
+ // path: `/${poast.id}`,
+ // },
+ // },
+ // ];
+ // const post: SentPoast = {
+ // host: our,
+ // author: our,
+ // thread: null,
+ // parent: null,
+ // contents: input,
+ // read: openLock,
+ // write: openLock,
+ // tags: [], // TODO
+ // };
+ // const r = await api!.addPost(post, false);
+ // setReposting(true);
+ // if (r) {
+ // setReposting(false);
+ // toast.success("Your post was published");
+ // }
+ }
+ function doReact(e: React.MouseEvent) {
+ e.stopPropagation();
+ const modal = <TrillReactModal poast={poast} />;
+ setModal(modal);
+ }
+ function showReplyCount() {
+ if (poast.children[0]) fetchAndShow(); // Flatpoast
+ // else {
+ // const authors = Object.keys(poast.children).map(
+ // (i) => poast.children[i].post.author
+ // );
+ // setEngagement({ type: "replies", ships: authors }, poast);
+ // }
+ }
+ async function fetchAndShow() {
+ // let authors = [];
+ // for (let i of poast.children as string[]) {
+ // const res = await scrypoastFull(poast.host, i);
+ // if (res)
+ // authors.push(res.post.author || "deleter");
+ // }
+ // setEngagement({ type: "replies", ships: authors }, poast);
+ }
+ function showRepostCount() {
+ // const ships = poast.engagement.shared.map((entry) => entry.host);
+ // setEngagement({ type: "reposts", ships: ships }, poast);
+ }
+ function showQuoteCount() {
+ // setEngagement({ type: "quotes", quotes: poast.engagement.quoted }, poast);
+ }
+ function showReactCount() {
+ // setEngagement({ type: "reacts", reacts: poast.engagement.reacts }, poast);
+ }
+
+ const mostCommonReact = Object.values(poast.engagement.reacts).reduce(
+ (acc: any, item) => {
+ if (!acc.counts[item]) acc.counts[item] = 0;
+ acc.counts[item] += 1;
+ if (!acc.winner || acc.counts[item] > acc.counts[acc.winner])
+ acc.winner = item;
+ return acc;
+ },
+ { counts: {}, winner: "" },
+ ).winner;
+ const reactIcon = stringToReact(mostCommonReact);
+
+ // TODO round up all helpers
+
+ return (
+ <div className="footer-wrapper post-footer">
+ <footer>
+ <div className="icon">
+ <span role="link" onMouseUp={showReplyCount} className="reply-count">
+ {displayCount(childrenCount)}
+ </span>
+ <img role="link" onMouseUp={doReply} src={reply} alt="" />
+ </div>
+ <div className="icon">
+ <span role="link" onMouseUp={showQuoteCount} className="quote-count">
+ {displayCount(poast.engagement.quoted.length)}
+ </span>
+ <img role="link" onMouseUp={doQuote} src={quote} alt="" />
+ </div>
+ <div className="icon">
+ <span
+ role="link"
+ onMouseUp={showRepostCount}
+ className="repost-count"
+ >
+ {displayCount(poast.engagement.shared.length)}
+ </span>
+ {reposting ? (
+ <p>...</p>
+ ) : myRP ? (
+ <img
+ role="link"
+ className="my-rp"
+ onMouseUp={cancelRP}
+ src={repost}
+ title="cancel repost"
+ />
+ ) : (
+ <img role="link" onMouseUp={sendRP} src={repost} title="repost" />
+ )}
+ </div>
+ <div className="icon" role="link" onMouseUp={doReact}>
+ <span
+ role="link"
+ onMouseUp={showReactCount}
+ className="reaction-count"
+ >
+ {displayCount(Object.keys(poast.engagement.reacts).length)}
+ </span>
+ {reactIcon}
+ </div>
+ <NostrIcon poast={poast} />
+ </footer>
+ </div>
+ );
+}
+export default Footer;
+
+// function Menu({
+// poast,
+// setShowMenu,
+// refetch,
+// }: {
+// poast: Poast;
+// setShowMenu: Function;
+// refetch: Function;
+// }) {
+// const ref = useRef<HTMLDivElement>(null);
+// const [location, navigate] = useLocation();
+// // TODO this is a mess and the event still propagates
+// useEffect(() => {
+// const checkIfClickedOutside = (e: any) => {
+// e.stopPropagation();
+// if (ref && ref.current && !ref.current.contains(e.target))
+// setShowMenu(false);
+// };
+// document.addEventListener("mousedown", checkIfClickedOutside);
+// return () => {
+// document.removeEventListener("mousedown", checkIfClickedOutside);
+// };
+// }, []);
+// const { our, setModal, setAlert } = useLocalState();
+// const mine = our === poast.host || our === poast.author;
+// async function doDelete(e: React.MouseEvent) {
+// e.stopPropagation();
+// deletePost(poast.host, poast.id);
+// setAlert("Post deleted");
+// setShowMenu(false);
+// refetch();
+// if (location.includes(poast.id)) navigate("/");
+// }
+// async function copyLink(e: React.MouseEvent) {
+// e.stopPropagation();
+// const link = trillPermalink(poast);
+// await navigator.clipboard.writeText(link);
+// // some alert
+// setShowMenu(false);
+// }
+// function openStats(e: React.MouseEvent) {
+// e.stopPropagation();
+// e.preventDefault();
+// const m = <StatsModal poast={poast} close={() => setModal(null)} />;
+// setModal(m);
+// }
+// return (
+// <div ref={ref} id="post-menu">
+// {/* <p onClick={openShare}>Share to Groups</p> */}
+// <p role="link" onMouseUp={openStats}>
+// See Stats
+// </p>
+// <p role="link" onMouseUp={copyLink}>
+// Permalink
+// </p>
+// {mine && (
+// <p role="link" onMouseUp={doDelete}>
+// Delete Post
+// </p>
+// )}
+// </div>
+// );
+// }
diff --git a/front/src/components/feed/Header.tsx b/front/src/components/feed/Header.tsx
new file mode 100644
index 0000000..7658bfb
--- /dev/null
+++ b/front/src/components/feed/Header.tsx
@@ -0,0 +1,33 @@
+import { date_diff } from "@/logic/utils";
+import type { PostProps } from "./Post";
+import { useLocation } from "wouter";
+function Header(props: PostProps) {
+ const [_, navigate] = useLocation();
+ function go(e: React.MouseEvent) {
+ e.stopPropagation();
+ }
+ function openThread(e: React.MouseEvent) {
+ e.stopPropagation();
+ const sel = window.getSelection()?.toString();
+ if (!sel) navigate(`/feed/${poast.host}/${poast.id}`);
+ }
+ const { poast } = props;
+ const name = (
+ <div className="name cp">
+ <p className="p-only">{poast.author}</p>
+ </div>
+ );
+ return (
+ <header>
+ <div className="author flex-align" role="link" onMouseUp={go}>
+ {name}
+ </div>
+ <div role="link" onMouseUp={openThread} className="date">
+ <p title={new Date(poast.time).toLocaleString()}>
+ {date_diff(poast.time, "short")}
+ </p>
+ </div>
+ </header>
+ );
+}
+export default Header;
diff --git a/front/src/components/feed/Media.tsx b/front/src/components/feed/Media.tsx
new file mode 100644
index 0000000..04ea156
--- /dev/null
+++ b/front/src/components/feed/Media.tsx
@@ -0,0 +1,35 @@
+import type { Media } from "@/types/trill";
+interface Props {
+ media: Media[];
+}
+function M({ media }: Props) {
+ return (
+ <div className="body-media">
+ {media.map((m, i) => {
+ return "video" in m.media ? (
+ <video key={JSON.stringify(m) + i} src={m.media.video} controls />
+ ) : "audio" in m.media ? (
+ <audio key={JSON.stringify(m) + i} src={m.media.audio} controls />
+ ) : "images" in m.media ? (
+ <Images key={JSON.stringify(m) + i} urls={m.media.images} />
+ ) : null;
+ })}
+ </div>
+ );
+}
+export default M;
+
+function Images({ urls }: { urls: string[] }) {
+ return (
+ <>
+ {urls.map((u, i) => (
+ <img
+ key={u + i}
+ className={`body-img body-img-1-of-${urls.length}`}
+ src={u}
+ alt=""
+ />
+ ))}
+ </>
+ );
+}
diff --git a/front/src/components/feed/NostrIcon.tsx b/front/src/components/feed/NostrIcon.tsx
new file mode 100644
index 0000000..0c368fb
--- /dev/null
+++ b/front/src/components/feed/NostrIcon.tsx
@@ -0,0 +1,22 @@
+import nostrIcon from "@/assets/icons/nostr.svg";
+import useLocalState from "@/state/state";
+import toast from "react-hot-toast";
+import type { Poast } from "@/types/trill";
+export default function ({ poast }: { poast: Poast }) {
+ const { relays, api, keys } = useLocalState();
+
+ async function sendToRelay(e: React.MouseEvent) {
+ e.stopPropagation();
+ //
+ const urls = Object.keys(relays);
+ await api!.relayPost(poast.host, poast.id, urls);
+ toast.success("Post relayed");
+ }
+ // TODO round up all helpers
+
+ return (
+ <div className="icon" role="link" onMouseUp={sendToRelay}>
+ <img role="link" src={nostrIcon} title="repost" />
+ </div>
+ );
+}
diff --git a/front/src/components/feed/Post.tsx b/front/src/components/feed/Post.tsx
new file mode 100644
index 0000000..1211a97
--- /dev/null
+++ b/front/src/components/feed/Post.tsx
@@ -0,0 +1,79 @@
+import type { PostID, Poast, Reference } from "@/types/trill";
+
+import Header from "./Header";
+import Body from "./Body";
+import Footer from "./Footer";
+import { useLocation } from "wouter";
+import useLocalState from "@/state/state";
+import RP from "./RP";
+import ShipModal from "../modals/ShipModal";
+import type { Ship } from "@/types/urbit";
+import Sigil from "../Sigil";
+
+export interface PostProps {
+ poast: Poast;
+ fake?: boolean;
+ rter?: Ship;
+ rtat?: number;
+ rtid?: PostID;
+ nest?: number;
+ refetch: Function;
+}
+function Post(props: PostProps) {
+ const { poast } = props;
+ console.log({ poast });
+ if (!poast || poast.contents === null) {
+ return null;
+ }
+ const isRP =
+ poast.contents.length === 1 &&
+ "ref" in poast.contents[0] &&
+ poast.contents[0].ref.type === "trill";
+ if (isRP) {
+ const ref = (poast.contents[0] as Reference).ref;
+ return (
+ <RP
+ host={ref.ship}
+ id={ref.path.slice(1)}
+ rter={poast.author}
+ rtat={poast.time}
+ rtid={poast.id}
+ />
+ );
+ } else return <TrillPost {...props} />;
+}
+export default Post;
+
+function TrillPost(props: PostProps) {
+ const { poast, fake } = props;
+ const { setModal } = useLocalState();
+ const [_, navigate] = useLocation();
+ function openThread(_e: React.MouseEvent) {
+ const sel = window.getSelection()?.toString();
+ if (!sel) navigate(`/feed/${poast.host}/${poast.id}`);
+ }
+
+ function openModal(e: React.MouseEvent) {
+ e.stopPropagation();
+ setModal(<ShipModal ship={poast.author} />);
+ }
+ const avatar = (
+ <div className="avatar-w sigil cp" role="link" onMouseUp={openModal}>
+ <Sigil patp={poast.author} size={42} />
+ </div>
+ );
+ return (
+ <div
+ className={`timeline-post trill-post cp`}
+ role="link"
+ onMouseUp={openThread}
+ >
+ <div className="left">{avatar}</div>
+ <div className="right">
+ <Header {...props} />
+ <Body {...props} />
+ {!fake && <Footer {...props} />}
+ </div>
+ </div>
+ );
+}
diff --git a/front/src/components/feed/PostData.tsx b/front/src/components/feed/PostData.tsx
new file mode 100644
index 0000000..f3c4715
--- /dev/null
+++ b/front/src/components/feed/PostData.tsx
@@ -0,0 +1,160 @@
+import { useQuery, useQueryClient } from "@tanstack/react-query";
+import spinner from "@/assets/triangles.svg";
+import { useEffect, useRef, useState } from "react";
+import useLocalState from "@/state/state";
+import type { PostID } from "@/types/trill";
+import type { Ship } from "@/types/urbit";
+
+function PostData(props: {
+ host: Ship;
+ id: PostID;
+ rter?: Ship;
+ rtat?: number;
+ rtid?: PostID;
+ nest?: number; // nested quotes
+ className?: string;
+}) {
+ const { api } = useLocalState();
+ const { host, id, nest } = props;
+ const [enest, setEnest] = useState(nest);
+ useEffect(() => {
+ setEnest(nest);
+ }, [nest]);
+
+ return function (Component: React.ElementType) {
+ // const [showNested, setShowNested] = useState(nest <= 3);
+ const handleShowNested = (e: React.MouseEvent) => {
+ e.stopPropagation();
+ setEnest(enest! - 3);
+ };
+ const [dead, setDead] = useState(false);
+ const [denied, setDenied] = useState(false);
+ const { isLoading, isError, data, refetch } = useQuery({
+ queryKey: ["trill-thread", host, id],
+ queryFn: fetchNode,
+ });
+ const queryClient = useQueryClient();
+ const dataRef = useRef(data);
+ useEffect(() => {
+ dataRef.current = data;
+ }, [data]);
+
+ async function fetchNode(): Promise<any> {
+ const res = await api!.scryPost(host, id, null, null);
+ if ("fpost" in res) return res;
+ else {
+ const existing = queryClient.getQueryData(["trill-thread", host, id]);
+ const existingData = existing || data;
+ if ("bugen" in res) {
+ // we peek for the actual node
+ peekTheNode();
+ // if we have a cache we don't invalidate it
+ if (existingData && "fpost" in existingData) return existingData;
+ // if we don't have a cache then we show the loading screen
+ else return res;
+ }
+ if ("no-node" in res) {
+ if (existingData && "fpost" in existingData) return existingData;
+ else return res;
+ }
+ }
+ }
+ function peekTheNode() {
+ let timer;
+ peekNode({ ship: host, id });
+ timer = setTimeout(() => {
+ const gotPost = dataRef.current && "fpost" in dataRef.current;
+ setDead(!gotPost);
+ // clearTimeout(timer);
+ }, 10_000);
+ }
+
+ useEffect(() => {
+ const path = `${host}/${id}`;
+ if (path in peekedPosts) {
+ queryClient.setQueryData(["trill-thread", host, id], {
+ fpost: peekedPosts[path],
+ });
+ } else if (path in deniedPosts) {
+ setDenied(true);
+ }
+ }, [peekedPosts]);
+ useEffect(() => {
+ const path = `${host}/${id}`;
+ if (path in deniedPosts) setDenied(true);
+ }, [deniedPosts]);
+
+ useEffect(() => {
+ const l = lastThread;
+ if (l && l.thread == id) {
+ queryClient.setQueryData(["trill-thread", host, id], { fpost: l });
+ }
+ }, [lastThread]);
+ function retryPeek(e: React.MouseEvent) {
+ e.stopPropagation();
+ setDead(false);
+ peekTheNode();
+ }
+ if (enest > 3)
+ return (
+ <div className={props.className}>
+ <div className="lazy x-center not-found">
+ <button className="x-center" onMouseUp={handleShowNested}>
+ Load more
+ </button>
+ </div>
+ </div>
+ );
+ else
+ return data ? (
+ dead ? (
+ <div className={props.className}>
+ <div className="no-response x-center not-found">
+ <p>{host} did not respond</p>
+ <button className="x-center" onMouseUp={retryPeek}>
+ Try again
+ </button>
+ </div>
+ </div>
+ ) : denied ? (
+ <div className={props.className}>
+ <p className="x-center not-found">
+ {host} denied you access to this post
+ </p>
+ </div>
+ ) : "no-node" in data || "bucun" in data ? (
+ <div className={props.className}>
+ <p className="x-center not-found">Post not found</p>
+ </div>
+ ) : "bugen" in data ? (
+ <div className={props.className}>
+ <div className="x-center not-found">
+ <p className="x-center">Post not found, requesting...</p>
+ <img src={spinner} className="x-center s-100" alt="" />
+ </div>
+ </div>
+ ) : "fpost" in data && data.fpost.contents === null ? (
+ <div className={props.className}>
+ <p className="x-center not-found">Post deleted</p>
+ </div>
+ ) : (
+ <Component
+ data={data.fpost}
+ refetch={refetch}
+ {...props}
+ nest={enest}
+ />
+ )
+ ) : // no data
+ isLoading || isError ? (
+ <div className={props.className}>
+ <img className="x-center post-spinner" src={spinner} alt="" />
+ </div>
+ ) : (
+ <div className={props.className}>
+ <p>...</p>
+ </div>
+ );
+ };
+}
+export default PostData;
diff --git a/front/src/components/feed/PostList.tsx b/front/src/components/feed/PostList.tsx
new file mode 100644
index 0000000..3d41ff8
--- /dev/null
+++ b/front/src/components/feed/PostList.tsx
@@ -0,0 +1,32 @@
+import TrillPost from "./Post";
+import type { FC } from "@/types/trill";
+// import { useEffect } from "react";
+// import { useQueryClient } from "@tanstack/react-query";
+// import { toFull } from "../thread/helpers";
+
+function TrillFeed({ data, refetch }: { data: FC; refetch: Function }) {
+ // const qc = useQueryClient();
+ // useEffect(() => {
+ // Object.values(data.feed).forEach((poast) => {
+ // const queryKey = ["trill-thread", poast.host, poast.id];
+ // const existing = qc.getQueryData(queryKey);
+ // if (!existing || !("fpost" in (existing as any))) {
+ // qc.setQueryData(queryKey, {
+ // fpost: toFull(poast),
+ // });
+ // }
+ // });
+ // }, [data]);
+ return (
+ <>
+ {Object.keys(data.feed)
+ .sort()
+ .reverse()
+ .map((i) => (
+ <TrillPost key={i} poast={data.feed[i]} refetch={refetch} />
+ ))}
+ </>
+ );
+}
+
+export default TrillFeed;
diff --git a/front/src/components/feed/Quote.tsx b/front/src/components/feed/Quote.tsx
new file mode 100644
index 0000000..d71be40
--- /dev/null
+++ b/front/src/components/feed/Quote.tsx
@@ -0,0 +1,37 @@
+import type { FullNode } from "@/types/trill";
+import { date_diff } from "@/logic/utils";
+import { useLocation } from "wouter";
+import Body from "./Body";
+import Sigil from "../Sigil";
+import { toFlat } from "./RP";
+
+function Quote({
+ data,
+ refetch,
+ nest,
+}: {
+ data: FullNode;
+ refetch?: Function;
+ nest: number;
+}) {
+ const [_, navigate] = useLocation();
+ function gotoQuote(e: React.MouseEvent) {
+ e.stopPropagation();
+ navigate(`/feed/${data.host}/${data.id}`);
+ }
+ return (
+ <div onMouseUp={gotoQuote} className="quote-in-post">
+ <header className="btw">
+ (
+ <div className="quote-author flex">
+ <Sigil patp={data.author} size={20} />
+ {data.author}
+ </div>
+ )<span>{date_diff(data.time, "short")}</span>
+ </header>
+ <Body poast={toFlat(data)} nest={nest} refetch={refetch!} />
+ </div>
+ );
+}
+
+export default Quote;
diff --git a/front/src/components/feed/RP.tsx b/front/src/components/feed/RP.tsx
new file mode 100644
index 0000000..dc733cc
--- /dev/null
+++ b/front/src/components/feed/RP.tsx
@@ -0,0 +1,47 @@
+import Post from "./Post";
+import type { Ship } from "@/types/urbit";
+import type { Poast, FullNode, ID } from "@/types/trill";
+import PostData from "./PostData";
+export default function (props: {
+ host: string;
+ id: string;
+ rter: Ship;
+ rtat: number;
+ rtid: ID;
+ refetch?: Function;
+}) {
+ return PostData(props)(RP);
+}
+
+function RP({
+ data,
+ refetch,
+ rter,
+ rtat,
+ rtid,
+}: {
+ data: FullNode;
+ refetch: Function;
+ rter: Ship;
+ rtat: number;
+ rtid: ID;
+}) {
+ return (
+ <Post
+ poast={toFlat(data)}
+ rter={rter}
+ rtat={rtat}
+ rtid={rtid}
+ refetch={refetch}
+ />
+ );
+}
+
+export function toFlat(n: FullNode): Poast {
+ return {
+ ...n,
+ children: !n.children
+ ? []
+ : Object.keys(n.children).map((c) => n.children[c].id),
+ };
+}
diff --git a/front/src/components/feed/Reactions.tsx b/front/src/components/feed/Reactions.tsx
new file mode 100644
index 0000000..58662cd
--- /dev/null
+++ b/front/src/components/feed/Reactions.tsx
@@ -0,0 +1,118 @@
+import type { Poast } from "@/types/trill";
+import yeschad from "@/assets/reacts/yeschad.png";
+import cringe from "@/assets/reacts/cringe.png";
+import cry from "@/assets/reacts/cry.png";
+import doom from "@/assets/reacts/doom.png";
+import galaxy from "@/assets/reacts/galaxy.png";
+import gigachad from "@/assets/reacts/gigachad.png";
+import pepechin from "@/assets/reacts/pepechin.png";
+import pepeeyes from "@/assets/reacts/pepeeyes.png";
+import pepegmi from "@/assets/reacts/pepegmi.png";
+import pepesad from "@/assets/reacts/pepesad.png";
+import pink from "@/assets/reacts/pink.png";
+import soy from "@/assets/reacts/soy.png";
+import chad from "@/assets/reacts/chad.png";
+import pika from "@/assets/reacts/pika.png";
+import facepalm from "@/assets/reacts/facepalm.png";
+import emoji from "@/assets/icons/emoji.svg";
+import emojis from "@/logic/emojis.json";
+import Modal from "../modals/Modal";
+import useLocalState from "@/state/state";
+
+export function ReactModal({ send }: { send: (s: string) => Promise<number> }) {
+ const { setModal } = useLocalState();
+ async function sendReact(e: React.MouseEvent, s: string) {
+ e.stopPropagation();
+ const res = await send(s);
+ if (res) setModal(null);
+ }
+ // todo one more meme
+ return (
+ <Modal>
+ <div id="react-list">
+ <span onMouseUp={(e) => sendReact(e, "❤️")}>️️❤️</span>
+ <span onMouseUp={(e) => sendReact(e, "🤔")}>🤔</span>
+ <span onMouseUp={(e) => sendReact(e, "😅")}>😅</span>
+ <span onMouseUp={(e) => sendReact(e, "🤬")}>🤬</span>
+ <span onMouseUp={(e) => sendReact(e, "😂")}>😂️</span>
+ <span onMouseUp={(e) => sendReact(e, "🫡")}>🫡️</span>
+ <span onMouseUp={(e) => sendReact(e, "🤢")}>🤢</span>
+ <span onMouseUp={(e) => sendReact(e, "😭")}>😭</span>
+ <span onMouseUp={(e) => sendReact(e, "😱")}>😱</span>
+ <img
+ onMouseUp={(e) => sendReact(e, "facepalm")}
+ src={facepalm}
+ alt=""
+ />
+ <span onMouseUp={(e) => sendReact(e, "👍")}>👍️</span>
+ <span onMouseUp={(e) => sendReact(e, "👎")}>👎️</span>
+ <span onMouseUp={(e) => sendReact(e, "☝")}>☝️</span>
+ <span onMouseUp={(e) => sendReact(e, "🤝")}>🤝</span>️
+ <span onMouseUp={(e) => sendReact(e, "🙏")}>🙏</span>
+ <span onMouseUp={(e) => sendReact(e, "🤡")}>🤡</span>
+ <span onMouseUp={(e) => sendReact(e, "👀")}>👀</span>
+ <span onMouseUp={(e) => sendReact(e, "🎤")}>🎤</span>
+ <span onMouseUp={(e) => sendReact(e, "💯")}>💯</span>
+ <span onMouseUp={(e) => sendReact(e, "🔥")}>🔥</span>
+ <img onMouseUp={(e) => sendReact(e, "yeschad")} src={yeschad} alt="" />
+ <img
+ onMouseUp={(e) => sendReact(e, "gigachad")}
+ src={gigachad}
+ alt=""
+ />
+ <img onMouseUp={(e) => sendReact(e, "pika")} src={pika} alt="" />
+ <img onMouseUp={(e) => sendReact(e, "cringe")} src={cringe} alt="" />
+ <img onMouseUp={(e) => sendReact(e, "pepegmi")} src={pepegmi} alt="" />
+ <img onMouseUp={(e) => sendReact(e, "pepesad")} src={pepesad} alt="" />
+ <img onMouseUp={(e) => sendReact(e, "galaxy")} src={galaxy} alt="" />
+ <img onMouseUp={(e) => sendReact(e, "pink")} src={pink} alt="" />
+ <img onMouseUp={(e) => sendReact(e, "soy")} src={soy} alt="" />
+ <img onMouseUp={(e) => sendReact(e, "cry")} src={cry} alt="" />
+ <img onMouseUp={(e) => sendReact(e, "doom")} src={doom} alt="" />
+ </div>
+ </Modal>
+ );
+}
+
+export function stringToReact(s: string) {
+ const em = (emojis as Record<string, string>)[s.replace(/\:/g, "")];
+ if (s === "yeschad")
+ return <img className="react-img" src={yeschad} alt="" />;
+ if (s === "facepalm")
+ return <img className="react-img" src={facepalm} alt="" />;
+ if (s === "yes.jpg")
+ return <img className="react-img" src={yeschad} alt="" />;
+ if (s === "gigachad")
+ return <img className="react-img" src={gigachad} alt="" />;
+ if (s === "pepechin")
+ return <img className="react-img" src={pepechin} alt="" />;
+ if (s === "pepeeyes")
+ return <img className="react-img" src={pepeeyes} alt="" />;
+ if (s === "pepegmi")
+ return <img className="react-img" src={pepegmi} alt="" />;
+ if (s === "pepesad")
+ return <img className="react-img" src={pepesad} alt="" />;
+ if (s === "")
+ return <img className="react-img no-react" src={emoji} alt="" />;
+ if (s === "cringe") return <img className="react-img" src={cringe} alt="" />;
+ if (s === "cry") return <img className="react-img" src={cry} alt="" />;
+ if (s === "crywojak") return <img className="react-img" src={cry} alt="" />;
+ if (s === "doom") return <img className="react-img" src={doom} alt="" />;
+ if (s === "galaxy") return <img className="react-img" src={galaxy} alt="" />;
+ if (s === "pink") return <img className="react-img" src={pink} alt="" />;
+ if (s === "pinkwojak") return <img className="react-img" src={pink} alt="" />;
+ if (s === "soy") return <img className="react-img" src={soy} alt="" />;
+ if (s === "chad") return <img className="react-img" src={chad} alt="" />;
+ if (s === "pika") return <img className="react-img" src={pika} alt="" />;
+ if (em) return <span className="react-icon">{em}</span>;
+ else if (s.length > 2) return <span className="react-icon"></span>;
+ else return <span className="react-icon">{s}</span>;
+}
+
+export function TrillReactModal({ poast }: { poast: Poast }) {
+ const { api } = useLocalState();
+ async function sendReact(s: string) {
+ return await api!.addReact(poast.host, poast.id, s);
+ }
+ return <ReactModal send={sendReact} />;
+}
diff --git a/front/src/components/feed/StatsModal.tsx b/front/src/components/feed/StatsModal.tsx
new file mode 100644
index 0000000..4720b2a
--- /dev/null
+++ b/front/src/components/feed/StatsModal.tsx
@@ -0,0 +1,106 @@
+import type { Poast } from "@/types/trill";
+import Modal from "../modals/Modal";
+import { useState } from "react";
+import Post from "./Post";
+import RP from "./RP";
+import Avatar from "../Avatar";
+import { stringToReact } from "./Reactions";
+
+function StatsModal({ poast, close }: { close: any; poast: Poast }) {
+ const [tab, setTab] = useState("replies");
+ const replies = poast.children || [];
+ const quotes = poast.engagement.quoted;
+ const reposts = poast.engagement.shared;
+ const reacts = poast.engagement.reacts;
+ function set(e: React.MouseEvent, s: string) {
+ e.stopPropagation();
+ setTab(s);
+ }
+ // TODO revise the global thingy here
+ return (
+ <Modal close={close}>
+ <div id="stats-modal">
+ <Post poast={poast} refetch={() => {}} />
+ <div id="tabs">
+ <div
+ role="link"
+ className={"tab" + (tab === "replies" ? " active-tab" : "")}
+ onClick={(e) => set(e, "replies")}
+ >
+ <h4>Replies</h4>
+ </div>
+ <div
+ role="link"
+ className={"tab" + (tab === "quotes" ? " active-tab" : "")}
+ onClick={(e) => set(e, "quotes")}
+ >
+ <h4>Quotes</h4>
+ </div>
+ <div
+ role="link"
+ className={"tab" + (tab === "reposts" ? " active-tab" : "")}
+ onClick={(e) => set(e, "reposts")}
+ >
+ <h4>Reposts</h4>
+ </div>
+ <div
+ role="link"
+ className={"tab" + (tab === "reacts" ? " active-tab" : "")}
+ onClick={(e) => set(e, "reacts")}
+ >
+ <h4>Reacts</h4>
+ </div>
+ </div>
+ <div id="engagement">
+ {tab === "replies" ? (
+ <div id="replies">
+ {replies.map((p) => (
+ <div key={p} className="reply-stat">
+ <RP
+ host={poast.host}
+ id={p}
+ rter={undefined}
+ rtat={undefined}
+ rtid={undefined}
+ />
+ </div>
+ ))}
+ </div>
+ ) : tab === "quotes" ? (
+ <div id="quotes">
+ {quotes.map((p) => (
+ <div key={p.pid.id} className="quote-stat">
+ <RP
+ host={p.pid.ship}
+ id={p.pid.id}
+ rter={undefined}
+ rtat={undefined}
+ rtid={undefined}
+ />
+ </div>
+ ))}
+ </div>
+ ) : tab === "reposts" ? (
+ <div id="reposts">
+ {reposts.map((p) => (
+ <div key={p.pid.id} className="repost-stat">
+ <Avatar p={p.pid.ship} size={40} />
+ </div>
+ ))}
+ </div>
+ ) : tab === "reacts" ? (
+ <div id="reacts">
+ {Object.keys(reacts).map((p) => (
+ <div key={p} className="react-stat btw">
+ <Avatar p={p} size={32} />
+ {stringToReact(reacts[p])}
+ </div>
+ ))}
+ </div>
+ ) : null}
+ </div>
+ </div>
+ </Modal>
+ );
+}
+export default StatsModal;
diff --git a/front/src/components/layout/Sidebar.tsx b/front/src/components/layout/Sidebar.tsx
new file mode 100644
index 0000000..1568421
--- /dev/null
+++ b/front/src/components/layout/Sidebar.tsx
@@ -0,0 +1,81 @@
+import { RADIO, versionNum } from "@/logic/constants";
+import { useLocation } from "wouter";
+import useLocalState from "@/state/state";
+import key from "@/assets/icons/key.svg";
+import logo from "@/assets/icons/logo.png";
+import home from "@/assets/icons/home.svg";
+import bell from "@/assets/icons/bell.svg";
+import settings from "@/assets/icons/settings.svg";
+import messages from "@/assets/icons/messages.svg";
+import profile from "@/assets/icons/profile.svg";
+import pals from "@/assets/icons/pals.svg";
+import rumors from "@/assets/icons/rumors.svg";
+import { ThemeSwitcher } from "@/styles/ThemeSwitcher";
+
+function SlidingMenu() {
+ const [_, navigate] = useLocation();
+ const { api } = useLocalState();
+ function goto(to: string) {
+ navigate(to);
+ }
+ return (
+ <div id="left-menu">
+ <div id="logo">
+ <img src={logo} />
+ <h3> Nostril </h3>
+ </div>
+ <h3>Feeds</h3>
+ <div className="opt" role="link" onClick={() => goto(`/feed/global`)}>
+ <img src={home} alt="" />
+ <div>Home</div>
+ </div>
+ <div className="opt" role="link" onClick={() => goto(`/hark`)}>
+ <img src={bell} alt="" />
+ <div>Activity</div>
+ </div>
+ <hr />
+
+ <div className="opt" role="link" onClick={() => goto("/chat")}>
+ <img src={messages} alt="" />
+ <div>Messages</div>
+ </div>
+ <div className="opt" role="link" onClick={() => goto("/pals")}>
+ <img src={pals} alt="" />
+ <div>Pals</div>
+ </div>
+ <hr />
+ <div
+ className="opt"
+ role="link"
+ onClick={() => goto(`/feed/${api!.airlock.our}`)}
+ >
+ <img src={profile} alt="" />
+ <div>Profile</div>
+ </div>
+ <div className="opt" role="link" onClick={() => goto("/feed/anon")}>
+ <img src={rumors} alt="" />
+ <div>Rumors</div>
+ </div>
+ <hr />
+ <div className="opt" role="link" onClick={() => goto("/radio")}>
+ <div className="img">{RADIO}</div>
+ <div>Radio</div>
+ </div>
+ <hr />
+ <div
+ className="opt"
+ role="link"
+ onClick={() => (window.location.href = "/cookies")}
+ >
+ <img src={key} alt="" />
+ <div>Logins</div>
+ </div>
+ <div className="opt" role="link" onClick={() => goto("/sets")}>
+ <img src={settings} alt="" />
+ <div>Settings</div>
+ </div>
+ <ThemeSwitcher />
+ </div>
+ );
+}
+export default SlidingMenu;
diff --git a/front/src/components/modals/Modal.tsx b/front/src/components/modals/Modal.tsx
new file mode 100644
index 0000000..7dd688c
--- /dev/null
+++ b/front/src/components/modals/Modal.tsx
@@ -0,0 +1,72 @@
+import useLocalState from "@/state/state";
+import { useEffect, useRef, useState } from "react";
+
+function Modal({ children }: any) {
+ const { setModal } = useLocalState();
+ function onKey(event: any) {
+ if (event.key === "Escape") setModal(null);
+ }
+ useEffect(() => {
+ document.addEventListener("keyup", onKey);
+ return () => {
+ document.removeEventListener("keyup", onKey);
+ };
+ }, [children]);
+
+ function clickAway(e: React.MouseEvent) {
+ console.log("clicked away");
+ e.stopPropagation();
+ if (!modalRef.current || !modalRef.current.contains(e.target))
+ setModal(null);
+ }
+ const modalRef = useRef(null);
+ return (
+ <div id="modal-background" onClick={clickAway}>
+ <div id="modal" ref={modalRef}>
+ {children}
+ </div>
+ </div>
+ );
+}
+export default Modal;
+
+export function Welcome() {
+ return (
+ <Modal>
+ <div id="welcome-msg">
+ <h1>Welcome to Nostril!</h1>
+ <p>
+ Trill is the world's only truly free and sovereign social media
+ platform, powered by Urbit.
+ </p>
+ <p>
+ Click on the crow icon on the top left to see all available feeds.
+ </p>
+ <p>The Global feed should be populated by default.</p>
+ <p>Follow people soon so your Global feed doesn't go stale.</p>
+ <p>
+ Trill is still on beta. The UI is Mobile only, we recommend you use
+ your phone or the browser dev tools. Desktop UI is on the works.
+ </p>
+ <p>
+ If you have any feedback please reach out to us on Groups at
+ ~hoster-dozzod-sortug/trill or here at ~polwex
+ </p>
+ </div>
+ </Modal>
+ );
+}
+
+export function Tooltip({ children, text, className }: any) {
+ const [show, toggle] = useState(false);
+ return (
+ <div
+ className={"tooltip-wrapper " + (className || "")}
+ onMouseOver={() => toggle(true)}
+ onMouseOut={() => toggle(false)}
+ >
+ {children}
+ {show && <div className="tooltip">{text}</div>}
+ </div>
+ );
+}
diff --git a/front/src/components/modals/ShipModal.tsx b/front/src/components/modals/ShipModal.tsx
new file mode 100644
index 0000000..86bffbb
--- /dev/null
+++ b/front/src/components/modals/ShipModal.tsx
@@ -0,0 +1,45 @@
+import type { Ship } from "@/types/urbit";
+import Modal from "./Modal";
+import Avatar from "../Avatar";
+import copyIcon from "@/assets/icons/copy.svg";
+import useLocalState from "@/state/state";
+import { useLocation } from "wouter";
+import toast from "react-hot-toast";
+
+export default function ({ ship }: { ship: Ship }) {
+ const { setModal, api } = useLocalState();
+ const [_, navigate] = useLocation();
+ function close() {
+ setModal(null);
+ }
+ async function copy(e: React.MouseEvent) {
+ e.stopPropagation();
+ await navigator.clipboard.writeText(ship);
+ toast.success("Copied to clipboard");
+ }
+ return (
+ <Modal close={close}>
+ <div id="ship-modal">
+ <div className="flex">
+ <Avatar p={ship} size={60} />
+ <img
+ className="copy-icon cp"
+ role="link"
+ onClick={copy}
+ src={copyIcon}
+ alt=""
+ />
+ </div>
+ <div className="buttons f1">
+ <button onClick={() => navigate(`/feed/${ship}`)}>Feed</button>
+ <button onClick={() => navigate(`/pals/${ship}`)}>Profile</button>
+ {ship !== api!.airlock.our && (
+ <>
+ <button onClick={() => navigate(`/chat/dm/${ship}`)}>DM</button>
+ </>
+ )}
+ </div>
+ </div>
+ </Modal>
+ );
+}
diff --git a/front/src/components/snippets/Snippets.tsx b/front/src/components/snippets/Snippets.tsx
new file mode 100644
index 0000000..68f5446
--- /dev/null
+++ b/front/src/components/snippets/Snippets.tsx
@@ -0,0 +1,395 @@
+import { fetchTweet, lurkTweet } from "@/logic/twatter/calls";
+import { pokeDister, scryDister, scryGangs } from "@/logic/requests/tlon";
+import { useEffect, useState } from "react";
+import Tweet from "@/sections/twatter/Tweet";
+import { toFlat } from "@/sections/feed/thread/helpers";
+import PostData from "@/sections/feed/PostData";
+import Post from "@/sections/feed/post/Post";
+import { FullNode, SortugRef } from "@/types/trill";
+import { useQuery, useQueryClient } from "@tanstack/react-query";
+import { subscribe, unsub } from "@/logic/requests/generic";
+import { AppData, GroupMetadata } from "@/types/tlon";
+import comet from "@/assets/icons/comet.svg";
+import Sigil from "@/ui/Sigil";
+import { PollLoader } from "@/sections/feed/poll/Show";
+import { parseThread, parseTweet } from "@/logic/twatter/parser";
+import { Tweet as TweetType } from "@/types/twatter";
+import { scryRadio } from "@/logic/requests/nostril";
+import useLocalState from "@/state/state";
+import { RadioTower, ScheduledRadio, radioLink } from "@/logic/requests/radio";
+import { Ship } from "@/types/urbit";
+import { RADIO } from "@/logic/constants";
+import { SigilOnly } from "../Avatar";
+import { date_diff } from "@/logic/utils";
+import ShipsModal from "../modals/ShipsModal";
+
+export function TrillSnippet({ r }: { r: SortugRef }) {
+ const { ship, path } = r;
+ return PostData({ host: ship, id: path.slice(1) })(TrillSnippetMarkup);
+}
+function TrillSnippetMarkup({
+ data,
+ refetch,
+}: {
+ data: FullNode;
+ refetch: Function;
+}) {
+ return (
+ <div className="trill-snippet">
+ <Post poast={toFlat(data)} refetch={refetch} />
+ </div>
+ );
+}
+// <div
+// onClick={() => {
+// if (pop) pop(link);
+// }}
+// className="chat-snippet trill-snippet"
+// >
+// Post not found
+// </div>
+// );
+
+export function TweetSnippet({
+ link,
+ giveBack,
+}: {
+ link: string;
+ giveBack?: Function;
+}) {
+ const id = link.split("/")[5];
+ const { isLoading, isError, data } = useQuery({
+ queryKey: ["twatter-thread", id],
+ queryFn: () => lurkTweet(id),
+ });
+ const [tw, setTw] = useState<TweetType>();
+ useEffect(() => {
+ if (data && "thread-lurk" in data) {
+ const js = JSON.parse(data["thread-lurk"]).data.tweetResult;
+ if (JSON.stringify(js) === "{}") return;
+ if (giveBack) giveBack(JSON.stringify(parseTweet(js.result)));
+ }
+ }, [data]);
+ if (isLoading || isError)
+ return (
+ <div className="tweet-snippet">
+ <p>Fetching Tweet from your Urbit...</p>
+ </div>
+ );
+ else {
+ if ("no-coki" in data)
+ return (
+ <div id="cookie-error" className="x-center">
+ <p className="">Your Twitter cookie isn't working correctly.</p>
+ <a href="/cookies">Check it out</a>
+ </div>
+ );
+ if ("fail" in data)
+ return (
+ <p>
+ Bad request. Please send some feedback (here) of what you were trying
+ to fetch.
+ </p>
+ );
+ if ("thread-lurk" in data) {
+ const js = JSON.parse(data["thread-lurk"]).data.tweetResult;
+ if (JSON.stringify(js) === "{}")
+ return null; // TODO wtf
+ else
+ return (
+ <div className="tweet-snippet">
+ <Tweet tweet={parseTweet(js.result)} quote={true} />
+ </div>
+ );
+ }
+ // else {
+ // const head = parseThread(JSON.parse(data.thread));
+ // const tweet = head.thread.tweets[0]
+ // giveBack(JSON.stringify(tweet))
+ // return (
+ // <div className="tweet-snippet">
+ // <Tweet tweet={tweet} quote={true} />
+ // </div>
+ // );
+ // }
+ }
+}
+
+export function AppSnippet({ r }: { r: SortugRef }) {
+ async function sub() {
+ if (!subn) {
+ const s = await subscribe(
+ "treaty",
+ "/treaties",
+ (data: { add: AppData }) => {
+ if ("ini" in data) {
+ const app = Object.values(data.ini).find((d) => d.desk === name);
+ setApp(app);
+ }
+ if ("add" in data && data.add.desk === name) setApp(data.add);
+ if (appData) unsub(subn);
+ },
+ );
+ setSub(s);
+ const res = await pokeDister(ship);
+ }
+ }
+ const { ship, path } = r;
+ const name = path.slice(1);
+ const [appData, setApp] = useState<AppData>();
+ const [subn, setSub] = useState<number>();
+ const { isLoading, data, isError } = useQuery({
+ queryKey: ["dister", ship],
+ queryFn: () => scryDister(ship),
+ });
+ if (isLoading || isError) return <div className="reference">...</div>;
+ else {
+ const app = Object.values(data.ini).find((d) => d.desk === name);
+ if (!app && !appData) sub();
+ const a = app
+ ? app
+ : appData
+ ? appData
+ : { title: name, image: comet, info: "", ship };
+ return (
+ <div className="reference app-ref">
+ <AppDiv app={a} />
+ </div>
+ );
+ }
+}
+function AppDiv({ app }: { app: Partial<AppData> }) {
+ return (
+ <>
+ <img src={app.image} alt="" />
+ <div className="text">
+ <p className="app-name">{app.title}</p>
+ <p className="app-info">{app.info}</p>
+ <p className="app-host">App from {app.ship}</p>
+ </div>
+ <p className="ref-ship">
+ <Sigil patp={app.ship} size={40} />
+ </p>
+ </>
+ );
+}
+
+export function TlonSnippet({ r }: { r: SortugRef }) {
+ if (r.type === "app") return <AppSnippet r={r} />;
+ if (r.type === "groups") return <GroupSnippet r={r} />;
+}
+export function GroupSnippet({ r }: { r: SortugRef }) {
+ const queryClient = useQueryClient();
+ async function sub() {
+ if (!subn) {
+ const path = `/gangs/index/${ship}`;
+ const s = await subscribe("groups", path, (data: any) => {
+ const key = `${ship}/${name}`;
+ const val = data[key];
+ queryClient.setQueryData(["gangs"], (old: any) => {
+ return { ...old, [key]: { preview: val } };
+ });
+ });
+ setSub(s);
+ }
+ }
+ const { ship, path } = r;
+ const name = path.slice(1);
+ const [groupData, setGroup] = useState<GroupMetadata>();
+ const [subn, setSub] = useState<number>();
+ const { isLoading, data, isError } = useQuery({
+ queryKey: ["gangs"],
+ queryFn: scryGangs,
+ });
+ if (isLoading || isError) return <div className="reference">...</div>;
+ else {
+ const group = data[`${ship}/${name}`];
+ if (!group && !groupData) sub();
+ const a =
+ group && group.preview
+ ? group.preview.meta
+ : groupData
+ ? groupData
+ : { title: name, image: comet, cover: "", description: "" };
+ return (
+ <div className="reference app-ref">
+ {a.image.startsWith("#") ? (
+ <div
+ className="group-color"
+ style={{ backgroundColor: a.image }}
+ ></div>
+ ) : (
+ <img src={a.image} alt="" />
+ )}
+ <div className="text">
+ <p className="app-name">{a.title}</p>
+ <p className="app-info">
+ {a.description.length > 25
+ ? a.description.substring(0, 25) + "..."
+ : a.description}
+ </p>
+ <p className="group-host">Group by {ship}</p>
+ </div>
+ {/* <p className="ref-ship">
+ <Sigil patp={ship} size={40} />
+ </p> */}
+ </div>
+ );
+ }
+}
+
+export function PollSnippet({ r }: { r: SortugRef }) {
+ return (
+ <div className="poll-snippet">
+ <PollLoader ship={r.ship} id={r.path.slice(1)} />
+ </div>
+ );
+}
+
+export function SnippetHandler(props: { r: SortugRef }) {
+ if (props.r.type === "trill") return <TrillSnippet r={props.r} />;
+ if (props.r.type === "trill-polls") return <PollSnippet r={props.r} />;
+ if (props.r.type === "app") return <AppSnippet r={props.r} />;
+ if (props.r.type === "groups") return <GroupSnippet r={props.r} />;
+}
+
+export function RadioSnippet({ ship }: { ship: Ship }) {
+ const { our } = useLocalState();
+ return ship === our ? <OwnRadio /> : <DudesRadio ship={ship} />;
+}
+
+function DudesRadio({ ship }: { ship }) {
+ function onc() {
+ radioLink(ship);
+ }
+ const { radioTowers } = useLocalState();
+ const tower = radioTowers.find((t) => t.location === ship);
+ if (!tower)
+ return (
+ <div role="link" onMouseUp={onc} className="radio-snippet">
+ <p className="img">{RADIO}</p>
+ <div className="radio-text">
+ <p>Radio data not published. Click and check.</p>;
+ </div>
+ </div>
+ );
+ else
+ return (
+ <div role="link" onMouseUp={onc} className="radio-snippet">
+ <p className="img">{RADIO}</p>
+ <div className="radio-text">
+ <p>Radio Session. Playing: {tower.description}</p>
+ <p>Started {new Date(tower.time).toLocaleString()}</p>
+ </div>
+ <div>
+ <SigilOnly p={ship} size={42} />
+ <span className="viewers">
+ {tower.viewers}
+ <span>👀</span>
+ </span>
+ </div>
+ </div>
+ );
+}
+
+function OwnRadio() {
+ const { currentRadio, our, setModal, radioTowers } = useLocalState();
+ const [scheduled, setS] = useState<ScheduledRadio | null>(null);
+ function onc() {
+ radioLink(our);
+ }
+ useEffect(() => {
+ scryRadio().then((r) => {
+ if (r) setS(r.radio);
+ });
+ }, []);
+ function showViewers() {
+ const modal = (
+ <ShipsModal
+ ships={currentRadio.viewers}
+ header={`People watching your %radio show`}
+ />
+ );
+ setModal(modal);
+ }
+ if (scheduled && scheduled.time > Date.now())
+ return (
+ <div role="link" onMouseUp={onc} className="radio-snippet">
+ <p className="img">{RADIO}</p>
+ <div className="radio-text">
+ <p>
+ Radio Session. Playing:
+ <a className="radio-link" href={scheduled.url}>
+ {scheduled.desc}
+ </a>
+ </p>
+ <p>Starting at {new Date(scheduled.time).toLocaleString()}</p>
+ </div>
+ <div>
+ <SigilOnly p={our} size={42} />
+ </div>
+ </div>
+ );
+ else if (!currentRadio)
+ return (
+ <div role="link" onMouseUp={onc} className="radio-snippet">
+ <p className="img">{RADIO}</p>
+ <div className="radio-text">
+ <p>Radio unavailable</p>
+ </div>
+ </div>
+ );
+ else
+ return (
+ <div role="link" onMouseUp={onc} className="radio-snippet">
+ <p className="img">{RADIO}</p>
+ <div className="radio-text">
+ <p>
+ Radio Session. Playing:
+ <a className="radio-link" href={currentRadio.stream}>
+ {currentRadio.description}
+ </a>
+ </p>
+ {/* <p>Started {date_diff(currentRadio.time, "long")}</p> */}
+ </div>
+ <div>
+ <SigilOnly p={our} size={42} />
+ <span onClick={showViewers} className="viewers">
+ {currentRadio?.viewers?.length || ""}
+ <span>👀</span>
+ </span>
+ </div>
+ </div>
+ );
+
+ // return (
+ // {scheduled > Date.now()
+ // ? (<>
+ // <p>
+ // Radio Session. Playing:
+ // <a className="radio-link" target="_blank" href={currentRadio.stream}>
+ // {currentRadio.description}
+ // </a>
+ // </p>
+
+ // <p>Starting at {new Date(scheduled).toLocaleString()}</p>
+ // </>
+
+ // ): scheduled !== 0()
+
+ // }
+ // <p>
+ // Radio Session. Playing:
+ // <a className="radio-link" target="_blank" href={currentRadio.stream}>
+ // {currentRadio.description}
+ // </a>
+ // </p>
+ // {scheduled && scheduled > Date.now() ? (
+ // <p>Starting at {new Date(scheduled).toLocaleString()}</p>
+ // ) : scheduled !== 0 ? (
+ // <p>Started {date_diff(new Date(scheduled), "long")}. Click to join.</p>
+ // ) : (
+ // <p>Unscheduled session. Click to join.</p>
+ // )}
+ // );
+}
diff --git a/front/src/logic/api.ts b/front/src/logic/api.ts
new file mode 100644
index 0000000..b8acba2
--- /dev/null
+++ b/front/src/logic/api.ts
@@ -0,0 +1,15 @@
+import Urbit from "urbit-api";
+
+export const URL = import.meta.env.PROD ? "" : "http://localhost:8080";
+
+export async function start(): Promise<Urbit> {
+ const airlock = new Urbit(URL, "");
+ const res = await fetch(URL + "/~/host");
+ const ship = await res.text();
+ airlock.ship = ship.slice(1);
+ airlock.our = ship;
+ airlock.desk = "nostril";
+ await airlock.poke({ app: "hood", mark: "helm-hi", json: "opening airlock" });
+ await airlock.eventSource();
+ return airlock;
+}
diff --git a/front/src/logic/bunts.ts b/front/src/logic/bunts.ts
new file mode 100644
index 0000000..dfa70e3
--- /dev/null
+++ b/front/src/logic/bunts.ts
@@ -0,0 +1,51 @@
+import type { Engagement, List, Lock } from "@/types/trill";
+
+export const openLock: Lock = {
+ rank: { caveats: [], locked: false, public: true },
+ luk: { caveats: [], locked: false, public: true },
+ ship: { caveats: [], locked: false, public: true },
+ tags: { caveats: [], locked: false, public: true },
+ custom: { fn: null, public: false },
+};
+
+export const engagementBunt: Engagement = {
+ reacts: {},
+ quoted: [],
+ shared: [],
+};
+
+export const pushStateBunt = {
+ followers: [],
+ gate: {
+ lock: openLock,
+ mute: openLock,
+ begs: [],
+ "post-begs": [],
+ backlog: 0,
+ },
+};
+
+export const harkStateBunt = {
+ unread: {},
+ engagement: [],
+};
+
+export const pullStateBunt = {
+ following: [],
+ begs: [],
+ "post-begs": [],
+};
+export const listBunt: List = {
+ symbol: "",
+ name: "",
+ desc: "",
+ icon: "",
+ cover: "",
+ members: [],
+ public: true,
+};
+
+// export const palsBunt: Pals = {
+// incoming: {},
+// outgoing: {}
+// }
diff --git a/front/src/logic/constants.ts b/front/src/logic/constants.ts
new file mode 100644
index 0000000..fcf5573
--- /dev/null
+++ b/front/src/logic/constants.ts
@@ -0,0 +1,36 @@
+import type { Poast } from "@/types/trill";
+
+export const versionNum = "0.1.0";
+export const TIMEOUT = 15_000;
+
+export const ChatPostCount = 50;
+export const FeedPostCount = 50;
+export const RumorShip = "~londev-dozzod-sortug";
+export const RumorShip2 = "~paldev";
+
+export function isRumor(poast: Poast) {
+ return poast.author === RumorShip || poast.author === RumorShip2;
+}
+
+export const MOBILE_BROWSER_REGEX =
+ /Android|webOS|iPhone|iPad|iPod|BlackBerry/i;
+export const AUDIO_REGEX = new RegExp(/https:\/\/.+\.(mp3|wav|ogg)\b/gim);
+export const VIDEO_REGEX = new RegExp(/https:\/\/.+\.(mov|mp4|ogv)\b/gim);
+export const TWITTER_REGEX = new RegExp(
+ /https:\/\/(twitter|x)\.com\/.+\/status\/\d+/gim,
+);
+
+export const REF_REGEX = new RegExp(
+ /urbit:\/\/[a-z0-9-]+\/~[a-z-_]+\/[a-z0-9-_]+/gim,
+);
+export const RADIO_REGEX = new RegExp(/urbit:\/\/radio\/~[a-z-_]+/gim);
+
+export const IMAGE_REGEX = new RegExp(
+ /https:\/\/.+\.(jpg|img|png|gif|tiff|jpeg|webp|webm|svg)\b/gim,
+);
+
+export const SHIP_REGEX = new RegExp(/\B~[a-z-]+/);
+export const HASHTAGS_REGEX = new RegExp(/#[a-z-]+/g);
+
+export const DEFAULT_DATE = { year: 1970, month: 1, day: 1 };
+export const RADIO = "📻";
diff --git a/front/src/logic/emojis.json b/front/src/logic/emojis.json
new file mode 100644
index 0000000..599f707
--- /dev/null
+++ b/front/src/logic/emojis.json
@@ -0,0 +1,3613 @@
+{
+ "100": "💯",
+ "1000": "1000",
+ "1234": "🔢",
+ "white_heavy_check_mark": "✅",
+ "done": "✅",
+ "pants": "👖",
+ "squirrel": "🐿️",
+ "partyparrot": "🦜",
+ "party-parrot": "🦜",
+ "60fps_parrot": "🦜",
+ "charmander": "🔥",
+ "java": "☕",
+ "slack": "S",
+ "discord": "D",
+ "github": "G",
+ "jira": "J",
+ "shame": "😳",
+ "airbyte-100": "💯",
+ "airbyte-fire": "🔥",
+ "firee": "🔥",
+ "meow_party": "🎉",
+ "meowparty": "🎉",
+ "partyblob": "🎉",
+ "party-blob": "🎉",
+ "party_blob": "🎉",
+ "octavia-hmm": "🤔",
+ "octavia-hello": "👋",
+ "ory_love": "❤️",
+ "grinning": "😀",
+ "smiley": "😃",
+ "smile": "😄",
+ "grin": "😁",
+ "laughing": "😆",
+ "satisfied": "😆",
+ "sweat_smile": "😅",
+ "rolling_on_the_floor_laughing": "🤣",
+ "joy": "😂",
+ "slightly_smiling_face": "🙂",
+ "upside_down_face": "🙃",
+ "melting_face": "🫠",
+ "wink": "😉",
+ "blush": "😊",
+ "innocent": "😇",
+ "smiling_face_with_3_hearts": "🥰",
+ "heart_eyes": "😍",
+ "star-struck": "🤩",
+ "grinning_face_with_star_eyes": "🤩",
+ "kissing_heart": "😘",
+ "kissing": "😗",
+ "relaxed": "☺️",
+ "kissing_closed_eyes": "😚",
+ "kissing_smiling_eyes": "😙",
+ "smiling_face_with_tear": "🥲",
+ "yum": "😋",
+ "stuck_out_tongue": "😛",
+ "stuck_out_tongue_winking_eye": "😜",
+ "zany_face": "🤪",
+ "grinning_face_with_one_large_and_one_small_eye": "🤪",
+ "stuck_out_tongue_closed_eyes": "😝",
+ "money_mouth_face": "🤑",
+ "hugging_face": "🤗",
+ "face_with_hand_over_mouth": "🤭",
+ "smiling_face_with_smiling_eyes_and_hand_covering_mouth": "🤭",
+ "face_with_open_eyes_and_hand_over_mouth": "🫢",
+ "face_with_peeking_eye": "🫣",
+ "shushing_face": "🤫",
+ "face_with_finger_covering_closed_lips": "🤫",
+ "thinking_face": "🤔",
+ "saluting_face": "🫡",
+ "zipper_mouth_face": "🤐",
+ "face_with_raised_eyebrow": "🤨",
+ "face_with_one_eyebrow_raised": "🤨",
+ "neutral_face": "😐",
+ "expressionless": "😑",
+ "no_mouth": "😶",
+ "dotted_line_face": "🫥",
+ "face_in_clouds": "😶‍🌫️",
+ "smirk": "😏",
+ "unamused": "😒",
+ "face_with_rolling_eyes": "🙄",
+ "grimacing": "😬",
+ "face_exhaling": "😮‍💨",
+ "lying_face": "🤥",
+ "relieved": "😌",
+ "pensive": "😔",
+ "sleepy": "😪",
+ "drooling_face": "🤤",
+ "sleeping": "😴",
+ "mask": "😷",
+ "face_with_thermometer": "🤒",
+ "face_with_head_bandage": "🤕",
+ "nauseated_face": "🤢",
+ "face_vomiting": "🤮",
+ "face_with_open_mouth_vomiting": "🤮",
+ "sneezing_face": "🤧",
+ "hot_face": "🥵",
+ "cold_face": "🥶",
+ "woozy_face": "🥴",
+ "dizzy_face": "😵",
+ "face_with_spiral_eyes": "😵‍💫",
+ "exploding_head": "🤯",
+ "wow_fb": "🤯",
+ "shocked_face_with_exploding_head": "🤯",
+ "face_with_cowboy_hat": "🤠",
+ "partying_face": "🥳",
+ "disguised_face": "🥸",
+ "sunglasses": "😎",
+ "nerd_face": "🤓",
+ "face_with_monocle": "🧐",
+ "confused": "😕",
+ "face_with_diagonal_mouth": "🫤",
+ "worried": "😟",
+ "slightly_frowning_face": "🙁",
+ "white_frowning_face": "☹️",
+ "open_mouth": "😮",
+ "hushed": "😯",
+ "astonished": "😲",
+ "flushed": "😳",
+ "pleading_face": "🥺",
+ "face_holding_back_tears": "🥹",
+ "frowning": "😦",
+ "anguished": "😧",
+ "fearful": "😨",
+ "cold_sweat": "😰",
+ "disappointed_relieved": "😥",
+ "cry": "😢",
+ "sob": "😭",
+ "scream": "😱",
+ "confounded": "😖",
+ "persevere": "😣",
+ "disappointed": "😞",
+ "sweat": "😓",
+ "weary": "😩",
+ "tired_face": "😫",
+ "yawning_face": "🥱",
+ "triumph": "😤",
+ "rage": "😡",
+ "jakesidsmithmadness": "😡",
+ "angry": "😠",
+ "face_with_symbols_on_mouth": "🤬",
+ "serious_face_with_symbols_covering_mouth": "🤬",
+ "smiling_imp": "😈",
+ "imp": "👿",
+ "skull": "💀",
+ "skull_and_crossbones": "☠️",
+ "hankey": "💩",
+ "shit": "💩",
+ "clown_face": "🤡",
+ "japanese_ogre": "👹",
+ "japanese_goblin": "👺",
+ "ghost": "👻",
+ "alien": "👽",
+ "space_invader": "👾",
+ "robot_face": "🤖",
+ "android": "🤖",
+ "smiley_cat": "😺",
+ "smile_cat": "😸",
+ "joy_cat": "😹",
+ "heart_eyes_cat": "😻",
+ "smirk_cat": "😼",
+ "kissing_cat": "😽",
+ "scream_cat": "🙀",
+ "crying_cat_face": "😿",
+ "pouting_cat": "😾",
+ "see_no_evil": "🙈",
+ "hear_no_evil": "🙉",
+ "speak_no_evil": "🙊",
+ "kiss": "💋",
+ "love_letter": "💌",
+ "cupid": "💘",
+ "gift_heart": "💝",
+ "sparkling_heart": "💖",
+ "heartpulse": "💗",
+ "heartbeat": "💓",
+ "revolving_hearts": "💞",
+ "two_hearts": "💕",
+ "heart_decoration": "💟",
+ "heavy_heart_exclamation_mark_ornament": "❣️",
+ "broken_heart": "💔",
+ "heart_on_fire": "❤️‍🔥",
+ "mending_heart": "❤️‍🩹",
+ "heart": "❤️",
+ "kodee_love": "❤️",
+ "kodee-love": "❤️",
+ "orange_heart": "🧡",
+ "yellow_heart": "💛",
+ "green_heart": "💚",
+ "blue_heart": "💙",
+ "purple_heart": "💜",
+ "brown_heart": "🤎",
+ "black_heart": "🖤",
+ "white_heart": "🤍",
+ "anger": "💢",
+ "boom": "💥",
+ "collision": "💥",
+ "dizzy": "💫",
+ "sweat_drops": "💦",
+ "dash": "💨",
+ "hole": "🕳️",
+ "bomb": "💣",
+ "speech_balloon": "💬",
+ "eye-in-speech-bubble": "👁️‍🗨️",
+ "left_speech_bubble": "🗨️",
+ "right_anger_bubble": "🗯️",
+ "thought_balloon": "💭",
+ "zzz": "💤",
+ "wave_animated": "👋",
+ "wave": "👋",
+ "wave::skin-tone-2": "👋🏻",
+ "wave::skin-tone-3": "👋🏼",
+ "wave::skin-tone-4": "👋🏽",
+ "wave::skin-tone-5": "👋🏾",
+ "wave::skin-tone-6": "👋🏿",
+ "raised_back_of_hand": "🤚",
+ "raised_back_of_hand::skin-tone-2": "🤚🏻",
+ "raised_back_of_hand::skin-tone-3": "🤚🏼",
+ "raised_back_of_hand::skin-tone-4": "🤚🏽",
+ "raised_back_of_hand::skin-tone-5": "🤚🏾",
+ "raised_back_of_hand::skin-tone-6": "🤚🏿",
+ "raised_hand_with_fingers_splayed": "🖐️",
+ "raised_hand_with_fingers_splayed::skin-tone-2": "🖐🏻",
+ "raised_hand_with_fingers_splayed::skin-tone-3": "🖐🏼",
+ "raised_hand_with_fingers_splayed::skin-tone-4": "🖐🏽",
+ "raised_hand_with_fingers_splayed::skin-tone-5": "🖐🏾",
+ "raised_hand_with_fingers_splayed::skin-tone-6": "🖐🏿",
+ "hand": "✋",
+ "raised_hand": "✋",
+ "hand::skin-tone-2": "✋🏻",
+ "raised_hand::skin-tone-2": "✋🏻",
+ "hand::skin-tone-3": "✋🏼",
+ "raised_hand::skin-tone-3": "✋🏼",
+ "hand::skin-tone-4": "✋🏽",
+ "raised_hand::skin-tone-4": "✋🏽",
+ "hand::skin-tone-5": "✋🏾",
+ "raised_hand::skin-tone-5": "✋🏾",
+ "hand::skin-tone-6": "✋🏿",
+ "raised_hand::skin-tone-6": "✋🏿",
+ "spock-hand": "🖖",
+ "spock-hand::skin-tone-2": "🖖🏻",
+ "spock-hand::skin-tone-3": "🖖🏼",
+ "spock-hand::skin-tone-4": "🖖🏽",
+ "spock-hand::skin-tone-5": "🖖🏾",
+ "spock-hand::skin-tone-6": "🖖🏿",
+ "rightwards_hand": "🫱",
+ "rightwards_hand::skin-tone-2": "🫱🏻",
+ "rightwards_hand::skin-tone-3": "🫱🏼",
+ "rightwards_hand::skin-tone-4": "🫱🏽",
+ "rightwards_hand::skin-tone-5": "🫱🏾",
+ "rightwards_hand::skin-tone-6": "🫱🏿",
+ "leftwards_hand": "🫲",
+ "leftwards_hand::skin-tone-2": "🫲🏻",
+ "leftwards_hand::skin-tone-3": "🫲🏼",
+ "leftwards_hand::skin-tone-4": "🫲🏽",
+ "leftwards_hand::skin-tone-5": "🫲🏾",
+ "leftwards_hand::skin-tone-6": "🫲🏿",
+ "palm_down_hand": "🫳",
+ "palm_down_hand::skin-tone-2": "🫳🏻",
+ "palm_down_hand::skin-tone-3": "🫳🏼",
+ "palm_down_hand::skin-tone-4": "🫳🏽",
+ "palm_down_hand::skin-tone-5": "🫳🏾",
+ "palm_down_hand::skin-tone-6": "🫳🏿",
+ "palm_up_hand": "🫴",
+ "palm_up_hand::skin-tone-2": "🫴🏻",
+ "palm_up_hand::skin-tone-3": "🫴🏼",
+ "palm_up_hand::skin-tone-4": "🫴🏽",
+ "palm_up_hand::skin-tone-5": "🫴🏾",
+ "palm_up_hand::skin-tone-6": "🫴🏿",
+ "ok_hand": "👌",
+ "ok_hand::skin-tone-2": "👌🏻",
+ "ok_hand::skin-tone-3": "👌🏼",
+ "ok_hand::skin-tone-4": "👌🏽",
+ "ok_hand::skin-tone-5": "👌🏾",
+ "ok_hand::skin-tone-6": "👌🏿",
+ "nice": "👌",
+ "nice::skin-tone-2": "👌🏻",
+ "nice::skin-tone-3": "👌🏼",
+ "nice::skin-tone-4": "👌🏽",
+ "nice::skin-tone-5": "👌🏾",
+ "nice::skin-tone-6": "👌🏿",
+ "pinched_fingers": "🤌",
+ "pinched_fingers::skin-tone-2": "🤌🏻",
+ "pinched_fingers::skin-tone-3": "🤌🏼",
+ "pinched_fingers::skin-tone-4": "🤌🏽",
+ "pinched_fingers::skin-tone-5": "🤌🏾",
+ "pinched_fingers::skin-tone-6": "🤌🏿",
+ "pinching_hand": "🤏",
+ "pinching_hand::skin-tone-2": "🤏🏻",
+ "pinching_hand::skin-tone-3": "🤏🏼",
+ "pinching_hand::skin-tone-4": "🤏🏽",
+ "pinching_hand::skin-tone-5": "🤏🏾",
+ "pinching_hand::skin-tone-6": "🤏🏿",
+ "v": "✌️",
+ "v::skin-tone-2": "✌🏻",
+ "v::skin-tone-3": "✌🏼",
+ "v::skin-tone-4": "✌🏽",
+ "v::skin-tone-5": "✌🏾",
+ "v::skin-tone-6": "✌🏿",
+ "crossed_fingers": "🤞",
+ "hand_with_index_and_middle_fingers_crossed": "🤞",
+ "crossed_fingers::skin-tone-2": "🤞🏻",
+ "hand_with_index_and_middle_fingers_crossed::skin-tone-2": "🤞🏻",
+ "crossed_fingers::skin-tone-3": "🤞🏼",
+ "hand_with_index_and_middle_fingers_crossed::skin-tone-3": "🤞🏼",
+ "crossed_fingers::skin-tone-4": "🤞🏽",
+ "hand_with_index_and_middle_fingers_crossed::skin-tone-4": "🤞🏽",
+ "crossed_fingers::skin-tone-5": "🤞🏾",
+ "hand_with_index_and_middle_fingers_crossed::skin-tone-5": "🤞🏾",
+ "crossed_fingers::skin-tone-6": "🤞🏿",
+ "hand_with_index_and_middle_fingers_crossed::skin-tone-6": "🤞🏿",
+ "hand_with_index_finger_and_thumb_crossed": "🫰",
+ "hand_with_index_finger_and_thumb_crossed::skin-tone-2": "🫰🏻",
+ "hand_with_index_finger_and_thumb_crossed::skin-tone-3": "🫰🏼",
+ "hand_with_index_finger_and_thumb_crossed::skin-tone-4": "🫰🏽",
+ "hand_with_index_finger_and_thumb_crossed::skin-tone-5": "🫰🏾",
+ "hand_with_index_finger_and_thumb_crossed::skin-tone-6": "🫰🏿",
+ "i_love_you_hand_sign": "🤟",
+ "i_love_you_hand_sign::skin-tone-2": "🤟🏻",
+ "i_love_you_hand_sign::skin-tone-3": "🤟🏼",
+ "i_love_you_hand_sign::skin-tone-4": "🤟🏽",
+ "i_love_you_hand_sign::skin-tone-5": "🤟🏾",
+ "i_love_you_hand_sign::skin-tone-6": "🤟🏿",
+ "the_horns": "🤘",
+ "sign_of_the_horns": "🤘",
+ "the_horns::skin-tone-2": "🤘🏻",
+ "sign_of_the_horns::skin-tone-2": "🤘🏻",
+ "the_horns::skin-tone-3": "🤘🏼",
+ "sign_of_the_horns::skin-tone-3": "🤘🏼",
+ "the_horns::skin-tone-4": "🤘🏽",
+ "sign_of_the_horns::skin-tone-4": "🤘🏽",
+ "the_horns::skin-tone-5": "🤘🏾",
+ "sign_of_the_horns::skin-tone-5": "🤘🏾",
+ "the_horns::skin-tone-6": "🤘🏿",
+ "sign_of_the_horns::skin-tone-6": "🤘🏿",
+ "call_me_hand": "🤙",
+ "call_me_hand::skin-tone-2": "🤙🏻",
+ "call_me_hand::skin-tone-3": "🤙🏼",
+ "call_me_hand::skin-tone-4": "🤙🏽",
+ "call_me_hand::skin-tone-5": "🤙🏾",
+ "call_me_hand::skin-tone-6": "🤙🏿",
+ "point_left": "👈",
+ "point_left::skin-tone-2": "👈🏻",
+ "point_left::skin-tone-3": "👈🏼",
+ "point_left::skin-tone-4": "👈🏽",
+ "point_left::skin-tone-5": "👈🏾",
+ "point_left::skin-tone-6": "👈🏿",
+ "point_right": "👉",
+ "point_right::skin-tone-2": "👉🏻",
+ "point_right::skin-tone-3": "👉🏼",
+ "point_right::skin-tone-4": "👉🏽",
+ "point_right::skin-tone-5": "👉🏾",
+ "point_right::skin-tone-6": "👉🏿",
+ "point_up_2": "👆",
+ "point_up_2::skin-tone-2": "👆🏻",
+ "point_up_2::skin-tone-3": "👆🏼",
+ "point_up_2::skin-tone-4": "👆🏽",
+ "point_up_2::skin-tone-5": "👆🏾",
+ "point_up_2::skin-tone-6": "👆🏿",
+ "middle_finger": "🖕",
+ "reversed_hand_with_middle_finger_extended": "🖕",
+ "middle_finger::skin-tone-2": "🖕🏻",
+ "reversed_hand_with_middle_finger_extended::skin-tone-2": "🖕🏻",
+ "middle_finger::skin-tone-3": "🖕🏼",
+ "reversed_hand_with_middle_finger_extended::skin-tone-3": "🖕🏼",
+ "middle_finger::skin-tone-4": "🖕🏽",
+ "reversed_hand_with_middle_finger_extended::skin-tone-4": "🖕🏽",
+ "middle_finger::skin-tone-5": "🖕🏾",
+ "reversed_hand_with_middle_finger_extended::skin-tone-5": "🖕🏾",
+ "middle_finger::skin-tone-6": "🖕🏿",
+ "reversed_hand_with_middle_finger_extended::skin-tone-6": "🖕🏿",
+ "point_down": "👇",
+ "point_down::skin-tone-2": "👇🏻",
+ "point_down::skin-tone-3": "👇🏼",
+ "point_down::skin-tone-4": "👇🏽",
+ "point_down::skin-tone-5": "👇🏾",
+ "point_down::skin-tone-6": "👇🏿",
+ "point_up": "☝️",
+ "point_up::skin-tone-2": "☝🏻",
+ "point_up::skin-tone-3": "☝🏼",
+ "point_up::skin-tone-4": "☝🏽",
+ "point_up::skin-tone-5": "☝🏾",
+ "point_up::skin-tone-6": "☝🏿",
+ "index_pointing_at_the_viewer": "🫵",
+ "index_pointing_at_the_viewer::skin-tone-2": "🫵🏻",
+ "index_pointing_at_the_viewer::skin-tone-3": "🫵🏼",
+ "index_pointing_at_the_viewer::skin-tone-4": "🫵🏽",
+ "index_pointing_at_the_viewer::skin-tone-5": "🫵🏾",
+ "index_pointing_at_the_viewer::skin-tone-6": "🫵🏿",
+ "+1": "👍",
+ "thumbsup": "👍",
+ "+1::skin-tone-2": "👍🏻",
+ "thumbsup::skin-tone-2": "👍🏻",
+ "+1::skin-tone-3": "👍🏼",
+ "thumbsup::skin-tone-3": "👍🏼",
+ "+1::skin-tone-4": "👍🏽",
+ "thumbsup::skin-tone-4": "👍🏽",
+ "+1::skin-tone-5": "👍🏾",
+ "thumbsup::skin-tone-5": "👍🏾",
+ "+1::skin-tone-6": "👍🏿",
+ "thumbsup::skin-tone-6": "👍🏿",
+ "-1": "👎",
+ "thumbsdown": "👎",
+ "-1::skin-tone-2": "👎🏻",
+ "thumbsdown::skin-tone-2": "👎🏻",
+ "-1::skin-tone-3": "👎🏼",
+ "thumbsdown::skin-tone-3": "👎🏼",
+ "-1::skin-tone-4": "👎🏽",
+ "thumbsdown::skin-tone-4": "👎🏽",
+ "-1::skin-tone-5": "👎🏾",
+ "thumbsdown::skin-tone-5": "👎🏾",
+ "-1::skin-tone-6": "👎🏿",
+ "thumbsdown::skin-tone-6": "👎🏿",
+ "fist": "✊",
+ "fist::skin-tone-2": "✊🏻",
+ "fist::skin-tone-3": "✊🏼",
+ "fist::skin-tone-4": "✊🏽",
+ "fist::skin-tone-5": "✊🏾",
+ "fist::skin-tone-6": "✊🏿",
+ "facepunch": "👊",
+ "punch": "👊",
+ "facepunch::skin-tone-2": "👊🏻",
+ "punch::skin-tone-2": "👊🏻",
+ "facepunch::skin-tone-3": "👊🏼",
+ "punch::skin-tone-3": "👊🏼",
+ "facepunch::skin-tone-4": "👊🏽",
+ "punch::skin-tone-4": "👊🏽",
+ "facepunch::skin-tone-5": "👊🏾",
+ "punch::skin-tone-5": "👊🏾",
+ "facepunch::skin-tone-6": "👊🏿",
+ "punch::skin-tone-6": "👊🏿",
+ "left-facing_fist": "🤛",
+ "left-facing_fist::skin-tone-2": "🤛🏻",
+ "left-facing_fist::skin-tone-3": "🤛🏼",
+ "left-facing_fist::skin-tone-4": "🤛🏽",
+ "left-facing_fist::skin-tone-5": "🤛🏾",
+ "left-facing_fist::skin-tone-6": "🤛🏿",
+ "right-facing_fist": "🤜",
+ "right-facing_fist::skin-tone-2": "🤜🏻",
+ "right-facing_fist::skin-tone-3": "🤜🏼",
+ "right-facing_fist::skin-tone-4": "🤜🏽",
+ "right-facing_fist::skin-tone-5": "🤜🏾",
+ "right-facing_fist::skin-tone-6": "🤜🏿",
+ "clap": "👏",
+ "clap::skin-tone-2": "👏🏻",
+ "clap::skin-tone-3": "👏🏼",
+ "clap::skin-tone-4": "👏🏽",
+ "clap::skin-tone-5": "👏🏾",
+ "clap::skin-tone-6": "👏🏿",
+ "raised_hands": "🙌",
+ "raised_hands::skin-tone-2": "🙌🏻",
+ "raised_hands::skin-tone-3": "🙌🏼",
+ "raised_hands::skin-tone-4": "🙌🏽",
+ "raised_hands::skin-tone-5": "🙌🏾",
+ "raised_hands::skin-tone-6": "🙌🏿",
+ "heart_hands": "🫶",
+ "heart_hands::skin-tone-2": "🫶🏻",
+ "heart_hands::skin-tone-3": "🫶🏼",
+ "heart_hands::skin-tone-4": "🫶🏽",
+ "heart_hands::skin-tone-5": "🫶🏾",
+ "heart_hands::skin-tone-6": "🫶🏿",
+ "open_hands": "👐",
+ "open_hands::skin-tone-2": "👐🏻",
+ "open_hands::skin-tone-3": "👐🏼",
+ "open_hands::skin-tone-4": "👐🏽",
+ "open_hands::skin-tone-5": "👐🏾",
+ "open_hands::skin-tone-6": "👐🏿",
+ "palms_up_together": "🤲",
+ "palms_up_together::skin-tone-2": "🤲🏻",
+ "palms_up_together::skin-tone-3": "🤲🏼",
+ "palms_up_together::skin-tone-4": "🤲🏽",
+ "palms_up_together::skin-tone-5": "🤲🏾",
+ "palms_up_together::skin-tone-6": "🤲🏿",
+ "handshake": "🤝",
+ "handshake::skin-tone-2": "🤝🏻",
+ "handshake::skin-tone-3": "🤝🏼",
+ "handshake::skin-tone-4": "🤝🏽",
+ "handshake::skin-tone-5": "🤝🏾",
+ "handshake::skin-tone-6": "🤝🏿",
+ "pray": "🙏",
+ "pray::skin-tone-2": "🙏🏻",
+ "pray::skin-tone-3": "🙏🏼",
+ "pray::skin-tone-4": "🙏🏽",
+ "pray::skin-tone-5": "🙏🏾",
+ "pray::skin-tone-6": "🙏🏿",
+ "writing_hand": "✍️",
+ "writing_hand::skin-tone-2": "✍🏻",
+ "writing_hand::skin-tone-3": "✍🏼",
+ "writing_hand::skin-tone-4": "✍🏽",
+ "writing_hand::skin-tone-5": "✍🏾",
+ "writing_hand::skin-tone-6": "✍🏿",
+ "nail_care": "💅",
+ "nail_care::skin-tone-2": "💅🏻",
+ "nail_care::skin-tone-3": "💅🏼",
+ "nail_care::skin-tone-4": "💅🏽",
+ "nail_care::skin-tone-5": "💅🏾",
+ "nail_care::skin-tone-6": "💅🏿",
+ "selfie": "🤳",
+ "selfie::skin-tone-2": "🤳🏻",
+ "selfie::skin-tone-3": "🤳🏼",
+ "selfie::skin-tone-4": "🤳🏽",
+ "selfie::skin-tone-5": "🤳🏾",
+ "selfie::skin-tone-6": "🤳🏿",
+ "muscle": "💪",
+ "muscle::skin-tone-2": "💪🏻",
+ "muscle::skin-tone-3": "💪🏼",
+ "muscle::skin-tone-4": "💪🏽",
+ "muscle::skin-tone-5": "💪🏾",
+ "muscle::skin-tone-6": "💪🏿",
+ "mechanical_arm": "🦾",
+ "mechanical_leg": "🦿",
+ "leg": "🦵",
+ "leg::skin-tone-2": "🦵🏻",
+ "leg::skin-tone-3": "🦵🏼",
+ "leg::skin-tone-4": "🦵🏽",
+ "leg::skin-tone-5": "🦵🏾",
+ "leg::skin-tone-6": "🦵🏿",
+ "foot": "🦶",
+ "foot::skin-tone-2": "🦶🏻",
+ "foot::skin-tone-3": "🦶🏼",
+ "foot::skin-tone-4": "🦶🏽",
+ "foot::skin-tone-5": "🦶🏾",
+ "foot::skin-tone-6": "🦶🏿",
+ "ear": "👂",
+ "ear::skin-tone-2": "👂🏻",
+ "ear::skin-tone-3": "👂🏼",
+ "ear::skin-tone-4": "👂🏽",
+ "ear::skin-tone-5": "👂🏾",
+ "ear::skin-tone-6": "👂🏿",
+ "ear_with_hearing_aid": "🦻",
+ "ear_with_hearing_aid::skin-tone-2": "🦻🏻",
+ "ear_with_hearing_aid::skin-tone-3": "🦻🏼",
+ "ear_with_hearing_aid::skin-tone-4": "🦻🏽",
+ "ear_with_hearing_aid::skin-tone-5": "🦻🏾",
+ "ear_with_hearing_aid::skin-tone-6": "🦻🏿",
+ "nose": "👃",
+ "nose::skin-tone-2": "👃🏻",
+ "nose::skin-tone-3": "👃🏼",
+ "nose::skin-tone-4": "👃🏽",
+ "nose::skin-tone-5": "👃🏾",
+ "nose::skin-tone-6": "👃🏿",
+ "brain": "🧠",
+ "anatomical_heart": "🫀",
+ "lungs": "🫁",
+ "tooth": "🦷",
+ "bone": "🦴",
+ "eyes": "👀",
+ "dag-eyes": "👀",
+ "eye": "👁️",
+ "tongue": "👅",
+ "lips": "👄",
+ "biting_lip": "🫦",
+ "baby": "👶",
+ "baby::skin-tone-2": "👶🏻",
+ "baby::skin-tone-3": "👶🏼",
+ "baby::skin-tone-4": "👶🏽",
+ "baby::skin-tone-5": "👶🏾",
+ "baby::skin-tone-6": "👶🏿",
+ "child": "🧒",
+ "child::skin-tone-2": "🧒🏻",
+ "child::skin-tone-3": "🧒🏼",
+ "child::skin-tone-4": "🧒🏽",
+ "child::skin-tone-5": "🧒🏾",
+ "child::skin-tone-6": "🧒🏿",
+ "boy": "👦",
+ "boy::skin-tone-2": "👦🏻",
+ "boy::skin-tone-3": "👦🏼",
+ "boy::skin-tone-4": "👦🏽",
+ "boy::skin-tone-5": "👦🏾",
+ "boy::skin-tone-6": "👦🏿",
+ "girl": "👧",
+ "girl::skin-tone-2": "👧🏻",
+ "girl::skin-tone-3": "👧🏼",
+ "girl::skin-tone-4": "👧🏽",
+ "girl::skin-tone-5": "👧🏾",
+ "girl::skin-tone-6": "👧🏿",
+ "adult": "🧑",
+ "adult::skin-tone-2": "🧑🏻",
+ "adult::skin-tone-3": "🧑🏼",
+ "adult::skin-tone-4": "🧑🏽",
+ "adult::skin-tone-5": "🧑🏾",
+ "adult::skin-tone-6": "🧑🏿",
+ "person_with_blond_hair": "👱",
+ "person_with_blond_hair::skin-tone-2": "👱🏻",
+ "person_with_blond_hair::skin-tone-3": "👱🏼",
+ "person_with_blond_hair::skin-tone-4": "👱🏽",
+ "person_with_blond_hair::skin-tone-5": "👱🏾",
+ "person_with_blond_hair::skin-tone-6": "👱🏿",
+ "man": "👨",
+ "man::skin-tone-2": "👨🏻",
+ "man::skin-tone-3": "👨🏼",
+ "man::skin-tone-4": "👨🏽",
+ "man::skin-tone-5": "👨🏾",
+ "man::skin-tone-6": "👨🏿",
+ "bearded_person": "🧔",
+ "bearded_person::skin-tone-2": "🧔🏻",
+ "bearded_person::skin-tone-3": "🧔🏼",
+ "bearded_person::skin-tone-4": "🧔🏽",
+ "bearded_person::skin-tone-5": "🧔🏾",
+ "bearded_person::skin-tone-6": "🧔🏿",
+ "man_with_beard": "🧔‍♂️",
+ "man_with_beard::skin-tone-2": "🧔🏻‍♂️",
+ "man_with_beard::skin-tone-3": "🧔🏼‍♂️",
+ "man_with_beard::skin-tone-4": "🧔🏽‍♂️",
+ "man_with_beard::skin-tone-5": "🧔🏾‍♂️",
+ "man_with_beard::skin-tone-6": "🧔🏿‍♂️",
+ "woman_with_beard": "🧔‍♀️",
+ "woman_with_beard::skin-tone-2": "🧔🏻‍♀️",
+ "woman_with_beard::skin-tone-3": "🧔🏼‍♀️",
+ "woman_with_beard::skin-tone-4": "🧔🏽‍♀️",
+ "woman_with_beard::skin-tone-5": "🧔🏾‍♀️",
+ "woman_with_beard::skin-tone-6": "🧔🏿‍♀️",
+ "red_haired_man": "👨‍🦰",
+ "red_haired_man::skin-tone-2": "👨🏻‍🦰",
+ "red_haired_man::skin-tone-3": "👨🏼‍🦰",
+ "red_haired_man::skin-tone-4": "👨🏽‍🦰",
+ "red_haired_man::skin-tone-5": "👨🏾‍🦰",
+ "red_haired_man::skin-tone-6": "👨🏿‍🦰",
+ "curly_haired_man": "👨‍🦱",
+ "curly_haired_man::skin-tone-2": "👨🏻‍🦱",
+ "curly_haired_man::skin-tone-3": "👨🏼‍🦱",
+ "curly_haired_man::skin-tone-4": "👨🏽‍🦱",
+ "curly_haired_man::skin-tone-5": "👨🏾‍🦱",
+ "curly_haired_man::skin-tone-6": "👨🏿‍🦱",
+ "white_haired_man": "👨‍🦳",
+ "white_haired_man::skin-tone-2": "👨🏻‍🦳",
+ "white_haired_man::skin-tone-3": "👨🏼‍🦳",
+ "white_haired_man::skin-tone-4": "👨🏽‍🦳",
+ "white_haired_man::skin-tone-5": "👨🏾‍🦳",
+ "white_haired_man::skin-tone-6": "👨🏿‍🦳",
+ "bald_man": "👨‍🦲",
+ "bald_man::skin-tone-2": "👨🏻‍🦲",
+ "bald_man::skin-tone-3": "👨🏼‍🦲",
+ "bald_man::skin-tone-4": "👨🏽‍🦲",
+ "bald_man::skin-tone-5": "👨🏾‍🦲",
+ "bald_man::skin-tone-6": "👨🏿‍🦲",
+ "woman": "👩",
+ "woman::skin-tone-2": "👩🏻",
+ "woman::skin-tone-3": "👩🏼",
+ "woman::skin-tone-4": "👩🏽",
+ "woman::skin-tone-5": "👩🏾",
+ "woman::skin-tone-6": "👩🏿",
+ "red_haired_woman": "👩‍🦰",
+ "red_haired_woman::skin-tone-2": "👩🏻‍🦰",
+ "red_haired_woman::skin-tone-3": "👩🏼‍🦰",
+ "red_haired_woman::skin-tone-4": "👩🏽‍🦰",
+ "red_haired_woman::skin-tone-5": "👩🏾‍🦰",
+ "red_haired_woman::skin-tone-6": "👩🏿‍🦰",
+ "red_haired_person": "🧑‍🦰",
+ "red_haired_person::skin-tone-2": "🧑🏻‍🦰",
+ "red_haired_person::skin-tone-3": "🧑🏼‍🦰",
+ "red_haired_person::skin-tone-4": "🧑🏽‍🦰",
+ "red_haired_person::skin-tone-5": "🧑🏾‍🦰",
+ "red_haired_person::skin-tone-6": "🧑🏿‍🦰",
+ "curly_haired_woman": "👩‍🦱",
+ "curly_haired_woman::skin-tone-2": "👩🏻‍🦱",
+ "curly_haired_woman::skin-tone-3": "👩🏼‍🦱",
+ "curly_haired_woman::skin-tone-4": "👩🏽‍🦱",
+ "curly_haired_woman::skin-tone-5": "👩🏾‍🦱",
+ "curly_haired_woman::skin-tone-6": "👩🏿‍🦱",
+ "curly_haired_person": "🧑‍🦱",
+ "curly_haired_person::skin-tone-2": "🧑🏻‍🦱",
+ "curly_haired_person::skin-tone-3": "🧑🏼‍🦱",
+ "curly_haired_person::skin-tone-4": "🧑🏽‍🦱",
+ "curly_haired_person::skin-tone-5": "🧑🏾‍🦱",
+ "curly_haired_person::skin-tone-6": "🧑🏿‍🦱",
+ "white_haired_woman": "👩‍🦳",
+ "white_haired_woman::skin-tone-2": "👩🏻‍🦳",
+ "white_haired_woman::skin-tone-3": "👩🏼‍🦳",
+ "white_haired_woman::skin-tone-4": "👩🏽‍🦳",
+ "white_haired_woman::skin-tone-5": "👩🏾‍🦳",
+ "white_haired_woman::skin-tone-6": "👩🏿‍🦳",
+ "white_haired_person": "🧑‍🦳",
+ "white_haired_person::skin-tone-2": "🧑🏻‍🦳",
+ "white_haired_person::skin-tone-3": "🧑🏼‍🦳",
+ "white_haired_person::skin-tone-4": "🧑🏽‍🦳",
+ "white_haired_person::skin-tone-5": "🧑🏾‍🦳",
+ "white_haired_person::skin-tone-6": "🧑🏿‍🦳",
+ "bald_woman": "👩‍🦲",
+ "bald_woman::skin-tone-2": "👩🏻‍🦲",
+ "bald_woman::skin-tone-3": "👩🏼‍🦲",
+ "bald_woman::skin-tone-4": "👩🏽‍🦲",
+ "bald_woman::skin-tone-5": "👩🏾‍🦲",
+ "bald_woman::skin-tone-6": "👩🏿‍🦲",
+ "bald_person": "🧑‍🦲",
+ "bald_person::skin-tone-2": "🧑🏻‍🦲",
+ "bald_person::skin-tone-3": "🧑🏼‍🦲",
+ "bald_person::skin-tone-4": "🧑🏽‍🦲",
+ "bald_person::skin-tone-5": "🧑🏾‍🦲",
+ "bald_person::skin-tone-6": "🧑🏿‍🦲",
+ "blond-haired-woman": "👱‍♀️",
+ "blond-haired-woman::skin-tone-2": "👱🏻‍♀️",
+ "blond-haired-woman::skin-tone-3": "👱🏼‍♀️",
+ "blond-haired-woman::skin-tone-4": "👱🏽‍♀️",
+ "blond-haired-woman::skin-tone-5": "👱🏾‍♀️",
+ "blond-haired-woman::skin-tone-6": "👱🏿‍♀️",
+ "blond-haired-man": "👱‍♂️",
+ "blond-haired-man::skin-tone-2": "👱🏻‍♂️",
+ "blond-haired-man::skin-tone-3": "👱🏼‍♂️",
+ "blond-haired-man::skin-tone-4": "👱🏽‍♂️",
+ "blond-haired-man::skin-tone-5": "👱🏾‍♂️",
+ "blond-haired-man::skin-tone-6": "👱🏿‍♂️",
+ "older_adult": "🧓",
+ "older_adult::skin-tone-2": "🧓🏻",
+ "older_adult::skin-tone-3": "🧓🏼",
+ "older_adult::skin-tone-4": "🧓🏽",
+ "older_adult::skin-tone-5": "🧓🏾",
+ "older_adult::skin-tone-6": "🧓🏿",
+ "older_man": "👴",
+ "older_man::skin-tone-2": "👴🏻",
+ "older_man::skin-tone-3": "👴🏼",
+ "older_man::skin-tone-4": "👴🏽",
+ "older_man::skin-tone-5": "👴🏾",
+ "older_man::skin-tone-6": "👴🏿",
+ "older_woman": "👵",
+ "older_woman::skin-tone-2": "👵🏻",
+ "older_woman::skin-tone-3": "👵🏼",
+ "older_woman::skin-tone-4": "👵🏽",
+ "older_woman::skin-tone-5": "👵🏾",
+ "older_woman::skin-tone-6": "👵🏿",
+ "person_frowning": "🙍",
+ "person_frowning::skin-tone-2": "🙍🏻",
+ "person_frowning::skin-tone-3": "🙍🏼",
+ "person_frowning::skin-tone-4": "🙍🏽",
+ "person_frowning::skin-tone-5": "🙍🏾",
+ "person_frowning::skin-tone-6": "🙍🏿",
+ "man-frowning": "🙍‍♂️",
+ "man-frowning::skin-tone-2": "🙍🏻‍♂️",
+ "man-frowning::skin-tone-3": "🙍🏼‍♂️",
+ "man-frowning::skin-tone-4": "🙍🏽‍♂️",
+ "man-frowning::skin-tone-5": "🙍🏾‍♂️",
+ "man-frowning::skin-tone-6": "🙍🏿‍♂️",
+ "woman-frowning": "🙍‍♀️",
+ "woman-frowning::skin-tone-2": "🙍🏻‍♀️",
+ "woman-frowning::skin-tone-3": "🙍🏼‍♀️",
+ "woman-frowning::skin-tone-4": "🙍🏽‍♀️",
+ "woman-frowning::skin-tone-5": "🙍🏾‍♀️",
+ "woman-frowning::skin-tone-6": "🙍🏿‍♀️",
+ "person_with_pouting_face": "🙎",
+ "person_with_pouting_face::skin-tone-2": "🙎🏻",
+ "person_with_pouting_face::skin-tone-3": "🙎🏼",
+ "person_with_pouting_face::skin-tone-4": "🙎🏽",
+ "person_with_pouting_face::skin-tone-5": "🙎🏾",
+ "person_with_pouting_face::skin-tone-6": "🙎🏿",
+ "man-pouting": "🙎‍♂️",
+ "man-pouting::skin-tone-2": "🙎🏻‍♂️",
+ "man-pouting::skin-tone-3": "🙎🏼‍♂️",
+ "man-pouting::skin-tone-4": "🙎🏽‍♂️",
+ "man-pouting::skin-tone-5": "🙎🏾‍♂️",
+ "man-pouting::skin-tone-6": "🙎🏿‍♂️",
+ "woman-pouting": "🙎‍♀️",
+ "woman-pouting::skin-tone-2": "🙎🏻‍♀️",
+ "woman-pouting::skin-tone-3": "🙎🏼‍♀️",
+ "woman-pouting::skin-tone-4": "🙎🏽‍♀️",
+ "woman-pouting::skin-tone-5": "🙎🏾‍♀️",
+ "woman-pouting::skin-tone-6": "🙎🏿‍♀️",
+ "no_good": "🙅",
+ "no_good::skin-tone-2": "🙅🏻",
+ "no_good::skin-tone-3": "🙅🏼",
+ "no_good::skin-tone-4": "🙅🏽",
+ "no_good::skin-tone-5": "🙅🏾",
+ "no_good::skin-tone-6": "🙅🏿",
+ "man-gesturing-no": "🙅‍♂️",
+ "man-gesturing-no::skin-tone-2": "🙅🏻‍♂️",
+ "man-gesturing-no::skin-tone-3": "🙅🏼‍♂️",
+ "man-gesturing-no::skin-tone-4": "🙅🏽‍♂️",
+ "man-gesturing-no::skin-tone-5": "🙅🏾‍♂️",
+ "man-gesturing-no::skin-tone-6": "🙅🏿‍♂️",
+ "woman-gesturing-no": "🙅‍♀️",
+ "woman-gesturing-no::skin-tone-2": "🙅🏻‍♀️",
+ "woman-gesturing-no::skin-tone-3": "🙅🏼‍♀️",
+ "woman-gesturing-no::skin-tone-4": "🙅🏽‍♀️",
+ "woman-gesturing-no::skin-tone-5": "🙅🏾‍♀️",
+ "woman-gesturing-no::skin-tone-6": "🙅🏿‍♀️",
+ "ok_woman": "🙆",
+ "ok_woman::skin-tone-2": "🙆🏻",
+ "ok_woman::skin-tone-3": "🙆🏼",
+ "ok_woman::skin-tone-4": "🙆🏽",
+ "ok_woman::skin-tone-5": "🙆🏾",
+ "ok_woman::skin-tone-6": "🙆🏿",
+ "man-gesturing-ok": "🙆‍♂️",
+ "man-gesturing-ok::skin-tone-2": "🙆🏻‍♂️",
+ "man-gesturing-ok::skin-tone-3": "🙆🏼‍♂️",
+ "man-gesturing-ok::skin-tone-4": "🙆🏽‍♂️",
+ "man-gesturing-ok::skin-tone-5": "🙆🏾‍♂️",
+ "man-gesturing-ok::skin-tone-6": "🙆🏿‍♂️",
+ "woman-gesturing-ok": "🙆‍♀️",
+ "woman-gesturing-ok::skin-tone-2": "🙆🏻‍♀️",
+ "woman-gesturing-ok::skin-tone-3": "🙆🏼‍♀️",
+ "woman-gesturing-ok::skin-tone-4": "🙆🏽‍♀️",
+ "woman-gesturing-ok::skin-tone-5": "🙆🏾‍♀️",
+ "woman-gesturing-ok::skin-tone-6": "🙆🏿‍♀️",
+ "information_desk_person": "💁",
+ "information_desk_person::skin-tone-2": "💁🏻",
+ "information_desk_person::skin-tone-3": "💁🏼",
+ "information_desk_person::skin-tone-4": "💁🏽",
+ "information_desk_person::skin-tone-5": "💁🏾",
+ "information_desk_person::skin-tone-6": "💁🏿",
+ "man-tipping-hand": "💁‍♂️",
+ "man-tipping-hand::skin-tone-2": "💁🏻‍♂️",
+ "man-tipping-hand::skin-tone-3": "💁🏼‍♂️",
+ "man-tipping-hand::skin-tone-4": "💁🏽‍♂️",
+ "man-tipping-hand::skin-tone-5": "💁🏾‍♂️",
+ "man-tipping-hand::skin-tone-6": "💁🏿‍♂️",
+ "woman-tipping-hand": "💁‍♀️",
+ "woman-tipping-hand::skin-tone-2": "💁🏻‍♀️",
+ "woman-tipping-hand::skin-tone-3": "💁🏼‍♀️",
+ "woman-tipping-hand::skin-tone-4": "💁🏽‍♀️",
+ "woman-tipping-hand::skin-tone-5": "💁🏾‍♀️",
+ "woman-tipping-hand::skin-tone-6": "💁🏿‍♀️",
+ "raising_hand": "🙋",
+ "raising_hand::skin-tone-2": "🙋🏻",
+ "raising_hand::skin-tone-3": "🙋🏼",
+ "raising_hand::skin-tone-4": "🙋🏽",
+ "raising_hand::skin-tone-5": "🙋🏾",
+ "raising_hand::skin-tone-6": "🙋🏿",
+ "man-raising-hand": "🙋‍♂️",
+ "man-raising-hand::skin-tone-2": "🙋🏻‍♂️",
+ "man-raising-hand::skin-tone-3": "🙋🏼‍♂️",
+ "man-raising-hand::skin-tone-4": "🙋🏽‍♂️",
+ "man-raising-hand::skin-tone-5": "🙋🏾‍♂️",
+ "man-raising-hand::skin-tone-6": "🙋🏿‍♂️",
+ "woman-raising-hand": "🙋‍♀️",
+ "woman-raising-hand::skin-tone-2": "🙋🏻‍♀️",
+ "woman-raising-hand::skin-tone-3": "🙋🏼‍♀️",
+ "woman-raising-hand::skin-tone-4": "🙋🏽‍♀️",
+ "woman-raising-hand::skin-tone-5": "🙋🏾‍♀️",
+ "woman-raising-hand::skin-tone-6": "🙋🏿‍♀️",
+ "deaf_person": "🧏",
+ "deaf_person::skin-tone-2": "🧏🏻",
+ "deaf_person::skin-tone-3": "🧏🏼",
+ "deaf_person::skin-tone-4": "🧏🏽",
+ "deaf_person::skin-tone-5": "🧏🏾",
+ "deaf_person::skin-tone-6": "🧏🏿",
+ "deaf_man": "🧏‍♂️",
+ "deaf_man::skin-tone-2": "🧏🏻‍♂️",
+ "deaf_man::skin-tone-3": "🧏🏼‍♂️",
+ "deaf_man::skin-tone-4": "🧏🏽‍♂️",
+ "deaf_man::skin-tone-5": "🧏🏾‍♂️",
+ "deaf_man::skin-tone-6": "🧏🏿‍♂️",
+ "deaf_woman": "🧏‍♀️",
+ "deaf_woman::skin-tone-2": "🧏🏻‍♀️",
+ "deaf_woman::skin-tone-3": "🧏🏼‍♀️",
+ "deaf_woman::skin-tone-4": "🧏🏽‍♀️",
+ "deaf_woman::skin-tone-5": "🧏🏾‍♀️",
+ "deaf_woman::skin-tone-6": "🧏🏿‍♀️",
+ "nod-nicholson": "🙇",
+ "daggy-celebrate": "🎉",
+ "bow": "🙇",
+ "bow::skin-tone-2": "🙇🏻",
+ "bow::skin-tone-3": "🙇🏼",
+ "bow::skin-tone-4": "🙇🏽",
+ "bow::skin-tone-5": "🙇🏾",
+ "bow::skin-tone-6": "🙇🏿",
+ "man-bowing": "🙇‍♂️",
+ "man-bowing::skin-tone-2": "🙇🏻‍♂️",
+ "man-bowing::skin-tone-3": "🙇🏼‍♂️",
+ "man-bowing::skin-tone-4": "🙇🏽‍♂️",
+ "man-bowing::skin-tone-5": "🙇🏾‍♂️",
+ "man-bowing::skin-tone-6": "🙇🏿‍♂️",
+ "woman-bowing": "🙇‍♀️",
+ "woman-bowing::skin-tone-2": "🙇🏻‍♀️",
+ "woman-bowing::skin-tone-3": "🙇🏼‍♀️",
+ "woman-bowing::skin-tone-4": "🙇🏽‍♀️",
+ "woman-bowing::skin-tone-5": "🙇🏾‍♀️",
+ "woman-bowing::skin-tone-6": "🙇🏿‍♀️",
+ "face_palm": "🤦",
+ "face_palm::skin-tone-2": "🤦🏻",
+ "face_palm::skin-tone-3": "🤦🏼",
+ "face_palm::skin-tone-4": "🤦🏽",
+ "face_palm::skin-tone-5": "🤦🏾",
+ "face_palm::skin-tone-6": "🤦🏿",
+ "man-facepalming": "🤦‍♂️",
+ "man-facepalming::skin-tone-2": "🤦🏻‍♂️",
+ "man-facepalming::skin-tone-3": "🤦🏼‍♂️",
+ "man-facepalming::skin-tone-4": "🤦🏽‍♂️",
+ "man-facepalming::skin-tone-5": "🤦🏾‍♂️",
+ "man-facepalming::skin-tone-6": "🤦🏿‍♂️",
+ "woman-facepalming": "🤦‍♀️",
+ "woman-facepalming::skin-tone-2": "🤦🏻‍♀️",
+ "woman-facepalming::skin-tone-3": "🤦🏼‍♀️",
+ "woman-facepalming::skin-tone-4": "🤦🏽‍♀️",
+ "woman-facepalming::skin-tone-5": "🤦🏾‍♀️",
+ "woman-facepalming::skin-tone-6": "🤦🏿‍♀️",
+ "shrug": "🤷",
+ "shrug::skin-tone-2": "🤷🏻",
+ "shrug::skin-tone-3": "🤷🏼",
+ "shrug::skin-tone-4": "🤷🏽",
+ "shrug::skin-tone-5": "🤷🏾",
+ "shrug::skin-tone-6": "🤷🏿",
+ "man-shrugging": "🤷‍♂️",
+ "man-shrugging::skin-tone-2": "🤷🏻‍♂️",
+ "man-shrugging::skin-tone-3": "🤷🏼‍♂️",
+ "man-shrugging::skin-tone-4": "🤷🏽‍♂️",
+ "man-shrugging::skin-tone-5": "🤷🏾‍♂️",
+ "man-shrugging::skin-tone-6": "🤷🏿‍♂️",
+ "woman-shrugging": "🤷‍♀️",
+ "woman-shrugging::skin-tone-2": "🤷🏻‍♀️",
+ "woman-shrugging::skin-tone-3": "🤷🏼‍♀️",
+ "woman-shrugging::skin-tone-4": "🤷🏽‍♀️",
+ "woman-shrugging::skin-tone-5": "🤷🏾‍♀️",
+ "woman-shrugging::skin-tone-6": "🤷🏿‍♀️",
+ "health_worker": "🧑‍⚕️",
+ "health_worker::skin-tone-2": "🧑🏻‍⚕️",
+ "health_worker::skin-tone-3": "🧑🏼‍⚕️",
+ "health_worker::skin-tone-4": "🧑🏽‍⚕️",
+ "health_worker::skin-tone-5": "🧑🏾‍⚕️",
+ "health_worker::skin-tone-6": "🧑🏿‍⚕️",
+ "male-doctor": "👨‍⚕️",
+ "male-doctor::skin-tone-2": "👨🏻‍⚕️",
+ "male-doctor::skin-tone-3": "👨🏼‍⚕️",
+ "male-doctor::skin-tone-4": "👨🏽‍⚕️",
+ "male-doctor::skin-tone-5": "👨🏾‍⚕️",
+ "male-doctor::skin-tone-6": "👨🏿‍⚕️",
+ "female-doctor": "👩‍⚕️",
+ "female-doctor::skin-tone-2": "👩🏻‍⚕️",
+ "female-doctor::skin-tone-3": "👩🏼‍⚕️",
+ "female-doctor::skin-tone-4": "👩🏽‍⚕️",
+ "female-doctor::skin-tone-5": "👩🏾‍⚕️",
+ "female-doctor::skin-tone-6": "👩🏿‍⚕️",
+ "student": "🧑‍🎓",
+ "student::skin-tone-2": "🧑🏻‍🎓",
+ "student::skin-tone-3": "🧑🏼‍🎓",
+ "student::skin-tone-4": "🧑🏽‍🎓",
+ "student::skin-tone-5": "🧑🏾‍🎓",
+ "student::skin-tone-6": "🧑🏿‍🎓",
+ "male-student": "👨‍🎓",
+ "male-student::skin-tone-2": "👨🏻‍🎓",
+ "male-student::skin-tone-3": "👨🏼‍🎓",
+ "male-student::skin-tone-4": "👨🏽‍🎓",
+ "male-student::skin-tone-5": "👨🏾‍🎓",
+ "male-student::skin-tone-6": "👨🏿‍🎓",
+ "female-student": "👩‍🎓",
+ "female-student::skin-tone-2": "👩🏻‍🎓",
+ "female-student::skin-tone-3": "👩🏼‍🎓",
+ "female-student::skin-tone-4": "👩🏽‍🎓",
+ "female-student::skin-tone-5": "👩🏾‍🎓",
+ "female-student::skin-tone-6": "👩🏿‍🎓",
+ "teacher": "🧑‍🏫",
+ "teacher::skin-tone-2": "🧑🏻‍🏫",
+ "teacher::skin-tone-3": "🧑🏼‍🏫",
+ "teacher::skin-tone-4": "🧑🏽‍🏫",
+ "teacher::skin-tone-5": "🧑🏾‍🏫",
+ "teacher::skin-tone-6": "🧑🏿‍🏫",
+ "male-teacher": "👨‍🏫",
+ "male-teacher::skin-tone-2": "👨🏻‍🏫",
+ "male-teacher::skin-tone-3": "👨🏼‍🏫",
+ "male-teacher::skin-tone-4": "👨🏽‍🏫",
+ "male-teacher::skin-tone-5": "👨🏾‍🏫",
+ "male-teacher::skin-tone-6": "👨🏿‍🏫",
+ "female-teacher": "👩‍🏫",
+ "female-teacher::skin-tone-2": "👩🏻‍🏫",
+ "female-teacher::skin-tone-3": "👩🏼‍🏫",
+ "female-teacher::skin-tone-4": "👩🏽‍🏫",
+ "female-teacher::skin-tone-5": "👩🏾‍🏫",
+ "female-teacher::skin-tone-6": "👩🏿‍🏫",
+ "judge": "🧑‍⚖️",
+ "judge::skin-tone-2": "🧑🏻‍⚖️",
+ "judge::skin-tone-3": "🧑🏼‍⚖️",
+ "judge::skin-tone-4": "🧑🏽‍⚖️",
+ "judge::skin-tone-5": "🧑🏾‍⚖️",
+ "judge::skin-tone-6": "🧑🏿‍⚖️",
+ "male-judge": "👨‍⚖️",
+ "male-judge::skin-tone-2": "👨🏻‍⚖️",
+ "male-judge::skin-tone-3": "👨🏼‍⚖️",
+ "male-judge::skin-tone-4": "👨🏽‍⚖️",
+ "male-judge::skin-tone-5": "👨🏾‍⚖️",
+ "male-judge::skin-tone-6": "👨🏿‍⚖️",
+ "female-judge": "👩‍⚖️",
+ "female-judge::skin-tone-2": "👩🏻‍⚖️",
+ "female-judge::skin-tone-3": "👩🏼‍⚖️",
+ "female-judge::skin-tone-4": "👩🏽‍⚖️",
+ "female-judge::skin-tone-5": "👩🏾‍⚖️",
+ "female-judge::skin-tone-6": "👩🏿‍⚖️",
+ "farmer": "🧑‍🌾",
+ "farmer::skin-tone-2": "🧑🏻‍🌾",
+ "farmer::skin-tone-3": "🧑🏼‍🌾",
+ "farmer::skin-tone-4": "🧑🏽‍🌾",
+ "farmer::skin-tone-5": "🧑🏾‍🌾",
+ "farmer::skin-tone-6": "🧑🏿‍🌾",
+ "male-farmer": "👨‍🌾",
+ "male-farmer::skin-tone-2": "👨🏻‍🌾",
+ "male-farmer::skin-tone-3": "👨🏼‍🌾",
+ "male-farmer::skin-tone-4": "👨🏽‍🌾",
+ "male-farmer::skin-tone-5": "👨🏾‍🌾",
+ "male-farmer::skin-tone-6": "👨🏿‍🌾",
+ "female-farmer": "👩‍🌾",
+ "female-farmer::skin-tone-2": "👩🏻‍🌾",
+ "female-farmer::skin-tone-3": "👩🏼‍🌾",
+ "female-farmer::skin-tone-4": "👩🏽‍🌾",
+ "female-farmer::skin-tone-5": "👩🏾‍🌾",
+ "female-farmer::skin-tone-6": "👩🏿‍🌾",
+ "cook": "🧑‍🍳",
+ "cook::skin-tone-2": "🧑🏻‍🍳",
+ "cook::skin-tone-3": "🧑🏼‍🍳",
+ "cook::skin-tone-4": "🧑🏽‍🍳",
+ "cook::skin-tone-5": "🧑🏾‍🍳",
+ "cook::skin-tone-6": "🧑🏿‍🍳",
+ "male-cook": "👨‍🍳",
+ "male-cook::skin-tone-2": "👨🏻‍🍳",
+ "male-cook::skin-tone-3": "👨🏼‍🍳",
+ "male-cook::skin-tone-4": "👨🏽‍🍳",
+ "male-cook::skin-tone-5": "👨🏾‍🍳",
+ "male-cook::skin-tone-6": "👨🏿‍🍳",
+ "female-cook": "👩‍🍳",
+ "female-cook::skin-tone-2": "👩🏻‍🍳",
+ "female-cook::skin-tone-3": "👩🏼‍🍳",
+ "female-cook::skin-tone-4": "👩🏽‍🍳",
+ "female-cook::skin-tone-5": "👩🏾‍🍳",
+ "female-cook::skin-tone-6": "👩🏿‍🍳",
+ "mechanic": "🧑‍🔧",
+ "mechanic::skin-tone-2": "🧑🏻‍🔧",
+ "mechanic::skin-tone-3": "🧑🏼‍🔧",
+ "mechanic::skin-tone-4": "🧑🏽‍🔧",
+ "mechanic::skin-tone-5": "🧑🏾‍🔧",
+ "mechanic::skin-tone-6": "🧑🏿‍🔧",
+ "male-mechanic": "👨‍🔧",
+ "male-mechanic::skin-tone-2": "👨🏻‍🔧",
+ "male-mechanic::skin-tone-3": "👨🏼‍🔧",
+ "male-mechanic::skin-tone-4": "👨🏽‍🔧",
+ "male-mechanic::skin-tone-5": "👨🏾‍🔧",
+ "male-mechanic::skin-tone-6": "👨🏿‍🔧",
+ "female-mechanic": "👩‍🔧",
+ "female-mechanic::skin-tone-2": "👩🏻‍🔧",
+ "female-mechanic::skin-tone-3": "👩🏼‍🔧",
+ "female-mechanic::skin-tone-4": "👩🏽‍🔧",
+ "female-mechanic::skin-tone-5": "👩🏾‍🔧",
+ "female-mechanic::skin-tone-6": "👩🏿‍🔧",
+ "factory_worker": "🧑‍🏭",
+ "factory_worker::skin-tone-2": "🧑🏻‍🏭",
+ "factory_worker::skin-tone-3": "🧑🏼‍🏭",
+ "factory_worker::skin-tone-4": "🧑🏽‍🏭",
+ "factory_worker::skin-tone-5": "🧑🏾‍🏭",
+ "factory_worker::skin-tone-6": "🧑🏿‍🏭",
+ "male-factory-worker": "👨‍🏭",
+ "male-factory-worker::skin-tone-2": "👨🏻‍🏭",
+ "male-factory-worker::skin-tone-3": "👨🏼‍🏭",
+ "male-factory-worker::skin-tone-4": "👨🏽‍🏭",
+ "male-factory-worker::skin-tone-5": "👨🏾‍🏭",
+ "male-factory-worker::skin-tone-6": "👨🏿‍🏭",
+ "female-factory-worker": "👩‍🏭",
+ "female-factory-worker::skin-tone-2": "👩🏻‍🏭",
+ "female-factory-worker::skin-tone-3": "👩🏼‍🏭",
+ "female-factory-worker::skin-tone-4": "👩🏽‍🏭",
+ "female-factory-worker::skin-tone-5": "👩🏾‍🏭",
+ "female-factory-worker::skin-tone-6": "👩🏿‍🏭",
+ "office_worker": "🧑‍💼",
+ "office_worker::skin-tone-2": "🧑🏻‍💼",
+ "office_worker::skin-tone-3": "🧑🏼‍💼",
+ "office_worker::skin-tone-4": "🧑🏽‍💼",
+ "office_worker::skin-tone-5": "🧑🏾‍💼",
+ "office_worker::skin-tone-6": "🧑🏿‍💼",
+ "male-office-worker": "👨‍💼",
+ "male-office-worker::skin-tone-2": "👨🏻‍💼",
+ "male-office-worker::skin-tone-3": "👨🏼‍💼",
+ "male-office-worker::skin-tone-4": "👨🏽‍💼",
+ "male-office-worker::skin-tone-5": "👨🏾‍💼",
+ "male-office-worker::skin-tone-6": "👨🏿‍💼",
+ "female-office-worker": "👩‍💼",
+ "female-office-worker::skin-tone-2": "👩🏻‍💼",
+ "female-office-worker::skin-tone-3": "👩🏼‍💼",
+ "female-office-worker::skin-tone-4": "👩🏽‍💼",
+ "female-office-worker::skin-tone-5": "👩🏾‍💼",
+ "female-office-worker::skin-tone-6": "👩🏿‍💼",
+ "scientist": "🧑‍🔬",
+ "scientist::skin-tone-2": "🧑🏻‍🔬",
+ "scientist::skin-tone-3": "🧑🏼‍🔬",
+ "scientist::skin-tone-4": "🧑🏽‍🔬",
+ "scientist::skin-tone-5": "🧑🏾‍🔬",
+ "scientist::skin-tone-6": "🧑🏿‍🔬",
+ "male-scientist": "👨‍🔬",
+ "male-scientist::skin-tone-2": "👨🏻‍🔬",
+ "male-scientist::skin-tone-3": "👨🏼‍🔬",
+ "male-scientist::skin-tone-4": "👨🏽‍🔬",
+ "male-scientist::skin-tone-5": "👨🏾‍🔬",
+ "male-scientist::skin-tone-6": "👨🏿‍🔬",
+ "female-scientist": "👩‍🔬",
+ "female-scientist::skin-tone-2": "👩🏻‍🔬",
+ "female-scientist::skin-tone-3": "👩🏼‍🔬",
+ "female-scientist::skin-tone-4": "👩🏽‍🔬",
+ "female-scientist::skin-tone-5": "👩🏾‍🔬",
+ "female-scientist::skin-tone-6": "👩🏿‍🔬",
+ "technologist": "🧑‍💻",
+ "technologist::skin-tone-2": "🧑🏻‍💻",
+ "technologist::skin-tone-3": "🧑🏼‍💻",
+ "technologist::skin-tone-4": "🧑🏽‍💻",
+ "technologist::skin-tone-5": "🧑🏾‍💻",
+ "technologist::skin-tone-6": "🧑🏿‍💻",
+ "male-technologist": "👨‍💻",
+ "male-technologist::skin-tone-2": "👨🏻‍💻",
+ "male-technologist::skin-tone-3": "👨🏼‍💻",
+ "male-technologist::skin-tone-4": "👨🏽‍💻",
+ "male-technologist::skin-tone-5": "👨🏾‍💻",
+ "male-technologist::skin-tone-6": "👨🏿‍💻",
+ "female-technologist": "👩‍💻",
+ "female-technologist::skin-tone-2": "👩🏻‍💻",
+ "female-technologist::skin-tone-3": "👩🏼‍💻",
+ "female-technologist::skin-tone-4": "👩🏽‍💻",
+ "female-technologist::skin-tone-5": "👩🏾‍💻",
+ "female-technologist::skin-tone-6": "👩🏿‍💻",
+ "singer": "🧑‍🎤",
+ "singer::skin-tone-2": "🧑🏻‍🎤",
+ "singer::skin-tone-3": "🧑🏼‍🎤",
+ "singer::skin-tone-4": "🧑🏽‍🎤",
+ "singer::skin-tone-5": "🧑🏾‍🎤",
+ "singer::skin-tone-6": "🧑🏿‍🎤",
+ "male-singer": "👨‍🎤",
+ "male-singer::skin-tone-2": "👨🏻‍🎤",
+ "male-singer::skin-tone-3": "👨🏼‍🎤",
+ "male-singer::skin-tone-4": "👨🏽‍🎤",
+ "male-singer::skin-tone-5": "👨🏾‍🎤",
+ "male-singer::skin-tone-6": "👨🏿‍🎤",
+ "female-singer": "👩‍🎤",
+ "female-singer::skin-tone-2": "👩🏻‍🎤",
+ "female-singer::skin-tone-3": "👩🏼‍🎤",
+ "female-singer::skin-tone-4": "👩🏽‍🎤",
+ "female-singer::skin-tone-5": "👩🏾‍🎤",
+ "female-singer::skin-tone-6": "👩🏿‍🎤",
+ "artist": "🧑‍🎨",
+ "artist::skin-tone-2": "🧑🏻‍🎨",
+ "artist::skin-tone-3": "🧑🏼‍🎨",
+ "artist::skin-tone-4": "🧑🏽‍🎨",
+ "artist::skin-tone-5": "🧑🏾‍🎨",
+ "artist::skin-tone-6": "🧑🏿‍🎨",
+ "male-artist": "👨‍🎨",
+ "male-artist::skin-tone-2": "👨🏻‍🎨",
+ "male-artist::skin-tone-3": "👨🏼‍🎨",
+ "male-artist::skin-tone-4": "👨🏽‍🎨",
+ "male-artist::skin-tone-5": "👨🏾‍🎨",
+ "male-artist::skin-tone-6": "👨🏿‍🎨",
+ "female-artist": "👩‍🎨",
+ "female-artist::skin-tone-2": "👩🏻‍🎨",
+ "female-artist::skin-tone-3": "👩🏼‍🎨",
+ "female-artist::skin-tone-4": "👩🏽‍🎨",
+ "female-artist::skin-tone-5": "👩🏾‍🎨",
+ "female-artist::skin-tone-6": "👩🏿‍🎨",
+ "pilot": "🧑‍✈️",
+ "pilot::skin-tone-2": "🧑🏻‍✈️",
+ "pilot::skin-tone-3": "🧑🏼‍✈️",
+ "pilot::skin-tone-4": "🧑🏽‍✈️",
+ "pilot::skin-tone-5": "🧑🏾‍✈️",
+ "pilot::skin-tone-6": "🧑🏿‍✈️",
+ "male-pilot": "👨‍✈️",
+ "male-pilot::skin-tone-2": "👨🏻‍✈️",
+ "male-pilot::skin-tone-3": "👨🏼‍✈️",
+ "male-pilot::skin-tone-4": "👨🏽‍✈️",
+ "male-pilot::skin-tone-5": "👨🏾‍✈️",
+ "male-pilot::skin-tone-6": "👨🏿‍✈️",
+ "female-pilot": "👩‍✈️",
+ "female-pilot::skin-tone-2": "👩🏻‍✈️",
+ "female-pilot::skin-tone-3": "👩🏼‍✈️",
+ "female-pilot::skin-tone-4": "👩🏽‍✈️",
+ "female-pilot::skin-tone-5": "👩🏾‍✈️",
+ "female-pilot::skin-tone-6": "👩🏿‍✈️",
+ "astronaut": "🧑‍🚀",
+ "astronaut::skin-tone-2": "🧑🏻‍🚀",
+ "astronaut::skin-tone-3": "🧑🏼‍🚀",
+ "astronaut::skin-tone-4": "🧑🏽‍🚀",
+ "astronaut::skin-tone-5": "🧑🏾‍🚀",
+ "astronaut::skin-tone-6": "🧑🏿‍🚀",
+ "male-astronaut": "👨‍🚀",
+ "male-astronaut::skin-tone-2": "👨🏻‍🚀",
+ "male-astronaut::skin-tone-3": "👨🏼‍🚀",
+ "male-astronaut::skin-tone-4": "👨🏽‍🚀",
+ "male-astronaut::skin-tone-5": "👨🏾‍🚀",
+ "male-astronaut::skin-tone-6": "👨🏿‍🚀",
+ "female-astronaut": "👩‍🚀",
+ "female-astronaut::skin-tone-2": "👩🏻‍🚀",
+ "female-astronaut::skin-tone-3": "👩🏼‍🚀",
+ "female-astronaut::skin-tone-4": "👩🏽‍🚀",
+ "female-astronaut::skin-tone-5": "👩🏾‍🚀",
+ "female-astronaut::skin-tone-6": "👩🏿‍🚀",
+ "firefighter": "🧑‍🚒",
+ "firefighter::skin-tone-2": "🧑🏻‍🚒",
+ "firefighter::skin-tone-3": "🧑🏼‍🚒",
+ "firefighter::skin-tone-4": "🧑🏽‍🚒",
+ "firefighter::skin-tone-5": "🧑🏾‍🚒",
+ "firefighter::skin-tone-6": "🧑🏿‍🚒",
+ "male-firefighter": "👨‍🚒",
+ "male-firefighter::skin-tone-2": "👨🏻‍🚒",
+ "male-firefighter::skin-tone-3": "👨🏼‍🚒",
+ "male-firefighter::skin-tone-4": "👨🏽‍🚒",
+ "male-firefighter::skin-tone-5": "👨🏾‍🚒",
+ "male-firefighter::skin-tone-6": "👨🏿‍🚒",
+ "female-firefighter": "👩‍🚒",
+ "female-firefighter::skin-tone-2": "👩🏻‍🚒",
+ "female-firefighter::skin-tone-3": "👩🏼‍🚒",
+ "female-firefighter::skin-tone-4": "👩🏽‍🚒",
+ "female-firefighter::skin-tone-5": "👩🏾‍🚒",
+ "female-firefighter::skin-tone-6": "👩🏿‍🚒",
+ "cop": "👮",
+ "cop::skin-tone-2": "👮🏻",
+ "cop::skin-tone-3": "👮🏼",
+ "cop::skin-tone-4": "👮🏽",
+ "cop::skin-tone-5": "👮🏾",
+ "cop::skin-tone-6": "👮🏿",
+ "male-police-officer": "👮‍♂️",
+ "male-police-officer::skin-tone-2": "👮🏻‍♂️",
+ "male-police-officer::skin-tone-3": "👮🏼‍♂️",
+ "male-police-officer::skin-tone-4": "👮🏽‍♂️",
+ "male-police-officer::skin-tone-5": "👮🏾‍♂️",
+ "male-police-officer::skin-tone-6": "👮🏿‍♂️",
+ "female-police-officer": "👮‍♀️",
+ "female-police-officer::skin-tone-2": "👮🏻‍♀️",
+ "female-police-officer::skin-tone-3": "👮🏼‍♀️",
+ "female-police-officer::skin-tone-4": "👮🏽‍♀️",
+ "female-police-officer::skin-tone-5": "👮🏾‍♀️",
+ "female-police-officer::skin-tone-6": "👮🏿‍♀️",
+ "sleuth_or_spy": "🕵️",
+ "sleuth_or_spy::skin-tone-2": "🕵🏻",
+ "sleuth_or_spy::skin-tone-3": "🕵🏼",
+ "sleuth_or_spy::skin-tone-4": "🕵🏽",
+ "sleuth_or_spy::skin-tone-5": "🕵🏾",
+ "sleuth_or_spy::skin-tone-6": "🕵🏿",
+ "male-detective": "🕵️‍♂️",
+ "male-detective::skin-tone-2": "🕵🏻‍♂️",
+ "male-detective::skin-tone-3": "🕵🏼‍♂️",
+ "male-detective::skin-tone-4": "🕵🏽‍♂️",
+ "male-detective::skin-tone-5": "🕵🏾‍♂️",
+ "male-detective::skin-tone-6": "🕵🏿‍♂️",
+ "female-detective": "🕵️‍♀️",
+ "female-detective::skin-tone-2": "🕵🏻‍♀️",
+ "female-detective::skin-tone-3": "🕵🏼‍♀️",
+ "female-detective::skin-tone-4": "🕵🏽‍♀️",
+ "female-detective::skin-tone-5": "🕵🏾‍♀️",
+ "female-detective::skin-tone-6": "🕵🏿‍♀️",
+ "guardsman": "💂",
+ "guardsman::skin-tone-2": "💂🏻",
+ "guardsman::skin-tone-3": "💂🏼",
+ "guardsman::skin-tone-4": "💂🏽",
+ "guardsman::skin-tone-5": "💂🏾",
+ "guardsman::skin-tone-6": "💂🏿",
+ "male-guard": "💂‍♂️",
+ "male-guard::skin-tone-2": "💂🏻‍♂️",
+ "male-guard::skin-tone-3": "💂🏼‍♂️",
+ "male-guard::skin-tone-4": "💂🏽‍♂️",
+ "male-guard::skin-tone-5": "💂🏾‍♂️",
+ "male-guard::skin-tone-6": "💂🏿‍♂️",
+ "female-guard": "💂‍♀️",
+ "female-guard::skin-tone-2": "💂🏻‍♀️",
+ "female-guard::skin-tone-3": "💂🏼‍♀️",
+ "female-guard::skin-tone-4": "💂🏽‍♀️",
+ "female-guard::skin-tone-5": "💂🏾‍♀️",
+ "female-guard::skin-tone-6": "💂🏿‍♀️",
+ "ninja": "🥷",
+ "ninja::skin-tone-2": "🥷🏻",
+ "ninja::skin-tone-3": "🥷🏼",
+ "ninja::skin-tone-4": "🥷🏽",
+ "ninja::skin-tone-5": "🥷🏾",
+ "ninja::skin-tone-6": "🥷🏿",
+ "construction_worker": "👷",
+ "construction_worker::skin-tone-2": "👷🏻",
+ "construction_worker::skin-tone-3": "👷🏼",
+ "construction_worker::skin-tone-4": "👷🏽",
+ "construction_worker::skin-tone-5": "👷🏾",
+ "construction_worker::skin-tone-6": "👷🏿",
+ "male-construction-worker": "👷‍♂️",
+ "male-construction-worker::skin-tone-2": "👷🏻‍♂️",
+ "male-construction-worker::skin-tone-3": "👷🏼‍♂️",
+ "male-construction-worker::skin-tone-4": "👷🏽‍♂️",
+ "male-construction-worker::skin-tone-5": "👷🏾‍♂️",
+ "male-construction-worker::skin-tone-6": "👷🏿‍♂️",
+ "female-construction-worker": "👷‍♀️",
+ "female-construction-worker::skin-tone-2": "👷🏻‍♀️",
+ "female-construction-worker::skin-tone-3": "👷🏼‍♀️",
+ "female-construction-worker::skin-tone-4": "👷🏽‍♀️",
+ "female-construction-worker::skin-tone-5": "👷🏾‍♀️",
+ "female-construction-worker::skin-tone-6": "👷🏿‍♀️",
+ "person_with_crown": "🫅",
+ "person_with_crown::skin-tone-2": "🫅🏻",
+ "person_with_crown::skin-tone-3": "🫅🏼",
+ "person_with_crown::skin-tone-4": "🫅🏽",
+ "person_with_crown::skin-tone-5": "🫅🏾",
+ "person_with_crown::skin-tone-6": "🫅🏿",
+ "prince": "🤴",
+ "prince::skin-tone-2": "🤴🏻",
+ "prince::skin-tone-3": "🤴🏼",
+ "prince::skin-tone-4": "🤴🏽",
+ "prince::skin-tone-5": "🤴🏾",
+ "prince::skin-tone-6": "🤴🏿",
+ "princess": "👸",
+ "princess::skin-tone-2": "👸🏻",
+ "princess::skin-tone-3": "👸🏼",
+ "princess::skin-tone-4": "👸🏽",
+ "princess::skin-tone-5": "👸🏾",
+ "princess::skin-tone-6": "👸🏿",
+ "man_with_turban": "👳",
+ "man_with_turban::skin-tone-2": "👳🏻",
+ "man_with_turban::skin-tone-3": "👳🏼",
+ "man_with_turban::skin-tone-4": "👳🏽",
+ "man_with_turban::skin-tone-5": "👳🏾",
+ "man_with_turban::skin-tone-6": "👳🏿",
+ "man-wearing-turban": "👳‍♂️",
+ "man-wearing-turban::skin-tone-2": "👳🏻‍♂️",
+ "man-wearing-turban::skin-tone-3": "👳🏼‍♂️",
+ "man-wearing-turban::skin-tone-4": "👳🏽‍♂️",
+ "man-wearing-turban::skin-tone-5": "👳🏾‍♂️",
+ "man-wearing-turban::skin-tone-6": "👳🏿‍♂️",
+ "woman-wearing-turban": "👳‍♀️",
+ "woman-wearing-turban::skin-tone-2": "👳🏻‍♀️",
+ "woman-wearing-turban::skin-tone-3": "👳🏼‍♀️",
+ "woman-wearing-turban::skin-tone-4": "👳🏽‍♀️",
+ "woman-wearing-turban::skin-tone-5": "👳🏾‍♀️",
+ "woman-wearing-turban::skin-tone-6": "👳🏿‍♀️",
+ "man_with_gua_pi_mao": "👲",
+ "man_with_gua_pi_mao::skin-tone-2": "👲🏻",
+ "man_with_gua_pi_mao::skin-tone-3": "👲🏼",
+ "man_with_gua_pi_mao::skin-tone-4": "👲🏽",
+ "man_with_gua_pi_mao::skin-tone-5": "👲🏾",
+ "man_with_gua_pi_mao::skin-tone-6": "👲🏿",
+ "person_with_headscarf": "🧕",
+ "person_with_headscarf::skin-tone-2": "🧕🏻",
+ "person_with_headscarf::skin-tone-3": "🧕🏼",
+ "person_with_headscarf::skin-tone-4": "🧕🏽",
+ "person_with_headscarf::skin-tone-5": "🧕🏾",
+ "person_with_headscarf::skin-tone-6": "🧕🏿",
+ "person_in_tuxedo": "🤵",
+ "person_in_tuxedo::skin-tone-2": "🤵🏻",
+ "person_in_tuxedo::skin-tone-3": "🤵🏼",
+ "person_in_tuxedo::skin-tone-4": "🤵🏽",
+ "person_in_tuxedo::skin-tone-5": "🤵🏾",
+ "person_in_tuxedo::skin-tone-6": "🤵🏿",
+ "man_in_tuxedo": "🤵‍♂️",
+ "man_in_tuxedo::skin-tone-2": "🤵🏻‍♂️",
+ "man_in_tuxedo::skin-tone-3": "🤵🏼‍♂️",
+ "man_in_tuxedo::skin-tone-4": "🤵🏽‍♂️",
+ "man_in_tuxedo::skin-tone-5": "🤵🏾‍♂️",
+ "man_in_tuxedo::skin-tone-6": "🤵🏿‍♂️",
+ "woman_in_tuxedo": "🤵‍♀️",
+ "woman_in_tuxedo::skin-tone-2": "🤵🏻‍♀️",
+ "woman_in_tuxedo::skin-tone-3": "🤵🏼‍♀️",
+ "woman_in_tuxedo::skin-tone-4": "🤵🏽‍♀️",
+ "woman_in_tuxedo::skin-tone-5": "🤵🏾‍♀️",
+ "woman_in_tuxedo::skin-tone-6": "🤵🏿‍♀️",
+ "bride_with_veil": "👰",
+ "bride_with_veil::skin-tone-2": "👰🏻",
+ "bride_with_veil::skin-tone-3": "👰🏼",
+ "bride_with_veil::skin-tone-4": "👰🏽",
+ "bride_with_veil::skin-tone-5": "👰🏾",
+ "bride_with_veil::skin-tone-6": "👰🏿",
+ "man_with_veil": "👰‍♂️",
+ "man_with_veil::skin-tone-2": "👰🏻‍♂️",
+ "man_with_veil::skin-tone-3": "👰🏼‍♂️",
+ "man_with_veil::skin-tone-4": "👰🏽‍♂️",
+ "man_with_veil::skin-tone-5": "👰🏾‍♂️",
+ "man_with_veil::skin-tone-6": "👰🏿‍♂️",
+ "woman_with_veil": "👰‍♀️",
+ "woman_with_veil::skin-tone-2": "👰🏻‍♀️",
+ "woman_with_veil::skin-tone-3": "👰🏼‍♀️",
+ "woman_with_veil::skin-tone-4": "👰🏽‍♀️",
+ "woman_with_veil::skin-tone-5": "👰🏾‍♀️",
+ "woman_with_veil::skin-tone-6": "👰🏿‍♀️",
+ "pregnant_woman": "🤰",
+ "pregnant_woman::skin-tone-2": "🤰🏻",
+ "pregnant_woman::skin-tone-3": "🤰🏼",
+ "pregnant_woman::skin-tone-4": "🤰🏽",
+ "pregnant_woman::skin-tone-5": "🤰🏾",
+ "pregnant_woman::skin-tone-6": "🤰🏿",
+ "pregnant_man": "🫃",
+ "pregnant_man::skin-tone-2": "🫃🏻",
+ "pregnant_man::skin-tone-3": "🫃🏼",
+ "pregnant_man::skin-tone-4": "🫃🏽",
+ "pregnant_man::skin-tone-5": "🫃🏾",
+ "pregnant_man::skin-tone-6": "🫃🏿",
+ "pregnant_person": "🫄",
+ "pregnant_person::skin-tone-2": "🫄🏻",
+ "pregnant_person::skin-tone-3": "🫄🏼",
+ "pregnant_person::skin-tone-4": "🫄🏽",
+ "pregnant_person::skin-tone-5": "🫄🏾",
+ "pregnant_person::skin-tone-6": "🫄🏿",
+ "breast-feeding": "🤱",
+ "breast-feeding::skin-tone-2": "🤱🏻",
+ "breast-feeding::skin-tone-3": "🤱🏼",
+ "breast-feeding::skin-tone-4": "🤱🏽",
+ "breast-feeding::skin-tone-5": "🤱🏾",
+ "breast-feeding::skin-tone-6": "🤱🏿",
+ "woman_feeding_baby": "👩‍🍼",
+ "woman_feeding_baby::skin-tone-2": "👩🏻‍🍼",
+ "woman_feeding_baby::skin-tone-3": "👩🏼‍🍼",
+ "woman_feeding_baby::skin-tone-4": "👩🏽‍🍼",
+ "woman_feeding_baby::skin-tone-5": "👩🏾‍🍼",
+ "woman_feeding_baby::skin-tone-6": "👩🏿‍🍼",
+ "man_feeding_baby": "👨‍🍼",
+ "man_feeding_baby::skin-tone-2": "👨🏻‍🍼",
+ "man_feeding_baby::skin-tone-3": "👨🏼‍🍼",
+ "man_feeding_baby::skin-tone-4": "👨🏽‍🍼",
+ "man_feeding_baby::skin-tone-5": "👨🏾‍🍼",
+ "man_feeding_baby::skin-tone-6": "👨🏿‍🍼",
+ "person_feeding_baby": "🧑‍🍼",
+ "person_feeding_baby::skin-tone-2": "🧑🏻‍🍼",
+ "person_feeding_baby::skin-tone-3": "🧑🏼‍🍼",
+ "person_feeding_baby::skin-tone-4": "🧑🏽‍🍼",
+ "person_feeding_baby::skin-tone-5": "🧑🏾‍🍼",
+ "person_feeding_baby::skin-tone-6": "🧑🏿‍🍼",
+ "angel": "👼",
+ "angel::skin-tone-2": "👼🏻",
+ "angel::skin-tone-3": "👼🏼",
+ "angel::skin-tone-4": "👼🏽",
+ "angel::skin-tone-5": "👼🏾",
+ "angel::skin-tone-6": "👼🏿",
+ "dagsanta": "🎅",
+ "santa": "🎅",
+ "santa::skin-tone-2": "🎅🏻",
+ "santa::skin-tone-3": "🎅🏼",
+ "santa::skin-tone-4": "🎅🏽",
+ "santa::skin-tone-5": "🎅🏾",
+ "santa::skin-tone-6": "🎅🏿",
+ "mrs_claus": "🤶",
+ "mother_christmas": "🤶",
+ "mrs_claus::skin-tone-2": "🤶🏻",
+ "mother_christmas::skin-tone-2": "🤶🏻",
+ "mrs_claus::skin-tone-3": "🤶🏼",
+ "mother_christmas::skin-tone-3": "🤶🏼",
+ "mrs_claus::skin-tone-4": "🤶🏽",
+ "mother_christmas::skin-tone-4": "🤶🏽",
+ "mrs_claus::skin-tone-5": "🤶🏾",
+ "mother_christmas::skin-tone-5": "🤶🏾",
+ "mrs_claus::skin-tone-6": "🤶🏿",
+ "mother_christmas::skin-tone-6": "🤶🏿",
+ "mx_claus": "🧑‍🎄",
+ "mx_claus::skin-tone-2": "🧑🏻‍🎄",
+ "mx_claus::skin-tone-3": "🧑🏼‍🎄",
+ "mx_claus::skin-tone-4": "🧑🏽‍🎄",
+ "mx_claus::skin-tone-5": "🧑🏾‍🎄",
+ "mx_claus::skin-tone-6": "🧑🏿‍🎄",
+ "superhero": "🦸",
+ "superhero::skin-tone-2": "🦸🏻",
+ "superhero::skin-tone-3": "🦸🏼",
+ "superhero::skin-tone-4": "🦸🏽",
+ "superhero::skin-tone-5": "🦸🏾",
+ "superhero::skin-tone-6": "🦸🏿",
+ "male_superhero": "🦸‍♂️",
+ "male_superhero::skin-tone-2": "🦸🏻‍♂️",
+ "male_superhero::skin-tone-3": "🦸🏼‍♂️",
+ "male_superhero::skin-tone-4": "🦸🏽‍♂️",
+ "male_superhero::skin-tone-5": "🦸🏾‍♂️",
+ "male_superhero::skin-tone-6": "🦸🏿‍♂️",
+ "female_superhero": "🦸‍♀️",
+ "female_superhero::skin-tone-2": "🦸🏻‍♀️",
+ "female_superhero::skin-tone-3": "🦸🏼‍♀️",
+ "female_superhero::skin-tone-4": "🦸🏽‍♀️",
+ "female_superhero::skin-tone-5": "🦸🏾‍♀️",
+ "female_superhero::skin-tone-6": "🦸🏿‍♀️",
+ "supervillain": "🦹",
+ "supervillain::skin-tone-2": "🦹🏻",
+ "supervillain::skin-tone-3": "🦹🏼",
+ "supervillain::skin-tone-4": "🦹🏽",
+ "supervillain::skin-tone-5": "🦹🏾",
+ "supervillain::skin-tone-6": "🦹🏿",
+ "male_supervillain": "🦹‍♂️",
+ "male_supervillain::skin-tone-2": "🦹🏻‍♂️",
+ "male_supervillain::skin-tone-3": "🦹🏼‍♂️",
+ "male_supervillain::skin-tone-4": "🦹🏽‍♂️",
+ "male_supervillain::skin-tone-5": "🦹🏾‍♂️",
+ "male_supervillain::skin-tone-6": "🦹🏿‍♂️",
+ "female_supervillain": "🦹‍♀️",
+ "female_supervillain::skin-tone-2": "🦹🏻‍♀️",
+ "female_supervillain::skin-tone-3": "🦹🏼‍♀️",
+ "female_supervillain::skin-tone-4": "🦹🏽‍♀️",
+ "female_supervillain::skin-tone-5": "🦹🏾‍♀️",
+ "female_supervillain::skin-tone-6": "🦹🏿‍♀️",
+ "mage": "🧙",
+ "mage_ai": "🧙",
+ "mage::skin-tone-2": "🧙🏻",
+ "mage::skin-tone-3": "🧙🏼",
+ "mage::skin-tone-4": "🧙🏽",
+ "mage::skin-tone-5": "🧙🏾",
+ "mage::skin-tone-6": "🧙🏿",
+ "male_mage": "🧙‍♂️",
+ "male_mage::skin-tone-2": "🧙🏻‍♂️",
+ "male_mage::skin-tone-3": "🧙🏼‍♂️",
+ "male_mage::skin-tone-4": "🧙🏽‍♂️",
+ "male_mage::skin-tone-5": "🧙🏾‍♂️",
+ "male_mage::skin-tone-6": "🧙🏿‍♂️",
+ "female_mage": "🧙‍♀️",
+ "female_mage::skin-tone-2": "🧙🏻‍♀️",
+ "female_mage::skin-tone-3": "🧙🏼‍♀️",
+ "female_mage::skin-tone-4": "🧙🏽‍♀️",
+ "female_mage::skin-tone-5": "🧙🏾‍♀️",
+ "female_mage::skin-tone-6": "🧙🏿‍♀️",
+ "airflow": "A",
+ "fairy": "🧚",
+ "fairy::skin-tone-2": "🧚🏻",
+ "fairy::skin-tone-3": "🧚🏼",
+ "fairy::skin-tone-4": "🧚🏽",
+ "fairy::skin-tone-5": "🧚🏾",
+ "fairy::skin-tone-6": "🧚🏿",
+ "male_fairy": "🧚‍♂️",
+ "male_fairy::skin-tone-2": "🧚🏻‍♂️",
+ "male_fairy::skin-tone-3": "🧚🏼‍♂️",
+ "male_fairy::skin-tone-4": "🧚🏽‍♂️",
+ "male_fairy::skin-tone-5": "🧚🏾‍♂️",
+ "male_fairy::skin-tone-6": "🧚🏿‍♂️",
+ "female_fairy": "🧚‍♀️",
+ "female_fairy::skin-tone-2": "🧚🏻‍♀️",
+ "female_fairy::skin-tone-3": "🧚🏼‍♀️",
+ "female_fairy::skin-tone-4": "🧚🏽‍♀️",
+ "female_fairy::skin-tone-5": "🧚🏾‍♀️",
+ "female_fairy::skin-tone-6": "🧚🏿‍♀️",
+ "vampire": "🧛",
+ "vampire::skin-tone-2": "🧛🏻",
+ "vampire::skin-tone-3": "🧛🏼",
+ "vampire::skin-tone-4": "🧛🏽",
+ "vampire::skin-tone-5": "🧛🏾",
+ "vampire::skin-tone-6": "🧛🏿",
+ "male_vampire": "🧛‍♂️",
+ "male_vampire::skin-tone-2": "🧛🏻‍♂️",
+ "male_vampire::skin-tone-3": "🧛🏼‍♂️",
+ "male_vampire::skin-tone-4": "🧛🏽‍♂️",
+ "male_vampire::skin-tone-5": "🧛🏾‍♂️",
+ "male_vampire::skin-tone-6": "🧛🏿‍♂️",
+ "female_vampire": "🧛‍♀️",
+ "female_vampire::skin-tone-2": "🧛🏻‍♀️",
+ "female_vampire::skin-tone-3": "🧛🏼‍♀️",
+ "female_vampire::skin-tone-4": "🧛🏽‍♀️",
+ "female_vampire::skin-tone-5": "🧛🏾‍♀️",
+ "female_vampire::skin-tone-6": "🧛🏿‍♀️",
+ "merperson": "🧜",
+ "merperson::skin-tone-2": "🧜🏻",
+ "merperson::skin-tone-3": "🧜🏼",
+ "merperson::skin-tone-4": "🧜🏽",
+ "merperson::skin-tone-5": "🧜🏾",
+ "merperson::skin-tone-6": "🧜🏿",
+ "merman": "🧜‍♂️",
+ "merman::skin-tone-2": "🧜🏻‍♂️",
+ "merman::skin-tone-3": "🧜🏼‍♂️",
+ "merman::skin-tone-4": "🧜🏽‍♂️",
+ "merman::skin-tone-5": "🧜🏾‍♂️",
+ "merman::skin-tone-6": "🧜🏿‍♂️",
+ "mermaid": "🧜‍♀️",
+ "mermaid::skin-tone-2": "🧜🏻‍♀️",
+ "mermaid::skin-tone-3": "🧜🏼‍♀️",
+ "mermaid::skin-tone-4": "🧜🏽‍♀️",
+ "mermaid::skin-tone-5": "🧜🏾‍♀️",
+ "mermaid::skin-tone-6": "🧜🏿‍♀️",
+ "elf": "🧝",
+ "elf::skin-tone-2": "🧝🏻",
+ "elf::skin-tone-3": "🧝🏼",
+ "elf::skin-tone-4": "🧝🏽",
+ "elf::skin-tone-5": "🧝🏾",
+ "elf::skin-tone-6": "🧝🏿",
+ "male_elf": "🧝‍♂️",
+ "male_elf::skin-tone-2": "🧝🏻‍♂️",
+ "male_elf::skin-tone-3": "🧝🏼‍♂️",
+ "male_elf::skin-tone-4": "🧝🏽‍♂️",
+ "male_elf::skin-tone-5": "🧝🏾‍♂️",
+ "male_elf::skin-tone-6": "🧝🏿‍♂️",
+ "female_elf": "🧝‍♀️",
+ "female_elf::skin-tone-2": "🧝🏻‍♀️",
+ "female_elf::skin-tone-3": "🧝🏼‍♀️",
+ "female_elf::skin-tone-4": "🧝🏽‍♀️",
+ "female_elf::skin-tone-5": "🧝🏾‍♀️",
+ "female_elf::skin-tone-6": "🧝🏿‍♀️",
+ "genie": "🧞",
+ "male_genie": "🧞‍♂️",
+ "female_genie": "🧞‍♀️",
+ "zombie": "🧟",
+ "male_zombie": "🧟‍♂️",
+ "female_zombie": "🧟‍♀️",
+ "troll": "🧌",
+ "massage": "💆",
+ "massage::skin-tone-2": "💆🏻",
+ "massage::skin-tone-3": "💆🏼",
+ "massage::skin-tone-4": "💆🏽",
+ "massage::skin-tone-5": "💆🏾",
+ "massage::skin-tone-6": "💆🏿",
+ "man-getting-massage": "💆‍♂️",
+ "man-getting-massage::skin-tone-2": "💆🏻‍♂️",
+ "man-getting-massage::skin-tone-3": "💆🏼‍♂️",
+ "man-getting-massage::skin-tone-4": "💆🏽‍♂️",
+ "man-getting-massage::skin-tone-5": "💆🏾‍♂️",
+ "man-getting-massage::skin-tone-6": "💆🏿‍♂️",
+ "woman-getting-massage": "💆‍♀️",
+ "woman-getting-massage::skin-tone-2": "💆🏻‍♀️",
+ "woman-getting-massage::skin-tone-3": "💆🏼‍♀️",
+ "woman-getting-massage::skin-tone-4": "💆🏽‍♀️",
+ "woman-getting-massage::skin-tone-5": "💆🏾‍♀️",
+ "woman-getting-massage::skin-tone-6": "💆🏿‍♀️",
+ "haircut": "💇",
+ "haircut::skin-tone-2": "💇🏻",
+ "haircut::skin-tone-3": "💇🏼",
+ "haircut::skin-tone-4": "💇🏽",
+ "haircut::skin-tone-5": "💇🏾",
+ "haircut::skin-tone-6": "💇🏿",
+ "man-getting-haircut": "💇‍♂️",
+ "man-getting-haircut::skin-tone-2": "💇🏻‍♂️",
+ "man-getting-haircut::skin-tone-3": "💇🏼‍♂️",
+ "man-getting-haircut::skin-tone-4": "💇🏽‍♂️",
+ "man-getting-haircut::skin-tone-5": "💇🏾‍♂️",
+ "man-getting-haircut::skin-tone-6": "💇🏿‍♂️",
+ "woman-getting-haircut": "💇‍♀️",
+ "woman-getting-haircut::skin-tone-2": "💇🏻‍♀️",
+ "woman-getting-haircut::skin-tone-3": "💇🏼‍♀️",
+ "woman-getting-haircut::skin-tone-4": "💇🏽‍♀️",
+ "woman-getting-haircut::skin-tone-5": "💇🏾‍♀️",
+ "woman-getting-haircut::skin-tone-6": "💇🏿‍♀️",
+ "lfg": "🚶",
+ "walking": "🚶",
+ "walking::skin-tone-2": "🚶🏻",
+ "walking::skin-tone-3": "🚶🏼",
+ "walking::skin-tone-4": "🚶🏽",
+ "walking::skin-tone-5": "🚶🏾",
+ "walking::skin-tone-6": "🚶🏿",
+ "man-walking": "🚶‍♂️",
+ "man-walking::skin-tone-2": "🚶🏻‍♂️",
+ "man-walking::skin-tone-3": "🚶🏼‍♂️",
+ "man-walking::skin-tone-4": "🚶🏽‍♂️",
+ "man-walking::skin-tone-5": "🚶🏾‍♂️",
+ "man-walking::skin-tone-6": "🚶🏿‍♂️",
+ "woman-walking": "🚶‍♀️",
+ "woman-walking::skin-tone-2": "🚶🏻‍♀️",
+ "woman-walking::skin-tone-3": "🚶🏼‍♀️",
+ "woman-walking::skin-tone-4": "🚶🏽‍♀️",
+ "woman-walking::skin-tone-5": "🚶🏾‍♀️",
+ "woman-walking::skin-tone-6": "🚶🏿‍♀️",
+ "standing_person": "🧍",
+ "standing_person::skin-tone-2": "🧍🏻",
+ "standing_person::skin-tone-3": "🧍🏼",
+ "standing_person::skin-tone-4": "🧍🏽",
+ "standing_person::skin-tone-5": "🧍🏾",
+ "standing_person::skin-tone-6": "🧍🏿",
+ "man_standing": "🧍‍♂️",
+ "man_standing::skin-tone-2": "🧍🏻‍♂️",
+ "man_standing::skin-tone-3": "🧍🏼‍♂️",
+ "man_standing::skin-tone-4": "🧍🏽‍♂️",
+ "man_standing::skin-tone-5": "🧍🏾‍♂️",
+ "man_standing::skin-tone-6": "🧍🏿‍♂️",
+ "woman_standing": "🧍‍♀️",
+ "woman_standing::skin-tone-2": "🧍🏻‍♀️",
+ "woman_standing::skin-tone-3": "🧍🏼‍♀️",
+ "woman_standing::skin-tone-4": "🧍🏽‍♀️",
+ "woman_standing::skin-tone-5": "🧍🏾‍♀️",
+ "woman_standing::skin-tone-6": "🧍🏿‍♀️",
+ "kneeling_person": "🧎",
+ "kneeling_person::skin-tone-2": "🧎🏻",
+ "kneeling_person::skin-tone-3": "🧎🏼",
+ "kneeling_person::skin-tone-4": "🧎🏽",
+ "kneeling_person::skin-tone-5": "🧎🏾",
+ "kneeling_person::skin-tone-6": "🧎🏿",
+ "man_kneeling": "🧎‍♂️",
+ "man_kneeling::skin-tone-2": "🧎🏻‍♂️",
+ "man_kneeling::skin-tone-3": "🧎🏼‍♂️",
+ "man_kneeling::skin-tone-4": "🧎🏽‍♂️",
+ "man_kneeling::skin-tone-5": "🧎🏾‍♂️",
+ "man_kneeling::skin-tone-6": "🧎🏿‍♂️",
+ "woman_kneeling": "🧎‍♀️",
+ "woman_kneeling::skin-tone-2": "🧎🏻‍♀️",
+ "woman_kneeling::skin-tone-3": "🧎🏼‍♀️",
+ "woman_kneeling::skin-tone-4": "🧎🏽‍♀️",
+ "woman_kneeling::skin-tone-5": "🧎🏾‍♀️",
+ "woman_kneeling::skin-tone-6": "🧎🏿‍♀️",
+ "person_with_probing_cane": "🧑‍🦯",
+ "person_with_probing_cane::skin-tone-2": "🧑🏻‍🦯",
+ "person_with_probing_cane::skin-tone-3": "🧑🏼‍🦯",
+ "person_with_probing_cane::skin-tone-4": "🧑🏽‍🦯",
+ "person_with_probing_cane::skin-tone-5": "🧑🏾‍🦯",
+ "person_with_probing_cane::skin-tone-6": "🧑🏿‍🦯",
+ "man_with_probing_cane": "👨‍🦯",
+ "man_with_probing_cane::skin-tone-2": "👨🏻‍🦯",
+ "man_with_probing_cane::skin-tone-3": "👨🏼‍🦯",
+ "man_with_probing_cane::skin-tone-4": "👨🏽‍🦯",
+ "man_with_probing_cane::skin-tone-5": "👨🏾‍🦯",
+ "man_with_probing_cane::skin-tone-6": "👨🏿‍🦯",
+ "woman_with_probing_cane": "👩‍🦯",
+ "woman_with_probing_cane::skin-tone-2": "👩🏻‍🦯",
+ "woman_with_probing_cane::skin-tone-3": "👩🏼‍🦯",
+ "woman_with_probing_cane::skin-tone-4": "👩🏽‍🦯",
+ "woman_with_probing_cane::skin-tone-5": "👩🏾‍🦯",
+ "woman_with_probing_cane::skin-tone-6": "👩🏿‍🦯",
+ "person_in_motorized_wheelchair": "🧑‍🦼",
+ "person_in_motorized_wheelchair::skin-tone-2": "🧑🏻‍🦼",
+ "person_in_motorized_wheelchair::skin-tone-3": "🧑🏼‍🦼",
+ "person_in_motorized_wheelchair::skin-tone-4": "🧑🏽‍🦼",
+ "person_in_motorized_wheelchair::skin-tone-5": "🧑🏾‍🦼",
+ "person_in_motorized_wheelchair::skin-tone-6": "🧑🏿‍🦼",
+ "man_in_motorized_wheelchair": "👨‍🦼",
+ "man_in_motorized_wheelchair::skin-tone-2": "👨🏻‍🦼",
+ "man_in_motorized_wheelchair::skin-tone-3": "👨🏼‍🦼",
+ "man_in_motorized_wheelchair::skin-tone-4": "👨🏽‍🦼",
+ "man_in_motorized_wheelchair::skin-tone-5": "👨🏾‍🦼",
+ "man_in_motorized_wheelchair::skin-tone-6": "👨🏿‍🦼",
+ "woman_in_motorized_wheelchair": "👩‍🦼",
+ "woman_in_motorized_wheelchair::skin-tone-2": "👩🏻‍🦼",
+ "woman_in_motorized_wheelchair::skin-tone-3": "👩🏼‍🦼",
+ "woman_in_motorized_wheelchair::skin-tone-4": "👩🏽‍🦼",
+ "woman_in_motorized_wheelchair::skin-tone-5": "👩🏾‍🦼",
+ "woman_in_motorized_wheelchair::skin-tone-6": "👩🏿‍🦼",
+ "person_in_manual_wheelchair": "🧑‍🦽",
+ "person_in_manual_wheelchair::skin-tone-2": "🧑🏻‍🦽",
+ "person_in_manual_wheelchair::skin-tone-3": "🧑🏼‍🦽",
+ "person_in_manual_wheelchair::skin-tone-4": "🧑🏽‍🦽",
+ "person_in_manual_wheelchair::skin-tone-5": "🧑🏾‍🦽",
+ "person_in_manual_wheelchair::skin-tone-6": "🧑🏿‍🦽",
+ "man_in_manual_wheelchair": "👨‍🦽",
+ "man_in_manual_wheelchair::skin-tone-2": "👨🏻‍🦽",
+ "man_in_manual_wheelchair::skin-tone-3": "👨🏼‍🦽",
+ "man_in_manual_wheelchair::skin-tone-4": "👨🏽‍🦽",
+ "man_in_manual_wheelchair::skin-tone-5": "👨🏾‍🦽",
+ "man_in_manual_wheelchair::skin-tone-6": "👨🏿‍🦽",
+ "woman_in_manual_wheelchair": "👩‍🦽",
+ "woman_in_manual_wheelchair::skin-tone-2": "👩🏻‍🦽",
+ "woman_in_manual_wheelchair::skin-tone-3": "👩🏼‍🦽",
+ "woman_in_manual_wheelchair::skin-tone-4": "👩🏽‍🦽",
+ "woman_in_manual_wheelchair::skin-tone-5": "👩🏾‍🦽",
+ "woman_in_manual_wheelchair::skin-tone-6": "👩🏿‍🦽",
+ "runner": "🏃",
+ "running": "🏃",
+ "runner::skin-tone-2": "🏃🏻",
+ "running::skin-tone-2": "🏃🏻",
+ "runner::skin-tone-3": "🏃🏼",
+ "running::skin-tone-3": "🏃🏼",
+ "runner::skin-tone-4": "🏃🏽",
+ "running::skin-tone-4": "🏃🏽",
+ "runner::skin-tone-5": "🏃🏾",
+ "running::skin-tone-5": "🏃🏾",
+ "runner::skin-tone-6": "🏃🏿",
+ "running::skin-tone-6": "🏃🏿",
+ "man-running": "🏃‍♂️",
+ "man-running::skin-tone-2": "🏃🏻‍♂️",
+ "man-running::skin-tone-3": "🏃🏼‍♂️",
+ "man-running::skin-tone-4": "🏃🏽‍♂️",
+ "man-running::skin-tone-5": "🏃🏾‍♂️",
+ "man-running::skin-tone-6": "🏃🏿‍♂️",
+ "woman-running": "🏃‍♀️",
+ "woman-running::skin-tone-2": "🏃🏻‍♀️",
+ "woman-running::skin-tone-3": "🏃🏼‍♀️",
+ "woman-running::skin-tone-4": "🏃🏽‍♀️",
+ "woman-running::skin-tone-5": "🏃🏾‍♀️",
+ "woman-running::skin-tone-6": "🏃🏿‍♀️",
+ "dancer": "💃",
+ "dancer::skin-tone-2": "💃🏻",
+ "dancer::skin-tone-3": "💃🏼",
+ "dancer::skin-tone-4": "💃🏽",
+ "dancer::skin-tone-5": "💃🏾",
+ "dancer::skin-tone-6": "💃🏿",
+ "man_dancing": "🕺",
+ "man_dancing::skin-tone-2": "🕺🏻",
+ "man_dancing::skin-tone-3": "🕺🏼",
+ "man_dancing::skin-tone-4": "🕺🏽",
+ "man_dancing::skin-tone-5": "🕺🏾",
+ "man_dancing::skin-tone-6": "🕺🏿",
+ "man_in_business_suit_levitating": "🕴️",
+ "man_in_business_suit_levitating::skin-tone-2": "🕴🏻",
+ "man_in_business_suit_levitating::skin-tone-3": "🕴🏼",
+ "man_in_business_suit_levitating::skin-tone-4": "🕴🏽",
+ "man_in_business_suit_levitating::skin-tone-5": "🕴🏾",
+ "man_in_business_suit_levitating::skin-tone-6": "🕴🏿",
+ "dancers": "👯",
+ "men-with-bunny-ears-partying": "👯‍♂️",
+ "man-with-bunny-ears-partying": "👯‍♂️",
+ "women-with-bunny-ears-partying": "👯‍♀️",
+ "woman-with-bunny-ears-partying": "👯‍♀️",
+ "person_in_steamy_room": "🧖",
+ "person_in_steamy_room::skin-tone-2": "🧖🏻",
+ "person_in_steamy_room::skin-tone-3": "🧖🏼",
+ "person_in_steamy_room::skin-tone-4": "🧖🏽",
+ "person_in_steamy_room::skin-tone-5": "🧖🏾",
+ "person_in_steamy_room::skin-tone-6": "🧖🏿",
+ "man_in_steamy_room": "🧖‍♂️",
+ "man_in_steamy_room::skin-tone-2": "🧖🏻‍♂️",
+ "man_in_steamy_room::skin-tone-3": "🧖🏼‍♂️",
+ "man_in_steamy_room::skin-tone-4": "🧖🏽‍♂️",
+ "man_in_steamy_room::skin-tone-5": "🧖🏾‍♂️",
+ "man_in_steamy_room::skin-tone-6": "🧖🏿‍♂️",
+ "woman_in_steamy_room": "🧖‍♀️",
+ "woman_in_steamy_room::skin-tone-2": "🧖🏻‍♀️",
+ "woman_in_steamy_room::skin-tone-3": "🧖🏼‍♀️",
+ "woman_in_steamy_room::skin-tone-4": "🧖🏽‍♀️",
+ "woman_in_steamy_room::skin-tone-5": "🧖🏾‍♀️",
+ "woman_in_steamy_room::skin-tone-6": "🧖🏿‍♀️",
+ "person_climbing": "🧗",
+ "person_climbing::skin-tone-2": "🧗🏻",
+ "person_climbing::skin-tone-3": "🧗🏼",
+ "person_climbing::skin-tone-4": "🧗🏽",
+ "person_climbing::skin-tone-5": "🧗🏾",
+ "person_climbing::skin-tone-6": "🧗🏿",
+ "man_climbing": "🧗‍♂️",
+ "man_climbing::skin-tone-2": "🧗🏻‍♂️",
+ "man_climbing::skin-tone-3": "🧗🏼‍♂️",
+ "man_climbing::skin-tone-4": "🧗🏽‍♂️",
+ "man_climbing::skin-tone-5": "🧗🏾‍♂️",
+ "man_climbing::skin-tone-6": "🧗🏿‍♂️",
+ "woman_climbing": "🧗‍♀️",
+ "woman_climbing::skin-tone-2": "🧗🏻‍♀️",
+ "woman_climbing::skin-tone-3": "🧗🏼‍♀️",
+ "woman_climbing::skin-tone-4": "🧗🏽‍♀️",
+ "woman_climbing::skin-tone-5": "🧗🏾‍♀️",
+ "woman_climbing::skin-tone-6": "🧗🏿‍♀️",
+ "fencer": "🤺",
+ "horse_racing": "🏇",
+ "horse_racing::skin-tone-2": "🏇🏻",
+ "horse_racing::skin-tone-3": "🏇🏼",
+ "horse_racing::skin-tone-4": "🏇🏽",
+ "horse_racing::skin-tone-5": "🏇🏾",
+ "horse_racing::skin-tone-6": "🏇🏿",
+ "skier": "⛷️",
+ "snowboarder": "🏂",
+ "snowboarder::skin-tone-2": "🏂🏻",
+ "snowboarder::skin-tone-3": "🏂🏼",
+ "snowboarder::skin-tone-4": "🏂🏽",
+ "snowboarder::skin-tone-5": "🏂🏾",
+ "snowboarder::skin-tone-6": "🏂🏿",
+ "golfer": "🏌️",
+ "golfer::skin-tone-2": "🏌🏻",
+ "golfer::skin-tone-3": "🏌🏼",
+ "golfer::skin-tone-4": "🏌🏽",
+ "golfer::skin-tone-5": "🏌🏾",
+ "golfer::skin-tone-6": "🏌🏿",
+ "man-golfing": "🏌️‍♂️",
+ "man-golfing::skin-tone-2": "🏌🏻‍♂️",
+ "man-golfing::skin-tone-3": "🏌🏼‍♂️",
+ "man-golfing::skin-tone-4": "🏌🏽‍♂️",
+ "man-golfing::skin-tone-5": "🏌🏾‍♂️",
+ "man-golfing::skin-tone-6": "🏌🏿‍♂️",
+ "woman-golfing": "🏌️‍♀️",
+ "woman-golfing::skin-tone-2": "🏌🏻‍♀️",
+ "woman-golfing::skin-tone-3": "🏌🏼‍♀️",
+ "woman-golfing::skin-tone-4": "🏌🏽‍♀️",
+ "woman-golfing::skin-tone-5": "🏌🏾‍♀️",
+ "woman-golfing::skin-tone-6": "🏌🏿‍♀️",
+ "surfer": "🏄",
+ "surfer::skin-tone-2": "🏄🏻",
+ "surfer::skin-tone-3": "🏄🏼",
+ "surfer::skin-tone-4": "🏄🏽",
+ "surfer::skin-tone-5": "🏄🏾",
+ "surfer::skin-tone-6": "🏄🏿",
+ "man-surfing": "🏄‍♂️",
+ "man-surfing::skin-tone-2": "🏄🏻‍♂️",
+ "man-surfing::skin-tone-3": "🏄🏼‍♂️",
+ "man-surfing::skin-tone-4": "🏄🏽‍♂️",
+ "man-surfing::skin-tone-5": "🏄🏾‍♂️",
+ "man-surfing::skin-tone-6": "🏄🏿‍♂️",
+ "woman-surfing": "🏄‍♀️",
+ "woman-surfing::skin-tone-2": "🏄🏻‍♀️",
+ "woman-surfing::skin-tone-3": "🏄🏼‍♀️",
+ "woman-surfing::skin-tone-4": "🏄🏽‍♀️",
+ "woman-surfing::skin-tone-5": "🏄🏾‍♀️",
+ "woman-surfing::skin-tone-6": "🏄🏿‍♀️",
+ "rowboat": "🚣",
+ "rowboat::skin-tone-2": "🚣🏻",
+ "rowboat::skin-tone-3": "🚣🏼",
+ "rowboat::skin-tone-4": "🚣🏽",
+ "rowboat::skin-tone-5": "🚣🏾",
+ "rowboat::skin-tone-6": "🚣🏿",
+ "man-rowing-boat": "🚣‍♂️",
+ "man-rowing-boat::skin-tone-2": "🚣🏻‍♂️",
+ "man-rowing-boat::skin-tone-3": "🚣🏼‍♂️",
+ "man-rowing-boat::skin-tone-4": "🚣🏽‍♂️",
+ "man-rowing-boat::skin-tone-5": "🚣🏾‍♂️",
+ "man-rowing-boat::skin-tone-6": "🚣🏿‍♂️",
+ "woman-rowing-boat": "🚣‍♀️",
+ "woman-rowing-boat::skin-tone-2": "🚣🏻‍♀️",
+ "woman-rowing-boat::skin-tone-3": "🚣🏼‍♀️",
+ "woman-rowing-boat::skin-tone-4": "🚣🏽‍♀️",
+ "woman-rowing-boat::skin-tone-5": "🚣🏾‍♀️",
+ "woman-rowing-boat::skin-tone-6": "🚣🏿‍♀️",
+ "swimmer": "🏊",
+ "swimmer::skin-tone-2": "🏊🏻",
+ "swimmer::skin-tone-3": "🏊🏼",
+ "swimmer::skin-tone-4": "🏊🏽",
+ "swimmer::skin-tone-5": "🏊🏾",
+ "swimmer::skin-tone-6": "🏊🏿",
+ "man-swimming": "🏊‍♂️",
+ "man-swimming::skin-tone-2": "🏊🏻‍♂️",
+ "man-swimming::skin-tone-3": "🏊🏼‍♂️",
+ "man-swimming::skin-tone-4": "🏊🏽‍♂️",
+ "man-swimming::skin-tone-5": "🏊🏾‍♂️",
+ "man-swimming::skin-tone-6": "🏊🏿‍♂️",
+ "woman-swimming": "🏊‍♀️",
+ "woman-swimming::skin-tone-2": "🏊🏻‍♀️",
+ "woman-swimming::skin-tone-3": "🏊🏼‍♀️",
+ "woman-swimming::skin-tone-4": "🏊🏽‍♀️",
+ "woman-swimming::skin-tone-5": "🏊🏾‍♀️",
+ "woman-swimming::skin-tone-6": "🏊🏿‍♀️",
+ "person_with_ball": "⛹️",
+ "person_with_ball::skin-tone-2": "⛹🏻",
+ "person_with_ball::skin-tone-3": "⛹🏼",
+ "person_with_ball::skin-tone-4": "⛹🏽",
+ "person_with_ball::skin-tone-5": "⛹🏾",
+ "person_with_ball::skin-tone-6": "⛹🏿",
+ "man-bouncing-ball": "⛹️‍♂️",
+ "man-bouncing-ball::skin-tone-2": "⛹🏻‍♂️",
+ "man-bouncing-ball::skin-tone-3": "⛹🏼‍♂️",
+ "man-bouncing-ball::skin-tone-4": "⛹🏽‍♂️",
+ "man-bouncing-ball::skin-tone-5": "⛹🏾‍♂️",
+ "man-bouncing-ball::skin-tone-6": "⛹🏿‍♂️",
+ "woman-bouncing-ball": "⛹️‍♀️",
+ "woman-bouncing-ball::skin-tone-2": "⛹🏻‍♀️",
+ "woman-bouncing-ball::skin-tone-3": "⛹🏼‍♀️",
+ "woman-bouncing-ball::skin-tone-4": "⛹🏽‍♀️",
+ "woman-bouncing-ball::skin-tone-5": "⛹🏾‍♀️",
+ "woman-bouncing-ball::skin-tone-6": "⛹🏿‍♀️",
+ "weight_lifter": "🏋️",
+ "weight_lifter::skin-tone-2": "🏋🏻",
+ "weight_lifter::skin-tone-3": "🏋🏼",
+ "weight_lifter::skin-tone-4": "🏋🏽",
+ "weight_lifter::skin-tone-5": "🏋🏾",
+ "weight_lifter::skin-tone-6": "🏋🏿",
+ "man-lifting-weights": "🏋️‍♂️",
+ "man-lifting-weights::skin-tone-2": "🏋🏻‍♂️",
+ "man-lifting-weights::skin-tone-3": "🏋🏼‍♂️",
+ "man-lifting-weights::skin-tone-4": "🏋🏽‍♂️",
+ "man-lifting-weights::skin-tone-5": "🏋🏾‍♂️",
+ "man-lifting-weights::skin-tone-6": "🏋🏿‍♂️",
+ "woman-lifting-weights": "🏋️‍♀️",
+ "woman-lifting-weights::skin-tone-2": "🏋🏻‍♀️",
+ "woman-lifting-weights::skin-tone-3": "🏋🏼‍♀️",
+ "woman-lifting-weights::skin-tone-4": "🏋🏽‍♀️",
+ "woman-lifting-weights::skin-tone-5": "🏋🏾‍♀️",
+ "woman-lifting-weights::skin-tone-6": "🏋🏿‍♀️",
+ "bicyclist": "🚴",
+ "bicyclist::skin-tone-2": "🚴🏻",
+ "bicyclist::skin-tone-3": "🚴🏼",
+ "bicyclist::skin-tone-4": "🚴🏽",
+ "bicyclist::skin-tone-5": "🚴🏾",
+ "bicyclist::skin-tone-6": "🚴🏿",
+ "man-biking": "🚴‍♂️",
+ "man-biking::skin-tone-2": "🚴🏻‍♂️",
+ "man-biking::skin-tone-3": "🚴🏼‍♂️",
+ "man-biking::skin-tone-4": "🚴🏽‍♂️",
+ "man-biking::skin-tone-5": "🚴🏾‍♂️",
+ "man-biking::skin-tone-6": "🚴🏿‍♂️",
+ "woman-biking": "🚴‍♀️",
+ "woman-biking::skin-tone-2": "🚴🏻‍♀️",
+ "woman-biking::skin-tone-3": "🚴🏼‍♀️",
+ "woman-biking::skin-tone-4": "🚴🏽‍♀️",
+ "woman-biking::skin-tone-5": "🚴🏾‍♀️",
+ "woman-biking::skin-tone-6": "🚴🏿‍♀️",
+ "mountain_bicyclist": "🚵",
+ "mountain_bicyclist::skin-tone-2": "🚵🏻",
+ "mountain_bicyclist::skin-tone-3": "🚵🏼",
+ "mountain_bicyclist::skin-tone-4": "🚵🏽",
+ "mountain_bicyclist::skin-tone-5": "🚵🏾",
+ "mountain_bicyclist::skin-tone-6": "🚵🏿",
+ "man-mountain-biking": "🚵‍♂️",
+ "man-mountain-biking::skin-tone-2": "🚵🏻‍♂️",
+ "man-mountain-biking::skin-tone-3": "🚵🏼‍♂️",
+ "man-mountain-biking::skin-tone-4": "🚵🏽‍♂️",
+ "man-mountain-biking::skin-tone-5": "🚵🏾‍♂️",
+ "man-mountain-biking::skin-tone-6": "🚵🏿‍♂️",
+ "woman-mountain-biking": "🚵‍♀️",
+ "woman-mountain-biking::skin-tone-2": "🚵🏻‍♀️",
+ "woman-mountain-biking::skin-tone-3": "🚵🏼‍♀️",
+ "woman-mountain-biking::skin-tone-4": "🚵🏽‍♀️",
+ "woman-mountain-biking::skin-tone-5": "🚵🏾‍♀️",
+ "woman-mountain-biking::skin-tone-6": "🚵🏿‍♀️",
+ "person_doing_cartwheel": "🤸",
+ "person_doing_cartwheel::skin-tone-2": "🤸🏻",
+ "person_doing_cartwheel::skin-tone-3": "🤸🏼",
+ "person_doing_cartwheel::skin-tone-4": "🤸🏽",
+ "person_doing_cartwheel::skin-tone-5": "🤸🏾",
+ "person_doing_cartwheel::skin-tone-6": "🤸🏿",
+ "man-cartwheeling": "🤸‍♂️",
+ "man-cartwheeling::skin-tone-2": "🤸🏻‍♂️",
+ "man-cartwheeling::skin-tone-3": "🤸🏼‍♂️",
+ "man-cartwheeling::skin-tone-4": "🤸🏽‍♂️",
+ "man-cartwheeling::skin-tone-5": "🤸🏾‍♂️",
+ "man-cartwheeling::skin-tone-6": "🤸🏿‍♂️",
+ "woman-cartwheeling": "🤸‍♀️",
+ "woman-cartwheeling::skin-tone-2": "🤸🏻‍♀️",
+ "woman-cartwheeling::skin-tone-3": "🤸🏼‍♀️",
+ "woman-cartwheeling::skin-tone-4": "🤸🏽‍♀️",
+ "woman-cartwheeling::skin-tone-5": "🤸🏾‍♀️",
+ "woman-cartwheeling::skin-tone-6": "🤸🏿‍♀️",
+ "wrestlers": "🤼",
+ "man-wrestling": "🤼‍♂️",
+ "woman-wrestling": "🤼‍♀️",
+ "water_polo": "🤽",
+ "water_polo::skin-tone-2": "🤽🏻",
+ "water_polo::skin-tone-3": "🤽🏼",
+ "water_polo::skin-tone-4": "🤽🏽",
+ "water_polo::skin-tone-5": "🤽🏾",
+ "water_polo::skin-tone-6": "🤽🏿",
+ "man-playing-water-polo": "🤽‍♂️",
+ "man-playing-water-polo::skin-tone-2": "🤽🏻‍♂️",
+ "man-playing-water-polo::skin-tone-3": "🤽🏼‍♂️",
+ "man-playing-water-polo::skin-tone-4": "🤽🏽‍♂️",
+ "man-playing-water-polo::skin-tone-5": "🤽🏾‍♂️",
+ "man-playing-water-polo::skin-tone-6": "🤽🏿‍♂️",
+ "woman-playing-water-polo": "🤽‍♀️",
+ "woman-playing-water-polo::skin-tone-2": "🤽🏻‍♀️",
+ "woman-playing-water-polo::skin-tone-3": "🤽🏼‍♀️",
+ "woman-playing-water-polo::skin-tone-4": "🤽🏽‍♀️",
+ "woman-playing-water-polo::skin-tone-5": "🤽🏾‍♀️",
+ "woman-playing-water-polo::skin-tone-6": "🤽🏿‍♀️",
+ "handball": "🤾",
+ "handball::skin-tone-2": "🤾🏻",
+ "handball::skin-tone-3": "🤾🏼",
+ "handball::skin-tone-4": "🤾🏽",
+ "handball::skin-tone-5": "🤾🏾",
+ "handball::skin-tone-6": "🤾🏿",
+ "man-playing-handball": "🤾‍♂️",
+ "man-playing-handball::skin-tone-2": "🤾🏻‍♂️",
+ "man-playing-handball::skin-tone-3": "🤾🏼‍♂️",
+ "man-playing-handball::skin-tone-4": "🤾🏽‍♂️",
+ "man-playing-handball::skin-tone-5": "🤾🏾‍♂️",
+ "man-playing-handball::skin-tone-6": "🤾🏿‍♂️",
+ "woman-playing-handball": "🤾‍♀️",
+ "woman-playing-handball::skin-tone-2": "🤾🏻‍♀️",
+ "woman-playing-handball::skin-tone-3": "🤾🏼‍♀️",
+ "woman-playing-handball::skin-tone-4": "🤾🏽‍♀️",
+ "woman-playing-handball::skin-tone-5": "🤾🏾‍♀️",
+ "woman-playing-handball::skin-tone-6": "🤾🏿‍♀️",
+ "juggling": "🤹",
+ "juggling::skin-tone-2": "🤹🏻",
+ "juggling::skin-tone-3": "🤹🏼",
+ "juggling::skin-tone-4": "🤹🏽",
+ "juggling::skin-tone-5": "🤹🏾",
+ "juggling::skin-tone-6": "🤹🏿",
+ "man-juggling": "🤹‍♂️",
+ "man-juggling::skin-tone-2": "🤹🏻‍♂️",
+ "man-juggling::skin-tone-3": "🤹🏼‍♂️",
+ "man-juggling::skin-tone-4": "🤹🏽‍♂️",
+ "man-juggling::skin-tone-5": "🤹🏾‍♂️",
+ "man-juggling::skin-tone-6": "🤹🏿‍♂️",
+ "woman-juggling": "🤹‍♀️",
+ "woman-juggling::skin-tone-2": "🤹🏻‍♀️",
+ "woman-juggling::skin-tone-3": "🤹🏼‍♀️",
+ "woman-juggling::skin-tone-4": "🤹🏽‍♀️",
+ "woman-juggling::skin-tone-5": "🤹🏾‍♀️",
+ "woman-juggling::skin-tone-6": "🤹🏿‍♀️",
+ "person_in_lotus_position": "🧘",
+ "person_in_lotus_position::skin-tone-2": "🧘🏻",
+ "person_in_lotus_position::skin-tone-3": "🧘🏼",
+ "person_in_lotus_position::skin-tone-4": "🧘🏽",
+ "person_in_lotus_position::skin-tone-5": "🧘🏾",
+ "person_in_lotus_position::skin-tone-6": "🧘🏿",
+ "man_in_lotus_position": "🧘‍♂️",
+ "man_in_lotus_position::skin-tone-2": "🧘🏻‍♂️",
+ "man_in_lotus_position::skin-tone-3": "🧘🏼‍♂️",
+ "man_in_lotus_position::skin-tone-4": "🧘🏽‍♂️",
+ "man_in_lotus_position::skin-tone-5": "🧘🏾‍♂️",
+ "man_in_lotus_position::skin-tone-6": "🧘🏿‍♂️",
+ "woman_in_lotus_position": "🧘‍♀️",
+ "woman_in_lotus_position::skin-tone-2": "🧘🏻‍♀️",
+ "woman_in_lotus_position::skin-tone-3": "🧘🏼‍♀️",
+ "woman_in_lotus_position::skin-tone-4": "🧘🏽‍♀️",
+ "woman_in_lotus_position::skin-tone-5": "🧘🏾‍♀️",
+ "woman_in_lotus_position::skin-tone-6": "🧘🏿‍♀️",
+ "bath": "🛀",
+ "bath::skin-tone-2": "🛀🏻",
+ "bath::skin-tone-3": "🛀🏼",
+ "bath::skin-tone-4": "🛀🏽",
+ "bath::skin-tone-5": "🛀🏾",
+ "bath::skin-tone-6": "🛀🏿",
+ "sleeping_accommodation": "🛌",
+ "sleeping_accommodation::skin-tone-2": "🛌🏻",
+ "sleeping_accommodation::skin-tone-3": "🛌🏼",
+ "sleeping_accommodation::skin-tone-4": "🛌🏽",
+ "sleeping_accommodation::skin-tone-5": "🛌🏾",
+ "sleeping_accommodation::skin-tone-6": "🛌🏿",
+ "people_holding_hands": "🧑‍🤝‍🧑",
+ "people_holding_hands::skin-tone-2": "🧑🏻‍🤝‍🧑🏻",
+ "people_holding_hands::skin-tone-3": "🧑🏼‍🤝‍🧑🏼",
+ "people_holding_hands::skin-tone-4": "🧑🏽‍🤝‍🧑🏽",
+ "people_holding_hands::skin-tone-5": "🧑🏾‍🤝‍🧑🏾",
+ "people_holding_hands::skin-tone-6": "🧑🏿‍🤝‍🧑🏿",
+ "two_women_holding_hands": "👭",
+ "women_holding_hands": "👭",
+ "two_women_holding_hands::skin-tone-2": "👭🏻",
+ "women_holding_hands::skin-tone-2": "👭🏻",
+ "two_women_holding_hands::skin-tone-3": "👭🏼",
+ "women_holding_hands::skin-tone-3": "👭🏼",
+ "two_women_holding_hands::skin-tone-4": "👭🏽",
+ "women_holding_hands::skin-tone-4": "👭🏽",
+ "two_women_holding_hands::skin-tone-5": "👭🏾",
+ "women_holding_hands::skin-tone-5": "👭🏾",
+ "two_women_holding_hands::skin-tone-6": "👭🏿",
+ "women_holding_hands::skin-tone-6": "👭🏿",
+ "man_and_woman_holding_hands": "👫",
+ "couple": "👫",
+ "man_and_woman_holding_hands::skin-tone-2": "👫🏻",
+ "couple::skin-tone-2": "👫🏻",
+ "man_and_woman_holding_hands::skin-tone-3": "👫🏼",
+ "couple::skin-tone-3": "👫🏼",
+ "man_and_woman_holding_hands::skin-tone-4": "👫🏽",
+ "couple::skin-tone-4": "👫🏽",
+ "man_and_woman_holding_hands::skin-tone-5": "👫🏾",
+ "couple::skin-tone-5": "👫🏾",
+ "man_and_woman_holding_hands::skin-tone-6": "👫🏿",
+ "couple::skin-tone-6": "👫🏿",
+ "two_men_holding_hands": "👬",
+ "men_holding_hands": "👬",
+ "two_men_holding_hands::skin-tone-2": "👬🏻",
+ "men_holding_hands::skin-tone-2": "👬🏻",
+ "two_men_holding_hands::skin-tone-3": "👬🏼",
+ "men_holding_hands::skin-tone-3": "👬🏼",
+ "two_men_holding_hands::skin-tone-4": "👬🏽",
+ "men_holding_hands::skin-tone-4": "👬🏽",
+ "two_men_holding_hands::skin-tone-5": "👬🏾",
+ "men_holding_hands::skin-tone-5": "👬🏾",
+ "two_men_holding_hands::skin-tone-6": "👬🏿",
+ "men_holding_hands::skin-tone-6": "👬🏿",
+ "couplekiss": "💏",
+ "couplekiss::skin-tone-2": "💏🏻",
+ "couplekiss::skin-tone-3": "💏🏼",
+ "couplekiss::skin-tone-4": "💏🏽",
+ "couplekiss::skin-tone-5": "💏🏾",
+ "couplekiss::skin-tone-6": "💏🏿",
+ "woman-kiss-man": "👩‍❤️‍💋‍👨",
+ "woman-kiss-man::skin-tone-2": "👩🏻‍❤️‍💋‍👨🏻",
+ "woman-kiss-man::skin-tone-3": "👩🏼‍❤️‍💋‍👨🏼",
+ "woman-kiss-man::skin-tone-4": "👩🏽‍❤️‍💋‍👨🏽",
+ "woman-kiss-man::skin-tone-5": "👩🏾‍❤️‍💋‍👨🏾",
+ "woman-kiss-man::skin-tone-6": "👩🏿‍❤️‍💋‍👨🏿",
+ "man-kiss-man": "👨‍❤️‍💋‍👨",
+ "man-kiss-man::skin-tone-2": "👨🏻‍❤️‍💋‍👨🏻",
+ "man-kiss-man::skin-tone-3": "👨🏼‍❤️‍💋‍👨🏼",
+ "man-kiss-man::skin-tone-4": "👨🏽‍❤️‍💋‍👨🏽",
+ "man-kiss-man::skin-tone-5": "👨🏾‍❤️‍💋‍👨🏾",
+ "man-kiss-man::skin-tone-6": "👨🏿‍❤️‍💋‍👨🏿",
+ "woman-kiss-woman": "👩‍❤️‍💋‍👩",
+ "woman-kiss-woman::skin-tone-2": "👩🏻‍❤️‍💋‍👩🏻",
+ "woman-kiss-woman::skin-tone-3": "👩🏼‍❤️‍💋‍👩🏼",
+ "woman-kiss-woman::skin-tone-4": "👩🏽‍❤️‍💋‍👩🏽",
+ "woman-kiss-woman::skin-tone-5": "👩🏾‍❤️‍💋‍👩🏾",
+ "woman-kiss-woman::skin-tone-6": "👩🏿‍❤️‍💋‍👩🏿",
+ "couple_with_heart": "💑",
+ "couple_with_heart::skin-tone-2": "💑🏻",
+ "couple_with_heart::skin-tone-3": "💑🏼",
+ "couple_with_heart::skin-tone-4": "💑🏽",
+ "couple_with_heart::skin-tone-5": "💑🏾",
+ "couple_with_heart::skin-tone-6": "💑🏿",
+ "woman-heart-man": "👩‍❤️‍👨",
+ "woman-heart-man::skin-tone-2": "👩🏻‍❤️‍👨🏻",
+ "woman-heart-man::skin-tone-3": "👩🏼‍❤️‍👨🏼",
+ "woman-heart-man::skin-tone-4": "👩🏽‍❤️‍👨🏽",
+ "woman-heart-man::skin-tone-5": "👩🏾‍❤️‍👨🏾",
+ "woman-heart-man::skin-tone-6": "👩🏿‍❤️‍👨🏿",
+ "man-heart-man": "👨‍❤️‍👨",
+ "man-heart-man::skin-tone-2": "👨🏻‍❤️‍👨🏻",
+ "man-heart-man::skin-tone-3": "👨🏼‍❤️‍👨🏼",
+ "man-heart-man::skin-tone-4": "👨🏽‍❤️‍👨🏽",
+ "man-heart-man::skin-tone-5": "👨🏾‍❤️‍👨🏾",
+ "man-heart-man::skin-tone-6": "👨🏿‍❤️‍👨🏿",
+ "woman-heart-woman": "👩‍❤️‍👩",
+ "woman-heart-woman::skin-tone-2": "👩🏻‍❤️‍👩🏻",
+ "woman-heart-woman::skin-tone-3": "👩🏼‍❤️‍👩🏼",
+ "woman-heart-woman::skin-tone-4": "👩🏽‍❤️‍👩🏽",
+ "woman-heart-woman::skin-tone-5": "👩🏾‍❤️‍👩🏾",
+ "woman-heart-woman::skin-tone-6": "👩🏿‍❤️‍👩🏿",
+ "family": "👪",
+ "man-woman-boy": "👨‍👩‍👦",
+ "man-woman-girl": "👨‍👩‍👧",
+ "man-woman-girl-boy": "👨‍👩‍👧‍👦",
+ "man-woman-boy-boy": "👨‍👩‍👦‍👦",
+ "man-woman-girl-girl": "👨‍👩‍👧‍👧",
+ "man-man-boy": "👨‍👨‍👦",
+ "man-man-girl": "👨‍👨‍👧",
+ "man-man-girl-boy": "👨‍👨‍👧‍👦",
+ "man-man-boy-boy": "👨‍👨‍👦‍👦",
+ "man-man-girl-girl": "👨‍👨‍👧‍👧",
+ "woman-woman-boy": "👩‍👩‍👦",
+ "woman-woman-girl": "👩‍👩‍👧",
+ "woman-woman-girl-boy": "👩‍👩‍👧‍👦",
+ "woman-woman-boy-boy": "👩‍👩‍👦‍👦",
+ "woman-woman-girl-girl": "👩‍👩‍👧‍👧",
+ "man-boy": "👨‍👦",
+ "man-boy-boy": "👨‍👦‍👦",
+ "man-girl": "👨‍👧",
+ "man-girl-boy": "👨‍👧‍👦",
+ "man-girl-girl": "👨‍👧‍👧",
+ "woman-boy": "👩‍👦",
+ "woman-boy-boy": "👩‍👦‍👦",
+ "woman-girl": "👩‍👧",
+ "woman-girl-boy": "👩‍👧‍👦",
+ "woman-girl-girl": "👩‍👧‍👧",
+ "speaking_head_in_silhouette": "🗣️",
+ "bust_in_silhouette": "👤",
+ "busts_in_silhouette": "👥",
+ "people_hugging": "🫂",
+ "footprints": "👣",
+ "monkey_face": "🐵",
+ "monkey": "🐒",
+ "gorilla": "🦍",
+ "orangutan": "🦧",
+ "dog": "🐶",
+ "dog2": "🐕",
+ "guide_dog": "🦮",
+ "service_dog": "🐕‍🦺",
+ "poodle": "🐩",
+ "wolf": "🐺",
+ "fox_face": "🦊",
+ "raccoon": "🦝",
+ "cat": "🐱",
+ "cat2": "🐈",
+ "black_cat": "🐈‍⬛",
+ "lion_face": "🦁",
+ "tiger": "🐯",
+ "tiger2": "🐅",
+ "leopard": "🐆",
+ "horse": "🐴",
+ "racehorse": "🐎",
+ "unicorn_face": "🦄",
+ "zebra_face": "🦓",
+ "deer": "🦌",
+ "bison": "🦬",
+ "cow": "🐮",
+ "ox": "🐂",
+ "water_buffalo": "🐃",
+ "cow2": "🐄",
+ "pig": "🐷",
+ "pig2": "🐖",
+ "boar": "🐗",
+ "pig_nose": "🐽",
+ "ram": "🐏",
+ "sheep": "🐑",
+ "goat": "🐐",
+ "dromedary_camel": "🐪",
+ "camel": "🐫",
+ "llama": "🦙",
+ "giraffe_face": "🦒",
+ "elephant": "🐘",
+ "mammoth": "🦣",
+ "rhinoceros": "🦏",
+ "hippopotamus": "🦛",
+ "mouse": "🐭",
+ "mouse2": "🐁",
+ "rat": "🐀",
+ "hamster": "🐹",
+ "rabbit": "🐰",
+ "rabbit2": "🐇",
+ "chipmunk": "🐿️",
+ "beaver": "🦫",
+ "hedgehog": "🦔",
+ "bat": "🦇",
+ "bear": "🐻",
+ "polar_bear": "🐻‍❄️",
+ "koala": "🐨",
+ "panda_face": "🐼",
+ "sloth": "🦥",
+ "otter": "🦦",
+ "skunk": "🦨",
+ "kangaroo": "🦘",
+ "badger": "🦡",
+ "feet": "🐾",
+ "paw_prints": "🐾",
+ "turkey": "🦃",
+ "chicken": "🐔",
+ "rooster": "🐓",
+ "hatching_chick": "🐣",
+ "baby_chick": "🐤",
+ "hatched_chick": "🐥",
+ "bird": "🐦",
+ "penguin": "🐧",
+ "dove_of_peace": "🕊️",
+ "eagle": "🦅",
+ "duck": "🦆",
+ "swan": "🦢",
+ "owl": "🦉",
+ "dodo": "🦤",
+ "feather": "🪶",
+ "flamingo": "🦩",
+ "peacock": "🦚",
+ "parrot": "🦜",
+ "frog": "🐸",
+ "crocodile": "🐊",
+ "turtle": "🐢",
+ "lizard": "🦎",
+ "snake": "🐍",
+ "dragon_face": "🐲",
+ "dragon": "🐉",
+ "sauropod": "🦕",
+ "t-rex": "🦖",
+ "philosoraptor": "🦖",
+ "whale": "🐳",
+ "whale2": "🐋",
+ "dolphin": "🐬",
+ "flipper": "🐬",
+ "seal": "🦭",
+ "fish": "🐟",
+ "tropical_fish": "🐠",
+ "blowfish": "🐡",
+ "shark": "🦈",
+ "octopus": "🐙",
+ "shell": "🐚",
+ "coral": "🪸",
+ "snail": "🐌",
+ "butterfly": "🦋",
+ "bug": "🐛",
+ "ant": "🐜",
+ "bee": "🐝",
+ "honeybee": "🐝",
+ "beetle": "🪲",
+ "ladybug": "🐞",
+ "lady_beetle": "🐞",
+ "cricket": "🦗",
+ "cockroach": "🪳",
+ "spider": "🕷️",
+ "spider_web": "🕸️",
+ "scorpion": "🦂",
+ "mosquito": "🦟",
+ "fly": "🪰",
+ "worm": "🪱",
+ "microbe": "🦠",
+ "bouquet": "💐",
+ "cherry_blossom": "🌸",
+ "white_flower": "💮",
+ "lotus": "🪷",
+ "rosette": "🏵️",
+ "rose": "🌹",
+ "wilted_flower": "🥀",
+ "hibiscus": "🌺",
+ "sunflower": "🌻",
+ "blossom": "🌼",
+ "tulip": "🌷",
+ "seedling": "🌱",
+ "potted_plant": "🪴",
+ "evergreen_tree": "🌲",
+ "deciduous_tree": "🌳",
+ "palm_tree": "🌴",
+ "cactus": "🌵",
+ "ear_of_rice": "🌾",
+ "herb": "🌿",
+ "shamrock": "☘️",
+ "four_leaf_clover": "🍀",
+ "maple_leaf": "🍁",
+ "fallen_leaf": "🍂",
+ "leaves": "🍃",
+ "empty_nest": "🪹",
+ "nest_with_eggs": "🪺",
+ "grapes": "🍇",
+ "melon": "🍈",
+ "watermelon": "🍉",
+ "tangerine": "🍊",
+ "lemon": "🍋",
+ "banana": "🍌",
+ "pineapple": "🍍",
+ "mango": "🥭",
+ "apple": "🍎",
+ "green_apple": "🍏",
+ "pear": "🍐",
+ "peach": "🍑",
+ "cherries": "🍒",
+ "strawberry": "🍓",
+ "blueberries": "🫐",
+ "kiwifruit": "🥝",
+ "tomato": "🍅",
+ "olive": "🫒",
+ "coconut": "🥥",
+ "avocado": "🥑",
+ "eggplant": "🍆",
+ "potato": "🥔",
+ "carrot": "🥕",
+ "corn": "🌽",
+ "hot_pepper": "🌶️",
+ "bell_pepper": "🫑",
+ "cucumber": "🥒",
+ "leafy_green": "🥬",
+ "broccoli": "🥦",
+ "garlic": "🧄",
+ "onion": "🧅",
+ "mushroom": "🍄",
+ "peanuts": "🥜",
+ "beans": "🫘",
+ "chestnut": "🌰",
+ "bread": "🍞",
+ "croissant": "🥐",
+ "baguette_bread": "🥖",
+ "flatbread": "🫓",
+ "pretzel": "🥨",
+ "bagel": "🥯",
+ "pancakes": "🥞",
+ "waffle": "🧇",
+ "cheese_wedge": "🧀",
+ "meat_on_bone": "🍖",
+ "poultry_leg": "🍗",
+ "cut_of_meat": "🥩",
+ "bacon": "🥓",
+ "hamburger": "🍔",
+ "fries": "🍟",
+ "pizza": "🍕",
+ "hotdog": "🌭",
+ "sandwich": "🥪",
+ "taco": "🌮",
+ "burrito": "🌯",
+ "tamale": "🫔",
+ "stuffed_flatbread": "🥙",
+ "falafel": "🧆",
+ "egg": "🥚",
+ "fried_egg": "🍳",
+ "cooking": "🍳",
+ "shallow_pan_of_food": "🥘",
+ "stew": "🍲",
+ "fondue": "🫕",
+ "bowl_with_spoon": "🥣",
+ "green_salad": "🥗",
+ "popcorn": "🍿",
+ "butter": "🧈",
+ "salt": "🧂",
+ "canned_food": "🥫",
+ "bento": "🍱",
+ "rice_cracker": "🍘",
+ "rice_ball": "🍙",
+ "rice": "🍚",
+ "curry": "🍛",
+ "ramen": "🍜",
+ "spaghetti": "🍝",
+ "sweet_potato": "🍠",
+ "oden": "🍢",
+ "sushi": "🍣",
+ "fried_shrimp": "🍤",
+ "fish_cake": "🍥",
+ "moon_cake": "🥮",
+ "dango": "🍡",
+ "dumpling": "🥟",
+ "fortune_cookie": "🥠",
+ "takeout_box": "🥡",
+ "crab": "🦀",
+ "lobster": "🦞",
+ "shrimp": "🦐",
+ "squid": "🦑",
+ "oyster": "🦪",
+ "icecream": "🍦",
+ "shaved_ice": "🍧",
+ "ice_cream": "🍨",
+ "doughnut": "🍩",
+ "cookie": "🍪",
+ "birthday": "🎂",
+ "cake": "🍰",
+ "cupcake": "🧁",
+ "pie": "🥧",
+ "chocolate_bar": "🍫",
+ "candy": "🍬",
+ "lollipop": "🍭",
+ "custard": "🍮",
+ "honey_pot": "🍯",
+ "baby_bottle": "🍼",
+ "glass_of_milk": "🥛",
+ "coffee": "☕",
+ "teapot": "🫖",
+ "tea": "🍵",
+ "sake": "🍶",
+ "champagne": "🍾",
+ "wine_glass": "🍷",
+ "cocktail": "🍸",
+ "tropical_drink": "🍹",
+ "beer": "🍺",
+ "beers": "🍻",
+ "clinking_glasses": "🥂",
+ "tumbler_glass": "🥃",
+ "pouring_liquid": "🫗",
+ "cup_with_straw": "🥤",
+ "bubble_tea": "🧋",
+ "beverage_box": "🧃",
+ "mate_drink": "🧉",
+ "ice_cube": "🧊",
+ "chopsticks": "🥢",
+ "knife_fork_plate": "🍽️",
+ "fork_and_knife": "🍴",
+ "spoon": "🥄",
+ "hocho": "🔪",
+ "knife": "🔪",
+ "jar": "🫙",
+ "amphora": "🏺",
+ "earth_africa": "🌍",
+ "earth_americas": "🌎",
+ "earth_asia": "🌏",
+ "globe_with_meridians": "🌐",
+ "world_map": "🗺️",
+ "japan": "🗾",
+ "compass": "🧭",
+ "snow_capped_mountain": "🏔️",
+ "mountain": "⛰️",
+ "volcano": "🌋",
+ "mount_fuji": "🗻",
+ "camping": "🏕️",
+ "beach_with_umbrella": "🏖️",
+ "desert": "🏜️",
+ "desert_island": "🏝️",
+ "national_park": "🏞️",
+ "stadium": "🏟️",
+ "classical_building": "🏛️",
+ "building_construction": "🏗️",
+ "bricks": "🧱",
+ "databricks": "🧱",
+ "pydata": "🪨",
+ "rock": "🪨",
+ "wood": "🪵",
+ "hut": "🛖",
+ "house_buildings": "🏘️",
+ "derelict_house_building": "🏚️",
+ "house": "🏠",
+ "house_with_garden": "🏡",
+ "office": "🏢",
+ "post_office": "🏣",
+ "european_post_office": "🏤",
+ "hospital": "🏥",
+ "bank": "🏦",
+ "hotel": "🏨",
+ "love_hotel": "🏩",
+ "convenience_store": "🏪",
+ "school": "🏫",
+ "department_store": "🏬",
+ "factory": "🏭",
+ "japanese_castle": "🏯",
+ "european_castle": "🏰",
+ "wedding": "💒",
+ "tokyo_tower": "🗼",
+ "statue_of_liberty": "🗽",
+ "church": "⛪",
+ "mosque": "🕌",
+ "hindu_temple": "🛕",
+ "synagogue": "🕍",
+ "shinto_shrine": "⛩️",
+ "kaaba": "🕋",
+ "fountain": "⛲",
+ "tent": "⛺",
+ "foggy": "🌁",
+ "night_with_stars": "🌃",
+ "cityscape": "🏙️",
+ "sunrise_over_mountains": "🌄",
+ "sunrise": "🌅",
+ "city_sunset": "🌆",
+ "city_sunrise": "🌇",
+ "bridge_at_night": "🌉",
+ "hotsprings": "♨️",
+ "carousel_horse": "🎠",
+ "playground_slide": "🛝",
+ "ferris_wheel": "🎡",
+ "roller_coaster": "🎢",
+ "barber": "💈",
+ "circus_tent": "🎪",
+ "steam_locomotive": "🚂",
+ "railway_car": "🚃",
+ "bullettrain_side": "🚄",
+ "bullettrain_front": "🚅",
+ "train2": "🚆",
+ "metro": "🚇",
+ "light_rail": "🚈",
+ "station": "🚉",
+ "tram": "🚊",
+ "monorail": "🚝",
+ "mountain_railway": "🚞",
+ "train": "🚋",
+ "bus": "🚌",
+ "oncoming_bus": "🚍",
+ "trolleybus": "🚎",
+ "minibus": "🚐",
+ "ambulance": "🚑",
+ "fire_engine": "🚒",
+ "police_car": "🚓",
+ "oncoming_police_car": "🚔",
+ "taxi": "🚕",
+ "oncoming_taxi": "🚖",
+ "car": "🚗",
+ "red_car": "🚗",
+ "oncoming_automobile": "🚘",
+ "blue_car": "🚙",
+ "pickup_truck": "🛻",
+ "truck": "🚚",
+ "articulated_lorry": "🚛",
+ "tractor": "🚜",
+ "racing_car": "🏎️",
+ "racing_motorcycle": "🏍️",
+ "motor_scooter": "🛵",
+ "manual_wheelchair": "🦽",
+ "motorized_wheelchair": "🦼",
+ "auto_rickshaw": "🛺",
+ "bike": "🚲",
+ "scooter": "🛴",
+ "skateboard": "🛹",
+ "roller_skate": "🛼",
+ "busstop": "🚏",
+ "motorway": "🛣️",
+ "railway_track": "🛤️",
+ "oil_drum": "🛢️",
+ "fuelpump": "⛽",
+ "wheel": "🛞",
+ "rotating_light": "🚨",
+ "traffic_light": "🚥",
+ "vertical_traffic_light": "🚦",
+ "octagonal_sign": "🛑",
+ "construction": "🚧",
+ "anchor": "⚓",
+ "ring_buoy": "🛟",
+ "boat": "⛵",
+ "sailboat": "⛵",
+ "canoe": "🛶",
+ "speedboat": "🚤",
+ "passenger_ship": "🛳️",
+ "ferry": "⛴️",
+ "motor_boat": "🛥️",
+ "ship": "🚢",
+ "airplane": "✈️",
+ "small_airplane": "🛩️",
+ "airplane_departure": "🛫",
+ "airplane_arriving": "🛬",
+ "parachute": "🪂",
+ "seat": "💺",
+ "helicopter": "🚁",
+ "suspension_railway": "🚟",
+ "mountain_cableway": "🚠",
+ "aerial_tramway": "🚡",
+ "satellite": "🛰️",
+ "rocket": "🚀",
+ "rocketing": "🚀",
+ "rocking": "🚀",
+ "ahhhhhhhhh": "🚀",
+ "flying_saucer": "🛸",
+ "bellhop_bell": "🛎️",
+ "luggage": "🧳",
+ "hourglass": "⌛",
+ "hourglass_flowing_sand": "⏳",
+ "watch": "⌚",
+ "alarm_clock": "⏰",
+ "stopwatch": "⏱️",
+ "timer_clock": "⏲️",
+ "mantelpiece_clock": "🕰️",
+ "clock12": "🕛",
+ "clock1230": "🕧",
+ "clock1": "🕐",
+ "clock130": "🕜",
+ "clock2": "🕑",
+ "clock230": "🕝",
+ "clock3": "🕒",
+ "clock330": "🕞",
+ "clock4": "🕓",
+ "clock430": "🕟",
+ "clock5": "🕔",
+ "clock530": "🕠",
+ "clock6": "🕕",
+ "clock630": "🕡",
+ "clock7": "🕖",
+ "clock730": "🕢",
+ "clock8": "🕗",
+ "clock830": "🕣",
+ "clock9": "🕘",
+ "clock930": "🕤",
+ "clock10": "🕙",
+ "clock1030": "🕥",
+ "clock11": "🕚",
+ "clock1130": "🕦",
+ "new_moon": "🌑",
+ "waxing_crescent_moon": "🌒",
+ "first_quarter_moon": "🌓",
+ "moon": "🌔",
+ "waxing_gibbous_moon": "🌔",
+ "full_moon": "🌕",
+ "waning_gibbous_moon": "🌖",
+ "last_quarter_moon": "🌗",
+ "waning_crescent_moon": "🌘",
+ "crescent_moon": "🌙",
+ "new_moon_with_face": "🌚",
+ "first_quarter_moon_with_face": "🌛",
+ "last_quarter_moon_with_face": "🌜",
+ "thermometer": "🌡️",
+ "sunny": "☀️",
+ "full_moon_with_face": "🌝",
+ "sun_with_face": "🌞",
+ "ringed_planet": "🪐",
+ "star": "⭐",
+ "star2": "🌟",
+ "stars": "🌠",
+ "milky_way": "🌌",
+ "cloud": "☁️",
+ "partly_sunny": "⛅",
+ "thunder_cloud_and_rain": "⛈️",
+ "mostly_sunny": "🌤️",
+ "sun_small_cloud": "🌤️",
+ "barely_sunny": "🌥️",
+ "sun_behind_cloud": "🌥️",
+ "partly_sunny_rain": "🌦️",
+ "sun_behind_rain_cloud": "🌦️",
+ "rain_cloud": "🌧️",
+ "snow_cloud": "🌨️",
+ "lightning": "🌩️",
+ "lightning_cloud": "🌩️",
+ "tornado": "🌪️",
+ "tornado_cloud": "🌪️",
+ "fog": "🌫️",
+ "wind_blowing_face": "🌬️",
+ "cyclone": "🌀",
+ "rainbow": "🌈",
+ "rainbow-daggy": "🌈",
+ "closed_umbrella": "🌂",
+ "umbrella": "☂️",
+ "umbrella_with_rain_drops": "☔",
+ "umbrella_on_ground": "⛱️",
+ "zap": "⚡",
+ "snowflake": "❄️",
+ "snowman": "☃️",
+ "snowman_without_snow": "⛄",
+ "comet": "☄️",
+ "fire": "🔥",
+ "tuzki_onfire": "🔥",
+ "tuzki-onfire": "🔥",
+ "droplet": "💧",
+ "ocean": "🌊",
+ "jack_o_lantern": "🎃",
+ "christmas_tree": "🎄",
+ "fireworks": "🎆",
+ "sparkler": "🎇",
+ "firecracker": "🧨",
+ "sparkles": "✨",
+ "balloon": "🎈",
+ "tada": "🎉",
+ "confetti_ball": "🎊",
+ "tanabata_tree": "🎋",
+ "bamboo": "🎍",
+ "dolls": "🎎",
+ "flags": "🎏",
+ "wind_chime": "🎐",
+ "rice_scene": "🎑",
+ "red_envelope": "🧧",
+ "ribbon": "🎀",
+ "gift": "🎁",
+ "reminder_ribbon": "🎗️",
+ "admission_tickets": "🎟️",
+ "ticket": "🎫",
+ "medal": "🎖️",
+ "trophy": "🏆",
+ "sports_medal": "🏅",
+ "first_place_medal": "🥇",
+ "second_place_medal": "🥈",
+ "third_place_medal": "🥉",
+ "soccer": "⚽",
+ "baseball": "⚾",
+ "softball": "🥎",
+ "basketball": "🏀",
+ "volleyball": "🏐",
+ "football": "🏈",
+ "rugby_football": "🏉",
+ "tennis": "🎾",
+ "flying_disc": "🥏",
+ "bowling": "🎳",
+ "cricket_bat_and_ball": "🏏",
+ "field_hockey_stick_and_ball": "🏑",
+ "ice_hockey_stick_and_puck": "🏒",
+ "lacrosse": "🥍",
+ "table_tennis_paddle_and_ball": "🏓",
+ "badminton_racquet_and_shuttlecock": "🏸",
+ "boxing_glove": "🥊",
+ "martial_arts_uniform": "🥋",
+ "goal_net": "🥅",
+ "golf": "⛳",
+ "ice_skate": "⛸️",
+ "fishing_pole_and_fish": "🎣",
+ "diving_mask": "🤿",
+ "running_shirt_with_sash": "🎽",
+ "ski": "🎿",
+ "sled": "🛷",
+ "curling_stone": "🥌",
+ "dart": "🎯",
+ "yo-yo": "🪀",
+ "kite": "🪁",
+ "8ball": "🎱",
+ "crystal_ball": "🔮",
+ "magic_wand": "🪄",
+ "nazar_amulet": "🧿",
+ "hamsa": "🪬",
+ "video_game": "🎮",
+ "joystick": "🕹️",
+ "slot_machine": "🎰",
+ "game_die": "🎲",
+ "jigsaw": "🧩",
+ "teddy_bear": "🧸",
+ "pinata": "🪅",
+ "mirror_ball": "🪩",
+ "nesting_dolls": "🪆",
+ "spades": "♠️",
+ "hearts": "♥️",
+ "diamonds": "♦️",
+ "clubs": "♣️",
+ "chess_pawn": "♟️",
+ "black_joker": "🃏",
+ "mahjong": "🀄",
+ "flower_playing_cards": "🎴",
+ "performing_arts": "🎭",
+ "frame_with_picture": "🖼️",
+ "art": "🎨",
+ "thread": "🧵",
+ "sewing_needle": "🪡",
+ "yarn": "🧶",
+ "knot": "🪢",
+ "eyeglasses": "👓",
+ "dark_sunglasses": "🕶️",
+ "goggles": "🥽",
+ "lab_coat": "🥼",
+ "safety_vest": "🦺",
+ "necktie": "👔",
+ "shirt": "👕",
+ "tshirt": "👕",
+ "jeans": "👖",
+ "scarf": "🧣",
+ "gloves": "🧤",
+ "coat": "🧥",
+ "socks": "🧦",
+ "dress": "👗",
+ "kimono": "👘",
+ "sari": "🥻",
+ "one-piece_swimsuit": "🩱",
+ "briefs": "🩲",
+ "shorts": "🩳",
+ "bikini": "👙",
+ "womans_clothes": "👚",
+ "purse": "👛",
+ "handbag": "👜",
+ "pouch": "👝",
+ "shopping_bags": "🛍️",
+ "school_satchel": "🎒",
+ "thong_sandal": "🩴",
+ "mans_shoe": "👞",
+ "shoe": "👞",
+ "athletic_shoe": "👟",
+ "hiking_boot": "🥾",
+ "womans_flat_shoe": "🥿",
+ "high_heel": "👠",
+ "sandal": "👡",
+ "ballet_shoes": "🩰",
+ "boot": "👢",
+ "crown": "👑",
+ "womans_hat": "👒",
+ "tophat": "🎩",
+ "mortar_board": "🎓",
+ "billed_cap": "🧢",
+ "military_helmet": "🪖",
+ "helmet_with_white_cross": "⛑️",
+ "prayer_beads": "📿",
+ "lipstick": "💄",
+ "ring": "💍",
+ "gem": "💎",
+ "mute": "🔇",
+ "speaker": "🔈",
+ "sound": "🔉",
+ "loud_sound": "🔊",
+ "loudspeaker": "📢",
+ "mega": "📣",
+ "postal_horn": "📯",
+ "bell": "🔔",
+ "no_bell": "🔕",
+ "musical_score": "🎼",
+ "musical_note": "🎵",
+ "notes": "🎶",
+ "studio_microphone": "🎙️",
+ "level_slider": "🎚️",
+ "control_knobs": "🎛️",
+ "microphone": "🎤",
+ "headphones": "🎧",
+ "radio": "📻",
+ "saxophone": "🎷",
+ "accordion": "🪗",
+ "guitar": "🎸",
+ "musical_keyboard": "🎹",
+ "trumpet": "🎺",
+ "violin": "🎻",
+ "banjo": "🪕",
+ "drum_with_drumsticks": "🥁",
+ "long_drum": "🪘",
+ "iphone": "📱",
+ "calling": "📲",
+ "phone": "☎️",
+ "telephone": "☎️",
+ "telephone_receiver": "📞",
+ "pager": "📟",
+ "fax": "📠",
+ "battery": "🔋",
+ "low_battery": "🪫",
+ "electric_plug": "🔌",
+ "computer": "💻",
+ "desktop_computer": "🖥️",
+ "printer": "🖨️",
+ "keyboard": "⌨️",
+ "three_button_mouse": "🖱️",
+ "trackball": "🖲️",
+ "minidisc": "💽",
+ "floppy_disk": "💾",
+ "cd": "💿",
+ "dvd": "📀",
+ "abacus": "🧮",
+ "movie_camera": "🎥",
+ "film_frames": "🎞️",
+ "film_projector": "📽️",
+ "webassembly": ".wasm",
+ "clapper": "🎬",
+ "tv": "📺",
+ "camera": "📷",
+ "camera_with_flash": "📸",
+ "video_camera": "📹",
+ "vhs": "📼",
+ "mag": "🔍",
+ "mag_right": "🔎",
+ "candle": "🕯️",
+ "bulb": "💡",
+ "flashlight": "🔦",
+ "izakaya_lantern": "🏮",
+ "lantern": "🏮",
+ "diya_lamp": "🪔",
+ "notebook_with_decorative_cover": "📔",
+ "closed_book": "📕",
+ "book": "📖",
+ "open_book": "📖",
+ "green_book": "📗",
+ "blue_book": "📘",
+ "orange_book": "📙",
+ "books": "📚",
+ "notebook": "📓",
+ "ledger": "📒",
+ "page_with_curl": "📃",
+ "scroll": "📜",
+ "page_facing_up": "📄",
+ "newspaper": "📰",
+ "rolled_up_newspaper": "🗞️",
+ "bookmark_tabs": "📑",
+ "bookmark": "🔖",
+ "label": "🏷️",
+ "moneybag": "💰",
+ "coin": "🪙",
+ "yen": "💴",
+ "dollar": "💵",
+ "euro": "💶",
+ "pound": "💷",
+ "money_with_wings": "💸",
+ "money_flying": "💸",
+ "credit_card": "💳",
+ "receipt": "🧾",
+ "chart": "💹",
+ "email": "✉️",
+ "envelope": "✉️",
+ "e-mail": "📧",
+ "incoming_envelope": "📨",
+ "envelope_with_arrow": "📩",
+ "outbox_tray": "📤",
+ "inbox_tray": "📥",
+ "package": "📦",
+ "mailbox": "📫",
+ "mailbox_closed": "📪",
+ "mailbox_with_mail": "📬",
+ "mailbox_with_no_mail": "📭",
+ "postbox": "📮",
+ "ballot_box_with_ballot": "🗳️",
+ "pencil2": "✏️",
+ "black_nib": "✒️",
+ "lower_left_fountain_pen": "🖋️",
+ "lower_left_ballpoint_pen": "🖊️",
+ "lower_left_paintbrush": "🖌️",
+ "lower_left_crayon": "🖍️",
+ "memo": "📝",
+ "pencil": "📝",
+ "briefcase": "💼",
+ "file_folder": "📁",
+ "open_file_folder": "📂",
+ "card_index_dividers": "🗂️",
+ "date": "📅",
+ "calendar": "📆",
+ "spiral_note_pad": "🗒️",
+ "spiral_calendar_pad": "🗓️",
+ "card_index": "📇",
+ "chart_with_upwards_trend": "📈",
+ "chart_with_downwards_trend": "📉",
+ "bar_chart": "📊",
+ "clipboard": "📋",
+ "pushpin": "📌",
+ "kodee_pin": "📌",
+ "kodee-pin": "📌",
+ "round_pushpin": "📍",
+ "paperclip": "📎",
+ "linked_paperclips": "🖇️",
+ "straight_ruler": "📏",
+ "triangular_ruler": "📐",
+ "scissors": "✂️",
+ "card_file_box": "🗃️",
+ "file_cabinet": "🗄️",
+ "wastebasket": "🗑️",
+ "lock": "🔒",
+ "unlock": "🔓",
+ "lock_with_ink_pen": "🔏",
+ "closed_lock_with_key": "🔐",
+ "key": "🔑",
+ "old_key": "🗝️",
+ "hammer": "🔨",
+ "axe": "🪓",
+ "pick": "⛏️",
+ "hammer_and_pick": "⚒️",
+ "hammer_and_wrench": "🛠️",
+ "dagger_knife": "🗡️",
+ "crossed_swords": "⚔️",
+ "gun": "🔫",
+ "boomerang": "🪃",
+ "bow_and_arrow": "🏹",
+ "shield": "🛡️",
+ "carpentry_saw": "🪚",
+ "wrench": "🔧",
+ "screwdriver": "🪛",
+ "nut_and_bolt": "🔩",
+ "gear": "⚙️",
+ "compression": "🗜️",
+ "scales": "⚖️",
+ "probing_cane": "🦯",
+ "link": "🔗",
+ "chains": "⛓️",
+ "hook": "🪝",
+ "toolbox": "🧰",
+ "magnet": "🧲",
+ "ladder": "🪜",
+ "alembic": "⚗️",
+ "test_tube": "🧪",
+ "petri_dish": "🧫",
+ "dna": "🧬",
+ "microscope": "🔬",
+ "telescope": "🔭",
+ "satellite_antenna": "📡",
+ "syringe": "💉",
+ "drop_of_blood": "🩸",
+ "pill": "💊",
+ "adhesive_bandage": "🩹",
+ "crutch": "🩼",
+ "stethoscope": "🩺",
+ "x-ray": "🩻",
+ "door": "🚪",
+ "elevator": "🛗",
+ "mirror": "🪞",
+ "window": "🪟",
+ "bed": "🛏️",
+ "couch_and_lamp": "🛋️",
+ "chair": "🪑",
+ "toilet": "🚽",
+ "plunger": "🪠",
+ "shower": "🚿",
+ "bathtub": "🛁",
+ "mouse_trap": "🪤",
+ "razor": "🪒",
+ "lotion_bottle": "🧴",
+ "safety_pin": "🧷",
+ "broom": "🧹",
+ "basket": "🧺",
+ "roll_of_paper": "🧻",
+ "bucket": "🪣",
+ "soap": "🧼",
+ "bubbles": "🫧",
+ "toothbrush": "🪥",
+ "sponge": "🧽",
+ "fire_extinguisher": "🧯",
+ "shopping_trolley": "🛒",
+ "smoking": "🚬",
+ "coffin": "⚰️",
+ "headstone": "🪦",
+ "funeral_urn": "⚱️",
+ "moyai": "🗿",
+ "placard": "🪧",
+ "identification_card": "🪪",
+ "atm": "🏧",
+ "put_litter_in_its_place": "🚮",
+ "potable_water": "🚰",
+ "wheelchair": "♿",
+ "mens": "🚹",
+ "womens": "🚺",
+ "restroom": "🚻",
+ "baby_symbol": "🚼",
+ "wc": "🚾",
+ "passport_control": "🛂",
+ "customs": "🛃",
+ "baggage_claim": "🛄",
+ "left_luggage": "🛅",
+ "warning": "⚠️",
+ "children_crossing": "🚸",
+ "no_entry": "⛔",
+ "no_entry_sign": "🚫",
+ "no_bicycles": "🚳",
+ "no_smoking": "🚭",
+ "do_not_litter": "🚯",
+ "non-potable_water": "🚱",
+ "no_pedestrians": "🚷",
+ "no_mobile_phones": "📵",
+ "underage": "🔞",
+ "radioactive_sign": "☢️",
+ "biohazard_sign": "☣️",
+ "arrow_up": "⬆️",
+ "arrow_upper_right": "↗️",
+ "arrow_right": "➡️",
+ "arrow_lower_right": "↘️",
+ "arrow_down": "⬇️",
+ "arrow_lower_left": "↙️",
+ "arrow_left": "⬅️",
+ "arrow_upper_left": "↖️",
+ "arrow_up_down": "↕️",
+ "left_right_arrow": "↔️",
+ "leftwards_arrow_with_hook": "↩️",
+ "arrow_right_hook": "↪️",
+ "arrow_heading_up": "⤴️",
+ "arrow_heading_down": "⤵️",
+ "arrows_clockwise": "🔃",
+ "arrows_counterclockwise": "🔄",
+ "back": "🔙",
+ "end": "🔚",
+ "on": "🔛",
+ "soon": "🔜",
+ "top": "🔝",
+ "place_of_worship": "🛐",
+ "atom_symbol": "⚛️",
+ "om_symbol": "🕉️",
+ "star_of_david": "✡️",
+ "wheel_of_dharma": "☸️",
+ "yin_yang": "☯️",
+ "latin_cross": "✝️",
+ "orthodox_cross": "☦️",
+ "star_and_crescent": "☪️",
+ "peace_symbol": "☮️",
+ "menorah_with_nine_branches": "🕎",
+ "six_pointed_star": "🔯",
+ "aries": "♈",
+ "taurus": "♉",
+ "gemini": "♊",
+ "cancer": "♋",
+ "leo": "♌",
+ "virgo": "♍",
+ "libra": "♎",
+ "scorpius": "♏",
+ "sagittarius": "♐",
+ "capricorn": "♑",
+ "aquarius": "♒",
+ "pisces": "♓",
+ "ophiuchus": "⛎",
+ "twisted_rightwards_arrows": "🔀",
+ "repeat": "🔁",
+ "repeat_one": "🔂",
+ "arrow_forward": "▶️",
+ "fast_forward": "⏩",
+ "black_right_pointing_double_triangle_with_vertical_bar": "⏭️",
+ "black_right_pointing_triangle_with_double_vertical_bar": "⏯️",
+ "arrow_backward": "◀️",
+ "rewind": "⏪",
+ "black_left_pointing_double_triangle_with_vertical_bar": "⏮️",
+ "arrow_up_small": "🔼",
+ "arrow_double_up": "⏫",
+ "arrow_down_small": "🔽",
+ "arrow_double_down": "⏬",
+ "double_vertical_bar": "⏸️",
+ "black_square_for_stop": "⏹️",
+ "black_circle_for_record": "⏺️",
+ "eject": "⏏️",
+ "cinema": "🎦",
+ "low_brightness": "🔅",
+ "high_brightness": "🔆",
+ "signal_strength": "📶",
+ "vibration_mode": "📳",
+ "mobile_phone_off": "📴",
+ "female_sign": "♀️",
+ "male_sign": "♂️",
+ "transgender_symbol": "⚧️",
+ "heavy_multiplication_x": "✖️",
+ "heavy_plus_sign": "➕",
+ "heavy_minus_sign": "➖",
+ "heavy_division_sign": "➗",
+ "heavy_equals_sign": "🟰",
+ "infinity": "♾️",
+ "bangbang": "‼️",
+ "interrobang": "⁉️",
+ "question": "❓",
+ "grey_question": "❔",
+ "grey_exclamation": "❕",
+ "exclamation": "❗",
+ "heavy_exclamation_mark": "❗",
+ "wavy_dash": "〰️",
+ "currency_exchange": "💱",
+ "heavy_dollar_sign": "💲",
+ "medical_symbol": "⚕️",
+ "staff_of_aesculapius": "⚕️",
+ "recycle": "♻️",
+ "fleur_de_lis": "⚜️",
+ "trident": "🔱",
+ "name_badge": "📛",
+ "beginner": "🔰",
+ "o": "⭕",
+ "white_check_mark": "✅",
+ "ballot_box_with_check": "☑️",
+ "heavy_check_mark": "✔️",
+ "x": "❌",
+ "negative_squared_cross_mark": "❎",
+ "curly_loop": "➰",
+ "loop": "➿",
+ "part_alternation_mark": "〽️",
+ "eight_spoked_asterisk": "✳️",
+ "eight_pointed_black_star": "✴️",
+ "sparkle": "❇️",
+ "copyright": "©️",
+ "registered": "®️",
+ "tm": "™️",
+ "hash": "#️⃣",
+ "keycap_star": "*️⃣",
+ "zero": "0️⃣",
+ "one": "1️⃣",
+ "two": "2️⃣",
+ "three": "3️⃣",
+ "four": "4️⃣",
+ "five": "5️⃣",
+ "six": "6️⃣",
+ "seven": "7️⃣",
+ "eight": "8️⃣",
+ "nine": "9️⃣",
+ "keycap_ten": "🔟",
+ "capital_abcd": "🔠",
+ "fivetran": "5️⃣",
+ "abcd": "🔡",
+ "symbols": "🔣",
+ "abc": "🔤",
+ "a": "🅰️",
+ "ab": "🆎",
+ "b": "🅱️",
+ "cl": "🆑",
+ "cool": "🆒",
+ "free": "🆓",
+ "information_source": "ℹ️",
+ "id": "🆔",
+ "m": "Ⓜ️",
+ "new": "🆕",
+ "ng": "🆖",
+ "o2": "🅾️",
+ "ok": "🆗",
+ "parking": "🅿️",
+ "sos": "🆘",
+ "up": "🆙",
+ "vs": "🆚",
+ "koko": "🈁",
+ "sa": "🈂️",
+ "u6708": "🈷️",
+ "u6709": "🈶",
+ "u6307": "🈯",
+ "ideograph_advantage": "🉐",
+ "u5272": "🈹",
+ "u7121": "🈚",
+ "u7981": "🈲",
+ "accept": "🉑",
+ "u7533": "🈸",
+ "u5408": "🈴",
+ "u7a7a": "🈳",
+ "congratulations": "㊗️",
+ "secret": "㊙️",
+ "u55b6": "🈺",
+ "u6e80": "🈵",
+ "red_circle": "🔴",
+ "large_orange_circle": "🟠",
+ "large_yellow_circle": "🟡",
+ "large_green_circle": "🟢",
+ "large_blue_circle": "🔵",
+ "large_purple_circle": "🟣",
+ "large_brown_circle": "🟤",
+ "black_circle": "⚫",
+ "white_circle": "⚪",
+ "large_red_square": "🟥",
+ "large_orange_square": "🟧",
+ "large_yellow_square": "🟨",
+ "large_green_square": "🟩",
+ "large_blue_square": "🟦",
+ "large_purple_square": "🟪",
+ "large_brown_square": "🟫",
+ "black_large_square": "⬛",
+ "white_large_square": "⬜",
+ "black_medium_square": "◼️",
+ "white_medium_square": "◻️",
+ "black_medium_small_square": "◾",
+ "white_medium_small_square": "◽",
+ "black_small_square": "▪️",
+ "white_small_square": "▫️",
+ "large_orange_diamond": "🔶",
+ "large_blue_diamond": "🔷",
+ "small_orange_diamond": "🔸",
+ "small_blue_diamond": "🔹",
+ "small_red_triangle": "🔺",
+ "small_red_triangle_down": "🔻",
+ "diamond_shape_with_a_dot_inside": "💠",
+ "radio_button": "🔘",
+ "white_square_button": "🔳",
+ "black_square_button": "🔲",
+ "checkered_flag": "🏁",
+ "triangular_flag_on_post": "🚩",
+ "crossed_flags": "🎌",
+ "waving_black_flag": "🏴",
+ "waving_white_flag": "🏳️",
+ "rainbow-flag": "🏳️‍🌈",
+ "transgender_flag": "🏳️‍⚧️",
+ "pirate_flag": "🏴‍☠️",
+ "flag-ac": "🇦🇨",
+ "flag-ad": "🇦🇩",
+ "flag-ae": "🇦🇪",
+ "flag-af": "🇦🇫",
+ "flag-ag": "🇦🇬",
+ "flag-ai": "🇦🇮",
+ "flag-al": "🇦🇱",
+ "flag-am": "🇦🇲",
+ "flag-ao": "🇦🇴",
+ "flag-aq": "🇦🇶",
+ "flag-ar": "🇦🇷",
+ "flag-as": "🇦🇸",
+ "flag-at": "🇦🇹",
+ "flag-au": "🇦🇺",
+ "flag-aw": "🇦🇼",
+ "flag-ax": "🇦🇽",
+ "flag-az": "🇦🇿",
+ "flag-ba": "🇧🇦",
+ "flag-bb": "🇧🇧",
+ "flag-bd": "🇧🇩",
+ "flag-be": "🇧🇪",
+ "flag-bf": "🇧🇫",
+ "flag-bg": "🇧🇬",
+ "flag-bh": "🇧🇭",
+ "flag-bi": "🇧🇮",
+ "flag-bj": "🇧🇯",
+ "flag-bl": "🇧🇱",
+ "flag-bm": "🇧🇲",
+ "flag-bn": "🇧🇳",
+ "flag-bo": "🇧🇴",
+ "flag-bq": "🇧🇶",
+ "flag-br": "🇧🇷",
+ "flag-bs": "🇧🇸",
+ "flag-bt": "🇧🇹",
+ "flag-bv": "🇧🇻",
+ "flag-bw": "🇧🇼",
+ "flag-by": "🇧🇾",
+ "flag-bz": "🇧🇿",
+ "flag-ca": "🇨🇦",
+ "flag-cc": "🇨🇨",
+ "flag-cd": "🇨🇩",
+ "flag-cf": "🇨🇫",
+ "flag-cg": "🇨🇬",
+ "flag-ch": "🇨🇭",
+ "flag-ci": "🇨🇮",
+ "flag-ck": "🇨🇰",
+ "flag-cl": "🇨🇱",
+ "flag-cm": "🇨🇲",
+ "cn": "🇨🇳",
+ "flag-cn": "🇨🇳",
+ "flag-co": "🇨🇴",
+ "flag-cp": "🇨🇵",
+ "flag-cr": "🇨🇷",
+ "flag-cu": "🇨🇺",
+ "flag-cv": "🇨🇻",
+ "flag-cw": "🇨🇼",
+ "flag-cx": "🇨🇽",
+ "flag-cy": "🇨🇾",
+ "flag-cz": "🇨🇿",
+ "de": "🇩🇪",
+ "flag-de": "🇩🇪",
+ "flag-dg": "🇩🇬",
+ "flag-dj": "🇩🇯",
+ "flag-dk": "🇩🇰",
+ "flag-dm": "🇩🇲",
+ "flag-do": "🇩🇴",
+ "flag-dz": "🇩🇿",
+ "flag-ea": "🇪🇦",
+ "flag-ec": "🇪🇨",
+ "flag-ee": "🇪🇪",
+ "flag-eg": "🇪🇬",
+ "flag-eh": "🇪🇭",
+ "flag-er": "🇪🇷",
+ "es": "🇪🇸",
+ "flag-es": "🇪🇸",
+ "flag-et": "🇪🇹",
+ "flag-eu": "🇪🇺",
+ "flag-fi": "🇫🇮",
+ "flag-fj": "🇫🇯",
+ "flag-fk": "🇫🇰",
+ "flag-fm": "🇫🇲",
+ "flag-fo": "🇫🇴",
+ "fr": "🇫🇷",
+ "flag-fr": "🇫🇷",
+ "flag-ga": "🇬🇦",
+ "gb": "🇬🇧",
+ "flag-gb": "🇬🇧",
+ "flag-gd": "🇬🇩",
+ "flag-ge": "🇬🇪",
+ "flag-gf": "🇬🇫",
+ "flag-gg": "🇬🇬",
+ "flag-gh": "🇬🇭",
+ "flag-gi": "🇬🇮",
+ "flag-gl": "🇬🇱",
+ "flag-gm": "🇬🇲",
+ "flag-gn": "🇬🇳",
+ "flag-gp": "🇬🇵",
+ "flag-gq": "🇬🇶",
+ "flag-gr": "🇬🇷",
+ "flag-gs": "🇬🇸",
+ "flag-gt": "🇬🇹",
+ "flag-gu": "🇬🇺",
+ "flag-gw": "🇬🇼",
+ "flag-gy": "🇬🇾",
+ "flag-hk": "🇭🇰",
+ "flag-hm": "🇭🇲",
+ "flag-hn": "🇭🇳",
+ "flag-hr": "🇭🇷",
+ "flag-ht": "🇭🇹",
+ "flag-hu": "🇭🇺",
+ "flag-ic": "🇮🇨",
+ "flag-id": "🇮🇩",
+ "flag-ie": "🇮🇪",
+ "flag-il": "🇮🇱",
+ "flag-im": "🇮🇲",
+ "flag-in": "🇮🇳",
+ "flag-io": "🇮🇴",
+ "flag-iq": "🇮🇶",
+ "flag-ir": "🇮🇷",
+ "flag-is": "🇮🇸",
+ "it": "🇮🇹",
+ "flag-it": "🇮🇹",
+ "flag-je": "🇯🇪",
+ "flag-jm": "🇯🇲",
+ "flag-jo": "🇯🇴",
+ "jp": "🇯🇵",
+ "flag-jp": "🇯🇵",
+ "flag-ke": "🇰🇪",
+ "flag-kg": "🇰🇬",
+ "flag-kh": "🇰🇭",
+ "flag-ki": "🇰🇮",
+ "flag-km": "🇰🇲",
+ "flag-kn": "🇰🇳",
+ "flag-kp": "🇰🇵",
+ "kr": "🇰🇷",
+ "flag-kr": "🇰🇷",
+ "flag-kw": "🇰🇼",
+ "flag-ky": "🇰🇾",
+ "flag-kz": "🇰🇿",
+ "flag-la": "🇱🇦",
+ "flag-lb": "🇱🇧",
+ "flag-lc": "🇱🇨",
+ "flag-li": "🇱🇮",
+ "flag-lk": "🇱🇰",
+ "flag-lr": "🇱🇷",
+ "flag-ls": "🇱🇸",
+ "flag-lt": "🇱🇹",
+ "flag-lu": "🇱🇺",
+ "flag-lv": "🇱🇻",
+ "flag-ly": "🇱🇾",
+ "flag-ma": "🇲🇦",
+ "flag-mc": "🇲🇨",
+ "flag-md": "🇲🇩",
+ "flag-me": "🇲🇪",
+ "flag-mf": "🇲🇫",
+ "flag-mg": "🇲🇬",
+ "flag-mh": "🇲🇭",
+ "flag-mk": "🇲🇰",
+ "flag-ml": "🇲🇱",
+ "flag-mm": "🇲🇲",
+ "flag-mn": "🇲🇳",
+ "flag-mo": "🇲🇴",
+ "flag-mp": "🇲🇵",
+ "flag-mq": "🇲🇶",
+ "flag-mr": "🇲🇷",
+ "flag-ms": "🇲🇸",
+ "flag-mt": "🇲🇹",
+ "flag-mu": "🇲🇺",
+ "flag-mv": "🇲🇻",
+ "flag-mw": "🇲🇼",
+ "flag-mx": "🇲🇽",
+ "flag-my": "🇲🇾",
+ "flag-mz": "🇲🇿",
+ "flag-na": "🇳🇦",
+ "flag-nc": "🇳🇨",
+ "flag-ne": "🇳🇪",
+ "flag-nf": "🇳🇫",
+ "flag-ng": "🇳🇬",
+ "flag-ni": "🇳🇮",
+ "flag-nl": "🇳🇱",
+ "flag-no": "🇳🇴",
+ "flag-np": "🇳🇵",
+ "flag-nr": "🇳🇷",
+ "flag-nu": "🇳🇺",
+ "flag-nz": "🇳🇿",
+ "flag-om": "🇴🇲",
+ "flag-pa": "🇵🇦",
+ "flag-pe": "🇵🇪",
+ "flag-pf": "🇵🇫",
+ "flag-pg": "🇵🇬",
+ "flag-ph": "🇵🇭",
+ "flag-pk": "🇵🇰",
+ "flag-pl": "🇵🇱",
+ "flag-pm": "🇵🇲",
+ "flag-pn": "🇵🇳",
+ "flag-pr": "🇵🇷",
+ "flag-ps": "🇵🇸",
+ "flag-pt": "🇵🇹",
+ "flag-pw": "🇵🇼",
+ "flag-py": "🇵🇾",
+ "flag-qa": "🇶🇦",
+ "flag-re": "🇷🇪",
+ "flag-ro": "🇷🇴",
+ "flag-rs": "🇷🇸",
+ "ru": "🇷🇺",
+ "flag-ru": "🇷🇺",
+ "flag-rw": "🇷🇼",
+ "flag-sa": "🇸🇦",
+ "flag-sb": "🇸🇧",
+ "flag-sc": "🇸🇨",
+ "flag-sd": "🇸🇩",
+ "flag-se": "🇸🇪",
+ "flag-sg": "🇸🇬",
+ "flag-sh": "🇸🇭",
+ "flag-si": "🇸🇮",
+ "flag-sj": "🇸🇯",
+ "flag-sk": "🇸🇰",
+ "flag-sl": "🇸🇱",
+ "flag-sm": "🇸🇲",
+ "flag-sn": "🇸🇳",
+ "flag-so": "🇸🇴",
+ "flag-sr": "🇸🇷",
+ "flag-ss": "🇸🇸",
+ "flag-st": "🇸🇹",
+ "flag-sv": "🇸🇻",
+ "flag-sx": "🇸🇽",
+ "flag-sy": "🇸🇾",
+ "flag-sz": "🇸🇿",
+ "flag-ta": "🇹🇦",
+ "flag-tc": "🇹🇨",
+ "flag-td": "🇹🇩",
+ "flag-tf": "🇹🇫",
+ "flag-tg": "🇹🇬",
+ "flag-th": "🇹🇭",
+ "flag-tj": "🇹🇯",
+ "flag-tk": "🇹🇰",
+ "flag-tl": "🇹🇱",
+ "flag-tm": "🇹🇲",
+ "flag-tn": "🇹🇳",
+ "flag-to": "🇹🇴",
+ "flag-tr": "🇹🇷",
+ "flag-tt": "🇹🇹",
+ "flag-tv": "🇹🇻",
+ "flag-tw": "🇹🇼",
+ "flag-tz": "🇹🇿",
+ "flag-ua": "🇺🇦",
+ "flag-ug": "🇺🇬",
+ "flag-um": "🇺🇲",
+ "flag-un": "🇺🇳",
+ "us": "🇺🇸",
+ "flag-us": "🇺🇸",
+ "flag-uy": "🇺🇾",
+ "flag-uz": "🇺🇿",
+ "flag-va": "🇻🇦",
+ "flag-vc": "🇻🇨",
+ "flag-ve": "🇻🇪",
+ "flag-vg": "🇻🇬",
+ "flag-vi": "🇻🇮",
+ "flag-vn": "🇻🇳",
+ "flag-vu": "🇻🇺",
+ "flag-wf": "🇼🇫",
+ "flag-ws": "🇼🇸",
+ "flag-xk": "🇽🇰",
+ "flag-ye": "🇾🇪",
+ "flag-yt": "🇾🇹",
+ "flag-za": "🇿🇦",
+ "flag-zm": "🇿🇲",
+ "flag-zw": "🇿🇼",
+ "flag-england": "🏴󠁧󠁢󠁥󠁮󠁧󠁿",
+ "flag-scotland": "🏴󠁧󠁢󠁳󠁣󠁴󠁿",
+ "flag-wales": "🏴󠁧󠁢󠁷󠁬󠁳󠁿",
+ "kotlinconf23": "K",
+ "kotlinconf-2023": "K",
+ "kotlin-intensifies-purple": "K",
+ "kotlin-intensifies": "K",
+ "compose-multiplatform": "K",
+ "kotlinnew": "K",
+ "kotlin": "K",
+ "kotlin_emoji": "K",
+ "kotlin-emoji": "K",
+ "kotlin-gradient": "K",
+ "kotlin_gradient": "K",
+ "kotlin-golf": "🏌️",
+ "mascot": "🧸",
+ "mascot-wink": "🧸",
+ "compose": "✏️",
+ "yes": "👌",
+ "ohyes": "👌",
+ "thank-you": "🙏",
+ "tnx": "🙏",
+ "cool-doge": "🐕",
+ "blob-hype": "🦠",
+ "suspend": "⏸️",
+ "parrot-upside-down": "🦜",
+ "twitter": "T",
+ "javascript": "JS",
+ "this-is-fine": "🙂",
+ "marrrcin": "🙂",
+ "partydagster": "🎉",
+ "kedroid-party": "🎉",
+ "planet-daggy": "🪐",
+ "flames-daggy": "🔥",
+ "next-level-daggy": "👌",
+ "awesome": "👌",
+ "dagster": "D",
+ "super": "👌",
+ "blob_ok_hand": "👌",
+ "blob-okay-hand": "👌",
+ "gradle": "G",
+ "maskot-wink": "🧸",
+ "maskot": "🧸",
+ "kotlin-flag": "K",
+ "oh-yeah": "🎉",
+ "thumbsup_all": "👍",
+ "not-kotlin": "😶",
+ "trollface": "🧌",
+ "no": "🚫",
+ "ohno": "🚫",
+ "nospam": "🚫",
+ "blob_shrug": "🤷",
+ "thread-please": "🧵",
+ "dagster-bot-resolve": "🤖",
+ "bananadance": "🍌",
+ "bananas": "🍌",
+ "laptop_parrot": "🦜",
+ "laptop-parrot": "🦜",
+ "dancing_parrot": "🦜",
+ "dancing-parrot": "🦜",
+ "bongo_blob": "🦠",
+ "blob": "🦠",
+ "blob_wave": "👋",
+ "pikachu_wave": "👋",
+ "android_wave": "👋",
+ "android-wave": "👋",
+ "dagster-bot-surfaced-to-issue": "🤖",
+ "tsow-slack-icon": "S",
+ "kedro": "K",
+ "pipe": "|",
+ "prefect": "P",
+ "snowflake-inc": "❄️",
+ "kestra": "K"
+} \ No newline at end of file
diff --git a/front/src/logic/nostril.ts b/front/src/logic/nostril.ts
new file mode 100644
index 0000000..4e5549d
--- /dev/null
+++ b/front/src/logic/nostril.ts
@@ -0,0 +1,36 @@
+import type { Event } from "@/types/nostr";
+import type { FC, FlatFeed, Poast } from "@/types/trill";
+import { engagementBunt, openLock } from "./bunts";
+export function eventsToFc(relayData: Record<string, Event[]>): FC {
+ const start = null;
+ const end = null;
+ const feed = Object.values(relayData).reduce((acc: FlatFeed, events) => {
+ const poasts = events.map(eventToPoast);
+ for (const p of poasts) {
+ if (p) acc[p.id] = p;
+ }
+ return acc;
+ }, {});
+ return { feed, start, end };
+}
+export function eventToPoast(event: Event): Poast | null {
+ if (event.kind !== 1) return null;
+ const contents = [{ paragraph: [{ text: event.content }] }];
+ const ts = event.created_at * 1000;
+ const id = `${ts}`;
+ const poast: Poast = {
+ id,
+ host: event.pubkey,
+ author: event.pubkey,
+ contents,
+ thread: id,
+ parent: null,
+ read: openLock,
+ write: openLock,
+ tags: [],
+ time: ts,
+ engagement: engagementBunt,
+ children: [],
+ };
+ return poast;
+}
diff --git a/front/src/logic/requests/nostril.ts b/front/src/logic/requests/nostril.ts
new file mode 100644
index 0000000..6f0edcf
--- /dev/null
+++ b/front/src/logic/requests/nostril.ts
@@ -0,0 +1,139 @@
+import type Urbit from "urbit-api";
+import type { Cursor, PostID, SentPoast } from "@/types/trill";
+import type { Ship } from "@/types/urbit";
+import { FeedPostCount } from "../constants";
+import type { UserProfile } from "@/types/nostril";
+
+// Subscribe
+type Handler = (date: any) => void;
+export default class IO {
+ airlock;
+ constructor(airlock: Urbit) {
+ this.airlock = airlock;
+ }
+ private async poke(json: any) {
+ return this.airlock.poke({ app: "nostril", mark: "json", json });
+ }
+ private async scry(path: string) {
+ return this.airlock.scry({ app: "nostril", path });
+ }
+ private async sub(path: string, handler: Handler) {
+ const err = (err: any, _id: string) =>
+ console.log(err, "error on nostril subscription");
+ const quit = (data: any) =>
+ console.log(data, "nostril subscription kicked");
+ const res = await this.airlock.subscribe({
+ app: "nostril",
+ path,
+ event: handler,
+ err,
+ quit,
+ });
+ console.log(res, "subscribed to nostril agent");
+ }
+ async unsub(sub: number) {
+ return await this.airlock.unsubscribe(sub);
+ }
+ // subs
+ async subscribeStore(handler: Handler) {
+ const res = await this.sub("/ui", handler);
+ return res;
+ }
+ // scries
+
+ async scryFeed(start: Cursor, end: Cursor, desc = true) {
+ const order = desc ? 1 : 0;
+ const term = "feed";
+
+ const path = `/j/feed/${term}/${start}/${end}/${FeedPostCount}/${order}`;
+ return await this.scry(path);
+ }
+ async scryPost(
+ host: Ship,
+ id: PostID,
+ start: Cursor,
+ end: Cursor,
+ desc = true,
+ ) {
+ const order = desc ? 1 : 0;
+
+ const path = `/j/post/${host}/${id}/${start}/${end}/${FeedPostCount}/${order}`;
+ return await this.scry(path);
+ }
+ // pokes
+
+ async pokeAlive() {
+ return await this.poke({ alive: true });
+ }
+ async addPost(pubkey: string, content: string) {
+ const json = { add: { pubkey, content } };
+ return this.poke({ post: json });
+ }
+ // async addPost(post: SentPoast, gossip: boolean) {
+ // const json = {
+ // "new-post": {
+ // "sent-post": post,
+ // gossip,
+ // },
+ // };
+ // return this.poke(json);
+ // }
+
+ async deletePost(id: string) {
+ const host = `~${this.airlock.ship}`;
+ const json = {
+ "del-post": {
+ ship: host,
+ id: id,
+ },
+ };
+ return this.poke(json);
+ }
+
+ async addReact(ship: Ship, id: PostID, reaction: string) {
+ const json = {
+ "new-react": {
+ react: reaction,
+ pid: {
+ id: id,
+ ship: ship,
+ },
+ },
+ };
+
+ return this.poke(json);
+ }
+
+ // follows
+ async follow(ship: Ship) {
+ const json = { add: ship };
+ return this.poke({ fols: json });
+ }
+
+ async unfollow(ship: Ship) {
+ const json = { del: ship };
+ return await this.poke({ fols: json });
+ }
+ // profiles
+ async createProfile(pubkey: string, profile: UserProfile) {
+ const json = { add: { pubkey, profile } };
+ return await this.poke({ prof: json });
+ }
+ async createKey() {
+ const json = { add: null };
+ return await this.poke({ keys: json });
+ }
+ async removeKey(pubkey: string) {
+ const json = { del: pubkey };
+ return await this.poke({ keys: json });
+ }
+ // relaying
+ async relayPost(host: string, id: string, relays: string[]) {
+ const json = { send: { host, id, relays } };
+ return await this.poke({ rela: json });
+ }
+}
+
+// notifications
+
+// mark as read
diff --git a/front/src/logic/utils.ts b/front/src/logic/utils.ts
new file mode 100644
index 0000000..dbd246e
--- /dev/null
+++ b/front/src/logic/utils.ts
@@ -0,0 +1,459 @@
+import type {
+ Content,
+ Notification,
+ ID,
+ ExternalContent,
+ Poast,
+ Reference,
+ Inline,
+ PID,
+ SortugRef,
+} from "@/types/trill";
+import type { Ship } from "@/types/urbit";
+import anyAscii from "any-ascii";
+import type { ReactGrouping, SPID } from "@/types/ui";
+import { openLock } from "./bunts";
+import { isValidPatp, patp2dec } from "urbit-ob";
+import { REF_REGEX } from "./constants";
+
+export function parseSortugLink(link: string): SortugRef {
+ const s = link.replace("urbit://", "").split("/");
+ const [type, ship, ...pat] = s;
+ const path = `/${pat.join("/")}`;
+ return { type, ship, path };
+}
+export function sortugRefTolink(r: SortugRef): string {
+ return `urbit://${r.type}/${r.ship}${r.path}`;
+}
+// TODO
+
+export function createReference(ship: Ship, id: ID) {
+ return {
+ reference: {
+ feed: { id: id, ship: ship },
+ },
+ };
+}
+
+export function addScheme(url: string) {
+ if (url.includes("localhost")) {
+ return `http://${url.replace("http://", "")}`;
+ } else {
+ return `https://${url.replace("http://", "")}`;
+ }
+}
+
+export function easyCode(code: string) {
+ const string = code.replace(/-/g, "");
+ const matches = string.match(/.{1,6}/g);
+ if (matches) return matches.join("-");
+}
+
+export function tilde(patp: Ship) {
+ if (patp[0] == "~") {
+ return patp;
+ } else {
+ return "~" + patp;
+ }
+}
+
+export function color_to_hex(color: string) {
+ let hex = "#" + color.replace(".", "").replace("0x", "").toUpperCase();
+ if (hex == "#0") {
+ hex = "#000000";
+ }
+ return hex;
+}
+
+export function date_diff(date: number | Date, type: "short" | "long") {
+ const now = new Date().getTime();
+ const diff = now - new Date(date).getTime();
+ if (type == "short") {
+ return to_string(diff / 1000);
+ } else {
+ return to_string_long(diff / 1000);
+ }
+}
+
+function to_string(s: number) {
+ if (s < 60) {
+ return "now";
+ } else if (s < 3600) {
+ return `${Math.ceil(s / 60)}m`;
+ } else if (s < 86400) {
+ return `${Math.ceil(s / 60 / 60)}h`;
+ } else if (s < 2678400) {
+ return `${Math.ceil(s / 60 / 60 / 24)}d`;
+ } else if (s < 32140800) {
+ return `${Math.ceil(s / 60 / 60 / 24 / 30)}mo`;
+ } else {
+ return `${Math.ceil(s / 60 / 60 / 24 / 30 / 12)}y`;
+ }
+}
+
+function to_string_long(s: number) {
+ if (s < 60) {
+ return "right now";
+ } else if (s < 3600) {
+ return `${Math.ceil(s / 60)} minutes ago`;
+ } else if (s < 86400) {
+ return `${Math.ceil(s / 60 / 60)} hours ago`;
+ } else if (s < 2678400) {
+ return `${Math.ceil(s / 60 / 60 / 24)} days ago`;
+ } else if (s < 32140800) {
+ return `${Math.ceil(s / 60 / 60 / 24 / 30)} months ago`;
+ } else {
+ return `${Math.ceil(s / 60 / 60 / 24 / 30 / 12)} years ago`;
+ }
+}
+
+export function regexes() {
+ const IMAGE_REGEX = new RegExp(/(jpg|img|png|gif|tiff|jpeg|webp|webm|svg)$/i);
+ const AUDIO_REGEX = new RegExp(/(mp3|wav|ogg)$/i);
+ const VIDEO_REGEX = new RegExp(/(mov|mp4|ogv)$/i);
+ return { img: IMAGE_REGEX, aud: AUDIO_REGEX, vid: VIDEO_REGEX };
+}
+
+export function stringToSymbol(str: string) {
+ const ascii = anyAscii(str);
+ let result = "";
+ for (let i = 0; i < ascii.length; i++) {
+ const n = ascii.charCodeAt(i);
+ if ((n >= 97 && n <= 122) || (n >= 48 && n <= 57)) {
+ result += ascii[i];
+ } else if (n >= 65 && n <= 90) {
+ result += String.fromCharCode(n + 32);
+ } else {
+ result += "-";
+ }
+ }
+ result = result.replace(/^[\-\d]+|\-+/g, "-");
+ result = result.replace(/^\-+|\-+$/g, "");
+ return result;
+}
+export function buildDM(author: Ship, recipient: Ship, contents: Content[]) {
+ const node: any = {};
+ const point = patp2dec(recipient);
+ const index = `/${point}/${makeIndex()}`;
+ node[index] = {
+ children: null,
+ post: {
+ author: author,
+ contents: contents,
+ hash: null,
+ index: index,
+ signatures: [],
+ "time-sent": Date.now(),
+ },
+ };
+ return {
+ app: "dm-hook",
+ mark: "graph-update-3",
+ json: {
+ "add-nodes": {
+ resource: { name: "dm-inbox", ship: author },
+ nodes: node,
+ },
+ },
+ };
+}
+
+export function makeIndex(): string {
+ const DA_UNIX_EPOCH = BigInt("170141184475152167957503069145530368000");
+ const DA_SECOND = BigInt("18446744073709551616");
+ const timeSinceEpoch = (BigInt(Date.now()) * DA_SECOND) / BigInt(1000);
+ return (DA_UNIX_EPOCH + timeSinceEpoch).toString();
+}
+export function makeDottedIndex() {
+ const DA_UNIX_EPOCH = BigInt("170141184475152167957503069145530368000");
+ const DA_SECOND = BigInt("18446744073709551616");
+ const timeSinceEpoch = (BigInt(Date.now()) * DA_SECOND) / BigInt(1000);
+ const index = (DA_UNIX_EPOCH + timeSinceEpoch).toString();
+ return index.replace(/\B(?=(\d{3})+(?!\d))/g, ".");
+}
+
+export function repostData(p: Poast): PID | null {
+ if (
+ p.contents.length === 1 &&
+ "ref" in p.contents[0] &&
+ p.contents[0].ref.type === "trill"
+ )
+ return {
+ id: p.contents[0].ref.path.slice(1),
+ ship: p.contents[0].ref.ship,
+ };
+ else return null;
+}
+
+export function getNotificationTime(n: Notification): number {
+ if ("follow" in n) {
+ return n.follow.time;
+ } else if ("unfollow" in n) {
+ return n.unfollow.time;
+ } else if ("mention" in n) {
+ return n.mention.time;
+ } else if ("react" in n) {
+ return n.react.time;
+ } else if ("reply" in n) {
+ return n.reply.time;
+ } else if ("quote" in n) {
+ return n.quote.time;
+ } else if ("share" in n) {
+ return n.share.time;
+ } else {
+ return Date.now();
+ }
+}
+export function abbreviateChat(s: string): string {
+ const plist = s.trim().split(" ");
+ if (isValidPatp(plist[0]) && plist.length > 1) {
+ return `${plist[0]} & ${plist.length - 1}+`;
+ } else if (s.length < 25) return s;
+ else return `${s.substring(0, 25)}...`;
+}
+
+export function timestring(n: number): string {
+ const nn = new Date(n);
+ return nn.toTimeString().slice(0, 5);
+}
+export function wait(ms: number) {
+ return new Promise((resolve, _reject) => {
+ setTimeout(resolve, ms);
+ });
+}
+
+export function quoteToReference(d: SPID): Reference | ExternalContent {
+ if (d.service === "twatter")
+ return {
+ json: {
+ origin: "twatter",
+ content: JSON.stringify(d.post),
+ },
+ };
+ else
+ return {
+ ref: {
+ type: "trill",
+ ship: d.post.host,
+ path: `/${d.post.id}`,
+ },
+ };
+}
+
+export function trillPermalink(t: Poast) {
+ return `urbit://trill/${t.host}/${t.id}`;
+}
+export function isFeedRef(c: Content): boolean {
+ return "ref" in c && (c as Reference).ref.type === "trill";
+}
+
+export function checkTilde(s: string) {
+ if (s[0] === "~") return s;
+ else return "~" + s;
+}
+
+export function addDots(s: string, num: number): string {
+ const reversed = s.split("").reverse().join("");
+ const reg = new RegExp(`.{${num}}`, "g");
+ const withCommas = reversed.replace(reg, "$&.");
+ return withCommas.split("").reverse().join("").slice(1);
+}
+export function addDots5(s: string): string {
+ const reversed = s.split("").reverse().join("");
+ const withCommas = reversed.replace(/.{5}/g, "$&.");
+ return withCommas.split("").reverse().join("");
+}
+// TODO
+export function getTrillText(c: Content): string {
+ if (!c) return "";
+ const reducePara = (acc: string, item: Inline) => {
+ let t = "";
+ if ("text" in item) t = item.text + " ";
+ if ("italic" in item) t = item.italic + " ";
+ if ("bold" in item) t = item.bold + " ";
+ if ("strike" in item) t = item.strike + " ";
+ if ("ship" in item) t = item.ship + " ";
+ if ("codespan" in item) t = item.codespan + " ";
+ if ("link" in item) t = item.link.href + " ";
+ if ("break" in item) t = "\n";
+ return acc + t;
+ };
+ return c.reduce((acc, item) => {
+ if ("paragraph" in item) {
+ const text = item.paragraph.reduce(reducePara, "");
+ return acc + text + "\n";
+ } else return acc;
+ }, "");
+}
+export function isTwatterLink(s: string) {
+ const sp = s
+ .replace("https://", "")
+ .split("/")
+ .filter((s) => s);
+ return sp.length === 4 && sp[0] === "twitter.com" && sp[2] === "status";
+}
+export const isSortugLink = (s: string) => !!s.match(REF_REGEX);
+export function parseOutSortugLinks(s: string): [SortugRef[], string] {
+ const matches = s.match(REF_REGEX);
+ let refs = [];
+ let rest = s;
+ for (let m of matches || []) {
+ rest = rest.replace(m, "");
+ refs.push(parseSortugLink(m));
+ }
+ return [refs, rest];
+}
+
+export function isTrillLink(s: string): boolean {
+ if (!isSortugLink(s)) return false;
+ const r = parseSortugLink(s);
+ if (r.type !== "trill") return false;
+ return isValidPatp(r.ship) && !isNaN(Number(r.path.slice(1)));
+}
+
+export function auraToHex(s: string): string {
+ if (s.startsWith("0x")) {
+ let numbers = s.replace("0x", "").replace(".", "");
+ while (numbers.length < 6) {
+ numbers = "0" + numbers;
+ }
+ return "#" + numbers;
+ } else if (s.startsWith("#")) return s;
+ else {
+ // console.log(s, "weird hex");
+ return "black";
+ }
+}
+
+export function buildPost(
+ author: Ship,
+ id: string,
+ time: number,
+ s: string,
+ content: string,
+): Poast {
+ return {
+ host: author,
+ author: author,
+ thread: null,
+ parent: null,
+ contents: [{ paragraph: [{ text: s }] }],
+ read: openLock,
+ write: openLock,
+ tags: [],
+ id,
+ time,
+ children: [],
+ engagement: { reacts: {}, quoted: [], shared: [] },
+ json: { origin: "rumors", content },
+ };
+}
+
+// default cursors
+export function makeNewestIndex() {
+ const DA_UNIX_EPOCH = BigInt("170141184475152167957503069145530368000");
+ const DA_SECOND = BigInt("18446744073709551616");
+ const timeSinceEpoch = (BigInt(Date.now()) * DA_SECOND) / BigInt(1000);
+ return (DA_UNIX_EPOCH + timeSinceEpoch).toString();
+}
+export const startCursor = makeNewestIndex();
+export const endCursor = "0";
+
+export function displayCount(c: number): string {
+ if (c <= 0) return "";
+ if (c < 1_000) return `${c}`;
+ if (c >= 1_000 && c < 1_000_000) return `${Math.round(c / 1_00) / 10}K`;
+ if (c >= 1_000_000) return `${Math.round(c / 100_000) / 10}M`;
+ else return "";
+}
+export function isWhiteish(hex: string): boolean {
+ if (hex.indexOf("#") === 0) hex = hex.slice(1);
+ const r = parseInt(hex.slice(0, 2), 16);
+ const g = parseInt(hex.slice(2, 4), 16);
+ const b = parseInt(hex.slice(4, 6), 16);
+ return r > 200 && g > 200 && b > 200;
+}
+
+export function localISOString(date: Date) {
+ const offset = new Date().getTimezoneOffset();
+ const localts = date.getTime() - offset * 60_000;
+ return new Date(localts).toISOString().slice(0, 16);
+}
+
+export function goback() {
+ window.history.back();
+}
+
+export function groupReacts(reacts: Record<Ship, string>): ReactGrouping {
+ const byReact = Object.entries(reacts).reduce(
+ (acc: Record<string, Ship[]>, item) => {
+ const shipList = acc[item[1]];
+ if (!shipList) acc[item[1]] = [item[0]];
+ else acc[item[1]] = [...shipList, item[0]];
+ return acc;
+ },
+ {},
+ );
+ return Object.entries(byReact)
+ .reduce((acc: ReactGrouping, item) => {
+ const pair = { react: item[0], ships: item[1] };
+ return [...acc, pair];
+ }, [])
+ .sort((a, b) => b.ships.length - a.ships.length);
+}
+
+export function reverseRecord(
+ a: Record<string, string>,
+): Record<string, string> {
+ return Object.entries(a).reduce((acc: Record<string, string>, [k, v]) => {
+ acc[v] = k;
+ return acc;
+ }, {});
+}
+
+export function getColorHex(color: string): string {
+ if (color.startsWith("0x"))
+ return `#${padString(stripFuckingDots(color), 6)}`;
+ else if (color.startsWith("#") && color.length === 7) return color;
+ else if (color.length === 6) return `#${color}`;
+ else {
+ console.log(color, "something weird with this color");
+ return "#FFFFFF";
+ }
+}
+
+export function stripFuckingDots(hex: string) {
+ return hex.replace("0x", "").replaceAll(".", "");
+}
+export function padString(s: string, size: number) {
+ if (s.length >= size) return s;
+ else return padString(`0${s}`, size);
+}
+export function isDark(hexColor: string): boolean {
+ const r = parseInt(hexColor.substring(1, 2), 16);
+ const g = parseInt(hexColor.substring(3, 5), 16);
+ const b = parseInt(hexColor.substring(5, 7), 16);
+
+ const sr = r / 255;
+ const sg = g / 255;
+ const sb = b / 255;
+ const rSrgb =
+ sr <= 0.03928 ? sr / 12.92 : Math.pow((sr + 0.055) / 1.055, 2.4);
+ const gSrgb =
+ sg <= 0.03928 ? sg / 12.92 : Math.pow((sg + 0.055) / 1.055, 2.4);
+ const bSrgb =
+ sb <= 0.03928 ? sb / 12.92 : Math.pow((sb + 0.055) / 1.055, 2.4);
+
+ // Calculate luminance
+ const luminance = 0.2126 * rSrgb + 0.7152 * gSrgb + 0.0722 * bSrgb;
+ return luminance < 0.12;
+}
+
+export function checkIfClickedOutside(
+ e: React.MouseEvent,
+ el: HTMLElement,
+ close: any,
+) {
+ e.stopPropagation();
+ if (el.contains(e.currentTarget)) close();
+}
diff --git a/front/src/main.tsx b/front/src/main.tsx
new file mode 100644
index 0000000..5d4a2be
--- /dev/null
+++ b/front/src/main.tsx
@@ -0,0 +1,9 @@
+import { StrictMode } from "react";
+import { createRoot } from "react-dom/client";
+import App from "./App.tsx";
+
+createRoot(document.getElementById("root")!).render(
+ <StrictMode>
+ <App />
+ </StrictMode>,
+);
diff --git a/front/src/pages/Feed.tsx b/front/src/pages/Feed.tsx
new file mode 100644
index 0000000..e29033e
--- /dev/null
+++ b/front/src/pages/Feed.tsx
@@ -0,0 +1,104 @@
+// import spinner from "@/assets/icons/spinner.svg";
+import "@/styles/trill.css";
+import UserFeed from "./User";
+import PostList from "@/components/feed/PostList";
+import useLocalState from "@/state/state";
+import { useParams, useLocation } from "wouter";
+import spinner from "@/assets/triangles.svg";
+import { useState } from "react";
+import Composer from "@/components/feed/Composer";
+// import UserFeed from "./User";
+import { P404 } from "@/Router";
+import { useQuery } from "@tanstack/react-query";
+import { isValidPatp } from "urbit-ob";
+import { eventsToFc } from "@/logic/nostril";
+
+type FeedType = "global" | "following" | "nostr";
+function Loader() {
+ // const { api } = useLocalState();
+ const params = useParams();
+ console.log({ params });
+ // const [loc, navigate] = useLocation();
+ // console.log({ loc });
+ // const our = api!.airlock.ship;
+ if (params.taip === "global") return <FeedPage t={"global"} />;
+ if (params.taip === "nostr") return <FeedPage t={"nostr"} />;
+ // else if (param === FeedType.Rumors) return <Rumors />;
+ // else if (param === FeedType.Home) return <UserFeed p={our} />;
+ else if (isValidPatp(params.taip!)) return <UserFeed p={params.taip!} />;
+ else return <P404 />;
+}
+function FeedPage({ t }: { t: FeedType }) {
+ const [active, setActive] = useState<FeedType>(t);
+ return (
+ <main>
+ <div id="top-tabs">
+ <div
+ className={active === "global" ? "active" : ""}
+ onClick={() => setActive("global")}
+ >
+ Global
+ </div>
+ <div
+ className={active === "following" ? "active" : ""}
+ onClick={() => setActive("following")}
+ >
+ Following
+ </div>
+ <div
+ className={active === "nostr" ? "active" : ""}
+ onClick={() => setActive("nostr")}
+ >
+ Nostr
+ </div>
+ </div>
+ <div id="feed-proper">
+ <Composer />
+ {active === "global" ? (
+ <Global />
+ ) : active === "following" ? (
+ <Global />
+ ) : active === "nostr" ? (
+ <Nostr />
+ ) : null}
+ </div>
+ </main>
+ );
+}
+// {active === "global" ? (
+// <Global />
+// ) : active === "following" ? (
+// <Global />
+// ) : (
+// <Global />
+// )}
+
+function Global() {
+ // const { api } = useLocalState();
+ // const { isPending, data, refetch } = useQuery({
+ // queryKey: ["globalFeed"],
+ // queryFn: () => {
+ // return api!.scryFeed(null, null);
+ // },
+ // });
+ // console.log(data, "scry feed data");
+ // if (isPending) return <img className="x-center" src={spinner} />;
+ // else if ("bucun" in data) return <p>Error</p>;
+ // else return <Inner data={data} refetch={refetch} />;
+ return <p>Error</p>;
+}
+function Nostr() {
+ const { relays } = useLocalState();
+ const feed = eventsToFc(relays);
+ console.log({ feed });
+ const refetch = () => feed;
+ return <PostList data={feed} refetch={refetch} />;
+}
+
+export default Loader;
+// TODO
+type MixFeed = any;
+
+function Inner({ data, refetch }: { data: MixFeed; refetch: Function }) {
+ return <PostList data={data.mix.fc} refetch={refetch} />;
+}
diff --git a/front/src/pages/Settings.tsx b/front/src/pages/Settings.tsx
new file mode 100644
index 0000000..e0f1da9
--- /dev/null
+++ b/front/src/pages/Settings.tsx
@@ -0,0 +1,92 @@
+import useLocalState from "@/state/state";
+import type { UserProfile } from "@/types/nostril";
+import { useState } from "react";
+
+function Settings() {
+ const { UISettings, keys, profiles, relays, api } = useLocalState();
+ const [newRelay, setNewRelay] = useState("");
+ async function saveSetting(
+ bucket: string,
+ key: string,
+ value: string | boolean | number | string[],
+ ) {
+ const json = {
+ "put-entry": {
+ desk: "trill",
+ "bucket-key": bucket,
+ "entry-key": key,
+ value,
+ },
+ };
+ // const res = await poke("settings", "settings-event", json);
+ // if (res) refetchSettings();
+ }
+ async function removeRelay(url: string) {
+ console.log({ url });
+ }
+ async function addNewRelay() {
+ //
+ // await addnr(newRelay);
+ }
+ async function removeProfile(pubkey: string) {
+ api!.removeKey(pubkey);
+ }
+ async function createProfile() {
+ //
+ api!.createKey();
+ }
+
+ return (
+ <div id="settings">
+ <h1>Settings</h1>
+ <div className="setting">
+ <label>Pubkeys</label>
+ {keys.map((k) => {
+ const profile = profiles.get(k);
+ const profileDiv = !profile ? (
+ <div className="profile">
+ <div>Pubkey: {k}</div>
+ <p>No profile set</p>)
+ </div>
+ ) : (
+ <div className="profile">
+ {profile.picture && <img src={profile.picture} />}
+ <div>Name: {profile.name}</div>
+ <div>Pubkey: {k}</div>
+ <div>About: {profile.about}</div>
+ <button onClick={() => removeProfile(k)}>x</button>
+ </div>
+ );
+ return (
+ <div className="options flex" key={k}>
+ {profileDiv}
+ </div>
+ );
+ })}
+ <div className="options flex">
+ <button onClick={createProfile}>Create New</button>
+ </div>
+ </div>
+ <div className="setting">
+ <label>Nostr Relays</label>
+ {Object.keys(relays).map((r) => (
+ // TODO: add connect button to connect and disc to relay one by one
+ <div className="options flex" key={r}>
+ <div>{r}</div>
+ <button onClick={() => removeRelay(r)}>x</button>
+ </div>
+ ))}
+ <div className="options flex">
+ <label>Add new</label>
+ <input
+ type="text"
+ value={newRelay}
+ onChange={(e) => setNewRelay(e.target.value)}
+ />
+ <button onClick={addNewRelay}>Add</button>
+ </div>
+ </div>
+ </div>
+ );
+}
+export default Settings;
diff --git a/front/src/pages/User.tsx b/front/src/pages/User.tsx
new file mode 100644
index 0000000..fc727e4
--- /dev/null
+++ b/front/src/pages/User.tsx
@@ -0,0 +1,18 @@
+// import spinner from "@/assets/icons/spinner.svg";
+import PostList from "@/components/feed/PostList";
+import useLocalState from "@/state/state";
+import type { Ship } from "@/types/urbit";
+
+function UserFeed({ p }: { p: Ship }) {
+ const { api, following } = useLocalState();
+ const feed = following.get(api!.airlock.our!);
+ const refetch = () => feed;
+ if (p === api!.airlock.our)
+ return (
+ <div id="feed-proper">
+ <PostList data={feed!} refetch={refetch} />
+ </div>
+ );
+}
+
+export default UserFeed;
diff --git a/front/src/state/state.ts b/front/src/state/state.ts
new file mode 100644
index 0000000..28f3fb2
--- /dev/null
+++ b/front/src/state/state.ts
@@ -0,0 +1,64 @@
+import type { JSX } from "react";
+import { start } from "@/logic/api";
+import IO from "@/logic/requests/nostril";
+import type { ComposerData } from "@/types/ui";
+import { create } from "zustand";
+import type { UserProfile } from "@/types/nostril";
+import type { Event } from "@/types/nostr";
+import type { FC } from "@/types/trill";
+// TODO handle airlock connection issues
+// the SSE pipeline has a "status-update" event FWIW
+// type AirlockState = "connecting" | "connected" | "failed";
+export type LocalState = {
+ isNew: boolean;
+ api: IO | null;
+ init: () => Promise<void>;
+ UISettings: Record<string, any>;
+ modal: JSX.Element | null;
+ setModal: (modal: JSX.Element | null) => void;
+ composerData: ComposerData | null;
+ setComposerData: (c: ComposerData | null) => void;
+ keys: string[];
+ relays: Record<string, Event[]>;
+ profiles: Map<string, UserProfile>; // pubkey key
+ following: Map<string, FC>;
+ followers: string[];
+};
+
+const creator = create<LocalState>();
+const useLocalState = creator((set, _get) => ({
+ isNew: false,
+ api: null,
+ init: async () => {
+ const airlock = await start();
+ const api = new IO(airlock);
+ console.log({ api });
+ await api.subscribeStore((data) => {
+ console.log("store sub", data);
+ const { feed, following, relays, profiles, keys } = data;
+
+ const flwing = new Map(Object.entries(following as Record<string, FC>));
+ flwing.set(api!.airlock.our!, feed);
+ set({
+ relays,
+ profiles: new Map(Object.entries(profiles)),
+ following: flwing,
+ keys,
+ });
+ });
+ set({ api });
+ },
+ keys: [],
+ profiles: new Map(),
+ relays: {},
+ following: new Map(),
+ followers: [],
+ UISettings: {},
+ modal: null,
+ setModal: (modal) => set({ modal }),
+ // composer data
+ composerData: null,
+ setComposerData: (composerData) => set({ composerData }),
+}));
+
+export default useLocalState;
diff --git a/front/src/styles/ThemeProvider.tsx b/front/src/styles/ThemeProvider.tsx
new file mode 100644
index 0000000..2cc0ca6
--- /dev/null
+++ b/front/src/styles/ThemeProvider.tsx
@@ -0,0 +1,302 @@
+import React, {
+ createContext,
+ useContext,
+ useEffect,
+ useState,
+ type ReactNode,
+} from "react";
+
+export type ThemeName =
+ | "light"
+ | "dark"
+ | "sepia"
+ | "noir"
+ | "ocean"
+ | "forest"
+ | "gruvbox";
+
+export interface ThemeColors {
+ primary: string;
+ primaryHover: string;
+ secondary: string;
+ background: string;
+ surface: string;
+ surfaceHover: string;
+ text: string;
+ textSecondary: string;
+ textMuted: string;
+ border: string;
+ borderLight: string;
+ success: string;
+ warning: string;
+ error: string;
+ info: string;
+ link: string;
+ linkHover: string;
+ shadow: string;
+ overlay: string;
+}
+
+export interface Theme {
+ name: ThemeName;
+ colors: ThemeColors;
+}
+
+const themes: Record<ThemeName, Theme> = {
+ light: {
+ name: "light",
+ colors: {
+ primary: "#543fd7",
+ primaryHover: "#4532b8",
+ secondary: "#f39c12",
+ background: "#ffffff",
+ surface: "#f8f9fa",
+ surfaceHover: "#e9ecef",
+ text: "#212529",
+ textSecondary: "#495057",
+ textMuted: "#6c757d",
+ border: "#dee2e6",
+ borderLight: "#e9ecef",
+ success: "#28a745",
+ warning: "#ffc107",
+ error: "#dc3545",
+ info: "#17a2b8",
+ link: "#543fd7",
+ linkHover: "#4532b8",
+ shadow: "rgba(0, 0, 0, 0.1)",
+ overlay: "rgba(0, 0, 0, 0.5)",
+ },
+ },
+ dark: {
+ name: "dark",
+ colors: {
+ primary: "#7c6ef7",
+ primaryHover: "#9085f9",
+ secondary: "#f39c12",
+ background: "#0d1117",
+ surface: "#161b22",
+ surfaceHover: "#21262d",
+ text: "#c9d1d9",
+ textSecondary: "#8b949e",
+ textMuted: "#6e7681",
+ border: "#30363d",
+ borderLight: "#21262d",
+ success: "#3fb950",
+ warning: "#d29922",
+ error: "#f85149",
+ info: "#58a6ff",
+ link: "#58a6ff",
+ linkHover: "#79b8ff",
+ shadow: "rgba(0, 0, 0, 0.3)",
+ overlay: "rgba(0, 0, 0, 0.7)",
+ },
+ },
+ sepia: {
+ name: "sepia",
+ colors: {
+ primary: "#8b4513",
+ primaryHover: "#6b3410",
+ secondary: "#d2691e",
+ background: "#f4e8d0",
+ surface: "#ede0c8",
+ surfaceHover: "#e6d9c0",
+ text: "#3e2723",
+ textSecondary: "#5d4037",
+ textMuted: "#6d4c41",
+ border: "#d7ccc8",
+ borderLight: "#e0d5d0",
+ success: "#689f38",
+ warning: "#ff9800",
+ error: "#d32f2f",
+ info: "#0288d1",
+ link: "#8b4513",
+ linkHover: "#6b3410",
+ shadow: "rgba(62, 39, 35, 0.1)",
+ overlay: "rgba(62, 39, 35, 0.5)",
+ },
+ },
+ noir: {
+ name: "noir",
+ colors: {
+ primary: "#ffffff",
+ primaryHover: "#e0e0e0",
+ secondary: "#808080",
+ background: "#000000",
+ surface: "#0a0a0a",
+ surfaceHover: "#1a1a1a",
+ text: "#ffffff",
+ textSecondary: "#b0b0b0",
+ textMuted: "#808080",
+ border: "#333333",
+ borderLight: "#1a1a1a",
+ success: "#4caf50",
+ warning: "#ff9800",
+ error: "#f44336",
+ info: "#2196f3",
+ link: "#b0b0b0",
+ linkHover: "#ffffff",
+ shadow: "rgba(255, 255, 255, 0.1)",
+ overlay: "rgba(0, 0, 0, 0.9)",
+ },
+ },
+ ocean: {
+ name: "ocean",
+ colors: {
+ primary: "#006994",
+ primaryHover: "#005577",
+ secondary: "#00acc1",
+ background: "#e1f5fe",
+ surface: "#b3e5fc",
+ surfaceHover: "#81d4fa",
+ text: "#01579b",
+ textSecondary: "#0277bd",
+ textMuted: "#4fc3f7",
+ border: "#81d4fa",
+ borderLight: "#b3e5fc",
+ success: "#00c853",
+ warning: "#ffab00",
+ error: "#d50000",
+ info: "#00b0ff",
+ link: "#0277bd",
+ linkHover: "#01579b",
+ shadow: "rgba(1, 87, 155, 0.1)",
+ overlay: "rgba(1, 87, 155, 0.5)",
+ },
+ },
+ forest: {
+ name: "forest",
+ colors: {
+ primary: "#2e7d32",
+ primaryHover: "#1b5e20",
+ secondary: "#689f38",
+ background: "#f1f8e9",
+ surface: "#dcedc8",
+ surfaceHover: "#c5e1a5",
+ text: "#1b5e20",
+ textSecondary: "#33691e",
+ textMuted: "#558b2f",
+ border: "#aed581",
+ borderLight: "#c5e1a5",
+ success: "#4caf50",
+ warning: "#ff9800",
+ error: "#f44336",
+ info: "#03a9f4",
+ link: "#388e3c",
+ linkHover: "#2e7d32",
+ shadow: "rgba(27, 94, 32, 0.1)",
+ overlay: "rgba(27, 94, 32, 0.5)",
+ },
+ },
+ gruvbox: {
+ name: "gruvbox",
+ colors: {
+ primary: "#fe8019",
+ primaryHover: "#d65d0e",
+ secondary: "#fabd2f",
+ background: "#282828",
+ surface: "#3c3836",
+ surfaceHover: "#504945",
+ text: "#ebdbb2",
+ textSecondary: "#d5c4a1",
+ textMuted: "#bdae93",
+ border: "#665c54",
+ borderLight: "#504945",
+ success: "#b8bb26",
+ warning: "#fabd2f",
+ error: "#fb4934",
+ info: "#83a598",
+ link: "#8ec07c",
+ linkHover: "#b8bb26",
+ shadow: "rgba(0, 0, 0, 0.3)",
+ overlay: "rgba(40, 40, 40, 0.8)",
+ },
+ },
+};
+
+interface ThemeContextType {
+ theme: Theme;
+ themeName: ThemeName;
+ setTheme: (name: ThemeName) => void;
+ availableThemes: ThemeName[];
+}
+
+const ThemeContext = createContext<ThemeContextType | undefined>(undefined);
+
+interface ThemeProviderProps {
+ children: ReactNode;
+ defaultTheme?: ThemeName;
+}
+
+export const ThemeProvider: React.FC<ThemeProviderProps> = ({
+ children,
+ defaultTheme = "light",
+}) => {
+ const [themeName, setThemeName] = useState<ThemeName>(() => {
+ const savedTheme = localStorage.getItem("theme") as ThemeName;
+ if (savedTheme && themes[savedTheme]) {
+ return savedTheme;
+ }
+
+ if (
+ window.matchMedia &&
+ window.matchMedia("(prefers-color-scheme: dark)").matches
+ ) {
+ return "dark";
+ }
+
+ return defaultTheme;
+ });
+
+ const theme = themes[themeName];
+
+ useEffect(() => {
+ const root = document.documentElement;
+
+ root.setAttribute("data-theme", themeName);
+
+ Object.entries(theme.colors).forEach(([key, value]) => {
+ const cssVarName = `--color-${key.replace(/([A-Z])/g, "-$1").toLowerCase()}`;
+ root.style.setProperty(cssVarName, value);
+ });
+
+ localStorage.setItem("theme", themeName);
+ }, [themeName, theme]);
+
+ useEffect(() => {
+ const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
+ const handleChange = (e: MediaQueryListEvent) => {
+ const savedTheme = localStorage.getItem("theme");
+ if (!savedTheme) {
+ setThemeName(e.matches ? "dark" : "light");
+ }
+ };
+
+ mediaQuery.addEventListener("change", handleChange);
+ return () => mediaQuery.removeEventListener("change", handleChange);
+ }, []);
+
+ const setTheme = (name: ThemeName) => {
+ if (themes[name]) {
+ setThemeName(name);
+ }
+ };
+
+ const value: ThemeContextType = {
+ theme,
+ themeName,
+ setTheme,
+ availableThemes: Object.keys(themes) as ThemeName[],
+ };
+
+ return (
+ <ThemeContext.Provider value={value}>{children}</ThemeContext.Provider>
+ );
+};
+
+export const useTheme = (): ThemeContextType => {
+ const context = useContext(ThemeContext);
+ if (context === undefined) {
+ throw new Error("useTheme must be used within a ThemeProvider");
+ }
+ return context;
+};
diff --git a/front/src/styles/ThemeSwitcher.css b/front/src/styles/ThemeSwitcher.css
new file mode 100644
index 0000000..518a00d
--- /dev/null
+++ b/front/src/styles/ThemeSwitcher.css
@@ -0,0 +1,249 @@
+/* Theme Switcher Styles */
+
+/* Compact variant */
+.theme-switcher-compact {
+ display: inline-flex;
+ align-items: center;
+ gap: var(--spacing-sm);
+ padding: var(--spacing-sm) var(--spacing-md);
+ background-color: var(--color-surface);
+ border: 1px solid var(--color-border);
+ border-radius: var(--radius-full);
+ cursor: pointer;
+ transition: all var(--transition-fast);
+ font-size: var(--font-md);
+ color: var(--color-text);
+}
+
+.theme-switcher-compact:hover {
+ background-color: var(--color-surface-hover);
+ border-color: var(--color-primary);
+ transform: scale(1.05);
+}
+
+.theme-switcher-compact:active {
+ transform: scale(0.98);
+}
+
+.theme-switcher-compact .theme-icon {
+ font-size: 1.2em;
+ display: flex;
+ align-items: center;
+}
+
+.theme-switcher-compact .theme-label {
+ font-weight: var(--font-medium);
+}
+
+/* Buttons variant */
+.theme-switcher-buttons {
+ display: flex;
+ align-items: center;
+ gap: var(--spacing-md);
+}
+
+.theme-switcher-buttons .theme-label {
+ color: var(--color-text-secondary);
+ font-weight: var(--font-medium);
+}
+
+.theme-buttons-group {
+ display: flex;
+ gap: var(--spacing-xs);
+ background-color: var(--color-surface);
+ padding: var(--spacing-xs);
+ border-radius: var(--radius-lg);
+ border: 1px solid var(--color-border);
+}
+
+.theme-button {
+ display: flex;
+ align-items: center;
+ gap: var(--spacing-xs);
+ padding: var(--spacing-xs) var(--spacing-sm);
+ background-color: transparent;
+ border: 1px solid transparent;
+ border-radius: var(--radius-md);
+ cursor: pointer;
+ transition: all var(--transition-fast);
+ color: var(--color-text-secondary);
+ font-size: var(--font-sm);
+}
+
+.theme-button:hover {
+ background-color: var(--color-surface-hover);
+ color: var(--color-text);
+}
+
+.theme-button.active {
+ background-color: var(--color-primary);
+ color: white;
+ border-color: var(--color-primary);
+}
+
+.theme-button .theme-icon {
+ font-size: 1.1em;
+}
+
+.theme-button .theme-name {
+ display: none;
+}
+
+@media (min-width: 768px) {
+ .theme-button .theme-name {
+ display: inline;
+ }
+}
+
+/* Dropdown variant */
+.theme-switcher-dropdown {
+ position: relative;
+ display: inline-block;
+}
+
+.theme-dropdown-toggle {
+ display: flex;
+ align-items: center;
+ gap: var(--spacing-sm);
+ padding: var(--spacing-sm) var(--spacing-md);
+ background-color: var(--color-surface);
+ border: 1px solid var(--color-border);
+ border-radius: var(--radius-md);
+ cursor: pointer;
+ transition: all var(--transition-fast);
+ color: var(--color-text);
+ font-size: var(--font-md);
+}
+
+.theme-dropdown-toggle:hover {
+ background-color: var(--color-surface-hover);
+ border-color: var(--color-primary);
+}
+
+.theme-dropdown-toggle .theme-icon {
+ font-size: 1.2em;
+}
+
+.theme-dropdown-toggle .theme-label {
+ font-weight: var(--font-medium);
+}
+
+.theme-dropdown-toggle .dropdown-arrow {
+ font-size: 0.7em;
+ margin-left: var(--spacing-xs);
+ transition: transform var(--transition-fast);
+ color: var(--color-text-muted);
+}
+
+.theme-dropdown-toggle[aria-expanded="true"] .dropdown-arrow {
+ transform: rotate(180deg);
+}
+
+.theme-dropdown-backdrop {
+ position: fixed;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ z-index: var(--z-dropdown);
+ background-color: transparent;
+}
+
+.theme-dropdown-menu {
+ position: absolute;
+ top: calc(100% + var(--spacing-xs));
+ right: 0;
+ min-width: 180px;
+ background-color: var(--color-background);
+ border: 1px solid var(--color-border);
+ border-radius: var(--radius-lg);
+ box-shadow: 0 4px 12px var(--color-shadow);
+ z-index: calc(var(--z-dropdown) + 1);
+ padding: var(--spacing-xs);
+ animation: dropdownSlide 0.2s ease-out;
+}
+
+@keyframes dropdownSlide {
+ from {
+ opacity: 0;
+ transform: translateY(-10px);
+ }
+ to {
+ opacity: 1;
+ transform: translateY(0);
+ }
+}
+
+.theme-dropdown-item {
+ display: flex;
+ align-items: center;
+ gap: var(--spacing-sm);
+ width: 100%;
+ padding: var(--spacing-sm) var(--spacing-md);
+ background-color: transparent;
+ border: none;
+ border-radius: var(--radius-md);
+ cursor: pointer;
+ transition: all var(--transition-fast);
+ color: var(--color-text);
+ font-size: var(--font-md);
+ text-align: left;
+}
+
+.theme-dropdown-item:hover {
+ background-color: var(--color-surface);
+}
+
+.theme-dropdown-item.active {
+ background-color: var(--color-surface);
+ color: var(--color-primary);
+ font-weight: var(--font-medium);
+}
+
+.theme-dropdown-item .theme-icon {
+ font-size: 1.2em;
+ width: 1.5em;
+ text-align: center;
+}
+
+.theme-dropdown-item .theme-name {
+ flex: 1;
+}
+
+.theme-dropdown-item .checkmark {
+ color: var(--color-success);
+ font-weight: var(--font-bold);
+}
+
+/* Accessibility */
+.theme-switcher-compact:focus,
+.theme-button:focus,
+.theme-dropdown-toggle:focus,
+.theme-dropdown-item:focus {
+ outline: 2px solid var(--color-primary);
+ outline-offset: 2px;
+}
+
+/* Dark theme adjustments */
+[data-theme="dark"] .theme-dropdown-menu {
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.5);
+}
+
+/* Reduced motion */
+@media (prefers-reduced-motion: reduce) {
+ .theme-switcher-compact,
+ .theme-button,
+ .theme-dropdown-toggle,
+ .theme-dropdown-item,
+ .dropdown-arrow {
+ transition: none;
+ }
+
+ .theme-dropdown-menu {
+ animation: none;
+ }
+
+ .theme-switcher-compact:hover {
+ transform: none;
+ }
+} \ No newline at end of file
diff --git a/front/src/styles/ThemeSwitcher.tsx b/front/src/styles/ThemeSwitcher.tsx
new file mode 100644
index 0000000..425bed9
--- /dev/null
+++ b/front/src/styles/ThemeSwitcher.tsx
@@ -0,0 +1,131 @@
+import React, { useState } from "react";
+import { useTheme, type ThemeName } from "../styles/ThemeProvider";
+import "./ThemeSwitcher.css";
+
+interface ThemeSwitcherProps {
+ variant?: "dropdown" | "buttons" | "compact";
+ showLabel?: boolean;
+}
+
+const themeIcons: Record<ThemeName, string> = {
+ light: "☀️",
+ dark: "🌙",
+ sepia: "📜",
+ noir: "⚫",
+ ocean: "🌊",
+ forest: "🌲",
+ gruvbox: "🍂",
+};
+
+const themeLabels: Record<ThemeName, string> = {
+ light: "Light",
+ dark: "Dark",
+ sepia: "Sepia",
+ noir: "Noir",
+ ocean: "Ocean",
+ forest: "Forest",
+ gruvbox: "Gruvbox",
+};
+
+export const ThemeSwitcher: React.FC<ThemeSwitcherProps> = ({
+ variant = "dropdown",
+ showLabel = true,
+}) => {
+ const { themeName, setTheme, availableThemes } = useTheme();
+ const [isOpen, setIsOpen] = useState(false);
+
+ const handleThemeChange = (theme: ThemeName) => {
+ setTheme(theme);
+ setIsOpen(false);
+ };
+
+ const cycleTheme = () => {
+ const currentIndex = availableThemes.indexOf(themeName);
+ const nextIndex = (currentIndex + 1) % availableThemes.length;
+ setTheme(availableThemes[nextIndex]);
+ };
+
+ if (variant === "compact") {
+ return (
+ <button
+ className="theme-switcher-compact"
+ onClick={cycleTheme}
+ title={`Current theme: ${themeLabels[themeName]}. Click to switch.`}
+ aria-label="Switch theme"
+ >
+ <span className="theme-icon">{themeIcons[themeName]}</span>
+ {showLabel && (
+ <span className="theme-label">{themeLabels[themeName]}</span>
+ )}
+ </button>
+ );
+ }
+
+ if (variant === "buttons") {
+ return (
+ <div className="theme-switcher-buttons">
+ {showLabel && <span className="theme-label">Theme:</span>}
+ <div className="theme-buttons-group">
+ {availableThemes.map((theme) => (
+ <button
+ key={theme}
+ className={`theme-button ${themeName === theme ? "active" : ""}`}
+ onClick={() => handleThemeChange(theme)}
+ title={themeLabels[theme]}
+ aria-label={`Switch to ${themeLabels[theme]} theme`}
+ aria-pressed={themeName === theme}
+ >
+ <span className="theme-icon">{themeIcons[theme]}</span>
+ {showLabel && (
+ <span className="theme-name">{themeLabels[theme]}</span>
+ )}
+ </button>
+ ))}
+ </div>
+ </div>
+ );
+ }
+
+ // Default dropdown variant
+ return (
+ <div className="theme-switcher-dropdown">
+ <button
+ className="theme-dropdown-toggle"
+ onClick={() => setIsOpen(!isOpen)}
+ aria-haspopup="true"
+ aria-expanded={isOpen}
+ >
+ <span className="theme-icon">{themeIcons[themeName]}</span>
+ {showLabel && (
+ <span className="theme-label">{themeLabels[themeName]}</span>
+ )}
+ <span className="dropdown-arrow">▼</span>
+ </button>
+
+ {isOpen && (
+ <>
+ <div
+ className="theme-dropdown-backdrop"
+ onClick={() => setIsOpen(false)}
+ aria-hidden="true"
+ />
+ <div className="theme-dropdown-menu" role="menu">
+ {availableThemes.map((theme) => (
+ <button
+ key={theme}
+ className={`theme-dropdown-item ${themeName === theme ? "active" : ""}`}
+ onClick={() => handleThemeChange(theme)}
+ role="menuitem"
+ aria-selected={themeName === theme}
+ >
+ <span className="theme-icon">{themeIcons[theme]}</span>
+ <span className="theme-name">{themeLabels[theme]}</span>
+ {themeName === theme && <span className="checkmark">✓</span>}
+ </button>
+ ))}
+ </div>
+ </>
+ )}
+ </div>
+ );
+};
diff --git a/front/src/styles/styles.css b/front/src/styles/styles.css
new file mode 100644
index 0000000..c2b05d6
--- /dev/null
+++ b/front/src/styles/styles.css
@@ -0,0 +1,438 @@
+/* assets */
+/* fonts */
+@font-face {
+ font-family: "Inter";
+ src: url(/fonts/Inter/Inter-VariableFont_opsz,wght.ttf);
+ font-weight: 100 900;
+ font-style: normal;
+ font-display: swap;
+}
+
+@font-face {
+ font-family: "Inter";
+ src: url(/fonts/Inter/Inter-Italic-VariableFont_opsz,wght.ttf);
+ font-weight: 100 900;
+ font-style: italic;
+ font-display: swap;
+}
+
+@font-face {
+ font-family: "Source Code Pro";
+ src: url(/fonts/Source_Code_Pro/SourceCodePro-VariableFont_wght.ttf);
+ font-weight: 100 900;
+ font-style: normal;
+ font-display: swap;
+}
+
+@font-face {
+ font-family: "Source Code Pro";
+ src: url(/fonts/Source_Code_Pro/SourceCodePro-Italic-VariableFont_wght.ttf);
+ font-weight: 100 900;
+ font-style: italic;
+ font-display: swap;
+}
+
+/* tailwindy */
+
+.grow {
+ flex-grow: 1;
+}
+
+button {
+ cursor: pointer;
+}
+
+code {
+ font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New",
+ monospace;
+}
+
+t .red {
+ background-color: rgb(200, 0, 0, 0.9);
+}
+
+.tc,
+.ct {
+ text-align: center;
+}
+
+.cb {
+ margin: auto;
+}
+
+.xc {
+ position: absolute;
+ left: 50%;
+ transform: translateX(-50%);
+}
+
+.hidden {
+ display: none;
+}
+
+.x-center {
+ margin: auto;
+ text-align: center;
+ display: block;
+}
+
+.flex {
+ display: flex;
+}
+
+.f1 {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+}
+
+.flex-align {
+ display: flex;
+ gap: 1rem;
+ align-items: center;
+}
+
+.noscroll {
+ overflow: hidden;
+}
+
+.scroll-y {
+ overflow-y: scroll;
+}
+
+.cp {
+ cursor: pointer;
+}
+
+.m0 {
+ margin: 0;
+}
+
+.mb {
+ margin: 0 0 1rem 0;
+}
+
+.mt {
+ margin-top: 1rem;
+}
+
+.mr {
+ margin-right: 0.5rem;
+}
+
+.s-50 {
+ width: 50px;
+}
+
+.s-100 {
+ width: 100px;
+}
+
+.border {
+ border: 1px solid var(--text-color);
+}
+
+/* styles */
+
+/* common */
+html {
+ box-sizing: border-box;
+ color: var(--text-color);
+ background-color: var(--background-color);
+}
+
+html,
+body,
+#root,
+#mobile-ui {
+ height: 100%;
+ width: 100vw;
+ overflow: hidden;
+ /* no scrolling!!!*/
+}
+
+*,
+*:before,
+*:after {
+ box-sizing: inherit;
+}
+
+body {
+ margin: 0;
+ font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
+ 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
+ sans-serif;
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+ background-color: var(--color-background);
+ color: var(--color-text);
+ line-height: 1.6;
+ transition: background-color var(--transition-normal), color var(--transition-normal);
+}
+
+/* Typography */
+h1,
+h2,
+h3,
+h4,
+h5,
+h6 {
+ margin-bottom: var(--spacing-md);
+ font-weight: var(--font-semibold);
+ line-height: 1.2;
+ color: var(--color-text);
+}
+
+#root {
+ margin: 1rem 2rem;
+ height: 100%;
+ overflow-y: auto;
+ font-family: "Inter";
+
+
+ display: flex;
+
+ & #left-menu {
+ margin-right: 1rem;
+
+ #logo {
+ display: flex;
+ gap: 0.3rem;
+
+ & img {
+ width: 48px;
+ height: 48px;
+ }
+ }
+
+ & .opt {
+ cursor: pointer;
+ display: flex;
+ gap: 1rem;
+ margin: 1rem 0;
+
+ & img {
+ width: 24px;
+ height: 24px;
+ }
+ }
+ }
+
+ & main {
+ width: 726px;
+ margin: auto;
+ height: 100vh;
+
+ & #top-tabs {
+ display: flex;
+ gap: 2rem;
+ justify-content: center;
+
+ & div {
+ cursor: pointer;
+ }
+
+ & .active {
+ font-weight: 700;
+ border-bottom: 3px solid var(--color-text);
+ }
+ }
+
+ & #feed-proper {
+ margin-top: 1rem;
+ border: 1px solid grey;
+ border-radius: 0.75rem;
+
+ & #composer {
+ padding: 10px;
+ display: flex;
+ gap: 0.5rem;
+
+ & .sigil {
+ width: 48px;
+ height: 48px;
+
+ & img {
+ width: inherit;
+ }
+ }
+
+ & input {
+ background-color: transparent;
+ color: var(--color-text);
+ flex-grow: 1;
+ border: none;
+ outline: none;
+ }
+ }
+ }
+
+ & .trill-post,
+ & .twatter-post {
+ border-top: 1px solid grey;
+
+ & .left {
+ margin-right: 10px;
+ width: unset;
+
+ & .sigil {
+ width: 48px;
+ height: 48px;
+ }
+ }
+
+ & header {
+ align-items: center;
+ justify-content: left;
+
+ & .author {
+ flex: unset;
+ gap: 0;
+
+ & .name {
+ display: flex;
+ align-items: center;
+
+ & .p {
+ font-family: "Source Code Pro";
+ }
+ }
+ }
+
+ & .date {
+ color: grey;
+ }
+
+ }
+
+ & footer {
+ justify-content: left;
+ margin: unset;
+
+ & .icon {
+ margin: 0;
+ align-items: center;
+ gap: 0.2rem;
+ width: 64px;
+
+ & img {
+ height: 18px;
+ }
+
+ & .react-img {
+ height: 24px;
+ }
+
+ & .react-icon {
+ font-size: 20px;
+ }
+
+ & span {
+ margin-right: unset;
+ text-align: left;
+ font-size: 14px;
+ line-height: 1rem;
+ color: grey;
+ width: unset;
+ }
+ }
+
+ & .menu-icon {
+ margin-left: auto;
+ }
+ }
+ }
+
+
+ & .user-contact {
+ & .contact-cover {
+ margin-bottom: -40px;
+
+ & img {
+ width: 100%;
+ height: 100%;
+ object-fit: cover;
+ }
+ }
+
+ & .contact-name {
+ display: flex;
+ align-items: center;
+ gap: 0.5rem;
+ }
+
+ & .contact-username {
+ margin-top: 1rem;
+ font-family: "Source Code Pro";
+ font-weight: 400;
+ }
+
+ & button {
+ width: unset;
+ margin: unset;
+ height: unset;
+ }
+ }
+ }
+
+ & button {
+ font-size: 0.9rem;
+ font-weight: 700;
+ line-height: 1rem;
+ border: none;
+ border-radius: 2rem;
+ padding: 0.5rem 2rem;
+ }
+
+ & .sigil,
+ & .sigil svg {
+ border-radius: 0.5rem;
+ }
+}
+
+#big-button {
+ position: absolute;
+ right: 2rem;
+ bottom: 2rem;
+ font-size: 1.5rem;
+ font-weight: bold;
+ cursor: pointer;
+ text-align: center;
+ line-height: 3rem;
+ width: 3rem;
+ height: 3rem;
+ border-radius: 50%;
+ z-index: 100;
+}
+
+/* modal */
+#modal-background {
+ height: 100vh;
+ width: 100vw;
+ background-color: rgb(0, 0, 0, 0.9);
+ position: fixed;
+ top: 0;
+ left: 0;
+ z-index: 100;
+}
+
+#modal {
+ position: fixed;
+ top: 50%;
+ left: 50%;
+ width: 80%;
+ z-index: 101;
+ transform: translate(-50%, -50%);
+ background-color: var(--background-color);
+ padding: 1rem;
+ max-height: 80%;
+}
+
+.modal-buttons {
+ display: flex;
+ justify-content: space-around;
+}
+
+::-webkit-scrollbar {
+ display: none;
+} \ No newline at end of file
diff --git a/front/src/styles/trill.css b/front/src/styles/trill.css
new file mode 100644
index 0000000..5687c7a
--- /dev/null
+++ b/front/src/styles/trill.css
@@ -0,0 +1,612 @@
+#not-found {
+ margin: auto;
+ padding: 2rem;
+ text-align: center;
+}
+
+#not-found button {
+ height: 1.5rem;
+ margin: auto;
+}
+
+#timeline {
+ overflow-y: auto;
+ overflow-x: hidden;
+}
+
+.timeline-post {
+ width: 100%;
+ border-top: 1px solid var(--text-color);
+}
+
+.trill-post {
+ display: flex;
+ padding: 0.5rem;
+ /* min-height: 150px; */
+}
+
+.trill-post .author {
+ flex: 1 0 auto;
+}
+
+.trill-reply-thread {
+ border-top: 1px solid var(--text-color);
+}
+
+.trill-post:first-child {
+ border-top: none;
+}
+
+.trill-post:last-child {
+ border-bottom: 1px solid var(--text-color);
+}
+
+.trill-post .left {
+ width: 8%;
+ margin-right: 1rem;
+}
+
+.trill-post .sigil {
+ height: 42px;
+ width: 42px;
+}
+
+.trill-post .right {
+ width: 90%;
+}
+
+.trill-post header {
+ display: flex;
+ justify-content: space-between;
+}
+
+.trill-post header p {
+ margin: 0 0.3rem;
+}
+
+.trill-post .nick {
+ font-weight: 700;
+}
+
+.trill-post header .p {
+ font-family: "Courier New", Courier, monospace;
+ font-weight: 100;
+ font-size: 1rem;
+}
+
+.trill-post .p-only {
+ margin: 0.7rem 0.3rem;
+ font-weight: 700;
+}
+
+.trill-post .p {
+ /* margin-top: -5px; */
+}
+
+.trill-post a {
+ text-decoration: 0;
+ color: var(--text-color);
+}
+
+.trill-post blockquote {
+ border-left: 2px solid grey;
+ margin-left: 0;
+ padding-left: 0.5rem;
+ opacity: 70%;
+}
+
+.trill-post .body {
+ margin: 1rem;
+ margin-left: 0;
+}
+
+.trill-post-body p span {
+ /* margin: 0 3px; */
+}
+
+.trill-post pre {
+ font-family: "Courier New", Courier, monospace;
+ background-color: rgb(200, 200, 200, 0.5);
+ padding: 0.2rem;
+ max-width: 90%;
+ border: 1px solid var(--text-color);
+ overflow: scroll;
+}
+
+.trill-post .quote-in-post .body {
+ margin: 0;
+}
+
+.quote-in-post svg {
+ margin-right: 0.5rem;
+}
+
+.trill-post .body-text {
+ /* font-family: Arial, Helvetica, sans-serif; */
+ margin: 0.3rem 0 1rem 0;
+ word-break: break-word;
+}
+
+.trill-post .trill-post-paragraph {
+ margin-block-start: 1em;
+ margin-block-end: 1em;
+}
+
+.trill-post .body-text a {
+ text-decoration: underline;
+}
+
+.trill-post .token {
+ margin: 0 0.5rem;
+}
+
+.trill-post .date {
+ float: right;
+}
+
+.trill-post .nav {
+ display: flex;
+}
+
+.trill-post .chevron {
+ width: 1.5rem;
+ height: 1.5rem;
+}
+
+.body-media {
+ width: 100%;
+ max-height: 520px;
+ text-align: center;
+ /* images being inline */
+}
+
+.body-media img {
+ margin: 1px 3px;
+}
+
+.body-img-1-of-1 {
+ max-width: 100%;
+ max-height: inherit;
+ margin: auto !important;
+}
+
+.body-img-1-of-2 {
+ max-width: 48.5%;
+ max-height: inherit;
+}
+
+.body-img-1-of-3 {
+ max-width: 48.5%;
+}
+
+.body-img-1-of-4 {
+ max-width: 48.5%;
+}
+
+.body-img-1-of-5 {
+ max-width: 31%;
+}
+
+.body-img-1-of-6 {
+ max-width: 31%;
+}
+
+.body-img-1-of-7 {
+ max-width: 31%;
+}
+
+.body-img-1-of-8 {
+ max-width: 31%;
+}
+
+.body-img-1-of-9 {
+ max-width: 31%;
+}
+
+/* quotes */
+
+.quote-in-post {
+ margin-top: 1rem;
+ padding: 0.5rem;
+ border: 1px solid grey;
+ border-radius: 0.5rem;
+ cursor: pointer;
+}
+
+.quote-in-post header {
+ display: flex;
+}
+
+.mention {
+ font-family: "Courier New", Courier, monospace;
+ font-weight: 700;
+}
+
+.mention:hover {
+ cursor: pointer;
+ text-decoration: underline;
+}
+
+.bad-quote {
+ border: 1px solid var(--text-color);
+ padding: 7px;
+ border-radius: 0.5rem;
+}
+
+/* post-cards */
+.trill-post-card {
+ position: relative;
+ border-radius: 0.3rem;
+ /* margin: 1rem 0 0 -8%; */
+ margin: 0.5rem 0;
+}
+
+.trill-post-card-logo {
+ position: absolute;
+ width: 25px;
+ height: 25px;
+ top: -17px;
+ left: -17px;
+}
+
+#post-menu {
+ position: absolute;
+ top: 0;
+ right: 50px;
+ z-index: 99;
+}
+
+.deleted-post {
+ text-align: center;
+ border: 1px solid var(--text-color);
+ padding: 0.4rem;
+}
+
+#post-menu p {
+ background-color: var(--background-color);
+ margin: 0;
+ padding: 0.5rem;
+ cursor: pointer;
+ border: 1px solid var(--text-color);
+ height: 40px;
+}
+
+#post-menu p:hover {
+ /* background-color: var(--highlighted-grey); */
+}
+
+/* threads */
+.trill-reply-thread {
+ margin-top: 1rem;
+}
+
+#replies>.trill-post:first-child {
+ border-top: 1px solid black;
+}
+
+/* footer */
+
+.footer-wrapper {
+ position: relative;
+ /* transform: rotate(0deg); */
+ /* the dummy transform enforces position fixed inheritance */
+}
+
+.post-footer footer {
+ display: flex;
+ margin-left: -20px;
+ height: 24px;
+ justify-content: space-between;
+}
+
+footer .icon {
+ cursor: pointer;
+ margin: 0 0.2rem;
+ display: flex;
+ /* min-width: 64px; */
+}
+
+footer #menu-icon {
+ width: 32px !important;
+ /* margin-left: 20px; */
+}
+
+.post-footer footer .icon img {
+ display: block;
+ width: 24px;
+ height: 24px;
+}
+
+footer .icon span {
+ display: block;
+ width: 30px;
+ text-align: right;
+ padding-top: 0.2rem;
+ margin-right: 0.4rem;
+}
+
+footer .icon span:hover {
+ text-decoration: underline;
+}
+
+.react-icon {
+ font-size: 26px;
+ margin: -10px 0 0 0 !important;
+ padding: 0;
+ padding-top: 0 !important;
+}
+
+#react-list {
+ display: flex;
+ flex-wrap: wrap;
+}
+
+#react-list img {
+ margin: 3px;
+ width: 50px;
+ height: 50px;
+ cursor: pointer;
+ border: 1px solid transparent;
+}
+
+#react-list span {
+ width: 50px;
+ height: 50px;
+ font-size: 38px;
+ margin: 3px;
+ cursor: pointer;
+ border: 1px solid transparent;
+}
+
+#react-list span:hover,
+#react-list img:hover {
+ border: 1px solid var(--text-color);
+}
+
+#menu-background {
+ position: fixed;
+ top: 0;
+ left: 0;
+ opacity: 0;
+ height: 100vh;
+ width: 100vw;
+}
+
+/* contact */
+
+.contact-cover {
+ height: 150px;
+ max-width: 100vw;
+ margin-bottom: -50px;
+}
+
+#contact-proper {
+ padding: 1rem;
+}
+
+#contact-proper .row {
+ display: flex;
+}
+
+.contact-avatar {
+ width: 6rem;
+ height: 6rem;
+}
+
+.contact-name {
+ margin-top: 1rem;
+ margin-bottom: 0.5rem;
+ margin-left: 0.3rem;
+ font-weight: 700;
+ font-size: 1.1rem;
+}
+
+.contact-username {
+ margin-top: -10px;
+}
+
+#contact-proper .buttons {
+ margin-top: 2rem;
+ margin-left: auto;
+}
+
+#contact-proper .buttons button {
+ width: 5rem;
+ margin-bottom: 5px;
+ height: 1.5rem;
+}
+
+#contact-proper .p {
+ font-family: "Courier New", Courier, monospace;
+}
+
+#contact-proper .p-only {
+ margin-top: 1rem;
+}
+
+.bio-row {
+ display: flex;
+ align-items: center;
+}
+
+.stats-row {
+ display: flex;
+ justify-content: center;
+}
+
+.stats-icon {
+ margin: 0 2px;
+}
+
+.stats-row p {
+ text-align: center;
+ font-size: 1.3rem;
+ margin: -5px 0 0 0;
+}
+
+.stats-row img {
+ width: 32px;
+}
+
+.locked-notice,
+.suspended-notice {
+ text-align: center;
+}
+
+.cover-placeholder {
+ height: 150px;
+ background-color: rgb(125, 125, 125, 0.5);
+}
+
+#stats-modal .trill-post {
+ border-bottom: 1px solid var(--text-color) !important;
+}
+
+#stats-modal {
+ height: 80vh;
+}
+
+#stats-modal #engagement {
+ min-height: 40%;
+ max-height: 40%;
+ overflow-y: scroll;
+}
+
+#stats-modal .trill-post {
+ max-height: 50%;
+ overflow-y: scroll;
+}
+
+.btw {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+}
+
+#stats-modal .react-stat img {
+ width: 32px;
+ height: 32px;
+}
+
+#stats-modal .react-stat react-icon {
+ width: 32px;
+ height: 32px;
+}
+
+#stats-modal #engagement .nickname {
+ font-size: 1rem;
+}
+
+#stats-modal #engagement .p {
+ font-size: 0.9rem;
+}
+
+#stats-modal .tab h4 {
+ font-weight: 100;
+}
+
+#stats-modal .tab.active-tab h4 {
+ font-weight: 700;
+}
+
+/* .not-found {
+ border: 1px solid var(--text-color);
+ border-radius: 1rem;
+ padding: 0.5rem;
+} */
+
+/* refs */
+.reference {}
+
+/* polls */
+.trill-poll {
+ /* border: 1px solid var(--text-color); */
+ border-radius: 1rem;
+ padding: 0.5rem;
+ position: relative;
+ background: linear-gradient(90deg,
+ rgba(255, 255, 168, 0.4) 0%,
+ /* Lighter yellow */
+ rgba(255, 233, 150, 0.5) 52%,
+ /* Mid-tone gold */
+ rgba(255, 209, 0, 0.4) 100%
+ /* Deeper gold */
+ );
+}
+
+.trill-poll .poll-option {
+ height: 2rem;
+ align-items: center;
+ text-align: center;
+ border: 1px solid var(--text-color);
+ border-radius: 0.7rem;
+ margin: 1rem;
+ position: relative;
+ outline: 3px solid transparent;
+}
+
+.trill-poll .my-vote:hover {
+ /* cursor:not-allowed */
+}
+
+.trill-poll .poll-option:hover {
+ opacity: 50%;
+ outline-color: var(--text-color);
+}
+
+.trill-poll .poll-option p {
+ padding: 0 0.5rem;
+ margin: 0;
+ line-height: 2rem;
+}
+
+.trill-poll .poll-option-stats {
+ height: 2rem;
+ position: relative;
+}
+
+.trill-poll .poll-option-bar {
+ height: 100%;
+ position: absolute;
+ background-color: rgb(100, 100, 100, 0.3);
+ border-radius: 0.7rem;
+}
+
+.trill-poll .my-vote {
+ border: 3px solid var(--text-color);
+ border-right: 4px solid var(--text-color);
+}
+
+.trill-poll .bottom-row {
+ opacity: 60%;
+}
+
+.youtube-thumbnail {
+ width: 70%;
+ margin: 0.7rem auto;
+}
+
+.cursor-button {
+ width: 100%;
+ padding: 1rem;
+ border-top: 1px solid var(--text-color);
+}
+
+.cursor-button button {
+ display: block;
+ margin: auto;
+ padding: 0.5rem;
+}
+
+.rumor-quote img {
+ width: 50px;
+ margin-right: 1rem;
+}
+
+#trill-thread {
+ flex-grow: 1;
+ height: 100%;
+ overflow-y: auto;
+
+
+} \ No newline at end of file
diff --git a/front/src/types/nostr.ts b/front/src/types/nostr.ts
new file mode 100644
index 0000000..0ccfaf3
--- /dev/null
+++ b/front/src/types/nostr.ts
@@ -0,0 +1,11 @@
+export type Event = {
+ id: string; // hex, no 0x, 32bytes
+ pubkey: string; // ""
+ sig: string; // "", 64 bytes
+ created_at: number;
+ kind: number;
+ tags: Tag[];
+ content: string;
+};
+
+export type Tag = any[];
diff --git a/front/src/types/nostril.ts b/front/src/types/nostril.ts
new file mode 100644
index 0000000..65a6194
--- /dev/null
+++ b/front/src/types/nostril.ts
@@ -0,0 +1,6 @@
+export type UserProfile = {
+ name: string;
+ picture: string; // URL
+ about: string;
+ other: Record<string, string>;
+};
diff --git a/front/src/types/trill.ts b/front/src/types/trill.ts
new file mode 100644
index 0000000..e0936ad
--- /dev/null
+++ b/front/src/types/trill.ts
@@ -0,0 +1,420 @@
+import type { Ship } from "./urbit";
+
+export type SortugRef = {
+ type: string; // could call it app... anyway
+ ship: Ship;
+ path: string; // `/${string}`
+};
+
+export type PostID = string; //
+export type ID = string; //
+export interface PID {
+ ship: Ship;
+ id: ID;
+}
+
+export type TrillNode = Poast | FullNode;
+export type FullFeed = Record<ID, FullNode>;
+export type FlatFeed = Record<ID, Poast>;
+
+export interface Engagement {
+ reacts: ReactMap;
+ quoted: Array<{ pid: PID }>;
+ shared: Array<{ pid: PID }>;
+}
+export type ReactMap = Record<Ship, string>;
+export interface SentPoast {
+ host: Ship;
+ author: Ship;
+ thread: ID | null;
+ parent: ID | null;
+ contents: string;
+ read: Lock;
+ write: Lock;
+ tags: string[];
+}
+export type Poast = {
+ host: Ship;
+ author: Ship;
+ thread: ID | null;
+ parent: ID | null;
+ read: Lock;
+ write: Lock;
+ tags: string[];
+ contents: Content;
+ id: string;
+ time: number; // not in the backend
+ children: ID[];
+ engagement: Engagement;
+ tlonRumor?: boolean;
+ json?: { origin: ExternalApp; content: string }; // for rumor quoting
+};
+export type FullNode = Omit<Poast, "children"> & {
+ children: FullFeed;
+ prov?: boolean;
+};
+export type Content = Block[];
+export type Block =
+ | Paragraph
+ | Blockquote
+ | Heading
+ | ListBlock
+ | Codeblock
+ | Eval
+ | Media
+ | Reference
+ | ExternalContent;
+
+export type Paragraph = { paragraph: Inline[] };
+export type Blockquote = { blockquote: Inline[] };
+export type Heading = { heading: { text: string; num: number } };
+export type Codeblock = { codeblock: { code: string; lang: string } };
+export type Eval = { hoon: string };
+export type ListBlock = { list: { ordered: boolean; text: Inline[] } };
+export type Media = { media: PostImages | PostVideo | PostAudio };
+export type PostImages = { images: string[] };
+export type PostVideo = { video: string };
+export type PostAudio = { audio: string };
+export type Reference = { ref: { type: string; ship: Ship; path: string } };
+
+export type Inline =
+ | TextInline
+ | Italic
+ | Bold
+ | Strike
+ | Underline
+ | Superscript
+ | Subscript
+ | Mention
+ | Codespan
+ | LinkInline
+ | Break;
+export type TextInline = { text: string };
+export type Italic = { italic: string };
+export type Bold = { bold: string };
+export type Strike = { strike: string };
+export type Underline = { underline: string };
+export type Superscript = { sup: string };
+export type Subscript = { sub: string };
+export type Mention = { ship: Ship };
+// TODO! export type Da = {date: number}
+export type Codespan = { codespan: string };
+export type LinkInline = { link: { href: string; show: string } };
+export type Break = { break: null };
+
+export type ExternalContent = {
+ json: {
+ origin: ExternalApp;
+ content: string;
+ };
+};
+export type ExternalApp = "twatter" | "insta" | "anon" | "rumors";
+export interface TwatterReference {
+ json: {
+ origin: "twatter";
+ content: string;
+ };
+}
+// interface CodeContent {
+// code: {
+// expression: string;
+// output: string[][];
+// };
+// }
+// Notifications
+export interface Notifications {
+ engagement: EngagementNotification[];
+ unread: Record<Ship, PID[]>;
+}
+export type Notification =
+ | EngagementNotification
+ | FollowNotification
+ | UnfollowNotification;
+export type EngagementNotification =
+ | ReactNotification
+ | ReplyNotification
+ | QuoteNotification
+ | RepostNotification
+ | MentionNotification;
+export type NotificationData = { ship: Ship; time: number };
+export interface FollowNotification {
+ follow: NotificationData;
+}
+export interface UnfollowNotification {
+ unfollow: NotificationData;
+}
+export interface ReactNotification {
+ react: {
+ pid: PID;
+ react: string;
+ } & NotificationData;
+}
+export interface ReplyNotification {
+ reply: {
+ ab: PID;
+ ad: PID;
+ } & NotificationData;
+}
+export interface QuoteNotification {
+ quote: {
+ ab: PID;
+ ad: PID;
+ } & NotificationData;
+}
+export interface RepostNotification {
+ share: {
+ ab: PID;
+ ad: PID;
+ } & NotificationData;
+}
+export interface MentionNotification {
+ mention: {
+ pid: PID;
+ } & NotificationData;
+}
+export interface UnreadDisplay {
+ [s: Ship]: string[];
+}
+
+// data fetching
+export type MixFeedScry = MixFeed | { bucun: string };
+
+export type Cursor = string | null;
+export type FC = {
+ feed: FlatFeed;
+ start: Cursor;
+ end: Cursor;
+};
+export type MixFeed = {
+ mix: {
+ name: string;
+ fc: FC;
+ };
+};
+export type PoastScry = { post: Poast } | Bucun | NotFollowScry;
+export type Bucun = { bucun: PID };
+// TODO bucun no-node come on
+export type UserFeedScry = UserScry | NotFollowScry;
+export type NotFollowScry = { bugen: Ship };
+export interface UserScry {
+ feed: {
+ ship: Ship;
+ fc: FC;
+ };
+}
+
+export type FullNodeScry =
+ | { fpost: FullNode }
+ | { "no-node": { ship: Ship; id: ID } };
+
+// Facts
+export type PostFact = {
+ post: ThreadFact | GossipFact;
+};
+export type ThreadFact = { thread: FullNode };
+export type GossipFact = { gossip: { post: FullNode; feeds: string[] } };
+
+export type PullFact = PeekFact | BegFact;
+export type PeekFact = { peek: any };
+export type BegFact = { beg: any };
+export type HarkFact = any;
+export type ListsFact = any;
+
+export type TrillProfile = {};
+
+export type TrillPostPermisssion =
+ | "everyone"
+ | "planets"
+ | "followers"
+ | "pals"
+ | "tag";
+
+// Lists
+
+export type List = {
+ name: string;
+ symbol: string; // @tas
+ public: boolean;
+ desc: string;
+ members: ListEntry[];
+ icon: string;
+ cover: string;
+};
+export type ListEntry = {
+ service: "trill" | "twatter" | "twitter";
+ username: string;
+};
+
+export type Lock = {
+ rank: { caveats: Rank[]; locked: boolean; public: boolean };
+ luk: { caveats: Ship[]; locked: boolean; public: boolean };
+ ship: { caveats: Ship[]; locked: boolean; public: boolean };
+ tags: { caveats: string[]; locked: boolean; public: boolean };
+ custom: { fn: null; public: boolean };
+};
+export type Rank = "czar" | "king" | "duke" | "earl" | "pawn";
+// Fetch return types
+export type PushState = {
+ followers: Ship[];
+ gate: {
+ lock: Lock;
+ begs: Ship[];
+ postBegs: PID[];
+ mute: Lock;
+ backlog: number;
+ };
+};
+
+export type PullState = {
+ begs: Ship[];
+ postBegs: PID[];
+ following: Ship[];
+};
+export type TrillSearchResponse = {
+ search: {
+ query: string;
+ fc: FC;
+ };
+};
+export type ListsResponse = {
+ lists: List[];
+};
+export type MetaPeek = {
+ posts: number;
+ inc: Ship[];
+ out: Ship[];
+ lock: Lock;
+ ship: Ship;
+};
+export type NodePeek = {};
+export type FeedPeek = {
+ ship: Ship;
+ feed: FlatFeed;
+};
+export interface FollowAttempt {
+ ship: Ship;
+ timestamp: number;
+}
+export interface Key {
+ ship: Ship;
+ name: string;
+}
+// pals stuff
+// TODO
+// export interface SocialData {
+// groups: any | null;
+// clubs: any | null;
+// lists: List[];
+// pals: Pals | null;
+// contacts: Contacts;
+// }
+
+export type Poll = {
+ host: Ship;
+ id: string; // atom id
+ expiry: number;
+ text: string;
+ options: string[];
+ votes: PollVotes;
+ // TODO locks
+};
+export type PollVotes = HiddenVotes | OpenExcVotes | OpenIncVotes;
+export type HiddenVotes = {
+ type: "hid";
+ exc: boolean;
+ votes: Record<number, number>;
+};
+export type OpenExcVotes = {
+ type: "exc";
+ votes: Record<Ship, VoteComment>;
+};
+export type OpenIncVotes = {
+ type: "inc";
+ votes: Record<number, Ship[]>;
+};
+export type VoteComment = { option: number; comment: string };
+
+export type PollPoke =
+ | CreatePoll
+ | CancelPoll
+ | ChangeExpiry
+ | VotePoke
+ | CancelVote
+ | PeekPoll;
+export type PeekPoll = { peek: PID };
+export type SentPoll = {
+ text: string;
+ expiry: number;
+ options: string[];
+ exc: boolean;
+ hidden: boolean;
+ private: boolean;
+ id: string;
+};
+export type CreatePoll = {
+ propose: SentPoll;
+};
+export type CancelPoll = {
+ cancel: ID;
+};
+export type ChangeExpiry = {
+ "change-expiry": {
+ pid: PID;
+ expiry: number;
+ };
+};
+export type VotePoke = {
+ vote: {
+ pid: PID;
+ option: number;
+ comment: string;
+ };
+};
+export type CancelVote = {
+ "cancel-vote": { pid: PID; option: number };
+};
+export type PollScry = OnePoll | DonePolls | CurrentPolls | BadPoll;
+export type OnePoll = { poll: Poll };
+export type DonePolls = { done: Poll[] };
+export type CurrentPolls = { cur: Poll[] };
+export type BadPoll = { ng: null };
+export type TombPoll = { tomb: null };
+
+export type PollUpdate = NewPollU | DedPollU | OldPollU | PollPeekRes;
+export type DedPollU = { "ded-poll": PID };
+export type OldPollU = { pid: PID } & (
+ | NewVoteU
+ | PollExpiryChanged
+ | VoteCanceled
+ | PollPeekRes
+);
+export type PollPeekRes = {
+ "peek-res": PollPeekOK | PollPeekNG | PollPeekNF;
+};
+export type PollPeekOK = {
+ "peek-ok": Poll;
+};
+export type PollPeekNG = { "peek-ng": string };
+export type PollPeekNF = { "no-poll": null };
+
+export type NewPollU = {
+ "new-poll": Poll;
+};
+export type NewVoteU = {
+ type: "new-vote";
+ update: {
+ option: number;
+ ship: Ship;
+ comment: string;
+ };
+};
+export type PollExpiryChanged = {
+ type: "expiry-changed";
+ update: {
+ expiry: number;
+ };
+};
+export type VoteCanceled = {
+ type: "vote-canceled";
+ update: { option: number; ship: Ship };
+};
diff --git a/front/src/types/twatter.ts b/front/src/types/twatter.ts
new file mode 100644
index 0000000..9814cbf
--- /dev/null
+++ b/front/src/types/twatter.ts
@@ -0,0 +1,336 @@
+import type { Ship } from "./urbit";
+import type { Content as TrillContent } from "@/types/trill";
+
+export interface APITweet {
+ core: APITweetCore;
+ legacy: APITweetLegacy;
+ rest_id?: string; // number
+ __typename?: string;
+ card?: any;
+ quoted_status_result?: { result: APIQuoteTweet };
+}
+export interface APIQuoteTweet extends APITweet {
+ quotedRefResult: { result: { rest_id: string; __typename: string } };
+}
+export interface APITwitterPoll {
+ binding_values: any[];
+ card_platform: any;
+ name: string;
+ url: string;
+ user_refs_results: any[];
+}
+export interface UserEntities {
+ description: {
+ urls: any[];
+ };
+ url: {
+ urls: URLEntity[];
+ };
+}
+export interface TweetEntities {
+ user_mentions: UserMentionEntity[];
+ urls: URLEntity[];
+ hashtags: HashtagEntity[];
+ symbols: any[];
+ media?: MediaEntity[];
+}
+export interface UserMentionEntity {
+ id_str: string; // "144930676"
+ indices: [number, number];
+ name: string; // "Naninizhoni"
+ screen_name: string; // "naninizhoni"
+}
+export interface HashtagEntity {
+ indices: [number, number];
+ text: string;
+}
+export interface URLEntity {
+ url: string;
+ display_url: string;
+ expanded_url: string;
+ indices: [number, number];
+}
+export interface MediaEntity {
+ display_url: string; // "pic.twitter.com/0qkz8kpFPQ"
+ expanded_url: string; // "https://twitter.com/ThaiNewsReports/status/1476368702924898304/photo/1"
+ media_url_https: string; // "https://pbs.twimg.com/media/FH0dgqeXEAEHVgI.jpg"
+ url: string; // "https://t.co/0qkz8kpFPQ"
+ features: {
+ large: { faces: any[] };
+ medium: { faces: any[] };
+ orig: { faces: any[] };
+ small: { faces: any[] };
+ };
+ id_str: string;
+ indices: [number, number];
+ original_info: {
+ height: number;
+ width: number;
+ focus_rects?: { x: number; y: number; w: number; h: number }[];
+ };
+ sizes: {
+ large: MediaSize;
+ medium: MediaSize;
+ small: MediaSize;
+ thumb: MediaSize;
+ };
+ type: "photo"; //"photo" | ??
+}
+export interface ExtendedEntity {
+ media: ExtendedMediaEntity[] | VideoEntity[];
+}
+export interface ExtendedMediaEntity {
+ display_url: string; // "pic.twitter.com/0qkz8kpFPQ"
+ expanded_url: string; // "https://twitter.com/ThaiNewsReports/status/1476368702924898304/photo/1"
+ media_url_https: string; // "https://pbs.twimg.com/media/FH0dgqeXEAEHVgI.jpg"
+ url: string; // "https://t.co/0qkz8kpFPQ"
+ features: {
+ large: { faces: any[] };
+ medium: { faces: any[] };
+ orig: { faces: any[] };
+ small: { faces: any[] };
+ };
+ id_str: string;
+ media_key: string; // "3_1476368699842039809"
+ indices: [number, number];
+ original_info: {
+ height: number;
+ width: number;
+ focus_rects?: { x: number; y: number; w: number; h: number }[];
+ };
+ sizes: {
+ large: MediaSize;
+ medium: MediaSize;
+ small: MediaSize;
+ thumb: MediaSize;
+ };
+ type: "photo" | "video"; // ??
+ ext_media_availability: { status: string }; // "Available"
+ ext_media_color: {
+ palette: {
+ percentage: number;
+ rgb: { red: number; blue: number; green: number };
+ }[];
+ };
+}
+export interface VideoEntity extends ExtendedMediaEntity {
+ original_info: { height: number; width: number };
+ additional_media_info: { monetizable: boolean };
+ mediaStats: { viewCount: number };
+ video_info: {
+ aspect_ratio: [number, number];
+ duration_millis: number;
+ variants: VideoVariant[];
+ };
+}
+export interface VideoVariant {
+ bitrate?: number;
+ content_type: string; // "video/mp4" "application/x-mpegURL"
+ url: string; // "https://video.twimg.com/ext_tw_video/1476257027378888711/pu/vid/640x360/KwFE_5vWD7hAVtu4.mp4?tag=12"
+}
+export interface MediaSize {
+ h: number;
+ w: number;
+ resize: "crop" | "fit";
+}
+export interface APITweetLegacy {
+ conversation_id_str: string; // thread id
+ created_at: string; // "Wed Dec 15 14:02:32 +0000 2021"
+ display_text_range: [number, number]; // [0, 96]
+ entities: TweetEntities;
+ favorite_count: number;
+ favorited: boolean;
+ full_text: string; //
+ id_str: string; // "1471118482095943680"
+ is_quote_status: boolean;
+ lang: string; // "en"
+ possibly_sensitive: boolean;
+ possibly_sensitive_editable: boolean;
+ quote_count: number;
+ reply_count: number;
+ retweet_count: number;
+ retweeted: boolean;
+ source: string; // "<a href=\"https://mobile.twitter.com\" rel=\"nofollow\">Twitter Web App</a>"
+ user_id_str: string; // "368897808"
+ retweeted_status_result?: { result: APITweet };
+ quoted_status_id_str?: string;
+ quoted_status_permalink?: {
+ display: string; //"twitter.com/lijukic/status…"
+ expanded: string; //"https://twitter.com/lijukic/status/1476284640826736640"
+ url: string; //"https://t.co/1yLiM97600"
+ };
+ in_reply_to_screen_name?: string;
+ in_reply_to_status_id_str?: string;
+ in_reply_to_user_id_str?: string;
+ self_thread?: { id_str: string };
+ extended_entities?: ExtendedEntity;
+}
+export interface Tweet {
+ index: string; // number
+ parent: string | null; // number
+ thread: string; // number
+ time: number;
+ author: TweetAuthor;
+ contents: TwatterToken[];
+ text: string;
+ media: TweetMedia[];
+ poll: TwatterPoll | null;
+ rt_by: TweetAuthor | null;
+ rt_time: number | null;
+ language: string;
+ quoting: Tweet | null;
+ replies: number;
+ rts: number;
+ likes: number;
+ quotes: number;
+}
+export type TweetMedia = TweetPic | TweetVideo;
+export interface TweetPic {
+ url: string; //url
+ thumbnail?: string; //url
+}
+export interface TweetVideo {
+ url: string; //url
+ thumbnail: string; //url
+}
+
+export interface TwatterPoll {
+ card_url: string;
+ api: string;
+ last_updated_datetime_utc: Date;
+ end_datetime_utc: Date;
+ counts_are_final: boolean;
+ choice1_label: string;
+ choice1_count: string;
+ choice2_label: string;
+ choice2_count: string;
+ choice3_label?: string;
+ choice3_count?: string;
+ choice4_label?: string;
+ choice4_count?: string;
+}
+
+export interface TweetAuthor {
+ suspended?: boolean;
+ username: string;
+ name: string;
+ id: string; // number
+ created: number; // date
+ bio: string;
+ avatar: string;
+ avatar_big: string;
+ cover_img: string;
+ following: number;
+ followers: number;
+ location: string;
+ url: string;
+ bluecheck: boolean;
+ locked: boolean;
+ withheld_in_countries: string[];
+ post_count: number;
+ media_count: number;
+ listed_count: number;
+ patp: Ship | null;
+}
+export type EntityType =
+ | "user_mentions"
+ | "hashtags"
+ | "urls"
+ | "media"
+ | "symbol";
+export type tokenizerData = [string, taggedContent[]];
+export type taggedContent = [string, TwatterToken];
+export type TwatterToken = TwatterContent | EmojiContent | HashtagContent;
+export type TwatterContent =
+ | { text: string }
+ | { mention: string }
+ | { url: string }
+ | { hashtag: string };
+export interface EmojiContent {
+ emoji: string;
+}
+export interface HashtagContent {
+ hashtag: string;
+}
+export interface TwatterThread {
+ thread: TweetsWithCursor;
+ replyThreads: TweetsWithCursor[];
+ cursor: string;
+}
+export interface TweetsWithCursor {
+ tweets: Tweet[];
+ cursor: string;
+ cursorBottom?: string;
+ type?: string;
+}
+export interface APITweetCore {
+ user: APIUserProfile;
+}
+export interface APIUserProfile {
+ affiliates_highlighted_label?: any;
+ id?: string; // base64
+ rest_id: string; // number
+ legacy: {
+ created_at: string; // "Tue Sep 06 12:23:27 +0000 2011"
+ default_profile: boolean;
+ default_profile_image: boolean;
+ description: string;
+ entities: UserEntities;
+ fast_followers_count: number;
+ favourites_count: number;
+ followers_count: number;
+ friends_count: number;
+ has_custom_timelines: boolean;
+ is_translator: boolean;
+ listed_count: number;
+ location: string;
+ media_count: number;
+ name: string;
+ normal_followers_count: number;
+ pinned_tweet_ids_str: string[]; // ['1471118482095943680']
+ profile_banner_extensions: any; //{mediaColor: {…}}
+ profile_banner_url: string; // "https://pbs.twimg.com/profile_banners/368897808/1398230281"
+ profile_image_extensions: any; // {mediaColor: {…}}
+ profile_image_url_https: string; //"https://pbs.twimg.com/profile_images/1193225494994571264/So4axAeC_normal.jpg"
+ profile_interstitial_type: string; // ""
+ protected: boolean;
+ screen_name: string;
+ statuses_count: number;
+ translator_type: string; // "none"
+ url?: string; // "https://t.co/uaINnItg4d"
+ verified: boolean;
+ withheld_in_countries: string[];
+ };
+}
+
+// return types of our Urbit fetcher
+export type NoCokiRes = { "no-coki": null };
+export type BadRequestRes = { fail: string };
+export type TwatterSearchRes = TwatterSearchResOK | NoCokiRes | BadRequestRes;
+export type TwatterUserRes = TwatterUserResOK | NoCokiRes | BadRequestRes;
+export type TwatterThreadRes = TwatterThreadResOK | NoCokiRes | BadRequestRes;
+export type TwatterUserResOK = {
+ user: {
+ profile: string;
+ feed: string;
+ };
+};
+export type TwatterThreadResOK = TwatterLoggedThreadRes | TwatterLurkThreadRes;
+export type TwatterLurkThreadRes = {
+ "thread-lurk": string;
+};
+export type TwatterLoggedThreadRes = {
+ thread: string;
+};
+export type TwatterSearchResOK = {
+ search: {
+ query: string;
+ data: string;
+ }
+}
+export type TwatterNotification = {
+ type: string;
+ user: string;
+ post?: string;
+ text: string;
+} \ No newline at end of file
diff --git a/front/src/types/ui.ts b/front/src/types/ui.ts
new file mode 100644
index 0000000..d964d84
--- /dev/null
+++ b/front/src/types/ui.ts
@@ -0,0 +1,49 @@
+import {Poast } from "./trill";
+import { Tweet } from "./twatter";
+import { Ship } from "./urbit";
+
+export type Timestamp = number;
+export type UrbitTime = string;
+
+export interface ComposerData {
+ type: "quote" | "reply";
+ post: SPID;
+}
+export type SPID = TrillPID | TwatterPID | RumorsPID;
+
+export interface TrillPID {
+ service: "trill";
+ post: Poast;
+}
+export interface TwatterPID {
+ service: "twatter";
+ post: Tweet;
+}
+export interface RumorsPID {
+ service: "rumors";
+ post: Poast
+}
+export interface Guanxi {
+ trill: Relationship;
+ pals: Relationship;
+}
+export type Relationship = "mutual" | "incoming" | "outgoing" | "none";
+
+// should make a sortug type codebase
+
+export type BucketCreds = {
+ opts: {
+ bucket: string;
+ origin: string; // this is the endpoint
+ region: string;
+ }, creds: {
+ credentials: {
+ accessKey: string;
+ secretKey: string;
+ }
+ }
+}
+
+export type DateStruct = {year: number, month: number, day: number}
+export type ChatQuoteParams = {p: Ship, nest: string, id: string}
+export type ReactGrouping = Array<{react: string, ships: Ship[]}> \ No newline at end of file
diff --git a/front/src/types/urbit.ts b/front/src/types/urbit.ts
new file mode 100644
index 0000000..af9ee06
--- /dev/null
+++ b/front/src/types/urbit.ts
@@ -0,0 +1,8 @@
+export type Ship = string;
+export interface S3Bucket {
+ accessKeyId: string;
+ endpoint: string;
+ secretAccessKey: string;
+ bucket: string;
+ region: string;
+} \ No newline at end of file
diff --git a/front/src/vite-env.d.ts b/front/src/vite-env.d.ts
new file mode 100644
index 0000000..11f02fe
--- /dev/null
+++ b/front/src/vite-env.d.ts
@@ -0,0 +1 @@
+/// <reference types="vite/client" />
diff --git a/front/tsconfig.app.json b/front/tsconfig.app.json
new file mode 100644
index 0000000..873ffa5
--- /dev/null
+++ b/front/tsconfig.app.json
@@ -0,0 +1,30 @@
+{
+ "compilerOptions": {
+ "baseUrl": ".",
+ "paths": { "@/*": ["./src/*"] },
+ "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
+ "target": "ES2022",
+ "useDefineForClassFields": true,
+ "lib": ["ES2022", "DOM", "DOM.Iterable"],
+ "types": ["vite/client"],
+ "module": "ESNext",
+ "skipLibCheck": true,
+
+ /* Bundler mode */
+ "moduleResolution": "bundler",
+ "allowImportingTsExtensions": true,
+ "verbatimModuleSyntax": true,
+ "moduleDetection": "force",
+ "noEmit": true,
+ "jsx": "react-jsx",
+
+ /* Linting */
+ "strict": true,
+ "noUnusedLocals": true,
+ "noUnusedParameters": true,
+ "erasableSyntaxOnly": true,
+ "noFallthroughCasesInSwitch": true,
+ "noUncheckedSideEffectImports": true
+ },
+ "include": ["src"]
+}
diff --git a/front/tsconfig.json b/front/tsconfig.json
new file mode 100644
index 0000000..1ffef60
--- /dev/null
+++ b/front/tsconfig.json
@@ -0,0 +1,7 @@
+{
+ "files": [],
+ "references": [
+ { "path": "./tsconfig.app.json" },
+ { "path": "./tsconfig.node.json" }
+ ]
+}
diff --git a/front/tsconfig.node.json b/front/tsconfig.node.json
new file mode 100644
index 0000000..f85a399
--- /dev/null
+++ b/front/tsconfig.node.json
@@ -0,0 +1,25 @@
+{
+ "compilerOptions": {
+ "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
+ "target": "ES2023",
+ "lib": ["ES2023"],
+ "module": "ESNext",
+ "skipLibCheck": true,
+
+ /* Bundler mode */
+ "moduleResolution": "bundler",
+ "allowImportingTsExtensions": true,
+ "verbatimModuleSyntax": true,
+ "moduleDetection": "force",
+ "noEmit": true,
+
+ /* Linting */
+ "strict": true,
+ "noUnusedLocals": true,
+ "noUnusedParameters": true,
+ "erasableSyntaxOnly": true,
+ "noFallthroughCasesInSwitch": true,
+ "noUncheckedSideEffectImports": true
+ },
+ "include": ["vite.config.ts"]
+}
diff --git a/front/vite.config.ts b/front/vite.config.ts
new file mode 100644
index 0000000..e2b7add
--- /dev/null
+++ b/front/vite.config.ts
@@ -0,0 +1,13 @@
+import { defineConfig } from "vite";
+import react from "@vitejs/plugin-react";
+import { resolve } from "node:path";
+
+// https://vite.dev/config/
+export default defineConfig({
+ plugins: [react()],
+ resolve: {
+ alias: {
+ "@": resolve(__dirname, "./src"),
+ },
+ },
+});
diff --git a/wss-shim b/wss-shim
new file mode 160000
+Subproject 823d410ab3961c035f392563dc02b5cfd9a3d7b