diff --git a/html/js/render/avatarVisuals.js b/html/js/render/avatarVisuals.js
index 9e85f50..62ec551 100644
--- a/html/js/render/avatarVisuals.js
+++ b/html/js/render/avatarVisuals.js
@@ -88,6 +88,15 @@
opts = opts || {};
var ap = normalize(appearance);
var projection = opts.projection || 'legacy-rot';
+ // A player who never customized arrives as avatar 'default' (or an unknown id), which is not
+ // a char/skin/model and would fall to the grey circle. On the 2D topdown/tavern path, coerce
+ // it to a real Kenney character so nobody is ever a grey dot in a room of people. (iso/3d
+ // keep their own fallbacks below.)
+ if (ap && projection !== 'iso' && projection !== '3d') {
+ var a = ap.avatar;
+ var known = (RK.isChar && RK.isChar(a)) || (RK.isSkin && RK.isSkin(a)) || (a && /^kenney-/.test(a));
+ if (!known) ap = Object.assign({}, ap, { avatar: 'char-villager' });
+ }
var kind = kindFor(ap, projection);
var pack = packFor(ap, kind, projection);
var visual = {