Vectorize logo: SVG source + render all logo assets from vector

Trace the flat-color logo to source/logo.svg (palette-locked to the canonical
brand colors via tools/trace_logo.py), and render every avatar/favicon/logo
master from the SVG at its exact size (tools/build_assets.py via resvg). Logo
assets are now crisp at any resolution — removes the 640px upscale ceiling.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
jedarden 2026-05-22 08:22:22 -04:00
parent 648fb03050
commit d51a763da8
26 changed files with 142 additions and 27 deletions

View file

@ -6,8 +6,8 @@ consistent wherever it appears.
| | Source | Style |
|---|---|---|
| **Logo** | `source/logo.png` | Flat cartoon avatar — red polo, used for all **profile pictures** |
| **Hero** | `source/hero.png` | Photoreal triple-monitor desk scene — red polo, used for all **banners / covers** |
| **Logo** | `source/logo.svg` | **Vector** cartoon avatar — red polo, scales infinitely; used for all **profile pictures**. (`source/logo.png` is the original raster it was traced from.) |
| **Hero** | `source/hero.png` | Photoreal triple-monitor desk scene — red polo, used for all **banners / covers**. Raster only — photoreal imagery can't meaningfully vectorize. |
> The logo (flat illustration) and the hero (photoreal render) are intentionally
> kept as separate assets rather than composited together — mixing the two styles
@ -42,8 +42,9 @@ exact required pixel dimensions.
### Logo masters (`logo/`)
`logo-original.png` (640²) plus `logo-256/512/1024.png` and the source JPG.
Use these when a platform isn't listed above or you need a custom size.
`logo.svg` (vector — scale to any size) plus pre-rendered `logo-256/512/1024.png`
and `logo-original.png` (the 640² raster). Use the SVG when a platform isn't
listed above or you need a custom/large size; it never pixelates.
## Palette
@ -57,15 +58,20 @@ Use these when a platform isn't listed above or you need a custom size.
## Regenerating
All derived assets are produced from the two sources in `source/`:
All derived assets are produced from the sources in `source/`:
```bash
python3 tools/build_assets.py # requires Pillow
python3 tools/trace_logo.py # raster logo.png -> vector logo.svg (needs vtracer)
python3 tools/build_assets.py # sources -> every platform asset (needs Pillow; resvg for crisp vector logo)
```
Edit `source/logo.png` or `source/hero.png` (or the size tables in the script),
re-run, and commit. `source/hero-alt.png` is an alternate desk composition kept
for reference.
`build_assets.py` renders each logo asset straight from `source/logo.svg` at its
exact target size (via `resvg`), so profile pictures and favicons are crisp at
any resolution. If `resvg` is unavailable it falls back to resizing the raster.
Tooling (one-time): `cargo install vtracer resvg`. Edit `source/logo.svg`/`hero.png`
(or the size tables in the script), re-run, and commit. `source/hero-alt.png` is
an alternate desk composition kept for reference.
## Usage & rights

Binary file not shown.

Before

Width:  |  Height:  |  Size: 91 KiB

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 138 KiB

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 64 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 116 KiB

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 64 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 91 KiB

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 91 KiB

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 64 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

After

Width:  |  Height:  |  Size: 8.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 91 KiB

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 280 KiB

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1,020 B

After

Width:  |  Height:  |  Size: 513 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 138 KiB

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 76 KiB

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 410 KiB

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 46 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 138 KiB

After

Width:  |  Height:  |  Size: 22 KiB

19
logo/logo.svg Normal file
View file

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generator: visioncortex VTracer 0.6.5 -->
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="640" height="640">
<path d="M0 0 C211.2 0 422.4 0 640 0 C640 211.2 640 422.4 640 640 C428.8 640 217.6 640 0 640 C0 428.8 0 217.6 0 0 Z " fill="#0A0A08" transform="translate(0,0)"/>
<path d="M0 0 C211.2 0 422.4 0 640 0 C640 211.2 640 422.4 640 640 C633.73 640 627.46 640 621 640 C620.82 639.31 620.82 639.31 619.93 635.81 C616.79 623.47 613.65 611.14 610.5 598.8 C609.04 593.09 607.59 587.39 606.14 581.68 C602.08 565.69 597.87 549.77 593 534 C592.69 532.98 592.37 531.96 592.05 530.9 C581.58 497.23 566.48 472.76 534.83 455.95 C519.73 448.08 503.87 442.12 488 436 C479.85 432.85 471.71 429.66 463.59 426.42 C461.12 425.44 458.65 424.48 456.16 423.53 C452.94 422.29 449.73 421.03 446.53 419.74 C444.75 419.02 442.95 418.35 441.15 417.67 C432.69 414.21 429.13 410.03 425 402 C423.99 400.31 422.97 398.62 421.94 396.94 C420.43 394.41 418.93 391.88 417.47 389.33 C413.97 383.29 410.87 378.91 405 375 C403.34 374.62 401.68 374.27 400 374 C399.15 369.6 398.64 365.47 399 361 C400.59 358.67 402.26 357.47 404.55 355.84 C421.5 343.07 430.63 319.95 436.8 300.58 C438 297 438 297 439 296 C440.68 295.7 442.37 295.44 444.06 295.19 C455.52 293.18 462.45 287.39 469.08 277.99 C477.7 264.59 481.18 249.53 481.25 233.81 C481.27 232.73 481.29 231.64 481.31 230.52 C481.35 221.77 480.22 213.59 475.31 206.12 C474.88 205.43 474.44 204.73 473.99 204.01 C471.11 201.11 467.7 199.65 464 198 C464.07 197.65 464.07 197.65 464.43 195.9 C465.08 192.68 465.73 189.47 466.38 186.25 C466.6 185.16 466.82 184.07 467.05 182.94 C473.73 149.71 476.7 112.63 457 83 C447.09 69.88 434.42 61.46 418.06 58.75 C412.97 57.72 410.9 56.4 407.94 52.12 C406.95 50.42 405.97 48.71 405 47 C392.7 30.16 368.1 22.39 348.39 19.19 C305.04 13.26 256.36 20.24 220.44 46.56 C215.08 50.81 209.98 55.31 205 60 C204.34 60.6 203.67 61.2 202.99 61.82 C181.39 82.1 165.81 114.77 164.8 144.43 C164.54 160.13 166.51 174.6 171.46 189.52 C173.52 195.88 173.52 195.88 172 199 C171.28 199.39 170.56 199.78 169.81 200.19 C164.07 203.89 161.06 209.88 159.12 216.31 C154.77 236.64 158.62 259.18 169.38 276.88 C175.7 286.21 183.37 293.15 194.77 295.59 C196.84 295.83 198.92 295.93 201 296 C201.3 297.02 201.61 298.03 201.92 299.08 C207.73 318.33 215.85 334.65 229 350 C229.58 350.7 230.16 351.4 230.76 352.12 C234.7 356.85 234.7 356.85 237 358 C237 358.66 237 359.32 237 360 C237.99 360.33 238.98 360.66 240 361 C240.08 365.52 240.1 369.59 239 374 C238.18 374.19 237.35 374.37 236.5 374.56 C226.24 378.78 222.35 387.26 217.4 396.59 C212.5 405.77 207.95 413.07 198.17 417.05 C197.48 417.33 196.78 417.62 196.07 417.92 C193.78 418.87 191.48 419.81 189.19 420.75 C187.58 421.42 185.96 422.08 184.35 422.75 C172.68 427.56 160.94 432.2 149.19 436.81 C108.09 452.94 75 467.19 55.63 508.96 C42.08 540.01 35.04 574.42 26.79 607.16 C24.02 618.15 21.07 629.08 18 640 C12.06 640 6.12 640 0 640 C0 428.8 0 217.6 0 0 Z " fill="#EFDDCB" transform="translate(0,0)"/>
<path d="M0 0 C1.99 2.99 2.36 4.22 2.82 7.66 C6.12 29.95 13.35 51.59 26.84 69.98 C29 73 29 73 29 75 C32.85 76.46 36.31 77.45 40.37 76.37 C46.16 73.64 51.1 69.76 56.1 65.81 C68.29 56.19 80.12 48.91 96 50 C101.22 51.04 104.69 54.08 107.89 58.18 C109.64 61.05 109.67 62.72 109 66 C108.12 67.93 107.14 69.78 106.13 71.64 C102.57 79.07 101.41 87.36 100.81 95.5 C100.73 96.54 100.65 97.59 100.57 98.66 C99.75 111.7 99.78 124.76 99.75 137.81 C99.74 138.97 99.74 140.12 99.73 141.31 C99.72 144.63 99.73 147.95 99.73 151.27 C99.73 151.77 99.73 151.77 99.72 154.32 C99.78 163.42 99.78 163.42 102 167 C105.36 168.12 107.88 168.11 111.42 168.1 C112.67 168.09 113.93 168.09 115.22 168.09 C116.53 168.08 117.84 168.07 119.19 168.06 C120.52 168.06 121.86 168.05 123.19 168.05 C126.46 168.04 129.73 168.02 133 168 C133.38 166.34 133.71 164.68 134 163 C132.4 161.4 130.63 161.8 128.41 161.72 C127.95 161.7 127.95 161.7 125.59 161.61 C124.61 161.57 123.63 161.54 122.62 161.5 C120.7 161.43 118.78 161.36 116.85 161.28 C115.99 161.25 115.14 161.22 114.25 161.19 C112 161 112 161 109 160 C108.93 151.67 108.88 143.34 108.84 135.01 C108.83 131.14 108.81 127.27 108.77 123.41 C108.74 119.66 108.72 115.91 108.72 112.16 C108.71 110.75 108.7 109.33 108.68 107.91 C108.47 88.91 111.38 72.46 124.75 58.16 C130.75 52.4 135.69 49.74 144.12 49.56 C156.66 49.83 165.69 56.46 175.32 63.73 C177.88 65.66 180.47 67.55 183.06 69.44 C183.48 69.75 183.48 69.75 185.6 71.31 C190.42 74.7 193.82 76.85 199.8 76.58 C203.34 75.65 204.57 73.65 206.48 70.64 C206.98 69.77 207.48 68.9 208 68 C208.61 67 209.23 66.01 209.86 64.98 C220.21 47.71 227.42 29.74 229.96 9.71 C230.07 8.89 230.18 8.06 230.29 7.21 C230.38 6.47 230.47 5.73 230.56 4.97 C231 3 231 3 233 0 C234.07 0.44 235.14 0.89 236.25 1.34 C271.91 16.07 271.91 16.07 283.31 20.31 C306.41 28.94 329.35 37.9 349 53 C349.48 53.36 349.48 53.36 351.89 55.17 C352.59 55.78 353.28 56.38 354 57 C354 57.66 354 58.32 354 59 C354.99 59.33 355.98 59.66 357 60 C364.11 67.84 368.65 77.47 373 87 C373.26 87.57 373.26 87.57 374.59 90.48 C379.11 101.1 381.98 112.17 384.98 123.29 C385.72 125.98 386.48 128.66 387.26 131.34 C391.6 146.23 395.48 161.24 399.29 176.28 C400.2 179.89 401.13 183.51 402.05 187.12 C402.77 189.93 403.49 192.74 404.2 195.55 C404.54 196.88 404.88 198.22 405.22 199.55 C405.69 201.4 406.16 203.25 406.63 205.1 C406.89 206.14 407.16 207.19 407.43 208.27 C408 211 408 211 408 215 C215.61 215 23.22 215 -175 215 C-170.4 194.28 -170.4 194.28 -168.05 185.32 C-167.79 184.32 -167.52 183.31 -167.26 182.28 C-166.42 179.08 -165.59 175.88 -164.75 172.69 C-164.46 171.59 -164.17 170.49 -163.88 169.35 C-161.93 161.9 -159.97 154.45 -158 147 C-157.89 146.59 -157.89 146.59 -157.35 144.54 C-141.08 82.79 -141.08 82.79 -125 63 C-124.52 62.33 -124.04 61.66 -123.54 60.98 C-106.03 38.28 -71.75 29 -46.05 18.81 C-41.28 16.92 -36.52 15.02 -31.76 13.11 C-29.26 12.12 -26.77 11.12 -24.27 10.13 C-16.12 6.89 -8.05 3.49 0 0 Z " fill="#DC3127" transform="translate(203,425)"/>
<path d="M0 0 C23.26 -0.5 46.83 2.58 64.26 19.24 C82.38 39.04 85.69 66.56 90.09 92 C90.21 92.73 90.34 93.46 90.47 94.21 C93.09 109.43 95.12 124.46 95.46 139.93 C95.52 142.38 95.58 144.82 95.65 147.27 C95.68 148.32 95.7 149.38 95.72 150.46 C95.9 153.12 95.9 153.12 96.9 156.12 C98.55 156.45 100.2 156.78 101.9 157.12 C102 156.57 102.11 156.01 102.22 155.44 C107.59 127.43 107.59 127.43 112.9 122.12 C116 120.57 118.48 120.83 121.9 121.12 C127.2 124.08 129.78 129.27 131.43 134.96 C135.05 151.69 131.15 170.23 122.49 184.76 C117.82 191.7 112.88 197.09 104.9 200.12 C100.96 200.56 100.96 200.56 97.9 200.12 C97.24 199.46 96.58 198.8 95.9 198.12 C94.58 198.12 93.26 198.12 91.9 198.12 C91.55 199.38 91.19 200.64 90.83 201.93 C84.9 222.67 77.06 240.55 62.9 257.12 C62.25 257.92 61.59 258.72 60.92 259.54 C42.68 281.03 15.02 295.65 -13.1 298.12 C-46.15 299.59 -74.17 287.49 -98.5 265.52 C-117.7 247.68 -128.45 224.4 -134.1 199.12 C-136.48 198.5 -136.48 198.5 -139.1 198.12 C-139.76 198.78 -140.42 199.44 -141.1 200.12 C-147.19 200.74 -152.13 198.57 -156.96 195.05 C-160.79 191.59 -163.47 187.53 -166.1 183.12 C-166.49 182.47 -166.88 181.82 -167.28 181.16 C-174.82 167.34 -178.03 148.49 -173.86 133.09 C-172.2 128.79 -170.17 124.4 -166.16 121.92 C-162.99 120.69 -160.46 120.76 -157.1 121.12 C-149.04 127.79 -148.27 139.65 -146.71 149.4 C-146.28 152.03 -145.82 154.55 -145.1 157.12 C-143.45 156.79 -141.8 156.46 -140.1 156.12 C-139.25 152.45 -139.01 149.12 -139.07 145.36 C-139.06 127.77 -137.15 110.9 -134.23 93.56 C-134.05 92.51 -133.87 91.46 -133.69 90.37 C-132.69 84.47 -131.65 78.58 -130.57 72.7 C-130.13 70.3 -129.73 67.9 -129.33 65.5 C-129.1 64.15 -128.86 62.81 -128.62 61.46 C-128.53 60.9 -128.53 60.9 -128.05 58.05 C-126.22 52.41 -121.74 49.49 -117.1 46.12 C-115.22 44.57 -113.35 43 -111.48 41.43 C-109.69 39.99 -107.9 38.55 -106.1 37.12 C-105.33 36.51 -104.56 35.89 -103.77 35.26 C-103.07 34.72 -102.38 34.18 -101.66 33.62 C-101.07 33.16 -100.47 32.69 -99.86 32.21 C-97.95 31.03 -96.29 30.55 -94.1 30.12 C-94.1 29.46 -94.1 28.8 -94.1 28.12 C-64.32 10.99 -34.54 1.35 0 0 Z " fill="#F4AF78" transform="translate(341.1015625,85.87890625)"/>
<path d="M0 0 C0.2 4.99 0.34 9.99 0.44 14.98 C0.48 16.68 0.53 18.37 0.6 20.06 C1.32 37.77 -4.33 48.71 -16 62 C-16.63 62.78 -17.26 63.57 -17.91 64.38 C-24.8 72.64 -33.4 78.65 -42 85 C-49.88 90.87 -57.34 96.96 -64.44 103.75 C-66.61 105.66 -68.35 106.9 -71 108 C-71.73 107.24 -72.45 106.48 -73.2 105.69 C-80.98 97.65 -89.24 90.99 -98.45 84.61 C-106.57 78.95 -113.87 72.87 -121 66 C-121.81 65.26 -122.63 64.52 -123.46 63.76 C-131.72 56.04 -140.04 44.82 -141.45 33.33 C-141.48 32.05 -141.51 30.77 -141.55 29.46 C-141.57 28.77 -141.59 28.08 -141.61 27.36 C-141.65 25.92 -141.68 24.47 -141.71 23.02 C-141.75 20.81 -141.81 18.6 -141.88 16.38 C-142.18 4.66 -142.18 4.66 -141 1 C-136.72 2.53 -133.02 4.74 -129.19 7.12 C-104.14 22.34 -77.75 30.89 -48.3 23.9 C-47.21 23.6 -46.12 23.31 -45 23 C-43.99 22.73 -42.98 22.47 -41.95 22.19 C-29.1 18.36 -17.91 11.25 -7.1 3.51 C-2.19 0 -2.19 0 0 0 Z " fill="#F4AF78" transform="translate(390,370)"/>
<path d="M0 0 C0.01 0.81 0.03 1.63 0.04 2.46 C1.1 27.9 13.33 47.27 31.56 64.44 C38.2 70.31 45.63 75.11 53 80 C49.92 82.05 48.13 82.48 44.56 83.19 C30.15 86.68 16.87 97.71 5.65 107.14 C4 108 4 108 2.02 107.99 C-2.87 105.59 -5.4 98.67 -8 94 C-8.35 93.39 -8.69 92.77 -9.05 92.14 C-17.86 76.34 -27.5 53.23 -23.54 34.84 C-22.03 30.36 -19.58 26.69 -16.88 22.84 C-13.88 18.31 -11.21 13.57 -8.52 8.85 C-8.1 8.14 -7.69 7.43 -7.27 6.7 C-6.9 6.06 -6.54 5.42 -6.16 4.76 C-3.02 0 -3.02 0 0 0 Z " fill="#DC3127" transform="translate(238,384)"/>
<path d="M0 0 C7.7 3.22 11.18 12.95 15.09 19.89 C16.96 23.2 18.88 26.44 20.94 29.62 C26.96 39.48 23.73 51.56 21.25 62.17 C17.17 78.5 9.58 94.18 0 108 C-3.68 107.38 -5.92 105.8 -8.88 103.56 C-9.84 102.84 -10.81 102.13 -11.81 101.39 C-13.43 100.17 -15.05 98.96 -16.67 97.74 C-27.23 89.8 -37.73 83.25 -51 81 C-47.05 76.64 -42.51 73.37 -37.72 69.96 C-18.44 56.03 -5.01 35.48 -1 12 C-0.54 8 -0.21 4.02 0 0 Z " fill="#DC3127" transform="translate(401,384)"/>
<path d="M0 0 C3.65 3.42 7.27 7.23 9 12 C8.71 13.67 8.38 15.34 8 17 C7.12 16.98 6.24 16.97 5.33 16.95 C-14.92 16.64 -33.15 17.47 -52.73 23.23 C-55.98 24 -58.67 24.25 -62 24 C-64.54 22.35 -65.67 21.02 -66.61 18.13 C-67.33 14.34 -67.5 12.8 -65.36 9.41 C-53.51 -2.67 -14.57 -10.22 0 0 Z " fill="#0A0A08" transform="translate(407,170)"/>
<path d="M0 0 C3.58 2.15 5.68 3.51 8 7 C8.3 11.18 8.44 14.47 6 18 C0.22 20.89 -8.84 17.11 -14.75 15.56 C-32.25 11.23 -49.08 10.58 -67 12 C-68.17 8.54 -68.06 8.13 -66.38 4.56 C-52.44 -17.78 -20.24 -8.69 0 0 Z " fill="#0A0A08" transform="translate(291,175)"/>
<path d="M0 0 C2.49 0.07 2.49 0.07 5 1 C6.25 3.14 6.25 3.14 7.11 5.92 C7.44 6.92 7.76 7.92 8.09 8.95 C8.39 9.96 8.69 10.96 9 12 C9.14 12.42 9.14 12.42 9.82 14.54 C21.67 51.52 33.43 93.94 32 133 C29.03 133 26.06 133 23 133 C22.94 132.27 22.88 131.54 22.82 130.79 C19.66 93.24 11.98 57.13 1.55 20.93 C1.31 20.12 1.08 19.3 0.84 18.46 C0.4 16.93 -0.04 15.41 -0.5 13.88 C-1.67 9.83 -2.42 6.22 -2 2 C-1.34 1.34 -0.68 0.68 0 0 Z " fill="#0A0A08" transform="translate(92,507)"/>
<path d="M0 0 C1.88 0.25 1.88 0.25 4 1 C5.42 3.15 6.05 4.43 5.83 7.02 C5.64 7.75 5.44 8.48 5.23 9.23 C5.01 10.1 4.78 10.96 4.55 11.85 C4.42 12.33 4.42 12.33 3.75 14.75 C3.18 16.91 2.62 19.08 2.05 21.24 C1.73 22.46 1.41 23.68 1.07 24.93 C-8.35 60.56 -16.87 96.06 -19 133 C-21.97 133 -24.94 133 -28 133 C-28.67 93.14 -17.04 52.33 -6.19 14.25 C-5.91 13.26 -5.63 12.27 -5.35 11.26 C-5.08 10.35 -4.82 9.45 -4.54 8.52 C-4.32 7.73 -4.09 6.95 -3.86 6.15 C-2.9 3.75 -1.63 1.99 0 0 Z " fill="#0A0A08" transform="translate(544,507)"/>
<path d="M0 0 C1.94 0.81 1.94 0.81 4 2 C6.78 10.33 4.71 18.3 1 26 C-0.52 28.55 -1.75 29.97 -4 32 C-6.81 32.38 -6.81 32.38 -9 32 C-9.33 31.34 -9.66 30.68 -10 30 C-8.81 27.02 -7.51 24.1 -6.16 21.18 C-3.98 16.01 -3.58 11.23 -3.41 5.64 C-2.95 2.69 -2.31 1.8 0 0 Z " fill="#DC3529" transform="translate(453,233)"/>
<path d="M0 0 C1.94 0.31 1.94 0.31 4 1 C5.14 4.43 5.43 7.59 5.81 11.19 C6.33 15.67 6.96 19.63 9.19 23.62 C11 27 11 27 10.75 30 C10.5 30.66 10.25 31.32 10 32 C6.98 31.68 5.42 31.43 3.27 29.21 C-1.65 21.53 -4.21 14.24 -3 5 C-1.5 1.94 -1.5 1.94 0 0 Z " fill="#DC3228" transform="translate(184,233)"/>
<path d="M0 0 C3.33 0.55 5.3 1.49 8 3.5 C9.62 6.73 9.71 10.02 9 13.5 C5.76 16.74 3.95 17.48 -0.62 17.56 C-4.69 16.28 -5.94 15.2 -8 11.5 C-8.56 8.5 -8.56 8.5 -8 5.5 C-5.54 2.17 -4.13 0.69 0 0 Z " fill="#0A0A08" transform="translate(328,546.5)"/>
<path d="M0 0 C2.75 1.06 2.75 1.06 5 3 C6.55 6.65 7.24 8.92 6.38 12.81 C4.75 15.4 3.91 16.11 1 17 C-3.02 17.6 -4.5 17.35 -7.88 15 C-10.81 10.85 -10.72 9.01 -10 4 C-7.28 -0.18 -4.83 -0.69 0 0 Z " fill="#0A0A08" transform="translate(331,504)"/>
</svg>

After

Width:  |  Height:  |  Size: 12 KiB

19
source/logo.svg Normal file
View file

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generator: visioncortex VTracer 0.6.5 -->
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="640" height="640">
<path d="M0 0 C211.2 0 422.4 0 640 0 C640 211.2 640 422.4 640 640 C428.8 640 217.6 640 0 640 C0 428.8 0 217.6 0 0 Z " fill="#0A0A08" transform="translate(0,0)"/>
<path d="M0 0 C211.2 0 422.4 0 640 0 C640 211.2 640 422.4 640 640 C633.73 640 627.46 640 621 640 C620.82 639.31 620.82 639.31 619.93 635.81 C616.79 623.47 613.65 611.14 610.5 598.8 C609.04 593.09 607.59 587.39 606.14 581.68 C602.08 565.69 597.87 549.77 593 534 C592.69 532.98 592.37 531.96 592.05 530.9 C581.58 497.23 566.48 472.76 534.83 455.95 C519.73 448.08 503.87 442.12 488 436 C479.85 432.85 471.71 429.66 463.59 426.42 C461.12 425.44 458.65 424.48 456.16 423.53 C452.94 422.29 449.73 421.03 446.53 419.74 C444.75 419.02 442.95 418.35 441.15 417.67 C432.69 414.21 429.13 410.03 425 402 C423.99 400.31 422.97 398.62 421.94 396.94 C420.43 394.41 418.93 391.88 417.47 389.33 C413.97 383.29 410.87 378.91 405 375 C403.34 374.62 401.68 374.27 400 374 C399.15 369.6 398.64 365.47 399 361 C400.59 358.67 402.26 357.47 404.55 355.84 C421.5 343.07 430.63 319.95 436.8 300.58 C438 297 438 297 439 296 C440.68 295.7 442.37 295.44 444.06 295.19 C455.52 293.18 462.45 287.39 469.08 277.99 C477.7 264.59 481.18 249.53 481.25 233.81 C481.27 232.73 481.29 231.64 481.31 230.52 C481.35 221.77 480.22 213.59 475.31 206.12 C474.88 205.43 474.44 204.73 473.99 204.01 C471.11 201.11 467.7 199.65 464 198 C464.07 197.65 464.07 197.65 464.43 195.9 C465.08 192.68 465.73 189.47 466.38 186.25 C466.6 185.16 466.82 184.07 467.05 182.94 C473.73 149.71 476.7 112.63 457 83 C447.09 69.88 434.42 61.46 418.06 58.75 C412.97 57.72 410.9 56.4 407.94 52.12 C406.95 50.42 405.97 48.71 405 47 C392.7 30.16 368.1 22.39 348.39 19.19 C305.04 13.26 256.36 20.24 220.44 46.56 C215.08 50.81 209.98 55.31 205 60 C204.34 60.6 203.67 61.2 202.99 61.82 C181.39 82.1 165.81 114.77 164.8 144.43 C164.54 160.13 166.51 174.6 171.46 189.52 C173.52 195.88 173.52 195.88 172 199 C171.28 199.39 170.56 199.78 169.81 200.19 C164.07 203.89 161.06 209.88 159.12 216.31 C154.77 236.64 158.62 259.18 169.38 276.88 C175.7 286.21 183.37 293.15 194.77 295.59 C196.84 295.83 198.92 295.93 201 296 C201.3 297.02 201.61 298.03 201.92 299.08 C207.73 318.33 215.85 334.65 229 350 C229.58 350.7 230.16 351.4 230.76 352.12 C234.7 356.85 234.7 356.85 237 358 C237 358.66 237 359.32 237 360 C237.99 360.33 238.98 360.66 240 361 C240.08 365.52 240.1 369.59 239 374 C238.18 374.19 237.35 374.37 236.5 374.56 C226.24 378.78 222.35 387.26 217.4 396.59 C212.5 405.77 207.95 413.07 198.17 417.05 C197.48 417.33 196.78 417.62 196.07 417.92 C193.78 418.87 191.48 419.81 189.19 420.75 C187.58 421.42 185.96 422.08 184.35 422.75 C172.68 427.56 160.94 432.2 149.19 436.81 C108.09 452.94 75 467.19 55.63 508.96 C42.08 540.01 35.04 574.42 26.79 607.16 C24.02 618.15 21.07 629.08 18 640 C12.06 640 6.12 640 0 640 C0 428.8 0 217.6 0 0 Z " fill="#EFDDCB" transform="translate(0,0)"/>
<path d="M0 0 C1.99 2.99 2.36 4.22 2.82 7.66 C6.12 29.95 13.35 51.59 26.84 69.98 C29 73 29 73 29 75 C32.85 76.46 36.31 77.45 40.37 76.37 C46.16 73.64 51.1 69.76 56.1 65.81 C68.29 56.19 80.12 48.91 96 50 C101.22 51.04 104.69 54.08 107.89 58.18 C109.64 61.05 109.67 62.72 109 66 C108.12 67.93 107.14 69.78 106.13 71.64 C102.57 79.07 101.41 87.36 100.81 95.5 C100.73 96.54 100.65 97.59 100.57 98.66 C99.75 111.7 99.78 124.76 99.75 137.81 C99.74 138.97 99.74 140.12 99.73 141.31 C99.72 144.63 99.73 147.95 99.73 151.27 C99.73 151.77 99.73 151.77 99.72 154.32 C99.78 163.42 99.78 163.42 102 167 C105.36 168.12 107.88 168.11 111.42 168.1 C112.67 168.09 113.93 168.09 115.22 168.09 C116.53 168.08 117.84 168.07 119.19 168.06 C120.52 168.06 121.86 168.05 123.19 168.05 C126.46 168.04 129.73 168.02 133 168 C133.38 166.34 133.71 164.68 134 163 C132.4 161.4 130.63 161.8 128.41 161.72 C127.95 161.7 127.95 161.7 125.59 161.61 C124.61 161.57 123.63 161.54 122.62 161.5 C120.7 161.43 118.78 161.36 116.85 161.28 C115.99 161.25 115.14 161.22 114.25 161.19 C112 161 112 161 109 160 C108.93 151.67 108.88 143.34 108.84 135.01 C108.83 131.14 108.81 127.27 108.77 123.41 C108.74 119.66 108.72 115.91 108.72 112.16 C108.71 110.75 108.7 109.33 108.68 107.91 C108.47 88.91 111.38 72.46 124.75 58.16 C130.75 52.4 135.69 49.74 144.12 49.56 C156.66 49.83 165.69 56.46 175.32 63.73 C177.88 65.66 180.47 67.55 183.06 69.44 C183.48 69.75 183.48 69.75 185.6 71.31 C190.42 74.7 193.82 76.85 199.8 76.58 C203.34 75.65 204.57 73.65 206.48 70.64 C206.98 69.77 207.48 68.9 208 68 C208.61 67 209.23 66.01 209.86 64.98 C220.21 47.71 227.42 29.74 229.96 9.71 C230.07 8.89 230.18 8.06 230.29 7.21 C230.38 6.47 230.47 5.73 230.56 4.97 C231 3 231 3 233 0 C234.07 0.44 235.14 0.89 236.25 1.34 C271.91 16.07 271.91 16.07 283.31 20.31 C306.41 28.94 329.35 37.9 349 53 C349.48 53.36 349.48 53.36 351.89 55.17 C352.59 55.78 353.28 56.38 354 57 C354 57.66 354 58.32 354 59 C354.99 59.33 355.98 59.66 357 60 C364.11 67.84 368.65 77.47 373 87 C373.26 87.57 373.26 87.57 374.59 90.48 C379.11 101.1 381.98 112.17 384.98 123.29 C385.72 125.98 386.48 128.66 387.26 131.34 C391.6 146.23 395.48 161.24 399.29 176.28 C400.2 179.89 401.13 183.51 402.05 187.12 C402.77 189.93 403.49 192.74 404.2 195.55 C404.54 196.88 404.88 198.22 405.22 199.55 C405.69 201.4 406.16 203.25 406.63 205.1 C406.89 206.14 407.16 207.19 407.43 208.27 C408 211 408 211 408 215 C215.61 215 23.22 215 -175 215 C-170.4 194.28 -170.4 194.28 -168.05 185.32 C-167.79 184.32 -167.52 183.31 -167.26 182.28 C-166.42 179.08 -165.59 175.88 -164.75 172.69 C-164.46 171.59 -164.17 170.49 -163.88 169.35 C-161.93 161.9 -159.97 154.45 -158 147 C-157.89 146.59 -157.89 146.59 -157.35 144.54 C-141.08 82.79 -141.08 82.79 -125 63 C-124.52 62.33 -124.04 61.66 -123.54 60.98 C-106.03 38.28 -71.75 29 -46.05 18.81 C-41.28 16.92 -36.52 15.02 -31.76 13.11 C-29.26 12.12 -26.77 11.12 -24.27 10.13 C-16.12 6.89 -8.05 3.49 0 0 Z " fill="#DC3127" transform="translate(203,425)"/>
<path d="M0 0 C23.26 -0.5 46.83 2.58 64.26 19.24 C82.38 39.04 85.69 66.56 90.09 92 C90.21 92.73 90.34 93.46 90.47 94.21 C93.09 109.43 95.12 124.46 95.46 139.93 C95.52 142.38 95.58 144.82 95.65 147.27 C95.68 148.32 95.7 149.38 95.72 150.46 C95.9 153.12 95.9 153.12 96.9 156.12 C98.55 156.45 100.2 156.78 101.9 157.12 C102 156.57 102.11 156.01 102.22 155.44 C107.59 127.43 107.59 127.43 112.9 122.12 C116 120.57 118.48 120.83 121.9 121.12 C127.2 124.08 129.78 129.27 131.43 134.96 C135.05 151.69 131.15 170.23 122.49 184.76 C117.82 191.7 112.88 197.09 104.9 200.12 C100.96 200.56 100.96 200.56 97.9 200.12 C97.24 199.46 96.58 198.8 95.9 198.12 C94.58 198.12 93.26 198.12 91.9 198.12 C91.55 199.38 91.19 200.64 90.83 201.93 C84.9 222.67 77.06 240.55 62.9 257.12 C62.25 257.92 61.59 258.72 60.92 259.54 C42.68 281.03 15.02 295.65 -13.1 298.12 C-46.15 299.59 -74.17 287.49 -98.5 265.52 C-117.7 247.68 -128.45 224.4 -134.1 199.12 C-136.48 198.5 -136.48 198.5 -139.1 198.12 C-139.76 198.78 -140.42 199.44 -141.1 200.12 C-147.19 200.74 -152.13 198.57 -156.96 195.05 C-160.79 191.59 -163.47 187.53 -166.1 183.12 C-166.49 182.47 -166.88 181.82 -167.28 181.16 C-174.82 167.34 -178.03 148.49 -173.86 133.09 C-172.2 128.79 -170.17 124.4 -166.16 121.92 C-162.99 120.69 -160.46 120.76 -157.1 121.12 C-149.04 127.79 -148.27 139.65 -146.71 149.4 C-146.28 152.03 -145.82 154.55 -145.1 157.12 C-143.45 156.79 -141.8 156.46 -140.1 156.12 C-139.25 152.45 -139.01 149.12 -139.07 145.36 C-139.06 127.77 -137.15 110.9 -134.23 93.56 C-134.05 92.51 -133.87 91.46 -133.69 90.37 C-132.69 84.47 -131.65 78.58 -130.57 72.7 C-130.13 70.3 -129.73 67.9 -129.33 65.5 C-129.1 64.15 -128.86 62.81 -128.62 61.46 C-128.53 60.9 -128.53 60.9 -128.05 58.05 C-126.22 52.41 -121.74 49.49 -117.1 46.12 C-115.22 44.57 -113.35 43 -111.48 41.43 C-109.69 39.99 -107.9 38.55 -106.1 37.12 C-105.33 36.51 -104.56 35.89 -103.77 35.26 C-103.07 34.72 -102.38 34.18 -101.66 33.62 C-101.07 33.16 -100.47 32.69 -99.86 32.21 C-97.95 31.03 -96.29 30.55 -94.1 30.12 C-94.1 29.46 -94.1 28.8 -94.1 28.12 C-64.32 10.99 -34.54 1.35 0 0 Z " fill="#F4AF78" transform="translate(341.1015625,85.87890625)"/>
<path d="M0 0 C0.2 4.99 0.34 9.99 0.44 14.98 C0.48 16.68 0.53 18.37 0.6 20.06 C1.32 37.77 -4.33 48.71 -16 62 C-16.63 62.78 -17.26 63.57 -17.91 64.38 C-24.8 72.64 -33.4 78.65 -42 85 C-49.88 90.87 -57.34 96.96 -64.44 103.75 C-66.61 105.66 -68.35 106.9 -71 108 C-71.73 107.24 -72.45 106.48 -73.2 105.69 C-80.98 97.65 -89.24 90.99 -98.45 84.61 C-106.57 78.95 -113.87 72.87 -121 66 C-121.81 65.26 -122.63 64.52 -123.46 63.76 C-131.72 56.04 -140.04 44.82 -141.45 33.33 C-141.48 32.05 -141.51 30.77 -141.55 29.46 C-141.57 28.77 -141.59 28.08 -141.61 27.36 C-141.65 25.92 -141.68 24.47 -141.71 23.02 C-141.75 20.81 -141.81 18.6 -141.88 16.38 C-142.18 4.66 -142.18 4.66 -141 1 C-136.72 2.53 -133.02 4.74 -129.19 7.12 C-104.14 22.34 -77.75 30.89 -48.3 23.9 C-47.21 23.6 -46.12 23.31 -45 23 C-43.99 22.73 -42.98 22.47 -41.95 22.19 C-29.1 18.36 -17.91 11.25 -7.1 3.51 C-2.19 0 -2.19 0 0 0 Z " fill="#F4AF78" transform="translate(390,370)"/>
<path d="M0 0 C0.01 0.81 0.03 1.63 0.04 2.46 C1.1 27.9 13.33 47.27 31.56 64.44 C38.2 70.31 45.63 75.11 53 80 C49.92 82.05 48.13 82.48 44.56 83.19 C30.15 86.68 16.87 97.71 5.65 107.14 C4 108 4 108 2.02 107.99 C-2.87 105.59 -5.4 98.67 -8 94 C-8.35 93.39 -8.69 92.77 -9.05 92.14 C-17.86 76.34 -27.5 53.23 -23.54 34.84 C-22.03 30.36 -19.58 26.69 -16.88 22.84 C-13.88 18.31 -11.21 13.57 -8.52 8.85 C-8.1 8.14 -7.69 7.43 -7.27 6.7 C-6.9 6.06 -6.54 5.42 -6.16 4.76 C-3.02 0 -3.02 0 0 0 Z " fill="#DC3127" transform="translate(238,384)"/>
<path d="M0 0 C7.7 3.22 11.18 12.95 15.09 19.89 C16.96 23.2 18.88 26.44 20.94 29.62 C26.96 39.48 23.73 51.56 21.25 62.17 C17.17 78.5 9.58 94.18 0 108 C-3.68 107.38 -5.92 105.8 -8.88 103.56 C-9.84 102.84 -10.81 102.13 -11.81 101.39 C-13.43 100.17 -15.05 98.96 -16.67 97.74 C-27.23 89.8 -37.73 83.25 -51 81 C-47.05 76.64 -42.51 73.37 -37.72 69.96 C-18.44 56.03 -5.01 35.48 -1 12 C-0.54 8 -0.21 4.02 0 0 Z " fill="#DC3127" transform="translate(401,384)"/>
<path d="M0 0 C3.65 3.42 7.27 7.23 9 12 C8.71 13.67 8.38 15.34 8 17 C7.12 16.98 6.24 16.97 5.33 16.95 C-14.92 16.64 -33.15 17.47 -52.73 23.23 C-55.98 24 -58.67 24.25 -62 24 C-64.54 22.35 -65.67 21.02 -66.61 18.13 C-67.33 14.34 -67.5 12.8 -65.36 9.41 C-53.51 -2.67 -14.57 -10.22 0 0 Z " fill="#0A0A08" transform="translate(407,170)"/>
<path d="M0 0 C3.58 2.15 5.68 3.51 8 7 C8.3 11.18 8.44 14.47 6 18 C0.22 20.89 -8.84 17.11 -14.75 15.56 C-32.25 11.23 -49.08 10.58 -67 12 C-68.17 8.54 -68.06 8.13 -66.38 4.56 C-52.44 -17.78 -20.24 -8.69 0 0 Z " fill="#0A0A08" transform="translate(291,175)"/>
<path d="M0 0 C2.49 0.07 2.49 0.07 5 1 C6.25 3.14 6.25 3.14 7.11 5.92 C7.44 6.92 7.76 7.92 8.09 8.95 C8.39 9.96 8.69 10.96 9 12 C9.14 12.42 9.14 12.42 9.82 14.54 C21.67 51.52 33.43 93.94 32 133 C29.03 133 26.06 133 23 133 C22.94 132.27 22.88 131.54 22.82 130.79 C19.66 93.24 11.98 57.13 1.55 20.93 C1.31 20.12 1.08 19.3 0.84 18.46 C0.4 16.93 -0.04 15.41 -0.5 13.88 C-1.67 9.83 -2.42 6.22 -2 2 C-1.34 1.34 -0.68 0.68 0 0 Z " fill="#0A0A08" transform="translate(92,507)"/>
<path d="M0 0 C1.88 0.25 1.88 0.25 4 1 C5.42 3.15 6.05 4.43 5.83 7.02 C5.64 7.75 5.44 8.48 5.23 9.23 C5.01 10.1 4.78 10.96 4.55 11.85 C4.42 12.33 4.42 12.33 3.75 14.75 C3.18 16.91 2.62 19.08 2.05 21.24 C1.73 22.46 1.41 23.68 1.07 24.93 C-8.35 60.56 -16.87 96.06 -19 133 C-21.97 133 -24.94 133 -28 133 C-28.67 93.14 -17.04 52.33 -6.19 14.25 C-5.91 13.26 -5.63 12.27 -5.35 11.26 C-5.08 10.35 -4.82 9.45 -4.54 8.52 C-4.32 7.73 -4.09 6.95 -3.86 6.15 C-2.9 3.75 -1.63 1.99 0 0 Z " fill="#0A0A08" transform="translate(544,507)"/>
<path d="M0 0 C1.94 0.81 1.94 0.81 4 2 C6.78 10.33 4.71 18.3 1 26 C-0.52 28.55 -1.75 29.97 -4 32 C-6.81 32.38 -6.81 32.38 -9 32 C-9.33 31.34 -9.66 30.68 -10 30 C-8.81 27.02 -7.51 24.1 -6.16 21.18 C-3.98 16.01 -3.58 11.23 -3.41 5.64 C-2.95 2.69 -2.31 1.8 0 0 Z " fill="#DC3529" transform="translate(453,233)"/>
<path d="M0 0 C1.94 0.31 1.94 0.31 4 1 C5.14 4.43 5.43 7.59 5.81 11.19 C6.33 15.67 6.96 19.63 9.19 23.62 C11 27 11 27 10.75 30 C10.5 30.66 10.25 31.32 10 32 C6.98 31.68 5.42 31.43 3.27 29.21 C-1.65 21.53 -4.21 14.24 -3 5 C-1.5 1.94 -1.5 1.94 0 0 Z " fill="#DC3228" transform="translate(184,233)"/>
<path d="M0 0 C3.33 0.55 5.3 1.49 8 3.5 C9.62 6.73 9.71 10.02 9 13.5 C5.76 16.74 3.95 17.48 -0.62 17.56 C-4.69 16.28 -5.94 15.2 -8 11.5 C-8.56 8.5 -8.56 8.5 -8 5.5 C-5.54 2.17 -4.13 0.69 0 0 Z " fill="#0A0A08" transform="translate(328,546.5)"/>
<path d="M0 0 C2.75 1.06 2.75 1.06 5 3 C6.55 6.65 7.24 8.92 6.38 12.81 C4.75 15.4 3.91 16.11 1 17 C-3.02 17.6 -4.5 17.35 -7.88 15 C-10.81 10.85 -10.72 9.01 -10 4 C-7.28 -0.18 -4.83 -0.69 0 0 Z " fill="#0A0A08" transform="translate(331,504)"/>
</svg>

After

Width:  |  Height:  |  Size: 12 KiB

View file

@ -1,22 +1,30 @@
#!/usr/bin/env python3
"""Regenerate every platform asset in the brand kit from the two canonical sources.
"""Regenerate every platform asset in the brand kit from the canonical sources.
Sources:
source/logo.png -- flat cartoon avatar (red polo), used for all profile pictures
source/hero.png -- photoreal desk scene (red polo), used for all banners/covers
source/logo.svg -- vector cartoon avatar (red polo); rendered crisply at each
target size. Falls back to source/logo.png if resvg is absent.
source/hero.png -- photoreal desk scene (red polo), used for all banners/covers.
Profile pictures + favicons come from the logo; banners/covers from the hero.
Requires Pillow, and (for crisp vector logo output) the `resvg` binary
(cargo install resvg). Regenerate the SVG itself with tools/trace_logo.py.
Run: python3 tools/build_assets.py
"""
from PIL import Image
import shutil
import subprocess
import tempfile
from pathlib import Path
from PIL import Image
ROOT = Path(__file__).resolve().parent.parent
SRC = ROOT / "source"
LOGO = Image.open(SRC / "logo.png").convert("RGB")
LOGO_SVG = SRC / "logo.svg"
LOGO_PNG = SRC / "logo.png"
HERO = Image.open(SRC / "hero.png").convert("RGB")
# Brand background (sampled from the logo's cream field) -- used to pad where needed.
CREAM = (242, 232, 213)
HAVE_RESVG = shutil.which("resvg") is not None and LOGO_SVG.exists()
def save(img, relpath):
@ -26,9 +34,17 @@ def save(img, relpath):
print(f" {relpath}: {img.size[0]}x{img.size[1]}")
def square(img, size):
"""Square profile asset from the (already square) logo."""
return img.resize((size, size), Image.LANCZOS)
def logo_at(size):
"""Render the vector logo crisply at size x size (raster fallback)."""
if HAVE_RESVG:
with tempfile.NamedTemporaryFile(suffix=".png") as tf:
subprocess.run(
["resvg", "--width", str(size), "--height", str(size),
str(LOGO_SVG), tf.name],
check=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL,
)
return Image.open(tf.name).convert("RGB")
return Image.open(LOGO_PNG).convert("RGB").resize((size, size), Image.LANCZOS)
def cover(img, tw, th, fy=0.45, fx=0.5):
@ -89,24 +105,28 @@ FAVICON_SIZES = {
def main():
print(f"logo source: {'vector (resvg)' if HAVE_RESVG else 'raster fallback'}")
print("avatars:")
for path, size in AVATARS.items():
save(square(LOGO, size), path)
save(logo_at(size), path)
print("logo masters:")
for path, size in LOGO_SIZES.items():
save(square(LOGO, size), path)
save(LOGO, "logo/logo-original.png")
save(logo_at(size), path)
if LOGO_SVG.exists():
shutil.copy(LOGO_SVG, ROOT / "logo/logo.svg")
print(" logo/logo.svg: vector")
save(Image.open(LOGO_PNG).convert("RGB"), "logo/logo-original.png")
print("favicons:")
for path, size in FAVICON_SIZES.items():
save(square(LOGO, size), path)
# multi-resolution .ico
save(logo_at(size), path)
ico = ROOT / "favicon/favicon.ico"
LOGO.resize((256, 256), Image.LANCZOS).save(
logo_at(256).save(
ico, sizes=[(16, 16), (32, 32), (48, 48), (64, 64), (128, 128), (256, 256)]
)
print(f" favicon/favicon.ico: multi-res")
print(" favicon/favicon.ico: multi-res")
print("banners:")
for path, (w, h, fy) in BANNERS.items():

51
tools/trace_logo.py Normal file
View file

@ -0,0 +1,51 @@
#!/usr/bin/env python3
"""Vectorize the raster logo into source/logo.svg (true infinite-scale vector).
The logo is flat cartoon line-art (~4 colors), so we:
1. Snap every pixel to the exact canonical brand palette (no color drift,
and anti-aliasing fringes collapse into clean regions), then
2. Trace the flat image to colored SVG paths with vtracer.
Requires the `vtracer` binary (cargo install vtracer).
Run: python3 tools/trace_logo.py
"""
import subprocess
import tempfile
from pathlib import Path
from PIL import Image
ROOT = Path(__file__).resolve().parent.parent
SRC = ROOT / "source"
# Exact canonical brand palette — see README.
PALETTE = [
0xEF, 0xDE, 0xCC, # canvas cream (background)
0xDC, 0x31, 0x27, # polo red
0xF5, 0xB0, 0x79, # skin tan
0x0A, 0x0A, 0x08, # ink (outlines + hair)
]
def main():
im = Image.open(SRC / "logo.png").convert("RGB")
pal = Image.new("P", (1, 1))
# Pad to 256 entries by repeating ink, so stray pixels never snap to a
# color outside the palette (e.g. pure black).
pal.putpalette(PALETTE + PALETTE[9:12] * (256 - 4))
flat = im.quantize(palette=pal, dither=Image.NONE).convert("RGB")
with tempfile.NamedTemporaryFile(suffix=".png", delete=False) as tf:
flat.save(tf.name)
subprocess.run(
["vtracer", "--input", tf.name, "--output", str(SRC / "logo.svg"),
"--colormode", "color", "--mode", "spline",
"--filter_speckle", "8", "--color_precision", "8",
"--corner_threshold", "60", "--segment_length", "4",
"--splice_threshold", "45"],
check=True,
)
print("wrote", SRC / "logo.svg")
if __name__ == "__main__":
main()