[object Object]

← back to Dw Domain Fleet

monetize: fix header overlap (in-flow sticky m-nav, not fixed topbar) + hero-image support with scrim (TK-11322)

6769abd59f5c644f8f85aff933bbb270f02aee88 · 2026-09-09 10:42:20 -0700 · Steve Abrams

Steve feedback: fixed topbar/hamburger overlapped the for-sale strip. Monetize
mode now uses an in-flow sticky header and an optional cfg.heroImage full-bleed
hero with a readability scrim; gradient fallback when no image.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01S81Y5KkGKrUHg2mwWQtD96

Files touched

Diff

commit 6769abd59f5c644f8f85aff933bbb270f02aee88
Author: Steve Abrams <steve@designerwallcoverings.com>
Date:   Wed Sep 9 10:42:20 2026 -0700

    monetize: fix header overlap (in-flow sticky m-nav, not fixed topbar) + hero-image support with scrim (TK-11322)
    
    Steve feedback: fixed topbar/hamburger overlapped the for-sale strip. Monetize
    mode now uses an in-flow sticky header and an optional cfg.heroImage full-bleed
    hero with a readability scrim; gradient fallback when no image.
    
    Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
    Claude-Session: https://claude.ai/code/session_01S81Y5KkGKrUHg2mwWQtD96
---
 shared/render.js | 66 ++++++++++++++++++++++++++++++++------------------------
 1 file changed, 38 insertions(+), 28 deletions(-)

diff --git a/shared/render.js b/shared/render.js
index 50b1700..547d2e2 100644
--- a/shared/render.js
+++ b/shared/render.js
@@ -1070,46 +1070,56 @@ function forSaleBanner(cfg) {
 /* Monetize-mode nav — no DW catalog / memo / trade links (this is not a DW
  * funnel). Home / Guide / About / Privacy / Contact only. */
 function monetizeChrome(cfg) {
+  // In-flow sticky header (not fixed) so it never overlaps the for-sale strip
+  // or the hero. Inline nav — no hamburger overlay needed at this link count.
   return `
-<div class="topbar">
-  <a class="brand" href="/">${esc(cfg.siteName)}</a>
-  <div style="display:flex;gap:14px;align-items:center">
+<header class="m-nav">
+  <a class="m-brand" href="/">${esc(cfg.siteName)}</a>
+  <nav class="m-nav__links">
+    <a href="/">Home</a>
+    <a href="/#guide">Guide</a>
+    <a href="/about">About</a>
+    <a href="/privacy">Privacy</a>
+    <a href="mailto:${esc(cfg.siteEmail)}">Contact</a>
     <button class="theme-toggle" id="themeBtn" aria-label="Toggle theme">
-      <svg class="icon-sun" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true">
+      <svg class="icon-sun" width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true">
         <circle cx="12" cy="12" r="5"/><path d="M12 1v2M12 21v2M4.2 4.2l1.4 1.4M18.4 18.4l1.4 1.4M1 12h2M21 12h2M4.2 19.8l1.4-1.4M18.4 5.6l1.4-1.4"/></svg>
-      <svg class="icon-moon" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true">
+      <svg class="icon-moon" width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true">
         <path d="M21 12.8A9 9 0 1 1 11.2 3a7 7 0 0 0 9.8 9.8z"/></svg>
     </button>
-  </div>
-</div>
-<button class="gucci-menu" id="menuBtn" aria-expanded="false" aria-controls="navpanel">
-  <span class="gucci-menu__bars" aria-hidden="true"><span></span><span></span><span></span></span>
-  <span class="gucci-menu__label">Menu</span>
-</button>
-<nav class="navpanel" id="navpanel">
-  <a href="/">Home</a>
-  <a href="/#guide">Guide</a>
-  <a href="/about">About</a>
-  <a href="/privacy">Privacy</a>
-  <a href="mailto:${esc(cfg.siteEmail)}">Contact</a>
-</nav>`;
+  </nav>
+</header>`;
 }
 
 /* Monetize-mode CSS — a real content-site hero + article layout, isolated from
  * the funnel template's catalog CSS. Uses the site theme vars already in css(). */
 function monetizeCss() {
   return `
-.m-hero{position:relative;min-height:clamp(460px,78vh,860px);display:flex;align-items:center;
+/* in-flow sticky header — NO fixed overlap with the for-sale strip / hero */
+.m-nav{position:sticky;top:0;z-index:50;display:flex;align-items:center;justify-content:space-between;
+  gap:16px;padding:15px 32px;background:var(--header-bg);border-bottom:1px solid var(--rule)}
+.m-nav .m-brand{font-family:var(--serif);font-size:20px;letter-spacing:.03em;color:var(--fg)}
+.m-nav__links{display:flex;align-items:center;gap:24px}
+.m-nav__links a{font-size:12px;letter-spacing:.13em;text-transform:uppercase;color:var(--muted)}
+.m-nav__links a:hover{color:var(--fg)}
+.m-nav .theme-toggle{position:static;top:auto;right:auto;color:var(--muted)}
+@media(max-width:680px){.m-nav{flex-wrap:wrap;gap:10px;padding:12px 18px}
+  .m-nav__links{gap:16px;font-size:11px;letter-spacing:.08em}}
+
+.m-hero{position:relative;min-height:clamp(440px,72vh,760px);display:flex;align-items:flex-end;
   justify-content:center;text-align:center;overflow:hidden;
   background:linear-gradient(135deg,var(--accent) 0%,var(--bg) 62%);}
 [data-theme=dark] .m-hero{background:linear-gradient(135deg,var(--accent) 0%,#0c0a08 70%);}
-.m-hero::before{content:"";position:absolute;inset:0;opacity:.10;
+.m-hero__bg{position:absolute;inset:0;background-size:cover;background-position:center;z-index:0}
+.m-hero.has-img::before{content:"";position:absolute;inset:0;z-index:1;
+  background:linear-gradient(180deg,rgba(0,0,0,.34) 0%,rgba(0,0,0,.15) 42%,rgba(0,0,0,.74) 100%)}
+.m-hero:not(.has-img)::before{content:"";position:absolute;inset:0;opacity:.10;z-index:1;
   background-image:radial-gradient(circle at 20% 30%,#fff 0,transparent 42%),radial-gradient(circle at 80% 70%,#fff 0,transparent 42%);}
-.m-hero__in{position:relative;z-index:2;max-width:820px;padding:40px 28px}
+.m-hero__in{position:relative;z-index:2;max-width:860px;padding:48px 28px 60px}
 .m-hero h1{font-family:var(--serif);font-size:clamp(44px,7vw,92px);font-weight:500;line-height:1.02;
-  letter-spacing:.01em;color:#fff;text-shadow:0 2px 30px rgba(0,0,0,.28);text-wrap:balance}
-.m-hero p{color:rgba(255,255,255,.92);font-size:clamp(16px,2vw,21px);margin-top:18px;line-height:1.6;
-  max-width:60ch;margin-left:auto;margin-right:auto}
+  letter-spacing:.01em;color:#fff;text-shadow:0 2px 30px rgba(0,0,0,.45);text-wrap:balance}
+.m-hero p{color:rgba(255,255,255,.94);font-size:clamp(16px,2vw,21px);margin-top:18px;line-height:1.6;
+  max-width:60ch;margin-left:auto;margin-right:auto;text-shadow:0 1px 14px rgba(0,0,0,.4)}
 .m-article{max-width:760px;margin:0 auto;padding:64px 0 30px}
 .m-article .lede{font-family:var(--serif);font-size:clamp(20px,2.4vw,26px);line-height:1.55;
   color:var(--fg);margin-bottom:32px}
@@ -1144,6 +1154,7 @@ function monetizeHome(cfg) {
   ];
   const guide = Array.isArray(c.guide) ? c.guide : [];
   const banner = forSaleBanner(cfg);
+  const heroImg = cfg.heroImage || '';
   // NOTE: authored content.* copy is rendered esc-only (NOT clean()) — these are
   // for-sale generic domains that legitimately contain "wallpaper"; the DW
   // wallpaper→wallcovering swap only applies to DW-branded funnel copy.
@@ -1156,10 +1167,11 @@ function monetizeHome(cfg) {
     <h2>${esc(c.guideTitle || 'A quick guide')}</h2>
     <ul>${guide.map(g => `<li><b>${esc(g.k)}</b><span>${esc(g.v)}</span></li>`).join('')}</ul>
   </div>` : '';
-  return head(cfg, title, desc, '/', null, banner ? 'promo-on' : '')
+  return head(cfg, title, desc, '/', null, '')
     + `<style>${monetizeCss()}</style>`
     + banner + jsonld(cfg) + monetizeChrome(cfg) + `
-<header class="m-hero">
+<header class="m-hero${heroImg ? ' has-img' : ''}">
+  ${heroImg ? `<div class="m-hero__bg" style="background-image:url('${esc(heroImg)}')"></div>` : ''}
   <div class="m-hero__in">
     <h1>${esc(cfg.heroHeadline || cfg.siteName)}</h1>
     <p>${esc(clean(cfg.tagline))}</p>
@@ -1198,7 +1210,6 @@ function privacyPage(cfg) {
   return head(cfg, title, `Privacy policy for ${clean(cfg.siteName)}.`, '/privacy')
     + `<style>${monetizeCss()}</style>`
     + (cfg.monetize || cfg.forSale ? '' : '') + jsonld(cfg) + monetizeChrome(cfg) + `
-<div style="height:96px"></div>
 <div class="wrap"><section class="m-legal">
   <h1>Privacy Policy</h1>
   <p>Last updated ${new Date().toLocaleDateString('en-US',{year:'numeric',month:'long',day:'numeric'})}. This policy explains how ${esc(clean(cfg.siteName))} (&ldquo;we&rdquo;, &ldquo;this site&rdquo;) handles information when you visit ${esc(cfg.domain)}.</p>
@@ -1232,7 +1243,6 @@ function monetizeAbout(cfg) {
   return head(cfg, title, clean(cfg.metaDesc || cfg.tagline), '/about')
     + `<style>${monetizeCss()}</style>`
     + jsonld(cfg) + monetizeChrome(cfg) + `
-<div style="height:96px"></div>
 <div class="wrap"><section class="m-legal">
   <h1>${esc(cfg.siteName)}</h1>
   ${String(body).split(/\n\n+/).map(p => `<p>${esc(p)}</p>`).join('')}

← ebca1a8 TK-11322: add red flocked hero asset for barwallpaper.com mo  ·  back to Dw Domain Fleet  ·  monetize: content sections + checklist as collapsed <details 00c6cee →