Skip to content

Commit a113f9f

Browse files
committed
fix: make About family icons ink-only and center the footer
HQ and Gateway buttons now use currentColor marks like the platform row. License and Version share a baseline. The footer is just the centered copyright line.
1 parent f09798e commit a113f9f

7 files changed

Lines changed: 59 additions & 60 deletions

File tree

app/fragments/about.py

Lines changed: 12 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -9,24 +9,21 @@
99

1010
# Official marks from VocaHQ/.github. Do not redraw.
1111
# Talk-to-us: brand/vocahq/social.
12-
# Family platforms: brand/promo/cards/platform.
12+
# Family row: brand/promo/cards/platform, vocahq/voca-mark, vocagateway-1u chassis.
1313
# Host hero: brand/vocagateway/vocagateway-tower.svg.
14-
# Small family button: brand/vocagateway/vocagateway-1u.svg (holds at 16px).
1514
_BRAND_DIR = Path(__file__).resolve().parent.parent / "webui" / "brand"
1615
_MARK_TOWER = "/assets/brand/vocagateway/vocagateway-tower.svg"
17-
_MARK_1U = "/assets/brand/vocagateway/vocagateway-1u.svg"
18-
_MARK_HQ = "/assets/voca-logo.svg"
1916
_ISSUES_URL = "https://github.com/VocaHQ/vocagateway/issues"
2017
_LICENSE_URL = "https://github.com/VocaHQ/vocagateway/blob/main/LICENSE"
2118

22-
# icon, href, label. Platform names are files in webui/brand/platform/.
23-
_FAMILY_LINKS: tuple[tuple[str, str, str], ...] = (
24-
("hq", "https://vocahq.com", "VocaHQ"),
25-
("linux", "https://vocalinux.com", "VocaLinux"),
26-
("apple", "https://vocamac.com", "VocaMac"),
27-
("windows", "https://vocawin.com", "VocaWin"),
28-
("android", "https://vocaphone.vocahq.com", "VocaPhone"),
29-
("gateway", "https://vocagateway.vocahq.com", "VocaGateway"),
19+
# folder, file stem, href, label.
20+
_FAMILY_LINKS: tuple[tuple[str, str, str, str], ...] = (
21+
("vocahq", "voca-mark", "https://vocahq.com", "VocaHQ"),
22+
("platform", "linux", "https://vocalinux.com", "VocaLinux"),
23+
("platform", "apple", "https://vocamac.com", "VocaMac"),
24+
("platform", "windows", "https://vocawin.com", "VocaWin"),
25+
("platform", "android", "https://vocaphone.vocahq.com", "VocaPhone"),
26+
("vocagateway", "vocagateway-1u-mark", "https://vocagateway.vocahq.com", "VocaGateway"),
3027
)
3128

3229
_CONTACT_LINKS: tuple[tuple[str, str, str], ...] = (
@@ -46,28 +43,13 @@ def _link_target(url: str) -> str:
4643
return ' target="_blank" rel="noopener noreferrer"'
4744

4845

49-
def _mark_img(src: str) -> str:
50-
return (
51-
f'<span class="about-icon">'
52-
f'<img src="{escape(src, quote=True)}" width="16" height="16" alt="" />'
53-
f"</span>"
54-
)
55-
56-
57-
def _family_icon(name: str) -> str:
58-
if name == "hq":
59-
return _mark_img(_MARK_HQ)
60-
if name == "gateway":
61-
return _mark_img(_MARK_1U)
62-
return f'<span class="about-icon">{_icon(name, folder="platform")}</span>'
63-
64-
6546
def about_fragment(version: str, commit: CommitStatus | None = None) -> str:
6647
family = "".join(
6748
f'<a class="ghost" href="{escape(url, quote=True)}"'
6849
f"{_link_target(url)}>"
69-
f"{_family_icon(name)}{escape(label)}</a>"
70-
for name, url, label in _FAMILY_LINKS
50+
f'<span class="about-icon">{_icon(stem, folder=folder)}</span>'
51+
f"{escape(label)}</a>"
52+
for folder, stem, url, label in _FAMILY_LINKS
7153
)
7254
contacts = "".join(
7355
f'<a class="ghost" href="{escape(url, quote=True)}"'
Lines changed: 4 additions & 0 deletions
Loading
Lines changed: 9 additions & 0 deletions
Loading

app/webui/index.html

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -103,12 +103,6 @@ <h1>VocaGateway</h1>
103103

104104
<footer class="site-footer">
105105
<p class="footer-copy">&copy; 2026 <a href="https://github.com/VocaHQ" target="_blank" rel="noopener noreferrer">VocaHQ</a></p>
106-
<nav class="footer-links" aria-label="Project repositories">
107-
<a href="https://github.com/VocaHQ/vocagateway" target="_blank" rel="noopener noreferrer">VocaGateway</a>
108-
<a href="https://github.com/VocaHQ/vocaphone" target="_blank" rel="noopener noreferrer">VocaPhone</a>
109-
<a href="https://github.com/VocaHQ/vocalinux" target="_blank" rel="noopener noreferrer">VocaLinux</a>
110-
<a href="https://github.com/VocaHQ/vocamac" target="_blank" rel="noopener noreferrer">VocaMac</a>
111-
</nav>
112106
</footer>
113107

114108
<div id="toast" class="toast hidden" role="status" aria-live="polite"></div>

app/webui/styles.css

Lines changed: 15 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -461,15 +461,14 @@ main {
461461
.site-footer {
462462
flex: 0 0 auto;
463463
display: flex;
464-
flex-wrap: wrap;
465464
align-items: center;
466-
justify-content: space-between;
467-
gap: 10px 20px;
465+
justify-content: center;
468466
margin-top: auto;
469467
padding: 18px var(--gutter) 22px;
470468
border-top: 1px solid var(--line-soft);
471469
color: var(--faint);
472470
font-size: 0.84rem;
471+
text-align: center;
473472
}
474473
.footer-copy {
475474
margin: 0;
@@ -480,18 +479,6 @@ main {
480479
text-decoration: none;
481480
}
482481
.footer-copy a:hover { color: var(--accent); }
483-
.footer-links {
484-
display: flex;
485-
flex-wrap: wrap;
486-
align-items: center;
487-
gap: 6px 14px;
488-
}
489-
.footer-links a {
490-
color: var(--muted);
491-
text-decoration: none;
492-
font-weight: 500;
493-
}
494-
.footer-links a:hover { color: var(--accent); }
495482

496483
/* ------------------------------------------------------------------ sections */
497484

@@ -2494,8 +2481,7 @@ button.danger.ghost:hover {
24942481
.htmx-request .actions button, .actions button.htmx-request { opacity: 0.45; pointer-events: none; }
24952482

24962483
/* About reuses Overview / Settings chrome. Official tower mark is 52px in the
2497-
system-card hero. Family and talk-to-us icons stay 16px. Platform glyphs
2498-
inherit currentColor; HQ and Gateway lockups keep approved fills. */
2484+
system-card hero. Family and talk-to-us icons stay 16px currentColor. */
24992485
#about-host .sys-hero {
25002486
display: flex;
25012487
align-items: center;
@@ -2558,8 +2544,18 @@ button.danger.ghost:hover {
25582544
width: 16px;
25592545
height: 16px;
25602546
}
2561-
.about-icon img {
2562-
border-radius: 3px;
2547+
#about-this-build .facts {
2548+
align-items: baseline;
2549+
column-gap: 12px;
2550+
row-gap: 6px;
2551+
}
2552+
#about-this-build .facts dt,
2553+
#about-this-build .facts dd {
2554+
font-size: 0.92rem;
2555+
line-height: 1.45;
2556+
}
2557+
#about-this-build .facts dd a {
2558+
text-underline-offset: 0.18em;
25632559
}
25642560

25652561
/* ---------------------------------------------------------------- responsive */
@@ -2576,9 +2572,6 @@ button.danger.ghost:hover {
25762572
:root { --gutter: 16px; }
25772573
main { padding: 20px 16px 40px; }
25782574
.site-footer {
2579-
flex-direction: column;
2580-
align-items: flex-start;
2581-
gap: 8px;
25822575
padding-block: 16px 20px;
25832576
}
25842577
.brand .muted { display: none; }

tests/test_about.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,19 @@ def test_platform_marks_are_the_official_files() -> None:
6969
assert "M18.4395 5.5586" in android
7070

7171

72+
def test_family_marks_are_current_color() -> None:
73+
hq = (BRAND / "vocahq" / "voca-mark.svg").read_text(encoding="utf-8")
74+
gateway = (BRAND / "vocagateway" / "vocagateway-1u-mark.svg").read_text(encoding="utf-8")
75+
for svg in (hq, gateway):
76+
assert 'fill="currentColor"' in svg
77+
assert "#0F6B57" not in svg
78+
assert "#0B1A15" not in svg
79+
assert "#F2F6F2" not in svg
80+
assert "M 164 127 A 65 65" in hq
81+
assert 'viewBox="96 372 832 280"' in gateway
82+
assert 'width="832" height="280"' in gateway
83+
84+
7285
def test_official_1u_mark_is_vendored() -> None:
7386
mark = (
7487
Path(__file__).resolve().parents[1]

tests/test_admin.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -772,7 +772,6 @@ def _assert_about_surface(html: str) -> None:
772772
assert "Early" not in html
773773
assert "The host you run" in html
774774
assert "/assets/brand/vocagateway/vocagateway-tower.svg" in html
775-
assert "/assets/brand/vocagateway/vocagateway-1u.svg" in html
776775
assert 'id="about-this-build"' in html
777776
assert 'id="about-family"' in html
778777
assert 'id="about-talk"' in html
@@ -807,7 +806,9 @@ def _assert_about_surface(html: str) -> None:
807806
assert "VocaWin</a>" in html
808807
assert "VocaPhone</a>" in html
809808
assert "VocaGateway</a>" in html
810-
assert "/assets/voca-logo.svg" in html
809+
# Family row is currentColor: HQ mic, 1U chassis, platform marks.
810+
assert "M 164 127 A 65 65" in html
811+
assert 'width="832" height="280"' in html
811812
# Official platform marks from VocaHQ/.github brand/promo/cards/platform.
812813
assert "M12.504 0c-.155" in html
813814
assert "M12.152 6.896" in html
@@ -843,6 +844,9 @@ async def test_webui_shell_is_public(admin_client: httpx.AsyncClient) -> None:
843844
# Fifth tab, after the existing four. Hash routing uses data-tab="about".
844845
tabs = [part.split('"', 1)[0] for part in response.text.split('data-tab="')[1:]]
845846
assert tabs[:5] == ["overview", "models", "pair", "settings", "about"]
847+
assert "footer-copy" in response.text
848+
assert "footer-links" not in response.text
849+
assert "© 2026" in response.text or "&copy; 2026" in response.text
846850
assert response.headers["cache-control"] == "no-store"
847851
assert response.headers["x-frame-options"] == "DENY"
848852
assert response.headers["x-content-type-options"] == "nosniff"

0 commit comments

Comments
 (0)