diff --git a/odoo-community-developers/index.html b/odoo-community-developers/index.html
index 9021b81..622b2f8 100644
--- a/odoo-community-developers/index.html
+++ b/odoo-community-developers/index.html
@@ -552,14 +552,33 @@
margin: 0.1rem 0 0;
color: var(--ink-soft);
}
+ /* Profile links are LOGO ONLY — no visible name. One uniform monochrome SVG set,
+ inlined (zero requests). The link's accessible name comes from its aria-label.
+ Each hit area is 36px around a 24px mark, so the row clears the WCAG 2.2 24px
+ target-size minimum with room to spare. */
.dev-links {
margin: 0;
- font-size: 0.85rem;
- color: var(--ink-soft);
+ display: flex;
+ align-items: center;
+ flex-wrap: wrap;
+ gap: 0.3rem;
}
.dev-links a {
- color: var(--brass-deep);
+ color: var(--midnight);
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ width: 36px;
+ height: 36px;
+ border-radius: 50%;
+ line-height: 0;
}
+ .dev-links a:hover { color: var(--brass-deep); }
+ .dev-links a:focus-visible {
+ outline: 3px solid var(--brass-deep);
+ outline-offset: 2px;
+ }
+ .dev-links svg { display: block; width: 24px; height: 24px; }
/* The "Ask question anonymously" trigger — added by script only while its route is
set. Styled as a link so it sits in the links row where the mailto chip was. */
.dev-links button {
@@ -2461,7 +2480,10 @@
// Our own count — rendered ONCE, with weight, never a score.
var clients = parseInt(rec.odoo4projects_clients, 10);
- if (!isNaN(clients)) {
+ // A count of 0 — or an absent count — shows NO line at all. Not "0 clients",
+ // not a dash: 0 is not a fact worth printing about a freelancer. The plural
+ // rules for >= 1 are unchanged ("1 client" / "N clients", the plain number).
+ if (!isNaN(clients) && clients >= 1) {
var p = liveEl("p", "dev-clients");
p.appendChild(liveEl("span", "dev-clients-n", String(clients)));
p.appendChild(document.createTextNode(" "));
@@ -2495,11 +2517,18 @@
[["Linkedin", "LinkedIn"], ["github", "GitHub"], ["upwork", "Upwork"],
["fiverr", "Fiverr"]].forEach(function (pair) {
var val = String(rec[pair[0]] || "").trim();
+ var label = pair[1];
if (isLink(val)) {
- var a = liveEl("a", null, pair[1]);
+ // Logo only: the visible content is the SVG, so the link keeps its name in
+ // the accessibility tree (aria-label + title) and never ships as an empty or
+ // unnamed anchor. A null/blank value renders NO anchor at all.
+ var a = liveEl("a", null);
a.href = val;
a.target = "_blank";
a.rel = "noopener nofollow";
+ a.setAttribute("aria-label", label + " profile");
+ a.setAttribute("title", label + " profile");
+ a.innerHTML = LINK_ICONS[label]; // a static constant, never data from a record
links.push(a);
}
});
@@ -2510,10 +2539,7 @@
if (canAsk(rec)) card.setAttribute("data-relay", "1");
if (links.length) {
var row = liveEl("p", "dev-links");
- links.forEach(function (a, i) {
- if (i) row.appendChild(document.createTextNode(" \u00b7 "));
- row.appendChild(a);
- });
+ links.forEach(function (a) { row.appendChild(a); });
card.appendChild(row);
}
if (!canAsk(rec)) {
@@ -2784,6 +2810,17 @@
' stroke-linejoin="round">' +
'';
+ /* The four profile marks — ONE uniform monochrome SVG set (Simple Icons, 24 x 24:
+ same grid, same internal padding, same weight), self-hosted copies in
+ static/icons/. Inlined so the row makes NO request and the mark inherits
+ currentColor. The mark is decorative (aria-hidden); the link carries the name. */
+ var LINK_ICONS = {
+ LinkedIn: '',
+ GitHub: '',
+ Upwork: '',
+ Fiverr: ''
+ };
+
/* Add the self-service controls to one card, in ONE row ABOVE the links so the
contact action comes first:
· "Ask question anonymously" — only while its route is set AND the card is
diff --git a/static/icons/README.md b/static/icons/README.md
new file mode 100644
index 0000000..7201fff
--- /dev/null
+++ b/static/icons/README.md
@@ -0,0 +1,22 @@
+# static/icons — the profile-link icon set
+
+Four monochrome brand marks shown in the freelancer directory card's links row
+(`/odoo-community-developers/`): LinkedIn, GitHub, Upwork, Fiverr.
+
+**Source:** [Simple Icons](https://simpleicons.org) v13 — one uniform set, so the four
+share one visual language by construction: the same 24 × 24 grid, the same internal
+padding, the same monochrome mass, single-path art. Nothing here is hand-drawn and
+nothing is fetched from a third party at runtime.
+
+**How the page uses them.** The card inlines the same path data (see `LINK_ICONS` in the
+page's script and in `work/build-directory.py`), so the links row makes **zero requests**
+and each mark inherits the link's `currentColor`. These files are the self-hosted,
+drop-in copy of that set — identical geometry — for any host that prefers a file over an
+inline `