tinyrelaycommit

Commit 3d347aa40d0b

browse files at this commit | history

1diff --git a/THIRD_PARTY_NOTICES b/THIRD_PARTY_NOTICES
2index bb4bc1e..6c98ce4 100644
3--- a/THIRD_PARTY_NOTICES
4+++ b/THIRD_PARTY_NOTICES
5@@ -72,3 +72,30 @@ If the optional local Fixi bundle is vendored, it is sourced from
6 https://fixiproject.org/ and the project states BSD-0 licensing for fixi,
7 moxi, paxi, ssexi, and rexi. Preserve the upstream notice with the vendored
8 files.
9+
10+Seedmark
11+--------
12+The deterministic avatar renderer in internal/seedmark is derived from
13+Seedmark version 1, commit c808a940bc193f97512c02d58da33ecc28ba1f53, from
14+https://012.run/npub1hgd4hmk4kkukjx7yf402adl7msw0ssnmqmt0y6sgz0j8yjjcj9nqh9znde/seedmark.
15+It is distributed under the MIT License:
16+
17+Copyright (c) 2026 Hermes contributors
18+
19+Permission is hereby granted, free of charge, to any person obtaining a copy
20+of this software and associated documentation files (the "Software"), to deal
21+in the Software without restriction, including without limitation the rights
22+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
23+copies of the Software, and to permit persons to whom the Software is
24+furnished to do so, subject to the following conditions:
25+
26+The above copyright notice and this permission notice shall be included in
27+all copies or substantial portions of the Software.
28+
29+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
30+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
31+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
32+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
33+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
34+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
35+SOFTWARE.
36diff --git a/docs/app.md b/docs/app.md
37index f06440f..b2ed4a3 100644
38--- a/docs/app.md
39+++ b/docs/app.md
40@@ -26,11 +26,13 @@ An agent's access request offers **Review access** instead. It opens the propose
41
42 ## Names
43
44-People show by name wherever the relay knows one: room authors and members, mentions, approvals, agent owners, wiki authors and the signed-in line. Names come from the person's profile (kind 0) as held by this relay, so looking up a name does not contact a public indexer. Names are cached in the browser for six hours. Without JavaScript, or before a profile arrives, the short key shows instead, and the key remains available in its label.
45+People show by name wherever the relay knows one: room authors and members, mentions, approvals, agent owners, wiki authors and the signed-in line. Names come from the person's profile (kind 0) as held by this relay, so looking up a name does not contact a public indexer. Names are cached in the browser for six hours. Without JavaScript, or before a profile arrives, the short key shows instead.
46+
47+A profile picture is used when it is a safe, usable URL. Otherwise the relay shows a deterministic Seedmark avatar generated from the public key, including before JavaScript loads. These avatars are decorative and do not verify identity; the public key remains available in the label.
48
49 ## Profile
50
51-**Profile** on the Account page edits the profile (kind 0) other people and apps see for your key: name, display name, about, picture, banner, website, NIP-05 address and lightning address. The form starts from the profile this relay holds, and fields it does not show are kept as they are. Saving signs the event with your connected signer, publishes it to this relay first, then to every relay in **Also publish to**, which starts out as the write relays from your relay list on this relay; each relay reports ok or failed under the form. The browser forgets your cached name at the same time, so pages show the new one on the next load.
52+**Profile** on the Account page edits the profile (kind 0) other people and apps see for your key: name, display name, about, picture, banner, website, NIP-05 address and lightning address. The form starts from the profile this relay holds, and fields it does not show are kept as they are. Saving signs the event with your connected signer, publishes it to this relay first, then to every relay in **Also publish to**, which starts out as the write relays from your relay list on this relay; each relay reports ok or failed under the form. The browser forgets your cached name at the same time, so pages show the new one on the next load. Removing or omitting a picture returns the account to its deterministic Seedmark avatar.
53
54 ## Account
55
56diff --git a/docs/architecture.md b/docs/architecture.md
57index 4a2c852..d0a7eec 100644
58--- a/docs/architecture.md
59+++ b/docs/architecture.md
60@@ -21,6 +21,7 @@ Each tenant has a SQLite store, a policy snapshot and a set of services. The dae
61 | [`relay`](../internal/relay/doc.go), [`mcp`](../internal/mcp/doc.go), [`webui`](../internal/webui/doc.go) | WebSocket sessions, MCP requests, HTML pages and browser interactions. |
62 | [`agentrunner`](../internal/agentrunner) | The optional agent process: room mentions, durable queue recovery, ACP or command execution, and permission prompts. |
63 | [`views`](../internal/views/doc.go), [`wiki`](../internal/wiki/doc.go), [`webpush`](../internal/webpush/doc.go) | Fenced-block parsing, article rendering and encrypted browser push delivery. |
64+| [`seedmark`](../internal/seedmark) | Deterministic decorative SVG avatars for people and rooms without a profile picture. |
65 | [`catalog`](../internal/catalog/doc.go), [`domains`](../internal/domains/doc.go) | Tenant lifecycle records, filesystem paths and host mappings. |
66 | [`templates`](../internal/templates/doc.go), [`configport`](../internal/configport/doc.go) | Built-in policy templates and configuration import, export and application. |
67 | [`telemetry`](../internal/telemetry/doc.go), [`daemon`](../internal/daemon/doc.go) | Observability, service assembly, request routing and worker ownership. |
68diff --git a/docs/rooms.md b/docs/rooms.md
69index 4fd4466..b3e31ec 100644
70--- a/docs/rooms.md
71+++ b/docs/rooms.md
72@@ -63,7 +63,9 @@ Direct conversations show replies, quoted messages and encrypted reactions. Choo
73
74 One-to-one messages require a connected signer with NIP-44 support. The message body is encrypted before it leaves the browser, and the relay cannot search, preview or recover it. Group rooms continue to work for clients and agents that speak NIP-29. Existing room links at `/rooms/<id>` remain valid.
75
76-Open a room to read its messages, oldest first. Each message shows the author's name, their room role and the time. Agent messages identify the operator when the grant names one, using the form `<operator>'s agent`; an agent without an operator is labeled `agent`. Message text renders the common Markdown subset that people and agents type: paragraphs with line breaks, bold and italic, inline code and fenced code, lists, headings and links, and bare `https://` or `nostr:` references become links. Nothing else in a message is treated as markup. Links open in place and `nostr:` links resolve through the relay. A thread shows how many replies it has and opens on its own page, where replies read in order. Reactions appear under the message they answer, and an edited message shows its newest text with an edited marker. Choose **load earlier** for older messages.
77+Open a room to read its messages, oldest first. Each message shows the author's profile picture when available, or a deterministic Seedmark avatar, along with their name, room role and time. Room lists and headers use the room picture when one is set, with a stable generated avatar otherwise. Agent messages identify the operator when the grant names one, using the form `<operator>'s agent`; an agent without an operator is labeled `agent`. Avatars are decorative; use the displayed public key when identity matters.
78+
79+Message text renders the common Markdown subset that people and agents type: paragraphs with line breaks, bold and italic, inline code and fenced code, lists, headings and links, and bare `https://` or `nostr:` references become links. Nothing else in a message is treated as markup. Links open in place and `nostr:` links resolve through the relay. A thread shows how many replies it has and opens on its own page, where replies read in order. Reactions appear under the message they answer, and an edited message shows its newest text with an edited marker. Choose **load earlier** for older messages.
80
81 For broad client compatibility, replies can use a kind 9 message with NIP-10 `e` tags: the root reference has marker `root` in the fourth tag value, and a nested reply can also identify its immediate parent. Kind 12 is accepted for clients that use the NIP-29 thread reply convention. Both forms are grouped into the same thread by the web UI.
82
83diff --git a/internal/seedmark/LICENSE b/internal/seedmark/LICENSE
84new file mode 100644
85index 0000000..d3bc0d2
86--- /dev/null
87+++ b/internal/seedmark/LICENSE
88@@ -0,0 +1,21 @@
89+MIT License
90+
91+Copyright (c) 2026 Hermes contributors
92+
93+Permission is hereby granted, free of charge, to any person obtaining a copy
94+of this software and associated documentation files (the "Software"), to deal
95+in the Software without restriction, including without limitation the rights
96+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
97+copies of the Software, and to permit persons to whom the Software is
98+furnished to do so, subject to the following conditions:
99+
100+The above copyright notice and this permission notice shall be included in all
101+copies or substantial portions of the Software.
102+
103+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
104+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
105+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
106+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
107+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
108+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
109+SOFTWARE.
110diff --git a/internal/seedmark/families_a.go b/internal/seedmark/families_a.go
111new file mode 100644
112index 0000000..93abc6e
113--- /dev/null
114+++ b/internal/seedmark/families_a.go
115@@ -0,0 +1,192 @@
116+package seedmark
117+
118+import "fmt"
119+
120+func masks(r recipe) string {
121+ bg, light, hot, cool := r.Palette[0], r.Palette[1], r.Palette[2], r.Palette[3]
122+ w, h := float64(r.Silhouette.Width), float64(r.Silhouette.Height)
123+ x, y := 32-w/2, 33-h/2
124+ var art string
125+ switch r.Layout.Variant {
126+ case 0:
127+ art = path("M17 23L10 9L28 19M47 23L54 9L36 19", cool)
128+ case 1:
129+ art = rect(20, 8, 24, 16, 4, hot)
130+ case 2:
131+ art = path("M17 23L20 7L32 16L44 7L47 23Z", hot)
132+ case 3:
133+ art = circle(32, 13, 10, cool) + circle(32, 13, 4, bg)
134+ }
135+ switch r.Silhouette.Variant {
136+ case 0:
137+ art += path(fmt.Sprintf("M%s %sQ32 %s %s %sL%s 43L32 56L%s 43Z", num(x), num(y), num(y-6), num(64-x), num(y), num(64-x-2), num(x+2)), light)
138+ case 1:
139+ art += ellipse(32, 33, w/2, h/2, light)
140+ case 2:
141+ art += rect(x, y, w, h, 8, light)
142+ case 3:
143+ art += path(fmt.Sprintf("M32 %sL%s 25L%s 47L32 54L%s 47L%s 25Z", num(y-3), num(64-x), num(64-x-4), num(x+4), num(x)), light)
144+ }
145+ if r.Features.Accent != 0 {
146+ art += path("M32 18L39 25L36 42L32 47Z", hot)
147+ } else {
148+ art += path("M32 18L39 25L36 42L32 47Z", cool)
149+ }
150+ switch r.Features.Variant {
151+ case 0:
152+ art += ellipse(24, 31, 5, 6, bg) + ellipse(40, 31, 5, 6, bg)
153+ case 1:
154+ art += path("M18 28L29 32L19 35ZM35 32L46 28L45 35Z", bg)
155+ case 2:
156+ art += rect(18, 28, 12, 6, 2, bg) + circle(40, 31, 5, bg)
157+ case 3:
158+ art += strokePath("M18 33Q24 23 29 33M35 33Q40 23 46 33", "none", bg, 4)
159+ }
160+ if r.Features.Accent != 0 {
161+ art += rect(26, 43, 12, 4, 2, bg)
162+ } else {
163+ art += path("M27 42L32 48L37 42Z", bg)
164+ }
165+ return art
166+}
167+
168+func creatures(r recipe) string {
169+ bg, light, hot, cool := r.Palette[0], r.Palette[1], r.Palette[2], r.Palette[3]
170+ w := float64(r.Silhouette.Width)
171+ var art string
172+ switch r.Layout.Variant {
173+ case 0:
174+ art = path("M22 27Q4 9 14 9Q24 10 27 26M36 26Q45 4 51 13L43 29", hot)
175+ case 1:
176+ art = path("M19 29L8 20L13 39M43 28L55 19L51 40", cool)
177+ case 2:
178+ art = strokePath("M25 25L23 10M39 25L44 12", "none", light, 5) + circle(23, 10, 5, hot) + circle(44, 12, 5, hot)
179+ case 3:
180+ art = path("M17 25L15 13L28 22L36 11L40 23L50 18L47 30Z", hot)
181+ }
182+ art += strokePath("M22 43L17 52L25 52M40 43L47 52L38 52", "none", cool, 6)
183+ switch r.Silhouette.Variant {
184+ case 0:
185+ art += ellipse(32, 35, w/2, 17, cool)
186+ case 1:
187+ art += path("M15 43Q10 19 32 22Q52 10 50 43Q43 55 32 46Q20 55 15 43Z", cool)
188+ case 2:
189+ art += rect(32-w/2, 22, w, 27, 10, cool)
190+ case 3:
191+ art += path("M12 42L23 20Q32 12 42 26L53 43Q33 58 12 42Z", cool)
192+ }
193+ switch r.Features.Variant {
194+ case 0:
195+ art += circle(32, 33, 10, light) + circle(32+float64(r.Features.Accent)*3, 33, 4, bg)
196+ case 1:
197+ art += ellipse(24, 32, 6, 8, light) + ellipse(40, 32, 6, 8, light) + circle(25, 33, 3, bg) + circle(41, 33, 3, bg)
198+ case 2:
199+ art += rect(19, 27, 26, 11, 5, bg) + circle(25, 32, 3, light) + circle(38, 32, 3, light)
200+ case 3:
201+ for i := 0; i < r.Features.Count; i++ {
202+ px := 20 + float64(i)*24/float64(r.Features.Count-1)
203+ py := 31 + float64(i%2)*4
204+ art += circle(px, py, 4, light) + circle(px, py+1, 2, bg)
205+ }
206+ }
207+ if r.Features.Accent != 0 {
208+ art += strokePath("M28 43Q32 49 37 42", "none", bg, 3)
209+ } else {
210+ art += rect(29, 42, 7, 4, 2, bg)
211+ }
212+ return art
213+}
214+
215+func botanical(r recipe) string {
216+ light, hot, cool := r.Palette[1], r.Palette[2], r.Palette[3]
217+ w := float64(r.Silhouette.Width)
218+ var art string
219+ switch r.Layout.Variant {
220+ case 0:
221+ art = path("M23 43L25 55L40 55L43 43Z", hot)
222+ case 1:
223+ art = ellipse(32, 48, 18, 7, hot)
224+ case 2:
225+ art = path("M20 52L25 44L39 44L46 52Z", light)
226+ case 3:
227+ art = strokePath("M25 54L32 45L39 54M20 50L32 45L45 49", "none", hot, 4)
228+ }
229+ art += strokePath("M32 46Q28 30 33 14", "none", light, 4)
230+ switch r.Silhouette.Variant {
231+ case 0:
232+ art += path(fmt.Sprintf("M31 35Q%s 37 12 21Q29 17 31 35ZM32 29Q35 12 51 13Q52 29 32 29Z", num(32-w/2)), cool)
233+ case 1:
234+ art += path("M31 41Q11 45 12 34Q15 28 30 34M32 28Q48 33 51 23Q51 14 33 20", cool)
235+ case 2:
236+ art += path("M31 39Q8 29 22 13Q35 20 31 39ZM33 37Q55 32 46 19Q32 23 33 37Z", cool)
237+ case 3:
238+ art += path("M30 40L13 29L27 27L15 16L31 23L38 9L40 26L53 19L45 36Z", cool)
239+ }
240+ bloomX, bloomY := 29.0, 16.0
241+ if r.Features.Variant%2 != 0 {
242+ bloomX = 41
243+ }
244+ if r.Features.Variant >= 2 {
245+ bloomY = 24
246+ }
247+ switch r.Features.Variant {
248+ case 0:
249+ art += circle(bloomX-6, bloomY, 7, hot) + circle(bloomX+6, bloomY, 7, hot) + circle(bloomX, bloomY-6, 7, hot) + circle(bloomX, bloomY+5, 7, hot) + circle(bloomX, bloomY, 4, light)
250+ case 1:
251+ art += path("M29 20L30 9L37 14L42 7L47 15L54 11L51 22Q42 32 29 20Z", hot) + circle(42, 21, 4, light)
252+ case 2:
253+ for i := 0; i < r.Features.Count; i++ {
254+ art += circle(19+float64(i)*6, 16+float64(i%2)*6, 4, hot)
255+ }
256+ case 3:
257+ art += ellipse(40, 18, 9, 13, hot) + strokePath("M40 10L40 25", "none", light, 3)
258+ }
259+ return art
260+}
261+
262+func orbital(r recipe) string {
263+ bg, light, hot, cool := r.Palette[0], r.Palette[1], r.Palette[2], r.Palette[3]
264+ w := float64(r.Silhouette.Width)
265+ radius := 11 + (w-26)/3
266+ var art string
267+ switch r.Layout.Variant {
268+ case 0:
269+ art = strokePath("M9 39Q1 18 31 12Q58 6 55 30Q49 53 23 52", "none", cool, 4)
270+ case 1:
271+ art = strokePath("M12 13L49 50M12 50L49 13", "none", cool, 4)
272+ case 2:
273+ art = strokePath("M9 32A23 23 0 1 1 32 55", "none", cool, 5)
274+ case 3:
275+ art = rect(12, 12, 40, 40, 12, cool) + rect(17, 17, 30, 30, 8, bg)
276+ }
277+ switch r.Silhouette.Variant {
278+ case 0:
279+ art += circle(32, 32, radius, hot)
280+ case 1:
281+ art += rect(18, 18, 28, 28, 6, hot)
282+ case 2:
283+ art += path("M32 14L50 32L32 50L14 32Z", hot)
284+ case 3:
285+ art += ellipse(32, 32, radius, 19, hot)
286+ }
287+ switch r.Features.Variant {
288+ case 0:
289+ art += strokePath("M10 37Q32 46 53 25", "none", light, 5)
290+ case 1:
291+ art += circle(29, 29, 7, light) + circle(33, 26, 7, hot)
292+ case 2:
293+ art += strokePath("M21 25L43 25M21 34L43 34M27 42L37 42", "none", light, 4)
294+ case 3:
295+ art += circle(32, 32, 7, bg) + circle(32, 32, 3, light)
296+ }
297+ for i := 0; i < r.Features.Count; i++ {
298+ px := []float64{13, 49, 16, 46, 32}[i]
299+ py := []float64{16, 46, 47, 13, 7}[i]
300+ pr := 4.0
301+ if i%2 != 0 {
302+ pr = 3
303+ }
304+ art += circle(px, py, pr, light)
305+ }
306+ return art
307+}
308diff --git a/internal/seedmark/families_b.go b/internal/seedmark/families_b.go
309new file mode 100644
310index 0000000..5f61e3d
311--- /dev/null
312+++ b/internal/seedmark/families_b.go
313@@ -0,0 +1,162 @@
314+package seedmark
315+
316+import "fmt"
317+
318+func landscapes(r recipe) string {
319+ bg, light, hot, cool := r.Palette[0], r.Palette[1], r.Palette[2], r.Palette[3]
320+ s, h := r.Silhouette.Variant, r.Silhouette.Height
321+ f, accent := r.Features.Variant, r.Features.Accent
322+ horizon := 31 + (float64(h)-28)/2
323+ art := []string{
324+ circle(22, 19, 9, hot),
325+ circle(43, 19, 10, hot),
326+ rect(14, 12, 34, 9, 4, hot),
327+ circle(32, 21, 15, hot),
328+ }[r.Layout.Variant]
329+ art += []string{
330+ path("M7 46L21 22L33 37L43 26L57 46V55H7Z", cool),
331+ path(fmt.Sprintf("M7 %sQ18 21 31 %sQ46 22 57 35V55H7Z", num(horizon), num(horizon)), cool),
332+ path("M8 53V25H20V38H30V19H40V32H55V53Z", cool),
333+ path("M7 36L18 28L26 32L39 23L57 33V55H7Z", cool),
334+ }[s]
335+ if f == 0 {
336+ art += path("M31 35L24 45L36 45L28 55H42L45 43L33 43L37 35Z", light)
337+ }
338+ if f == 1 {
339+ art += strokePath("M9 45Q21 40 32 46T55 46M13 53Q23 48 35 53", "none", light, 4)
340+ }
341+ if f == 2 {
342+ art += strokePath("M18 48V35M12 42L18 32L24 42ZM42 50V38M36 43L42 33L48 43Z", light, light, 2)
343+ }
344+ if f == 3 {
345+ art += rect(26, 36, 15, 17, 2, light) + path("M23 36L33 27L44 36Z", light) + rect(31, 43, 5, 10, 0, bg)
346+ }
347+ if accent != 0 {
348+ art += strokePath("M9 18Q13 13 17 18Q21 13 25 18", "none", light, 2)
349+ } else {
350+ art += circle(51, 12, 3, light)
351+ }
352+ return art
353+}
354+
355+func glyphs(r recipe) string {
356+ bg, light, hot, cool := r.Palette[0], r.Palette[1], r.Palette[2], r.Palette[3]
357+ w := float64(r.Silhouette.Width)
358+ f, accent := r.Features.Variant, r.Features.Accent
359+ art := []string{
360+ circle(32, 32, 24, cool) + circle(32, 32, 18, bg),
361+ rect(10, 10, 44, 44, 10, cool) + rect(16, 16, 32, 32, 5, bg),
362+ strokePath("M10 26L26 10M38 10L54 26M54 38L38 54M26 54L10 38", "none", cool, 6),
363+ strokePath("M10 47V17H24M54 17V47H40", "none", cool, 6),
364+ }[r.Layout.Variant]
365+ a, b := 32-w/2+4, 64-(32-w/2+4)
366+ art += []string{
367+ strokePath(fmt.Sprintf("M%s 43L32 17L%s 43M24 35H40", num(a), num(b)), "none", light, 7),
368+ strokePath(fmt.Sprintf("M%s 22H%sL%s 43H%s", num(a), num(b), num(a), num(b)), "none", light, 7),
369+ strokePath(fmt.Sprintf("M%s 19V44H%sV19M32 20V39", num(a), num(b)), "none", light, 7),
370+ path("M21 18H37Q49 24 37 32Q50 40 38 46H21Z", light) + rect(27, 24, 9, 5, 2, bg) + rect(27, 36, 10, 5, 2, bg),
371+ }[r.Silhouette.Variant]
372+ art += []string{
373+ circle(32, 32, 5, hot),
374+ path("M32 24L40 32L32 40L24 32Z", hot),
375+ rect(26, 27, 12, 10, 2, hot),
376+ strokePath("M22 37L42 27", "none", hot, 6),
377+ }[f]
378+ if accent != 0 {
379+ art += circle(49, 15, 4, light)
380+ } else {
381+ art += circle(15, 49, 4, light)
382+ }
383+ return art
384+}
385+
386+func woven(r recipe) string {
387+ bg, light, hot, cool := r.Palette[0], r.Palette[1], r.Palette[2], r.Palette[3]
388+ s, w := r.Silhouette.Variant, float64(r.Silhouette.Width)
389+ f, count := r.Features.Variant, r.Features.Count
390+ gap := 10 + (w-26)/6
391+ art := ""
392+ if s == 0 {
393+ for i := 0; i < 3; i++ {
394+ fill := light
395+ if i%2 != 0 {
396+ fill = hot
397+ }
398+ art += rect(13+float64(i)*gap, 10, 7, 44, 3, fill)
399+ }
400+ for i := 0; i < 3; i++ {
401+ art += rect(9, 16+float64(i)*gap, 45, 6, 2, cool)
402+ }
403+ art += rect(24, 23, 7, 15, 2, hot)
404+ }
405+ if s == 1 {
406+ for i := 0; i < 3; i++ {
407+ colors := []string{light, hot, cool}
408+ x := 12 + i*12
409+ art += strokePath(fmt.Sprintf("M%d 12L%d 25L%d 39L%d 52", x, x+8, x, x+8), "none", colors[i], 8)
410+ }
411+ }
412+ if s == 2 {
413+ art += strokePath("M12 20Q12 11 22 11H43Q52 11 52 21V43Q52 53 42 53H22Q12 53 12 43Z", "none", light, 6)
414+ art += strokePath("M21 10V44H43V20H10M54 32H32V54", "none", hot, 7)
415+ art += rect(28, 22, 8, 8, 1, cool)
416+ }
417+ if s == 3 {
418+ for i := 0; i < 3; i++ {
419+ colors := []string{light, hot, cool}
420+ y := 18 + i*13
421+ art += path(fmt.Sprintf("M10 %dL22 %dL34 %dL46 %dL54 %dL46 %dL34 %dL22 %dZ", y, 10+i*13, y, 10+i*13, y, 26+i*13, y, 26+i*13), colors[i])
422+ }
423+ }
424+ art = group(art, fmt.Sprintf("rotate(%d 32 32) scale(.88) translate(4.36 4.36)", r.Layout.Variant*45))
425+ art += []string{
426+ circle(32, 32, 5, bg) + circle(32, 32, 2, light),
427+ rect(26, 26, 12, 12, 3, hot),
428+ path("M32 24L40 32L32 40L24 32Z", cool),
429+ strokePath("M27 28L37 36M37 28L27 36", "none", bg, 4),
430+ }[f]
431+ for i := 0; i < count; i++ {
432+ art += circle(18+float64(i)*7, 56, 2, hot)
433+ }
434+ return art
435+}
436+
437+func machines(r recipe) string {
438+ bg, light, hot, cool := r.Palette[0], r.Palette[1], r.Palette[2], r.Palette[3]
439+ s, w := r.Silhouette.Variant, float64(r.Silhouette.Width)
440+ f, count, accent := r.Features.Variant, r.Features.Count, r.Features.Accent
441+ x := 32 - w/2
442+ art := []string{
443+ strokePath("M22 23L17 11M42 23L49 11", "none", hot, 4) + circle(17, 11, 4, light),
444+ rect(23, 9, 18, 16, 4, hot) + rect(28, 12, 8, 6, 1, bg),
445+ strokePath("M12 27L8 39L19 44M51 27L56 39L47 44", "none", hot, 6),
446+ circle(22, 49, 8, hot) + circle(43, 49, 8, hot),
447+ }[r.Layout.Variant]
448+ art += []string{
449+ rect(x, 20, w, 30, 5, light),
450+ path(fmt.Sprintf("M%s 19H%sL%s 45L41 52H23L%s 45Z", num(x+5), num(59-x), num(64-x), num(x)), light),
451+ ellipse(32, 35, w/2, 18, light),
452+ path("M23 17H41L52 29V44L41 52H23L12 44V29Z", light),
453+ }[s]
454+ if f == 0 {
455+ art += circle(32, 34, 11, bg) + circle(32, 34, 7, cool) + circle(35, 31, 3, light)
456+ }
457+ if f == 1 {
458+ art += rect(20, 26, 24, 17, 3, bg) + strokePath("M24 37L29 30L34 36L40 29", "none", cool, 3)
459+ }
460+ if f == 2 {
461+ art += rect(19, 25, 26, 15, 2, bg)
462+ for i := 0; i < count; i++ {
463+ art += rect(22+float64(i)*4, 28, 2, 9, 1, cool)
464+ }
465+ }
466+ if f == 3 {
467+ art += circle(25, 32, 6, bg) + circle(39, 32, 6, bg) + strokePath("M20 44H44", "none", hot, 4)
468+ }
469+ if accent != 0 {
470+ art += circle(43, 46, 3, hot)
471+ } else {
472+ art += circle(21, 46, 3, hot)
473+ }
474+ return art
475+}
476diff --git a/internal/seedmark/primitives.go b/internal/seedmark/primitives.go
477new file mode 100644
478index 0000000..701bca3
479--- /dev/null
480+++ b/internal/seedmark/primitives.go
481@@ -0,0 +1,27 @@
482+package seedmark
483+
484+import "strconv"
485+
486+func num(value float64) string { return strconv.FormatFloat(value, 'f', -1, 64) }
487+
488+func circle(x, y, radius float64, fill string) string {
489+ return `<circle cx="` + num(x) + `" cy="` + num(y) + `" r="` + num(radius) + `" fill="` + fill + `"/>`
490+}
491+
492+func ellipse(x, y, rx, ry float64, fill string) string {
493+ return `<ellipse cx="` + num(x) + `" cy="` + num(y) + `" rx="` + num(rx) + `" ry="` + num(ry) + `" fill="` + fill + `"/>`
494+}
495+
496+func rect(x, y, width, height, rx float64, fill string) string {
497+ return `<rect x="` + num(x) + `" y="` + num(y) + `" width="` + num(width) + `" height="` + num(height) + `" rx="` + num(rx) + `" fill="` + fill + `"/>`
498+}
499+
500+func path(d, fill string) string { return strokePath(d, fill, "none", 0) }
501+
502+func strokePath(d, fill, stroke string, width float64) string {
503+ return `<path d="` + d + `" fill="` + fill + `" stroke="` + stroke + `" stroke-width="` + num(width) + `" stroke-linecap="round" stroke-linejoin="round"/>`
504+}
505+
506+func group(body, transform string) string {
507+ return `<g transform="` + transform + `">` + body + `</g>`
508+}
509diff --git a/internal/seedmark/seedmark.go b/internal/seedmark/seedmark.go
510new file mode 100644
511index 0000000..e9738f0
512--- /dev/null
513+++ b/internal/seedmark/seedmark.go
514@@ -0,0 +1,109 @@
515+// Package seedmark renders version 1 of the Seedmark avatar design without
516+// JavaScript. It follows the upstream generator at c808a94; fixtures pin its
517+// visual output. Avatars are decorative and are not identity verification.
518+package seedmark
519+
520+import (
521+ "strconv"
522+ "strings"
523+ "unicode/utf16"
524+)
525+
526+const Version = 1
527+
528+var families = [...]string{"masks", "creatures", "botanical", "orbital", "landscapes", "glyphs", "woven", "machines"}
529+
530+var palettes = [...][4]string{
531+ {"#142d36", "#f5dfad", "#ed7351", "#65c4ae"},
532+ {"#24223c", "#f7dfbf", "#a89cfc", "#f7788b"},
533+ {"#163b32", "#f4eacb", "#b4cf66", "#f69c64"},
534+ {"#3a2330", "#ffe5b9", "#ef7689", "#8dceba"},
535+ {"#1d304c", "#e8eff0", "#f4b855", "#72b9d0"},
536+ {"#422d26", "#f8e8c8", "#e8a04d", "#72afa0"},
537+ {"#283526", "#f4edcf", "#d3c65e", "#ed8863"},
538+ {"#292745", "#efe8f5", "#d89ada", "#8fcabc"},
539+ {"#18343c", "#f8e4d0", "#f88c66", "#a7cee0"},
540+ {"#393127", "#f4ebd8", "#adb77a", "#da8c6f"},
541+ {"#2c2440", "#fbe8c2", "#f2b54f", "#b2a1e2"},
542+ {"#1b3537", "#e9f0d7", "#79c7b8", "#e5a4aa"},
543+}
544+
545+type recipe struct {
546+ Family string
547+ Palette [4]string
548+ Layout struct{ Variant, Flip, Tilt int }
549+ Silhouette struct{ Variant, Width, Height int }
550+ Features struct{ Variant, Count, Accent int }
551+ Texture struct{ Variant, Marks int }
552+}
553+
554+type rng struct{ a, b, c, d uint32 }
555+
556+func newRNG(seed, namespace string) *rng {
557+ var framed strings.Builder
558+ for _, part := range []string{"seedmark", "1", seed, namespace} {
559+ framed.WriteString(strconv.Itoa(len(utf16.Encode([]rune(part)))))
560+ framed.WriteByte(':')
561+ framed.WriteString(part)
562+ }
563+ a, b, c, d := uint32(1779033703), uint32(3144134277), uint32(1013904242), uint32(2773480762)
564+ for _, unit := range utf16.Encode([]rune(framed.String())) {
565+ k := uint32(unit)
566+ a = b ^ (a^k)*597399067
567+ b = c ^ (b^k)*2869860233
568+ c = d ^ (c^k)*951274213
569+ d = a ^ (d^k)*2716044179
570+ }
571+ a = (c ^ (a >> 18)) * 597399067
572+ b = (d ^ (b >> 22)) * 2869860233
573+ c = (a ^ (c >> 17)) * 951274213
574+ d = (b ^ (d >> 19)) * 2716044179
575+ return &rng{a ^ b ^ c ^ d, b ^ a, c ^ a, d ^ a}
576+}
577+
578+func (r *rng) integer(minimum, maximum int) int {
579+ t := r.a + r.b + r.d
580+ r.d++
581+ r.a = r.b ^ (r.b >> 9)
582+ r.b = r.c + (r.c << 3)
583+ r.c = ((r.c << 21) | (r.c >> 11)) + t
584+ return minimum + int(float64(t)/4294967296*float64(maximum-minimum+1))
585+}
586+
587+func recipeFor(seed string) recipe {
588+ var r recipe
589+ r.Family = families[newRNG(seed, "family").integer(0, len(families)-1)]
590+ r.Palette = palettes[newRNG(seed, "palette").integer(0, len(palettes)-1)]
591+ layout, silhouette := newRNG(seed, "layout"), newRNG(seed, "silhouette")
592+ features, texture := newRNG(seed, "features"), newRNG(seed, "texture")
593+ r.Layout.Variant, r.Layout.Flip = layout.integer(0, 3), layout.integer(0, 1)
594+ r.Layout.Tilt = [...]int{-12, 0, 12}[layout.integer(0, 2)]
595+ r.Silhouette.Variant = silhouette.integer(0, 3)
596+ r.Silhouette.Width, r.Silhouette.Height = silhouette.integer(26, 38), silhouette.integer(28, 42)
597+ r.Features.Variant, r.Features.Count = features.integer(0, 3), features.integer(2, 5)
598+ r.Features.Accent = features.integer(0, 1)
599+ r.Texture.Variant, r.Texture.Marks = texture.integer(0, 2), texture.integer(2, 4)
600+ return r
601+}
602+
603+// Avatar returns a standalone 64-pixel SVG for the full seed. The version 1
604+// geometry remains fixed; CSS may resize the SVG without changing its design.
605+func Avatar(seed string) string {
606+ r := recipeFor(seed)
607+ render := map[string]func(recipe) string{"masks": masks, "creatures": creatures, "botanical": botanical, "orbital": orbital, "landscapes": landscapes, "glyphs": glyphs, "woven": woven, "machines": machines}
608+ texture := ""
609+ for i := 0; i < r.Texture.Marks; i++ {
610+ x := float64(8 + i*6)
611+ if r.Texture.Variant == 1 {
612+ texture += circle(x, 6, 1.5, r.Palette[3])
613+ } else if r.Texture.Variant == 2 {
614+ texture += rect(x-1, 5, 3, 3, 0, r.Palette[2])
615+ }
616+ }
617+ flip := "1"
618+ if r.Layout.Flip != 0 {
619+ flip = "-1"
620+ }
621+ transform := "translate(32 32) rotate(" + strconv.Itoa(r.Layout.Tilt) + ") scale(" + flip + " 1) translate(-32 -32)"
622+ return `<svg xmlns="http://www.w3.org/2000/svg" width="64" height="64" viewBox="0 0 64 64"><rect width="64" height="64" fill="` + r.Palette[0] + `"/>` + texture + group(render[r.Family](r), transform) + `</svg>`
623+}
624diff --git a/internal/seedmark/seedmark_test.go b/internal/seedmark/seedmark_test.go
625new file mode 100644
626index 0000000..f9f365d
627--- /dev/null
628+++ b/internal/seedmark/seedmark_test.go
629@@ -0,0 +1,48 @@
630+package seedmark
631+
632+import (
633+ "crypto/sha256"
634+ "encoding/json"
635+ "fmt"
636+ "os"
637+ "strings"
638+ "testing"
639+)
640+
641+// TestVersionOneMatchesUpstreamSVG pins the v1 output from Seedmark commit
642+// c808a940bc193f97512c02d58da33ecc28ba1f53. Seedmark is MIT licensed; its
643+// Go port and upstream license are in this package. The fixture generator is
644+// scripts/qa/generate-seedmark-fixture.mjs.
645+func TestVersionOneMatchesUpstreamSVG(t *testing.T) {
646+ raw, err := os.ReadFile("testdata/v1.json")
647+ if err != nil {
648+ t.Fatal(err)
649+ }
650+ var fixtures []struct{ Seed, Family, SHA256 string }
651+ if err := json.Unmarshal(raw, &fixtures); err != nil {
652+ t.Fatal(err)
653+ }
654+ families := map[string]bool{}
655+ if len(fixtures) != 1010 {
656+ t.Fatalf("fixtures contain %d cases, want 1010", len(fixtures))
657+ }
658+ for _, fixture := range fixtures {
659+ families[fixture.Family] = true
660+ digest := fmt.Sprintf("%x", sha256.Sum256([]byte(Avatar(fixture.Seed))))
661+ if digest != fixture.SHA256 {
662+ t.Fatalf("seed %q (%s): got SHA256 %s, want %s", fixture.Seed, fixture.Family, digest, fixture.SHA256)
663+ }
664+ }
665+ if len(families) != 8 {
666+ t.Fatalf("fixtures cover %d families", len(families))
667+ }
668+}
669+
670+func TestSeedNeverAppearsInMarkup(t *testing.T) {
671+ for _, seed := range []string{`<script>alert(1)</script>`, `" onload="alert(1)`, "https://example.test/identity"} {
672+ svg := Avatar(seed)
673+ if strings.Contains(svg, seed) || strings.Contains(svg, "<script") || strings.Contains(svg, "onload") || strings.Contains(svg, "href=") || strings.Contains(svg, "class=") {
674+ t.Fatalf("seed affected SVG markup: %s", svg)
675+ }
676+ }
677+}
678diff --git a/internal/seedmark/testdata/v1.json b/internal/seedmark/testdata/v1.json
679new file mode 100644
680index 0000000..51b3cde
681--- /dev/null
682+++ b/internal/seedmark/testdata/v1.json
683@@ -0,0 +1,5052 @@
684+[
685+ {
686+ "seed": "",
687+ "family": "glyphs",
688+ "sha256": "94aebee8d0dcbba49bc2e7080ed318f0aa5a466060e8bb5633e2f75ad867472d"
689+ },
690+ {
691+ "seed": "seedmark",
692+ "family": "masks",
693+ "sha256": "2e47dfd552f5be1d5b9466bb74d4e60b3aff6b8a98488057cedab2160d6641dc"
694+ },
695+ {
696+ "seed": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
697+ "family": "creatures",
698+ "sha256": "1e65a63635fb7dbcae3f5da68871dda36b99f4cd97d4e5208be6ba485df546c4"
699+ },
700+ {
701+ "seed": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
702+ "family": "glyphs",
703+ "sha256": "b5a726748884f0070411d805a94cbb84e9851b7d659c6a4d4b288edbef61c817"
704+ },
705+ {
706+ "seed": "0000000000000000000000000000000000000000000000000000000000000000",
707+ "family": "botanical",
708+ "sha256": "67adf0a470c3a4817f6c2fd45ef9a7da6459a3ab79fa8b2f90dc7ce1a89ab396"
709+ },
710+ {
711+ "seed": "seed/\u0000part",
712+ "family": "botanical",
713+ "sha256": "5c46a3bbd0a84363cec9f3d3039569f598af9005b6262694a0b85c35f97a2d11"
714+ },
715+ {
716+ "seed": "é",
717+ "family": "glyphs",
718+ "sha256": "8e432527cfa52a02c1097a9d41df7fcd915869f404569af4dbd8eddf3f25a832"
719+ },
720+ {
721+ "seed": "é",
722+ "family": "botanical",
723+ "sha256": "7daa100363c25f8c46be83289cb6d49f4ac6c04077fba448c01d47c8bad4fb1a"
724+ },
725+ {
726+ "seed": "猫🌱",
727+ "family": "creatures",
728+ "sha256": "dba4d0a680ef2c452e79e8573b0dfcd38fe7c44caad47f43380f203dec81329d"
729+ },
730+ {
731+ "seed": "👩‍💻",
732+ "family": "glyphs",
733+ "sha256": "0e2ab3646ecc7bb0a17f7a7f87713c43c6cfa9b3421825419a79ede038f6abd0"
734+ },
735+ {
736+ "seed": "sample/0",
737+ "family": "machines",
738+ "sha256": "f45c9670784bd677175fbfa4e0a80a480e9f28736559188a7d7b64d6c1392206"
739+ },
740+ {
741+ "seed": "sample/1",
742+ "family": "woven",
743+ "sha256": "4bcaac3b7f45c439c9bf976906d65cfe92a7634a076399e9466b756139d13252"
744+ },
745+ {
746+ "seed": "sample/2",
747+ "family": "masks",
748+ "sha256": "f2a00bbc4b5b12e0206cc85183684f1017f8d9f438df7afd345ac104524fd232"
749+ },
750+ {
751+ "seed": "sample/3",
752+ "family": "botanical",
753+ "sha256": "9a23bf4f25a1e89d310e1d57f08c48d6e9959b507ff297746463a0463ad28b71"
754+ },
755+ {
756+ "seed": "sample/4",
757+ "family": "machines",
758+ "sha256": "178cf45d3ec5f785d55a7d999436a4450d738d1a95e58c49d85732317e4d22e7"
759+ },
760+ {
761+ "seed": "sample/5",
762+ "family": "woven",
763+ "sha256": "360f04b086fbc37e82951704e0c6601a361055d42baa22c9e5d203d60a23a5c1"
764+ },
765+ {
766+ "seed": "sample/6",
767+ "family": "landscapes",
768+ "sha256": "6bf1f3bd679a72b3a7d95f84e38580cf32bf55228a6813bf065a8588047f9d86"
769+ },
770+ {
771+ "seed": "sample/7",
772+ "family": "glyphs",
773+ "sha256": "3146f760179e5821f9bb69d71041335cfb7ca0990d43eee65978e13f2822b63e"
774+ },
775+ {
776+ "seed": "sample/8",
777+ "family": "masks",
778+ "sha256": "84efc391dfaa92d9015c7c9cf17db02725d2944f20f855bea8670e2e3d65fe59"
779+ },
780+ {
781+ "seed": "sample/9",
782+ "family": "woven",
783+ "sha256": "412878395eb00ab8b047467bcb624d65590d2bdfe5c3af9b37a808d5d518ae0c"
784+ },
785+ {
786+ "seed": "sample/10",
787+ "family": "masks",
788+ "sha256": "7988f79494f1ce59cd3dd3cb3c7a2e2b8e52fceaeaab550928530f4ca571da77"
789+ },
790+ {
791+ "seed": "sample/11",
792+ "family": "masks",
793+ "sha256": "6d7b72f3cc3407f64d0f5b26da94afaa549863667c90e10aa62bcf704e97b7fe"
794+ },
795+ {
796+ "seed": "sample/12",
797+ "family": "orbital",
798+ "sha256": "26cb8e37ee4d87b5d0e531bea538d6af92ca1c04f1248f341570a0ee663e16d1"
799+ },
800+ {
801+ "seed": "sample/13",
802+ "family": "masks",
803+ "sha256": "f958eed9b4afd6bc7c2ce2310ca8147f470f5663fdb6da4c8b26edf29f14ed55"
804+ },
805+ {
806+ "seed": "sample/14",
807+ "family": "creatures",
808+ "sha256": "d360f8e0da1c067e0951be886404a1a01d16e1fb41cc32b3ef54996abcd526c2"
809+ },
810+ {
811+ "seed": "sample/15",
812+ "family": "woven",
813+ "sha256": "e8246a598c4b8c57d91c88f2849a2c760dedc56bde7edcedc3e58c2022aeb832"
814+ },
815+ {
816+ "seed": "sample/16",
817+ "family": "woven",
818+ "sha256": "eb5167c97d4df58034d90e062a654eb57894d38a71c1e228b07f11430788e421"
819+ },
820+ {
821+ "seed": "sample/17",
822+ "family": "woven",
823+ "sha256": "3143ca5c5ba75173e144f292a5231bc726c9f7c4c4e93a17afd7eeb85266d5de"
824+ },
825+ {
826+ "seed": "sample/18",
827+ "family": "creatures",
828+ "sha256": "f05cc848a3977eb7d0b81e3447d696af93c5da084096db34d7c406d57525c41e"
829+ },
830+ {
831+ "seed": "sample/19",
832+ "family": "orbital",
833+ "sha256": "fa8707bddd1aa1c4d88076f42abc1a6f29329d65469fdd323d1ec5ad68fe28b0"
834+ },
835+ {
836+ "seed": "sample/20",
837+ "family": "landscapes",
838+ "sha256": "636a7d87293a2b8228da2edb8511a8dcc695cd0ee4e58973d9827adbbd7cccce"
839+ },
840+ {
841+ "seed": "sample/21",
842+ "family": "glyphs",
843+ "sha256": "3074353911ac60434236c3ad8fec65435e08d4690790ef5d58751fb559341182"
844+ },
845+ {
846+ "seed": "sample/22",
847+ "family": "glyphs",
848+ "sha256": "7b15b57e41039ff14ef919910be9f1e347e3cccd855d5a2b76759bdbebddc588"
849+ },
850+ {
851+ "seed": "sample/23",
852+ "family": "masks",
853+ "sha256": "82eec3e1a1ed3be6e6119c4de90740cee19f63d09f77e2be7e5494b2345e9a98"
854+ },
855+ {
856+ "seed": "sample/24",
857+ "family": "machines",
858+ "sha256": "362daae2ef3c9cc8670471b2db1357191265463de277268d28d3c30380584c10"
859+ },
860+ {
861+ "seed": "sample/25",
862+ "family": "machines",
863+ "sha256": "83defb7de5d732c653be310772eeb845009272571e6cbcb56af2da4765919d55"
864+ },
865+ {
866+ "seed": "sample/26",
867+ "family": "machines",
868+ "sha256": "2a069db22e5d2b251d9d2ce314ec8a7a61676e6b9965dc484e0c5f66f4eb39b4"
869+ },
870+ {
871+ "seed": "sample/27",
872+ "family": "landscapes",
873+ "sha256": "f8e7d3ccbea0af09a7ecd21546bb3ee48bddc8d706cca4f5149c6a3e22dc1b8e"
874+ },
875+ {
876+ "seed": "sample/28",
877+ "family": "creatures",
878+ "sha256": "307737a1ae8442937b0dab11dc9bf56791b7e041bd80502246fd0dc3f14d4997"
879+ },
880+ {
881+ "seed": "sample/29",
882+ "family": "glyphs",
883+ "sha256": "74666daeade8084678a0dc4dc6507674742f453d62f26bbc2a3313816cab1196"
884+ },
885+ {
886+ "seed": "sample/30",
887+ "family": "masks",
888+ "sha256": "fdc480c964363d6d1fd7eb9e291298ce8038395bbe3c31852f2db5c7e676c7be"
889+ },
890+ {
891+ "seed": "sample/31",
892+ "family": "machines",
893+ "sha256": "ad82b661abd8c647aca50b88c73d778b989edf12778e1e431e8ac45fec0a769f"
894+ },
895+ {
896+ "seed": "sample/32",
897+ "family": "machines",
898+ "sha256": "aa581e70d554daa7bcdcd51ed4e1d32df4b8cce57c7b47c966e0899c2277e102"
899+ },
900+ {
901+ "seed": "sample/33",
902+ "family": "creatures",
903+ "sha256": "d771e226024b91b51d4893d613aaae5e1bb74b5e3e800f841e9b9b07ea8f4593"
904+ },
905+ {
906+ "seed": "sample/34",
907+ "family": "glyphs",
908+ "sha256": "98c57633fc33d3dac78429ef2c9250ef02f72a0de4027fc4189c306d8ba0d0a7"
909+ },
910+ {
911+ "seed": "sample/35",
912+ "family": "woven",
913+ "sha256": "8aa1a668deafdbe00059406af4cb6b3f9331bd89019c3bbba6dd298d45c60c36"
914+ },
915+ {
916+ "seed": "sample/36",
917+ "family": "machines",
918+ "sha256": "10fec47d317af2702cc91152a9a6b1df61d8ff096e1bbafb5a8565a2821eaf12"
919+ },
920+ {
921+ "seed": "sample/37",
922+ "family": "landscapes",
923+ "sha256": "8f72464e9ea8d001a712144ae1a22549da0f5e24c9de4397e8e36224fe658856"
924+ },
925+ {
926+ "seed": "sample/38",
927+ "family": "machines",
928+ "sha256": "3bc47742b159bfffff7158206350e162c3d074ebce8bbab67c686cf19fed58eb"
929+ },
930+ {
931+ "seed": "sample/39",
932+ "family": "orbital",
933+ "sha256": "6161b7dcbe8dd3f79cfaf0c25a6a219fc45878cb3a0b325d5cb92315f68807c3"
934+ },
935+ {
936+ "seed": "sample/40",
937+ "family": "woven",
938+ "sha256": "e075e859ef9e121fdfb46f3a10f58654f394efbc93451e95ac6821292d1f8752"
939+ },
940+ {
941+ "seed": "sample/41",
942+ "family": "glyphs",
943+ "sha256": "a92f1b16c9a7d234fa72aa102cb19b805abf20daf289774d26c01f23194bfcc7"
944+ },
945+ {
946+ "seed": "sample/42",
947+ "family": "orbital",
948+ "sha256": "d4d58e3623b8c4adca5dfb4fd51ba450374e3ef2f930e865522672ecf2d3e3b7"
949+ },
950+ {
951+ "seed": "sample/43",
952+ "family": "botanical",
953+ "sha256": "cd729ff66613f2bd244dba6215a32da6e4d5b9452c777673c8cad41be294b5e1"
954+ },
955+ {
956+ "seed": "sample/44",
957+ "family": "creatures",
958+ "sha256": "820b1621176c59928934a74241df5fec7cb285a40832ca10912429611236fafb"
959+ },
960+ {
961+ "seed": "sample/45",
962+ "family": "botanical",
963+ "sha256": "bce2002b9b7a3d84197f7d54243b9ebd0ccab57520342bd0ef9bbb9530ac2c4a"
964+ },
965+ {
966+ "seed": "sample/46",
967+ "family": "botanical",
968+ "sha256": "6fe94a4f9f04397da60dd0c3aa38d1d56a4439c412cef6668c3996919c9b8541"
969+ },
970+ {
971+ "seed": "sample/47",
972+ "family": "woven",
973+ "sha256": "aca9309f3a6ba94ceb1860490ea06aefdd09d9ccd6e11d19ec7fb0d81d66e405"
974+ },
975+ {
976+ "seed": "sample/48",
977+ "family": "woven",
978+ "sha256": "c4ab9752c7bc24277fee2713610c575d88a71f2d16fb1872205127e8f70d51e7"
979+ },
980+ {
981+ "seed": "sample/49",
982+ "family": "woven",
983+ "sha256": "e3b2ff606b28ae9393ffcca076409e560dcf916aca3c4ae9d876d94f3ab0c010"
984+ },
985+ {
986+ "seed": "sample/50",
987+ "family": "machines",
988+ "sha256": "daeb562eb026bb7ee3760343f662630f3a754b14b8521622864359570617e100"
989+ },
990+ {
991+ "seed": "sample/51",
992+ "family": "orbital",
993+ "sha256": "d54b5cd80ef4204a3578f8e0ca30d4cb483662bb5a09523687c1d1fc1aa6a1a5"
994+ },
995+ {
996+ "seed": "sample/52",
997+ "family": "woven",
998+ "sha256": "866273f06b447d06437cba2184e4a77dbfbdffb067786476aed880aa2d9a9aa3"
999+ },
1000+ {
1001+ "seed": "sample/53",
1002+ "family": "creatures",
1003+ "sha256": "f3513d1b6b498584e82afdb06b5ee2b59f3a680ac0abcaae4fac8698ddeb430e"
1004+ },
1005+ {
1006+ "seed": "sample/54",
1007+ "family": "landscapes",
1008+ "sha256": "8dbad3d1ee71b73f9425506a5f2c9e44ce8c6acf7c2faf02bee582b0ed0f0cdc"
1009+ },
1010+ {
1011+ "seed": "sample/55",
1012+ "family": "machines",
1013+ "sha256": "6d799c96fe62f5211183ff3e4c6c817d28bb30a93d891c28dbfabeba84351fad"
1014+ },
1015+ {
1016+ "seed": "sample/56",
1017+ "family": "botanical",
1018+ "sha256": "e71ccebceb086d080e41223c4e7a035260430d2219e2a630c34875b6f10ddb0c"
1019+ },
1020+ {
1021+ "seed": "sample/57",
1022+ "family": "botanical",
1023+ "sha256": "7a829c4e8ac939f60526e2457f9f52120ef6e4b2e96ebb1666f801cd543e56d6"
1024+ },
1025+ {
1026+ "seed": "sample/58",
1027+ "family": "machines",
1028+ "sha256": "d4e4c79250507035126ff36e7cca4408e67423829d7d159375c4548d6c5d6aca"
1029+ },
1030+ {
1031+ "seed": "sample/59",
1032+ "family": "orbital",
1033+ "sha256": "4d81d67f82bafa2be012027fcc19caf3ec6c3763e8890ffaecdf4301eee8230e"
1034+ },
1035+ {
1036+ "seed": "sample/60",
1037+ "family": "landscapes",
1038+ "sha256": "ba8ad8d23f84c743b76bd969d4cb1cfda7997cb6fed6b569d3fb0b677c0e4a54"
1039+ },
1040+ {
1041+ "seed": "sample/61",
1042+ "family": "woven",
1043+ "sha256": "8d33021e42697dc01cd714f9b66f8712849c9a4fa9f7bc9b8644270fd96bb027"
1044+ },
1045+ {
1046+ "seed": "sample/62",
1047+ "family": "masks",
1048+ "sha256": "347a18dfe5794a46d5a835efe2d28adc0e29b97e2d09ae799fdbcbd19e07dd83"
1049+ },
1050+ {
1051+ "seed": "sample/63",
1052+ "family": "masks",
1053+ "sha256": "b780f518504f925cc6d931c697a8dcf2020165f64fe353929459167bea99cc16"
1054+ },
1055+ {
1056+ "seed": "sample/64",
1057+ "family": "botanical",
1058+ "sha256": "a5f29580682cbcae49448b9376cb80240ed36b40cea61b6067a8b495a0b4dcf2"
1059+ },
1060+ {
1061+ "seed": "sample/65",
1062+ "family": "botanical",
1063+ "sha256": "b9afa623712f8138ad1e3f1470b2e76f0d66aa4542c15ce39aaa10370275c460"
1064+ },
1065+ {
1066+ "seed": "sample/66",
1067+ "family": "machines",
1068+ "sha256": "70a12ec2d582ac9beac513b786204c3a0bb342d42f297450ae73fb3155393048"
1069+ },
1070+ {
1071+ "seed": "sample/67",
1072+ "family": "woven",
1073+ "sha256": "a6697371ba9fbc79a5618daa7cb443de17be72556fa7805e9348dd0c70344158"
1074+ },
1075+ {
1076+ "seed": "sample/68",
1077+ "family": "woven",
1078+ "sha256": "68b938d2c30c2785a76d70783d9722419e9bbc0a9a68040f583425ea8bd9a7ee"
1079+ },
1080+ {
1081+ "seed": "sample/69",
1082+ "family": "landscapes",
1083+ "sha256": "73eb43a6694fcb5185af156ba4bcc65645547427d70f37778ab1fcb7bbdcefb8"
1084+ },
1085+ {
1086+ "seed": "sample/70",
1087+ "family": "creatures",
1088+ "sha256": "6874416d4ad64bd2392c65ba1a8d9fbdf3eeceb497da5e0e146dc3a8c4559f9d"
1089+ },
1090+ {
1091+ "seed": "sample/71",
1092+ "family": "landscapes",
1093+ "sha256": "dc1174b107b2dc79885453bbe2bca24dc6d2575fbab5651d56e10982f53609b9"
1094+ },
1095+ {
1096+ "seed": "sample/72",
1097+ "family": "machines",
1098+ "sha256": "ddac9d5b5137ae91a7d35816dc27382658e12ff05faccc1f350d204ba4742d5c"
1099+ },
1100+ {
1101+ "seed": "sample/73",
1102+ "family": "landscapes",
1103+ "sha256": "2b776eb324cb0e2b90b1bf678b61942bd96b5e15a70dbb4a71127f3943d68acc"
1104+ },
1105+ {
1106+ "seed": "sample/74",
1107+ "family": "woven",
1108+ "sha256": "c67f05cc0aa9bbda3a36504a77929a2fb9736740c293bcfaef5301a66b94c4b4"
1109+ },
1110+ {
1111+ "seed": "sample/75",
1112+ "family": "woven",
1113+ "sha256": "410e470976eacd9ae529ee9551cb1f9e157c9deb4c0aff5639739539bee7a54d"
1114+ },
1115+ {
1116+ "seed": "sample/76",
1117+ "family": "landscapes",
1118+ "sha256": "1833c83ca7ae599435dc422421c6d0d4405ba448302c1568c4716594d7940774"
1119+ },
1120+ {
1121+ "seed": "sample/77",
1122+ "family": "masks",
1123+ "sha256": "fc2abc9c43c342b05f196e5965f90a85001042114f454d641bebface0e6d644a"
1124+ },
1125+ {
1126+ "seed": "sample/78",
1127+ "family": "machines",
1128+ "sha256": "098d40e8331dc790d42585d978747541f3b5915d609f36ae520f0afadb1c83b7"
1129+ },
1130+ {
1131+ "seed": "sample/79",
1132+ "family": "botanical",
1133+ "sha256": "def19606031133f58a3f963728e3de8a71d034cd30aa981e62e187bac65812b2"
1134+ },
1135+ {
1136+ "seed": "sample/80",
1137+ "family": "creatures",
1138+ "sha256": "c1ce68a624a6b96966f0845b0883125200c621b511da089d19689db30fd2290d"
1139+ },
1140+ {
1141+ "seed": "sample/81",
1142+ "family": "machines",
1143+ "sha256": "59cd2f69592c718125e275e52336ddd028aa518f389e4246a1cfa141c78644a6"
1144+ },
1145+ {
1146+ "seed": "sample/82",
1147+ "family": "glyphs",
1148+ "sha256": "724aeff5eef8da625f4ee72819b1a244b28361d7422f53fd8a5f5c7900a6212a"
1149+ },
1150+ {
1151+ "seed": "sample/83",
1152+ "family": "orbital",
1153+ "sha256": "b2633c506c3d88c0914a460eb383ba5cb87a9865340c8fc729eb3ccf41657215"
1154+ },
1155+ {
1156+ "seed": "sample/84",
1157+ "family": "orbital",
1158+ "sha256": "d20b748699562b25a23b8967c381f8ce0a8bacfa7d6e8bd168dab8d9ae6c9a81"
1159+ },
1160+ {
1161+ "seed": "sample/85",
1162+ "family": "creatures",
1163+ "sha256": "fd30845e9d0e76fecd3d82ad1bd8c20e8c8dc2c4c8533d7511e817bcc82cdc05"
1164+ },
1165+ {
1166+ "seed": "sample/86",
1167+ "family": "landscapes",
1168+ "sha256": "c93060f5f278fa6660a904b9b78bb519f842a8d34bebbe6b713f6a627d8b6428"
1169+ },
1170+ {
1171+ "seed": "sample/87",
1172+ "family": "masks",
1173+ "sha256": "c0fc36005e2968787f99e7e6c89a9772e94c98fdab452945f670ce7f613534a8"
1174+ },
1175+ {
1176+ "seed": "sample/88",
1177+ "family": "machines",
1178+ "sha256": "aae5442174348459a08a259e68f045156085d5d4b51ba0edf1c62e8603271690"
1179+ },
1180+ {
1181+ "seed": "sample/89",
1182+ "family": "botanical",
1183+ "sha256": "b06de3d96baa257da9638c8a95a1a79c47d5b196c0ddc2e2ebc36affba559c6e"
1184+ },
1185+ {
1186+ "seed": "sample/90",
1187+ "family": "botanical",
1188+ "sha256": "daf39093fcbfeb492c9b53b097b29285578d1e63d3fa36575e7b5457258af964"
1189+ },
1190+ {
1191+ "seed": "sample/91",
1192+ "family": "botanical",
1193+ "sha256": "0b87dd9df9c2f7ac4cefb02b0a37106ce9c911428085fd96dccb2df83b666dee"
1194+ },
1195+ {
1196+ "seed": "sample/92",
1197+ "family": "machines",
1198+ "sha256": "432deaeaa5cbd6bde975cc8d17fd4d3f26f04cb1fb33c7136a8429a88f90c7c1"
1199+ },
1200+ {
1201+ "seed": "sample/93",
1202+ "family": "creatures",
1203+ "sha256": "08c9bb89bfff4721218873d5b9d66714969cef5c18a7f44aaf0add974a444925"
1204+ },
1205+ {
1206+ "seed": "sample/94",
1207+ "family": "masks",
1208+ "sha256": "30be92735fa610c184eeaac1d52ba89415020ffd816e597095685bbae2f79c5e"
1209+ },
1210+ {
1211+ "seed": "sample/95",
1212+ "family": "machines",
1213+ "sha256": "0bd768447aefa71454ba984dfe3989a0dafd43185676788eeb6b2298387150fd"
1214+ },
1215+ {
1216+ "seed": "sample/96",
1217+ "family": "machines",
1218+ "sha256": "ffa94a32ed88b5f7aba28c29dde32b585d1472961989710b215b204ead29de21"
1219+ },
1220+ {
1221+ "seed": "sample/97",
1222+ "family": "orbital",
1223+ "sha256": "18f27c8d66f5e4d1955ce0698ffaf07e4fb50c5ee206cde86c9aadcc0a8ef2f2"
1224+ },
1225+ {
1226+ "seed": "sample/98",
1227+ "family": "masks",
1228+ "sha256": "5fcf0654f99f22c55fbd1a648f8991cd2ec53fb4fd3cf71dc0dfc88b1cd5289a"
1229+ },
1230+ {
1231+ "seed": "sample/99",
1232+ "family": "creatures",
1233+ "sha256": "cdefdea3581a30e1f26111a5048b59ec2b62a71109c54a2464dcb5d8195bb0fc"
1234+ },
1235+ {
1236+ "seed": "sample/100",
1237+ "family": "creatures",
1238+ "sha256": "8362260a72f2f599ef78f81ceba3880d5d7ce34967125a5bfb1859ba831912cd"
1239+ },
1240+ {
1241+ "seed": "sample/101",
1242+ "family": "creatures",
1243+ "sha256": "d9c0196345b0fb77ea8923ebbba9f7defb458228f3ecf25beb81a0e9a16ee37f"
1244+ },
1245+ {
1246+ "seed": "sample/102",
1247+ "family": "woven",
1248+ "sha256": "3ee62001de8b7c460b8fd0b593fb619a9431bb65008a31a6b2b8dd4259c6a3b8"
1249+ },
1250+ {
1251+ "seed": "sample/103",
1252+ "family": "machines",
1253+ "sha256": "7cc84412daab7ea311ab166fc52c9e06a4ecb303bee985f64fdcef378af3e9d3"
1254+ },
1255+ {
1256+ "seed": "sample/104",
1257+ "family": "glyphs",
1258+ "sha256": "6056d1dc560015578ce37ec91877119ccf5260a22e25c17cfa12c6545b5e67d9"
1259+ },
1260+ {
1261+ "seed": "sample/105",
1262+ "family": "creatures",
1263+ "sha256": "162c9f18e3468d8d9b1d90fb2714886b5615ac797c7a096a0dc4dec1bd61e839"
1264+ },
1265+ {
1266+ "seed": "sample/106",
1267+ "family": "masks",
1268+ "sha256": "c65acce1b25f0de486ad7b7e570702582fd80eabb0a9db1facb7b09c02836790"
1269+ },
1270+ {
1271+ "seed": "sample/107",
1272+ "family": "orbital",
1273+ "sha256": "bcdc769da640d3fb2db8694295b6f7b89896f40c0686567d702174b6e8dbd66b"
1274+ },
1275+ {
1276+ "seed": "sample/108",
1277+ "family": "glyphs",
1278+ "sha256": "8141655b50c6b86d8789d1927c8f3969d405aef855528378717904d735e006ed"
1279+ },
1280+ {
1281+ "seed": "sample/109",
1282+ "family": "creatures",
1283+ "sha256": "1e5c790be58c42b4084e0c93f80e15bfadf462d0e8dd892101a3168dc1a6006e"
1284+ },
1285+ {
1286+ "seed": "sample/110",
1287+ "family": "botanical",
1288+ "sha256": "44461963c51d8f1e6dc88572f6d8932a77c61e5f155c0e808a9c33bf85dd8058"
1289+ },
1290+ {
1291+ "seed": "sample/111",
1292+ "family": "woven",
1293+ "sha256": "030a399bb64859585c75a15f42a08857ac73638041eae09e2dc89f6f4767bfb7"
1294+ },
1295+ {
1296+ "seed": "sample/112",
1297+ "family": "masks",
1298+ "sha256": "ddfdcf4d908b97c6a9026dbb2fb8c6d5c0cbc5b780613c52f0f1ac3f113f3109"
1299+ },
1300+ {
1301+ "seed": "sample/113",
1302+ "family": "machines",
1303+ "sha256": "5f2f895f016bb08e63aa9d0d4a694d99b5eac2def5a3d555e902715ba3093902"
1304+ },
1305+ {
1306+ "seed": "sample/114",
1307+ "family": "landscapes",
1308+ "sha256": "47481fcc040a29c2448d33b31fa959d6b9574c01310b5b180d97138bf7028bb5"
1309+ },
1310+ {
1311+ "seed": "sample/115",
1312+ "family": "botanical",
1313+ "sha256": "6bef7b31de34d9d70566fd265bcbde2b87ae9f4dd90f9fd2ae75278b91ac6e15"
1314+ },
1315+ {
1316+ "seed": "sample/116",
1317+ "family": "orbital",
1318+ "sha256": "95ae310efbf9460f8ee79a2d55b4aaa9e415a81447c755c6bf3f119d08ba73eb"
1319+ },
1320+ {
1321+ "seed": "sample/117",
1322+ "family": "masks",
1323+ "sha256": "ffddde87258e30f6c48e695b6996150f135bbe30f1cdaf771f0cef3e186d46f1"
1324+ },
1325+ {
1326+ "seed": "sample/118",
1327+ "family": "masks",
1328+ "sha256": "5d42b3949fb547304cd7301d74a3e63b5092cb18cfd6cd232eebc7ed0932d8e6"
1329+ },
1330+ {
1331+ "seed": "sample/119",
1332+ "family": "creatures",
1333+ "sha256": "17f137319319bf7f559d5b851f31d6b753fe95eda5a4ee673f1f26f0e6b950f7"
1334+ },
1335+ {
1336+ "seed": "sample/120",
1337+ "family": "orbital",
1338+ "sha256": "48c61af0533c3125f5c884e90359dd5e5295e9f2874a62fd595d6c9d79244ebd"
1339+ },
1340+ {
1341+ "seed": "sample/121",
1342+ "family": "woven",
1343+ "sha256": "1dceff3fcd0628295ba5deb0bff221f71d7cfaa1c8b445f9c15111689129d550"
1344+ },
1345+ {
1346+ "seed": "sample/122",
1347+ "family": "landscapes",
1348+ "sha256": "55b85c0d5c15e17e3022f6132a584ddcde292c44e3ee8111f6ff7886cbdb26c6"
1349+ },
1350+ {
1351+ "seed": "sample/123",
1352+ "family": "creatures",
1353+ "sha256": "f08e598cb535c1929df8501d3572c90ffc7b0eefa83ea62ce43ae74aea94ec49"
1354+ },
1355+ {
1356+ "seed": "sample/124",
1357+ "family": "masks",
1358+ "sha256": "261cb5fd1e0ea296dd41265ad272c289bab6e698f39a3948cd411c83eb862204"
1359+ },
1360+ {
1361+ "seed": "sample/125",
1362+ "family": "machines",
1363+ "sha256": "8f1db4695a02baafcf8ace4d8d432fd4cf3a873afa48cd40114b39bc2754fee8"
1364+ },
1365+ {
1366+ "seed": "sample/126",
1367+ "family": "orbital",
1368+ "sha256": "75ebda39aa0f2346f3f12d4e843f54f602384b0eced122936976ad1a4311fc62"
1369+ },
1370+ {
1371+ "seed": "sample/127",
1372+ "family": "landscapes",
1373+ "sha256": "8ed4d29c29673e01d80225f1057caa2bd89bfb7fbbc408b8eaf619a802147115"
1374+ },
1375+ {
1376+ "seed": "sample/128",
1377+ "family": "machines",
1378+ "sha256": "7cba12cf3084b692b58b57bc074b56da18140755c048f7c0a9b0e695fbc8f42b"
1379+ },
1380+ {
1381+ "seed": "sample/129",
1382+ "family": "orbital",
1383+ "sha256": "72ebda49207d65a4347be1c7d32bf48471a5eebce434338face5c9481d96e7b3"
1384+ },
1385+ {
1386+ "seed": "sample/130",
1387+ "family": "machines",
1388+ "sha256": "2d2c700812185507d681e46fb52144c79c3fc8932a03ca297f829cfb45abc1d7"
1389+ },
1390+ {
1391+ "seed": "sample/131",
1392+ "family": "woven",
1393+ "sha256": "454350e879d6a7502765ea47c60a4865c5fc677c3a1b110bb41ae440ae842fee"
1394+ },
1395+ {
1396+ "seed": "sample/132",
1397+ "family": "woven",
1398+ "sha256": "bb281d63d5b03ebce09fa8cc23e4d22d59ec1ea18548c42608c1248175e3276a"
1399+ },
1400+ {
1401+ "seed": "sample/133",
1402+ "family": "machines",
1403+ "sha256": "f26f620b595f3017cb19705b99182dd9014538db88aa44d99d5ecdd28a2cd02a"
1404+ },
1405+ {
1406+ "seed": "sample/134",
1407+ "family": "landscapes",
1408+ "sha256": "f0564f568e667d88e13b512443988b163f3ff784a3ca6ff23edf3c5741597c88"
1409+ },
1410+ {
1411+ "seed": "sample/135",
1412+ "family": "creatures",
1413+ "sha256": "13c2d24e3c548be99c37c316d68a540b75159fcb881a6cac1aa896a2f0719d42"
1414+ },
1415+ {
1416+ "seed": "sample/136",
1417+ "family": "creatures",
1418+ "sha256": "782ef7a8bfa073c3a6e5912af3d58aeec06588ccd7299d03f786846f49962c48"
1419+ },
1420+ {
1421+ "seed": "sample/137",
1422+ "family": "machines",
1423+ "sha256": "52b390c4c08a5a2d6264ee8068a7f108db23f2951b755733326eaaf195a0d8df"
1424+ },
1425+ {
1426+ "seed": "sample/138",
1427+ "family": "botanical",
1428+ "sha256": "843b437490cf5371117f544307bb8ac6a07aff6f0f9a6aeab9fc3e10be0c00b2"
1429+ },
1430+ {
1431+ "seed": "sample/139",
1432+ "family": "glyphs",
1433+ "sha256": "ca7c3976719774e7e00f4647a3a51b4af7c0242e8e6de2b87dc7296c69f8ee6c"
1434+ },
1435+ {
1436+ "seed": "sample/140",
1437+ "family": "glyphs",
1438+ "sha256": "f5fa817d897df0f0090824d0feac9404d1361e7a0e33465cd310f72801045d2a"
1439+ },
1440+ {
1441+ "seed": "sample/141",
1442+ "family": "landscapes",
1443+ "sha256": "17fc8e3b29d5e47920d5c54147b99b510b98334437503f13783dcc42ca648432"
1444+ },
1445+ {
1446+ "seed": "sample/142",
1447+ "family": "glyphs",
1448+ "sha256": "5c21cc12134eb1f3ad147aec7b1965473691dabcbcc0f20ceeb291c2cb624aee"
1449+ },
1450+ {
1451+ "seed": "sample/143",
1452+ "family": "glyphs",
1453+ "sha256": "253b45f4c26668cd6da55ad8092d6a353449f1a22bec60a013ab6966d6c9ab21"
1454+ },
1455+ {
1456+ "seed": "sample/144",
1457+ "family": "machines",
1458+ "sha256": "bbdbf99b92f63ff229d1807dd2eae2faffa749373557dffd05e8341e542d2b7e"
1459+ },
1460+ {
1461+ "seed": "sample/145",
1462+ "family": "orbital",
1463+ "sha256": "3179a33bd34ddf904ab43437e14b7f5306dc5cf8cb694e99b111b9a084dec02e"
1464+ },
1465+ {
1466+ "seed": "sample/146",
1467+ "family": "landscapes",
1468+ "sha256": "a03c1bf2608ee7484c41b2e5bcb339b61853d91fa7cd54e7e5e897ebff6087d7"
1469+ },
1470+ {
1471+ "seed": "sample/147",
1472+ "family": "creatures",
1473+ "sha256": "174adbb7beaf40034172eb6f1784cd6a5c505e16d89cdc62793c0273fefac962"
1474+ },
1475+ {
1476+ "seed": "sample/148",
1477+ "family": "masks",
1478+ "sha256": "28222c41f87e27ee604d2e74ca58a09e34e89382e9af9c182fad8554d837eeb7"
1479+ },
1480+ {
1481+ "seed": "sample/149",
1482+ "family": "machines",
1483+ "sha256": "fd3f09016e764e7d70ba2607a266f5986a8553eeacca081a0f42c6191bbcf9ab"
1484+ },
1485+ {
1486+ "seed": "sample/150",
1487+ "family": "machines",
1488+ "sha256": "af4e65bd7d470aae43e5031dc21b40935e8a47a2171b54b722ff5665058f38c9"
1489+ },
1490+ {
1491+ "seed": "sample/151",
1492+ "family": "woven",
1493+ "sha256": "7283ccf1222427133ee6b188a8be91d9290b23636265a8f0cd713cd85e62d696"
1494+ },
1495+ {
1496+ "seed": "sample/152",
1497+ "family": "landscapes",
1498+ "sha256": "784853b214ea3be21c81a846801d48c7c0b5ac6325eb5609ceceb2ce7e5126bb"
1499+ },
1500+ {
1501+ "seed": "sample/153",
1502+ "family": "creatures",
1503+ "sha256": "41ea518dd8e8093ec1a0285584c77d82c3c551dd39f015c18dc62fb50551d482"
1504+ },
1505+ {
1506+ "seed": "sample/154",
1507+ "family": "landscapes",
1508+ "sha256": "044785917e8ae486f55c562e37a8b3c6eac35d0cf692377f4e5eebebf7ae8f93"
1509+ },
1510+ {
1511+ "seed": "sample/155",
1512+ "family": "orbital",
1513+ "sha256": "95f1ca89a1d287563fad925c63006c31f448c487ec808172d07f7cdc656aae20"
1514+ },
1515+ {
1516+ "seed": "sample/156",
1517+ "family": "botanical",
1518+ "sha256": "bd5f6d77f0393baef82687aed4fc058ef462bafb0f1163761205f55a2d8c33bf"
1519+ },
1520+ {
1521+ "seed": "sample/157",
1522+ "family": "masks",
1523+ "sha256": "2708a5543855803e3476da45e2611b7e999da3ea303b511ba6eb43f1ec61909c"
1524+ },
1525+ {
1526+ "seed": "sample/158",
1527+ "family": "creatures",
1528+ "sha256": "cb23dedb951cc97ffd5ac301d2d4c80e59fc32cb6535a298184231be6a9976e0"
1529+ },
1530+ {
1531+ "seed": "sample/159",
1532+ "family": "masks",
1533+ "sha256": "31cc7e6912fccdd149c699cd960e190926a9dcab8cdcbe239dd2e99db35c59cb"
1534+ },
1535+ {
1536+ "seed": "sample/160",
1537+ "family": "machines",
1538+ "sha256": "f32a0be5575f3829bf7a7733f24b31049a4a9c56933354bc4efe80c0cd7338a3"
1539+ },
1540+ {
1541+ "seed": "sample/161",
1542+ "family": "glyphs",
1543+ "sha256": "5928efcfe418b35d0fdaa9d9fcbf78571c058315cab682c4f9f40b92de138cf0"
1544+ },
1545+ {
1546+ "seed": "sample/162",
1547+ "family": "machines",
1548+ "sha256": "cde5883f7c8b6cc2f5eb382cca09bd4daa3a95fbf078181bb74871abc1bdbb97"
1549+ },
1550+ {
1551+ "seed": "sample/163",
1552+ "family": "glyphs",
1553+ "sha256": "73e394f43e411c4266bd5426fba8705a2806cf61097c22690aae0231f07db89d"
1554+ },
1555+ {
1556+ "seed": "sample/164",
1557+ "family": "glyphs",
1558+ "sha256": "d36f4b95b5ac293ba6355f550b46b4d674d66a1d22c5460247673682b1fbd1aa"
1559+ },
1560+ {
1561+ "seed": "sample/165",
1562+ "family": "machines",
1563+ "sha256": "a906ce9a545c335e9e6c2b4049ef18ee39fa8c87dc4c6a0c56b7104dfc61d0e2"
1564+ },
1565+ {
1566+ "seed": "sample/166",
1567+ "family": "botanical",
1568+ "sha256": "00c9e8030e53d46be0f291ae03644ffcbe96de251186820db849408348dcd501"
1569+ },
1570+ {
1571+ "seed": "sample/167",
1572+ "family": "glyphs",
1573+ "sha256": "619bf35a4cfb233371445282f641ea5ebfd5a7376cf439f6dea4cf96924fb735"
1574+ },
1575+ {
1576+ "seed": "sample/168",
1577+ "family": "landscapes",
1578+ "sha256": "cb0f763ea5c9b9bab9b3a1a3933700dc7fd11350c1df681b47dd2d214874e81d"
1579+ },
1580+ {
1581+ "seed": "sample/169",
1582+ "family": "machines",
1583+ "sha256": "e178765bdbc4a8bc3e61d21ebc5bfb47f8400fee03dab157d7fb06f89d9695bd"
1584+ },
1585+ {
1586+ "seed": "sample/170",
1587+ "family": "woven",
1588+ "sha256": "be37bad3415ca4d067bdefe46745aa1bb5851de0417d2007235db320f76a0415"
1589+ },
1590+ {
1591+ "seed": "sample/171",
1592+ "family": "glyphs",
1593+ "sha256": "8d5d5e80accd08b0e985b173d12d37f2261761575776c4e05c3fcd8e3e0bf2b7"
1594+ },
1595+ {
1596+ "seed": "sample/172",
1597+ "family": "machines",
1598+ "sha256": "c3d7bfb5c65d0358dbbd4bbb606a77300d14953d35eb28542b2695736b8d53cd"
1599+ },
1600+ {
1601+ "seed": "sample/173",
1602+ "family": "glyphs",
1603+ "sha256": "4f32fa3c7251cfa5c0ad85c90e79b36ddf3dc37f1857659f4415b66301d6b37f"
1604+ },
1605+ {
1606+ "seed": "sample/174",
1607+ "family": "glyphs",
1608+ "sha256": "f6e8a7811dceee13da5cd045d0e00822378738074d74e63ce622820b83215e3c"
1609+ },
1610+ {
1611+ "seed": "sample/175",
1612+ "family": "orbital",
1613+ "sha256": "b5b97ac74904dbd8e71a560d3633c12b82531b57b347ccb1775b6b721358292b"
1614+ },
1615+ {
1616+ "seed": "sample/176",
1617+ "family": "creatures",
1618+ "sha256": "6c74ab52671122d394013219d912cbae3f797e40c42d89bc7c19ad3bbab81a4a"
1619+ },
1620+ {
1621+ "seed": "sample/177",
1622+ "family": "woven",
1623+ "sha256": "34be6446216fd248de85f56d8e064e535fea058890622ff58d16082868059fde"
1624+ },
1625+ {
1626+ "seed": "sample/178",
1627+ "family": "glyphs",
1628+ "sha256": "bfb8f66e9dfe4cffd6af6b185ce976d006994a5efbab4b40ccea07f598d88518"
1629+ },
1630+ {
1631+ "seed": "sample/179",
1632+ "family": "orbital",
1633+ "sha256": "d7dc337fc810c6cd89d22ec21d2795da6424c334a763f5a7ecdedd1a5955a153"
1634+ },
1635+ {
1636+ "seed": "sample/180",
1637+ "family": "orbital",
1638+ "sha256": "cc92db0e351d9e3973715553647e42b9527b21f5619edcd696c3f16c38b686e8"
1639+ },
1640+ {
1641+ "seed": "sample/181",
1642+ "family": "botanical",
1643+ "sha256": "3cf61849fae7cc4aa390b87d62e52a1bded9b2f79ee3ca06f4e9b67ed885d378"
1644+ },
1645+ {
1646+ "seed": "sample/182",
1647+ "family": "orbital",
1648+ "sha256": "3df71c77bbd697f13ee07c7dcbd6c212e844b349e14745ca1a232bc8fc39a086"
1649+ },
1650+ {
1651+ "seed": "sample/183",
1652+ "family": "landscapes",
1653+ "sha256": "1589dcc0f25a6ff26235cf72dea39b3becca4605e507f5d86867579dc37246cc"
1654+ },
1655+ {
1656+ "seed": "sample/184",
1657+ "family": "orbital",
1658+ "sha256": "8489a9f60f888030bfb324f1984827ab6c9f6d5e923dd0f37eb93d48d53aca94"
1659+ },
1660+ {
1661+ "seed": "sample/185",
1662+ "family": "machines",
1663+ "sha256": "076643082ee6923f0add08b76b2d2ee8e2893774f9fab7a62f4d0834ca3cfe0c"
1664+ },
1665+ {
1666+ "seed": "sample/186",
1667+ "family": "creatures",
1668+ "sha256": "393bfbcab2092d694f8066eee9b32c07a0169e2a6f0ff74d717d1a6cd082f3e2"
1669+ },
1670+ {
1671+ "seed": "sample/187",
1672+ "family": "botanical",
1673+ "sha256": "85ed55cacfa7f9d1482e8a8bda199c7500634b7c64fe27a491e7cd800b426dd2"
1674+ },
1675+ {
1676+ "seed": "sample/188",
1677+ "family": "machines",
1678+ "sha256": "742a90355d1336c41c8be23b3a32b98700c46c1c7960882679f979c9a6f570ac"
1679+ },
1680+ {
1681+ "seed": "sample/189",
1682+ "family": "orbital",
1683+ "sha256": "d39840560b3b2db9c0406e552606fa1cc3b4409db356e4ab33ab37dddff84f13"
1684+ },
1685+ {
1686+ "seed": "sample/190",
1687+ "family": "orbital",
1688+ "sha256": "3ca993f0006e72d84f250115ded5e6e3f5173a27b12037fa5036202ee1a181b7"
1689+ },
1690+ {
1691+ "seed": "sample/191",
1692+ "family": "woven",
1693+ "sha256": "719b4be81e1c97af42d96bef8f35f0182b533010d64f01fc02c57ccba5ad3b7b"
1694+ },
1695+ {
1696+ "seed": "sample/192",
1697+ "family": "glyphs",
1698+ "sha256": "bd97d5995ed28fed93421b70d3b651e61ee4443810d80cc5ff20d93e19d63db0"
1699+ },
1700+ {
1701+ "seed": "sample/193",
1702+ "family": "botanical",
1703+ "sha256": "af9215cfd96d0c71ef856dd3f17ef0806c58bdc36027b380c217d1b29a079006"
1704+ },
1705+ {
1706+ "seed": "sample/194",
1707+ "family": "glyphs",
1708+ "sha256": "b9efff1c21cc32075a063d95db2ac9d8c04b4be3dcd41785be348010ac118ccc"
1709+ },
1710+ {
1711+ "seed": "sample/195",
1712+ "family": "machines",
1713+ "sha256": "b1c601fe88a53433c73ac66f74fad5094971b303b249803507fe3b39a50f02ce"
1714+ },
1715+ {
1716+ "seed": "sample/196",
1717+ "family": "woven",
1718+ "sha256": "84b0bf3691bf442181c220423fa871f713cb50e9e1375a5187c5bbe575324388"
1719+ },
1720+ {
1721+ "seed": "sample/197",
1722+ "family": "glyphs",
1723+ "sha256": "8aa4fa2a39d7ff53c6fa34789975c3881209903e1e6bb02e97b6a2151eb3ef30"
1724+ },
1725+ {
1726+ "seed": "sample/198",
1727+ "family": "creatures",
1728+ "sha256": "4dfb3b3c8fc4f544370da80caa546b0811447aca85a903de3c87c63731c5c750"
1729+ },
1730+ {
1731+ "seed": "sample/199",
1732+ "family": "machines",
1733+ "sha256": "e5b475e3d00f6b9f861757a33911772828ba6523ee4ee13be8eec64f36333c11"
1734+ },
1735+ {
1736+ "seed": "sample/200",
1737+ "family": "creatures",
1738+ "sha256": "e173ce9f4a26299f5e05ab09a3fd93d951076db23869773252ba2f984cb765f5"
1739+ },
1740+ {
1741+ "seed": "sample/201",
1742+ "family": "landscapes",
1743+ "sha256": "15af0538a7859ddd5b8e44c0a07f32c517a3dda97bf94b90b3d4e891c323eb76"
1744+ },
1745+ {
1746+ "seed": "sample/202",
1747+ "family": "orbital",
1748+ "sha256": "adb5b541244e58bd6735605ca7db014102bdc6fb7e4a98104b37d9122d78d2e3"
1749+ },
1750+ {
1751+ "seed": "sample/203",
1752+ "family": "botanical",
1753+ "sha256": "c8f0381f3e7b8b92b7f3d9e030c4308a5d98488778d9f1aaed50645cc272d451"
1754+ },
1755+ {
1756+ "seed": "sample/204",
1757+ "family": "machines",
1758+ "sha256": "f797ac06ce4affa5b6722591f95a613a188f03caa153a8068c212ee68070a69b"
1759+ },
1760+ {
1761+ "seed": "sample/205",
1762+ "family": "landscapes",
1763+ "sha256": "9360507bdcb843616efbbdc53b62da6cefe283414dadfc4ccbd040a009088015"
1764+ },
1765+ {
1766+ "seed": "sample/206",
1767+ "family": "creatures",
1768+ "sha256": "e99cef80229c1057fec5e22ba4ffb742a425e9be96f17dda49842086c8cdab7c"
1769+ },
1770+ {
1771+ "seed": "sample/207",
1772+ "family": "landscapes",
1773+ "sha256": "22bc556880a411b12155f8068a79ee5b53eee288fd83fb3fc80d921c47f3c81c"
1774+ },
1775+ {
1776+ "seed": "sample/208",
1777+ "family": "masks",
1778+ "sha256": "4cc4d1266604124d93ae7d1145a648245427559ad35e6834fe9dc30f1cf1fdf8"
1779+ },
1780+ {
1781+ "seed": "sample/209",
1782+ "family": "masks",
1783+ "sha256": "71a874a109fd209d6b94cfacf18bf0b7a9d1fb8a8fc47aa01f5bb2ce0340f1a6"
1784+ },
1785+ {
1786+ "seed": "sample/210",
1787+ "family": "orbital",
1788+ "sha256": "5d137f4a5bda5292a84944649c5e97e73321e7742b12cad4d91296f763d747d4"
1789+ },
1790+ {
1791+ "seed": "sample/211",
1792+ "family": "botanical",
1793+ "sha256": "74df6847499fe13630364c3f25af1d06b11e58f76824f24b49613d7ae5197e93"
1794+ },
1795+ {
1796+ "seed": "sample/212",
1797+ "family": "machines",
1798+ "sha256": "36dc23006d7948b1befb136e970be4360219b912ac48a0e468a58e576c22aea2"
1799+ },
1800+ {
1801+ "seed": "sample/213",
1802+ "family": "masks",
1803+ "sha256": "d38fece2dc9b32caf8e61cb6d003f2b4e937d25da32b15650a730d005ff5bf21"
1804+ },
1805+ {
1806+ "seed": "sample/214",
1807+ "family": "woven",
1808+ "sha256": "beba8aacef4b3e828f743eaf7291286894b9b9fe13a605c008abd7280386faa2"
1809+ },
1810+ {
1811+ "seed": "sample/215",
1812+ "family": "masks",
1813+ "sha256": "bf04a2e24f466262695551cc0f2024e9d2dc067364d8a8931c1240bcf530307f"
1814+ },
1815+ {
1816+ "seed": "sample/216",
1817+ "family": "machines",
1818+ "sha256": "645bd7fb6bdcee56fca3de50079f7f270903c7aa35f58ea51dfefd60aab94aa8"
1819+ },
1820+ {
1821+ "seed": "sample/217",
1822+ "family": "woven",
1823+ "sha256": "76dab525874a019da971ef502c83f2c9a7b49be688ebecad1cfd1b9703902278"
1824+ },
1825+ {
1826+ "seed": "sample/218",
1827+ "family": "creatures",
1828+ "sha256": "eb1efc4822942b502e15eb2b3a5be438a4efdf0adc35b8fb152e77ba3e1235ce"
1829+ },
1830+ {
1831+ "seed": "sample/219",
1832+ "family": "glyphs",
1833+ "sha256": "4ec8607d03d1b4dbdbb22227169ce4a6c848735e692c0cbd2cf038c0279ab030"
1834+ },
1835+ {
1836+ "seed": "sample/220",
1837+ "family": "creatures",
1838+ "sha256": "d8807b70d2ce6ff4feefd61fddc77d6e156c6ac2ca81ddbd81c724b5c795e497"
1839+ },
1840+ {
1841+ "seed": "sample/221",
1842+ "family": "creatures",
1843+ "sha256": "5ffa32ed530c45a8187e390626d0203233ee4590dbaeced3ac6d6d558465b4d8"
1844+ },
1845+ {
1846+ "seed": "sample/222",
1847+ "family": "creatures",
1848+ "sha256": "d2a35956a819b3f40bd7b00f4c15acd58232d12efee7f93b64e3c6ab953390e8"
1849+ },
1850+ {
1851+ "seed": "sample/223",
1852+ "family": "masks",
1853+ "sha256": "a6a5f628c917f9c68cde30e09a222a478013becbcb39ab403898569cc1cb0ea3"
1854+ },
1855+ {
1856+ "seed": "sample/224",
1857+ "family": "landscapes",
1858+ "sha256": "0723b4ef6071d73414ad83c915e8fdfa34a28a98b62e666fcac4d983c11c3ccf"
1859+ },
1860+ {
1861+ "seed": "sample/225",
1862+ "family": "woven",
1863+ "sha256": "6059d4ee15f9909e6e58bd1a4d8e724ae523911ffeeec368ad4c18805c95938b"
1864+ },
1865+ {
1866+ "seed": "sample/226",
1867+ "family": "machines",
1868+ "sha256": "44cde40c0cd3befd578d8e8687dd7da0b1fbdd7299f45aa7139833ee8cd7a132"
1869+ },
1870+ {
1871+ "seed": "sample/227",
1872+ "family": "glyphs",
1873+ "sha256": "4d7b75fd3936b36c0679d8d06195c34d452f4b30e39c975caa813442107ea9c6"
1874+ },
1875+ {
1876+ "seed": "sample/228",
1877+ "family": "masks",
1878+ "sha256": "cbef4fe57c3fb627905964aacbb07313421372dc78c3a10cafff66c4d2ef43f2"
1879+ },
1880+ {
1881+ "seed": "sample/229",
1882+ "family": "masks",
1883+ "sha256": "107c57eb7c5f0d24074f3aae3730fdefb305e1b44a3e51a539b6107f4f1a022a"
1884+ },
1885+ {
1886+ "seed": "sample/230",
1887+ "family": "masks",
1888+ "sha256": "e0f1fd357e640f8d84520b2d599f8e4c8ab4ed58f770cae164f021c4ee1341d1"
1889+ },
1890+ {
1891+ "seed": "sample/231",
1892+ "family": "masks",
1893+ "sha256": "88e17effe9e45d67b329bb68f6b8b635a3c5d370d4aae9ddba7098688c8ebfc0"
1894+ },
1895+ {
1896+ "seed": "sample/232",
1897+ "family": "woven",
1898+ "sha256": "45137046e990d23c394ca7e43ff164259f3f3cd2b486842e814d9ca37d86f71a"
1899+ },
1900+ {
1901+ "seed": "sample/233",
1902+ "family": "orbital",
1903+ "sha256": "a8bc465222b10915b560f472fe011aefa1b657e69a37f445376d28e03860456c"
1904+ },
1905+ {
1906+ "seed": "sample/234",
1907+ "family": "masks",
1908+ "sha256": "a81241eeeb6094196613d3ea8788e0f777334579ab7ae45958605f137393f4f5"
1909+ },
1910+ {
1911+ "seed": "sample/235",
1912+ "family": "botanical",
1913+ "sha256": "fa62272d79a795a84376815140d49b8d1dfb22f5f733d308547fa13a836dd9ed"
1914+ },
1915+ {
1916+ "seed": "sample/236",
1917+ "family": "creatures",
1918+ "sha256": "d1f986704090d15daa096623cdab1c71ec44abee42162471146eb2d790ff4036"
1919+ },
1920+ {
1921+ "seed": "sample/237",
1922+ "family": "orbital",
1923+ "sha256": "b12e45060cc73a0dfb251976baad312d9f69e31e186556c9c64c82b4b010d31d"
1924+ },
1925+ {
1926+ "seed": "sample/238",
1927+ "family": "landscapes",
1928+ "sha256": "b171657de2ecebe579a205e05bf59b6a8c1998aeab9cb7981bbecd7466fc8892"
1929+ },
1930+ {
1931+ "seed": "sample/239",
1932+ "family": "creatures",
1933+ "sha256": "6a71a042ad8b4cfc8f9cbddad52ffe148a0d2ad263a793a233d1ad874e182707"
1934+ },
1935+ {
1936+ "seed": "sample/240",
1937+ "family": "masks",
1938+ "sha256": "63ebe2166fb22a6ac5e180aefd6d9c96df71c0e9e9e78892375a1f30ec117316"
1939+ },
1940+ {
1941+ "seed": "sample/241",
1942+ "family": "creatures",
1943+ "sha256": "bbee402bda2ae7399ab1eb426db8e2f190e5d26577a3aaa38e3808d729897465"
1944+ },
1945+ {
1946+ "seed": "sample/242",
1947+ "family": "orbital",
1948+ "sha256": "033844ef263cf6669ed82d7a935f4d6f6d1c9bfe2dec504e7f8a09ca87072f1b"
1949+ },
1950+ {
1951+ "seed": "sample/243",
1952+ "family": "landscapes",
1953+ "sha256": "3d9dcd34efeff07839b5ba9488eefe31334cf09143875aea54ccf9b112a5f3ac"
1954+ },
1955+ {
1956+ "seed": "sample/244",
1957+ "family": "landscapes",
1958+ "sha256": "1f3c24a6945a61e149e02a6b49c2f4e42a1e274dcc49da8b6a0d49d38aec1aad"
1959+ },
1960+ {
1961+ "seed": "sample/245",
1962+ "family": "orbital",
1963+ "sha256": "62d5d9be3910bf0344d23aaa54ba762d99e78ce4db604c4f50ee08cd2ead2b76"
1964+ },
1965+ {
1966+ "seed": "sample/246",
1967+ "family": "masks",
1968+ "sha256": "691290f3f71d29bf7cf61faa932ce776d7f6379c992d910e8077bc63a102eb04"
1969+ },
1970+ {
1971+ "seed": "sample/247",
1972+ "family": "woven",
1973+ "sha256": "de768a973af9e7bbcef7ad330fedb50f1987392f02f9fc8a2207b4dd18029f3c"
1974+ },
1975+ {
1976+ "seed": "sample/248",
1977+ "family": "botanical",
1978+ "sha256": "ce3e9e5d3d2770daf54b1bfa238f987fa0f06ba68997fbfb6950f9d34bd88c47"
1979+ },
1980+ {
1981+ "seed": "sample/249",
1982+ "family": "orbital",
1983+ "sha256": "24a1d207189a834fdf25cc9e31a55bcae5bbb53f389ba76a33980dae10a68f0a"
1984+ },
1985+ {
1986+ "seed": "sample/250",
1987+ "family": "orbital",
1988+ "sha256": "24271e83191a4d7ffe4518d35cce9198d3bd75a7d8b6efed1ddede1da893ee9a"
1989+ },
1990+ {
1991+ "seed": "sample/251",
1992+ "family": "glyphs",
1993+ "sha256": "a836c4584d66dc043172f3f3f54d144c138d0ba979064edccaaa28af2856bc7d"
1994+ },
1995+ {
1996+ "seed": "sample/252",
1997+ "family": "masks",
1998+ "sha256": "2302a394e7bbbb3c83ed270e8c346d59ddb80e56d8b3710e2f6fdd1724c1abce"
1999+ },
2000+ {
2001+ "seed": "sample/253",
2002+ "family": "glyphs",
2003+ "sha256": "4bbca31ce643d2e8a34d9ffb47b2f58781bb4e95d448d523bfffb6bfae64e519"
2004+ },
2005+ {
2006+ "seed": "sample/254",
2007+ "family": "botanical",
2008+ "sha256": "8c1fec78ddf203b7315f25f9faa1557c07baf3b95bf75db67bd30e3f06e59d7f"
2009+ },
2010+ {
2011+ "seed": "sample/255",
2012+ "family": "glyphs",
2013+ "sha256": "5be613c7e0f7ede9072a641f5ac3aad7b1e54373805c042c2f81f21541df7f8d"
2014+ },
2015+ {
2016+ "seed": "sample/256",
2017+ "family": "orbital",
2018+ "sha256": "de0a69bf620d0ee40f0933ff54e438a8b063c6658b2114fbf01a9fce8d100f45"
2019+ },
2020+ {
2021+ "seed": "sample/257",
2022+ "family": "creatures",
2023+ "sha256": "2c525819f6aa1fddab14ef50a5e9e1e6f384c4ece1b4989999853b9bb906f493"
2024+ },
2025+ {
2026+ "seed": "sample/258",
2027+ "family": "landscapes",
2028+ "sha256": "e5d78a00f43c43c6d0de870800c35c766f5c3f9a36cea050b6dd13e95dfa8337"
2029+ },
2030+ {
2031+ "seed": "sample/259",
2032+ "family": "masks",
2033+ "sha256": "c4888975b581899c64179a2b4d78348519b443a8dc66b0b1255837a592a0bbcf"
2034+ },
2035+ {
2036+ "seed": "sample/260",
2037+ "family": "woven",
2038+ "sha256": "00cc1cee52416f0bc107fa843f62dc317fb388fab92eaa69a08bd1e58aaa399d"
2039+ },
2040+ {
2041+ "seed": "sample/261",
2042+ "family": "masks",
2043+ "sha256": "f5b98697e504c7bead86f68c3ffbeaef8d8e16eadd155afbf13f9935ce63dfa1"
2044+ },
2045+ {
2046+ "seed": "sample/262",
2047+ "family": "glyphs",
2048+ "sha256": "7fc002089ab22c3273e4b8e6a3a9cb28f4d8356575a6ea22c8ebf02817e71449"
2049+ },
2050+ {
2051+ "seed": "sample/263",
2052+ "family": "orbital",
2053+ "sha256": "76958c271ba7cb7ccbdc8b574ca46cc3229e4a33056f7a2a6bb9db60bc2e17ba"
2054+ },
2055+ {
2056+ "seed": "sample/264",
2057+ "family": "masks",
2058+ "sha256": "c57ce953beb27e78771c9043909c92af3e863c3fa152c6e95159add4dd54285f"
2059+ },
2060+ {
2061+ "seed": "sample/265",
2062+ "family": "machines",
2063+ "sha256": "b74563f343239b689ba17a1d3a8ee42c1bb4fb59e1170875a28db3f85b811006"
2064+ },
2065+ {
2066+ "seed": "sample/266",
2067+ "family": "masks",
2068+ "sha256": "aeee6abb83aafe7758bbab6fc826e918e4c9758ee39bd4740beadc6981ff9868"
2069+ },
2070+ {
2071+ "seed": "sample/267",
2072+ "family": "glyphs",
2073+ "sha256": "d43ea0b7baf7b64ccc80b4ece91983a9511393d45a5ad9c69e1668c48e18720f"
2074+ },
2075+ {
2076+ "seed": "sample/268",
2077+ "family": "landscapes",
2078+ "sha256": "6645a94132610248bed4b9f0d29b4bd1a24b43088f4dc7cb90b3fbbfadebb7e1"
2079+ },
2080+ {
2081+ "seed": "sample/269",
2082+ "family": "botanical",
2083+ "sha256": "94478c95570a9075b1888074269c37624611e43cb8690fdf38e32e42d5931236"
2084+ },
2085+ {
2086+ "seed": "sample/270",
2087+ "family": "landscapes",
2088+ "sha256": "f038b343ec50801aff10e8af8d9ddaf0168e53c1db991285a8612baa7ff5e982"
2089+ },
2090+ {
2091+ "seed": "sample/271",
2092+ "family": "glyphs",
2093+ "sha256": "bf6d448d97d8d6b1d9c29932709d480feb9f722884d45ea0c24d58cf992a890f"
2094+ },
2095+ {
2096+ "seed": "sample/272",
2097+ "family": "woven",
2098+ "sha256": "057b7285bcab85bc32655b143ceab35a59f827f820470fba9219398f060de0e5"
2099+ },
2100+ {
2101+ "seed": "sample/273",
2102+ "family": "botanical",
2103+ "sha256": "e4882c69d7119a03d31a91808c77f1c2abd039d668aa6fa6c72ac09695d6ba72"
2104+ },
2105+ {
2106+ "seed": "sample/274",
2107+ "family": "botanical",
2108+ "sha256": "da29c9987c8115cbccd17e0eac7d363f766f5fbb4086e673f97b392e07f96bc3"
2109+ },
2110+ {
2111+ "seed": "sample/275",
2112+ "family": "creatures",
2113+ "sha256": "b5da8f8cb303e131259cf62e65f168507af3971de429ac0dce4c7dc76627ae83"
2114+ },
2115+ {
2116+ "seed": "sample/276",
2117+ "family": "creatures",
2118+ "sha256": "8b1e904a04cd2819bf6fdd92be270eb2108b0f66c3f4abf1984df9cb81c4ff9b"
2119+ },
2120+ {
2121+ "seed": "sample/277",
2122+ "family": "woven",
2123+ "sha256": "85fee3bbeb78549a7c10fc3745b6fb83374e6084b9abb3f0f01cedc92ba10390"
2124+ },
2125+ {
2126+ "seed": "sample/278",
2127+ "family": "glyphs",
2128+ "sha256": "ce3f7214f6c2d25d3565ef35b06554bc3864f2e66caa5678f5d7d5abc8d1edd0"
2129+ },
2130+ {
2131+ "seed": "sample/279",
2132+ "family": "machines",
2133+ "sha256": "efbd4e3b0e8ff6b6226a91f1a1b97764b5dcbd7fd5d703d67c71f3223afc0218"
2134+ },
2135+ {
2136+ "seed": "sample/280",
2137+ "family": "glyphs",
2138+ "sha256": "d49870e6ad94f31e7bbfd69c41a12d563c5f9f2e69a00d02f147677ee96bc260"
2139+ },
2140+ {
2141+ "seed": "sample/281",
2142+ "family": "machines",
2143+ "sha256": "2734a80f81e0f6aba8742bd4d66d4ad0751476c1e6138c3968473a860fd1b7a8"
2144+ },
2145+ {
2146+ "seed": "sample/282",
2147+ "family": "woven",
2148+ "sha256": "b28bfbefc42f604b09256350406e94c6b2fe65c0cefd504dcaec0338a09c74f5"
2149+ },
2150+ {
2151+ "seed": "sample/283",
2152+ "family": "creatures",
2153+ "sha256": "5ff5ea1ed549f46cc64c5e39715efd9104eeed96c85773f2fd4c93c4be4a3ce2"
2154+ },
2155+ {
2156+ "seed": "sample/284",
2157+ "family": "landscapes",
2158+ "sha256": "c1718913b227bdf760afff5247c023ea4dcb9a90a2b86a82428aa90bcabfabba"
2159+ },
2160+ {
2161+ "seed": "sample/285",
2162+ "family": "masks",
2163+ "sha256": "e303d06cd64f0713a1b9ed157bbd3408e205f0a12c897bff4c19c6465515fb36"
2164+ },
2165+ {
2166+ "seed": "sample/286",
2167+ "family": "masks",
2168+ "sha256": "d91ebda0b72e06a40616ba65f0d99359bc85fadb74863a7a8e92b9355042f110"
2169+ },
2170+ {
2171+ "seed": "sample/287",
2172+ "family": "botanical",
2173+ "sha256": "f7ce059834078642f37139dcd3665ed4b0d34fdea8f7a2bac4d3cf78ac476c99"
2174+ },
2175+ {
2176+ "seed": "sample/288",
2177+ "family": "orbital",
2178+ "sha256": "898b8a19724ca331cba87aa4eab056053124ca0d5e475d87cd4342956117894c"
2179+ },
2180+ {
2181+ "seed": "sample/289",
2182+ "family": "botanical",
2183+ "sha256": "9641f22a050db580ca5f5de274a7574ab3056de69f38a3ad225fa0e0f64e6b5a"
2184+ },
2185+ {
2186+ "seed": "sample/290",
2187+ "family": "botanical",
2188+ "sha256": "bddfcd6aa1c7ef8bec7d7b7cd3c71b7870abac14c8add0b9c8f78e176eaa5df8"
2189+ },
2190+ {
2191+ "seed": "sample/291",
2192+ "family": "machines",
2193+ "sha256": "2194430be7c24caf34d1227a63e291d53763d4b61c7212509e15e39c17be6370"
2194+ },
2195+ {
2196+ "seed": "sample/292",
2197+ "family": "woven",
2198+ "sha256": "838c48567b9f60a49545ab0241cc0da84f5f3942ffd681fe190eb8f0a00bd715"
2199+ },
2200+ {
2201+ "seed": "sample/293",
2202+ "family": "botanical",
2203+ "sha256": "bcaddf982aa8775533e7a7842a0a871d633848522a223fcbc1e9e5958de7c5b0"
2204+ },
2205+ {
2206+ "seed": "sample/294",
2207+ "family": "landscapes",
2208+ "sha256": "963f9d941c4ce68debf8475eaf4f43d3795a21b741b28124f648d7f138f695e8"
2209+ },
2210+ {
2211+ "seed": "sample/295",
2212+ "family": "machines",
2213+ "sha256": "1c2c3296d59ddb2d67a967ddb63d35a803ea040e5697e7255c89ef0635e63ccc"
2214+ },
2215+ {
2216+ "seed": "sample/296",
2217+ "family": "machines",
2218+ "sha256": "23084231347c18601dd566dbfc712fdf907174849544fe704fde4c11ec5490d1"
2219+ },
2220+ {
2221+ "seed": "sample/297",
2222+ "family": "machines",
2223+ "sha256": "b61ced8e7ba2f61eae3b4480f962ad78e85f0b4c1bca59184bf6447fdf09c845"
2224+ },
2225+ {
2226+ "seed": "sample/298",
2227+ "family": "glyphs",
2228+ "sha256": "2edc34201a3dd4bf81fabc9b3fac660d37bfecaf8ad4c4a907a42ce4f955df4e"
2229+ },
2230+ {
2231+ "seed": "sample/299",
2232+ "family": "glyphs",
2233+ "sha256": "e1e749cc53462a26f1d58716de01ff6d6b45829e8a2db9e5804a3fef9cdbf2bd"
2234+ },
2235+ {
2236+ "seed": "sample/300",
2237+ "family": "botanical",
2238+ "sha256": "c0838849d95c13be3fe4d40ece7ce4226357937b2e43c3ee7b4d7c99057d53b8"
2239+ },
2240+ {
2241+ "seed": "sample/301",
2242+ "family": "landscapes",
2243+ "sha256": "4f2f33c87d03dca41ed48cc94365ee9cf1b3f23072871ee57b92b8211cef284c"
2244+ },
2245+ {
2246+ "seed": "sample/302",
2247+ "family": "landscapes",
2248+ "sha256": "4d66ba07ebba60c88353cb01a987bdd1ac966bfdadc569a2b8bc988430b04341"
2249+ },
2250+ {
2251+ "seed": "sample/303",
2252+ "family": "landscapes",
2253+ "sha256": "7c86c9be7b2c5c4ee6e1ebf72def7c50f0002d5a16499f6c0b8d5172322c460e"
2254+ },
2255+ {
2256+ "seed": "sample/304",
2257+ "family": "botanical",
2258+ "sha256": "2049c8fc9039b96bc1c5a256451425d6b28cb9fbef3a4a6fd21345f8646c9b4d"
2259+ },
2260+ {
2261+ "seed": "sample/305",
2262+ "family": "machines",
2263+ "sha256": "34b5cc8574cc04f8bcef37520a47ad0db6b878a55cad298af8ec92cc7a067af5"
2264+ },
2265+ {
2266+ "seed": "sample/306",
2267+ "family": "creatures",
2268+ "sha256": "073e28b0903e3c64c22ed80e2861d672ee2abcf24ea7efbe02ec5da68f383f5d"
2269+ },
2270+ {
2271+ "seed": "sample/307",
2272+ "family": "masks",
2273+ "sha256": "a210ce3728f7b32c091d05904d55460fb30e1ea9f8da7fb86c9f8113461697fd"
2274+ },
2275+ {
2276+ "seed": "sample/308",
2277+ "family": "botanical",
2278+ "sha256": "05961b0dc4d7c2fcdcf17a214745c5fef35320ecc75f0f1d6292635f7b5cc113"
2279+ },
2280+ {
2281+ "seed": "sample/309",
2282+ "family": "masks",
2283+ "sha256": "73978f8ee1245438e69e5f029122d8f794aed28d90b6ca1a7a25918568c8ae46"
2284+ },
2285+ {
2286+ "seed": "sample/310",
2287+ "family": "woven",
2288+ "sha256": "7027b9ea7c0a22f2bde9aa93387a94dda22d4cf258eabbe46260d32e4e959db5"
2289+ },
2290+ {
2291+ "seed": "sample/311",
2292+ "family": "landscapes",
2293+ "sha256": "8a6f74aec960183bb28626265c882e59e116a41c216a26687fc2d5183d31572a"
2294+ },
2295+ {
2296+ "seed": "sample/312",
2297+ "family": "glyphs",
2298+ "sha256": "ebcae3dce034850bcc03db79d4ec3ecfb30767b7e6627ea770613a72911b63d6"
2299+ },
2300+ {
2301+ "seed": "sample/313",
2302+ "family": "woven",
2303+ "sha256": "b71c333f798182a01182c61f0ecd7c4e13fae187a9ec106701c6a2f3ff9db7b0"
2304+ },
2305+ {
2306+ "seed": "sample/314",
2307+ "family": "landscapes",
2308+ "sha256": "1860dfec4d58eac09ec0907aec820cfd195ecceb67d8315a581a0e2f8f618bdf"
2309+ },
2310+ {
2311+ "seed": "sample/315",
2312+ "family": "masks",
2313+ "sha256": "96ca992a5d8b7b36c8165c06e9417cadb45b71a8b710bbca609a73feed7dd565"
2314+ },
2315+ {
2316+ "seed": "sample/316",
2317+ "family": "orbital",
2318+ "sha256": "39396c5da766ca320a3c379259d52b70f1d5cc41f7901a02844de214c8091b3b"
2319+ },
2320+ {
2321+ "seed": "sample/317",
2322+ "family": "machines",
2323+ "sha256": "bef8132ae48cf9bfdb7d6bca348d1d7414bb56222a1b8d9e1eee978b8f50ea00"
2324+ },
2325+ {
2326+ "seed": "sample/318",
2327+ "family": "machines",
2328+ "sha256": "11e8453d3525e5c9b896ec29f558f616f85991b490148e89f6feced501b242dd"
2329+ },
2330+ {
2331+ "seed": "sample/319",
2332+ "family": "glyphs",
2333+ "sha256": "8df7ca35caae7f026836d90dfedd64f9dff060bb022b52df825d7593957198ca"
2334+ },
2335+ {
2336+ "seed": "sample/320",
2337+ "family": "creatures",
2338+ "sha256": "e50784984da226c8c28d222d731da5aaa43781c5572e63e305f39b3e492fbaa5"
2339+ },
2340+ {
2341+ "seed": "sample/321",
2342+ "family": "woven",
2343+ "sha256": "6f9e68793b3caf3c2eaebfc87b592bf4f3a4430d837bf6612e0cb6186eabbf1a"
2344+ },
2345+ {
2346+ "seed": "sample/322",
2347+ "family": "botanical",
2348+ "sha256": "f7c2dc2a0d328dee67202afcce9af4b399a5f2eaeb02646f58840f5c67e6fe70"
2349+ },
2350+ {
2351+ "seed": "sample/323",
2352+ "family": "botanical",
2353+ "sha256": "3a2227f020574734fb578e0ac284848842f657392afe5580c17e0a374a3d4e0a"
2354+ },
2355+ {
2356+ "seed": "sample/324",
2357+ "family": "masks",
2358+ "sha256": "1f9304349e135f840687ea093c1c3c58bb2dcd9c3a73211a8be765087ea7daf5"
2359+ },
2360+ {
2361+ "seed": "sample/325",
2362+ "family": "masks",
2363+ "sha256": "e7bc66cbfae4b19e5b4201b0e643a6ba73e0dcac5ed9648d0ddfebc9a6273ef4"
2364+ },
2365+ {
2366+ "seed": "sample/326",
2367+ "family": "botanical",
2368+ "sha256": "9e7d647a0b5b799846efb1eb62778a0b9ab2d77a64ce2ec2758226c27eda419a"
2369+ },
2370+ {
2371+ "seed": "sample/327",
2372+ "family": "botanical",
2373+ "sha256": "9dacdab8e918de3550b7e203647e5f9e9ac2ada4c3d061f13edc48515066101c"
2374+ },
2375+ {
2376+ "seed": "sample/328",
2377+ "family": "glyphs",
2378+ "sha256": "31e397683d6e37368b7079a1aa4156b41ffc356765c4cb7345a4bc56f32675a0"
2379+ },
2380+ {
2381+ "seed": "sample/329",
2382+ "family": "glyphs",
2383+ "sha256": "646269249ed9a5a58e17b826a50994c773a91bbea82e54b271df0b0f694e4f03"
2384+ },
2385+ {
2386+ "seed": "sample/330",
2387+ "family": "masks",
2388+ "sha256": "e2cb2321f6edd21861c30f782aab1d9e1700c0afe855e9401a6482a44c53a8e1"
2389+ },
2390+ {
2391+ "seed": "sample/331",
2392+ "family": "creatures",
2393+ "sha256": "9dbd50216a8079afb439d9c71675a03158b04adc0cc58588dc9afe52313910bd"
2394+ },
2395+ {
2396+ "seed": "sample/332",
2397+ "family": "machines",
2398+ "sha256": "f34c7d55b56d5abf3f14480a86c33492307057372e85d036533a76dae461ed66"
2399+ },
2400+ {
2401+ "seed": "sample/333",
2402+ "family": "creatures",
2403+ "sha256": "b8dfb4df1b003cb3f16246e8052b747a491dc2ffde5704aaf2f31a24c1ffc035"
2404+ },
2405+ {
2406+ "seed": "sample/334",
2407+ "family": "glyphs",
2408+ "sha256": "59fe06d3c287f3a1389a681a70a088a2d6c1d1422759730c87117a79ba37c8a0"
2409+ },
2410+ {
2411+ "seed": "sample/335",
2412+ "family": "glyphs",
2413+ "sha256": "d8810997f449c6e08d4d9540aa388e47e704b482b9d1a51806131bb80d5292eb"
2414+ },
2415+ {
2416+ "seed": "sample/336",
2417+ "family": "botanical",
2418+ "sha256": "9641f22a050db580ca5f5de274a7574ab3056de69f38a3ad225fa0e0f64e6b5a"
2419+ },
2420+ {
2421+ "seed": "sample/337",
2422+ "family": "landscapes",
2423+ "sha256": "dc2953c4a8cfeecde1c05a7eca7eccc186f48ce44150fdb029dd683d51ba9470"
2424+ },
2425+ {
2426+ "seed": "sample/338",
2427+ "family": "botanical",
2428+ "sha256": "4ade9335c966eed0a9a4c008d2023a14929981488e43d593dd3eff7e4fb4b5a2"
2429+ },
2430+ {
2431+ "seed": "sample/339",
2432+ "family": "machines",
2433+ "sha256": "dc374b26384b692b7de8fc56b314c66593da9bde5e15cffb22d4ad3f7d093657"
2434+ },
2435+ {
2436+ "seed": "sample/340",
2437+ "family": "machines",
2438+ "sha256": "4200fa4ef7d552248f2f8da720bed54e5d4fcdc56a50dd00f0c3d79a9af78726"
2439+ },
2440+ {
2441+ "seed": "sample/341",
2442+ "family": "machines",
2443+ "sha256": "ef67cfe67710a27aaf742dcbb17e8beb1085c339afc21e867d68e1cb5d9809f6"
2444+ },
2445+ {
2446+ "seed": "sample/342",
2447+ "family": "glyphs",
2448+ "sha256": "28aac8f8901322a9ce6f2f84e2f59dac550f13bec06cb35f7bdb523e2eaaca5a"
2449+ },
2450+ {
2451+ "seed": "sample/343",
2452+ "family": "botanical",
2453+ "sha256": "c508580fdd9ea87ab8eeb7f12128d802ff0f569a849f6e7379102c8fdab47889"
2454+ },
2455+ {
2456+ "seed": "sample/344",
2457+ "family": "machines",
2458+ "sha256": "2aa5a26af8a91789ce2bb2342d9454617a70f3d37a6122d1796f0a1ab0609fa2"
2459+ },
2460+ {
2461+ "seed": "sample/345",
2462+ "family": "orbital",
2463+ "sha256": "eaa918a182a3f95ab6765ca67baa3251ac3f0d847e595882804beffda95b70ed"
2464+ },
2465+ {
2466+ "seed": "sample/346",
2467+ "family": "masks",
2468+ "sha256": "374c128951e94362fc59acf92e3216b903ab0984077e1e27d3ff22e240686784"
2469+ },
2470+ {
2471+ "seed": "sample/347",
2472+ "family": "orbital",
2473+ "sha256": "4ace27fe0b15717cb91fcf81121e09093cfcb27c56af929ef9b6f03ea2229bb1"
2474+ },
2475+ {
2476+ "seed": "sample/348",
2477+ "family": "orbital",
2478+ "sha256": "bdeedb47f6ad528f77edf31e77c7056e4b8f9110482fab91c2cac65c04c9a824"
2479+ },
2480+ {
2481+ "seed": "sample/349",
2482+ "family": "landscapes",
2483+ "sha256": "04869f87b60ddbe67adb73a63dd033eb3bfb3e7567d1f7f00f1c255007e8f030"
2484+ },
2485+ {
2486+ "seed": "sample/350",
2487+ "family": "masks",
2488+ "sha256": "dfd1c6bccd16a608f3db022453fe5e93eb7798ae4c73a1c36de80374624d632e"
2489+ },
2490+ {
2491+ "seed": "sample/351",
2492+ "family": "creatures",
2493+ "sha256": "848b3a0465d4e9b1d7e584d7db9490015ea1f80e9ebe42dbf22a935d94780f3c"
2494+ },
2495+ {
2496+ "seed": "sample/352",
2497+ "family": "machines",
2498+ "sha256": "4003dd2f4cce713fea0f27cc5302f7360113c49e76776c1ab5772185bd726064"
2499+ },
2500+ {
2501+ "seed": "sample/353",
2502+ "family": "machines",
2503+ "sha256": "53bbaa818e35a0cebb4f194d47a54ad3d2234f8e35deedd8e962aa103b33200b"
2504+ },
2505+ {
2506+ "seed": "sample/354",
2507+ "family": "creatures",
2508+ "sha256": "0383636677120983e7db18a97f974db8a41cf4897daeb6a4fc4b1bd49ea38348"
2509+ },
2510+ {
2511+ "seed": "sample/355",
2512+ "family": "machines",
2513+ "sha256": "046f85621b45be751deeef3bf49a1f1994e929a1223ebe5b409fea2336aaed7b"
2514+ },
2515+ {
2516+ "seed": "sample/356",
2517+ "family": "glyphs",
2518+ "sha256": "c3b7edca11850e981af45130c385f471c57862b4f071e9488af3609ba29ab18f"
2519+ },
2520+ {
2521+ "seed": "sample/357",
2522+ "family": "woven",
2523+ "sha256": "445fef1e213ca83999e006e06dee97a35647147db4e5df4cfc2b0166e4419a42"
2524+ },
2525+ {
2526+ "seed": "sample/358",
2527+ "family": "woven",
2528+ "sha256": "d3203791411ddc8446a053f10ec53909804cef4fec9a9739a61c133dc6682f1a"
2529+ },
2530+ {
2531+ "seed": "sample/359",
2532+ "family": "creatures",
2533+ "sha256": "95df192849e7b65bac2dcc6a5948e949c5488a99707f4b4cd6bfeb0b9380f278"
2534+ },
2535+ {
2536+ "seed": "sample/360",
2537+ "family": "creatures",
2538+ "sha256": "9576ee31f49826377522baa35c74c0ab18dc6ca5d6f23e78af28cd1a9277962e"
2539+ },
2540+ {
2541+ "seed": "sample/361",
2542+ "family": "landscapes",
2543+ "sha256": "b12176062dfa97f8eb6f0e316d306a2a557bbff241e8a21292b9e203ef933175"
2544+ },
2545+ {
2546+ "seed": "sample/362",
2547+ "family": "woven",
2548+ "sha256": "180fbde97af4dfb30cd6866869529d3070954e5a7d02a20448d9a6662cd99a0c"
2549+ },
2550+ {
2551+ "seed": "sample/363",
2552+ "family": "botanical",
2553+ "sha256": "2ac62a6ea02da232c4e791bf1e82d3820b0209b63f4c429d443e71ab782f7f5d"
2554+ },
2555+ {
2556+ "seed": "sample/364",
2557+ "family": "glyphs",
2558+ "sha256": "79f70b7511c3c74ec60b1d25c37faf2e030b05c3a9a2c05b6773f5d706e3e4a8"
2559+ },
2560+ {
2561+ "seed": "sample/365",
2562+ "family": "glyphs",
2563+ "sha256": "a781d97060e40579223c4fa9afefaf230372267a97906f25095e6b350bbd187a"
2564+ },
2565+ {
2566+ "seed": "sample/366",
2567+ "family": "glyphs",
2568+ "sha256": "28380302d3be2708dbead049ff1b2cd25d7fd3ff5e2a93a7d97da7cbc8ffacf6"
2569+ },
2570+ {
2571+ "seed": "sample/367",
2572+ "family": "creatures",
2573+ "sha256": "58955a9f0b61b4b4bce1bbcc555990a24ad6e2893e45a476dbf70b98a53b3cb9"
2574+ },
2575+ {
2576+ "seed": "sample/368",
2577+ "family": "orbital",
2578+ "sha256": "5e190a3d0fa89a29fb2a974c5882cc2433468e3ae9e38741a547cda9f96e2aa2"
2579+ },
2580+ {
2581+ "seed": "sample/369",
2582+ "family": "creatures",
2583+ "sha256": "b6038cf6570d998cf5669a8b6f03bae751305a0b2c656a208465da177351e3d7"
2584+ },
2585+ {
2586+ "seed": "sample/370",
2587+ "family": "botanical",
2588+ "sha256": "7eeb94d4c7beecaeefd7391eebecf9cfcc3f5baa9de73a40946962fc6b09a6c9"
2589+ },
2590+ {
2591+ "seed": "sample/371",
2592+ "family": "woven",
2593+ "sha256": "79f86240970dff05fed35bfb329ef5b2d17dbf88ff3b37851ee2748a9d6959d7"
2594+ },
2595+ {
2596+ "seed": "sample/372",
2597+ "family": "landscapes",
2598+ "sha256": "d6d09ffb49c997bcac2f1444eb5e0ce547fb8c3b8d5a15398e932d3b6ca56957"
2599+ },
2600+ {
2601+ "seed": "sample/373",
2602+ "family": "woven",
2603+ "sha256": "32e453510d29fd736efff8a517ce2cdfdabfae30298c14074d76f21d99f3be49"
2604+ },
2605+ {
2606+ "seed": "sample/374",
2607+ "family": "creatures",
2608+ "sha256": "3103c9f468f6456283654963919657fcb60b2418dc9acf697f89b8dcac1c2b2c"
2609+ },
2610+ {
2611+ "seed": "sample/375",
2612+ "family": "botanical",
2613+ "sha256": "f60c9631956c136bfe9e00898d06ef1954070ec80567a8b1f94b4f5c78011b11"
2614+ },
2615+ {
2616+ "seed": "sample/376",
2617+ "family": "creatures",
2618+ "sha256": "e96f5b3c29fbb12a45eaa3ccf311a26f5a8b467b067f830dbce52b3ac435e447"
2619+ },
2620+ {
2621+ "seed": "sample/377",
2622+ "family": "botanical",
2623+ "sha256": "43512249c5b9231147bc2b7a8ff205fb56f45edb4f956386a54ad25a6ac07fd2"
2624+ },
2625+ {
2626+ "seed": "sample/378",
2627+ "family": "creatures",
2628+ "sha256": "91cb9533775025d1e8d92b356df4d88ecbe67ae2e635178b89d3d679a5409110"
2629+ },
2630+ {
2631+ "seed": "sample/379",
2632+ "family": "landscapes",
2633+ "sha256": "cab3c5201c4a3824cf38d5028279b681d0cf634069006eccdc39d52d95642620"
2634+ },
2635+ {
2636+ "seed": "sample/380",
2637+ "family": "glyphs",
2638+ "sha256": "1667666556815317496743baf0b309d188968e3255d18e5179ba97511db2b32b"
2639+ },
2640+ {
2641+ "seed": "sample/381",
2642+ "family": "creatures",
2643+ "sha256": "ebeb0406f7d2ea5d1a29c20b3dede781c7af84bbea5159f5b29e1b7c06ad66a6"
2644+ },
2645+ {
2646+ "seed": "sample/382",
2647+ "family": "landscapes",
2648+ "sha256": "63c17af13153875a94464e87de3c30a59b6f4306c01c742f908d5cc75fb5f39c"
2649+ },
2650+ {
2651+ "seed": "sample/383",
2652+ "family": "masks",
2653+ "sha256": "705b29f9be57d4b2f7fb561a7357934cb3c591cbe83c1a2feef3b52e60e0c0d6"
2654+ },
2655+ {
2656+ "seed": "sample/384",
2657+ "family": "machines",
2658+ "sha256": "1b415b2a6db8b3883352a0ae0bfb07a54214d6eb1f189a2924a91129426033cb"
2659+ },
2660+ {
2661+ "seed": "sample/385",
2662+ "family": "orbital",
2663+ "sha256": "9536bbc19c29c0951457081b29b02d02b8e5f5fd7e7a7705e7e29b6fce8b69ff"
2664+ },
2665+ {
2666+ "seed": "sample/386",
2667+ "family": "machines",
2668+ "sha256": "e12dd5747f6a24b0c175a90edc151157395478a967cce3683ac35c8cdfd32fdd"
2669+ },
2670+ {
2671+ "seed": "sample/387",
2672+ "family": "orbital",
2673+ "sha256": "713d354413f2b264d0725b3d4536b6fce3d669bfdce54b051b977d08257b74ed"
2674+ },
2675+ {
2676+ "seed": "sample/388",
2677+ "family": "glyphs",
2678+ "sha256": "fc63885c70a97b8f1f267b2faedf881ef3cc3de9e1b9c0c03618eeafb1c44587"
2679+ },
2680+ {
2681+ "seed": "sample/389",
2682+ "family": "creatures",
2683+ "sha256": "2d98c37ec5fcfd7edd5a53a18ac52229046479c629a5ae5586131dd2733c5447"
2684+ },
2685+ {
2686+ "seed": "sample/390",
2687+ "family": "machines",
2688+ "sha256": "24c0bb7258a7ec176fc667204a7727ad849b5088e57f44f16bf5f14181a306a1"
2689+ },
2690+ {
2691+ "seed": "sample/391",
2692+ "family": "masks",
2693+ "sha256": "d58cd087b7fde2b5cea8b944487ee432e37f19733d557b6e97b1e5e9d0fb1106"
2694+ },
2695+ {
2696+ "seed": "sample/392",
2697+ "family": "machines",
2698+ "sha256": "3d83e84cd3ae99b609af767a485023d538dd89637f9771103083d9749bf845bf"
2699+ },
2700+ {
2701+ "seed": "sample/393",
2702+ "family": "glyphs",
2703+ "sha256": "1fad412500597cc29c58f13a0a8963723ea1f32742335477429a7ec76b0ccc12"
2704+ },
2705+ {
2706+ "seed": "sample/394",
2707+ "family": "landscapes",
2708+ "sha256": "bfa830602aae3c76506f359782bf4cc523f635ffe66bc2ea4f1f2e66e64d91ce"
2709+ },
2710+ {
2711+ "seed": "sample/395",
2712+ "family": "machines",
2713+ "sha256": "10e8c712dea997037ce00036f0b16284e0d6b1a6fc45ec53e1705ff542e063c8"
2714+ },
2715+ {
2716+ "seed": "sample/396",
2717+ "family": "masks",
2718+ "sha256": "e9728193a3dbb1d3c1211f1ff03b016b7b3d1c0c07151db62b9984678ce1eed7"
2719+ },
2720+ {
2721+ "seed": "sample/397",
2722+ "family": "machines",
2723+ "sha256": "461faa9be17f459899b9dc4c8f218f51e11713a911bcd02f2b6bb2eac9d2db2c"
2724+ },
2725+ {
2726+ "seed": "sample/398",
2727+ "family": "machines",
2728+ "sha256": "84ae00ce18559dec8a1c02cf93566c13d4f1627330c6184da717ec62600d524a"
2729+ },
2730+ {
2731+ "seed": "sample/399",
2732+ "family": "creatures",
2733+ "sha256": "233e1682bc9388f25ecbe4be156acbf7b56e5f2d7ba6b6deb2b8829fe7a79e57"
2734+ },
2735+ {
2736+ "seed": "sample/400",
2737+ "family": "machines",
2738+ "sha256": "b3921068084ebac7ab1864186b6470e0be8ca540f5454720b2144c979df61954"
2739+ },
2740+ {
2741+ "seed": "sample/401",
2742+ "family": "glyphs",
2743+ "sha256": "5b0df6f62069536f6160d3525db78f95c1527f045ceb90a5701851e4cf5493f4"
2744+ },
2745+ {
2746+ "seed": "sample/402",
2747+ "family": "machines",
2748+ "sha256": "8ae81a2fc5ede16a2437940226a46685be50338337b82d80312e3352a261448d"
2749+ },
2750+ {
2751+ "seed": "sample/403",
2752+ "family": "glyphs",
2753+ "sha256": "a296c0a542254207a45667d60820fefdb971cf5b8ac3f5afa4efd0175531c5e1"
2754+ },
2755+ {
2756+ "seed": "sample/404",
2757+ "family": "woven",
2758+ "sha256": "dc6757d9358c5d321702269f0aee73910ae80bbaa3da3c0e1a099f91b3b96247"
2759+ },
2760+ {
2761+ "seed": "sample/405",
2762+ "family": "landscapes",
2763+ "sha256": "8af9afed6623253cde9c6e58377fc3395a926e56254c2ce1c776485d0bf73fd1"
2764+ },
2765+ {
2766+ "seed": "sample/406",
2767+ "family": "creatures",
2768+ "sha256": "78f775d7f38deb68e122592123a6fbcbd6fdc86f79e0c908647315ab3a42f322"
2769+ },
2770+ {
2771+ "seed": "sample/407",
2772+ "family": "creatures",
2773+ "sha256": "3090d757edefe05b6af419e3df731f72ac40b516280d662955903e1afbfc24ca"
2774+ },
2775+ {
2776+ "seed": "sample/408",
2777+ "family": "creatures",
2778+ "sha256": "1dc06a17548a8b4c1b825a78770713cddff0182148b2e91b13c34c3b2f82d55e"
2779+ },
2780+ {
2781+ "seed": "sample/409",
2782+ "family": "woven",
2783+ "sha256": "0213a00b44b3d85c389f1d871fb3f1490b0bee5975337e0f19a9d6d4dc4028b2"
2784+ },
2785+ {
2786+ "seed": "sample/410",
2787+ "family": "creatures",
2788+ "sha256": "a4a21c5de88f6e0b4f1ef25801d7c728592c790c5f8c7cc664703200b4dbecad"
2789+ },
2790+ {
2791+ "seed": "sample/411",
2792+ "family": "masks",
2793+ "sha256": "0bdf88195e80738db23cd1d1aeb7393910820c7526fbaaa574d37c996a877eac"
2794+ },
2795+ {
2796+ "seed": "sample/412",
2797+ "family": "landscapes",
2798+ "sha256": "18698d9708f8f63503fd9da412a9f995bb1058317750da2bb32387c5eca66301"
2799+ },
2800+ {
2801+ "seed": "sample/413",
2802+ "family": "machines",
2803+ "sha256": "dcd1789e739b9aa1ae9772c5e7c7cbddbd8436a6b25f56e8ae30e71dd08be761"
2804+ },
2805+ {
2806+ "seed": "sample/414",
2807+ "family": "botanical",
2808+ "sha256": "09be9aca2970b4b03193ee61a4a18e867df250ad173ae75e3d24b203aa54680d"
2809+ },
2810+ {
2811+ "seed": "sample/415",
2812+ "family": "orbital",
2813+ "sha256": "07b207ff47395c40eea2a1ac8105c8e469db6d9195e07aa00333fb9ad8f04b92"
2814+ },
2815+ {
2816+ "seed": "sample/416",
2817+ "family": "machines",
2818+ "sha256": "b12a13e35e71de4a16c14fd4213004e91cb997ac0906a5f0bb23bc0344cf4232"
2819+ },
2820+ {
2821+ "seed": "sample/417",
2822+ "family": "creatures",
2823+ "sha256": "333a3ae7555aba45e251219850884a356a583cfeac9c0ed5acd5b4313447dced"
2824+ },
2825+ {
2826+ "seed": "sample/418",
2827+ "family": "woven",
2828+ "sha256": "cd4c9dbee4656a856e35951f5ce07e123334c9e11a3c57906b99cc06b956d454"
2829+ },
2830+ {
2831+ "seed": "sample/419",
2832+ "family": "machines",
2833+ "sha256": "3d698e49bfed25a628416cc27243097f2719669785ec07d4fb8ee579ecb758d8"
2834+ },
2835+ {
2836+ "seed": "sample/420",
2837+ "family": "glyphs",
2838+ "sha256": "a2785df8a6f572786d59862832e345823a33476ed6cef98c32ec5dea081b2cfd"
2839+ },
2840+ {
2841+ "seed": "sample/421",
2842+ "family": "machines",
2843+ "sha256": "00fcd336020675a1d4c9109f659582142ca1e2813468274c7cbd949c30e4bfe9"
2844+ },
2845+ {
2846+ "seed": "sample/422",
2847+ "family": "botanical",
2848+ "sha256": "d478ac7e4338cbda5e6efc6bf21bff788ca56a10763831fbc503536c4808a6fe"
2849+ },
2850+ {
2851+ "seed": "sample/423",
2852+ "family": "glyphs",
2853+ "sha256": "fd6a7af6d8d4ad9811f44f569f5d1fbef4ee441c9c08f5f658361ba5f2211f4a"
2854+ },
2855+ {
2856+ "seed": "sample/424",
2857+ "family": "machines",
2858+ "sha256": "261448e7e9e781ed09511521da41eb727ce68ac4141c0dc9a3b0cebd2b370bd7"
2859+ },
2860+ {
2861+ "seed": "sample/425",
2862+ "family": "botanical",
2863+ "sha256": "71178affcceef3155645037360d4d50a24535d482d6463636f1c8fcad965401f"
2864+ },
2865+ {
2866+ "seed": "sample/426",
2867+ "family": "woven",
2868+ "sha256": "7c992c10b38439a5fda4e0546a9201957890b2d4e4825746367489096d6bf4cb"
2869+ },
2870+ {
2871+ "seed": "sample/427",
2872+ "family": "machines",
2873+ "sha256": "219cb7d3c337ee1085853ae3e51dfbb1eace354874c7ddae2c2c03afde858923"
2874+ },
2875+ {
2876+ "seed": "sample/428",
2877+ "family": "glyphs",
2878+ "sha256": "62e07e913ef987216822332ee973f7765243cf0e4c226fdc16d6ef9ce015e59c"
2879+ },
2880+ {
2881+ "seed": "sample/429",
2882+ "family": "glyphs",
2883+ "sha256": "7749bafcb53243ec35af733a36cdb2d884897f470c549f33e8fc9029c41c7740"
2884+ },
2885+ {
2886+ "seed": "sample/430",
2887+ "family": "masks",
2888+ "sha256": "e864f456211b84c1336b0040765ba938972804a24efc602cf9688923f247de84"
2889+ },
2890+ {
2891+ "seed": "sample/431",
2892+ "family": "woven",
2893+ "sha256": "4e925f4fefe199f618c8c068d01114c9d80f0744be066884cf9f30637ca05088"
2894+ },
2895+ {
2896+ "seed": "sample/432",
2897+ "family": "orbital",
2898+ "sha256": "3a2f15eeb7fb87f3a2288725a61ad16ef551d934e814bf7c135863f5151f6905"
2899+ },
2900+ {
2901+ "seed": "sample/433",
2902+ "family": "orbital",
2903+ "sha256": "7950e99e6658ab8e6bb49a20a3d666bb670ff03bea50fba736ea067d8f32ee22"
2904+ },
2905+ {
2906+ "seed": "sample/434",
2907+ "family": "creatures",
2908+ "sha256": "ecfdde445e9968f2b1ebcdc83f362bd120b3ce7be91fe3a7a32827beb7a66e81"
2909+ },
2910+ {
2911+ "seed": "sample/435",
2912+ "family": "creatures",
2913+ "sha256": "9cf47ddd540cf15f8766575f62cf6fe0e535df9c6b398f66cd6373d45cdc2f9a"
2914+ },
2915+ {
2916+ "seed": "sample/436",
2917+ "family": "woven",
2918+ "sha256": "ffefbe30c27fb23f5ce875441f5a351ae87a55bb8f46483e7001bc7874d3e387"
2919+ },
2920+ {
2921+ "seed": "sample/437",
2922+ "family": "glyphs",
2923+ "sha256": "658d939740fdaf56882d65ac87a31da784046a8d8793964d043538a935c3c5d4"
2924+ },
2925+ {
2926+ "seed": "sample/438",
2927+ "family": "creatures",
2928+ "sha256": "c5f9c1116d1607fc2957d4afa406020cfe7d54b351a7b96e9d1d89cd1060f48c"
2929+ },
2930+ {
2931+ "seed": "sample/439",
2932+ "family": "creatures",
2933+ "sha256": "b4167bbecc660070eaa06d8a065f6c3a1973ec26ba427083b1c48c77450c0bb0"
2934+ },
2935+ {
2936+ "seed": "sample/440",
2937+ "family": "creatures",
2938+ "sha256": "4629ec2ba0cc5d0716059c6f3952ffe6a24195b01877825785633b36a3bb20c5"
2939+ },
2940+ {
2941+ "seed": "sample/441",
2942+ "family": "woven",
2943+ "sha256": "9724d2a42b14bfee1999a6c558ae3c73fec0a5c742885a07a7c4df1d2e12b781"
2944+ },
2945+ {
2946+ "seed": "sample/442",
2947+ "family": "glyphs",
2948+ "sha256": "491bd4832107285feed5aa45efe079c9c7a675a3e15804cb0b97cadc55e27bbe"
2949+ },
2950+ {
2951+ "seed": "sample/443",
2952+ "family": "machines",
2953+ "sha256": "c648bb2566f99bc2e617a202132ce9f5a79c000518573d2b10ad5f7511d861e7"
2954+ },
2955+ {
2956+ "seed": "sample/444",
2957+ "family": "masks",
2958+ "sha256": "70e970d07f69ece20a17ed703238cb5f9a3bd576dad6362f0ac7cec5ac0e00ef"
2959+ },
2960+ {
2961+ "seed": "sample/445",
2962+ "family": "orbital",
2963+ "sha256": "c45c8169b5cfc17a713c6727867a3ec2cf2e851ed94ad2d57c3511fcbc7c6068"
2964+ },
2965+ {
2966+ "seed": "sample/446",
2967+ "family": "masks",
2968+ "sha256": "a188d34b8251f7951db87bbc2653ff154115b02fd5ac86ba6e3c0d251bd2369b"
2969+ },
2970+ {
2971+ "seed": "sample/447",
2972+ "family": "orbital",
2973+ "sha256": "045469e7b44c573f10eb851d370b0629dab1be166e1a1acf156ad77b369cf8bf"
2974+ },
2975+ {
2976+ "seed": "sample/448",
2977+ "family": "woven",
2978+ "sha256": "618bd0d9f89f4558b69d3ab294769689a382a06c901aef2b1b8c592c373935fc"
2979+ },
2980+ {
2981+ "seed": "sample/449",
2982+ "family": "glyphs",
2983+ "sha256": "4b4260f5fdaf2c554c2ee5153ea1c1e1a90ffb81ebc6fdbdb9b16a1810acbf79"
2984+ },
2985+ {
2986+ "seed": "sample/450",
2987+ "family": "landscapes",
2988+ "sha256": "a5ce00f63692d7a89ba774b1ec95d5776742ef971bf9c633867703b3e46cc99e"
2989+ },
2990+ {
2991+ "seed": "sample/451",
2992+ "family": "masks",
2993+ "sha256": "08483129874b8c3008ac8e61edb009a7f825d34a7adb7bdc68835161b9c843f3"
2994+ },
2995+ {
2996+ "seed": "sample/452",
2997+ "family": "creatures",
2998+ "sha256": "94897c5ebdcabb30e7a20af650b845c505665a488bacf2e0149ae854f993b6d9"
2999+ },
3000+ {
3001+ "seed": "sample/453",
3002+ "family": "glyphs",
3003+ "sha256": "22649352b24c774abbbe1d3ee3db7c2758b2a8cb573ff21c27e262b79f3b5bb7"
3004+ },
3005+ {
3006+ "seed": "sample/454",
3007+ "family": "masks",
3008+ "sha256": "dadfc85ea8ca6c469200bbe510d97d55c6e1b30a05109077b72abf81dc37f45e"
3009+ },
3010+ {
3011+ "seed": "sample/455",
3012+ "family": "masks",
3013+ "sha256": "9fd2465bf1cd4dc0fff538021a3a01ad155ff57614c64b66913cd6623c7e2261"
3014+ },
3015+ {
3016+ "seed": "sample/456",
3017+ "family": "woven",
3018+ "sha256": "4e57ec8783bbd3434c44ec5a5a302b9d3b246af62ae7077c40fe86c7a898ddd3"
3019+ },
3020+ {
3021+ "seed": "sample/457",
3022+ "family": "orbital",
3023+ "sha256": "3adfd2c9b76e31ff00c9aa5c53a02393d50832c1d10248b20a2d6acd76c8f409"
3024+ },
3025+ {
3026+ "seed": "sample/458",
3027+ "family": "masks",
3028+ "sha256": "dcf690f67417cf31b9f7ed5a2d1cfd92569ef28fb8137a72ad9e6ef957839349"
3029+ },
3030+ {
3031+ "seed": "sample/459",
3032+ "family": "landscapes",
3033+ "sha256": "89c81b253854409ba65f96834e3ca46afd3de025946e989e6b9c9317365bf4e2"
3034+ },
3035+ {
3036+ "seed": "sample/460",
3037+ "family": "orbital",
3038+ "sha256": "70ecff7d5592bc89e657abf5d373fdffa52f9f3f2c7d83fd2c16e6d440049569"
3039+ },
3040+ {
3041+ "seed": "sample/461",
3042+ "family": "botanical",
3043+ "sha256": "4a0b35f8aff7606ea24afa1ca54b18f1bb843c14f812a14635ac48f5a1af3487"
3044+ },
3045+ {
3046+ "seed": "sample/462",
3047+ "family": "machines",
3048+ "sha256": "3010430393de25939225746e82684a545ed6091488d5733fec36b87ced7ef96a"
3049+ },
3050+ {
3051+ "seed": "sample/463",
3052+ "family": "woven",
3053+ "sha256": "de7f15d7a69cae9ba64951c6d36af79f305b0b8cbe9529956cf82d6f33285b00"
3054+ },
3055+ {
3056+ "seed": "sample/464",
3057+ "family": "woven",
3058+ "sha256": "03e11b38db2181ed26b3d9c5863fa4d14cbaaa47f95bc4cb5909f7ec24dd8c83"
3059+ },
3060+ {
3061+ "seed": "sample/465",
3062+ "family": "orbital",
3063+ "sha256": "85de34968e94cb69c9d8c8a3c164afa1d12f31182e0507f781a4190be5d6e907"
3064+ },
3065+ {
3066+ "seed": "sample/466",
3067+ "family": "glyphs",
3068+ "sha256": "80605b58420078e4a60596e4b74f1b17edb6719de671943408af0b028bee8c30"
3069+ },
3070+ {
3071+ "seed": "sample/467",
3072+ "family": "creatures",
3073+ "sha256": "1db7080c2a6d7c07c87efcd1570d93224363bc7d9e7b0d0b3a649200c324c4fd"
3074+ },
3075+ {
3076+ "seed": "sample/468",
3077+ "family": "masks",
3078+ "sha256": "12933976822f6e184a9a06486a9da1b318d4b128468706e419297f01c2306495"
3079+ },
3080+ {
3081+ "seed": "sample/469",
3082+ "family": "machines",
3083+ "sha256": "5e43b5fe4cb2e70fc26b219f5d479925fac3b213bed51fff25c5ed7a35542689"
3084+ },
3085+ {
3086+ "seed": "sample/470",
3087+ "family": "botanical",
3088+ "sha256": "3572709ba57f1db1683362ac55dce216cd2f1db78679c73dda090def53735adf"
3089+ },
3090+ {
3091+ "seed": "sample/471",
3092+ "family": "masks",
3093+ "sha256": "aa635f70036b0aebec379bd8026de7497a82c7d90fade10a9159f0d9151913f7"
3094+ },
3095+ {
3096+ "seed": "sample/472",
3097+ "family": "glyphs",
3098+ "sha256": "45e528ec2da8e09d1f86e5a4ef2a72c93f288579320bb20bab38380f82e70ac6"
3099+ },
3100+ {
3101+ "seed": "sample/473",
3102+ "family": "creatures",
3103+ "sha256": "c17c3b4750e14b2627a93cfb6cecec5cc5bbcef238e7a26ef3c2295b6de7d3e1"
3104+ },
3105+ {
3106+ "seed": "sample/474",
3107+ "family": "masks",
3108+ "sha256": "d192f82231f4a1d5687f046daf58d1d61b3608ed6769c137f3d13542a5c0b7e7"
3109+ },
3110+ {
3111+ "seed": "sample/475",
3112+ "family": "landscapes",
3113+ "sha256": "c4cee12e0cac6446c8f7c4f1b2588f425ef9202b81fb58a4a76724cbba8a3478"
3114+ },
3115+ {
3116+ "seed": "sample/476",
3117+ "family": "botanical",
3118+ "sha256": "62393ad3591ff060d6aafca4ebe51e6203b1e1f8aeca4d88580d30d3bfaa2276"
3119+ },
3120+ {
3121+ "seed": "sample/477",
3122+ "family": "machines",
3123+ "sha256": "2dc40f2a406e1589d63923a4a1c099024b4e2ed31bbb24a2abc06c3d731be743"
3124+ },
3125+ {
3126+ "seed": "sample/478",
3127+ "family": "botanical",
3128+ "sha256": "561eef1c603762f16fdcfe208221323937708ff94581a37812e55130af07a404"
3129+ },
3130+ {
3131+ "seed": "sample/479",
3132+ "family": "machines",
3133+ "sha256": "57a3b822744fcd4b1f3a64aec839daef8c44fa904ff4d1590549e1fdcb5d3b57"
3134+ },
3135+ {
3136+ "seed": "sample/480",
3137+ "family": "landscapes",
3138+ "sha256": "e6ef941a1482cbfa7d8e7d4c6d6a7f501b8277bd112a3135246ac334da4c3a69"
3139+ },
3140+ {
3141+ "seed": "sample/481",
3142+ "family": "machines",
3143+ "sha256": "33d08a736b75a3fd64d3bb2a6bcd14e2a1df1008830231d559b1039c77b7f06d"
3144+ },
3145+ {
3146+ "seed": "sample/482",
3147+ "family": "masks",
3148+ "sha256": "fe5b3222ac56035171b9e563075b4c5755f781c572ec131759c3c038c87ab75f"
3149+ },
3150+ {
3151+ "seed": "sample/483",
3152+ "family": "creatures",
3153+ "sha256": "2ce07685d2d23efc5e0ca44eda42cc6a01440bb731b0b3170c6228f564d2f119"
3154+ },
3155+ {
3156+ "seed": "sample/484",
3157+ "family": "masks",
3158+ "sha256": "1531279e1fd679c82ed64974eb043f546380698b1f3b93ef88ed6394cc8aa8fd"
3159+ },
3160+ {
3161+ "seed": "sample/485",
3162+ "family": "woven",
3163+ "sha256": "af0f8a9d3119395d35b0aa07f9459fb080bb5b5c68e14e8ed1df0c4e6f5e47c7"
3164+ },
3165+ {
3166+ "seed": "sample/486",
3167+ "family": "woven",
3168+ "sha256": "f38a460844364912d63001e8ec46ce789e96be5d630b4a2f7594a5179a31e0fb"
3169+ },
3170+ {
3171+ "seed": "sample/487",
3172+ "family": "creatures",
3173+ "sha256": "ad1b994a985f1d86a82bfb2ac18b4248c944fa725ba1d17140c75eec75aa569b"
3174+ },
3175+ {
3176+ "seed": "sample/488",
3177+ "family": "creatures",
3178+ "sha256": "85c0ab9b6f57a2d3bcc87e085907e3f6da7044098bca67a6fbb0c675eab48cf3"
3179+ },
3180+ {
3181+ "seed": "sample/489",
3182+ "family": "orbital",
3183+ "sha256": "04b3f5192b245367bf2b3189105d4d85a002df60487bf736ae979ebc160c0086"
3184+ },
3185+ {
3186+ "seed": "sample/490",
3187+ "family": "machines",
3188+ "sha256": "8d042d37129a5d4f64c020aa6b2403f6b23df50a4baa1a03a8d44654645bb093"
3189+ },
3190+ {
3191+ "seed": "sample/491",
3192+ "family": "woven",
3193+ "sha256": "411920cdbf139126a29fe919463d8dad1c95139286e6208778dd69b114c753b0"
3194+ },
3195+ {
3196+ "seed": "sample/492",
3197+ "family": "landscapes",
3198+ "sha256": "ef4b48a5f4c15b46e6e50577693f2a80dc1886a51f065aafaa129e5450f32cf0"
3199+ },
3200+ {
3201+ "seed": "sample/493",
3202+ "family": "woven",
3203+ "sha256": "9444f99a10ee66a977084bc7ce357b6e001761605868fe85e788f31ab876e279"
3204+ },
3205+ {
3206+ "seed": "sample/494",
3207+ "family": "masks",
3208+ "sha256": "8f88901ba302799620dc80b87b934e3cd0440fb334ca80589a203a4eb23fd124"
3209+ },
3210+ {
3211+ "seed": "sample/495",
3212+ "family": "landscapes",
3213+ "sha256": "3b1f129d55c710ccc5e2f6b24d46aa29a74830c84624059e7eb8808f3d4491a6"
3214+ },
3215+ {
3216+ "seed": "sample/496",
3217+ "family": "landscapes",
3218+ "sha256": "f56d52a26f12a38e09dc96f3d2b46ee40b970a68ae88d052c7fbbdd32bbe1ebd"
3219+ },
3220+ {
3221+ "seed": "sample/497",
3222+ "family": "orbital",
3223+ "sha256": "0c7745f1295ad996add5cb1b215215958809a7542a647ee61cf486843c7c5ee5"
3224+ },
3225+ {
3226+ "seed": "sample/498",
3227+ "family": "botanical",
3228+ "sha256": "3e1bd3938f12e2b225dbb57f3a8a63372100779f7ff3479d7692f3abe74b623c"
3229+ },
3230+ {
3231+ "seed": "sample/499",
3232+ "family": "masks",
3233+ "sha256": "da35ba4b35c5fa032f050872c070ea71566aa401e708f9acaada13164206a294"
3234+ },
3235+ {
3236+ "seed": "sample/500",
3237+ "family": "woven",
3238+ "sha256": "9daf25fab9c30917652a4872afc8ff6ca5355c788540c87807aebc07f06884d9"
3239+ },
3240+ {
3241+ "seed": "sample/501",
3242+ "family": "glyphs",
3243+ "sha256": "c30db93cac8569f88ecc2aaa299c5c520614d39b70e01f37bd5e72530f680b68"
3244+ },
3245+ {
3246+ "seed": "sample/502",
3247+ "family": "botanical",
3248+ "sha256": "e7a53b3ebe126a4f289f3a66f98a5d466af71f2046144e5b52cdf30ed915b3a4"
3249+ },
3250+ {
3251+ "seed": "sample/503",
3252+ "family": "landscapes",
3253+ "sha256": "c5d67fb20b889e4c80cfec004b20ca6e3028f3245e8a5653bf3514da874334bc"
3254+ },
3255+ {
3256+ "seed": "sample/504",
3257+ "family": "machines",
3258+ "sha256": "b360529a914df3e1663bdce16f4e4bdf7f31d9ff14524f47cc908eea9ed99526"
3259+ },
3260+ {
3261+ "seed": "sample/505",
3262+ "family": "orbital",
3263+ "sha256": "65a5fe457b436df1fdc5aa3b4fccb78445ca0c092fb00b44687b6614df9144ff"
3264+ },
3265+ {
3266+ "seed": "sample/506",
3267+ "family": "glyphs",
3268+ "sha256": "807a2dbdf9e6ca7bca1332e9153d105113ca9ea0cf40b6720ee4774a64486edd"
3269+ },
3270+ {
3271+ "seed": "sample/507",
3272+ "family": "masks",
3273+ "sha256": "7ed207e49a8413ceeb2faf7405f5eb4c9169b9b037669e755ed6d992e79cd9b5"
3274+ },
3275+ {
3276+ "seed": "sample/508",
3277+ "family": "creatures",
3278+ "sha256": "1797f8ad8e784b16e78cdc24c2eb2f3b6451c84107cbf6b948ba151e30cdef05"
3279+ },
3280+ {
3281+ "seed": "sample/509",
3282+ "family": "orbital",
3283+ "sha256": "8b9ea8b74272f9bf84dd6e1d8a45af7833ca250fd38d6d41e8f44a396bd273ef"
3284+ },
3285+ {
3286+ "seed": "sample/510",
3287+ "family": "botanical",
3288+ "sha256": "9c0bd9a4f914d6b795fea46436563d4a56507b6d05595699561a285a9e4078a0"
3289+ },
3290+ {
3291+ "seed": "sample/511",
3292+ "family": "glyphs",
3293+ "sha256": "cafd8280e234ff833a612d6c932fec4e5699023f0ed27bdaadf1ba099e7d3cfc"
3294+ },
3295+ {
3296+ "seed": "sample/512",
3297+ "family": "machines",
3298+ "sha256": "65d89391f30cdf37796b870475ed2bf9ab14ee7124b86f1e7bd599d6795d74f0"
3299+ },
3300+ {
3301+ "seed": "sample/513",
3302+ "family": "masks",
3303+ "sha256": "be14b6ffdd6cd47ede9b98b0bc15a8e5782addb9b35e5c3299b0ed2dbbed0c5e"
3304+ },
3305+ {
3306+ "seed": "sample/514",
3307+ "family": "machines",
3308+ "sha256": "7371bdd5a27b082fceb8a6ff036d5ec620642190fc04709fd975a8ce34dc4eb1"
3309+ },
3310+ {
3311+ "seed": "sample/515",
3312+ "family": "orbital",
3313+ "sha256": "a97dc9a09865ce3a1b8db4f2df87c2e7ebac4dd520a4c6badbcb1045dccfcf20"
3314+ },
3315+ {
3316+ "seed": "sample/516",
3317+ "family": "masks",
3318+ "sha256": "b0f711220d323f51023d70990071a9c6933a659f553d096d0c58bf310be35959"
3319+ },
3320+ {
3321+ "seed": "sample/517",
3322+ "family": "masks",
3323+ "sha256": "6231e2346a5dc1d3cb1ff03a33e4efd913e640cd56959e0420a643700975aec8"
3324+ },
3325+ {
3326+ "seed": "sample/518",
3327+ "family": "woven",
3328+ "sha256": "8eb795d0cfb0b44d5f75926290ca343323a197a9776349cf8d05ba35a22d69c9"
3329+ },
3330+ {
3331+ "seed": "sample/519",
3332+ "family": "glyphs",
3333+ "sha256": "80250713480385f6aff70a252ceb2a08d03317b48fb5ae2d8f4377519956b844"
3334+ },
3335+ {
3336+ "seed": "sample/520",
3337+ "family": "glyphs",
3338+ "sha256": "b261f431b5d2f2a09875380c2d23117e3433e37a21ca6e1dc73cde51afb1d34d"
3339+ },
3340+ {
3341+ "seed": "sample/521",
3342+ "family": "botanical",
3343+ "sha256": "5092ecf3b26533f126ae1ef3a946b2c38a47dbe4e7d650af60464b4e7361e9ba"
3344+ },
3345+ {
3346+ "seed": "sample/522",
3347+ "family": "orbital",
3348+ "sha256": "3a8929b0217b4947920c6a6cfcc49010cae9edce2d0d8193825bf872126db775"
3349+ },
3350+ {
3351+ "seed": "sample/523",
3352+ "family": "woven",
3353+ "sha256": "82c42cf3ff27afe1b66beee048671a2a1636046882c668a63ef6440984a2473e"
3354+ },
3355+ {
3356+ "seed": "sample/524",
3357+ "family": "botanical",
3358+ "sha256": "764cc89a523ba9c41933231c6f0a9d5e60d887b3544d19d435cae47d6ff37655"
3359+ },
3360+ {
3361+ "seed": "sample/525",
3362+ "family": "creatures",
3363+ "sha256": "44b99c0ff5abcdeb5ce0593e8976a64c526cca7485c41e23ffc55ced725b91b6"
3364+ },
3365+ {
3366+ "seed": "sample/526",
3367+ "family": "machines",
3368+ "sha256": "67e7f261dba543fab053ead76b3e2ce2b636b5c21da8e2e0c81b86a5296a1089"
3369+ },
3370+ {
3371+ "seed": "sample/527",
3372+ "family": "machines",
3373+ "sha256": "252ae78445c5b79ef03015b51602934cad239b8b0a1bb86d22b800d00b7f49bf"
3374+ },
3375+ {
3376+ "seed": "sample/528",
3377+ "family": "masks",
3378+ "sha256": "bc592373f97593cf997524bb61d1fadc45a5c027616a47e64e3a59742f67223f"
3379+ },
3380+ {
3381+ "seed": "sample/529",
3382+ "family": "masks",
3383+ "sha256": "ad5d3375b22f2ebe64535e0893479408b0f519ff0c0a77e2e1e8b1dac557846f"
3384+ },
3385+ {
3386+ "seed": "sample/530",
3387+ "family": "masks",
3388+ "sha256": "3bcc5c84bd5161905dc3c931557d349b5b216224e43e0eb1eceb070aad50b841"
3389+ },
3390+ {
3391+ "seed": "sample/531",
3392+ "family": "landscapes",
3393+ "sha256": "853387fe6633e2275bc181429dfc637d1cb6f08dde007cd09a63b62da3e94934"
3394+ },
3395+ {
3396+ "seed": "sample/532",
3397+ "family": "machines",
3398+ "sha256": "1a635606b4bd55b22d7b86b5c62ece5d9d7b7b1678cb38de765bda80192fa513"
3399+ },
3400+ {
3401+ "seed": "sample/533",
3402+ "family": "orbital",
3403+ "sha256": "dcf4c58bc6e8d1a930ca047dc233ec40627901d37eb993b50b636e788b108e19"
3404+ },
3405+ {
3406+ "seed": "sample/534",
3407+ "family": "creatures",
3408+ "sha256": "95b316f729d1392edd19cee3ddb8b2c5c26c079645a3d314141dac45077f7c54"
3409+ },
3410+ {
3411+ "seed": "sample/535",
3412+ "family": "masks",
3413+ "sha256": "8beb37722a38b9558b2e9b9523231d07ad6a1b015bcd8953aea18b45dcdc7b2f"
3414+ },
3415+ {
3416+ "seed": "sample/536",
3417+ "family": "woven",
3418+ "sha256": "ba82c20346d49ace1306ea705b5972e0f162a5804aac4d177a3310e0b5155427"
3419+ },
3420+ {
3421+ "seed": "sample/537",
3422+ "family": "woven",
3423+ "sha256": "4bdbc35493551c1d597de1a7f360846ce89ee92b6d80f6c3bb6ceb7bca3458db"
3424+ },
3425+ {
3426+ "seed": "sample/538",
3427+ "family": "glyphs",
3428+ "sha256": "6303ebd983c5c8b71551a0ac8d99ccc6e1b49c8b2a01b225fbfeedffe58b0fb9"
3429+ },
3430+ {
3431+ "seed": "sample/539",
3432+ "family": "machines",
3433+ "sha256": "2ce174b4f75b9cadf4f7ba1f6388339efdf750c917c9f940fbe37b66499fdcf9"
3434+ },
3435+ {
3436+ "seed": "sample/540",
3437+ "family": "glyphs",
3438+ "sha256": "dbcd0fb5f2973bfebc834ece42c19dcd2f0fdbdf450fc4abc68d07c6dde91a7b"
3439+ },
3440+ {
3441+ "seed": "sample/541",
3442+ "family": "landscapes",
3443+ "sha256": "395cec829a3129f42aec2a2ac50706565b7154e70f16bf054f3a2bef245e7e8d"
3444+ },
3445+ {
3446+ "seed": "sample/542",
3447+ "family": "machines",
3448+ "sha256": "fba7cf34ebdb580604d11828ae140d28a14a5c0ab25e5e8811e0fcf7219d866e"
3449+ },
3450+ {
3451+ "seed": "sample/543",
3452+ "family": "woven",
3453+ "sha256": "ccff27e0a60ea35ca13c53742d40aefd50e93729c9f7ecf08b70d9d0cec50bdc"
3454+ },
3455+ {
3456+ "seed": "sample/544",
3457+ "family": "botanical",
3458+ "sha256": "55578cfca3297db150c2b601e6bdae30d9935fa1951bf3865cf96e814e9e993d"
3459+ },
3460+ {
3461+ "seed": "sample/545",
3462+ "family": "botanical",
3463+ "sha256": "4e16657d3839c21d9f76fb7b080bab3749341683ba14ed12df3025a87bc8f9ab"
3464+ },
3465+ {
3466+ "seed": "sample/546",
3467+ "family": "machines",
3468+ "sha256": "11f56a59275cf413dae60bd79a30d613df0ad3b8c236996dccb74ec55bd45653"
3469+ },
3470+ {
3471+ "seed": "sample/547",
3472+ "family": "creatures",
3473+ "sha256": "bc0504e1781465c330afc83f72611bcbdafd607a0f266196e55c6ef109324719"
3474+ },
3475+ {
3476+ "seed": "sample/548",
3477+ "family": "glyphs",
3478+ "sha256": "fa9f36d4d61c727beb99cd92fcd79022bd5e25c885c3cf5f65f95c29288cb7f1"
3479+ },
3480+ {
3481+ "seed": "sample/549",
3482+ "family": "landscapes",
3483+ "sha256": "743ac1d443238188d33db09a3a08e76962db62a51bd42c21c76a22a03e0ffd57"
3484+ },
3485+ {
3486+ "seed": "sample/550",
3487+ "family": "creatures",
3488+ "sha256": "dc5a3dd6b9f47ab8d4e81f7e901f102ba9670bfe1b0933f894c2e864efa8da37"
3489+ },
3490+ {
3491+ "seed": "sample/551",
3492+ "family": "masks",
3493+ "sha256": "f3c7eae70cc86ee5c1f1755913d84bb68da43b1bf5f28577443220f1a632d13b"
3494+ },
3495+ {
3496+ "seed": "sample/552",
3497+ "family": "orbital",
3498+ "sha256": "f86f182aec008991549019666afcd0e82d024dfe25388ccb19d068d42b83628e"
3499+ },
3500+ {
3501+ "seed": "sample/553",
3502+ "family": "orbital",
3503+ "sha256": "0cafb1f0b2dd89ef6d8ab0d17e68bf48bd5c5148c4a86fe78a3f27128086b565"
3504+ },
3505+ {
3506+ "seed": "sample/554",
3507+ "family": "woven",
3508+ "sha256": "2f4d42daeb6470bc39189178d395de1c400ae2792768932b3b598981ebad70cd"
3509+ },
3510+ {
3511+ "seed": "sample/555",
3512+ "family": "machines",
3513+ "sha256": "dc0356bd0940dae678db535ff38a10a42b8a788cbad01bd5feac15a1697ec63b"
3514+ },
3515+ {
3516+ "seed": "sample/556",
3517+ "family": "botanical",
3518+ "sha256": "7573cca261d15096424a8bcfca8016c577e8f4a2812be147943ff0bfd6be1466"
3519+ },
3520+ {
3521+ "seed": "sample/557",
3522+ "family": "landscapes",
3523+ "sha256": "cd762519507f60e6af276363f4f5d40290b7530f4b249d62db9b33ab2cc65c0f"
3524+ },
3525+ {
3526+ "seed": "sample/558",
3527+ "family": "woven",
3528+ "sha256": "623c6db20aa108dbb8e470e1ff511f17ef080b16e7e566fc0ab3c80e759265fc"
3529+ },
3530+ {
3531+ "seed": "sample/559",
3532+ "family": "woven",
3533+ "sha256": "780e1bebe2c31c46df89c52aac027c894797cd284e50fe0a00ce5747b97a905b"
3534+ },
3535+ {
3536+ "seed": "sample/560",
3537+ "family": "glyphs",
3538+ "sha256": "23345d30d04ac7b6bd29467aac06d000646e4bbd328c28edfc101f1cbbac6ec4"
3539+ },
3540+ {
3541+ "seed": "sample/561",
3542+ "family": "woven",
3543+ "sha256": "4018ceea49e083b58c227b2deaec447fb8693bbd6533c37bc7e7b63dfe1213f9"
3544+ },
3545+ {
3546+ "seed": "sample/562",
3547+ "family": "woven",
3548+ "sha256": "b105ca78dd206b26e42fb778c811502b408fc917d9768db830d02bd913d425df"
3549+ },
3550+ {
3551+ "seed": "sample/563",
3552+ "family": "landscapes",
3553+ "sha256": "c565d9f32634efa07c64cc9f0eaf8a46d2b0af376664d6d99348640b16e0e5c1"
3554+ },
3555+ {
3556+ "seed": "sample/564",
3557+ "family": "botanical",
3558+ "sha256": "4af76e37bb9363bc315673661bf2d72e8cd28c77b5e18be38ba0087731059cea"
3559+ },
3560+ {
3561+ "seed": "sample/565",
3562+ "family": "masks",
3563+ "sha256": "02dc9cdcce4a1d4c53c7bd71ac4ec170922816845219762e8b6920b5009e1b86"
3564+ },
3565+ {
3566+ "seed": "sample/566",
3567+ "family": "glyphs",
3568+ "sha256": "128c1eb111ff671fc9409bb8776eedea1f6c0864e92b1335d8159842fc3620ce"
3569+ },
3570+ {
3571+ "seed": "sample/567",
3572+ "family": "landscapes",
3573+ "sha256": "423b35cf0678a14ea937b45b22b7e75411d736fd3b299266dcdc1b8b64ee942f"
3574+ },
3575+ {
3576+ "seed": "sample/568",
3577+ "family": "creatures",
3578+ "sha256": "3007f9ef23c9f2654eed19eeeb9af398b5fa20817d044698176686299c85be57"
3579+ },
3580+ {
3581+ "seed": "sample/569",
3582+ "family": "glyphs",
3583+ "sha256": "93c2280fad97567c6b2b9087863e85c1ead23633a069190a98da957bfdde1318"
3584+ },
3585+ {
3586+ "seed": "sample/570",
3587+ "family": "woven",
3588+ "sha256": "242da5ffec852d3e9f7148a4b265ada34972e2f9a5c731cff8a217f57122f465"
3589+ },
3590+ {
3591+ "seed": "sample/571",
3592+ "family": "machines",
3593+ "sha256": "c2d3603b818d78b2a6683e9306a221d32e998165b361dc4774fe20335f5ed4c4"
3594+ },
3595+ {
3596+ "seed": "sample/572",
3597+ "family": "orbital",
3598+ "sha256": "bc16c2847a2637a3e00dbef9c32846dbfb74cf9d690887b72470d982e04c4a03"
3599+ },
3600+ {
3601+ "seed": "sample/573",
3602+ "family": "masks",
3603+ "sha256": "80852e3e517ac520a9290aea020e75fd3b36acc3200ab97b0774591c0b519d8a"
3604+ },
3605+ {
3606+ "seed": "sample/574",
3607+ "family": "masks",
3608+ "sha256": "a12bfb4f097e22b34a6584a03d67d3e985e654c9bf41fdee9f5995a23a226edc"
3609+ },
3610+ {
3611+ "seed": "sample/575",
3612+ "family": "landscapes",
3613+ "sha256": "81f410f74c90b35b6a0539db5b733ad43556489ffae524fbac515d2b00e907b3"
3614+ },
3615+ {
3616+ "seed": "sample/576",
3617+ "family": "woven",
3618+ "sha256": "554e7ea914213c9753f103e97fa328afd42c97859321ec16520985660be5d687"
3619+ },
3620+ {
3621+ "seed": "sample/577",
3622+ "family": "landscapes",
3623+ "sha256": "6a4f955ebd66977f0453f4ee80300389cd11e31b4c59af20349f1d909851d3f5"
3624+ },
3625+ {
3626+ "seed": "sample/578",
3627+ "family": "creatures",
3628+ "sha256": "397d9749f0df004689f0ee2d23179d73bd5825c7390c1524a51a526e48ef5c34"
3629+ },
3630+ {
3631+ "seed": "sample/579",
3632+ "family": "glyphs",
3633+ "sha256": "4d07015e8b5cd4363676895aa229e503259bf9728df6a3c2f8fdf3d4c9815dca"
3634+ },
3635+ {
3636+ "seed": "sample/580",
3637+ "family": "creatures",
3638+ "sha256": "1fd43ef3315e26198f756a043b4d72573a282021d5d864e6cf727c20553dad49"
3639+ },
3640+ {
3641+ "seed": "sample/581",
3642+ "family": "creatures",
3643+ "sha256": "c0efa9eafc155da7b3fe3d2952d691d1b86f79ce29949f05dcb790525f89d7be"
3644+ },
3645+ {
3646+ "seed": "sample/582",
3647+ "family": "machines",
3648+ "sha256": "674cbdbc43a561fb425778dd29909e03db45ecc470366f4cfa3f59d21bea8c44"
3649+ },
3650+ {
3651+ "seed": "sample/583",
3652+ "family": "landscapes",
3653+ "sha256": "87389a83ea52f43da997c2daba4c141877142f5081e7e7fb32698262adbb862d"
3654+ },
3655+ {
3656+ "seed": "sample/584",
3657+ "family": "masks",
3658+ "sha256": "d603ea5d874bce827d9cbfd7d527a18f8778999520596e1189b40cf23b9e6012"
3659+ },
3660+ {
3661+ "seed": "sample/585",
3662+ "family": "creatures",
3663+ "sha256": "1a863f789ad440d892c364bcfbc209c86d0bb16804482d4f2aa2d145d937afaf"
3664+ },
3665+ {
3666+ "seed": "sample/586",
3667+ "family": "orbital",
3668+ "sha256": "439c7757c46cf61fd4ac078963e052ef0d638dedd3d747d80c88cfa111344d23"
3669+ },
3670+ {
3671+ "seed": "sample/587",
3672+ "family": "woven",
3673+ "sha256": "b9e3474b19592f572926614dd7c00296f8dc0f9114d7fd1d17eb25eee1da8a95"
3674+ },
3675+ {
3676+ "seed": "sample/588",
3677+ "family": "machines",
3678+ "sha256": "4a0658790a1ef139b7512cf9c5c5a20663a2120f617cdb7bf52d6438db2eec9d"
3679+ },
3680+ {
3681+ "seed": "sample/589",
3682+ "family": "botanical",
3683+ "sha256": "d6c1b6a49029240dd60de32e435d11bb176483c4cdf8b15c0b7336f01f5340b3"
3684+ },
3685+ {
3686+ "seed": "sample/590",
3687+ "family": "masks",
3688+ "sha256": "0c2528731fe4f31df69e0774cf29e1bb40addd58c047213e43e95382fbf95b47"
3689+ },
3690+ {
3691+ "seed": "sample/591",
3692+ "family": "landscapes",
3693+ "sha256": "e0c157155be2b189353fe18836d6205c2b44b13c363d4cd1d0dd41dcf61eec88"
3694+ },
3695+ {
3696+ "seed": "sample/592",
3697+ "family": "masks",
3698+ "sha256": "6364f7030d3e9c3ad60ef6b0e7940b317aec2c877f29ad5aa0d87dea5c57609e"
3699+ },
3700+ {
3701+ "seed": "sample/593",
3702+ "family": "landscapes",
3703+ "sha256": "b1accbcb96d6658af6a2bea58bba41f312e6d71cfb416368253e53b8ca5822d3"
3704+ },
3705+ {
3706+ "seed": "sample/594",
3707+ "family": "landscapes",
3708+ "sha256": "6dc9d12382c7bd7561983281c298538fbfda77e4c45c38b37a38ce88c9076b72"
3709+ },
3710+ {
3711+ "seed": "sample/595",
3712+ "family": "orbital",
3713+ "sha256": "ab307de523affae830bcc677f61dc805c8dc53ddfa6915373a3fb90f424bbd05"
3714+ },
3715+ {
3716+ "seed": "sample/596",
3717+ "family": "glyphs",
3718+ "sha256": "807704fe9fedd43639d796dea0abba98252bcea7fc6337736b3fc2ea46c96634"
3719+ },
3720+ {
3721+ "seed": "sample/597",
3722+ "family": "masks",
3723+ "sha256": "26c3c0a2e52e5d3327be39906150138d522b6fdc5130ab82ec85059eb842c0b7"
3724+ },
3725+ {
3726+ "seed": "sample/598",
3727+ "family": "landscapes",
3728+ "sha256": "78fcd36e785dcbab46a9eb59fcd2c735840c64d94dfb89f75b5da90f6c114ed4"
3729+ },
3730+ {
3731+ "seed": "sample/599",
3732+ "family": "orbital",
3733+ "sha256": "8c0710d3535d46f5a6afb098e0801460d00105fce7c2152d727920c64e0984d2"
3734+ },
3735+ {
3736+ "seed": "sample/600",
3737+ "family": "orbital",
3738+ "sha256": "087fb91c52251d91723149252052bdddd03b8291f701fc9ab87341ae6d4401b8"
3739+ },
3740+ {
3741+ "seed": "sample/601",
3742+ "family": "masks",
3743+ "sha256": "3001032f429524b9d884405a6389c3a6d27285389b7f542c0098a0b6528fdf98"
3744+ },
3745+ {
3746+ "seed": "sample/602",
3747+ "family": "orbital",
3748+ "sha256": "33a0d416c4c07c562bd3316a14b46b1e4cbd8b08c4b7644a7d995184e78d2dcb"
3749+ },
3750+ {
3751+ "seed": "sample/603",
3752+ "family": "creatures",
3753+ "sha256": "bc513fbbae6292f25813afefcd3b1b15086ad6ecaac883ae5460379e1ba29146"
3754+ },
3755+ {
3756+ "seed": "sample/604",
3757+ "family": "orbital",
3758+ "sha256": "ef8fc4361d258fde7a039eee8f930c73fd1bc7e7ae62b67b2fa19b2a14710894"
3759+ },
3760+ {
3761+ "seed": "sample/605",
3762+ "family": "orbital",
3763+ "sha256": "ea65b2e79469ac554fe8310ab3d41cf6182ba53e0aefe1ef87edc4a06bc231ba"
3764+ },
3765+ {
3766+ "seed": "sample/606",
3767+ "family": "glyphs",
3768+ "sha256": "f933091a645aa81967b5fe0203f21b825f68a88b32293c050d8a31f9c49cf6ed"
3769+ },
3770+ {
3771+ "seed": "sample/607",
3772+ "family": "masks",
3773+ "sha256": "0b5c0e219b5577c761a207cf9d40471b74519169102aa40f12b0a4beac71bcdb"
3774+ },
3775+ {
3776+ "seed": "sample/608",
3777+ "family": "machines",
3778+ "sha256": "d814f43f7aba9e3b927c3d37c8eadf5fdcb7cef197a5a7aec48f99d8fef5349f"
3779+ },
3780+ {
3781+ "seed": "sample/609",
3782+ "family": "woven",
3783+ "sha256": "f74feee4c860dd1b5fc25627e1fa5e7781072ab16e9043321bbe5149e238944d"
3784+ },
3785+ {
3786+ "seed": "sample/610",
3787+ "family": "creatures",
3788+ "sha256": "480dd0097bc4cb218162593bac918ebc53638c2adadb45302016598f279fe1db"
3789+ },
3790+ {
3791+ "seed": "sample/611",
3792+ "family": "landscapes",
3793+ "sha256": "c564cde19afa2a3ba5c6639ca9c6d073963fb0c56a5367a3d9b6fee880ef7cdf"
3794+ },
3795+ {
3796+ "seed": "sample/612",
3797+ "family": "glyphs",
3798+ "sha256": "757b5d686207509b22d5be7c56281bc7da54d3d5cdaeef3db5c77778fd8409c7"
3799+ },
3800+ {
3801+ "seed": "sample/613",
3802+ "family": "landscapes",
3803+ "sha256": "3bbf608fb635dbf94d988aeded25db6d3be8dfd41ee7470e94e1336baaeebdf7"
3804+ },
3805+ {
3806+ "seed": "sample/614",
3807+ "family": "orbital",
3808+ "sha256": "58ec5728c5302a77570a0a6a9effe8f8226202f0b470997a53d647a180842f32"
3809+ },
3810+ {
3811+ "seed": "sample/615",
3812+ "family": "machines",
3813+ "sha256": "54906ca517230cb6d88c0bcd60006909cb3fb22e4632178dfe84ec2ecd01b413"
3814+ },
3815+ {
3816+ "seed": "sample/616",
3817+ "family": "glyphs",
3818+ "sha256": "7326d8ba22078e0ea92d95dceebd3143f63994a91ee48b66690bff8c5756993b"
3819+ },
3820+ {
3821+ "seed": "sample/617",
3822+ "family": "landscapes",
3823+ "sha256": "c9973a190f0a8e4e5fa69d5829f3c7ca55c8820701d1113cb4e9837ad9835fe2"
3824+ },
3825+ {
3826+ "seed": "sample/618",
3827+ "family": "landscapes",
3828+ "sha256": "901ccc97bd21d91736ec460c4f49130b82d99befbaaba95e75e0c8d4b146ba49"
3829+ },
3830+ {
3831+ "seed": "sample/619",
3832+ "family": "orbital",
3833+ "sha256": "1695493fefd2ca394b80a7585d1a02a4d6a889485ee125ed692df939f446f979"
3834+ },
3835+ {
3836+ "seed": "sample/620",
3837+ "family": "machines",
3838+ "sha256": "47c7984271dfde8f037a5d269be4b8f993feef4a746aa0f3b182dc56b46f1b94"
3839+ },
3840+ {
3841+ "seed": "sample/621",
3842+ "family": "masks",
3843+ "sha256": "8db163bbadb0647e4456da41bba2e10a9b08e9b5cab7022f1b727e606bd5e0ad"
3844+ },
3845+ {
3846+ "seed": "sample/622",
3847+ "family": "orbital",
3848+ "sha256": "e38f1835d3bb90c1b1e3b0536277ac591ea37e15ae482d9d6dd7679fe749051b"
3849+ },
3850+ {
3851+ "seed": "sample/623",
3852+ "family": "creatures",
3853+ "sha256": "5bb383f30d7e3852aedd4658072bcd1014ad2df94269200980e8d23f02ab6782"
3854+ },
3855+ {
3856+ "seed": "sample/624",
3857+ "family": "landscapes",
3858+ "sha256": "05c4d1832f25dfa3c3b8256c017e48a18ea0ac9975271ca520756266f19b6a9b"
3859+ },
3860+ {
3861+ "seed": "sample/625",
3862+ "family": "creatures",
3863+ "sha256": "7a69067a16316a903410fba101f8af1730a538becd0076a2c98abc58ff74912b"
3864+ },
3865+ {
3866+ "seed": "sample/626",
3867+ "family": "woven",
3868+ "sha256": "cd8d7ae4a26b737be6389875404bd775ce5c5f7889110a09d59c66d8881a8aed"
3869+ },
3870+ {
3871+ "seed": "sample/627",
3872+ "family": "woven",
3873+ "sha256": "886bfa378e714cd365508aa1ea318e6a2b9a90b99e00016f12d9d07bcc450d45"
3874+ },
3875+ {
3876+ "seed": "sample/628",
3877+ "family": "orbital",
3878+ "sha256": "630dc655c21afae452bf1ea851c823c72d2da168beb0c1a290a494f5cb250ae7"
3879+ },
3880+ {
3881+ "seed": "sample/629",
3882+ "family": "machines",
3883+ "sha256": "b1f78602e2c678e5ffb625bf84905459990276b36d0cda957a2dc8d23a6aba4b"
3884+ },
3885+ {
3886+ "seed": "sample/630",
3887+ "family": "woven",
3888+ "sha256": "8da75573b8cee19904a3523df53b14ecb18fae101bda40073195bb09daa70368"
3889+ },
3890+ {
3891+ "seed": "sample/631",
3892+ "family": "glyphs",
3893+ "sha256": "f344f8fad3a859cc580f069d5a5e1f9c79c21deb44a70c480805e18fa72f8e88"
3894+ },
3895+ {
3896+ "seed": "sample/632",
3897+ "family": "glyphs",
3898+ "sha256": "cbd34d8ef87a040ac984165cf718a1a0402bdb581fd437f4a255eec9b79a5976"
3899+ },
3900+ {
3901+ "seed": "sample/633",
3902+ "family": "machines",
3903+ "sha256": "00977344036e975e7c2a26ed1e024cfe926e83c6dcc6883984d6e42310e57dab"
3904+ },
3905+ {
3906+ "seed": "sample/634",
3907+ "family": "woven",
3908+ "sha256": "ae654263f3db7a53cf6df9e207ce137167506d89f20ff5550eec2f9c32b985ed"
3909+ },
3910+ {
3911+ "seed": "sample/635",
3912+ "family": "woven",
3913+ "sha256": "13d7b9ec9c72dc64760776ece13d893d4ea767feec1d54e29b1d29ae81d955da"
3914+ },
3915+ {
3916+ "seed": "sample/636",
3917+ "family": "orbital",
3918+ "sha256": "468fe462f232cef5543fdbffc29b57b4d4d5e9eb8d56c351ff8918245ccbe1aa"
3919+ },
3920+ {
3921+ "seed": "sample/637",
3922+ "family": "woven",
3923+ "sha256": "7685227e06ff0c781bb957db33585d48e6b5f49dad6eadda6bb331aa61904088"
3924+ },
3925+ {
3926+ "seed": "sample/638",
3927+ "family": "masks",
3928+ "sha256": "d68dbae3b2f2fa5fbc6f0a37513fe40f4702df006c2e432471bd87e308558810"
3929+ },
3930+ {
3931+ "seed": "sample/639",
3932+ "family": "masks",
3933+ "sha256": "f923ebf4488a183a2f2fd747098f5876708f0ef12ca80536659605c2eb0c88a1"
3934+ },
3935+ {
3936+ "seed": "sample/640",
3937+ "family": "machines",
3938+ "sha256": "780160b5d72afcc74d5d867b49e40f764b0edf438a3759734d6b94f1d229bfeb"
3939+ },
3940+ {
3941+ "seed": "sample/641",
3942+ "family": "landscapes",
3943+ "sha256": "f28a30ff6e942dc07b14c9926214d9c1fb2daf08e131a975a2a1a4a10fdaebd5"
3944+ },
3945+ {
3946+ "seed": "sample/642",
3947+ "family": "creatures",
3948+ "sha256": "72b292113b3a5a6c4cff958eecd8bb19e80b05b22152fd54f1ab3cd4eba74a2e"
3949+ },
3950+ {
3951+ "seed": "sample/643",
3952+ "family": "glyphs",
3953+ "sha256": "79c470e05007fa74bac945318d5ddc5879592920a83dd246fbeab1a5eeca2741"
3954+ },
3955+ {
3956+ "seed": "sample/644",
3957+ "family": "woven",
3958+ "sha256": "e8f86639bfb4432971ee17341fc2faf097923b4d4123d819296441f28b4c1e26"
3959+ },
3960+ {
3961+ "seed": "sample/645",
3962+ "family": "orbital",
3963+ "sha256": "30009fd076a0503489af829e41633d2d45902120746238785a3b8052f6c04857"
3964+ },
3965+ {
3966+ "seed": "sample/646",
3967+ "family": "creatures",
3968+ "sha256": "62701f62cf947c5e73a0f38d67a7c3242cb4e3a3a65cced50de4787ada20bcbc"
3969+ },
3970+ {
3971+ "seed": "sample/647",
3972+ "family": "botanical",
3973+ "sha256": "94420ef84ff28402aa5fdc573a9aced54d048268d6a6d30ad635dd77c1224b6f"
3974+ },
3975+ {
3976+ "seed": "sample/648",
3977+ "family": "woven",
3978+ "sha256": "a2a4d8ed6d104f4cc22becb4b44fe45093c40d92f581fec417585bd79ba1262a"
3979+ },
3980+ {
3981+ "seed": "sample/649",
3982+ "family": "creatures",
3983+ "sha256": "703fbba86d8ace61fababef711ab9f80e36e281d6d3d33627a8c163b25cec662"
3984+ },
3985+ {
3986+ "seed": "sample/650",
3987+ "family": "creatures",
3988+ "sha256": "2273c13f6b8ae283c789391f79e2a9dbba631090d511232bf3c390b28794f463"
3989+ },
3990+ {
3991+ "seed": "sample/651",
3992+ "family": "glyphs",
3993+ "sha256": "d32248bad865504585834e30c4b1328e86df25ad63d3b5fa04cd3bf190078dd3"
3994+ },
3995+ {
3996+ "seed": "sample/652",
3997+ "family": "landscapes",
3998+ "sha256": "9d6d64de7ec8d86d459659190d23d51b28601d898c4cdb94afd94679a2bc0d07"
3999+ },
4000+ {
4001+ "seed": "sample/653",
4002+ "family": "woven",
4003+ "sha256": "1223dd1ccae414e350677ab552773f494aae4388bd01bcff2d85fde5b39ca7ca"
4004+ },
4005+ {
4006+ "seed": "sample/654",
4007+ "family": "landscapes",
4008+ "sha256": "2f2937057e3a83121145fefc3fa51a009a307744270eed9e755b476d02d92b9f"
4009+ },
4010+ {
4011+ "seed": "sample/655",
4012+ "family": "machines",
4013+ "sha256": "7ced09b48a349d522ff3a117a3e2f79f0a8e5874db7d29cdc976594e65f8481d"
4014+ },
4015+ {
4016+ "seed": "sample/656",
4017+ "family": "orbital",
4018+ "sha256": "6afa13c7204ee4f9677e54796cb24cb4a2cb7df494a3df532b0733119c591fa5"
4019+ },
4020+ {
4021+ "seed": "sample/657",
4022+ "family": "glyphs",
4023+ "sha256": "ce5aca31fc9802725e66e2a8cf2322fc045592a15fe3b5a089f555345cb744a4"
4024+ },
4025+ {
4026+ "seed": "sample/658",
4027+ "family": "botanical",
4028+ "sha256": "9531993deb1ca98da8f9bac90def8a61c1ff019c8babf4d6cdf784401192f892"
4029+ },
4030+ {
4031+ "seed": "sample/659",
4032+ "family": "woven",
4033+ "sha256": "3eed0c773a049417b71641212af136f2d5d0a3ad47b6f391ae378e3b59d8ee81"
4034+ },
4035+ {
4036+ "seed": "sample/660",
4037+ "family": "landscapes",
4038+ "sha256": "b862d438de4669aec8972784e91656746d0ee9794c56e43729a68b3024a95e2a"
4039+ },
4040+ {
4041+ "seed": "sample/661",
4042+ "family": "woven",
4043+ "sha256": "c0dda6df93810e22bd1e98f567b66faa87c9cbf93ae284293d814eeeeff1a4b6"
4044+ },
4045+ {
4046+ "seed": "sample/662",
4047+ "family": "orbital",
4048+ "sha256": "4234e64d6f81a8ac7d4c9e3ba71ce1ed6b479ce790c3b1e3e2f8076bddf93e2f"
4049+ },
4050+ {
4051+ "seed": "sample/663",
4052+ "family": "botanical",
4053+ "sha256": "ef9b367c40d35323825c0cc276e31d4f9df1d0797f7e73d757ee8677355d4342"
4054+ },
4055+ {
4056+ "seed": "sample/664",
4057+ "family": "woven",
4058+ "sha256": "3321edabd8ed79f8ee6ad500fcb0315e2ed607b6f89fc9949ce53bdab194668f"
4059+ },
4060+ {
4061+ "seed": "sample/665",
4062+ "family": "glyphs",
4063+ "sha256": "323a7a5b588e49cc73e701e1552a32d6a4384eda80433f3db7649e62ba2dafbf"
4064+ },
4065+ {
4066+ "seed": "sample/666",
4067+ "family": "machines",
4068+ "sha256": "fe51e73e2a9d0d20757a2c1f5d42ba8e543667d13bab4713a28c290e7be18878"
4069+ },
4070+ {
4071+ "seed": "sample/667",
4072+ "family": "botanical",
4073+ "sha256": "f39b03bf0b83b03b526d9d57c34470cd51fd7e859a2744e532833a5a04b8b3ed"
4074+ },
4075+ {
4076+ "seed": "sample/668",
4077+ "family": "botanical",
4078+ "sha256": "c6c24e2daba5fb1ec5d48338e43dbdad67c1ccee9958548645d79b5c64c8e8cd"
4079+ },
4080+ {
4081+ "seed": "sample/669",
4082+ "family": "landscapes",
4083+ "sha256": "941345ed8f0134d884831c54cfd5d55b001ec7ed1df011346e9a8cfaf2c3ba46"
4084+ },
4085+ {
4086+ "seed": "sample/670",
4087+ "family": "masks",
4088+ "sha256": "60af0e774e3323897f6149f513fb9ecb7fced4c1c2218b1b00c7bc1650f75810"
4089+ },
4090+ {
4091+ "seed": "sample/671",
4092+ "family": "machines",
4093+ "sha256": "25ded61a758b6a8735e7e1edaf424b389b6f822ab603be758f6f6e025ac02c24"
4094+ },
4095+ {
4096+ "seed": "sample/672",
4097+ "family": "landscapes",
4098+ "sha256": "c1d68ed29a1e2334305eba2d19f9971fdc6bb2752e37152d0db9a3a88c70ba71"
4099+ },
4100+ {
4101+ "seed": "sample/673",
4102+ "family": "creatures",
4103+ "sha256": "d53219ded31b42ff0e6ecc283c1c884db555a500d9683b8923252ce6b477d8ba"
4104+ },
4105+ {
4106+ "seed": "sample/674",
4107+ "family": "masks",
4108+ "sha256": "8dda0ad23bd486f70079115f708aa2ebafe3e0f088919bfbf89e71ec48bca122"
4109+ },
4110+ {
4111+ "seed": "sample/675",
4112+ "family": "botanical",
4113+ "sha256": "8962d847ea61449091fd5715d6617e94926c41f3c419718ac46543b85726cada"
4114+ },
4115+ {
4116+ "seed": "sample/676",
4117+ "family": "botanical",
4118+ "sha256": "74c7a9fd8636ce5294d31ac7a895eadf000c03e77dad4ba93ef15eec76e46230"
4119+ },
4120+ {
4121+ "seed": "sample/677",
4122+ "family": "glyphs",
4123+ "sha256": "cb2f0d35a833abe5a1ee33ee224792cd64a1520aabdf9315df9b2617ef7e265f"
4124+ },
4125+ {
4126+ "seed": "sample/678",
4127+ "family": "masks",
4128+ "sha256": "eb47ceafe57a415b76d8732c0757e26306562be9d934ddd55cc0d1940423f6ad"
4129+ },
4130+ {
4131+ "seed": "sample/679",
4132+ "family": "creatures",
4133+ "sha256": "3d47a05d84084461f643507b78debac47c0770f0c311ed5d83b90e835911adee"
4134+ },
4135+ {
4136+ "seed": "sample/680",
4137+ "family": "glyphs",
4138+ "sha256": "5944a40efad94f78234ead13b80829e7eb0052faf846d85ded19f35bd8fd16a9"
4139+ },
4140+ {
4141+ "seed": "sample/681",
4142+ "family": "masks",
4143+ "sha256": "e313b1127f62a31e56fbf1699a45e4fbe73ed3cf557417eb0b84d31e3c372a36"
4144+ },
4145+ {
4146+ "seed": "sample/682",
4147+ "family": "masks",
4148+ "sha256": "47c131f2a01fca2828392dca828ff62580331aa8fba5d7cbd6a083286d80bbae"
4149+ },
4150+ {
4151+ "seed": "sample/683",
4152+ "family": "orbital",
4153+ "sha256": "6a93fc3e5bd444aeee0993ac0d557cc4b5fb8a817cb6a39886c21e9a8d2d19ca"
4154+ },
4155+ {
4156+ "seed": "sample/684",
4157+ "family": "botanical",
4158+ "sha256": "38e5abb5c52ab981e5ccc68038d9f166e1b7d51106fb3e3e6881888a9bdce96e"
4159+ },
4160+ {
4161+ "seed": "sample/685",
4162+ "family": "glyphs",
4163+ "sha256": "1b925e2335c10024b2d606656d4d7a6edcc3eb7da37380fc00d5580d082afdf7"
4164+ },
4165+ {
4166+ "seed": "sample/686",
4167+ "family": "glyphs",
4168+ "sha256": "6e3f5596004d2077caa764481866bf172abc11d69caf52841bf20497a30dee48"
4169+ },
4170+ {
4171+ "seed": "sample/687",
4172+ "family": "orbital",
4173+ "sha256": "d390037f97516eab0ec5868428630c25b255c5b0936a6da481daf191006cc271"
4174+ },
4175+ {
4176+ "seed": "sample/688",
4177+ "family": "landscapes",
4178+ "sha256": "6b8a2f84568080318d9eeabba662ae1448b0883d09cb4d44ce31bf67fc2dc57d"
4179+ },
4180+ {
4181+ "seed": "sample/689",
4182+ "family": "glyphs",
4183+ "sha256": "1ceb7ae87f3545d2c6fd494b6a50bb8284662d1f41f7bada2ae64b64b57abc94"
4184+ },
4185+ {
4186+ "seed": "sample/690",
4187+ "family": "glyphs",
4188+ "sha256": "abf8acc89e9385a961c414e631045f98f4898058237438b700653eb049b8a376"
4189+ },
4190+ {
4191+ "seed": "sample/691",
4192+ "family": "glyphs",
4193+ "sha256": "ae139d5a6239e3b2df79f69fafdb9eb50aca70b404280f05af478db0320c7df9"
4194+ },
4195+ {
4196+ "seed": "sample/692",
4197+ "family": "masks",
4198+ "sha256": "abf56aa63c6288348d6f1f2ba0cc80a4aa5125b3ecaf1f20c1ed976efa3816d8"
4199+ },
4200+ {
4201+ "seed": "sample/693",
4202+ "family": "landscapes",
4203+ "sha256": "b0ca890909a207f0563e3af4d130c59edeebe401773119fd557c06b06878f373"
4204+ },
4205+ {
4206+ "seed": "sample/694",
4207+ "family": "woven",
4208+ "sha256": "0894dcebbda712b31f8b7874498ebaf7d5e6e5797333a0bd65377041503f2904"
4209+ },
4210+ {
4211+ "seed": "sample/695",
4212+ "family": "creatures",
4213+ "sha256": "ce6517a0472354184a9d6ea93b61900b04643b2bf6165db6d60c88eac8caae06"
4214+ },
4215+ {
4216+ "seed": "sample/696",
4217+ "family": "masks",
4218+ "sha256": "3eba513f6d2c7cf203d557ced6abc49d7c5fdef2b683e0e318f2d462eceecd85"
4219+ },
4220+ {
4221+ "seed": "sample/697",
4222+ "family": "botanical",
4223+ "sha256": "410532106cdf97637099314ee10c452dd1f1f29c3ddf1c9f6e97d8315aa908ee"
4224+ },
4225+ {
4226+ "seed": "sample/698",
4227+ "family": "orbital",
4228+ "sha256": "6cce2344dbab63a88e2554b7b1a76bba26b942f5f3b100b4b8a1cd5d700a768c"
4229+ },
4230+ {
4231+ "seed": "sample/699",
4232+ "family": "glyphs",
4233+ "sha256": "2ab077aff81fd29e463c079275d4fbe71dc0ac6eb2edf3318756879ed91edaaa"
4234+ },
4235+ {
4236+ "seed": "sample/700",
4237+ "family": "woven",
4238+ "sha256": "f03e9546444b75687d8cd9c573f2df5053db75cfe5175fe030a44a0f2eb6f22b"
4239+ },
4240+ {
4241+ "seed": "sample/701",
4242+ "family": "landscapes",
4243+ "sha256": "069848690efa6a6560edb96ddbf1da6a8cd75ac9089d479da15e75a49e752477"
4244+ },
4245+ {
4246+ "seed": "sample/702",
4247+ "family": "landscapes",
4248+ "sha256": "c61bb939a410382d32d9b4cdab2e6e96196ac47907cb5ad633824aa3a4ead71c"
4249+ },
4250+ {
4251+ "seed": "sample/703",
4252+ "family": "machines",
4253+ "sha256": "76047aac332fe19370915b5e1ec7faa94841dcf1148d1bb06b4d3d4edeff8787"
4254+ },
4255+ {
4256+ "seed": "sample/704",
4257+ "family": "creatures",
4258+ "sha256": "27ec45433f6e445843af105309474ff3d7d20325bd7dbb800541a0e7878f0552"
4259+ },
4260+ {
4261+ "seed": "sample/705",
4262+ "family": "orbital",
4263+ "sha256": "467acac4862ad0ac6e2b9f50a95c3700407710392bba7a2eae8e5e4f3cc7d178"
4264+ },
4265+ {
4266+ "seed": "sample/706",
4267+ "family": "masks",
4268+ "sha256": "76c4c307f35b3b39e160df3e6b9173dc1eb2e1020488879b4ddf0b54ff5e3ea5"
4269+ },
4270+ {
4271+ "seed": "sample/707",
4272+ "family": "machines",
4273+ "sha256": "1b12a1a5dbe3d086d4ae7266a198fb845af8b5e4725ada4d4f76b1140c503a97"
4274+ },
4275+ {
4276+ "seed": "sample/708",
4277+ "family": "creatures",
4278+ "sha256": "01b397e3378eed77181129520c7425eeae13c02b17ba509fdb9a2713cf938fcb"
4279+ },
4280+ {
4281+ "seed": "sample/709",
4282+ "family": "woven",
4283+ "sha256": "44231ddcf7a21ab625d7d10af83a2cabc60f9519fad062c8fef8c60343c0d63f"
4284+ },
4285+ {
4286+ "seed": "sample/710",
4287+ "family": "orbital",
4288+ "sha256": "14e58eb093c4bbbc22dc0475e31973a98d8a0640ea3547377247ff8677e87a11"
4289+ },
4290+ {
4291+ "seed": "sample/711",
4292+ "family": "masks",
4293+ "sha256": "3788a0b31f1c146dcad44beb0ee44fe62cdf454643edb80b23d90dc2730baa12"
4294+ },
4295+ {
4296+ "seed": "sample/712",
4297+ "family": "landscapes",
4298+ "sha256": "2b92990f8e6a53350e8eaeffc9d44458396fdadbe94ee19e03f9b47abff27b64"
4299+ },
4300+ {
4301+ "seed": "sample/713",
4302+ "family": "woven",
4303+ "sha256": "64f8af69b4bc845c565bf3b96ab5a02f7cb5261802932f14d22cf0ee12ed0d0a"
4304+ },
4305+ {
4306+ "seed": "sample/714",
4307+ "family": "landscapes",
4308+ "sha256": "0be5e9a151865020d5885d003f4f951f92977fbd76fa32d4ca003fea294bc3d6"
4309+ },
4310+ {
4311+ "seed": "sample/715",
4312+ "family": "machines",
4313+ "sha256": "39fe8d2e806b5a83ffbb16d6687e33968806954c857f5d538816c809403a57b9"
4314+ },
4315+ {
4316+ "seed": "sample/716",
4317+ "family": "glyphs",
4318+ "sha256": "fc615d2319f766b5fb68518cb5b606ee6f86e418bc73c9d3d62163fb0d0370cf"
4319+ },
4320+ {
4321+ "seed": "sample/717",
4322+ "family": "botanical",
4323+ "sha256": "53a9231107a6fcedd268c7b5743b9bb93208d5af8a156634feaa06ad94ff15bc"
4324+ },
4325+ {
4326+ "seed": "sample/718",
4327+ "family": "landscapes",
4328+ "sha256": "6e8e2692f2bd636bc892c648abbe12a234b08a2c4a01f015ad18a590eeffd6af"
4329+ },
4330+ {
4331+ "seed": "sample/719",
4332+ "family": "machines",
4333+ "sha256": "5029771bf6574dac6df3fbdffbb6cb74c781fdd75628ceaccfbbd5086dc5934a"
4334+ },
4335+ {
4336+ "seed": "sample/720",
4337+ "family": "landscapes",
4338+ "sha256": "0245638d6a86c5d04d2e61b940be08e1fba1ff3592928d504c2e8e6502c33a2a"
4339+ },
4340+ {
4341+ "seed": "sample/721",
4342+ "family": "landscapes",
4343+ "sha256": "4e4beed9d7157179fcfcf3244e03175f2766239c9fad1ef2590eed9aaa010a51"
4344+ },
4345+ {
4346+ "seed": "sample/722",
4347+ "family": "woven",
4348+ "sha256": "fec6d098fabed38c9381d2dea0971829f8d16b8dd41cf20cfb0d35bd53dc35cd"
4349+ },
4350+ {
4351+ "seed": "sample/723",
4352+ "family": "machines",
4353+ "sha256": "f610684f455d7c6e17f792d15a881995ebc43c84ad42ce88d600488e4791b0b2"
4354+ },
4355+ {
4356+ "seed": "sample/724",
4357+ "family": "botanical",
4358+ "sha256": "556587cb1f4f0ac620e3f065983d8627ab75d772f332dcf665cd8d8b43a70996"
4359+ },
4360+ {
4361+ "seed": "sample/725",
4362+ "family": "woven",
4363+ "sha256": "108d8b740ecb3d1db31f63f4c5855dfa7f2bd85206208d707164f3daad9e42c4"
4364+ },
4365+ {
4366+ "seed": "sample/726",
4367+ "family": "glyphs",
4368+ "sha256": "63fb754f256027fa3f226988a103ae8e0a36b3c5353b6476856a2ec8fa07fde0"
4369+ },
4370+ {
4371+ "seed": "sample/727",
4372+ "family": "woven",
4373+ "sha256": "5a60363b80dc6298a23e86b14cbfb881e96430705e9ca087531da7e08f4ce94f"
4374+ },
4375+ {
4376+ "seed": "sample/728",
4377+ "family": "creatures",
4378+ "sha256": "70a5b71f6c9fb5b99430085362da928b64555fb45e5ffa134c480c2f99cc291c"
4379+ },
4380+ {
4381+ "seed": "sample/729",
4382+ "family": "landscapes",
4383+ "sha256": "a208f907a9b8a9458e955752f21b9766838210501a48db3a4da863e5c09996ec"
4384+ },
4385+ {
4386+ "seed": "sample/730",
4387+ "family": "orbital",
4388+ "sha256": "0fc01f72742441f3ea14f2a18f405220e44551bbc6ec4c5d0bab788c457b2e99"
4389+ },
4390+ {
4391+ "seed": "sample/731",
4392+ "family": "machines",
4393+ "sha256": "653c162c603224f12033d1b96036256fbe664118589517e7d1949bc1841fb491"
4394+ },
4395+ {
4396+ "seed": "sample/732",
4397+ "family": "landscapes",
4398+ "sha256": "1ab926c887bdcca0febf773595ca3d07fa2222c70520d8388d9e82bfbc372360"
4399+ },
4400+ {
4401+ "seed": "sample/733",
4402+ "family": "machines",
4403+ "sha256": "fb3627d980b4244317f4af42b21358a03e9aeb4e5ef7cdbb1ade32d6c08c8964"
4404+ },
4405+ {
4406+ "seed": "sample/734",
4407+ "family": "woven",
4408+ "sha256": "0763d08c58ea1163098cd791a4792e790333c8ad46f69a7c48909bd98d0b3edc"
4409+ },
4410+ {
4411+ "seed": "sample/735",
4412+ "family": "orbital",
4413+ "sha256": "fbdbb77942d9f840e779f06eb771db2540f57d33ef25535ea8b40b0082952011"
4414+ },
4415+ {
4416+ "seed": "sample/736",
4417+ "family": "glyphs",
4418+ "sha256": "1a77833e80d66bde5f68aeff79cd7fbe2c0d75bc45807d93be608e7368d6bd21"
4419+ },
4420+ {
4421+ "seed": "sample/737",
4422+ "family": "botanical",
4423+ "sha256": "0fe981041f29823dca8828cffcc9e502e63f755f354f144c04e71c5d6e162aa1"
4424+ },
4425+ {
4426+ "seed": "sample/738",
4427+ "family": "woven",
4428+ "sha256": "79da058a82c17cb502ae26753b38c136fcf5c575a668e3c06c9997ca83b5206e"
4429+ },
4430+ {
4431+ "seed": "sample/739",
4432+ "family": "landscapes",
4433+ "sha256": "908dbea050fecd15f66491874819080c2ccd526866139e06aff8b5d273d629bd"
4434+ },
4435+ {
4436+ "seed": "sample/740",
4437+ "family": "masks",
4438+ "sha256": "09011a3b3d1eb76e2a387676eab7f036a45a13c305703a1e9be19c1134101aa3"
4439+ },
4440+ {
4441+ "seed": "sample/741",
4442+ "family": "woven",
4443+ "sha256": "0cd89ddc6a495ef3de2cbdcf8752ed15ccdd802fb2f90e3b45666ee4a4f4be60"
4444+ },
4445+ {
4446+ "seed": "sample/742",
4447+ "family": "creatures",
4448+ "sha256": "016b000f5c1beca338f2be450c15f55cd26bafd07a733ce4afb6a43a90ae902f"
4449+ },
4450+ {
4451+ "seed": "sample/743",
4452+ "family": "landscapes",
4453+ "sha256": "3c9c7b151b1e8721a2857ab64aa1ea77e2c794f9cbed093063eb117c85c3372e"
4454+ },
4455+ {
4456+ "seed": "sample/744",
4457+ "family": "machines",
4458+ "sha256": "5af39e43bf9ac023459a808e786dcc21a1bf3753838944c459d68dfbf52de882"
4459+ },
4460+ {
4461+ "seed": "sample/745",
4462+ "family": "glyphs",
4463+ "sha256": "7ea9a5ed61d020db67addaa5e8c7edad103fe33e59f5a87858e5bb2f0f7ac255"
4464+ },
4465+ {
4466+ "seed": "sample/746",
4467+ "family": "masks",
4468+ "sha256": "70d8a05749dc3d860d4ee8e45d3b5175a9157445844a2e8133d645f0ee136ff4"
4469+ },
4470+ {
4471+ "seed": "sample/747",
4472+ "family": "creatures",
4473+ "sha256": "02160d60d8746ee4800eefb8b167cbaba74ef61f5e75296bc719993430de9565"
4474+ },
4475+ {
4476+ "seed": "sample/748",
4477+ "family": "masks",
4478+ "sha256": "a5fe3470e83053df23f74498eddf7b9973885ea3b296b79370865a6b36582d85"
4479+ },
4480+ {
4481+ "seed": "sample/749",
4482+ "family": "orbital",
4483+ "sha256": "f014e11a50c9c7f26af9e46a04af8bd9ba8b7e53386e52d891ae973d004d50e7"
4484+ },
4485+ {
4486+ "seed": "sample/750",
4487+ "family": "glyphs",
4488+ "sha256": "9f2eacd516bbd846c815169d4aa59a1bcebc3e4c334ba6176b63847ec1ffb158"
4489+ },
4490+ {
4491+ "seed": "sample/751",
4492+ "family": "botanical",
4493+ "sha256": "eb9c0ce64a7b33e55e6917f5941adb40e85effc152709486867767855f43ada9"
4494+ },
4495+ {
4496+ "seed": "sample/752",
4497+ "family": "landscapes",
4498+ "sha256": "b61a345808fe3de451a35560ee24cdb41f7cb2aa7d0f3a34028b5078bd6c1bc0"
4499+ },
4500+ {
4501+ "seed": "sample/753",
4502+ "family": "machines",
4503+ "sha256": "9dee6a528ed04d48352ac4d931b7b486e7b46180637739de35e855666cf589f9"
4504+ },
4505+ {
4506+ "seed": "sample/754",
4507+ "family": "landscapes",
4508+ "sha256": "c4a3d70a411d63ea18742a223c6b94980189944b69031b32ff9b01754d66a276"
4509+ },
4510+ {
4511+ "seed": "sample/755",
4512+ "family": "woven",
4513+ "sha256": "4639cff368f89a80da3154296085cd466815022c1b2263c2240f678a7a465719"
4514+ },
4515+ {
4516+ "seed": "sample/756",
4517+ "family": "orbital",
4518+ "sha256": "513cfda2ef53e586a264d9810e9bbd1dd14b7a1450c8b650d3b146ade28875c2"
4519+ },
4520+ {
4521+ "seed": "sample/757",
4522+ "family": "woven",
4523+ "sha256": "0f98ad98d3cfd314adaa4ce49656c8e0cfa02016d0d735b2dfb4dad707ae6870"
4524+ },
4525+ {
4526+ "seed": "sample/758",
4527+ "family": "masks",
4528+ "sha256": "238c93023a64dac23496b152317159a9bd2f4926bfefc144025464ad05b868eb"
4529+ },
4530+ {
4531+ "seed": "sample/759",
4532+ "family": "machines",
4533+ "sha256": "a0a71986bb6de27223058b702f4bf17fcd7d89d12afbcbdcd14129124a4ab804"
4534+ },
4535+ {
4536+ "seed": "sample/760",
4537+ "family": "landscapes",
4538+ "sha256": "a9dbbd0b95a1424d6fa2b2b9c18b5f9416c19e9ed22b133928b21e8017bc7154"
4539+ },
4540+ {
4541+ "seed": "sample/761",
4542+ "family": "woven",
4543+ "sha256": "764c61e222a0507b95c8562a156b837a026bdf4ad378c9dbedb47cb2f4a79107"
4544+ },
4545+ {
4546+ "seed": "sample/762",
4547+ "family": "orbital",
4548+ "sha256": "3cf708ee956a30d4c3312348a89c946ad00f69737e42b346904b4c3ca9324b05"
4549+ },
4550+ {
4551+ "seed": "sample/763",
4552+ "family": "machines",
4553+ "sha256": "3e66a1ca8437fa320c9b12017914296dfe96e462642f82a160e808eda38c71ee"
4554+ },
4555+ {
4556+ "seed": "sample/764",
4557+ "family": "glyphs",
4558+ "sha256": "91fb2f4afa765ff572fb77f06c0e1d5fe25c8963d8404e938c25dfc8738ad40f"
4559+ },
4560+ {
4561+ "seed": "sample/765",
4562+ "family": "glyphs",
4563+ "sha256": "0e9256735946eb56cab5a96907663a89ff9d4f96a942d477347b3e8c7f6e6d7b"
4564+ },
4565+ {
4566+ "seed": "sample/766",
4567+ "family": "masks",
4568+ "sha256": "0eff0aa0997c186c2ee0c0c19c93c346ca8baca9d0bf6ce347b6b1dfcbadebe5"
4569+ },
4570+ {
4571+ "seed": "sample/767",
4572+ "family": "creatures",
4573+ "sha256": "987852c679af3e533d41493616e5238832114dc21490b49eeab4c73635a27f70"
4574+ },
4575+ {
4576+ "seed": "sample/768",
4577+ "family": "botanical",
4578+ "sha256": "434e35678f37a16e9fa36e2ee3d536640cd269094c714e067a72ef4b3bf00931"
4579+ },
4580+ {
4581+ "seed": "sample/769",
4582+ "family": "botanical",
4583+ "sha256": "e4a809c8900322f932448f63785cd64d7fb6ae18ff600df761c0579a7e35875f"
4584+ },
4585+ {
4586+ "seed": "sample/770",
4587+ "family": "masks",
4588+ "sha256": "da0a12f15335c2524e2cd3c401899efa6b6dd59ac017408d677256c95995f55b"
4589+ },
4590+ {
4591+ "seed": "sample/771",
4592+ "family": "machines",
4593+ "sha256": "ee96f1cd7f1789416ff2d1055b419834910f9e9f89add32648b30260466e7f89"
4594+ },
4595+ {
4596+ "seed": "sample/772",
4597+ "family": "landscapes",
4598+ "sha256": "21c12489dd8a698da01f346c6a7c4042ab93d94e3c4e6af2330ffd9f8aa5c01c"
4599+ },
4600+ {
4601+ "seed": "sample/773",
4602+ "family": "creatures",
4603+ "sha256": "5a6c273834da4a08c1105a9b1478982658847ce32d402405cbf4a88854d235d0"
4604+ },
4605+ {
4606+ "seed": "sample/774",
4607+ "family": "landscapes",
4608+ "sha256": "e983c5ef1bea3c90c2e8872e7dfb1af7ebee769923af5110f3d6ae21ac338aef"
4609+ },
4610+ {
4611+ "seed": "sample/775",
4612+ "family": "botanical",
4613+ "sha256": "5086e9856fbf05531283c1b4b5a2686d99f280994c2bb74b4e6ead0ffcacd312"
4614+ },
4615+ {
4616+ "seed": "sample/776",
4617+ "family": "glyphs",
4618+ "sha256": "7c2a92a3b1fc567bf399c78a2b2efab3c9f4d0f3bb52c098ac2dbe1c44c31725"
4619+ },
4620+ {
4621+ "seed": "sample/777",
4622+ "family": "landscapes",
4623+ "sha256": "18917a1247268943fc7ea131b6a2698a7117c3eff110cb20f64b09672ad36d5e"
4624+ },
4625+ {
4626+ "seed": "sample/778",
4627+ "family": "masks",
4628+ "sha256": "0dbd96e3136bf5116237c171cffeb9b259c236a69fb068194cb5d3af095ee757"
4629+ },
4630+ {
4631+ "seed": "sample/779",
4632+ "family": "landscapes",
4633+ "sha256": "2147f965098cdeff4ff0096f913f68007bc657e6061aae0d6f379bdbe2c413be"
4634+ },
4635+ {
4636+ "seed": "sample/780",
4637+ "family": "landscapes",
4638+ "sha256": "cc41698a8ac3bac633845fa83cfbaefc9a02a75020df198b16a6c86361bdaf80"
4639+ },
4640+ {
4641+ "seed": "sample/781",
4642+ "family": "orbital",
4643+ "sha256": "1a44673bacaa237d62b42af7f8caa048227c0224a2ebfce3bf466da71459ea1d"
4644+ },
4645+ {
4646+ "seed": "sample/782",
4647+ "family": "botanical",
4648+ "sha256": "697909e08c75584a1abef81f3ad81f91db36bb3789d6147ebc7e07c4cbbfa995"
4649+ },
4650+ {
4651+ "seed": "sample/783",
4652+ "family": "creatures",
4653+ "sha256": "10597b393ada85c28733951a4de9e49495b82bd3e28c8a2fed4fe8f66e18bff3"
4654+ },
4655+ {
4656+ "seed": "sample/784",
4657+ "family": "creatures",
4658+ "sha256": "7e36c22d4f29cc8e96950604e6037e2221f15d657dfa52a1e61e2ce426d6daba"
4659+ },
4660+ {
4661+ "seed": "sample/785",
4662+ "family": "botanical",
4663+ "sha256": "1da9a9895111da5384656a9a77679fbd537454002fd5b600c8e4e64dd662d896"
4664+ },
4665+ {
4666+ "seed": "sample/786",
4667+ "family": "woven",
4668+ "sha256": "0bd5d0d6906347634eb6f29af636da87152f82e8774622fbd38a809327d9998a"
4669+ },
4670+ {
4671+ "seed": "sample/787",
4672+ "family": "masks",
4673+ "sha256": "4596ea676dd77fff82ff07f4f54612ddb3e9da76c3aa88c0e587aee24a531113"
4674+ },
4675+ {
4676+ "seed": "sample/788",
4677+ "family": "woven",
4678+ "sha256": "9327218a1893c79fb6cbb971b22c2bf5e499038ac593d183056c01ca0bc5dd97"
4679+ },
4680+ {
4681+ "seed": "sample/789",
4682+ "family": "machines",
4683+ "sha256": "e7ce0af9eb25fbb69bc89dfccc5dab1321352501234a0b60cc4eb914a994c5a4"
4684+ },
4685+ {
4686+ "seed": "sample/790",
4687+ "family": "machines",
4688+ "sha256": "e58234a19e1a70cbc9354f93678b62cb510000162c0370aa5d7e7cfbc504742c"
4689+ },
4690+ {
4691+ "seed": "sample/791",
4692+ "family": "creatures",
4693+ "sha256": "846c6b0bce2b903f61f77fc67398aa0f3f1d48e6e1e4860843b9b48086c48ec3"
4694+ },
4695+ {
4696+ "seed": "sample/792",
4697+ "family": "creatures",
4698+ "sha256": "1c33f37d7c6c9e0e90f165a63b6f52b92a6f3cb717757d613df965b94e283c74"
4699+ },
4700+ {
4701+ "seed": "sample/793",
4702+ "family": "glyphs",
4703+ "sha256": "e316f43f64f0eecf79f56bf86b0e06066b5b6fc89586fc92b7dee44aae022307"
4704+ },
4705+ {
4706+ "seed": "sample/794",
4707+ "family": "woven",
4708+ "sha256": "904734e8e5ce31289fe3566a478d9b4f59e58facce50a630d6f616380e22b3d3"
4709+ },
4710+ {
4711+ "seed": "sample/795",
4712+ "family": "landscapes",
4713+ "sha256": "ca6c3aa3e1cf20cbc8815c6308929a63c465449026d7ba2a93c07b1ff1216151"
4714+ },
4715+ {
4716+ "seed": "sample/796",
4717+ "family": "orbital",
4718+ "sha256": "e34b5b9843a96e8639b4327d4906c5a4ced2f5d2c5ee5ff0fbd042b85d09d9e3"
4719+ },
4720+ {
4721+ "seed": "sample/797",
4722+ "family": "masks",
4723+ "sha256": "74ca0c87cdd944a3eea14df915d4c0602a3d75495917ac54a1b090b7adc526a2"
4724+ },
4725+ {
4726+ "seed": "sample/798",
4727+ "family": "creatures",
4728+ "sha256": "6f9ab8ecc2f43643c43ad3ba666fa45e0955203cbe340db333a3169957307d06"
4729+ },
4730+ {
4731+ "seed": "sample/799",
4732+ "family": "woven",
4733+ "sha256": "daddb44cbd97084f6ca0909170abc58ec47a354ccebe92211188aa40393168e1"
4734+ },
4735+ {
4736+ "seed": "sample/800",
4737+ "family": "orbital",
4738+ "sha256": "49b2a35c9eb14fdcf13780e7297154f1d57c20c9ea1322f0e76a1985f07f57a7"
4739+ },
4740+ {
4741+ "seed": "sample/801",
4742+ "family": "creatures",
4743+ "sha256": "0f9c70223620610075f70a34f43455aad4182346f3461c70ebfd1261c9a764de"
4744+ },
4745+ {
4746+ "seed": "sample/802",
4747+ "family": "masks",
4748+ "sha256": "5952e7c4dc0039ddc47ac2994ee3945771c8b887185b61fa79b871e2987d5e97"
4749+ },
4750+ {
4751+ "seed": "sample/803",
4752+ "family": "landscapes",
4753+ "sha256": "6e60986e64eaec9b919e1a6418fca19fd472102bcd115dee104a98cf7351ed6a"
4754+ },
4755+ {
4756+ "seed": "sample/804",
4757+ "family": "creatures",
4758+ "sha256": "f33fb68b179438310132ca49936184a09faf71eb14bc29edf875f020d50fcdd5"
4759+ },
4760+ {
4761+ "seed": "sample/805",
4762+ "family": "botanical",
4763+ "sha256": "3d8610e1bf953d5069f9a953921475b4ae948f11585a33ea4e1b819452c4ca79"
4764+ },
4765+ {
4766+ "seed": "sample/806",
4767+ "family": "orbital",
4768+ "sha256": "51bd388fae38ffb549c23e56ef7b58242cde46d70edf657ee3dde57c4355db27"
4769+ },
4770+ {
4771+ "seed": "sample/807",
4772+ "family": "botanical",
4773+ "sha256": "017dc178d465a2595f85bc465c5adb74a4d0dad6a16e4de536bea85624f73282"
4774+ },
4775+ {
4776+ "seed": "sample/808",
4777+ "family": "glyphs",
4778+ "sha256": "374fed768098b698fde6784bba3cfc9e4f9e2d36cd30b78f26132dad73cffe75"
4779+ },
4780+ {
4781+ "seed": "sample/809",
4782+ "family": "botanical",
4783+ "sha256": "759141b41c395871065f988335d11cea6620aa5e227fc99fa2ba0a834b70f745"
4784+ },
4785+ {
4786+ "seed": "sample/810",
4787+ "family": "woven",
4788+ "sha256": "56a615fafdae56e32bd17f6b8b6236fcf93c2f748cc8d4ea5cbcc706fd69a9cd"
4789+ },
4790+ {
4791+ "seed": "sample/811",
4792+ "family": "landscapes",
4793+ "sha256": "1b0ebebcfa195ddd3cea0cd32eacf750e038a9cfdb67654a07a18e0110c4545f"
4794+ },
4795+ {
4796+ "seed": "sample/812",
4797+ "family": "glyphs",
4798+ "sha256": "adf4a107118c17026a36c3888e66230ffb856c24a049f37263dcf643e76e63c3"
4799+ },
4800+ {
4801+ "seed": "sample/813",
4802+ "family": "landscapes",
4803+ "sha256": "472c67d526282d57917fdfe62c8a427e8de481793e4b93a70a4ee51f72d5d554"
4804+ },
4805+ {
4806+ "seed": "sample/814",
4807+ "family": "machines",
4808+ "sha256": "e69fb94fb290cf79c50ec75193a1fadfdfe32e4230ce774a42a7c943a2c0260d"
4809+ },
4810+ {
4811+ "seed": "sample/815",
4812+ "family": "woven",
4813+ "sha256": "09e478a22a42e4d17e0e5695e1045a82165aa853f4464993ab041883ba37d2e1"
4814+ },
4815+ {
4816+ "seed": "sample/816",
4817+ "family": "botanical",
4818+ "sha256": "13936cf90023cfdebbb6a8e1b94a403f8204a040e06d2c6d707f2eced9bb9dff"
4819+ },
4820+ {
4821+ "seed": "sample/817",
4822+ "family": "woven",
4823+ "sha256": "a74e900ed042957543589228d8f86920ea47cdef6f0ca54501774c499fa97cf3"
4824+ },
4825+ {
4826+ "seed": "sample/818",
4827+ "family": "creatures",
4828+ "sha256": "f1dfe41ac036f0378936c9a007588c7116f7dfc5bee45f66904ec6ea61927656"
4829+ },
4830+ {
4831+ "seed": "sample/819",
4832+ "family": "orbital",
4833+ "sha256": "4362086df775f5ef65b7390f9f51b6fc94e1616da552189f871add56dfaf5c1f"
4834+ },
4835+ {
4836+ "seed": "sample/820",
4837+ "family": "landscapes",
4838+ "sha256": "95d546e58d8274be13358ac97a3c2ed2c0b2623b5c2a793284aa9fa9db687c6e"
4839+ },
4840+ {
4841+ "seed": "sample/821",
4842+ "family": "glyphs",
4843+ "sha256": "752350c3a35ec4efda9b6d10bf6cda2e5ca2ebc5a812c054a564ff7dda5788a9"
4844+ },
4845+ {
4846+ "seed": "sample/822",
4847+ "family": "orbital",
4848+ "sha256": "1ada6dd6d9c42406670596d4b015a389c16de967a280702f9ef5880a8570ef5b"
4849+ },
4850+ {
4851+ "seed": "sample/823",
4852+ "family": "woven",
4853+ "sha256": "992429b047e7f7385fbfe1df4802900aa166d68e9313a756b745669623984c6c"
4854+ },
4855+ {
4856+ "seed": "sample/824",
4857+ "family": "landscapes",
4858+ "sha256": "80fc83e6568d4ab0d1cbc1ce5c021bc5506e07b17495ab2b483d5636a2e0ac51"
4859+ },
4860+ {
4861+ "seed": "sample/825",
4862+ "family": "masks",
4863+ "sha256": "0c060efa4013c4f4093ec7fd892a0b972f8976ce051429c896bd5709bf669986"
4864+ },
4865+ {
4866+ "seed": "sample/826",
4867+ "family": "creatures",
4868+ "sha256": "962cc51e765714abc1693d2c994b37e231a6dcf1666b51ed30a0a5c08587d0ed"
4869+ },
4870+ {
4871+ "seed": "sample/827",
4872+ "family": "machines",
4873+ "sha256": "063e199b9b710e330194bafd115e78b2ef5af831e2b87d47e5ff41700564a5b4"
4874+ },
4875+ {
4876+ "seed": "sample/828",
4877+ "family": "orbital",
4878+ "sha256": "5d4bb8a8a85663148ff6624f483490eac7e345996c29b7b909a6e5c3141a70e7"
4879+ },
4880+ {
4881+ "seed": "sample/829",
4882+ "family": "machines",
4883+ "sha256": "059776e86d8abdea06ab6605f928040aab1f9ed1a919a35c301bd0ba4f68d068"
4884+ },
4885+ {
4886+ "seed": "sample/830",
4887+ "family": "machines",
4888+ "sha256": "7e666c6ea7ccb7e4d5c0130a9203b1fdef7e222461eeba4f229c4ff0fe79bba6"
4889+ },
4890+ {
4891+ "seed": "sample/831",
4892+ "family": "creatures",
4893+ "sha256": "3de9a5d9a8fe899db0485bc0dad0fc8af03f5b935d450aaaafd09921ef10ae16"
4894+ },
4895+ {
4896+ "seed": "sample/832",
4897+ "family": "landscapes",
4898+ "sha256": "9862c6a59df0845bb00f66d03f8a2247a048e184f9387e5abb29c99d9ec26971"
4899+ },
4900+ {
4901+ "seed": "sample/833",
4902+ "family": "glyphs",
4903+ "sha256": "c180901c44d2f1d6cd70838369df9b476180a8186ce16a3dec82b35da2af5f53"
4904+ },
4905+ {
4906+ "seed": "sample/834",
4907+ "family": "botanical",
4908+ "sha256": "35dbea0b51ce13831af4986813a0f30b932db39b527f08b9fea147d0989a36eb"
4909+ },
4910+ {
4911+ "seed": "sample/835",
4912+ "family": "masks",
4913+ "sha256": "8abd33cca220ac01bcb47d40fe812ba3aa15f10addbfc9f4144f0c379205fc95"
4914+ },
4915+ {
4916+ "seed": "sample/836",
4917+ "family": "machines",
4918+ "sha256": "35ccd960f146761196e5fdcf8c8471319af8016453d0e29ce9ae0f3b93477ef3"
4919+ },
4920+ {
4921+ "seed": "sample/837",
4922+ "family": "creatures",
4923+ "sha256": "07b5bace96d35e3a483971644f800905d5a2747f64f6a6c24a8107569e66e0af"
4924+ },
4925+ {
4926+ "seed": "sample/838",
4927+ "family": "glyphs",
4928+ "sha256": "318132f3100e9d58226b913af746b53c91135c2163b6560c5018e2995b17934a"
4929+ },
4930+ {
4931+ "seed": "sample/839",
4932+ "family": "machines",
4933+ "sha256": "ef2470184da1b701a6dd56d2f883b84d570204386c00c12e0edd4594e545b25f"
4934+ },
4935+ {
4936+ "seed": "sample/840",
4937+ "family": "machines",
4938+ "sha256": "224f58abb15293c8388a38aafcf51ec227291e11a9c0684fcffb49bcb572c598"
4939+ },
4940+ {
4941+ "seed": "sample/841",
4942+ "family": "creatures",
4943+ "sha256": "631c6c0a2097677ddb0a2a9cb73d67d263f0c6e13bbf10f62fc0f29974fdd2bb"
4944+ },
4945+ {
4946+ "seed": "sample/842",
4947+ "family": "glyphs",
4948+ "sha256": "ca82a47ad46e817adc5be28a1ba50d92c40cf282be48f076298c321404b26731"
4949+ },
4950+ {
4951+ "seed": "sample/843",
4952+ "family": "botanical",
4953+ "sha256": "229d55c16b1eec58c9906bab5932e6f10b45e27dc69a126345e67acbca5bc329"
4954+ },
4955+ {
4956+ "seed": "sample/844",
4957+ "family": "botanical",
4958+ "sha256": "3184ba72fe9c2f5f1426e727dee4ac3a96ee2ed185778e9c69f8f6075dadbb3d"
4959+ },
4960+ {
4961+ "seed": "sample/845",
4962+ "family": "woven",
4963+ "sha256": "f6b29bad9ea03fb53bff94b830121a5699013bb99626d71bc80cd36492be2fc9"
4964+ },
4965+ {
4966+ "seed": "sample/846",
4967+ "family": "masks",
4968+ "sha256": "d3d2b0bf60ec5192591b5b51034ed54b30a548971e6fbd4296b7ed756498a40b"
4969+ },
4970+ {
4971+ "seed": "sample/847",
4972+ "family": "botanical",
4973+ "sha256": "0f9a0be37e19ca719dae548770d62ce3f0573d1b4be9c400dc1902b01dc9f16c"
4974+ },
4975+ {
4976+ "seed": "sample/848",
4977+ "family": "woven",
4978+ "sha256": "fb05197312cc3cd3306a573a80f1bf6f2190ebb7e8d3ea5c0e2ba19b546c7d5e"
4979+ },
4980+ {
4981+ "seed": "sample/849",
4982+ "family": "machines",
4983+ "sha256": "a3eaca3aa2e59c5c7f8fffbb22b6b48f7b48eeca73cc929c88f49a91de10749e"
4984+ },
4985+ {
4986+ "seed": "sample/850",
4987+ "family": "orbital",
4988+ "sha256": "2a39e7fef6badeb678f122157b441a301563bc1cce5c6abb2e1dfad6932cae44"
4989+ },
4990+ {
4991+ "seed": "sample/851",
4992+ "family": "orbital",
4993+ "sha256": "e82cb806e36f40092b30b053aa4e8af77412cb3d4063c4a73259e61e894c504a"
4994+ },
4995+ {
4996+ "seed": "sample/852",
4997+ "family": "creatures",
4998+ "sha256": "efc42eefeac63e56cc1b41aad971c6107ae74372f4a5ec81c53777ee1ff7eb1d"
4999+ },
5000+ {
5001+ "seed": "sample/853",
5002+ "family": "machines",
5003+ "sha256": "cebbaa3a31e653c912f70833f7a5c9bdd6ce30252061c552781013abccadebc0"
5004+ },
5005+ {
5006+ "seed": "sample/854",
5007+ "family": "woven",
5008+ "sha256": "0dc8f61554586b6ec797e4ab79cb3d47440584ee55ae9fe187b9983fc0d56497"
5009+ },
5010+ {
5011+ "seed": "sample/855",
5012+ "family": "orbital",
5013+ "sha256": "ab15a7244a7e51b40f3d1ecab718e7553a855f6ef84e8ff5d1ce6bd1ca34d582"
5014+ },
5015+ {
5016+ "seed": "sample/856",
5017+ "family": "creatures",
5018+ "sha256": "5114468488b1dc4ac1cdf6bef9f121d55d35955a064f7f82e8f679ac0127f36d"
5019+ },
5020+ {
5021+ "seed": "sample/857",
5022+ "family": "creatures",
5023+ "sha256": "64597535fd8d2aea4ef25b9414b4325fd4bce23b0836936f4ddcaa1777cc5a06"
5024+ },
5025+ {
5026+ "seed": "sample/858",
5027+ "family": "glyphs",
5028+ "sha256": "360ff5a92de3eaaef4d41dbe7b5f51b1314019f6acc5be25b72bc8c1af95d94b"
5029+ },
5030+ {
5031+ "seed": "sample/859",
5032+ "family": "masks",
5033+ "sha256": "02cb1e3bb6b6bf0ac7398490f28b17c0808e4abf044dbab0aec3f3cf01fc94e5"
5034+ },
5035+ {
5036+ "seed": "sample/860",
5037+ "family": "machines",
5038+ "sha256": "b5015061f33e1e5abcec3ae299b8582c648cc96c498f6c012e76a2a4037bd15f"
5039+ },
5040+ {
5041+ "seed": "sample/861",
5042+ "family": "orbital",
5043+ "sha256": "7e2d1ef084ef2d901f4b1e892eba7a8e160b4ca2aef3f9fca80087ff81c9f840"
5044+ },
5045+ {
5046+ "seed": "sample/862",
5047+ "family": "orbital",
5048+ "sha256": "f8db962cfadfb01a202d7b3f12a28ecb7851cb67aa53034982635d333143a5ab"
5049+ },
5050+ {
5051+ "seed": "sample/863",
5052+ "family": "orbital",
5053+ "sha256": "aeb9c2b62815b7f8644b668f947ebc96fa4dc08b224befe38e320aa72f08e10d"
5054+ },
5055+ {
5056+ "seed": "sample/864",
5057+ "family": "landscapes",
5058+ "sha256": "b3c097dd94c5256bc6e87463a942cc2721845b4826fb7a64f0230fa8ff013233"
5059+ },
5060+ {
5061+ "seed": "sample/865",
5062+ "family": "landscapes",
5063+ "sha256": "9be5ce477cfaafd32f81a149c7320a7dc0c1a377492f564fdb45a881c08c911c"
5064+ },
5065+ {
5066+ "seed": "sample/866",
5067+ "family": "machines",
5068+ "sha256": "04c1c65a787b69c0c9b0a247148a9dd08ff23c48cc330169d2384d81c695ea74"
5069+ },
5070+ {
5071+ "seed": "sample/867",
5072+ "family": "creatures",
5073+ "sha256": "66d010743169cb754c778cbc0b3a5d3d2ce14121bea333432be29d76741c972f"
5074+ },
5075+ {
5076+ "seed": "sample/868",
5077+ "family": "botanical",
5078+ "sha256": "2ec4125259c4372408e35e7c5d429f07e76b09b3865ed33b9eded070c23cacf6"
5079+ },
5080+ {
5081+ "seed": "sample/869",
5082+ "family": "landscapes",
5083+ "sha256": "e99fc4d9bd9b827f719f20d8c826604c1b9d01bf5a56aedf316de4ae30199350"
5084+ },
5085+ {
5086+ "seed": "sample/870",
5087+ "family": "glyphs",
5088+ "sha256": "edf3a07dc770799d6b66a50317428ee9e6b20e928b6106c83cac4381c870c0ec"
5089+ },
5090+ {
5091+ "seed": "sample/871",
5092+ "family": "creatures",
5093+ "sha256": "ba864a3e31e046896c612577b7488e738126c3cef57eb409976b63e45beeeb92"
5094+ },
5095+ {
5096+ "seed": "sample/872",
5097+ "family": "orbital",
5098+ "sha256": "629f532fbf09e859125c7c4a1e3994c030042f4ae997d4e965bbc0b63f8937fa"
5099+ },
5100+ {
5101+ "seed": "sample/873",
5102+ "family": "orbital",
5103+ "sha256": "76c659e6eb810b7c7bd20dde4c8c0a959e88251363999aed2a473ddeae20eb2e"
5104+ },
5105+ {
5106+ "seed": "sample/874",
5107+ "family": "botanical",
5108+ "sha256": "4499a00a2fd6fa2f4b2778a075f7939f5370e77e5f228ac0e0c276cd16ccb9cf"
5109+ },
5110+ {
5111+ "seed": "sample/875",
5112+ "family": "machines",
5113+ "sha256": "447deaa8c8d2a5e787190ac1ace5d43dfb279d6d76477634d3b982d95b78ca74"
5114+ },
5115+ {
5116+ "seed": "sample/876",
5117+ "family": "orbital",
5118+ "sha256": "309c605e5f4eebd7134c93727289239a959f8aff0882ed1221f9b1664b691090"
5119+ },
5120+ {
5121+ "seed": "sample/877",
5122+ "family": "masks",
5123+ "sha256": "d69c95f29daab9a3a39041c75c12e1ab858996a4f02d35cadd16b72da6f92a5e"
5124+ },
5125+ {
5126+ "seed": "sample/878",
5127+ "family": "botanical",
5128+ "sha256": "9f9d359d1c4cf197ce89fe3b56b1fd4a50e991183fe8f67ad974716d55c70c95"
5129+ },
5130+ {
5131+ "seed": "sample/879",
5132+ "family": "glyphs",
5133+ "sha256": "a0a899d803d48e2ba75fcc92800c0f21e92ee3a0afbfad0ec7f62e0e042f9f17"
5134+ },
5135+ {
5136+ "seed": "sample/880",
5137+ "family": "masks",
5138+ "sha256": "3675ae6d0a6efcf9a8898a55e481426e1d1e95050168e44484ecdc3936602a97"
5139+ },
5140+ {
5141+ "seed": "sample/881",
5142+ "family": "creatures",
5143+ "sha256": "310ab0e328983e3507a702819052d0d7da49b0ed48663492f1949e9343987242"
5144+ },
5145+ {
5146+ "seed": "sample/882",
5147+ "family": "landscapes",
5148+ "sha256": "81c60e3808b50e0eb07ae6c6b55b2893c87975816afa66a2b9d1dddaa4460689"
5149+ },
5150+ {
5151+ "seed": "sample/883",
5152+ "family": "masks",
5153+ "sha256": "a34600deebdfa9328daf6f656b845c77fa6f6e4b6d3d416fad042e7085132ced"
5154+ },
5155+ {
5156+ "seed": "sample/884",
5157+ "family": "botanical",
5158+ "sha256": "6e28cc1128fdc7fa94668c61eb716954011aa0c83d630157d5ae0c84cedf6cc9"
5159+ },
5160+ {
5161+ "seed": "sample/885",
5162+ "family": "woven",
5163+ "sha256": "91f275113088db66560f02e43ee09ba1cf88e21f2fccb27fd4e6f1d0a851111e"
5164+ },
5165+ {
5166+ "seed": "sample/886",
5167+ "family": "machines",
5168+ "sha256": "732b77057d8204ca594692c9999a09512440b90a4b8326a7d29cf44d8568793a"
5169+ },
5170+ {
5171+ "seed": "sample/887",
5172+ "family": "orbital",
5173+ "sha256": "99bc5eaaa561f5212ba32006d426c75a7d4e6f7ec12af1b52456015d2963a4f0"
5174+ },
5175+ {
5176+ "seed": "sample/888",
5177+ "family": "creatures",
5178+ "sha256": "e73f473f9eb3c6815eae9deefbc2e9bc69095f55d5561ef50aded0c82890e72e"
5179+ },
5180+ {
5181+ "seed": "sample/889",
5182+ "family": "orbital",
5183+ "sha256": "5e0a6bfd8d01ab94252659fba319edc5acd1958897127d0bffda45654202566a"
5184+ },
5185+ {
5186+ "seed": "sample/890",
5187+ "family": "landscapes",
5188+ "sha256": "d3ca21e6c2a796354971b2945c1d8b8e470f28826d2201d5029e58d35eeb92ae"
5189+ },
5190+ {
5191+ "seed": "sample/891",
5192+ "family": "creatures",
5193+ "sha256": "65e8696e5268e02fab845ec103600ab1b1e3664aba44184f2e1ed59cee2ac5e5"
5194+ },
5195+ {
5196+ "seed": "sample/892",
5197+ "family": "creatures",
5198+ "sha256": "d094ef5aa92afcb968a5fd019ed8c3e4e18f3b7f1714fab7dfbe0737c5beb2f6"
5199+ },
5200+ {
5201+ "seed": "sample/893",
5202+ "family": "botanical",
5203+ "sha256": "6bc1228d7070822cb8d6f56e7ee7c36463db59d0c3f3831f4c9c63e0242dc514"
5204+ },
5205+ {
5206+ "seed": "sample/894",
5207+ "family": "botanical",
5208+ "sha256": "4746d14bde7dd5c9e678c08a73fe4f221fc78e5953b756cbb0e04fb4c2a557e1"
5209+ },
5210+ {
5211+ "seed": "sample/895",
5212+ "family": "creatures",
5213+ "sha256": "56744d73f3613221539dec85421d890b4729b53e56f3436ffc7a261bb52fa8ac"
5214+ },
5215+ {
5216+ "seed": "sample/896",
5217+ "family": "glyphs",
5218+ "sha256": "32eba8456759972301db45a925c892884819365df54b1e8ed64f53fca1496137"
5219+ },
5220+ {
5221+ "seed": "sample/897",
5222+ "family": "masks",
5223+ "sha256": "9088ff2276bea3b96e11d2449ed3fbd07cecbefe03264b5ef308e6790205bcc9"
5224+ },
5225+ {
5226+ "seed": "sample/898",
5227+ "family": "landscapes",
5228+ "sha256": "c9b7e9394b63c9c82685a9602c7cbdf54a23282080e18e28661c637da0a7147f"
5229+ },
5230+ {
5231+ "seed": "sample/899",
5232+ "family": "landscapes",
5233+ "sha256": "108feb08b16364ba3c5983d505ccf4570d19b9266f2cd11e05f2af9962aac096"
5234+ },
5235+ {
5236+ "seed": "sample/900",
5237+ "family": "masks",
5238+ "sha256": "06a7a4207e804202ca37d5e570a31b6857ad2ce2bcd569744fd5c9a2c9446169"
5239+ },
5240+ {
5241+ "seed": "sample/901",
5242+ "family": "masks",
5243+ "sha256": "3847910e2e0c9bf04e6a6b0a0656fef25f5a6e2aa2faeb39cab27137e6ad93d8"
5244+ },
5245+ {
5246+ "seed": "sample/902",
5247+ "family": "landscapes",
5248+ "sha256": "1456ff2660a009efdd2c2c9ed5c67bfefd38623440832e7972fd81c9121717df"
5249+ },
5250+ {
5251+ "seed": "sample/903",
5252+ "family": "landscapes",
5253+ "sha256": "b4a95bdaf084a622a5363fa930b057ed99358a89666dd93dbe2c411a7d422e60"
5254+ },
5255+ {
5256+ "seed": "sample/904",
5257+ "family": "masks",
5258+ "sha256": "d4d95898e32d6912a1b17daf409c729b52a3f16369756c2a4e0b34131c77e171"
5259+ },
5260+ {
5261+ "seed": "sample/905",
5262+ "family": "machines",
5263+ "sha256": "57630e4a9fe937fae06706231e44ef6c85fdb1014d444829e9c706631bd0958b"
5264+ },
5265+ {
5266+ "seed": "sample/906",
5267+ "family": "glyphs",
5268+ "sha256": "6409370c01127cedfc9ace39f4c60579e37628638754bf51f0260b5090feb8b4"
5269+ },
5270+ {
5271+ "seed": "sample/907",
5272+ "family": "orbital",
5273+ "sha256": "8db001f8bfd317ef3b35b190a731fc5a875b39b5c600f209b0cd474b52d540b0"
5274+ },
5275+ {
5276+ "seed": "sample/908",
5277+ "family": "masks",
5278+ "sha256": "3cd947b709862eacc6b09b1907a716e3809438957e9019bdcf2ff881e27f58ae"
5279+ },
5280+ {
5281+ "seed": "sample/909",
5282+ "family": "creatures",
5283+ "sha256": "a2b01d231c84869cb6971d2149d29dcc0a206319ddcc8c81fdb17224e0ec9b6f"
5284+ },
5285+ {
5286+ "seed": "sample/910",
5287+ "family": "creatures",
5288+ "sha256": "d648f21a337d55b9dea6003f6e39663607f093ec46249833491e8c42ad327408"
5289+ },
5290+ {
5291+ "seed": "sample/911",
5292+ "family": "landscapes",
5293+ "sha256": "ef58d200a5d9cf75b4c56960ccd1d10849338189c0bdfac2363cf467e306c03a"
5294+ },
5295+ {
5296+ "seed": "sample/912",
5297+ "family": "landscapes",
5298+ "sha256": "2289fde89928361e72ab4621d83b7f71276303b8f0e60e638169d6d8e5cab147"
5299+ },
5300+ {
5301+ "seed": "sample/913",
5302+ "family": "woven",
5303+ "sha256": "b7fd72fc21745c8b4004c3649a1ad371fcc083867011900e7db00f04f3ba34e6"
5304+ },
5305+ {
5306+ "seed": "sample/914",
5307+ "family": "landscapes",
5308+ "sha256": "4dd720e5ef32aa1b14a09ece53a8859eb4c0c901b2a8b3d7fb4901af0602790a"
5309+ },
5310+ {
5311+ "seed": "sample/915",
5312+ "family": "machines",
5313+ "sha256": "d5b7ab4fdf29878e4d33ae8f69f6549e67dcc23515cbfbf3b3d934e98f621f95"
5314+ },
5315+ {
5316+ "seed": "sample/916",
5317+ "family": "machines",
5318+ "sha256": "107d098d1d176d0627cad6eab3ae21d114116b252a6b5cf06b756b9494152055"
5319+ },
5320+ {
5321+ "seed": "sample/917",
5322+ "family": "machines",
5323+ "sha256": "3c22aff8f585260c6e374d7b796162dabc0da3a435c954d87f6cb9c1bea8a7ab"
5324+ },
5325+ {
5326+ "seed": "sample/918",
5327+ "family": "woven",
5328+ "sha256": "17affca0188df7d56f4ce51410cc0a9eeb491ddea75f29c8831557e591bb3e63"
5329+ },
5330+ {
5331+ "seed": "sample/919",
5332+ "family": "botanical",
5333+ "sha256": "34b83af2b034293cbe761d3d5f1a08966a185f6c8f649426150d06f98f867d6c"
5334+ },
5335+ {
5336+ "seed": "sample/920",
5337+ "family": "creatures",
5338+ "sha256": "d2a288fa3a5dc72223d8de105ea4ac4dec12006346f2f3edcea77c55369608a2"
5339+ },
5340+ {
5341+ "seed": "sample/921",
5342+ "family": "orbital",
5343+ "sha256": "be0d9c504167ce4654ccc48b2518c6f3344f86992e834b79408d6ff476216ae5"
5344+ },
5345+ {
5346+ "seed": "sample/922",
5347+ "family": "glyphs",
5348+ "sha256": "d5cdaee437cc29df718125a72385a51c103a12cca69fa66433b45a64e62eda31"
5349+ },
5350+ {
5351+ "seed": "sample/923",
5352+ "family": "creatures",
5353+ "sha256": "233eea26b389e8f8e003c1b6737c891953018981f7d1cf3a02af31fe209d71d2"
5354+ },
5355+ {
5356+ "seed": "sample/924",
5357+ "family": "machines",
5358+ "sha256": "80614d7c368e00e05d588960202bb6f7efe3dd7dad90851f33b288ea9a3144ec"
5359+ },
5360+ {
5361+ "seed": "sample/925",
5362+ "family": "botanical",
5363+ "sha256": "1348923280c261de955336e962fbfb39967436b3f1e9196ff7eec17331973136"
5364+ },
5365+ {
5366+ "seed": "sample/926",
5367+ "family": "landscapes",
5368+ "sha256": "c1de4c1b1cd1ceab72c163b62f331bcd8b655d6fda415d263332ed2b37c53edb"
5369+ },
5370+ {
5371+ "seed": "sample/927",
5372+ "family": "botanical",
5373+ "sha256": "e95b00120b16db38fe17b98c939771f58d2b623b5cb663fda9349582d8bed488"
5374+ },
5375+ {
5376+ "seed": "sample/928",
5377+ "family": "masks",
5378+ "sha256": "0615f0a92d9eed7a6313ad68cb454ca638e75a846cdfbd04e74d5a5e456e2c36"
5379+ },
5380+ {
5381+ "seed": "sample/929",
5382+ "family": "glyphs",
5383+ "sha256": "1903a669b5ff07ca9e3140c38f89c8b96da55264b78da13cf10b36bbcb96fdb6"
5384+ },
5385+ {
5386+ "seed": "sample/930",
5387+ "family": "creatures",
5388+ "sha256": "6db19a77a246d9f4f28f25804411e9da4cd45b15862e9b1847e8758d5d98efd3"
5389+ },
5390+ {
5391+ "seed": "sample/931",
5392+ "family": "machines",
5393+ "sha256": "57ee508642f9d48f6fc5c77f759d7fa363785ee1231d9c2233c6e8d8f276e7e3"
5394+ },
5395+ {
5396+ "seed": "sample/932",
5397+ "family": "botanical",
5398+ "sha256": "27687e598003a19c2e27ece5cbee71df4f9ac1cf3d7586a203121f6776c4bc75"
5399+ },
5400+ {
5401+ "seed": "sample/933",
5402+ "family": "woven",
5403+ "sha256": "1eac87dba438dcde11829d1a0e48b5f1f09d953f03772283577c19043471cc84"
5404+ },
5405+ {
5406+ "seed": "sample/934",
5407+ "family": "machines",
5408+ "sha256": "d4bd685e1159f8123d59e27cc24dd2a8b4645f1ab3fc47ec87215ecb88fb4fa3"
5409+ },
5410+ {
5411+ "seed": "sample/935",
5412+ "family": "botanical",
5413+ "sha256": "53bfe342feb8807cfd1e5901bb67201cd25c7c85ec3991f6f99e3fa2ae1480a4"
5414+ },
5415+ {
5416+ "seed": "sample/936",
5417+ "family": "woven",
5418+ "sha256": "1c7d966bc92011c2181c99a77a3cc60092f7ae9f65eb3c6a631405b191b44acd"
5419+ },
5420+ {
5421+ "seed": "sample/937",
5422+ "family": "woven",
5423+ "sha256": "bc3699ab7c7c612e71b39bc2d459e37777dc5ae8296f292ad3ca6ad7115ca4c1"
5424+ },
5425+ {
5426+ "seed": "sample/938",
5427+ "family": "masks",
5428+ "sha256": "06f449154552d79581f6334ebdb038ef2d484f9e995ac88638c6a4c8a919dd67"
5429+ },
5430+ {
5431+ "seed": "sample/939",
5432+ "family": "botanical",
5433+ "sha256": "af3a3b1546e1597311001f2b24adddbdc09f6c999e0a0fb618fa1b244aed7477"
5434+ },
5435+ {
5436+ "seed": "sample/940",
5437+ "family": "machines",
5438+ "sha256": "f0b51a99b6a2bcd7a8082bcf859e2b17b424b3fd9292c12017f2c1a53a6a3c40"
5439+ },
5440+ {
5441+ "seed": "sample/941",
5442+ "family": "landscapes",
5443+ "sha256": "a8f8d1eaf5d58e1b29b976255a6595383fe0b14ec965b0222c49c52e01b306c6"
5444+ },
5445+ {
5446+ "seed": "sample/942",
5447+ "family": "masks",
5448+ "sha256": "c41f751ded0057bb5fd03f836ddd72d6cec536cb7f7cf4035cdcbd25fab5a649"
5449+ },
5450+ {
5451+ "seed": "sample/943",
5452+ "family": "machines",
5453+ "sha256": "4b376316e8ec7466724e3c6de6026ad7ee908f730ae2d57a9a63715706e9a4a4"
5454+ },
5455+ {
5456+ "seed": "sample/944",
5457+ "family": "glyphs",
5458+ "sha256": "b7c1b58bd0548954645d30c65114d818571eb27308c4ed47d1b76c9f2ee0fb24"
5459+ },
5460+ {
5461+ "seed": "sample/945",
5462+ "family": "machines",
5463+ "sha256": "64e7770a9bf7fb542729aece23cee2364cbc52c93322179411851f55c399fc73"
5464+ },
5465+ {
5466+ "seed": "sample/946",
5467+ "family": "machines",
5468+ "sha256": "5284472e2642b459bd7402c55d5a8f6cafba3d9c584760b7ff18be05c048fdef"
5469+ },
5470+ {
5471+ "seed": "sample/947",
5472+ "family": "glyphs",
5473+ "sha256": "01eb4051500ddab1a49e6c41b3c2de5329a943df8894285b4b129fe7aa8478dc"
5474+ },
5475+ {
5476+ "seed": "sample/948",
5477+ "family": "masks",
5478+ "sha256": "7d6569a02ad35e02d59a7250fc84199829bdb0a7f873f62b13eb3b1bbd4e8902"
5479+ },
5480+ {
5481+ "seed": "sample/949",
5482+ "family": "creatures",
5483+ "sha256": "885528a1cc5ebc4ab4db9a423364c117715886694a2f5d5261707d8ecd8b91b1"
5484+ },
5485+ {
5486+ "seed": "sample/950",
5487+ "family": "glyphs",
5488+ "sha256": "75a84788156bf7a1e6bf4c90065e652ff710accc0649056d50d7e74c3f2a2f91"
5489+ },
5490+ {
5491+ "seed": "sample/951",
5492+ "family": "creatures",
5493+ "sha256": "4407cc9af8ec5e9c7816a14c598abb5542df6e66bd1ef1f94dfefaf53d69af56"
5494+ },
5495+ {
5496+ "seed": "sample/952",
5497+ "family": "glyphs",
5498+ "sha256": "67f5c2435952562b90061a996e06801594b82cdcaa4860c9e3d3371a95e05db3"
5499+ },
5500+ {
5501+ "seed": "sample/953",
5502+ "family": "orbital",
5503+ "sha256": "dfb9c11100f1a80f712d8f1b90af45b790837901386cd6e297f92905b56ec263"
5504+ },
5505+ {
5506+ "seed": "sample/954",
5507+ "family": "masks",
5508+ "sha256": "c42a4a418b5a3f4b4cce7d437e95a963c6172152b3ccc46f920ef4b923b8f4ab"
5509+ },
5510+ {
5511+ "seed": "sample/955",
5512+ "family": "woven",
5513+ "sha256": "3780041f61c56041a6f5e5a77508391bb91fea49807b0c7565623c979e3c3a6a"
5514+ },
5515+ {
5516+ "seed": "sample/956",
5517+ "family": "botanical",
5518+ "sha256": "5584f9c39bb87cc832662a5ac24414444776ffe9f1bb8106f99de8f2bb12ed2d"
5519+ },
5520+ {
5521+ "seed": "sample/957",
5522+ "family": "orbital",
5523+ "sha256": "71f2273257ea336ebef37d432e7b93a8ca69e1dafd09ce7d0f4b42508e98823e"
5524+ },
5525+ {
5526+ "seed": "sample/958",
5527+ "family": "masks",
5528+ "sha256": "56867583f4ec1c5323587b15cde46420a424369e9215e6bdd03184df18a63ae6"
5529+ },
5530+ {
5531+ "seed": "sample/959",
5532+ "family": "glyphs",
5533+ "sha256": "2eecab6a91051185e1967eeb6e537ce122fac02bec989d92c44487211d515c70"
5534+ },
5535+ {
5536+ "seed": "sample/960",
5537+ "family": "masks",
5538+ "sha256": "168e17bffed425fc7dc0f4b04b77d9c73a647480eb00de65199365db17cb2c82"
5539+ },
5540+ {
5541+ "seed": "sample/961",
5542+ "family": "masks",
5543+ "sha256": "1d5785c4410894535309dd22902e29ea9a35f28ae7c525d3e2b2a8aee79872ef"
5544+ },
5545+ {
5546+ "seed": "sample/962",
5547+ "family": "orbital",
5548+ "sha256": "5165e0d44995d28632c9d461541eea33cadb23c87f405eb341862e4909306d93"
5549+ },
5550+ {
5551+ "seed": "sample/963",
5552+ "family": "machines",
5553+ "sha256": "64ab1ab773a297ed5cfb97c2a348ef17dc4d3d968ecfb288d87bb29f2e2bf32f"
5554+ },
5555+ {
5556+ "seed": "sample/964",
5557+ "family": "glyphs",
5558+ "sha256": "f0ef55e4e57c811966a183c04cf8fdd7cc326f086e3d3cef7bc8294faf4cb07e"
5559+ },
5560+ {
5561+ "seed": "sample/965",
5562+ "family": "orbital",
5563+ "sha256": "8db3c63e99a8ac26b7ba1e908a98357d949c9407f3fccc8e17b490dcbb461c06"
5564+ },
5565+ {
5566+ "seed": "sample/966",
5567+ "family": "landscapes",
5568+ "sha256": "99dbcfca2df2a00245b86061e4086a2bebb5c4d0f78b46f9896a703f973052f1"
5569+ },
5570+ {
5571+ "seed": "sample/967",
5572+ "family": "machines",
5573+ "sha256": "c802583dacb0f3bba62e3695d5397bb3ac7fd55e9736c1a3cb6cb0ee2681a064"
5574+ },
5575+ {
5576+ "seed": "sample/968",
5577+ "family": "botanical",
5578+ "sha256": "aadd300f91bba8d89bd8b2feaf28fd8420a6d2b6866fcb2c3e39ffee03a404fb"
5579+ },
5580+ {
5581+ "seed": "sample/969",
5582+ "family": "glyphs",
5583+ "sha256": "27397122b333288b5297d7a69f607c11831a76c9da3c4d517a766de1a97b534c"
5584+ },
5585+ {
5586+ "seed": "sample/970",
5587+ "family": "landscapes",
5588+ "sha256": "dbdde070747064ab64572bd343873cb79212a7ad02cdee5be5e86fafa8a63701"
5589+ },
5590+ {
5591+ "seed": "sample/971",
5592+ "family": "landscapes",
5593+ "sha256": "95bac1580a1bbd76638e5f97c3df1b3afe8d93fa1738b1f317b3f09579cd814e"
5594+ },
5595+ {
5596+ "seed": "sample/972",
5597+ "family": "creatures",
5598+ "sha256": "343532e6cc05c648e2478e59fe12cc035e420016d0daf6fcb27defbc14e92a8b"
5599+ },
5600+ {
5601+ "seed": "sample/973",
5602+ "family": "creatures",
5603+ "sha256": "01362a9fcb23ea9a10280666a7cc347d80f955b098c27c082927784c13b4b961"
5604+ },
5605+ {
5606+ "seed": "sample/974",
5607+ "family": "masks",
5608+ "sha256": "d73cd55d4bdbd7e16852052aceb7c8fb29e140162ad70eff2bbdbf001cd2e2b7"
5609+ },
5610+ {
5611+ "seed": "sample/975",
5612+ "family": "masks",
5613+ "sha256": "bf800833a20cf6de4486703d2de4c149560004adaa417049c218bebabdd61a9e"
5614+ },
5615+ {
5616+ "seed": "sample/976",
5617+ "family": "machines",
5618+ "sha256": "6b219df5411a4833434a6ade962cff67312079084bcd51e59189ea6c2a1e4856"
5619+ },
5620+ {
5621+ "seed": "sample/977",
5622+ "family": "creatures",
5623+ "sha256": "c9a16fc9ccfcdc2a437468896451f8d9162c826a5138a603d0408e42cec800d0"
5624+ },
5625+ {
5626+ "seed": "sample/978",
5627+ "family": "orbital",
5628+ "sha256": "b008522d0ddd57c3a0204d7922c38c7bee15752d01889ffa9f7e66473c552db6"
5629+ },
5630+ {
5631+ "seed": "sample/979",
5632+ "family": "masks",
5633+ "sha256": "6710193091b33d688b63ab162ef7dc6bcfe9e2c532d4f5fdb2531f45c7143a41"
5634+ },
5635+ {
5636+ "seed": "sample/980",
5637+ "family": "woven",
5638+ "sha256": "4e3a384dd3a7500c4bf7455e2ccfd2ac9e6cdeb439a7c1de814cd31ef1f8985e"
5639+ },
5640+ {
5641+ "seed": "sample/981",
5642+ "family": "masks",
5643+ "sha256": "c44534d3dd0efae32fbf3e6dc425429b35d52a0b08c6e929033a8359fc4ab78d"
5644+ },
5645+ {
5646+ "seed": "sample/982",
5647+ "family": "machines",
5648+ "sha256": "d3dee66113ab7dfcc6c5f5d44aa0bc2b786ec2f1636cc145c2ab232775554fd5"
5649+ },
5650+ {
5651+ "seed": "sample/983",
5652+ "family": "landscapes",
5653+ "sha256": "cf02dfb57222f3351c4a3d88165e8b2acb4f7d063522ca78a11a406e9ce044c1"
5654+ },
5655+ {
5656+ "seed": "sample/984",
5657+ "family": "machines",
5658+ "sha256": "5b93143cc93d67e4da74108b0a49f226850a9fd2d197594825e646ecc1ad7a94"
5659+ },
5660+ {
5661+ "seed": "sample/985",
5662+ "family": "masks",
5663+ "sha256": "db4af2740fb0903c96f1d06f4281dcdc06875fce0b629fb2c017c50d6269aef0"
5664+ },
5665+ {
5666+ "seed": "sample/986",
5667+ "family": "orbital",
5668+ "sha256": "4f5f4d9f43e8a3674dbbc6f1cf06ffb78d659b4dc798fbd8db453f49c85bde8b"
5669+ },
5670+ {
5671+ "seed": "sample/987",
5672+ "family": "landscapes",
5673+ "sha256": "d8e6b9734639654c5ac9ccf3a47b88f3e9bdf32e4e5778ac48a472b41187e6e0"
5674+ },
5675+ {
5676+ "seed": "sample/988",
5677+ "family": "machines",
5678+ "sha256": "26679fa54594e4c77fba19fedc3d04ea53db8167b630f85c46877ed0ca20d004"
5679+ },
5680+ {
5681+ "seed": "sample/989",
5682+ "family": "glyphs",
5683+ "sha256": "9ade78ac80d05eee2681e5b14dc5e8bcb3bd3f725430907b106644ba69050004"
5684+ },
5685+ {
5686+ "seed": "sample/990",
5687+ "family": "creatures",
5688+ "sha256": "158727cb735313ef8c1f499b0f86831cb0ec93dd49feb6816e250bb8705d70db"
5689+ },
5690+ {
5691+ "seed": "sample/991",
5692+ "family": "woven",
5693+ "sha256": "c71802627ff56c703c726a86e07575003e070cb0c120e6e5ff8a2889972d1ed6"
5694+ },
5695+ {
5696+ "seed": "sample/992",
5697+ "family": "creatures",
5698+ "sha256": "060a1a862104402ca8b34dbdac876f04b15c7da788f163ea564ccac962b6c6a5"
5699+ },
5700+ {
5701+ "seed": "sample/993",
5702+ "family": "masks",
5703+ "sha256": "9dd80a6af66afca2ea6426562b9400a4203e8d119f6f226ab0b865ff894092ae"
5704+ },
5705+ {
5706+ "seed": "sample/994",
5707+ "family": "landscapes",
5708+ "sha256": "4286df75a86f8ad2117cd5944363568de028c9b54af5cf7d8539aa5e513652c0"
5709+ },
5710+ {
5711+ "seed": "sample/995",
5712+ "family": "landscapes",
5713+ "sha256": "fdf5688aa1bf9c9eeb0f15ed689987880800d2fff05416424639862fd7c55b11"
5714+ },
5715+ {
5716+ "seed": "sample/996",
5717+ "family": "machines",
5718+ "sha256": "f3b734f00488830f868a61d17627393fe0c2fddf1eeef9606fdd52662aaa26e1"
5719+ },
5720+ {
5721+ "seed": "sample/997",
5722+ "family": "masks",
5723+ "sha256": "f8c87fe51767ed34c44373b6825e72d75e1b0bbd8deb72c94d82d85581a26632"
5724+ },
5725+ {
5726+ "seed": "sample/998",
5727+ "family": "orbital",
5728+ "sha256": "404dec5d4611385140016ff3aa88370e57bfa67c9d6add52352a8674efce2899"
5729+ },
5730+ {
5731+ "seed": "sample/999",
5732+ "family": "masks",
5733+ "sha256": "b4ca1a8ed1d4ae09a4976e55f9ebe512a05be38a42634d0b3fe5efca135ffa99"
5734+ }
5735+]
5736diff --git a/internal/webui/avatars.go b/internal/webui/avatars.go
5737new file mode 100644
5738index 0000000..a78d36b
5739--- /dev/null
5740+++ b/internal/webui/avatars.go
5741@@ -0,0 +1,47 @@
5742+package webui
5743+
5744+import (
5745+ "crypto/sha256"
5746+ "fmt"
5747+ "net/http"
5748+ "regexp"
5749+ "strings"
5750+ "time"
5751+
5752+ "github.com/FelineStateMachine/tinyrelay/internal/seedmark"
5753+)
5754+
5755+var avatarPath = regexp.MustCompile(`^/avatars/v1/([0-9a-f]{64})\.svg$`)
5756+
5757+func avatarURL(pubkey string) string {
5758+ key := strings.ToLower(pubkey)
5759+ if !eventIDPattern.MatchString(key) {
5760+ key = strings.Repeat("0", 64)
5761+ }
5762+ return "/avatars/v1/" + key + ".svg"
5763+}
5764+
5765+func roomAvatarURL(relay, id string) string {
5766+ seed := sha256.Sum256([]byte("tinyrelay:room:v1\x00" + strings.TrimRight(relay, "/") + "\x00" + id))
5767+ return avatarURL(fmt.Sprintf("%x", seed))
5768+}
5769+
5770+// Avatars depend only on the supplied seed and never look up tenant, room or
5771+// profile data. Versioned URLs keep each identity's appearance stable.
5772+func serveAvatar(w http.ResponseWriter, r *http.Request) {
5773+ if r.Method != http.MethodGet && r.Method != http.MethodHead {
5774+ w.Header().Set("Allow", "GET, HEAD")
5775+ http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
5776+ return
5777+ }
5778+ match := avatarPath.FindStringSubmatch(r.URL.Path)
5779+ if match == nil {
5780+ http.NotFound(w, r)
5781+ return
5782+ }
5783+ w.Header().Set("Content-Type", "image/svg+xml; charset=utf-8")
5784+ w.Header().Set("X-Content-Type-Options", "nosniff")
5785+ w.Header().Set("Cache-Control", "public, max-age=31536000, immutable")
5786+ w.Header().Set("ETag", `"seedmark-v1-`+match[1]+`"`)
5787+ http.ServeContent(w, r, "avatar.svg", time.Time{}, strings.NewReader(seedmark.Avatar(match[1])))
5788+}
5789diff --git a/internal/webui/avatars_test.go b/internal/webui/avatars_test.go
5790new file mode 100644
5791index 0000000..8178ee3
5792--- /dev/null
5793+++ b/internal/webui/avatars_test.go
5794@@ -0,0 +1,78 @@
5795+package webui
5796+
5797+import (
5798+ "net/http"
5799+ "net/http/httptest"
5800+ "strings"
5801+ "testing"
5802+
5803+ "github.com/FelineStateMachine/tinyrelay/internal/policy"
5804+ "github.com/FelineStateMachine/tinyrelay/internal/seedmark"
5805+)
5806+
5807+func TestAvatarEndpointRendersWithoutProfileAccess(t *testing.T) {
5808+ backend := &fakeBackend{policy: policy.Defaults(strings.Repeat("a", 64))}
5809+ backend.policy.Features.Grasp08 = true
5810+ app, err := New(backend, Options{})
5811+ if err != nil {
5812+ t.Fatal(err)
5813+ }
5814+ key := strings.Repeat("b", 64)
5815+ path := avatarURL(key)
5816+ response := httptest.NewRecorder()
5817+ app.ServeHTTP(response, httptest.NewRequest(http.MethodGet, path, nil))
5818+ if response.Code != http.StatusOK || response.Body.String() != seedmark.Avatar(key) {
5819+ t.Fatalf("avatar: status=%d body=%s", response.Code, response.Body.String())
5820+ }
5821+ if backend.call != "" || response.Header().Get("Content-Type") != "image/svg+xml; charset=utf-8" || !strings.Contains(response.Header().Get("Cache-Control"), "immutable") {
5822+ t.Fatalf("avatar accessed relay data or lacks image caching: call=%q headers=%v", backend.call, response.Header())
5823+ }
5824+ for _, method := range []string{http.MethodHead, http.MethodGet} {
5825+ request := httptest.NewRequest(method, path, nil)
5826+ if method == http.MethodGet {
5827+ request.Header.Set("If-None-Match", response.Header().Get("ETag"))
5828+ }
5829+ next := httptest.NewRecorder()
5830+ app.ServeHTTP(next, request)
5831+ if next.Body.Len() != 0 || (method == http.MethodHead && next.Code != http.StatusOK) || (method == http.MethodGet && next.Code != http.StatusNotModified) {
5832+ t.Fatalf("%s cache response: status=%d body=%s", method, next.Code, next.Body.String())
5833+ }
5834+ }
5835+}
5836+
5837+func TestAvatarEndpointRejectsOtherVersionsSeedsAndWrites(t *testing.T) {
5838+ app, err := New(&fakeBackend{policy: policy.Defaults(strings.Repeat("a", 64))}, Options{})
5839+ if err != nil {
5840+ t.Fatal(err)
5841+ }
5842+ for _, tc := range []struct {
5843+ method, path string
5844+ status int
5845+ }{
5846+ {http.MethodGet, "/avatars/v2/" + strings.Repeat("a", 64) + ".svg", http.StatusNotFound},
5847+ {http.MethodGet, "/avatars/v1/short.svg", http.StatusNotFound},
5848+ {http.MethodGet, "/avatars/v1/" + strings.Repeat("g", 64) + ".svg", http.StatusNotFound},
5849+ {http.MethodGet, "/avatars/v1/" + strings.Repeat("a", 64) + ".png", http.StatusNotFound},
5850+ {http.MethodPost, avatarURL(strings.Repeat("a", 64)), http.StatusMethodNotAllowed},
5851+ } {
5852+ response := httptest.NewRecorder()
5853+ app.ServeHTTP(response, httptest.NewRequest(tc.method, tc.path, nil))
5854+ if response.Code != tc.status {
5855+ t.Errorf("%s %s: status=%d, want %d", tc.method, tc.path, response.Code, tc.status)
5856+ }
5857+ }
5858+}
5859+
5860+func TestAvatarSeedsUseFullKeysAndRoomIdentity(t *testing.T) {
5861+ key := strings.Repeat("ab", 32)
5862+ if avatarURL(strings.ToUpper(key)) != avatarURL(key) || avatarURL(key) == avatarURL(key[:62]+"cd") {
5863+ t.Fatal("profile seed must use the full normalized key")
5864+ }
5865+ if avatarURL("invalid") != "/avatars/v1/"+strings.Repeat("0", 64)+".svg" {
5866+ t.Fatal("invalid keys should use the anonymous fallback")
5867+ }
5868+ room := roomAvatarURL("https://relay.test/r/team", "general")
5869+ if room != roomAvatarURL("https://relay.test/r/team/", "general") || room == roomAvatarURL("https://relay.test/r/other", "general") || room == roomAvatarURL("https://relay.test/r/team", "random") {
5870+ t.Fatal("room avatars must follow stable relay and room identity")
5871+ }
5872+}
5873diff --git a/internal/webui/chat.js b/internal/webui/chat.js
5874index 19c4cb0..5f65b70 100644
5875--- a/internal/webui/chat.js
5876+++ b/internal/webui/chat.js
5877@@ -116,7 +116,7 @@
5878 const messages = (value, peer) => chronological(value).filter(rumor => [14, 15].includes(rumor.kind) && !deleted(value, rumor) && (!peer || peerFor(rumor, value.actor) === peer));
5879 const profile = pubkey => {
5880 const author = node("span"); author.setAttribute("data-author", "");
5881- const avatar = node("nostr-avatar", pubkey.slice(0, 2)); avatar.setAttribute("pubkey", pubkey); avatar.setAttribute("aria-hidden", "true");
5882+ const avatar = node("nostr-avatar"); avatar.setAttribute("pubkey", pubkey); avatar.setAttribute("aria-hidden", "true");
5883 const name = node("nostr-name", pubkey.slice(0, 8)); name.setAttribute("pubkey", pubkey);
5884 author.append(avatar, name); return author;
5885 };
5886diff --git a/internal/webui/components.js b/internal/webui/components.js
5887index f26b5cd..9ad41db 100644
5888--- a/internal/webui/components.js
5889+++ b/internal/webui/components.js
5890@@ -768,18 +768,32 @@
5891
5892 render() {
5893 const pubkey = String(this.getAttribute("pubkey") || "").toLowerCase();
5894- const fallback = pubkey.slice(0, 2).toUpperCase();
5895+ const valid = /^[0-9a-f]{64}$/.test(pubkey);
5896+ const seed = valid ? pubkey : "0".repeat(64);
5897+ const fallback = tiny.localPath ? tiny.localPath("/avatars/v1/" + seed + ".svg") : "/avatars/v1/" + seed + ".svg";
5898 const serial = (this.serial || 0) + 1;
5899 this.serial = serial;
5900+ const changed = this.renderedPubkey !== undefined && this.renderedPubkey !== pubkey;
5901+ this.renderedPubkey = pubkey;
5902 const restore = () => {
5903 if (serial !== this.serial) return;
5904- this.replaceChildren(document.createTextNode(fallback));
5905+ const image = el("img");
5906+ image.src = fallback;
5907+ image.alt = "";
5908+ image.loading = "lazy";
5909+ image.referrerPolicy = "no-referrer";
5910+ image.setAttribute("aria-hidden", "true");
5911+ this.replaceChildren(image);
5912 };
5913- const load = window.tinyNames?.load;
5914- if (!load || !/^[0-9a-f]{64}$/.test(pubkey)) {
5915+ const current = this.querySelector("img");
5916+ if (!valid) {
5917 restore();
5918 return;
5919 }
5920+ if (changed || !current) restore();
5921+ else current.addEventListener("error", restore, {once: true});
5922+ const load = window.tinyNames?.load;
5923+ if (!load) return;
5924 Promise.resolve(load({pubkey, refresh: true})).then(user => {
5925 const raw = user?.image;
5926 let url;
5927@@ -800,6 +814,56 @@
5928 }
5929 }
5930
5931+ class RoomAvatar extends HTMLElement {
5932+ static get observedAttributes() { return ["picture", "fallback"]; }
5933+
5934+ connectedCallback() { this.render(); }
5935+
5936+ attributeChangedCallback() { this.render(); }
5937+
5938+ render(forceFallback = false) {
5939+ const serial = (this.serial || 0) + 1;
5940+ this.serial = serial;
5941+ let picture;
5942+ try {
5943+ const raw = this.getAttribute("picture") || "";
5944+ if (/^https?:\/\/\S+$/i.test(raw)) {
5945+ const candidate = new URL(raw);
5946+ picture = candidate.href;
5947+ }
5948+ } catch {}
5949+ let fallback;
5950+ try {
5951+ const candidate = new URL(this.getAttribute("fallback") || "", location.href);
5952+ if (candidate.origin === location.origin && /^(?:\/avatars|\/r\/[^/]+\/avatars)\/v1\/[0-9a-f]{64}\.svg$/.test(candidate.pathname)) fallback = candidate.href;
5953+ } catch {}
5954+ const src = forceFallback ? fallback : picture || fallback;
5955+ const current = this.querySelector("img");
5956+ if (current && current.src === src) {
5957+ if (picture && !forceFallback) {
5958+ if (current.complete && current.naturalWidth === 0) this.render(true);
5959+ else current.addEventListener("error", () => this.restore(serial), {once: true});
5960+ }
5961+ return;
5962+ }
5963+ this.replaceChildren();
5964+ if (!src) return;
5965+ const image = el("img");
5966+ image.src = src;
5967+ image.alt = "";
5968+ image.loading = "lazy";
5969+ image.referrerPolicy = "no-referrer";
5970+ image.setAttribute("aria-hidden", "true");
5971+ if (picture && !forceFallback) image.addEventListener("error", () => this.restore(serial), {once: true});
5972+ this.append(image);
5973+ }
5974+
5975+ restore(serial) {
5976+ if (serial !== this.serial) return;
5977+ this.render(true);
5978+ }
5979+ }
5980+
5981 // PageLink is the crumb that names the current page. A tap copies the
5982 // page's public address, the one the server put in url, and shows
5983 // "copied" for a moment. Without JavaScript it is plain text.
5984@@ -1639,6 +1703,7 @@
5985 customElements.define("share-link", ShareLink);
5986 customElements.define("nostr-key", NostrKey);
5987 customElements.define("nostr-avatar", NostrAvatar);
5988+ customElements.define("room-avatar", RoomAvatar);
5989 customElements.define("page-link", PageLink);
5990 customElements.define("json-view", JsonView);
5991
5992diff --git a/internal/webui/group_avatars_test.go b/internal/webui/group_avatars_test.go
5993new file mode 100644
5994index 0000000..205f03e
5995--- /dev/null
5996+++ b/internal/webui/group_avatars_test.go
5997@@ -0,0 +1,76 @@
5998+package webui
5999+
6000+import (
6001+ "context"
6002+ "encoding/json"
6003+ "net/http"
6004+ "net/http/httptest"
6005+ "strings"
6006+ "testing"
6007+
6008+ "github.com/FelineStateMachine/tinyrelay/internal/policy"
6009+)
6010+
6011+type pictureRoomsBackend struct{ *roomsBackend }
6012+
6013+func (b *pictureRoomsBackend) Query(ctx context.Context, method string, params []json.RawMessage, actor string) (any, error) {
6014+ result, err := b.roomsBackend.Query(ctx, method, params, actor)
6015+ if err != nil {
6016+ return result, err
6017+ }
6018+ page, ok := result.(map[string]any)
6019+ if !ok {
6020+ return result, nil
6021+ }
6022+ if method == "browserooms" {
6023+ for _, item := range page["items"].([]any) {
6024+ item.(map[string]any)["picture"] = "https://cdn.example/general.png"
6025+ }
6026+ } else if room, ok := page["room"].(map[string]any); ok {
6027+ room["picture"] = "https://cdn.example/general.png"
6028+ }
6029+ return page, nil
6030+}
6031+
6032+func TestRoomSurfacesRenderStableSeedmarkFallbackAvatars(t *testing.T) {
6033+ app, _ := roomsApp(t, roomOwner)
6034+ for _, path := range []string{"/chat", "/rooms/general", "/rooms/general/thread/" + roomThread} {
6035+ body := roomsPage(t, app, path)
6036+ if !strings.Contains(body, `fallback="/avatars/v1/`) {
6037+ t.Fatalf("%s has no Seedmark room fallback: %s", path, body)
6038+ }
6039+ if strings.Count(body, "<room-avatar") == 0 {
6040+ t.Fatalf("%s has no room avatar element", path)
6041+ }
6042+ }
6043+}
6044+
6045+func TestRoomAvatarSeedAndTenantScoping(t *testing.T) {
6046+ first := roomAvatarURL("https://relay.example", "general")
6047+ if first == "" || first != roomAvatarURL("https://relay.example", "general") {
6048+ t.Fatalf("room avatar URL is not stable: %q", first)
6049+ }
6050+ if first == roomAvatarURL("https://relay.example", "build") {
6051+ t.Fatal("different room IDs share an avatar URL")
6052+ }
6053+ if scoped := injectBase(`<room-avatar fallback="`+first+`"><img src="`+first+`"></room-avatar>`, "/r/alice"); !strings.Contains(scoped, `fallback="/r/alice`+first+`"`) || !strings.Contains(scoped, `src="/r/alice`+first+`"`) {
6054+ t.Fatalf("tenant prefix missed room avatar URL: %s", scoped)
6055+ }
6056+}
6057+
6058+func TestRoomAvatarUsesValidatedPictureForSSR(t *testing.T) {
6059+ base := &roomsBackend{fakeBackend: fakeBackend{policy: policy.Defaults(roomOwner)}}
6060+ app, err := New(&pictureRoomsBackend{roomsBackend: base}, Options{Actor: func(*http.Request) (string, error) { return roomOwner, nil }})
6061+ if err != nil {
6062+ t.Fatal(err)
6063+ }
6064+ recorder := httptest.NewRecorder()
6065+ app.ServeHTTP(recorder, httptest.NewRequest(http.MethodGet, "/rooms/general", nil))
6066+ if recorder.Code != http.StatusOK {
6067+ t.Fatalf("status = %d", recorder.Code)
6068+ }
6069+ body := recorder.Body.String()
6070+ if !strings.Contains(body, `picture="https://cdn.example/general.png"`) || !strings.Contains(body, `<img src="https://cdn.example/general.png"`) {
6071+ t.Fatalf("validated room picture was not preferred in SSR: %s", body)
6072+ }
6073+}
6074diff --git a/internal/webui/page.html b/internal/webui/page.html
6075index 6c4aea5..fbe8250 100644
6076--- a/internal/webui/page.html
6077+++ b/internal/webui/page.html
6078@@ -110,7 +110,7 @@ then feature modules are loaded for the current page. */}}
6079 {{if .Actor}}<h4>Direct chats</h4><direct-chats actor="{{.Actor}}" relay="{{wsURL .URL}}" compact><p>Connect your signer to see direct chats.</p></direct-chats>
6080 <p><a href="/chat#new-chat">+ new chat</a></p>{{end}}
6081 <h4>Rooms</h4>
6082-<nav id="room-list">{{range .Rooms}}{{$r := asMap .}}<a href="/rooms/{{str (index $r "id")}}"{{if eq (str (index $r "id")) $.View}} aria-current="page"{{end}}>{{or (str (index $r "name")) (str (index $r "id"))}}{{with age (index $r "last_message_at")}} <small>{{.}}</small>{{end}}</a>{{else}}<a href="/chat">Browse rooms</a>{{end}}</nav>
6083+<nav id="room-list">{{range .Rooms}}{{$r := asMap .}}{{$id := str (index $r "id")}}{{$picture := socialMediaURL (str (index $r "picture"))}}<a href="/rooms/{{$id}}"{{if eq $id $.View}} aria-current="page"{{end}}><room-avatar picture="{{$picture}}" fallback="{{roomAvatarURL $.URL $id}}" aria-hidden="true"><img src="{{if $picture}}{{$picture}}{{else}}{{roomAvatarURL $.URL $id}}{{end}}" alt="" width="24" height="24" loading="lazy"></room-avatar>{{or (str (index $r "name")) $id}}{{with age (index $r "last_message_at")}} <small>{{.}}</small>{{end}}</a>{{else}}<a href="/chat">Browse rooms</a>{{end}}</nav>
6084 <p><a href="/chat#new-room">+ new room</a></p>
6085 {{else}}<header><span><a id="mark" href="/" title="{{.Slug}}"><i>t</i><i>i</i><i>n</i><i>y</i></a></span></header>
6086 {{range $group := navGroups relayItems}}<nav>{{range $item := $group}}<a href="{{$item.Href}}"{{if eq $item.Tab $.Tab}} aria-current="page"{{end}}>{{$item.Label}}</a>{{end}}</nav>{{end}}{{if .Actor}}<p id="personal-nav"><a href="/account"{{if eq .Tab "account"}} aria-current="page"{{end}}>account</a></p>{{end}}
6087diff --git a/internal/webui/prefix.go b/internal/webui/prefix.go
6088index fe0cf5d..25c0103 100644
6089--- a/internal/webui/prefix.go
6090+++ b/internal/webui/prefix.go
6091@@ -7,7 +7,7 @@ import (
6092 "golang.org/x/net/html"
6093 )
6094
6095-var rootURLAttribute = regexp.MustCompile(`\s(?:href|src|fx-action|action|data)="(/[^\"]*)"`)
6096+var rootURLAttribute = regexp.MustCompile(`\s(?:href|src|fx-action|action|data|fallback)="(/[^\"]*)"`)
6097
6098 // injectBase scopes root-relative template URLs without changing scripts or
6099 // literal content. The signer bridge scopes its requests with localPath.
6100diff --git a/internal/webui/prefix_test.go b/internal/webui/prefix_test.go
6101index 09bff56..a21083b 100644
6102--- a/internal/webui/prefix_test.go
6103+++ b/internal/webui/prefix_test.go
6104@@ -14,6 +14,7 @@ func TestInjectBasePreservesExternalURLsAndContent(t *testing.T) {
6105 {"external image", `<img src="//example.org/icon.png">`, `<img src="//example.org/icon.png">`},
6106 {"already scoped", `<a href="/r/alice/files">files</a>`, `<a href="/r/alice/files">files</a>`},
6107 {"script source", `<script src="/fixi.js"></script>`, `<script src="/r/alice/fixi.js"></script>`},
6108+ {"room avatar fallback", `<room-avatar fallback="/avatars/v1/avatar.svg"><img src="/avatars/v1/avatar.svg"></room-avatar>`, `<room-avatar fallback="/r/alice/avatars/v1/avatar.svg"><img src="/r/alice/avatars/v1/avatar.svg"></room-avatar>`},
6109 {"script text", `<script>const example = ' href="/example"';</script>`, `<script>const example = ' href="/example"';</script>`},
6110 {"textarea", `<textarea> href="/example"</textarea>`, `<textarea> href="/example"</textarea>`},
6111 {"local action", `<button fx-action="/connect/fragment">preview</button>`, `<button fx-action="/r/alice/connect/fragment">preview</button>`},
6112diff --git a/internal/webui/rooms.go b/internal/webui/rooms.go
6113index 9e448ee..3feac73 100644
6114--- a/internal/webui/rooms.go
6115+++ b/internal/webui/rooms.go
6116@@ -288,13 +288,13 @@ func clock(value any) string {
6117 // roomItem is one message as the page shows it: the event's fields, the
6118 // author's markers, the thread state and the reactions it has received.
6119 type roomItem struct {
6120- ID, PubKey, Avatar, Kind, Content, Room, Root, Quote, Role, Operator, Notice string
6121- CreatedAt, UpdatedAt int64
6122- Agent, InThread, Edited, Own bool
6123- Mentions []string
6124- Replies int
6125- Reactions []reaction
6126- Attachments []roomAttachment
6127+ ID, PubKey, Kind, Content, Room, Root, Quote, Role, Operator, Notice string
6128+ CreatedAt, UpdatedAt int64
6129+ Agent, InThread, Edited, Own bool
6130+ Mentions []string
6131+ Replies int
6132+ Reactions []reaction
6133+ Attachments []roomAttachment
6134 }
6135
6136 // roomItems turns a browse result's messages or replies into view items,
6137@@ -376,9 +376,6 @@ func newRoomItem(row any, room string, members map[string]map[string]any) (roomI
6138 case "9", "12":
6139 item.Root = webRoomReplyRoot(row)
6140 }
6141- if len(item.PubKey) >= 2 {
6142- item.Avatar = strings.ToUpper(item.PubKey[:2])
6143- }
6144 if member := members[item.PubKey]; member != nil {
6145 item.Role = plainString(member["role"])
6146 item.Agent, _ = member["agent"].(bool)
6147diff --git a/internal/webui/rooms.html b/internal/webui/rooms.html
6148index 145f737..96ffe9a 100644
6149--- a/internal/webui/rooms.html
6150+++ b/internal/webui/rooms.html
6151@@ -9,7 +9,7 @@ establishes the initial state. */}}
6152 {{else if .Feed}}<table id="rows">
6153 <thead><tr><th>room</th><th>access</th><th>members</th><th>last message</th></tr></thead>
6154 <tbody>
6155-{{range .Feed}}{{$r := asMap .}}<tr><td><a href="/rooms/{{str (index $r "id")}}">{{or (str (index $r "name")) (str (index $r "id"))}}</a></td><td>{{if eq (str (index $r "access")) "members"}}members only{{else}}open{{end}}{{with str (index $r "about")}} <small>{{.}}</small>{{end}}</td><td>{{str (index $r "members")}}</td><td>{{with index $r "last_message_at"}}<time datetime="{{datetime .}}">{{when .}}</time>{{else}}no messages{{end}}</td></tr>
6156+{{range .Feed}}{{$r := asMap .}}{{$id := str (index $r "id")}}{{$picture := socialMediaURL (str (index $r "picture"))}}<tr><td><a href="/rooms/{{$id}}"><room-avatar picture="{{$picture}}" fallback="{{roomAvatarURL $.URL $id}}" aria-hidden="true"><img src="{{if $picture}}{{$picture}}{{else}}{{roomAvatarURL $.URL $id}}{{end}}" alt="" width="32" height="32" loading="lazy"></room-avatar>{{or (str (index $r "name")) $id}}</a></td><td>{{if eq (str (index $r "access")) "members"}}members only{{else}}open{{end}}{{with str (index $r "about")}} <small>{{.}}</small>{{end}}</td><td>{{str (index $r "members")}}</td><td>{{with index $r "last_message_at"}}<time datetime="{{datetime .}}">{{when .}}</time>{{else}}no messages{{end}}</td></tr>
6157 {{end}}</tbody>
6158 </table>
6159 {{else}}<p>No rooms yet.</p>
6160@@ -26,8 +26,8 @@ establishes the initial state. */}}
6161 {{template "alert" .Error}}
6162 {{if not .Actor}}<p><a href="{{signinURL .Base .Path .Query}}">Sign in</a> to read this room.</p>{{end}}
6163 </section>
6164-{{else}}{{$data := asMap .Event}}{{$room := asMap (index $data "room")}}{{$id := str (index $room "id")}}<section id="room" data-viewer="{{.Actor}}">
6165-<h1>{{or (str (index $room "name")) $id}} <small>{{if eq (str (index $room "access")) "members"}}members only{{else}}open room{{end}}</small></h1>
6166+{{else}}{{$data := asMap .Event}}{{$room := asMap (index $data "room")}}{{$id := str (index $room "id")}}{{$picture := socialMediaURL (str (index $room "picture"))}}<section id="room" data-viewer="{{.Actor}}">
6167+<h1><room-avatar picture="{{$picture}}" fallback="{{roomAvatarURL $.URL $id}}" aria-hidden="true"><img src="{{if $picture}}{{$picture}}{{else}}{{roomAvatarURL $.URL $id}}{{end}}" alt="" width="40" height="40" loading="lazy"></room-avatar>{{or (str (index $room "name")) $id}} <small>{{if eq (str (index $room "access")) "members"}}members only{{else}}open room{{end}}</small></h1>
6168 {{with str (index $room "about")}}<p>{{.}}</p>{{end}}
6169 {{with index $data "next_cursor"}}<p id="pages"><a href="/rooms/{{$id}}?cursor={{urlquery (str .)}}">load earlier</a></p>{{end}}
6170 {{if .Query.Get "cursor"}}<p id="newest"><a href="/rooms/{{$id}}">newest messages</a></p>{{end}}
6171@@ -47,8 +47,8 @@ establishes the initial state. */}}
6172 <h1>Thread</h1>
6173 {{template "alert" .Error}}
6174 </section>
6175-{{else}}{{$data := asMap .Event}}{{$room := asMap (index $data "room")}}{{$id := str (index $room "id")}}{{$root := roomRoot .Event .Actor}}<section id="thread" data-viewer="{{.Actor}}">
6176-<p id="crumbs"><a href="/rooms/{{$id}}">{{or (str (index $room "name")) $id}}</a></p>
6177+{{else}}{{$data := asMap .Event}}{{$room := asMap (index $data "room")}}{{$id := str (index $room "id")}}{{$picture := socialMediaURL (str (index $room "picture"))}}{{$root := roomRoot .Event .Actor}}<section id="thread" data-viewer="{{.Actor}}">
6178+<p id="crumbs"><a href="/rooms/{{$id}}"><room-avatar picture="{{$picture}}" fallback="{{roomAvatarURL $.URL $id}}" aria-hidden="true"><img src="{{if $picture}}{{$picture}}{{else}}{{roomAvatarURL $.URL $id}}{{end}}" alt="" width="28" height="28" loading="lazy"></room-avatar>{{or (str (index $room "name")) $id}}</a></p>
6179 <h1>Thread <small>{{$root.Replies}} {{if eq $root.Replies 1}}reply{{else}}replies{{end}}</small></h1>
6180 <div id="root">{{template "roomMessage" $root}}</div>
6181 {{template "chatActivity" .Activity}}
6182@@ -68,7 +68,7 @@ establishes the initial state. */}}
6183 {{define "roomSendIcon"}}<svg viewBox="0 0 24 24" width="22" height="22" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 19V5m-7 7 7-7 7 7"/></svg>{{end}}
6184
6185 {{/* One message. room-live builds the same markup for messages that arrive on the stream. */}}
6186-{{define "roomMessage"}}<room-message id="msg-{{.ID}}" data-id="{{.ID}}" data-kind="{{.Kind}}" data-updated-at="{{.UpdatedAt}}" data-pubkey="{{.PubKey}}"{{if .Own}} data-own{{end}}{{if .Agent}} data-agent{{end}}{{if .Notice}} data-notice{{end}}{{if .Edited}} data-edited{{end}}><nostr-avatar pubkey="{{.PubKey}}" aria-hidden="true">{{.Avatar}}</nostr-avatar>
6187+{{define "roomMessage"}}<room-message id="msg-{{.ID}}" data-id="{{.ID}}" data-kind="{{.Kind}}" data-updated-at="{{.UpdatedAt}}" data-pubkey="{{.PubKey}}"{{if .Own}} data-own{{end}}{{if .Agent}} data-agent{{end}}{{if .Notice}} data-notice{{end}}{{if .Edited}} data-edited{{end}}><nostr-avatar pubkey="{{.PubKey}}" aria-hidden="true"><img src="{{avatarURL .PubKey}}" alt="" width="32" height="32" loading="lazy"></nostr-avatar>
6188 <header><b>{{template "nostrName" .PubKey}}</b>{{if .Own}}<span data-own-label>you</span>{{end}}{{if .Agent}} | {{if .Operator}}{{template "nostrName" .Operator}}'s agent{{else}}agent{{end}}{{else if .Role}} | {{.Role}}{{end}}<small><time datetime="{{datetime .CreatedAt}}" title="{{when .CreatedAt}}">{{clock .CreatedAt}}</time></small></header>
6189 {{if .Notice}}<p>{{.Notice}}</p>{{else}}{{if .Quote}}<blockquote data-quote><a href="/open?target={{urlquery (printf "nostr:%s" .Quote)}}">quoted event {{shortID .Quote}}</a></blockquote>{{end}}<div>{{chatMarkdown (roomAttachmentContent .Content .Attachments)}}</div>{{roomAttachmentMarkup .Attachments}}{{end}}
6190 {{if or .Mentions (and (not .InThread) (or (eq .Kind "11") (eq .Kind "9") (eq .Kind "40002") .Root)) .Reactions .Edited}}<footer>{{if .Mentions}}<span>to {{range .Mentions}}{{template "nostrName" .}} {{end}}</span>{{end}}{{if not .InThread}}{{if or (eq .Kind "11") (eq .Kind "9") (eq .Kind "40002")}}<a href="/rooms/{{.Room}}/thread/{{.ID}}">thread{{if .Replies}} | {{.Replies}} {{if eq .Replies 1}}reply{{else}}replies{{end}}{{end}}</a>{{else if .Root}}<a href="/rooms/{{.Room}}/thread/{{.Root}}">in thread</a>{{end}}{{end}}{{range .Reactions}}<span data-reaction="{{.Content}}">{{.Content}} {{.Count}}</span>{{end}}{{if .Edited}}<span data-edited>edited</span>{{end}}</footer>{{end}}
6191diff --git a/internal/webui/rooms.js b/internal/webui/rooms.js
6192index 8d4a245..efffcf6 100644
6193--- a/internal/webui/rooms.js
6194+++ b/internal/webui/rooms.js
6195@@ -357,7 +357,7 @@
6196 if (own) node.dataset.own = "";
6197 if (member?.agent) node.dataset.agent = "";
6198 if (notice) node.dataset.notice = "";
6199- const avatar = el("nostr-avatar", pubkey.slice(0, 2).toUpperCase());
6200+ const avatar = el("nostr-avatar");
6201 avatar.setAttribute("pubkey", pubkey);
6202 avatar.setAttribute("aria-hidden", "true");
6203 const header = el("header"), name = el("b"), time = el("time", clock(event.created_at)), small = el("small");
6204diff --git a/internal/webui/rooms_test.go b/internal/webui/rooms_test.go
6205index 3ad6ddb..f738285 100644
6206--- a/internal/webui/rooms_test.go
6207+++ b/internal/webui/rooms_test.go
6208@@ -115,7 +115,7 @@ func roomsPage(t *testing.T, app *App, path string) string {
6209 func TestRoomsListRendersRoomsRailAndCreateForm(t *testing.T) {
6210 app, backend := roomsApp(t, roomOwner)
6211 body := roomsPage(t, app, "/chat")
6212- for _, want := range []string{`<table id="rows">`, `<a href="/rooms/general">General</a>`, `<a href="/rooms/build">Build</a>`, `members only <small>Where Build happens.</small>`, `<room-create>`, `<a href="/chat"><b>chat</b></a>`, `<nav id="room-list"><a href="/rooms/general">General`, `<a href="/chat#new-room">+ new room</a>`, `<p id="rail-tools"><a href="/">&larr; relay</a>`, `<h4>Rooms</h4>`, `<td>2</td>`} {
6213+ for _, want := range []string{`<table id="rows">`, `</room-avatar>General</a>`, `</room-avatar>Build</a>`, `members only <small>Where Build happens.</small>`, `<room-create>`, `<a href="/chat"><b>chat</b></a>`, `<nav id="room-list"><a href="/rooms/general"><room-avatar`, `<a href="/chat#new-room">+ new room</a>`, `<p id="rail-tools"><a href="/">&larr; relay</a>`, `<h4>Rooms</h4>`, `<td>2</td>`} {
6214 if !strings.Contains(body, want) {
6215 t.Errorf("rooms list missing %q", want)
6216 }
6217@@ -141,11 +141,11 @@ func TestRoomPageRendersMessagesOldestFirstWithMarkers(t *testing.T) {
6218 app, backend := roomsApp(t, roomOwner)
6219 body := roomsPage(t, app, "/rooms/general")
6220 for _, want := range []string{
6221- `<h1>General <small>open room</small></h1>`, `<p>Where General happens.</p>`,
6222+ `</room-avatar>General <small>open room</small></h1>`, `<p>Where General happens.</p>`,
6223 `<a href="/rooms/general?cursor=cursor-1">load earlier</a>`,
6224 `<room-message id="msg-` + roomHello + `" data-id="` + roomHello + `" data-kind="9" data-updated-at="1757203650" data-pubkey="` + roomAgent + `" data-agent data-edited>`,
6225- `<nostr-avatar pubkey="` + roomAgent + `" aria-hidden="true">BB</nostr-avatar>`,
6226- `<room-message id="msg-` + roomChat + `" data-id="` + roomChat + `" data-kind="9" data-updated-at="1757202000" data-pubkey="` + roomOwner + `" data-own><nostr-avatar pubkey="` + roomOwner + `" aria-hidden="true">AA</nostr-avatar>`,
6227+ `<nostr-avatar pubkey="` + roomAgent + `" aria-hidden="true"><img src="` + avatarURL(roomAgent) + `" alt="" width="32" height="32" loading="lazy"></nostr-avatar>`,
6228+ `<room-message id="msg-` + roomChat + `" data-id="` + roomChat + `" data-kind="9" data-updated-at="1757202000" data-pubkey="` + roomOwner + `" data-own><nostr-avatar pubkey="` + roomOwner + `" aria-hidden="true"><img src="` + avatarURL(roomOwner) + `" alt="" width="32" height="32" loading="lazy"></nostr-avatar>`,
6229 `</b><span data-own-label>you</span>`,
6230 `<section id="room" data-viewer="` + roomOwner + `">`,
6231 `<a href="https://example.com/docs" rel="noopener">https://example.com/docs</a>.`,
6232@@ -161,7 +161,7 @@ func TestRoomPageRendersMessagesOldestFirstWithMarkers(t *testing.T) {
6233 `<noscript><p>Sending needs JavaScript and a connected signer.</p></noscript>`,
6234 `<ul id="members"><li><nostr-name pubkey="` + roomOwner + `"`, `<li data-agent data-operator="` + roomOwner + `"><nostr-name pubkey="` + roomAgent + `"`, `<small><nostr-name pubkey="` + roomOwner + `" title="` + roomOwner + `">` + shortID(roomOwner) + `</nostr-name>'s agent</small>`,
6235 `<room-action room="general" kind="9000">`, `<room-action room="general" kind="9002">`, `<room-action room="general" kind="9022">`,
6236- `<nav id="room-list"><a href="/rooms/general" aria-current="page">General`,
6237+ `<nav id="room-list"><a href="/rooms/general" aria-current="page"><room-avatar`,
6238 `&raquo; <page-link url="http://relay.example/rooms/general" title="Copy the page address">rooms/general</page-link></span>`,
6239 } {
6240 if !strings.Contains(body, want) {
6241@@ -196,7 +196,7 @@ func TestMembersOnlyRoomIsHiddenFromGuests(t *testing.T) {
6242 }
6243 app, _ := roomsApp(t, roomOwner)
6244 body = roomsPage(t, app, "/rooms/build")
6245- if !strings.Contains(body, `<h1>Build <small>members only</small></h1>`) || !strings.Contains(body, `id="msg-`+roomHello) {
6246+ if !strings.Contains(body, `</room-avatar>Build <small>members only</small></h1>`) || !strings.Contains(body, `id="msg-`+roomHello) {
6247 t.Fatal("owner did not see the members-only room")
6248 }
6249 }
6250@@ -205,7 +205,7 @@ func TestThreadPageRendersRootRepliesAndReplyCompose(t *testing.T) {
6251 app, _ := roomsApp(t, roomOwner)
6252 body := roomsPage(t, app, "/rooms/general/thread/"+roomThread)
6253 for _, want := range []string{
6254- `<p id="crumbs"><a href="/rooms/general">General</a></p>`, `<h1>Thread <small>1 reply</small></h1>`,
6255+ `<p id="crumbs"><a href="/rooms/general"><room-avatar`, `</room-avatar>General</a></p>`, `<h1>Thread <small>1 reply</small></h1>`,
6256 `<div id="root"><room-message id="msg-` + roomThread + `"`, `<div id="messages">`, `id="msg-` + roomReply + `"`,
6257 `data-viewer="` + roomOwner + `"`, `<span data-own-label>you</span>`,
6258 `<room-live room="general" root="` + roomThread + `"></room-live>`,
6259diff --git a/internal/webui/social.html b/internal/webui/social.html
6260index 568a20a..2b1d3ed 100644
6261--- a/internal/webui/social.html
6262+++ b/internal/webui/social.html
6263@@ -34,7 +34,7 @@
6264 {{template "socialActions" $p}}
6265 </li>{{end}}
6266
6267-{{define "socialByline"}}{{$p := asMap .}}<header data-social-byline><span data-social-avatar><nostr-avatar pubkey="{{index $p "pubkey"}}" aria-hidden="true">{{with socialMediaURL (str (index $p "author_picture"))}}<img src="{{.}}" alt="" loading="lazy" width="36" height="36" referrerpolicy="no-referrer">{{else}}<span aria-hidden="true">@</span>{{end}}</nostr-avatar></span><span><a href="/social?author={{str (index $p "pubkey")}}"><b>{{if index $p "author_name"}}{{str (index $p "author_name")}}{{else}}{{template "nostrName" (str (index $p "pubkey"))}}{{end}}</b></a> <a href="{{socialURL $p}}"><time datetime="{{datetime (index $p "created_at")}}">{{when (index $p "created_at")}}</time></a>{{if eq (str (index $p "kind")) "30023"}} <small>Article</small>{{end}}{{with index $p "parent_url"}}<small data-social-parent>↳ <a href="{{.}}">Replying{{if index $p "parent_author"}} to {{template "nostrName" (str (index $p "parent_author"))}}{{else}} to a post{{end}}</a></small>{{end}}</span></header>{{end}}
6268+{{define "socialByline"}}{{$p := asMap .}}<header data-social-byline><span data-social-avatar><nostr-avatar pubkey="{{index $p "pubkey"}}" aria-hidden="true">{{with socialMediaURL (str (index $p "author_picture"))}}<img src="{{.}}" alt="" loading="lazy" width="36" height="36" referrerpolicy="no-referrer">{{else}}<img src="{{avatarURL (str (index $p "pubkey"))}}" alt="" width="36" height="36" loading="lazy">{{end}}</nostr-avatar></span><span><a href="/social?author={{str (index $p "pubkey")}}"><b>{{if index $p "author_name"}}{{str (index $p "author_name")}}{{else}}{{template "nostrName" (str (index $p "pubkey"))}}{{end}}</b></a> <a href="{{socialURL $p}}"><time datetime="{{datetime (index $p "created_at")}}">{{when (index $p "created_at")}}</time></a>{{if eq (str (index $p "kind")) "30023"}} <small>Article</small>{{end}}{{with index $p "parent_url"}}<small data-social-parent>↳ <a href="{{.}}">Replying{{if index $p "parent_author"}} to {{template "nostrName" (str (index $p "parent_author"))}}{{else}} to a post{{end}}</a></small>{{end}}</span></header>{{end}}
6269
6270 {{define "socialActions"}}{{$p := asMap .}}<footer data-social-actions>
6271 <a href="{{socialURL $p}}#reply">{{if index $p "reply_count"}}{{index $p "reply_count"}} {{if eq (str (index $p "reply_count")) "1"}}reply{{else}}replies{{end}}{{else}}Reply{{end}}</a>
6272diff --git a/internal/webui/style.css b/internal/webui/style.css
6273index c27b12d..7c54e87 100644
6274--- a/internal/webui/style.css
6275+++ b/internal/webui/style.css
6276@@ -299,17 +299,25 @@ wiki-compose output{display:block;font:12px var(--mono);color:var(--muted);margi
6277 /* Rooms: the rail lists rooms, messages read oldest first, and the compose bar stays at the bottom of the column. */
6278 #rail h4{margin:16px 0 4px;padding:0 2ch 0 2.5ch;font:11px var(--mono);color:var(--muted);text-transform:uppercase;letter-spacing:.04em}
6279 #room-list a{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}#room-list a small{float:right;color:var(--muted);font-size:11px}
6280+#room-list room-avatar{display:inline-block;vertical-align:middle;width:24px;height:24px;margin-right:7px}
6281+#room-list room-avatar img{display:block;width:100%;height:100%;border-radius:50%;object-fit:cover}
6282+#rooms #rows room-avatar,#chat #rows room-avatar{display:inline-block;vertical-align:middle;width:32px;height:32px;margin-right:8px}
6283+#rooms #rows room-avatar img,#chat #rows room-avatar img{display:block;width:100%;height:100%;border-radius:50%;object-fit:cover}
6284 #rooms #rows td:first-child{width:220px}#rooms #rows td:nth-child(3){text-align:right;width:80px;font:12px var(--mono)}
6285 #content>section#room,#content>section#thread{padding-bottom:0}
6286 #room h1 small,#thread h1 small{font:12px var(--mono);color:var(--muted)}
6287+#room h1 room-avatar{display:inline-block;vertical-align:middle;width:40px;height:40px;margin-right:10px}
6288+#room h1 room-avatar img{display:block;width:100%;height:100%;border-radius:50%;object-fit:cover}
6289+#thread #crumbs room-avatar{display:inline-block;vertical-align:middle;width:28px;height:28px;margin-right:7px}
6290+#thread #crumbs room-avatar img{display:block;width:100%;height:100%;border-radius:50%;object-fit:cover}
6291 #crumbs,#newest,#empty{font:12px var(--mono);color:var(--muted)}
6292 /* Rooms read as a centered conversation column; the compose bar spans the
6293 content column but its controls sit in the same 720px lane. */
6294 #room>*:not(room-compose),#thread>*:not(room-compose),room-compose>*{max-width:720px;margin-left:auto;margin-right:auto}
6295 room-message{display:block;position:relative;min-width:0;margin:10px 0;padding:12px 0 14px 44px;border-bottom:1px solid var(--line)}
6296 room-message>nostr-avatar{position:absolute;top:12px;left:0}
6297-nostr-avatar{display:inline-block;box-sizing:border-box;width:32px;height:32px;overflow:hidden;border:1px solid var(--line);border-radius:50%;background:var(--rail);color:var(--muted);text-align:center;font:11px/30px var(--mono);user-select:none;-webkit-user-select:none}
6298-nostr-avatar img{display:block;width:100%;height:100%;object-fit:cover}
6299+nostr-avatar,room-avatar{display:inline-block;box-sizing:border-box;width:32px;height:32px;overflow:hidden;border:1px solid var(--line);border-radius:50%;background:var(--rail);color:var(--muted);text-align:center;font:11px/30px var(--mono);user-select:none;-webkit-user-select:none}
6300+nostr-avatar img,room-avatar img{display:block;width:100%;height:100%;object-fit:cover}
6301 room-message>header{font:12px/1.5 var(--mono);color:var(--muted);margin-bottom:6px;overflow-wrap:anywhere;user-select:none;-webkit-user-select:none}
6302 room-message>header b{color:var(--ink);font-weight:500}room-message>header b nostr-key{cursor:copy}
6303 room-message>header small{float:right;margin-left:8px;white-space:nowrap}
6304diff --git a/internal/webui/templates.go b/internal/webui/templates.go
6305index 49ecae4..425795d 100644
6306--- a/internal/webui/templates.go
6307+++ b/internal/webui/templates.go
6308@@ -301,6 +301,8 @@ func parseTemplates(a *App) (*template.Template, error) {
6309 "socialBody": a.socialBody,
6310 "socialPreview": socialPreview,
6311 "socialMediaURL": socialMediaURL,
6312+ "avatarURL": avatarURL,
6313+ "roomAvatarURL": roomAvatarURL,
6314 "markdown": a.markdown,
6315 "chatMarkdown": a.chatMarkdown,
6316 "hasPrefix": strings.HasPrefix,
6317diff --git a/internal/webui/webui.go b/internal/webui/webui.go
6318index 4fb8827..4b0e9cc 100644
6319--- a/internal/webui/webui.go
6320+++ b/internal/webui/webui.go
6321@@ -181,6 +181,10 @@ func defaultQR(text string) ([]byte, error) {
6322 }
6323
6324 func (a *App) ServeHTTP(writer http.ResponseWriter, request *http.Request) {
6325+ if strings.HasPrefix(request.URL.Path, "/avatars/") {
6326+ serveAvatar(writer, request)
6327+ return
6328+ }
6329 if a.denyPrivateEndpoint(writer, request) {
6330 return
6331 }
6332diff --git a/scripts/chat-identity.test.mjs b/scripts/chat-identity.test.mjs
6333index fcdbf3d..3a7a561 100644
6334--- a/scripts/chat-identity.test.mjs
6335+++ b/scripts/chat-identity.test.mjs
6336@@ -15,7 +15,7 @@ test("live room and thread messages identify the viewer and render avatars", ()
6337 const avatar = own.querySelector(":scope > nostr-avatar");
6338 assert.equal(avatar.getAttribute("pubkey"), s.pubkey);
6339 assert.equal(avatar.getAttribute("aria-hidden"), "true");
6340- assert.equal(avatar.textContent, s.pubkey.slice(0, 2).toUpperCase());
6341+ assert.equal(avatar.textContent, "", "the avatar component supplies an image rather than initials");
6342 const other = s.rooms.messageNode({...event, pubkey: "b".repeat(64)});
6343 assert.equal(other.hasAttribute("data-own"), false);
6344 assert.equal(other.querySelector("[data-own-label]"), null);
6345diff --git a/scripts/nostr-avatar.test.mjs b/scripts/nostr-avatar.test.mjs
6346index a3b269d..292d64e 100644
6347--- a/scripts/nostr-avatar.test.mjs
6348+++ b/scripts/nostr-avatar.test.mjs
6349@@ -6,32 +6,35 @@ import vm from "node:vm";
6350 const source = fs.readFileSync("internal/webui/components.js", "utf8");
6351 const avatarSource = source.slice(source.indexOf(" class NostrAvatar "), source.indexOf(" // PageLink"));
6352 const key = "a".repeat(64);
6353+const location = {href: "https://relay.example/r/demo/chat", origin: "https://relay.example"};
6354
6355-function setup(userPromise) {
6356+function setup(userPromise, tag = "nostr-avatar", children = []) {
6357 const images = [], requests = [];
6358 const document = {
6359- createTextNode: text => ({textContent: text}),
6360 createElement: name => {
6361- const image = {nodeName: name, addEventListener: (event, callback) => { image.handlers ??= {}; image.handlers[event] = callback; }, setAttribute() {}};
6362- images.push(image);
6363- return image;
6364+ const node = {nodeName: name, children: [], setAttribute(name, value) { this[name] = value; }, append(...nodes) { this.children.push(...nodes); }, addEventListener(event, callback) { this.handlers ??= {}; this.handlers[event] = callback; }};
6365+ if (name === "img") images.push(node);
6366+ return node;
6367 }
6368 };
6369 const window = {tinyNames: {load: request => { requests.push(request); return typeof userPromise === "function" ? userPromise() : userPromise; }}};
6370 const HTMLElement = class {
6371- constructor() { this.attributes = {}; this.children = []; }
6372+ constructor() { this.attributes = {}; this.children = children; }
6373 getAttribute(name) { return this.attributes[name] ?? null; }
6374- replaceChildren(...children) { this.children = children; }
6375+ setAttribute(name, value) { this.attributes[name] = value; }
6376+ replaceChildren(...nodes) { this.children = nodes; }
6377+ append(...nodes) { this.children.push(...nodes); }
6378 querySelector(name) { return this.children.find(child => child.nodeName === name) || null; }
6379 };
6380- const el = (name, text) => { const node = document.createElement(name); if (text !== undefined) node.textContent = text; return node; };
6381- const Constructor = vm.runInNewContext(`${avatarSource}\nNostrAvatar`, {HTMLElement, window, document, URL, Promise, String, setTimeout, el});
6382+ const el = name => document.createElement(name);
6383+ const tiny = {localPath: path => "/r/demo" + path};
6384+ const Constructor = vm.runInNewContext(`${avatarSource}\n${tag === "room-avatar" ? "RoomAvatar" : "NostrAvatar"}`, {HTMLElement, window, document, URL, Promise, String, setTimeout, el, tiny, location});
6385 const component = new Constructor();
6386 component.attributes.pubkey = key;
6387 return {component, images, requests};
6388 }
6389
6390-test("loads a fresh profile image with privacy attributes", async () => {
6391+test("loads a profile image with a tenant scoped generated fallback", async () => {
6392 const {component, requests} = setup(Promise.resolve({image: "https://cdn.example/avatar.png"}));
6393 component.connectedCallback();
6394 await new Promise(resolve => setTimeout(resolve, 0));
6395@@ -44,24 +47,28 @@ test("loads a fresh profile image with privacy attributes", async () => {
6396 assert.equal(requests[0].refresh, true);
6397 });
6398
6399-test("keeps the two character fallback for missing or unsafe pictures", async () => {
6400+test("uses generated avatars for missing or unsafe pictures", async () => {
6401 for (const image of [undefined, "javascript:alert(1)", "/avatar.png"]) {
6402 const {component} = setup(Promise.resolve(image === undefined ? {} : {image}));
6403 component.connectedCallback();
6404 await new Promise(resolve => setTimeout(resolve, 0));
6405- assert.equal(component.children[0].textContent, "AA");
6406+ assert.equal(component.children[0].src, "/r/demo/avatars/v1/" + key + ".svg");
6407 }
6408+ const {component} = setup(Promise.resolve({}));
6409+ component.attributes.pubkey = "bad";
6410+ component.connectedCallback();
6411+ assert.equal(component.children[0].src, "/r/demo/avatars/v1/" + "0".repeat(64) + ".svg");
6412 });
6413
6414-test("restores the fallback after an image load failure", async () => {
6415+test("restores the generated fallback after an image load failure", async () => {
6416 const {component, images} = setup(Promise.resolve({image: "https://cdn.example/avatar.png"}));
6417 component.connectedCallback();
6418 await new Promise(resolve => setTimeout(resolve, 0));
6419- images[0].handlers.error();
6420- assert.equal(component.children[0].textContent, "AA");
6421+ images.at(-1).handlers.error();
6422+ assert.equal(component.children[0].src, "/r/demo/avatars/v1/" + key + ".svg");
6423 });
6424
6425-test("ignores a stale profile result after the pubkey changes", async () => {
6426+test("ignores stale profile results after the pubkey changes", async () => {
6427 let resolve, calls = 0;
6428 const {component} = setup(() => calls++ === 0 ? new Promise(done => { resolve = done; }) : Promise.resolve({}));
6429 component.connectedCallback();
6430@@ -69,14 +76,39 @@ test("ignores a stale profile result after the pubkey changes", async () => {
6431 component.attributeChangedCallback();
6432 resolve({image: "https://cdn.example/avatar.png"});
6433 await new Promise(resolve => setTimeout(resolve, 0));
6434- assert.equal(component.children[0].textContent, "BB");
6435+ assert.equal(component.children[0].src, "/r/demo/avatars/v1/" + "b".repeat(64) + ".svg");
6436 });
6437
6438-test("replaces a prior image when the pubkey becomes invalid", async () => {
6439- const {component} = setup(Promise.resolve({image: "https://cdn.example/avatar.png"}));
6440+test("room avatars prefer safe pictures and reject unsafe or cross origin fallbacks", () => {
6441+ const fallback = "/r/demo/avatars/v1/" + key + ".svg";
6442+ const {component} = setup(undefined, "room-avatar");
6443+ component.attributes.picture = "https://cdn.example/room.png";
6444+ component.attributes.fallback = fallback;
6445 component.connectedCallback();
6446- await new Promise(resolve => setTimeout(resolve, 0));
6447- component.attributes.pubkey = "bad";
6448+ assert.equal(component.children[0].src, "https://cdn.example/room.png");
6449+ component.attributes.picture = "javascript:alert(1)";
6450+ component.attributeChangedCallback();
6451+ assert.equal(component.children[0].src, "https://relay.example/r/demo/avatars/v1/" + key + ".svg");
6452+ component.attributes.fallback = "https://evil.example/avatars/v1/" + key + ".svg";
6453 component.attributeChangedCallback();
6454- assert.equal(component.children[0].textContent, "BA");
6455+ assert.equal(component.children.length, 0);
6456+});
6457+
6458+test("room avatars accept the root fallback path", () => {
6459+ const fallback = "/avatars/v1/" + key + ".svg";
6460+ const {component} = setup(undefined, "room-avatar");
6461+ component.attributes.fallback = fallback;
6462+ component.connectedCallback();
6463+ assert.equal(component.children[0].src, "https://relay.example" + fallback);
6464+});
6465+
6466+test("room avatars restore their fallback after a picture fails", () => {
6467+ const fallback = "/r/demo/avatars/v1/" + key + ".svg";
6468+ const {component, images} = setup(undefined, "room-avatar");
6469+ component.attributes.picture = "https://cdn.example/room.png";
6470+ component.attributes.fallback = fallback;
6471+ component.connectedCallback();
6472+ images[0].handlers.error();
6473+ assert.equal(component.children[0].src, "https://relay.example" + fallback);
6474+ assert.equal(images.at(-1).handlers?.error, undefined);
6475 });
6476diff --git a/scripts/qa/generate-seedmark-fixture.mjs b/scripts/qa/generate-seedmark-fixture.mjs
6477new file mode 100644
6478index 0000000..af05b77
6479--- /dev/null
6480+++ b/scripts/qa/generate-seedmark-fixture.mjs
6481@@ -0,0 +1,42 @@
6482+#!/usr/bin/env node
6483+
6484+// Regenerate the Seedmark v1 parity fixture from a local upstream checkout.
6485+// Usage: node scripts/qa/generate-seedmark-fixture.mjs ../seedmark [output]
6486+import {execFileSync} from 'node:child_process';
6487+import {createHash} from 'node:crypto';
6488+import {writeFile} from 'node:fs/promises';
6489+import {pathToFileURL} from 'node:url';
6490+import path from 'node:path';
6491+
6492+const upstream = path.resolve(process.argv[2] || '../seedmark');
6493+const output = path.resolve(process.argv[3] || 'internal/seedmark/testdata/v1.json');
6494+const expectedCommit = 'c808a940bc193f97512c02d58da33ecc28ba1f53';
6495+const commit = execFileSync('git', ['-C', upstream, 'rev-parse', 'HEAD'], {encoding: 'utf8'}).trim();
6496+if (commit !== expectedCommit) {
6497+ throw new Error(`Seedmark checkout is ${commit}; expected ${expectedCommit}`);
6498+}
6499+
6500+const {avatar, recipe} = await import(pathToFileURL(path.join(upstream, 'src/index.js')).href);
6501+const seeds = [
6502+ '',
6503+ 'seedmark',
6504+ 'a'.repeat(64),
6505+ 'A'.repeat(64),
6506+ '0'.repeat(64),
6507+ 'seed/\u0000part',
6508+ 'é',
6509+ 'e\u0301',
6510+ '猫🌱',
6511+ '👩‍💻',
6512+ ...Array.from({length: 1000}, (_, index) => `sample/${index}`),
6513+];
6514+const fixtures = seeds.map(seed => {
6515+ const svg = avatar(seed);
6516+ return {
6517+ seed,
6518+ family: recipe(seed).family,
6519+ sha256: createHash('sha256').update(svg).digest('hex'),
6520+ };
6521+});
6522+await writeFile(output, `${JSON.stringify(fixtures, null, 2)}\n`);
6523+process.stderr.write(`wrote ${fixtures.length} cases from Seedmark ${commit} to ${output}\n`);

About

ownerc01503e8035f
visibilitypublic
head3d347aa40d0b

Maintainers

  • c01503e8035f owner
  • ba1b5beed5b5 agent hermes

Clone

  • https://012.run/npub1cq2s86qrtadf36eqq3epm38wmhdynrrcwxf84eldk3f94dkv7ttsrulrz5/tinyrelay.git

Refs