← back to Ventura Claw Leads
feat(ux): hand-drawn SVG glyphs replace emoji on vertical hero gradients
f5d2cd961596c525ac17abd6c7e49a8897132315 · 2026-05-07 07:58:25 -0700 · Steve Abrams
- new partial views/partials/vertical-glyph.ejs renders an inline line-art
SVG per vertical (food/beauty/retail/fitness/pet_services/auto_detail/
cleaning/creative). Uses currentColor so it picks up theme-aware tinting.
- swapped 4 card-grid glyph sites (find/home recently-joined/home featured/
business similar-nearby/neighborhood) and the profile-page hero banner.
- CSS .biz-card-glyph-svg sized via clamp() with drop-shadow + light-mode
override for dark glyphs on light gradients.
- 46/46 tests stable; deployed to prod.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Files touched
M public/css/public.cssA views/partials/vertical-glyph.ejsM views/public/business.ejsM views/public/find.ejsM views/public/home.ejsM views/public/neighborhood.ejs
Diff
commit f5d2cd961596c525ac17abd6c7e49a8897132315
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Thu May 7 07:58:25 2026 -0700
feat(ux): hand-drawn SVG glyphs replace emoji on vertical hero gradients
- new partial views/partials/vertical-glyph.ejs renders an inline line-art
SVG per vertical (food/beauty/retail/fitness/pet_services/auto_detail/
cleaning/creative). Uses currentColor so it picks up theme-aware tinting.
- swapped 4 card-grid glyph sites (find/home recently-joined/home featured/
business similar-nearby/neighborhood) and the profile-page hero banner.
- CSS .biz-card-glyph-svg sized via clamp() with drop-shadow + light-mode
override for dark glyphs on light gradients.
- 46/46 tests stable; deployed to prod.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---
public/css/public.css | 18 +++++++++++
views/partials/vertical-glyph.ejs | 64 +++++++++++++++++++++++++++++++++++++++
views/public/business.ejs | 6 ++--
views/public/find.ejs | 2 +-
views/public/home.ejs | 4 +--
views/public/neighborhood.ejs | 2 +-
6 files changed, 90 insertions(+), 6 deletions(-)
diff --git a/public/css/public.css b/public/css/public.css
index e2d8c66..02cf173 100644
--- a/public/css/public.css
+++ b/public/css/public.css
@@ -84,6 +84,24 @@
border-radius: 4px 4px 0 0;
}
.biz-card-glyph { font-size: clamp(36px, 5vw, 56px); opacity: 0.9; line-height: 1; user-select: none; }
+.biz-card-glyph-svg {
+ width: clamp(48px, 9vw, 88px);
+ height: clamp(48px, 9vw, 88px);
+ color: rgba(255,255,255,0.94);
+ fill: none;
+ stroke: currentColor;
+ stroke-width: 2.4;
+ stroke-linecap: round;
+ stroke-linejoin: round;
+ filter: drop-shadow(0 1px 2px rgba(0,0,0,0.18));
+}
+[data-theme="light"] .biz-card-glyph-svg { color: rgba(40,40,40,0.78); }
+.vertical-hero-glyph-svg { display: flex; align-items: center; justify-content: center; }
+.vertical-hero-glyph-svg .biz-card-glyph-svg {
+ width: clamp(96px, 16vw, 168px);
+ height: clamp(96px, 16vw, 168px);
+ stroke-width: 2.0;
+}
.vertical-hero-photo { padding: 0; }
.vertical-hero-photo img { width: 100%; height: 100%; object-fit: cover; display: block; }
.biz-card-hero-photo { padding: 0; overflow: hidden; }
diff --git a/views/partials/vertical-glyph.ejs b/views/partials/vertical-glyph.ejs
new file mode 100644
index 0000000..65dbd43
--- /dev/null
+++ b/views/partials/vertical-glyph.ejs
@@ -0,0 +1,64 @@
+<%
+ // Vertical glyph SVG renderer. Replaces the emoji-on-gradient look with a
+ // line-art SVG that picks up text color from the parent .vertical-hero-* gradient
+ // (we set color: rgba(255,255,255,0.92) on those classes — see public.css).
+ // Falls back to a centered dot for unknown verticals.
+ // Locals: verticalKey (string)
+ var _vk = String(typeof verticalKey === 'undefined' ? '' : verticalKey || '');
+%>
+<% if (_vk === 'food') { %>
+<svg class="biz-card-glyph-svg" viewBox="0 0 64 64" aria-hidden="true" focusable="false">
+ <path d="M22 12 v22 a4 4 0 0 1 -8 0 V12 M18 12 v22 M42 12 c0 6 -4 10 -4 14 v26 M50 12 c0 6 4 10 4 14 v26"/>
+</svg>
+<% } else if (_vk === 'beauty') { %>
+<svg class="biz-card-glyph-svg" viewBox="0 0 64 64" aria-hidden="true" focusable="false">
+ <path d="M32 8 L36 28 L56 32 L36 36 L32 56 L28 36 L8 32 L28 28 Z"/>
+ <circle cx="50" cy="14" r="2.5"/>
+ <circle cx="14" cy="50" r="2.5"/>
+</svg>
+<% } else if (_vk === 'retail') { %>
+<svg class="biz-card-glyph-svg" viewBox="0 0 64 64" aria-hidden="true" focusable="false">
+ <path d="M14 22 h36 l-3 32 H17 Z"/>
+ <path d="M22 22 v-4 a10 10 0 0 1 20 0 v4"/>
+</svg>
+<% } else if (_vk === 'fitness') { %>
+<svg class="biz-card-glyph-svg" viewBox="0 0 64 64" aria-hidden="true" focusable="false">
+ <rect x="6" y="26" width="6" height="12" rx="1.5"/>
+ <rect x="14" y="22" width="4" height="20" rx="1.5"/>
+ <line x1="18" y1="32" x2="46" y2="32"/>
+ <rect x="46" y="22" width="4" height="20" rx="1.5"/>
+ <rect x="52" y="26" width="6" height="12" rx="1.5"/>
+</svg>
+<% } else if (_vk === 'pet_services') { %>
+<svg class="biz-card-glyph-svg" viewBox="0 0 64 64" aria-hidden="true" focusable="false">
+ <ellipse cx="32" cy="42" rx="11" ry="9"/>
+ <ellipse cx="16" cy="24" rx="5" ry="6"/>
+ <ellipse cx="48" cy="24" rx="5" ry="6"/>
+ <ellipse cx="22" cy="14" rx="4" ry="5"/>
+ <ellipse cx="42" cy="14" rx="4" ry="5"/>
+</svg>
+<% } else if (_vk === 'auto_detail') { %>
+<svg class="biz-card-glyph-svg" viewBox="0 0 64 64" aria-hidden="true" focusable="false">
+ <path d="M8 38 l4 -10 a6 6 0 0 1 5 -4 h30 a6 6 0 0 1 5 4 l4 10 v10 h-6 a4 4 0 0 1 -8 0 H22 a4 4 0 0 1 -8 0 H8 Z"/>
+ <line x1="14" y1="38" x2="50" y2="38"/>
+</svg>
+<% } else if (_vk === 'cleaning') { %>
+<svg class="biz-card-glyph-svg" viewBox="0 0 64 64" aria-hidden="true" focusable="false">
+ <line x1="42" y1="12" x2="22" y2="32"/>
+ <path d="M18 28 l18 18 l-2 8 l-22 -4 z"/>
+ <line x1="20" y1="32" x2="34" y2="46"/>
+ <line x1="16" y1="38" x2="30" y2="50"/>
+</svg>
+<% } else if (_vk === 'creative') { %>
+<svg class="biz-card-glyph-svg" viewBox="0 0 64 64" aria-hidden="true" focusable="false">
+ <path d="M32 8 a22 22 0 1 0 0 44 c4 0 6 -3 4 -6 c-2 -3 0 -6 4 -6 h6 a8 8 0 0 0 8 -8 a22 22 0 0 0 -22 -24 z"/>
+ <circle cx="20" cy="22" r="2.5"/>
+ <circle cx="32" cy="16" r="2.5"/>
+ <circle cx="44" cy="22" r="2.5"/>
+ <circle cx="48" cy="34" r="2.5"/>
+</svg>
+<% } else { %>
+<svg class="biz-card-glyph-svg" viewBox="0 0 64 64" aria-hidden="true" focusable="false">
+ <circle cx="32" cy="32" r="6"/>
+</svg>
+<% } %>
diff --git a/views/public/business.ejs b/views/public/business.ejs
index d3cdaff..4ec2310 100644
--- a/views/public/business.ejs
+++ b/views/public/business.ejs
@@ -87,7 +87,9 @@
</div>
<% } else { %>
<div class="vertical-hero vertical-hero-<%= business.vertical %>" aria-hidden="true">
- <div class="vertical-hero-glyph"><%= verticalMeta ? verticalMeta.icon : '•' %></div>
+ <div class="vertical-hero-glyph vertical-hero-glyph-svg">
+ <%- include('../partials/vertical-glyph', { verticalKey: business.vertical }) %>
+ </div>
</div>
<% } %>
@@ -227,7 +229,7 @@
</div>
<% } else { %>
<div class="biz-card-hero vertical-hero-<%= n.vertical %>" aria-hidden="true">
- <span class="biz-card-glyph"><%= nMeta ? nMeta.icon : '•' %></span>
+ <%- include('../partials/vertical-glyph', { verticalKey: n.vertical }) %>
</div>
<% } %>
<p class="biz-name" style="font-size:16px;margin:6px 0 2px"><%= n.business_name %></p>
diff --git a/views/public/find.ejs b/views/public/find.ejs
index 0399cc3..c57cb5a 100644
--- a/views/public/find.ejs
+++ b/views/public/find.ejs
@@ -95,7 +95,7 @@
</div>
<% } else { %>
<div class="biz-card-hero vertical-hero-<%= b.vertical %>" aria-hidden="true">
- <span class="biz-card-glyph"><%= vMeta ? vMeta.icon : '•' %></span>
+ <%- include('../partials/vertical-glyph', { verticalKey: b.vertical }) %>
</div>
<% } %>
<p class="biz-vertical"><%= vMeta ? vMeta.label : b.vertical %></p>
diff --git a/views/public/home.ejs b/views/public/home.ejs
index e9bed3a..bc1f3f1 100644
--- a/views/public/home.ejs
+++ b/views/public/home.ejs
@@ -100,7 +100,7 @@
</div>
<% } else { %>
<div class="biz-card-hero vertical-hero-<%= b.vertical %>" aria-hidden="true" style="aspect-ratio:16/9;margin:-14px -16px 12px">
- <span class="biz-card-glyph"><%= vMeta ? vMeta.icon : '•' %></span>
+ <%- include('../partials/vertical-glyph', { verticalKey: b.vertical }) %>
</div>
<% } %>
<p class="biz-vertical" style="font-size:10px"><%= vMeta ? vMeta.label : b.vertical %></p>
@@ -126,7 +126,7 @@
</div>
<% } else { %>
<div class="biz-card-hero vertical-hero-<%= b.vertical %>" aria-hidden="true">
- <span class="biz-card-glyph"><%= vMeta ? vMeta.icon : '•' %></span>
+ <%- include('../partials/vertical-glyph', { verticalKey: b.vertical }) %>
</div>
<% } %>
<p class="biz-vertical"><%= vMeta ? vMeta.label : b.vertical %></p>
diff --git a/views/public/neighborhood.ejs b/views/public/neighborhood.ejs
index d5bdf37..b257e55 100644
--- a/views/public/neighborhood.ejs
+++ b/views/public/neighborhood.ejs
@@ -54,7 +54,7 @@
</div>
<% } else { %>
<div class="biz-card-hero vertical-hero-<%= b.vertical %>" aria-hidden="true">
- <span class="biz-card-glyph"><%= vMeta ? vMeta.icon : '•' %></span>
+ <%- include('../partials/vertical-glyph', { verticalKey: b.vertical }) %>
</div>
<% } %>
<p class="biz-vertical"><%= vMeta ? vMeta.label : b.vertical %></p>
← a52f7bd feat(share): per-business share-count w/ session-dedup track
·
back to Ventura Claw Leads
·
feat(admin): surface share-count on dashboard stat row c5e7571 →