[object Object]

← 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

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 →