← back to Consulting Rentv Com
build.mjs
875 lines
#!/usr/bin/env node
// RENTV.com — consulting deliverable generator (fantasea structure + CRCP Chart.js
// graphics + real motion). Emits public/portal.html (the analysis app, served
// behind the gate at /portal) + public/versions/*.html (6 CRE-news-leader concepts).
import { writeFileSync, mkdirSync, readFileSync } from 'node:fs';
import { dirname, join } from 'node:path';
import { fileURLToPath } from 'node:url';
const HERE = dirname(fileURLToPath(import.meta.url));
const OUT = join(HERE, 'public');
mkdirSync(`${OUT}/versions`, { recursive: true });
const client = (() => { try { return JSON.parse(readFileSync(join(HERE, 'data', 'client.json'), 'utf8')); } catch { return {}; } })();
// Real CRE data sampled from CRCP (~/Projects/commercialrealestate) — deals, map points, Census demographics.
const CRCP = (() => { try { return JSON.parse(readFileSync(join(HERE, 'data', 'deals-sample.json'), 'utf8')); } catch { return { deals: [], extraPoints: [], demographics: [] }; } })();
// Growth-move suggestions (impact/effort scored) — the same bucket the admin ranks.
// Surfaced client-facing in the deliverable as the "Low Hanging Fruit" section.
const SUGGESTIONS = (() => { try { return JSON.parse(readFileSync(join(HERE, 'data', 'suggestions.json'), 'utf8')); } catch { return []; } })();
/* ------------------------------------------------------------------ data --- */
const BIZ = {
name: 'RENTV.com', since: 1998, area: 'Los Angeles · Western U.S.',
email: client?.contact?.email || 'rentadmin@rentv.com',
phone: '(310) 213-6409',
site: 'rentv.com',
focus: 'Commercial real estate news, deals & conferences',
// Verified via Daniel Ginzburg (CFO, Dandeana Corp) email package, 2026-07-17
owner: 'Steve Bloom', addr: '5757 W. Century Blvd., #700, Los Angeles, CA 90045',
team: [['Steve Bloom','Owner / Producer','(310) 213-6409'],['Arnie Garfinkel','CRE Talk co-host','(818) 532-7660'],['Allen Wolfsheimer','News/Resources','(310) 836-8238'],['Daniel Ginzburg','CFO, Dandeana Corp','(424) 251-8405']],
};
// Rotating hero — real skyline / CRE photography (Unsplash, hotlinkable, desaturated for editorial calm).
const HERO_IMGS = [
'https://images.unsplash.com/photo-1486406146926-c627a92ad1ab?auto=format&fit=crop&w=1920&q=68&sat=-40',
'https://images.unsplash.com/photo-1449824913935-59a10b8d2000?auto=format&fit=crop&w=1920&q=68&sat=-40',
'https://images.unsplash.com/photo-1460472178825-e5240623afd5?auto=format&fit=crop&w=1920&q=68&sat=-40',
'https://images.unsplash.com/photo-1515263487990-61b07816b324?auto=format&fit=crop&w=1920&q=68&sat=-40',
'https://images.unsplash.com/photo-1554469384-e58fac16e23a?auto=format&fit=crop&w=1920&q=68&sat=-40',
];
// ---- CRE-news-leader concept directions (the "suggested new websites") --------
const HOUSES = [
{ key:'thewire', label:'The Wire', model:'The Real Deal', bg:'#111114', panel:'#1a1a1f', ink:'#f5f5f7', gold:'#e0243b', line:'rgba(224,36,59,.30)', disp:"'Playfair Display',Georgia,serif", sans:"'Inter',system-ui,sans-serif", tag:'Breaking CRE, in bold.', mood:'Real-Deal energy — red-on-black newsroom, aggressive headlines.' },
{ key:'dispatch', label:'Dispatch', model:'Bisnow', bg:'#0d1b2a', panel:'#14273d', ink:'#eef3f8', gold:'#3fb0ff', line:'rgba(63,176,255,.30)', disp:"'Inter',system-ui,sans-serif", sans:"'Inter',system-ui,sans-serif", tag:'The morning brief that runs CRE.', mood:'Bisnow-style — newsletter-forward, clean, capture-first.' },
{ key:'observer', label:'The Observer', model:'Commercial Observer', bg:'#14110c', panel:'#1e1a12', ink:'#f6efe2', gold:'#c9a24b', line:'rgba(201,162,75,.30)', disp:"'Cormorant Garamond',Georgia,serif", sans:"'Jost',system-ui,sans-serif", tag:'The editorial voice of the deal.', mood:'Commercial-Observer editorial — serif authority, gold on ink.' },
{ key:'terminal', label:'Terminal', model:'CoStar / GlobeSt', bg:'#0a0e12', panel:'#111820', ink:'#e9eef3', gold:'#37d39a', line:'rgba(55,211,154,.28)', disp:"'IBM Plex Sans',system-ui,sans-serif", sans:"'IBM Plex Sans',system-ui,sans-serif", tag:'Data first. Deals decoded.', mood:'CoStar/GlobeSt utility — dark data terminal, live tickers & charts.' },
{ key:'broadsheet',label:'Broadsheet', model:'The Financial Times', bg:'#fbf3e9', panel:'#f4e7d5', ink:'#2a211a', gold:'#a8442b', line:'rgba(42,33,26,.18)', disp:"'Playfair Display',Georgia,serif", sans:"'Georgia',serif", tag:'The paper of record for CRE.', mood:'FT-style broadsheet — cream stock, classic authority, print heritage.' },
{ key:'modern', label:'Modern', model:'Axios', bg:'#0e0f11', panel:'#17181b', ink:'#f2f3f5', gold:'#8b5cf6', line:'rgba(139,92,246,.30)', disp:"'Inter',system-ui,sans-serif", sans:"'Inter',system-ui,sans-serif", tag:'Smart brevity for commercial real estate.', mood:'Axios-style modern — minimal, scannable, mobile-native.' },
];
/* ---- Chart datasets (real CRE-shaped figures; refine with CRCP data) ------- */
const CHART = {
competitors: { labels:['RENTV','Bisnow','The Real Deal','Comm. Observer','GlobeSt','CoStar News'],
reach:[35,95,90,70,80,88], digital:[28,96,92,75,70,90] },
advertising: { labels:['LinkedIn','Newsletter','Google Search','Sponsored Content','Events','X / Social','Programmatic','SEO'],
roi:[95,98,82,78,88,60,55,84] },
timing: { labels:['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'],
deals:[60,68,82,88,80,72,58,55,86,92,84,78], readership:[70,72,88,90,78,64,52,50,84,95,88,80] },
social: { labels:['Now','+30d','+60d','+90d','+180d','+1yr'], linkedin:[818,1400,2600,4200,7500,15000] },
revenue: { labels:['Subscriptions','Conferences','Sponsored Content','Newsletter Ads','Data & Reports','Job Board','Webinars','Video Sponsorships'],
mix:[26,24,18,12,8,5,4,3] },
};
/* ---------------------------------------------------------- concept page --- */
function versionPage(h) {
const dark = h.key !== 'broadsheet';
return `<!doctype html><html lang="en"><head>
<meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
<title>RENTV.com — ${h.label} concept</title>
<link rel="preconnect" href="https://fonts.googleapis.com"><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Playfair+Display:ital,wght@0,400;0,600;1,400&family=Cormorant+Garamond:ital,wght@0,400;1,400&family=Inter:wght@300;400;600;800&family=Jost:wght@300;400;500&family=IBM+Plex+Sans:wght@300;400;600&display=swap" rel="stylesheet">
<style>
:root{--bg:${h.bg};--panel:${h.panel};--ink:${h.ink};--gold:${h.gold};--line:${h.line}}
*{margin:0;padding:0;box-sizing:border-box}
body{background:var(--bg);color:var(--ink);font-family:${h.sans};font-size:16px;line-height:1.5;-webkit-font-smoothing:antialiased}
.disp{font-family:${h.disp}}a{color:inherit;text-decoration:none}
.rv{opacity:0;transform:translateY(24px);transition:opacity .7s cubic-bezier(.2,.7,.2,1),transform .7s cubic-bezier(.2,.7,.2,1)}
.rv.in{opacity:1;transform:none}
.badge{position:fixed;left:16px;bottom:16px;z-index:60;background:var(--gold);color:${dark?'#0b0b0c':'#fff'};font-size:10px;letter-spacing:.2em;text-transform:uppercase;padding:7px 13px;border-radius:2px;font-family:${h.sans}}
.util{background:${dark?'#000':'#2a211a'};color:${dark?'#c9ccd1':'#f4e7d5'};font-size:12px}
.util .in{max-width:1200px;margin:0 auto;display:flex;justify-content:space-between;padding:8px 20px}
.tick{display:flex;gap:22px;overflow:hidden;white-space:nowrap}.tick b{color:var(--gold)}
.mast{border-bottom:2px solid var(--gold);max-width:1200px;margin:0 auto;padding:20px}
.mast .in{display:flex;justify-content:space-between;align-items:flex-end}
.logo{font-family:${h.disp};font-weight:${dark?'800':'600'};font-size:34px;letter-spacing:-.5px}.logo span{color:var(--gold)}
.logo small{display:block;font-size:10px;letter-spacing:.3em;text-transform:uppercase;color:var(--gold);margin-top:3px;font-family:${h.sans};font-weight:400}
nav.sec{border-bottom:1px solid var(--line);position:sticky;top:0;z-index:20;background:var(--bg)}
nav.sec .in{max-width:1200px;margin:0 auto;display:flex;gap:2px;overflow:auto;padding:0 12px}
nav.sec a{font-size:12px;font-weight:600;text-transform:uppercase;letter-spacing:.04em;padding:15px 13px;white-space:nowrap;border-bottom:3px solid transparent}
nav.sec a:hover{color:var(--gold);border-color:var(--gold)}
.breaking{background:var(--gold);color:${dark?'#0b0b0c':'#fff'};font-size:13px}
.breaking .in{max-width:1200px;margin:0 auto;display:flex;gap:14px;align-items:center;padding:10px 20px;overflow:hidden}
.breaking b{background:${dark?'#0b0b0c':'#fff'};color:var(--gold);font-size:11px;font-weight:800;text-transform:uppercase;padding:3px 9px;border-radius:2px;white-space:nowrap}
.wrap{max-width:1200px;margin:0 auto;padding:0 20px}
.grid{display:grid;grid-template-columns:1fr 330px;gap:34px;padding:28px 0}
.chip{display:inline-block;font-size:11px;font-weight:800;text-transform:uppercase;letter-spacing:.06em;color:var(--gold);margin-bottom:6px}
.lead .img{aspect-ratio:16/8;border-radius:6px;overflow:hidden;background:linear-gradient(135deg,var(--panel),var(--gold))}
.lead .img img{width:100%;height:100%;object-fit:cover;filter:saturate(.85)}
.lead h1{font-family:${h.disp};font-size:40px;line-height:1.1;margin:14px 0 8px}
.lead p{opacity:.75;font-size:17px;max-width:54ch}.byl{font-size:12px;opacity:.6;margin-top:10px}
.subs{display:grid;grid-template-columns:1fr 1fr;gap:22px;margin-top:24px;border-top:1px solid var(--line);padding-top:22px}
.subs .img{aspect-ratio:16/9;border-radius:5px;background:linear-gradient(135deg,var(--panel),color-mix(in srgb,var(--gold) 60%,var(--panel)))}
.subs h3{font-family:${h.disp};font-size:19px;margin:9px 0 4px;line-height:1.2}.subs p{font-size:13px;opacity:.7}
.sh{display:flex;align-items:center;gap:12px;border-top:3px solid var(--gold);padding-top:10px;margin:30px 0 16px}.sh h2{font-size:15px;text-transform:uppercase;letter-spacing:.06em}
.cards{display:grid;grid-template-columns:1fr 1fr 1fr;gap:22px}
.card .img{aspect-ratio:16/10;border-radius:5px;background:linear-gradient(135deg,var(--panel),color-mix(in srgb,var(--gold) 45%,var(--panel)))}
.card h4{font-family:${h.disp};font-size:17px;line-height:1.22;margin:9px 0 4px}.card .byl{margin-top:6px}
.rail>*{margin-bottom:24px}.box{border:1px solid var(--line);border-radius:6px;padding:18px}
.ns{background:var(--gold);color:${dark?'#0b0b0c':'#fff'};border:0}.ns h3{font-size:18px;margin-bottom:6px}.ns p{font-size:13px;opacity:.85;margin-bottom:12px}
.ns input{width:100%;padding:11px;border:0;border-radius:4px;margin-bottom:8px;font-size:14px}
.ns button{width:100%;padding:11px;background:${dark?'#0b0b0c':'#2a211a'};color:#fff;border:0;border-radius:4px;font-weight:800;text-transform:uppercase;letter-spacing:.06em;font-size:12px;cursor:pointer}
.mr{list-style:none;counter-reset:m}.mr li{counter-increment:m;display:flex;gap:12px;padding:11px 0;border-bottom:1px solid var(--line)}
.mr li::before{content:counter(m);font-family:${h.disp};font-size:24px;color:var(--gold);line-height:1}.mr a{font-size:14px;font-weight:600;line-height:1.25}
.conf{background:linear-gradient(135deg,var(--panel),var(--gold));border-radius:6px;padding:22px;color:#fff}
.conf .k{font-size:11px;letter-spacing:.2em;text-transform:uppercase;opacity:.85}.conf h3{font-family:${h.disp};font-size:22px;margin:6px 0 8px}
.conf a{display:inline-block;background:#fff;color:#111;font-weight:800;font-size:12px;text-transform:uppercase;letter-spacing:.06em;padding:9px 16px;border-radius:4px;margin-top:6px}
.mkt .row{display:flex;justify-content:space-between;padding:7px 0;border-bottom:1px solid var(--line);font-size:13px}.mkt .row:last-child{border:0}
footer{background:${dark?'#000':'#2a211a'};color:${dark?'#aeb6bd':'#f4e7d5'};margin-top:30px;padding:36px 0;font-size:13px}
footer .in{max-width:1200px;margin:0 auto;padding:0 20px;display:grid;grid-template-columns:2fr 1fr 1fr 1fr;gap:24px}
footer .logo{color:#fff;font-size:24px}footer h5{color:var(--gold);font-size:11px;text-transform:uppercase;letter-spacing:.1em;margin-bottom:10px}footer a{display:block;padding:3px 0}
@media(max-width:860px){.grid{grid-template-columns:1fr}.cards,.subs{grid-template-columns:1fr 1fr}}
</style></head><body>
<a class="badge" href="/portal#suggested">◀ Concept · ${h.model} direction</a>
<div class="util"><div class="in"><div class="tick"><span><b>CRE INDEX</b> 4,182 ▲0.6%</span><span><b>10-YR</b> 4.21%</span><span><b>LA VAC</b> 23.1%</span><span><b>IE CAP</b> 5.2%</span></div><div>Subscribe · Log In</div></div></div>
<header class="mast"><div class="in"><div class="logo">REN<span>TV</span>.com<small>${h.label} · ${h.model} direction</small></div><div style="font-size:12px;opacity:.7;text-align:right">Western U.S. Edition<br>Friday, July 17, 2026</div></div></header>
<nav class="sec"><div class="in"><a>Deals</a><a>Sales</a><a>Leases</a><a>Financing</a><a>Development</a><a>Markets</a><a>People</a><a>Conferences</a><a>Video</a></div></nav>
<div class="breaking"><div class="in"><b>Breaking</b><span>$212M multifamily portfolio trades in the San Fernando Valley · Downtown LA tower lands 140K SF lease · IE industrial cap rates compress</span></div></div>
<div class="wrap"><div class="grid">
<main>
<article class="lead rv"><div class="img"><img src="${HERO_IMGS[0]}" alt="" loading="lazy"></div><span class="chip" style="margin-top:14px">Deals · Los Angeles</span><h1 class="disp">Institutional Buyer Pays $212M for 8-Property Valley Multifamily Portfolio</h1><p>One of the largest SoCal multifamily trades of the year signals renewed confidence in workforce housing as rate expectations settle.</p><div class="byl">By RENTV Staff · 2 hours ago · 4 min read</div></article>
<div class="subs"><article class="rv"><div class="img"></div><span class="chip">Financing</span><h3>Bridge Lender Closes $95M Recap on Century City Office</h3><p>Sponsors extend runway as maturities loom across the Westside.</p></article><article class="rv"><div class="img"></div><span class="chip">Leases</span><h3>Life-Science Tenant Takes 140K SF in Pasadena</h3><p>Lab conversions keep the San Gabriel Valley pipeline moving.</p></article></div>
<div class="sh rv"><h2>Latest CRE News</h2></div>
<div class="cards">
<article class="card rv"><div class="img"></div><span class="chip">Sales</span><h4>Inland Empire Warehouse Trades at Record-Low Cap Rate</h4><div class="byl">RENTV Staff · 5h</div></article>
<article class="card rv"><div class="img"></div><span class="chip">Development</span><h4>320-Unit Mixed-Use Project Breaks Ground in San Diego</h4><div class="byl">RENTV Staff · 6h</div></article>
<article class="card rv"><div class="img"></div><span class="chip">Retail</span><h4>Grocery-Anchored Center Sells in Orange County for $61M</h4><div class="byl">RENTV Staff · 8h</div></article>
</div>
</main>
<aside class="rail">
<div class="ns box rv"><h3>The RENTV Daily</h3><p>Western-U.S. commercial real estate deals in your inbox every morning — free.</p><input placeholder="you@company.com"><button>Subscribe free</button></div>
<div class="rv"><div class="sh" style="margin-top:0"><h2>Most Read</h2></div><ol class="mr"><li><a>Blackstone venture buys SoCal logistics campus for $340M</a></li><li><a>Office-to-resi conversions accelerate in DTLA</a></li><li><a>Top 10 Western-U.S. multifamily deals of Q2</a></li><li><a>Where CRE cap rates are heading into 2027</a></li></ol></div>
<div class="conf rv"><div class="k">RENTV Conferences</div><h3>SoCal Real Estate Summit 2026</h3><p style="font-size:13px;opacity:.9">600+ brokers, investors & developers · Sept 24 · Los Angeles.</p><a>Register →</a></div>
<div class="box mkt rv"><div class="sh" style="margin-top:0"><h2>Market Snapshot</h2></div><div class="row"><span>LA Office Vacancy</span><b>23.1%</b></div><div class="row"><span>IE Industrial Cap</span><b>5.2%</b></div><div class="row"><span>SF Multifamily Rent YoY</span><b style="color:var(--gold)">+3.4%</b></div><div class="row"><span>Construction Starts</span><b>−8.7%</b></div></div>
</aside>
</div></div>
<footer><div class="in"><div><div class="logo">REN<span style="color:var(--gold)">TV</span>.com</div><p style="max-width:34ch;opacity:.8;margin-top:8px">CRE news, deals & conferences across the Western U.S. since 1998.</p></div><div><h5>Sections</h5><a>Deals</a><a>Sales</a><a>Leases</a><a>Financing</a></div><div><h5>Company</h5><a>About</a><a>Advertise</a><a>Conferences</a><a>Contact</a></div><div><h5>Follow</h5><a>LinkedIn</a><a>X</a><a>Newsletter</a></div></div></footer>
<div style="max-width:1200px;margin:0 auto;padding:14px 20px;font-size:12px;opacity:.5">Concept "${h.label}" (${h.model} direction) · sample headlines for layout · one of six directions.</div>
<script>
const io=new IntersectionObserver(es=>es.forEach(e=>{if(e.isIntersecting){e.target.classList.add('in');io.unobserve(e.target)}}),{threshold:.12});
document.querySelectorAll('.rv').forEach(el=>io.observe(el));
</script>
</body></html>`;
}
/* ---- Page-by-page teardown (contrarian pass over live screenshots) --------- */
const TEARDOWN=[
{k:'index',u:'rentv.com (homepage)',g:'D+',png:'index.png',
i:['Above the fold is a flea market: a sublease.com banner owns the top-right quarter, plus two more ads and a video box — before a single headline.','Three-column table layout leaves the actual news ~45% of a fixed-width page; nav links are 11px gray text.','Every story gets identical tiny treatment — no lead story, no hierarchy, no way to scan. No bylines, no trust anchors.','"The REview" widget renders as an unexplained black box with no CTA.'],
f:['Kill the top-of-fold ad wall; hero = one featured story card (large image, 24px+ headline, deck, byline).','Responsive grid: full-width hero → card feed → labeled sticky sponsor rail (max 2 ads).','Editorial tiers: lead story, top-3 row, then the feed — type scale does the talking.']},
{k:'advertise',u:'/advertise.php — the AD SALES page',g:'F',
png:'advertise.png',
i:['The page that makes the money is a wall of 12px small print — products listed with no pricing table, no media kit, no visuals of any ad unit.','Zero proof of audience: no open rates, no advertiser logos, no case study. A media buyer closes the tab in 8 seconds.','Sole CTA is "call us / raw email" — no form, no rate-card download, no buy path.','A sublease.com ad sits in the header of the page selling RENTV\u2019s own inventory — self-defeating.'],
f:['Rebuild as a media-kit landing page: 3-tier pricing table (Newsletter / eBlast / Display), audience stats in bold, "Request Media Kit" form.','Add a Current Advertisers logo row + one pull-quote (one phone call gets it).','Remove sublease.com from this page entirely.']},
{k:'subscriber',u:'/subscriber_info.php — the $146/yr member page',g:'D',
png:'subscriber.png',
i:['A real revenue product ($146/yr Executive Subscriber) sold via a dense bullet wall — free vs. paid never cleanly separated; unanswerable in 10 seconds.','No sample issue, no preview, no testimonial, no subscriber count — buying an information product sight-unseen.','CTA is plain text: "CLICK HERE or call us." No visible checkout; beige 2005-registrar aesthetic.','The News Archive is sold as a paid benefit — but the archive page is freely accessible to everyone.'],
f:['Two-column conversion page: benefits (headline + one-liner + frequency) left, price card with live Stripe checkout right — add a $15/mo option.','Publish one Sample Issue link — the single biggest conversion lift available.','Gate the archive or stop selling it; never sell what you give away.']},
{k:'providers',u:'/service-providers.php — the marketplace',g:'F',
png:'providers.png',
i:['~40 categories, every single one "(0)" listings — Accounting (0), Brokerage (0), Construction (0). A directory of failure that trains visitors never to return.','No search, no cards, no map, no filters — a 1999 Yellow Pages list even if inventory existed.','"Don\u2019t Be Left Out!" CTA asks providers to join a visibly empty room.'],
f:['SEED BEFORE RELAUNCH: scrape LA County business-license data + web research (Exa) for CRE-category firms — contractors, brokers, architects, property managers, lenders — and pre-populate 10–15 real listings per major category with phone numbers. Offer each firm its free listing to claim; they upgrade. An empty directory is not a product; a full one is. <a href="/versions/marketplace.html" target="_blank" style="color:#9fd6b0;text-decoration:underline">→ We already built the seeded demo: 62 real LA providers, live here.</a>','Rebuild as a searchable card grid (name, category badge, city, phone, Contact) with geography filter.','Monetize with a Featured Listing tier — after inventory exists, never before.']},
{k:'store',u:'/store.php — conferences/store',g:'D-',
png:'store.png',
i:['Labeled "store," contains no product, price, or buy button — a press page wearing a store costume.','A FUTURE conference (Arizona, Oct 29 2026) is on the page with no Register button, no speakers, no price — revenue advertising that goes nowhere.','Past and future events unfiltered in one feed; sponsor logos outweigh the editorial 2:1.'],
f:['Split: "Upcoming Events" above the fold (date, venue, price, Register Now) vs. "Past Coverage" archive grid.','Sell recorded sessions as an on-demand library: title, price, 90-second preview, buy button.','Rename the tab — Conferences and Store are different intents.']},
{k:'archive',u:'/archive.php',g:'D',
png:'archive.png',
i:['20 bare hyperlinks with no dates, story counts, previews, or search — a filing cabinet with the labels ripped off.','Freely accessible while being sold as a paid subscriber benefit.','No orientation: what years, what geographies, how fresh — unknowable.'],
f:['Full-text search + geography/content-type filters over the archive.','Each link shows recent stories + a count ("482 articles, 2019–2026").','Pick a lane: gate it as a benefit, or use it free to drive newsletter signups.']},
{k:'newsletter',u:'/newsletter.php',g:'D+',
png:'newsletter.png',
i:['NINE fields for a free newsletter (address, zip, phone…) — Bisnow asks for one. Conversion ≈ zero.','Distorted-text homemade CAPTCHA ("rjvxk6") — broken-looking, inaccessible.','Right half of the page is empty void; no pitch, no sample, no reason to sign up — the heading is just "NEWSLETTER."'],
f:['Three fields max: Email (required), Name, Company. Delete the rest.','Invisible reCAPTCHA v3 or honeypot; kill the distorted image.','Add the pitch: "Join 50,000+ CRE professionals · twice-weekly SoCal deals · free" + a sample-issue link.']},
{k:'subscribe',u:'/subscribe.php — the paywall',g:'F',
png:'subscribe.png',
i:['The paywall page is a cartoon dog GIF + "Hold on there sport!" + a login box. That is the entire page every non-subscriber hits.','No subscribe CTA, no path for non-members, no visible password reset — a dead end that costs conversions daily.'],
f:['Replace with a real paywall intercept: what you\u2019re missing, "$146/yr — Subscribe Now" primary button, login secondary.','Remove the dog and "sport" TODAY — before any redesign.','Wire a real password-reset flow; a locked-out subscriber is a churned subscriber.']},
{k:'contact',u:'/contact.php',g:'C-',
png:'contact.png',
i:['Twelve fields including FAX in 2026; same broken CAPTCHA; right half of the page is empty.','No visible email fallback if the form breaks (and on a Windows-1252 site, forms break).'],
f:['Six fields: Name, Company, Email, Phone (opt), Subject dropdown, Message.','Show a direct email + phone under the form; fix the half-empty template site-wide.']},
{k:'jobworks',u:'/jobworks.php — the jobs board',g:'F',
png:'jobworks.png',
i:['Opens with an "Adobe Flash Player is no longer supported" error banner — Flash died Dec 2020; this has greeted every visitor for 5+ years.','Every job category is "(0)" — the second of three marketplace pillars with zero inventory.','Bare "create a listing" link with no pricing, reach, or pitch attached.'],
f:['Delete the Flash widget today; replace with static HTML.','Seed or kill: offer 10–15 subscriber firms free 90-day listings, or pull JobWorks from the nav until it has inventory.','One combined CRE Marketplace landing (live counts + featured listings + "Post a listing" CTA) instead of empty silos.']},
];
const tdCards=TEARDOWN.map(t=>{
const gc=t.g[0]==='F'?'#dc2626':t.g[0]==='D'?'#ea580c':'#ca8a04';
return '<div class="tdp rv"><div class="tdshot"><a href="/portal/audit/'+t.png+'" target="_blank"><img src="/portal/audit/'+t.png+'" loading="lazy" alt="'+t.k+' screenshot"></a><div class="tdcap">live capture · click to open</div></div>'+
'<div class="tdbody"><div class="tdhead"><span class="tdgrade" style="background:'+gc+'">'+t.g+'</span><h3 class="disp">'+t.u+'</h3></div>'+
'<div class="tdl">Issues</div><ul>'+t.i.map(x=>'<li>'+x+'</li>').join('')+'</ul>'+
'<div class="tdl fix">The fix</div><ul class="fixul">'+t.f.map(x=>'<li>'+x+'</li>').join('')+'</ul></div></div>';
}).join('');
/* --------------------------------------------------- analysis app content --- */
const houseTiles = HOUSES.map(h => `
<a class="vtile rv" href="/versions/${h.key}.html" target="_blank" style="--vb:${h.bg};--vi:${h.ink};--vg:${h.gold}">
<div class="vswatch"><span style="background:${h.bg}"></span><span style="background:${h.panel}"></span><span style="background:${h.gold}"></span><span style="background:${h.ink}"></span></div>
<div class="vname">${h.label}</div><div class="vmodel">after ${h.model}</div>
<div class="vmood">${h.mood}</div><div class="vopen">Open live concept →</div>
</a>`).join('');
const competitors = [
['RENTV.com (you)','CRE news · deals · conferences','Western U.S.','Since 1998','Deep regional authority + a live events franchise — on a dated site with dormant social'],
['Bisnow','News + events, national','National','Newsletter-first','The model to study: free newsletters → events → sponsorship. Massive email reach'],
['The Real Deal','CRE news, bold brand','NY / national','Aggressive digital','Strong brand, paywall + events, heavy social + video'],
['Commercial Observer','Editorial CRE','NY / national','Premium editorial','Long-form authority, events, print heritage'],
['GlobeSt (ALM)','News + data','National','Utility / data','Broad coverage, data tools, conference network'],
['CoStar News','Data-backed news','National','Authority / data','Owns the data layer; news drives the CoStar/LoopNet funnel'],
];
const compRows = competitors.map((c,i)=>`<tr class="${i===0?'you':''}"><td>${c[0]}</td><td>${c[1]}</td><td>${c[2]}</td><td>${c[3]}</td><td>${c[4]}</td></tr>`).join('');
/* ---- News-wire + conference rivals, by geography (LA -> CA -> West) --------
* RENTV's real moat is news + a live conference franchise. These are the rivals
* who run that same playbook, mapped from the backyard outward — the closer in,
* the more directly they fight for the same brokers, sponsors & stage. Each
* outlet verified (Jul 2026) to run BOTH news coverage AND its own events. */
const WIRES = [
{ label:'① Los Angeles — the home turf', scope:'Same brokers · same sponsors · same stage',
read:'These outlets compete with RENTV head-on — for the same LA deal coverage, the same sponsor dollars, and the same live audience. This is the tier that matters most, and the one where RENTV’s 25-year local authority plus the State of the Market franchise should win.',
anchor:['RENTV.com — you','CRE news since 1998 + State of the Market conferences','Deep LA / Western-U.S. authority · a live event franchise','—'],
rows:[
['Bisnow — Los Angeles','LA news vertical + a packed LA event calendar (SoCal CRE Finance & Capital Markets, SoCal Industrial)','The newsletter→events→sponsorship machine, run locally','The most direct model rival — but a generic national voice. Out-<i>local</i> it with regional depth & relationships.'],
['Los Angeles Business Journal','LA business news + the 31st-annual CRE Awards (Biltmore, Feb) + Valley CRE Awards','Print/digital + a marquee awards-gala franchise','Broad business focus, not CRE-native. RENTV owns the deal-desk expertise LABJ can’t match.'],
['Connect CRE (California)','CA/LA news + Connect events & meetups; sells session video','Regional news + events + paid video (a REview parallel)','The closest structural twin. RENTV’s edge = a real conference franchise + a 25-yr archive.'],
['The Real Deal — Los Angeles','Aggressive LA CRE news + forums / showcases','Strong brand, heavy digital + social, events','Wins on brand buzz; RENTV wins on regional trust + events. Don’t out-loud them — out-cover them.'],
['NAIOP SoCal','Association news + I.CON West industrial conference (LA, 2026)','Membership + a big industrial conference','An association, not media — a partner as much as a rival (co-brand the event).'],
['ULI Los Angeles','Local research/content + member convenings','Nonprofit authority + events','Authority ally, not a news competitor — a content + panel partner.'],
] },
{ label:'② California — the state fight', scope:'NorCal + SoCal + Inland Empire',
read:'One step out: statewide players and the Bay Area’s own regional shops. RENTV can extend its SoCal authority up the state before the nationals localize any further.',
rows:[
['GlobeSt (ALM)','National CRE news + the GlobeSt Events series (CA multifamily / apartments events)','National authority + a large event slate','A scale rival. Compete on regional intimacy, not national breadth.'],
['Connect CRE — California','Statewide news + events (NorCal, SoCal, Inland Empire)','A regional-news + event network','Direct footprint overlap; RENTV’s conference franchise is the differentiator.'],
['The Registry (Bay Area)','Northern-California CRE news + events','The NorCal analog to RENTV’s SoCal model','Proof the model works up-state — a template to emulate (or partner with) in NorCal.'],
['Bisnow — CA markets','SF, OC, San Diego & Sacramento verticals, each with events','Market-by-market news + events','Same playbook, more markets. RENTV’s answer: own the Western-U.S. regional lane deeper.'],
['InterFace / Western States CREF','CA-focused CRE conferences (Inland Empire; CREF finance)','Conference-led, news-adjacent','Event rivals RENTV can out-flank by pairing coverage WITH the stage.'],
] },
{ label:'③ Western U.S. — the regional model', scope:'The template RENTV can own market-by-market',
read:'The widest tier is less “competitor,” more “proof of model”: regional publishers who pair CRE news with a conference franchise in each Western market — exactly what RENTV can scale from LA outward.',
rows:[
['France Media — Western Real Estate Business + InterFace','The largest regional CRE publisher: magazines + e-news + InterFace conferences across the West','A news + regional-conference machine at scale','The at-scale version of RENTV’s own model — study it, then own the SoCal lane it’s thin in.'],
['Colorado Real Estate Journal (CREJ)','Rocky-Mountain CRE news + the full CREJ Conference Series (Denver, 2026)','A market-owning news + conference franchise','The clearest “do this in your market” blueprint — RENTV = the CREJ of the West Coast.'],
['AZRE / AZ Big Media (Arizona)','Arizona CRE magazine + the AZRE Forum, RED Awards & PTK','State-level news + awards + a forecast forum','Arizona’s RENTV. Same shape, adjacent market — an expansion or partnership target.'],
['Connect CRE (regional West)','Regional news + events across Western metros','A network of regional news + events','Broad but shallow per-market; RENTV wins on depth where it plays.'],
] },
];
function wiresTable(rows, anchor){
const body = (anchor ? `<tr class="you"><td>${anchor[0]}</td><td>${anchor[1]}</td><td>${anchor[2]}</td><td>${anchor[3]}</td></tr>` : '')
+ rows.map(r=>`<tr><td><b>${r[0]}</b></td><td>${r[1]}</td><td>${r[2]}</td><td>${r[3]}</td></tr>`).join('');
return `<table><thead><tr><th>Outlet</th><th>News + conferences</th><th>Model / reach</th><th>RENTV’s angle</th></tr></thead><tbody>${body}</tbody></table>`;
}
const wiresBlocks = WIRES.map((t,i)=>`
<div class="eyebrow"${i?' style="margin-top:52px"':''}>${t.label} · ${t.scope}</div>
<p class="lead2">${t.read}</p>
${wiresTable(t.rows, t.anchor)}`).join('');
const adChannels = [
['LinkedIn (primary)','B2B CRE audience','★★★★★','The CRE audience lives here. Your company page has 818 followers and posts dormant — post daily deal coverage, have staff reshare, run "CRE news" thought-leadership ads.'],
['Email newsletter','Owned audience','★★★★★','Bisnow\'s entire empire is newsletters → events → sponsorship. A free daily/weekly "RENTV Daily" is the single highest-leverage build. You own the list forever.'],
['Google Ads (Search)','High-intent','★★★★☆','Own "commercial real estate news [market]", "[market] office/industrial deals". Capture brokers searching for the deal you just covered.'],
['Sponsored content','Monetize + reach','★★★★☆','Brokerages & lenders pay to co-publish deal analysis. Doubles as revenue AND distribution when they reshare.'],
['RENTV Conferences','Events flywheel','★★★★★','Your events ARE the moat. Cross-promote content↔conferences: every article plugs the summit; every attendee joins the newsletter.'],
['X / Twitter','CRE deal community','★★★☆☆','CRE Twitter breaks + trades deal news. Auto-post headlines, engage brokers; low cost, real reach in-industry.'],
['Programmatic / native','Awareness','★★★☆☆','Run native units on CRE + finance sites to pull new readers into the newsletter funnel. Measure cost-per-subscriber.'],
['SEO','Compounding','★★★★☆','20+ years of archives = a ranking asset. Modernize the site (mobile + speed) and structure deal pages to own "[property] sells" search.'],
];
const adRows = adChannels.map(a=>`<tr><td><b>${a[0]}</b></td><td>${a[1]}</td><td class="stars">${a[2]}</td><td>${a[3]}</td></tr>`).join('');
const calendar = [
['Jan','Year-ahead outlook · forecasts','Publish the "2026 Western-U.S. CRE Outlook"; open annual sponsor packages'],
['Feb','Q4 earnings / REIT results','Cover public-REIT & brokerage earnings; recap year-end deal volume'],
['Mar','SPRING conference season','Peak events: cover + host panels; drive summit registration'],
['Apr','Q1 market reports','Publish quarterly vacancy/cap-rate reports (data content = links + leads)'],
['May','Deal season builds','Sales/leasing volume rises — max deal coverage + newsletter growth push'],
['Jun','Mid-year review','"Biggest deals of H1" roundup — highly shareable, sponsor-friendly'],
['Jul','Summer slow · evergreen','Run explainers, market primers, and build the fall content pipeline'],
['Aug','Pre-fall sell-in','Lock Q4 conference sponsors; tease the fall summit'],
['Sep','FALL conference peak','Your marquee summit — content + events + sponsorship converge'],
['Oct','Q3 reports · deal surge','Quarterly data + heavy transaction coverage (year\'s busiest)'],
['Nov','Year-end deal push','"Deals of the year" build; open next-year sponsor renewals'],
['Dec','Year in review · predictions','Top-10 deals, people moves, and the "what\'s next" predictions issue'],
];
const calRows = calendar.map(c=>`<tr><td class="mo">${c[0]}</td><td>${c[1]}</td><td class="act">${c[2]}</td></tr>`).join('');
const partners = [
['Major brokerages (CBRE, JLL, Cushman, Colliers)','They generate the deals you cover — formalize data-sharing + co-published market reports. Their PR teams feed you scoops; you give their deals reach.'],
['CRE associations (NAIOP, ULI, ICSC, BOMA)','Co-branded content + event cross-promotion. Become the official news partner of the chapters across your Western-U.S. footprint.'],
['CRE data providers (CoStar, Reonomy, CompStak)','License data feeds to power live charts & deal pages — turns your news into a data product competitors can\'t match.'],
['CRE law & finance firms','Sponsor deal-analysis columns ("Financing this week, presented by ___"). Recurring sponsorship + expert bylines that build authority.'],
['Conference & trade-show operators','Co-host or media-partner other CRE events — extend the RENTV Conferences franchise without producing every show yourself.'],
['PropTech startups','Product-spotlight series + demo days. They pay for exposure to your broker/investor audience; you get fresh, forward-looking content.'],
['Universities (USC Lusk, UCLA Ziman)','Research partnerships + academic authority. Co-publish market studies; recruit the next generation of CRE readers early.'],
['City economic-development orgs','Market data + "why invest here" content for every metro you cover — free, credible, SEO-rich local coverage.'],
['CRE lenders & banks','Sponsor the "Financing" vertical + rate/market commentary. Lenders want mindshare with borrowers — you have exactly that audience.'],
['Listing platforms (LoopNet, Crexi, Ten-X)','Deal-flow content partnerships — surface notable listings as news; they drive traffic, you drive their listings.'],
];
const partnerRows = partners.map((p,i)=>`<div class="pcard rv"><div class="pnum">${String(i+1).padStart(2,'0')}</div><div><h4>${p[0]}</h4><p>${p[1]}</p></div></div>`).join('');
const CATS = [['summary','Executive Summary'],['swot','SWOT Analysis'],['lowhanging','Low Hanging Fruit'],['reputation','Reputation & Authority'],['empire','The Empire & Sublease.com'],['competitors','Competitors'],['wires','News + Conference Rivals'],['advertising','Where to Advertise'],['timing','Timing & Cadence'],['audit','Website Audit'],['teardown','Page-by-Page Teardown'],['social','Social Media Audit'],['suggested','Suggested New Websites'],['partners','Unlikely Partners'],['revenue','Unlikely Revenue'],['videos','Video + Brand Films'],['dealdesk','Live Deal Desk (demo)'],['roadmap','90-Day Roadmap'],['sources','Sources & Methodology']];
/* ---- Live Deal Desk (real CRCP data) --------------------------------------- */
const DESK_DEALS = (CRCP.deals || []).filter(d => d.score != null).slice(0, 24);
const DESK_POINTS = [
...(CRCP.deals || []).filter(d => d.lat && d.lng),
...(CRCP.extraPoints || []),
];
const dealCards = DESK_DEALS.map(d => `
<div class="deal rv">
<div class="dscore" data-score="${d.score}">${d.score}</div>
<div class="dbody"><div class="daddr">${d.address}</div><div class="dcity">${d.city} · ${d.type}${d.units ? ' · ' + d.units + ' units' : ''}</div>
<div class="dnums"><span>$${(d.price/1e6).toFixed(2)}M</span>${d.cap_rate ? `<span>${d.cap_rate.toFixed(1)}% cap</span>` : ''}${d.dscr ? `<span>${d.dscr.toFixed(2)} DSCR</span>` : ''}${d.coc ? `<span>${d.coc.toFixed(1)}% CoC</span>` : ''}</div></div>
</div>`).join('');
/* ---- SWOT agent -----------------------------------------------------------
* A self-contained "agent" that runs the four SWOT lenses over the client's
* profile and emits a 2x2 strategic snapshot. Derives Strengths/Weaknesses from
* the reputation read, Opportunities from the revenue + partner playbook, and
* Threats from the competitive landscape — so the quadrant stays consistent with
* the rest of the brief. Reusable: swap SWOT_INPUT per client and it re-runs. */
const SWOT_INPUT = {
strengths: [
'25-year brand & archive — trusted CRE authority since 1998',
'State of the Market conference franchise ($175 ticket, live audience)',
'CRE Talk — 19+ sponsored CEO episodes',
'The REview video platform + an active email operation',
'Owns sublease.com (relaunch plan in hand)',
'Deep, defensible Western-U.S. focus',
],
weaknesses: [
'Dated, pre-mobile website',
'Social accounts dormant & unlinked (LinkedIn 818 followers, idle)',
'No visible newsletter capture — audience not owned',
'No paid distribution',
'Three properties siloed — no cross-linking, separate lists',
],
opportunities: [
'Daily newsletter — convert 25 years of authority into owned audience',
'Relaunch sublease.com as a marketplace attached to the media brand',
'Recurring plans to brokers / agents / broker-dealers ($99–$900+/mo)',
'Package video + brand films for sponsors',
'Referral engines: lenders, PropTech, universities, EDC orgs',
],
threats: [
'National machines out-distribute regionally (Bisnow, CoStar/LoopNet, Crexi, The Real Deal)',
'Younger CRE pros discover news on other platforms',
'Platform algorithm shifts & ad-blocking erode reach',
'CRE downturn softens conference & sponsor spend',
],
};
function swotAgent(input){
const quad = (key,title,cls) => `<div class="swotq ${cls}"><h3>${title}</h3><ul>${(input[key]||[]).map(x=>`<li>${x}</li>`).join('')}</ul></div>`;
return `<div class="swotgrid">
${quad('strengths','Strengths','pos')}
${quad('weaknesses','Weaknesses','neg')}
${quad('opportunities','Opportunities','pos')}
${quad('threats','Threats','neg')}
</div>`;
}
const swotGrid = swotAgent(SWOT_INPUT);
// ---- Low Hanging Fruit (client-facing) — ranks the suggestions bucket by
// ROI = impact/effort and time = effort; flags true quick wins (low effort +
// high impact). Server-rendered from suggestions.json at build time so the
// deliverable is a static, self-contained brief (no runtime fetch/auth). ----
const lhfEsc = (s) => String(s == null ? '' : s).replace(/[&<>]/g, (c) => ({ '&': '&', '<': '<', '>': '>' }[c]));
function lowHangingFruit(list) {
const items = (list || []).filter((s) => s && s.title).map((s) => {
const i = Number(s.impact) || 0, e = Number(s.effort) || 3;
return { title: s.title, category: s.category, rationale: s.rationale, i, e, roi: i / Math.max(1, e), fruit: e <= 2 && i >= 4 };
}).sort((a, b) => b.roi - a.roi || a.e - b.e || b.i - a.i);
const timeLabel = (e) => (e <= 2 ? 'Quick' : e === 3 ? 'Moderate' : 'Involved');
if (!items.length) return '<p class="lead2">No growth moves scored yet.</p>';
return '<ol class="lhf-list">' + items.map((s, idx) =>
`<li class="lhf-item${s.fruit ? ' fruit' : ''} rv"><div class="lhf-rk">${idx + 1}</div><div>` +
`<div class="lhf-ti">${lhfEsc(s.title)}</div>` +
`<div class="lhf-badges">${s.fruit ? '<span class="lhf-b fruit">⚡ Quick win</span>' : ''}` +
`<span class="lhf-b">ROI ${s.roi.toFixed(1)}</span><span class="lhf-b">⏱ ${timeLabel(s.e)}</span>` +
`${s.category ? `<span class="lhf-b">${lhfEsc(s.category)}</span>` : ''}` +
`<span class="lhf-b">impact ${s.i} · effort ${s.e}</span></div>` +
`${s.rationale ? `<p class="lhf-rat">${lhfEsc(s.rationale)}</p>` : ''}</div></li>`
).join('') + '</ol>';
}
const lhfList = lowHangingFruit(SUGGESTIONS);
/* ---- Sources & methodology (data provenance) ------------------------------
* Honest map of where every part of the brief comes from and how it's made, so
* the client can weigh each claim by its provenance. Tiers are colour-coded and
* estimates are flagged AS estimates — never dressed up as measured analytics.
* Add a row when a new data-backed section ships; keep the tier honest. */
const SRC_TIER = {
verified: ['Client-verified', 'v'],
observed: ['Observed live', 'o'],
real: ['Real dataset', 'r'],
derived: ['Computed', 'd'],
analyst: ['Analyst view', 'a'],
estimate: ['Illustrative', 'e'],
illustrative: ['Decorative', 'a'],
generated: ['Generated', 'd'],
};
const SOURCES = [
['Portfolio, owner, team & contact', "The client's own materials — the package supplied by Daniel Ginzburg (CFO, Dandeana Corp), Jul 2026", 'Transcribed into <code>data/client.json</code> and rendered verbatim', 'verified'],
['Sublease.com market size & revenue', '"Sublease.com Business Plan & Market Strategy," April 2026 (confidential, client-supplied)', 'Figures ($650B market, ~$5.9M Year-2 mix) lifted straight from the plan and charted', 'verified'],
['Website & page-by-page audit', 'Live rentv.com — every page loaded and screenshotted directly', 'Adversarial teardown; a grade + fixes authored per page. The dead analytics tag (UA-148799896-1) was read from the live page source', 'observed'],
['Live Deal Desk — listings & map', 'Real LA-area CRE listings sampled from CRCP into <code>data/deals-sample.json</code>', 'Deal scores computed by a transparent weighted model (<code>deal-score.js</code>): rent yield, cap rate, DSCR, financing signals', 'real'],
['Deal Desk — demographics chart', 'U.S. Census median gross rent & income, LA-area cities', 'Carried in the <code>demographics[]</code> block of deals-sample.json and charted live', 'real'],
['SWOT snapshot', 'Derived from the reputation, revenue & competitive reads elsewhere in this brief', 'A small agent (<code>swotAgent()</code>) runs four lenses over one profile so the quadrant stays consistent with the rest', 'derived'],
['Competitors · channels · timing · partners · revenue', 'Analyst strategy, benchmarked to the Bisnow / CoStar / Real Deal / Commercial Observer playbooks', 'Authored as consulting recommendations — industry-standard models, not scraped metrics', 'analyst'],
['News + conference rivals (LA → West)', 'Public web research on each outlet’s news + event programming (Bisnow, Connect CRE, France Media / Western RE Business, CREJ, AZRE, LABJ, The Registry, GlobeSt, NAIOP)', 'Compiled Jul 2026; each outlet’s conference franchise verified from its own events pages', 'observed'],
['Charts (reach, ROI, readership, growth)', 'Illustrative CRE-shaped figures around one real anchor — the observed LinkedIn count (818)', 'Estimates for shape & direction only. The live site ran no analytics for ~3 years, so measured traffic does not exist to chart', 'estimate'],
['Hero & section imagery', 'Unsplash editorial stock (desaturated skyline / CRE photography)', 'Hotlinked, decorative only — carries no data meaning', 'illustrative'],
['Brand films', 'Generated presenter videos (HeyGen) over CRE footage', 'Rendered to <code>/portal/videos/heygen-*.mp4</code>; appear on the page as they finish', 'generated'],
];
const srcRows = SOURCES.map(s => {
const t = SRC_TIER[s[3]] || ['—', 'a'];
return `<tr><td><b>${s[0]}</b></td><td>${s[1]}</td><td>${s[2]}</td><td class="srccell"><span class="srcb ${t[1]}">${t[0]}</span></td></tr>`;
}).join('');
const srcLegend = [...new Set(SOURCES.map(s => s[3]))]
.map(k => { const t = SRC_TIER[k]; return `<span class="srcb ${t[1]}">${t[0]}</span>`; }).join('');
const navLinks = CATS.map(c=>`<a href="#${c[0]}">${c[1].replace(/&/g,'&')}</a>`).join('');
const heroSlides = HERO_IMGS.map((u,i)=>`<div class="slide${i===0?' on':''}" style="background-image:url('${u}')"></div>`).join('');
const app = `<!doctype html><html lang="en"><head>
<meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
<title>RENTV.com — Growth Strategy</title>
<link rel="preconnect" href="https://fonts.googleapis.com"><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Cormorant+Garamond:ital,wght@0,400;0,500;1,400&family=Jost:wght@300;400;500&display=swap" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.1/dist/chart.umd.min.js"></script>
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css">
<link rel="stylesheet" href="https://unpkg.com/leaflet.markercluster@1.5.3/dist/MarkerCluster.css">
<link rel="stylesheet" href="https://unpkg.com/leaflet.markercluster@1.5.3/dist/MarkerCluster.Default.css">
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>
<script src="https://unpkg.com/leaflet.markercluster@1.5.3/dist/leaflet.markercluster.js"></script>
<script src="/portal/deal-score.js"></script>
<style>
:root{--bg:#0c1016;--panel:#121722;--ink:#eef1f6;--gold:#c8a15a;--line:rgba(200,161,90,.22);--dim:rgba(238,241,246,.66)}
*{margin:0;padding:0;box-sizing:border-box}
body{background:var(--bg);color:var(--ink);font-family:'Jost',system-ui,sans-serif;font-size:19px;line-height:1.75;-webkit-font-smoothing:antialiased}
.disp{font-family:'Cormorant Garamond',Georgia,serif}a{color:inherit;text-decoration:none}
.bar{position:fixed;top:0;left:0;right:0;z-index:40;display:flex;align-items:center;justify-content:flex-start;padding:18px 34px;background:linear-gradient(180deg,rgba(12,16,22,.94),rgba(12,16,22,0));backdrop-filter:blur(5px)}
.burger{width:30px;height:20px;position:relative;cursor:pointer;background:none;border:0}.burger span{position:absolute;left:0;right:0;height:1.6px;background:var(--ink);transition:.35s}
.burger span:nth-child(1){top:1px}.burger span:nth-child(2){top:9px}.burger span:nth-child(3){top:17px}
body.nav .burger span:nth-child(1){transform:translateY(8px) rotate(45deg)}body.nav .burger span:nth-child(2){opacity:0}body.nav .burger span:nth-child(3){transform:translateY(-8px) rotate(-45deg)}
.menu{position:fixed;top:0;left:0;bottom:0;width:min(420px,86vw);z-index:39;background:var(--panel);border-right:1px solid var(--line);transform:translateX(-100%);transition:.42s cubic-bezier(.6,0,.2,1);padding:92px 40px;overflow:auto}
.mbrand{display:block;font-family:'Cormorant Garamond',serif;font-size:26px;letter-spacing:.28em;text-transform:uppercase;color:var(--ink);margin-bottom:28px}
.mbrand span{color:var(--gold)}
.mbrand small{display:block;font-family:'Jost',system-ui,sans-serif;font-size:9px;letter-spacing:.32em;color:var(--gold);margin-top:4px}
body.nav .menu{transform:none}body.nav .scrim{opacity:1;pointer-events:auto}
.scrim{position:fixed;inset:0;z-index:38;background:rgba(0,0,0,.5);opacity:0;pointer-events:none;transition:.42s}
.menu .mh{font-family:'Cormorant Garamond',serif;font-size:13px;letter-spacing:.3em;text-transform:uppercase;color:var(--gold);margin-bottom:18px}
.menu a{display:block;font-family:'Cormorant Garamond',serif;font-size:25px;padding:10px 0;border-bottom:1px solid var(--line);opacity:.85;transition:.25s}
.menu a:hover{opacity:1;color:var(--gold);padding-left:8px}
.menu .minfo{margin-top:28px;border-top:1px solid var(--line);padding-top:20px}.menu .minfo p{font-size:13px;line-height:1.7;color:var(--dim);border:0;padding:2px 0}.menu .minfo a{display:inline;font-size:13px;color:var(--gold);border:0;padding:0}
.hero{min-height:96vh;position:relative;display:flex;flex-direction:column;justify-content:center;padding:0 clamp(24px,7vw,120px);overflow:hidden}
.slides{position:absolute;inset:0;z-index:0}
.slide{position:absolute;inset:0;background-size:cover;background-position:center;opacity:0;transform:scale(1.04);transition:opacity 1.4s ease;will-change:transform,opacity}
.slide.on{opacity:1;animation:kenburns 13s ease-out forwards}
@keyframes kenburns{from{transform:scale(1.04) translate3d(0,0,0)}to{transform:scale(1.13) translate3d(-1.4%,-1.2%,0)}}
.hero:after{content:'';position:absolute;inset:0;background:linear-gradient(90deg,rgba(12,16,22,.94),rgba(12,16,22,.6) 55%,rgba(12,16,22,.35));z-index:1}
.hero .in{position:relative;z-index:2;max-width:920px}
.kick{font-size:12px;letter-spacing:.4em;text-transform:uppercase;color:var(--gold);margin-bottom:22px}
.hero h1{font-family:'Cormorant Garamond',serif;font-weight:400;font-size:clamp(44px,7.5vw,104px);line-height:1}.hero h1 span{color:var(--gold)}
.hero p{max-width:62ch;margin-top:24px;font-size:18px;color:var(--dim)}
.metrics{display:flex;flex-wrap:wrap;gap:46px;margin-top:46px}
.metrics .v{font-family:'Cormorant Garamond',serif;font-size:40px;color:var(--gold);line-height:1}
.metrics .l{font-size:11px;letter-spacing:.22em;text-transform:uppercase;color:var(--dim);margin-top:6px}
section{padding:0 clamp(24px,7vw,120px);border-top:1px solid var(--line);scroll-margin-top:60px}
.accbar{display:flex;gap:12px;justify-content:flex-end;padding:14px clamp(24px,7vw,120px);border-top:1px solid var(--line);border-bottom:1px solid var(--line)}
.accbar button{background:none;border:1px solid var(--line);color:var(--gold);font-family:'Jost';font-size:11px;letter-spacing:.18em;text-transform:uppercase;padding:9px 18px;cursor:pointer}.accbar button:hover{background:var(--gold);color:var(--bg)}
.acchead{width:100%;text-align:left;background:none;border:0;cursor:pointer;display:flex;gap:22px;padding:36px 0;color:var(--ink)}
.acchead .htext{flex:1}.eyebrow{font-size:12.5px;letter-spacing:.36em;text-transform:uppercase;color:var(--gold);margin-bottom:12px}
h2{font-family:'Cormorant Garamond',serif;font-weight:400;font-size:clamp(30px,4.4vw,54px);line-height:1.05;max-width:20ch}
.acchead .chev{font-family:'Cormorant Garamond',serif;font-size:36px;color:var(--gold);transition:.3s;line-height:.7}
section.open .chev{transform:rotate(45deg)}.acchead:hover h2{color:var(--gold);transition:.25s}
.accbody{display:none;padding-bottom:60px}section.open .accbody{display:block;animation:af .45s ease}
@keyframes af{from{opacity:0;transform:translateY(-8px)}to{opacity:1;transform:none}}
.lead2{max-width:70ch;color:var(--dim);margin-top:6px;font-size:20px}
table{width:100%;border-collapse:collapse;margin-top:34px;font-size:16px}th,td{text-align:left;padding:16px 14px;border-bottom:1px solid var(--line);vertical-align:top;font-size:15.5px}
th{font-size:11px;letter-spacing:.2em;text-transform:uppercase;color:var(--gold);font-weight:400}
tr.you{background:rgba(200,161,90,.08)}tr.you td:first-child{color:var(--gold)}.stars{color:var(--gold);letter-spacing:2px}
td.mo{font-family:'Cormorant Garamond',serif;color:var(--gold);font-size:18px;width:60px}
.chartwrap{margin-top:34px;background:var(--panel);border:1px solid var(--line);border-radius:8px;padding:22px 20px 14px;position:relative;height:340px}
.chartwrap.tall{height:400px}.chartwrap .ct{font-family:'Cormorant Garamond',serif;font-size:15px;letter-spacing:.2em;text-transform:uppercase;color:var(--gold);margin-bottom:10px}
.cards2{display:grid;grid-template-columns:repeat(auto-fit,minmax(280px,1fr));gap:1px;background:var(--line);margin-top:34px}
.cards2 .c{background:var(--bg);padding:32px 28px}.cards2 .c h3{font-family:'Cormorant Garamond',serif;font-size:22px;color:var(--gold);margin-bottom:10px}.cards2 .c p{color:var(--dim);font-size:16px;line-height:1.6}
.flag{color:#e8a0a0}.good{color:#9fd6b0}
.swotgrid{display:grid;grid-template-columns:repeat(auto-fit,minmax(300px,1fr));gap:1px;background:var(--line);margin-top:34px}
.swotq{background:var(--bg);padding:28px 26px}.swotq h3{font-family:'Cormorant Garamond',serif;font-size:22px;margin-bottom:12px}
.swotq.pos{border-top:2px solid #9fd6b0}.swotq.neg{border-top:2px solid #e8a0a0}
.swotq.pos h3{color:#9fd6b0}.swotq.neg h3{color:#e8a0a0}
.swotq ul{margin:0;padding-left:18px}.swotq li{color:var(--dim);font-size:15px;line-height:1.55;margin:6px 0}
.lhf-list{list-style:none;margin:34px 0 0;padding:0;display:grid;gap:14px}
.lhf-item{display:grid;grid-template-columns:44px 1fr;gap:18px;background:var(--panel);border:1px solid var(--line);border-radius:8px;padding:20px 22px}
.lhf-item.fruit{border-color:var(--gold)}
.lhf-rk{font-family:'Cormorant Garamond',Georgia,serif;font-size:32px;color:var(--gold);line-height:1}
.lhf-ti{font-size:19px;color:var(--ink);font-weight:500;line-height:1.3}
.lhf-badges{display:flex;flex-wrap:wrap;gap:8px;margin:10px 0 0}
.lhf-b{font-size:11px;letter-spacing:.08em;text-transform:uppercase;color:var(--dim);border:1px solid var(--line);padding:4px 10px;border-radius:3px}
.lhf-b.fruit{background:var(--gold);color:var(--bg);border:0;font-weight:700}
.lhf-rat{color:var(--dim);font-size:15px;line-height:1.55;margin-top:10px}
.srclegend{display:flex;flex-wrap:wrap;gap:10px;margin:26px 0 4px}
.srcb{display:inline-block;font-size:10px;letter-spacing:.14em;text-transform:uppercase;padding:5px 11px;border-radius:3px;border:1px solid var(--line);white-space:nowrap}
.srcb.v{color:#9fd6b0;border-color:rgba(159,214,176,.4)}
.srcb.o{color:#78aaff;border-color:rgba(120,170,255,.4)}
.srcb.r{color:var(--gold)}
.srcb.d{color:#b78d3f}
.srcb.a{color:var(--dim)}
.srcb.e{color:#e8a0a0;border-color:rgba(232,160,160,.4)}
td.srccell{white-space:nowrap;vertical-align:middle}
.srcnote{margin-top:34px;display:flex;gap:22px;padding:28px 30px;border:1px solid var(--line);background:var(--panel)}
.srcnote .i{font-size:26px;color:var(--gold);line-height:1}
.srcnote h4{font-family:'Cormorant Garamond',serif;font-size:21px;color:var(--gold);margin-bottom:8px}
.srcnote p{color:var(--dim);font-size:15px;line-height:1.6}
.srcnote code,.accbody td code{font-family:ui-monospace,Menlo,monospace;font-size:12.5px;color:var(--ink);background:rgba(200,161,90,.12);padding:1px 6px;border-radius:3px}
.flagbox{display:flex;gap:22px;margin-top:34px;padding:30px 32px;border:1px solid var(--gold);background:rgba(200,161,90,.07)}
.flagbox .i{font-size:30px;color:var(--gold)}.flagbox h3{font-family:'Cormorant Garamond',serif;font-size:24px;color:var(--gold);margin-bottom:10px}.flagbox p{color:var(--ink);opacity:.92;font-size:16px;line-height:1.6}
.vgrid{display:grid;grid-template-columns:repeat(auto-fit,minmax(280px,1fr));gap:20px;margin-top:20px}
.vtile{background:var(--vb);border:1px solid var(--line);padding:28px 26px;transition:.3s;position:relative}.vtile:hover{transform:translateY(-5px);box-shadow:0 22px 60px rgba(0,0,0,.55)}
.vswatch{display:flex;height:36px;border-radius:3px;overflow:hidden;margin-bottom:20px}.vswatch span{flex:1}
.vname{font-family:'Cormorant Garamond',serif;font-size:26px;color:var(--vi)}.vmodel{font-size:11px;letter-spacing:.14em;text-transform:uppercase;color:var(--vg);margin-top:2px}
.vmood{color:var(--vi);opacity:.72;font-size:13px;margin-top:10px;min-height:38px}.vopen{margin-top:16px;font-size:11px;letter-spacing:.22em;text-transform:uppercase;color:var(--vg)}
.pcard{display:flex;gap:22px;padding:24px 0;border-bottom:1px solid var(--line)}.pnum{font-family:'Cormorant Garamond',serif;font-size:30px;color:var(--gold);min-width:44px}.pcard h4{font-family:'Cormorant Garamond',serif;font-size:21px;margin-bottom:6px}.pcard p{color:var(--dim);font-size:16px;line-height:1.6}
.heybox{margin-top:34px;display:grid;grid-template-columns:minmax(260px,360px) 1fr;gap:1px;background:var(--line);border:1px solid var(--line)}.heybox>div{background:var(--bg)}
.heybox .film{background:#000;position:relative;aspect-ratio:9/16;max-height:520px}.heybox .film video{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}
.heybox .film .ph{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:12px;color:var(--gold);font-size:11px;letter-spacing:.24em;text-transform:uppercase;background:linear-gradient(160deg,#123048,#0c1016);text-align:center;padding:20px}
.heybox .copy{padding:38px 36px}.heybox .copy h3{font-family:'Cormorant Garamond',serif;font-size:27px;margin-bottom:14px}.heybox .copy p{color:var(--dim);font-size:15px}
.heybox .spec{margin-top:20px;display:flex;flex-wrap:wrap;gap:10px}.heybox .spec span{font-size:10px;letter-spacing:.16em;text-transform:uppercase;border:1px solid var(--line);padding:6px 12px;color:var(--gold)}
.films5{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:16px;margin-top:34px}
.f5{border:1px solid var(--line);background:var(--panel)}.f5 .fv{position:relative;aspect-ratio:9/16;background:#000;overflow:hidden}.f5 .fv video{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}
.f5 .fph{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;color:var(--gold);font-size:11px;letter-spacing:.2em;text-transform:uppercase;background:linear-gradient(160deg,#123048,#0c1016);opacity:.9}
.f5 .ft{font-family:'Cormorant Garamond',serif;font-size:19px;color:var(--gold);padding:14px 16px 4px}.f5 .fa{font-size:12.5px;color:var(--dim);padding:0 16px 16px}
.sugg{display:grid;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));gap:1px;background:var(--line);margin-top:20px}.sugg .s{background:var(--bg);padding:26px 24px}.sugg .s .p{font-size:10px;letter-spacing:.2em;text-transform:uppercase;color:var(--gold)}.sugg .s h4{font-family:'Cormorant Garamond',serif;font-size:20px;margin:8px 0}.sugg .s p{font-size:15px;color:var(--dim);line-height:1.55}
.road{list-style:none;margin-top:20px;position:relative;padding-left:36px}
.road:before{content:'';position:absolute;left:9px;top:10px;bottom:10px;width:2px;background:linear-gradient(180deg,var(--gold),rgba(200,161,90,.14));transform:scaleY(0);transform-origin:top;transition:transform 1.5s cubic-bezier(.5,0,.2,1)}
.road.drawn:before{transform:scaleY(1)}
.road li{padding:22px 0;border-bottom:1px solid var(--line);display:flex;gap:26px;position:relative}
.road li:before{content:'';position:absolute;left:-32px;top:30px;width:12px;height:12px;border-radius:50%;background:var(--bg);border:2px solid var(--gold);box-shadow:0 0 0 4px var(--bg);transform:scale(0);transition:transform .5s cubic-bezier(.2,1.5,.4,1)}
.road.drawn li:before{transform:scale(1)}
.road.drawn li:nth-child(1):before{transition-delay:.30s}.road.drawn li:nth-child(2):before{transition-delay:.62s}.road.drawn li:nth-child(3):before{transition-delay:.94s}.road.drawn li:nth-child(4):before{transition-delay:1.26s}
.road .w{font-family:'Cormorant Garamond',serif;color:var(--gold);font-size:15px;letter-spacing:.2em;text-transform:uppercase;min-width:130px}.road .d{color:var(--dim)}
@media(prefers-reduced-motion:reduce){.slide.on{animation:none;transform:scale(1)}.road:before{transition:none;transform:scaleY(1)}.road li:before{transition:none;transform:scale(1)}.accbody{animation:none!important}}
.rv{opacity:0;transform:translateY(22px);transition:opacity .7s cubic-bezier(.2,.7,.2,1),transform .7s cubic-bezier(.2,.7,.2,1)}.rv.in{opacity:1;transform:none}
/* Live Deal Desk (real CRCP data) */
#dealmap{height:440px;border:1px solid var(--line);border-radius:8px;margin-top:34px;background:#0a0d12}
.leaflet-container{background:#0a0d12;font-family:'Jost',sans-serif}
.leaflet-popup-content-wrapper{background:var(--panel);color:var(--ink);border:1px solid var(--line)}
.leaflet-popup-tip{background:var(--panel)}
.dealgrid{display:grid;grid-template-columns:repeat(auto-fill,minmax(300px,1fr));gap:14px;margin-top:30px}
.deal{display:flex;gap:14px;background:var(--panel);border:1px solid var(--line);border-radius:6px;padding:16px;transition:.25s}
.deal:hover{transform:translateY(-3px);box-shadow:0 14px 40px rgba(0,0,0,.4)}
.dscore{min-width:52px;height:52px;border-radius:8px;display:flex;align-items:center;justify-content:center;font-family:'Cormorant Garamond',serif;font-size:24px;color:#fff;background:#555}
.daddr{font-weight:500;font-size:15px;line-height:1.3}
.dcity{font-size:12.5px;color:var(--dim);margin-top:2px}
.dnums{display:flex;flex-wrap:wrap;gap:8px;margin-top:8px}
.dnums span{font-size:11px;letter-spacing:.06em;border:1px solid var(--line);color:var(--gold);padding:3px 8px;border-radius:3px}
/* page-by-page teardown */
.tdp{display:grid;grid-template-columns:minmax(280px,400px) 1fr;gap:26px;padding:34px 0;border-bottom:1px solid var(--line)}
.tdshot img{width:100%;border:1px solid var(--line);border-radius:6px;display:block;transition:.3s}
.tdshot a:hover img{transform:scale(1.02);box-shadow:0 16px 44px rgba(0,0,0,.5)}
.tdcap{font-size:10.5px;letter-spacing:.18em;text-transform:uppercase;color:var(--dim);margin-top:8px;text-align:center}
.tdhead{display:flex;align-items:center;gap:16px;margin-bottom:14px}
.tdhead h3{font-size:clamp(20px,2.2vw,27px);font-weight:400}
.tdgrade{min-width:52px;height:52px;border-radius:8px;display:flex;align-items:center;justify-content:center;font-family:'Cormorant Garamond',serif;font-size:26px;color:#fff}
.tdl{font-size:11px;letter-spacing:.28em;text-transform:uppercase;color:#e8a0a0;margin:14px 0 6px}
.tdl.fix{color:#9fd6b0}
.tdp ul{list-style:none}
.tdp ul li{padding:6px 0 6px 20px;position:relative;color:var(--dim);font-size:15.5px;line-height:1.55}
.tdp ul li:before{content:'✕';position:absolute;left:0;color:#e8a0a0;font-size:12px;top:9px}
.tdp ul.fixul li:before{content:'→';color:#9fd6b0}
@media(max-width:820px){.tdp{grid-template-columns:1fr}}
footer{padding:56px clamp(24px,7vw,120px);border-top:1px solid var(--line);color:var(--dim);font-size:12px;letter-spacing:.14em;text-transform:uppercase;display:flex;justify-content:space-between;flex-wrap:wrap;gap:20px}
@media(max-width:640px){.heybox{grid-template-columns:1fr}.metrics{gap:26px}}
</style></head><body>
<header class="bar"><button class="burger" onclick="document.body.classList.toggle('nav')" aria-label="Menu" aria-expanded="false" aria-controls="portalmenu"><span></span><span></span><span></span></button></header>
<div class="scrim" onclick="document.body.classList.remove('nav')"></div>
<nav class="menu" id="portalmenu" onclick="if(event.target.closest('a'))document.body.classList.remove('nav')">
<a class="mbrand" href="#summary">REN<span>TV</span>.com<small>Growth Strategy · 2026</small></a>
<div class="mh">Contents</div>${navLinks}
<div class="minfo"><div class="mh">RENTV.com, Inc.</div><p>${BIZ.addr}</p>${BIZ.team.map(t=>`<p>${t[0]} — ${t[1]} · ${t[2]}</p>`).join('')}<p><span>rentv.com</span> · <a href="https://www.rentvreview.com" target="_blank" rel="noopener">The REview ↗</a> · <a href="https://www.linkedin.com/company/rentv.com-inc" target="_blank" rel="noopener">LinkedIn ↗</a></p></div>
</nav>
<div class="hero" id="summary">
<div class="slides">${heroSlides}</div>
<div class="in">
<div class="kick">${BIZ.area} · Confidential strategy brief · for Steve Bloom</div>
<h1 class="disp">REN<span>TV</span>.com</h1>
<p>Steve Bloom has quietly built a CRE media <b>empire</b>: the RENTV news brand (est. 1998), the State of the Market conference franchise, the CRE Talk interview show, "The REview" video platform, an active email operation — and the sublease.com domain with a relaunch plan in hand. What's missing is one modern web presence that unifies it, captures the audience, and monetizes the whole. This brief maps exactly that.</p>
<div class="metrics">
<div class="m"><div class="v">3</div><div class="l">Web properties (rentv · REview · sublease)</div></div>
<div class="m"><div class="v" data-c="19">0</div><div class="l">CRE Talk CEO episodes</div></div>
<div class="m"><div class="v" data-c="818">0</div><div class="l">LinkedIn followers (dormant)</div></div>
<div class="m"><div class="v">$175</div><div class="l">Conference ticket · real franchise</div></div>
</div>
</div>
</div>
<div class="accbar"><button id="xall">Expand all</button><button id="call">Collapse all</button></div>
<section id="reputation"><div class="eyebrow">01 · Reputation & Authority</div><h2 class="disp">A trusted name — under-leveraged.</h2><div class="accbody">
<p class="lead2">RENTV has covered Western-U.S. commercial real estate since <b>1998</b> and runs the RENTV Conferences franchise — that's two-plus decades of brand equity and a live events audience most competitors would pay dearly for. The gap isn't credibility; it's <b>distribution and modernization</b>.</p>
<div class="cards2"><div class="c"><h3>Strengths</h3><p class="good">25-year archive & authority · the State of the Market conference franchise · CRE Talk (19+ CEO episodes, sponsored) · The REview video platform · an active email operation · deep Western-U.S. focus.</p></div><div class="c"><h3>Watch-outs</h3><p class="flag">Dated pre-mobile site · social dormant & unlinked · no newsletter capture visible · no paid distribution · younger CRE pros discover news elsewhere.</p></div><div class="c"><h3>Action</h3><p>Modernize the site, turn on a daily newsletter, activate LinkedIn — convert 25 years of authority into owned audience & recurring revenue.</p></div></div>
</div></section>
<section id="swot"><div class="eyebrow">Strategic Snapshot · SWOT</div><h2 class="disp">The whole board on one screen.</h2><div class="accbody">
<p class="lead2">The SWOT agent runs four lenses over RENTV's profile — internal <b>Strengths</b> and <b>Weaknesses</b>, external <b>Opportunities</b> and <b>Threats</b> — so the strategy that follows has a single, honest starting picture.</p>
${swotGrid}
<div class="flagbox" style="margin-top:34px"><div class="i">⚡</div><div><h3 class="disp">Why the low-hanging fruit is low-hanging</h3><p>The quickest wins sit where your <b>Strengths</b> meet your <b>Opportunities</b> — they activate assets you <i>already own</i> (the 25-year brand, the State of the Market conference franchise, the dormant-but-real social accounts, the Constant Contact list) to capture demand that <i>already exists</i>. That is exactly what makes them simple: no new infrastructure, no long build — just switching on what is already there. Ranked by <b>ROI ÷ time</b>, the fastest, highest-return of these — your low-hanging fruit — are listed in order just below.</p></div></div>
</div></section>
<section id="lowhanging"><div class="eyebrow">Strategic Snapshot · Quick Wins</div><h2 class="disp">Your low-hanging fruit, ranked.</h2><div class="accbody">
<p class="lead2">The fastest, highest-return moves — ranked by <b>ROI ÷ time</b> so the quickest wins with the biggest payoff rise to the top. <b>⚡</b> marks a true quick win: low effort, high impact, activating assets you already own.</p>
${lhfList}
</div></section>
<section id="empire"><div class="eyebrow">02 · The Portfolio — one owner, three properties</div><h2 class="disp">You're not a website. You're a media company.</h2><div class="accbody">
<p class="lead2">Verified from your own materials (via Daniel Ginzburg, 2026): Steve Bloom operates <b>three web properties and four content franchises</b>. Today they live in silos — separate sites, separate lists, no cross-linking. Unified, they're a regional CRE media company with a marketplace attached.</p>
<div class="cards2">
<div class="c"><h3>rentv.com</h3><p>The news & resources brand since 1998 — deal coverage, Property Spotlight emails, the trusted name. <span class="flag">Dated pre-mobile build.</span></p></div>
<div class="c"><h3>The REview — rentvreview.com</h3><p>Your video platform "created by RENTV for the real estate industry" — home of CRE Talk's Producer Channel. <b>Boom's main site</b>, and the industry's free video hub. Underexposed.</p></div>
<div class="c"><h3>sublease.com</h3><p>A category-defining premium domain in relaunch phase — with a full business plan already drafted (April 2026). The marketplace leg of the empire.</p></div>
</div>
<div class="cards2" style="margin-top:20px">
<div class="c"><h3>CRE Talk with Steve & Arnie</h3><p>19+ CEO interviews (Shopoff, Rising, Penner, Sigal…), 4 sponsors incl. Rockefeller Group. A real, sponsored show — cut it into shorts and it feeds every channel.</p></div>
<div class="c"><h3>State of the Market Conferences</h3><p>The Greater LA edition: Hilton Culver City, $175/seat, panels with CBRE, Colliers, Cushman, Rexford, Trammell Crow + the CoStar market report. A live franchise competitors can't fake.</p></div>
<div class="c"><h3>Email operation (Constant Contact)</h3><p>Conferences, CRE Talk, and sponsored Property Spotlight sends (e.g. The Hanley Archive) already go out — but the website never captures new readers into the list.</p></div>
</div>
<div style="margin-top:56px"></div>
<div class="eyebrow">The Sublease.com play — from Scott's plan</div>
<h2 class="disp">"The internet's most valuable vacant address in real estate."</h2>
<p class="lead2">The April 2026 business plan (drafted in Claude) maps sublease.com as the definitive two-sided sublease marketplace — residential + commercial — with RENTV as the warm-start: <i>"The RENTV.com relationship gives Sublease.com immediate access to a commercial real estate audience and credibility with brokers."</i> The new RENTV site should be built with that hand-off in mind.</p>
<div class="cards2">
<div class="c"><h3>The market</h3><p><b>$650B+</b> U.S. rental market · <b>40M+</b> renters moving annually · <b>190M sf</b> of commercial sublease inventory · competition rising through 2026.</p></div>
<div class="c"><h3>The model</h3><p>Premium commercial listings ($1.8M Yr-2) · ~3% residential transaction fee ($2.2M) · screening ($600K) · AI sublease agreements ($400K) · broker CRM ($900K) → <b>~$5.9M Yr-2</b>.</p></div>
<div class="c"><h3>The ask</h3><p><b>$2.5M seed</b> · 18-month path to profitability · Phase I: 500 verified listings, 50 brokers, 10K users — the broker network RENTV already owns.</p></div>
</div>
<div class="chartwrap"><div class="ct">Sublease.com — Year-2 revenue mix from the plan ($5.9M)</div><canvas id="subChart"></canvas></div>
<p class="lead2" style="font-size:15px;opacity:.7">Source: "Sublease.com Business Plan & Market Strategy · April 2026" (confidential, attached by Daniel Ginzburg).</p>
</div></section>
<section id="competitors"><div class="eyebrow">03 · Competitive Landscape</div><h2 class="disp">The regional authority vs. the national machines.</h2><div class="accbody">
<p class="lead2">RENTV's edge is regional depth + events. The threats are national newsletter/data machines (Bisnow, CoStar) with huge email reach and modern product.</p>
<div class="chartwrap"><div class="ct">Reach vs. digital modernization — RENTV vs. the field</div><canvas id="compChart"></canvas></div>
<table><thead><tr><th>Outlet</th><th>Focus</th><th>Footprint</th><th>Model</th><th>Read</th></tr></thead><tbody>${compRows}</tbody></table>
<p class="lead2"><b>Takeaway:</b> don't out-scale the nationals — out-<i>local</i> them. Own Western-U.S. deal coverage + events, and copy Bisnow's newsletter→events→sponsorship flywheel at regional scale.</p>
</div></section>
<section id="wires"><div class="eyebrow">Competitive deep-dive · news + conferences</div><h2 class="disp">The rivals who already pair news with a stage.</h2><div class="accbody">
<p class="lead2">RENTV isn’t just a news site — it’s a news brand with a <b>live conference franchise</b> (State of the Market). That pairing is the moat. Below are the outlets running the same <b>news + events</b> playbook, mapped from your backyard outward — <b>Los Angeles → California → the Western U.S.</b> The closer in, the more directly they compete for the same brokers, sponsors, and stage.</p>
${wiresBlocks}
<div class="flagbox" style="margin-top:52px"><div class="i">◆</div><div><h3 class="disp">The wedge nobody owns</h3><p>National machines (Bisnow, GlobeSt, CoStar) out-distribute everyone but speak in a generic voice; the regional models (France Media, CREJ, AZRE) prove a <b>news + conference franchise wins a market</b> — yet none of them own <b>Western-U.S. CRE with a live events franchise and 25 years of local authority</b> the way RENTV can. Modernize distribution — a daily newsletter, an active LinkedIn, a mobile site — and the deep-LA authority + the conference franchise become a position no national or out-of-region rival can copy.</p></div></div>
</div></section>
<section id="advertising"><div class="eyebrow">04 · Where to Advertise & Grow</div><h2 class="disp">Build the owned audience first.</h2><div class="accbody">
<p class="lead2">Ranked by ROI for a regional CRE-news brand. The pattern: <b>newsletter + LinkedIn</b> (owned + B2B) first, then search + sponsorship.</p>
<div class="chartwrap"><div class="ct">Channel priority — relative ROI for a CRE-news brand</div><canvas id="adChart"></canvas></div>
<table><thead><tr><th>Channel</th><th>Best for</th><th>Priority</th><th>Why / play</th></tr></thead><tbody>${adRows}</tbody></table>
</div></section>
<section id="timing"><div class="eyebrow">05 · Timing & Cadence</div><h2 class="disp">Ride the deal + conference calendar.</h2><div class="accbody">
<p class="lead2">CRE news demand tracks the transaction & events calendar — quarterly reports, spring & fall conference seasons, year-end roundups. Publish daily; spike coverage on the peaks.</p>
<div class="chartwrap"><div class="ct">Deal activity vs. readership by month</div><canvas id="timeChart"></canvas></div>
<table><thead><tr><th>Month</th><th>Driver</th><th>The move</th></tr></thead><tbody>${calRows}</tbody></table>
<p class="lead2"><b>Posting rhythm:</b> daily deal briefs, a weekly roundup newsletter, LinkedIn 1–2×/day on weekday mornings when brokers scan. Publish quarterly data reports on schedule — they earn links and leads.</p>
</div></section>
<section id="audit"><div class="eyebrow">06 · Website Audit</div><h2 class="disp">A 1998 site for a 2026 audience.</h2><div class="accbody">
<p class="lead2">Live audit of <b>rentv.com</b> — observed directly:</p>
<div class="cards2">
<div class="c"><h3>Architecture</h3><p class="flag">Legacy <b>table-based layout</b> with <b>window.open() popups</b> and non-UTF-8 encoding — a pre-responsive build. Breaks on mobile, where most CRE reading now happens.</p></div>
<div class="c"><h3>First impression</h3><p>No modern hero, no motion, dense text. The #1 upgrade: a <b>clean editorial front page</b> with a lead story, card grid, and a newsletter capture above the fold.</p></div>
<div class="c"><h3>Mobile & speed</h3><p class="flag">Not mobile-responsive; heavy legacy markup. Brokers scan on phones between meetings — this is lost readership every day.</p></div>
<div class="c"><h3>Conversion</h3><p>No visible newsletter capture or clear subscribe path. Every visitor should be one click from joining the list — the audience you own forever.</p></div>
</div>
<p class="lead2">Six ready-to-review redesign concepts below — each modeled on a CRE-news leader, with a modern editorial front page already built.</p>
</div></section>
<section id="teardown"><div class="eyebrow">07 · Page-by-Page Teardown</div><h2 class="disp">Every page, graded — with the fix.</h2><div class="accbody">
<p class="lead2">We captured every page of rentv.com live and put each through an adversarial review. The pattern: <b>the content operation works — the website destroys it at every conversion point.</b> Headline finding: the site still runs <b>Universal Analytics (UA-148799896-1)</b>, which Google shut down in 2023 — <b>there has been no traffic data for ~3 years</b>. Every decision below is currently being made blind.</p>
${tdCards}
<p class="lead2" style="margin-top:30px"><b>Overall verdict:</b> a site that was genuinely valuable in 2005 and has received near-zero strategic investment since. News still publishes, conferences still run, and 50,000 opt-in subscribers is a real asset — but a broken Flash banner, an all-zeros marketplace, a cartoon-dog paywall and a phone-number ad page are actively destroying that asset. First fix, before any redesign: <b>install GA4 today</b> — until RENTV knows its own traffic, everything else is guesswork.</p>
</div></section>
<section id="social"><div class="eyebrow">08 · Social Media Audit</div><h2 class="disp">Real accounts, dormant and hidden.</h2><div class="accbody">
<div class="flagbox"><div class="i">⚠</div><div><h3 class="disp">You already make the content — it just never reaches the channels</h3><p>RENTV runs a real email operation (Constant Contact: Conferences, CRE Talk, sponsored Property Spotlights) and produces a real video show — yet the <b>LinkedIn page (818 followers) sits dormant</b>, <b>nothing is linked from rentv.com</b>, there's <b>no X or Instagram</b>, <b>no on-site newsletter capture</b>, and <b>zero paid distribution</b>. The content engine exists; the distribution engine was never plugged in. That's the single biggest growth lever on this list — and it's mostly free.</p></div></div>
<div class="chartwrap" style="margin-top:34px"><div class="ct">LinkedIn growth potential — activate + post daily (projection)</div><canvas id="socialChart"></canvas></div>
<div class="cards2" style="margin-top:34px">
<div class="c"><h3>LinkedIn — 818 followers</h3><p>Your #1 channel, dormant. <b>Fix:</b> link it site-wide, post daily deal coverage, have staff reshare, run thought-leadership ads. This is where the CRE audience & the sponsor money are.</p></div>
<div class="c"><h3>Facebook</h3><p class="flag">Exists, dormant. <b>Fix:</b> auto-syndicate headlines; low priority vs. LinkedIn but keep it current for older readers & reviews.</p></div>
<div class="c"><h3>X / Twitter — none</h3><p>CRE Twitter breaks & trades deal news. <b>Fix:</b> stand up @RENTV, auto-post headlines, engage brokers. Cheap, real in-industry reach.</p></div>
<div class="c"><h3>YouTube / Instagram — the CRE Talk goldmine</h3><p>You produce <b>CRE Talk</b> (19+ CEO episodes) and own <b>The REview</b> video platform — but neither feeds YouTube Shorts or IG Reels. Cut every episode into 30-second clips and the next generation of CRE pros finds you weekly.</p></div>
</div>
</div></section>
<section id="suggested"><div class="eyebrow">09 · Suggested New Websites</div><h2 class="disp">Six directions — each after a CRE-news leader.</h2><div class="accbody">
<p class="lead2">Modern, editorial, mobile-first — modeled on the outlets winning CRE news today. Each opens as a working front-page concept with real layout & motion. Pick a direction; we build it out.</p>
<div class="vgrid">${houseTiles}</div>
</div></section>
<section id="partners"><div class="eyebrow">10 · Unlikely Partners</div><h2 class="disp">Ten referral engines hiding in the industry.</h2><div class="accbody">
<p class="lead2">Your readers & sponsors already sit inside these organizations. Content + data + event swaps turn them into a low-cost pipeline of audience and revenue.</p>
${partnerRows}
</div></section>
<section id="revenue"><div class="eyebrow">11 · Unlikely Revenue Streams</div><h2 class="disp">The audience is the asset. It can earn eight ways.</h2><div class="accbody">
<p class="lead2">News is the draw — but the brand, the list, and the events can each throw off high-margin recurring revenue. Bisnow proved the model; you have the regional authority to run it.</p>
<div class="chartwrap tall"><div class="ct">Target revenue mix</div><canvas id="revChart"></canvas></div>
<div class="cards2" style="margin-top:34px">
<div class="c"><h3>① Premium subscriptions</h3><p>A paid tier for deep deal data, archives & early access — recurring revenue off your most engaged readers.</p></div>
<div class="c"><h3>② RENTV Conferences (expand)</h3><p>Your events franchise is the crown jewel — add markets, sponsorships & ticket tiers. Content feeds events; events feed the list.</p></div>
<div class="c"><h3>③ Sponsored content</h3><p>Brokerages & lenders pay to co-publish deal analysis — revenue that also reshares into new reach.</p></div>
<div class="c"><h3>④ Newsletter sponsorships</h3><p>The Bisnow engine: a daily newsletter with a sponsor slot. Own the inbox, sell the placement.</p></div>
<div class="c"><h3>⑤ Data & market reports</h3><p>Package quarterly vacancy/cap-rate/deal-volume data into paid reports — high-margin, link-earning, lead-generating.</p></div>
<div class="c"><h3>⑥ CRE job board</h3><p>A careers board for brokers, analysts & developers — recurring listings revenue on an audience employers want.</p></div>
<div class="c"><h3>⑦ Webinars & virtual events</h3><p>Sponsored market-outlook webinars between the big conferences — low cost, high sponsor value.</p></div>
<div class="c"><h3>⑧ Video sponsorships</h3><p>Your video programming, sponsored: "Deal of the Week, presented by ___." Monetize content you already make.</p></div>
</div>
<div style="margin-top:56px"></div>
<div class="eyebrow">Sell PLANS to brokers, agents & broker-dealers — recurring cash flow</div>
<h2 class="disp">Turn the audience into subscribers with a rate card.</h2>
<p class="lead2">The Hanley Archive proves it: brokerages already pay RENTV to reach this audience. Productize that into published tiers — monthly cash flow instead of one-off sponsorships. Every deal you cover is a sales lead for a plan.</p>
<table><thead><tr><th>Plan</th><th>Who</th><th>Monthly</th><th>What they get</th></tr></thead><tbody>
<tr><td><b>Agent</b></td><td>Individual agents</td><td>$99</td><td>Profile page · their closings published as deal briefs · newsletter mention · directory listing</td></tr>
<tr><td><b>Broker Pro</b></td><td>Top producers</td><td>$299</td><td>Everything in Agent + priority deal coverage · quarterly CRE Talk clip feature · Property Spotlight slot</td></tr>
<tr><td><b>Brokerage</b></td><td>Firms / teams</td><td>$999</td><td>Firm-wide profiles · all closings covered · co-branded quarterly market report · conference discounts</td></tr>
<tr><td><b>Capital Partner</b></td><td>Lenders / broker-dealers / title</td><td>$2,500</td><td>Vertical sponsorship ("Financing presented by ___") · CRE Talk episode sponsor · conference panel seat · lead flow</td></tr>
</tbody></table>
<p class="lead2" style="font-size:15px;opacity:.75">100 Agent + 30 Broker Pro + 10 Brokerage + 6 Capital Partner ≈ <b>$44K/mo (~$530K/yr) recurring</b> — before conferences or the sublease.com broker CRM line ($900K in the plan).</p>
<div style="margin-top:48px"></div>
<div class="eyebrow">The Zoom economy — unlikely, high-margin, zero build</div>
<h2 class="disp">Paid calls: the fastest cash flow you can turn on.</h2>
<div class="sugg">
<div class="s"><div class="p">Monthly · $49/seat</div><h4>State of the Market LIVE</h4><p>A monthly Zoom market briefing — the conference franchise, miniaturized. Sponsor slot + paid seats; free for plan subscribers (drives upgrades).</p></div>
<div class="s"><div class="p">Members · $99/seat</div><h4>CEO Office Hours</h4><p>A CRE Talk alum (Shopoff, Rising, Sigal…) takes questions for 60 minutes, members-only. The guest list already exists — it's your show's rolodex.</p></div>
<div class="s"><div class="p">Quarterly · $199</div><h4>Broker Masterminds</h4><p>Curated 8-seat Zoom roundtables by asset class (industrial / multifamily / retail). Scarcity pricing; brokers pay to be in the room.</p></div>
<div class="s"><div class="p">Marketplace · 20% take</div><h4>Book-a-Dealmaker</h4><p>30-minute 1:1 calls with top brokers & lenders, booked through RENTV. They set the rate; RENTV takes 20% and owns the relationship.</p></div>
<div class="s"><div class="p">Per event · listing fee</div><h4>Deal War-Rooms</h4><p>Brokers pitch live listings to an investor audience on Zoom — listing fee + paid seats. Deal flow becomes an event.</p></div>
<div class="s"><div class="p">Sponsored · CE-style</div><h4>Paid Webinar Series</h4><p>"Financing in 2027," "1031 in practice" — lender-sponsored educational Zooms with paid certificates of attendance.</p></div>
</div>
</div></section>
<section id="videos"><div class="eyebrow">12 · Video + Brand Films</div><h2 class="disp">You make video — package it to sell.</h2><div class="accbody">
<p class="lead2">RENTV already produces <b>CRE Talk with Steve & Arnie</b> (Shopoff, Rising Realty, Mosaic, NewMark Merrill and 15+ more CEO interviews) and hosts it on <b>The REview</b> — plus a full conference program each year. That's a sponsored content library most CRE outlets would kill for. Standardize it into short, mobile-first formats and add a presenter-led brand film.</p>
<div style="margin-top:10px"></div>
<div class="eyebrow">The upgrade — a presenter over YOUR footage</div>
<h2 class="disp">A host, over real CRE footage. Motion, music, one action item.</h2>
<p class="lead2">The format to standardize: RENTV's own market/conference footage as the backdrop, a polished presenter delivering one message, fade in/out, a music bed, one clear CTA. Drop-in for LinkedIn, ads & the site hero.</p>
<div class="heybox">
<div class="film"><video id="heyfilm" autoplay muted loop playsinline></video><div class="ph" id="heyph">● RENTV brand film<br>presenter over your footage<br>— renders here when ready</div></div>
<div class="copy"><h3 class="disp">"The deal desk of the West."</h3><p>Presenter script: <i>"Since 1998, RENTV has covered the deals that move Western commercial real estate. Home of CRE Talk with Steve & Arnie, the State of the Market conferences, and The REview. Your action item: get it first — subscribe to the RENTV Daily."</i></p><div class="spec"><span>◐ Fade in / out</span><span>♪ Music bed</span><span>▶ Action item</span><span>🏙 Your footage</span><span>15–30s · LinkedIn</span></div></div>
</div>
<div style="margin-top:60px"></div>
<div class="eyebrow">New video formats to make</div>
<h2 class="disp">Eight shorts that own CRE attention.</h2>
<div class="sugg">
<div class="s"><div class="p">Daily · Deals</div><h4>Deal of the Week</h4><p>60-second breakdown of the biggest trade — who, how much, why it matters.</p></div>
<div class="s"><div class="p">Data · Weekly</div><h4>Market Minute</h4><p>One chart, one takeaway — cap rates, vacancy, absorption. Repurpose the report data.</p></div>
<div class="s"><div class="p">Events</div><h4>Conference Recap</h4><p>Cut every RENTV Conferences panel into shareable clips — content + promo in one.</p></div>
<div class="s"><div class="p">People</div><h4>Broker / Investor Spotlight</h4><p>Two-minute interview series — access is your moat; put faces on the deals.</p></div>
<div class="s"><div class="p">Explainer</div><h4>Why This Deal Matters</h4><p>Context video for the non-expert — grows the audience beyond insiders.</p></div>
<div class="s"><div class="p">Quarterly</div><h4>The Outlook</h4><p>A polished quarterly market outlook — a sponsor-ready flagship video.</p></div>
<div class="s"><div class="p">Development</div><h4>Groundbreaking Tour</h4><p>Walk the projects reshaping each metro — visual, shareable, developer-friendly.</p></div>
<div class="s"><div class="p">Annual</div><h4>Year in Review</h4><p>Top deals, people moves & predictions — the December franchise video.</p></div>
</div>
<div style="margin-top:60px"></div>
<div class="eyebrow">Five brand films — one per recommendation</div>
<h2 class="disp">Presenter shorts, each ending on an action item.</h2>
<p class="lead2">Each renders here as it finishes (refresh to pick up new ones).</p>
<div class="films5">
<div class="f5" data-key="reputation"><div class="fv"><video muted loop playsinline></video><div class="fph">● rendering</div></div><div class="ft">Authority</div><div class="fa">▶ Modernize + own the region</div></div>
<div class="f5" data-key="advertising"><div class="fv"><video muted loop playsinline></video><div class="fph">● rendering</div></div><div class="ft">Grow</div><div class="fa">▶ Newsletter + LinkedIn</div></div>
<div class="f5" data-key="competitors"><div class="fv"><video muted loop playsinline></video><div class="fph">● rendering</div></div><div class="ft">Compete</div><div class="fa">▶ Out-local the nationals</div></div>
<div class="f5" data-key="timing"><div class="fv"><video muted loop playsinline></video><div class="fph">● rendering</div></div><div class="ft">Timing</div><div class="fa">▶ Own the deal calendar</div></div>
<div class="f5" data-key="social"><div class="fv"><video muted loop playsinline></video><div class="fph">● rendering</div></div><div class="ft">Social</div><div class="fa">▶ Activate LinkedIn today</div></div>
</div>
</div></section>
<section id="dealdesk"><div class="eyebrow">13 · Live Deal Desk — demo with REAL data</div><h2 class="disp">What your modernized site can do: live, scored deal data.</h2><div class="accbody">
<p class="lead2">This is not a mockup — it's a working demo running on <b>real Los Angeles CRE listings</b> (multifamily, retail, mixed-use) with real cap rates and a transparent 0–100 deal score. A modernized RENTV pairs your deal <i>reporting</i> with live deal <i>data</i> like this — the product wedge none of the news competitors ship regionally.</p>
<div id="dealmap"></div>
<p class="lead2" style="font-size:15px;margin-top:14px;opacity:.7">Clustered map of live LA-area commercial listings · zoom to explode clusters · click a marker for price & type.</p>
<div class="chartwrap"><div class="ct">Real Census market data — median rent vs. income, LA-area cities</div><canvas id="demoChart"></canvas></div>
<div class="dealgrid">${dealCards}</div>
<p class="lead2" style="font-size:15px;margin-top:16px;opacity:.7">Scores computed by a transparent weighted model (rent yield, cap rate, DSCR, financing signals) — every badge explains itself. Data: live LA CRE listing sample, July 2026.</p>
</div></section>
<section id="roadmap"><div class="eyebrow">14 · 90-Day Roadmap</div><h2 class="disp">What to do, in order.</h2><div class="accbody">
<ul class="road">
<li><div class="w">Weeks 1–2</div><div class="d">Cross-link the empire: rentv.com ↔ The REview ↔ conferences, everywhere. Link LinkedIn + Facebook site-wide and begin daily posting. Put a newsletter capture on every page (the Constant Contact lists already exist). Pick a website direction from the six concepts.</div></li>
<li><div class="w">Weeks 3–6</div><div class="d">Ship the new mobile-first front page. Launch the free "RENTV Daily" newsletter. Start Google Ads on regional CRE-news keywords. Sign the first sponsored-content partner.</div></li>
<li><div class="w">Weeks 6–10</div><div class="d">Open conference-sponsor + newsletter-sponsor packages. Sign 3 "unlikely partner" swaps (a brokerage, an association, a lender). Publish the first quarterly data report.</div></li>
<li><div class="w">Weeks 10–13</div><div class="d">Launch the video formats (Deal of the Week, Market Minute) + the presenter brand film. Measure cost-per-subscriber & sponsor pipeline; double down on the winner.</div></li>
</ul>
</div></section>
<section id="sources"><div class="eyebrow">15 · Sources & Methodology</div><h2 class="disp">Where every number comes from — and how.</h2><div class="accbody">
<p class="lead2">A brief is only as trustworthy as its sourcing, so here is the whole provenance map. Each row states <b>where the data came from</b> and <b>how it was produced</b> — and anything that is an estimate is labelled an estimate, never dressed up as measured analytics.</p>
<div class="srclegend">${srcLegend}</div>
<table><thead><tr><th>Section of the brief</th><th>Where it comes from</th><th>How it’s produced</th><th>Provenance</th></tr></thead><tbody>${srcRows}</tbody></table>
<div class="srcnote"><div class="i">⚙</div><div><h4>How this document is built</h4><p>This portal is generated, not hand-typed. Client-supplied facts live in <code>data/*.json</code>; a build step (<code>build.mjs</code>) renders them into the page and redraws the charts & map on every deploy — so the brief updates when the underlying data does. Nothing is invented at page-load: the charts read fixed datasets, the Deal Desk reads a real listing sample, and projections appear only where the row above is labelled <b>Illustrative</b>.</p></div></div>
</div></section>
<footer><span>RENTV.com · Growth Strategy Brief</span><span>Prepared for the ${new Date().getFullYear()} consulting review</span><span>Confidential — for discussion</span></footer>
<script>
(function(){var s=document.querySelectorAll('.hero .slide'),i=0;if(s.length<2)return;setInterval(function(){s[i].classList.remove('on');i=(i+1)%s.length;s[i].classList.add('on');},5200);})();
var REDUCE=window.matchMedia&&window.matchMedia('(prefers-reduced-motion:reduce)').matches;
function countUp(el){var t=+el.dataset.c;if(!t)return;if(REDUCE){el.textContent=t.toLocaleString();return;}var d=1300,st=null;function step(ts){st=st||ts;var p=Math.min((ts-st)/d,1),e=1-Math.pow(1-p,3);el.textContent=Math.round(t*e).toLocaleString();if(p<1)requestAnimationFrame(step);}requestAnimationFrame(step);}
var secs=[].slice.call(document.querySelectorAll('section[id]'));var accs=[];
secs.forEach(function(sec){var eb=sec.querySelector(':scope>.eyebrow'),h2=sec.querySelector(':scope>h2');if(!eb&&!h2)return;accs.push(sec);
var head=document.createElement('button');head.type='button';head.className='acchead';var txt=document.createElement('div');txt.className='htext';if(eb)txt.appendChild(eb);if(h2)txt.appendChild(h2);
var chev=document.createElement('span');chev.className='chev';chev.textContent='+';head.appendChild(txt);head.appendChild(chev);sec.insertBefore(head,sec.querySelector('.accbody'));
head.addEventListener('click',function(){var open=sec.classList.toggle('open');chev.textContent=open?'\\u2013':'+';if(open){initCharts();initDesk();drawRoad(sec);}});});
function drawRoad(sec){var rd=sec.querySelector('.road');if(rd)setTimeout(function(){rd.classList.add('drawn');},140);}
function setAll(o){accs.forEach(function(s){s.classList.toggle('open',o);var c=s.querySelector('.chev');if(c)c.textContent=o?'\\u2013':'+';if(o)drawRoad(s);});if(o){initCharts();initDesk();}}
document.getElementById('xall').onclick=function(){setAll(true);};document.getElementById('call').onclick=function(){setAll(false);};
document.querySelectorAll('.menu a[href^="#"]').forEach(function(a){a.addEventListener('click',function(){var id=a.getAttribute('href').slice(1),s=document.getElementById(id);if(s&&!s.classList.contains('open')&&s.querySelector('.acchead')){s.querySelector('.acchead').click();}if(s)setTimeout(function(){s.scrollIntoView({behavior:'smooth'});},80);});});
// Keep the burger's aria-expanded in sync with body.nav no matter which path (burger, scrim, or a menu link) toggles it.
(function(){var burger=document.querySelector('.burger');if(!burger)return;function sync(){burger.setAttribute('aria-expanded',document.body.classList.contains('nav'));}new MutationObserver(sync).observe(document.body,{attributes:true,attributeFilter:['class']});sync();})();
var io=new IntersectionObserver(function(es){es.forEach(function(e){if(e.isIntersecting){e.target.classList.add('in');io.unobserve(e.target);}});},{threshold:.12});
document.querySelectorAll('.rv').forEach(function(el){io.observe(el);});
document.querySelectorAll('.metrics .v[data-c]').forEach(function(el){var mo=new IntersectionObserver(function(es){es.forEach(function(e){if(e.isIntersecting){countUp(el);mo.unobserve(el);}});});mo.observe(el);});
var charted=false;
function initCharts(){if(charted||!window.Chart)return;charted=true;
var gold='#c8a15a',dim='rgba(238,241,246,.6)',line='rgba(200,161,90,.18)';Chart.defaults.color=dim;Chart.defaults.font.family='Jost,system-ui,sans-serif';
var RM=window.matchMedia&&window.matchMedia('(prefers-reduced-motion:reduce)').matches;
Chart.defaults.animation=RM?false:{duration:1150,easing:'easeInOutQuart'};
if(!RM){Chart.defaults.animations={y:{from:function(c){return c.chart.scales.y?c.chart.scales.y.getPixelForValue(0):0;}}};}
var C=${JSON.stringify(CHART)};
new Chart(document.getElementById('compChart'),{type:'bar',data:{labels:C.competitors.labels,datasets:[{label:'Audience reach',data:C.competitors.reach,backgroundColor:'rgba(200,161,90,.75)'},{label:'Digital modernization',data:C.competitors.digital,backgroundColor:'rgba(120,170,255,.6)'}]},options:{responsive:true,maintainAspectRatio:false,scales:{y:{grid:{color:line},max:100},x:{grid:{display:false}}},plugins:{legend:{labels:{color:dim}}}}});
new Chart(document.getElementById('adChart'),{type:'bar',data:{labels:C.advertising.labels,datasets:[{label:'Relative ROI',data:C.advertising.roi,backgroundColor:C.advertising.roi.map(function(v){return v>=88?'rgba(200,161,90,.85)':'rgba(200,161,90,.4)';})}]},options:{indexAxis:'y',responsive:true,maintainAspectRatio:false,scales:{x:{grid:{color:line},max:100},y:{grid:{display:false}}},plugins:{legend:{display:false}}}});
new Chart(document.getElementById('timeChart'),{type:'line',data:{labels:C.timing.labels,datasets:[{label:'Deal activity',data:C.timing.deals,borderColor:gold,backgroundColor:'rgba(200,161,90,.12)',fill:true,tension:.4},{label:'Readership',data:C.timing.readership,borderColor:'#78aaff',backgroundColor:'rgba(120,170,255,.08)',fill:true,tension:.4}]},options:{responsive:true,maintainAspectRatio:false,scales:{y:{grid:{color:line}},x:{grid:{display:false}}}}});
new Chart(document.getElementById('socialChart'),{type:'line',data:{labels:C.social.labels,datasets:[{label:'LinkedIn followers (projected)',data:C.social.linkedin,borderColor:gold,backgroundColor:'rgba(200,161,90,.14)',fill:true,tension:.4,pointRadius:4}]},options:{responsive:true,maintainAspectRatio:false,scales:{y:{grid:{color:line}},x:{grid:{display:false}}},plugins:{legend:{display:false}}}});
new Chart(document.getElementById('revChart'),{type:'doughnut',data:{labels:C.revenue.labels,datasets:[{data:C.revenue.mix,backgroundColor:['#c8a15a','#b78d3f','#a67c32','#d9b877','#8f6d2c','#e3c98d','#7c5f26','#efd9a3'],borderColor:'#0c1016',borderWidth:2}]},options:{responsive:true,maintainAspectRatio:false,plugins:{legend:{position:'right',labels:{color:dim,boxWidth:12}}},cutout:'58%'}});
if(document.getElementById('subChart')){new Chart(document.getElementById('subChart'),{type:'doughnut',data:{labels:['Premium listings (comm.)','Transaction fee (resi.)','Broker CRM & leads','Tenant screening','AI legal docs'],datasets:[{data:[1.8,2.2,0.9,0.6,0.4],backgroundColor:['#c8a15a','#78aaff','#37d39a','#d9b877','#8f6d2c'],borderColor:'#0c1016',borderWidth:2}]},options:{responsive:true,maintainAspectRatio:false,plugins:{legend:{position:'right',labels:{color:dim,boxWidth:12}}},cutout:'58%'}});}
var DG=${JSON.stringify((CRCP.demographics || []))};
if(DG.length&&document.getElementById('demoChart')){new Chart(document.getElementById('demoChart'),{type:'bar',data:{labels:DG.map(function(x){return x.city;}),datasets:[{label:'Median gross rent ($/mo)',data:DG.map(function(x){return x.rent;}),backgroundColor:'rgba(200,161,90,.8)',yAxisID:'y'},{label:'Median income ($k/yr)',data:DG.map(function(x){return Math.round(x.income/1000);}),backgroundColor:'rgba(120,170,255,.6)',yAxisID:'y1'}]},options:{responsive:true,maintainAspectRatio:false,scales:{y:{grid:{color:line},position:'left'},y1:{grid:{display:false},position:'right'},x:{grid:{display:false}}},plugins:{legend:{labels:{color:dim}}}}});}
}
/* Live Deal Desk — real CRCP points + transparent score colors */
var desked=false, deskMap=null;
function scoreColor(s){try{if(window.DealScore&&DealScore.scoreColor)return DealScore.scoreColor(s);}catch(e){}return s>=80?'#16a34a':s>=60?'#ca8a04':s>=40?'#ea580c':s>=20?'#dc2626':'#7f1d1d';}
function initDesk(){
document.querySelectorAll('.dscore').forEach(function(b){b.style.background=scoreColor(+b.dataset.score);});
if(desked||!window.L||!document.getElementById('dealmap'))return;desked=true;
var pts=${JSON.stringify(DESK_POINTS)};
deskMap=L.map('dealmap',{scrollWheelZoom:false}).setView([34.05,-118.3],10);
L.tileLayer('https://{s}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}{r}.png',{attribution:'© OpenStreetMap © CARTO',maxZoom:18}).addTo(deskMap);
var cluster=L.markerClusterGroup();
pts.forEach(function(p){if(!p.lat||!p.lng)return;var m=L.circleMarker([p.lat,p.lng],{radius:7,color:p.score?scoreColor(+p.score):'#c8a15a',fillColor:p.score?scoreColor(+p.score):'#c8a15a',fillOpacity:.85,weight:1});
m.bindPopup('<b>'+(p.address||'')+'</b><br>'+(p.city||'')+(p.type?' · '+p.type:'')+(p.price?'<br>$'+Number(p.price).toLocaleString():'')+(p.score?'<br>Deal score: '+p.score:''));cluster.addLayer(m);});
deskMap.addLayer(cluster);
setTimeout(function(){deskMap.invalidateSize();},300);
}
fetch('/portal/videos/heygen-brandfilm.mp4',{method:'HEAD'}).then(function(r){if(r.ok){var v=document.getElementById('heyfilm');v.src='/portal/videos/heygen-brandfilm.mp4';v.play();var p=document.getElementById('heyph');if(p)p.style.display='none';}}).catch(function(){});
document.querySelectorAll('.f5').forEach(function(c){var k=c.getAttribute('data-key'),src='/portal/videos/heygen-'+k+'.mp4';fetch(src,{method:'HEAD'}).then(function(r){if(r.ok){var v=c.querySelector('video');v.src=src;v.play();var p=c.querySelector('.fph');if(p)p.style.display='none';}}).catch(function(){});});
</script>
<a href="/portal/slideshow" style="position:fixed;bottom:20px;right:20px;z-index:60;background:#c6a765;color:#12100e;font-family:system-ui,-apple-system,sans-serif;font-size:11px;font-weight:700;letter-spacing:.16em;text-transform:uppercase;padding:11px 18px;border-radius:4px;text-decoration:none;box-shadow:0 8px 24px rgba(0,0,0,.45)">▶ Present</a>
</body></html>`;
writeFileSync(`${OUT}/portal.html`, app);
for (const h of HOUSES) writeFileSync(`${OUT}/versions/${h.key}.html`, versionPage(h));
console.log(`Wrote portal.html (analysis app w/ Chart.js + motion) + ${HOUSES.length} concepts: ${HOUSES.map(h=>h.key).join(', ')}`);