vole
Clone
Read only, no credentials:
https://rodent.software/git/vole.git
Write over SSH with a registered key:
git clone ssh://git@0.0.0.0:2222/vole.git
A free and open-source forge that lives in your Git repo.
Replace the vole faces with an abstract mark
ca098f628ce251501444a286932ff388d52a543c · Keenan Nemetz · 7d ago · parent 753cd703
Replace the vole faces with an abstract mark The faces were too literal for the rest of the interface. A name now gets one curled stroke instead: a burrow turned in on itself, a fern frond, a shell, whichever the reader sees. It never says which. The point is what it does not do. It is one cream line on one of seven earthy grounds, with the same round caps and stroke language for everyone, so it is quiet next to a name and still legible at 17px. A few shapes were drawn and dropped on the way: a crescent is elegant but barely changes between names, arches read as rainbows or smiles, and rings, mosaics and tally marks read as icons. A curl carries enough variation (how far it winds, tightness, direction, rotation, thickness, position) to tell people apart without looking like a diagram. The derivation is unchanged: SHA-256 over the name, nothing stored, no upload, no avatar service. The path is marked `fill="none"` in the markup; the sheet owns the stroke colour, so the palette stays a theme decision.
server/web/static/vole.css +8−19
| @@ -1160,12 +1160,12 @@ pre code { background: none; border: 0; padding: 0; font-size: inherit; } | |||
| 1160 | 1160 | .contributors .cname { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: calc(13.75px * var(--font-scale)); } | |
| 1161 | 1161 | .contributors .muted { font-size: calc(12.65px * var(--font-scale)); } | |
| 1162 | 1162 | ||
| 1163 | /* A name's portrait is a vole drawn from the name (see server/web/avatar.go). | ||
| 1164 | The sheet owns the palette and the SVG owns the geometry, so the face follows | ||
| 1165 | the theme: the seven grounds are the Everforest accents pulled toward the page, | ||
| 1166 | and the fur and ink are the palette's own cream and dark ground. The tones are | ||
| 1167 | the same in every Everforest variant on purpose; a person who is moss green on | ||
| 1168 | one theme must not be clay on another. */ | ||
| 1163 | /* A name's mark is a curled stroke derived from the name (see | ||
| 1164 | server/web/avatar.go). The sheet owns the palette and the SVG owns the | ||
| 1165 | geometry: seven Everforest grounds pulled toward the page, one cream line, and | ||
| 1166 | the same stroke language for everyone. The tones are identical in every | ||
| 1167 | Everforest variant on purpose; a person who is moss green on one theme must not | ||
| 1168 | be clay on another. */ | ||
| 1169 | 1169 | .avatar { | |
| 1170 | 1170 | display: inline-grid; | |
| 1171 | 1171 | place-items: center; | |
| @@ -1175,9 +1175,7 @@ pre code { background: none; border: 0; padding: 0; font-size: inherit; } | |||
| 1175 | 1175 | border-radius: 50%; | |
| 1176 | 1176 | overflow: hidden; | |
| 1177 | 1177 | background: var(--av-bg, #6b7561); | |
| 1178 | --av-fur: #f0e6d2; | ||
| 1179 | --av-ink: #2d353b; | ||
| 1180 | --av-mark: #d8c5a3; | ||
| 1178 | --av-mark: #f0e6d2; | ||
| 1181 | 1179 | } | |
| 1182 | 1180 | .avatar.c1 { --av-bg: #6f8a5f; } | |
| 1183 | 1181 | .avatar.c2 { --av-bg: #a2734f; } | |
| @@ -1187,16 +1185,7 @@ pre code { background: none; border: 0; padding: 0; font-size: inherit; } | |||
| 1187 | 1185 | .avatar.c6 { --av-bg: #94843f; } | |
| 1188 | 1186 | .avatar.c7 { --av-bg: #7a6b5f; } | |
| 1189 | 1187 | .avatar svg { display: block; width: 100%; height: 100%; } | |
| 1190 | .avatar .fur-2 { --av-fur: #e6d5b3; } | ||
| 1191 | .avatar .fur-3 { --av-fur: #f7f0de; } | ||
| 1192 | .avatar .av-fur { fill: var(--av-fur); } | ||
| 1193 | .avatar .av-head { fill: var(--av-fur); } | ||
| 1194 | .avatar .av-ink { fill: var(--av-ink); } | ||
| 1195 | .avatar .av-mark { fill: var(--av-mark); } | ||
| 1196 | .avatar .av-ring { fill: none; stroke: var(--av-ink); stroke-width: 1.1; } | ||
| 1197 | .avatar .av-nose { fill: var(--av-ink); stroke: var(--av-ink); stroke-width: 0.7; stroke-linejoin: round; } | ||
| 1198 | .avatar .av-line { fill: none; stroke: var(--av-ink); stroke-width: 0.95; stroke-linecap: round; stroke-linejoin: round; } | ||
| 1199 | .avatar .av-whisker { fill: none; stroke: var(--av-ink); stroke-width: 0.75; stroke-linecap: round; opacity: 0.8; } | ||
| 1188 | .avatar .av-mark { fill: none; stroke: var(--av-mark); stroke-linecap: round; stroke-linejoin: round; } | ||
| 1200 | 1189 | ||
| 1201 | 1190 | .lang { display: grid; grid-template-columns: 1fr auto; gap: 2px 8px; margin-bottom: 8px; font-size: calc(13.2px * var(--font-scale)); } | |
| 1202 | 1191 | .lang .muted { font-size: calc(12.65px * var(--font-scale)); } | |