[object Object]

← back to Ventura Claw Leads

yolo tick 8: vertical-themed hero panels (no external image fetches)

1a8b9b4dc8a13ed5864ef1b447ebfa402416ef3b · 2026-05-06 18:17:07 -0700 · Steve Abrams

Every business now gets a CSS-gradient banner per vertical instead of plain
initials — visual upgrade across the directory grid + profile pages without
calling Wikimedia or Google Places (those are still v0.3 candidates).

views/public/business.ejs: 16/4 aspect-ratio .vertical-hero above the
profile-hero, with the vertical's emoji glyph centered.

views/public/find.ejs: 16/9 .biz-card-hero on top of every business card,
extending to card edges via negative margin.

public/css/public.css: 8 vertical-keyed gradient classes (food/beauty/retail/
fitness/pet_services/auto_detail/cleaning/creative), each with paired
light + dark mode palettes. Single-source emoji glyph from lib/verticals.js.
Pure CSS, no external images, no JS needed.

46/46 tests still pass. Live on prod.

Files touched

Diff

commit 1a8b9b4dc8a13ed5864ef1b447ebfa402416ef3b
Author: Steve Abrams <steve@designerwallcoverings.com>
Date:   Wed May 6 18:17:07 2026 -0700

    yolo tick 8: vertical-themed hero panels (no external image fetches)
    
    Every business now gets a CSS-gradient banner per vertical instead of plain
    initials — visual upgrade across the directory grid + profile pages without
    calling Wikimedia or Google Places (those are still v0.3 candidates).
    
    views/public/business.ejs: 16/4 aspect-ratio .vertical-hero above the
    profile-hero, with the vertical's emoji glyph centered.
    
    views/public/find.ejs: 16/9 .biz-card-hero on top of every business card,
    extending to card edges via negative margin.
    
    public/css/public.css: 8 vertical-keyed gradient classes (food/beauty/retail/
    fitness/pet_services/auto_detail/cleaning/creative), each with paired
    light + dark mode palettes. Single-source emoji glyph from lib/verticals.js.
    Pure CSS, no external images, no JS needed.
    
    46/46 tests still pass. Live on prod.
---
 public/css/public.css     | 41 +++++++++++++++++++++++++++++++++++++++++
 views/public/business.ejs |  4 ++++
 views/public/find.ejs     |  9 +++++++--
 3 files changed, 52 insertions(+), 2 deletions(-)

diff --git a/public/css/public.css b/public/css/public.css
index e6b7e97..7ab15d5 100644
--- a/public/css/public.css
+++ b/public/css/public.css
@@ -40,6 +40,47 @@
 .biz-badge.is-premier { background: var(--brass); color: #fff; }
 .biz-badge.is-standard { background: #e0e7ff; color: #3730a3; }
 
+/* Vertical-themed hero panel — gradient + emoji glyph per vertical, used as
+   the banner above /business/:slug profiles and as the card-top on /find.
+   Pure CSS so no external image fetches; deterministic per vertical. */
+.vertical-hero {
+  width: 100%; aspect-ratio: 16/4;
+  display: flex; align-items: center; justify-content: center;
+  position: relative; overflow: hidden;
+  margin: 0; padding: 0;
+}
+.vertical-hero-glyph {
+  font-size: clamp(48px, 7vw, 84px);
+  filter: drop-shadow(0 2px 8px rgba(0,0,0,0.25)) saturate(1.1);
+  opacity: 0.95; line-height: 1; user-select: none;
+}
+.biz-card-hero {
+  width: 100%; aspect-ratio: 16/9;
+  display: flex; align-items: center; justify-content: center;
+  margin: -18px -20px 12px; /* extend to card edges, account for .business-card padding */
+  border-radius: 4px 4px 0 0;
+}
+.biz-card-glyph { font-size: clamp(36px, 5vw, 56px); opacity: 0.9; line-height: 1; user-select: none; }
+
+/* 8-vertical palette: a saturated gradient + readable emoji on each.
+   Each pair chosen to remain legible in light + dark modes. */
+.vertical-hero-food         { background: linear-gradient(135deg, #fef3c7 0%, #f59e0b 100%); }
+.vertical-hero-beauty       { background: linear-gradient(135deg, #fce7f3 0%, #ec4899 100%); }
+.vertical-hero-retail       { background: linear-gradient(135deg, #ede9fe 0%, #8b5cf6 100%); }
+.vertical-hero-fitness      { background: linear-gradient(135deg, #d1fae5 0%, #10b981 100%); }
+.vertical-hero-pet_services { background: linear-gradient(135deg, #fed7aa 0%, #f97316 100%); }
+.vertical-hero-auto_detail  { background: linear-gradient(135deg, #dbeafe 0%, #3b82f6 100%); }
+.vertical-hero-cleaning     { background: linear-gradient(135deg, #e0f2fe 0%, #0ea5e9 100%); }
+.vertical-hero-creative     { background: linear-gradient(135deg, #f3e8ff 0%, #a855f7 100%); }
+[data-theme="dark"] .vertical-hero-food         { background: linear-gradient(135deg, #78350f 0%, #f59e0b 100%); }
+[data-theme="dark"] .vertical-hero-beauty       { background: linear-gradient(135deg, #831843 0%, #ec4899 100%); }
+[data-theme="dark"] .vertical-hero-retail       { background: linear-gradient(135deg, #4c1d95 0%, #8b5cf6 100%); }
+[data-theme="dark"] .vertical-hero-fitness      { background: linear-gradient(135deg, #064e3b 0%, #10b981 100%); }
+[data-theme="dark"] .vertical-hero-pet_services { background: linear-gradient(135deg, #7c2d12 0%, #f97316 100%); }
+[data-theme="dark"] .vertical-hero-auto_detail  { background: linear-gradient(135deg, #1e3a8a 0%, #3b82f6 100%); }
+[data-theme="dark"] .vertical-hero-cleaning     { background: linear-gradient(135deg, #075985 0%, #0ea5e9 100%); }
+[data-theme="dark"] .vertical-hero-creative     { background: linear-gradient(135deg, #581c87 0%, #a855f7 100%); }
+
 /* Business profile page */
 .profile-hero { padding: 56px 28px 32px; max-width: 1100px; margin: 0 auto; }
 .profile-hero h1 { font-size: clamp(32px, 4.5vw, 52px); margin: 8px 0 12px; }
diff --git a/views/public/business.ejs b/views/public/business.ejs
index 1768baa..9cfa64e 100644
--- a/views/public/business.ejs
+++ b/views/public/business.ejs
@@ -42,6 +42,10 @@
 %>
 <script type="application/ld+json"><%- JSON.stringify(_ldBusiness) %></script>
 
+<div class="vertical-hero vertical-hero-<%= business.vertical %>" aria-hidden="true">
+  <div class="vertical-hero-glyph"><%= verticalMeta ? verticalMeta.icon : '•' %></div>
+</div>
+
 <section class="profile-hero">
   <p class="kicker"><%= verticalMeta ? verticalMeta.icon + '  ' + verticalMeta.label : business.vertical %></p>
   <h1><%= business.business_name %></h1>
diff --git a/views/public/find.ejs b/views/public/find.ejs
index fd5cb14..a5d7162 100644
--- a/views/public/find.ejs
+++ b/views/public/find.ejs
@@ -70,9 +70,14 @@
     </div>
   <% } else { %>
     <div class="business-grid" id="grid">
-      <% businesses.forEach(function(b){ %>
+      <% businesses.forEach(function(b){
+           var vMeta = verticals.find(function(vv){return vv.key===b.vertical});
+      %>
         <a class="business-card" href="/business/<%= b.slug %>">
-          <p class="biz-vertical"><%= verticals.find(function(vv){return vv.key===b.vertical}) ? verticals.find(function(vv){return vv.key===b.vertical}).label : b.vertical %></p>
+          <div class="biz-card-hero vertical-hero-<%= b.vertical %>" aria-hidden="true">
+            <span class="biz-card-glyph"><%= vMeta ? vMeta.icon : '•' %></span>
+          </div>
+          <p class="biz-vertical"><%= vMeta ? vMeta.label : b.vertical %></p>
           <p class="biz-name"><%= b.business_name %></p>
           <p class="biz-loc"><%= [b.neighborhood, b.city, b.state].filter(Boolean).join(' · ') %></p>
           <% if (b.headline) { %><p class="biz-headline"><%= b.headline %></p><% } %>

← d4d9dd2 yolo tick 7: bug fix — drop DEFAULT now() from business_inte  ·  back to Ventura Claw Leads  ·  yolo tick 9: lead read/unread tracking + dashboard unread co 0d288c7 →