Add branding: Focus mark, wordmark, banner, social preview

- assets/branding/: icon (SVG + 512px PNG for Gitea avatar), adaptive-icon
  foreground/background layers, path-only wordmark for dark/light grounds,
  1200x300 README banner, 1280x640 social preview (SVG + PNG)
- README: banner hero
- build-status: branding decision log (includes the pending website section
  from the parallel web/ session, interleaved in the same file)

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
mrambossek
2026-07-30 10:52:12 +02:00
co-authored by Claude Opus 5
parent 6ddf013dfe
commit d3e35ecead
11 changed files with 193 additions and 0 deletions
+4
View File
@@ -1,3 +1,7 @@
<p align="center">
<img src="assets/branding/banner.svg" alt="echolot — measure, don't guess" width="100%">
</p>
# Echolot # Echolot
Free software for detecting and debugging **local network issues** from an Android phone — Free software for detecting and debugging **local network issues** from an Android phone —
+39
View File
@@ -0,0 +1,39 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 300">
<rect width="1200" height="300" fill="#071522"/>
<!-- graduated rule -->
<path d="M 0 250 H 1200" fill="none" stroke="#0F2E3D" stroke-width="1.5"/>
<path d="M 30 255 H 1180" fill="none" stroke="#0F2E3D" stroke-width="9" stroke-dasharray="1.5 58.5"/>
<!-- glyph: focus -->
<g transform="translate(60,15) scale(2.8)">
<g fill="#1E4A5C">
<circle cx="24" cy="24" r="2.6"/><circle cx="48" cy="24" r="2.6"/><circle cx="72" cy="24" r="2.6"/>
<circle cx="24" cy="48" r="2.6"/><circle cx="72" cy="48" r="2.6"/>
<circle cx="24" cy="72" r="2.6"/><circle cx="48" cy="72" r="2.6"/><circle cx="72" cy="72" r="2.6"/>
</g>
<circle cx="48" cy="48" r="8" fill="none" stroke="#FFB454" stroke-opacity="0.3" stroke-width="2"/>
<circle cx="48" cy="48" r="4.5" fill="#FFB454"/>
<g fill="none" stroke="#35E0C4" stroke-width="3.5" stroke-linecap="round" stroke-linejoin="round">
<path d="M 33 41 V 33 H 41"/>
<path d="M 55 33 H 63 V 41"/>
<path d="M 63 55 V 63 H 55"/>
<path d="M 41 63 H 33 V 55"/>
</g>
</g>
<!-- wordmark -->
<g transform="translate(350,182)">
<g fill="none" stroke="#E8F4F2" stroke-width="11" stroke-linecap="round">
<path d="M 0 -24 H 48"/>
<path d="M 48 -24 A 24 24 0 1 0 40.97 -7.03"/>
<path d="M 110.97 -40.97 A 24 24 0 1 0 110.97 -7.03"/>
<path d="M 140 -76 V 0"/>
<path d="M 140 -24 A 24 24 0 0 1 188 -24 L 188 0"/>
<circle cx="234" cy="-24" r="24"/>
<path d="M 280 -76 V 0"/>
<circle cx="326" cy="-24" r="24" stroke="#35E0C4"/>
<path d="M 372 -48 H 402"/>
<path d="M 387 -68 V 0"/>
</g>
<circle cx="326" cy="-24" r="6.5" fill="#FFB454"/>
</g>
<text x="352" y="228" font-family="ui-monospace,'Cascadia Code','SF Mono',Menlo,Consolas,monospace" font-size="19" letter-spacing="3.5" fill="#5E8B96">measure, don't guess</text>
</svg>

After

Width:  |  Height:  |  Size: 1.9 KiB

@@ -0,0 +1,10 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 108 108">
<!-- Android adaptive-icon background layer: full-bleed, launcher applies the mask -->
<defs>
<linearGradient id="tile" x1="0" y1="0" x2="0" y2="1">
<stop offset="0" stop-color="#0E2433"/>
<stop offset="1" stop-color="#071522"/>
</linearGradient>
</defs>
<rect width="108" height="108" fill="url(#tile)"/>
</svg>

After

Width:  |  Height:  |  Size: 404 B

@@ -0,0 +1,18 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 108 108">
<!-- Android adaptive-icon foreground layer: 108dp canvas, art kept inside the 66dp safe circle -->
<g transform="translate(54,54) scale(0.8) translate(-48,-48)">
<g fill="#1E4A5C">
<circle cx="24" cy="24" r="2.6"/><circle cx="48" cy="24" r="2.6"/><circle cx="72" cy="24" r="2.6"/>
<circle cx="24" cy="48" r="2.6"/> <circle cx="72" cy="48" r="2.6"/>
<circle cx="24" cy="72" r="2.6"/><circle cx="48" cy="72" r="2.6"/><circle cx="72" cy="72" r="2.6"/>
</g>
<circle cx="48" cy="48" r="8" fill="none" stroke="#FFB454" stroke-opacity="0.3" stroke-width="2"/>
<circle cx="48" cy="48" r="4.5" fill="#FFB454"/>
<g fill="none" stroke="#35E0C4" stroke-width="3.5" stroke-linecap="round" stroke-linejoin="round">
<path d="M 33 41 V 33 H 41"/>
<path d="M 55 33 H 63 V 41"/>
<path d="M 63 55 V 63 H 55"/>
<path d="M 41 63 H 33 V 55"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1005 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

+24
View File
@@ -0,0 +1,24 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 96 96">
<defs>
<linearGradient id="tile" x1="0" y1="0" x2="0" y2="1">
<stop offset="0" stop-color="#0E2433"/>
<stop offset="1" stop-color="#071522"/>
</linearGradient>
</defs>
<rect width="96" height="96" rx="21" fill="url(#tile)"/>
<!-- the network, at rest -->
<g fill="#1E4A5C">
<circle cx="24" cy="24" r="2.6"/><circle cx="48" cy="24" r="2.6"/><circle cx="72" cy="24" r="2.6"/>
<circle cx="24" cy="48" r="2.6"/> <circle cx="72" cy="48" r="2.6"/>
<circle cx="24" cy="72" r="2.6"/><circle cx="48" cy="72" r="2.6"/><circle cx="72" cy="72" r="2.6"/>
</g>
<!-- one node, under examination -->
<circle cx="48" cy="48" r="8" fill="none" stroke="#FFB454" stroke-opacity="0.3" stroke-width="2"/>
<circle cx="48" cy="48" r="4.5" fill="#FFB454"/>
<g fill="none" stroke="#35E0C4" stroke-width="3.5" stroke-linecap="round" stroke-linejoin="round">
<path d="M 33 41 V 33 H 41"/>
<path d="M 55 33 H 63 V 41"/>
<path d="M 63 55 V 63 H 55"/>
<path d="M 41 63 H 33 V 55"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

+39
View File
@@ -0,0 +1,39 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1280 640">
<rect width="1280" height="640" fill="#071522"/>
<!-- graduated rule -->
<path d="M 0 560 H 1280" fill="none" stroke="#0F2E3D" stroke-width="1.5"/>
<path d="M 40 565 H 1240" fill="none" stroke="#0F2E3D" stroke-width="9" stroke-dasharray="1.5 58.5"/>
<!-- glyph: focus -->
<g transform="translate(481.6,30) scale(3.3)">
<g fill="#1E4A5C">
<circle cx="24" cy="24" r="2.6"/><circle cx="48" cy="24" r="2.6"/><circle cx="72" cy="24" r="2.6"/>
<circle cx="24" cy="48" r="2.6"/><circle cx="72" cy="48" r="2.6"/>
<circle cx="24" cy="72" r="2.6"/><circle cx="48" cy="72" r="2.6"/><circle cx="72" cy="72" r="2.6"/>
</g>
<circle cx="48" cy="48" r="8" fill="none" stroke="#FFB454" stroke-opacity="0.3" stroke-width="2"/>
<circle cx="48" cy="48" r="4.5" fill="#FFB454"/>
<g fill="none" stroke="#35E0C4" stroke-width="3.5" stroke-linecap="round" stroke-linejoin="round">
<path d="M 33 41 V 33 H 41"/>
<path d="M 55 33 H 63 V 41"/>
<path d="M 63 55 V 63 H 55"/>
<path d="M 41 63 H 33 V 55"/>
</g>
</g>
<!-- wordmark, centered -->
<g transform="translate(356,442) scale(1.4)">
<g fill="none" stroke="#E8F4F2" stroke-width="11" stroke-linecap="round">
<path d="M 0 -24 H 48"/>
<path d="M 48 -24 A 24 24 0 1 0 40.97 -7.03"/>
<path d="M 110.97 -40.97 A 24 24 0 1 0 110.97 -7.03"/>
<path d="M 140 -76 V 0"/>
<path d="M 140 -24 A 24 24 0 0 1 188 -24 L 188 0"/>
<circle cx="234" cy="-24" r="24"/>
<path d="M 280 -76 V 0"/>
<circle cx="326" cy="-24" r="24" stroke="#35E0C4"/>
<path d="M 372 -48 H 402"/>
<path d="M 387 -68 V 0"/>
</g>
<circle cx="326" cy="-24" r="6.5" fill="#FFB454"/>
</g>
<text x="640" y="505" text-anchor="middle" font-family="ui-monospace,'Cascadia Code','SF Mono',Menlo,Consolas,monospace" font-size="22" letter-spacing="4" fill="#5E8B96">measure, don't guess</text>
</svg>

After

Width:  |  Height:  |  Size: 2.0 KiB

+17
View File
@@ -0,0 +1,17 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="-10 -92 433 104">
<!-- "echolot" — hand-drawn monoline letterforms (no font dependency). For dark grounds. -->
<g fill="none" stroke="#E8F4F2" stroke-width="11" stroke-linecap="round">
<path d="M 0 -24 H 48"/>
<path d="M 48 -24 A 24 24 0 1 0 40.97 -7.03"/>
<path d="M 110.97 -40.97 A 24 24 0 1 0 110.97 -7.03"/>
<path d="M 140 -76 V 0"/>
<path d="M 140 -24 A 24 24 0 0 1 188 -24 L 188 0"/>
<circle cx="234" cy="-24" r="24"/>
<path d="M 280 -76 V 0"/>
<circle cx="326" cy="-24" r="24" stroke="#35E0C4"/>
<path d="M 372 -48 H 402"/>
<path d="M 387 -68 V 0"/>
</g>
<!-- the finding -->
<circle cx="326" cy="-24" r="6.5" fill="#FFB454"/>
</svg>

After

Width:  |  Height:  |  Size: 742 B

+17
View File
@@ -0,0 +1,17 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="-10 -92 433 104">
<!-- "echolot" — hand-drawn monoline letterforms (no font dependency). For light grounds. -->
<g fill="none" stroke="#1B3540" stroke-width="11" stroke-linecap="round">
<path d="M 0 -24 H 48"/>
<path d="M 48 -24 A 24 24 0 1 0 40.97 -7.03"/>
<path d="M 110.97 -40.97 A 24 24 0 1 0 110.97 -7.03"/>
<path d="M 140 -76 V 0"/>
<path d="M 140 -24 A 24 24 0 0 1 188 -24 L 188 0"/>
<circle cx="234" cy="-24" r="24"/>
<path d="M 280 -76 V 0"/>
<circle cx="326" cy="-24" r="24" stroke="#0E9384"/>
<path d="M 372 -48 H 402"/>
<path d="M 387 -68 V 0"/>
</g>
<!-- the finding -->
<circle cx="326" cy="-24" r="6.5" fill="#E08A1E"/>
</svg>

After

Width:  |  Height:  |  Size: 743 B

+25
View File
@@ -33,6 +33,31 @@ Could NOT be compiled in the cloud sandbox: dl.google.com (Google Maven) and ser
are proxy-blocked, and no device is reachable for on-device runs. Build + iterate locally are proxy-blocked, and no device is reachable for on-device runs. Build + iterate locally
(Android Studio / Claude Code). Wrapper is pinned to Gradle 8.14.3. (Android Studio / Claude Code). Wrapper is pinned to Gradle 8.14.3.
## Website — `web/` (2026-07-30)
Single-page site for echo-lot.app on Cloudflare Workers: static `public/` from the edge, a small
Worker for the stable short URLs (`/apk`, `/apk.sha256`, `/fdroid`, `/source`) and `/api/latest`.
Version info is resolved from the Gitea releases API at request time (edge-cached 5 min), so
tagging a release is the only publish step — the homepage shows the latest version/date/size via
progressive-enhancement JS and falls back to pre-release copy otherwise. Auto light/dark via
`prefers-color-scheme`: dark = sonar display, light = chart-recorder printout, same amber-accent
token system. Deploy: `npx wrangler deploy` from `web/`, or CI via
`.gitea/workflows/deploy-site.yml` (needs `CLOUDFLARE_API_TOKEN` + `CLOUDFLARE_ACCOUNT_ID`
secrets); full story in `web/README.md`. Open: favicon/wordmark are placeholders until the
branding assets land (in progress in a parallel session).
## Branding — `assets/branding/` (2026-07-30)
Identity chosen: the **Focus** mark — a quiet lattice of nodes with exactly one under examination
(amber) inside teal viewfinder brackets. Tone is surgical measurement, not scanning (sonar-sweep
visuals and the "sound out your network" tagline were explicitly rejected); tagline is
**"measure, don't guess"**. Palette: abyss `#071522`, tile `#0E2433`, instrument teal `#35E0C4`,
finding amber `#FFB454`, foam `#E8F4F2` — teal is always the instrument, the single amber point is
the finding. The wordmark is hand-drawn monoline SVG paths (zero font dependency); the second "o"
is the signature teal ring + amber ping. Assets: `icon.svg` (+ `icon.png` 512² — Gitea avatars reject SVG), `icon-adaptive-{foreground,background}.svg`
(108dp adaptive-icon layers, art inside the 66dp safe circle), `wordmark-on-{dark,light}.svg`,
`banner.svg` (1200×300, wired into the repo README), `social-preview.svg`/`.png` (1280×640, for the
Gitea/GitHub social-preview slot). The website's placeholder favicon/wordmark can now be replaced
from these.
## Next steps ## Next steps
1. Build locally, run on several physical devices (varied Android versions/vendors), collect the 1. Build locally, run on several physical devices (varied Android versions/vendors), collect the
JSON reports — especially the real per-device Shizuku dump formats. JSON reports — especially the real per-device Shizuku dump formats.