feat(brand): nova logo — pixels que se juntam num lobo-guará de silhueta lisa

Validada pelo autor. Gerada de forma determinística por scripts/make-logo.py;
ícones do app regenerados a partir dela.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
Lucas RayanandClaude Sonnet 5.5 committed 2026-10-18 15:53:34 -03:00
1 parent c5c94a9956
commit 1457caa453
9 files changed
+207 -64

No files matched your search

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 126 KiB

After

Width:  |  Height:  |  Size: 123 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 416 KiB

After

Width:  |  Height:  |  Size: 455 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 416 KiB

After

Width:  |  Height:  |  Size: 455 KiB

+1 -1
View File
@@ -1 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 160 100" role="img" aria-label="Guará"><rect x="1.66" y="1.00" width="2.52" height="2.52" rx="0.30" fill="#67e8f9" opacity="0.50"/><rect x="5.59" y="0.44" width="2.16" height="2.16" rx="0.26" fill="#67e8f9" opacity="0.50"/><rect x="15.38" y="-1.68" width="1.95" height="1.95" rx="0.23" fill="#67e8f9" opacity="0.50"/><rect x="34.96" y="-2.08" width="3.04" height="3.04" rx="0.37" fill="#61e0ef" opacity="0.58"/><rect x="116.00" y="0.00" width="4.00" height="4.00" rx="0.48" fill="#0f766e" opacity="1.00"/><rect x="45.74" y="8.23" width="2.65" height="2.65" rx="0.32" fill="#48c0c8" opacity="0.63"/><rect x="58.59" y="2.22" width="2.04" height="2.04" rx="0.25" fill="#42b8bf" opacity="0.75"/><rect x="116.00" y="4.00" width="4.00" height="4.00" rx="0.48" fill="#127a73" opacity="1.00"/><rect x="22.44" y="11.12" width="3.15" height="3.15" rx="0.38" fill="#5fddec" opacity="0.51"/><rect x="29.61" y="5.65" width="2.48" height="2.48" rx="0.30" fill="#63e3f2" opacity="0.56"/><rect x="33.91" y="5.53" width="1.74" height="1.74" rx="0.21" fill="#60dfee" opacity="0.58"/><rect x="37.69" y="11.80" width="1.80" height="1.80" rx="0.22" fill="#52ccd7" opacity="0.60"/><rect x="80.66" y="8.60" width="2.43" height="2.43" rx="0.29" fill="#17807a" opacity="0.90"/><rect x="116.00" y="8.00" width="4.00" height="4.00" rx="0.48" fill="#10776f" opacity="1.00"/><rect x="23.94" y="11.79" width="0.95" height="0.95" rx="0.11" fill="#5fdeec" opacity="0.52"/><rect x="80.55" y="11.98" width="3.38" height="3.38" rx="0.41" fill="#1a8580" opacity="0.90"/><rect x="116.00" y="12.00" width="4.00" height="4.00" rx="0.48" fill="#0f766e" opacity="1.00"/><rect x="12.93" y="18.62" width="0.92" height="0.92" rx="0.11" fill="#66e7f8" opacity="0.50"/><rect x="80.08" y="16.11" width="3.84" height="3.84" rx="0.46" fill="#1d8884" opacity="0.90"/><rect x="84.27" y="16.17" width="3.12" height="3.12" rx="0.37" fill="#137b74" opacity="0.92"/><rect x="112.00" y="16.00" width="4.00" height="4.00" rx="0.48" fill="#0f766e" opacity="1.00"/><rect x="116.00" y="16.00" width="4.00" height="4.00" rx="0.48" fill="#0f766e" opacity="1.00"/><rect x="36.99" y="18.33" width="1.19" height="1.19" rx="0.14" fill="#5edceb" opacity="0.58"/><rect x="42.76" y="23.58" width="2.57" height="2.57" rx="0.31" fill="#5bd9e7" opacity="0.60"/><rect x="84.65" y="20.70" width="2.62" height="2.62" rx="0.31" fill="#1c8783" opacity="0.92"/><rect x="88.57" y="20.34" width="3.00" height="3.00" rx="0.36" fill="#147c76" opacity="0.94"/><rect x="112.00" y="20.00" width="4.00" height="4.00" rx="0.48" fill="#0f766e" opacity="1.00"/><rect x="116.00" y="20.00" width="4.00" height="4.00" rx="0.48" fill="#0f766e" opacity="1.00"/><rect x="2.84" y="24.95" width="1.02" height="1.02" rx="0.12" fill="#67e8f9" opacity="0.50"/><rect x="13.36" y="27.09" width="3.04" height="3.04" rx="0.36" fill="#67e8f9" opacity="0.50"/><rect x="35.01" y="22.08" width="2.21" height="2.21" rx="0.26" fill="#60dfed" opacity="0.58"/><rect x="39.95" y="23.90" width="1.39" height="1.39" rx="0.17" fill="#4fc8d2" opacity="0.60"/><rect x="57.75" y="26.92" width="1.51" height="1.51" rx="0.18" fill="#38abae" opacity="0.75"/><rect x="84.57" y="24.33" width="3.22" height="3.22" rx="0.39" fill="#19837e" opacity="0.92"/><rect x="87.85" y="24.01" width="4.20" height="4.20" rx="0.50" fill="#117871" opacity="0.94"/><rect x="112.00" y="24.00" width="4.00" height="4.00" rx="0.48" fill="#127a72" opacity="1.00"/><rect x="116.00" y="24.00" width="4.00" height="4.00" rx="0.48" fill="#0f766e" opacity="1.00"/><rect x="16.90" y="29.10" width="1.84" height="1.84" rx="0.22" fill="#67e8f9" opacity="0.50"/><rect x="22.27" y="28.50" width="1.55" height="1.55" rx="0.19" fill="#67e8f9" opacity="0.52"/><rect x="27.25" y="29.79" width="1.65" height="1.65" rx="0.20" fill="#60deed" opacity="0.54"/><rect x="75.33" y="29.42" width="2.98" height="2.98" rx="0.36" fill="#23908d" opacity="0.84"/><rect x="80.43" y="28.69" width="3.16" height="3.16" rx="0.38" fill="#17817b" opacity="0.90"/><rect x="84.52" y="28.41" width="3.38" height="3.38" rx="0.41" fill="#157e77" opacity="0.92"/><rect x="88.64" y="28.72" width="2.47" height="2.47" rx="0.30" fill="#1d8985" opacity="0.94"/><rect x="92.11" y="28.12" width="3.81" height="3.81" rx="0.46" fill="#0f766e" opacity="1.00"/><rect x="112.00" y="28.00" width="4.00" height="4.00" rx="0.48" fill="#0f766e" opacity="1.00"/><rect x="116.00" y="28.00" width="4.00" height="4.00" rx="0.48" fill="#147c75" opacity="1.00"/><rect x="120.00" y="28.00" width="4.00" height="4.00" rx="0.48" fill="#0f766e" opacity="1.00"/><rect x="2.99" y="31.83" width="1.52" height="1.52" rx="0.18" fill="#66e6f7" opacity="0.50"/><rect x="3.82" y="34.72" width="1.03" height="1.03" rx="0.12" fill="#63e3f3" opacity="0.50"/><rect x="26.27" y="35.88" width="3.13" height="3.13" rx="0.38" fill="#57d3e0" opacity="0.54"/><rect x="35.28" y="36.35" width="2.04" height="2.04" rx="0.24" fill="#5edcea" opacity="0.56"/><rect x="84.84" y="3Line truncated <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 160 100" role="img" aria-label="Guará"><defs><linearGradient id="wh" gradientUnits="userSpaceOnUse" x1="58" y1="0" x2="160" y2="100"><stop offset="0" stop-color="#3BE3CC"/> <stop offset="0.45" stop-color="#12B5A8"/> <stop offset="1" stop-color="#0B6A86"/></linearGradient><mask id="wm" maskUnits="userSpaceOnUse" x="0" y="0" width="160" height="100"><g shape-rendering="crispEdges"><rect x="80" y="0" width="81" height="100" fill="#fff"/><rect x="72.38" y="34.88" width="2.74" height="2.74" fill="#fff"/><rect x="59.88" y="59.88" width="2.74" height="2.74" fill="#fff"/><rect x="62.38" y="87.38" width="2.74" height="2.74" fill="#fff"/><rect x="72.38" y="64.88" width="2.74" height="2.74" fill="#fff"/><rect x="77.38" y="74.88" width="2.74" height="2.74" fill="#fff"/><rect x="74.88" y="47.38" width="2.74" height="2.74" fill="#fff"/><rect x="72.38" y="72.38" width="2.74" height="2.74" fill="#fff"/><rect x="67.38" y="64.88" width="2.74" height="2.74" fill="#fff"/><rect x="64.88" y="52.38" width="5.24" height="5.24" fill="#fff"/><rect x="77.38" y="42.38" width="2.74" height="2.74" fill="#fff"/><rect x="59.88" y="62.38" width="5.24" height="5.24" fill="#fff"/><rect x="77.38" y="72.38" width="2.74" height="2.74" fill="#fff"/><rect x="69.88" y="72.38" width="2.74" height="2.74" fill="#fff"/><rect x="77.38" y="64.88" width="2.74" height="2.74" fill="#fff"/><rect x="64.88" y="47.38" width="5.24" height="5.24" fill="#fff"/><rect x="57.38" y="59.88" width="2.74" height="2.74" fill="#fff"/><rect x="77.38" y="37.38" width="2.74" height="2.74" fill="#fff"/><rect x="77.38" y="84.88" width="2.74" height="2.74" fill="#fff"/><rect x="69.88" y="44.88" width="2.74" height="2.74" fill="#fff"/><rect x="77.38" y="34.88" width="2.74" height="2.74" fill="#fff"/><rect x="74.88" y="49.88" width="2.74" height="2.74" fill="#fff"/><rect x="59.88" y="79.88" width="2.74" height="2.74" fill="#fff"/><rect x="72.38" y="59.88" width="2.74" height="2.74" fill="#fff"/><rect x="74.88" y="64.88" width="2.74" height="2.74" fill="#fff"/><rect x="74.88" y="37.38" width="2.74" height="2.74" fill="#fff"/><rect x="57.38" y="47.38" width="2.74" height="2.74" fill="#fff"/><rect x="69.88" y="77.38" width="2.74" height="2.74" fill="#fff"/><rect x="57.38" y="87.38" width="5.24" height="5.24" fill="#fff"/><rect x="74.88" y="59.88" width="2.74" height="2.74" fill="#fff"/><rect x="57.38" y="82.38" width="2.74" height="2.74" fill="#fff"/><rect x="72.38" y="67.38" width="2.74" height="2.74" fill="#fff"/><rect x="67.38" y="72.38" width="2.74" height="2.74" fill="#fff"/><rect x="64.88" y="42.38" width="2.74" height="2.74" fill="#fff"/><rect x="74.88" y="84.88" width="2.74" height="2.74" fill="#fff"/><rect x="67.38" y="74.88" width="2.74" height="2.74" fill="#fff"/><rect x="57.38" y="54.88" width="5.24" height="5.24" fill="#fff"/><rect x="77.38" y="79.88" width="2.74" height="2.74" fill="#fff"/><rect x="64.88" y="57.38" width="2.74" height="2.74" fill="#fff"/><rect x="74.88" y="42.38" width="2.74" height="2.74" fill="#fff"/><rect x="62.38" y="69.88" width="5.24" height="5.24" fill="#fff"/><rect x="77.38" y="54.88" width="2.74" height="2.74" fill="#fff"/><rect x="74.88" y="34.88" width="2.74" height="2.74" fill="#fff"/><rect x="74.88" y="57.38" width="2.74" height="2.74" fill="#fff"/><rect x="59.88" y="69.88" width="2.74" height="2.74" fill="#fff"/><rect x="77.38" y="62.38" width="2.74" height="2.74" fill="#fff"/><rect x="72.38" y="77.38" width="2.74" height="2.74" fill="#fff"/><rect x="67.38" y="87.38" width="2.74" height="2.74" fill="#fff"/><rect x="72.38" y="42.38" width="2.74" height="2.74" fill="#fff"/><rect x="64.88" y="59.88" width="2.74" height="2.74" fill="#fff"/><rect x="69.88" y="47.38" width="2.74" height="2.74" fill="#fff"/><rect x="72.38" y="79.88" width="2.74" height="2.74" fill="#fff"/><rect x="74.88" y="32.38" width="2.74" height="2.74" fill="#fff"/><rect x="74.88" y="87.38" width="2.74" height="2.74" fill="#fff"/><rect x="74.88" y="74.88" width="2.74" height="2.74" fill="#fff"/><rect x="72.38" y="62.38" width="2.74" height="2.74" fill="#fff"/><rect x="72.38" y="44.88" width="2.74" height="2.74" fill="#fff"/><rect x="74.88" y="72.38" width="2.74" height="2.74" fill="#fff"/><rect x="67.38" y="59.88" width="2.74" height="2.74" fill="#fff"/><rect x="74.88" y="44.88" width="2.74" height="2.74" fill="#fff"/><rect x="64.88" y="67.38" width="2.74" height="2.74" fill="#fff"/><rect x="64.88" y="77.38" width="2.74" height="2.74" fill="#fff"/><rect x="72.38" y="57.38" width="2.74" height="2.74" fill="#fff"/><rect x="74.88" y="67.38" width="2.74" height="2.74" fill="#fff"/><rect x="77.38" y="39.88" width="2.74" height="2.74" fill="#fff"/><rect x="77.38" y="32.38" width="2.74" height="2.74" fill="#fff"/><rect x="77.38" y="59.88" width="2.74" height="2.74" fill="#fff"/><rect x="77.38" y="57.38" width="2.74" height="2.74" fill="#fff"/><rect x="62.38" y="82.38" width="2.74" height="2.74" fill="#fff"/><rect x="72.38" y="Line truncated

Before

Width:  |  Height:  |  Size: 33 KiB

After

Width:  |  Height:  |  Size: 20 KiB

+1 -1
View File
@@ -1 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 128" role="img" aria-label="Guará"><defs><linearGradient id="g" x1="0" y1="0" x2="1" y2="1"><stop offset="0" stop-color="#14b8a6"/><stop offset="1" stop-color="#0c4a6e"/></linearGradient></defs><rect width="128" height="128" rx="29" fill="url(#g)"/><g transform="translate(-19 20) scale(0.88)"><rect x="116.00" y="0.00" width="4.00" height="4.00" rx="0.48" fill="#effdfa" opacity="1.00"/><rect x="55.88" y="7.09" width="2.81" height="2.81" rx="0.34" fill="#bff9ee" opacity="0.72"/><rect x="72.25" y="5.08" width="1.41" height="1.41" rx="0.17" fill="#dcfbf5" opacity="0.81"/><rect x="116.00" y="4.00" width="4.00" height="4.00" rx="0.48" fill="#eefdf9" opacity="1.00"/><rect x="80.28" y="8.30" width="2.76" height="2.76" rx="0.33" fill="#e3fcf7" opacity="0.90"/><rect x="116.00" y="8.00" width="4.00" height="4.00" rx="0.48" fill="#f0fdfa" opacity="1.00"/><rect x="26.46" y="13.82" width="3.31" height="3.31" rx="0.40" fill="#9bf6e4" opacity="0.54"/><rect x="53.70" y="15.81" width="1.46" height="1.46" rx="0.17" fill="#bef9ed" opacity="0.69"/><rect x="68.83" y="10.06" width="1.56" height="1.56" rx="0.19" fill="#cbfaf1" opacity="0.81"/><rect x="80.87" y="12.94" width="2.88" height="2.88" rx="0.35" fill="#e5fcf7" opacity="0.90"/><rect x="84.12" y="12.06" width="3.38" height="3.38" rx="0.41" fill="#dcfbf5" opacity="0.92"/><rect x="116.00" y="12.00" width="4.00" height="4.00" rx="0.48" fill="#f0fdfa" opacity="1.00"/><rect x="64.31" y="19.49" width="2.49" height="2.49" rx="0.30" fill="#cbfaf1" opacity="0.75"/><rect x="83.91" y="16.21" width="3.68" height="3.68" rx="0.44" fill="#e6fcf7" opacity="0.92"/><rect x="112.00" y="16.00" width="4.00" height="4.00" rx="0.48" fill="#eefdfa" opacity="1.00"/><rect x="116.00" y="16.00" width="4.00" height="4.00" rx="0.48" fill="#f0fdfa" opacity="1.00"/><rect x="35.36" y="23.45" width="2.13" height="2.13" rx="0.26" fill="#a8f7e8" opacity="0.56"/><rect x="84.51" y="20.97" width="2.47" height="2.47" rx="0.30" fill="#ddfbf5" opacity="0.92"/><rect x="88.20" y="20.36" width="3.47" height="3.47" rx="0.42" fill="#e0fcf6" opacity="0.94"/><rect x="112.00" y="20.00" width="4.00" height="4.00" rx="0.48" fill="#f0fdfa" opacity="1.00"/><rect x="116.00" y="20.00" width="4.00" height="4.00" rx="0.48" fill="#f0fdfa" opacity="1.00"/><rect x="57.99" y="21.72" width="3.23" height="3.23" rx="0.39" fill="#c0f9ee" opacity="0.72"/><rect x="88.09" y="24.27" width="3.62" height="3.62" rx="0.43" fill="#f0fdfa" opacity="0.94"/><rect x="112.00" y="24.00" width="4.00" height="4.00" rx="0.48" fill="#f0fdfa" opacity="1.00"/><rect x="116.00" y="24.00" width="4.00" height="4.00" rx="0.48" fill="#ecfdf9" opacity="1.00"/><rect x="33.49" y="30.98" width="1.25" height="1.25" rx="0.15" fill="#aaf7e8" opacity="0.56"/><rect x="53.47" y="27.77" width="1.44" height="1.44" rx="0.17" fill="#c0f9ee" opacity="0.69"/><rect x="88.16" y="28.01" width="3.99" height="3.99" rx="0.48" fill="#ecfdf9" opacity="0.94"/><rect x="92.10" y="28.10" width="3.81" height="3.81" rx="0.46" fill="#f0fdfa" opacity="1.00"/><rect x="112.00" y="28.00" width="4.00" height="4.00" rx="0.48" fill="#f0fdfa" opacity="1.00"/><rect x="116.00" y="28.00" width="4.00" height="4.00" rx="0.48" fill="#f0fdfa" opacity="1.00"/><rect x="120.00" y="28.00" width="4.00" height="4.00" rx="0.48" fill="#edfdf9" opacity="1.00"/><rect x="31.35" y="34.66" width="1.37" height="1.37" rx="0.16" fill="#a0f7e6" opacity="0.56"/><rect x="41.92" y="32.71" width="2.72" height="2.72" rx="0.33" fill="#abf7e9" opacity="0.63"/><rect x="80.35" y="32.60" width="3.35" height="3.35" rx="0.40" fill="#e4fcf7" opacity="0.90"/><rect x="88.21" y="32.24" width="3.78" height="3.78" rx="0.45" fill="#e6fcf8" opacity="0.94"/><rect x="92.18" y="32.04" width="3.81" height="3.81" rx="0.46" fill="#f0fdfa" opacity="1.00"/><rect x="96.02" y="32.03" width="3.89" height="3.89" rx="0.47" fill="#f0fdfa" opacity="1.00"/><rect x="108.00" y="32.00" width="4.00" height="4.00" rx="0.48" fill="#edfdf9" opacity="1.00"/><rect x="112.00" y="32.00" width="4.00" height="4.00" rx="0.48" fill="#eefdfa" opacity="1.00"/><rect x="116.00" y="32.00" width="4.00" height="4.00" rx="0.48" fill="#ecfdf9" opacity="1.00"/><rect x="120.00" y="32.00" width="4.00" height="4.00" rx="0.48" fill="#f0fdfa" opacity="1.00"/><rect x="48.73" y="37.21" width="1.04" height="1.04" rx="0.12" fill="#b6f8eb" opacity="0.63"/><rect x="71.16" y="34.38" width="2.65" height="2.65" rx="0.32" fill="#d1fbf2" opacity="0.81"/><rect x="80.74" y="36.35" width="2.54" height="2.54" rx="0.30" fill="#eafcf8" opacity="0.90"/><rect x="84.39" y="36.27" width="3.60" height="3.60" rx="0.43" fill="#e4fcf7" opacity="0.92"/><rect x="88.49" y="36.43" width="3.34" height="3.34" rx="0.40" fill="#e5fcf7" opacity="0.94"/><rect x="92.14" y="36.15" width="3.81" height="3.81" rx="0.46" fill="#f0fdfa" opacity="1.00"/><rect x="96.09" y="36.09" width="3.89" height="3.89" rx="0.47" fill="#f0fdfa" opacity="1.00"/><rect x="108.00" y="36.00" widLine truncated <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 128" role="img" aria-label="Guará"><defs><linearGradient id="bg" x1="0" y1="0" x2="1" y2="1"><stop offset="0" stop-color="#0f766e"/><stop offset="1" stop-color="#083344"/></linearGradient><clipPath id="ic"><rect width="128" height="128" rx="29"/></clipPath></defs><rect width="128" height="128" rx="29" fill="url(#bg)"/><g clip-path="url(#ic)"><g transform="translate(-13 18) scale(0.86)"><defs><linearGradient id="ih" gradientUnits="userSpaceOnUse" x1="58" y1="0" x2="160" y2="100"><stop offset="0" stop-color="#d9fff7"/> <stop offset="0.5" stop-color="#8df1e0"/> <stop offset="1" stop-color="#3fc8cf"/></linearGradient><mask id="im" maskUnits="userSpaceOnUse" x="0" y="0" width="160" height="100"><g shape-rendering="crispEdges"><rect x="80" y="0" width="81" height="100" fill="#fff"/><rect x="67.38" y="49.88" width="2.74" height="2.74" fill="#fff"/><rect x="77.38" y="77.38" width="2.74" height="2.74" fill="#fff"/><rect x="57.38" y="62.38" width="5.24" height="5.24" fill="#fff"/><rect x="67.38" y="57.38" width="2.74" height="2.74" fill="#fff"/><rect x="57.38" y="59.88" width="2.74" height="2.74" fill="#fff"/><rect x="62.38" y="79.88" width="5.24" height="5.24" fill="#fff"/><rect x="74.88" y="64.88" width="2.74" height="2.74" fill="#fff"/><rect x="72.38" y="84.88" width="2.74" height="2.74" fill="#fff"/><rect x="72.38" y="54.88" width="2.74" height="2.74" fill="#fff"/><rect x="62.38" y="84.88" width="2.74" height="2.74" fill="#fff"/><rect x="72.38" y="72.38" width="2.74" height="2.74" fill="#fff"/><rect x="62.38" y="67.38" width="2.74" height="2.74" fill="#fff"/><rect x="69.88" y="44.88" width="2.74" height="2.74" fill="#fff"/><rect x="74.88" y="57.38" width="2.74" height="2.74" fill="#fff"/><rect x="69.88" y="62.38" width="2.74" height="2.74" fill="#fff"/><rect x="59.88" y="57.38" width="2.74" height="2.74" fill="#fff"/><rect x="72.38" y="52.38" width="2.74" height="2.74" fill="#fff"/><rect x="77.38" y="37.38" width="2.74" height="2.74" fill="#fff"/><rect x="77.38" y="79.88" width="2.74" height="2.74" fill="#fff"/><rect x="62.38" y="74.88" width="2.74" height="2.74" fill="#fff"/><rect x="77.38" y="42.38" width="2.74" height="2.74" fill="#fff"/><rect x="62.38" y="44.88" width="2.74" height="2.74" fill="#fff"/><rect x="74.88" y="84.88" width="2.74" height="2.74" fill="#fff"/><rect x="72.38" y="44.88" width="2.74" height="2.74" fill="#fff"/><rect x="72.38" y="87.38" width="2.74" height="2.74" fill="#fff"/><rect x="77.38" y="47.38" width="2.74" height="2.74" fill="#fff"/><rect x="67.38" y="39.88" width="2.74" height="2.74" fill="#fff"/><rect x="67.38" y="62.38" width="2.74" height="2.74" fill="#fff"/><rect x="77.38" y="67.38" width="2.74" height="2.74" fill="#fff"/><rect x="69.88" y="54.88" width="2.74" height="2.74" fill="#fff"/><rect x="77.38" y="89.88" width="2.74" height="2.74" fill="#fff"/><rect x="74.88" y="74.88" width="2.74" height="2.74" fill="#fff"/><rect x="69.88" y="72.38" width="2.74" height="2.74" fill="#fff"/><rect x="74.88" y="42.38" width="2.74" height="2.74" fill="#fff"/><rect x="74.88" y="37.38" width="2.74" height="2.74" fill="#fff"/><rect x="77.38" y="57.38" width="2.74" height="2.74" fill="#fff"/><rect x="67.38" y="59.88" width="2.74" height="2.74" fill="#fff"/><rect x="74.88" y="49.88" width="2.74" height="2.74" fill="#fff"/><rect x="72.38" y="69.88" width="2.74" height="2.74" fill="#fff"/><rect x="69.88" y="47.38" width="2.74" height="2.74" fill="#fff"/><rect x="62.38" y="57.38" width="5.24" height="5.24" fill="#fff"/><rect x="62.38" y="62.38" width="2.74" height="2.74" fill="#fff"/><rect x="77.38" y="82.38" width="2.74" height="2.74" fill="#fff"/><rect x="72.38" y="82.38" width="2.74" height="2.74" fill="#fff"/><rect x="64.88" y="39.88" width="2.74" height="2.74" fill="#fff"/><rect x="69.88" y="59.88" width="2.74" height="2.74" fill="#fff"/><rect x="64.88" y="74.88" width="2.74" height="2.74" fill="#fff"/><rect x="72.38" y="37.38" width="2.74" height="2.74" fill="#fff"/><rect x="77.38" y="34.88" width="2.74" height="2.74" fill="#fff"/><rect x="67.38" y="79.88" width="2.74" height="2.74" fill="#fff"/><rect x="59.88" y="79.88" width="2.74" height="2.74" fill="#fff"/><rect x="69.88" y="74.88" width="2.74" height="2.74" fill="#fff"/><rect x="69.88" y="69.88" width="2.74" height="2.74" fill="#fff"/><rect x="77.38" y="32.38" width="2.74" height="2.74" fill="#fff"/><rect x="77.38" y="39.88" width="2.74" height="2.74" fill="#fff"/><rect x="62.38" y="42.38" width="2.74" height="2.74" fill="#fff"/><rect x="67.38" y="54.88" width="2.74" height="2.74" fill="#fff"/><rect x="59.88" y="44.88" width="2.74" height="2.74" fill="#fff"/><rect x="69.88" y="42.38" width="2.74" height="2.74" fill="#fff"/><rect x="64.88" y="49.88" width="2.74" height="2.74" fill="#fff"/><rect x="74.88" y="59.88" width="2.74" height="2.74" fill="#fff"/><rect x="77.38" y="62.38" width="2.74" height="2.74" fill="#fff"/><rect x="74.88" y="32.38" width="2.74" height="2.74" fill="#ffLine truncated

Before

Width:  |  Height:  |  Size: 29 KiB

After

Width:  |  Height:  |  Size: 18 KiB

+205 -62
View File
@@ -1,9 +1,15 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
"""Gera a identidade visual do Guará: pixels de tamanhos distintos, soltos à esquerda, """Gera a identidade visual do Guará.
que se juntam até formar a cabeça de um lobo-guará à direita.
Uso: python3 scripts/make-logo.py (escreve apps/gui/ui/guara.svg e guara-logo.svg) Conceito: pixels de tamanhos distintos, soltos à esquerda, que se juntam numa
Determinístico (semente fixa): a mesma execução gera o mesmo desenho. grade cada vez mais densa até formar a cabeça de um lobo-guará à direita.
- O lobo é uma silhueta VETORIAL suave (curvas), sutil, sem serrilhado.
- À esquerda a silhueta é recortada por uma máscara de quadrados de tamanhos
distintos que ficam cada vez mais densos até se fundirem no lobo inteiro.
- Partículas soltas (quadrados) completam a dissolução fora da silhueta.
Uso: python3 scripts/make-logo.py -> apps/gui/ui/guara-logo.svg e guara.svg
""" """
import math import math
import random import random
@@ -11,15 +17,46 @@ from pathlib import Path
OUT = Path(__file__).resolve().parent.parent / "apps/gui/ui" OUT = Path(__file__).resolve().parent.parent / "apps/gui/ui"
# Cabeça de lobo-guará de perfil, olhando para a direita (coordenadas 0..100). W, H = 160.0, 100.0
CELL = 2.5 # módulo da grade de pixels
COLS, ROWS = int(W / CELL), int(H / CELL)
# --- silhueta -------------------------------------------------------------
# Cabeça de lobo-guará (3/4, olhando para a direita): orelhas enormes, focinho
# longo e fino, e a juba escorrendo para a esquerda (é ela que se desmancha em
# pixels). Coordenadas 0..100 na altura; x pode ser negativo (juba).
WOLF = [ WOLF = [
(-18, 100), (-2, 76), (10, 62), (16, 54), (21, 2), (30, 24), (41, 40), (47, 38), (57, 0), (62, 34), (72, 46), (100, 57), (97.5, 54), (91, 51), (83, 48), (75, 45), (69, 41), (65, 36), (62, 29), (59, 20), (56, 11),
(88, 55), (100, 60), (100, 69), (88, 73), (74, 77), (68, 84), (62, 100), (40, 100), (52.5, 4), (49, 0.5), (46, 4), (43, 13), (41, 23), (40, 32), (38, 31), (35, 22), (31, 11), (27.5, 3),
(24.5, 0.5), (22, 5), (20, 15), (19, 27), (9, 35), (-6, 45), (-20, 58), (-30, 76), (-34, 100), (-10, 100), (20, 100), (44, 100),
(60, 100), (59.2, 95), (59.6, 89), (62, 82), (65, 78), (72, 74), (82, 71.5), (92, 69), (98.5, 66.5), (100, 63),
] ]
EYE = (63, 54, 2.4) # x, y, raio (em coords do lobo) # Interior das orelhas (escuro, como no animal real).
EAR_IN = [
[(53, 9), (50, 3), (47, 10), (45, 20), (47, 27), (51, 24), (54, 15)],
[(27.5, 8), (25, 4), (23, 14), (22, 24), (25, 27), (28, 20)],
]
WX0, WSCALE = 64.0, 88.0 # nariz em x=152 (margem de 8 à direita)
Y0, YS = 6.0, 88.0 # topo das orelhas em y=6, base em y=94 # x do desenho onde wx=0 e largura de 100 unidades do lobo
def inside(poly, x, y): def to_wolf(x, y):
return (x - WX0) * 100.0 / WSCALE, y * 100.0 / H
def wolf_at(x, y):
wx, wy = to_wolf(x, y)
if not _inside(WOLF, wx, wy):
return False
return math.hypot(wx - 71.0, wy - 49.0) >= 1.7 # olho
def ear_in(x, y):
wx, wy = to_wolf(x, y)
return any(_inside(p, wx, wy) for p in EAR_IN)
def _inside(poly, x, y):
c = False c = False
j = len(poly) - 1 j = len(poly) - 1
for i in range(len(poly)): for i in range(len(poly)):
@@ -31,76 +68,182 @@ def inside(poly, x, y):
return c return c
def lerp(a, b, t):
return a + (b - a) * t
def hexmix(c1, c2, t):
a = [int(c1[i:i + 2], 16) for i in (1, 3, 5)]
b = [int(c2[i:i + 2], 16) for i in (1, 3, 5)]
return "#" + "".join(f"{round(lerp(x, y, t)):02x}" for x, y in zip(a, b))
def smooth(t): def smooth(t):
t = max(0.0, min(1.0, t)) t = max(0.0, min(1.0, t))
return t * t * (3 - 2 * t) return t * t * (3 - 2 * t)
def pixels(x_from, x_to, c_left, c_right, seed=7): def mix(c1, c2, t):
t = max(0.0, min(1.0, t))
a = [int(c1[i:i + 2], 16) for i in (1, 3, 5)]
b = [int(c2[i:i + 2], 16) for i in (1, 3, 5)]
return "#" + "".join(f"{round(p + (q - p) * t):02x}" for p, q in zip(a, b))
def smooth_path(pts, dup=()):
"""Curva fechada (Catmull-Rom -> Bézier); `dup` = índices de quinas vivas."""
P = []
for i, p in enumerate(pts):
P.append(p)
if i in dup:
P.append(p)
n = len(P)
d = f"M{P[0][0]:.2f},{P[0][1]:.2f}"
for i in range(n):
p0, p1, p2, p3 = P[(i - 1) % n], P[i], P[(i + 1) % n], P[(i + 2) % n]
c1 = (p1[0] + (p2[0] - p0[0]) / 6, p1[1] + (p2[1] - p0[1]) / 6)
c2 = (p2[0] - (p3[0] - p1[0]) / 6, p2[1] - (p3[1] - p1[1]) / 6)
d += f"C{c1[0]:.2f},{c1[1]:.2f} {c2[0]:.2f},{c2[1]:.2f} {p2[0]:.2f},{p2[1]:.2f}"
return d + "Z"
def tx(pts):
return [(WX0 + x * WSCALE / 100.0, Y0 + y * YS / 100.0) for x, y in pts]
def lerp(a, b, t):
return a + (b - a) * t
def build(pal, scatter=1.0, seed=5, uid="a", x_min=8.0):
rnd = random.Random(seed) rnd = random.Random(seed)
cell = 4.0 wolf = tx(WOLF)
out = [] corners = {i for i, (_, y) in enumerate(WOLF) if y >= 99.5 or y <= 0.6} # pontas e cantos vivos
wolf_x0, wolf_w = 62, 98 # onde o lobo começa e quanto mede (em unidades do desenho) body = smooth_path(wolf, dup=corners)
for cy in range(25): ears = [smooth_path(tx(e)) for e in EAR_IN]
for cx in range(40): cols, rows = int(W / CELL), int(H / CELL)
x, y = cx * cell + cell / 2, cy * cell + cell / 2
if not (x_from <= x <= x_to): # gradiente da figura (o mesmo para a silhueta e para cada pixel => fusão sem emenda)
gx0, gy0, gx1, gy1 = 58.0, 0.0, 160.0, 100.0
stops = pal["stops"]
def grad(x, y):
dx, dy = gx1 - gx0, gy1 - gy0
t = max(0.0, min(1.0, ((x - gx0) * dx + (y - gy0) * dy) / (dx * dx + dy * dy)))
for (t0, c0), (t1, c1) in zip(stops, stops[1:]):
if t <= t1:
return mix(c0, c1, (t - t0) / (t1 - t0))
return stops[-1][1]
X_SOLID = 80.0 # múltiplo do módulo: a partir daqui a figura é inteira e lisa
def ramp(x):
return min(1.0, max(0.0, x / X_SOLID)) ** 2.0
# envelope da "cauda": nasce na largura do pescoço e se afunila para a esquerda
def envelope(x, y):
k = smooth((x + 6) / 80.0)
yc = lerp(70, 62, k)
hh = lerp(5, 31, k ** 1.15)
return math.exp(-(abs(y - yc) / hh) ** 3.0)
occ = set()
def free(cx, cy, n, m=0):
return all((cx + i, cy + j) not in occ for i in range(-m, n + m) for j in range(-m, n + m))
def take(cx, cy, n):
for i in range(n):
for j in range(n):
occ.add((cx + i, cy + j))
mask_sq, free_sq = [], []
def emit(cx, cy, n, sz_scale, op, gap):
x0, y0 = cx * CELL, cy * CELL
size = n * CELL
sz = size * sz_scale
off = (size - sz) / 2
cxm, cym = x0 + size / 2, y0 + size / 2
inside = _inside(wolf, cxm, cym)
if inside and x0 >= 56:
# faz parte da figura lisa: vira janela da máscara
e = 0.12
mask_sq.append(f'<rect x="{x0 - e:.2f}" y="{y0 - e:.2f}" width="{size + 2 * e:.2f}" height="{size + 2 * e:.2f}" fill="#fff"/>')
else:
free_sq.append(f'<rect x="{x0 + off:.2f}" y="{y0 + off:.2f}" width="{sz:.2f}" height="{sz:.2f}" fill="{grad(cxm, cym)}" fill-opacity="{op:.2f}"/>')
# 1) campo de pixels da esquerda até a figura: tamanhos em múltiplos do módulo
order = [(cx, cy) for cy in range(rows) for cx in range(int(x_min / CELL), int(X_SOLID / CELL))]
rnd.shuffle(order)
for cx, cy in order:
x, y = (cx + 0.5) * CELL, (cy + 0.5) * CELL
r, env = ramp(x), envelope(x, y)
p = r * env
if p < 0.01 or y > 94:
continue
# blocos grandes na faixa média; sempre 1×1 colados perto da figura
n = 1
if r < 0.7:
big = rnd.random() < 0.9 * (1 - r) * env ** 0.5 * min(1.0, r * 3.2)
if big:
n = rnd.choice([2, 2, 3]) if r < 0.45 else 2
if cx + n > cols or cy + n > rows or not free(cx, cy, n, 0):
n = 1
if not free(cx, cy, 1, 0):
continue continue
t = smooth((x - 14) / 96) acc = p if n == 1 else min(1.0, p * 1.6)
wx, wy = (x - wolf_x0) * 100 / wolf_w, y if r > 0.88:
in_wolf = inside(WOLF, wx, wy) and math.hypot(wx - EYE[0], wy - EYE[1]) > EYE[2] acc = 1.0 if env > 0.45 else acc
if in_wolf: if rnd.random() > acc:
keep = 0.06 + 0.94 * t ** 1.15 continue
if t > 0.9: take(cx, cy, n)
keep = 1.0 gap_scale = 1.0 if r > 0.86 else (0.9 - 0.45 * (1 - r)) if n > 1 else rnd.choice([0.5, 0.65, 0.8, 0.9]) * (0.7 + 0.3 * r)
if rnd.random() > keep: op = 0.38 + 0.62 * smooth(r * 1.25)
continue emit(cx, cy, n, gap_scale if r <= 0.86 else 1.02, op, 0)
size = cell * (0.28 + 0.72 * t ** 0.9) * (1 if t > 0.9 else rnd.uniform(0.65, 1.15))
jit = (1 - t) ** 1.4 * cell * 0.9
else:
if rnd.random() > 0.2 * (1 - t) ** 1.2 or x > 96:
continue
size = cell * rnd.uniform(0.22, 0.85)
jit = cell * 0.9
size = min(size, cell * 1.05)
px = x - size / 2 + rnd.uniform(-jit, jit)
py = y - size / 2 + rnd.uniform(-jit, jit)
col = hexmix(c_left, c_right, max(0.0, min(1.0, t * 1.05 + rnd.uniform(-0.12, 0.12))))
op = 0.5 + 0.5 * t if not in_wolf or t < 0.9 else 1
out.append((px, py, size, col, op))
return out
# 2) partículas esparsas bem à esquerda e acima/abaixo da cauda (profundidade)
placed, tries, target = 0, 0, int(34 * scatter)
while placed < target and tries < 6000:
tries += 1
x = x_min + rnd.random() ** 1.3 * (70 - x_min)
cy = rnd.randrange(3, rows - 4)
cx = int(x / CELL)
y = (cy + 0.5) * CELL
env = envelope(x, y)
if env > 0.5 or not free(cx, cy, 1, 1):
continue
r = ramp(x)
# sempre perto da cauda, nunca longe demais
near = math.exp(-((abs(y - 62) - 26) / 22.0) ** 2)
if rnd.random() > 0.55 * near * (0.35 + 0.65 * r):
continue
take(cx, cy, 1)
emit(cx, cy, 1, rnd.choice([0.45, 0.6, 0.75]), 0.22 + 0.38 * r, 0)
placed += 1
def rects(px, dx=0.0, dy=0.0): ex, ey = tx([(71.0, 49.0)])[0]
return "".join( hx = " ".join(f'<stop offset="{t:g}" stop-color="{c}"/>' for t, c in stops)
f'<rect x="{x + dx:.2f}" y="{y + dy:.2f}" width="{s:.2f}" height="{s:.2f}" rx="{s * 0.12:.2f}" fill="{c}" opacity="{o:.2f}"/>' svg = (
for x, y, s, c, o in px "<defs>"
f'<linearGradient id="{uid}h" gradientUnits="userSpaceOnUse" x1="{gx0:g}" y1="{gy0:g}" x2="{gx1:g}" y2="{gy1:g}">{hx}</linearGradient>'
f'<mask id="{uid}m" maskUnits="userSpaceOnUse" x="0" y="0" width="{W:g}" height="{H:g}"><g shape-rendering="crispEdges">'
f'<rect x="{X_SOLID:g}" y="0" width="{W - X_SOLID + 1:g}" height="{H:g}" fill="#fff"/>'
+ "".join(mask_sq)
+ "</g></mask></defs>"
f'<g mask="url(#{uid}m)"><path d="{body}" fill="url(#{uid}h)"/>'
+ "".join(f'<path d="{e}" fill="{pal["ear"]}" fill-opacity="{pal["ear_op"]}"/>' for e in ears)
+ "</g>"
+ '<g shape-rendering="crispEdges">' + "".join(free_sq) + "</g>"
+ f'<circle cx="{ex:.2f}" cy="{ey:.2f}" r="1.35" fill="{pal["eye"]}"/>'
) )
return svg
def main(): def main():
# Marca larga (fundo transparente): ciano claro -> verde-azulado profundo. # Marca larga: funciona em fundo claro e escuro. Verde-azulado -> azul petróleo.
wide = pixels(0, 160, "#67e8f9", "#0f766e") pal = dict(stops=[(0.0, "#3BE3CC"), (0.45, "#12B5A8"), (1.0, "#0B6A86")], ear="#05323a", ear_op=0.5, eye="#ecfeff")
(OUT / "guara-logo.svg").write_text( (OUT / "guara-logo.svg").write_text(
'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 160 100" role="img" aria-label="Guará">' + rects(wide) + "</svg>\n" f'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 {W:g} {H:g}" role="img" aria-label="Guará">' + build(pal, uid="w") + "</svg>\n"
) )
# Ícone quadrado: fundo verde-azulado escuro, pixels claros. # Ícone: fundo petróleo profundo, figura clara.
icon_px = pixels(30, 160, "#99f6e4", "#f0fdfa", seed=11) ipal = dict(stops=[(0.0, "#d9fff7"), (0.5, "#8df1e0"), (1.0, "#3fc8cf")], ear="#0b4a55", ear_op=0.45, eye="#083344")
(OUT / "guara.svg").write_text( (OUT / "guara.svg").write_text(
'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 128" role="img" aria-label="Guará">' '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 128" role="img" aria-label="Guará">'
'<defs><linearGradient id="g" x1="0" y1="0" x2="1" y2="1"><stop offset="0" stop-color="#14b8a6"/><stop offset="1" stop-color="#0c4a6e"/></linearGradient></defs>' '<defs><linearGradient id="bg" x1="0" y1="0" x2="1" y2="1"><stop offset="0" stop-color="#0f766e"/><stop offset="1" stop-color="#083344"/></linearGradient>'
'<rect width="128" height="128" rx="29" fill="url(#g)"/>' '<clipPath id="ic"><rect width="128" height="128" rx="29"/></clipPath></defs>'
'<g transform="translate(-19 20) scale(0.88)">' + rects(icon_px) + "</g></svg>\n" '<rect width="128" height="128" rx="29" fill="url(#bg)"/>'
'<g clip-path="url(#ic)"><g transform="translate(-13 18) scale(0.86)">' + build(ipal, scatter=0.5, seed=9, uid="i", x_min=30.0) + "</g></g></svg>\n"
) )