Compare commits

...

203 Commits

Author SHA1 Message Date
Andrey Antukh
36bc085663 Add minor improvements to error reporting 2026-02-18 15:53:41 +01:00
Alejandro Alonso
a1a7f643ec Merge pull request #8390 from penpot/niwinz-staging-exporter-bundle
🐛 Fix exporter bundle deps issue with pnpm
2026-02-17 18:38:50 +01:00
Andrey Antukh
70013fde74 🐛 Fix exporter bundle deps issue with pnpm 2026-02-17 17:46:09 +01:00
Andrey Antukh
916107ce04 📎 Update pnpm-lock.yaml file on plugins module 2026-02-17 17:42:39 +01:00
Andrey Antukh
8eb5bd3dd8 🔧 Add minor adjustments to mcp build-types script 2026-02-17 17:42:39 +01:00
Andrey Antukh
5718698bff Update mcp api_types.yml file with latest plugins doc updates 2026-02-17 17:42:39 +01:00
Andrey Antukh
f00b222262 Revert "♻️ Replace some components with DS ones" (#8384)
* Revert "♻️ Replace some components with DS ones"

This reverts commit 6879f54e5d.

* 📎 Restore missing styles

* 📎 Fix tests

---------

Co-authored-by: Luis de Dios <luis.dedios@kaleidos.net>
2026-02-17 16:23:04 +01:00
Andrey Antukh
137febcbab 📎 Clean changelog 2026-02-17 10:00:42 +01:00
Andrey Antukh
f98c0bbd16 📎 Update changelog 2026-02-17 09:58:40 +01:00
Luis de Dios
7f3212d5a4 🐛 Fix changelog to remove MCP (#8380) 2026-02-17 09:53:12 +01:00
Andrés Moya
643cd6f61f 🐛 Add resolved value to tokens in plugins API (#8372) 2026-02-17 09:20:04 +01:00
Luis de Dios
166dc05ff2 🐛 Fix incorrect icons in grid view (#8373) 2026-02-16 16:39:39 +01:00
Andrés Moya
619e2387dc 🐛 Fix applied tokens property names 2026-02-16 15:16:14 +01:00
Andrés Moya
813c804d45 🔧 Enhance schema validation of token application 2026-02-16 15:16:14 +01:00
Andrey Antukh
63f0c68977 Merge remote-tracking branch 'origin/main' into staging 2026-02-16 14:35:28 +01:00
Andrey Antukh
1f2a234458 📚 Update changelog 2026-02-16 14:32:28 +01:00
Andrey Antukh
b281870c50 📚 Update changelog 2026-02-16 14:27:33 +01:00
Andrey Antukh
3909bc0fc1 Merge remote-tracking branch 'origin/main' into staging 2026-02-16 14:17:46 +01:00
Andrey Antukh
b6427ecaac 🐛 Revert yetti upgrade
Because of regression introduced on undertow-core 2.3.19
2026-02-16 14:16:29 +01:00
Andrey Antukh
e82319c49e Merge tag '2.13.2' 2026-02-16 14:13:51 +01:00
Andrey Antukh
ce63bae92d Add better approach for error handling to obj/reify 2026-02-16 11:07:40 +01:00
Andrey Antukh
d1d50138ed Merge remote-tracking branch 'origin/staging-render' into develop 2026-02-16 10:00:46 +01:00
Andrey Antukh
c63de58b7f Merge remote-tracking branch 'origin/staging' into staging-render 2026-02-16 10:00:27 +01:00
Andrey Antukh
7301973655 🌐 Rehash and sync translation files 2026-02-16 09:41:49 +01:00
Sebastiaan Pasma
e6990e996c 🌐 Add translations for: Dutch
Currently translated at 98.9% (2052 of 2074 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/nl/
2026-02-16 09:35:25 +01:00
Alejandro Alonso
82a6e73b0d 🌐 Add translations for: Yoruba
Currently translated at 56.5% (1172 of 2074 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/yo/
2026-02-16 09:35:24 +01:00
VKing9
a0fc14d4e8 🌐 Add translations for: Hindi
Currently translated at 96.3% (1998 of 2074 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hi/
2026-02-16 09:35:24 +01:00
Anonymous
a5dc3a4e2b 🌐 Add translations for: Croatian
Currently translated at 76.9% (1596 of 2074 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/hr/
2026-02-16 09:35:24 +01:00
Ņikita K.
f60f259937 🌐 Add translations for: Latvian
Currently translated at 90.7% (1883 of 2074 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/lv/
2026-02-16 09:35:23 +01:00
Anonymous
c669bd7327 🌐 Add translations for: Chinese (Simplified Han script)
Currently translated at 86.8% (1801 of 2074 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/zh_Hans/
2026-02-16 09:35:23 +01:00
Anonymous
c33a52ec51 🌐 Add translations for: Basque
Currently translated at 55.5% (1152 of 2074 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/eu/
2026-02-16 09:35:23 +01:00
Anonymous
9b2e847d99 🌐 Add translations for: Spanish
Currently translated at 97.1% (2015 of 2074 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/es/
2026-02-16 09:35:22 +01:00
Anonymous
d1e82c4d40 🌐 Add translations for: Hebrew
Currently translated at 95.6% (1984 of 2074 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/he/
2026-02-16 09:35:22 +01:00
AlexTECPlayz
71ef2294e4 🌐 Add translations for: Romanian
Currently translated at 93.3% (1937 of 2074 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/ro/
2026-02-16 09:35:21 +01:00
Alejandro Alonso
3576c581a3 🌐 Add translations for: Arabic
Currently translated at 54.1% (1123 of 2074 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/ar/
2026-02-16 09:35:21 +01:00
Anonymous
13be3599b6 🌐 Add translations for: Portuguese (Portugal)
Currently translated at 75.6% (1568 of 2074 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/pt_PT/
2026-02-16 09:35:20 +01:00
Nicola Bortoletto
7b5e1f0196 🌐 Add translations for: Italian
Currently translated at 98.6% (2047 of 2074 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/it/
2026-02-16 09:35:20 +01:00
Anonymous
a483c99480 🌐 Add translations for: Polish
Currently translated at 54.3% (1127 of 2074 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/pl/
2026-02-16 09:35:20 +01:00
Radek Sawicki
60ebbd57c6 🌐 Add translations for: Polish
Currently translated at 54.3% (1127 of 2074 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/pl/
2026-02-16 09:35:19 +01:00
Црнобог
e830689987 🌐 Add translations for: Serbian
Currently translated at 65.9% (1368 of 2074 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/sr/
2026-02-16 09:35:19 +01:00
Amerey.eu
c8f9f49793 🌐 Add translations for: Czech
Currently translated at 76.7% (1591 of 2074 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/cs/
2026-02-16 09:35:19 +01:00
Anonymous
f24f872c24 🌐 Add translations for: French
Currently translated at 95.2% (1976 of 2074 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/fr/
2026-02-16 09:35:19 +01:00
Renan Mayrinck
4a1a7e6e8f 🌐 Add translations for: Portuguese (Brazil)
Currently translated at 67.0% (1391 of 2074 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/pt_BR/
2026-02-16 09:35:18 +01:00
Denys Kisil
46ee8402fe 🌐 Add translations for: Ukrainian (ukr_UA)
Currently translated at 87.5% (1815 of 2074 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/ukr_UA/
2026-02-16 09:35:18 +01:00
The_BadUser
b6d813dd51 🌐 Add translations for: Russian
Currently translated at 76.1% (1579 of 2074 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/ru/
2026-02-16 09:35:13 +01:00
Anonymous
a9f674389a 🌐 Add translations for: German
Currently translated at 94.4% (1958 of 2074 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/de/
2026-02-16 09:35:13 +01:00
william chen
78bdb13831 🌐 Add translations for: Chinese (Traditional Han script)
Currently translated at 77.0% (1599 of 2074 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/zh_Hant/
2026-02-16 09:35:12 +01:00
im424
e548b2d863 🌐 Add translations for: Chinese (Traditional Han script)
Currently translated at 77.0% (1599 of 2074 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/zh_Hant/
2026-02-16 09:35:12 +01:00
Alejandro Alonso
7543527fae 🌐 Add translations for: Hausa
Currently translated at 59.6% (1238 of 2074 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/ha/
2026-02-16 09:35:12 +01:00
Anonymous
da488373e2 🌐 Add translations for: Turkish
Currently translated at 98.9% (2052 of 2074 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/tr/
2026-02-16 09:35:12 +01:00
Henrik Allberg
91e1c8299d 🌐 Add translations for: Swedish
Currently translated at 95.6% (1983 of 2074 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/sv/
2026-02-16 09:35:11 +01:00
Linerly
adc661126a 🌐 Add translations for: Indonesian
Currently translated at 81.6% (1694 of 2074 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/id/
2026-02-16 09:35:11 +01:00
Hosted Weblate
3b07ff2613 🌐 Update translation files
Updated by "Cleanup translation files" hook in Weblate.

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/
2026-02-16 09:15:59 +01:00
Alexis Morin
3aebff0799 🌐 Add translations for: French (Canada)
Currently translated at 61.2% (1266 of 2066 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/fr_CA/
2026-02-16 09:15:49 +01:00
Alexis Morin
3b14acc93e 🌐 Add translations for: French (Canada)
Currently translated at 60.2% (1244 of 2066 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/fr_CA/
2026-02-16 09:15:49 +01:00
Alexis Morin
ad2db07123 🌐 Add translations for: French (Canada)
Currently translated at 55.8% (1154 of 2066 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/fr_CA/
2026-02-16 09:15:49 +01:00
Alexis Morin
068ecc3847 🌐 Add translations for: French (Canada)
Currently translated at 55.4% (1146 of 2066 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/fr_CA/
2026-02-16 09:15:49 +01:00
Alexis Morin
c850fe2d4f 🌐 Add translations for: French (Canada)
Currently translated at 55.0% (1138 of 2066 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/fr_CA/
2026-02-16 09:15:49 +01:00
Alexis Morin
59acf71255 🌐 Add translations for: French (Canada)
Currently translated at 52.4% (1083 of 2066 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/fr_CA/
2026-02-16 09:15:49 +01:00
Alexis Morin
d7c5e7798c 🌐 Add translations for: French (Canada)
Currently translated at 48.8% (1009 of 2066 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/fr_CA/
2026-02-16 09:15:49 +01:00
Alexis Morin
ee81459d87 🌐 Add translations for: French (Canada)
Currently translated at 44.6% (923 of 2066 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/fr_CA/
2026-02-16 09:15:49 +01:00
Alexis Morin
ea54ff4bd5 🌐 Add translations for: French (Canada)
Currently translated at 43.6% (902 of 2066 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/fr_CA/
2026-02-16 09:15:49 +01:00
Alexis Morin
353998b989 🌐 Add translations for: French (Canada)
Currently translated at 42.3% (874 of 2066 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/fr_CA/
2026-02-16 09:15:49 +01:00
Alexis Morin
6b1ae46116 🌐 Add translations for: French (Canada)
Currently translated at 40.8% (844 of 2066 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/fr_CA/
2026-02-16 09:15:49 +01:00
Sandy S Kuo
727a0adf1f 🌐 Add translations for: Chinese (Traditional Han script)
Currently translated at 77.5% (1603 of 2066 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/zh_Hant/
2026-02-16 09:15:49 +01:00
Alexis Morin
b99e4e8954 🌐 Add translations for: French (Canada)
Currently translated at 37.5% (775 of 2066 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/fr_CA/
2026-02-16 09:15:49 +01:00
Alexis Morin
e8f893a668 🌐 Add translations for: French (Canada)
Currently translated at 36.6% (758 of 2066 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/fr_CA/
2026-02-16 09:15:49 +01:00
Yaron Shahrabani
44964bc98b 🌐 Add translations for: Hebrew
Currently translated at 96.2% (1988 of 2066 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/he/
2026-02-16 09:15:49 +01:00
Dogyeong
86f52a15a5 🌐 Add translations for: Korean
Currently translated at 12.1% (250 of 2066 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/ko/
2026-02-16 09:15:49 +01:00
Alexis Morin
cc43426bb8 🌐 Add translations for: French (Canada)
Currently translated at 35.8% (740 of 2066 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/fr_CA/
2026-02-16 09:15:49 +01:00
Dogyeong
5da2865158 🌐 Add translations for: Korean
Currently translated at 11.4% (237 of 2066 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/ko/
2026-02-16 09:15:49 +01:00
Alexis Morin
eeb998409d 🌐 Add translations for: French (Canada)
Currently translated at 33.8% (699 of 2066 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/fr_CA/
2026-02-16 09:15:48 +01:00
Alexis Morin
b9ac8f7616 🌐 Add translations for: French (Canada)
Currently translated at 32.2% (667 of 2066 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/fr_CA/
2026-02-16 09:15:48 +01:00
Nicola Bortoletto
626d6a285d 🌐 Add translations for: Italian
Currently translated at 99.5% (2057 of 2066 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/it/
2026-02-16 09:15:48 +01:00
Alexis Morin
7159d00d75 🌐 Add translations for: French (Canada)
Currently translated at 29.3% (607 of 2066 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/fr_CA/
2026-02-16 09:15:48 +01:00
Louis Chance
380c5382c7 🌐 Add translations for: French
Currently translated at 95.8% (1980 of 2066 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/fr/
2026-02-16 09:15:48 +01:00
Alexis Morin
28c244f8ee 🌐 Add translations for: French (Canada)
Currently translated at 24.1% (499 of 2066 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/fr_CA/
2026-02-16 09:15:48 +01:00
Stas Haas
af149afd08 🌐 Add translations for: German
Currently translated at 95.0% (1963 of 2066 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/de/
2026-02-16 09:15:48 +01:00
Alexis Morin
afd8add839 🌐 Add translations for: French (Canada)
Currently translated at 22.6% (467 of 2066 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/fr_CA/
2026-02-16 09:15:48 +01:00
Andrey Antukh
d6aad1d79b 🌐 Add translations for: French
Currently translated at 95.1% (1966 of 2066 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/fr/
2026-02-16 09:15:48 +01:00
Nicola Bortoletto
621e5161dc 🌐 Add translations for: Italian
Currently translated at 99.1% (2049 of 2066 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/it/
2026-02-16 09:15:48 +01:00
Alexis Morin
00df74d602 🌐 Add translations for: French (Canada)
Currently translated at 21.7% (449 of 2066 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/fr_CA/
2026-02-16 09:15:48 +01:00
Alexis Morin
d31501ddb6 🌐 Add translations for: French (Canada)
Currently translated at 18.9% (392 of 2066 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/fr_CA/
2026-02-16 09:15:48 +01:00
Louis Chance
b0fda4cb06 🌐 Add translations for: French
Currently translated at 95.1% (1966 of 2066 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/fr/
2026-02-16 09:15:48 +01:00
Stephan Paternotte
ce80c049cd 🌐 Add translations for: Dutch
Currently translated at 99.8% (2062 of 2066 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/nl/
2026-02-16 09:15:48 +01:00
Marius
2873bffff1 🌐 Add translations for: German
Currently translated at 93.7% (1937 of 2066 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/de/
2026-02-16 09:15:48 +01:00
Alexis Morin
56c7ef8e99 🌐 Add translations for: French (Canada)
Currently translated at 18.7% (388 of 2066 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/fr_CA/
2026-02-16 09:15:48 +01:00
Edgars Andersons
594551c16a 🌐 Add translations for: Latvian
Currently translated at 91.3% (1887 of 2066 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/lv/
2026-02-16 09:15:47 +01:00
Stephan Paternotte
00c34ecf12 🌐 Add translations for: Dutch
Currently translated at 99.8% (2062 of 2066 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/nl/
2026-02-16 09:15:47 +01:00
Alexis Morin
033a1f39fa 🌐 Add translations for: French (Canada)
Currently translated at 17.5% (363 of 2066 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/fr_CA/
2026-02-16 09:15:47 +01:00
Oğuz Ersen
aaab3e6b3e 🌐 Add translations for: Turkish
Currently translated at 99.8% (2062 of 2066 strings)

Translation: Penpot/frontend
Translate-URL: https://hosted.weblate.org/projects/penpot/frontend/tr/
2026-02-16 09:15:47 +01:00
Andrey Antukh
4a7b89a1da Merge pull request #8327 from penpot/niwinz-develop-rlimit-notifications
 Add proper mattermost notifications for rlimit rejects
2026-02-13 17:11:54 +01:00
Elena Torró
51782551cc Merge pull request #8346 from penpot/alotor-fix-problem-text-autogrouw
🐛 Fix problem with autogrow change while editing text
2026-02-13 15:25:35 +01:00
alonso.torres
f60a4cd111 🐛 Fix problem with autogrow change while editing text 2026-02-13 14:52:40 +01:00
David Barragán Merino
1349789a7b 🔧 Fix the plugin style documentation build command 2026-02-13 14:20:34 +01:00
David Barragán Merino
8dbb169061 🔧 Fix the plugin style documentation build command 2026-02-13 14:20:01 +01:00
David Barragán Merino
cc28bd44f6 🔧 Fix the plugin style documentation build command 2026-02-13 14:18:35 +01:00
Alejandro Alonso
d9d4a99e1d 🔧 Migrate variants tests to wasm viewport 2026-02-13 14:13:03 +01:00
David Barragán Merino
fe833c9e34 🔧 Disable observability for plugin docs and packages
This reverts commit a4f2641cc9.
2026-02-13 13:55:13 +01:00
Elena Torró
38ad24ea07 Merge pull request #8349 from penpot/alotor-fix-editor-selrect
🐛 Fix problem with text editor outline
2026-02-13 13:25:13 +01:00
Alejandro Alonso
8d225af13a Merge pull request #8351 from penpot/alotor-fix-create-rect-click
🐛 Fix problem when create click
2026-02-13 13:21:27 +01:00
Juanfran
449aa65f8d 🐛 Fix e2e tests for plugins 2026-02-13 13:17:08 +01:00
Andrey Antukh
bd7f4dca3a 🐛 Fix rpc methods on plugins e2e tests 2026-02-13 13:17:08 +01:00
Andrey Antukh
1e7bef081a Allow self-signed certs on plugins e2e browser setup 2026-02-13 13:17:08 +01:00
Andrey Antukh
12bc3ac9ed Update default cors headers 2026-02-13 13:17:08 +01:00
Elena Torró
80a3f4cd60 Merge pull request #8350 from penpot/superalex-migrate-tests-to-wasm-viewport-3
🔧 Migrate inspect tab tests to wasm viewport
2026-02-13 13:06:14 +01:00
alonso.torres
3ea0a781f1 🐛 Fix problem when create click 2026-02-13 12:38:33 +01:00
alonso.torres
35abf8a179 🐛 Fix problem with text editor outline 2026-02-13 12:23:05 +01:00
Sagar
cfcebf59d5 🐛 Make S3Client and S3Presigner use identical credential resolution (#8316) 2026-02-13 12:21:05 +01:00
Andrey Antukh
cf43ac23a1 Merge pull request #8340 from penpot/hiru-fix-plugins-api-tokens
🐛 Fix problems about applying tokens to shapes with plugins
2026-02-13 12:18:29 +01:00
Alejandro Alonso
7e9fb0742d 🔧 Migrate inspect tab tests to wasm viewport 2026-02-13 12:09:31 +01:00
Elena Torró
39b3767203 Merge pull request #8348 from penpot/superalex-fix-non-existent-google-font
🐛 Fix non existent google font
2026-02-13 12:08:18 +01:00
Alejandro Alonso
23333aa3c3 Merge pull request #8347 from penpot/elenatorro-13386-fix-flex-absolute-index
🐛 Fix absolute z-index values on layout children
2026-02-13 12:06:45 +01:00
Alejandro Alonso
684e2b6950 🐛 Fix non existent google font 2026-02-13 11:59:59 +01:00
Elena Torro
fd6f70a740 🐛 Fix absolute z-index values on layout children 2026-02-13 11:41:16 +01:00
Elena Torro
b892cc9b14 🔧 Refactor shape base props to use transmute 2026-02-13 11:28:18 +01:00
Belén Albeza
50ddf5e628 🔧 Add integration test for bug 13305 2026-02-13 10:57:27 +01:00
Belén Albeza
75a4102637 🐛 Fix resize board to fit (wasm) 2026-02-13 10:57:27 +01:00
David Barragán Merino
d7203ef24c 🔧 Fix the plugin bundle build command 2026-02-13 09:39:12 +01:00
David Barragán Merino
61f3e090da 🔧 Fix the plugin bundle build command 2026-02-13 09:38:39 +01:00
David Barragán Merino
fda09b02b9 🔧 Fix the plugin bundle build command 2026-02-13 09:37:22 +01:00
Elena Torró
8f478aa6e5 Merge pull request #8325 from penpot/superalex-fix-wasm-forcing-url-param
🐛 Fix forcing wasm via url param
2026-02-12 17:46:50 +01:00
Alejandro Alonso
95e1efa5ff 🐛 Fix forcing wasm via url param 2026-02-12 17:35:02 +01:00
Andrés Moya
a23ca6a1cb 🐛 Fix applied tokens reading in shape proxy 2026-02-12 17:14:16 +01:00
Eva Marco
d07f568ba2 🐛 Avoid modifying shape by apply negative tokens to border radius (#8336) 2026-02-12 17:01:36 +01:00
Andrés Moya
c626634610 🐛 Detect empty font-family 2026-02-12 16:04:23 +01:00
Andrés Moya
11eedd0368 🐛 Patch alternative ways of applying tokens to shapes 2026-02-12 16:01:55 +01:00
Florian Schroedl
375608b44b ⬆️ Update tokenscript interpreter to 0.26.0 and add CSS color schemas
Regenerate schemas.js with preset:cssColors to support CSS color constants.
2026-02-12 14:14:45 +01:00
Elena Torró
97d24b190f Merge pull request #8334 from penpot/superalex-migrate-tests-to-wasm-viewport
🔧 Migrate straightforward tests to user the wasm viewport
2026-02-12 14:03:06 +01:00
Alejandro Alonso
434ac0556a 🔧 Migrate straightforward tests to user the wasm viewport 2026-02-12 13:29:13 +01:00
Andrey Antukh
12e5d8d8c4 Merge remote-tracking branch 'origin/staging-render' into develop 2026-02-12 11:00:56 +01:00
Andrey Antukh
04a3126856 Merge remote-tracking branch 'origin/main' into staging-render 2026-02-12 11:00:38 +01:00
Elena Torró
2f71663470 Merge pull request #8245 from penpot/elenatorro-13047-setup-embedded-text-editor
🔧 Set up embedded editor
2026-02-12 10:05:39 +01:00
Andrey Antukh
43cb313cd7 Merge pull request #8310 from oraios/mcp-tokens
 MCP improvements to enable UC2, design token handling
2026-02-12 09:47:32 +01:00
Elena Torró
0b199c606a Merge pull request #8331 from penpot/ladybenko-add-wasm-config-playwright-helper
🔧 Add helper utils to mock config flags for WasmWorkspacePage (e2e)
2026-02-12 09:45:03 +01:00
Aitor Moreno
54f63c5dc5 ♻️ Refactor minor things 2026-02-12 09:34:21 +01:00
Elena Torro
a14c36e996 📚 Add embedded text editor MVP documentation 2026-02-12 09:34:20 +01:00
Elena Torro
2b525f0f48 🔧 Set up embedded editor 2026-02-12 09:34:20 +01:00
Belén Albeza
fd6ff04e90 🔧 Add helper utils to mock config flags for WasmWorkspacePage (e2e) 2026-02-12 09:25:08 +01:00
eps-epsiloneridani
dbb0aa8ce2 📚 Update recommended-settings.md (#8330)
Got rid of a stray quotation mark

Signed-off-by: eps-epsiloneridani <162043859+eps-epsiloneridani@users.noreply.github.com>
2026-02-12 09:19:10 +01:00
Andrey Antukh
12822833f6 Merge pull request #8301 from eureka928/fix/4513-shift-arrow-color-inputs
🐛 Add Shift/Alt arrow key stepping to color picker inputs
2026-02-12 08:26:05 +01:00
eureka928
307ae374fe ♻️ Unify color picker input handlers by treating alpha as a property
Eliminate duplicated on-change-opacity and on-key-down-opacity handlers
by routing alpha through apply-property-change, and extract shared
stepping logic into on-key-down-step.

Signed-off-by: eureka928 <meobius123@gmail.com>
2026-02-12 08:25:37 +01:00
eureka928
7d7dbd4662 🐛 Add Shift/Alt arrow key stepping to color picker inputs (#4513)
Color picker numeric inputs (R, G, B, H, S, V, Alpha) now support
Shift+Arrow for ×10 steps and Alt+Arrow for ×0.1 steps, matching
the behavior of numeric inputs elsewhere in the application.

Signed-off-by: eureka928 <meobius123@gmail.com>
2026-02-12 08:25:37 +01:00
Alejandro Alonso
139d4ba13c Merge pull request #8328 from penpot/elenatorro-13311-fix-multiple-strokes-blending
🐛 Fix stroke color aliasing when a shape has multiple strokes
2026-02-12 07:05:44 +01:00
Elena Torro
0cb5c16823 🐛 Fix fallback font 2026-02-12 06:43:52 +01:00
Elena Torro
4ed1a544f8 🐛 Fix stroke color aliasing when a shape has multiple strokes 2026-02-12 06:43:52 +01:00
Elena Torró
566ac67fc9 Merge pull request #8324 from penpot/azazeln28-fix-editor-fills
🐛 Fix text editor issues
2026-02-11 16:37:20 +01:00
Juanfran
394d597736 Add enhacements to plugins build mechanism (#8326)
* 🐛 Fix plugin code build

* 🔧 Update editor.defaultFormatter to new Prettier

* 🐛 Fix lint issues in create-palette-plugin

* 🐛 Add missing run in pnpm init script for plugins
2026-02-11 15:28:33 +01:00
Aitor Moreno
b2231e520c 📚 Add best practices to text editor README.md 2026-02-11 13:09:56 +01:00
Aitor Moreno
e722e17b10 🐛 Fix paragraph styles not being applied 2026-02-11 12:49:20 +01:00
Aitor Moreno
755d720b34 🐛 Fix text editor fills not being updated 2026-02-11 12:29:03 +01:00
Alejandro Alonso
d991d59852 Merge pull request #8318 from penpot/elenatorro-13311-fix-multiple-fills-blending
🐛 Fix fill aliasing when a shape has multiple fills
2026-02-11 11:37:43 +01:00
Dominik Jain
7eb9a207f5 Change PenpotUtils.findShapes to search on all pages by default
This matches the behaviour of findShape, more closely aligning with
the LLM's expectations (given the lack of concrete information in
the instructions)
2026-02-11 11:35:10 +01:00
Dominik Jain
8ac17604fd Improve information on component instances
* Add information on detachment
* Add information on remove behaviour in component instances
2026-02-11 11:35:10 +01:00
Elena Torro
eede023d6b 🐛 Fix fill aliasing when a shape has multiple fills 2026-02-11 11:21:08 +01:00
Belén Albeza
ccd42852b7 🐛 Fix token not being highlighted (wasm) 2026-02-11 11:17:27 +01:00
Alejandro Alonso
a2f7ae549e Merge pull request #8312 from penpot/elenatorro-13256-sync-text-selection
🔧 Hide text color from selected text
2026-02-11 11:02:35 +01:00
Alejandro Alonso
6f74d458a8 🐛 Adding lost file for render e2e testing get-file-stroke-styles.json 2026-02-11 10:47:50 +01:00
Alejandro Alonso
8d033de145 Merge pull request #8299 from penpot/elenatorro-13242-review-performance
🔧 Improve layout performance
2026-02-11 10:45:40 +01:00
Dominik Jain
f5afcde0de Improve shapeStructure
* Add information on component instance (component id, name; main instance id)
* Improve JSON result order (children should come last)
2026-02-11 10:45:22 +01:00
Dominik Jain
b6dfdc23cd Update information on TokenProperty 2026-02-11 10:45:22 +01:00
Dominik Jain
a5a084cf0f Update API type information based on current repo state 2026-02-11 10:45:22 +01:00
Dominik Jain
1546025814 Avoid certain <ul> elements with single <li> generating bullets 2026-02-11 10:45:22 +01:00
Dominik Jain
8de510d1c6 🐛 Fix PenpotAPIDocsProcessor not requiring the url parameter
* Add additional constant for the PROD url
* Adapt the debug function to use a URL
* Improve logging
2026-02-11 10:45:10 +01:00
Elena Torró
2e77c09ca5 Merge pull request #8309 from penpot/superalex-fix-stroke-dot-dash-mix
🐛 Fix dot strokes
2026-02-11 10:37:46 +01:00
Elena Torró
47346e478e Merge pull request #8303 from penpot/superalex-fix-stroke-opacity-for-boards
🐛 Fix stroke opacity for boards
2026-02-11 10:05:47 +01:00
Andrey Antukh
89cd4d820c 🔥 Remove mcp from compose 2026-02-11 09:13:24 +01:00
Alejandro Alonso
f32c377f17 🐛 Fix stroke opacity for boards 2026-02-11 09:08:03 +01:00
Andrey Antukh
8693623b13 📎 Update SECURITY.md file 2026-02-11 08:11:04 +01:00
Alejandro Alonso
97f01c646d 🎉 Improve multiple emoji E2E test 2026-02-11 07:36:22 +01:00
Alejandro Alonso
eea1d3c0a5 🎉 Improve updating canvas background E2E test 2026-02-11 07:19:22 +01:00
Alejandro Alonso
9eef4de87d 🐛 Fix dot/dahs/mixed strokes 2026-02-11 07:08:28 +01:00
Andrey Antukh
f4d07a3c36 ⬆️ Update pnpm on frontend and plugins modules 2026-02-10 19:02:32 +01:00
Dominik Jain
76289df32c Establish compatibility with new member anchors (h3 instead of a tag) 2026-02-10 14:03:40 +01:00
Elena Torro
187d1118c0 🔧 Hide text color from selected text 2026-02-10 13:15:55 +01:00
Dominik Jain
a674b5f914 📚 Add instructions on running only the docs server 2026-02-10 12:53:20 +01:00
Dominik Jain
71507fb9b7 ♻️ Adjust ConfigurationLoader to use markdown file instead of yml 2026-02-10 12:35:44 +01:00
Dominik Jain
024aedc3ca ♻️ Convert prompt content to markdown format 2026-02-10 12:35:44 +01:00
Dominik Jain
44657c95df ♻️ Rename prompts.yml -> initial_instructions.md 2026-02-10 12:35:44 +01:00
Dominik Jain
d4d5009a3d Improve prompts on token application 2026-02-10 12:35:44 +01:00
Dominik Jain
bb4d0322d8 🚧 Temporarily add ts-ignore statements
This shall be reverted once the new API types are published
2026-02-10 12:35:44 +01:00
Dominik Jain
56e369a1c0 Add helper functions for token exploration
Extend PenpotUtils with helper functions for token exploration/discovery
and describe them in the system prompt
2026-02-10 12:35:44 +01:00
Dominik Jain
6b277956b9 Add information on clone() method 2026-02-10 12:35:44 +01:00
Dominik Jain
e9a56c9d9f Shorten design token instructions 2026-02-10 12:35:44 +01:00
Dominik Jain
8d90edcc2f Add instructions on design tokens 2026-02-10 12:35:44 +01:00
Dominik Jain
8186f3c87c 📚 Remove misleading information from README
The types build is not part of the bootstrap, and it is not
relevant to regular users (only to developers).

Information on how to apply it is now in types-generator/README.md
2026-02-10 12:35:44 +01:00
Dominik Jain
d7282518c4 📚 Improve usage documentation of API type generator script 2026-02-10 12:35:44 +01:00
Dominik Jain
467eb3c333 Update API docs to include token-related types 2026-02-10 12:35:44 +01:00
Dominik Jain
d2299f83ec Apply bash in build scripts explicitly (Win compatibility) 2026-02-10 12:35:44 +01:00
Andrey Antukh
11a283916d Merge remote-tracking branch 'origin/staging' into staging-render 2026-02-10 11:58:27 +01:00
Aitor Moreno
e9b2e9e818 🚑 Hot fix for text editor internal error 2026-02-10 11:10:16 +01:00
Belén Albeza
c4aa51bc01 🐛 Fix permanent blur when switching pages 2026-02-10 10:59:47 +01:00
Belén Albeza
1c270ac9c6 Remove leftover println in render code 2026-02-10 10:59:47 +01:00
Elena Torro
969666b39b 🔧 Simplify view interaction log message
Remove zoom_changed from log output as it's no longer needed
for debugging after the tile optimization changes.
2026-02-09 11:44:50 +01:00
Elena Torro
a8322215dd 🔧 Optimize pan/zoom tile handling
- Add incremental tile update that preserves cache during pan
- Only invalidate tile cache when zoom changes
- Force visible tiles to render synchronously (no yielding)
- Increase interest area threshold from 2 to 3 tiles
2026-02-09 09:38:01 +01:00
Elena Torro
e1ce97a2b4 🔧 Prioritize visible tiles over interest-area tiles
Partition pending tiles into 4 groups by visibility and cache status.
Visible tiles are processed first to eliminate empty squares during
pan/zoom. Cached tiles within each group are processed before uncached.
2026-02-09 09:38:01 +01:00
Elena Torro
2ccd2a6679 🔧 Use HashSet for grid layout children lookup
HashSet provides O(1) contains() vs Vec's O(n), improving
child lookup performance in grid cell data creation.
2026-02-09 09:38:01 +01:00
Elena Torro
2d9a2e0d50 🔧 Use swap_remove in flex layout distribution
swap_remove is O(1) vs remove's O(n) when order doesn't matter.
These loops iterate backwards, so swap_remove is safe.
2026-02-09 09:38:01 +01:00
Elena Torro
216d400262 🔧 Prevent duplicate layout calculations
Use HashSet for layout_reflows to avoid processing the same
layout multiple times. Also use std::mem::take instead of
creating a new Vec on each iteration.
2026-02-09 09:37:58 +01:00
Elena Torro
c87ffdcd30 🔧 Add forward children iterator for flex layout
Avoid Vec allocation + reverse for reversed flex layouts.
The new children_ids_iter_forward returns children in original order,
eliminating the need to collect and reverse.
2026-02-09 09:35:04 +01:00
Elena Torro
8ef6600cdc 🔧 Return HashSet from update_shape_tiles
Avoid final collect() allocation by returning HashSet directly.
Callers already use extend() which works with both types.
2026-02-09 09:35:04 +01:00
Elena Torro
a3764b9713 🔧 Avoid clone in rebuild_touched_tiles
Use std::mem::take instead of clone to avoid HashSet allocation.
The set was cleared anyway by clean_touched(), so take() is safe.
2026-02-09 09:35:03 +01:00
andrés gonzález
79e5d2f4cd 📚 Change link to post at SH guide (#8247) 2026-02-03 08:27:17 +01:00
301 changed files with 43459 additions and 20636 deletions

View File

@@ -80,7 +80,7 @@ jobs:
- name: "Build package for ${{ inputs.plugin_name }}-plugin"
working-directory: plugins
shell: bash
run: npx nx build ${{ inputs.plugin_name }}-plugin
run: pnpm --filter ${{ inputs.plugin_name }}-plugin build
- name: Select Worker name
run: |

View File

@@ -78,7 +78,7 @@ jobs:
- name: Build styles
working-directory: plugins
shell: bash
run: npx nx run example-styles:build
run: pnpm run build:styles-example
- name: Select Worker name
run: |

View File

@@ -2,12 +2,6 @@
## 2.14.0 (Unreleased)
### :boom: Breaking changes & Deprecations
### :rocket: Epics and highlights
### :heart: Community contributions (Thank you!)
### :sparkles: New features & Enhancements
- Access to design tokens in Penpot Plugins [Taiga #8990](https://tree.taiga.io/project/penpot/us/8990)
@@ -35,11 +29,18 @@
- Fix viewer can update library [Taiga #13186](https://tree.taiga.io/project/penpot/issue/13186)
- Fix remove fill affects different element than selected [Taiga #13128](https://tree.taiga.io/project/penpot/issue/13128)
## 2.13.3
### :bug: Bugs fixed
- Revert yetti (http server) update, because that caused a regression on multipart uploads
## 2.13.2
### :bug: Bugs fixed
- Fix security issue (Path Traversal Vulnerability) on fonts related RPC method
- Fix modifying shapes by apply negative tokens to border radius [Taiga #13317](https://tree.taiga.io/project/penpot/issue/13317)
- Fix arbitrary file read security issue on create-font-variant rpc method (https://github.com/penpot/penpot/security/advisories/GHSA-xp3f-g8rq-9px2)
## 2.13.1

View File

@@ -2,4 +2,30 @@
## Reporting a Vulnerability
Please report security issues to `support@penpot.app`
We take the security of this project seriously. If you have discovered
a security vulnerability, please do **not** open a public issue.
Please report vulnerabilities via email to: **[support@penpot.app]**
### What to include:
* A brief description of the vulnerability.
* Steps to reproduce the issue.
* Potential impact if exploited.
We appreciate your patience and your commitment to **responsible disclosure**.
---
## Security Contributors
We are incredibly grateful to the following individuals and
organizations for their help in keeping this project safe.
* **Ali Maharramli** for identifying critical path traversal vulnerability
> **Note:** This list is a work in progress. If you have contributed
> to the security of this project and would like to be recognized (or
> prefer to remain anonymous), please let us know.

View File

@@ -28,8 +28,8 @@
com.google.guava/guava {:mvn/version "33.4.8-jre"}
funcool/yetti
{:git/tag "v11.9"
:git/sha "5fad7a9"
{:git/tag "v11.8"
:git/sha "1d1b33f"
:git/url "https://github.com/funcool/yetti.git"
:exclusions [org.slf4j/slf4j-api]}

View File

@@ -12,6 +12,7 @@ penpot - error list
<a class="{% if version = 3 %}strong{% endif %}" href="?version=3">[BACKEND ERRORS]</a>
<a class="{% if version = 4 %}strong{% endif %}" href="?version=4">[FRONTEND ERRORS]</a>
<a class="{% if version = 5 %}strong{% endif %}" href="?version=5">[RLIMIT REPORTS]</a>
</div>
</nav>
<main class="horizontal-list">

View File

@@ -8,7 +8,6 @@ Report: {{hint|abbreviate:150}} - {{id}} - Penpot Error Report (v4)
<nav>
<div>[<a href="/dbg/error?version={{version}}">⮜</a>]</div>
<div>[<a href="#head">head</a>]</div>
<!-- <div>[<a href="#props">props</a>]</div> -->
<div>[<a href="#context">context</a>]</div>
{% if report %}
<div>[<a href="#report">report</a>]</div>
@@ -21,7 +20,8 @@ Report: {{hint|abbreviate:150}} - {{id}} - Penpot Error Report (v4)
<div class="table-val">
<h1><span class="not-important">Hint:</span> <br/> {{hint}}</h1>
<h2><span class="not-important">Reported at:</span> <br/> {{created-at}}</h2>
<h2><span class="not-important">Report ID:</span> <br/> {{id}}</h2>
<h2><span class="not-important">Origin:</span> <br/> {{origin}}</h2>
<h2><span class="not-important">HREF:</span> <br/> {{href}}</h2>
</div>
</div>

View File

@@ -0,0 +1,40 @@
{% extends "app/templates/base.tmpl" %}
{% block title %}
Report: {{hint|abbreviate:150}} - {{id}} - Penpot Rate Limit Report
{% endblock %}
{% block content %}
<nav>
<div>[<a href="/dbg/error?version={{version}}">⮜</a>]</div>
<div>[<a href="#head">head</a>]</div>
<div>[<a href="#context">context</a>]</div>
<div>[<a href="#result">result</a>]</div>
</nav>
<main>
<div class="table">
<div class="table-row multiline">
<div id="head" class="table-key">HEAD:</div>
<div class="table-val">
<h1><span class="not-important">Hint:</span> <br/> {{hint}}</h1>
<h2><span class="not-important">Reported at:</span> <br/> {{created-at}}</h2>
<h2><span class="not-important">Report ID:</span> <br/> {{id}}</h2>
</div>
</div>
<div class="table-row multiline">
<div id="context" class="table-key">CONTEXT: </div>
<div class="table-val">
<pre>{{context}}</pre>
</div>
</div>
<div class="table-row multiline">
<div id="result" class="table-key">RESULT: </div>
<div class="table-val">
<pre>{{result}}</pre>
</div>
</div>
</div>
</main>
{% endblock %}

View File

@@ -3,9 +3,9 @@
{:default
[[:default :window "200000/h"]]
;; #{:command/get-teams}
;; #{:main/get-teams}
;; [[:burst :bucket "5/5/5s"]]
;; #{:command/get-profile}
;; #{:main/get-profile}
;; [[:burst :bucket "60/60/1m"]]
}

View File

@@ -240,6 +240,13 @@
(tmpl/render (-> content
(assoc :id id)
(assoc :version 4)
(assoc :created-at (ct/format-inst created-at :rfc1123))))))
(render-template-v5 [{:keys [content id created-at]}]
(-> (io/resource "app/templates/error-report.v5.tmpl")
(tmpl/render (-> content
(assoc :id id)
(assoc :version 5)
(assoc :created-at (ct/format-inst created-at :rfc1123))))))]
(if-let [report (get-report request)]
@@ -247,7 +254,8 @@
1 (render-template-v1 report)
2 (render-template-v2 report)
3 (render-template-v3 report)
4 (render-template-v4 report))]
4 (render-template-v4 report)
5 (render-template-v5 report))]
{::yres/status 200
::yres/body result
::yres/headers {"content-type" "text/html; charset=utf-8"

View File

@@ -213,14 +213,14 @@
(assoc "access-control-allow-origin" origin)
(assoc "access-control-allow-methods" "GET,POST,DELETE,OPTIONS,PUT,HEAD,PATCH")
(assoc "access-control-allow-credentials" "true")
(assoc "access-control-expose-headers" "x-requested-with, content-type, cookie")
(assoc "access-control-allow-headers" "x-frontend-version, content-type, accept, x-requested-width")))
(assoc "access-control-expose-headers" "content-type, set-cookie")
(assoc "access-control-allow-headers" "x-frontend-version, x-client, x-requested-width, content-type, accept, cookie")))
(defn wrap-cors
[handler]
(fn [request]
(let [response (if (= (yreq/method request) :options)
{::yres/status 200}
{::yres/status 204}
(handler request))
origin (yreq/get-header request "origin")]
(update response ::yres/headers with-cors-headers origin))))

View File

@@ -151,20 +151,22 @@
uuid/zero)
props (-> (or (::replace-props resultm)
(-> params
(merge (::props resultm))
(dissoc :profile-id)
(dissoc :type)))
(merge params (::props resultm)))
(clean-props))
context (merge (::context resultm)
(prepare-context-from-request request))
ip-addr (inet/parse-request request)]
ip-addr (inet/parse-request request)
module (get cfg ::rpc/module)]
{::type (or (::type resultm)
(::rpc/type cfg))
::name (or (::name resultm)
(::sv/name mdata))
(let [sname (::sv/name mdata)]
(if (not= module "main")
(str module "-" sname)
sname)))
::profile-id profile-id
::ip-addr ip-addr
::props props

View File

@@ -15,6 +15,7 @@
[app.config :as cf]
[app.db :as db]
[app.loggers.audit :as audit]
[app.rpc.rlimit :as-alias rlimit]
[clojure.spec.alpha :as s]
[integrant.core :as ig]
[promesa.exec :as px]
@@ -41,7 +42,7 @@
(or (instance? java.util.concurrent.CompletionException cause)
(instance? java.util.concurrent.ExecutionException cause)))
(defn record->report
(defn- log-record->report
[{:keys [::l/context ::l/message ::l/props ::l/logger ::l/level ::l/cause] :as record}]
(assert (l/valid-record? record) "expectd valid log record")
(let [data (if (concurrent-exception? cause)
@@ -86,16 +87,16 @@
[{:keys [::db/pool]} {:keys [::l/id] :as record}]
(try
(let [uri (cf/get :public-uri)
report (-> record record->report d/without-nils)]
report (-> record log-record->report d/without-nils)]
(l/dbg :hint "registering error on database"
:id id
:id (str id)
:src "logging"
:uri (str uri "/dbg/error/" id))
(persist-on-database! pool id 3 report))
(catch Throwable cause
(l/warn :hint "unexpected exception on database error logger" :cause cause))))
(defn- event->report
(defn- audit-event->report
[{:keys [::audit/context ::audit/props ::audit/ip-addr] :as record}]
(let [context
(reduce-kv (fn [context k v]
@@ -116,7 +117,8 @@
{:context (-> (into (sorted-map) context)
(pp/pprint-str :length 50))
:props (pp/pprint-str props :length 50)
:origin (::audit/name record)
:href (get props :href)
:hint (get props :hint)
:report (get props :report)}))
@@ -125,15 +127,51 @@
[{:keys [::db/pool]} {:keys [::audit/id] :as event}]
(try
(let [uri (cf/get :public-uri)
report (-> event event->report d/without-nils)]
report (-> event audit-event->report d/without-nils)]
(l/dbg :hint "registering error on database"
:id id
:id (str id)
:src "audit-log"
:uri (str uri "/dbg/error/" id))
(persist-on-database! pool id 4 report))
(catch Throwable cause
(l/warn :hint "unexpected exception on database error logger" :cause cause))))
(defn- rlimit-event->report
[event]
(let [context
(-> {}
(assoc :rlimit/uid (::rlimit/uid event))
(assoc :rlimit/method (::rlimit/method event))
(assoc :backend/tenant (cf/get :tenant))
(assoc :backend/host (cf/get :host))
(assoc :backend/public-uri (str (cf/get :public-uri)))
(assoc :backend/version (:full cf/version)))
result
(->> (::rlimit/results event)
(mapv (fn [result]
(-> (into (sorted-map) result)
(dissoc ::rlimit/method)))))]
{:hint (str "Rate Limit Rejection: " (::rlimit/method event) " for " (::rlimit/uid event))
:context (-> (into (sorted-map) context)
(pp/pprint-str :length 50))
:result (pp/pprint-str result :length 50)}))
(defn- handle-rlimit-event
"Convert the log record into a report object and persist it on the database"
[{:keys [::db/pool]} {:keys [::rlimit/id] :as event}]
(try
(let [uri (cf/get :public-uri)
report (-> event rlimit-event->report d/without-nils)]
(l/dbg :hint "registering rate limit rejection"
:id (str id)
:src "rlimit"
:uri (str uri "/dbg/error/" id))
(persist-on-database! pool id 5 report))
(catch Throwable cause
(l/warn :hint "unexpected exception on database error logger" :cause cause))))
(defmethod ig/assert-key ::reporter
[_ params]
(assert (db/pool? (::db/pool params)) "expect valid database pool"))
@@ -154,6 +192,9 @@
(::audit/id item)
(handle-audit-event cfg item)
(::rlimit/id item)
(handle-rlimit-event cfg item)
:else
(l/warn :hint "received unexpected item" :item item))

View File

@@ -9,10 +9,12 @@
(:require
[app.common.exceptions :as ex]
[app.common.logging :as l]
[app.common.pprint :as pp]
[app.common.uri :as u]
[app.config :as cf]
[app.http.client :as http]
[app.loggers.audit :as audit]
[app.rpc.rlimit :as-alias rlimit]
[app.util.json :as json]
[integrant.core :as ig]
[promesa.exec :as px]
@@ -22,21 +24,28 @@
(defn- send-mattermost-notification!
[cfg {:keys [id] :as report}]
(let [type (get report :type)
text (str "#" type " | " (get report :hint) "\n"
(when id
(str (u/join (cf/get :public-uri) "/dbg/error/" id) " "))
(let [url (u/join (cf/get :public-uri) "/dbg/error/" id)
text (str "Exception: " url " "
(when-let [pid (:profile-id report)]
(str "(pid: #uuid-" pid ")"))
(if (uuid? pid)
(str "(pid: #uuid-" pid ")")
(str "(pid: #ip-" pid ")")))
"\n"
"- host: #" (:host report) "\n"
"- tenant: #" (:tenant report) "\n"
"- origin: #" (:origin report) "\n"
"- href: `" (:href report) "`\n"
"- frontend-version: `" (:frontend-version report) "`\n"
"- backend-version: `" (:backend-version report) "`\n"
(when-let [href (get report :href)]
(str "- href: `" href "`\n"))
(when-let [version (get report :frontend-version)]
(str "- frontend-version: `" version "`\n"))
(when-let [version (get report :backend-version)]
(str "- backend-version: `" version "`\n"))
"\n"
(when-let [info (:info report)]
(str "```\n" info "```"))
(when-let [trace (:trace report)]
(str "```\n"
"Trace:\n"
@@ -54,13 +63,15 @@
(l/warn :hint "error on sending data"
:response (pr-str resp)))))
(defn- record->report
[{:keys [::l/context ::l/id ::l/cause] :as record}]
(defn- log-record->report
[{:keys [::l/context ::l/id ::l/cause ::l/message] :as record}]
(assert (l/valid-record? record) "expectd valid log record")
(let [public-uri (cf/get :public-uri)]
{:id id
:type "exception"
:origin "logging"
:hint (or (some-> cause ex-message) @message)
:tenant (cf/get :tenant)
:host (cf/get :host)
:backend-version (:full cf/version)
@@ -74,7 +85,9 @@
(defn- audit-event->report
[{:keys [::audit/context ::audit/props ::audit/id] :as event}]
{:id id
:type "exception"
:origin "audit-log"
:hint (get props :hint)
:tenant (cf/get :tenant)
:host (cf/get :host)
:backend-version (:full cf/version)
@@ -82,18 +95,35 @@
:profile-id (:audit/profile-id event)
:href (get props :href)})
(defn- handle-log-record
[cfg record]
(try
(let [report (record->report record)]
(send-mattermost-notification! cfg report))
(catch Throwable cause
(l/warn :hint "unhandled error" :cause cause))))
(defn- rlimit-event->report
[event]
{:id (::rlimit/id event)
:type "notification"
:origin "rlimit"
:hint (str "rlimit reject of "
(::rlimit/method event)
" for "
(::rlimit/uid event))
:tenant (cf/get :tenant)
:host (cf/get :host)
:backend-version (:full cf/version)
:profile-id (::rlimit/profile-id event)
:info (with-out-str
(println "Rejected by:")
(println "------------")
(println "Method: " (::rlimit/method event))
(println "Limit Name: " (::rlimit/name event))
(println "Limit Strategy:" (::rlimit/strategy event))
(println)
(println "Results & Config:")
(println "-----------------")
(doseq [result (::rlimit/results event)]
(pp/pprint (into (sorted-map) result))))})
(defn- handle-audit-event
[cfg record]
(defn- handle-event
[cfg event event->report]
(try
(let [report (audit-event->report record)]
(let [report (event->report event)]
(send-mattermost-notification! cfg report))
(catch Throwable cause
(l/warn :hint "unhandled error" :cause cause))))
@@ -116,10 +146,13 @@
(when @enabled
(cond
(::l/id item)
(handle-log-record cfg item)
(handle-event cfg item log-record->report)
(::audit/id item)
(handle-audit-event cfg item)
(handle-event cfg item audit-event->report)
(::rlimit/id item)
(handle-event cfg item rlimit-event->report)
:else
(l/warn :hint "received unexpected item" :item item)))

View File

@@ -317,7 +317,13 @@
::climit/enabled (contains? cf/flags :rpc-climit)}
:app.rpc/rlimit
{::wrk/executor (ig/ref ::wrk/netty-executor)}
{::wrk/executor (ig/ref ::wrk/netty-executor)
:app.loggers.mattermost/reporter
(ig/ref :app.loggers.mattermost/reporter)
:app.loggers.database/reporter
(ig/ref :app.loggers.database/reporter)}
:app.rpc/methods
{::http.client/client (ig/ref ::http.client/client)

View File

@@ -90,7 +90,7 @@
[methods]
(let [methods (update-vals methods peek)]
(fn [{:keys [params path-params method] :as request}]
(let [handler-name (:type path-params)
(let [handler-name (:method-name path-params)
etag (yreq/get-header request "if-none-match")
key-id (get request ::http/auth-key-id)
@@ -227,8 +227,8 @@
(wrap-authentication cfg $ mdata)))
(defn- process-method
[cfg module wrap-fn [f mdata]]
(l/trc :hint "add method" :module module :name (::sv/name mdata))
[cfg wrap-fn [f mdata]]
(l/trc :hint "add method" :module (::module cfg) :type (::type cfg) :name (::sv/name mdata))
(let [f (wrap-fn cfg f mdata)
k (keyword (::sv/name mdata))]
[k [mdata (partial f cfg)]]))
@@ -239,7 +239,7 @@
(defn- resolve-methods
[cfg]
(let [cfg (assoc cfg ::type "command" ::metrics-id :rpc-command-timing)]
(let [cfg (assoc cfg ::module "main" ::type "command" ::metrics-id :rpc-main-timing)]
(->> (sv/scan-ns
'app.rpc.commands.access-token
'app.rpc.commands.audit
@@ -266,7 +266,7 @@
'app.rpc.commands.verify-token
'app.rpc.commands.viewer
'app.rpc.commands.webhooks)
(map (partial process-method cfg "rpc" wrap))
(map (partial process-method cfg wrap))
(into {}))))
(def ^:private schema:methods-params
@@ -298,13 +298,13 @@
(defn- resolve-management-methods
[cfg]
(let [cfg (assoc cfg ::type "management" ::metrics-id :rpc-management-timing)
(let [cfg (assoc cfg ::module "management" ::type "command" ::metrics-id :rpc-management-timing)
mods (cond->> (list 'app.rpc.management.exporter)
(contains? cf/flags :nitrate)
(cons 'app.rpc.management.nitrate))]
(->> (apply sv/scan-ns mods)
(map (partial process-method cfg "management" wrap-management))
(map (partial process-method cfg wrap-management))
(into {}))))
(def ^:private schema:management-methods-params
@@ -359,7 +359,7 @@
(let [public-uri (cf/get :public-uri)]
["/api"
["/management"
["/methods/:type"
["/methods/:method-name"
{:middleware [[mw/shared-key-auth shared-keys]
[session/authz cfg]]
:handler (make-rpc-handler management-methods)}]
@@ -370,7 +370,7 @@
:description "MANAGEMENT API")]
["/main"
["/methods/:type"
["/methods/:method-name"
{:middleware [[mw/cors]
[sec/client-header-check]
[session/authz cfg]
@@ -388,7 +388,7 @@
["/openapi" {:handler (redirect (u/join public-uri "/api/main/doc/openapi"))}]
["/openapi.join" {:handler (redirect (u/join public-uri "/api/main/doc/openapi.json"))}]
["/rpc/command/:type"
["/rpc/command/:method-name"
{:middleware [[mw/cors]
[sec/client-header-check]
[session/authz cfg]

View File

@@ -52,6 +52,8 @@
[app.common.uuid :as uuid]
[app.config :as cf]
[app.http :as-alias http]
[app.loggers.database :as loggers.db]
[app.loggers.mattermost :as loggers.mm]
[app.redis :as rds]
[app.redis.script :as-alias rscript]
[app.rpc :as-alias rpc]
@@ -171,9 +173,9 @@
:hint (str/ffmt "looks like '%' does not have a valid format" opts))))
(defmethod process-limit :bucket
[rconn profile-id now {:keys [::key ::params ::service ::capacity ::interval ::rate] :as limit}]
[rconn profile-id now {:keys [::key ::params ::method ::capacity ::interval ::rate] :as limit}]
(let [script (-> bucket-rate-limit-script
(assoc ::rscript/keys [(str key "." service "." profile-id)])
(assoc ::rscript/keys [(str key "." method "." profile-id)])
(assoc ::rscript/vals (conj params (->seconds now))))
result (rds/eval rconn script)
allowed? (boolean (nth result 0))
@@ -181,7 +183,7 @@
reset (* (/ (inst-ms interval) rate)
(- capacity remaining))]
(l/trace :hint "limit processed"
:service service
:method method
:limit (name (::name limit))
:strategy (name (::strategy limit))
:opts (::opts limit)
@@ -193,17 +195,17 @@
(assoc ::lresult/remaining remaining))))
(defmethod process-limit :window
[rconn profile-id now {:keys [::permits ::unit ::key ::service] :as limit}]
[rconn uid now {:keys [::permits ::unit ::key ::method] :as limit}]
(let [ts (ct/truncate now unit)
ttl (ct/diff now (ct/plus ts {unit 1}))
script (-> window-rate-limit-script
(assoc ::rscript/keys [(str key "." service "." profile-id "." (ct/format-inst ts))])
(assoc ::rscript/keys [(str key "." method "." uid "." (ct/format-inst ts))])
(assoc ::rscript/vals [permits (->seconds ttl)]))
result (rds/eval rconn script)
allowed? (boolean (nth result 0))
remaining (nth result 1)]
(l/trace :hint "limit processed"
:service service
:method method
:name (name (::name limit))
:strategy (name (::strategy limit))
:opts (::opts limit)
@@ -211,12 +213,13 @@
:remaining remaining)
(-> limit
(assoc ::lresult/allowed allowed?)
(assoc ::lresult/timestamp ts)
(assoc ::lresult/remaining remaining)
(assoc ::lresult/reset (ct/plus ts {unit 1})))))
(defn- process-limits
[rconn profile-id limits now]
(let [results (into [] (map (partial process-limit rconn profile-id now)) limits)
[{:keys [::rds/conn] :as cfg} uid limits now]
(let [results (into [] (map (partial process-limit conn uid now)) limits)
remaining (->> results
(d/index-by ::name ::lresult/remaining)
(uri/map->query-string))
@@ -227,11 +230,22 @@
rejected (d/seek (complement ::lresult/allowed) results)]
(when rejected
(l/warn :hint "rejected rate limit"
:profile-id (str profile-id)
:limit-service (-> rejected ::service name)
:limit-name (-> rejected ::name name)
:limit-strategy (-> rejected ::strategy name)))
(let [event {::id (uuid/next)
::uid uid
::method (-> rejected ::method name)
::name (-> rejected ::name name)
::strategy (-> rejected ::strategy name)
::results results}]
(l/warn :hint "rejected rate limit"
:method (-> rejected ::method name)
:name (-> rejected ::name name)
:strategy (-> rejected ::strategy name)
:uid (str uid)
:report-id (:id event))
(loggers.mm/emit cfg event)
(loggers.db/emit cfg event)))
{::enabled true
::allowed (not (some? rejected))
@@ -244,7 +258,7 @@
[state skey sname]
(when-let [limits (or (get-in @state [::limits skey])
(get-in @state [::limits :default]))]
(into [] (map #(assoc % ::service sname)) limits)))
(into [] (map #(assoc % ::method sname)) limits)))
(defn- get-uid
[{:keys [::rpc/profile-id] :as params}]
@@ -254,10 +268,10 @@
uuid/zero)))
(defn- process-request'
[{:keys [::rds/conn] :as cfg} limits params]
[cfg limits params]
(try
(let [uid (get-uid params)
result (process-limits conn uid limits (ct/now))]
result (process-limits cfg uid limits (ct/now))]
(if (contains? cf/flags :soft-rpc-rlimit)
{::enabled false}
result))
@@ -275,8 +289,8 @@
(assert (or (nil? rlimit) (valid-rlimit-instance? rlimit)) "expected a valid rlimit instance")
(if rlimit
(let [skey (keyword (::rpc/type cfg) (->> mdata ::sv/spec name))
sname (str (::rpc/type cfg) "." (->> mdata ::sv/spec name))
(let [skey (keyword (::rpc/module cfg) (->> mdata ::sv/spec name))
sname (str (::rpc/module cfg) "." (->> mdata ::sv/spec name))
cfg (-> cfg
(assoc ::skey skey)
(assoc ::sname sname))]

View File

@@ -33,6 +33,7 @@
java.util.Optional
java.util.concurrent.atomic.AtomicLong
org.reactivestreams.Subscriber
software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider
software.amazon.awssdk.core.ResponseBytes
software.amazon.awssdk.core.async.AsyncRequestBody
software.amazon.awssdk.core.async.AsyncResponseTransformer
@@ -199,7 +200,8 @@
(defn- build-s3-client
[{:keys [::region ::endpoint ::wrk/netty-io-executor]}]
(let [aconfig (-> (ClientAsyncConfiguration/builder)
(let [creds-provider (DefaultCredentialsProvider/create)
aconfig (-> (ClientAsyncConfiguration/builder)
(.build))
sconfig (-> (S3Configuration/builder)
@@ -221,6 +223,7 @@
builder (.asyncConfiguration ^S3AsyncClientBuilder builder ^ClientAsyncConfiguration aconfig)
builder (.httpClient ^S3AsyncClientBuilder builder ^NettyNioAsyncHttpClient hclient)
builder (.region ^S3AsyncClientBuilder builder (lookup-region region))
builder (.credentialsProvider ^S3AsyncClientBuilder builder creds-provider)
builder (cond-> ^S3AsyncClientBuilder builder
(some? endpoint)
(.endpointOverride (URI. (str endpoint))))]
@@ -237,7 +240,8 @@
(defn- build-s3-presigner
[{:keys [::region ::endpoint]}]
(let [config (-> (S3Configuration/builder)
(let [creds-provider (DefaultCredentialsProvider/create)
config (-> (S3Configuration/builder)
(cond-> (some? endpoint) (.pathStyleAccessEnabled true))
(.build))]
@@ -245,6 +249,7 @@
(cond-> (some? endpoint) (.endpointOverride (URI. (str endpoint))))
(.region (lookup-region region))
(.serviceConfiguration ^S3Configuration config)
(.credentialsProvider creds-provider)
(.build))))
(defn- write-input-stream

View File

@@ -104,13 +104,13 @@
(assoc-in [::db/pool ::db/password] (:database-password config))
(assoc-in [:app.rpc/methods :app.setup/templates] templates)
(assoc-in [:app.rpc/methods :app.setup/templates] templates)
(update :app.rpc/methods
(fn [state]
(-> state
(assoc :app.setup/templates templates)
(assoc :app.loggers.mattermost/reporter nil)
(assoc :app.loggers.database/reporter nil))))
(update :app.rpc/rlimit assoc
:app.loggers.mattermost/reporter nil
:app.loggers.database/reporter nil)
(update :app.rpc/methods assoc
:app.setup/templates templates
:app.loggers.mattermost/reporter nil
:app.loggers.database/reporter nil)
(dissoc :app.srepl/server
:app.http/server
:app.http/route

View File

@@ -299,3 +299,8 @@
(js/console.log (format-throwable cause))
(finally
(js/console.groupEnd))))))
(defn get-hint
[cause]
(or (some-> (ex-data cause) (get :hint) first-line)
(some-> (ex-message cause) first-line)))

View File

@@ -55,6 +55,7 @@
"design-tokens/v1"
"text-editor/v2-html-paste"
"text-editor/v2"
"text-editor-wasm/v1"
"render-wasm/v1"
"variants/v1"})
@@ -78,6 +79,7 @@
"plugins/runtime"
"text-editor/v2-html-paste"
"text-editor/v2"
"text-editor-wasm/v1"
"tokens/numeric-input"
"render-wasm/v1"})
@@ -127,6 +129,7 @@
:feature-design-tokens "design-tokens/v1"
:feature-text-editor-v2 "text-editor/v2"
:feature-text-editor-v2-html-paste "text-editor/v2-html-paste"
:feature-text-editor-wasm "text-editor-wasm/v1"
:feature-render-wasm "render-wasm/v1"
:feature-variants "variants/v1"
:feature-token-input "tokens/numeric-input"

View File

@@ -35,7 +35,7 @@
[::sm/text {:error/fn token-value-empty-fn}])
(def schema:token-value-font-family
[:vector :string])
[:vector ::sm/text])
(def schema:token-value-typography-map
[:map

View File

@@ -5,7 +5,8 @@ ENV LANG=en_US.UTF-8 \
LC_ALL=en_US.UTF-8 \
NODE_VERSION=v22.22.0 \
DEBIAN_FRONTEND=noninteractive \
PATH=/opt/node/bin:/opt/imagick/bin:$PATH
PATH=/opt/node/bin:/opt/imagick/bin:$PATH \
PLAYWRIGHT_BROWSERS_PATH=/opt/penpot/browsers
RUN set -ex; \
useradd -U -M -u 1001 -s /bin/false -d /opt/penpot penpot; \

View File

@@ -198,13 +198,6 @@ services:
## Valkey (or previously Redis) is used for the websockets notifications.
PENPOT_REDIS_URI: redis://penpot-valkey/0
penpot-mcp:
image: penpotapp/mcp:${PENPOT_VERSION:-latest}
restart: always
networks:
- penpot
penpot-postgres:
image: "postgres:15"
restart: always

View File

@@ -8,9 +8,7 @@ desc: Customize your Penpot instance today. Learn how to install with Elestio, D
This guide explains how to get your own Penpot instance, running on a machine you control,
to test it, use it by you or your team, or even customize and extend it any way you like.
If you need more context you can look at the <a
href="https://community.penpot.app/t/self-hosting-penpot-i/2336" target="_blank">post
about self-hosting</a> in Penpot community.
For additional context, see the post <a href="https://penpot.app/blog/how-to-self-host-penpot/" target="_blank">How to self-host Penpot: A technical implementation guide</a> on the Penpot blog.
<strong>The experience stays the same, whether you use
Penpot <a href="https://design.penpot.app" target="_blank">in the cloud</a>

View File

@@ -14,7 +14,7 @@ Keep in mind that database size doesn't grow strictly proportionally with user c
# About Valkey / Redis requirements
"Valkey is mainly used for coordinating websocket notifications and, since Penpot 2.11, as a cache. Therefore, disk storage will not be necessary as it will use the instance's RAM.
Valkey is mainly used for coordinating websocket notifications and, since Penpot 2.11, as a cache. Therefore, disk storage will not be necessary as it will use the instance's RAM.
To prevent the cache from hogging all the system's RAM usage, it is recommended to use two configuration parameters which, both in the docker-compose.yaml provided by Penpot and in the official Helm Chart, come with default parameters that should be sufficient for most deployments:

View File

@@ -15,6 +15,7 @@ pnpm run build;
cp pnpm-lock.yaml target/;
cp package.json target/;
touch target/pnpm-workspace.yaml;
cat <<EOF | tee target/setup
#/usr/bin/env bash
@@ -22,7 +23,7 @@ set -e;
corepack enable;
corepack install;
pnpm install
pnpx playwright install chromium;
pnpm exec playwright install chromium;
EOF
chmod +x target/setup;

View File

@@ -4,7 +4,7 @@
"license": "MPL-2.0",
"author": "Kaleidos INC",
"private": true,
"packageManager": "pnpm@10.28.2+sha512.41872f037ad22f7348e3b1debbaf7e867cfd448f2726d9cf74c08f19507c31d2c8e7a11525b983febc2df640b5438dee6023ebb1f84ed43cc2d654d2bc326264",
"packageManager": "pnpm@10.29.2+sha512.bef43fa759d91fd2da4b319a5a0d13ef7a45bb985a3d7342058470f9d2051a3ba8674e629672654686ef9443ad13a82da2beb9eeb3e0221c87b8154fff9d74b8",
"browserslist": [
"defaults"
],
@@ -47,12 +47,12 @@
"devDependencies": {
"@penpot/draft-js": "workspace:./packages/draft-js",
"@penpot/mousetrap": "workspace:./packages/mousetrap",
"@penpot/tokenscript": "workspace:./packages/tokenscript",
"@penpot/plugins-runtime": "1.4.2",
"@penpot/svgo": "penpot/svgo#v3.2",
"@penpot/text-editor": "workspace:./text-editor",
"@playwright/test": "1.58.0",
"@penpot/tokenscript": "workspace:./packages/tokenscript",
"@penpot/ui": "workspace:./packages/ui",
"@playwright/test": "1.58.0",
"@storybook/addon-docs": "10.1.11",
"@storybook/addon-themes": "10.1.11",
"@storybook/addon-vitest": "10.1.11",
@@ -103,6 +103,7 @@
"sass": "^1.89.0",
"sass-embedded": "^1.89.0",
"sax": "^1.4.1",
"scheduler": "^0.27.0",
"source-map-support": "^0.5.21",
"storybook": "10.1.11",
"style-dictionary": "5.0.0-rc.1",

View File

@@ -8,6 +8,6 @@
"author": "Andrey Antukh",
"license": "MPL-2.0",
"dependencies": {
"@tokens-studio/tokenscript-interpreter": "^0.23.1"
"@tokens-studio/tokenscript-interpreter": "^0.26.0"
}
}

View File

@@ -1,12 +1,12 @@
// Auto-generated by @tokens-studio/tokenscript-schemas
// Version: @tokens-studio/tokenscript-schemas@v0.1.2
// Version: @tokens-studio/tokenscript-schemas@v0.4.0
// GitHub: https://github.com/tokens-studio/tokenscript-schemas
// Command: npx @tokens-studio/tokenscript-schemas bundle preset:css --output ./tokenscript-schemas.js
// Generated: 2026-01-07T09:21:11.478Z
// Command: npx @tokens-studio/tokenscript-schemas bundle preset:css preset:cssColors --output ./schemas.js
// Generated: 2026-02-11T08:46:40.467Z
import { Config } from "@tokens-studio/tokenscript-interpreter";
const SCHEMAS = [
export const SCHEMAS = [
{
uri: "https://schema.tokenscript.dev.gcp.tokens.studio/api/v1/core/hex-color/0/",
schema: {
@@ -31,7 +31,127 @@ const SCHEMAS = [
}
}
],
"conversions": []
"conversions": [
{
"source": "https://schema.tokenscript.dev.gcp.tokens.studio/api/v1/core/srgb-color/0/",
"target": "$self",
"description": "Converts sRGB (0-1) to Hex format",
"lossless": true,
"script": {
"type": "https://schema.tokenscript.dev.gcp.tokens.studio/api/v1/core/tokenscript/0/",
"script": "// sRGB to Hex Conversion\n// Converts sRGB (0-1) to hexadecimal string format\n//\n// Examples:\n// sRGB(1, 0, 0) → #ff0000\n// sRGB(0, 1, 0.5) → #00ff80\n\nvariable hex: String = \"#\";\nvariable value: Number = 0;\n\n// Red channel\nvalue = round({input}.r * 255);\nif (value < 0) [ value = 0; ];\nif (value > 255) [ value = 255; ];\nif (value < 16) [\n hex = hex.concat(\"0\").concat(value.to_string(16));\n] else [\n hex = hex.concat(value.to_string(16));\n];\n\n// Green channel\nvalue = round({input}.g * 255);\nif (value < 0) [ value = 0; ];\nif (value > 255) [ value = 255; ];\nif (value < 16) [\n hex = hex.concat(\"0\").concat(value.to_string(16));\n] else [\n hex = hex.concat(value.to_string(16));\n];\n\n// Blue channel\nvalue = round({input}.b * 255);\nif (value < 0) [ value = 0; ];\nif (value > 255) [ value = 255; ];\nif (value < 16) [\n hex = hex.concat(\"0\").concat(value.to_string(16));\n] else [\n hex = hex.concat(value.to_string(16));\n];\n\nreturn hex;"
}
},
{
"source": "https://schema.tokenscript.dev.gcp.tokens.studio/api/v1/core/p3-color/0/",
"target": "$self",
"description": "Converts Display P3 to Hex format (clamps to sRGB gamut)",
"lossless": false,
"script": {
"type": "https://schema.tokenscript.dev.gcp.tokens.studio/api/v1/core/tokenscript/0/",
"script": "// Display P3 to Hex Conversion\n// Converts P3 (0-1) to hexadecimal string format\n// Note: P3 colors may be out of sRGB gamut, values are clamped to 0-1\n//\n// Examples:\n// P3(1, 0, 0) → #ff0000\n// P3(0, 1, 0.5) → #00ff80\n\nvariable hex: String = \"#\";\nvariable value: Number = 0;\n\n// Red channel (clamp P3 to sRGB range)\nvalue = {input}.r;\nif (value < 0) [ value = 0; ];\nif (value > 1) [ value = 1; ];\nvalue = round(value * 255);\nif (value < 16) [\n hex = hex.concat(\"0\").concat(value.to_string(16));\n] else [\n hex = hex.concat(value.to_string(16));\n];\n\n// Green channel\nvalue = {input}.g;\nif (value < 0) [ value = 0; ];\nif (value > 1) [ value = 1; ];\nvalue = round(value * 255);\nif (value < 16) [\n hex = hex.concat(\"0\").concat(value.to_string(16));\n] else [\n hex = hex.concat(value.to_string(16));\n];\n\n// Blue channel\nvalue = {input}.b;\nif (value < 0) [ value = 0; ];\nif (value > 1) [ value = 1; ];\nvalue = round(value * 255);\nif (value < 16) [\n hex = hex.concat(\"0\").concat(value.to_string(16));\n] else [\n hex = hex.concat(value.to_string(16));\n];\n\nreturn hex;"
}
},
{
"source": "https://schema.tokenscript.dev.gcp.tokens.studio/api/v1/core/hsl-color/0/",
"target": "$self",
"description": "Converts HSL to Hex format",
"lossless": true,
"script": {
"type": "https://schema.tokenscript.dev.gcp.tokens.studio/api/v1/core/tokenscript/0/",
"script": "// HSL to Hex Conversion\n// Converts HSL to hexadecimal string format\n// Reference: Standard HSL to RGB algorithm\n//\n// Input: Color.HSL with h (0-360), s (0-1), l (0-1)\n// Output: Hex string #rrggbb\n\n// Get input HSL values\nvariable h: Number = {input}.h;\nvariable s: Number = {input}.s;\nvariable l: Number = {input}.l;\n\n// Normalize hue to 0-1 range\nvariable hue: Number = h / 360;\n\n// RGB values (default to achromatic)\nvariable r: Number = l;\nvariable g: Number = l;\nvariable b: Number = l;\n\n// Only calculate if there's saturation\nif (s > 0) [\n variable q: Number = 0;\n if (l < 0.5) [\n q = l * (1 + s);\n ] else [\n q = l + s - l * s;\n ];\n\n variable p: Number = 2 * l - q;\n\n // Red (hue + 1/3)\n variable tr: Number = hue + 0.333333333333333;\n if (tr < 0) [ tr = tr + 1; ];\n if (tr > 1) [ tr = tr - 1; ];\n\n if (tr < 0.166666666666667) [\n r = p + (q - p) * 6 * tr;\n ] else [\n if (tr < 0.5) [\n r = q;\n ] else [\n if (tr < 0.666666666666667) [\n r = p + (q - p) * (0.666666666666667 - tr) * 6;\n ] else [\n r = p;\n ];\n ];\n ];\n\n // Green (hue)\n variable tg: Number = hue;\n if (tg < 0) [ tg = tg + 1; ];\n if (tg > 1) [ tg = tg - 1; ];\n\n if (tg < 0.166666666666667) [\n g = p + (q - p) * 6 * tg;\n ] else [\n if (tg < 0.5) [\n g = q;\n ] else [\n if (tg < 0.666666666666667) [\n g = p + (q - p) * (0.666666666666667 - tg) * 6;\n ] else [\n g = p;\n ];\n ];\n ];\n\n // Blue (hue - 1/3)\n variable tb: Number = hue - 0.333333333333333;\n if (tb < 0) [ tb = tb + 1; ];\n if (tb > 1) [ tb = tb - 1; ];\n\n if (tb < 0.166666666666667) [\n b = p + (q - p) * 6 * tb;\n ] else [\n if (tb < 0.5) [\n b = q;\n ] else [\n if (tb < 0.666666666666667) [\n b = p + (q - p) * (0.666666666666667 - tb) * 6;\n ] else [\n b = p;\n ];\n ];\n ];\n];\n\n// Convert RGB to hex\nvariable hex: String = \"#\";\nvariable value: Number = 0;\n\n// Red\nvalue = round(r * 255);\nif (value < 0) [ value = 0; ];\nif (value > 255) [ value = 255; ];\nif (value < 16) [\n hex = hex.concat(\"0\").concat(value.to_string(16));\n] else [\n hex = hex.concat(value.to_string(16));\n];\n\n// Green\nvalue = round(g * 255);\nif (value < 0) [ value = 0; ];\nif (value > 255) [ value = 255; ];\nif (value < 16) [\n hex = hex.concat(\"0\").concat(value.to_string(16));\n] else [\n hex = hex.concat(value.to_string(16));\n];\n\n// Blue\nvalue = round(b * 255);\nif (value < 0) [ value = 0; ];\nif (value > 255) [ value = 255; ];\nif (value < 16) [\n hex = hex.concat(\"0\").concat(value.to_string(16));\n] else [\n hex = hex.concat(value.to_string(16));\n];\n\nreturn hex;"
}
},
{
"source": "https://schema.tokenscript.dev.gcp.tokens.studio/api/v1/core/oklch-color/0/",
"target": "$self",
"description": "Converts OKLCH to Hex format (clamps to sRGB gamut)",
"lossless": false,
"script": {
"type": "https://schema.tokenscript.dev.gcp.tokens.studio/api/v1/core/tokenscript/0/",
"script": "// OKLCH to Hex Conversion\n// Converts OKLCH perceptual color to hexadecimal string format\n// Path: OKLCH → OKLab → XYZ-D65 → Linear sRGB → sRGB → Hex\n//\n// Input: Color.OKLCH with l (0-1), c, h (0-360)\n// Output: Hex string #rrggbb\n\n// Get input OKLCH values\nvariable ok_l: Number = {input}.l;\nvariable ok_c: Number = {input}.c;\nvariable ok_h: Number = {input}.h;\n\n// === Step 1: OKLCH to OKLab (polar to cartesian) ===\nvariable pi: Number = pi();\nvariable deg_to_rad: Number = pi / 180;\nvariable h_rad: Number = ok_h * deg_to_rad;\n\nvariable lab_a: Number = ok_c * cos(h_rad);\nvariable lab_b: Number = ok_c * sin(h_rad);\n\n// === Step 2: OKLab to XYZ-D65 ===\n// Inverse Lab-to-LMS matrix\nvariable lms_l: Number = 1.0 * ok_l + 0.3963377773761749 * lab_a + 0.2158037573099136 * lab_b;\nvariable lms_m: Number = 1.0 * ok_l + -0.1055613458156586 * lab_a + -0.0638541728258133 * lab_b;\nvariable lms_s: Number = 1.0 * ok_l + -0.0894841775298119 * lab_a + -1.2914855480194092 * lab_b;\n\n// Cube the values (inverse of cube root)\nvariable lms_l_cubed: Number = lms_l * lms_l * lms_l;\nvariable lms_m_cubed: Number = lms_m * lms_m * lms_m;\nvariable lms_s_cubed: Number = lms_s * lms_s * lms_s;\n\n// Inverse LMS-to-XYZ matrix\nvariable xyz_x: Number = 1.2268798758459243 * lms_l_cubed + -0.5578149944602171 * lms_m_cubed + 0.2813910456659647 * lms_s_cubed;\nvariable xyz_y: Number = -0.0405757452148008 * lms_l_cubed + 1.1122868032803170 * lms_m_cubed + -0.0717110580655164 * lms_s_cubed;\nvariable xyz_z: Number = -0.0763729366746601 * lms_l_cubed + -0.4214933324022432 * lms_m_cubed + 1.5869240198367816 * lms_s_cubed;\n\n// === Step 3: XYZ-D65 to Linear sRGB ===\nvariable linear_r: Number = 3.2409699419045226 * xyz_x + -1.537383177570094 * xyz_y + -0.4986107602930034 * xyz_z;\nvariable linear_g: Number = -0.9692436362808796 * xyz_x + 1.8759675015077202 * xyz_y + 0.04155505740717559 * xyz_z;\nvariable linear_b: Number = 0.05563007969699366 * xyz_x + -0.20397695888897652 * xyz_y + 1.0569715142428786 * xyz_z;\n\n// === Step 4: Linear sRGB to sRGB (gamma correction) ===\nvariable threshold: Number = 0.0031308;\nvariable linear_scale: Number = 12.92;\nvariable gamma_offset: Number = 0.055;\nvariable gamma_scale: Number = 1.055;\nvariable gamma_exp: Number = 0.416666666666667;\n\nvariable srgb_r: Number = 0;\nif (linear_r <= threshold) [\n srgb_r = linear_r * linear_scale;\n] else [\n if (linear_r > 0) [\n srgb_r = gamma_scale * pow(linear_r, gamma_exp) - gamma_offset;\n ] else [\n srgb_r = 0;\n ];\n];\n\nvariable srgb_g: Number = 0;\nif (linear_g <= threshold) [\n srgb_g = linear_g * linear_scale;\n] else [\n if (linear_g > 0) [\n srgb_g = gamma_scale * pow(linear_g, gamma_exp) - gamma_offset;\n ] else [\n srgb_g = 0;\n ];\n];\n\nvariable srgb_b: Number = 0;\nif (linear_b <= threshold) [\n srgb_b = linear_b * linear_scale;\n] else [\n if (linear_b > 0) [\n srgb_b = gamma_scale * pow(linear_b, gamma_exp) - gamma_offset;\n ] else [\n srgb_b = 0;\n ];\n];\n\n// === Step 5: sRGB to Hex ===\nvariable hex: String = \"#\";\nvariable value: Number = 0;\n\n// Red (clamp to 0-1)\nvalue = srgb_r;\nif (value < 0) [ value = 0; ];\nif (value > 1) [ value = 1; ];\nvalue = round(value * 255);\nif (value < 16) [\n hex = hex.concat(\"0\").concat(value.to_string(16));\n] else [\n hex = hex.concat(value.to_string(16));\n];\n\n// Green\nvalue = srgb_g;\nif (value < 0) [ value = 0; ];\nif (value > 1) [ value = 1; ];\nvalue = round(value * 255);\nif (value < 16) [\n hex = hex.concat(\"0\").concat(value.to_string(16));\n] else [\n hex = hex.concat(value.to_string(16));\n];\n\n// Blue\nvalue = srgb_b;\nif (value < 0) [ value = 0; ];\nif (value > 1) [ value = 1; ];\nvalue = round(value * 255);\nif (value < 16) [\n hex = hex.concat(\"0\").concat(value.to_string(16));\n] else [\n hex = hex.concat(value.to_string(16));\n];\n\nreturn hex;"
}
}
]
}
},
{
uri: "https://schema.tokenscript.dev.gcp.tokens.studio/api/v1/core/srgb-color/0/",
schema: {
"name": "SRGB",
"type": "color",
"description": "sRGB color space with normalized 0-1 range. The standard color space for web and displays.",
"schema": {
"type": "object",
"properties": {
"r": {
"type": "number",
"description": "Red channel (0-1)"
},
"g": {
"type": "number",
"description": "Green channel (0-1)"
},
"b": {
"type": "number",
"description": "Blue channel (0-1)"
}
},
"required": [
"r",
"g",
"b"
],
"order": [
"r",
"g",
"b"
],
"additionalProperties": false
},
"initializers": [
{
"title": "sRGB Color Initializer",
"keyword": "srgb",
"description": "Creates an sRGB color from normalized 0-1 values",
"script": {
"type": "https://schema.tokenscript.dev.gcp.tokens.studio/api/v1/core/tokenscript/0/",
"script": "// sRGB Color Initializer\n// Creates an sRGB color from normalized 0-1 values\n// Input: List of [r, g, b] or [r, g, b, alpha] values in 0-1 range\n\nvariable color_values: List = {input};\nvariable output: Color.SRGB;\n\noutput.r = color_values.get(0);\noutput.g = color_values.get(1);\noutput.b = color_values.get(2);\n\n// Set alpha if provided as 4th parameter\nif (color_values.length() > 3) [\n output.alpha = color_values.get(3);\n];\n\nreturn output;"
}
}
],
"conversions": [
{
"source": "https://schema.tokenscript.dev.gcp.tokens.studio/api/v1/core/rgb-color/0/",
"target": "$self",
"description": "Converts RGB (0-255) to sRGB (0-1) by normalizing",
"lossless": true,
"script": {
"type": "https://schema.tokenscript.dev.gcp.tokens.studio/api/v1/core/tokenscript/0/",
"script": "// RGB to sRGB Conversion\n// Converts RGB (0-255) to sRGB (0-1) by normalizing\n// Input: Color.Rgb with r, g, b in 0-255 range\n// Output: Color.SRGB with r, g, b in 0-1 range\n// Lossless: Yes (simple division)\n\nvariable r_normalized: Number = {input}.r / 255;\nvariable g_normalized: Number = {input}.g / 255;\nvariable b_normalized: Number = {input}.b / 255;\n\nvariable output: Color.SRGB;\noutput.r = r_normalized;\noutput.g = g_normalized;\noutput.b = b_normalized;\n\nreturn output;"
}
},
{
"source": "https://schema.tokenscript.dev.gcp.tokens.studio/api/v1/core/hsl-color/0/",
"target": "$self",
"description": "Converts HSL to sRGB",
"lossless": true,
"script": {
"type": "https://schema.tokenscript.dev.gcp.tokens.studio/api/v1/core/tokenscript/0/",
"script": "// HSL to sRGB Conversion\n// Reference: https://github.com/color-js/color.js/blob/main/src/spaces/hsl.js\n//\n// Algorithm:\n// 1. If saturation is 0, it's achromatic: R=G=B=L\n// 2. Otherwise use the HSL to RGB formula:\n// - Calculate intermediate values based on L\n// - Use hue to determine RGB components\n//\n// Input: Color.HSL with h (0-360), s (0-1), l (0-1)\n// Output: Color.SRGB with r, g, b in 0-1 range\n\n// Get input HSL values\nvariable h: Number = {input}.h;\nvariable s: Number = {input}.s;\nvariable l: Number = {input}.l;\n\n// Normalize hue to 0-1 range\nvariable hue: Number = h / 360;\n\n// Output values\nvariable r: Number = l;\nvariable g: Number = l;\nvariable b: Number = l;\n\n// Only calculate if there's saturation (not achromatic)\nif (s > 0) [\n // Calculate intermediate value\n variable q: Number = 0;\n if (l < 0.5) [\n q = l * (1 + s);\n ] else [\n q = l + s - l * s;\n ];\n \n variable p: Number = 2 * l - q;\n \n // Helper function logic inlined for R (hue + 1/3)\n variable tr: Number = hue + 0.333333333333333;\n if (tr < 0) [ tr = tr + 1; ];\n if (tr > 1) [ tr = tr - 1; ];\n \n if (tr < 0.166666666666667) [\n r = p + (q - p) * 6 * tr;\n ] else [\n if (tr < 0.5) [\n r = q;\n ] else [\n if (tr < 0.666666666666667) [\n r = p + (q - p) * (0.666666666666667 - tr) * 6;\n ] else [\n r = p;\n ];\n ];\n ];\n \n // Helper function logic inlined for G (hue)\n variable tg: Number = hue;\n if (tg < 0) [ tg = tg + 1; ];\n if (tg > 1) [ tg = tg - 1; ];\n \n if (tg < 0.166666666666667) [\n g = p + (q - p) * 6 * tg;\n ] else [\n if (tg < 0.5) [\n g = q;\n ] else [\n if (tg < 0.666666666666667) [\n g = p + (q - p) * (0.666666666666667 - tg) * 6;\n ] else [\n g = p;\n ];\n ];\n ];\n \n // Helper function logic inlined for B (hue - 1/3)\n variable tb: Number = hue - 0.333333333333333;\n if (tb < 0) [ tb = tb + 1; ];\n if (tb > 1) [ tb = tb - 1; ];\n \n if (tb < 0.166666666666667) [\n b = p + (q - p) * 6 * tb;\n ] else [\n if (tb < 0.5) [\n b = q;\n ] else [\n if (tb < 0.666666666666667) [\n b = p + (q - p) * (0.666666666666667 - tb) * 6;\n ] else [\n b = p;\n ];\n ];\n ];\n];\n\n// Create output\nvariable output: Color.SRGB;\noutput.r = r;\noutput.g = g;\noutput.b = b;\n\nreturn output;"
}
},
{
"source": "https://schema.tokenscript.dev.gcp.tokens.studio/api/v1/core/srgb-linear-color/0/",
"target": "$self",
"description": "Converts Linear sRGB to sRGB by applying gamma correction",
"lossless": true,
"script": {
"type": "https://schema.tokenscript.dev.gcp.tokens.studio/api/v1/core/tokenscript/0/",
"script": "// Linear sRGB to sRGB Conversion\n// Applies gamma correction (transfer function)\n// Reference: IEC 61966-2-1:1999 (sRGB specification)\n//\n// Algorithm:\n// if linear ≤ 0.0031308: srgb = linear * 12.92\n// else: srgb = 1.055 * linear^(1/2.4) - 0.055\n//\n// Input: Color.LinearSRGB with r, g, b in linear 0-1 range\n// Output: Color.SRGB with r, g, b in gamma-corrected 0-1 range\n\n// Gamma correction constants (IEC 61966-2-1)\nvariable threshold: Number = 0.0031308;\nvariable linear_scale: Number = 12.92;\nvariable gamma_offset: Number = 0.055;\nvariable gamma_scale: Number = 1.055;\nvariable gamma_exponent: Number = 0.416666666666667;\n\n// Get input linear values\nvariable linear_r: Number = {input}.r;\nvariable linear_g: Number = {input}.g;\nvariable linear_b: Number = {input}.b;\n\n// Convert red channel\nvariable srgb_r: Number = 0;\nif (linear_r <= threshold) [\n srgb_r = linear_r * linear_scale;\n] else [\n srgb_r = gamma_scale * pow(linear_r, gamma_exponent) - gamma_offset;\n];\n\n// Convert green channel\nvariable srgb_g: Number = 0;\nif (linear_g <= threshold) [\n srgb_g = linear_g * linear_scale;\n] else [\n srgb_g = gamma_scale * pow(linear_g, gamma_exponent) - gamma_offset;\n];\n\n// Convert blue channel\nvariable srgb_b: Number = 0;\nif (linear_b <= threshold) [\n srgb_b = linear_b * linear_scale;\n] else [\n srgb_b = gamma_scale * pow(linear_b, gamma_exponent) - gamma_offset;\n];\n\n// Create output\nvariable output: Color.SRGB;\noutput.r = srgb_r;\noutput.g = srgb_g;\noutput.b = srgb_b;\n\nreturn output;"
}
}
]
}
},
{
@@ -177,85 +297,6 @@ const SCHEMAS = [
]
}
},
{
uri: "https://schema.tokenscript.dev.gcp.tokens.studio/api/v1/core/srgb-color/0/",
schema: {
"name": "SRGB",
"type": "color",
"description": "sRGB color space with normalized 0-1 range. The standard color space for web and displays.",
"schema": {
"type": "object",
"properties": {
"r": {
"type": "number",
"description": "Red channel (0-1)"
},
"g": {
"type": "number",
"description": "Green channel (0-1)"
},
"b": {
"type": "number",
"description": "Blue channel (0-1)"
}
},
"required": [
"r",
"g",
"b"
],
"order": [
"r",
"g",
"b"
],
"additionalProperties": false
},
"initializers": [
{
"title": "sRGB Color Initializer",
"keyword": "srgb",
"description": "Creates an sRGB color from normalized 0-1 values",
"script": {
"type": "https://schema.tokenscript.dev.gcp.tokens.studio/api/v1/core/tokenscript/0/",
"script": "// sRGB Color Initializer\n// Creates an sRGB color from normalized 0-1 values\n// Input: List of [r, g, b] or [r, g, b, alpha] values in 0-1 range\n\nvariable color_values: List = {input};\nvariable output: Color.SRGB;\n\noutput.r = color_values.get(0);\noutput.g = color_values.get(1);\noutput.b = color_values.get(2);\n\n// Set alpha if provided as 4th parameter\nif (color_values.length() > 3) [\n output.alpha = color_values.get(3);\n];\n\nreturn output;"
}
}
],
"conversions": [
{
"source": "https://schema.tokenscript.dev.gcp.tokens.studio/api/v1/core/rgb-color/0/",
"target": "$self",
"description": "Converts RGB (0-255) to sRGB (0-1) by normalizing",
"lossless": true,
"script": {
"type": "https://schema.tokenscript.dev.gcp.tokens.studio/api/v1/core/tokenscript/0/",
"script": "// RGB to sRGB Conversion\n// Converts RGB (0-255) to sRGB (0-1) by normalizing\n// Input: Color.Rgb with r, g, b in 0-255 range\n// Output: Color.SRGB with r, g, b in 0-1 range\n// Lossless: Yes (simple division)\n\nvariable r_normalized: Number = {input}.r / 255;\nvariable g_normalized: Number = {input}.g / 255;\nvariable b_normalized: Number = {input}.b / 255;\n\nvariable output: Color.SRGB;\noutput.r = r_normalized;\noutput.g = g_normalized;\noutput.b = b_normalized;\n\nreturn output;"
}
},
{
"source": "https://schema.tokenscript.dev.gcp.tokens.studio/api/v1/core/hsl-color/0/",
"target": "$self",
"description": "Converts HSL to sRGB",
"lossless": true,
"script": {
"type": "https://schema.tokenscript.dev.gcp.tokens.studio/api/v1/core/tokenscript/0/",
"script": "// HSL to sRGB Conversion\n// Reference: https://github.com/color-js/color.js/blob/main/src/spaces/hsl.js\n//\n// Algorithm:\n// 1. If saturation is 0, it's achromatic: R=G=B=L\n// 2. Otherwise use the HSL to RGB formula:\n// - Calculate intermediate values based on L\n// - Use hue to determine RGB components\n//\n// Input: Color.HSL with h (0-360), s (0-1), l (0-1)\n// Output: Color.SRGB with r, g, b in 0-1 range\n\n// Get input HSL values\nvariable h: Number = {input}.h;\nvariable s: Number = {input}.s;\nvariable l: Number = {input}.l;\n\n// Normalize hue to 0-1 range\nvariable hue: Number = h / 360;\n\n// Output values\nvariable r: Number = l;\nvariable g: Number = l;\nvariable b: Number = l;\n\n// Only calculate if there's saturation (not achromatic)\nif (s > 0) [\n // Calculate intermediate value\n variable q: Number = 0;\n if (l < 0.5) [\n q = l * (1 + s);\n ] else [\n q = l + s - l * s;\n ];\n \n variable p: Number = 2 * l - q;\n \n // Helper function logic inlined for R (hue + 1/3)\n variable tr: Number = hue + 0.333333333333333;\n if (tr < 0) [ tr = tr + 1; ];\n if (tr > 1) [ tr = tr - 1; ];\n \n if (tr < 0.166666666666667) [\n r = p + (q - p) * 6 * tr;\n ] else [\n if (tr < 0.5) [\n r = q;\n ] else [\n if (tr < 0.666666666666667) [\n r = p + (q - p) * (0.666666666666667 - tr) * 6;\n ] else [\n r = p;\n ];\n ];\n ];\n \n // Helper function logic inlined for G (hue)\n variable tg: Number = hue;\n if (tg < 0) [ tg = tg + 1; ];\n if (tg > 1) [ tg = tg - 1; ];\n \n if (tg < 0.166666666666667) [\n g = p + (q - p) * 6 * tg;\n ] else [\n if (tg < 0.5) [\n g = q;\n ] else [\n if (tg < 0.666666666666667) [\n g = p + (q - p) * (0.666666666666667 - tg) * 6;\n ] else [\n g = p;\n ];\n ];\n ];\n \n // Helper function logic inlined for B (hue - 1/3)\n variable tb: Number = hue - 0.333333333333333;\n if (tb < 0) [ tb = tb + 1; ];\n if (tb > 1) [ tb = tb - 1; ];\n \n if (tb < 0.166666666666667) [\n b = p + (q - p) * 6 * tb;\n ] else [\n if (tb < 0.5) [\n b = q;\n ] else [\n if (tb < 0.666666666666667) [\n b = p + (q - p) * (0.666666666666667 - tb) * 6;\n ] else [\n b = p;\n ];\n ];\n ];\n];\n\n// Create output\nvariable output: Color.SRGB;\noutput.r = r;\noutput.g = g;\noutput.b = b;\n\nreturn output;"
}
},
{
"source": "https://schema.tokenscript.dev.gcp.tokens.studio/api/v1/core/srgb-linear-color/0/",
"target": "$self",
"description": "Converts Linear sRGB to sRGB by applying gamma correction",
"lossless": true,
"script": {
"type": "https://schema.tokenscript.dev.gcp.tokens.studio/api/v1/core/tokenscript/0/",
"script": "// Linear sRGB to sRGB Conversion\n// Applies gamma correction (transfer function)\n// Reference: IEC 61966-2-1:1999 (sRGB specification)\n//\n// Algorithm:\n// if linear ≤ 0.0031308: srgb = linear * 12.92\n// else: srgb = 1.055 * linear^(1/2.4) - 0.055\n//\n// Input: Color.LinearSRGB with r, g, b in linear 0-1 range\n// Output: Color.SRGB with r, g, b in gamma-corrected 0-1 range\n\n// Gamma correction constants (IEC 61966-2-1)\nvariable threshold: Number = 0.0031308;\nvariable linear_scale: Number = 12.92;\nvariable gamma_offset: Number = 0.055;\nvariable gamma_scale: Number = 1.055;\nvariable gamma_exponent: Number = 0.416666666666667;\n\n// Get input linear values\nvariable linear_r: Number = {input}.r;\nvariable linear_g: Number = {input}.g;\nvariable linear_b: Number = {input}.b;\n\n// Convert red channel\nvariable srgb_r: Number = 0;\nif (linear_r <= threshold) [\n srgb_r = linear_r * linear_scale;\n] else [\n srgb_r = gamma_scale * pow(linear_r, gamma_exponent) - gamma_offset;\n];\n\n// Convert green channel\nvariable srgb_g: Number = 0;\nif (linear_g <= threshold) [\n srgb_g = linear_g * linear_scale;\n] else [\n srgb_g = gamma_scale * pow(linear_g, gamma_exponent) - gamma_offset;\n];\n\n// Convert blue channel\nvariable srgb_b: Number = 0;\nif (linear_b <= threshold) [\n srgb_b = linear_b * linear_scale;\n] else [\n srgb_b = gamma_scale * pow(linear_b, gamma_exponent) - gamma_offset;\n];\n\n// Create output\nvariable output: Color.SRGB;\noutput.r = srgb_r;\noutput.g = srgb_g;\noutput.b = srgb_b;\n\nreturn output;"
}
}
]
}
},
{
uri: "https://schema.tokenscript.dev.gcp.tokens.studio/api/v1/core/srgb-linear-color/0/",
schema: {
@@ -729,6 +770,65 @@ const SCHEMAS = [
]
}
},
{
uri: "https://schema.tokenscript.dev.gcp.tokens.studio/api/v1/core/p3-color/0/",
schema: {
"name": "P3",
"type": "color",
"description": "Display-P3 color space with sRGB transfer function. Wider gamut than sRGB, common on modern Apple displays.",
"schema": {
"type": "object",
"properties": {
"r": {
"type": "number",
"description": "Red channel (0-1, can exceed for out-of-gamut)"
},
"g": {
"type": "number",
"description": "Green channel (0-1, can exceed for out-of-gamut)"
},
"b": {
"type": "number",
"description": "Blue channel (0-1, can exceed for out-of-gamut)"
}
},
"required": [
"r",
"g",
"b"
],
"order": [
"r",
"g",
"b"
],
"additionalProperties": false
},
"initializers": [
{
"title": "Display-P3 Color Initializer",
"keyword": "p3",
"description": "Creates a Display-P3 color from 0-1 values",
"script": {
"type": "https://schema.tokenscript.dev.gcp.tokens.studio/api/v1/core/tokenscript/0/",
"script": "// Display-P3 Color Initializer\n// Creates a Display-P3 color from 0-1 values\n// Input: List of [r, g, b] or [r, g, b, alpha] values\n\nvariable color_values: List = {input};\nvariable output: Color.P3;\n\noutput.r = color_values.get(0);\noutput.g = color_values.get(1);\noutput.b = color_values.get(2);\n\n// Set alpha if provided as 4th parameter\nif (color_values.length() > 3) [\n output.alpha = color_values.get(3);\n];\n\nreturn output;"
}
}
],
"conversions": [
{
"source": "https://schema.tokenscript.dev.gcp.tokens.studio/api/v1/core/p3-linear-color/0/",
"target": "$self",
"description": "Converts Linear P3 to P3 by applying sRGB transfer function",
"lossless": true,
"script": {
"type": "https://schema.tokenscript.dev.gcp.tokens.studio/api/v1/core/tokenscript/0/",
"script": "// Linear P3 to P3 Conversion\n// Applies sRGB transfer function (gamma encoding)\n// P3 uses the same transfer function as sRGB\n// Reference: CSS Color Level 4\n//\n// Algorithm (same as sRGB):\n// if linear ≤ 0.0031308: encoded = 12.92 × linear\n// else: encoded = 1.055 × linear^(1/2.4) - 0.055\n//\n// Input: Color.LinearP3 with linear r, g, b values\n// Output: Color.P3 with gamma-encoded r, g, b values\n\n// Transfer function constants (same as sRGB)\nvariable threshold: Number = 0.0031308;\nvariable linear_scale: Number = 12.92;\nvariable gamma_scale: Number = 1.055;\nvariable gamma_offset: Number = 0.055;\nvariable gamma_exponent: Number = 0.4166666666666667;\n\n// Get linear values\nvariable linear_r: Number = {input}.r;\nvariable linear_g: Number = {input}.g;\nvariable linear_b: Number = {input}.b;\n\n// Convert red channel\nvariable encoded_r: Number = 0;\nif (linear_r <= threshold) [\n encoded_r = linear_scale * linear_r;\n] else [\n encoded_r = gamma_scale * pow(linear_r, gamma_exponent) - gamma_offset;\n];\n\n// Convert green channel\nvariable encoded_g: Number = 0;\nif (linear_g <= threshold) [\n encoded_g = linear_scale * linear_g;\n] else [\n encoded_g = gamma_scale * pow(linear_g, gamma_exponent) - gamma_offset;\n];\n\n// Convert blue channel\nvariable encoded_b: Number = 0;\nif (linear_b <= threshold) [\n encoded_b = linear_scale * linear_b;\n] else [\n encoded_b = gamma_scale * pow(linear_b, gamma_exponent) - gamma_offset;\n];\n\n// Create output\nvariable output: Color.P3;\noutput.r = encoded_r;\noutput.g = encoded_g;\noutput.b = encoded_b;\n\nreturn output;"
}
}
]
}
},
{
uri: "https://schema.tokenscript.dev.gcp.tokens.studio/api/v1/core/css-color/0/",
schema: {
@@ -1186,65 +1286,6 @@ const SCHEMAS = [
]
}
},
{
uri: "https://schema.tokenscript.dev.gcp.tokens.studio/api/v1/core/p3-color/0/",
schema: {
"name": "P3",
"type": "color",
"description": "Display-P3 color space with sRGB transfer function. Wider gamut than sRGB, common on modern Apple displays.",
"schema": {
"type": "object",
"properties": {
"r": {
"type": "number",
"description": "Red channel (0-1, can exceed for out-of-gamut)"
},
"g": {
"type": "number",
"description": "Green channel (0-1, can exceed for out-of-gamut)"
},
"b": {
"type": "number",
"description": "Blue channel (0-1, can exceed for out-of-gamut)"
}
},
"required": [
"r",
"g",
"b"
],
"order": [
"r",
"g",
"b"
],
"additionalProperties": false
},
"initializers": [
{
"title": "Display-P3 Color Initializer",
"keyword": "p3",
"description": "Creates a Display-P3 color from 0-1 values",
"script": {
"type": "https://schema.tokenscript.dev.gcp.tokens.studio/api/v1/core/tokenscript/0/",
"script": "// Display-P3 Color Initializer\n// Creates a Display-P3 color from 0-1 values\n// Input: List of [r, g, b] or [r, g, b, alpha] values\n\nvariable color_values: List = {input};\nvariable output: Color.P3;\n\noutput.r = color_values.get(0);\noutput.g = color_values.get(1);\noutput.b = color_values.get(2);\n\n// Set alpha if provided as 4th parameter\nif (color_values.length() > 3) [\n output.alpha = color_values.get(3);\n];\n\nreturn output;"
}
}
],
"conversions": [
{
"source": "https://schema.tokenscript.dev.gcp.tokens.studio/api/v1/core/p3-linear-color/0/",
"target": "$self",
"description": "Converts Linear P3 to P3 by applying sRGB transfer function",
"lossless": true,
"script": {
"type": "https://schema.tokenscript.dev.gcp.tokens.studio/api/v1/core/tokenscript/0/",
"script": "// Linear P3 to P3 Conversion\n// Applies sRGB transfer function (gamma encoding)\n// P3 uses the same transfer function as sRGB\n// Reference: CSS Color Level 4\n//\n// Algorithm (same as sRGB):\n// if linear ≤ 0.0031308: encoded = 12.92 × linear\n// else: encoded = 1.055 × linear^(1/2.4) - 0.055\n//\n// Input: Color.LinearP3 with linear r, g, b values\n// Output: Color.P3 with gamma-encoded r, g, b values\n\n// Transfer function constants (same as sRGB)\nvariable threshold: Number = 0.0031308;\nvariable linear_scale: Number = 12.92;\nvariable gamma_scale: Number = 1.055;\nvariable gamma_offset: Number = 0.055;\nvariable gamma_exponent: Number = 0.4166666666666667;\n\n// Get linear values\nvariable linear_r: Number = {input}.r;\nvariable linear_g: Number = {input}.g;\nvariable linear_b: Number = {input}.b;\n\n// Convert red channel\nvariable encoded_r: Number = 0;\nif (linear_r <= threshold) [\n encoded_r = linear_scale * linear_r;\n] else [\n encoded_r = gamma_scale * pow(linear_r, gamma_exponent) - gamma_offset;\n];\n\n// Convert green channel\nvariable encoded_g: Number = 0;\nif (linear_g <= threshold) [\n encoded_g = linear_scale * linear_g;\n] else [\n encoded_g = gamma_scale * pow(linear_g, gamma_exponent) - gamma_offset;\n];\n\n// Convert blue channel\nvariable encoded_b: Number = 0;\nif (linear_b <= threshold) [\n encoded_b = linear_scale * linear_b;\n] else [\n encoded_b = gamma_scale * pow(linear_b, gamma_exponent) - gamma_offset;\n];\n\n// Create output\nvariable output: Color.P3;\noutput.r = encoded_r;\noutput.g = encoded_g;\noutput.b = encoded_b;\n\nreturn output;"
}
}
]
}
},
{
uri: "https://schema.tokenscript.dev.gcp.tokens.studio/api/v1/function/lighten/0/",
schema: {
@@ -1424,6 +1465,165 @@ const SCHEMAS = [
]
}
},
{
uri: "https://schema.tokenscript.dev.gcp.tokens.studio/api/v1/constants/css-hex-colors/0/",
schema: {
"name": "CSS Hex Colors",
"type": "constants",
"description": "CSS named colors mapped to their hex values (CSS Color Level 4)",
"inline": true,
"values": {
"aliceblue": "#F0F8FF",
"antiquewhite": "#FAEBD7",
"aqua": "#00FFFF",
"aquamarine": "#7FFFD4",
"azure": "#F0FFFF",
"beige": "#F5F5DC",
"bisque": "#FFE4C4",
"black": "#000000",
"blanchedalmond": "#FFEBCD",
"blue": "#0000FF",
"blueviolet": "#8A2BE2",
"brown": "#A52A2A",
"burlywood": "#DEB887",
"cadetblue": "#5F9EA0",
"chartreuse": "#7FFF00",
"chocolate": "#D2691E",
"coral": "#FF7F50",
"cornflowerblue": "#6495ED",
"cornsilk": "#FFF8DC",
"crimson": "#DC143C",
"cyan": "#00FFFF",
"darkblue": "#00008B",
"darkcyan": "#008B8B",
"darkgoldenrod": "#B8860B",
"darkgray": "#A9A9A9",
"darkgreen": "#006400",
"darkgrey": "#A9A9A9",
"darkkhaki": "#BDB76B",
"darkmagenta": "#8B008B",
"darkolivegreen": "#556B2F",
"darkorange": "#FF8C00",
"darkorchid": "#9932CC",
"darkred": "#8B0000",
"darksalmon": "#E9967A",
"darkseagreen": "#8FBC8F",
"darkslateblue": "#483D8B",
"darkslategray": "#2F4F4F",
"darkslategrey": "#2F4F4F",
"darkturquoise": "#00CED1",
"darkviolet": "#9400D3",
"deeppink": "#FF1493",
"deepskyblue": "#00BFFF",
"dimgray": "#696969",
"dimgrey": "#696969",
"dodgerblue": "#1E90FF",
"firebrick": "#B22222",
"floralwhite": "#FFFAF0",
"forestgreen": "#228B22",
"fuchsia": "#FF00FF",
"gainsboro": "#DCDCDC",
"ghostwhite": "#F8F8FF",
"gold": "#FFD700",
"goldenrod": "#DAA520",
"gray": "#808080",
"green": "#008000",
"greenyellow": "#ADFF2F",
"grey": "#808080",
"honeydew": "#F0FFF0",
"hotpink": "#FF69B4",
"indianred": "#CD5C5C",
"indigo": "#4B0082",
"ivory": "#FFFFF0",
"khaki": "#F0E68C",
"lavender": "#E6E6FA",
"lavenderblush": "#FFF0F5",
"lawngreen": "#7CFC00",
"lemonchiffon": "#FFFACD",
"lightblue": "#ADD8E6",
"lightcoral": "#F08080",
"lightcyan": "#E0FFFF",
"lightgoldenrodyellow": "#FAFAD2",
"lightgray": "#D3D3D3",
"lightgreen": "#90EE90",
"lightgrey": "#D3D3D3",
"lightpink": "#FFB6C1",
"lightsalmon": "#FFA07A",
"lightseagreen": "#20B2AA",
"lightskyblue": "#87CEFA",
"lightslategray": "#778899",
"lightslategrey": "#778899",
"lightsteelblue": "#B0C4DE",
"lightyellow": "#FFFFE0",
"lime": "#00FF00",
"limegreen": "#32CD32",
"linen": "#FAF0E6",
"magenta": "#FF00FF",
"maroon": "#800000",
"mediumaquamarine": "#66CDAA",
"mediumblue": "#0000CD",
"mediumorchid": "#BA55D3",
"mediumpurple": "#9370DB",
"mediumseagreen": "#3CB371",
"mediumslateblue": "#7B68EE",
"mediumspringgreen": "#00FA9A",
"mediumturquoise": "#48D1CC",
"mediumvioletred": "#C71585",
"midnightblue": "#191970",
"mintcream": "#F5FFFA",
"mistyrose": "#FFE4E1",
"moccasin": "#FFE4B5",
"navajowhite": "#FFDEAD",
"navy": "#000080",
"oldlace": "#FDF5E6",
"olive": "#808000",
"olivedrab": "#6B8E23",
"orange": "#FFA500",
"orangered": "#FF4500",
"orchid": "#DA70D6",
"palegoldenrod": "#EEE8AA",
"palegreen": "#98FB98",
"paleturquoise": "#AFEEEE",
"palevioletred": "#DB7093",
"papayawhip": "#FFEFD5",
"peachpuff": "#FFDAB9",
"peru": "#CD853F",
"pink": "#FFC0CB",
"plum": "#DDA0DD",
"powderblue": "#B0E0E6",
"purple": "#800080",
"rebeccapurple": "#663399",
"red": "#FF0000",
"rosybrown": "#BC8F8F",
"royalblue": "#4169E1",
"saddlebrown": "#8B4513",
"salmon": "#FA8072",
"sandybrown": "#F4A460",
"seagreen": "#2E8B57",
"seashell": "#FFF5EE",
"sienna": "#A0522D",
"silver": "#C0C0C0",
"skyblue": "#87CEEB",
"slateblue": "#6A5ACD",
"slategray": "#708090",
"slategrey": "#708090",
"snow": "#FFFAFA",
"springgreen": "#00FF7F",
"steelblue": "#4682B4",
"tan": "#D2B48C",
"teal": "#008080",
"thistle": "#D8BFD8",
"tomato": "#FF6347",
"turquoise": "#40E0D0",
"violet": "#EE82EE",
"wheat": "#F5DEB3",
"white": "#FFFFFF",
"whitesmoke": "#F5F5F5",
"yellow": "#FFFF00",
"yellowgreen": "#9ACD32"
}
}
},
];
export function makeConfig() {

View File

@@ -0,0 +1,147 @@
{
"~:features": {
"~#set": [
"fdata/path-data",
"plugins/runtime",
"design-tokens/v1",
"variants/v1",
"layout/grid",
"styles/v2",
"fdata/objects-map",
"text-editor/v2",
"render-wasm/v1",
"components/v2",
"fdata/shape-data-type"
]
},
"~:team-id": "~ud7430f09-4f59-8049-8007-6277bb7586f6",
"~:permissions": {
"~:type": "~:membership",
"~:is-owner": true,
"~:is-admin": true,
"~:can-edit": true,
"~:can-read": true,
"~:is-logged": true
},
"~:has-media-trimmed": false,
"~:comment-thread-seqn": 0,
"~:name": "test_color_blending",
"~:revn": 78,
"~:modified-at": "~m1770820738388",
"~:vern": 0,
"~:id": "~ub15901d7-d46d-8056-8007-8d5e34fc1f0c",
"~:is-shared": false,
"~:migrations": {
"~#ordered-set": [
"legacy-2",
"legacy-3",
"legacy-5",
"legacy-6",
"legacy-7",
"legacy-8",
"legacy-9",
"legacy-10",
"legacy-11",
"legacy-12",
"legacy-13",
"legacy-14",
"legacy-16",
"legacy-17",
"legacy-18",
"legacy-19",
"legacy-25",
"legacy-26",
"legacy-27",
"legacy-28",
"legacy-29",
"legacy-31",
"legacy-32",
"legacy-33",
"legacy-34",
"legacy-36",
"legacy-37",
"legacy-38",
"legacy-39",
"legacy-40",
"legacy-41",
"legacy-42",
"legacy-43",
"legacy-44",
"legacy-45",
"legacy-46",
"legacy-47",
"legacy-48",
"legacy-49",
"legacy-50",
"legacy-51",
"legacy-52",
"legacy-53",
"legacy-54",
"legacy-55",
"legacy-56",
"legacy-57",
"legacy-59",
"legacy-62",
"legacy-65",
"legacy-66",
"legacy-67",
"0001-remove-tokens-from-groups",
"0002-normalize-bool-content-v2",
"0002-clean-shape-interactions",
"0003-fix-root-shape",
"0003-convert-path-content-v2",
"0005-deprecate-image-type",
"0006-fix-old-texts-fills",
"0008-fix-library-colors-v4",
"0009-clean-library-colors",
"0009-add-partial-text-touched-flags",
"0010-fix-swap-slots-pointing-non-existent-shapes",
"0011-fix-invalid-text-touched-flags",
"0012-fix-position-data",
"0013-fix-component-path",
"0013-clear-invalid-strokes-and-fills",
"0014-fix-tokens-lib-duplicate-ids",
"0014-clear-components-nil-objects",
"0015-fix-text-attrs-blank-strings",
"0015-clean-shadow-color",
"0016-copy-fills-from-position-data-to-text-node"
]
},
"~:version": 67,
"~:project-id": "~ud7430f09-4f59-8049-8007-6277bb765abd",
"~:created-at": "~m1770741329904",
"~:backend": "legacy-db",
"~:data": {
"~:pages": [
"~ub15901d7-d46d-8056-8007-8d5e34fc1f0d"
],
"~:pages-index": {
"~ub15901d7-d46d-8056-8007-8d5e34fc1f0d": {
"~:objects": {
"~#penpot/objects-map/v2": {
"~u00000000-0000-0000-0000-000000000000": "[\"~#shape\",[\"^ \",\"~:y\",0,\"~:hide-fill-on-export\",false,\"~:transform\",[\"~#matrix\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:rotation\",0,\"~:name\",\"Root Frame\",\"~:width\",0.01,\"~:type\",\"~:frame\",\"~:points\",[[\"~#point\",[\"^ \",\"~:x\",0.0,\"~:y\",0.0]],[\"^:\",[\"^ \",\"~:x\",0.01,\"~:y\",0.0]],[\"^:\",[\"^ \",\"~:x\",0.01,\"~:y\",0.01]],[\"^:\",[\"^ \",\"~:x\",0.0,\"~:y\",0.01]]],\"~:r2\",0,\"~:proportion-lock\",false,\"~:transform-inverse\",[\"^3\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:r3\",0,\"~:r1\",0,\"~:id\",\"~u00000000-0000-0000-0000-000000000000\",\"~:parent-id\",\"~u00000000-0000-0000-0000-000000000000\",\"~:frame-id\",\"~u00000000-0000-0000-0000-000000000000\",\"~:strokes\",[],\"~:x\",0,\"~:proportion\",1.0,\"~:r4\",0,\"~:selrect\",[\"~#rect\",[\"^ \",\"~:x\",0,\"~:y\",0,\"^6\",0.01,\"~:height\",0.01,\"~:x1\",0,\"~:y1\",0,\"~:x2\",0.01,\"~:y2\",0.01]],\"~:fills\",[[\"^ \",\"~:fill-color\",\"#FFFFFF\",\"~:fill-opacity\",1]],\"~:flip-x\",null,\"^H\",0.01,\"~:flip-y\",null,\"~:shapes\",[\"~u3b7d4c1f-3b79-80e5-8007-8d5e38c5a297\",\"~udb80df91-a3a3-803b-8007-8e379b5fd50f\",\"~udb80df91-a3a3-803b-8007-8e38034ff7c8\",\"~udb80df91-a3a3-803b-8007-8e37a71c9d28\",\"~udb80df91-a3a3-803b-8007-8e384d8c53b9\",\"~udb80df91-a3a3-803b-8007-8e37c09b4084\",\"~u18522c44-655d-8050-8007-8e89f4bdc0c4\",\"~u097859f1-ca3b-80ba-8007-8e8beb99a3f5\",\"~u18522c44-655d-8050-8007-8e89f4bdc0c5\",\"~u097859f1-ca3b-80ba-8007-8e8bfca43303\",\"~ufb1f50bf-1bff-8030-8007-8e8c3bd8fcd7\",\"~u18522c44-655d-8050-8007-8e89f4bdc0c6\"]]]",
"~u097859f1-ca3b-80ba-8007-8e8bfca43303": "[\"~#shape\",[\"^ \",\"~:y\",-637.0000057220459,\"~:transform\",[\"~#matrix\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:rotation\",0,\"~:grow-type\",\"~:fixed\",\"~:hide-in-viewer\",false,\"~:name\",\"Rectangle\",\"~:width\",300.0000100135803,\"~:type\",\"~:rect\",\"~:points\",[[\"~#point\",[\"^ \",\"~:x\",336.9999895095825,\"~:y\",-637.000005722046]],[\"^<\",[\"^ \",\"~:x\",636.9999995231628,\"~:y\",-637.000005722046]],[\"^<\",[\"^ \",\"~:x\",636.9999995231628,\"~:y\",-337.00000858306885]],[\"^<\",[\"^ \",\"~:x\",336.9999895095825,\"~:y\",-337.00000858306885]]],\"~:r2\",0,\"~:proportion-lock\",false,\"~:transform-inverse\",[\"^2\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:r3\",0,\"~:blur\",[\"^ \",\"~:id\",\"~udb80df91-a3a3-803b-8007-8e380b12ac2a\",\"^9\",\"~:layer-blur\",\"~:value\",7,\"~:hidden\",false],\"~:r1\",0,\"^B\",\"~u097859f1-ca3b-80ba-8007-8e8bfca43303\",\"~:parent-id\",\"~u00000000-0000-0000-0000-000000000000\",\"~:frame-id\",\"~u00000000-0000-0000-0000-000000000000\",\"~:strokes\",[[\"^ \",\"~:stroke-style\",\"~:solid\",\"~:stroke-alignment\",\"~:center\",\"~:stroke-width\",10,\"~:stroke-color\",\"#4bff00\",\"~:stroke-opacity\",1],[\"^ \",\"^J\",\"^K\",\"^L\",\"~:outer\",\"^N\",10,\"^O\",\"#333fbd\",\"^P\",1],[\"^ \",\"^J\",\"^K\",\"^L\",\"~:inner\",\"^N\",10,\"^O\",\"#ff0000\",\"^P\",1]],\"~:x\",336.9999895095825,\"~:proportion\",1,\"~:r4\",0,\"~:selrect\",[\"~#rect\",[\"^ \",\"~:x\",336.9999895095825,\"~:y\",-637.0000057220459,\"^8\",300.0000100135803,\"~:height\",299.99999713897705,\"~:x1\",336.9999895095825,\"~:y1\",-637.0000057220459,\"~:x2\",636.9999995231628,\"~:y2\",-337.00000858306885]],\"~:fills\",[[\"^ \",\"~:fill-color\",\"#B1B2B5\",\"~:fill-opacity\",1],[\"^ \",\"^11\",\"#ff0000\",\"^12\",1]],\"~:flip-x\",null,\"^W\",299.99999713897705,\"~:flip-y\",null]]",
"~udb80df91-a3a3-803b-8007-8e384d8c53b9": "[\"~#shape\",[\"^ \",\"~:y\",450.99999806284904,\"~:transform\",[\"~#matrix\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:rotation\",0,\"~:grow-type\",\"~:fixed\",\"~:hide-in-viewer\",false,\"~:name\",\"Ellipse\",\"~:width\",300.0000065565109,\"~:type\",\"~:circle\",\"~:points\",[[\"~#point\",[\"^ \",\"~:x\",1021.0000203847885,\"~:y\",450.99999806284904]],[\"^<\",[\"^ \",\"~:x\",1321.0000269412994,\"~:y\",450.99999806284904]],[\"^<\",[\"^ \",\"~:x\",1321.0000269412994,\"~:y\",751.0000142753124]],[\"^<\",[\"^ \",\"~:x\",1021.0000203847885,\"~:y\",751.0000142753124]]],\"~:proportion-lock\",false,\"~:transform-inverse\",[\"^2\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:blur\",[\"^ \",\"~:id\",\"~udb80df91-a3a3-803b-8007-8e37b7ddd15c\",\"^9\",\"~:layer-blur\",\"~:value\",7,\"~:hidden\",false],\"^@\",\"~udb80df91-a3a3-803b-8007-8e384d8c53b9\",\"~:parent-id\",\"~u00000000-0000-0000-0000-000000000000\",\"~:frame-id\",\"~u00000000-0000-0000-0000-000000000000\",\"~:strokes\",[[\"^ \",\"~:stroke-style\",\"~:solid\",\"~:stroke-alignment\",\"~:inner\",\"~:stroke-width\",20,\"~:stroke-color\",\"#333fbd\",\"~:stroke-opacity\",1]],\"~:x\",1021.0000203847885,\"~:proportion\",1,\"~:selrect\",[\"~#rect\",[\"^ \",\"~:x\",1021.0000203847885,\"~:y\",450.99999806284904,\"^8\",300.0000065565109,\"~:height\",300.0000162124634,\"~:x1\",1021.0000203847885,\"~:y1\",450.99999806284904,\"~:x2\",1321.0000269412994,\"~:y2\",751.0000142753124]],\"~:fills\",[[\"^ \",\"~:fill-color\",\"#B1B2B5\",\"~:fill-opacity\",1],[\"^ \",\"^W\",\"#ff0000\",\"^X\",1]],\"~:flip-x\",null,\"^Q\",300.0000162124634,\"~:flip-y\",null]]",
"~udb80df91-a3a3-803b-8007-8e379b5fd50f": "[\"~#shape\",[\"^ \",\"~:y\",82.00000368146124,\"~:transform\",[\"~#matrix\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:rotation\",0,\"~:grow-type\",\"~:fixed\",\"~:hide-in-viewer\",false,\"~:name\",\"Rectangle\",\"~:width\",300.0000100135803,\"~:type\",\"~:rect\",\"~:points\",[[\"~#point\",[\"^ \",\"~:x\",686.7500124588994,\"~:y\",82.00000368146122]],[\"^<\",[\"^ \",\"~:x\",986.7500224724797,\"~:y\",82.00000368146122]],[\"^<\",[\"^ \",\"~:x\",986.7500224724797,\"~:y\",382.0000008204383]],[\"^<\",[\"^ \",\"~:x\",686.7500124588994,\"~:y\",382.0000008204383]]],\"~:r2\",0,\"~:proportion-lock\",false,\"~:transform-inverse\",[\"^2\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:r3\",0,\"~:r1\",0,\"~:id\",\"~udb80df91-a3a3-803b-8007-8e379b5fd50f\",\"~:parent-id\",\"~u00000000-0000-0000-0000-000000000000\",\"~:frame-id\",\"~u00000000-0000-0000-0000-000000000000\",\"~:strokes\",[],\"~:x\",686.7500124588994,\"~:proportion\",1,\"~:r4\",0,\"~:selrect\",[\"~#rect\",[\"^ \",\"~:x\",686.7500124588994,\"~:y\",82.00000368146124,\"^8\",300.0000100135803,\"~:height\",299.99999713897705,\"~:x1\",686.7500124588994,\"~:y1\",82.00000368146124,\"~:x2\",986.7500224724797,\"~:y2\",382.0000008204383]],\"~:fills\",[[\"^ \",\"~:fill-color\",\"#B1B2B5\",\"~:fill-opacity\",1],[\"^ \",\"^P\",\"#ff0000\",\"^Q\",1]],\"~:flip-x\",null,\"^J\",299.99999713897705,\"~:flip-y\",null]]",
"~u3b7d4c1f-3b79-80e5-8007-8d5e38c5a297": "[\"~#shape\",[\"^ \",\"~:y\",81.9999960520667,\"~:transform\",[\"~#matrix\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:rotation\",0,\"~:grow-type\",\"~:fixed\",\"~:hide-in-viewer\",false,\"~:name\",\"Rectangle\",\"~:width\",300.0000100135803,\"~:type\",\"~:rect\",\"~:points\",[[\"~#point\",[\"^ \",\"~:x\",337.0000200882939,\"~:y\",81.99999605206669]],[\"^<\",[\"^ \",\"~:x\",637.0000301018742,\"~:y\",81.99999605206669]],[\"^<\",[\"^ \",\"~:x\",637.0000301018742,\"~:y\",381.99999319104376]],[\"^<\",[\"^ \",\"~:x\",337.0000200882939,\"~:y\",381.99999319104376]]],\"~:r2\",0,\"~:proportion-lock\",false,\"~:transform-inverse\",[\"^2\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:r3\",0,\"~:blur\",[\"^ \",\"~:id\",\"~u432cbb09-2ee7-80bf-8007-8d660b2f52ad\",\"^9\",\"~:layer-blur\",\"~:value\",7,\"~:hidden\",false],\"~:r1\",0,\"^B\",\"~u3b7d4c1f-3b79-80e5-8007-8d5e38c5a297\",\"~:parent-id\",\"~u00000000-0000-0000-0000-000000000000\",\"~:frame-id\",\"~u00000000-0000-0000-0000-000000000000\",\"~:strokes\",[],\"~:x\",337.0000200882939,\"~:proportion\",1,\"~:r4\",0,\"~:selrect\",[\"~#rect\",[\"^ \",\"~:x\",337.0000200882939,\"~:y\",81.9999960520667,\"^8\",300.0000100135803,\"~:height\",299.99999713897705,\"~:x1\",337.0000200882939,\"~:y1\",81.9999960520667,\"~:x2\",637.0000301018742,\"~:y2\",381.99999319104376]],\"~:fills\",[[\"^ \",\"~:fill-color\",\"#B1B2B5\",\"~:fill-opacity\",1],[\"^ \",\"^T\",\"#ff0000\",\"^U\",1]],\"~:flip-x\",null,\"^N\",299.99999713897705,\"~:flip-y\",null]]",
"~ufb1f50bf-1bff-8030-8007-8e8c3bd8fcd7": "[\"~#shape\",[\"^ \",\"~:y\",-629.9999999999998,\"~:transform\",[\"~#matrix\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:rotation\",0,\"~:grow-type\",\"~:fixed\",\"~:hide-in-viewer\",false,\"~:name\",\"Rectangle\",\"~:width\",300.0000100135803,\"~:type\",\"~:rect\",\"~:points\",[[\"~#point\",[\"^ \",\"~:x\",1037,\"~:y\",-630]],[\"^<\",[\"^ \",\"~:x\",1337.0000100135803,\"~:y\",-630]],[\"^<\",[\"^ \",\"~:x\",1337.0000100135803,\"~:y\",-330.0000028610228]],[\"^<\",[\"^ \",\"~:x\",1037,\"~:y\",-330.0000028610228]]],\"~:r2\",0,\"~:proportion-lock\",false,\"~:transform-inverse\",[\"^2\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:r3\",0,\"~:blur\",[\"^ \",\"~:id\",\"~udb80df91-a3a3-803b-8007-8e380b12ac2a\",\"^9\",\"~:layer-blur\",\"~:value\",7,\"~:hidden\",false],\"~:r1\",0,\"^B\",\"~ufb1f50bf-1bff-8030-8007-8e8c3bd8fcd7\",\"~:parent-id\",\"~u00000000-0000-0000-0000-000000000000\",\"~:frame-id\",\"~u00000000-0000-0000-0000-000000000000\",\"~:strokes\",[[\"^ \",\"~:stroke-style\",\"~:solid\",\"~:stroke-alignment\",\"~:outer\",\"~:stroke-width\",10,\"~:stroke-color\",\"#333fbd\",\"~:stroke-opacity\",1],[\"^ \",\"^J\",\"^K\",\"^L\",\"~:inner\",\"^N\",10,\"^O\",\"#ff0000\",\"^P\",1],[\"^ \",\"^J\",\"^K\",\"^L\",\"~:center\",\"^N\",10,\"^O\",\"#4bff00\",\"^P\",1]],\"~:x\",1037,\"~:proportion\",1,\"~:r4\",0,\"~:selrect\",[\"~#rect\",[\"^ \",\"~:x\",1037,\"~:y\",-629.9999999999998,\"^8\",300.0000100135803,\"~:height\",299.999997138977,\"~:x1\",1037,\"~:y1\",-629.9999999999998,\"~:x2\",1337.0000100135803,\"~:y2\",-330.0000028610228]],\"~:fills\",[[\"^ \",\"~:fill-color\",\"#B1B2B5\",\"~:fill-opacity\",1],[\"^ \",\"^11\",\"#ff0000\",\"^12\",1]],\"~:flip-x\",null,\"^W\",299.999997138977,\"~:flip-y\",null]]",
"~u097859f1-ca3b-80ba-8007-8e8beb99a3f5": "[\"~#shape\",[\"^ \",\"~:y\",-626.0000057220459,\"~:transform\",[\"~#matrix\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:rotation\",0,\"~:grow-type\",\"~:fixed\",\"~:hide-in-viewer\",false,\"~:name\",\"Rectangle\",\"~:width\",300.0000100135803,\"~:type\",\"~:rect\",\"~:points\",[[\"~#point\",[\"^ \",\"~:x\",687.0000123977661,\"~:y\",-626.000005722046]],[\"^<\",[\"^ \",\"~:x\",987.0000224113464,\"~:y\",-626.000005722046]],[\"^<\",[\"^ \",\"~:x\",987.0000224113464,\"~:y\",-326.00000858306885]],[\"^<\",[\"^ \",\"~:x\",687.0000123977661,\"~:y\",-326.00000858306885]]],\"~:r2\",0,\"~:proportion-lock\",false,\"~:transform-inverse\",[\"^2\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:r3\",0,\"~:blur\",[\"^ \",\"~:id\",\"~udb80df91-a3a3-803b-8007-8e380b12ac2a\",\"^9\",\"~:layer-blur\",\"~:value\",7,\"~:hidden\",false],\"~:r1\",0,\"^B\",\"~u097859f1-ca3b-80ba-8007-8e8beb99a3f5\",\"~:parent-id\",\"~u00000000-0000-0000-0000-000000000000\",\"~:frame-id\",\"~u00000000-0000-0000-0000-000000000000\",\"~:strokes\",[[\"^ \",\"~:stroke-style\",\"~:solid\",\"~:stroke-alignment\",\"~:inner\",\"~:stroke-width\",10,\"~:stroke-color\",\"#333fbd\",\"~:stroke-opacity\",1],[\"^ \",\"^J\",\"^K\",\"^L\",\"^M\",\"^N\",10,\"^O\",\"#ff0000\",\"^P\",1]],\"~:x\",687.0000123977661,\"~:proportion\",1,\"~:r4\",0,\"~:selrect\",[\"~#rect\",[\"^ \",\"~:x\",687.0000123977661,\"~:y\",-626.0000057220459,\"^8\",300.0000100135803,\"~:height\",299.99999713897705,\"~:x1\",687.0000123977661,\"~:y1\",-626.0000057220459,\"~:x2\",987.0000224113464,\"~:y2\",-326.00000858306885]],\"~:fills\",[[\"^ \",\"~:fill-color\",\"#B1B2B5\",\"~:fill-opacity\",1],[\"^ \",\"^[\",\"#ff0000\",\"^10\",1]],\"~:flip-x\",null,\"^U\",299.99999713897705,\"~:flip-y\",null]]",
"~udb80df91-a3a3-803b-8007-8e37a71c9d28": "[\"~#shape\",[\"^ \",\"~:y\",450.99999806284904,\"~:transform\",[\"~#matrix\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:rotation\",0,\"~:grow-type\",\"~:fixed\",\"~:hide-in-viewer\",false,\"~:name\",\"Ellipse\",\"~:width\",300.0000065565109,\"~:type\",\"~:circle\",\"~:points\",[[\"~#point\",[\"^ \",\"~:x\",337.0000203847885,\"~:y\",450.99999806284904]],[\"^<\",[\"^ \",\"~:x\",637.0000269412994,\"~:y\",450.99999806284904]],[\"^<\",[\"^ \",\"~:x\",637.0000269412994,\"~:y\",751.0000142753124]],[\"^<\",[\"^ \",\"~:x\",337.0000203847885,\"~:y\",751.0000142753124]]],\"~:proportion-lock\",false,\"~:transform-inverse\",[\"^2\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:blur\",[\"^ \",\"~:id\",\"~udb80df91-a3a3-803b-8007-8e37b7ddd15c\",\"^9\",\"~:layer-blur\",\"~:value\",7,\"~:hidden\",false],\"^@\",\"~udb80df91-a3a3-803b-8007-8e37a71c9d28\",\"~:parent-id\",\"~u00000000-0000-0000-0000-000000000000\",\"~:frame-id\",\"~u00000000-0000-0000-0000-000000000000\",\"~:strokes\",[],\"~:x\",337.0000203847885,\"~:proportion\",1,\"~:selrect\",[\"~#rect\",[\"^ \",\"~:x\",337.0000203847885,\"~:y\",450.99999806284904,\"^8\",300.0000065565109,\"~:height\",300.0000162124634,\"~:x1\",337.0000203847885,\"~:y1\",450.99999806284904,\"~:x2\",637.0000269412994,\"~:y2\",751.0000142753124]],\"~:fills\",[[\"^ \",\"~:fill-color\",\"#B1B2B5\",\"~:fill-opacity\",1],[\"^ \",\"^P\",\"#ff0000\",\"^Q\",1]],\"~:flip-x\",null,\"^J\",300.0000162124634,\"~:flip-y\",null]]",
"~u18522c44-655d-8050-8007-8e89f4bdc0c5": "[\"~#shape\",[\"^ \",\"~:y\",-287.0000057220459,\"~:transform\",[\"~#matrix\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:rotation\",0,\"~:grow-type\",\"~:fixed\",\"~:hide-in-viewer\",false,\"~:name\",\"Rectangle\",\"~:width\",300.0000100135803,\"~:type\",\"~:rect\",\"~:points\",[[\"~#point\",[\"^ \",\"~:x\",337.00002002716064,\"~:y\",-287.000005722046]],[\"^<\",[\"^ \",\"~:x\",637.000030040741,\"~:y\",-287.000005722046]],[\"^<\",[\"^ \",\"~:x\",637.000030040741,\"~:y\",12.999991416931152]],[\"^<\",[\"^ \",\"~:x\",337.00002002716064,\"~:y\",12.999991416931152]]],\"~:r2\",0,\"~:proportion-lock\",false,\"~:transform-inverse\",[\"^2\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:r3\",0,\"~:blur\",[\"^ \",\"~:id\",\"~udb80df91-a3a3-803b-8007-8e380b12ac2a\",\"^9\",\"~:layer-blur\",\"~:value\",7,\"~:hidden\",false],\"~:r1\",0,\"^B\",\"~u18522c44-655d-8050-8007-8e89f4bdc0c5\",\"~:parent-id\",\"~u00000000-0000-0000-0000-000000000000\",\"~:frame-id\",\"~u00000000-0000-0000-0000-000000000000\",\"~:strokes\",[[\"^ \",\"~:stroke-style\",\"~:solid\",\"~:stroke-alignment\",\"~:outer\",\"~:stroke-width\",10,\"~:stroke-color\",\"#333fbd\",\"~:stroke-opacity\",1],[\"^ \",\"^J\",\"^K\",\"^L\",\"~:inner\",\"^N\",10,\"^O\",\"#ff0000\",\"^P\",1]],\"~:x\",337.00002002716064,\"~:proportion\",1,\"~:r4\",0,\"~:selrect\",[\"~#rect\",[\"^ \",\"~:x\",337.00002002716064,\"~:y\",-287.0000057220459,\"^8\",300.0000100135803,\"~:height\",299.99999713897705,\"~:x1\",337.00002002716064,\"~:y1\",-287.0000057220459,\"~:x2\",637.000030040741,\"~:y2\",12.999991416931152]],\"~:fills\",[[\"^ \",\"~:fill-color\",\"#B1B2B5\",\"~:fill-opacity\",1],[\"^ \",\"^10\",\"#ff0000\",\"^11\",1]],\"~:flip-x\",null,\"^V\",299.99999713897705,\"~:flip-y\",null]]",
"~udb80df91-a3a3-803b-8007-8e37c09b4084": "[\"~#shape\",[\"^ \",\"~:y\",450.99999806284904,\"~:transform\",[\"~#matrix\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:rotation\",0,\"~:grow-type\",\"~:fixed\",\"~:hide-in-viewer\",false,\"~:name\",\"Ellipse\",\"~:width\",300.0000065565109,\"~:type\",\"~:circle\",\"~:points\",[[\"~#point\",[\"^ \",\"~:x\",679.0000203847885,\"~:y\",450.99999806284904]],[\"^<\",[\"^ \",\"~:x\",979.0000269412994,\"~:y\",450.99999806284904]],[\"^<\",[\"^ \",\"~:x\",979.0000269412994,\"~:y\",751.0000142753124]],[\"^<\",[\"^ \",\"~:x\",679.0000203847885,\"~:y\",751.0000142753124]]],\"~:proportion-lock\",false,\"~:transform-inverse\",[\"^2\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:id\",\"~udb80df91-a3a3-803b-8007-8e37c09b4084\",\"~:parent-id\",\"~u00000000-0000-0000-0000-000000000000\",\"~:frame-id\",\"~u00000000-0000-0000-0000-000000000000\",\"~:strokes\",[],\"~:x\",679.0000203847885,\"~:proportion\",1,\"~:selrect\",[\"~#rect\",[\"^ \",\"~:x\",679.0000203847885,\"~:y\",450.99999806284904,\"^8\",300.0000065565109,\"~:height\",300.0000162124634,\"~:x1\",679.0000203847885,\"~:y1\",450.99999806284904,\"~:x2\",979.0000269412994,\"~:y2\",751.0000142753124]],\"~:fills\",[[\"^ \",\"~:fill-color\",\"#B1B2B5\",\"~:fill-opacity\",1],[\"^ \",\"^L\",\"#ff0000\",\"^M\",1]],\"~:flip-x\",null,\"^F\",300.0000162124634,\"~:flip-y\",null]]",
"~u18522c44-655d-8050-8007-8e89f4bdc0c4": "[\"~#shape\",[\"^ \",\"~:y\",-287.0000057220459,\"~:transform\",[\"~#matrix\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:rotation\",0,\"~:grow-type\",\"~:fixed\",\"~:hide-in-viewer\",false,\"~:name\",\"Rectangle\",\"~:width\",300.0000100135803,\"~:type\",\"~:rect\",\"~:points\",[[\"~#point\",[\"^ \",\"~:x\",686.7500123977661,\"~:y\",-287.000005722046]],[\"^<\",[\"^ \",\"~:x\",986.7500224113464,\"~:y\",-287.000005722046]],[\"^<\",[\"^ \",\"~:x\",986.7500224113464,\"~:y\",12.999991416931152]],[\"^<\",[\"^ \",\"~:x\",686.7500123977661,\"~:y\",12.999991416931152]]],\"~:r2\",0,\"~:proportion-lock\",false,\"~:transform-inverse\",[\"^2\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:r3\",0,\"~:blur\",[\"^ \",\"~:id\",\"~udb80df91-a3a3-803b-8007-8e380b12ac2a\",\"^9\",\"~:layer-blur\",\"~:value\",7,\"~:hidden\",false],\"~:r1\",0,\"^B\",\"~u18522c44-655d-8050-8007-8e89f4bdc0c4\",\"~:parent-id\",\"~u00000000-0000-0000-0000-000000000000\",\"~:frame-id\",\"~u00000000-0000-0000-0000-000000000000\",\"~:strokes\",[[\"^ \",\"~:stroke-style\",\"~:solid\",\"~:stroke-alignment\",\"~:inner\",\"~:stroke-width\",10,\"~:stroke-color\",\"#333fbd\",\"~:stroke-opacity\",0.5],[\"^ \",\"^J\",\"^K\",\"^L\",\"^M\",\"^N\",10,\"^O\",\"#ff0000\",\"^P\",1]],\"~:x\",686.7500123977661,\"~:proportion\",1,\"~:r4\",0,\"~:selrect\",[\"~#rect\",[\"^ \",\"~:x\",686.7500123977661,\"~:y\",-287.0000057220459,\"^8\",300.0000100135803,\"~:height\",299.99999713897705,\"~:x1\",686.7500123977661,\"~:y1\",-287.0000057220459,\"~:x2\",986.7500224113464,\"~:y2\",12.999991416931152]],\"~:fills\",[[\"^ \",\"~:fill-color\",\"#B1B2B5\",\"~:fill-opacity\",1],[\"^ \",\"^[\",\"#ff0000\",\"^10\",1]],\"~:flip-x\",null,\"^U\",299.99999713897705,\"~:flip-y\",null]]",
"~udb80df91-a3a3-803b-8007-8e38034ff7c8": "[\"~#shape\",[\"^ \",\"~:y\",82.00000368146124,\"~:transform\",[\"~#matrix\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:rotation\",0,\"~:grow-type\",\"~:fixed\",\"~:hide-in-viewer\",false,\"~:name\",\"Rectangle\",\"~:width\",300.0000100135803,\"~:type\",\"~:rect\",\"~:points\",[[\"~#point\",[\"^ \",\"~:x\",1036.5000048295049,\"~:y\",82.00000368146122]],[\"^<\",[\"^ \",\"~:x\",1336.5000148430852,\"~:y\",82.00000368146122]],[\"^<\",[\"^ \",\"~:x\",1336.5000148430852,\"~:y\",382.0000008204383]],[\"^<\",[\"^ \",\"~:x\",1036.5000048295049,\"~:y\",382.0000008204383]]],\"~:r2\",0,\"~:proportion-lock\",false,\"~:transform-inverse\",[\"^2\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:r3\",0,\"~:blur\",[\"^ \",\"~:id\",\"~udb80df91-a3a3-803b-8007-8e380b12ac2a\",\"^9\",\"~:layer-blur\",\"~:value\",7,\"~:hidden\",false],\"~:r1\",0,\"^B\",\"~udb80df91-a3a3-803b-8007-8e38034ff7c8\",\"~:parent-id\",\"~u00000000-0000-0000-0000-000000000000\",\"~:frame-id\",\"~u00000000-0000-0000-0000-000000000000\",\"~:strokes\",[[\"^ \",\"~:stroke-style\",\"~:solid\",\"~:stroke-alignment\",\"~:inner\",\"~:stroke-width\",10,\"~:stroke-color\",\"#333fbd\",\"~:stroke-opacity\",1]],\"~:x\",1036.5000048295049,\"~:proportion\",1,\"~:r4\",0,\"~:selrect\",[\"~#rect\",[\"^ \",\"~:x\",1036.5000048295049,\"~:y\",82.00000368146124,\"^8\",300.0000100135803,\"~:height\",299.99999713897705,\"~:x1\",1036.5000048295049,\"~:y1\",82.00000368146124,\"~:x2\",1336.5000148430852,\"~:y2\",382.0000008204383]],\"~:fills\",[[\"^ \",\"~:fill-color\",\"#B1B2B5\",\"~:fill-opacity\",1],[\"^ \",\"^[\",\"#ff0000\",\"^10\",1]],\"~:flip-x\",null,\"^U\",299.99999713897705,\"~:flip-y\",null]]",
"~u18522c44-655d-8050-8007-8e89f4bdc0c6": "[\"~#shape\",[\"^ \",\"~:y\",-287.0000057220459,\"~:transform\",[\"~#matrix\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:rotation\",0,\"~:grow-type\",\"~:fixed\",\"~:hide-in-viewer\",false,\"~:name\",\"Rectangle\",\"~:width\",300.0000100135803,\"~:type\",\"~:rect\",\"~:points\",[[\"~#point\",[\"^ \",\"~:x\",1036.5000047683716,\"~:y\",-287.000005722046]],[\"^<\",[\"^ \",\"~:x\",1336.500014781952,\"~:y\",-287.000005722046]],[\"^<\",[\"^ \",\"~:x\",1336.500014781952,\"~:y\",12.999991416931152]],[\"^<\",[\"^ \",\"~:x\",1036.5000047683716,\"~:y\",12.999991416931152]]],\"~:r2\",0,\"~:proportion-lock\",false,\"~:transform-inverse\",[\"^2\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:r3\",0,\"~:blur\",[\"^ \",\"~:id\",\"~udb80df91-a3a3-803b-8007-8e380b12ac2a\",\"^9\",\"~:layer-blur\",\"~:value\",7,\"~:hidden\",false],\"~:r1\",0,\"^B\",\"~u18522c44-655d-8050-8007-8e89f4bdc0c6\",\"~:parent-id\",\"~u00000000-0000-0000-0000-000000000000\",\"~:frame-id\",\"~u00000000-0000-0000-0000-000000000000\",\"~:strokes\",[[\"^ \",\"~:stroke-style\",\"~:solid\",\"~:stroke-alignment\",\"~:inner\",\"~:stroke-width\",10,\"~:stroke-color\",\"#333fbd\",\"~:stroke-opacity\",1],[\"^ \",\"^J\",\"^K\",\"^L\",\"~:outer\",\"^N\",10,\"^O\",\"#ff0000\",\"^P\",1]],\"~:x\",1036.5000047683716,\"~:proportion\",1,\"~:r4\",0,\"~:selrect\",[\"~#rect\",[\"^ \",\"~:x\",1036.5000047683716,\"~:y\",-287.0000057220459,\"^8\",300.0000100135803,\"~:height\",299.99999713897705,\"~:x1\",1036.5000047683716,\"~:y1\",-287.0000057220459,\"~:x2\",1336.500014781952,\"~:y2\",12.999991416931152]],\"~:fills\",[[\"^ \",\"~:fill-color\",\"#B1B2B5\",\"~:fill-opacity\",1],[\"^ \",\"^10\",\"#ff0000\",\"^11\",1]],\"~:flip-x\",null,\"^V\",299.99999713897705,\"~:flip-y\",null]]"
}
},
"~:id": "~ub15901d7-d46d-8056-8007-8d5e34fc1f0d",
"~:name": "Page 1"
}
},
"~:id": "~ub15901d7-d46d-8056-8007-8d5e34fc1f0c",
"~:options": {
"~:components-v2": true,
"~:base-font-size": "16px"
}
}
}

View File

@@ -22,8 +22,8 @@
"~:has-media-trimmed": false,
"~:comment-thread-seqn": 0,
"~:name": "flex_index_position",
"~:revn": 114,
"~:modified-at": "~m1769430362161",
"~:revn": 126,
"~:modified-at": "~m1770978609930",
"~:vern": 0,
"~:id": "~u31fe2e21-73e7-80f3-8007-73894fb58240",
"~:is-shared": false,
@@ -117,31 +117,63 @@
"~:name": "Page 1",
"~:objects": {
"~#penpot/objects-map/v2": {
"~u00000000-0000-0000-0000-000000000000": "[\"~#shape\",[\"^ \",\"~:y\",0,\"~:hide-fill-on-export\",false,\"~:transform\",[\"~#matrix\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:rotation\",0,\"~:name\",\"Root Frame\",\"~:width\",0.01,\"~:type\",\"~:frame\",\"~:points\",[[\"~#point\",[\"^ \",\"~:x\",0.0,\"~:y\",0.0]],[\"^:\",[\"^ \",\"~:x\",0.01,\"~:y\",0.0]],[\"^:\",[\"^ \",\"~:x\",0.01,\"~:y\",0.01]],[\"^:\",[\"^ \",\"~:x\",0.0,\"~:y\",0.01]]],\"~:r2\",0,\"~:proportion-lock\",false,\"~:transform-inverse\",[\"^3\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:page-id\",\"~u02e9633d-4ce7-80da-8007-736558496fa8\",\"~:r3\",0,\"~:r1\",0,\"~:id\",\"~u00000000-0000-0000-0000-000000000000\",\"~:parent-id\",\"~u00000000-0000-0000-0000-000000000000\",\"~:frame-id\",\"~u00000000-0000-0000-0000-000000000000\",\"~:strokes\",[],\"~:x\",0,\"~:proportion\",1.0,\"~:r4\",0,\"~:selrect\",[\"~#rect\",[\"^ \",\"~:x\",0,\"~:y\",0,\"^6\",0.01,\"~:height\",0.01,\"~:x1\",0,\"~:y1\",0,\"~:x2\",0.01,\"~:y2\",0.01]],\"~:fills\",[[\"^ \",\"~:fill-color\",\"#FFFFFF\",\"~:fill-opacity\",1]],\"~:flip-x\",null,\"^I\",0.01,\"~:flip-y\",null,\"~:shapes\",[\"~u94eaebe4-addd-80d1-8007-79d50980078e\",\"~u94eaebe4-addd-80d1-8007-79d508a9dc2f\",\"~u94eaebe4-addd-80d1-8007-79d5055d6859\",\"~u77c71dba-32ee-804c-8007-736561cf857f\"]]]",
"~u77c71dba-32ee-804c-8007-736561cff457": "[\"~#shape\",[\"^ \",\"~:y\",396.00000357564704,\"~:rx\",8,\"~:transform\",[\"~#matrix\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:rotation\",0,\"~:grow-type\",\"~:fixed\",\"~:hide-in-viewer\",false,\"~:name\",\"Rectangle\",\"~:width\",80,\"~:transforming\",false,\"~:type\",\"~:rect\",\"~:points\",[[\"~#point\",[\"^ \",\"~:x\",688.9999775886536,\"~:y\",396.00000357564704]],[\"^>\",[\"^ \",\"~:x\",768.9999775886536,\"~:y\",396.00000357564704]],[\"^>\",[\"^ \",\"~:x\",768.9999775886536,\"~:y\",476.00000357564704]],[\"^>\",[\"^ \",\"~:x\",688.9999775886536,\"~:y\",476.00000357564704]]],\"~:r2\",8,\"~:proportion-lock\",false,\"~:transform-inverse\",[\"^3\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:page-id\",\"~u02e9633d-4ce7-80da-8007-736558496fa8\",\"~:r3\",8,\"~:r1\",8,\"~:id\",\"~u77c71dba-32ee-804c-8007-736561cff457\",\"~:parent-id\",\"~u77c71dba-32ee-804c-8007-736561cf8584\",\"~:frame-id\",\"~u77c71dba-32ee-804c-8007-736561cf8584\",\"~:strokes\",[],\"~:x\",688.9999775886536,\"~:proportion\",1,\"~:r4\",8,\"~:selrect\",[\"~#rect\",[\"^ \",\"~:x\",688.9999775886536,\"~:y\",396.00000357564704,\"^9\",80,\"~:height\",80,\"~:x1\",688.9999775886536,\"~:y1\",396.00000357564704,\"~:x2\",768.9999775886536,\"~:y2\",476.00000357564704]],\"~:fills\",[[\"^ \",\"~:fill-color\",\"#e8e9ea\",\"~:fill-opacity\",1]],\"~:flip-x\",null,\"~:ry\",8,\"^M\",80,\"~:flip-y\",null]]",
"~u94eaebe4-addd-80d1-8007-79d508aa2885": "[\"~#shape\",[\"^ \",\"~:y\",612.0000188344361,\"~:rx\",8,\"~:transform\",[\"~#matrix\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:rotation\",0,\"~:grow-type\",\"~:fixed\",\"~:hide-in-viewer\",false,\"~:name\",\"Rectangle\",\"~:width\",80,\"~:transforming\",false,\"~:type\",\"~:rect\",\"~:points\",[[\"~#point\",[\"^ \",\"~:x\",604.9999165534973,\"~:y\",612.0000188344361]],[\"^>\",[\"^ \",\"~:x\",684.9999165534973,\"~:y\",612.0000188344361]],[\"^>\",[\"^ \",\"~:x\",684.9999165534973,\"~:y\",692.0000188344361]],[\"^>\",[\"^ \",\"~:x\",604.9999165534973,\"~:y\",692.0000188344361]]],\"~:r2\",8,\"~:proportion-lock\",false,\"~:transform-inverse\",[\"^3\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:page-id\",\"~u02e9633d-4ce7-80da-8007-736558496fa8\",\"~:r3\",8,\"~:r1\",8,\"~:id\",\"~u94eaebe4-addd-80d1-8007-79d508aa2885\",\"~:parent-id\",\"~u94eaebe4-addd-80d1-8007-79d508a9dc30\",\"~:frame-id\",\"~u94eaebe4-addd-80d1-8007-79d508a9dc30\",\"~:strokes\",[],\"~:x\",604.9999165534973,\"~:proportion\",1,\"~:r4\",8,\"~:selrect\",[\"~#rect\",[\"^ \",\"~:x\",604.9999165534973,\"~:y\",612.0000188344361,\"^9\",80,\"~:height\",80,\"~:x1\",604.9999165534973,\"~:y1\",612.0000188344361,\"~:x2\",684.9999165534973,\"~:y2\",692.0000188344361]],\"~:fills\",[[\"^ \",\"~:fill-color\",\"#e8e9ea\",\"~:fill-opacity\",1]],\"~:flip-x\",null,\"~:ry\",8,\"^M\",80,\"~:flip-y\",null]]",
"~u94eaebe4-addd-80d1-8007-79d508aa2886": "[\"~#shape\",[\"^ \",\"~:y\",636.0000188344361,\"~:hide-fill-on-export\",false,\"~:layout-gap-type\",\"~:multiple\",\"~:rx\",8,\"~:layout-padding\",[\"^ \",\"~:p1\",8,\"~:p2\",12,\"~:p3\",8,\"~:p4\",12],\"~:transform\",[\"~#matrix\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:rotation\",0,\"~:layout-wrap-type\",\"~:nowrap\",\"~:layout\",\"~:flex\",\"~:hide-in-viewer\",true,\"~:name\",\"Dark / Button / Primary / Text / Default\",\"~:layout-align-items\",\"~:center\",\"~:width\",66,\"~:layout-padding-type\",\"~:simple\",\"~:type\",\"~:frame\",\"~:points\",[[\"~#point\",[\"^ \",\"~:x\",611.9999165534973,\"~:y\",636.0000188344361]],[\"^K\",[\"^ \",\"~:x\",677.9999165534973,\"~:y\",636.0000188344361]],[\"^K\",[\"^ \",\"~:x\",677.9999165534973,\"~:y\",668.0000188344361]],[\"^K\",[\"^ \",\"~:x\",611.9999165534973,\"~:y\",668.0000188344361]]],\"~:r2\",8,\"~:show-content\",true,\"~:proportion-lock\",false,\"~:layout-gap\",[\"^ \",\"~:row-gap\",4,\"~:column-gap\",4],\"~:transform-inverse\",[\"^;\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:page-id\",\"~u02e9633d-4ce7-80da-8007-736558496fa8\",\"~:r3\",8,\"~:layout-justify-content\",\"^D\",\"~:r1\",8,\"~:id\",\"~u94eaebe4-addd-80d1-8007-79d508aa2886\",\"~:parent-id\",\"~u94eaebe4-addd-80d1-8007-79d508a9dc30\",\"~:layout-flex-dir\",\"~:row\",\"~:layout-align-content\",\"~:stretch\",\"~:frame-id\",\"~u94eaebe4-addd-80d1-8007-79d508a9dc30\",\"~:strokes\",[],\"~:x\",611.9999165534973,\"~:proportion\",1,\"~:r4\",8,\"~:selrect\",[\"~#rect\",[\"^ \",\"~:x\",611.9999165534973,\"~:y\",636.0000188344361,\"^E\",66,\"~:height\",32,\"~:x1\",611.9999165534973,\"~:y1\",636.0000188344361,\"~:x2\",677.9999165534973,\"~:y2\",668.0000188344361]],\"~:fills\",[[\"^ \",\"~:fill-color\",\"#7efff5\",\"~:fill-opacity\",1]],\"~:flip-x\",null,\"~:ry\",8,\"^17\",32,\"~:flip-y\",null,\"~:shapes\",[\"~u94eaebe4-addd-80d1-8007-79d508aa2887\"]]]",
"~u94eaebe4-addd-80d1-8007-79d508aa2887": "[\"~#shape\",[\"^ \",\"~:y\",644.0000188344361,\"~:hide-fill-on-export\",false,\"~:layout-gap-type\",\"~:multiple\",\"~:layout-padding\",[\"^ \",\"~:p1\",0,\"~:p2\",2,\"~:p3\",0,\"~:p4\",2],\"~:transform\",[\"~#matrix\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:rotation\",0,\"~:layout-wrap-type\",\"~:nowrap\",\"~:layout\",\"~:flex\",\"~:hide-in-viewer\",true,\"~:name\",\"_Utilities / Text / White\",\"~:layout-align-items\",\"~:start\",\"~:width\",42,\"~:layout-padding-type\",\"~:simple\",\"~:transforming\",false,\"~:type\",\"~:frame\",\"~:points\",[[\"~#point\",[\"^ \",\"~:x\",623.9999165534973,\"~:y\",644.0000188344361]],[\"^K\",[\"^ \",\"~:x\",665.9999165534973,\"~:y\",644.0000188344361]],[\"^K\",[\"^ \",\"~:x\",665.9999165534973,\"~:y\",660.0000188344361]],[\"^K\",[\"^ \",\"~:x\",623.9999165534973,\"~:y\",660.0000188344361]]],\"~:show-content\",true,\"~:layout-item-h-sizing\",\"~:auto\",\"~:proportion-lock\",false,\"~:layout-gap\",[\"^ \",\"~:row-gap\",0,\"~:column-gap\",6],\"~:transform-inverse\",[\"^:\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:page-id\",\"~u02e9633d-4ce7-80da-8007-736558496fa8\",\"~:layout-justify-content\",\"~:center\",\"~:id\",\"~u94eaebe4-addd-80d1-8007-79d508aa2887\",\"~:parent-id\",\"~u94eaebe4-addd-80d1-8007-79d508aa2886\",\"~:layout-flex-dir\",\"~:column\",\"~:layout-align-content\",\"~:stretch\",\"~:frame-id\",\"~u94eaebe4-addd-80d1-8007-79d508aa2886\",\"~:strokes\",[],\"~:x\",623.9999165534973,\"~:proportion\",1,\"~:selrect\",[\"~#rect\",[\"^ \",\"~:x\",623.9999165534973,\"~:y\",644.0000188344361,\"^D\",42,\"~:height\",16,\"~:x1\",623.9999165534973,\"~:y1\",644.0000188344361,\"~:x2\",665.9999165534973,\"~:y2\",660.0000188344361]],\"~:fills\",[],\"~:flip-x\",null,\"^16\",16,\"~:flip-y\",null,\"~:shapes\",[\"~u94eaebe4-addd-80d1-8007-79d508aa2888\"]]]",
"~u94eaebe4-addd-80d1-8007-79d508aa2888": "[\"~#shape\",[\"^ \",\"~:y\",645.0000188344363,\"~:transform\",[\"~#matrix\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:rotation\",0,\"~:grow-type\",\"~:auto-width\",\"~:index\",null,\"~:content\",[\"^ \",\"~:type\",\"root\",\"~:children\",[[\"^ \",\"^8\",\"paragraph-set\",\"^9\",[[\"^ \",\"~:line-height\",\"1.2\",\"~:path\",\"\",\"~:font-style\",\"normal\",\"^9\",[[\"^ \",\"^:\",\"1.2\",\"^;\",\"\",\"^<\",\"normal\",\"~:text-transform\",\"uppercase\",\"~:text-align\",\"left\",\"~:font-id\",\"gfont-work-sans\",\"~:font-size\",\"12\",\"~:font-weight\",\"500\",\"~:modified-at\",\"2024-06-04T14:15:09.786Z\",\"~:font-variant-id\",\"500\",\"~:text-decoration\",\"underline\",\"~:letter-spacing\",\"0\",\"~:fills\",[[\"^ \",\"~:fill-color\",\"#000000\",\"~:fill-color-ref-file\",\"~ucaa70d02-51e1-81ae-8007-735e7de3d7bc\",\"~:fill-opacity\",1,\"~:fill-color-ref-id\",\"~udfa92acf-7d18-8079-8003-baba8789d8af\"]],\"~:font-family\",\"Work Sans\",\"~:text\",\"Label\"]],\"^=\",\"uppercase\",\"^>\",\"center\",\"^?\",\"gfont-work-sans\",\"^@\",\"12\",\"^A\",\"500\",\"^8\",\"paragraph\",\"^B\",\"2024-06-04T14:15:09.786Z\",\"^C\",\"500\",\"^D\",\"underline\",\"^E\",\"0\",\"^F\",[[\"^ \",\"^G\",\"#000000\",\"^H\",\"~ucaa70d02-51e1-81ae-8007-735e7de3d7bc\",\"^I\",1,\"^J\",\"~udfa92acf-7d18-8079-8003-baba8789d8af\"]],\"^K\",\"Work Sans\"]]]],\"~:vertical-align\",\"center\",\"^F\",[[\"^ \",\"^G\",\"#000000\",\"^I\",1]]],\"~:hide-in-viewer\",true,\"~:name\",\"Input\",\"~:saved-component-root\",null,\"~:width\",38,\"^8\",\"^L\",\"~:points\",[[\"~#point\",[\"^ \",\"~:x\",625.9999165534973,\"~:y\",645.0000188344363]],[\"^S\",[\"^ \",\"~:x\",663.9999165534973,\"~:y\",645.0000188344363]],[\"^S\",[\"^ \",\"~:x\",663.9999165534973,\"~:y\",660.0000188344359]],[\"^S\",[\"^ \",\"~:x\",625.9999165534973,\"~:y\",660.0000188344363]]],\"~:layout-item-h-sizing\",\"~:fix\",\"~:transform-inverse\",[\"^2\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:page-id\",\"~u02e9633d-4ce7-80da-8007-736558496fa8\",\"~:id\",\"~u94eaebe4-addd-80d1-8007-79d508aa2888\",\"~:parent-id\",\"~u94eaebe4-addd-80d1-8007-79d508aa2887\",\"~:position-data\",[[\"^ \",\"~:y\",659.3400268554688,\"^:\",\"1.2\",\"^<\",\"normal\",\"^=\",\"uppercase\",\"^>\",\"left\",\"^?\",\"sourcesanspro\",\"^@\",\"12\",\"^A\",\"500\",\"~:text-direction\",\"ltr\",\"^Q\",37.94000244140625,\"^C\",\"regular\",\"^D\",\"underline\",\"^E\",\"0\",\"~:x\",626.0299682617188,\"^F\",[[\"^ \",\"^G\",\"#000000\",\"^H\",\"~ucaa70d02-51e1-81ae-8007-735e7de3d7bc\",\"^I\",1,\"^J\",\"~udfa92acf-7d18-8079-8003-baba8789d8af\"]],\"~:direction\",\"ltr\",\"^K\",\"Work Sans\",\"~:height\",14.08001708984375,\"^L\",\"Label\"]],\"~:frame-id\",\"~u94eaebe4-addd-80d1-8007-79d508aa2887\",\"~:strokes\",[],\"~:x\",625.9999165534973,\"~:selrect\",[\"~#rect\",[\"^ \",\"~:x\",625.9999165534973,\"~:y\",645.0000188344363,\"^Q\",38,\"^11\",15,\"~:x1\",625.9999165534973,\"~:y1\",645.0000188344363,\"~:x2\",663.9999165534973,\"~:y2\",660.0000188344363]],\"^F\",[],\"~:flip-x\",null,\"^11\",15,\"~:flip-y\",null]]",
"~u77c71dba-32ee-804c-8007-736561cff45a": "[\"~#shape\",[\"^ \",\"~:y\",429.00000357564727,\"~:transform\",[\"~#matrix\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:rotation\",0,\"~:grow-type\",\"~:auto-width\",\"~:index\",null,\"~:content\",[\"^ \",\"~:type\",\"root\",\"~:children\",[[\"^ \",\"^8\",\"paragraph-set\",\"^9\",[[\"^ \",\"~:line-height\",\"1.2\",\"~:path\",\"\",\"~:font-style\",\"normal\",\"^9\",[[\"^ \",\"^:\",\"1.2\",\"^;\",\"\",\"^<\",\"normal\",\"~:text-transform\",\"uppercase\",\"~:text-align\",\"left\",\"~:font-id\",\"gfont-work-sans\",\"~:font-size\",\"12\",\"~:font-weight\",\"500\",\"~:modified-at\",\"2024-06-04T14:15:09.786Z\",\"~:font-variant-id\",\"500\",\"~:text-decoration\",\"underline\",\"~:letter-spacing\",\"0\",\"~:fills\",[[\"^ \",\"~:fill-color\",\"#000000\",\"~:fill-color-ref-file\",\"~ucaa70d02-51e1-81ae-8007-735e7de3d7bc\",\"~:fill-opacity\",1,\"~:fill-color-ref-id\",\"~udfa92acf-7d18-8079-8003-baba8789d8af\"]],\"~:font-family\",\"Work Sans\",\"~:text\",\"Label\"]],\"^=\",\"uppercase\",\"^>\",\"center\",\"^?\",\"gfont-work-sans\",\"^@\",\"12\",\"^A\",\"500\",\"^8\",\"paragraph\",\"^B\",\"2024-06-04T14:15:09.786Z\",\"^C\",\"500\",\"^D\",\"underline\",\"^E\",\"0\",\"^F\",[[\"^ \",\"^G\",\"#000000\",\"^H\",\"~ucaa70d02-51e1-81ae-8007-735e7de3d7bc\",\"^I\",1,\"^J\",\"~udfa92acf-7d18-8079-8003-baba8789d8af\"]],\"^K\",\"Work Sans\"]]]],\"~:vertical-align\",\"center\",\"^F\",[[\"^ \",\"^G\",\"#000000\",\"^I\",1]]],\"~:hide-in-viewer\",true,\"~:name\",\"Input\",\"~:saved-component-root\",null,\"~:width\",38,\"^8\",\"^L\",\"~:points\",[[\"~#point\",[\"^ \",\"~:x\",709.9999775886536,\"~:y\",429.00000357564727]],[\"^S\",[\"^ \",\"~:x\",747.9999775886536,\"~:y\",429.00000357564727]],[\"^S\",[\"^ \",\"~:x\",747.9999775886536,\"~:y\",444.0000035756468]],[\"^S\",[\"^ \",\"~:x\",709.9999775886536,\"~:y\",444.00000357564727]]],\"~:layout-item-h-sizing\",\"~:fix\",\"~:transform-inverse\",[\"^2\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:page-id\",\"~u02e9633d-4ce7-80da-8007-736558496fa8\",\"~:id\",\"~u77c71dba-32ee-804c-8007-736561cff45a\",\"~:parent-id\",\"~u77c71dba-32ee-804c-8007-736561cff459\",\"~:position-data\",[[\"^ \",\"~:y\",443.3399963378906,\"^:\",\"1.2\",\"^<\",\"normal\",\"^=\",\"uppercase\",\"^>\",\"left\",\"^?\",\"sourcesanspro\",\"^@\",\"12\",\"^A\",\"500\",\"~:text-direction\",\"ltr\",\"^Q\",37.93994140625,\"^C\",\"regular\",\"^D\",\"underline\",\"^E\",\"0\",\"~:x\",710.030029296875,\"^F\",[[\"^ \",\"^G\",\"#000000\",\"^H\",\"~ucaa70d02-51e1-81ae-8007-735e7de3d7bc\",\"^I\",1,\"^J\",\"~udfa92acf-7d18-8079-8003-baba8789d8af\"]],\"~:direction\",\"ltr\",\"^K\",\"Work Sans\",\"~:height\",14.079986572265625,\"^L\",\"Label\"]],\"~:frame-id\",\"~u77c71dba-32ee-804c-8007-736561cff459\",\"~:strokes\",[],\"~:x\",709.9999775886536,\"~:selrect\",[\"~#rect\",[\"^ \",\"~:x\",709.9999775886536,\"~:y\",429.00000357564727,\"^Q\",38,\"^11\",15,\"~:x1\",709.9999775886536,\"~:y1\",429.00000357564727,\"~:x2\",747.9999775886536,\"~:y2\",444.00000357564727]],\"^F\",[],\"~:flip-x\",null,\"^11\",15,\"~:flip-y\",null]]",
"~u77c71dba-32ee-804c-8007-736561cff459": "[\"~#shape\",[\"^ \",\"~:y\",428.00000357564704,\"~:hide-fill-on-export\",false,\"~:layout-gap-type\",\"~:multiple\",\"~:layout-padding\",[\"^ \",\"~:p1\",0,\"~:p2\",2,\"~:p3\",0,\"~:p4\",2],\"~:transform\",[\"~#matrix\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:rotation\",0,\"~:layout-wrap-type\",\"~:nowrap\",\"~:layout\",\"~:flex\",\"~:hide-in-viewer\",true,\"~:name\",\"_Utilities / Text / White\",\"~:layout-align-items\",\"~:start\",\"~:width\",42,\"~:layout-padding-type\",\"~:simple\",\"~:transforming\",false,\"~:type\",\"~:frame\",\"~:points\",[[\"~#point\",[\"^ \",\"~:x\",707.9999775886536,\"~:y\",428.00000357564704]],[\"^K\",[\"^ \",\"~:x\",749.9999775886536,\"~:y\",428.00000357564704]],[\"^K\",[\"^ \",\"~:x\",749.9999775886536,\"~:y\",444.00000357564704]],[\"^K\",[\"^ \",\"~:x\",707.9999775886536,\"~:y\",444.00000357564704]]],\"~:show-content\",true,\"~:layout-item-h-sizing\",\"~:auto\",\"~:proportion-lock\",false,\"~:layout-gap\",[\"^ \",\"~:row-gap\",0,\"~:column-gap\",6],\"~:transform-inverse\",[\"^:\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:page-id\",\"~u02e9633d-4ce7-80da-8007-736558496fa8\",\"~:layout-justify-content\",\"~:center\",\"~:id\",\"~u77c71dba-32ee-804c-8007-736561cff459\",\"~:parent-id\",\"~u77c71dba-32ee-804c-8007-736561cff458\",\"~:layout-flex-dir\",\"~:column\",\"~:layout-align-content\",\"~:stretch\",\"~:frame-id\",\"~u77c71dba-32ee-804c-8007-736561cff458\",\"~:strokes\",[],\"~:x\",707.9999775886536,\"~:proportion\",1,\"~:selrect\",[\"~#rect\",[\"^ \",\"~:x\",707.9999775886536,\"~:y\",428.00000357564704,\"^D\",42,\"~:height\",16,\"~:x1\",707.9999775886536,\"~:y1\",428.00000357564704,\"~:x2\",749.9999775886536,\"~:y2\",444.00000357564704]],\"~:fills\",[],\"~:flip-x\",null,\"^16\",16,\"~:flip-y\",null,\"~:shapes\",[\"~u77c71dba-32ee-804c-8007-736561cff45a\"]]]",
"~u77c71dba-32ee-804c-8007-736561cff458": "[\"~#shape\",[\"^ \",\"~:y\",420.00000357564704,\"~:hide-fill-on-export\",false,\"~:layout-gap-type\",\"~:multiple\",\"~:rx\",8,\"~:layout-padding\",[\"^ \",\"~:p1\",8,\"~:p2\",12,\"~:p3\",8,\"~:p4\",12],\"~:transform\",[\"~#matrix\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:rotation\",0,\"~:layout-wrap-type\",\"~:nowrap\",\"~:layout\",\"~:flex\",\"~:hide-in-viewer\",true,\"~:name\",\"Dark / Button / Primary / Text / Default\",\"~:layout-align-items\",\"~:center\",\"~:width\",66,\"~:layout-padding-type\",\"~:simple\",\"~:type\",\"~:frame\",\"~:points\",[[\"~#point\",[\"^ \",\"~:x\",695.9999775886536,\"~:y\",420.00000357564704]],[\"^K\",[\"^ \",\"~:x\",761.9999775886536,\"~:y\",420.00000357564704]],[\"^K\",[\"^ \",\"~:x\",761.9999775886536,\"~:y\",452.00000357564704]],[\"^K\",[\"^ \",\"~:x\",695.9999775886536,\"~:y\",452.00000357564704]]],\"~:r2\",8,\"~:show-content\",true,\"~:proportion-lock\",false,\"~:layout-gap\",[\"^ \",\"~:row-gap\",4,\"~:column-gap\",4],\"~:transform-inverse\",[\"^;\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:page-id\",\"~u02e9633d-4ce7-80da-8007-736558496fa8\",\"~:r3\",8,\"~:layout-justify-content\",\"^D\",\"~:r1\",8,\"~:id\",\"~u77c71dba-32ee-804c-8007-736561cff458\",\"~:parent-id\",\"~u77c71dba-32ee-804c-8007-736561cf8584\",\"~:layout-flex-dir\",\"~:row\",\"~:layout-align-content\",\"~:stretch\",\"~:frame-id\",\"~u77c71dba-32ee-804c-8007-736561cf8584\",\"~:strokes\",[],\"~:x\",695.9999775886536,\"~:proportion\",1,\"~:r4\",8,\"~:selrect\",[\"~#rect\",[\"^ \",\"~:x\",695.9999775886536,\"~:y\",420.00000357564704,\"^E\",66,\"~:height\",32,\"~:x1\",695.9999775886536,\"~:y1\",420.00000357564704,\"~:x2\",761.9999775886536,\"~:y2\",452.00000357564704]],\"~:fills\",[[\"^ \",\"~:fill-color\",\"#7efff5\",\"~:fill-opacity\",1]],\"~:flip-x\",null,\"~:ry\",8,\"^17\",32,\"~:flip-y\",null,\"~:shapes\",[\"~u77c71dba-32ee-804c-8007-736561cff459\"]]]",
"~u77c71dba-32ee-804c-8007-736561cf857f": "[\"~#shape\",[\"^ \",\"~:y\",395.99997913999186,\"~:hide-fill-on-export\",false,\"~:layout-gap-type\",\"~:multiple\",\"~:layout-padding\",[\"^ \",\"~:p1\",0,\"~:p2\",12,\"~:p3\",0,\"~:p4\",12],\"~:transform\",[\"~#matrix\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:rotation\",0,\"~:layout-wrap-type\",\"~:wrap\",\"~:layout\",\"~:flex\",\"~:hide-in-viewer\",true,\"~:name\",\"Board Parent 1\",\"~:layout-align-items\",\"~:start\",\"~:width\",272,\"~:layout-padding-type\",\"~:simple\",\"~:type\",\"~:frame\",\"~:points\",[[\"~#point\",[\"^ \",\"~:x\",593.0000386238098,\"~:y\",395.99997913999186]],[\"^J\",[\"^ \",\"~:x\",865.0000386238098,\"~:y\",395.99997913999186]],[\"^J\",[\"^ \",\"~:x\",865.0000386238098,\"~:y\",475.9999669761459]],[\"^J\",[\"^ \",\"~:x\",593.0000386238098,\"~:y\",475.9999669761459]]],\"~:show-content\",true,\"~:proportion-lock\",false,\"~:layout-gap\",[\"^ \",\"~:row-gap\",4,\"~:column-gap\",4],\"~:transform-inverse\",[\"^:\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:page-id\",\"~u02e9633d-4ce7-80da-8007-736558496fa8\",\"~:layout-item-v-sizing\",\"~:fix\",\"~:layout-justify-content\",\"~:center\",\"~:id\",\"~u77c71dba-32ee-804c-8007-736561cf857f\",\"~:parent-id\",\"~u00000000-0000-0000-0000-000000000000\",\"~:layout-flex-dir\",\"~:row\",\"~:layout-align-content\",\"~:stretch\",\"~:frame-id\",\"~u00000000-0000-0000-0000-000000000000\",\"~:strokes\",[],\"~:x\",593.0000386238098,\"~:proportion\",1,\"~:selrect\",[\"~#rect\",[\"^ \",\"~:x\",593.0000386238098,\"~:y\",395.99997913999186,\"^D\",272,\"~:height\",79.99998783615405,\"~:x1\",593.0000386238098,\"~:y1\",395.99997913999186,\"~:x2\",865.0000386238098,\"~:y2\",475.9999669761459]],\"~:fills\",[],\"~:flip-x\",null,\"^15\",79.99998783615405,\"~:flip-y\",null,\"~:shapes\",[\"~u77c71dba-32ee-804c-8007-736561cf8584\"]]]",
"~u94eaebe4-addd-80d1-8007-79d50980078e": "[\"~#shape\",[\"^ \",\"~:y\",720.0000478045426,\"~:hide-fill-on-export\",false,\"~:layout-gap-type\",\"~:multiple\",\"~:layout-padding\",[\"^ \",\"~:p1\",0,\"~:p2\",12,\"~:p3\",0,\"~:p4\",12],\"~:transform\",[\"~#matrix\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:rotation\",0,\"~:layout-wrap-type\",\"~:wrap\",\"~:layout\",\"~:flex\",\"~:hide-in-viewer\",true,\"~:name\",\"Board Parent 4\",\"~:layout-align-items\",\"~:start\",\"~:width\",272,\"~:layout-padding-type\",\"~:simple\",\"~:type\",\"~:frame\",\"~:points\",[[\"~#point\",[\"^ \",\"~:x\",592.9998555183411,\"~:y\",720.0000478045426]],[\"^J\",[\"^ \",\"~:x\",864.9998555183411,\"~:y\",720.0000478045426]],[\"^J\",[\"^ \",\"~:x\",864.9998555183411,\"~:y\",800.0000356406968]],[\"^J\",[\"^ \",\"~:x\",592.9998555183411,\"~:y\",800.0000356406968]]],\"~:show-content\",true,\"~:proportion-lock\",false,\"~:layout-gap\",[\"^ \",\"~:row-gap\",4,\"~:column-gap\",4],\"~:transform-inverse\",[\"^:\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:page-id\",\"~u02e9633d-4ce7-80da-8007-736558496fa8\",\"~:layout-item-v-sizing\",\"~:fix\",\"~:layout-justify-content\",\"~:center\",\"~:id\",\"~u94eaebe4-addd-80d1-8007-79d50980078e\",\"~:parent-id\",\"~u00000000-0000-0000-0000-000000000000\",\"~:layout-flex-dir\",\"~:column-reverse\",\"~:layout-align-content\",\"~:stretch\",\"~:frame-id\",\"~u00000000-0000-0000-0000-000000000000\",\"~:strokes\",[],\"~:x\",592.9998555183411,\"~:proportion\",1,\"~:selrect\",[\"~#rect\",[\"^ \",\"~:x\",592.9998555183411,\"~:y\",720.0000478045426,\"^D\",272,\"~:height\",79.9999878361541,\"~:x1\",592.9998555183411,\"~:y1\",720.0000478045426,\"~:x2\",864.9998555183411,\"~:y2\",800.0000356406968]],\"~:fills\",[],\"~:flip-x\",null,\"^15\",79.9999878361541,\"~:flip-y\",null,\"~:shapes\",[\"~u94eaebe4-addd-80d1-8007-79d50980078f\"]]]",
"~u94eaebe4-addd-80d1-8007-79d50980078f": "[\"~#shape\",[\"^ \",\"~:y\",719.9999806874634,\"~:hide-fill-on-export\",false,\"~:transform\",[\"~#matrix\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:rotation\",0,\"~:hide-in-viewer\",true,\"~:name\",\"Board Child\",\"~:width\",80,\"~:type\",\"~:frame\",\"~:points\",[[\"~#point\",[\"^ \",\"~:x\",604.9999775886536,\"~:y\",719.9999806874634]],[\"^;\",[\"^ \",\"~:x\",684.9999775886536,\"~:y\",719.9999806874634]],[\"^;\",[\"^ \",\"~:x\",684.9999775886536,\"~:y\",799.9999806874634]],[\"^;\",[\"^ \",\"~:x\",604.9999775886536,\"~:y\",799.9999806874634]]],\"~:show-content\",true,\"~:proportion-lock\",false,\"~:transform-inverse\",[\"^3\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:page-id\",\"~u02e9633d-4ce7-80da-8007-736558496fa8\",\"~:constraints-v\",\"~:top\",\"~:constraints-h\",\"~:left\",\"~:id\",\"~u94eaebe4-addd-80d1-8007-79d50980078f\",\"~:parent-id\",\"~u94eaebe4-addd-80d1-8007-79d50980078e\",\"~:frame-id\",\"~u94eaebe4-addd-80d1-8007-79d50980078e\",\"~:strokes\",[],\"~:x\",604.9999775886536,\"~:proportion\",1,\"~:selrect\",[\"~#rect\",[\"^ \",\"~:x\",604.9999775886536,\"~:y\",719.9999806874634,\"^7\",80,\"~:height\",80,\"~:x1\",604.9999775886536,\"~:y1\",719.9999806874634,\"~:x2\",684.9999775886536,\"~:y2\",799.9999806874634]],\"~:fills\",[],\"~:flip-x\",null,\"^K\",80,\"~:flip-y\",null,\"~:shapes\",[\"~u94eaebe4-addd-80d1-8007-79d509800790\",\"~u94eaebe4-addd-80d1-8007-79d509800791\"]]]",
"~u94eaebe4-addd-80d1-8007-79d508a9dc2f": "[\"~#shape\",[\"^ \",\"~:y\",612.000024916359,\"~:hide-fill-on-export\",false,\"~:layout-gap-type\",\"~:multiple\",\"~:layout-padding\",[\"^ \",\"~:p1\",0,\"~:p2\",12,\"~:p3\",0,\"~:p4\",12],\"~:transform\",[\"~#matrix\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:rotation\",0,\"~:layout-wrap-type\",\"~:wrap\",\"~:layout\",\"~:flex\",\"~:hide-in-viewer\",true,\"~:name\",\"Board Parent 3\",\"~:layout-align-items\",\"~:start\",\"~:width\",272,\"~:layout-padding-type\",\"~:simple\",\"~:type\",\"~:frame\",\"~:points\",[[\"~#point\",[\"^ \",\"~:x\",592.9999165534973,\"~:y\",612.000024916359]],[\"^J\",[\"^ \",\"~:x\",864.9999165534973,\"~:y\",612.000024916359]],[\"^J\",[\"^ \",\"~:x\",864.9999165534973,\"~:y\",692.0000127525132]],[\"^J\",[\"^ \",\"~:x\",592.9999165534973,\"~:y\",692.0000127525132]]],\"~:show-content\",true,\"~:proportion-lock\",false,\"~:layout-gap\",[\"^ \",\"~:row-gap\",4,\"~:column-gap\",4],\"~:transform-inverse\",[\"^:\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:page-id\",\"~u02e9633d-4ce7-80da-8007-736558496fa8\",\"~:layout-item-v-sizing\",\"~:fix\",\"~:layout-justify-content\",\"~:center\",\"~:id\",\"~u94eaebe4-addd-80d1-8007-79d508a9dc2f\",\"~:parent-id\",\"~u00000000-0000-0000-0000-000000000000\",\"~:layout-flex-dir\",\"~:column\",\"~:layout-align-content\",\"~:stretch\",\"~:frame-id\",\"~u00000000-0000-0000-0000-000000000000\",\"~:strokes\",[],\"~:x\",592.9999165534973,\"~:proportion\",1,\"~:selrect\",[\"~#rect\",[\"^ \",\"~:x\",592.9999165534973,\"~:y\",612.000024916359,\"^D\",272,\"~:height\",79.9999878361541,\"~:x1\",592.9999165534973,\"~:y1\",612.000024916359,\"~:x2\",864.9999165534973,\"~:y2\",692.0000127525132]],\"~:fills\",[],\"~:flip-x\",null,\"^15\",79.9999878361541,\"~:flip-y\",null,\"~:shapes\",[\"~u94eaebe4-addd-80d1-8007-79d508a9dc30\"]]]",
"~u94eaebe4-addd-80d1-8007-79d509800790": "[\"~#shape\",[\"^ \",\"~:y\",720.0000417226197,\"~:rx\",8,\"~:transform\",[\"~#matrix\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:rotation\",0,\"~:grow-type\",\"~:fixed\",\"~:hide-in-viewer\",false,\"~:name\",\"Rectangle\",\"~:width\",80,\"~:transforming\",false,\"~:type\",\"~:rect\",\"~:points\",[[\"~#point\",[\"^ \",\"~:x\",604.9998555183411,\"~:y\",720.0000417226197]],[\"^>\",[\"^ \",\"~:x\",684.9998555183411,\"~:y\",720.0000417226197]],[\"^>\",[\"^ \",\"~:x\",684.9998555183411,\"~:y\",800.0000417226197]],[\"^>\",[\"^ \",\"~:x\",604.9998555183411,\"~:y\",800.0000417226197]]],\"~:r2\",8,\"~:proportion-lock\",false,\"~:transform-inverse\",[\"^3\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:page-id\",\"~u02e9633d-4ce7-80da-8007-736558496fa8\",\"~:r3\",8,\"~:r1\",8,\"~:id\",\"~u94eaebe4-addd-80d1-8007-79d509800790\",\"~:parent-id\",\"~u94eaebe4-addd-80d1-8007-79d50980078f\",\"~:frame-id\",\"~u94eaebe4-addd-80d1-8007-79d50980078f\",\"~:strokes\",[],\"~:x\",604.9998555183411,\"~:proportion\",1,\"~:r4\",8,\"~:selrect\",[\"~#rect\",[\"^ \",\"~:x\",604.9998555183411,\"~:y\",720.0000417226197,\"^9\",80,\"~:height\",80,\"~:x1\",604.9998555183411,\"~:y1\",720.0000417226197,\"~:x2\",684.9998555183411,\"~:y2\",800.0000417226197]],\"~:fills\",[[\"^ \",\"~:fill-color\",\"#e8e9ea\",\"~:fill-opacity\",1]],\"~:flip-x\",null,\"~:ry\",8,\"^M\",80,\"~:flip-y\",null]]",
"~u94eaebe4-addd-80d1-8007-79d508a9dc30": "[\"~#shape\",[\"^ \",\"~:y\",612.0000188344361,\"~:hide-fill-on-export\",false,\"~:transform\",[\"~#matrix\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:rotation\",0,\"~:hide-in-viewer\",true,\"~:name\",\"Board Child\",\"~:width\",80,\"~:type\",\"~:frame\",\"~:points\",[[\"~#point\",[\"^ \",\"~:x\",604.9999775886536,\"~:y\",612.0000188344361]],[\"^;\",[\"^ \",\"~:x\",684.9999775886536,\"~:y\",612.0000188344361]],[\"^;\",[\"^ \",\"~:x\",684.9999775886536,\"~:y\",692.0000188344361]],[\"^;\",[\"^ \",\"~:x\",604.9999775886536,\"~:y\",692.0000188344361]]],\"~:show-content\",true,\"~:proportion-lock\",false,\"~:transform-inverse\",[\"^3\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:page-id\",\"~u02e9633d-4ce7-80da-8007-736558496fa8\",\"~:constraints-v\",\"~:top\",\"~:constraints-h\",\"~:left\",\"~:id\",\"~u94eaebe4-addd-80d1-8007-79d508a9dc30\",\"~:parent-id\",\"~u94eaebe4-addd-80d1-8007-79d508a9dc2f\",\"~:frame-id\",\"~u94eaebe4-addd-80d1-8007-79d508a9dc2f\",\"~:strokes\",[],\"~:x\",604.9999775886536,\"~:proportion\",1,\"~:selrect\",[\"~#rect\",[\"^ \",\"~:x\",604.9999775886536,\"~:y\",612.0000188344361,\"^7\",80,\"~:height\",80,\"~:x1\",604.9999775886536,\"~:y1\",612.0000188344361,\"~:x2\",684.9999775886536,\"~:y2\",692.0000188344361]],\"~:fills\",[],\"~:flip-x\",null,\"^K\",80,\"~:flip-y\",null,\"~:shapes\",[\"~u94eaebe4-addd-80d1-8007-79d508aa2885\",\"~u94eaebe4-addd-80d1-8007-79d508aa2886\"]]]",
"~u94eaebe4-addd-80d1-8007-79d509800791": "[\"~#shape\",[\"^ \",\"~:y\",744.0000417226197,\"~:hide-fill-on-export\",false,\"~:layout-gap-type\",\"~:multiple\",\"~:rx\",8,\"~:layout-padding\",[\"^ \",\"~:p1\",8,\"~:p2\",12,\"~:p3\",8,\"~:p4\",12],\"~:transform\",[\"~#matrix\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:rotation\",0,\"~:layout-wrap-type\",\"~:nowrap\",\"~:layout\",\"~:flex\",\"~:hide-in-viewer\",true,\"~:name\",\"Dark / Button / Primary / Text / Default\",\"~:layout-align-items\",\"~:center\",\"~:width\",66,\"~:layout-padding-type\",\"~:simple\",\"~:type\",\"~:frame\",\"~:points\",[[\"~#point\",[\"^ \",\"~:x\",611.9998555183411,\"~:y\",744.0000417226197]],[\"^K\",[\"^ \",\"~:x\",677.9998555183411,\"~:y\",744.0000417226197]],[\"^K\",[\"^ \",\"~:x\",677.9998555183411,\"~:y\",776.0000417226197]],[\"^K\",[\"^ \",\"~:x\",611.9998555183411,\"~:y\",776.0000417226197]]],\"~:r2\",8,\"~:show-content\",true,\"~:proportion-lock\",false,\"~:layout-gap\",[\"^ \",\"~:row-gap\",4,\"~:column-gap\",4],\"~:transform-inverse\",[\"^;\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:page-id\",\"~u02e9633d-4ce7-80da-8007-736558496fa8\",\"~:r3\",8,\"~:layout-justify-content\",\"^D\",\"~:r1\",8,\"~:id\",\"~u94eaebe4-addd-80d1-8007-79d509800791\",\"~:parent-id\",\"~u94eaebe4-addd-80d1-8007-79d50980078f\",\"~:layout-flex-dir\",\"~:row\",\"~:layout-align-content\",\"~:stretch\",\"~:frame-id\",\"~u94eaebe4-addd-80d1-8007-79d50980078f\",\"~:strokes\",[],\"~:x\",611.9998555183411,\"~:proportion\",1,\"~:r4\",8,\"~:selrect\",[\"~#rect\",[\"^ \",\"~:x\",611.9998555183411,\"~:y\",744.0000417226197,\"^E\",66,\"~:height\",32,\"~:x1\",611.9998555183411,\"~:y1\",744.0000417226197,\"~:x2\",677.9998555183411,\"~:y2\",776.0000417226197]],\"~:fills\",[[\"^ \",\"~:fill-color\",\"#7efff5\",\"~:fill-opacity\",1]],\"~:flip-x\",null,\"~:ry\",8,\"^17\",32,\"~:flip-y\",null,\"~:shapes\",[\"~u94eaebe4-addd-80d1-8007-79d509800792\"]]]",
"~u94eaebe4-addd-80d1-8007-79d509800792": "[\"~#shape\",[\"^ \",\"~:y\",752.0000417226197,\"~:hide-fill-on-export\",false,\"~:layout-gap-type\",\"~:multiple\",\"~:layout-padding\",[\"^ \",\"~:p1\",0,\"~:p2\",2,\"~:p3\",0,\"~:p4\",2],\"~:transform\",[\"~#matrix\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:rotation\",0,\"~:layout-wrap-type\",\"~:nowrap\",\"~:layout\",\"~:flex\",\"~:hide-in-viewer\",true,\"~:name\",\"_Utilities / Text / White\",\"~:layout-align-items\",\"~:start\",\"~:width\",42,\"~:layout-padding-type\",\"~:simple\",\"~:transforming\",false,\"~:type\",\"~:frame\",\"~:points\",[[\"~#point\",[\"^ \",\"~:x\",623.9998555183411,\"~:y\",752.0000417226197]],[\"^K\",[\"^ \",\"~:x\",665.9998555183411,\"~:y\",752.0000417226197]],[\"^K\",[\"^ \",\"~:x\",665.9998555183411,\"~:y\",768.0000417226197]],[\"^K\",[\"^ \",\"~:x\",623.9998555183411,\"~:y\",768.0000417226197]]],\"~:show-content\",true,\"~:layout-item-h-sizing\",\"~:auto\",\"~:proportion-lock\",false,\"~:layout-gap\",[\"^ \",\"~:row-gap\",0,\"~:column-gap\",6],\"~:transform-inverse\",[\"^:\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:page-id\",\"~u02e9633d-4ce7-80da-8007-736558496fa8\",\"~:layout-justify-content\",\"~:center\",\"~:id\",\"~u94eaebe4-addd-80d1-8007-79d509800792\",\"~:parent-id\",\"~u94eaebe4-addd-80d1-8007-79d509800791\",\"~:layout-flex-dir\",\"~:column\",\"~:layout-align-content\",\"~:stretch\",\"~:frame-id\",\"~u94eaebe4-addd-80d1-8007-79d509800791\",\"~:strokes\",[],\"~:x\",623.9998555183411,\"~:proportion\",1,\"~:selrect\",[\"~#rect\",[\"^ \",\"~:x\",623.9998555183411,\"~:y\",752.0000417226197,\"^D\",42,\"~:height\",16,\"~:x1\",623.9998555183411,\"~:y1\",752.0000417226197,\"~:x2\",665.9998555183411,\"~:y2\",768.0000417226197]],\"~:fills\",[],\"~:flip-x\",null,\"^16\",16,\"~:flip-y\",null,\"~:shapes\",[\"~u94eaebe4-addd-80d1-8007-79d509800793\"]]]",
"~u94eaebe4-addd-80d1-8007-79d509800793": "[\"~#shape\",[\"^ \",\"~:y\",753.0000417226199,\"~:transform\",[\"~#matrix\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:rotation\",0,\"~:grow-type\",\"~:auto-width\",\"~:index\",null,\"~:content\",[\"^ \",\"~:type\",\"root\",\"~:children\",[[\"^ \",\"^8\",\"paragraph-set\",\"^9\",[[\"^ \",\"~:line-height\",\"1.2\",\"~:path\",\"\",\"~:font-style\",\"normal\",\"^9\",[[\"^ \",\"^:\",\"1.2\",\"^;\",\"\",\"^<\",\"normal\",\"~:text-transform\",\"uppercase\",\"~:text-align\",\"left\",\"~:font-id\",\"gfont-work-sans\",\"~:font-size\",\"12\",\"~:font-weight\",\"500\",\"~:modified-at\",\"2024-06-04T14:15:09.786Z\",\"~:font-variant-id\",\"500\",\"~:text-decoration\",\"underline\",\"~:letter-spacing\",\"0\",\"~:fills\",[[\"^ \",\"~:fill-color\",\"#000000\",\"~:fill-color-ref-file\",\"~ucaa70d02-51e1-81ae-8007-735e7de3d7bc\",\"~:fill-opacity\",1,\"~:fill-color-ref-id\",\"~udfa92acf-7d18-8079-8003-baba8789d8af\"]],\"~:font-family\",\"Work Sans\",\"~:text\",\"Label\"]],\"^=\",\"uppercase\",\"^>\",\"center\",\"^?\",\"gfont-work-sans\",\"^@\",\"12\",\"^A\",\"500\",\"^8\",\"paragraph\",\"^B\",\"2024-06-04T14:15:09.786Z\",\"^C\",\"500\",\"^D\",\"underline\",\"^E\",\"0\",\"^F\",[[\"^ \",\"^G\",\"#000000\",\"^H\",\"~ucaa70d02-51e1-81ae-8007-735e7de3d7bc\",\"^I\",1,\"^J\",\"~udfa92acf-7d18-8079-8003-baba8789d8af\"]],\"^K\",\"Work Sans\"]]]],\"~:vertical-align\",\"center\",\"^F\",[[\"^ \",\"^G\",\"#000000\",\"^I\",1]]],\"~:hide-in-viewer\",true,\"~:name\",\"Input\",\"~:saved-component-root\",null,\"~:width\",38,\"^8\",\"^L\",\"~:points\",[[\"~#point\",[\"^ \",\"~:x\",625.9998555183411,\"~:y\",753.0000417226199]],[\"^S\",[\"^ \",\"~:x\",663.9998555183411,\"~:y\",753.0000417226199]],[\"^S\",[\"^ \",\"~:x\",663.9998555183411,\"~:y\",768.0000417226195]],[\"^S\",[\"^ \",\"~:x\",625.9998555183411,\"~:y\",768.0000417226199]]],\"~:layout-item-h-sizing\",\"~:fix\",\"~:transform-inverse\",[\"^2\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:page-id\",\"~u02e9633d-4ce7-80da-8007-736558496fa8\",\"~:id\",\"~u94eaebe4-addd-80d1-8007-79d509800793\",\"~:parent-id\",\"~u94eaebe4-addd-80d1-8007-79d509800792\",\"~:position-data\",[[\"^ \",\"~:y\",767.340087890625,\"^:\",\"1.2\",\"^<\",\"normal\",\"^=\",\"uppercase\",\"^>\",\"left\",\"^?\",\"sourcesanspro\",\"^@\",\"12\",\"^A\",\"500\",\"~:text-direction\",\"ltr\",\"^Q\",37.93994140625,\"^C\",\"regular\",\"^D\",\"underline\",\"^E\",\"0\",\"~:x\",626.0299072265625,\"^F\",[[\"^ \",\"^G\",\"#000000\",\"^H\",\"~ucaa70d02-51e1-81ae-8007-735e7de3d7bc\",\"^I\",1,\"^J\",\"~udfa92acf-7d18-8079-8003-baba8789d8af\"]],\"~:direction\",\"ltr\",\"^K\",\"Work Sans\",\"~:height\",14.08001708984375,\"^L\",\"Label\"]],\"~:frame-id\",\"~u94eaebe4-addd-80d1-8007-79d509800792\",\"~:strokes\",[],\"~:x\",625.9998555183411,\"~:selrect\",[\"~#rect\",[\"^ \",\"~:x\",625.9998555183411,\"~:y\",753.0000417226199,\"^Q\",38,\"^11\",15,\"~:x1\",625.9998555183411,\"~:y1\",753.0000417226199,\"~:x2\",663.9998555183411,\"~:y2\",768.0000417226199]],\"^F\",[],\"~:flip-x\",null,\"^11\",15,\"~:flip-y\",null]]",
"~u77c71dba-32ee-804c-8007-736561cf8584": "[\"~#shape\",[\"^ \",\"~:y\",396.00000357564704,\"~:hide-fill-on-export\",false,\"~:transform\",[\"~#matrix\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:rotation\",0,\"~:hide-in-viewer\",true,\"~:name\",\"Board Child\",\"~:width\",80,\"~:type\",\"~:frame\",\"~:points\",[[\"~#point\",[\"^ \",\"~:x\",688.9999775886536,\"~:y\",396.00000357564704]],[\"^;\",[\"^ \",\"~:x\",768.9999775886536,\"~:y\",396.00000357564704]],[\"^;\",[\"^ \",\"~:x\",768.9999775886536,\"~:y\",476.00000357564704]],[\"^;\",[\"^ \",\"~:x\",688.9999775886536,\"~:y\",476.00000357564704]]],\"~:show-content\",true,\"~:proportion-lock\",false,\"~:transform-inverse\",[\"^3\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:page-id\",\"~u02e9633d-4ce7-80da-8007-736558496fa8\",\"~:constraints-v\",\"~:top\",\"~:constraints-h\",\"~:left\",\"~:id\",\"~u77c71dba-32ee-804c-8007-736561cf8584\",\"~:parent-id\",\"~u77c71dba-32ee-804c-8007-736561cf857f\",\"~:frame-id\",\"~u77c71dba-32ee-804c-8007-736561cf857f\",\"~:strokes\",[],\"~:x\",688.9999775886536,\"~:proportion\",1,\"~:selrect\",[\"~#rect\",[\"^ \",\"~:x\",688.9999775886536,\"~:y\",396.00000357564704,\"^7\",80,\"~:height\",80,\"~:x1\",688.9999775886536,\"~:y1\",396.00000357564704,\"~:x2\",768.9999775886536,\"~:y2\",476.00000357564704]],\"~:fills\",[],\"~:flip-x\",null,\"^K\",80,\"~:flip-y\",null,\"~:shapes\",[\"~u77c71dba-32ee-804c-8007-736561cff457\",\"~u77c71dba-32ee-804c-8007-736561cff458\"]]]",
"~u94eaebe4-addd-80d1-8007-79d5055d6859": "[\"~#shape\",[\"^ \",\"~:y\",504.00000202817546,\"~:hide-fill-on-export\",false,\"~:layout-gap-type\",\"~:multiple\",\"~:layout-padding\",[\"^ \",\"~:p1\",0,\"~:p2\",12,\"~:p3\",0,\"~:p4\",12],\"~:transform\",[\"~#matrix\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:rotation\",0,\"~:layout-wrap-type\",\"~:wrap\",\"~:layout\",\"~:flex\",\"~:hide-in-viewer\",true,\"~:name\",\"Board Parent 2\",\"~:layout-align-items\",\"~:start\",\"~:width\",272,\"~:layout-padding-type\",\"~:simple\",\"~:type\",\"~:frame\",\"~:points\",[[\"~#point\",[\"^ \",\"~:x\",592.9999775886536,\"~:y\",504.00000202817546]],[\"^J\",[\"^ \",\"~:x\",864.9999775886536,\"~:y\",504.00000202817546]],[\"^J\",[\"^ \",\"~:x\",864.9999775886536,\"~:y\",583.9999898643296]],[\"^J\",[\"^ \",\"~:x\",592.9999775886536,\"~:y\",583.9999898643296]]],\"~:show-content\",true,\"~:proportion-lock\",false,\"~:layout-gap\",[\"^ \",\"~:row-gap\",4,\"~:column-gap\",4],\"~:transform-inverse\",[\"^:\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:page-id\",\"~u02e9633d-4ce7-80da-8007-736558496fa8\",\"~:layout-item-v-sizing\",\"~:fix\",\"~:layout-justify-content\",\"~:center\",\"~:id\",\"~u94eaebe4-addd-80d1-8007-79d5055d6859\",\"~:parent-id\",\"~u00000000-0000-0000-0000-000000000000\",\"~:layout-flex-dir\",\"~:row-reverse\",\"~:layout-align-content\",\"~:stretch\",\"~:frame-id\",\"~u00000000-0000-0000-0000-000000000000\",\"~:strokes\",[],\"~:x\",592.9999775886536,\"~:proportion\",1,\"~:selrect\",[\"~#rect\",[\"^ \",\"~:x\",592.9999775886536,\"~:y\",504.00000202817546,\"^D\",272,\"~:height\",79.9999878361541,\"~:x1\",592.9999775886536,\"~:y1\",504.00000202817546,\"~:x2\",864.9999775886536,\"~:y2\",583.9999898643296]],\"~:fills\",[],\"~:flip-x\",null,\"^15\",79.9999878361541,\"~:flip-y\",null,\"~:shapes\",[\"~u94eaebe4-addd-80d1-8007-79d5055d685a\"]]]",
"~u94eaebe4-addd-80d1-8007-79d5055d685a": "[\"~#shape\",[\"^ \",\"~:y\",503.9999959462525,\"~:hide-fill-on-export\",false,\"~:transform\",[\"~#matrix\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:rotation\",0,\"~:hide-in-viewer\",true,\"~:name\",\"Board Child\",\"~:width\",80,\"~:type\",\"~:frame\",\"~:points\",[[\"~#point\",[\"^ \",\"~:x\",688.9999775886536,\"~:y\",503.9999959462525]],[\"^;\",[\"^ \",\"~:x\",768.9999775886536,\"~:y\",503.9999959462525]],[\"^;\",[\"^ \",\"~:x\",768.9999775886536,\"~:y\",583.9999959462525]],[\"^;\",[\"^ \",\"~:x\",688.9999775886536,\"~:y\",583.9999959462525]]],\"~:show-content\",true,\"~:proportion-lock\",false,\"~:transform-inverse\",[\"^3\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:page-id\",\"~u02e9633d-4ce7-80da-8007-736558496fa8\",\"~:constraints-v\",\"~:top\",\"~:constraints-h\",\"~:left\",\"~:id\",\"~u94eaebe4-addd-80d1-8007-79d5055d685a\",\"~:parent-id\",\"~u94eaebe4-addd-80d1-8007-79d5055d6859\",\"~:frame-id\",\"~u94eaebe4-addd-80d1-8007-79d5055d6859\",\"~:strokes\",[],\"~:x\",688.9999775886536,\"~:proportion\",1,\"~:selrect\",[\"~#rect\",[\"^ \",\"~:x\",688.9999775886536,\"~:y\",503.9999959462525,\"^7\",80,\"~:height\",80,\"~:x1\",688.9999775886536,\"~:y1\",503.9999959462525,\"~:x2\",768.9999775886536,\"~:y2\",583.9999959462525]],\"~:fills\",[],\"~:flip-x\",null,\"^K\",80,\"~:flip-y\",null,\"~:shapes\",[\"~u94eaebe4-addd-80d1-8007-79d5055d685b\",\"~u94eaebe4-addd-80d1-8007-79d5055d685c\"]]]",
"~u94eaebe4-addd-80d1-8007-79d5055d685b": "[\"~#shape\",[\"^ \",\"~:y\",503.9999959462525,\"~:rx\",8,\"~:transform\",[\"~#matrix\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:rotation\",0,\"~:grow-type\",\"~:fixed\",\"~:hide-in-viewer\",false,\"~:name\",\"Rectangle\",\"~:width\",80,\"~:transforming\",false,\"~:type\",\"~:rect\",\"~:points\",[[\"~#point\",[\"^ \",\"~:x\",688.9999775886536,\"~:y\",503.9999959462525]],[\"^>\",[\"^ \",\"~:x\",768.9999775886536,\"~:y\",503.9999959462525]],[\"^>\",[\"^ \",\"~:x\",768.9999775886536,\"~:y\",583.9999959462525]],[\"^>\",[\"^ \",\"~:x\",688.9999775886536,\"~:y\",583.9999959462525]]],\"~:r2\",8,\"~:proportion-lock\",false,\"~:transform-inverse\",[\"^3\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:page-id\",\"~u02e9633d-4ce7-80da-8007-736558496fa8\",\"~:r3\",8,\"~:r1\",8,\"~:id\",\"~u94eaebe4-addd-80d1-8007-79d5055d685b\",\"~:parent-id\",\"~u94eaebe4-addd-80d1-8007-79d5055d685a\",\"~:frame-id\",\"~u94eaebe4-addd-80d1-8007-79d5055d685a\",\"~:strokes\",[],\"~:x\",688.9999775886536,\"~:proportion\",1,\"~:r4\",8,\"~:selrect\",[\"~#rect\",[\"^ \",\"~:x\",688.9999775886536,\"~:y\",503.9999959462525,\"^9\",80,\"~:height\",80,\"~:x1\",688.9999775886536,\"~:y1\",503.9999959462525,\"~:x2\",768.9999775886536,\"~:y2\",583.9999959462525]],\"~:fills\",[[\"^ \",\"~:fill-color\",\"#e8e9ea\",\"~:fill-opacity\",1]],\"~:flip-x\",null,\"~:ry\",8,\"^M\",80,\"~:flip-y\",null]]",
"~u94eaebe4-addd-80d1-8007-79d5055d685c": "[\"~#shape\",[\"^ \",\"~:y\",527.9999959462525,\"~:hide-fill-on-export\",false,\"~:layout-gap-type\",\"~:multiple\",\"~:rx\",8,\"~:layout-padding\",[\"^ \",\"~:p1\",8,\"~:p2\",12,\"~:p3\",8,\"~:p4\",12],\"~:transform\",[\"~#matrix\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:rotation\",0,\"~:layout-wrap-type\",\"~:nowrap\",\"~:layout\",\"~:flex\",\"~:hide-in-viewer\",true,\"~:name\",\"Dark / Button / Primary / Text / Default\",\"~:layout-align-items\",\"~:center\",\"~:width\",66,\"~:layout-padding-type\",\"~:simple\",\"~:type\",\"~:frame\",\"~:points\",[[\"~#point\",[\"^ \",\"~:x\",695.9999775886536,\"~:y\",527.9999959462525]],[\"^K\",[\"^ \",\"~:x\",761.9999775886536,\"~:y\",527.9999959462525]],[\"^K\",[\"^ \",\"~:x\",761.9999775886536,\"~:y\",559.9999959462525]],[\"^K\",[\"^ \",\"~:x\",695.9999775886536,\"~:y\",559.9999959462525]]],\"~:r2\",8,\"~:show-content\",true,\"~:proportion-lock\",false,\"~:layout-gap\",[\"^ \",\"~:row-gap\",4,\"~:column-gap\",4],\"~:transform-inverse\",[\"^;\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:page-id\",\"~u02e9633d-4ce7-80da-8007-736558496fa8\",\"~:r3\",8,\"~:layout-justify-content\",\"^D\",\"~:r1\",8,\"~:id\",\"~u94eaebe4-addd-80d1-8007-79d5055d685c\",\"~:parent-id\",\"~u94eaebe4-addd-80d1-8007-79d5055d685a\",\"~:layout-flex-dir\",\"~:row\",\"~:layout-align-content\",\"~:stretch\",\"~:frame-id\",\"~u94eaebe4-addd-80d1-8007-79d5055d685a\",\"~:strokes\",[],\"~:x\",695.9999775886536,\"~:proportion\",1,\"~:r4\",8,\"~:selrect\",[\"~#rect\",[\"^ \",\"~:x\",695.9999775886536,\"~:y\",527.9999959462525,\"^E\",66,\"~:height\",32,\"~:x1\",695.9999775886536,\"~:y1\",527.9999959462525,\"~:x2\",761.9999775886536,\"~:y2\",559.9999959462525]],\"~:fills\",[[\"^ \",\"~:fill-color\",\"#7efff5\",\"~:fill-opacity\",1]],\"~:flip-x\",null,\"~:ry\",8,\"^17\",32,\"~:flip-y\",null,\"~:shapes\",[\"~u94eaebe4-addd-80d1-8007-79d5055d685d\"]]]",
"~u94eaebe4-addd-80d1-8007-79d5055d685d": "[\"~#shape\",[\"^ \",\"~:y\",535.9999959462525,\"~:hide-fill-on-export\",false,\"~:layout-gap-type\",\"~:multiple\",\"~:layout-padding\",[\"^ \",\"~:p1\",0,\"~:p2\",2,\"~:p3\",0,\"~:p4\",2],\"~:transform\",[\"~#matrix\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:rotation\",0,\"~:layout-wrap-type\",\"~:nowrap\",\"~:layout\",\"~:flex\",\"~:hide-in-viewer\",true,\"~:name\",\"_Utilities / Text / White\",\"~:layout-align-items\",\"~:start\",\"~:width\",42,\"~:layout-padding-type\",\"~:simple\",\"~:transforming\",false,\"~:type\",\"~:frame\",\"~:points\",[[\"~#point\",[\"^ \",\"~:x\",707.9999775886536,\"~:y\",535.9999959462525]],[\"^K\",[\"^ \",\"~:x\",749.9999775886536,\"~:y\",535.9999959462525]],[\"^K\",[\"^ \",\"~:x\",749.9999775886536,\"~:y\",551.9999959462525]],[\"^K\",[\"^ \",\"~:x\",707.9999775886536,\"~:y\",551.9999959462525]]],\"~:show-content\",true,\"~:layout-item-h-sizing\",\"~:auto\",\"~:proportion-lock\",false,\"~:layout-gap\",[\"^ \",\"~:row-gap\",0,\"~:column-gap\",6],\"~:transform-inverse\",[\"^:\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:page-id\",\"~u02e9633d-4ce7-80da-8007-736558496fa8\",\"~:layout-justify-content\",\"~:center\",\"~:id\",\"~u94eaebe4-addd-80d1-8007-79d5055d685d\",\"~:parent-id\",\"~u94eaebe4-addd-80d1-8007-79d5055d685c\",\"~:layout-flex-dir\",\"~:column\",\"~:layout-align-content\",\"~:stretch\",\"~:frame-id\",\"~u94eaebe4-addd-80d1-8007-79d5055d685c\",\"~:strokes\",[],\"~:x\",707.9999775886536,\"~:proportion\",1,\"~:selrect\",[\"~#rect\",[\"^ \",\"~:x\",707.9999775886536,\"~:y\",535.9999959462525,\"^D\",42,\"~:height\",16,\"~:x1\",707.9999775886536,\"~:y1\",535.9999959462525,\"~:x2\",749.9999775886536,\"~:y2\",551.9999959462525]],\"~:fills\",[],\"~:flip-x\",null,\"^16\",16,\"~:flip-y\",null,\"~:shapes\",[\"~u94eaebe4-addd-80d1-8007-79d5055d685e\"]]]",
"~u94eaebe4-addd-80d1-8007-79d5055d685e": "[\"~#shape\",[\"^ \",\"~:y\",536.9999959462527,\"~:transform\",[\"~#matrix\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:rotation\",0,\"~:grow-type\",\"~:auto-width\",\"~:index\",null,\"~:content\",[\"^ \",\"~:type\",\"root\",\"~:children\",[[\"^ \",\"^8\",\"paragraph-set\",\"^9\",[[\"^ \",\"~:line-height\",\"1.2\",\"~:path\",\"\",\"~:font-style\",\"normal\",\"^9\",[[\"^ \",\"^:\",\"1.2\",\"^;\",\"\",\"^<\",\"normal\",\"~:text-transform\",\"uppercase\",\"~:text-align\",\"left\",\"~:font-id\",\"gfont-work-sans\",\"~:font-size\",\"12\",\"~:font-weight\",\"500\",\"~:modified-at\",\"2024-06-04T14:15:09.786Z\",\"~:font-variant-id\",\"500\",\"~:text-decoration\",\"underline\",\"~:letter-spacing\",\"0\",\"~:fills\",[[\"^ \",\"~:fill-color\",\"#000000\",\"~:fill-color-ref-file\",\"~ucaa70d02-51e1-81ae-8007-735e7de3d7bc\",\"~:fill-opacity\",1,\"~:fill-color-ref-id\",\"~udfa92acf-7d18-8079-8003-baba8789d8af\"]],\"~:font-family\",\"Work Sans\",\"~:text\",\"Label\"]],\"^=\",\"uppercase\",\"^>\",\"center\",\"^?\",\"gfont-work-sans\",\"^@\",\"12\",\"^A\",\"500\",\"^8\",\"paragraph\",\"^B\",\"2024-06-04T14:15:09.786Z\",\"^C\",\"500\",\"^D\",\"underline\",\"^E\",\"0\",\"^F\",[[\"^ \",\"^G\",\"#000000\",\"^H\",\"~ucaa70d02-51e1-81ae-8007-735e7de3d7bc\",\"^I\",1,\"^J\",\"~udfa92acf-7d18-8079-8003-baba8789d8af\"]],\"^K\",\"Work Sans\"]]]],\"~:vertical-align\",\"center\",\"^F\",[[\"^ \",\"^G\",\"#000000\",\"^I\",1]]],\"~:hide-in-viewer\",true,\"~:name\",\"Input\",\"~:saved-component-root\",null,\"~:width\",38,\"^8\",\"^L\",\"~:points\",[[\"~#point\",[\"^ \",\"~:x\",709.9999775886536,\"~:y\",536.9999959462527]],[\"^S\",[\"^ \",\"~:x\",747.9999775886536,\"~:y\",536.9999959462527]],[\"^S\",[\"^ \",\"~:x\",747.9999775886536,\"~:y\",551.9999959462523]],[\"^S\",[\"^ \",\"~:x\",709.9999775886536,\"~:y\",551.9999959462527]]],\"~:layout-item-h-sizing\",\"~:fix\",\"~:transform-inverse\",[\"^2\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:page-id\",\"~u02e9633d-4ce7-80da-8007-736558496fa8\",\"~:id\",\"~u94eaebe4-addd-80d1-8007-79d5055d685e\",\"~:parent-id\",\"~u94eaebe4-addd-80d1-8007-79d5055d685d\",\"~:position-data\",[[\"^ \",\"~:y\",551.3400268554688,\"^:\",\"1.2\",\"^<\",\"normal\",\"^=\",\"uppercase\",\"^>\",\"left\",\"^?\",\"sourcesanspro\",\"^@\",\"12\",\"^A\",\"500\",\"~:text-direction\",\"ltr\",\"^Q\",37.93994140625,\"^C\",\"regular\",\"^D\",\"underline\",\"^E\",\"0\",\"~:x\",710.030029296875,\"^F\",[[\"^ \",\"^G\",\"#000000\",\"^H\",\"~ucaa70d02-51e1-81ae-8007-735e7de3d7bc\",\"^I\",1,\"^J\",\"~udfa92acf-7d18-8079-8003-baba8789d8af\"]],\"~:direction\",\"ltr\",\"^K\",\"Work Sans\",\"~:height\",14.08001708984375,\"^L\",\"Label\"]],\"~:frame-id\",\"~u94eaebe4-addd-80d1-8007-79d5055d685d\",\"~:strokes\",[],\"~:x\",709.9999775886536,\"~:selrect\",[\"~#rect\",[\"^ \",\"~:x\",709.9999775886536,\"~:y\",536.9999959462527,\"^Q\",38,\"^11\",15,\"~:x1\",709.9999775886536,\"~:y1\",536.9999959462527,\"~:x2\",747.9999775886536,\"~:y2\",551.9999959462527]],\"^F\",[],\"~:flip-x\",null,\"^11\",15,\"~:flip-y\",null]]"
"~u00000000-0000-0000-0000-000000000000": "[\"~#shape\",[\"^ \",\"~:y\",0,\"~:hide-fill-on-export\",false,\"~:transform\",[\"~#matrix\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:rotation\",0,\"~:name\",\"Root Frame\",\"~:width\",0.01,\"~:type\",\"~:frame\",\"~:points\",[[\"~#point\",[\"^ \",\"~:x\",0.0,\"~:y\",0.0]],[\"^:\",[\"^ \",\"~:x\",0.01,\"~:y\",0.0]],[\"^:\",[\"^ \",\"~:x\",0.01,\"~:y\",0.01]],[\"^:\",[\"^ \",\"~:x\",0.0,\"~:y\",0.01]]],\"~:r2\",0,\"~:proportion-lock\",false,\"~:transform-inverse\",[\"^3\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:page-id\",\"~u02e9633d-4ce7-80da-8007-736558496fa8\",\"~:r3\",0,\"~:r1\",0,\"~:id\",\"~u00000000-0000-0000-0000-000000000000\",\"~:parent-id\",\"~u00000000-0000-0000-0000-000000000000\",\"~:frame-id\",\"~u00000000-0000-0000-0000-000000000000\",\"~:strokes\",[],\"~:x\",0,\"~:proportion\",1.0,\"~:r4\",0,\"~:selrect\",[\"~#rect\",[\"^ \",\"~:x\",0,\"~:y\",0,\"^6\",0.01,\"~:height\",0.01,\"~:x1\",0,\"~:y1\",0,\"~:x2\",0.01,\"~:y2\",0.01]],\"~:fills\",[[\"^ \",\"~:fill-color\",\"#FFFFFF\",\"~:fill-opacity\",1]],\"~:flip-x\",null,\"^I\",0.01,\"~:flip-y\",null,\"~:shapes\",[\"~u94eaebe4-addd-80d1-8007-79d50980078e\",\"~u94eaebe4-addd-80d1-8007-79d508a9dc2f\",\"~u94eaebe4-addd-80d1-8007-79d5055d6859\",\"~u77c71dba-32ee-804c-8007-736561cf857f\",\"~u9299427e-8172-80bb-8007-90e7059421c0\",\"~u9299427e-8172-80bb-8007-90e71cbb9fea\",\"~u9299427e-8172-80bb-8007-90e71fba0f7d\",\"~u9299427e-8172-80bb-8007-90e72469bf8c\"]]]",
"~u9299427e-8172-80bb-8007-90e71fba0f82": "[\"~#shape\",[\"^ \",\"~:y\",210.0000271241638,\"~:transform\",[\"~#matrix\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:rotation\",null,\"~:index\",null,\"~:name\",\"base-background\",\"~:width\",24,\"~:type\",\"~:rect\",\"~:svg-attrs\",[\"^ \",\"~:fill\",\"none\",\"~:stroke-linejoin\",\"round\",\"~:stroke-linecap\",\"round\",\"~:id\",\"base-background\"],\"~:points\",[[\"~#point\",[\"^ \",\"~:x\",1140,\"~:y\",210.0000271241638]],[\"^?\",[\"^ \",\"~:x\",1164,\"~:y\",210.0000271241638]],[\"^?\",[\"^ \",\"~:x\",1164,\"~:y\",234.0000271241638]],[\"^?\",[\"^ \",\"~:x\",1140,\"~:y\",234.0000271241638]]],\"~:shape-ref\",\"~u9299427e-8172-80bb-8007-90e7059421c5\",\"~:proportion-lock\",false,\"~:transform-inverse\",[\"^2\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:page-id\",\"~u7c4e00d1-1f97-8161-8007-8f7861f33b60\",\"~:hidden\",true,\"^=\",\"~u9299427e-8172-80bb-8007-90e71fba0f82\",\"~:parent-id\",\"~u9299427e-8172-80bb-8007-90e71fba0f81\",\"~:svg-viewbox\",[\"^ \",\"~:y\",0,\"~:y1\",0,\"^6\",24,\"~:x\",0,\"~:x1\",0,\"~:y2\",24,\"~:x2\",24,\"~:height\",24],\"~:svg-defs\",[\"^ \"],\"~:frame-id\",\"~u9299427e-8172-80bb-8007-90e71fba0f81\",\"~:strokes\",[[\"^ \",\"~:stroke-style\",\"~:solid\",\"~:stroke-color\",\"#ffffff\",\"~:stroke-opacity\",1,\"~:stroke-alignment\",\"~:inner\",\"~:stroke-width\",2]],\"~:x\",1140,\"~:proportion\",1,\"~:selrect\",[\"~#rect\",[\"^ \",\"~:x\",1140,\"~:y\",210.0000271241638,\"^6\",24,\"^K\",24,\"^H\",1140,\"^G\",210.0000271241638,\"^J\",1164,\"^I\",234.0000271241638]],\"~:fills\",[],\"~:flip-x\",null,\"^K\",24,\"~:flip-y\",null]]",
"~u9299427e-8172-80bb-8007-90e7059421c2": "[\"~#shape\",[\"^ \",\"~:y\",198.00002998518676,\"~:hide-fill-on-export\",false,\"~:layout-item-absolute\",true,\"~:layout-gap-type\",\"~:multiple\",\"~:layout-padding\",[\"^ \",\"~:p1\",0,\"~:p2\",0,\"~:p3\",0,\"~:p4\",0],\"~:transform\",[\"~#matrix\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:rotation\",0,\"~:layout-wrap-type\",\"~:nowrap\",\"~:grow-type\",\"~:fixed\",\"~:layout\",\"~:flex\",\"~:hide-in-viewer\",true,\"~:name\",\"add-favorites\",\"~:layout-align-items\",\"~:center\",\"~:width\",48,\"~:layout-padding-type\",\"~:simple\",\"~:type\",\"~:frame\",\"~:touched\",[\"~#set\",[\"^2\",\"~:layout-item-z-index\"]],\"~:points\",[[\"~#point\",[\"^ \",\"~:x\",792,\"~:y\",198.00002998518676]],[\"^P\",[\"^ \",\"~:x\",840,\"~:y\",198.00002998518676]],[\"^P\",[\"^ \",\"~:x\",840,\"~:y\",246.00002426314086]],[\"^P\",[\"^ \",\"~:x\",792,\"~:y\",246.00002426314086]]],\"~:r2\",50,\"~:shape-ref\",\"~uc8b014fe-f285-8021-8007-8ea400bd9406\",\"~:proportion-lock\",false,\"~:layout-gap\",[\"^ \",\"~:row-gap\",0,\"~:column-gap\",0],\"~:transform-inverse\",[\"^;\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:page-id\",\"~u7c4e00d1-1f97-8161-8007-8f7861f33b60\",\"~:r3\",50,\"~:layout-justify-content\",\"^F\",\"~:r1\",50,\"~:id\",\"~u9299427e-8172-80bb-8007-90e7059421c2\",\"~:parent-id\",\"~u9299427e-8172-80bb-8007-90e7059421c0\",\"~:layout-flex-dir\",\"~:row\",\"~:applied-tokens\",[\"^ \",\"~:fill\",\"color.bg.default\"],\"~:layout-align-content\",\"~:stretch\",\"~:component-id\",\"~uc8b014fe-f285-8021-8007-8ea447a0bc30\",\"~:frame-id\",\"~u9299427e-8172-80bb-8007-90e7059421c0\",\"~:strokes\",[],\"~:x\",792,\"~:proportion\",1,\"~:r4\",50,\"~:selrect\",[\"~#rect\",[\"^ \",\"~:x\",792,\"~:y\",198.00002998518676,\"^G\",48,\"~:height\",47.9999942779541,\"~:x1\",792,\"~:y1\",198.00002998518676,\"~:x2\",840,\"~:y2\",246.00002426314086]],\"~:fills\",[[\"^ \",\"~:fill-color\",\"#ffffff\",\"~:fill-opacity\",0.3]],\"~:flip-x\",null,\"^1?\",47.9999942779541,\"~:component-file\",\"~ud0eb4518-f33d-81e1-8007-8fe418fea255\",\"~:flip-y\",null,\"~:shapes\",[\"~u9299427e-8172-80bb-8007-90e7059421c4\"]]]",
"~u9299427e-8172-80bb-8007-90e71fba0f83": "[\"~#shape\",[\"^ \",\"~:y\",212.99997181105346,\"~:hide-fill-on-export\",false,\"~:transform\",[\"~#matrix\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:rotation\",0,\"~:hide-in-viewer\",true,\"~:name\",\"svg-path\",\"~:width\",20,\"~:type\",\"~:frame\",\"~:points\",[[\"~#point\",[\"^ \",\"~:x\",1142,\"~:y\",212.99997181105346]],[\"^;\",[\"^ \",\"~:x\",1162,\"~:y\",212.99997181105346]],[\"^;\",[\"^ \",\"~:x\",1162,\"~:y\",230.99997181105346]],[\"^;\",[\"^ \",\"~:x\",1142,\"~:y\",230.99997181105346]]],\"~:r2\",0,\"~:shape-ref\",\"~u9299427e-8172-80bb-8007-90e7059421c6\",\"~:show-content\",true,\"~:proportion-lock\",false,\"~:transform-inverse\",[\"^3\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:page-id\",\"~u7c4e00d1-1f97-8161-8007-8f7861f33b60\",\"~:r3\",0,\"~:r1\",0,\"~:id\",\"~u9299427e-8172-80bb-8007-90e71fba0f83\",\"~:parent-id\",\"~u9299427e-8172-80bb-8007-90e71fba0f81\",\"~:applied-tokens\",[\"^ \"],\"~:component-id\",\"~uc8b014fe-f285-8021-8007-8ea4f64a1c9b\",\"~:frame-id\",\"~u9299427e-8172-80bb-8007-90e71fba0f81\",\"~:strokes\",[],\"~:x\",1142,\"~:proportion\",1,\"~:r4\",0,\"~:selrect\",[\"~#rect\",[\"^ \",\"~:x\",1142,\"~:y\",212.99997181105346,\"^7\",20,\"~:height\",18,\"~:x1\",1142,\"~:y1\",212.99997181105346,\"~:x2\",1162,\"~:y2\",230.99997181105346]],\"~:fills\",[],\"~:flip-x\",null,\"^N\",18,\"~:component-file\",\"~ud0eb4518-f33d-81e1-8007-8fe418fea255\",\"~:flip-y\",null,\"~:shapes\",[\"~u9299427e-8172-80bb-8007-90e71fba0f84\"]]]",
"~u9299427e-8172-80bb-8007-90e7059421c3": "[\"~#shape\",[\"^ \",\"~:y\",192.00001259178498,\"~:transform\",[\"~#matrix\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:rotation\",0,\"~:name\",\"patinegro\",\"~:width\",264.80230943863717,\"~:type\",\"~:rect\",\"~:points\",[[\"~#point\",[\"^ \",\"~:x\",579.9999793759137,\"~:y\",192.00001259178498]],[\"^9\",[\"^ \",\"~:x\",844.8022888145506,\"~:y\",192.00001259178498]],[\"^9\",[\"^ \",\"~:x\",844.8022888145506,\"~:y\",388.1131514739925]],[\"^9\",[\"^ \",\"~:x\",579.9999793759137,\"~:y\",388.1131514739925]]],\"~:r2\",0,\"~:proportion-lock\",true,\"~:transform-inverse\",[\"^2\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:page-id\",\"~u7c4e00d1-1f97-8161-8007-8f7861f33b60\",\"~:r3\",0,\"~:r1\",0,\"~:id\",\"~u9299427e-8172-80bb-8007-90e7059421c3\",\"~:parent-id\",\"~u9299427e-8172-80bb-8007-90e7059421c1\",\"~:frame-id\",\"~u9299427e-8172-80bb-8007-90e7059421c1\",\"~:strokes\",[],\"~:x\",579.9999793759134,\"~:proportion\",1.3487940630797774,\"~:r4\",0,\"~:selrect\",[\"~#rect\",[\"^ \",\"~:x\",579.9999793759134,\"~:y\",192.00001259178498,\"^5\",264.80230943863717,\"~:height\",196.11313888220752,\"~:x1\",579.9999793759134,\"~:y1\",192.00001259178498,\"~:x2\",844.8022888145506,\"~:y2\",388.1131514739925]],\"~:fills\",[[\"^ \",\"~:fill-color\",\"#b73d3d\",\"~:fill-opacity\",1]],\"~:flip-x\",null,\"^H\",196.11313888220752,\"~:flip-y\",null]]",
"~u9299427e-8172-80bb-8007-90e71fba0f80": "[\"~#shape\",[\"^ \",\"~:y\",192.00001259178498,\"~:transform\",[\"~#matrix\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:rotation\",0,\"~:name\",\"patinegro\",\"~:width\",264.80230943863717,\"~:type\",\"~:rect\",\"~:points\",[[\"~#point\",[\"^ \",\"~:x\",915.9999793759137,\"~:y\",192.00001259178498]],[\"^9\",[\"^ \",\"~:x\",1180.8022888145506,\"~:y\",192.00001259178498]],[\"^9\",[\"^ \",\"~:x\",1180.8022888145506,\"~:y\",388.1131514739925]],[\"^9\",[\"^ \",\"~:x\",915.9999793759137,\"~:y\",388.1131514739925]]],\"~:r2\",0,\"~:shape-ref\",\"~u9299427e-8172-80bb-8007-90e7059421c3\",\"~:proportion-lock\",true,\"~:transform-inverse\",[\"^2\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:page-id\",\"~u7c4e00d1-1f97-8161-8007-8f7861f33b60\",\"~:r3\",0,\"~:r1\",0,\"~:id\",\"~u9299427e-8172-80bb-8007-90e71fba0f80\",\"~:parent-id\",\"~u9299427e-8172-80bb-8007-90e71fba0f7e\",\"~:frame-id\",\"~u9299427e-8172-80bb-8007-90e71fba0f7e\",\"~:strokes\",[],\"~:x\",915.9999793759134,\"~:proportion\",1.3487940630797774,\"~:r4\",0,\"~:selrect\",[\"~#rect\",[\"^ \",\"~:x\",915.9999793759134,\"~:y\",192.00001259178498,\"^5\",264.80230943863717,\"~:height\",196.11313888220752,\"~:x1\",915.9999793759134,\"~:y1\",192.00001259178498,\"~:x2\",1180.8022888145506,\"~:y2\",388.1131514739925]],\"~:fills\",[[\"^ \",\"~:fill-color\",\"#b73d3d\",\"~:fill-opacity\",1]],\"~:flip-x\",null,\"^I\",196.11313888220752,\"~:flip-y\",null]]",
"~u9299427e-8172-80bb-8007-90e7059421c0": "[\"~#shape\",[\"^ \",\"~:y\",191.99998474121094,\"~:hide-fill-on-export\",false,\"~:layout-gap-type\",\"~:multiple\",\"~:layout-padding\",[\"^ \",\"~:p1\",0,\"~:p2\",0,\"~:p3\",0,\"~:p4\",0],\"~:transform\",[\"~#matrix\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:rotation\",0,\"~:layout-wrap-type\",\"~:nowrap\",\"~:grow-type\",\"~:fixed\",\"~:layout\",\"~:flex\",\"~:hide-in-viewer\",true,\"~:name\",\"card-img / patinegro\",\"~:layout-align-items\",\"~:start\",\"~:variant-name\",\"patinegro\",\"~:width\",265,\"~:layout-padding-type\",\"~:simple\",\"~:type\",\"~:frame\",\"~:points\",[[\"~#point\",[\"^ \",\"~:x\",580,\"~:y\",191.99998474121094]],[\"^M\",[\"^ \",\"~:x\",845,\"~:y\",191.99998474121094]],[\"^M\",[\"^ \",\"~:x\",845,\"~:y\",369.99997875688996]],[\"^M\",[\"^ \",\"~:x\",580,\"~:y\",369.99997875688996]]],\"~:r2\",20,\"~:component-root\",true,\"~:proportion-lock\",false,\"~:layout-gap\",[\"^ \",\"~:row-gap\",0,\"~:column-gap\",0],\"~:transform-inverse\",[\"^:\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:page-id\",\"~u7c4e00d1-1f97-8161-8007-8f7861f33b60\",\"~:layout-item-v-sizing\",\"~:fix\",\"~:r3\",20,\"~:layout-justify-content\",\"^E\",\"~:r1\",20,\"~:id\",\"~u9299427e-8172-80bb-8007-90e7059421c0\",\"~:parent-id\",\"~u00000000-0000-0000-0000-000000000000\",\"~:layout-flex-dir\",\"~:column\",\"~:layout-align-content\",\"~:stretch\",\"~:component-id\",\"~u9299427e-8172-80bb-8007-90e7059a83e2\",\"~:frame-id\",\"~u00000000-0000-0000-0000-000000000000\",\"~:strokes\",[],\"~:x\",580,\"~:main-instance\",true,\"~:proportion\",1,\"~:r4\",20,\"~:selrect\",[\"~#rect\",[\"^ \",\"~:x\",580,\"~:y\",191.99998474121094,\"^G\",265,\"~:height\",177.99999401567902,\"~:x1\",580,\"~:y1\",191.99998474121094,\"~:x2\",845,\"~:y2\",369.99997875688996]],\"~:fills\",[[\"^ \",\"~:fill-color\",\"#FFFFFF\",\"~:fill-opacity\",1]],\"~:flip-x\",null,\"^1=\",177.99999401567902,\"~:component-file\",\"~u31fe2e21-73e7-80f3-8007-73894fb58240\",\"~:flip-y\",null,\"~:shapes\",[\"~u9299427e-8172-80bb-8007-90e7059421c1\",\"~u9299427e-8172-80bb-8007-90e7059421c2\"]]]",
"~u9299427e-8172-80bb-8007-90e71fba0f81": "[\"~#shape\",[\"^ \",\"~:y\",209.99999660658568,\"~:rx\",0,\"~:transform\",[\"~#matrix\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:rotation\",null,\"~:index\",null,\"~:hide-in-viewer\",true,\"~:name\",\"heart\",\"~:width\",24,\"~:type\",\"~:frame\",\"~:svg-attrs\",[\"^ \",\"^8\",\"24\",\"~:height\",\"24\"],\"~:points\",[[\"~#point\",[\"^ \",\"~:x\",1140,\"~:y\",209.99999660658568]],[\"^>\",[\"^ \",\"~:x\",1164,\"~:y\",209.99999660658568]],[\"^>\",[\"^ \",\"~:x\",1164,\"~:y\",233.99999660658568]],[\"^>\",[\"^ \",\"~:x\",1140,\"~:y\",233.99999660658568]]],\"~:r2\",0,\"~:shape-ref\",\"~u9299427e-8172-80bb-8007-90e7059421c4\",\"~:show-content\",true,\"~:proportion-lock\",false,\"~:transform-inverse\",[\"^3\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:page-id\",\"~u7c4e00d1-1f97-8161-8007-8f7861f33b60\",\"~:r3\",0,\"~:constraints-v\",\"~:top\",\"~:constraints-h\",\"~:left\",\"~:r1\",0,\"~:id\",\"~u9299427e-8172-80bb-8007-90e71fba0f81\",\"~:parent-id\",\"~u9299427e-8172-80bb-8007-90e71fba0f7f\",\"~:frame-id\",\"~u9299427e-8172-80bb-8007-90e71fba0f7f\",\"~:strokes\",[],\"~:x\",1140,\"~:proportion\",1,\"~:r4\",0,\"~:selrect\",[\"~#rect\",[\"^ \",\"~:x\",1140,\"~:y\",209.99999660658568,\"^8\",24,\"^<\",24,\"~:x1\",1140,\"~:y1\",209.99999660658568,\"~:x2\",1164,\"~:y2\",233.99999660658568]],\"~:fills\",[],\"~:flip-x\",null,\"~:ry\",0,\"^<\",24,\"~:flip-y\",null,\"~:shapes\",[\"~u9299427e-8172-80bb-8007-90e71fba0f82\",\"~u9299427e-8172-80bb-8007-90e71fba0f83\"]]]",
"~u9299427e-8172-80bb-8007-90e7059421c1": "[\"~#shape\",[\"^ \",\"~:y\",191.99999475401955,\"~:hide-fill-on-export\",false,\"~:transform\",[\"~#matrix\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:rotation\",0,\"~:hide-in-viewer\",true,\"~:name\",\"img-city\",\"~:width\",265,\"~:type\",\"~:frame\",\"~:points\",[[\"~#point\",[\"^ \",\"~:x\",580,\"~:y\",191.99999475401978]],[\"^;\",[\"^ \",\"~:x\",845,\"~:y\",191.99999475401978]],[\"^;\",[\"^ \",\"~:x\",845,\"~:y\",369.9899634401968]],[\"^;\",[\"^ \",\"~:x\",580,\"~:y\",369.9899634401968]]],\"~:r2\",0,\"~:layout-item-h-sizing\",\"~:fill\",\"~:proportion-lock\",false,\"~:transform-inverse\",[\"^3\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:page-id\",\"~u7c4e00d1-1f97-8161-8007-8f7861f33b60\",\"~:layout-item-v-sizing\",\"^>\",\"~:r3\",0,\"~:r1\",0,\"~:id\",\"~u9299427e-8172-80bb-8007-90e7059421c1\",\"~:parent-id\",\"~u9299427e-8172-80bb-8007-90e7059421c0\",\"~:frame-id\",\"~u9299427e-8172-80bb-8007-90e7059421c0\",\"~:strokes\",[],\"~:x\",580,\"~:proportion\",1,\"~:r4\",0,\"~:selrect\",[\"~#rect\",[\"^ \",\"~:x\",580,\"~:y\",191.99999475401955,\"^7\",265,\"~:height\",177.989968686177,\"~:x1\",580,\"~:y1\",191.99999475401955,\"~:x2\",845,\"~:y2\",369.98996344019656]],\"~:fills\",[[\"^ \",\"~:fill-color\",\"#FFFFFF\",\"~:fill-opacity\",1]],\"~:flip-x\",null,\"^M\",177.989968686177,\"~:flip-y\",null,\"~:shapes\",[\"~u9299427e-8172-80bb-8007-90e7059421c3\"]]]",
"~u77c71dba-32ee-804c-8007-736561cff457": "[\"~#shape\",[\"^ \",\"~:y\",222.00000357564704,\"~:rx\",8,\"~:transform\",[\"~#matrix\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:rotation\",0,\"~:grow-type\",\"~:fixed\",\"~:hide-in-viewer\",false,\"~:name\",\"Rectangle\",\"~:width\",80,\"~:transforming\",false,\"~:type\",\"~:rect\",\"~:points\",[[\"~#point\",[\"^ \",\"~:x\",379.0000081062317,\"~:y\",222.00000357564704]],[\"^>\",[\"^ \",\"~:x\",459.0000081062317,\"~:y\",222.00000357564704]],[\"^>\",[\"^ \",\"~:x\",459.0000081062317,\"~:y\",302.00000357564704]],[\"^>\",[\"^ \",\"~:x\",379.0000081062317,\"~:y\",302.00000357564704]]],\"~:r2\",8,\"~:proportion-lock\",false,\"~:transform-inverse\",[\"^3\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:page-id\",\"~u02e9633d-4ce7-80da-8007-736558496fa8\",\"~:r3\",8,\"~:r1\",8,\"~:id\",\"~u77c71dba-32ee-804c-8007-736561cff457\",\"~:parent-id\",\"~u77c71dba-32ee-804c-8007-736561cf8584\",\"~:frame-id\",\"~u77c71dba-32ee-804c-8007-736561cf8584\",\"~:strokes\",[],\"~:x\",379.0000081062317,\"~:proportion\",1,\"~:r4\",8,\"~:selrect\",[\"~#rect\",[\"^ \",\"~:x\",379.0000081062317,\"~:y\",222.00000357564704,\"^9\",80,\"~:height\",80,\"~:x1\",379.0000081062317,\"~:y1\",222.00000357564704,\"~:x2\",459.0000081062317,\"~:y2\",302.00000357564704]],\"~:fills\",[[\"^ \",\"~:fill-color\",\"#e8e9ea\",\"~:fill-opacity\",1]],\"~:flip-x\",null,\"~:ry\",8,\"^M\",80,\"~:flip-y\",null]]",
"~u9299427e-8172-80bb-8007-90e7059421c6": "[\"~#shape\",[\"^ \",\"~:y\",212.99997181105346,\"~:hide-fill-on-export\",false,\"~:transform\",[\"~#matrix\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:rotation\",0,\"~:hide-in-viewer\",true,\"~:name\",\"svg-path\",\"~:width\",20,\"~:type\",\"~:frame\",\"~:points\",[[\"~#point\",[\"^ \",\"~:x\",806,\"~:y\",212.99997181105346]],[\"^;\",[\"^ \",\"~:x\",826,\"~:y\",212.99997181105346]],[\"^;\",[\"^ \",\"~:x\",826,\"~:y\",230.99997181105346]],[\"^;\",[\"^ \",\"~:x\",806,\"~:y\",230.99997181105346]]],\"~:r2\",0,\"~:shape-ref\",\"~uc8b014fe-f285-8021-8007-8ea51856a422\",\"~:show-content\",true,\"~:proportion-lock\",false,\"~:transform-inverse\",[\"^3\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:page-id\",\"~u7c4e00d1-1f97-8161-8007-8f7861f33b60\",\"~:r3\",0,\"~:r1\",0,\"~:id\",\"~u9299427e-8172-80bb-8007-90e7059421c6\",\"~:parent-id\",\"~u9299427e-8172-80bb-8007-90e7059421c4\",\"~:applied-tokens\",[\"^ \"],\"~:component-id\",\"~uc8b014fe-f285-8021-8007-8ea4f64a1c9b\",\"~:frame-id\",\"~u9299427e-8172-80bb-8007-90e7059421c4\",\"~:strokes\",[],\"~:x\",806,\"~:proportion\",1,\"~:r4\",0,\"~:selrect\",[\"~#rect\",[\"^ \",\"~:x\",806,\"~:y\",212.99997181105346,\"^7\",20,\"~:height\",18,\"~:x1\",806,\"~:y1\",212.99997181105346,\"~:x2\",826,\"~:y2\",230.99997181105346]],\"~:fills\",[],\"~:flip-x\",null,\"^N\",18,\"~:component-file\",\"~ud0eb4518-f33d-81e1-8007-8fe418fea255\",\"~:flip-y\",null,\"~:shapes\",[\"~u9299427e-8172-80bb-8007-90e705944588\"]]]",
"~u94eaebe4-addd-80d1-8007-79d508aa2885": "[\"~#shape\",[\"^ \",\"~:y\",437.999988316858,\"~:rx\",8,\"~:transform\",[\"~#matrix\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:rotation\",0,\"~:grow-type\",\"~:fixed\",\"~:hide-in-viewer\",false,\"~:name\",\"Rectangle\",\"~:width\",80,\"~:transforming\",false,\"~:type\",\"~:rect\",\"~:points\",[[\"~#point\",[\"^ \",\"~:x\",295.0000081062317,\"~:y\",437.999988316858]],[\"^>\",[\"^ \",\"~:x\",375.0000081062317,\"~:y\",437.999988316858]],[\"^>\",[\"^ \",\"~:x\",375.0000081062317,\"~:y\",517.999988316858]],[\"^>\",[\"^ \",\"~:x\",295.0000081062317,\"~:y\",517.999988316858]]],\"~:r2\",8,\"~:proportion-lock\",false,\"~:transform-inverse\",[\"^3\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:page-id\",\"~u02e9633d-4ce7-80da-8007-736558496fa8\",\"~:r3\",8,\"~:r1\",8,\"~:id\",\"~u94eaebe4-addd-80d1-8007-79d508aa2885\",\"~:parent-id\",\"~u94eaebe4-addd-80d1-8007-79d508a9dc30\",\"~:frame-id\",\"~u94eaebe4-addd-80d1-8007-79d508a9dc30\",\"~:strokes\",[],\"~:x\",295.0000081062317,\"~:proportion\",1,\"~:r4\",8,\"~:selrect\",[\"~#rect\",[\"^ \",\"~:x\",295.0000081062317,\"~:y\",437.999988316858,\"^9\",80,\"~:height\",80,\"~:x1\",295.0000081062317,\"~:y1\",437.999988316858,\"~:x2\",375.0000081062317,\"~:y2\",517.999988316858]],\"~:fills\",[[\"^ \",\"~:fill-color\",\"#e8e9ea\",\"~:fill-opacity\",1]],\"~:flip-x\",null,\"~:ry\",8,\"^M\",80,\"~:flip-y\",null]]",
"~u9299427e-8172-80bb-8007-90e71fba0f84": "[\"~#shape\",[\"^ \",\"~:y\",null,\"~:stroke-cap-start\",\"round\",\"~:transform\",[\"~#matrix\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:rotation\",null,\"~:index\",null,\"~:content\",[\"~#penpot/path-data\",\"~bAQAAAAAAAAAAAAAAAAAAAAAAAAAA4JBE/P9fQwMAAACuD5FE/IleQwBAkUT8yVxDAECRRPx/WkMDAAAAAECRRHx2V0M08ZBE/P9UQwCQkET8/1RDAwAAAK5XkET8/1RDADCQRPx/VUMAAJBE/P9WQwMAAAAA0I9E/H9VQ1Koj0T8/1RDAHCPRPz/VEMDAAAAzA6PRPz/VEMAwI5EfHZXQwDAjkT8f1pDAwAAAADAjkT8zFxDAPCORPyMXkMAII9E/P9fQwIAAAAAAAAAAAAAAAAAAAAAAAAAAACQRPz/ZkMCAAAAAAAAAAAAAAAAAAAAAAAAAADgkET8/19D\"],\"~:name\",\"svg-path\",\"~:width\",null,\"~:type\",\"~:path\",\"~:svg-attrs\",[\"^ \",\"~:fill\",\"none\",\"~:stroke-linecap\",\"round\",\"~:stroke-linejoin\",\"round\"],\"~:points\",[[\"~#point\",[\"^ \",\"~:x\",1142,\"~:y\",212.99997181105346]],[\"^A\",[\"^ \",\"~:x\",1162,\"~:y\",212.99997181105346]],[\"^A\",[\"^ \",\"~:x\",1162,\"~:y\",230.99997181105346]],[\"^A\",[\"^ \",\"~:x\",1142,\"~:y\",230.99997181105346]]],\"~:shape-ref\",\"~u9299427e-8172-80bb-8007-90e705944588\",\"~:proportion-lock\",false,\"~:stroke-cap-end\",\"round\",\"~:transform-inverse\",[\"^3\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:page-id\",\"~u7c4e00d1-1f97-8161-8007-8f7861f33b60\",\"~:constraints-v\",\"~:scale\",\"~:svg-transform\",[\"^ \",\"~:a\",1,\"~:b\",0,\"~:c\",0,\"~:d\",1,\"~:e\",0,\"~:f\",0],\"~:constraints-h\",\"^H\",\"~:id\",\"~u9299427e-8172-80bb-8007-90e71fba0f84\",\"~:parent-id\",\"~u9299427e-8172-80bb-8007-90e71fba0f83\",\"~:svg-viewbox\",[\"^ \",\"~:y\",3,\"~:y1\",3,\"^9\",20,\"~:x\",2,\"~:x1\",2,\"~:y2\",21,\"~:x2\",22,\"~:height\",18],\"~:applied-tokens\",[\"^ \",\"~:stroke-color\",\"color.icon.default\"],\"~:svg-defs\",[\"^ \"],\"~:frame-id\",\"~u9299427e-8172-80bb-8007-90e71fba0f83\",\"~:strokes\",[[\"^ \",\"~:stroke-style\",\"~:solid\",\"~:stroke-alignment\",\"~:inner\",\"~:stroke-width\",2,\"^T\",\"#ffffff\",\"~:stroke-opacity\",1]],\"~:x\",null,\"~:proportion\",1,\"~:selrect\",[\"~#rect\",[\"^ \",\"~:x\",1142,\"~:y\",212.99997181105346,\"^9\",20,\"^R\",18,\"^O\",1142,\"^N\",212.99997181105346,\"^Q\",1162,\"^P\",230.99997181105346]],\"~:fills\",[],\"~:flip-x\",null,\"^R\",null,\"~:flip-y\",null]]",
"~u94eaebe4-addd-80d1-8007-79d508aa2886": "[\"~#shape\",[\"^ \",\"~:y\",461.999988316858,\"~:hide-fill-on-export\",false,\"~:layout-gap-type\",\"~:multiple\",\"~:rx\",8,\"~:layout-padding\",[\"^ \",\"~:p1\",8,\"~:p2\",12,\"~:p3\",8,\"~:p4\",12],\"~:transform\",[\"~#matrix\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:rotation\",0,\"~:layout-wrap-type\",\"~:nowrap\",\"~:layout\",\"~:flex\",\"~:hide-in-viewer\",true,\"~:name\",\"Dark / Button / Primary / Text / Default\",\"~:layout-align-items\",\"~:center\",\"~:width\",66,\"~:layout-padding-type\",\"~:simple\",\"~:type\",\"~:frame\",\"~:points\",[[\"~#point\",[\"^ \",\"~:x\",302.0000081062317,\"~:y\",461.999988316858]],[\"^K\",[\"^ \",\"~:x\",368.0000081062317,\"~:y\",461.999988316858]],[\"^K\",[\"^ \",\"~:x\",368.0000081062317,\"~:y\",493.999988316858]],[\"^K\",[\"^ \",\"~:x\",302.0000081062317,\"~:y\",493.999988316858]]],\"~:r2\",8,\"~:show-content\",true,\"~:proportion-lock\",false,\"~:layout-gap\",[\"^ \",\"~:row-gap\",4,\"~:column-gap\",4],\"~:transform-inverse\",[\"^;\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:page-id\",\"~u02e9633d-4ce7-80da-8007-736558496fa8\",\"~:r3\",8,\"~:layout-justify-content\",\"^D\",\"~:r1\",8,\"~:id\",\"~u94eaebe4-addd-80d1-8007-79d508aa2886\",\"~:parent-id\",\"~u94eaebe4-addd-80d1-8007-79d508a9dc30\",\"~:layout-flex-dir\",\"~:row\",\"~:layout-align-content\",\"~:stretch\",\"~:frame-id\",\"~u94eaebe4-addd-80d1-8007-79d508a9dc30\",\"~:strokes\",[],\"~:x\",302.0000081062317,\"~:proportion\",1,\"~:r4\",8,\"~:selrect\",[\"~#rect\",[\"^ \",\"~:x\",302.0000081062317,\"~:y\",461.999988316858,\"^E\",66,\"~:height\",32,\"~:x1\",302.0000081062317,\"~:y1\",461.999988316858,\"~:x2\",368.0000081062317,\"~:y2\",493.999988316858]],\"~:fills\",[[\"^ \",\"~:fill-color\",\"#7efff5\",\"~:fill-opacity\",1]],\"~:flip-x\",null,\"~:ry\",8,\"^17\",32,\"~:flip-y\",null,\"~:shapes\",[\"~u94eaebe4-addd-80d1-8007-79d508aa2887\"]]]",
"~u9299427e-8172-80bb-8007-90e7059421c4": "[\"~#shape\",[\"^ \",\"~:y\",209.99999660658568,\"~:rx\",0,\"~:transform\",[\"~#matrix\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:rotation\",null,\"~:index\",null,\"~:hide-in-viewer\",true,\"~:name\",\"heart\",\"~:width\",24,\"~:type\",\"~:frame\",\"~:svg-attrs\",[\"^ \",\"^8\",\"24\",\"~:height\",\"24\"],\"~:points\",[[\"~#point\",[\"^ \",\"~:x\",804,\"~:y\",209.99999660658568]],[\"^>\",[\"^ \",\"~:x\",828,\"~:y\",209.99999660658568]],[\"^>\",[\"^ \",\"~:x\",828,\"~:y\",233.99999660658568]],[\"^>\",[\"^ \",\"~:x\",804,\"~:y\",233.99999660658568]]],\"~:r2\",0,\"~:shape-ref\",\"~uc8b014fe-f285-8021-8007-8ea400bd9407\",\"~:show-content\",true,\"~:proportion-lock\",false,\"~:transform-inverse\",[\"^3\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:page-id\",\"~u7c4e00d1-1f97-8161-8007-8f7861f33b60\",\"~:r3\",0,\"~:constraints-v\",\"~:top\",\"~:constraints-h\",\"~:left\",\"~:r1\",0,\"~:id\",\"~u9299427e-8172-80bb-8007-90e7059421c4\",\"~:parent-id\",\"~u9299427e-8172-80bb-8007-90e7059421c2\",\"~:frame-id\",\"~u9299427e-8172-80bb-8007-90e7059421c2\",\"~:strokes\",[],\"~:x\",804,\"~:proportion\",1,\"~:r4\",0,\"~:selrect\",[\"~#rect\",[\"^ \",\"~:x\",804,\"~:y\",209.99999660658568,\"^8\",24,\"^<\",24,\"~:x1\",804,\"~:y1\",209.99999660658568,\"~:x2\",828,\"~:y2\",233.99999660658568]],\"~:fills\",[],\"~:flip-x\",null,\"~:ry\",0,\"^<\",24,\"~:flip-y\",null,\"~:shapes\",[\"~u9299427e-8172-80bb-8007-90e7059421c5\",\"~u9299427e-8172-80bb-8007-90e7059421c6\"]]]",
"~u94eaebe4-addd-80d1-8007-79d508aa2887": "[\"~#shape\",[\"^ \",\"~:y\",469.999988316858,\"~:hide-fill-on-export\",false,\"~:layout-gap-type\",\"~:multiple\",\"~:layout-padding\",[\"^ \",\"~:p1\",0,\"~:p2\",2,\"~:p3\",0,\"~:p4\",2],\"~:transform\",[\"~#matrix\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:rotation\",0,\"~:layout-wrap-type\",\"~:nowrap\",\"~:layout\",\"~:flex\",\"~:hide-in-viewer\",true,\"~:name\",\"_Utilities / Text / White\",\"~:layout-align-items\",\"~:start\",\"~:width\",42,\"~:layout-padding-type\",\"~:simple\",\"~:transforming\",false,\"~:type\",\"~:frame\",\"~:points\",[[\"~#point\",[\"^ \",\"~:x\",314.0000081062317,\"~:y\",469.999988316858]],[\"^K\",[\"^ \",\"~:x\",356.0000081062317,\"~:y\",469.999988316858]],[\"^K\",[\"^ \",\"~:x\",356.0000081062317,\"~:y\",485.999988316858]],[\"^K\",[\"^ \",\"~:x\",314.0000081062317,\"~:y\",485.999988316858]]],\"~:show-content\",true,\"~:layout-item-h-sizing\",\"~:auto\",\"~:proportion-lock\",false,\"~:layout-gap\",[\"^ \",\"~:row-gap\",0,\"~:column-gap\",6],\"~:transform-inverse\",[\"^:\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:page-id\",\"~u02e9633d-4ce7-80da-8007-736558496fa8\",\"~:layout-justify-content\",\"~:center\",\"~:id\",\"~u94eaebe4-addd-80d1-8007-79d508aa2887\",\"~:parent-id\",\"~u94eaebe4-addd-80d1-8007-79d508aa2886\",\"~:layout-flex-dir\",\"~:column\",\"~:layout-align-content\",\"~:stretch\",\"~:frame-id\",\"~u94eaebe4-addd-80d1-8007-79d508aa2886\",\"~:strokes\",[],\"~:x\",314.0000081062317,\"~:proportion\",1,\"~:selrect\",[\"~#rect\",[\"^ \",\"~:x\",314.0000081062317,\"~:y\",469.999988316858,\"^D\",42,\"~:height\",16,\"~:x1\",314.0000081062317,\"~:y1\",469.999988316858,\"~:x2\",356.0000081062317,\"~:y2\",485.999988316858]],\"~:fills\",[],\"~:flip-x\",null,\"^16\",16,\"~:flip-y\",null,\"~:shapes\",[\"~u94eaebe4-addd-80d1-8007-79d508aa2888\"]]]",
"~u9299427e-8172-80bb-8007-90e7059421c5": "[\"~#shape\",[\"^ \",\"~:y\",210.0000271241638,\"~:transform\",[\"~#matrix\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:rotation\",null,\"~:index\",null,\"~:name\",\"base-background\",\"~:width\",24,\"~:type\",\"~:rect\",\"~:svg-attrs\",[\"^ \",\"~:fill\",\"none\",\"~:stroke-linejoin\",\"round\",\"~:stroke-linecap\",\"round\",\"~:id\",\"base-background\"],\"~:points\",[[\"~#point\",[\"^ \",\"~:x\",804,\"~:y\",210.0000271241638]],[\"^?\",[\"^ \",\"~:x\",828,\"~:y\",210.0000271241638]],[\"^?\",[\"^ \",\"~:x\",828,\"~:y\",234.0000271241638]],[\"^?\",[\"^ \",\"~:x\",804,\"~:y\",234.0000271241638]]],\"~:shape-ref\",\"~uc8b014fe-f285-8021-8007-8ea400bd9408\",\"~:proportion-lock\",false,\"~:transform-inverse\",[\"^2\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:page-id\",\"~u7c4e00d1-1f97-8161-8007-8f7861f33b60\",\"~:hidden\",true,\"^=\",\"~u9299427e-8172-80bb-8007-90e7059421c5\",\"~:parent-id\",\"~u9299427e-8172-80bb-8007-90e7059421c4\",\"~:svg-viewbox\",[\"^ \",\"~:y\",0,\"~:y1\",0,\"^6\",24,\"~:x\",0,\"~:x1\",0,\"~:y2\",24,\"~:x2\",24,\"~:height\",24],\"~:svg-defs\",[\"^ \"],\"~:frame-id\",\"~u9299427e-8172-80bb-8007-90e7059421c4\",\"~:strokes\",[[\"^ \",\"~:stroke-style\",\"~:solid\",\"~:stroke-color\",\"#ffffff\",\"~:stroke-opacity\",1,\"~:stroke-alignment\",\"~:inner\",\"~:stroke-width\",2]],\"~:x\",804,\"~:proportion\",1,\"~:selrect\",[\"~#rect\",[\"^ \",\"~:x\",804,\"~:y\",210.0000271241638,\"^6\",24,\"^K\",24,\"^H\",804,\"^G\",210.0000271241638,\"^J\",828,\"^I\",234.0000271241638]],\"~:fills\",[],\"~:flip-x\",null,\"^K\",24,\"~:flip-y\",null]]",
"~u9299427e-8172-80bb-8007-90e71cbb9fea": "[\"~#shape\",[\"^ \",\"~:y\",428.99998474121094,\"~:hide-fill-on-export\",false,\"~:layout-gap-type\",\"~:multiple\",\"~:layout-padding\",[\"^ \",\"~:p1\",0,\"~:p2\",0,\"~:p3\",0,\"~:p4\",0],\"~:transform\",[\"~#matrix\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:rotation\",0,\"~:layout-wrap-type\",\"~:nowrap\",\"~:grow-type\",\"~:fixed\",\"~:layout\",\"~:flex\",\"~:hide-in-viewer\",true,\"~:name\",\"card-img / patinegro\",\"~:layout-align-items\",\"~:start\",\"~:width\",265,\"~:layout-padding-type\",\"~:simple\",\"~:type\",\"~:frame\",\"~:points\",[[\"~#point\",[\"^ \",\"~:x\",580,\"~:y\",428.99998474121094]],[\"^L\",[\"^ \",\"~:x\",845,\"~:y\",428.99998474121094]],[\"^L\",[\"^ \",\"~:x\",845,\"~:y\",606.99997875689]],[\"^L\",[\"^ \",\"~:x\",580,\"~:y\",606.99997875689]]],\"~:r2\",20,\"~:component-root\",true,\"~:shape-ref\",\"~u9299427e-8172-80bb-8007-90e7059421c0\",\"~:proportion-lock\",false,\"~:layout-gap\",[\"^ \",\"~:row-gap\",0,\"~:column-gap\",0],\"~:transform-inverse\",[\"^:\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:page-id\",\"~u7c4e00d1-1f97-8161-8007-8f7861f33b60\",\"~:r3\",20,\"~:layout-justify-content\",\"^E\",\"~:r1\",20,\"~:id\",\"~u9299427e-8172-80bb-8007-90e71cbb9fea\",\"~:parent-id\",\"~u00000000-0000-0000-0000-000000000000\",\"~:layout-flex-dir\",\"~:column\",\"~:layout-align-content\",\"~:stretch\",\"~:component-id\",\"~u9299427e-8172-80bb-8007-90e7059a83e2\",\"~:frame-id\",\"~u00000000-0000-0000-0000-000000000000\",\"~:strokes\",[],\"~:x\",580,\"~:proportion\",1,\"~:r4\",20,\"~:selrect\",[\"~#rect\",[\"^ \",\"~:x\",580,\"~:y\",428.99998474121094,\"^F\",265,\"~:height\",177.99999401567902,\"~:x1\",580,\"~:y1\",428.99998474121094,\"~:x2\",845,\"~:y2\",606.99997875689]],\"~:fills\",[[\"^ \",\"~:fill-color\",\"#FFFFFF\",\"~:fill-opacity\",1]],\"~:flip-x\",null,\"^1:\",177.99999401567902,\"~:component-file\",\"~u31fe2e21-73e7-80f3-8007-73894fb58240\",\"~:flip-y\",null,\"~:shapes\",[\"~u9299427e-8172-80bb-8007-90e71cbc342d\",\"~u9299427e-8172-80bb-8007-90e71cbc342f\"]]]",
"~u94eaebe4-addd-80d1-8007-79d508aa2888": "[\"~#shape\",[\"^ \",\"~:y\",470.9999883168582,\"~:transform\",[\"~#matrix\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:rotation\",0,\"~:grow-type\",\"~:auto-width\",\"~:index\",null,\"~:content\",[\"^ \",\"~:type\",\"root\",\"~:children\",[[\"^ \",\"^8\",\"paragraph-set\",\"^9\",[[\"^ \",\"~:line-height\",\"1.2\",\"~:path\",\"\",\"~:font-style\",\"normal\",\"^9\",[[\"^ \",\"^:\",\"1.2\",\"^;\",\"\",\"^<\",\"normal\",\"~:text-transform\",\"uppercase\",\"~:text-align\",\"left\",\"~:font-id\",\"gfont-work-sans\",\"~:font-size\",\"12\",\"~:font-weight\",\"500\",\"~:modified-at\",\"2024-06-04T14:15:09.786Z\",\"~:font-variant-id\",\"500\",\"~:text-decoration\",\"underline\",\"~:letter-spacing\",\"0\",\"~:fills\",[[\"^ \",\"~:fill-color\",\"#000000\",\"~:fill-color-ref-file\",\"~ucaa70d02-51e1-81ae-8007-735e7de3d7bc\",\"~:fill-opacity\",1,\"~:fill-color-ref-id\",\"~udfa92acf-7d18-8079-8003-baba8789d8af\"]],\"~:font-family\",\"Work Sans\",\"~:text\",\"Label\"]],\"^=\",\"uppercase\",\"^>\",\"center\",\"^?\",\"gfont-work-sans\",\"^@\",\"12\",\"^A\",\"500\",\"^8\",\"paragraph\",\"^B\",\"2024-06-04T14:15:09.786Z\",\"^C\",\"500\",\"^D\",\"underline\",\"^E\",\"0\",\"^F\",[[\"^ \",\"^G\",\"#000000\",\"^H\",\"~ucaa70d02-51e1-81ae-8007-735e7de3d7bc\",\"^I\",1,\"^J\",\"~udfa92acf-7d18-8079-8003-baba8789d8af\"]],\"^K\",\"Work Sans\"]]]],\"~:vertical-align\",\"center\",\"^F\",[[\"^ \",\"^G\",\"#000000\",\"^I\",1]]],\"~:hide-in-viewer\",true,\"~:name\",\"Input\",\"~:saved-component-root\",null,\"~:width\",38,\"^8\",\"^L\",\"~:points\",[[\"~#point\",[\"^ \",\"~:x\",316.0000081062317,\"~:y\",470.9999883168582]],[\"^S\",[\"^ \",\"~:x\",354.0000081062317,\"~:y\",470.9999883168582]],[\"^S\",[\"^ \",\"~:x\",354.0000081062317,\"~:y\",485.99998831685775]],[\"^S\",[\"^ \",\"~:x\",316.0000081062317,\"~:y\",485.9999883168582]]],\"~:layout-item-h-sizing\",\"~:fix\",\"~:transform-inverse\",[\"^2\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:page-id\",\"~u02e9633d-4ce7-80da-8007-736558496fa8\",\"~:id\",\"~u94eaebe4-addd-80d1-8007-79d508aa2888\",\"~:parent-id\",\"~u94eaebe4-addd-80d1-8007-79d508aa2887\",\"~:position-data\",[[\"^ \",\"~:y\",485.3399963378906,\"^:\",\"1.2\",\"^<\",\"normal\",\"^=\",\"uppercase\",\"^>\",\"left\",\"^?\",\"sourcesanspro\",\"^@\",\"12\",\"^A\",\"500\",\"~:text-direction\",\"ltr\",\"^Q\",37.94000244140625,\"^C\",\"regular\",\"^D\",\"underline\",\"^E\",\"0\",\"~:x\",316.0299987792969,\"^F\",[[\"^ \",\"^G\",\"#000000\",\"^H\",\"~ucaa70d02-51e1-81ae-8007-735e7de3d7bc\",\"^I\",1,\"^J\",\"~udfa92acf-7d18-8079-8003-baba8789d8af\"]],\"~:direction\",\"ltr\",\"^K\",\"Work Sans\",\"~:height\",14.079986572265625,\"^L\",\"Label\"]],\"~:frame-id\",\"~u94eaebe4-addd-80d1-8007-79d508aa2887\",\"~:strokes\",[],\"~:x\",316.0000081062317,\"~:selrect\",[\"~#rect\",[\"^ \",\"~:x\",316.0000081062317,\"~:y\",470.9999883168582,\"^Q\",38,\"^11\",15,\"~:x1\",316.0000081062317,\"~:y1\",470.9999883168582,\"~:x2\",354.0000081062317,\"~:y2\",485.9999883168582]],\"^F\",[],\"~:flip-x\",null,\"^11\",15,\"~:flip-y\",null]]",
"~u77c71dba-32ee-804c-8007-736561cff45a": "[\"~#shape\",[\"^ \",\"~:y\",255.00000357564727,\"~:transform\",[\"~#matrix\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:rotation\",0,\"~:grow-type\",\"~:auto-width\",\"~:index\",null,\"~:content\",[\"^ \",\"~:type\",\"root\",\"~:children\",[[\"^ \",\"^8\",\"paragraph-set\",\"^9\",[[\"^ \",\"~:line-height\",\"1.2\",\"~:path\",\"\",\"~:font-style\",\"normal\",\"^9\",[[\"^ \",\"^:\",\"1.2\",\"^;\",\"\",\"^<\",\"normal\",\"~:text-transform\",\"uppercase\",\"~:text-align\",\"left\",\"~:font-id\",\"gfont-work-sans\",\"~:font-size\",\"12\",\"~:font-weight\",\"500\",\"~:modified-at\",\"2024-06-04T14:15:09.786Z\",\"~:font-variant-id\",\"500\",\"~:text-decoration\",\"underline\",\"~:letter-spacing\",\"0\",\"~:fills\",[[\"^ \",\"~:fill-color\",\"#000000\",\"~:fill-color-ref-file\",\"~ucaa70d02-51e1-81ae-8007-735e7de3d7bc\",\"~:fill-opacity\",1,\"~:fill-color-ref-id\",\"~udfa92acf-7d18-8079-8003-baba8789d8af\"]],\"~:font-family\",\"Work Sans\",\"~:text\",\"Label\"]],\"^=\",\"uppercase\",\"^>\",\"center\",\"^?\",\"gfont-work-sans\",\"^@\",\"12\",\"^A\",\"500\",\"^8\",\"paragraph\",\"^B\",\"2024-06-04T14:15:09.786Z\",\"^C\",\"500\",\"^D\",\"underline\",\"^E\",\"0\",\"^F\",[[\"^ \",\"^G\",\"#000000\",\"^H\",\"~ucaa70d02-51e1-81ae-8007-735e7de3d7bc\",\"^I\",1,\"^J\",\"~udfa92acf-7d18-8079-8003-baba8789d8af\"]],\"^K\",\"Work Sans\"]]]],\"~:vertical-align\",\"center\",\"^F\",[[\"^ \",\"^G\",\"#000000\",\"^I\",1]]],\"~:hide-in-viewer\",true,\"~:name\",\"Input\",\"~:saved-component-root\",null,\"~:width\",38,\"^8\",\"^L\",\"~:points\",[[\"~#point\",[\"^ \",\"~:x\",400.0000081062317,\"~:y\",255.00000357564727]],[\"^S\",[\"^ \",\"~:x\",438.0000081062317,\"~:y\",255.00000357564727]],[\"^S\",[\"^ \",\"~:x\",438.0000081062317,\"~:y\",270.0000035756468]],[\"^S\",[\"^ \",\"~:x\",400.0000081062317,\"~:y\",270.00000357564727]]],\"~:layout-item-h-sizing\",\"~:fix\",\"~:transform-inverse\",[\"^2\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:page-id\",\"~u02e9633d-4ce7-80da-8007-736558496fa8\",\"~:id\",\"~u77c71dba-32ee-804c-8007-736561cff45a\",\"~:parent-id\",\"~u77c71dba-32ee-804c-8007-736561cff459\",\"~:position-data\",[[\"^ \",\"~:y\",269.3399963378906,\"^:\",\"1.2\",\"^<\",\"normal\",\"^=\",\"uppercase\",\"^>\",\"left\",\"^?\",\"sourcesanspro\",\"^@\",\"12\",\"^A\",\"500\",\"~:text-direction\",\"ltr\",\"^Q\",37.94000244140625,\"^C\",\"regular\",\"^D\",\"underline\",\"^E\",\"0\",\"~:x\",400.0299987792969,\"^F\",[[\"^ \",\"^G\",\"#000000\",\"^H\",\"~ucaa70d02-51e1-81ae-8007-735e7de3d7bc\",\"^I\",1,\"^J\",\"~udfa92acf-7d18-8079-8003-baba8789d8af\"]],\"~:direction\",\"ltr\",\"^K\",\"Work Sans\",\"~:height\",14.080001831054688,\"^L\",\"Label\"]],\"~:frame-id\",\"~u77c71dba-32ee-804c-8007-736561cff459\",\"~:strokes\",[],\"~:x\",400.0000081062317,\"~:selrect\",[\"~#rect\",[\"^ \",\"~:x\",400.0000081062317,\"~:y\",255.00000357564727,\"^Q\",38,\"^11\",15,\"~:x1\",400.0000081062317,\"~:y1\",255.00000357564727,\"~:x2\",438.0000081062317,\"~:y2\",270.00000357564727]],\"^F\",[],\"~:flip-x\",null,\"^11\",15,\"~:flip-y\",null]]",
"~u77c71dba-32ee-804c-8007-736561cff459": "[\"~#shape\",[\"^ \",\"~:y\",254.00000357564704,\"~:hide-fill-on-export\",false,\"~:layout-gap-type\",\"~:multiple\",\"~:layout-padding\",[\"^ \",\"~:p1\",0,\"~:p2\",2,\"~:p3\",0,\"~:p4\",2],\"~:transform\",[\"~#matrix\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:rotation\",0,\"~:layout-wrap-type\",\"~:nowrap\",\"~:layout\",\"~:flex\",\"~:hide-in-viewer\",true,\"~:name\",\"_Utilities / Text / White\",\"~:layout-align-items\",\"~:start\",\"~:width\",42,\"~:layout-padding-type\",\"~:simple\",\"~:transforming\",false,\"~:type\",\"~:frame\",\"~:points\",[[\"~#point\",[\"^ \",\"~:x\",398.0000081062317,\"~:y\",254.00000357564704]],[\"^K\",[\"^ \",\"~:x\",440.0000081062317,\"~:y\",254.00000357564704]],[\"^K\",[\"^ \",\"~:x\",440.0000081062317,\"~:y\",270.00000357564704]],[\"^K\",[\"^ \",\"~:x\",398.0000081062317,\"~:y\",270.00000357564704]]],\"~:show-content\",true,\"~:layout-item-h-sizing\",\"~:auto\",\"~:proportion-lock\",false,\"~:layout-gap\",[\"^ \",\"~:row-gap\",0,\"~:column-gap\",6],\"~:transform-inverse\",[\"^:\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:page-id\",\"~u02e9633d-4ce7-80da-8007-736558496fa8\",\"~:layout-justify-content\",\"~:center\",\"~:id\",\"~u77c71dba-32ee-804c-8007-736561cff459\",\"~:parent-id\",\"~u77c71dba-32ee-804c-8007-736561cff458\",\"~:layout-flex-dir\",\"~:column\",\"~:layout-align-content\",\"~:stretch\",\"~:frame-id\",\"~u77c71dba-32ee-804c-8007-736561cff458\",\"~:strokes\",[],\"~:x\",398.0000081062317,\"~:proportion\",1,\"~:selrect\",[\"~#rect\",[\"^ \",\"~:x\",398.0000081062317,\"~:y\",254.00000357564704,\"^D\",42,\"~:height\",16,\"~:x1\",398.0000081062317,\"~:y1\",254.00000357564704,\"~:x2\",440.0000081062317,\"~:y2\",270.00000357564704]],\"~:fills\",[],\"~:flip-x\",null,\"^16\",16,\"~:flip-y\",null,\"~:shapes\",[\"~u77c71dba-32ee-804c-8007-736561cff45a\"]]]",
"~u9299427e-8172-80bb-8007-90e705944588": "[\"~#shape\",[\"^ \",\"~:y\",null,\"~:stroke-cap-start\",\"round\",\"~:transform\",[\"~#matrix\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:rotation\",null,\"~:index\",null,\"~:content\",[\"~#penpot/path-data\",\"~bAQAAAAAAAAAAAAAAAAAAAAAAAAAAwE1E/P9fQwMAAABcH05E/IleQwCATkT8yVxDAIBORPx/WkMDAAAAAIBORHx2V0No4k1E/P9UQwAgTUT8/1RDAwAAAFyvTET8/1RDAGBMRPx/VUMAAExE/P9WQwMAAAAAoEtE/H9VQ6RQS0T8/1RDAOBKRPz/VEMDAAAAmB1KRPz/VEMAgElEfHZXQwCASUT8f1pDAwAAAACASUT8zFxDAOBJRPyMXkMAQEpE/P9fQwIAAAAAAAAAAAAAAAAAAAAAAAAAAABMRPz/ZkMCAAAAAAAAAAAAAAAAAAAAAAAAAADATUT8/19D\"],\"~:name\",\"svg-path\",\"~:width\",null,\"~:type\",\"~:path\",\"~:svg-attrs\",[\"^ \",\"~:fill\",\"none\",\"~:stroke-linecap\",\"round\",\"~:stroke-linejoin\",\"round\"],\"~:points\",[[\"~#point\",[\"^ \",\"~:x\",806,\"~:y\",212.99997181105346]],[\"^A\",[\"^ \",\"~:x\",826,\"~:y\",212.99997181105346]],[\"^A\",[\"^ \",\"~:x\",826,\"~:y\",230.99997181105346]],[\"^A\",[\"^ \",\"~:x\",806,\"~:y\",230.99997181105346]]],\"~:shape-ref\",\"~uc8b014fe-f285-8021-8007-8ea518570b0f\",\"~:proportion-lock\",false,\"~:stroke-cap-end\",\"round\",\"~:transform-inverse\",[\"^3\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:page-id\",\"~u7c4e00d1-1f97-8161-8007-8f7861f33b60\",\"~:constraints-v\",\"~:scale\",\"~:svg-transform\",[\"^ \",\"~:a\",1,\"~:b\",0,\"~:c\",0,\"~:d\",1,\"~:e\",0,\"~:f\",0],\"~:constraints-h\",\"^H\",\"~:id\",\"~u9299427e-8172-80bb-8007-90e705944588\",\"~:parent-id\",\"~u9299427e-8172-80bb-8007-90e7059421c6\",\"~:svg-viewbox\",[\"^ \",\"~:y\",3,\"~:y1\",3,\"^9\",20,\"~:x\",2,\"~:x1\",2,\"~:y2\",21,\"~:x2\",22,\"~:height\",18],\"~:applied-tokens\",[\"^ \",\"~:stroke-color\",\"color.icon.default\"],\"~:svg-defs\",[\"^ \"],\"~:frame-id\",\"~u9299427e-8172-80bb-8007-90e7059421c6\",\"~:strokes\",[[\"^ \",\"~:stroke-style\",\"~:solid\",\"~:stroke-alignment\",\"~:inner\",\"~:stroke-width\",2,\"^T\",\"#ffffff\",\"~:stroke-opacity\",1]],\"~:x\",null,\"~:proportion\",1,\"~:selrect\",[\"~#rect\",[\"^ \",\"~:x\",806,\"~:y\",212.99997181105346,\"^9\",20,\"^R\",18,\"^O\",806,\"^N\",212.99997181105346,\"^Q\",826,\"^P\",230.99997181105346]],\"~:fills\",[],\"~:flip-x\",null,\"^R\",null,\"~:flip-y\",null]]",
"~u77c71dba-32ee-804c-8007-736561cff458": "[\"~#shape\",[\"^ \",\"~:y\",246.00000357564704,\"~:hide-fill-on-export\",false,\"~:layout-gap-type\",\"~:multiple\",\"~:rx\",8,\"~:layout-padding\",[\"^ \",\"~:p1\",8,\"~:p2\",12,\"~:p3\",8,\"~:p4\",12],\"~:transform\",[\"~#matrix\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:rotation\",0,\"~:layout-wrap-type\",\"~:nowrap\",\"~:layout\",\"~:flex\",\"~:hide-in-viewer\",true,\"~:name\",\"Dark / Button / Primary / Text / Default\",\"~:layout-align-items\",\"~:center\",\"~:width\",66,\"~:layout-padding-type\",\"~:simple\",\"~:type\",\"~:frame\",\"~:points\",[[\"~#point\",[\"^ \",\"~:x\",386.0000081062317,\"~:y\",246.00000357564704]],[\"^K\",[\"^ \",\"~:x\",452.0000081062317,\"~:y\",246.00000357564704]],[\"^K\",[\"^ \",\"~:x\",452.0000081062317,\"~:y\",278.00000357564704]],[\"^K\",[\"^ \",\"~:x\",386.0000081062317,\"~:y\",278.00000357564704]]],\"~:r2\",8,\"~:show-content\",true,\"~:proportion-lock\",false,\"~:layout-gap\",[\"^ \",\"~:row-gap\",4,\"~:column-gap\",4],\"~:transform-inverse\",[\"^;\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:page-id\",\"~u02e9633d-4ce7-80da-8007-736558496fa8\",\"~:r3\",8,\"~:layout-justify-content\",\"^D\",\"~:r1\",8,\"~:id\",\"~u77c71dba-32ee-804c-8007-736561cff458\",\"~:parent-id\",\"~u77c71dba-32ee-804c-8007-736561cf8584\",\"~:layout-flex-dir\",\"~:row\",\"~:layout-align-content\",\"~:stretch\",\"~:frame-id\",\"~u77c71dba-32ee-804c-8007-736561cf8584\",\"~:strokes\",[],\"~:x\",386.0000081062317,\"~:proportion\",1,\"~:r4\",8,\"~:selrect\",[\"~#rect\",[\"^ \",\"~:x\",386.0000081062317,\"~:y\",246.00000357564704,\"^E\",66,\"~:height\",32,\"~:x1\",386.0000081062317,\"~:y1\",246.00000357564704,\"~:x2\",452.0000081062317,\"~:y2\",278.00000357564704]],\"~:fills\",[[\"^ \",\"~:fill-color\",\"#7efff5\",\"~:fill-opacity\",1]],\"~:flip-x\",null,\"~:ry\",8,\"^17\",32,\"~:flip-y\",null,\"~:shapes\",[\"~u77c71dba-32ee-804c-8007-736561cff459\"]]]",
"~u9299427e-8172-80bb-8007-90e72469bf8e": "[\"~#shape\",[\"^ \",\"~:y\",444.00002998518676,\"~:hide-fill-on-export\",false,\"~:layout-item-absolute\",true,\"~:layout-gap-type\",\"~:multiple\",\"~:layout-padding\",[\"^ \",\"~:p1\",0,\"~:p2\",0,\"~:p3\",0,\"~:p4\",0],\"~:transform\",[\"~#matrix\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:rotation\",0,\"~:layout-wrap-type\",\"~:nowrap\",\"~:grow-type\",\"~:fixed\",\"~:layout\",\"~:flex\",\"~:hide-in-viewer\",true,\"~:name\",\"add-favorites\",\"~:layout-align-items\",\"~:center\",\"~:width\",48,\"~:layout-padding-type\",\"~:simple\",\"~:type\",\"~:frame\",\"~:points\",[[\"~#point\",[\"^ \",\"~:x\",1128,\"~:y\",444.00002998518676]],[\"^M\",[\"^ \",\"~:x\",1176,\"~:y\",444.00002998518676]],[\"^M\",[\"^ \",\"~:x\",1176,\"~:y\",492.00002426314086]],[\"^M\",[\"^ \",\"~:x\",1128,\"~:y\",492.00002426314086]]],\"~:r2\",50,\"~:shape-ref\",\"~u9299427e-8172-80bb-8007-90e7059421c2\",\"~:proportion-lock\",false,\"~:layout-gap\",[\"^ \",\"~:row-gap\",0,\"~:column-gap\",0],\"~:transform-inverse\",[\"^;\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:page-id\",\"~u7c4e00d1-1f97-8161-8007-8f7861f33b60\",\"~:r3\",50,\"~:layout-justify-content\",\"^F\",\"~:r1\",50,\"~:id\",\"~u9299427e-8172-80bb-8007-90e72469bf8e\",\"~:parent-id\",\"~u9299427e-8172-80bb-8007-90e72469bf8c\",\"~:layout-flex-dir\",\"~:row\",\"~:applied-tokens\",[\"^ \",\"~:fill\",\"color.bg.default\"],\"~:layout-align-content\",\"~:stretch\",\"~:component-id\",\"~uc8b014fe-f285-8021-8007-8ea447a0bc30\",\"~:frame-id\",\"~u9299427e-8172-80bb-8007-90e72469bf8c\",\"~:strokes\",[],\"~:x\",1128,\"~:proportion\",1,\"~:r4\",50,\"~:selrect\",[\"~#rect\",[\"^ \",\"~:x\",1128,\"~:y\",444.00002998518676,\"^G\",48,\"~:height\",47.9999942779541,\"~:x1\",1128,\"~:y1\",444.00002998518676,\"~:x2\",1176,\"~:y2\",492.00002426314086]],\"~:fills\",[[\"^ \",\"~:fill-color\",\"#ffffff\",\"~:fill-opacity\",0.3]],\"~:flip-x\",null,\"^1<\",47.9999942779541,\"~:component-file\",\"~ud0eb4518-f33d-81e1-8007-8fe418fea255\",\"~:flip-y\",null,\"~:shapes\",[\"~u9299427e-8172-80bb-8007-90e72469bf90\"]]]",
"~u9299427e-8172-80bb-8007-90e71cbc342e": "[\"~#shape\",[\"^ \",\"~:y\",429.000012591785,\"~:transform\",[\"~#matrix\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:rotation\",0,\"~:name\",\"patinegro\",\"~:width\",264.80230943863717,\"~:type\",\"~:rect\",\"~:points\",[[\"~#point\",[\"^ \",\"~:x\",579.9999793759137,\"~:y\",429.000012591785]],[\"^9\",[\"^ \",\"~:x\",844.8022888145506,\"~:y\",429.000012591785]],[\"^9\",[\"^ \",\"~:x\",844.8022888145506,\"~:y\",625.1131514739925]],[\"^9\",[\"^ \",\"~:x\",579.9999793759137,\"~:y\",625.1131514739925]]],\"~:r2\",0,\"~:shape-ref\",\"~u9299427e-8172-80bb-8007-90e7059421c3\",\"~:proportion-lock\",true,\"~:transform-inverse\",[\"^2\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:page-id\",\"~u7c4e00d1-1f97-8161-8007-8f7861f33b60\",\"~:r3\",0,\"~:r1\",0,\"~:id\",\"~u9299427e-8172-80bb-8007-90e71cbc342e\",\"~:parent-id\",\"~u9299427e-8172-80bb-8007-90e71cbc342d\",\"~:frame-id\",\"~u9299427e-8172-80bb-8007-90e71cbc342d\",\"~:strokes\",[],\"~:x\",579.9999793759134,\"~:proportion\",1.3487940630797774,\"~:r4\",0,\"~:selrect\",[\"~#rect\",[\"^ \",\"~:x\",579.9999793759134,\"~:y\",429.000012591785,\"^5\",264.80230943863717,\"~:height\",196.11313888220752,\"~:x1\",579.9999793759134,\"~:y1\",429.000012591785,\"~:x2\",844.8022888145506,\"~:y2\",625.1131514739925]],\"~:fills\",[[\"^ \",\"~:fill-color\",\"#b73d3d\",\"~:fill-opacity\",1]],\"~:flip-x\",null,\"^I\",196.11313888220752,\"~:flip-y\",null]]",
"~u77c71dba-32ee-804c-8007-736561cf857f": "[\"~#shape\",[\"^ \",\"~:y\",221.99999439878093,\"~:hide-fill-on-export\",false,\"~:layout-gap-type\",\"~:multiple\",\"~:layout-padding\",[\"^ \",\"~:p1\",0,\"~:p2\",12,\"~:p3\",0,\"~:p4\",12],\"~:transform\",[\"~#matrix\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:rotation\",0,\"~:layout-wrap-type\",\"~:wrap\",\"~:layout\",\"~:flex\",\"~:hide-in-viewer\",true,\"~:name\",\"Board Parent 1\",\"~:layout-align-items\",\"~:start\",\"~:width\",272,\"~:layout-padding-type\",\"~:simple\",\"~:type\",\"~:frame\",\"~:points\",[[\"~#point\",[\"^ \",\"~:x\",283.0000081062317,\"~:y\",221.99999439878093]],[\"^J\",[\"^ \",\"~:x\",555.0000081062317,\"~:y\",221.99999439878093]],[\"^J\",[\"^ \",\"~:x\",555.0000081062317,\"~:y\",301.999982234935]],[\"^J\",[\"^ \",\"~:x\",283.0000081062317,\"~:y\",301.999982234935]]],\"~:show-content\",true,\"~:proportion-lock\",false,\"~:layout-gap\",[\"^ \",\"~:row-gap\",4,\"~:column-gap\",4],\"~:transform-inverse\",[\"^:\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:page-id\",\"~u02e9633d-4ce7-80da-8007-736558496fa8\",\"~:layout-item-v-sizing\",\"~:fix\",\"~:layout-justify-content\",\"~:center\",\"~:id\",\"~u77c71dba-32ee-804c-8007-736561cf857f\",\"~:parent-id\",\"~u00000000-0000-0000-0000-000000000000\",\"~:layout-flex-dir\",\"~:row\",\"~:layout-align-content\",\"~:stretch\",\"~:frame-id\",\"~u00000000-0000-0000-0000-000000000000\",\"~:strokes\",[],\"~:x\",283.0000081062317,\"~:proportion\",1,\"~:selrect\",[\"~#rect\",[\"^ \",\"~:x\",283.0000081062317,\"~:y\",221.99999439878093,\"^D\",272,\"~:height\",79.99998783615405,\"~:x1\",283.0000081062317,\"~:y1\",221.99999439878093,\"~:x2\",555.0000081062317,\"~:y2\",301.999982234935]],\"~:fills\",[],\"~:flip-x\",null,\"^15\",79.99998783615405,\"~:flip-y\",null,\"~:shapes\",[\"~u77c71dba-32ee-804c-8007-736561cf8584\"]]]",
"~u9299427e-8172-80bb-8007-90e72469bf8f": "[\"~#shape\",[\"^ \",\"~:y\",438.000012591785,\"~:transform\",[\"~#matrix\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:rotation\",0,\"~:name\",\"patinegro\",\"~:width\",264.80230943863717,\"~:type\",\"~:rect\",\"~:points\",[[\"~#point\",[\"^ \",\"~:x\",915.9999793759137,\"~:y\",438.000012591785]],[\"^9\",[\"^ \",\"~:x\",1180.8022888145506,\"~:y\",438.000012591785]],[\"^9\",[\"^ \",\"~:x\",1180.8022888145506,\"~:y\",634.1131514739925]],[\"^9\",[\"^ \",\"~:x\",915.9999793759137,\"~:y\",634.1131514739925]]],\"~:r2\",0,\"~:shape-ref\",\"~u9299427e-8172-80bb-8007-90e7059421c3\",\"~:proportion-lock\",true,\"~:transform-inverse\",[\"^2\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:page-id\",\"~u7c4e00d1-1f97-8161-8007-8f7861f33b60\",\"~:r3\",0,\"~:r1\",0,\"~:id\",\"~u9299427e-8172-80bb-8007-90e72469bf8f\",\"~:parent-id\",\"~u9299427e-8172-80bb-8007-90e72469bf8d\",\"~:frame-id\",\"~u9299427e-8172-80bb-8007-90e72469bf8d\",\"~:strokes\",[],\"~:x\",915.9999793759134,\"~:proportion\",1.3487940630797774,\"~:r4\",0,\"~:selrect\",[\"~#rect\",[\"^ \",\"~:x\",915.9999793759134,\"~:y\",438.000012591785,\"^5\",264.80230943863717,\"~:height\",196.11313888220752,\"~:x1\",915.9999793759134,\"~:y1\",438.000012591785,\"~:x2\",1180.8022888145506,\"~:y2\",634.1131514739925]],\"~:fills\",[[\"^ \",\"~:fill-color\",\"#b73d3d\",\"~:fill-opacity\",1]],\"~:flip-x\",null,\"^I\",196.11313888220752,\"~:flip-y\",null]]",
"~u9299427e-8172-80bb-8007-90e71cbc342f": "[\"~#shape\",[\"^ \",\"~:y\",435.00002998518676,\"~:hide-fill-on-export\",false,\"~:layout-item-absolute\",true,\"~:layout-gap-type\",\"~:multiple\",\"~:layout-padding\",[\"^ \",\"~:p1\",0,\"~:p2\",0,\"~:p3\",0,\"~:p4\",0],\"~:transform\",[\"~#matrix\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:rotation\",0,\"~:layout-wrap-type\",\"~:nowrap\",\"~:grow-type\",\"~:fixed\",\"~:layout\",\"~:flex\",\"~:hide-in-viewer\",true,\"~:name\",\"add-favorites\",\"~:layout-align-items\",\"~:center\",\"~:width\",48,\"~:layout-padding-type\",\"~:simple\",\"~:type\",\"~:frame\",\"~:touched\",[\"~#set\",[\"~:layout-item-z-index\"]],\"~:points\",[[\"~#point\",[\"^ \",\"~:x\",792,\"~:y\",435.00002998518676]],[\"^P\",[\"^ \",\"~:x\",840,\"~:y\",435.00002998518676]],[\"^P\",[\"^ \",\"~:x\",840,\"~:y\",483.00002426314086]],[\"^P\",[\"^ \",\"~:x\",792,\"~:y\",483.00002426314086]]],\"~:r2\",50,\"~:shape-ref\",\"~u9299427e-8172-80bb-8007-90e7059421c2\",\"~:proportion-lock\",false,\"~:layout-gap\",[\"^ \",\"~:row-gap\",0,\"~:column-gap\",0],\"~:transform-inverse\",[\"^;\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:page-id\",\"~u7c4e00d1-1f97-8161-8007-8f7861f33b60\",\"~:r3\",50,\"~:layout-justify-content\",\"^F\",\"~:r1\",50,\"~:id\",\"~u9299427e-8172-80bb-8007-90e71cbc342f\",\"~:parent-id\",\"~u9299427e-8172-80bb-8007-90e71cbb9fea\",\"~:layout-flex-dir\",\"~:row\",\"~:applied-tokens\",[\"^ \",\"~:fill\",\"color.bg.default\"],\"~:layout-align-content\",\"~:stretch\",\"~:component-id\",\"~uc8b014fe-f285-8021-8007-8ea447a0bc30\",\"~:frame-id\",\"~u9299427e-8172-80bb-8007-90e71cbb9fea\",\"~:strokes\",[],\"~:x\",792,\"~:proportion\",1,\"~:r4\",50,\"~:selrect\",[\"~#rect\",[\"^ \",\"~:x\",792,\"~:y\",435.00002998518676,\"^G\",48,\"~:height\",47.9999942779541,\"~:x1\",792,\"~:y1\",435.00002998518676,\"~:x2\",840,\"~:y2\",483.00002426314086]],\"~:fills\",[[\"^ \",\"~:fill-color\",\"#ffffff\",\"~:fill-opacity\",0.3]],\"~:flip-x\",null,\"^1?\",47.9999942779541,\"~:component-file\",\"~ud0eb4518-f33d-81e1-8007-8fe418fea255\",\"~:flip-y\",null,\"^N\",1,\"~:shapes\",[\"~u9299427e-8172-80bb-8007-90e71cbc3430\"]]]",
"~u94eaebe4-addd-80d1-8007-79d50980078e": "[\"~#shape\",[\"^ \",\"~:y\",546.0000478045426,\"~:hide-fill-on-export\",false,\"~:layout-gap-type\",\"~:multiple\",\"~:layout-padding\",[\"^ \",\"~:p1\",0,\"~:p2\",12,\"~:p3\",0,\"~:p4\",12],\"~:transform\",[\"~#matrix\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:rotation\",0,\"~:layout-wrap-type\",\"~:wrap\",\"~:layout\",\"~:flex\",\"~:hide-in-viewer\",true,\"~:name\",\"Board Parent 4\",\"~:layout-align-items\",\"~:start\",\"~:width\",272,\"~:layout-padding-type\",\"~:simple\",\"~:type\",\"~:frame\",\"~:points\",[[\"~#point\",[\"^ \",\"~:x\",283.0000081062317,\"~:y\",546.0000478045426]],[\"^J\",[\"^ \",\"~:x\",555.0000081062317,\"~:y\",546.0000478045426]],[\"^J\",[\"^ \",\"~:x\",555.0000081062317,\"~:y\",626.0000356406968]],[\"^J\",[\"^ \",\"~:x\",283.0000081062317,\"~:y\",626.0000356406968]]],\"~:show-content\",true,\"~:proportion-lock\",false,\"~:layout-gap\",[\"^ \",\"~:row-gap\",4,\"~:column-gap\",4],\"~:transform-inverse\",[\"^:\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:page-id\",\"~u02e9633d-4ce7-80da-8007-736558496fa8\",\"~:layout-item-v-sizing\",\"~:fix\",\"~:layout-justify-content\",\"~:center\",\"~:id\",\"~u94eaebe4-addd-80d1-8007-79d50980078e\",\"~:parent-id\",\"~u00000000-0000-0000-0000-000000000000\",\"~:layout-flex-dir\",\"~:column-reverse\",\"~:layout-align-content\",\"~:stretch\",\"~:frame-id\",\"~u00000000-0000-0000-0000-000000000000\",\"~:strokes\",[],\"~:x\",283.0000081062317,\"~:proportion\",1,\"~:selrect\",[\"~#rect\",[\"^ \",\"~:x\",283.0000081062317,\"~:y\",546.0000478045426,\"^D\",272,\"~:height\",79.9999878361541,\"~:x1\",283.0000081062317,\"~:y1\",546.0000478045426,\"~:x2\",555.0000081062317,\"~:y2\",626.0000356406968]],\"~:fills\",[],\"~:flip-x\",null,\"^15\",79.9999878361541,\"~:flip-y\",null,\"~:shapes\",[\"~u94eaebe4-addd-80d1-8007-79d50980078f\"]]]",
"~u9299427e-8172-80bb-8007-90e72469bf8c": "[\"~#shape\",[\"^ \",\"~:y\",437.99998474121094,\"~:hide-fill-on-export\",false,\"~:layout-gap-type\",\"~:multiple\",\"~:layout-padding\",[\"^ \",\"~:p1\",0,\"~:p2\",0,\"~:p3\",0,\"~:p4\",0],\"~:transform\",[\"~#matrix\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:rotation\",0,\"~:layout-wrap-type\",\"~:nowrap\",\"~:grow-type\",\"~:fixed\",\"~:layout\",\"~:flex\",\"~:hide-in-viewer\",true,\"~:name\",\"card-img / patinegro\",\"~:layout-align-items\",\"~:start\",\"~:width\",265,\"~:layout-padding-type\",\"~:simple\",\"~:type\",\"~:frame\",\"~:points\",[[\"~#point\",[\"^ \",\"~:x\",916,\"~:y\",437.99998474121094]],[\"^L\",[\"^ \",\"~:x\",1181,\"~:y\",437.99998474121094]],[\"^L\",[\"^ \",\"~:x\",1181,\"~:y\",615.99997875689]],[\"^L\",[\"^ \",\"~:x\",916,\"~:y\",615.99997875689]]],\"~:r2\",20,\"~:component-root\",true,\"~:shape-ref\",\"~u9299427e-8172-80bb-8007-90e7059421c0\",\"~:proportion-lock\",false,\"~:layout-gap\",[\"^ \",\"~:row-gap\",0,\"~:column-gap\",0],\"~:transform-inverse\",[\"^:\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:page-id\",\"~u7c4e00d1-1f97-8161-8007-8f7861f33b60\",\"~:r3\",20,\"~:layout-justify-content\",\"^E\",\"~:r1\",20,\"~:id\",\"~u9299427e-8172-80bb-8007-90e72469bf8c\",\"~:parent-id\",\"~u00000000-0000-0000-0000-000000000000\",\"~:layout-flex-dir\",\"~:column\",\"~:layout-align-content\",\"~:stretch\",\"~:component-id\",\"~u9299427e-8172-80bb-8007-90e7059a83e2\",\"~:frame-id\",\"~u00000000-0000-0000-0000-000000000000\",\"~:strokes\",[],\"~:x\",916,\"~:proportion\",1,\"~:r4\",20,\"~:selrect\",[\"~#rect\",[\"^ \",\"~:x\",916,\"~:y\",437.99998474121094,\"^F\",265,\"~:height\",177.99999401567902,\"~:x1\",916,\"~:y1\",437.99998474121094,\"~:x2\",1181,\"~:y2\",615.99997875689]],\"~:fills\",[[\"^ \",\"~:fill-color\",\"#FFFFFF\",\"~:fill-opacity\",1]],\"~:flip-x\",null,\"^1:\",177.99999401567902,\"~:component-file\",\"~u31fe2e21-73e7-80f3-8007-73894fb58240\",\"~:flip-y\",null,\"~:shapes\",[\"~u9299427e-8172-80bb-8007-90e72469bf8d\",\"~u9299427e-8172-80bb-8007-90e72469bf8e\"]]]",
"~u94eaebe4-addd-80d1-8007-79d50980078f": "[\"~#shape\",[\"^ \",\"~:y\",545.9999806874634,\"~:hide-fill-on-export\",false,\"~:transform\",[\"~#matrix\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:rotation\",0,\"~:hide-in-viewer\",true,\"~:name\",\"Board Child\",\"~:width\",80,\"~:type\",\"~:frame\",\"~:points\",[[\"~#point\",[\"^ \",\"~:x\",295.0000081062317,\"~:y\",545.9999806874634]],[\"^;\",[\"^ \",\"~:x\",375.0000081062317,\"~:y\",545.9999806874634]],[\"^;\",[\"^ \",\"~:x\",375.0000081062317,\"~:y\",625.9999806874634]],[\"^;\",[\"^ \",\"~:x\",295.0000081062317,\"~:y\",625.9999806874634]]],\"~:show-content\",true,\"~:proportion-lock\",false,\"~:transform-inverse\",[\"^3\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:page-id\",\"~u02e9633d-4ce7-80da-8007-736558496fa8\",\"~:constraints-v\",\"~:top\",\"~:constraints-h\",\"~:left\",\"~:id\",\"~u94eaebe4-addd-80d1-8007-79d50980078f\",\"~:parent-id\",\"~u94eaebe4-addd-80d1-8007-79d50980078e\",\"~:frame-id\",\"~u94eaebe4-addd-80d1-8007-79d50980078e\",\"~:strokes\",[],\"~:x\",295.0000081062317,\"~:proportion\",1,\"~:selrect\",[\"~#rect\",[\"^ \",\"~:x\",295.0000081062317,\"~:y\",545.9999806874634,\"^7\",80,\"~:height\",80,\"~:x1\",295.0000081062317,\"~:y1\",545.9999806874634,\"~:x2\",375.0000081062317,\"~:y2\",625.9999806874634]],\"~:fills\",[],\"~:flip-x\",null,\"^K\",80,\"~:flip-y\",null,\"~:shapes\",[\"~u94eaebe4-addd-80d1-8007-79d509800790\",\"~u94eaebe4-addd-80d1-8007-79d509800791\"]]]",
"~u9299427e-8172-80bb-8007-90e72469bf8d": "[\"~#shape\",[\"^ \",\"~:y\",437.99999475401955,\"~:hide-fill-on-export\",false,\"~:transform\",[\"~#matrix\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:rotation\",0,\"~:hide-in-viewer\",true,\"~:name\",\"img-city\",\"~:width\",265,\"~:type\",\"~:frame\",\"~:points\",[[\"~#point\",[\"^ \",\"~:x\",916,\"~:y\",437.9999947540198]],[\"^;\",[\"^ \",\"~:x\",1181,\"~:y\",437.9999947540198]],[\"^;\",[\"^ \",\"~:x\",1181,\"~:y\",615.9899634401968]],[\"^;\",[\"^ \",\"~:x\",916,\"~:y\",615.9899634401968]]],\"~:r2\",0,\"~:shape-ref\",\"~u9299427e-8172-80bb-8007-90e7059421c1\",\"~:layout-item-h-sizing\",\"~:fill\",\"~:proportion-lock\",false,\"~:transform-inverse\",[\"^3\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:page-id\",\"~u7c4e00d1-1f97-8161-8007-8f7861f33b60\",\"~:layout-item-v-sizing\",\"^?\",\"~:r3\",0,\"~:r1\",0,\"~:id\",\"~u9299427e-8172-80bb-8007-90e72469bf8d\",\"~:parent-id\",\"~u9299427e-8172-80bb-8007-90e72469bf8c\",\"~:frame-id\",\"~u9299427e-8172-80bb-8007-90e72469bf8c\",\"~:strokes\",[],\"~:x\",916,\"~:proportion\",1,\"~:r4\",0,\"~:selrect\",[\"~#rect\",[\"^ \",\"~:x\",916,\"~:y\",437.99999475401955,\"^7\",265,\"~:height\",177.989968686177,\"~:x1\",916,\"~:y1\",437.99999475401955,\"~:x2\",1181,\"~:y2\",615.9899634401966]],\"~:fills\",[[\"^ \",\"~:fill-color\",\"#FFFFFF\",\"~:fill-opacity\",1]],\"~:flip-x\",null,\"^N\",177.989968686177,\"~:flip-y\",null,\"~:shapes\",[\"~u9299427e-8172-80bb-8007-90e72469bf8f\"]]]",
"~u9299427e-8172-80bb-8007-90e71cbc342d": "[\"~#shape\",[\"^ \",\"~:y\",428.99999475401955,\"~:hide-fill-on-export\",false,\"~:transform\",[\"~#matrix\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:rotation\",0,\"~:hide-in-viewer\",true,\"~:name\",\"img-city\",\"~:width\",265,\"~:type\",\"~:frame\",\"~:points\",[[\"~#point\",[\"^ \",\"~:x\",580,\"~:y\",428.9999947540198]],[\"^;\",[\"^ \",\"~:x\",845,\"~:y\",428.9999947540198]],[\"^;\",[\"^ \",\"~:x\",845,\"~:y\",606.9899634401968]],[\"^;\",[\"^ \",\"~:x\",580,\"~:y\",606.9899634401968]]],\"~:r2\",0,\"~:shape-ref\",\"~u9299427e-8172-80bb-8007-90e7059421c1\",\"~:layout-item-h-sizing\",\"~:fill\",\"~:proportion-lock\",false,\"~:transform-inverse\",[\"^3\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:page-id\",\"~u7c4e00d1-1f97-8161-8007-8f7861f33b60\",\"~:layout-item-v-sizing\",\"^?\",\"~:r3\",0,\"~:r1\",0,\"~:id\",\"~u9299427e-8172-80bb-8007-90e71cbc342d\",\"~:parent-id\",\"~u9299427e-8172-80bb-8007-90e71cbb9fea\",\"~:frame-id\",\"~u9299427e-8172-80bb-8007-90e71cbb9fea\",\"~:strokes\",[],\"~:x\",580,\"~:proportion\",1,\"~:r4\",0,\"~:selrect\",[\"~#rect\",[\"^ \",\"~:x\",580,\"~:y\",428.99999475401955,\"^7\",265,\"~:height\",177.989968686177,\"~:x1\",580,\"~:y1\",428.99999475401955,\"~:x2\",845,\"~:y2\",606.9899634401966]],\"~:fills\",[[\"^ \",\"~:fill-color\",\"#FFFFFF\",\"~:fill-opacity\",1]],\"~:flip-x\",null,\"^N\",177.989968686177,\"~:flip-y\",null,\"~:shapes\",[\"~u9299427e-8172-80bb-8007-90e71cbc342e\"]]]",
"~u94eaebe4-addd-80d1-8007-79d508a9dc2f": "[\"~#shape\",[\"^ \",\"~:y\",437.9999943987809,\"~:hide-fill-on-export\",false,\"~:layout-gap-type\",\"~:multiple\",\"~:layout-padding\",[\"^ \",\"~:p1\",0,\"~:p2\",12,\"~:p3\",0,\"~:p4\",12],\"~:transform\",[\"~#matrix\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:rotation\",0,\"~:layout-wrap-type\",\"~:wrap\",\"~:layout\",\"~:flex\",\"~:hide-in-viewer\",true,\"~:name\",\"Board Parent 3\",\"~:layout-align-items\",\"~:start\",\"~:width\",272,\"~:layout-padding-type\",\"~:simple\",\"~:type\",\"~:frame\",\"~:points\",[[\"~#point\",[\"^ \",\"~:x\",283.0000081062317,\"~:y\",437.9999943987809]],[\"^J\",[\"^ \",\"~:x\",555.0000081062317,\"~:y\",437.9999943987809]],[\"^J\",[\"^ \",\"~:x\",555.0000081062317,\"~:y\",517.999982234935]],[\"^J\",[\"^ \",\"~:x\",283.0000081062317,\"~:y\",517.999982234935]]],\"~:show-content\",true,\"~:proportion-lock\",false,\"~:layout-gap\",[\"^ \",\"~:row-gap\",4,\"~:column-gap\",4],\"~:transform-inverse\",[\"^:\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:page-id\",\"~u02e9633d-4ce7-80da-8007-736558496fa8\",\"~:layout-item-v-sizing\",\"~:fix\",\"~:layout-justify-content\",\"~:center\",\"~:id\",\"~u94eaebe4-addd-80d1-8007-79d508a9dc2f\",\"~:parent-id\",\"~u00000000-0000-0000-0000-000000000000\",\"~:layout-flex-dir\",\"~:column\",\"~:layout-align-content\",\"~:stretch\",\"~:frame-id\",\"~u00000000-0000-0000-0000-000000000000\",\"~:strokes\",[],\"~:x\",283.0000081062317,\"~:proportion\",1,\"~:selrect\",[\"~#rect\",[\"^ \",\"~:x\",283.0000081062317,\"~:y\",437.9999943987809,\"^D\",272,\"~:height\",79.9999878361541,\"~:x1\",283.0000081062317,\"~:y1\",437.9999943987809,\"~:x2\",555.0000081062317,\"~:y2\",517.999982234935]],\"~:fills\",[],\"~:flip-x\",null,\"^15\",79.9999878361541,\"~:flip-y\",null,\"~:shapes\",[\"~u94eaebe4-addd-80d1-8007-79d508a9dc30\"]]]",
"~u94eaebe4-addd-80d1-8007-79d509800790": "[\"~#shape\",[\"^ \",\"~:y\",546.0000417226197,\"~:rx\",8,\"~:transform\",[\"~#matrix\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:rotation\",0,\"~:grow-type\",\"~:fixed\",\"~:hide-in-viewer\",false,\"~:name\",\"Rectangle\",\"~:width\",80,\"~:transforming\",false,\"~:type\",\"~:rect\",\"~:points\",[[\"~#point\",[\"^ \",\"~:x\",295.0000081062317,\"~:y\",546.0000417226197]],[\"^>\",[\"^ \",\"~:x\",375.0000081062317,\"~:y\",546.0000417226197]],[\"^>\",[\"^ \",\"~:x\",375.0000081062317,\"~:y\",626.0000417226197]],[\"^>\",[\"^ \",\"~:x\",295.0000081062317,\"~:y\",626.0000417226197]]],\"~:r2\",8,\"~:proportion-lock\",false,\"~:transform-inverse\",[\"^3\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:page-id\",\"~u02e9633d-4ce7-80da-8007-736558496fa8\",\"~:r3\",8,\"~:r1\",8,\"~:id\",\"~u94eaebe4-addd-80d1-8007-79d509800790\",\"~:parent-id\",\"~u94eaebe4-addd-80d1-8007-79d50980078f\",\"~:frame-id\",\"~u94eaebe4-addd-80d1-8007-79d50980078f\",\"~:strokes\",[],\"~:x\",295.0000081062317,\"~:proportion\",1,\"~:r4\",8,\"~:selrect\",[\"~#rect\",[\"^ \",\"~:x\",295.0000081062317,\"~:y\",546.0000417226197,\"^9\",80,\"~:height\",80,\"~:x1\",295.0000081062317,\"~:y1\",546.0000417226197,\"~:x2\",375.0000081062317,\"~:y2\",626.0000417226197]],\"~:fills\",[[\"^ \",\"~:fill-color\",\"#e8e9ea\",\"~:fill-opacity\",1]],\"~:flip-x\",null,\"~:ry\",8,\"^M\",80,\"~:flip-y\",null]]",
"~u9299427e-8172-80bb-8007-90e72469bf92": "[\"~#shape\",[\"^ \",\"~:y\",458.99997181105346,\"~:hide-fill-on-export\",false,\"~:transform\",[\"~#matrix\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:rotation\",0,\"~:hide-in-viewer\",true,\"~:name\",\"svg-path\",\"~:width\",20,\"~:type\",\"~:frame\",\"~:points\",[[\"~#point\",[\"^ \",\"~:x\",1142,\"~:y\",458.99997181105346]],[\"^;\",[\"^ \",\"~:x\",1162,\"~:y\",458.99997181105346]],[\"^;\",[\"^ \",\"~:x\",1162,\"~:y\",476.99997181105346]],[\"^;\",[\"^ \",\"~:x\",1142,\"~:y\",476.99997181105346]]],\"~:r2\",0,\"~:shape-ref\",\"~u9299427e-8172-80bb-8007-90e7059421c6\",\"~:show-content\",true,\"~:proportion-lock\",false,\"~:transform-inverse\",[\"^3\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:page-id\",\"~u7c4e00d1-1f97-8161-8007-8f7861f33b60\",\"~:r3\",0,\"~:r1\",0,\"~:id\",\"~u9299427e-8172-80bb-8007-90e72469bf92\",\"~:parent-id\",\"~u9299427e-8172-80bb-8007-90e72469bf90\",\"~:applied-tokens\",[\"^ \"],\"~:component-id\",\"~uc8b014fe-f285-8021-8007-8ea4f64a1c9b\",\"~:frame-id\",\"~u9299427e-8172-80bb-8007-90e72469bf90\",\"~:strokes\",[],\"~:x\",1142,\"~:proportion\",1,\"~:r4\",0,\"~:selrect\",[\"~#rect\",[\"^ \",\"~:x\",1142,\"~:y\",458.99997181105346,\"^7\",20,\"~:height\",18,\"~:x1\",1142,\"~:y1\",458.99997181105346,\"~:x2\",1162,\"~:y2\",476.99997181105346]],\"~:fills\",[],\"~:flip-x\",null,\"^N\",18,\"~:component-file\",\"~ud0eb4518-f33d-81e1-8007-8fe418fea255\",\"~:flip-y\",null,\"~:shapes\",[\"~u9299427e-8172-80bb-8007-90e72469bf93\"]]]",
"~u9299427e-8172-80bb-8007-90e71cbc3432": "[\"~#shape\",[\"^ \",\"~:y\",449.99997181105346,\"~:hide-fill-on-export\",false,\"~:transform\",[\"~#matrix\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:rotation\",0,\"~:hide-in-viewer\",true,\"~:name\",\"svg-path\",\"~:width\",20,\"~:type\",\"~:frame\",\"~:points\",[[\"~#point\",[\"^ \",\"~:x\",806,\"~:y\",449.99997181105346]],[\"^;\",[\"^ \",\"~:x\",826,\"~:y\",449.99997181105346]],[\"^;\",[\"^ \",\"~:x\",826,\"~:y\",467.99997181105346]],[\"^;\",[\"^ \",\"~:x\",806,\"~:y\",467.99997181105346]]],\"~:r2\",0,\"~:shape-ref\",\"~u9299427e-8172-80bb-8007-90e7059421c6\",\"~:show-content\",true,\"~:proportion-lock\",false,\"~:transform-inverse\",[\"^3\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:page-id\",\"~u7c4e00d1-1f97-8161-8007-8f7861f33b60\",\"~:r3\",0,\"~:r1\",0,\"~:id\",\"~u9299427e-8172-80bb-8007-90e71cbc3432\",\"~:parent-id\",\"~u9299427e-8172-80bb-8007-90e71cbc3430\",\"~:applied-tokens\",[\"^ \"],\"~:component-id\",\"~uc8b014fe-f285-8021-8007-8ea4f64a1c9b\",\"~:frame-id\",\"~u9299427e-8172-80bb-8007-90e71cbc3430\",\"~:strokes\",[],\"~:x\",806,\"~:proportion\",1,\"~:r4\",0,\"~:selrect\",[\"~#rect\",[\"^ \",\"~:x\",806,\"~:y\",449.99997181105346,\"^7\",20,\"~:height\",18,\"~:x1\",806,\"~:y1\",449.99997181105346,\"~:x2\",826,\"~:y2\",467.99997181105346]],\"~:fills\",[],\"~:flip-x\",null,\"^N\",18,\"~:component-file\",\"~ud0eb4518-f33d-81e1-8007-8fe418fea255\",\"~:flip-y\",null,\"~:shapes\",[\"~u9299427e-8172-80bb-8007-90e71cbc3433\"]]]",
"~u94eaebe4-addd-80d1-8007-79d508a9dc30": "[\"~#shape\",[\"^ \",\"~:y\",437.999988316858,\"~:hide-fill-on-export\",false,\"~:transform\",[\"~#matrix\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:rotation\",0,\"~:hide-in-viewer\",true,\"~:name\",\"Board Child\",\"~:width\",80,\"~:type\",\"~:frame\",\"~:points\",[[\"~#point\",[\"^ \",\"~:x\",295.0000081062317,\"~:y\",437.999988316858]],[\"^;\",[\"^ \",\"~:x\",375.0000081062317,\"~:y\",437.999988316858]],[\"^;\",[\"^ \",\"~:x\",375.0000081062317,\"~:y\",517.999988316858]],[\"^;\",[\"^ \",\"~:x\",295.0000081062317,\"~:y\",517.999988316858]]],\"~:show-content\",true,\"~:proportion-lock\",false,\"~:transform-inverse\",[\"^3\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:page-id\",\"~u02e9633d-4ce7-80da-8007-736558496fa8\",\"~:constraints-v\",\"~:top\",\"~:constraints-h\",\"~:left\",\"~:id\",\"~u94eaebe4-addd-80d1-8007-79d508a9dc30\",\"~:parent-id\",\"~u94eaebe4-addd-80d1-8007-79d508a9dc2f\",\"~:frame-id\",\"~u94eaebe4-addd-80d1-8007-79d508a9dc2f\",\"~:strokes\",[],\"~:x\",295.0000081062317,\"~:proportion\",1,\"~:selrect\",[\"~#rect\",[\"^ \",\"~:x\",295.0000081062317,\"~:y\",437.999988316858,\"^7\",80,\"~:height\",80,\"~:x1\",295.0000081062317,\"~:y1\",437.999988316858,\"~:x2\",375.0000081062317,\"~:y2\",517.999988316858]],\"~:fills\",[],\"~:flip-x\",null,\"^K\",80,\"~:flip-y\",null,\"~:shapes\",[\"~u94eaebe4-addd-80d1-8007-79d508aa2885\",\"~u94eaebe4-addd-80d1-8007-79d508aa2886\"]]]",
"~u94eaebe4-addd-80d1-8007-79d509800791": "[\"~#shape\",[\"^ \",\"~:y\",570.0000417226197,\"~:hide-fill-on-export\",false,\"~:layout-gap-type\",\"~:multiple\",\"~:rx\",8,\"~:layout-padding\",[\"^ \",\"~:p1\",8,\"~:p2\",12,\"~:p3\",8,\"~:p4\",12],\"~:transform\",[\"~#matrix\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:rotation\",0,\"~:layout-wrap-type\",\"~:nowrap\",\"~:layout\",\"~:flex\",\"~:hide-in-viewer\",true,\"~:name\",\"Dark / Button / Primary / Text / Default\",\"~:layout-align-items\",\"~:center\",\"~:width\",66,\"~:layout-padding-type\",\"~:simple\",\"~:type\",\"~:frame\",\"~:points\",[[\"~#point\",[\"^ \",\"~:x\",302.0000081062317,\"~:y\",570.0000417226197]],[\"^K\",[\"^ \",\"~:x\",368.0000081062317,\"~:y\",570.0000417226197]],[\"^K\",[\"^ \",\"~:x\",368.0000081062317,\"~:y\",602.0000417226197]],[\"^K\",[\"^ \",\"~:x\",302.0000081062317,\"~:y\",602.0000417226197]]],\"~:r2\",8,\"~:show-content\",true,\"~:proportion-lock\",false,\"~:layout-gap\",[\"^ \",\"~:row-gap\",4,\"~:column-gap\",4],\"~:transform-inverse\",[\"^;\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:page-id\",\"~u02e9633d-4ce7-80da-8007-736558496fa8\",\"~:r3\",8,\"~:layout-justify-content\",\"^D\",\"~:r1\",8,\"~:id\",\"~u94eaebe4-addd-80d1-8007-79d509800791\",\"~:parent-id\",\"~u94eaebe4-addd-80d1-8007-79d50980078f\",\"~:layout-flex-dir\",\"~:row\",\"~:layout-align-content\",\"~:stretch\",\"~:frame-id\",\"~u94eaebe4-addd-80d1-8007-79d50980078f\",\"~:strokes\",[],\"~:x\",302.0000081062317,\"~:proportion\",1,\"~:r4\",8,\"~:selrect\",[\"~#rect\",[\"^ \",\"~:x\",302.0000081062317,\"~:y\",570.0000417226197,\"^E\",66,\"~:height\",32,\"~:x1\",302.0000081062317,\"~:y1\",570.0000417226197,\"~:x2\",368.0000081062317,\"~:y2\",602.0000417226197]],\"~:fills\",[[\"^ \",\"~:fill-color\",\"#7efff5\",\"~:fill-opacity\",1]],\"~:flip-x\",null,\"~:ry\",8,\"^17\",32,\"~:flip-y\",null,\"~:shapes\",[\"~u94eaebe4-addd-80d1-8007-79d509800792\"]]]",
"~u9299427e-8172-80bb-8007-90e72469bf93": "[\"~#shape\",[\"^ \",\"~:y\",null,\"~:stroke-cap-start\",\"round\",\"~:transform\",[\"~#matrix\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:rotation\",null,\"~:index\",null,\"~:content\",[\"~#penpot/path-data\",\"~bAQAAAAAAAAAAAAAAAAAAAAAAAAAA4JBE/v/qQwMAAACuD5FE/kTqQwBAkUT+ZOlDAECRRP4/6EMDAAAAAECRRD675kM08ZBE/n/lQwCQkET+f+VDAwAAAK5XkET+f+VDADCQRP6/5UMAAJBE/n/mQwMAAAAA0I9E/r/lQ1Koj0T+f+VDAHCPRP5/5UMDAAAAzA6PRP5/5UMAwI5EPrvmQwDAjkT+P+hDAwAAAADAjkR+ZulDAPCORH5G6kMAII9E/v/qQwIAAAAAAAAAAAAAAAAAAAAAAAAAAACQRP5/7kMCAAAAAAAAAAAAAAAAAAAAAAAAAADgkET+/+pD\"],\"~:name\",\"svg-path\",\"~:width\",null,\"~:type\",\"~:path\",\"~:svg-attrs\",[\"^ \",\"~:fill\",\"none\",\"~:stroke-linecap\",\"round\",\"~:stroke-linejoin\",\"round\"],\"~:points\",[[\"~#point\",[\"^ \",\"~:x\",1142,\"~:y\",458.99997181105346]],[\"^A\",[\"^ \",\"~:x\",1162,\"~:y\",458.99997181105346]],[\"^A\",[\"^ \",\"~:x\",1162,\"~:y\",476.99997181105346]],[\"^A\",[\"^ \",\"~:x\",1142,\"~:y\",476.99997181105346]]],\"~:shape-ref\",\"~u9299427e-8172-80bb-8007-90e705944588\",\"~:proportion-lock\",false,\"~:stroke-cap-end\",\"round\",\"~:transform-inverse\",[\"^3\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:page-id\",\"~u7c4e00d1-1f97-8161-8007-8f7861f33b60\",\"~:constraints-v\",\"~:scale\",\"~:svg-transform\",[\"^ \",\"~:a\",1,\"~:b\",0,\"~:c\",0,\"~:d\",1,\"~:e\",0,\"~:f\",0],\"~:constraints-h\",\"^H\",\"~:id\",\"~u9299427e-8172-80bb-8007-90e72469bf93\",\"~:parent-id\",\"~u9299427e-8172-80bb-8007-90e72469bf92\",\"~:svg-viewbox\",[\"^ \",\"~:y\",3,\"~:y1\",3,\"^9\",20,\"~:x\",2,\"~:x1\",2,\"~:y2\",21,\"~:x2\",22,\"~:height\",18],\"~:applied-tokens\",[\"^ \",\"~:stroke-color\",\"color.icon.default\"],\"~:svg-defs\",[\"^ \"],\"~:frame-id\",\"~u9299427e-8172-80bb-8007-90e72469bf92\",\"~:strokes\",[[\"^ \",\"~:stroke-style\",\"~:solid\",\"~:stroke-alignment\",\"~:inner\",\"~:stroke-width\",2,\"^T\",\"#ffffff\",\"~:stroke-opacity\",1]],\"~:x\",null,\"~:proportion\",1,\"~:selrect\",[\"~#rect\",[\"^ \",\"~:x\",1142,\"~:y\",458.99997181105346,\"^9\",20,\"^R\",18,\"^O\",1142,\"^N\",458.99997181105346,\"^Q\",1162,\"^P\",476.99997181105346]],\"~:fills\",[],\"~:flip-x\",null,\"^R\",null,\"~:flip-y\",null]]",
"~u9299427e-8172-80bb-8007-90e71cbc3433": "[\"~#shape\",[\"^ \",\"~:y\",null,\"~:stroke-cap-start\",\"round\",\"~:transform\",[\"~#matrix\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:rotation\",null,\"~:index\",null,\"~:content\",[\"~#penpot/path-data\",\"~bAQAAAAAAAAAAAAAAAAAAAAAAAAAAwE1E/n/mQwMAAABcH05E/sTlQwCATkT+5ORDAIBORP6/40MDAAAAAIBORD474kNo4k1E/v/gQwAgTUT+/+BDAwAAAFyvTET+/+BDAGBMRP4/4UMAAExE/v/hQwMAAAAAoEtE/j/hQ6RQS0T+/+BDAOBKRP7/4EMDAAAAmB1KRP7/4EMAgElEPjviQwCASUT+v+NDAwAAAACASUR+5uRDAOBJRH7G5UMAQEpE/n/mQwIAAAAAAAAAAAAAAAAAAAAAAAAAAABMRP7/6UMCAAAAAAAAAAAAAAAAAAAAAAAAAADATUT+f+ZD\"],\"~:name\",\"svg-path\",\"~:width\",null,\"~:type\",\"~:path\",\"~:svg-attrs\",[\"^ \",\"~:fill\",\"none\",\"~:stroke-linecap\",\"round\",\"~:stroke-linejoin\",\"round\"],\"~:points\",[[\"~#point\",[\"^ \",\"~:x\",806,\"~:y\",449.99997181105346]],[\"^A\",[\"^ \",\"~:x\",826,\"~:y\",449.99997181105346]],[\"^A\",[\"^ \",\"~:x\",826,\"~:y\",467.99997181105346]],[\"^A\",[\"^ \",\"~:x\",806,\"~:y\",467.99997181105346]]],\"~:shape-ref\",\"~u9299427e-8172-80bb-8007-90e705944588\",\"~:proportion-lock\",false,\"~:stroke-cap-end\",\"round\",\"~:transform-inverse\",[\"^3\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:page-id\",\"~u7c4e00d1-1f97-8161-8007-8f7861f33b60\",\"~:constraints-v\",\"~:scale\",\"~:svg-transform\",[\"^ \",\"~:a\",1,\"~:b\",0,\"~:c\",0,\"~:d\",1,\"~:e\",0,\"~:f\",0],\"~:constraints-h\",\"^H\",\"~:id\",\"~u9299427e-8172-80bb-8007-90e71cbc3433\",\"~:parent-id\",\"~u9299427e-8172-80bb-8007-90e71cbc3432\",\"~:svg-viewbox\",[\"^ \",\"~:y\",3,\"~:y1\",3,\"^9\",20,\"~:x\",2,\"~:x1\",2,\"~:y2\",21,\"~:x2\",22,\"~:height\",18],\"~:applied-tokens\",[\"^ \",\"~:stroke-color\",\"color.icon.default\"],\"~:svg-defs\",[\"^ \"],\"~:frame-id\",\"~u9299427e-8172-80bb-8007-90e71cbc3432\",\"~:strokes\",[[\"^ \",\"~:stroke-style\",\"~:solid\",\"~:stroke-alignment\",\"~:inner\",\"~:stroke-width\",2,\"^T\",\"#ffffff\",\"~:stroke-opacity\",1]],\"~:x\",null,\"~:proportion\",1,\"~:selrect\",[\"~#rect\",[\"^ \",\"~:x\",806,\"~:y\",449.99997181105346,\"^9\",20,\"^R\",18,\"^O\",806,\"^N\",449.99997181105346,\"^Q\",826,\"^P\",467.99997181105346]],\"~:fills\",[],\"~:flip-x\",null,\"^R\",null,\"~:flip-y\",null]]",
"~u94eaebe4-addd-80d1-8007-79d509800792": "[\"~#shape\",[\"^ \",\"~:y\",578.0000417226197,\"~:hide-fill-on-export\",false,\"~:layout-gap-type\",\"~:multiple\",\"~:layout-padding\",[\"^ \",\"~:p1\",0,\"~:p2\",2,\"~:p3\",0,\"~:p4\",2],\"~:transform\",[\"~#matrix\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:rotation\",0,\"~:layout-wrap-type\",\"~:nowrap\",\"~:layout\",\"~:flex\",\"~:hide-in-viewer\",true,\"~:name\",\"_Utilities / Text / White\",\"~:layout-align-items\",\"~:start\",\"~:width\",42,\"~:layout-padding-type\",\"~:simple\",\"~:transforming\",false,\"~:type\",\"~:frame\",\"~:points\",[[\"~#point\",[\"^ \",\"~:x\",314.0000081062317,\"~:y\",578.0000417226197]],[\"^K\",[\"^ \",\"~:x\",356.0000081062317,\"~:y\",578.0000417226197]],[\"^K\",[\"^ \",\"~:x\",356.0000081062317,\"~:y\",594.0000417226197]],[\"^K\",[\"^ \",\"~:x\",314.0000081062317,\"~:y\",594.0000417226197]]],\"~:show-content\",true,\"~:layout-item-h-sizing\",\"~:auto\",\"~:proportion-lock\",false,\"~:layout-gap\",[\"^ \",\"~:row-gap\",0,\"~:column-gap\",6],\"~:transform-inverse\",[\"^:\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:page-id\",\"~u02e9633d-4ce7-80da-8007-736558496fa8\",\"~:layout-justify-content\",\"~:center\",\"~:id\",\"~u94eaebe4-addd-80d1-8007-79d509800792\",\"~:parent-id\",\"~u94eaebe4-addd-80d1-8007-79d509800791\",\"~:layout-flex-dir\",\"~:column\",\"~:layout-align-content\",\"~:stretch\",\"~:frame-id\",\"~u94eaebe4-addd-80d1-8007-79d509800791\",\"~:strokes\",[],\"~:x\",314.0000081062317,\"~:proportion\",1,\"~:selrect\",[\"~#rect\",[\"^ \",\"~:x\",314.0000081062317,\"~:y\",578.0000417226197,\"^D\",42,\"~:height\",16,\"~:x1\",314.0000081062317,\"~:y1\",578.0000417226197,\"~:x2\",356.0000081062317,\"~:y2\",594.0000417226197]],\"~:fills\",[],\"~:flip-x\",null,\"^16\",16,\"~:flip-y\",null,\"~:shapes\",[\"~u94eaebe4-addd-80d1-8007-79d509800793\"]]]",
"~u9299427e-8172-80bb-8007-90e72469bf90": "[\"~#shape\",[\"^ \",\"~:y\",455.9999966065857,\"~:rx\",0,\"~:transform\",[\"~#matrix\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:rotation\",null,\"~:index\",null,\"~:hide-in-viewer\",true,\"~:name\",\"heart\",\"~:width\",24,\"~:type\",\"~:frame\",\"~:svg-attrs\",[\"^ \",\"^8\",\"24\",\"~:height\",\"24\"],\"~:points\",[[\"~#point\",[\"^ \",\"~:x\",1140,\"~:y\",455.9999966065857]],[\"^>\",[\"^ \",\"~:x\",1164,\"~:y\",455.9999966065857]],[\"^>\",[\"^ \",\"~:x\",1164,\"~:y\",479.9999966065857]],[\"^>\",[\"^ \",\"~:x\",1140,\"~:y\",479.9999966065857]]],\"~:r2\",0,\"~:shape-ref\",\"~u9299427e-8172-80bb-8007-90e7059421c4\",\"~:show-content\",true,\"~:proportion-lock\",false,\"~:transform-inverse\",[\"^3\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:page-id\",\"~u7c4e00d1-1f97-8161-8007-8f7861f33b60\",\"~:r3\",0,\"~:constraints-v\",\"~:top\",\"~:constraints-h\",\"~:left\",\"~:r1\",0,\"~:id\",\"~u9299427e-8172-80bb-8007-90e72469bf90\",\"~:parent-id\",\"~u9299427e-8172-80bb-8007-90e72469bf8e\",\"~:frame-id\",\"~u9299427e-8172-80bb-8007-90e72469bf8e\",\"~:strokes\",[],\"~:x\",1140,\"~:proportion\",1,\"~:r4\",0,\"~:selrect\",[\"~#rect\",[\"^ \",\"~:x\",1140,\"~:y\",455.9999966065857,\"^8\",24,\"^<\",24,\"~:x1\",1140,\"~:y1\",455.9999966065857,\"~:x2\",1164,\"~:y2\",479.9999966065857]],\"~:fills\",[],\"~:flip-x\",null,\"~:ry\",0,\"^<\",24,\"~:flip-y\",null,\"~:shapes\",[\"~u9299427e-8172-80bb-8007-90e72469bf91\",\"~u9299427e-8172-80bb-8007-90e72469bf92\"]]]",
"~u9299427e-8172-80bb-8007-90e71cbc3430": "[\"~#shape\",[\"^ \",\"~:y\",446.9999966065857,\"~:rx\",0,\"~:transform\",[\"~#matrix\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:rotation\",null,\"~:index\",null,\"~:hide-in-viewer\",true,\"~:name\",\"heart\",\"~:width\",24,\"~:type\",\"~:frame\",\"~:svg-attrs\",[\"^ \",\"^8\",\"24\",\"~:height\",\"24\"],\"~:points\",[[\"~#point\",[\"^ \",\"~:x\",804,\"~:y\",446.9999966065857]],[\"^>\",[\"^ \",\"~:x\",828,\"~:y\",446.9999966065857]],[\"^>\",[\"^ \",\"~:x\",828,\"~:y\",470.9999966065857]],[\"^>\",[\"^ \",\"~:x\",804,\"~:y\",470.9999966065857]]],\"~:r2\",0,\"~:shape-ref\",\"~u9299427e-8172-80bb-8007-90e7059421c4\",\"~:show-content\",true,\"~:proportion-lock\",false,\"~:transform-inverse\",[\"^3\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:page-id\",\"~u7c4e00d1-1f97-8161-8007-8f7861f33b60\",\"~:r3\",0,\"~:constraints-v\",\"~:top\",\"~:constraints-h\",\"~:left\",\"~:r1\",0,\"~:id\",\"~u9299427e-8172-80bb-8007-90e71cbc3430\",\"~:parent-id\",\"~u9299427e-8172-80bb-8007-90e71cbc342f\",\"~:frame-id\",\"~u9299427e-8172-80bb-8007-90e71cbc342f\",\"~:strokes\",[],\"~:x\",804,\"~:proportion\",1,\"~:r4\",0,\"~:selrect\",[\"~#rect\",[\"^ \",\"~:x\",804,\"~:y\",446.9999966065857,\"^8\",24,\"^<\",24,\"~:x1\",804,\"~:y1\",446.9999966065857,\"~:x2\",828,\"~:y2\",470.9999966065857]],\"~:fills\",[],\"~:flip-x\",null,\"~:ry\",0,\"^<\",24,\"~:flip-y\",null,\"~:shapes\",[\"~u9299427e-8172-80bb-8007-90e71cbc3431\",\"~u9299427e-8172-80bb-8007-90e71cbc3432\"]]]",
"~u94eaebe4-addd-80d1-8007-79d509800793": "[\"~#shape\",[\"^ \",\"~:y\",579.0000417226199,\"~:transform\",[\"~#matrix\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:rotation\",0,\"~:grow-type\",\"~:auto-width\",\"~:index\",null,\"~:content\",[\"^ \",\"~:type\",\"root\",\"~:children\",[[\"^ \",\"^8\",\"paragraph-set\",\"^9\",[[\"^ \",\"~:line-height\",\"1.2\",\"~:path\",\"\",\"~:font-style\",\"normal\",\"^9\",[[\"^ \",\"^:\",\"1.2\",\"^;\",\"\",\"^<\",\"normal\",\"~:text-transform\",\"uppercase\",\"~:text-align\",\"left\",\"~:font-id\",\"gfont-work-sans\",\"~:font-size\",\"12\",\"~:font-weight\",\"500\",\"~:modified-at\",\"2024-06-04T14:15:09.786Z\",\"~:font-variant-id\",\"500\",\"~:text-decoration\",\"underline\",\"~:letter-spacing\",\"0\",\"~:fills\",[[\"^ \",\"~:fill-color\",\"#000000\",\"~:fill-color-ref-file\",\"~ucaa70d02-51e1-81ae-8007-735e7de3d7bc\",\"~:fill-opacity\",1,\"~:fill-color-ref-id\",\"~udfa92acf-7d18-8079-8003-baba8789d8af\"]],\"~:font-family\",\"Work Sans\",\"~:text\",\"Label\"]],\"^=\",\"uppercase\",\"^>\",\"center\",\"^?\",\"gfont-work-sans\",\"^@\",\"12\",\"^A\",\"500\",\"^8\",\"paragraph\",\"^B\",\"2024-06-04T14:15:09.786Z\",\"^C\",\"500\",\"^D\",\"underline\",\"^E\",\"0\",\"^F\",[[\"^ \",\"^G\",\"#000000\",\"^H\",\"~ucaa70d02-51e1-81ae-8007-735e7de3d7bc\",\"^I\",1,\"^J\",\"~udfa92acf-7d18-8079-8003-baba8789d8af\"]],\"^K\",\"Work Sans\"]]]],\"~:vertical-align\",\"center\",\"^F\",[[\"^ \",\"^G\",\"#000000\",\"^I\",1]]],\"~:hide-in-viewer\",true,\"~:name\",\"Input\",\"~:saved-component-root\",null,\"~:width\",38,\"^8\",\"^L\",\"~:points\",[[\"~#point\",[\"^ \",\"~:x\",316.0000081062317,\"~:y\",579.0000417226199]],[\"^S\",[\"^ \",\"~:x\",354.0000081062317,\"~:y\",579.0000417226199]],[\"^S\",[\"^ \",\"~:x\",354.0000081062317,\"~:y\",594.0000417226195]],[\"^S\",[\"^ \",\"~:x\",316.0000081062317,\"~:y\",594.0000417226199]]],\"~:layout-item-h-sizing\",\"~:fix\",\"~:transform-inverse\",[\"^2\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:page-id\",\"~u02e9633d-4ce7-80da-8007-736558496fa8\",\"~:id\",\"~u94eaebe4-addd-80d1-8007-79d509800793\",\"~:parent-id\",\"~u94eaebe4-addd-80d1-8007-79d509800792\",\"~:position-data\",[[\"^ \",\"~:y\",593.340087890625,\"^:\",\"1.2\",\"^<\",\"normal\",\"^=\",\"uppercase\",\"^>\",\"left\",\"^?\",\"sourcesanspro\",\"^@\",\"12\",\"^A\",\"500\",\"~:text-direction\",\"ltr\",\"^Q\",37.94000244140625,\"^C\",\"regular\",\"^D\",\"underline\",\"^E\",\"0\",\"~:x\",316.0299987792969,\"^F\",[[\"^ \",\"^G\",\"#000000\",\"^H\",\"~ucaa70d02-51e1-81ae-8007-735e7de3d7bc\",\"^I\",1,\"^J\",\"~udfa92acf-7d18-8079-8003-baba8789d8af\"]],\"~:direction\",\"ltr\",\"^K\",\"Work Sans\",\"~:height\",14.08001708984375,\"^L\",\"Label\"]],\"~:frame-id\",\"~u94eaebe4-addd-80d1-8007-79d509800792\",\"~:strokes\",[],\"~:x\",316.0000081062317,\"~:selrect\",[\"~#rect\",[\"^ \",\"~:x\",316.0000081062317,\"~:y\",579.0000417226199,\"^Q\",38,\"^11\",15,\"~:x1\",316.0000081062317,\"~:y1\",579.0000417226199,\"~:x2\",354.0000081062317,\"~:y2\",594.0000417226199]],\"^F\",[],\"~:flip-x\",null,\"^11\",15,\"~:flip-y\",null]]",
"~u9299427e-8172-80bb-8007-90e72469bf91": "[\"~#shape\",[\"^ \",\"~:y\",456.0000271241638,\"~:transform\",[\"~#matrix\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:rotation\",null,\"~:index\",null,\"~:name\",\"base-background\",\"~:width\",24,\"~:type\",\"~:rect\",\"~:svg-attrs\",[\"^ \",\"~:fill\",\"none\",\"~:stroke-linejoin\",\"round\",\"~:stroke-linecap\",\"round\",\"~:id\",\"base-background\"],\"~:points\",[[\"~#point\",[\"^ \",\"~:x\",1140,\"~:y\",456.0000271241638]],[\"^?\",[\"^ \",\"~:x\",1164,\"~:y\",456.0000271241638]],[\"^?\",[\"^ \",\"~:x\",1164,\"~:y\",480.0000271241638]],[\"^?\",[\"^ \",\"~:x\",1140,\"~:y\",480.0000271241638]]],\"~:shape-ref\",\"~u9299427e-8172-80bb-8007-90e7059421c5\",\"~:proportion-lock\",false,\"~:transform-inverse\",[\"^2\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:page-id\",\"~u7c4e00d1-1f97-8161-8007-8f7861f33b60\",\"~:hidden\",true,\"^=\",\"~u9299427e-8172-80bb-8007-90e72469bf91\",\"~:parent-id\",\"~u9299427e-8172-80bb-8007-90e72469bf90\",\"~:svg-viewbox\",[\"^ \",\"~:y\",0,\"~:y1\",0,\"^6\",24,\"~:x\",0,\"~:x1\",0,\"~:y2\",24,\"~:x2\",24,\"~:height\",24],\"~:svg-defs\",[\"^ \"],\"~:frame-id\",\"~u9299427e-8172-80bb-8007-90e72469bf90\",\"~:strokes\",[[\"^ \",\"~:stroke-style\",\"~:solid\",\"~:stroke-color\",\"#ffffff\",\"~:stroke-opacity\",1,\"~:stroke-alignment\",\"~:inner\",\"~:stroke-width\",2]],\"~:x\",1140,\"~:proportion\",1,\"~:selrect\",[\"~#rect\",[\"^ \",\"~:x\",1140,\"~:y\",456.0000271241638,\"^6\",24,\"^K\",24,\"^H\",1140,\"^G\",456.0000271241638,\"^J\",1164,\"^I\",480.0000271241638]],\"~:fills\",[],\"~:flip-x\",null,\"^K\",24,\"~:flip-y\",null]]",
"~u9299427e-8172-80bb-8007-90e71cbc3431": "[\"~#shape\",[\"^ \",\"~:y\",447.0000271241638,\"~:transform\",[\"~#matrix\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:rotation\",null,\"~:index\",null,\"~:name\",\"base-background\",\"~:width\",24,\"~:type\",\"~:rect\",\"~:svg-attrs\",[\"^ \",\"~:fill\",\"none\",\"~:stroke-linejoin\",\"round\",\"~:stroke-linecap\",\"round\",\"~:id\",\"base-background\"],\"~:points\",[[\"~#point\",[\"^ \",\"~:x\",804,\"~:y\",447.0000271241638]],[\"^?\",[\"^ \",\"~:x\",828,\"~:y\",447.0000271241638]],[\"^?\",[\"^ \",\"~:x\",828,\"~:y\",471.0000271241638]],[\"^?\",[\"^ \",\"~:x\",804,\"~:y\",471.0000271241638]]],\"~:shape-ref\",\"~u9299427e-8172-80bb-8007-90e7059421c5\",\"~:proportion-lock\",false,\"~:transform-inverse\",[\"^2\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:page-id\",\"~u7c4e00d1-1f97-8161-8007-8f7861f33b60\",\"~:hidden\",true,\"^=\",\"~u9299427e-8172-80bb-8007-90e71cbc3431\",\"~:parent-id\",\"~u9299427e-8172-80bb-8007-90e71cbc3430\",\"~:svg-viewbox\",[\"^ \",\"~:y\",0,\"~:y1\",0,\"^6\",24,\"~:x\",0,\"~:x1\",0,\"~:y2\",24,\"~:x2\",24,\"~:height\",24],\"~:svg-defs\",[\"^ \"],\"~:frame-id\",\"~u9299427e-8172-80bb-8007-90e71cbc3430\",\"~:strokes\",[[\"^ \",\"~:stroke-style\",\"~:solid\",\"~:stroke-color\",\"#ffffff\",\"~:stroke-opacity\",1,\"~:stroke-alignment\",\"~:inner\",\"~:stroke-width\",2]],\"~:x\",804,\"~:proportion\",1,\"~:selrect\",[\"~#rect\",[\"^ \",\"~:x\",804,\"~:y\",447.0000271241638,\"^6\",24,\"^K\",24,\"^H\",804,\"^G\",447.0000271241638,\"^J\",828,\"^I\",471.0000271241638]],\"~:fills\",[],\"~:flip-x\",null,\"^K\",24,\"~:flip-y\",null]]",
"~u77c71dba-32ee-804c-8007-736561cf8584": "[\"~#shape\",[\"^ \",\"~:y\",222.00000357564704,\"~:hide-fill-on-export\",false,\"~:transform\",[\"~#matrix\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:rotation\",0,\"~:hide-in-viewer\",true,\"~:name\",\"Board Child\",\"~:width\",80,\"~:type\",\"~:frame\",\"~:points\",[[\"~#point\",[\"^ \",\"~:x\",379.0000081062317,\"~:y\",222.00000357564704]],[\"^;\",[\"^ \",\"~:x\",459.0000081062317,\"~:y\",222.00000357564704]],[\"^;\",[\"^ \",\"~:x\",459.0000081062317,\"~:y\",302.00000357564704]],[\"^;\",[\"^ \",\"~:x\",379.0000081062317,\"~:y\",302.00000357564704]]],\"~:show-content\",true,\"~:proportion-lock\",false,\"~:transform-inverse\",[\"^3\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:page-id\",\"~u02e9633d-4ce7-80da-8007-736558496fa8\",\"~:constraints-v\",\"~:top\",\"~:constraints-h\",\"~:left\",\"~:id\",\"~u77c71dba-32ee-804c-8007-736561cf8584\",\"~:parent-id\",\"~u77c71dba-32ee-804c-8007-736561cf857f\",\"~:frame-id\",\"~u77c71dba-32ee-804c-8007-736561cf857f\",\"~:strokes\",[],\"~:x\",379.0000081062317,\"~:proportion\",1,\"~:selrect\",[\"~#rect\",[\"^ \",\"~:x\",379.0000081062317,\"~:y\",222.00000357564704,\"^7\",80,\"~:height\",80,\"~:x1\",379.0000081062317,\"~:y1\",222.00000357564704,\"~:x2\",459.0000081062317,\"~:y2\",302.00000357564704]],\"~:fills\",[],\"~:flip-x\",null,\"^K\",80,\"~:flip-y\",null,\"~:shapes\",[\"~u77c71dba-32ee-804c-8007-736561cff457\",\"~u77c71dba-32ee-804c-8007-736561cff458\"]]]",
"~u94eaebe4-addd-80d1-8007-79d5055d6859": "[\"~#shape\",[\"^ \",\"~:y\",330.00000202817546,\"~:hide-fill-on-export\",false,\"~:layout-gap-type\",\"~:multiple\",\"~:layout-padding\",[\"^ \",\"~:p1\",0,\"~:p2\",12,\"~:p3\",0,\"~:p4\",12],\"~:transform\",[\"~#matrix\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:rotation\",0,\"~:layout-wrap-type\",\"~:wrap\",\"~:layout\",\"~:flex\",\"~:hide-in-viewer\",true,\"~:name\",\"Board Parent 2\",\"~:layout-align-items\",\"~:start\",\"~:width\",272,\"~:layout-padding-type\",\"~:simple\",\"~:type\",\"~:frame\",\"~:points\",[[\"~#point\",[\"^ \",\"~:x\",283.0000081062317,\"~:y\",330.00000202817546]],[\"^J\",[\"^ \",\"~:x\",555.0000081062317,\"~:y\",330.00000202817546]],[\"^J\",[\"^ \",\"~:x\",555.0000081062317,\"~:y\",409.99998986432956]],[\"^J\",[\"^ \",\"~:x\",283.0000081062317,\"~:y\",409.99998986432956]]],\"~:show-content\",true,\"~:proportion-lock\",false,\"~:layout-gap\",[\"^ \",\"~:row-gap\",4,\"~:column-gap\",4],\"~:transform-inverse\",[\"^:\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:page-id\",\"~u02e9633d-4ce7-80da-8007-736558496fa8\",\"~:layout-item-v-sizing\",\"~:fix\",\"~:layout-justify-content\",\"~:center\",\"~:id\",\"~u94eaebe4-addd-80d1-8007-79d5055d6859\",\"~:parent-id\",\"~u00000000-0000-0000-0000-000000000000\",\"~:layout-flex-dir\",\"~:row-reverse\",\"~:layout-align-content\",\"~:stretch\",\"~:frame-id\",\"~u00000000-0000-0000-0000-000000000000\",\"~:strokes\",[],\"~:x\",283.0000081062317,\"~:proportion\",1,\"~:selrect\",[\"~#rect\",[\"^ \",\"~:x\",283.0000081062317,\"~:y\",330.00000202817546,\"^D\",272,\"~:height\",79.9999878361541,\"~:x1\",283.0000081062317,\"~:y1\",330.00000202817546,\"~:x2\",555.0000081062317,\"~:y2\",409.99998986432956]],\"~:fills\",[],\"~:flip-x\",null,\"^15\",79.9999878361541,\"~:flip-y\",null,\"~:shapes\",[\"~u94eaebe4-addd-80d1-8007-79d5055d685a\"]]]",
"~u94eaebe4-addd-80d1-8007-79d5055d685a": "[\"~#shape\",[\"^ \",\"~:y\",329.9999959462525,\"~:hide-fill-on-export\",false,\"~:transform\",[\"~#matrix\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:rotation\",0,\"~:hide-in-viewer\",true,\"~:name\",\"Board Child\",\"~:width\",80,\"~:type\",\"~:frame\",\"~:points\",[[\"~#point\",[\"^ \",\"~:x\",379.0000081062317,\"~:y\",329.9999959462525]],[\"^;\",[\"^ \",\"~:x\",459.0000081062317,\"~:y\",329.9999959462525]],[\"^;\",[\"^ \",\"~:x\",459.0000081062317,\"~:y\",409.9999959462525]],[\"^;\",[\"^ \",\"~:x\",379.0000081062317,\"~:y\",409.9999959462525]]],\"~:show-content\",true,\"~:proportion-lock\",false,\"~:transform-inverse\",[\"^3\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:page-id\",\"~u02e9633d-4ce7-80da-8007-736558496fa8\",\"~:constraints-v\",\"~:top\",\"~:constraints-h\",\"~:left\",\"~:id\",\"~u94eaebe4-addd-80d1-8007-79d5055d685a\",\"~:parent-id\",\"~u94eaebe4-addd-80d1-8007-79d5055d6859\",\"~:frame-id\",\"~u94eaebe4-addd-80d1-8007-79d5055d6859\",\"~:strokes\",[],\"~:x\",379.0000081062317,\"~:proportion\",1,\"~:selrect\",[\"~#rect\",[\"^ \",\"~:x\",379.0000081062317,\"~:y\",329.9999959462525,\"^7\",80,\"~:height\",80,\"~:x1\",379.0000081062317,\"~:y1\",329.9999959462525,\"~:x2\",459.0000081062317,\"~:y2\",409.9999959462525]],\"~:fills\",[],\"~:flip-x\",null,\"^K\",80,\"~:flip-y\",null,\"~:shapes\",[\"~u94eaebe4-addd-80d1-8007-79d5055d685b\",\"~u94eaebe4-addd-80d1-8007-79d5055d685c\"]]]",
"~u94eaebe4-addd-80d1-8007-79d5055d685b": "[\"~#shape\",[\"^ \",\"~:y\",329.9999959462525,\"~:rx\",8,\"~:transform\",[\"~#matrix\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:rotation\",0,\"~:grow-type\",\"~:fixed\",\"~:hide-in-viewer\",false,\"~:name\",\"Rectangle\",\"~:width\",80,\"~:transforming\",false,\"~:type\",\"~:rect\",\"~:points\",[[\"~#point\",[\"^ \",\"~:x\",379.0000081062317,\"~:y\",329.9999959462525]],[\"^>\",[\"^ \",\"~:x\",459.0000081062317,\"~:y\",329.9999959462525]],[\"^>\",[\"^ \",\"~:x\",459.0000081062317,\"~:y\",409.9999959462525]],[\"^>\",[\"^ \",\"~:x\",379.0000081062317,\"~:y\",409.9999959462525]]],\"~:r2\",8,\"~:proportion-lock\",false,\"~:transform-inverse\",[\"^3\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:page-id\",\"~u02e9633d-4ce7-80da-8007-736558496fa8\",\"~:r3\",8,\"~:r1\",8,\"~:id\",\"~u94eaebe4-addd-80d1-8007-79d5055d685b\",\"~:parent-id\",\"~u94eaebe4-addd-80d1-8007-79d5055d685a\",\"~:frame-id\",\"~u94eaebe4-addd-80d1-8007-79d5055d685a\",\"~:strokes\",[],\"~:x\",379.0000081062317,\"~:proportion\",1,\"~:r4\",8,\"~:selrect\",[\"~#rect\",[\"^ \",\"~:x\",379.0000081062317,\"~:y\",329.9999959462525,\"^9\",80,\"~:height\",80,\"~:x1\",379.0000081062317,\"~:y1\",329.9999959462525,\"~:x2\",459.0000081062317,\"~:y2\",409.9999959462525]],\"~:fills\",[[\"^ \",\"~:fill-color\",\"#e8e9ea\",\"~:fill-opacity\",1]],\"~:flip-x\",null,\"~:ry\",8,\"^M\",80,\"~:flip-y\",null]]",
"~u9299427e-8172-80bb-8007-90e71fba0f7e": "[\"~#shape\",[\"^ \",\"~:y\",191.99999475401955,\"~:hide-fill-on-export\",false,\"~:transform\",[\"~#matrix\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:rotation\",0,\"~:hide-in-viewer\",true,\"~:name\",\"img-city\",\"~:width\",265,\"~:type\",\"~:frame\",\"~:points\",[[\"~#point\",[\"^ \",\"~:x\",916,\"~:y\",191.99999475401978]],[\"^;\",[\"^ \",\"~:x\",1181,\"~:y\",191.99999475401978]],[\"^;\",[\"^ \",\"~:x\",1181,\"~:y\",369.9899634401968]],[\"^;\",[\"^ \",\"~:x\",916,\"~:y\",369.9899634401968]]],\"~:r2\",0,\"~:shape-ref\",\"~u9299427e-8172-80bb-8007-90e7059421c1\",\"~:layout-item-h-sizing\",\"~:fill\",\"~:proportion-lock\",false,\"~:transform-inverse\",[\"^3\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:page-id\",\"~u7c4e00d1-1f97-8161-8007-8f7861f33b60\",\"~:layout-item-v-sizing\",\"^?\",\"~:r3\",0,\"~:r1\",0,\"~:id\",\"~u9299427e-8172-80bb-8007-90e71fba0f7e\",\"~:parent-id\",\"~u9299427e-8172-80bb-8007-90e71fba0f7d\",\"~:frame-id\",\"~u9299427e-8172-80bb-8007-90e71fba0f7d\",\"~:strokes\",[],\"~:x\",916,\"~:proportion\",1,\"~:r4\",0,\"~:selrect\",[\"~#rect\",[\"^ \",\"~:x\",916,\"~:y\",191.99999475401955,\"^7\",265,\"~:height\",177.989968686177,\"~:x1\",916,\"~:y1\",191.99999475401955,\"~:x2\",1181,\"~:y2\",369.98996344019656]],\"~:fills\",[[\"^ \",\"~:fill-color\",\"#FFFFFF\",\"~:fill-opacity\",1]],\"~:flip-x\",null,\"^N\",177.989968686177,\"~:flip-y\",null,\"~:shapes\",[\"~u9299427e-8172-80bb-8007-90e71fba0f80\"]]]",
"~u94eaebe4-addd-80d1-8007-79d5055d685c": "[\"~#shape\",[\"^ \",\"~:y\",353.9999959462525,\"~:hide-fill-on-export\",false,\"~:layout-gap-type\",\"~:multiple\",\"~:rx\",8,\"~:layout-padding\",[\"^ \",\"~:p1\",8,\"~:p2\",12,\"~:p3\",8,\"~:p4\",12],\"~:transform\",[\"~#matrix\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:rotation\",0,\"~:layout-wrap-type\",\"~:nowrap\",\"~:layout\",\"~:flex\",\"~:hide-in-viewer\",true,\"~:name\",\"Dark / Button / Primary / Text / Default\",\"~:layout-align-items\",\"~:center\",\"~:width\",66,\"~:layout-padding-type\",\"~:simple\",\"~:type\",\"~:frame\",\"~:points\",[[\"~#point\",[\"^ \",\"~:x\",386.0000081062317,\"~:y\",353.9999959462525]],[\"^K\",[\"^ \",\"~:x\",452.0000081062317,\"~:y\",353.9999959462525]],[\"^K\",[\"^ \",\"~:x\",452.0000081062317,\"~:y\",385.9999959462525]],[\"^K\",[\"^ \",\"~:x\",386.0000081062317,\"~:y\",385.9999959462525]]],\"~:r2\",8,\"~:show-content\",true,\"~:proportion-lock\",false,\"~:layout-gap\",[\"^ \",\"~:row-gap\",4,\"~:column-gap\",4],\"~:transform-inverse\",[\"^;\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:page-id\",\"~u02e9633d-4ce7-80da-8007-736558496fa8\",\"~:r3\",8,\"~:layout-justify-content\",\"^D\",\"~:r1\",8,\"~:id\",\"~u94eaebe4-addd-80d1-8007-79d5055d685c\",\"~:parent-id\",\"~u94eaebe4-addd-80d1-8007-79d5055d685a\",\"~:layout-flex-dir\",\"~:row\",\"~:layout-align-content\",\"~:stretch\",\"~:frame-id\",\"~u94eaebe4-addd-80d1-8007-79d5055d685a\",\"~:strokes\",[],\"~:x\",386.0000081062317,\"~:proportion\",1,\"~:r4\",8,\"~:selrect\",[\"~#rect\",[\"^ \",\"~:x\",386.0000081062317,\"~:y\",353.9999959462525,\"^E\",66,\"~:height\",32,\"~:x1\",386.0000081062317,\"~:y1\",353.9999959462525,\"~:x2\",452.0000081062317,\"~:y2\",385.9999959462525]],\"~:fills\",[[\"^ \",\"~:fill-color\",\"#7efff5\",\"~:fill-opacity\",1]],\"~:flip-x\",null,\"~:ry\",8,\"^17\",32,\"~:flip-y\",null,\"~:shapes\",[\"~u94eaebe4-addd-80d1-8007-79d5055d685d\"]]]",
"~u9299427e-8172-80bb-8007-90e71fba0f7f": "[\"~#shape\",[\"^ \",\"~:y\",198.00002998518676,\"~:hide-fill-on-export\",false,\"~:layout-item-absolute\",true,\"~:layout-gap-type\",\"~:multiple\",\"~:layout-padding\",[\"^ \",\"~:p1\",0,\"~:p2\",0,\"~:p3\",0,\"~:p4\",0],\"~:transform\",[\"~#matrix\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:rotation\",0,\"~:layout-wrap-type\",\"~:nowrap\",\"~:grow-type\",\"~:fixed\",\"~:layout\",\"~:flex\",\"~:hide-in-viewer\",true,\"~:name\",\"add-favorites\",\"~:layout-align-items\",\"~:center\",\"~:width\",48,\"~:layout-padding-type\",\"~:simple\",\"~:type\",\"~:frame\",\"~:touched\",[\"~#set\",[\"~:layout-item-z-index\"]],\"~:points\",[[\"~#point\",[\"^ \",\"~:x\",1128,\"~:y\",198.00002998518676]],[\"^P\",[\"^ \",\"~:x\",1176,\"~:y\",198.00002998518676]],[\"^P\",[\"^ \",\"~:x\",1176,\"~:y\",246.00002426314086]],[\"^P\",[\"^ \",\"~:x\",1128,\"~:y\",246.00002426314086]]],\"~:r2\",50,\"~:shape-ref\",\"~u9299427e-8172-80bb-8007-90e7059421c2\",\"~:proportion-lock\",false,\"~:layout-gap\",[\"^ \",\"~:row-gap\",0,\"~:column-gap\",0],\"~:transform-inverse\",[\"^;\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:page-id\",\"~u7c4e00d1-1f97-8161-8007-8f7861f33b60\",\"~:r3\",50,\"~:layout-justify-content\",\"^F\",\"~:r1\",50,\"~:id\",\"~u9299427e-8172-80bb-8007-90e71fba0f7f\",\"~:parent-id\",\"~u9299427e-8172-80bb-8007-90e71fba0f7d\",\"~:layout-flex-dir\",\"~:row\",\"~:applied-tokens\",[\"^ \",\"~:fill\",\"color.bg.default\"],\"~:layout-align-content\",\"~:stretch\",\"~:component-id\",\"~uc8b014fe-f285-8021-8007-8ea447a0bc30\",\"~:frame-id\",\"~u9299427e-8172-80bb-8007-90e71fba0f7d\",\"~:strokes\",[],\"~:x\",1128,\"~:proportion\",1,\"~:r4\",50,\"~:selrect\",[\"~#rect\",[\"^ \",\"~:x\",1128,\"~:y\",198.00002998518676,\"^G\",48,\"~:height\",47.9999942779541,\"~:x1\",1128,\"~:y1\",198.00002998518676,\"~:x2\",1176,\"~:y2\",246.00002426314086]],\"~:fills\",[[\"^ \",\"~:fill-color\",\"#ffffff\",\"~:fill-opacity\",0.3]],\"~:flip-x\",null,\"^1?\",47.9999942779541,\"~:component-file\",\"~ud0eb4518-f33d-81e1-8007-8fe418fea255\",\"~:flip-y\",null,\"^N\",0,\"~:shapes\",[\"~u9299427e-8172-80bb-8007-90e71fba0f81\"]]]",
"~u94eaebe4-addd-80d1-8007-79d5055d685d": "[\"~#shape\",[\"^ \",\"~:y\",361.9999959462525,\"~:hide-fill-on-export\",false,\"~:layout-gap-type\",\"~:multiple\",\"~:layout-padding\",[\"^ \",\"~:p1\",0,\"~:p2\",2,\"~:p3\",0,\"~:p4\",2],\"~:transform\",[\"~#matrix\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:rotation\",0,\"~:layout-wrap-type\",\"~:nowrap\",\"~:layout\",\"~:flex\",\"~:hide-in-viewer\",true,\"~:name\",\"_Utilities / Text / White\",\"~:layout-align-items\",\"~:start\",\"~:width\",42,\"~:layout-padding-type\",\"~:simple\",\"~:transforming\",false,\"~:type\",\"~:frame\",\"~:points\",[[\"~#point\",[\"^ \",\"~:x\",398.0000081062317,\"~:y\",361.9999959462525]],[\"^K\",[\"^ \",\"~:x\",440.0000081062317,\"~:y\",361.9999959462525]],[\"^K\",[\"^ \",\"~:x\",440.0000081062317,\"~:y\",377.9999959462525]],[\"^K\",[\"^ \",\"~:x\",398.0000081062317,\"~:y\",377.9999959462525]]],\"~:show-content\",true,\"~:layout-item-h-sizing\",\"~:auto\",\"~:proportion-lock\",false,\"~:layout-gap\",[\"^ \",\"~:row-gap\",0,\"~:column-gap\",6],\"~:transform-inverse\",[\"^:\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:page-id\",\"~u02e9633d-4ce7-80da-8007-736558496fa8\",\"~:layout-justify-content\",\"~:center\",\"~:id\",\"~u94eaebe4-addd-80d1-8007-79d5055d685d\",\"~:parent-id\",\"~u94eaebe4-addd-80d1-8007-79d5055d685c\",\"~:layout-flex-dir\",\"~:column\",\"~:layout-align-content\",\"~:stretch\",\"~:frame-id\",\"~u94eaebe4-addd-80d1-8007-79d5055d685c\",\"~:strokes\",[],\"~:x\",398.0000081062317,\"~:proportion\",1,\"~:selrect\",[\"~#rect\",[\"^ \",\"~:x\",398.0000081062317,\"~:y\",361.9999959462525,\"^D\",42,\"~:height\",16,\"~:x1\",398.0000081062317,\"~:y1\",361.9999959462525,\"~:x2\",440.0000081062317,\"~:y2\",377.9999959462525]],\"~:fills\",[],\"~:flip-x\",null,\"^16\",16,\"~:flip-y\",null,\"~:shapes\",[\"~u94eaebe4-addd-80d1-8007-79d5055d685e\"]]]",
"~u94eaebe4-addd-80d1-8007-79d5055d685e": "[\"~#shape\",[\"^ \",\"~:y\",362.99999594625274,\"~:transform\",[\"~#matrix\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:rotation\",0,\"~:grow-type\",\"~:auto-width\",\"~:index\",null,\"~:content\",[\"^ \",\"~:type\",\"root\",\"~:children\",[[\"^ \",\"^8\",\"paragraph-set\",\"^9\",[[\"^ \",\"~:line-height\",\"1.2\",\"~:path\",\"\",\"~:font-style\",\"normal\",\"^9\",[[\"^ \",\"^:\",\"1.2\",\"^;\",\"\",\"^<\",\"normal\",\"~:text-transform\",\"uppercase\",\"~:text-align\",\"left\",\"~:font-id\",\"gfont-work-sans\",\"~:font-size\",\"12\",\"~:font-weight\",\"500\",\"~:modified-at\",\"2024-06-04T14:15:09.786Z\",\"~:font-variant-id\",\"500\",\"~:text-decoration\",\"underline\",\"~:letter-spacing\",\"0\",\"~:fills\",[[\"^ \",\"~:fill-color\",\"#000000\",\"~:fill-color-ref-file\",\"~ucaa70d02-51e1-81ae-8007-735e7de3d7bc\",\"~:fill-opacity\",1,\"~:fill-color-ref-id\",\"~udfa92acf-7d18-8079-8003-baba8789d8af\"]],\"~:font-family\",\"Work Sans\",\"~:text\",\"Label\"]],\"^=\",\"uppercase\",\"^>\",\"center\",\"^?\",\"gfont-work-sans\",\"^@\",\"12\",\"^A\",\"500\",\"^8\",\"paragraph\",\"^B\",\"2024-06-04T14:15:09.786Z\",\"^C\",\"500\",\"^D\",\"underline\",\"^E\",\"0\",\"^F\",[[\"^ \",\"^G\",\"#000000\",\"^H\",\"~ucaa70d02-51e1-81ae-8007-735e7de3d7bc\",\"^I\",1,\"^J\",\"~udfa92acf-7d18-8079-8003-baba8789d8af\"]],\"^K\",\"Work Sans\"]]]],\"~:vertical-align\",\"center\",\"^F\",[[\"^ \",\"^G\",\"#000000\",\"^I\",1]]],\"~:hide-in-viewer\",true,\"~:name\",\"Input\",\"~:saved-component-root\",null,\"~:width\",38,\"^8\",\"^L\",\"~:points\",[[\"~#point\",[\"^ \",\"~:x\",400.0000081062317,\"~:y\",362.99999594625274]],[\"^S\",[\"^ \",\"~:x\",438.0000081062317,\"~:y\",362.99999594625274]],[\"^S\",[\"^ \",\"~:x\",438.0000081062317,\"~:y\",377.9999959462523]],[\"^S\",[\"^ \",\"~:x\",400.0000081062317,\"~:y\",377.99999594625274]]],\"~:layout-item-h-sizing\",\"~:fix\",\"~:transform-inverse\",[\"^2\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:page-id\",\"~u02e9633d-4ce7-80da-8007-736558496fa8\",\"~:id\",\"~u94eaebe4-addd-80d1-8007-79d5055d685e\",\"~:parent-id\",\"~u94eaebe4-addd-80d1-8007-79d5055d685d\",\"~:position-data\",[[\"^ \",\"~:y\",377.3399963378906,\"^:\",\"1.2\",\"^<\",\"normal\",\"^=\",\"uppercase\",\"^>\",\"left\",\"^?\",\"sourcesanspro\",\"^@\",\"12\",\"^A\",\"500\",\"~:text-direction\",\"ltr\",\"^Q\",37.94000244140625,\"^C\",\"regular\",\"^D\",\"underline\",\"^E\",\"0\",\"~:x\",400.0299987792969,\"^F\",[[\"^ \",\"^G\",\"#000000\",\"^H\",\"~ucaa70d02-51e1-81ae-8007-735e7de3d7bc\",\"^I\",1,\"^J\",\"~udfa92acf-7d18-8079-8003-baba8789d8af\"]],\"~:direction\",\"ltr\",\"^K\",\"Work Sans\",\"~:height\",14.079986572265625,\"^L\",\"Label\"]],\"~:frame-id\",\"~u94eaebe4-addd-80d1-8007-79d5055d685d\",\"~:strokes\",[],\"~:x\",400.0000081062317,\"~:selrect\",[\"~#rect\",[\"^ \",\"~:x\",400.0000081062317,\"~:y\",362.99999594625274,\"^Q\",38,\"^11\",15,\"~:x1\",400.0000081062317,\"~:y1\",362.99999594625274,\"~:x2\",438.0000081062317,\"~:y2\",377.99999594625274]],\"^F\",[],\"~:flip-x\",null,\"^11\",15,\"~:flip-y\",null]]",
"~u9299427e-8172-80bb-8007-90e71fba0f7d": "[\"~#shape\",[\"^ \",\"~:y\",191.99998474121094,\"~:hide-fill-on-export\",false,\"~:layout-gap-type\",\"~:multiple\",\"~:layout-padding\",[\"^ \",\"~:p1\",0,\"~:p2\",0,\"~:p3\",0,\"~:p4\",0],\"~:transform\",[\"~#matrix\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:rotation\",0,\"~:layout-wrap-type\",\"~:nowrap\",\"~:grow-type\",\"~:fixed\",\"~:layout\",\"~:flex\",\"~:hide-in-viewer\",true,\"~:name\",\"card-img / patinegro\",\"~:layout-align-items\",\"~:start\",\"~:width\",265,\"~:layout-padding-type\",\"~:simple\",\"~:type\",\"~:frame\",\"~:points\",[[\"~#point\",[\"^ \",\"~:x\",916,\"~:y\",191.99998474121094]],[\"^L\",[\"^ \",\"~:x\",1181,\"~:y\",191.99998474121094]],[\"^L\",[\"^ \",\"~:x\",1181,\"~:y\",369.99997875688996]],[\"^L\",[\"^ \",\"~:x\",916,\"~:y\",369.99997875688996]]],\"~:r2\",20,\"~:component-root\",true,\"~:shape-ref\",\"~u9299427e-8172-80bb-8007-90e7059421c0\",\"~:proportion-lock\",false,\"~:layout-gap\",[\"^ \",\"~:row-gap\",0,\"~:column-gap\",0],\"~:transform-inverse\",[\"^:\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:page-id\",\"~u7c4e00d1-1f97-8161-8007-8f7861f33b60\",\"~:r3\",20,\"~:layout-justify-content\",\"^E\",\"~:r1\",20,\"~:id\",\"~u9299427e-8172-80bb-8007-90e71fba0f7d\",\"~:parent-id\",\"~u00000000-0000-0000-0000-000000000000\",\"~:layout-flex-dir\",\"~:column\",\"~:layout-align-content\",\"~:stretch\",\"~:component-id\",\"~u9299427e-8172-80bb-8007-90e7059a83e2\",\"~:frame-id\",\"~u00000000-0000-0000-0000-000000000000\",\"~:strokes\",[],\"~:x\",916,\"~:proportion\",1,\"~:r4\",20,\"~:selrect\",[\"~#rect\",[\"^ \",\"~:x\",916,\"~:y\",191.99998474121094,\"^F\",265,\"~:height\",177.99999401567902,\"~:x1\",916,\"~:y1\",191.99998474121094,\"~:x2\",1181,\"~:y2\",369.99997875688996]],\"~:fills\",[[\"^ \",\"~:fill-color\",\"#FFFFFF\",\"~:fill-opacity\",1]],\"~:flip-x\",null,\"^1:\",177.99999401567902,\"~:component-file\",\"~u31fe2e21-73e7-80f3-8007-73894fb58240\",\"~:flip-y\",null,\"~:shapes\",[\"~u9299427e-8172-80bb-8007-90e71fba0f7e\",\"~u9299427e-8172-80bb-8007-90e71fba0f7f\"]]]"
}
}
}
@@ -150,6 +182,16 @@
"~:options": {
"~:components-v2": true,
"~:base-font-size": "16px"
},
"~:components": {
"~u9299427e-8172-80bb-8007-90e7059a83e2": {
"~:id": "~u9299427e-8172-80bb-8007-90e7059a83e2",
"~:name": "patinegro",
"~:path": "card-img",
"~:modified-at": "~m1770978606872",
"~:main-instance-id": "~u9299427e-8172-80bb-8007-90e7059421c0",
"~:main-instance-page": "~u02e9633d-4ce7-80da-8007-736558496fa8"
}
}
}
}

View File

File diff suppressed because it is too large Load Diff

View File

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,137 @@
{
"~:features": {
"~#set": [
"fdata/path-data",
"plugins/runtime",
"design-tokens/v1",
"variants/v1",
"layout/grid",
"styles/v2",
"fdata/objects-map",
"render-wasm/v1",
"components/v2",
"fdata/shape-data-type"
]
},
"~:team-id": "~u99e49e93-362f-80ef-8007-3450ea52c9a4",
"~:permissions": {
"~:type": "~:membership",
"~:is-owner": true,
"~:is-admin": true,
"~:can-edit": true,
"~:can-read": true,
"~:is-logged": true
},
"~:has-media-trimmed": false,
"~:comment-thread-seqn": 0,
"~:name": "BUG 13305",
"~:revn": 11,
"~:modified-at": "~m1770911234124",
"~:vern": 0,
"~:id": "~u9666e946-78e8-8111-8007-8fe5f0f454bf",
"~:is-shared": false,
"~:migrations": {
"~#ordered-set": [
"legacy-2",
"legacy-3",
"legacy-5",
"legacy-6",
"legacy-7",
"legacy-8",
"legacy-9",
"legacy-10",
"legacy-11",
"legacy-12",
"legacy-13",
"legacy-14",
"legacy-16",
"legacy-17",
"legacy-18",
"legacy-19",
"legacy-25",
"legacy-26",
"legacy-27",
"legacy-28",
"legacy-29",
"legacy-31",
"legacy-32",
"legacy-33",
"legacy-34",
"legacy-36",
"legacy-37",
"legacy-38",
"legacy-39",
"legacy-40",
"legacy-41",
"legacy-42",
"legacy-43",
"legacy-44",
"legacy-45",
"legacy-46",
"legacy-47",
"legacy-48",
"legacy-49",
"legacy-50",
"legacy-51",
"legacy-52",
"legacy-53",
"legacy-54",
"legacy-55",
"legacy-56",
"legacy-57",
"legacy-59",
"legacy-62",
"legacy-65",
"legacy-66",
"legacy-67",
"0001-remove-tokens-from-groups",
"0002-normalize-bool-content-v2",
"0002-clean-shape-interactions",
"0003-fix-root-shape",
"0003-convert-path-content-v2",
"0005-deprecate-image-type",
"0006-fix-old-texts-fills",
"0008-fix-library-colors-v4",
"0009-clean-library-colors",
"0009-add-partial-text-touched-flags",
"0010-fix-swap-slots-pointing-non-existent-shapes",
"0011-fix-invalid-text-touched-flags",
"0012-fix-position-data",
"0013-fix-component-path",
"0013-clear-invalid-strokes-and-fills",
"0014-fix-tokens-lib-duplicate-ids",
"0014-clear-components-nil-objects",
"0015-fix-text-attrs-blank-strings",
"0015-clean-shadow-color",
"0016-copy-fills-from-position-data-to-text-node"
]
},
"~:version": 67,
"~:project-id": "~ucd8f7672-e5d1-810f-8007-87e124eda82a",
"~:created-at": "~m1770911129553",
"~:backend": "legacy-db",
"~:data": {
"~:pages": [
"~u9666e946-78e8-8111-8007-8fe5f0f49ac6"
],
"~:pages-index": {
"~u9666e946-78e8-8111-8007-8fe5f0f49ac6": {
"~:objects": {
"~#penpot/objects-map/v2": {
"~u00000000-0000-0000-0000-000000000000": "[\"~#shape\",[\"^ \",\"~:y\",0,\"~:hide-fill-on-export\",false,\"~:transform\",[\"~#matrix\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:rotation\",0,\"~:name\",\"Root Frame\",\"~:width\",0.01,\"~:type\",\"~:frame\",\"~:points\",[[\"~#point\",[\"^ \",\"~:x\",0.0,\"~:y\",0.0]],[\"^:\",[\"^ \",\"~:x\",0.01,\"~:y\",0.0]],[\"^:\",[\"^ \",\"~:x\",0.01,\"~:y\",0.01]],[\"^:\",[\"^ \",\"~:x\",0.0,\"~:y\",0.01]]],\"~:r2\",0,\"~:proportion-lock\",false,\"~:transform-inverse\",[\"^3\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:r3\",0,\"~:r1\",0,\"~:id\",\"~u00000000-0000-0000-0000-000000000000\",\"~:parent-id\",\"~u00000000-0000-0000-0000-000000000000\",\"~:frame-id\",\"~u00000000-0000-0000-0000-000000000000\",\"~:strokes\",[],\"~:x\",0,\"~:proportion\",1.0,\"~:r4\",0,\"~:selrect\",[\"~#rect\",[\"^ \",\"~:x\",0,\"~:y\",0,\"^6\",0.01,\"~:height\",0.01,\"~:x1\",0,\"~:y1\",0,\"~:x2\",0.01,\"~:y2\",0.01]],\"~:fills\",[[\"^ \",\"~:fill-color\",\"#FFFFFF\",\"~:fill-opacity\",1]],\"~:flip-x\",null,\"^H\",0.01,\"~:flip-y\",null,\"~:shapes\",[\"~u3edd6127-ced7-80c6-8007-8fe5f6c52e5a\"]]]",
"~u3edd6127-ced7-80c6-8007-8fe5f6c52e5a": "[\"~#shape\",[\"^ \",\"~:y\",99.99999499320984,\"~:hide-fill-on-export\",false,\"~:transform\",[\"~#matrix\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:rotation\",0,\"~:grow-type\",\"~:fixed\",\"~:hide-in-viewer\",false,\"~:name\",\"Board\",\"~:width\",511.99998180389287,\"~:type\",\"~:frame\",\"~:points\",[[\"~#point\",[\"^ \",\"~:x\",99.9999820137034,\"~:y\",99.99999499320984]],[\"^=\",[\"^ \",\"~:x\",611.9999638175963,\"~:y\",99.99999499320984]],[\"^=\",[\"^ \",\"~:x\",611.9999638175963,\"~:y\",611.9999695949548]],[\"^=\",[\"^ \",\"~:x\",99.9999820137034,\"~:y\",611.9999695949548]]],\"~:r2\",0,\"~:proportion-lock\",false,\"~:transform-inverse\",[\"^3\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:r3\",0,\"~:r1\",0,\"~:id\",\"~u3edd6127-ced7-80c6-8007-8fe5f6c52e5a\",\"~:parent-id\",\"~u00000000-0000-0000-0000-000000000000\",\"~:frame-id\",\"~u00000000-0000-0000-0000-000000000000\",\"~:strokes\",[],\"~:x\",99.9999820137034,\"~:proportion\",1,\"~:r4\",0,\"~:selrect\",[\"~#rect\",[\"^ \",\"~:x\",99.9999820137034,\"~:y\",99.99999499320984,\"^9\",511.99998180389287,\"~:height\",511.99997460174495,\"~:x1\",99.9999820137034,\"~:y1\",99.99999499320984,\"~:x2\",611.9999638175963,\"~:y2\",611.9999695949548]],\"~:fills\",[[\"^ \",\"~:fill-color\",\"#FFFFFF\",\"~:fill-opacity\",1]],\"~:flip-x\",null,\"^K\",511.99997460174495,\"~:flip-y\",null,\"~:shapes\",[\"~u3edd6127-ced7-80c6-8007-8fe60306baa7\",\"~u3edd6127-ced7-80c6-8007-8fe61479065a\"]]]",
"~u3edd6127-ced7-80c6-8007-8fe60306baa7": "[\"~#shape\",[\"^ \",\"~:y\",109.99999433755875,\"~:transform\",[\"~#matrix\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:rotation\",0,\"~:grow-type\",\"~:fixed\",\"~:hide-in-viewer\",false,\"~:name\",\"Rectangle\",\"~:width\",100.00000357627869,\"~:type\",\"~:rect\",\"~:points\",[[\"~#point\",[\"^ \",\"~:x\",109.99998164176941,\"~:y\",109.99999433755875]],[\"^<\",[\"^ \",\"~:x\",209.9999852180481,\"~:y\",109.99999433755875]],[\"^<\",[\"^ \",\"~:x\",209.9999852180481,\"~:y\",209.9999930858612]],[\"^<\",[\"^ \",\"~:x\",109.99998164176941,\"~:y\",209.9999930858612]]],\"~:r2\",0,\"~:proportion-lock\",false,\"~:transform-inverse\",[\"^2\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:r3\",0,\"~:constraints-v\",\"~:top\",\"~:constraints-h\",\"~:left\",\"~:r1\",0,\"~:id\",\"~u3edd6127-ced7-80c6-8007-8fe60306baa7\",\"~:parent-id\",\"~u3edd6127-ced7-80c6-8007-8fe5f6c52e5a\",\"~:frame-id\",\"~u3edd6127-ced7-80c6-8007-8fe5f6c52e5a\",\"~:strokes\",[],\"~:x\",109.99998164176941,\"~:proportion\",1,\"~:r4\",0,\"~:selrect\",[\"~#rect\",[\"^ \",\"~:x\",109.99998164176941,\"~:y\",109.99999433755875,\"^8\",100.00000357627869,\"~:height\",99.99999874830246,\"~:x1\",109.99998164176941,\"~:y1\",109.99999433755875,\"~:x2\",209.9999852180481,\"~:y2\",209.9999930858612]],\"~:fills\",[[\"^ \",\"~:fill-color\",\"#B1B2B5\",\"~:fill-opacity\",1]],\"~:flip-x\",null,\"^N\",99.99999874830246,\"~:flip-y\",null]]",
"~u3edd6127-ced7-80c6-8007-8fe61479065a": "[\"~#shape\",[\"^ \",\"~:y\",483.9999952316284,\"~:transform\",[\"~#matrix\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:rotation\",0,\"~:grow-type\",\"~:fixed\",\"~:hide-in-viewer\",false,\"~:name\",\"Ellipse\",\"~:width\",256.000000834465,\"~:type\",\"~:circle\",\"~:points\",[[\"~#point\",[\"^ \",\"~:x\",483.99998211860657,\"~:y\",483.9999952316284]],[\"^<\",[\"^ \",\"~:x\",739.9999829530716,\"~:y\",483.9999952316284]],[\"^<\",[\"^ \",\"~:x\",739.9999829530716,\"~:y\",739.9999876022339]],[\"^<\",[\"^ \",\"~:x\",483.99998211860657,\"~:y\",739.9999876022339]]],\"~:proportion-lock\",false,\"~:transform-inverse\",[\"^2\",[\"^ \",\"~:a\",1.0,\"~:b\",0.0,\"~:c\",0.0,\"~:d\",1.0,\"~:e\",0.0,\"~:f\",0.0]],\"~:constraints-v\",\"~:top\",\"~:constraints-h\",\"~:left\",\"~:id\",\"~u3edd6127-ced7-80c6-8007-8fe61479065a\",\"~:parent-id\",\"~u3edd6127-ced7-80c6-8007-8fe5f6c52e5a\",\"~:frame-id\",\"~u3edd6127-ced7-80c6-8007-8fe5f6c52e5a\",\"~:strokes\",[],\"~:x\",483.99998211860657,\"~:proportion\",1,\"~:selrect\",[\"~#rect\",[\"^ \",\"~:x\",483.99998211860657,\"~:y\",483.9999952316284,\"^8\",256.000000834465,\"~:height\",255.99999237060547,\"~:x1\",483.99998211860657,\"~:y1\",483.9999952316284,\"~:x2\",739.9999829530716,\"~:y2\",739.9999876022339]],\"~:fills\",[[\"^ \",\"~:fill-color\",\"#B1B2B5\",\"~:fill-opacity\",1]],\"~:flip-x\",null,\"^J\",255.99999237060547,\"~:flip-y\",null]]"
}
},
"~:id": "~u9666e946-78e8-8111-8007-8fe5f0f49ac6",
"~:name": "Page 1"
}
},
"~:id": "~u9666e946-78e8-8111-8007-8fe5f0f454bf",
"~:options": {
"~:components-v2": true,
"~:base-font-size": "16px"
}
}
}

View File

@@ -0,0 +1,98 @@
{
"~:revn": 11,
"~:lagged": [
{
"~:id": "~u9666e946-78e8-8111-8007-8fe7be6223c2",
"~:revn": 12,
"~:file-id": "~u9666e946-78e8-8111-8007-8fe5f0f454bf",
"~:session-id": "~u3966be0d-5f49-807f-8007-8fe68b13fee6",
"~:changes": [
{
"~:type": "~:mod-obj",
"~:id": "~u3edd6127-ced7-80c6-8007-8fe5f6c52e5a",
"~:page-id": "~u9666e946-78e8-8111-8007-8fe5f0f49ac6",
"~:operations": [
{
"~:type": "~:set",
"~:attr": "~:y",
"~:val": 110.00000528339297,
"~:ignore-geometry": false,
"~:ignore-touched": false
},
{
"~:type": "~:set",
"~:attr": "~:width",
"~:val": 629.9999776102587,
"~:ignore-geometry": false,
"~:ignore-touched": false
},
{
"~:type": "~:set",
"~:attr": "~:points",
"~:val": [
{
"~#point": {
"~:x": 109.99999217353886,
"~:y": 110.00000528339297
}
},
{
"~#point": {
"~:x": 739.9999697837976,
"~:y": 110.00000528339297
}
},
{
"~#point": {
"~:x": 739.9999697837976,
"~:y": 739.9999740316338
}
},
{
"~#point": {
"~:x": 109.99999217353886,
"~:y": 739.9999740316338
}
}
],
"~:ignore-geometry": false,
"~:ignore-touched": false
},
{
"~:type": "~:set",
"~:attr": "~:x",
"~:val": 109.99999217353889,
"~:ignore-geometry": false,
"~:ignore-touched": false
},
{
"~:type": "~:set",
"~:attr": "~:selrect",
"~:val": {
"~#rect": {
"~:x": 109.99999217353889,
"~:y": 110.00000528339297,
"~:width": 629.9999776102587,
"~:height": 629.9999687482408,
"~:x1": 109.99999217353889,
"~:y1": 110.00000528339297,
"~:x2": 739.9999697837976,
"~:y2": 739.9999740316338
}
},
"~:ignore-geometry": false,
"~:ignore-touched": false
},
{
"~:type": "~:set",
"~:attr": "~:height",
"~:val": 629.9999687482408,
"~:ignore-geometry": false,
"~:ignore-touched": false
}
]
}
]
}
]
}

View File

@@ -10,7 +10,7 @@ export const WASM_FLAGS = [
export class WasmWorkspacePage extends WorkspacePage {
static async init(page) {
await super.init(page);
await WorkspacePage.mockConfigFlags(page, WASM_FLAGS);
await WasmWorkspacePage.mockConfigFlags(page, WASM_FLAGS);
await page.addInitScript(() => {
document.addEventListener("penpot:wasm:loaded", () => {
@@ -27,6 +27,14 @@ export class WasmWorkspacePage extends WorkspacePage {
});
}
static async mockConfigFlags(page, flags) {
await super.mockConfigFlags(page, [...WASM_FLAGS, ...flags]);
}
async mockConfigFlags(flags) {
return WasmWorkspacePage.mockConfigFlags(this.page, flags);
}
constructor(page) {
super(page);
this.canvas = page.getByTestId("canvas-wasm-shapes");

View File

@@ -198,10 +198,10 @@ export class WorkspacePage extends BaseWebSocketPage {
`[id="shape-00000000-0000-0000-0000-000000000000"]`,
);
this.toolbarOptions = page.getByTestId("toolbar-options");
this.rectShapeButton = page.getByTestId("toolbar-options").getByRole("button", { name: "Rectangle" });
this.ellipseShapeButton = page.getByTestId("toolbar-options").getByRole("button", { name: "Ellipse" });
this.moveButton = page.getByTestId("toolbar-options").getByRole("button", { name: "Move" });
this.boardButton = page.getByTestId("toolbar-options").getByRole("button", { name: "Board" });
this.rectShapeButton = page.getByRole("button", { name: "Rectangle (R)" });
this.ellipseShapeButton = page.getByRole("button", { name: "Ellipse (E)" });
this.moveButton = page.getByRole("button", { name: "Move (V)" });
this.boardButton = page.getByRole("button", { name: "Board (B)" });
this.toggleToolbarButton = page.getByRole("button", {
name: "Toggle toolbar",
});
@@ -338,9 +338,18 @@ export class WorkspacePage extends BaseWebSocketPage {
async clickWithDragViewportAt(x, y, width, height) {
await this.page.waitForTimeout(100);
await this.viewport.hover({ position: { x, y } });
const box = await this.viewport.boundingBox();
if (!box) throw new Error('Viewport not visible');
const startX = box.x + x;
const startY = box.y + y;
const endX = startX + width;
const endY = startY + height;
await this.page.mouse.move(startX, startY);
await this.page.mouse.down();
await this.viewport.hover({ position: { x: x + width, y: y + height } });
// Use steps so mouseup is properly processed (see Playwright issue #20254)
await this.page.mouse.move(endX, endY, { steps: 10 });
await this.page.mouse.up();
}

View File

@@ -165,6 +165,7 @@ test("Updates canvas background", async ({ page }) => {
});
await canvasBackgroundInput.fill("FABADA");
await workspace.page.keyboard.press("Enter");
await workspace.waitForFirstRenderWithoutUI();
await expect(workspace.canvas).toHaveScreenshot();
});
@@ -196,7 +197,7 @@ test("Renders a file with blurs applied to any kind of shape", async ({
test("Renders a file with shadows applied to any kind of shape", async ({
page,
}) => {
}) => {
const workspace = new WasmWorkspacePage(page);
await workspace.setupEmptyFile();
await workspace.mockGetFile("render-wasm/get-file-shadows.json");
@@ -290,6 +291,24 @@ test("Renders a file with nested clipping frames", async ({ page }) => {
await expect(workspace.canvas).toHaveScreenshot();
});
test("Renders clipped frames with strokes correctly (no double painting)", async ({
page,
}) => {
const workspace = new WasmWorkspacePage(page);
await workspace.setupEmptyFile();
await workspace.mockGetFile(
"render-wasm/get-file-frame-strokes-opacity.json",
);
await workspace.goToWorkspace({
id: "3144ac7c-a5cc-80e8-8007-8bbb29a4e56e",
pageId: "3144ac7c-a5cc-80e8-8007-8bbb29a510ac",
});
await workspace.waitForFirstRenderWithoutUI();
await expect(workspace.canvas).toHaveScreenshot();
});
test("Renders a clipped frame with a large blur drop shadow", async ({
page,
}) => {
@@ -305,3 +324,35 @@ test("Renders a clipped frame with a large blur drop shadow", async ({
await expect(workspace.canvas).toHaveScreenshot();
});
test("Renders a file with solid, dotted, dashed and mixed stroke styles", async ({
page,
}) => {
const workspace = new WasmWorkspacePage(page);
await workspace.setupEmptyFile();
await workspace.mockGetFile("render-wasm/get-file-stroke-styles.json");
await workspace.goToWorkspace({
id: "b888b894-3697-80d3-8006-51cc8a55c200",
pageId: "b888b894-3697-80d3-8006-51cc8a55c210",
});
await workspace.waitForFirstRenderWithoutUI();
await expect(workspace.canvas).toHaveScreenshot();
});
test("Renders shapes with multiple fills and blur", async ({
page,
}) => {
const workspace = new WasmWorkspacePage(page);
await workspace.setupEmptyFile();
await workspace.mockGetFile("render-wasm/get-file-fill-blend-blurs.json");
await workspace.goToWorkspace({
id: "b15901d7-d46d-8056-8007-8d5e34fc1f0c",
pageId: "b15901d7-d46d-8056-8007-8d5e34fc1f0d",
});
await workspace.waitForFirstRenderWithoutUI();
await expect(workspace.canvas).toHaveScreenshot();
});

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 24 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 360 KiB

After

Width:  |  Height:  |  Size: 348 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 123 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 115 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 32 KiB

After

Width:  |  Height:  |  Size: 15 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 216 KiB

After

Width:  |  Height:  |  Size: 220 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 124 KiB

After

Width:  |  Height:  |  Size: 126 KiB

View File

@@ -1,14 +1,14 @@
import { test, expect } from "@playwright/test";
import { WorkspacePage } from "../pages/WorkspacePage";
import { WasmWorkspacePage } from "../pages/WasmWorkspacePage";
test.beforeEach(async ({ page }) => {
await WorkspacePage.init(page);
await WasmWorkspacePage.init(page);
});
test("User adds a library and its automatically selected in the color palette", async ({
page,
}) => {
const workspacePage = new WorkspacePage(page);
const workspacePage = new WasmWorkspacePage(page);
await workspacePage.setupEmptyFile();
await workspacePage.mockRPC(
"link-file-to-library",
@@ -53,7 +53,7 @@ test("User adds a library and its automatically selected in the color palette",
test("BUG 10090 - Local library should be expanded by default", async ({
page,
}) => {
const workspacePage = new WorkspacePage(page);
const workspacePage = new WasmWorkspacePage(page);
await workspacePage.setupEmptyFile(page);
await workspacePage.goToWorkspace();

View File

@@ -1,15 +1,15 @@
import { test, expect } from "@playwright/test";
import { WorkspacePage } from "../pages/WorkspacePage";
import { WasmWorkspacePage } from "../pages/WasmWorkspacePage";
test.beforeEach(async ({ page }) => {
await WorkspacePage.init(page);
await WasmWorkspacePage.init(page);
});
// Fix for https://tree.taiga.io/project/penpot/issue/7549
test("Bug 7549 - User clicks on color swatch to display the color picker next to it", async ({
page,
}) => {
const workspacePage = new WorkspacePage(page);
const workspacePage = new WasmWorkspacePage(page);
await workspacePage.setupEmptyFile(page);
await workspacePage.goToWorkspace();
@@ -25,7 +25,7 @@ test("Bug 7549 - User clicks on color swatch to display the color picker next to
});
test("Create a LINEAR gradient", async ({ page }) => {
const workspacePage = new WorkspacePage(page);
const workspacePage = new WasmWorkspacePage(page);
await workspacePage.setupEmptyFile();
await workspacePage.mockRPC(
/get\-file\?/,
@@ -99,7 +99,7 @@ test("Create a LINEAR gradient", async ({ page }) => {
});
test("Create a RADIAL gradient", async ({ page }) => {
const workspacePage = new WorkspacePage(page);
const workspacePage = new WasmWorkspacePage(page);
await workspacePage.setupEmptyFile();
await workspacePage.mockRPC(
/get\-file\?/,
@@ -183,7 +183,7 @@ test("Create a RADIAL gradient", async ({ page }) => {
});
test("Gradient stops limit", async ({ page }) => {
const workspacePage = new WorkspacePage(page);
const workspacePage = new WasmWorkspacePage(page);
await workspacePage.mockConfigFlags(["enable-feature-render-wasm"]);
await workspacePage.setupEmptyFile(page);
@@ -215,7 +215,7 @@ test("Gradient stops limit", async ({ page }) => {
test("Bug 9900 - Color picker has no inputs for HSV values", async ({
page,
}) => {
const workspacePage = new WorkspacePage(page);
const workspacePage = new WasmWorkspacePage(page);
await workspacePage.setupEmptyFile(page);
await workspacePage.goToWorkspace();
@@ -232,7 +232,7 @@ test("Bug 9900 - Color picker has no inputs for HSV values", async ({
});
test("Bug 10089 - Cannot change alpha", async ({ page }) => {
const workspacePage = new WorkspacePage(page);
const workspacePage = new WasmWorkspacePage(page);
await workspacePage.setupEmptyFile();
await workspacePage.mockRPC(
/get\-file\?/,

View File

@@ -1,8 +1,8 @@
import { test, expect } from "@playwright/test";
import { WorkspacePage } from "../pages/WorkspacePage";
import { WasmWorkspacePage } from "../pages/WasmWorkspacePage";
test.beforeEach(async ({ page }) => {
await WorkspacePage.init(page);
await WasmWorkspacePage.init(page);
});
const multipleConstraintsFileId = `03bff843-920f-81a1-8004-756365e1eb6a`;
@@ -42,7 +42,7 @@ test.describe("Constraints", () => {
test("Constraint dropdown shows 'Mixed' when multiple layers are selected with different constraints", async ({
page,
}) => {
const workspace = new WorkspacePage(page);
const workspace = new WasmWorkspacePage(page);
await setupFileWithMultipeConstraints(workspace);
await workspace.goToWorkspace({
fileId: multipleConstraintsFileId,
@@ -70,7 +70,7 @@ test.describe("Shape attributes", () => {
test("Cannot add a new fill when the limit has been reached", async ({
page,
}) => {
const workspace = new WorkspacePage(page);
const workspace = new WasmWorkspacePage(page);
await workspace.mockConfigFlags(["enable-feature-render-wasm"]);
await workspace.setupEmptyFile();
await workspace.mockRPC(/get\-file\?/, "design/get-file-fills-limit.json");
@@ -94,7 +94,7 @@ test.describe("Shape attributes", () => {
test.skip("Cannot add a new text fill when the limit has been reached", async ({
page,
}) => {
const workspace = new WorkspacePage(page);
const workspace = new WasmWorkspacePage(page);
await workspace.mockConfigFlags(["enable-feature-render-wasm"]);
await workspace.setupEmptyFile();
await workspace.mockRPC(
@@ -128,7 +128,7 @@ test.describe("Multiple shapes attributes", () => {
test("User selects multiple shapes with sames fills, strokes, shadows and blur", async ({
page,
}) => {
const workspace = new WorkspacePage(page);
const workspace = new WasmWorkspacePage(page);
await setupFileWithMultipeConstraints(workspace);
await workspace.goToWorkspace({
fileId: multipleConstraintsFileId,
@@ -148,7 +148,7 @@ test.describe("Multiple shapes attributes", () => {
test("User selects multiple shapes with different fills, strokes, shadows and blur", async ({
page,
}) => {
const workspace = new WorkspacePage(page);
const workspace = new WasmWorkspacePage(page);
await setupFileWithMultipeAttributes(workspace);
await workspace.goToWorkspace({
fileId: multipleAttributesFileId,
@@ -168,7 +168,7 @@ test.describe("Multiple shapes attributes", () => {
test("BUG 7760 - Layout losing properties when changing parents", async ({
page,
}) => {
const workspacePage = new WorkspacePage(page);
const workspacePage = new WasmWorkspacePage(page);
await workspacePage.setupEmptyFile();
await workspacePage.mockRPC(/get\-file\?/, "workspace/get-file-7760.json");
await workspacePage.mockRPC(
@@ -189,8 +189,8 @@ test("BUG 7760 - Layout losing properties when changing parents", async ({
await workspacePage.clickLeafLayer("Flex Board");
// Move the first board into the second
const hAuto = await workspacePage.page.getByTestId("behaviour-h-auto");
const vAuto = await workspacePage.page.getByTestId("behaviour-v-auto");
const hAuto = await workspacePage.page.getByTitle("Fit content (Horizontal)");
const vAuto = await workspacePage.page.getByTitle("Fit content (Vertical)");
await expect(vAuto.locator("input")).toBeChecked();
await expect(hAuto.locator("input")).toBeChecked();
@@ -205,7 +205,7 @@ test("BUG 7760 - Layout losing properties when changing parents", async ({
test("BUG 9061 - Group blur visibility toggle icon not updating", async ({
page,
}) => {
const workspace = new WorkspacePage(page);
const workspace = new WasmWorkspacePage(page);
await workspace.setupEmptyFile();
await workspace.mockRPC(/get\-file\?/, "design/get-file-9061.json");
await workspace.mockRPC(
@@ -234,7 +234,7 @@ test("BUG 9061 - Group blur visibility toggle icon not updating", async ({
test("BUG 9543 - Layout padding inputs not showing 'mixed' when needed", async ({
page,
}) => {
const workspace = new WorkspacePage(page);
const workspace = new WasmWorkspacePage(page);
await workspace.setupEmptyFile();
await workspace.mockRPC(/get\-file\?/, "design/get-file-9543.json");
await workspace.mockRPC(
@@ -267,7 +267,7 @@ test("BUG 9543 - Layout padding inputs not showing 'mixed' when needed", async (
test("BUG 11177 - Font size input not showing 'mixed' when needed", async ({
page,
}) => {
const workspace = new WorkspacePage(page);
const workspace = new WasmWorkspacePage(page);
await workspace.setupEmptyFile();
await workspace.mockRPC(/get\-file\?/, "design/get-file-11177.json");
@@ -288,7 +288,7 @@ test("BUG 11177 - Font size input not showing 'mixed' when needed", async ({
test("BUG 12287 Fix identical text fills not being added/removed", async ({
page,
}) => {
const workspace = new WorkspacePage(page);
const workspace = new WasmWorkspacePage(page);
await workspace.setupEmptyFile();
await workspace.mockRPC(/get\-file\?/, "design/get-file-12287.json");
@@ -323,7 +323,7 @@ test("BUG 12287 Fix identical text fills not being added/removed", async ({
});
test("BUG 12384 - Export crashing when exporting a board", async ({ page }) => {
const workspace = new WorkspacePage(page);
const workspace = new WasmWorkspacePage(page);
await workspace.setupEmptyFile();
await workspace.mockRPC(/get\-file\?/, "design/get-file-12384.json");

View File

@@ -1,8 +1,8 @@
import { test, expect } from "@playwright/test";
import { WorkspacePage } from "../pages/WorkspacePage";
import { WasmWorkspacePage } from "../pages/WasmWorkspacePage";
test.beforeEach(async ({ page }) => {
await WorkspacePage.init(page);
await WasmWorkspacePage.init(page);
});
/**
@@ -32,7 +32,7 @@ test.describe("Export frames to PDF", () => {
test("Export frames menu option is NOT visible when page has no frames", async ({
page,
}) => {
const workspacePage = new WorkspacePage(page);
const workspacePage = new WasmWorkspacePage(page);
await workspacePage.setupEmptyFile();
await workspacePage.goToWorkspace();
@@ -48,7 +48,7 @@ test.describe("Export frames to PDF", () => {
test("Export frames menu option is visible when there are frames (even if not selected)", async ({
page,
}) => {
const workspacePage = new WorkspacePage(page);
const workspacePage = new WasmWorkspacePage(page);
await setupWorkspaceWithFrames(workspacePage);
// Open main menu
@@ -62,7 +62,7 @@ test.describe("Export frames to PDF", () => {
test("Export frames modal shows all frames when none are selected", async ({
page,
}) => {
const workspacePage = new WorkspacePage(page);
const workspacePage = new WasmWorkspacePage(page);
await setupWorkspaceWithFrames(workspacePage);
// Don't select any frame
@@ -88,7 +88,7 @@ test.describe("Export frames to PDF", () => {
test("Export frames modal shows only the selected frames", async ({
page,
}) => {
const workspacePage = new WorkspacePage(page);
const workspacePage = new WasmWorkspacePage(page);
await setupWorkspaceWithFrames(workspacePage);
// Select Frame 1
@@ -116,7 +116,7 @@ test.describe("Export frames to PDF", () => {
});
test("User can deselect frames in the export modal", async ({ page }) => {
const workspacePage = new WorkspacePage(page);
const workspacePage = new WasmWorkspacePage(page);
await setupWorkspaceWithFrames(workspacePage);
// Select Frame 1
@@ -149,7 +149,7 @@ test.describe("Export frames to PDF", () => {
test("Export button is disabled when all frames are deselected", async ({
page,
}) => {
const workspacePage = new WorkspacePage(page);
const workspacePage = new WasmWorkspacePage(page);
await setupWorkspaceWithFrames(workspacePage);
// Select Frame 1
@@ -173,7 +173,7 @@ test.describe("Export frames to PDF", () => {
});
test("User can cancel the export modal", async ({ page }) => {
const workspacePage = new WorkspacePage(page);
const workspacePage = new WasmWorkspacePage(page);
await setupWorkspaceWithFrames(workspacePage);
// Select Frame 1

View File

@@ -1,15 +1,15 @@
import { test, expect } from "@playwright/test";
import { WorkspacePage } from "../pages/WorkspacePage";
import { WasmWorkspacePage } from "../pages/WasmWorkspacePage";
test.beforeEach(async ({ page }) => {
await WorkspacePage.init(page);
await WasmWorkspacePage.init(page);
});
// Fix for https://tree.taiga.io/project/penpot/issue/9042
test("Bug 9042 - Measurement unit dropdowns for columns are cut off in grid layout edit mode", async ({
page,
}) => {
const workspacePage = new WorkspacePage(page);
const workspacePage = new WasmWorkspacePage(page);
await workspacePage.setupEmptyFile(page);
await workspacePage.mockRPC(/get\-file\?/, "workspace/get-file-9042.json");
await workspacePage.mockRPC(
@@ -37,7 +37,7 @@ test("[Taiga #9116] Copy CSS background color in the selected format in the INSP
page,
context,
}) => {
const workspacePage = new WorkspacePage(page);
const workspacePage = new WasmWorkspacePage(page);
await workspacePage.setupEmptyFile(page);
await workspacePage.goToWorkspace();
@@ -87,7 +87,7 @@ test("[Taiga #10630] [INSPECT] Style assets not being displayed on info tab", as
page,
context,
}) => {
const workspacePage = new WorkspacePage(page);
const workspacePage = new WasmWorkspacePage(page);
await workspacePage.setupEmptyFile(page);
await workspacePage.goToWorkspace();
await workspacePage.mockRPC(

View File

@@ -1,10 +1,10 @@
import { test, expect } from "@playwright/test";
import { WorkspacePage } from "../pages/WorkspacePage";
import { WasmWorkspacePage } from "../pages/WasmWorkspacePage";
const flags = ["enable-inspect-styles"];
test.beforeEach(async ({ page }) => {
await WorkspacePage.init(page);
await WasmWorkspacePage.init(page);
});
const setupFile = async (workspacePage) => {
@@ -90,7 +90,7 @@ const copyPropertyFromPropertyRow = async (panel, property) => {
/**
* Returns the style panel by its title
* @param {WorkspacePage} workspacePage - The workspace page instance
* @param {WasmWorkspacePage} workspacePage - The workspace page instance
* @param {string} title - The title of the panel to retrieve
*/
const getPanelByTitle = async (workspacePage, title) => {
@@ -103,7 +103,7 @@ const getPanelByTitle = async (workspacePage, title) => {
/**
* Selects a layer in the layers panel
* @param {WorkspacePage} workspacePage - The workspace page instance
* @param {WasmWorkspacePage} workspacePage - The workspace page instance
* @param {string} layerName - The name of the layer to select
* @param {string} parentLayerName - The name of the parent layer to expand (optional)
*/
@@ -118,7 +118,7 @@ const selectLayer = async (workspacePage, layerName, parentLayerName) => {
/**
* Opens the Inspect tab
* @param {WorkspacePage} workspacePage - The workspace page instance
* @param {WasmWorkspacePage} workspacePage - The workspace page instance
*/
const openInspectTab = async (workspacePage) => {
@@ -133,7 +133,7 @@ const openInspectTab = async (workspacePage) => {
/**
* @typedef {'hex' | 'rgba' | 'hsla'} ColorSpace
*
* @param {WorkspacePage} workspacePage - The workspace page instance
* @param {WasmWorkspacePage} workspacePage - The workspace page instance
* @param {ColorSpace} colorSpace - The color space to select
*/
const selectColorSpace = async (workspacePage, colorSpace) => {
@@ -148,7 +148,7 @@ const selectColorSpace = async (workspacePage, colorSpace) => {
test.describe("Inspect tab - Styles", () => {
test.skip("Open Inspect tab", async ({ page }) => {
const workspacePage = new WorkspacePage(page);
const workspacePage = new WasmWorkspacePage(page);
await setupFile(workspacePage);
await selectLayer(workspacePage, shapeToLayerName.flex);
@@ -162,7 +162,7 @@ test.describe("Inspect tab - Styles", () => {
});
test.describe("Inspect tab - Flex", () => {
test("Shape Layout Flex ", async ({ page }) => {
const workspacePage = new WorkspacePage(page);
const workspacePage = new WasmWorkspacePage(page);
await setupFile(workspacePage);
await selectLayer(workspacePage, shapeToLayerName.flex);
@@ -178,7 +178,7 @@ test.describe("Inspect tab - Styles", () => {
});
test("Shape Layout Flex Element", async ({ page }) => {
const workspacePage = new WorkspacePage(page);
const workspacePage = new WasmWorkspacePage(page);
await setupFile(workspacePage);
await selectLayer(
@@ -199,7 +199,7 @@ test.describe("Inspect tab - Styles", () => {
});
test("Shape Layout Grid", async ({ page }) => {
const workspacePage = new WorkspacePage(page);
const workspacePage = new WasmWorkspacePage(page);
await setupFile(workspacePage);
await selectLayer(workspacePage, shapeToLayerName.grid);
@@ -216,7 +216,7 @@ test.describe("Inspect tab - Styles", () => {
test.describe("Inspect tab - Shadow", () => {
test("Shape Shadow - Single shadow", async ({ page }) => {
const workspacePage = new WorkspacePage(page);
const workspacePage = new WasmWorkspacePage(page);
await setupFile(workspacePage);
await selectLayer(workspacePage, shapeToLayerName.shadow);
@@ -232,7 +232,7 @@ test.describe("Inspect tab - Styles", () => {
});
test("Shape Shadow - Multiple shadow", async ({ page }) => {
const workspacePage = new WorkspacePage(page);
const workspacePage = new WasmWorkspacePage(page);
await setupFile(workspacePage);
await selectLayer(workspacePage, shapeToLayerName.shadowMultiple);
@@ -249,7 +249,7 @@ test.describe("Inspect tab - Styles", () => {
// FIXME: flaky/random (depends on trace ?)
test.skip("Shape Shadow - Composite shadow", async ({ page }) => {
const workspacePage = new WorkspacePage(page);
const workspacePage = new WasmWorkspacePage(page);
await setupFile(workspacePage);
await selectLayer(workspacePage, shapeToLayerName.shadowComposite);
@@ -278,7 +278,7 @@ test.describe("Inspect tab - Styles", () => {
});
test("Shape - Blur", async ({ page }) => {
const workspacePage = new WorkspacePage(page);
const workspacePage = new WasmWorkspacePage(page);
await setupFile(workspacePage);
await selectLayer(workspacePage, shapeToLayerName.blur);
@@ -295,7 +295,7 @@ test.describe("Inspect tab - Styles", () => {
test.describe("Inspect tab - Border radius", () => {
test("Shape - Border radius - individual", async ({ page }) => {
const workspacePage = new WorkspacePage(page);
const workspacePage = new WasmWorkspacePage(page);
await setupFile(workspacePage);
await selectLayer(
@@ -325,7 +325,7 @@ test.describe("Inspect tab - Styles", () => {
});
test("Shape - Border radius - multiple", async ({ page }) => {
const workspacePage = new WorkspacePage(page);
const workspacePage = new WasmWorkspacePage(page);
await setupFile(workspacePage);
await selectLayer(
@@ -365,7 +365,7 @@ test.describe("Inspect tab - Styles", () => {
});
test("Shape - Border radius - token", async ({ page }) => {
const workspacePage = new WorkspacePage(page);
const workspacePage = new WasmWorkspacePage(page);
await setupFile(workspacePage);
await selectLayer(
@@ -399,7 +399,7 @@ test.describe("Inspect tab - Styles", () => {
test.describe("Inspect tab - Fill", () => {
test("Shape - Fill - Solid", async ({ page }) => {
const workspacePage = new WorkspacePage(page);
const workspacePage = new WasmWorkspacePage(page);
await setupFile(workspacePage);
await selectLayer(workspacePage, shapeToLayerName.fill.solid);
@@ -416,7 +416,7 @@ test.describe("Inspect tab - Styles", () => {
test("Change color space and ensure fill and shorthand changes", async ({
page,
}) => {
const workspacePage = new WorkspacePage(page);
const workspacePage = new WasmWorkspacePage(page);
await setupFile(workspacePage);
await selectLayer(workspacePage, shapeToLayerName.fill.solid);
@@ -454,7 +454,7 @@ test.describe("Inspect tab - Styles", () => {
});
test("Shape - Fill - Gradient", async ({ page }) => {
const workspacePage = new WorkspacePage(page);
const workspacePage = new WasmWorkspacePage(page);
await setupFile(workspacePage);
await selectLayer(workspacePage, shapeToLayerName.fill.gradient);
@@ -469,7 +469,7 @@ test.describe("Inspect tab - Styles", () => {
});
test("Shape - Fill - Image", async ({ page }) => {
const workspacePage = new WorkspacePage(page);
const workspacePage = new WasmWorkspacePage(page);
await setupFile(workspacePage);
await selectLayer(workspacePage, shapeToLayerName.fill.image);
@@ -489,7 +489,7 @@ test.describe("Inspect tab - Styles", () => {
});
test("Shape - Fill - Multiple", async ({ page }) => {
const workspacePage = new WorkspacePage(page);
const workspacePage = new WasmWorkspacePage(page);
await setupFile(workspacePage);
await selectLayer(workspacePage, shapeToLayerName.fill.multiple);
@@ -509,7 +509,7 @@ test.describe("Inspect tab - Styles", () => {
});
test("Shape - Fill - Token", async ({ page }) => {
const workspacePage = new WorkspacePage(page);
const workspacePage = new WasmWorkspacePage(page);
await setupFile(workspacePage);
await selectLayer(workspacePage, shapeToLayerName.fill.token);
@@ -532,7 +532,7 @@ test.describe("Inspect tab - Styles", () => {
test.describe("Inspect tab - Stroke", () => {
test("Shape - Stroke - Solid", async ({ page }) => {
const workspacePage = new WorkspacePage(page);
const workspacePage = new WasmWorkspacePage(page);
await setupFile(workspacePage);
await selectLayer(workspacePage, shapeToLayerName.stroke.solid);
@@ -547,7 +547,7 @@ test.describe("Inspect tab - Styles", () => {
});
test("Shape - Stroke - Gradient", async ({ page }) => {
const workspacePage = new WorkspacePage(page);
const workspacePage = new WasmWorkspacePage(page);
await setupFile(workspacePage);
await selectLayer(workspacePage, shapeToLayerName.stroke.gradient);
@@ -562,7 +562,7 @@ test.describe("Inspect tab - Styles", () => {
});
test("Shape - Stroke - Image", async ({ page }) => {
const workspacePage = new WorkspacePage(page);
const workspacePage = new WasmWorkspacePage(page);
await setupFile(workspacePage);
await selectLayer(workspacePage, shapeToLayerName.stroke.image);
@@ -582,7 +582,7 @@ test.describe("Inspect tab - Styles", () => {
});
test("Shape - Stroke - Multiple", async ({ page }) => {
const workspacePage = new WorkspacePage(page);
const workspacePage = new WasmWorkspacePage(page);
await setupFile(workspacePage);
await selectLayer(workspacePage, shapeToLayerName.stroke.multiple);
@@ -602,7 +602,7 @@ test.describe("Inspect tab - Styles", () => {
});
test("Shape - Stroke - Token", async ({ page }) => {
const workspacePage = new WorkspacePage(page);
const workspacePage = new WasmWorkspacePage(page);
await setupFile(workspacePage);
await selectLayer(workspacePage, shapeToLayerName.stroke.token);
@@ -625,7 +625,7 @@ test.describe("Inspect tab - Styles", () => {
test.describe("Inspect tab - Typography", () => {
test("Text - simple", async ({ page }) => {
const workspacePage = new WorkspacePage(page);
const workspacePage = new WasmWorkspacePage(page);
await setupFile(workspacePage);
await selectLayer(workspacePage, shapeToLayerName.text.simple);
@@ -643,7 +643,7 @@ test.describe("Inspect tab - Styles", () => {
});
test("Text - token", async ({ page }) => {
const workspacePage = new WorkspacePage(page);
const workspacePage = new WasmWorkspacePage(page);
await setupFile(workspacePage);
await selectLayer(workspacePage, shapeToLayerName.text.token);
@@ -679,7 +679,7 @@ test.describe("Inspect tab - Styles", () => {
await expect(textPreview).toBeVisible();
});
test("Text - composite token", async ({ page }) => {
const workspacePage = new WorkspacePage(page);
const workspacePage = new WasmWorkspacePage(page);
await setupFile(workspacePage);
await selectLayer(workspacePage, shapeToLayerName.text.compositeToken);
@@ -705,7 +705,7 @@ test.describe("Inspect tab - Styles", () => {
test.describe("Copy properties", () => {
test("Copy single property", async ({ page }) => {
const workspacePage = new WorkspacePage(page);
const workspacePage = new WasmWorkspacePage(page);
await setupFile(workspacePage);
await selectLayer(workspacePage, shapeToLayerName.flex);
@@ -722,7 +722,7 @@ test.describe("Inspect tab - Styles", () => {
expect(shorthand).toBe("display: flex;");
});
test("Copy shorthand - multiple properties", async ({ page }) => {
const workspacePage = new WorkspacePage(page);
const workspacePage = new WasmWorkspacePage(page);
await setupFile(workspacePage);
await selectLayer(workspacePage, shapeToLayerName.shadow);

View File

@@ -1,14 +1,14 @@
import { test, expect } from "@playwright/test";
import { WorkspacePage } from "../pages/WorkspacePage";
import { WasmWorkspacePage } from "../pages/WasmWorkspacePage";
test.beforeEach(async ({ page }) => {
await WorkspacePage.init(page);
await WasmWorkspacePage.init(page);
});
test("BUG 7466 - Layers tab height extends to the bottom when 'Pages' is collapsed", async ({
page,
}) => {
const workspace = new WorkspacePage(page);
const workspace = new WasmWorkspacePage(page);
await workspace.setupEmptyFile();
await workspace.goToWorkspace();

View File

@@ -1,9 +1,9 @@
import { test, expect } from "@playwright/test";
import WorkspacePage from "../pages/WorkspacePage";
import { WasmWorkspacePage } from "../pages/WasmWorkspacePage";
test.beforeEach(async ({ page }) => {
await WorkspacePage.init(page);
await WorkspacePage.mockConfigFlags(page, [
await WasmWorkspacePage.init(page);
await WasmWorkspacePage.mockConfigFlags(page, [
"enable-subscriptions",
"disable-onboarding",
]);
@@ -13,16 +13,16 @@ test.describe("Subscriptions: workspace", () => {
test("Unlimited team should have 'Power up your plan' link in main menu", async ({
page,
}) => {
const workspacePage = new WorkspacePage(page);
const workspacePage = new WasmWorkspacePage(page);
await workspacePage.setupEmptyFile();
await WorkspacePage.mockRPC(
await WasmWorkspacePage.mockRPC(
page,
"get-profile",
"subscription/get-profile-unlimited-subscription.json",
);
await WorkspacePage.mockRPC(
await WasmWorkspacePage.mockRPC(
page,
"get-subscription-usage",
"subscription/get-subscription-usage.json",
@@ -41,16 +41,16 @@ test.describe("Subscriptions: workspace", () => {
test("Enterprise team should not have 'Power up your plan' link in main menu", async ({
page,
}) => {
const workspacePage = new WorkspacePage(page);
const workspacePage = new WasmWorkspacePage(page);
await workspacePage.setupEmptyFile();
await WorkspacePage.mockRPC(
await WasmWorkspacePage.mockRPC(
page,
"get-profile",
"subscription/get-profile-enterprise-subscription.json",
);
await WorkspacePage.mockRPC(
await WasmWorkspacePage.mockRPC(
page,
"get-subscription-usage",
"subscription/get-subscription-usage.json",
@@ -69,16 +69,16 @@ test.describe("Subscriptions: workspace", () => {
test("Professional team should have 7 days autosaved versions", async ({
page,
}) => {
const workspacePage = new WorkspacePage(page);
const workspacePage = new WasmWorkspacePage(page);
await workspacePage.setupEmptyFile();
await WorkspacePage.mockRPC(
await WasmWorkspacePage.mockRPC(
page,
"get-profile",
"subscription/get-profile-enterprise-subscription.json",
);
await WorkspacePage.mockRPC(
await WasmWorkspacePage.mockRPC(
page,
"get-subscription-usage",
"subscription/get-subscription-usage.json",
@@ -105,22 +105,22 @@ test.describe("Subscriptions: workspace", () => {
test("Unlimited team should have 30 days autosaved versions", async ({
page,
}) => {
const workspacePage = new WorkspacePage(page);
const workspacePage = new WasmWorkspacePage(page);
await workspacePage.setupEmptyFile();
await WorkspacePage.mockRPC(
await WasmWorkspacePage.mockRPC(
page,
"get-profile",
"subscription/get-profile-unlimited-subscription.json",
);
await WorkspacePage.mockRPC(
await WasmWorkspacePage.mockRPC(
page,
"get-subscription-usage",
"subscription/get-subscription-usage.json",
);
await WorkspacePage.mockRPC(
await WasmWorkspacePage.mockRPC(
page,
"get-teams",
"subscription/get-teams-unlimited-one-team.json",
@@ -147,22 +147,22 @@ test.describe("Subscriptions: workspace", () => {
test("Unlimited team should have 90 days autosaved versions", async ({
page,
}) => {
const workspacePage = new WorkspacePage(page);
const workspacePage = new WasmWorkspacePage(page);
await workspacePage.setupEmptyFile();
await WorkspacePage.mockRPC(
await WasmWorkspacePage.mockRPC(
page,
"get-profile",
"subscription/get-profile-enterprise-subscription.json",
);
await WorkspacePage.mockRPC(
await WasmWorkspacePage.mockRPC(
page,
"get-subscription-usage",
"subscription/get-subscription-usage.json",
);
await WorkspacePage.mockRPC(
await WasmWorkspacePage.mockRPC(
page,
"get-teams",
"subscription/get-teams-enterprise-one-team.json",

View File

@@ -1493,10 +1493,8 @@ test.describe("Tokens - creation", () => {
const nameField = tokensUpdateCreateModal.getByLabel("Name");
await nameField.fill(newTokenTitle);
const referenceTabButton = tokensUpdateCreateModal.getByRole("button", {
name: "Use a reference",
});
referenceTabButton.click();
const referenceTabButton = tokensUpdateCreateModal.getByTestId("reference-opt");
await referenceTabButton.click();
const referenceField = tokensUpdateCreateModal.getByRole("textbox", {
name: "Reference",

View File

@@ -1,12 +1,12 @@
import { test, expect } from "@playwright/test";
import { WorkspacePage } from "../pages/WorkspacePage";
import { WasmWorkspacePage } from "../pages/WasmWorkspacePage";
import { BaseWebSocketPage } from "../pages/BaseWebSocketPage";
import { Clipboard } from "../../helpers/Clipboard";
test.beforeEach(async ({ page, context }) => {
await Clipboard.enable(context, Clipboard.Permission.ALL);
await WorkspacePage.init(page);
await WasmWorkspacePage.init(page);
await BaseWebSocketPage.mockRPC(page, "get-teams", "get-teams-variants.json");
});
@@ -127,7 +127,7 @@ const validateVariant = async (variant) => {
};
test("User creates a variant", async ({ page }) => {
const workspacePage = new WorkspacePage(page);
const workspacePage = new WasmWorkspacePage(page);
await setupVariantsFileWithVariant(workspacePage);
await workspacePage.clickLeafLayer("Rectangle");
@@ -154,7 +154,7 @@ test("User creates a variant", async ({ page }) => {
});
test("User duplicates a variant container", async ({ page }) => {
const workspacePage = new WorkspacePage(page);
const workspacePage = new WasmWorkspacePage(page);
await setupVariantsFileWithVariant(workspacePage);
const variant = await findVariant(workspacePage, 0);
@@ -177,7 +177,7 @@ test("User duplicates a variant container", async ({ page }) => {
});
test("User copy paste a variant container", async ({ page, context }) => {
const workspacePage = new WorkspacePage(page);
const workspacePage = new WasmWorkspacePage(page);
// Access to the read/write clipboard necesary for this functionality
await setupVariantsFileWithVariant(workspacePage);
await workspacePage.mockRPC(
@@ -212,7 +212,7 @@ test("User copy paste a variant container", async ({ page, context }) => {
});
test("User cut paste a variant container", async ({ page }) => {
const workspacePage = new WorkspacePage(page);
const workspacePage = new WasmWorkspacePage(page);
await setupVariantsFileWithVariant(workspacePage);
const variant = await findVariant(workspacePage, 0);
@@ -240,7 +240,7 @@ test("User cut paste a variant container", async ({ page }) => {
test("User cut paste a variant container into a board, and undo twice", async ({
page,
}) => {
const workspacePage = new WorkspacePage(page);
const workspacePage = new WasmWorkspacePage(page);
await setupVariantsFileWithVariant(workspacePage);
const variant = await findVariant(workspacePage, 0);
@@ -283,7 +283,7 @@ test("User cut paste a variant container into a board, and undo twice", async ({
});
test("User copy paste a variant", async ({ page }) => {
const workspacePage = new WorkspacePage(page);
const workspacePage = new WasmWorkspacePage(page);
await setupVariantsFileWithVariant(workspacePage);
const variant = await findVariant(workspacePage, 0);
@@ -308,7 +308,7 @@ test("User copy paste a variant", async ({ page }) => {
});
test("User cut paste a variant outside the container", async ({ page }) => {
const workspacePage = new WorkspacePage(page);
const workspacePage = new WasmWorkspacePage(page);
await setupVariantsFileWithVariant(workspacePage);
const variant = await findVariant(workspacePage, 0);
@@ -333,7 +333,7 @@ test("User cut paste a variant outside the container", async ({ page }) => {
});
test("User drag and drop a variant outside the container", async ({ page }) => {
const workspacePage = new WorkspacePage(page);
const workspacePage = new WasmWorkspacePage(page);
await setupVariantsFileWithVariant(workspacePage);
const variant = await findVariant(workspacePage, 0);
@@ -347,7 +347,7 @@ test("User drag and drop a variant outside the container", async ({ page }) => {
});
test("User cut paste a component inside a variant", async ({ page }) => {
const workspacePage = new WorkspacePage(page);
const workspacePage = new WasmWorkspacePage(page);
await setupVariantsFileWithVariant(workspacePage);
const variant = await findVariant(workspacePage, 0);
@@ -378,7 +378,7 @@ test("User cut paste a component inside a variant", async ({ page }) => {
test("User cut paste a component with path inside a variant", async ({
page,
}) => {
const workspacePage = new WorkspacePage(page);
const workspacePage = new WasmWorkspacePage(page);
await setupVariantsFileWithVariant(workspacePage);
const variant = await findVariant(workspacePage, 0);
@@ -417,7 +417,7 @@ test("User cut paste a component with path inside a variant", async ({
test("User drag and drop a component with path inside a variant", async ({
page,
}) => {
const workspacePage = new WorkspacePage(page);
const workspacePage = new WasmWorkspacePage(page);
await setupVariantsFileWithVariant(workspacePage);
const variant = findVariantNoWait(workspacePage, 0);
@@ -450,7 +450,7 @@ test("User drag and drop a component with path inside a variant", async ({
});
test("User cut paste a variant into another container", async ({ page }) => {
const workspacePage = new WorkspacePage(page);
const workspacePage = new WasmWorkspacePage(page);
await setupVariantsFileWithVariant(workspacePage);
// Create anothe variant

View File

@@ -1,15 +1,15 @@
import { test, expect } from "@playwright/test";
import { WorkspacePage } from "../pages/WorkspacePage";
import { WasmWorkspacePage } from "../pages/WasmWorkspacePage";
import { presenceFixture } from "../../data/workspace/ws-notifications";
test.beforeEach(async ({ page }) => {
await WorkspacePage.init(page);
const workspacePage = new WorkspacePage(page);
await WasmWorkspacePage.init(page);
const workspacePage = new WasmWorkspacePage(page);
await workspacePage.setupEmptyFile(page);
});
test("Save and restore version", async ({ page }) => {
const workspacePage = new WorkspacePage(page);
const workspacePage = new WasmWorkspacePage(page);
await workspacePage.mockRPC(/get\-file\?/, "workspace/versions-init.json");
await workspacePage.mockRPC(
@@ -97,7 +97,7 @@ test("Save and restore version", async ({ page }) => {
});
test("BUG 11006 - Fix history panel shortcut", async ({ page }) => {
const workspacePage = new WorkspacePage(page);
const workspacePage = new WasmWorkspacePage(page);
await workspacePage.mockRPC(/get\-file\?/, "workspace/versions-init.json");
await workspacePage.mockRPC(
"get-file-snapshots?file-id=*",

View File

@@ -1,12 +1,12 @@
import { test, expect } from "@playwright/test";
import { WorkspacePage } from "../pages/WorkspacePage";
import { WasmWorkspacePage } from "../pages/WasmWorkspacePage";
test.beforeEach(async ({ page }) => {
await WorkspacePage.init(page);
await WasmWorkspacePage.init(page);
});
test("Group bubbles when zooming out if they overlap", async ({ page }) => {
const workspacePage = new WorkspacePage(page);
const workspacePage = new WasmWorkspacePage(page);
await workspacePage.setupEmptyFile();
await workspacePage.setupFileWithComments();

View File

@@ -0,0 +1,26 @@
import { test, expect } from "@playwright/test";
import { WasmWorkspacePage } from "../pages/WasmWorkspacePage";
test.beforeEach(async ({ page }) => {
await WasmWorkspacePage.init(page);
});
test("BUG 13305 - Fix resize board to fit content", async ({ page }) => {
const workspacePage = new WasmWorkspacePage(page);
await workspacePage.setupEmptyFile();
await workspacePage.mockGetFile("workspace/get-file-13305.json");
await workspacePage.mockRPC("update-file?id=*", "workspace/update-file-13305.json");
await workspacePage.goToWorkspace({
fileId: "9666e946-78e8-8111-8007-8fe5f0f454bf",
pageId: "9666e946-78e8-8111-8007-8fe5f0f49ac6",
});
await workspacePage.clickLeafLayer("Board");
await workspacePage.rightSidebar.getByRole("button", { name: "Resize board to fit content" }).click();
await expect(workspacePage.rightSidebar.getByTitle("Width").getByRole("textbox")).toHaveValue("630");
await expect(workspacePage.rightSidebar.getByTitle("Height").getByRole("textbox")).toHaveValue("630");
await expect(workspacePage.rightSidebar.getByTitle("X axis").getByRole("textbox")).toHaveValue("110");
await expect(workspacePage.rightSidebar.getByTitle("Y axis").getByRole("textbox")).toHaveValue("110");
});

View File

@@ -1,5 +1,5 @@
import { test, expect } from "@playwright/test";
import { WorkspacePage } from "../pages/WorkspacePage";
import { WasmWorkspacePage } from "../pages/WasmWorkspacePage";
const mainFileId = "3622460c-3408-81e2-8005-2fd0e55888b7";
const sharedFileId = "3622460c-3408-81e2-8005-2fc938010233";
@@ -13,12 +13,12 @@ const sharedFileFragmentId1 = "3622460c-3408-81e2-8005-31859c15ff91";
const sharedFileFragmentId2 = "3622460c-3408-81e2-8005-31859c15ff90";
test.beforeEach(async ({ page }) => {
await WorkspacePage.init(page);
await WasmWorkspacePage.init(page);
});
// Fix for https://tree.taiga.io/project/penpot/issue/9042
test("Bug 9056 - 'More info' doesn't open the update tab", async ({ page }) => {
const workspacePage = new WorkspacePage(page);
const workspacePage = new WasmWorkspacePage(page);
await workspacePage.setupEmptyFile(page);
await workspacePage.mockRPC(
@@ -76,7 +76,7 @@ test("Bug 9056 - 'More info' doesn't open the update tab", async ({ page }) => {
test("Bug 10113 - Empty library modal for non-empty library", async ({
page,
}) => {
const workspace = new WorkspacePage(page);
const workspace = new WasmWorkspacePage(page);
await workspace.setupEmptyFile(page);
await workspace.mockRPC(/get\-file\?/, "workspace/get-file-10113.json");

View File

@@ -1,13 +1,13 @@
import { test, expect } from "@playwright/test";
import { WorkspacePage } from "../pages/WorkspacePage";
import { WasmWorkspacePage } from "../pages/WasmWorkspacePage";
import { presenceFixture } from "../../data/workspace/ws-notifications";
test.beforeEach(async ({ page }) => {
await WorkspacePage.init(page);
await WasmWorkspacePage.init(page);
const workspacePage = new WorkspacePage(page);
const workspacePage = new WasmWorkspacePage(page);
await workspacePage.setupEmptyFile(page);
await WorkspacePage.mockRPC(page, "get-teams", "get-teams-role-viewer.json");
await WasmWorkspacePage.mockRPC(page, "get-teams", "get-teams-role-viewer.json");
await workspacePage.goToWorkspace();
});

View File

@@ -353,33 +353,24 @@ test("Copy/paste properties", async ({ page, context }) => {
await page.getByText("Copy/Paste as").hover();
await page.getByText("Paste properties").click();
await page
.getByTestId("layer-item")
.getByText("Rectangle")
.first()
.click({ button: "right" });
await page.getByText("Rectangle").first().click({ button: "right" });
await page.getByText("Copy/Paste as").hover();
await page.getByText("Paste properties").click();
await page.getByText("Board").nth(2).click({ button: "right" });
await page.getByText("Copy/Paste as").hover();
await page.getByText("Paste properties").click();
await page
.getByTestId("layer-item")
.getByText("Board")
.locator("div")
.filter({ hasText: "Path" })
.nth(1)
.click({ button: "right" });
await page.getByText("Copy/Paste as").hover();
await page.getByText("Paste properties").click();
await page
.getByTestId("layer-item")
.getByText("Path")
.click({ button: "right" });
await page.getByText("Copy/Paste as").hover();
await page.getByText("Paste properties").click();
await page
.getByTestId("layer-item")
.getByText("Ellipse")
.click({ button: "right" });
await page.getByText("Ellipse").click({ button: "right" });
await page.getByText("Copy/Paste as").hover();
await page.getByText("Paste properties").click();
});

View File

@@ -187,6 +187,9 @@ importers:
sax:
specifier: ^1.4.1
version: 1.4.4
scheduler:
specifier: ^0.27.0
version: 0.27.0
source-map-support:
specifier: ^0.5.21
version: 0.5.21
@@ -257,8 +260,8 @@ importers:
packages/tokenscript:
dependencies:
'@tokens-studio/tokenscript-interpreter':
specifier: ^0.23.1
version: 0.23.1
specifier: ^0.26.0
version: 0.26.0
packages/ui:
dependencies:
@@ -1717,8 +1720,8 @@ packages:
peerDependencies:
style-dictionary: '>=4.3.0 < 6'
'@tokens-studio/tokenscript-interpreter@0.23.1':
resolution: {integrity: sha512-aIcJprCkHIyckl0Knn78Sn7ef3U3IXLjNv9MOePdNR0Mz3Z4PleerldtfLmr1DdXUXiroVSyJROyJrO3TfB2Gg==}
'@tokens-studio/tokenscript-interpreter@0.26.0':
resolution: {integrity: sha512-dGjvUJnXRspWYp98FZw43l4cN+0ey/cF5sEJjL3coKc5C7DY7MsKgkmOONizmaZqf13GUIzklTEas3gt3jvrOQ==}
engines: {node: '>=16.0.0'}
hasBin: true
@@ -6712,7 +6715,7 @@ snapshots:
is-mergeable-object: 1.1.1
style-dictionary: 5.0.0-rc.1(tslib@2.8.1)
'@tokens-studio/tokenscript-interpreter@0.23.1':
'@tokens-studio/tokenscript-interpreter@0.26.0':
dependencies:
arktype: 2.1.29
commander: 14.0.3

View File

@@ -244,6 +244,13 @@
--assets-component-second-border-selected: var(--color-background-primary);
--assets-component-hightlight: var(--color-accent-secondary);
--radio-btns-background-color: var(--color-background-tertiary);
--radio-btn-background-color-selected: var(--color-background-quaternary);
--radio-btn-foreground-color: var(--color-foreground-secondary);
--radio-btn-foreground-color-selected: var(--color-accent-primary);
--radio-btn-border-color: var(--color-background-tertiary);
--radio-btn-border-color-selected: var(--color-background-quaternary);
--library-name-foreground-color: var(--color-foreground-primary);
--library-content-foreground-color: var(--color-foreground-secondary);
@@ -416,6 +423,13 @@
--tab-border-color: var(--color-background-tertiary);
--tab-border-color-selected: var(--color-background-secondary);
--radio-btns-background-color: var(--color-background-tertiary);
--radio-btn-background-color-selected: var(--color-background-primary);
--radio-btn-foreground-color: var(--color-foreground-secondary);
--radio-btn-foreground-color-selected: var(--color-accent-primary);
--radio-btn-border-color: var(--color-background-tertiary);
--radio-btn-border-color-selected: var(--color-background-secondary);
--button-icon-background-color-selected: var(--color-background-primary);
--button-icon-border-color-selected: var(--color-background-secondary);

View File

@@ -43,9 +43,13 @@
(> dy dx)
(assoc :x (- (:x point) (* sx (- dy dx)))))))
(defn resize-shape [{:keys [x y width height] :as shape} initial point lock? mod?]
(defn resize-shape [{:keys [x y width height] :as shape} initial point lock? mod? snap-pixel?]
(if (and (some? x) (some? y) (some? width) (some? height))
(let [draw-rect (grc/make-rect initial (cond-> point lock? (adjust-ratio initial)))
(let [draw-rect (cond-> (grc/make-rect initial (cond-> point lock? (adjust-ratio initial)))
snap-pixel?
(-> (update :width max 1)
(update :height max 1)))
shape-rect (grc/make-rect x y width height)
scalev (gpt/point (/ (:width draw-rect)
@@ -64,8 +68,8 @@
(ctm/move movev)))))
shape))
(defn update-drawing [state initial point lock? mod?]
(update-in state [:workspace-drawing :object] resize-shape initial point lock? mod?))
(defn- update-drawing [state initial point lock? mod? snap-pixel?]
(update-in state [:workspace-drawing :object] resize-shape initial point lock? mod? snap-pixel?))
(defn move-drawing
[{:keys [x y]}]
@@ -120,7 +124,7 @@
(rx/map move-drawing))
(->> ms/mouse-position
(rx/filter #(> (gpt/distance % initial) (/ 2 zoom)))
(rx/filter #(> (* (gpt/distance % initial) zoom) 10))
;; Take until before the snap calculation otherwise we could cancel the snap in the worker
;; and its a problem for fast moving drawing
(rx/take-until stopper)
@@ -131,7 +135,7 @@
(rx/map (partial array/conj current)))))
(rx/map
(fn [[_ shift? mod? point]]
#(update-drawing % initial (cond-> point snap-pixel? (gpt/round-step 1)) shift? mod?))))))
#(update-drawing % initial (cond-> point snap-pixel? (gpt/round-step 1)) shift? mod? snap-pixel?))))))
(->> (rx/of (common/handle-finish-drawing))
(rx/delay 100)))))))

View File

@@ -571,11 +571,13 @@
nil
(ctm/has-geometry? (:modifiers data))
(d/vec2 id (ctm/modifiers->transform (:modifiers data)))
(let [parent (:geometry-parent (:modifiers data))
kind (if (d/not-empty? parent) :parent :child)]
(d/vec2 id {:transform (ctm/modifiers->transform (:modifiers data)) :kind kind}))
;; Unit matrix is used for reflowing
:else
(d/vec2 id default-transform))))))
(d/vec2 id {:transform default-transform :kind :parent}))))))
(defn- parse-geometry-modifiers
[modif-tree]

View File

@@ -32,6 +32,7 @@
[app.main.features :as features]
[app.main.fonts :as fonts]
[app.main.router :as rt]
[app.render-wasm.api :as wasm.api]
[app.util.text-editor :as ted]
[app.util.text.content.styles :as styles]
[app.util.timers :as ts]
@@ -508,12 +509,12 @@
ptk/EffectEvent
(effect [_ state _]
(when (features/active-feature? state "text-editor/v2")
(let [instance (:workspace-editor state)
styles (some-> (editor.v2/getCurrentStyle instance)
(styles/get-styles-from-style-declaration :removed-mixed true)
((comp update-node-fn migrate-node))
(styles/attrs->styles))]
(editor.v2/applyStylesToSelection instance styles)))))))
(when-let [instance (:workspace-editor state)]
(let [styles (some-> (editor.v2/getCurrentStyle instance)
(styles/get-styles-from-style-declaration :removed-mixed true)
((comp update-node-fn migrate-node))
(styles/attrs->styles))]
(editor.v2/applyStylesToSelection instance styles))))))))
;; --- RESIZE UTILS
@@ -777,17 +778,30 @@
(rx/of (v2-update-text-editor-styles id attrs)))
(when (features/active-feature? state "render-wasm/v1")
(rx/of (dwwt/resize-wasm-text-debounce id)))))))
(rx/concat
;; Apply style to selected spans and sync content
(when (wasm.api/text-editor-is-active?)
(let [span-attrs (select-keys attrs txt/text-node-attrs)]
(when (not (empty? span-attrs))
(let [result (wasm.api/apply-style-to-selection span-attrs)]
(when result
(rx/of (v2-update-text-shape-content
(:shape-id result) (:content result)
:update-name? true)))))))
;; Resize (with delay for font-id changes)
(cond->> (rx/of (dwwt/resize-wasm-text id))
(contains? attrs :font-id)
(rx/delay 200))))))))
ptk/EffectEvent
(effect [_ state _]
(when (features/active-feature? state "text-editor/v2")
(let [instance (:workspace-editor state)
attrs-to-override (some-> (editor.v2/getCurrentStyle instance)
(styles/get-styles-from-style-declaration))
overriden-attrs (merge attrs-to-override attrs)
styles (styles/attrs->styles overriden-attrs)]
(editor.v2/applyStylesToSelection instance styles))))))
(when-let [instance (:workspace-editor state)]
(let [attrs-to-override (some-> (editor.v2/getCurrentStyle instance)
(styles/get-styles-from-style-declaration))
overriden-attrs (merge attrs-to-override attrs)
styles (styles/attrs->styles overriden-attrs)]
(editor.v2/applyStylesToSelection instance styles)))))))
(defn update-all-attrs
[ids attrs]
@@ -936,14 +950,11 @@
new-shape))
{:save-undo? save-undo? :undo-group (when new-shape? id)})
(if (and (not= :fixed (:grow-type shape)) finalize?)
(dwm/apply-wasm-modifiers
(dwwt/resize-wasm-text-modifiers shape content)
{:undo-group (when new-shape? id)})
(dwm/set-wasm-modifiers
(dwwt/resize-wasm-text-modifiers shape content)
{:undo-group (when new-shape? id)})))
(let [modifiers (dwwt/resize-wasm-text-modifiers shape content)
options {:undo-group (when new-shape? id)}]
(if (and (not= :fixed (:grow-type shape)) finalize?)
(dwm/apply-wasm-modifiers modifiers options)
(dwm/set-wasm-modifiers modifiers options))))
(when finalize?
(rx/concat

View File

@@ -53,26 +53,27 @@
([value shape-ids attributes] (update-shape-radius-all value shape-ids attributes nil))
([value shape-ids _attributes page-id] ; The attributes param is needed to have the same arity that other update functions
(when (number? value)
(dwsh/update-shapes shape-ids
(fn [shape]
(ctsr/set-radius-to-all-corners shape value))
{:reg-objects? true
:ignore-touched true
:page-id page-id
:attrs ctt/border-radius-keys}))))
(let [value (max 0 value)]
(dwsh/update-shapes shape-ids
(fn [shape]
(ctsr/set-radius-to-all-corners shape value))
{:reg-objects? true
:ignore-touched true
:page-id page-id
:attrs ctt/border-radius-keys})))))
(defn update-shape-radius-for-corners
([value shape-ids attributes] (update-shape-radius-for-corners value shape-ids attributes nil))
([value shape-ids attributes page-id]
(when (number? value)
(dwsh/update-shapes shape-ids
(fn [shape]
(ctsr/set-radius-for-corners shape attributes value))
{:reg-objects? true
:ignore-touched true
:page-id page-id
:attrs ctt/border-radius-keys}))))
(let [value (max 0 value)]
(dwsh/update-shapes shape-ids
(fn [shape]
(ctsr/set-radius-for-corners shape attributes value))
{:reg-objects? true
:ignore-touched true
:page-id page-id
:attrs ctt/border-radius-keys})))))
(defn update-opacity
([value shape-ids attributes] (update-opacity value shape-ids attributes nil))
([value shape-ids _attributes page-id] ; The attributes param is needed to have the same arity that other update functions

View File

@@ -409,7 +409,7 @@
modif-tree (dwm/build-modif-tree ids objects get-modifier)]
(if (features/active-feature? state "render-wasm/v1")
(rx/of (dwm/apply-wasm-modifiers modif-tree {:ignore-snap-pixel true}))
(rx/of (dwm/apply-wasm-modifiers modif-tree (assoc options :ignore-snap-pixel true)))
(let [modif-tree (gm/set-objects-modifiers modif-tree objects)]
(rx/of (dwm/apply-modifiers* objects modif-tree nil options)))))))))
@@ -1261,7 +1261,6 @@
(some? new-modif)
(assoc (:id frame) {:modifiers new-modif})))))
{}))]
(if (features/active-feature? state "render-wasm/v1")
(rx/of (dwm/apply-wasm-modifiers modifiers {:undo-group undo-group}))
(rx/of (dwm/apply-modifiers {:modifiers modifiers :undo-group undo-group})))))))

View File

@@ -72,7 +72,6 @@
(when-let [file-id (or (:file-id data) file-id)]
(println "File ID: " (str file-id)))
(println "Version: " (:full cf/version))
(println "URI: " (str cf/public-uri))
(println "HREF: " (rt/get-current-href))
(println)
@@ -88,24 +87,36 @@
(.error js/console "error on generating report" cause)
nil)))
(defn- show-not-blocking-error
"Show a non user blocking error notification"
[cause]
(let [data (ex-data cause)
hint (or (some-> (:hint data) ex/first-line)
(ex-message cause))]
(defn submit-report
"Report the error report to the audit log subsystem"
[& {:keys [event-name report hint] :or {event-name "unhandled-exception"}}]
(when (and (not (str/empty? hint))
(string? report)
(string? event-name))
(st/emit!
(ev/event {::ev/name "unhandled-exception"
(ev/event {::ev/name event-name
:hint hint
:href (rt/get-current-href)
:type (get data :type :unknown)
:report (generate-report cause)})
:report report}))))
(ntf/show {:content (tr "errors.unexpected-exception" hint)
:type :toast
:level :error
:timeout 3000}))))
(defn flash
"Show error notification banner and emit error report"
[& {:keys [type hint cause] :or {type :handled}}]
(when (ex/exception? cause)
(when-let [event-name (case type
:handled "handled-exception"
:unhandled "unhandled-exception"
:silent nil)]
(let [report (generate-report cause)]
(submit-report :event-name event-name
:report report
:hint (ex/get-hint cause)))))
(st/emit!
(ntf/show {:content (or ^boolean hint (tr "errors.generic"))
:type :toast
:level :error
:timeout 5000})))
(defmethod ptk/handle-error :default
[error]
@@ -114,7 +125,7 @@
(ptk/handle-error (assoc error :type :assertion))
(when-let [cause (::instance error)]
(ex/print-throwable cause :prefix "Unexpected Error")
(show-not-blocking-error cause))))
(flash :cause cause :type :unhandled))))
;; We receive a explicit authentication error; If the uri is for
;; workspace, dashboard, viewer or settings, then assign the exception
@@ -203,7 +214,7 @@
(defmethod ptk/handle-error :assertion
[error]
(when-let [cause (::instance error)]
(show-not-blocking-error cause)
(flash :cause cause :type :handled)
(ex/print-throwable cause :prefix "Assertion Error")))
;; ;; All the errors that happens on worker are handled here.
@@ -307,7 +318,7 @@
:else
(when-let [cause (::instance error)]
(ex/print-throwable cause :prefix "Restriction Error")
(show-not-blocking-error cause))))
(flash :cause cause :type :unhandled))))
;; This happens when the backed server fails to process the
;; request. This can be caused by an internal assertion or any other
@@ -333,14 +344,14 @@
(set! last-exception cause)
(when-not (is-ignorable-exception? cause)
(ex/print-throwable cause :prefix "Uncaught Exception")
(ts/schedule #(show-not-blocking-error cause)))))
(ts/schedule #(flash :cause cause :type :unhandled)))))
(on-unhandled-rejection [event]
(.preventDefault ^js event)
(when-let [cause (unchecked-get event "reason")]
(set! last-exception cause)
(ex/print-throwable cause :prefix "Uncaught Rejection")
(ts/schedule #(show-not-blocking-error cause))))]
(ts/schedule #(flash :cause cause :type :unhandled))))]
(.addEventListener g/window "error" on-unhandled-error)
(.addEventListener g/window "unhandledrejection" on-unhandled-rejection)

View File

@@ -50,17 +50,41 @@
(set/union (get team :features))
(setup-wasm-features state))))
(defn enabled-by-flags?
[{:keys [features-runtime features]} feature]
(or (contains? features-runtime feature)
(contains? features feature)))
(defn enabled-without-migration?
[{:keys [features-runtime features]} feature]
(or (contains? features-runtime feature)
(contains? global-enabled-features feature)
(contains? features feature)))
(defn wasm-url-override
[state]
(case (get (rt/get-params state) :wasm)
"true" true
"false" false
nil))
(defn active-feature?
"Given a state and feature, check if feature is enabled."
[state feature]
(assert (contains? cfeat/supported-features feature) "feature not supported")
(let [runtime-features (get state :features-runtime)
enabled-features (get state :features)]
(or (contains? runtime-features feature)
(if (contains? cfeat/no-migration-features feature)
(or (contains? global-enabled-features feature)
(contains? enabled-features feature))
(contains? enabled-features feature)))))
(assert (contains? cfeat/supported-features feature)
"feature not supported")
(let [wasm-override (when (= feature "render-wasm/v1")
(wasm-url-override state))]
(cond
(some? wasm-override)
wasm-override
(contains? cfeat/no-migration-features feature)
(enabled-without-migration? state feature)
:else
(enabled-by-flags? state feature))))
(def ^:private features-ref
(l/derived (l/key :features) st/state))

View File

@@ -10,9 +10,9 @@
[app.util.dom :as dom]
[rumext.v2 :as mf]))
(mf/defc file-uploader*
(mf/defc file-uploader
{::mf/forward-ref true}
[{:keys [accept multi label-text label-class input-id on-selected data-testid]} input-ref]
[{:keys [accept multi label-text label-class input-id on-selected data-testid] :as props} input-ref]
(let [opt-pick-one #(if multi % (first %))
on-files-selected

View File

@@ -0,0 +1,107 @@
;; This Source Code Form is subject to the terms of the Mozilla Public
;; License, v. 2.0. If a copy of the MPL was not distributed with this
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
;;
;; Copyright (c) KALEIDOS INC
(ns app.main.ui.components.radio-buttons
(:require-macros [app.main.style :as stl])
(:require
[app.common.data :as d]
[app.common.data.macros :as dm]
[app.main.ui.ds.foundations.assets.icon :refer [icon*]]
[app.main.ui.formats :as fmt]
[app.util.dom :as dom]
[rumext.v2 :as mf]))
(def context
(mf/create-context nil))
(mf/defc radio-button
{::mf/props :obj}
[{:keys [icon id value disabled title icon-class type]}]
(let [context (mf/use-ctx context)
allow-empty (unchecked-get context "allow-empty")
type (if ^boolean type
type
(if ^boolean allow-empty
"checkbox"
"radio"))
on-change (unchecked-get context "on-change")
selected (unchecked-get context "selected")
name (unchecked-get context "name")
encode-fn (unchecked-get context "encode-fn")
checked? (= selected value)
value (encode-fn value)]
[:label {:html-for id
:data-testid id
:title title
:class (stl/css-case
:radio-icon true
:checked checked?
:disabled disabled)}
(if (some? icon)
[:> icon* {:icon-id icon :class icon-class :aria-hidden true}]
[:span {:class (stl/css :title-name)} value])
[:input {:id id
:on-change on-change
:type type
:name name
:disabled disabled
:value value
:default-checked checked?}]]))
(mf/defc radio-buttons
{::mf/props :obj}
[{:keys [name children on-change selected class wide encode-fn decode-fn allow-empty] :as props}]
(let [encode-fn (d/nilv encode-fn identity)
decode-fn (d/nilv decode-fn identity)
nitems (if (array? children)
(count (keep identity children))
1)
;; FIXME: we should handle this with CSS
width (mf/with-memo [nitems]
(if (= wide true)
"unset"
(fmt/format-pixels
(+ (* 4 (- nitems 1))
(* 32 nitems)))))
on-change'
(mf/use-fn
(mf/deps selected on-change)
(fn [event]
(let [input (dom/get-target event)
value (dom/get-target-val event)
;; Only allow null values when the "allow-empty" prop is true
value (when (or (not allow-empty)
(not= value selected)) value)]
(when (fn? on-change)
(on-change (decode-fn value) event))
(dom/blur! input))))
context-value
(mf/spread-object props
;; We pass a special metadata for disable
;; key casing transformation in this
;; concrete case, because this component
;; uses legacy mode and props are in
;; kebab-case style
^{::mf/transform false}
{:on-change on-change'
:encode-fn encode-fn
:decode-fn decode-fn})]
[:& (mf/provider context) {:value context-value}
[:div {:class (dm/str class " " (stl/css :radio-btn-wrapper))
:style {:width width}
:key (dm/str name "-" selected)}
children]]))

View File

@@ -0,0 +1,79 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
//
// Copyright (c) KALEIDOS INC
@use "refactor/common-refactor.scss" as deprecated;
.radio-btn-wrapper {
@include deprecated.flexCenter;
border-radius: deprecated.$br-8;
height: deprecated.$s-32;
background-color: var(--input-background-color);
gap: deprecated.$s-4;
}
.radio-icon {
--radio-icon-border-color: var(--radio-btn-border-color);
@include deprecated.buttonStyle;
@include deprecated.flexCenter;
@include deprecated.focusRadio;
height: deprecated.$s-32;
flex-grow: 1;
border-radius: deprecated.$s-8;
box-sizing: border-box;
border: deprecated.$br-2 solid var(--radio-icon-border-color);
input {
display: none;
}
svg {
@extend .button-icon;
stroke: var(--radio-btn-foreground-color);
}
.title-name {
@include deprecated.uppercaseTitleTipography;
color: var(--radio-btn-foreground-color);
}
&:hover {
svg {
stroke: var(--radio-btn-foreground-color-selected);
}
}
}
.checked {
--radio-icon-border-color: var(--radio-btn-border-color-selected);
background-color: var(--radio-btn-background-color-selected);
svg {
stroke: var(--radio-btn-foreground-color-selected);
}
.title-name {
color: var(--radio-btn-foreground-color-selected);
}
}
.disabled {
cursor: default;
background-color: transparent;
border: deprecated.$s-2 solid transparent;
svg {
stroke: var(--button-foreground-color-disabled);
}
.title-name {
color: var(--button-foreground-color-disabled);
}
&:hover {
background-color: transparent;
border: deprecated.$s-2 solid transparent;
svg {
stroke: var(--button-foreground-color-disabled);
}
.title-name {
color: var(--button-foreground-color-disabled);
}
}
}

View File

@@ -17,7 +17,7 @@
[app.main.repo :as rp]
[app.main.store :as st]
[app.main.ui.components.context-menu-a11y :refer [context-menu*]]
[app.main.ui.components.file-uploader :refer [file-uploader*]]
[app.main.ui.components.file-uploader :refer [file-uploader]]
[app.main.ui.ds.product.empty-placeholder :refer [empty-placeholder*]]
[app.main.ui.icons :as deprecated-icon]
[app.main.ui.notifications.context-notification :refer [context-notification]]
@@ -184,11 +184,11 @@
:on-click on-click
:tab-index "0"}
[:span (tr "labels.add-custom-font")]
[:> file-uploader* {:input-id "font-upload"
:accept accept-font-types
:multi true
:ref input-ref
:on-selected on-selected}]]
[:& file-uploader {:input-id "font-upload"
:accept accept-font-types
:multi true
:ref input-ref
:on-selected on-selected}]]
(when-let [url cf/terms-of-service-uri]
[:& context-notification {:content (tr "dashboard.fonts.hero-text2" url)

View File

@@ -16,7 +16,7 @@
[app.main.data.modal :as modal]
[app.main.data.notifications :as ntf]
[app.main.store :as st]
[app.main.ui.components.file-uploader :refer [file-uploader*]]
[app.main.ui.components.file-uploader :refer [file-uploader]]
[app.main.ui.ds.product.loader :refer [loader*]]
[app.main.ui.icons :as deprecated-icon]
[app.main.ui.notifications.context-notification :refer [context-notification]]
@@ -58,10 +58,10 @@
[{:keys [project-id on-finish-import]} external-ref]
(let [on-file-selected (use-import-file project-id on-finish-import)]
[:form.import-file {:aria-hidden "true"}
[:> file-uploader* {:accept ".penpot,.zip"
:multi true
:ref external-ref
:on-selected on-file-selected}]]))
[:& file-uploader {:accept ".penpot,.zip"
:multi true
:ref external-ref
:on-selected on-file-selected}]]))
(defn- update-entry-name
[entries file-id new-name]

View File

@@ -19,7 +19,7 @@
[app.main.refs :as refs]
[app.main.store :as st]
[app.main.ui.components.dropdown :refer [dropdown]]
[app.main.ui.components.file-uploader :refer [file-uploader*]]
[app.main.ui.components.file-uploader :refer [file-uploader]]
[app.main.ui.components.forms :as fm]
[app.main.ui.dashboard.change-owner]
[app.main.ui.dashboard.subscription :refer [members-cta*
@@ -1315,10 +1315,10 @@
[:img {:class (stl/css :team-image)
:src (cfg/resolve-team-photo-url team)}]
(when can-edit
[:> file-uploader* {:accept "image/jpeg,image/png"
:multi false
:ref finput
:on-selected on-file-selected}])]
[:& file-uploader {:accept "image/jpeg,image/png"
:multi false
:ref finput
:on-selected on-file-selected}])]
[:div {:class (stl/css :block-label)}
(tr "dashboard.team-info")]
[:div {:class (stl/css :block-text)}

View File

@@ -11,10 +11,8 @@
[app.main.data.modal :as modal]
[app.main.repo :as rp]
[app.main.store :as st]
[app.main.ui.ds.buttons.button :refer [button*]]
[app.main.ui.ds.buttons.icon-button :refer [icon-button*]]
[app.main.ui.ds.foundations.assets.icon :as i]
[app.main.ui.ds.notifications.context-notification :refer [context-notification*]]
[app.main.ui.icons :as deprecated-icon]
[app.util.dom :as dom]
[app.util.i18n :as i18n :refer [tr]]
[app.util.keyboard :as k]
@@ -99,11 +97,8 @@
[:div {:class (stl/css :modal-container)}
[:div {:class (stl/css :modal-header)}
[:h2 {:class (stl/css :modal-title)} title]
[:> icon-button* {:variant "ghost"
:class (stl/css :modal-close-btn)
:icon i/close
:aria-label (tr "labels.close")
:on-click cancel-fn}]]
[:button {:class (stl/css :modal-close-btn)
:on-click cancel-fn} deprecated-icon/close]]
[:div {:class (stl/css :modal-content)}
(when (and (string? subtitle) (not= subtitle ""))
@@ -129,10 +124,14 @@
[:div {:class (stl/css :modal-footer)}
[:div {:class (stl/css :action-buttons)}
(when-not (= cancel-label :omit)
[:> button* {:variant "secondary"
:on-click cancel-fn}
cancel-label])
[:input {:class (stl/css :cancel-button)
:type "button"
:value cancel-label
:on-click cancel-fn}])
[:> button* {:variant (if (= accept-style :danger) "destructive" "primary")
:on-click accept-fn}
accept-label]]]]]))
[:input {:class (stl/css-case :accept-btn true
:danger (= accept-style :danger)
:primary (= accept-style :primary))
:type "button"
:value accept-label
:on-click accept-fn}]]]]]))

View File

@@ -33,9 +33,7 @@
}
.modal-close-btn {
position: absolute;
top: var(--sp-s);
right: var(--sp-s);
@extend .modal-close-btn-base;
}
.modal-content {
@@ -55,6 +53,17 @@
@extend .modal-action-btns;
}
.cancel-button {
@extend .modal-cancel-btn;
}
.accept-btn {
@extend .modal-accept-btn;
&.danger {
@extend .modal-danger-btn;
}
}
.modal-scd-msg {
margin-block: 0;
}

View File

@@ -15,7 +15,6 @@
display: inline-flex;
align-items: center;
justify-content: center;
column-gap: var(--sp-xs);
}

View File

@@ -208,7 +208,7 @@
;; FIXME: deprecated, should be refactored in two components and use
;; the generic progress reporter
(mf/defc progress-widget*
(mf/defc progress-widget
{::mf/wrap [mf/memo]}
[]
(let [state (mf/deref refs/export)

View File

@@ -19,10 +19,7 @@
[app.main.store :as st]
[app.main.ui.components.code-block :refer [code-block]]
[app.main.ui.components.copy-button :refer [copy-button*]]
[app.main.ui.ds.buttons.button :refer [button*]]
[app.main.ui.ds.buttons.icon-button :refer [icon-button*]]
[app.main.ui.ds.controls.radio-buttons :refer [radio-buttons*]]
[app.main.ui.ds.foundations.assets.icon :as i]
[app.main.ui.components.radio-buttons :refer [radio-button radio-buttons]]
[app.main.ui.hooks.resize :refer [use-resize-hook]]
[app.main.ui.icons :as deprecated-icon]
[app.main.ui.shapes.text.fontfaces :refer [shapes->fonts]]
@@ -263,9 +260,8 @@
[:div {:class (stl/css-case :element-options true
:viewer-code-block (= :viewer from))}
[:div {:class (stl/css :attributes-block)}
[:> button* {:variant "secondary"
:class (stl/css :download-button)
:on-click handle-copy-all-code}
[:button {:class (stl/css :download-button)
:on-click handle-copy-all-code}
"Copy all code"]]
#_[:div.attributes-block
@@ -292,10 +288,10 @@
;; :options [{:label "CSS" :value "css"}]}]
[:div {:class (stl/css :action-btns)}
[:> icon-button* {:variant "ghost"
:aria-label "Expand"
:on-click on-expand
:icon i/code}]
[:button {:class (stl/css :expand-button)
:on-click on-expand}
deprecated-icon/code]
[:> copy-button* {:data copy-css-fn
:class (stl/css :css-copy-btn)
:on-copied on-style-copied}]]]
@@ -322,21 +318,21 @@
:rotated collapsed-markup?)}
deprecated-icon/arrow]]
[:> radio-buttons* {:selected markup-type
:on-change set-markup
:name "listing-style"
:options [{:id "html"
:label "HTML"
:value "html"}
{:id "svg"
:label "SVG"
:value "svg"}]}]
[:& radio-buttons {:selected markup-type
:on-change set-markup
:class (stl/css :code-lang-options)
:wide true
:name "listing-style"}
[:& radio-button {:value "html"
:id :html}]
[:& radio-button {:value "svg"
:id :svg}]]
[:div {:class (stl/css :action-btns)}
[:> icon-button* {:variant "ghost"
:aria-label "Expand"
:on-click on-expand
:icon i/code}]
[:button {:class (stl/css :expand-button)
:on-click on-expand}
deprecated-icon/code]
[:> copy-button* {:data copy-html-fn
:class (stl/css :html-copy-btn)
:on-copied on-markup-copied}]]]

View File

@@ -17,18 +17,16 @@
padding-inline: var(--sp-m);
}
.attributes-block {
display: flex;
flex-direction: column;
row-gap: 12px;
}
.viewer-code-block {
height: calc(100vh - #{deprecated.$s-108}); // TODO: Fix this hardcoded value
}
.download-button {
margin: var(--sp-s) 0;
@extend .button-secondary;
@include deprecated.uppercaseTitleTipography;
height: deprecated.$s-32;
width: 100%;
margin: deprecated.$s-8 0;
}
.code-block {
@@ -75,6 +73,7 @@
gap: deprecated.$s-4;
}
.expand-button,
.css-copy-btn,
.html-copy-btn {
@extend .button-tertiary;
@@ -86,6 +85,9 @@
}
}
.code-lang-options {
max-width: deprecated.$s-108;
}
.code-lang-select {
@include deprecated.uppercaseTitleTipography;
width: deprecated.$s-72;

View File

@@ -14,7 +14,7 @@
[app.main.data.profile :as du]
[app.main.refs :as refs]
[app.main.store :as st]
[app.main.ui.components.file-uploader :refer [file-uploader*]]
[app.main.ui.components.file-uploader :refer [file-uploader]]
[app.main.ui.components.forms :as fm]
[app.util.dom :as dom]
[app.util.i18n :as i18n :refer [tr]]
@@ -110,11 +110,11 @@
[:span {:class (stl/css :update-overlay)
:on-click on-image-click} (tr "labels.update")]
[:img {:src photo}]
[:> file-uploader* {:accept "image/jpeg,image/png"
:multi false
:ref input-ref
:on-selected on-file-selected
:data-testid "profile-image-input"}]]]))
[:& file-uploader {:accept "image/jpeg,image/png"
:multi false
:ref input-ref
:on-selected on-file-selected
:data-testid "profile-image-input"}]]]))
;; --- Profile Page

View File

@@ -9,13 +9,12 @@
(:require
["rxjs" :as rxjs]
[app.common.data :as d]
[app.common.exceptions :as ex]
[app.common.pprint :as pp]
[app.common.uri :as u]
[app.common.uuid :as uuid]
[app.config :as cf]
[app.main.data.auth :refer [is-authenticated?]]
[app.main.data.common :as dcm]
[app.main.data.event :as ev]
[app.main.errors :as errors]
[app.main.refs :as refs]
[app.main.repo :as rp]
@@ -448,22 +447,22 @@
(mf/defc exception-section*
{::mf/private true}
[{:keys [data route] :as props}]
[{:keys [data] :as props}]
(let [type (get data :type)
report (mf/with-memo [data]
(some-> data ::errors/instance errors/generate-report))
cause (get data ::errors/instance)
report (mf/with-memo [cause]
(when (ex/exception? cause)
(errors/generate-report cause)))
props (mf/spread-props props {:report report})]
(mf/with-effect [data route report]
(let [params (:query-params route)
params (u/map->query-string params)]
(st/emit! (ev/event {::ev/name "exception-page"
:type (get data :type :unknown)
:href (rt/get-current-href)
:hint (get data :hint)
:path (get route :path)
:report report
:params params}))))
(mf/with-effect [report type cause]
(when (and (ex/exception? cause)
(not (contains? #{:not-found :authentication} type)))
(errors/submit-report :event-name "exception-page"
:report report
:hint (ex/get-hint cause))))
(case type
:not-found

View File

@@ -27,8 +27,9 @@
[okulary.core :as l]
[rumext.v2 :as mf]))
(mf/defc comments-menu*
{::mf/memo true}
(mf/defc comments-menu
{::mf/props :obj
::mf/memo true}
[]
(let [state (mf/deref refs/comments-local)
cmode (:mode state)

View File

@@ -14,13 +14,10 @@
[app.main.data.viewer.shortcuts :as sc]
[app.main.store :as st]
[app.main.ui.components.dropdown :refer [dropdown]]
[app.main.ui.ds.buttons.button :refer [button*]]
[app.main.ui.ds.buttons.icon-button :refer [icon-button*]]
[app.main.ui.ds.foundations.assets.icon :as i]
[app.main.ui.exports.assets :refer [progress-widget*]]
[app.main.ui.exports.assets :refer [progress-widget]]
[app.main.ui.formats :as fmt]
[app.main.ui.icons :as deprecated-icon]
[app.main.ui.viewer.comments :refer [comments-menu*]]
[app.main.ui.viewer.comments :refer [comments-menu]]
[app.main.ui.viewer.interactions :refer [flows-menu* interactions-menu*]]
[app.util.dom :as dom]
[app.util.i18n :refer [tr]]
@@ -36,12 +33,20 @@
[]
(modal/show! :login-register {}))
(mf/defc zoom-widget*
{::mf/memo true}
[{:keys [zoom on-increase on-decrease on-zoom-reset on-fullscreen on-zoom-fit on-zoom-fill]}]
(let [open* (mf/use-state false)
open? (deref open*)
(mf/defc zoom-widget
{::mf/memo true
::mf/props :obj}
[{:keys [zoom
on-increase
on-decrease
on-zoom-reset
on-fullscreen
on-zoom-fit
on-zoom-fill]
:as props}]
(let [open* (mf/use-state false)
open? (deref open*)
open-dropdown
(mf/use-fn
(fn [event]
@@ -70,7 +75,7 @@
[:div {:class (stl/css-case :zoom-widget true
:selected open?)
:on-click (if open? close-dropdown open-dropdown)
:on-click open-dropdown
:title (tr "workspace.header.zoom")}
[:span {:class (stl/css :label)} (fmt/format-percent zoom)]
[:& dropdown {:show open?
@@ -78,18 +83,18 @@
[:ul {:class (stl/css :dropdown)}
[:li {:class (stl/css :basic-zoom-bar)}
[:span {:class (stl/css :zoom-btns)}
[:> icon-button* {:variant "ghost"
:aria-label (tr "shortcuts.decrease-zoom")
:on-click on-decrease
:icon i/remove}]
[:p {:class (stl/css :zoom-text)}
[:button {:class (stl/css :zoom-btn)
:on-click on-decrease}
[:span {:class (stl/css :zoom-icon)}
deprecated-icon/remove-icon]]
[:p {:class (stl/css :zoom-text)}
(fmt/format-percent zoom)]
[:> icon-button* {:variant "ghost"
:aria-label (tr "shortcuts.increase-zoom")
:on-click on-increase
:icon i/add}]]
[:> button* {:variant "ghost"
:on-click on-zoom-reset}
[:button {:class (stl/css :zoom-btn)
:on-click on-increase}
[:span {:class (stl/css :zoom-icon)}
deprecated-icon/add]]]
[:button {:class (stl/css :reset-btn)
:on-click on-zoom-reset}
(tr "workspace.header.reset-zoom")]]
[:li {:class (stl/css :zoom-option)
@@ -114,7 +119,7 @@
[:span {:class (stl/css :shortcut-key)
:key (dm/str "zoom-fullscreen-" sc)} sc])]]]]]))
(mf/defc header-options*
(mf/defc header-options
[{:keys [section zoom page file index permissions interactions-mode share]}]
(let [fullscreen? (mf/deref fullscreen-ref)
@@ -154,7 +159,6 @@
handle-zoom-fit
(mf/use-fn
#(st/emit! dv/zoom-to-fit))]
(mf/with-effect [permissions share]
(when (and
(:in-team permissions)
@@ -163,7 +167,7 @@
(open-share-dialog)))
[:div {:class (stl/css :options-zone)}
[:> progress-widget*]
[:& progress-widget]
(case section
:interactions [:*
@@ -171,41 +175,40 @@
[:> flows-menu* {:page page :index index}])
[:> interactions-menu*
{:interactions-mode interactions-mode}]]
:comments [:> comments-menu*]
:comments [:& comments-menu]
[:div {:class (stl/css :view-options)}])
[:> zoom-widget* {:zoom zoom
:on-increase handle-increase
:on-decrease handle-decrease
:on-zoom-reset handle-zoom-reset
:on-zoom-fill handle-zoom-fill
:on-zoom-fit handle-zoom-fit
:on-fullscreen toggle-fullscreen}]
[:& zoom-widget
{:zoom zoom
:on-increase handle-increase
:on-decrease handle-decrease
:on-zoom-reset handle-zoom-reset
:on-zoom-fill handle-zoom-fill
:on-zoom-fit handle-zoom-fit
:on-fullscreen toggle-fullscreen}]
(when (:in-team permissions)
[:> icon-button* {:variant "ghost"
:aria-label (tr "viewer.header.edit-in-workspace")
:on-click go-to-workspace
:icon i/curve}])
[:span {:on-click go-to-workspace
:class (stl/css :edit-btn)}
deprecated-icon/curve])
[:> icon-button* {:variant "ghost"
:aria-pressed fullscreen?
:aria-label (tr "viewer.header.fullscreen")
:on-click toggle-fullscreen
:icon i/expand}]
[:span {:title (tr "viewer.header.fullscreen")
:class (stl/css-case :fullscreen-btn true
:selected fullscreen?)
:on-click toggle-fullscreen}
deprecated-icon/expand]
(when (:in-team permissions)
[:> button* {:variant "primary"
:class (stl/css :share-btn)
:on-click open-share-dialog}
[:button {:on-click open-share-dialog
:class (stl/css :share-btn)}
(tr "labels.share")])
(when-not (:is-logged permissions)
[:span {:on-click open-login-dialog
:class (stl/css :go-log-btn)} (tr "labels.log-or-sign")])]))
(mf/defc header-sitemap*
[{:keys [project file page frame toggle-thumbnails]}]
(mf/defc header-sitemap
[{:keys [project file page frame toggle-thumbnails] :as props}]
(let [project-name (:name project)
file-name (:name file)
page-name (:name page)
@@ -314,44 +317,44 @@
:pointer-events (when-not (:in-team permissions) "none")}}
penpot-logo-icon]
[:> header-sitemap* {:project project
:file file
:page page
:frame frame
:toggle-thumbnails toggle-thumbnails
:index index}]]
[:& header-sitemap {:project project
:file file
:page page
:frame frame
:toggle-thumbnails toggle-thumbnails
:index index}]]
[:div {:class (stl/css :mode-zone)}
[:> icon-button* {:variant "ghost"
:aria-pressed (= section :interactions)
:aria-label (tr "viewer.header.interactions-section" (sc/get-tooltip :open-interactions))
:data-value "interactions"
:on-click navigate
:icon i/play}]
[:button {:on-click navigate
:data-value "interactions"
:class (stl/css-case :mode-zone-btn true
:selected (= section :interactions))
:title (tr "viewer.header.interactions-section" (sc/get-tooltip :open-interactions))}
deprecated-icon/play]
(when (or (:in-team permissions)
(= (:who-comment permissions) "all"))
[:> icon-button* {:variant "ghost"
:aria-pressed (= section :comments)
:aria-label (tr "viewer.header.comments-section" (sc/get-tooltip :open-comments))
:data-value "comments"
:on-click navigate
:icon i/comments}])
[:button {:on-click navigate
:data-value "comments"
:class (stl/css-case :mode-zone-btn true
:selected (= section :comments))
:title (tr "viewer.header.comments-section" (sc/get-tooltip :open-comments))}
deprecated-icon/comments])
(when (or (:in-team permissions)
(and (= (:type permissions) :share-link)
(= (:who-inspect permissions) "all")))
[:> icon-button* {:variant "ghost"
:aria-pressed (= section :inspect)
:aria-label (tr "viewer.header.inspect-section" (sc/get-tooltip :open-inspect))
:on-click go-to-inspect
:icon i/code}])]
[:button {:on-click go-to-inspect
:class (stl/css-case :mode-zone-btn true
:selected (= section :inspect))
:title (tr "viewer.header.inspect-section" (sc/get-tooltip :open-inspect))}
deprecated-icon/code])]
[:> header-options* {:section section
:permissions permissions
:page page
:file file
:index index
:zoom zoom
:interactions-mode interactions-mode
:share share}]]))
[:& header-options {:section section
:permissions permissions
:page page
:file file
:index index
:zoom zoom
:interactions-mode interactions-mode
:share share}]]))

View File

@@ -12,7 +12,7 @@
grid-column: 1 / span 1;
grid-row: 1 / span 1;
display: grid;
grid-template-columns: 1fr auto 1fr;
grid-template-columns: 1fr deprecated.$s-92 1fr;
justify-content: space-between;
align-items: center;
height: deprecated.$s-48;
@@ -130,9 +130,23 @@
// SECTION BUTTONS
.mode-zone {
display: flex;
flex-direction: row;
gap: var(--sp-xs);
@include deprecated.flexRow;
height: 100%;
}
.mode-zone-btn {
@extend .button-tertiary;
@include deprecated.flexCenter;
height: deprecated.$s-32;
width: deprecated.$s-28;
padding: 0;
svg {
@extend .button-icon;
}
}
.selected {
@extend .button-icon-selected;
}
// OPTION AREA
@@ -151,8 +165,33 @@
cursor: pointer;
}
.fullscreen-btn {
@extend .button-tertiary;
@include deprecated.flexCenter;
height: deprecated.$s-32;
width: deprecated.$s-28;
svg {
@extend .button-icon;
stroke: var(--icon-foreground);
}
}
.share-btn {
margin-left: var(--sp-xs);
@extend .button-primary;
height: deprecated.$s-32;
min-width: deprecated.$s-72;
margin-left: deprecated.$s-4;
}
.edit-btn {
@extend .button-tertiary;
@include deprecated.flexCenter;
height: deprecated.$s-32;
width: deprecated.$s-28;
svg {
@extend .button-icon;
stroke: var(--icon-foreground);
}
}
.go-log-btn {
@@ -206,15 +245,43 @@
display: flex;
}
.zoom-btn {
@extend .button-tertiary;
height: deprecated.$s-28;
width: deprecated.$s-28;
border-radius: deprecated.$br-8;
.zoom-icon {
@include deprecated.flexCenter;
width: deprecated.$s-24;
height: deprecated.$s-32;
svg {
@extend .button-icon;
stroke: var(--icon-foreground);
}
}
&:hover {
.zoom-icon svg {
stroke: var(--button-tertiary-foreground-color-hover);
}
}
}
.zoom-text {
@include deprecated.flexCenter;
height: 100%;
min-width: deprecated.$s-48;
min-width: deprecated.$s-64;
padding: 0;
margin: 0 deprecated.$s-2;
color: var(--modal-title-foreground-color);
}
.reset-btn {
@extend .button-tertiary;
color: var(--button-tertiary-foreground-color-hover);
height: deprecated.$s-28;
border-radius: deprecated.$br-8;
}
.zoom-option {
@extend .menu-item-base;
.shortcuts {

View File

@@ -20,9 +20,6 @@
[app.main.router :as rt]
[app.main.store :as st]
[app.main.ui.components.select :refer [select]]
[app.main.ui.ds.buttons.button :refer [button*]]
[app.main.ui.ds.buttons.icon-button :refer [icon-button*]]
[app.main.ui.ds.foundations.assets.icon :as i]
[app.main.ui.icons :as deprecated-icon]
[app.util.clipboard :as clipboard]
[app.util.dom :as dom]
@@ -174,11 +171,10 @@
[:div {:class (stl/css :share-link-header)}
[:h2 {:class (stl/css :share-link-title)}
(tr "common.share-link.title")]
[:> icon-button* {:variant "ghost"
:class (stl/css :modal-close-button)
:aria-label (tr "labels.close")
:on-click on-close
:icon i/close}]]
[:button {:class (stl/css :modal-close-button)
:on-click on-close
:title (tr "labels.close")}
deprecated-icon/close]]
[:div {:class (stl/css :modal-content)}
[:div {:class (stl/css :share-link-section)}
(when (and (not confirm?) (some? current-link))
@@ -189,10 +185,10 @@
:placeholder (tr "common.share-link.placeholder")
:read-only true}]
[:> icon-button* {:variant "ghost"
:aria-label (tr "viewer.header.share.copy-link")
:on-click copy-link
:icon i/clipboard}]])
[:button {:class (stl/css :copy-button)
:title (tr "viewer.header.share.copy-link")
:on-click copy-link}
deprecated-icon/clipboard]])
[:div {:class (stl/css :hint-wrapper)}
(when (not ^boolean confirm?)
@@ -203,22 +199,28 @@
[:div {:class (stl/css :description)}
(tr "common.share-link.confirm-deletion-link-description")]
[:div {:class (stl/css :actions)}
[:> button* {:variant "secondary"
:on-click #(reset! confirm* false)}
(tr "labels.cancel")]
[:> button* {:variant "destructive"
:on-click delete-link}
(tr "common.share-link.destroy-link")]]]
[:input {:type "button"
:class (stl/css :button-cancel)
:on-click #(reset! confirm* false)
:value (tr "labels.cancel")}]
[:input {:type "button"
:class (stl/css :button-danger)
:on-click delete-link
:value (tr "common.share-link.destroy-link")}]]]
(some? current-link)
[:> button* {:variant "destructive"
:on-click try-delete-link}
(tr "common.share-link.destroy-link")]
[:input
{:type "button"
:class (stl/css :button-danger)
:on-click try-delete-link
:value (tr "common.share-link.destroy-link")}]
:else
[:> button* {:variant "primary"
:on-click create-link}
(tr "common.share-link.get-link")])]]
[:input
{:type "button"
:class (stl/css :button-active)
:on-click create-link
:value (tr "common.share-link.get-link")}])]]
(when (not ^boolean confirm?)
@@ -303,7 +305,6 @@
:options [{:value "team" :label (tr "common.share-link.team-members")}
{:value "all" :label (tr "common.share-link.all-users")}]
:on-change on-comment-change}]]]
[:div {:class (stl/css :inspect-mode)}
[:div {:class (stl/css :subtitle)}
(tr "common.share-link.permissions-can-inspect")]
@@ -314,3 +315,6 @@
:options [{:value "team" :label (tr "common.share-link.team-members")}
{:value "all" :label (tr "common.share-link.all-users")}]
:on-change on-inspect-change}]]]])])]]]))

View File

@@ -30,9 +30,7 @@
}
.modal-close-button {
position: absolute;
top: var(--sp-s);
right: var(--sp-s);
@extend .modal-close-btn-base;
}
.modal-content {
@@ -76,6 +74,18 @@
}
}
.copy-button {
@extend .button-secondary;
@include deprecated.flexRow;
gap: deprecated.$s-8;
height: deprecated.$s-32;
width: deprecated.$s-28;
svg {
@extend .button-icon;
stroke: var(--icon-foreground-hover);
}
}
.description {
@include deprecated.bodySmallTypography;
color: var(--modal-text-foreground-color);
@@ -87,6 +97,18 @@
justify-content: flex-end;
}
.button-active {
@extend .modal-accept-btn;
}
.button-cancel {
@extend .modal-cancel-btn;
}
.button-danger {
@extend .modal-danger-btn;
}
.permissions-section {
@include deprecated.flexColumn;
gap: deprecated.$s-8;

View File

@@ -25,11 +25,10 @@
[app.main.features :as features]
[app.main.refs :as refs]
[app.main.store :as st]
[app.main.ui.components.file-uploader :refer [file-uploader*]]
[app.main.ui.components.file-uploader :refer [file-uploader]]
[app.main.ui.components.numeric-input :refer [numeric-input*]]
[app.main.ui.components.radio-buttons :refer [radio-buttons radio-button]]
[app.main.ui.components.select :refer [select]]
[app.main.ui.ds.buttons.icon-button :refer [icon-button*]]
[app.main.ui.ds.controls.radio-buttons :refer [radio-buttons*]]
[app.main.ui.ds.foundations.assets.icon :as i]
[app.main.ui.ds.layout.tab-switcher :refer [tab-switcher*]]
[app.main.ui.hooks :as hooks]
@@ -416,25 +415,24 @@
:on-change handle-change-mode}]])
(when (and (= origin :sidebar) show-tokens? token-color)
[:> radio-buttons* {:selected color-style
:on-change toggle-token-color
:name "color-style"
:options [{:id "swap-opt-list"
:icon i/swatches
:label (tr "labels.color")
:value :direct-color}
{:id "swap-opt-grid"
:icon i/tokens
:label (tr "workspace.colorpicker.color-tokens")
:value :token-color}]}])]
[:& radio-buttons {:selected color-style
:on-change toggle-token-color
:name "color-style"}
[:& radio-button {:icon i/swatches
:value :direct-color
:title (tr "labels.color")
:id "opt-color"}]
[:& radio-button {:icon i/tokens
:value :token-color
:title (tr "workspace.colorpicker.color-tokens")
:id "opt-token-color"}]])]
(when (and (not= selected-mode :image)
(= color-style :direct-color))
[:> icon-button* {:variant "ghost"
:aria-label (tr "workspace.colorpicker.get-color")
:aria-pressed picking-color?
:on-click handle-click-picker
:icon i/picker}])
[:button {:class (stl/css-case :picker-btn true
:selected picking-color?)
:on-click handle-click-picker}
deprecated-icon/picker])
(when (= color-style :token-color)
[:div {:class (stl/css :token-color-title)}
@@ -485,11 +483,12 @@
:aria-label (tr "media.choose-image")
:on-click on-fill-image-click}
(tr "media.choose-image")
[:> file-uploader* {:input-id "fill-image-upload"
:accept "image/jpeg,image/png"
:multi false
:ref fill-image-ref
:on-selected on-fill-image-selected}]]])
[:& file-uploader
{:input-id "fill-image-upload"
:accept "image/jpeg,image/png"
:multi false
:ref fill-image-ref
:on-selected on-fill-image-selected}]]])
[:*
[:div {:class (stl/css :colorpicker-tabs)}

View File

@@ -46,6 +46,52 @@
width: px2rem(68);
}
// TODO: change to DS button component
.picker-btn {
display: flex;
justify-content: center;
align-items: center;
border: none;
background: none;
cursor: pointer;
border-radius: $br-8;
background-color: transparent;
border: $b-1 solid transparent;
height: var(--sp-xl);
width: var(--sp-xl);
border-radius: $br-4;
padding: 0;
margin-top: var(--sp-xs);
svg {
@extend .button-icon;
stroke: var(--button-tertiary-foreground-color-rest);
}
&:hover {
svg {
stroke: var(--button-tertiary-foreground-color-focus);
}
}
&:focus,
&:focus-visible {
outline: none;
svg {
stroke: var(--button-secondary-foreground-color-hover);
}
}
&:active {
outline: none;
border: $b-1 solid transparent;
svg {
stroke: var(--button-tertiary-foreground-color-active);
}
}
&.selected {
svg {
stroke: var(--button-tertiary-foreground-color-active);
}
}
}
.gradient-buttons {
display: flex;
align-items: center;

View File

@@ -11,6 +11,7 @@
[app.common.math :as mth]
[app.common.types.color :as cc]
[app.util.dom :as dom]
[app.util.keyboard :as kbd]
[rumext.v2 :as mf]))
(defn parse-hex
@@ -67,34 +68,60 @@
(when (some? val)
(setup-hex-color val))))
apply-property-change
(fn [property val]
(let [val (case property
:s (/ val 100)
:v (value->hsv-value val)
:alpha (/ val 100)
val)]
(cond
(= property :alpha)
(on-change {:alpha val})
(#{:r :g :b} property)
(let [{:keys [r g b]} (merge color (hash-map property val))
hex (cc/rgb->hex [r g b])
[h s v] (cc/hex->hsv hex)]
(on-change {:hex hex
:h h :s s :v v
:r r :g g :b b}))
:else
(let [{:keys [h s v]} (merge color (hash-map property val))
hex (cc/hsv->hex [h s v])
[r g b] (cc/hex->rgb hex)]
(on-change {:hex hex
:h h :s s :v v
:r r :g g :b b})))))
on-change-property
(fn [property max-value]
(fn [e]
(let [val (-> e dom/get-target-val d/parse-double (mth/clamp 0 max-value))
val (case property
:s (/ val 100)
:v (value->hsv-value val)
val)]
(when (not (nil? val))
(if (#{:r :g :b} property)
(let [{:keys [r g b]} (merge color (hash-map property val))
hex (cc/rgb->hex [r g b])
[h s v] (cc/hex->hsv hex)]
(on-change {:hex hex
:h h :s s :v v
:r r :g g :b b}))
(let [val (-> e dom/get-target-val d/parse-double (mth/clamp 0 max-value))]
(when (some? val)
(apply-property-change property val)))))
(let [{:keys [h s v]} (merge color (hash-map property val))
hex (cc/hsv->hex [h s v])
[r g b] (cc/hex->rgb hex)]
(on-change {:hex hex
:h h :s s :v v
:r r :g g :b b})))))))
on-key-down-step
(fn [max-value on-step]
(fn [e]
(let [up? (kbd/up-arrow? e)
down? (kbd/down-arrow? e)]
(when (and (or up? down?)
(or (kbd/shift? e) (kbd/alt? e)))
(dom/prevent-default e)
(when-let [current-value (-> e dom/get-target-val d/parse-double)]
(let [step (cond
(kbd/shift? e) (if up? 10 -10)
(kbd/alt? e) (if up? 0.1 -0.1))
new-value (mth/clamp (+ current-value step) 0 max-value)
node (dom/get-target e)]
(dom/set-value! node new-value)
(on-step new-value)))))))
on-change-opacity
(fn [e]
(when-let [new-alpha (-> e dom/get-target-val (mth/clamp 0 100) (/ 100))]
(on-change {:alpha new-alpha})))]
on-key-down-property
(fn [property max-value]
(on-key-down-step max-value #(apply-property-change property %)))]
;; Updates the inputs values when a property is changed in the parent
@@ -127,7 +154,8 @@
:min 0
:max 255
:default-value red
:on-change (on-change-property :r 255)}]]
:on-change (on-change-property :r 255)
:on-key-down (on-key-down-property :r 255)}]]
[:div {:class (stl/css :input-wrapper)}
[:label {:for "green-value" :class (stl/css :input-label)} "G"]
[:input {:id "green-value"
@@ -136,7 +164,8 @@
:min 0
:max 255
:default-value green
:on-change (on-change-property :g 255)}]]
:on-change (on-change-property :g 255)
:on-key-down (on-key-down-property :g 255)}]]
[:div {:class (stl/css :input-wrapper)}
[:label {:for "blue-value" :class (stl/css :input-label)} "B"]
[:input {:id "blue-value"
@@ -145,7 +174,8 @@
:min 0
:max 255
:default-value blue
:on-change (on-change-property :b 255)}]]]
:on-change (on-change-property :b 255)
:on-key-down (on-key-down-property :b 255)}]]]
[:*
[:div {:class (stl/css :input-wrapper)}
@@ -156,7 +186,8 @@
:min 0
:max 360
:default-value hue
:on-change (on-change-property :h 360)}]]
:on-change (on-change-property :h 360)
:on-key-down (on-key-down-property :h 360)}]]
[:div {:class (stl/css :input-wrapper)}
[:label {:for "saturation-value" :class (stl/css :input-label)} "S"]
[:input {:id "saturation-value"
@@ -166,7 +197,8 @@
:max 100
:step 1
:default-value saturation
:on-change (on-change-property :s 100)}]]
:on-change (on-change-property :s 100)
:on-key-down (on-key-down-property :s 100)}]]
[:div {:class (stl/css :input-wrapper)}
[:label {:for "value-value" :class (stl/css :input-label)} "V"]
[:input {:id "value-value"
@@ -175,7 +207,8 @@
:min 0
:max 100
:default-value value
:on-change (on-change-property :v 100)}]]])]
:on-change (on-change-property :v 100)
:on-key-down (on-key-down-property :v 100)}]]])]
[:div {:class (stl/css :hex-alpha-wrapper)}
[:div {:class (stl/css-case :input-wrapper true
:hex true)}
@@ -195,4 +228,5 @@
:step 1
:max 100
:default-value (if (= alpha :multiple) "" alpha)
:on-change on-change-opacity}]])]]))
:on-change (on-change-property :alpha 100)
:on-key-down (on-key-down-property :alpha 100)}]])]]))

View File

@@ -30,7 +30,6 @@
[app.main.ui.components.search-bar :refer [search-bar*]]
[app.main.ui.components.title-bar :refer [title-bar*]]
[app.main.ui.context :as ctx]
[app.main.ui.ds.buttons.button :refer [button*]]
[app.main.ui.ds.buttons.icon-button :refer [icon-button*]]
[app.main.ui.ds.foundations.assets.icon :as i]
[app.main.ui.ds.layout.tab-switcher :refer [tab-switcher*]]
@@ -45,6 +44,12 @@
[cuerdas.core :as str]
[rumext.v2 :as mf]))
(def ^:private close-icon
(deprecated-icon/icon-xref :close (stl/css :close-icon)))
(def ^:private add-icon
(deprecated-icon/icon-xref :add (stl/css :add-icon)))
(defn- get-library-summary
"Given a library data return a summary representation of this library"
[data]
@@ -163,10 +168,12 @@
[:div {:class (stl/css :sample-library-item)
:key (dm/str id)}
[:div {:class (stl/css :sample-library-item-name)} (:name library)]
[:> button* {:variant "secondary"
:on-click import-library
:disabled (some? importing?)}
(if (= importing? id) (tr "labels.adding") (tr "labels.add"))]]))
[:input {:class (stl/css-case :sample-library-button true
:sample-library-add (nil? importing?)
:sample-library-adding (some? importing?))
:type "button"
:value (if (= importing? id) (tr "labels.adding") (tr "labels.add"))
:on-click import-library}]]))
(defn- empty-library?
"Check if currentt library summary has elements or not"
@@ -315,12 +322,14 @@
[:> library-description* {:summary summary}]]]
(if ^boolean is-shared
[:> button* {:variant "secondary"
:on-click unpublish}
(tr "common.unpublish")]
[:> button* {:variant "primary"
:on-click publish}
(tr "common.publish")])]
[:input {:class (stl/css :item-unpublish)
:type "button"
:value (tr "common.unpublish")
:on-click unpublish}]
[:input {:class (stl/css :item-publish)
:type "button"
:value (tr "common.publish")
:on-click publish}])]
(for [{:keys [id name data connected-to connected-to-names] :as library} linked-libraries]
(let [disabled? (some #(contains? linked-libraries-ids %) connected-to)]
@@ -368,11 +377,12 @@
(let [summary (-> (:library-summary library)
(adapt-backend-summary))]
[:> library-description* {:summary summary}])]]
[:> icon-button* {:variant "secondary"
:aria-label (tr "workspace.libraries.shared-library-btn")
:icon i/add
:data-library-id (dm/str id)
:on-click link-library}]])]
[:button {:class (stl/css :item-button-shared)
:data-library-id (dm/str id)
:title (tr "workspace.libraries.shared-library-btn")
:on-click link-library}
add-icon]])]
(when (empty? shared-libraries)
[:div {:class (stl/css :section-list-empty)}
@@ -637,13 +647,11 @@
:on-click close-dialog-outside
:data-testid "libraries-modal"}
[:div {:class (stl/css :modal-dialog)}
[:> icon-button* {:variant "ghost"
:class (stl/css :close-btn)
:icon i/close
:aria-label (tr "labels.close")
:data-testid "close-libraries"
:on-click close-dialog}]
[:button {:class (stl/css :close-btn)
:on-click close-dialog
:aria-label (tr "labels.close")
:data-testid "close-libraries"}
close-icon]
[:div {:class (stl/css :modal-title)}
(tr "workspace.libraries.libraries")]

View File

@@ -33,7 +33,7 @@
background-color: var(--modal-background-color);
border: $b-2 solid var(--modal-border-color);
display: grid;
grid-template-rows: 0 auto 1fr;
grid-template-rows: auto 1fr;
min-width: $sz-364;
min-height: $sz-192;
height: $sz-520;
@@ -42,10 +42,21 @@
max-width: $sz-712;
}
// TODO: Remove this extended creating modal component
.close-btn {
position: absolute;
top: var(--sp-s);
right: var(--sp-s);
@extend .modal-close-btn-base;
}
.close-icon {
display: flex;
justify-content: center;
align-items: center;
height: $sz-16;
width: $sz-16;
color: transparent;
fill: none;
stroke-width: $b-1;
stroke: var(--icon-foreground);
}
.modal-title {
@@ -109,6 +120,46 @@
height: fit-content;
}
.item-publish,
.item-unpublish {
// TODO: remove this extended by using DS button component
@extend .button-primary;
@include t.use-typography("headline-small");
height: $sz-32;
min-width: px2rem(92);
padding: var(--sp-s) var(--sp-xxl);
margin: 0;
border-radius: $br-8;
}
.item-unpublish {
// TODO: remove this extended by using DS button component
@extend .button-secondary;
}
.item-button,
.item-button-shared {
// TODO: remove this extended by using DS button component
@extend .button-secondary;
height: $sz-32;
width: $sz-32;
margin-inline-start: var(--sp-xxs);
padding: var(--sp-s);
}
.detach-icon,
.add-icon {
display: flex;
justify-content: center;
align-items: center;
height: $sz-16;
width: $sz-16;
color: transparent;
fill: none;
stroke-width: $b-1;
stroke: var(--icon-foreground);
}
.section-list-shared {
max-height: px2rem(272);
}
@@ -119,6 +170,26 @@
color: var(--title-foreground-color);
}
.search-icon {
display: flex;
justify-content: center;
align-items: center;
width: px2rem(20);
padding: 0 0 0 var(--sp-s);
svg {
display: flex;
justify-content: center;
align-items: center;
color: transparent;
fill: none;
height: px2rem(12);
width: px2rem(12);
stroke-width: 1.33px;
stroke: var(--icon-foreground);
}
}
// empty state
.section-list-empty {
display: grid;
@@ -357,3 +428,24 @@
text-overflow: ellipsis;
max-width: px2rem(232);
}
// TODO: Remove this extended using a DS component
.sample-library-add {
@extend .button-secondary;
}
// TODO: Remove this extended using a DS component
.sample-library-adding {
@extend .button-disabled;
}
.sample-library-button {
@include t.use-typography("headline-small");
height: $sz-32;
width: px2rem(80);
margin: 0;
border-radius: $br-8;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}

View File

@@ -853,9 +853,8 @@
[:*
[:> icon-button* {:variant "ghost"
:aria-pressed show-menu?
:aria-label (tr "shortcut-subsection.main-menu")
:on-click (if show-menu? close-all-menus open-menu)
:on-click open-menu
:icon i/menu}]
[:> dropdown-menu* {:show show-menu?

View File

@@ -18,10 +18,9 @@
[app.main.refs :as refs]
[app.main.store :as st]
[app.main.ui.context :as ctx]
[app.main.ui.ds.buttons.icon-button :refer [icon-button*]]
[app.main.ui.ds.foundations.assets.icon :as i]
[app.main.ui.hooks :as h]
[app.main.ui.hooks.resize :as r]
[app.main.ui.icons :as deprecated-icon]
[app.main.ui.workspace.color-palette :refer [color-palette*]]
[app.main.ui.workspace.color-palette-ctx-menu :refer [color-palette-ctx-menu*]]
[app.main.ui.workspace.text-palette :refer [text-palette]]
@@ -179,27 +178,27 @@
[:ul {:class (dm/str size-classname " " (stl/css-case :palette-btn-list true
:hidden-bts hide-palettes?))}
[:li {:class (stl/css :palette-item)}
[:> icon-button* {:variant "ghost"
:aria-pressed (some? color-palette?)
:aria-label (tr "workspace.toolbar.color-palette" (sc/get-tooltip :toggle-colorpalette))
:on-click on-select-color-palette
:icon i/drop}]]
[:button {:title (tr "workspace.toolbar.color-palette" (sc/get-tooltip :toggle-colorpalette))
:aria-label (tr "workspace.toolbar.color-palette" (sc/get-tooltip :toggle-colorpalette))
:class (stl/css-case :palette-btn true
:selected color-palette?)
:on-click on-select-color-palette}
deprecated-icon/drop-icon]]
[:li {:class (stl/css :palette-item)}
[:> icon-button* {:variant "ghost"
:aria-pressed (some? text-palette?)
:aria-label (tr "workspace.toolbar.text-palette" (sc/get-tooltip :toggle-textpalette))
:on-click on-select-text-palette
:icon i/text-palette}]]]
[:button {:title (tr "workspace.toolbar.text-palette" (sc/get-tooltip :toggle-textpalette))
:aria-label (tr "workspace.toolbar.text-palette" (sc/get-tooltip :toggle-textpalette))
:class (stl/css-case :palette-btn true
:selected text-palette?)
:on-click on-select-text-palette}
deprecated-icon/text-palette]]]
(if any-palette?
[:*
[:div {:class (stl/css :menu-btn)}
[:> icon-button* {:variant "ghost"
:aria-pressed show-menu?
:aria-label (tr "labels.options")
:on-click #(swap! state* update :show-menu not)
:icon i/menu}]]
[:button {:class (stl/css :palette-actions)
:on-click #(swap! state* update :show-menu not)}
deprecated-icon/menu]
[:div {:class (stl/css :palette)
:ref container}
(when text-palette?

View File

@@ -49,6 +49,7 @@
&.wide {
width: 100%;
}
.resize-area {
grid-area: resize;
height: deprecated.$s-8;
@@ -71,22 +72,49 @@
&.small-palette {
display: flex;
}
.palette-item {
@include deprecated.flexCenter;
border-radius: deprecated.$br-8;
opacity: deprecated.$op-10;
transition: opacity 1s ease;
.palette-btn {
@extend .button-tertiary;
height: deprecated.$s-32;
width: deprecated.$s-32;
border-radius: deprecated.$br-8;
background-clip: padding-box;
padding: 0;
svg {
@extend .button-icon-small;
stroke: var(--icon-foreground);
}
&.selected {
@extend .button-icon-selected;
}
}
}
}
.palette-actions {
@extend .button-tertiary;
grid-area: actions;
height: calc(var(--height) - deprecated.$s-16);
width: deprecated.$s-32;
padding: 0;
margin-left: deprecated.$s-4;
border-radius: deprecated.$br-8;
background-color: var(--palette-background-color);
z-index: deprecated.$z-index-2;
svg {
@extend .button-icon;
stroke: var(--icon-foreground);
}
}
.palette {
grid-area: palette;
width: 100%;
min-width: 0;
}
.palette-item {
display: flex;
align-items: center;
}
}
.menu-btn {
display: flex;
align-items: center;
margin-left: var(--sp-s);
}
.handler {

View File

@@ -29,7 +29,7 @@
:style {:background-color color}
:src (cfg/resolve-profile-photo-url profile)}]]))
(mf/defc active-sessions*
(mf/defc active-sessions
{::mf/memo true}
[]
(let [profiles (mf/deref refs/profiles)

Some files were not shown because too many files have changed in this diff Show More