[object Object]

← back to Rentv V1

rentv-v1: 10-theme live switcher (dropdown in util bar, localStorage-persisted) — 10 professional CRE-news themes from graphic-designer incl 3 dark, dark-surface overrides, Google Fonts loaded; Boomer toggles to pick

88ae7aa2bb47e86c44bd39edb0cca41b7e887b8e · 2026-07-21 14:53:39 -0700 · Steve Abrams

Files touched

Diff

commit 88ae7aa2bb47e86c44bd39edb0cca41b7e887b8e
Author: Steve Abrams <steve@designerwallcoverings.com>
Date:   Tue Jul 21 14:53:39 2026 -0700

    rentv-v1: 10-theme live switcher (dropdown in util bar, localStorage-persisted) — 10 professional CRE-news themes from graphic-designer incl 3 dark, dark-surface overrides, Google Fonts loaded; Boomer toggles to pick
---
 build.mjs               |  1 +
 public/about.html       |  1 +
 public/advertise.html   |  1 +
 public/article.html     |  1 +
 public/conferences.html |  1 +
 public/cre-talk.html    |  1 +
 public/index.html       |  1 +
 public/markets.html     |  1 +
 public/review.html      |  1 +
 public/section.html     |  1 +
 public/subscribe.html   |  1 +
 public/theme.js         | 66 +++++++++++++++++++++++++++++++++++++++++++++++++
 12 files changed, 77 insertions(+)

diff --git a/build.mjs b/build.mjs
index 2014d1d..cbd1201 100644
--- a/build.mjs
+++ b/build.mjs
@@ -149,6 +149,7 @@ ${utilBar}${masthead}${nav(active)}
 ${main}
 ${footer}
 <script>${baseJS}</script>
+<script src="/theme.js"></script>
 </body></html>`;
 
 // ── Conferences ──
diff --git a/public/about.html b/public/about.html
index f584bc8..18d2d10 100644
--- a/public/about.html
+++ b/public/about.html
@@ -145,4 +145,5 @@
         else{if(btn)btn.removeAttribute('disabled');alert((j&&j.error)?('Please enter a valid email — '+j.error):'Could not subscribe, please try again.');}
       }).catch(function(){if(btn)btn.removeAttribute('disabled');alert('Network error — please try again.');});
   });});</script>
+<script src="/theme.js"></script>
 </body></html>
\ No newline at end of file
diff --git a/public/advertise.html b/public/advertise.html
index 32c97f1..ba52067 100644
--- a/public/advertise.html
+++ b/public/advertise.html
@@ -154,4 +154,5 @@
         else{if(btn)btn.removeAttribute('disabled');alert((j&&j.error)?('Please enter a valid email — '+j.error):'Could not subscribe, please try again.');}
       }).catch(function(){if(btn)btn.removeAttribute('disabled');alert('Network error — please try again.');});
   });});</script>
+<script src="/theme.js"></script>
 </body></html>
\ No newline at end of file
diff --git a/public/article.html b/public/article.html
index b3a459c..914ffef 100644
--- a/public/article.html
+++ b/public/article.html
@@ -133,5 +133,6 @@ const hamBtn=document.getElementById('hamBtn');
 hamBtn.addEventListener('click',()=>{const open=document.getElementById('nav').classList.toggle('open');hamBtn.setAttribute('aria-expanded',open);});
 load();
 </script>
+<script src="/theme.js"></script>
 </body>
 </html>
diff --git a/public/conferences.html b/public/conferences.html
index 34cb7f5..5ac7a7d 100644
--- a/public/conferences.html
+++ b/public/conferences.html
@@ -142,4 +142,5 @@
         else{if(btn)btn.removeAttribute('disabled');alert((j&&j.error)?('Please enter a valid email — '+j.error):'Could not subscribe, please try again.');}
       }).catch(function(){if(btn)btn.removeAttribute('disabled');alert('Network error — please try again.');});
   });});</script>
+<script src="/theme.js"></script>
 </body></html>
\ No newline at end of file
diff --git a/public/cre-talk.html b/public/cre-talk.html
index 539c461..9aa84ad 100644
--- a/public/cre-talk.html
+++ b/public/cre-talk.html
@@ -159,4 +159,5 @@
         else{if(btn)btn.removeAttribute('disabled');alert((j&&j.error)?('Please enter a valid email — '+j.error):'Could not subscribe, please try again.');}
       }).catch(function(){if(btn)btn.removeAttribute('disabled');alert('Network error — please try again.');});
   });});</script>
+<script src="/theme.js"></script>
 </body></html>
\ No newline at end of file
diff --git a/public/index.html b/public/index.html
index b09c546..f1ef3e7 100644
--- a/public/index.html
+++ b/public/index.html
@@ -186,5 +186,6 @@ if(cat!=='all'){document.querySelectorAll('#nav a').forEach(function(a){a.classL
 load(); setInterval(load, 120000); // refresh the live feed every 2 minutes
 loadTicker(); setInterval(loadTicker, 120000); // live market ticker
 </script>
+<script src="/theme.js"></script>
 </body>
 </html>
diff --git a/public/markets.html b/public/markets.html
index cbd2ce6..2ef8ada 100644
--- a/public/markets.html
+++ b/public/markets.html
@@ -108,5 +108,6 @@ async function load(){
 load(); setInterval(load,120000);
 var hb=document.getElementById('hamBtn');if(hb)hb.addEventListener('click',function(){var o=document.getElementById('nav').classList.toggle('open');hb.setAttribute('aria-expanded',o);});
 </script>
+<script src="/theme.js"></script>
 </body>
 </html>
diff --git a/public/review.html b/public/review.html
index c4351f3..df35717 100644
--- a/public/review.html
+++ b/public/review.html
@@ -202,5 +202,6 @@ async function load(){
 load(); setInterval(load, 300000); // re-sync every 5 min
 var hb=document.getElementById('hamBtn');if(hb)hb.addEventListener('click',function(){var o=document.getElementById('nav').classList.toggle('open');hb.setAttribute('aria-expanded',o);});
 </script>
+<script src="/theme.js"></script>
 </body>
 </html>
diff --git a/public/section.html b/public/section.html
index 8a281e1..131b56f 100644
--- a/public/section.html
+++ b/public/section.html
@@ -125,5 +125,6 @@ async function load(){
 }
 load();
 </script>
+<script src="/theme.js"></script>
 </body>
 </html>
diff --git a/public/subscribe.html b/public/subscribe.html
index ce8a926..9165785 100644
--- a/public/subscribe.html
+++ b/public/subscribe.html
@@ -146,4 +146,5 @@
         else{if(btn)btn.removeAttribute('disabled');alert((j&&j.error)?('Please enter a valid email — '+j.error):'Could not subscribe, please try again.');}
       }).catch(function(){if(btn)btn.removeAttribute('disabled');alert('Network error — please try again.');});
   });});</script>
+<script src="/theme.js"></script>
 </body></html>
\ No newline at end of file
diff --git a/public/theme.js b/public/theme.js
new file mode 100644
index 0000000..f5449fc
--- /dev/null
+++ b/public/theme.js
@@ -0,0 +1,66 @@
+/* rentv-v1 THEME SWITCHER — 10 professional CRE-news themes, toggled live via a
+   dropdown in the util bar. Persists to localStorage. Designed with the
+   graphic-designer agent (real financial-publication aesthetics). $0/local. */
+(function () {
+  var THEMES = [
+    { name:"RENTV Classic",       dark:false, accent:"#c8102e", ink:"#14171a", sub:"#5b636b", line:"#e4e7ea", bg:"#ffffff", wash:"#f5f6f8", serif:"'Playfair Display', Georgia, serif", sans:"'Inter', system-ui, sans-serif" },
+    { name:"Broadsheet",          dark:false, accent:"#8b1a1a", ink:"#111111", sub:"#555555", line:"#d6cfc4", bg:"#faf7f2", wash:"#f0ece4", serif:"'Newsreader', Georgia, serif", sans:"'Libre Franklin', system-ui, sans-serif" },
+    { name:"FT Salmon",           dark:false, accent:"#00538b", ink:"#1a1a1a", sub:"#5c5c5c", line:"#d4c9b8", bg:"#fff1e5", wash:"#fde8d1", serif:"'Source Serif 4', Georgia, serif", sans:"'Inter', system-ui, sans-serif" },
+    { name:"Bloomberg Terminal",  dark:true,  accent:"#ff6600", ink:"#e8ffe8", sub:"#7fbf7f", line:"#1e3a1e", bg:"#0a0f0a", wash:"#111a11", serif:"'IBM Plex Serif', Georgia, serif", sans:"'IBM Plex Sans', ui-monospace, monospace" },
+    { name:"Midnight Capital",    dark:true,  accent:"#c9a84c", ink:"#f0f2f5", sub:"#8fa3b8", line:"#1e2d40", bg:"#0d1b2a", wash:"#132336", serif:"'DM Serif Display', Georgia, serif", sans:"'Archivo', system-ui, sans-serif" },
+    { name:"The Transcript",      dark:false, accent:"#3a5a8c", ink:"#1c2330", sub:"#586070", line:"#dce0e6", bg:"#f8f9fb", wash:"#edf0f4", serif:"'Spectral', Georgia, serif", sans:"'Space Grotesk', system-ui, sans-serif" },
+    { name:"Western Dispatch",    dark:false, accent:"#b84a1e", ink:"#1e1712", sub:"#6b5a4e", line:"#e0d4c8", bg:"#fdf8f3", wash:"#f5ede3", serif:"'Fraunces', Georgia, serif", sans:"'Libre Franklin', system-ui, sans-serif" },
+    { name:"Gunmetal Report",     dark:true,  accent:"#e82535", ink:"#f2f2f2", sub:"#9aa0a8", line:"#2e3540", bg:"#181c22", wash:"#22282f", serif:"'Playfair Display', Georgia, serif", sans:"'Inter', system-ui, sans-serif" },
+    { name:"Legal Pad",           dark:false, accent:"#2d5a27", ink:"#1a1a14", sub:"#5a5a40", line:"#d8d8b8", bg:"#fdfde6", wash:"#f5f5d0", serif:"'Lora', Georgia, serif", sans:"'IBM Plex Sans', system-ui, sans-serif" },
+    { name:"Institutional White", dark:false, accent:"#1a3a6b", ink:"#0f1923", sub:"#5a6474", line:"#e0e4eb", bg:"#ffffff", wash:"#f2f4f8", serif:"'Source Serif 4', Georgia, serif", sans:"'Archivo', system-ui, sans-serif" }
+  ];
+
+  // Load the Google Fonts used across all themes (once).
+  var fams = ['Playfair Display:wght@400;700','Newsreader:wght@400;700','Libre Franklin:wght@400;600;800',
+    'Source Serif 4:wght@400;700','IBM Plex Serif:wght@400;700','IBM Plex Sans:wght@400;600;700',
+    'DM Serif Display','Archivo:wght@400;600;800','Spectral:wght@400;700','Space Grotesk:wght@400;700',
+    'Fraunces:wght@400;700','Lora:wght@400;700','Inter:wght@300;400;600;800'];
+  var l = document.createElement('link'); l.rel='stylesheet';
+  l.href='https://fonts.googleapis.com/css2?'+fams.map(function(f){return 'family='+f.replace(/ /g,'+');}).join('&')+'&display=swap';
+  document.head.appendChild(l);
+
+  // Dark-theme surface overrides: the design system overloads var(--ink) as both text
+  // AND dark-surface bg (util bar/footer/subscribe box). In a dark theme --ink is light,
+  // so re-point those surfaces to --wash (a dark panel) and their text to --ink.
+  var st = document.createElement('style');
+  st.textContent =
+    "body.theme-dark .util,body.theme-dark footer,body.theme-dark .ns,body.theme-dark .mast{background:var(--wash)!important}" +
+    "body.theme-dark .util,body.theme-dark .util a,body.theme-dark footer,body.theme-dark footer a,body.theme-dark footer p{color:var(--sub)!important}" +
+    "body.theme-dark footer .logo,body.theme-dark footer h5{color:var(--ink)!important}" +
+    "body.theme-dark .ns{color:var(--ink)!important}body.theme-dark .ns p{color:var(--sub)!important}" +
+    "body.theme-dark .card .img,body.theme-dark .lead .img{filter:brightness(.85)}" +
+    "#rentv-theme{background:transparent;color:inherit;border:1px solid currentColor;border-radius:3px;font:inherit;font-size:11px;padding:2px 6px;cursor:pointer;margin-left:14px;opacity:.85}" +
+    "#rentv-theme:hover{opacity:1}";
+  document.head.appendChild(st);
+
+  function apply(i) {
+    var t = THEMES[i] || THEMES[0], r = document.documentElement;
+    r.style.setProperty('--red', t.accent); r.style.setProperty('--ink', t.ink);
+    r.style.setProperty('--sub', t.sub); r.style.setProperty('--line', t.line);
+    r.style.setProperty('--bg', t.bg); r.style.setProperty('--wash', t.wash);
+    r.style.setProperty('--serif', t.serif); r.style.setProperty('--sans', t.sans);
+    document.body.classList.toggle('theme-dark', !!t.dark);
+    try { localStorage.setItem('rentv-theme', i); } catch (e) {}
+  }
+
+  function mountPicker() {
+    if (document.getElementById('rentv-theme')) return;
+    var host = document.querySelector('.util .acts') || document.querySelector('.util .wrap');
+    if (!host) return;
+    var sel = document.createElement('select'); sel.id = 'rentv-theme'; sel.title = 'Preview a site theme';
+    THEMES.forEach(function (t, i) { var o = document.createElement('option'); o.value = i; o.textContent = '🎨 ' + t.name; sel.appendChild(o); });
+    var saved = 0; try { saved = parseInt(localStorage.getItem('rentv-theme') || '0', 10) || 0; } catch (e) {}
+    sel.value = saved; sel.addEventListener('change', function () { apply(+sel.value); });
+    host.appendChild(sel);
+  }
+
+  // Apply saved theme ASAP (before paint where possible), then mount the picker.
+  var saved0 = 0; try { saved0 = parseInt(localStorage.getItem('rentv-theme') || '0', 10) || 0; } catch (e) {}
+  if (document.body) { apply(saved0); mountPicker(); }
+  else document.addEventListener('DOMContentLoaded', function () { apply(saved0); mountPicker(); });
+})();

← 6ca6f36 rentv-v1 polish batch: wordmark 34→42px, mobile hamburger →  ·  back to Rentv V1  ·  rentv-v1: 10 full site VERSIONS (distinct homepage layouts o 6b7158a →