# tak — logo
`tak` is a tachometer for code, so the mark is a tach: a 240° sweep, an amber
swept arc, a red band where CI fails, and a needle that does not wobble.
Every SVG is generated by [`logo.py`](logo.py) — pure geometry, no dependencies,
no editor round-trip. Change a number, re-run, commit the diff:
```bash
python3 assets/logo.py
```
## Files
| `tak-wordmark.svg` | **primary.** The bowl of the `a` is the dial — that's the whole joke. |
| `tak-mark.svg` | square mark, for anything ≥48px |
| `tak-mark-small.svg` | same mark, ticks dropped and weights fattened, for ≤32px |
| `tak-lockup.svg` | mark + wordmark, for wide headers. The `a` drops its dial here — two gauges side by side just read as a repeat. |
| `tak-icon-tile.svg` | app icon / avatar, rounded ink field with the dial reversed out |
| `tak-icon-tile-small.svg` | the tile at ≤32px |
| `tak-icon-square*.svg` | favicon sources — same field, square corners. iOS and Android apply their own mask, so pre-rounded corners come out double-rounded. |
| `tak-wordmark-plain.svg` | wordmark with an ordinary `a`, when the dial would be too small to read |
| `tak-lockup-light.svg` / `-dark.svg` | fixed-palette lockups, for `<picture>` where the host picks the file rather than the SVG picking its own colours |
## Theming
Colours are emitted as presentation attributes carrying the **light** palette,
with the dark palette layered on top in a `<style>` block:
```svg
<style>@media (prefers-color-scheme:dark){.ink{stroke:#F2F5F9} ...}</style>
<path … class="ink" stroke="#12161C" …/>
```
Presentation attributes lose to any CSS rule, so the override still wins. The
point of the redundancy is the failure mode: if a host strips the `<style>`
— GitHub has historically sanitised SVG — the file falls back to the light
palette instead of rendering blank, which is what happens when the only colour
source is a stylesheet that got removed.
The icon tiles skip all of this. They carry a fixed dark palette and no CSS at
all, so a self-contained dark tile reads correctly on a light or a dark page.
That is what makes `tak-icon-tile.svg` the safe thing to drop into a README,
and it is what the README uses.
## Palette
| ink (needle, letterforms) | `#12161C` | `#F2F5F9` |
| track (unswept dial) | `#CBD3DE` | `#333D4B` |
| ticks | `#9AA5B5` | `#6C7788` |
| swept arc | `#F0A02A` | same |
| redline | `#E5484D` | same |
Amber and red are fixed — they carry meaning, not theme.
## Three weights of the same dial
The dial is drawn at three weights, because one set of proportions does not
survive the whole size range:
| default | 13 | yes | ≥64px |
| `-small` | 18 | no | 32–48px — the ticks turn to mush below ~48 |
| `-tiny` | 30 | no | 16px — an 18px ring lands under one device pixel and antialiases to brown mud |
## Favicons
`docs/public/` holds the generated favicon set, in the same layout as mise, hk,
aube and fnox, so a VitePress site can pick it up later with no changes:
```
favicon.svg favicon.ico (16+32+48) favicon-16x16.png favicon-32x32.png
apple-touch-icon.png (180) android-chrome-192x192.png android-chrome-512x512.png
site.webmanifest
```
Regenerate after changing the mark. This step needs two libraries, so it is not
part of the normal edit loop:
```bash
pip install resvg-py pillow && python3 assets/favicons.py
```
Each `.ico` frame and each PNG is rendered at its own size from the weight that
suits it, rather than downscaled from one bitmap.
## Clear space and minimum size
Keep clear space equal to the dial's hub diameter on all sides. Below 32px use
the `-small` variants; below 16px use nothing, use text.
## Previewing a change
There's no rasteriser in the repo. To eyeball an edit:
```bash
pip install resvg-py && python3 -c "import resvg_py,pathlib; pathlib.Path('/tmp/tak.png').write_bytes(bytes(resvg_py.svg_to_bytes(svg_path='assets/tak-lockup.svg', zoom=3, background='#fff')))"
```
Note that resvg does not evaluate `@media` queries, so that renders the light
theme only. To check dark, render `tak-lockup-dark.svg`, which has the dark
palette baked in.