← back to Rentv 2026
RENTV 2026: element-numbering overlay (all templates) + demo sold-sponsorship creatives
089da29ba092735d9f38c30d358429ee30f8097a · 2026-08-07 11:30:01 -0700 · Steve (RENTV 2026)
- public/2026/elements.js: shared drop-in that numbers every significant element
(stable DOM-order N + badge + searchable index panel), toggled by button / 'e' key / ?num=1.
Injected into all 5 templates + selector + advertise + ad-admin so any element is
referenceable as 'Template C · el N' in future feedback.
- public/ad-creatives/{jll-leaderboard,cbre-masthead,mm-rectangle}.svg: demo banner
creatives so the sold-slot creative-serving state is visible on the live templates
(data/ad-state.json seeds 3 sold banners + 3 sold video sponsorships; runtime, gitignored).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Files touched
M public/2026/a.htmlM public/2026/b.htmlM public/2026/c.htmlM public/2026/d.htmlM public/2026/e.htmlA public/2026/elements.jsM public/2026/index.htmlM public/ad-admin.htmlA public/ad-creatives/cbre-masthead.svgA public/ad-creatives/jll-leaderboard.svgA public/ad-creatives/mm-rectangle.svgM public/advertise.html
Diff
commit 089da29ba092735d9f38c30d358429ee30f8097a
Author: Steve (RENTV 2026) <steve@designerwallcoverings.com>
Date: Fri Aug 7 11:30:01 2026 -0700
RENTV 2026: element-numbering overlay (all templates) + demo sold-sponsorship creatives
- public/2026/elements.js: shared drop-in that numbers every significant element
(stable DOM-order N + badge + searchable index panel), toggled by button / 'e' key / ?num=1.
Injected into all 5 templates + selector + advertise + ad-admin so any element is
referenceable as 'Template C · el N' in future feedback.
- public/ad-creatives/{jll-leaderboard,cbre-masthead,mm-rectangle}.svg: demo banner
creatives so the sold-slot creative-serving state is visible on the live templates
(data/ad-state.json seeds 3 sold banners + 3 sold video sponsorships; runtime, gitignored).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---
public/2026/a.html | 1 +
public/2026/b.html | 1 +
public/2026/c.html | 1 +
public/2026/d.html | 1 +
public/2026/e.html | 1 +
public/2026/elements.js | 164 ++++++++++++++++++++++++++++++++
public/2026/index.html | 1 +
public/ad-admin.html | 1 +
public/ad-creatives/cbre-masthead.svg | 10 ++
public/ad-creatives/jll-leaderboard.svg | 9 ++
public/ad-creatives/mm-rectangle.svg | 10 ++
public/advertise.html | 1 +
12 files changed, 201 insertions(+)
diff --git a/public/2026/a.html b/public/2026/a.html
index 952f4f0c..2e02b257 100644
--- a/public/2026/a.html
+++ b/public/2026/a.html
@@ -1346,5 +1346,6 @@ img { display: block; }
})();
</script>
+<script src="/2026/elements.js" defer></script>
</body>
</html>
diff --git a/public/2026/b.html b/public/2026/b.html
index 1838974f..91198194 100644
--- a/public/2026/b.html
+++ b/public/2026/b.html
@@ -1467,5 +1467,6 @@ button { cursor: pointer; border: none; background: none; font: inherit; }
})();
</script>
+<script src="/2026/elements.js" defer></script>
</body>
</html>
diff --git a/public/2026/c.html b/public/2026/c.html
index 17195255..efe26532 100644
--- a/public/2026/c.html
+++ b/public/2026/c.html
@@ -1090,5 +1090,6 @@ init();
})();
</script>
+<script src="/2026/elements.js" defer></script>
</body>
</html>
diff --git a/public/2026/d.html b/public/2026/d.html
index a63c35e0..d109ba2f 100644
--- a/public/2026/d.html
+++ b/public/2026/d.html
@@ -1709,5 +1709,6 @@ loadVideos();
loadOriginals();
</script>
+<script src="/2026/elements.js" defer></script>
</body>
</html>
diff --git a/public/2026/e.html b/public/2026/e.html
index 23efaf81..4c0cca3d 100644
--- a/public/2026/e.html
+++ b/public/2026/e.html
@@ -1406,5 +1406,6 @@ footer {
})();
</script>
+<script src="/2026/elements.js" defer></script>
</body>
</html>
diff --git a/public/2026/elements.js b/public/2026/elements.js
new file mode 100644
index 00000000..8360d633
--- /dev/null
+++ b/public/2026/elements.js
@@ -0,0 +1,164 @@
+/* RENTV 2026 — Element Numbering overlay (shared drop-in).
+ *
+ * Purpose: give every significant element on every template a STABLE number so
+ * Steve can reference "Template C, element 14" in future feedback.
+ *
+ * Include on any page: <script src="/2026/elements.js" defer></script>
+ * Toggle: the "①② Elements" button (bottom-left) · the "e" key · or ?num=1 in the URL.
+ *
+ * Numbers are assigned in DOM order over a curated selector set, so they are
+ * stable across reloads (as long as the page structure doesn't change). Each
+ * numbered element gets a badge; a searchable index panel lists them all and
+ * clicking an index row scrolls to + flashes that element. State persists in
+ * localStorage per page path. Zero dependencies; fully removable (toggle off
+ * restores the DOM).
+ */
+(function () {
+ var SEL = [
+ 'header', 'nav', 'section', 'main', 'footer',
+ '[data-ad-slot]',
+ '.card', '.slot', '.vslot', '.vidcard', '.rescard', '.tile', '.panel',
+ 'h1', 'h2', 'h3', 'h4',
+ 'nav a', 'footer a',
+ 'button', 'a.btn', '.btn', '.chip', '.cta',
+ 'input', 'select', 'textarea',
+ '.hero', '.vhero', '.controls', '.filters', '.rate', '.invgrid', '.river', '.vidrow'
+ ].join(',');
+
+ var KEY = 'rentv_num_' + location.pathname;
+ var on = false, badges = [], touched = [];
+
+ function label(el) {
+ var t = (el.getAttribute('aria-label') || el.getAttribute('placeholder') || '').trim();
+ if (!t) {
+ var clone = el.cloneNode(true);
+ // strip our own badge text if present
+ t = (clone.textContent || '').replace(/\s+/g, ' ').trim();
+ }
+ if (!t && el.getAttribute('data-ad-slot')) t = 'ad-slot:' + el.getAttribute('data-ad-slot');
+ if (!t && el.tagName === 'IMG') t = el.getAttribute('alt') || 'image';
+ var cls = (el.className && typeof el.className === 'string') ? '.' + el.className.split(/\s+/).slice(0, 2).join('.') : '';
+ return { tag: el.tagName.toLowerCase() + cls, text: t.slice(0, 60) };
+ }
+
+ function css() {
+ if (document.getElementById('rentv-num-css')) return;
+ var s = document.createElement('style'); s.id = 'rentv-num-css';
+ s.textContent = [
+ '.rentv-el-badge{position:absolute;z-index:2147483000;top:0;left:0;transform:translate(-4px,-9px);',
+ ' background:#c8102e;color:#fff;font:800 10px/1 ui-monospace,Menlo,monospace;padding:2px 4px;border-radius:4px;',
+ ' box-shadow:0 1px 4px rgba(0,0,0,.4);pointer-events:none;letter-spacing:.02em}',
+ '.rentv-num-mark{outline:1px dashed rgba(200,16,46,.5);outline-offset:1px}',
+ '.rentv-num-flash{outline:3px solid #f0b429!important;transition:outline .2s}',
+ '#rentv-num-toggle{position:fixed;left:14px;bottom:14px;z-index:2147483600;background:#0b0e12;color:#fff;',
+ ' border:1px solid #c8102e;border-radius:9px;padding:9px 13px;font:800 12px Inter,system-ui,sans-serif;',
+ ' cursor:pointer;box-shadow:0 8px 26px rgba(0,0,0,.4)}',
+ '#rentv-num-toggle.on{background:#c8102e}',
+ '#rentv-num-index{position:fixed;right:14px;top:70px;bottom:70px;width:290px;z-index:2147483500;background:#0b0e12;',
+ ' color:#e7ecf1;border:1px solid #1c232b;border-radius:12px;display:none;flex-direction:column;box-shadow:0 20px 60px rgba(0,0,0,.5)}',
+ '#rentv-num-index.on{display:flex}',
+ '#rentv-num-index .h{padding:11px 13px;border-bottom:1px solid #1c232b;display:flex;gap:8px;align-items:center}',
+ '#rentv-num-index .h b{font:800 12px Inter;letter-spacing:.04em}',
+ '#rentv-num-index .h .ct{margin-left:auto;color:#7b848d;font:700 11px Inter}',
+ '#rentv-num-index input{width:100%;margin:8px 10px 6px;width:calc(100% - 20px);padding:7px 9px;border:1px solid #1c232b;',
+ ' background:#11161c;color:#e7ecf1;border-radius:7px;font:13px Inter}',
+ '#rentv-num-index .list{overflow:auto;flex:1;padding:2px 6px 10px}',
+ '#rentv-num-index .row{display:flex;gap:8px;padding:6px 8px;border-radius:6px;cursor:pointer;font:12px/1.3 Inter}',
+ '#rentv-num-index .row:hover{background:#161d25}',
+ '#rentv-num-index .row .n{color:#fff;font:800 11px ui-monospace,monospace;background:#c8102e;border-radius:4px;padding:1px 5px;height:fit-content}',
+ '#rentv-num-index .row .m .tg{color:#8b949e;font-weight:700}',
+ '#rentv-num-index .row .m .tx{color:#c3cbd3}',
+ '#rentv-num-index .cp{padding:8px 12px;border-top:1px solid #1c232b;color:#7b848d;font:11px Inter}'
+ ].join('');
+ document.head.appendChild(s);
+ }
+
+ function build() {
+ var seen = new Set();
+ var els = Array.prototype.slice.call(document.querySelectorAll(SEL)).filter(function (el) {
+ if (seen.has(el)) return false; seen.add(el);
+ if (el.closest('#rentv-num-index') || el.id === 'rentv-num-toggle') return false;
+ var r = el.getBoundingClientRect();
+ return r.width > 8 && r.height > 8; // visible-ish
+ });
+ var rows = '';
+ els.forEach(function (el, i) {
+ var n = i + 1;
+ el.setAttribute('data-el', n);
+ el.classList.add('rentv-num-mark');
+ touched.push(el);
+ var cs = getComputedStyle(el);
+ if (cs.position === 'static') { el.style.position = 'relative'; el.setAttribute('data-num-posfix', '1'); }
+ var b = document.createElement('span'); b.className = 'rentv-el-badge'; b.textContent = n;
+ el.appendChild(b); badges.push(b);
+ var L = label(el);
+ rows += '<div class="row" data-goto="' + n + '"><span class="n">' + n + '</span><span class="m"><span class="tg">' +
+ L.tag + '</span> <span class="tx">' + (L.text ? L.text.replace(/[<>&]/g, '') : '') + '</span></span></div>';
+ });
+ idx.querySelector('.list').innerHTML = rows;
+ idx.querySelector('.ct').textContent = els.length + ' elements';
+ }
+
+ function clear() {
+ badges.forEach(function (b) { b.remove(); }); badges = [];
+ touched.forEach(function (el) {
+ el.classList.remove('rentv-num-mark'); el.removeAttribute('data-el');
+ if (el.getAttribute('data-num-posfix')) { el.style.position = ''; el.removeAttribute('data-num-posfix'); }
+ });
+ touched = [];
+ idx.querySelector('.list').innerHTML = '';
+ }
+
+ var idx, toggleBtn;
+ function ui() {
+ css();
+ toggleBtn = document.createElement('button'); toggleBtn.id = 'rentv-num-toggle';
+ toggleBtn.innerHTML = '①② Elements'; document.body.appendChild(toggleBtn);
+ idx = document.createElement('div'); idx.id = 'rentv-num-index';
+ idx.innerHTML = '<div class="h"><b>Element index</b><span class="ct"></span></div>' +
+ '<input placeholder="filter by number or text…" aria-label="Filter elements">' +
+ '<div class="list"></div>' +
+ '<div class="cp">Click a row to jump. Ref future edits as “' + pageTag() + ' · el N”.</div>';
+ document.body.appendChild(idx);
+
+ toggleBtn.addEventListener('click', function () { set(!on); });
+ document.addEventListener('keydown', function (e) {
+ if (e.key === 'e' && !/input|textarea|select/i.test((e.target.tagName || ''))) set(!on);
+ });
+ idx.querySelector('input').addEventListener('input', function (e) {
+ var q = e.target.value.toLowerCase();
+ idx.querySelectorAll('.row').forEach(function (r) {
+ r.style.display = (!q || r.textContent.toLowerCase().indexOf(q) >= 0) ? '' : 'none';
+ });
+ });
+ idx.querySelector('.list').addEventListener('click', function (e) {
+ var r = e.target.closest('[data-goto]'); if (!r) return;
+ var el = document.querySelector('[data-el="' + r.dataset.goto + '"]'); if (!el) return;
+ el.scrollIntoView({ behavior: 'smooth', block: 'center' });
+ el.classList.add('rentv-num-flash'); setTimeout(function () { el.classList.remove('rentv-num-flash'); }, 1400);
+ });
+ }
+
+ function pageTag() {
+ var m = location.pathname.match(/2026\/([a-e])\.html/); if (m) return 'Template ' + m[1].toUpperCase();
+ if (/2026\/?$/.test(location.pathname)) return 'Selector';
+ if (/advertise/.test(location.pathname)) return 'Advertise';
+ return location.pathname;
+ }
+
+ function set(v) {
+ on = v; toggleBtn.classList.toggle('on', on); idx.classList.toggle('on', on);
+ toggleBtn.innerHTML = on ? '✕ Hide numbers' : '①② Elements';
+ if (on) build(); else clear();
+ try { localStorage.setItem(KEY, on ? '1' : '0'); } catch (e) { }
+ }
+
+ function boot() {
+ ui();
+ var auto = /[?&]num=1/.test(location.search);
+ try { if (!auto && localStorage.getItem(KEY) === '1') auto = true; } catch (e) { }
+ if (auto) set(true);
+ }
+ if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', boot); else boot();
+ window.RENTVNumber = { on: function () { set(true); }, off: function () { set(false); } };
+})();
diff --git a/public/2026/index.html b/public/2026/index.html
index 6f072cec..e595bb1c 100644
--- a/public/2026/index.html
+++ b/public/2026/index.html
@@ -206,4 +206,5 @@ function paintChosen(){
paintChosen();
})();
</script>
+<script src="/2026/elements.js" defer></script>
</body></html>
diff --git a/public/ad-admin.html b/public/ad-admin.html
index b9c39b27..148c9cbd 100644
--- a/public/ad-admin.html
+++ b/public/ad-admin.html
@@ -193,4 +193,5 @@ async function loadRes(){ const d=await jget('/api/ad/admin/reservations'); if(!
initVCols(); loadPlace(); loadVid(); loadRes();
</script>
+<script src="/2026/elements.js" defer></script>
</body></html>
diff --git a/public/ad-creatives/cbre-masthead.svg b/public/ad-creatives/cbre-masthead.svg
new file mode 100644
index 00000000..10032938
--- /dev/null
+++ b/public/ad-creatives/cbre-masthead.svg
@@ -0,0 +1,10 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="970" height="250" viewBox="0 0 970 250" font-family="Inter,Arial,sans-serif">
+<defs><linearGradient id="g" x1="0" y1="0" x2="1" y2="1"><stop offset="0" stop-color="#003f2d"/><stop offset="1" stop-color="#0a5c44"/></linearGradient></defs>
+<rect width="970" height="250" fill="url(#g)"/>
+<rect x="0" y="0" width="8" height="250" fill="#17e88f"/>
+<text x="54" y="96" fill="#fff" font-size="46" font-weight="800" letter-spacing="4">CBRE</text>
+<text x="56" y="140" fill="#8fe3c6" font-size="20" font-weight="600">Advisory & Transaction Services</text>
+<text x="56" y="184" fill="#dff5ec" font-size="17">The market intelligence behind every close.</text>
+<rect x="56" y="200" width="210" height="34" rx="5" fill="#17e88f"/>
+<text x="74" y="223" fill="#023" font-size="15" font-weight="800">See our 2026 outlook →</text>
+</svg>
diff --git a/public/ad-creatives/jll-leaderboard.svg b/public/ad-creatives/jll-leaderboard.svg
new file mode 100644
index 00000000..f553d550
--- /dev/null
+++ b/public/ad-creatives/jll-leaderboard.svg
@@ -0,0 +1,9 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="970" height="90" viewBox="0 0 970 90" font-family="Inter,Arial,sans-serif">
+<rect width="970" height="90" fill="#0a1a2f"/>
+<rect x="0" y="0" width="6" height="90" fill="#e30613"/>
+<text x="34" y="42" fill="#fff" font-size="27" font-weight="800" letter-spacing="2">JLL</text>
+<text x="34" y="68" fill="#9fb4cc" font-size="14">Capital Markets · Western U.S.</text>
+<text x="640" y="40" fill="#fff" font-size="17" font-weight="700">Move your portfolio forward.</text>
+<rect x="640" y="52" width="150" height="26" rx="4" fill="#e30613"/>
+<text x="655" y="70" fill="#fff" font-size="13" font-weight="800">Talk to our team →</text>
+</svg>
diff --git a/public/ad-creatives/mm-rectangle.svg b/public/ad-creatives/mm-rectangle.svg
new file mode 100644
index 00000000..2919c837
--- /dev/null
+++ b/public/ad-creatives/mm-rectangle.svg
@@ -0,0 +1,10 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="300" height="250" viewBox="0 0 300 250" font-family="Inter,Arial,sans-serif">
+<rect width="300" height="250" fill="#10233f"/>
+<rect x="0" y="0" width="300" height="70" fill="#c8102e"/>
+<text x="20" y="45" fill="#fff" font-size="22" font-weight="800">Marcus & Millichap</text>
+<text x="20" y="118" fill="#fff" font-size="18" font-weight="700">Multifamily is</text>
+<text x="20" y="144" fill="#fff" font-size="18" font-weight="700">still moving.</text>
+<text x="20" y="180" fill="#9db4d4" font-size="13">See what's trading in your metro.</text>
+<rect x="20" y="196" width="180" height="34" rx="5" fill="#fff"/>
+<text x="34" y="219" fill="#10233f" font-size="13" font-weight="800">Get the report →</text>
+</svg>
diff --git a/public/advertise.html b/public/advertise.html
index 619ca1a1..117b76c1 100644
--- a/public/advertise.html
+++ b/public/advertise.html
@@ -309,4 +309,5 @@ $('#rForm').addEventListener('submit',async e=>{e.preventDefault();
(function(){const d=new Date();$('#fStart').value=d.getFullYear()+'-'+String(d.getMonth()+1).padStart(2,'0');})();
loadPersist(); loadRate(); loadInv();
</script>
+<script src="/2026/elements.js" defer></script>
</body></html>
← 827eb166 RENTV 2026: 5-template selector + ad-slots-for-sale system (
·
back to Rentv 2026
·
rentv: re-gate site behind un/pw (reverse 2026-08-06 public 23094df1 →