← back to Rentv Website

public/review.html

214 lines

<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
<title>The REview — RENTV.com Commercial Real Estate Video</title>
<meta name="description" content="The REview by RENTV.com — free commercial real estate video: market analysis, technology, property showcases and industry events across the Western U.S.">
<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,700;1,400&family=Inter:wght@300;400;600;800&display=swap" rel="stylesheet">
<style>
  /* ── shared RENTV design system (same tokens as index.html) ── */
  :root{--red:#c8102e;--ink:#14171a;--sub:#5b636b;--line:#e4e7ea;--bg:#fff;--wash:#f5f6f8;--sans:'Inter',system-ui,sans-serif;--serif:'Playfair Display',Georgia,serif}
  *{box-sizing:border-box;margin:0;padding:0}
  body{font-family:var(--sans);color:var(--ink);background:var(--bg);line-height:1.45}
  a{color:inherit;text-decoration:none}
  .wrap{max-width:1200px;margin:0 auto;padding:0 20px}
  .util{background:var(--ink);color:#cfd4d9;font-size:12px}
  .util .wrap{display:flex;justify-content:space-between;align-items:center;height:34px}
  .util .left a{color:#cfd4d9;margin-right:16px}
  .util .acts a{margin-left:14px;color:#cfd4d9}.util .acts a.sub{color:#fff;background:var(--red);padding:4px 12px;border-radius:3px;font-weight:700}
  .mast{border-bottom:2px solid var(--ink);padding:18px 0 12px}
  .mast .wrap{display:flex;align-items:center;justify-content:space-between}
  .logo{font-family:var(--serif);font-weight:700;font-size:34px;letter-spacing:-1px}.logo span{color:var(--red)}
  .logo small{display:block;font-size:11px;font-weight:600;letter-spacing:3px;color:var(--sub);text-transform:uppercase;margin-top:2px;font-family:var(--sans)}
  .datebox{font-size:12px;color:var(--sub);text-align:right}
  nav{border-bottom:1px solid var(--line);position:sticky;top:0;background:#fff;z-index:10}
  nav .wrap{display:flex;gap:2px;align-items:center;height:46px;overflow-x:auto}
  nav a{font-size:13px;font-weight:700;text-transform:uppercase;letter-spacing:.04em;padding:14px 13px;border-bottom:3px solid transparent;white-space:nowrap;cursor:pointer}
  nav a:hover,nav a.on{color:var(--red);border-color:var(--red)}
  /* ── REview hero band ── */
  .rhero{background:linear-gradient(120deg,#111827,#c8102e);color:#fff;padding:30px 0}
  .rhero .wrap{display:flex;align-items:center;justify-content:space-between;gap:24px;flex-wrap:wrap}
  .rhero .k{font-size:11px;letter-spacing:.24em;text-transform:uppercase;opacity:.85}
  .rhero h1{font-family:var(--serif);font-size:34px;line-height:1.1;margin:6px 0 6px}
  .rhero p{font-size:14px;opacity:.92;max-width:56ch}
  .rhero .cta{display:flex;gap:10px;flex:none}
  .rhero .cta a{display:inline-block;font-weight:800;font-size:12px;text-transform:uppercase;letter-spacing:.06em;padding:11px 18px;border-radius:4px}
  .rhero .cta .p{background:#fff;color:var(--red)}.rhero .cta .g{border:1.5px solid rgba(255,255,255,.6);color:#fff}
  /* ── search + filter bar ── */
  .toolbar{display:flex;gap:12px;align-items:center;flex-wrap:wrap;padding:22px 0 6px}
  .toolbar input{flex:1;min-width:220px;padding:11px 14px;border:1px solid var(--line);border-radius:5px;font-size:14px;font-family:var(--sans)}
  .chips{display:flex;gap:8px;flex-wrap:wrap;padding:8px 0 4px}
  .chips button{font-size:12px;font-weight:700;text-transform:uppercase;letter-spacing:.04em;padding:7px 13px;border:1px solid var(--line);background:#fff;color:var(--sub);border-radius:20px;cursor:pointer}
  .chips button.on{background:var(--red);border-color:var(--red);color:#fff}
  .live{display:inline-flex;align-items:center;gap:6px;font-size:11px;color:var(--sub);letter-spacing:.06em;text-transform:uppercase;margin-left:auto}
  .live .dot{width:7px;height:7px;border-radius:50%;background:#22c55e;animation:pulse 2s infinite}
  @keyframes pulse{0%{box-shadow:0 0 0 0 rgba(34,197,94,.6)}70%{box-shadow:0 0 0 7px rgba(34,197,94,0)}100%{box-shadow:0 0 0 0 rgba(34,197,94,0)}}
  /* ── rails + cards ── */
  .rail{padding:14px 0 6px}
  .sechead{display:flex;align-items:center;gap:12px;border-top:3px solid var(--ink);padding-top:10px;margin:22px 0 16px}
  .sechead h2{font-size:16px;text-transform:uppercase;letter-spacing:.06em}
  .sechead .count{margin-left:auto;font-size:12px;color:var(--sub)}
  .cards{display:grid;grid-template-columns:1fr 1fr 1fr 1fr;gap:22px}
  .vcard{display:block;cursor:pointer;text-align:left;background:none;border:0;padding:0;font:inherit;color:inherit}
  .vcard .thumb{aspect-ratio:16/9;border-radius:6px;overflow:hidden;background:linear-gradient(135deg,#475569,#94a3b8);position:relative}
  .vcard .thumb img{width:100%;height:100%;object-fit:cover;display:block}
  .vcard .thumb::after{content:'▶';position:absolute;inset:0;display:flex;align-items:center;justify-content:center;color:#fff;font-size:34px;text-shadow:0 2px 12px rgba(0,0,0,.5);opacity:.92;transition:transform .15s}
  .vcard:hover .thumb::after{transform:scale(1.18)}
  .vcard .rcat{display:inline-block;font-size:11px;font-weight:800;text-transform:uppercase;letter-spacing:.06em;color:var(--red);margin:9px 0 3px}
  .vcard h4{font-family:var(--serif);font-size:16px;line-height:1.22}
  .vcard .d{font-size:12px;color:var(--sub);margin-top:5px;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
  .empty{color:var(--sub);padding:26px 0}
  /* ── watch modal ── */
  .modal{position:fixed;inset:0;background:rgba(10,12,14,.86);display:none;align-items:center;justify-content:center;z-index:50;padding:20px}
  .modal.open{display:flex}
  .modal .panel{background:#0d0f11;border-radius:10px;overflow:hidden;max-width:960px;width:100%}
  .modal .video{aspect-ratio:16/9;background:#000}.modal iframe{width:100%;height:100%;border:0}
  .modal .meta{padding:16px 20px;color:#e7ebee}
  .modal .meta .rcat{color:#ff6b81;font-size:11px;font-weight:800;text-transform:uppercase;letter-spacing:.06em}
  .modal .meta h3{font-family:var(--serif);font-size:22px;margin:6px 0 8px}
  .modal .meta p{font-size:13px;color:#aeb6bd}
  .modal .meta .row{display:flex;gap:16px;align-items:center;margin-top:12px}
  .modal .meta a{font-size:12px;font-weight:700;color:#ff6b81}
  .modal .x{position:absolute;top:16px;right:22px;color:#fff;font-size:30px;cursor:pointer;line-height:1}
  footer{background:var(--ink);color:#aeb6bd;margin-top:36px;padding:40px 0 30px;font-size:13px}
  footer .cols{display:grid;grid-template-columns:2fr 1fr 1fr 1fr;gap:28px}
  footer .logo{color:#fff;font-size:26px;margin-bottom:8px}footer h5{color:#fff;font-size:12px;text-transform:uppercase;letter-spacing:.08em;margin-bottom:10px}footer a{display:block;padding:4px 0;color:#aeb6bd}
  footer .fine{border-top:1px solid #2a2f34;margin-top:26px;padding-top:16px;font-size:12px;color:#7c848b}
  @media(max-width:980px){.cards{grid-template-columns:1fr 1fr 1fr}}
  @media(max-width:720px){.cards{grid-template-columns:1fr 1fr}.rhero h1{font-size:26px}}
</style>
</head>
<body>
  <div class="util"><div class="wrap">
    <div class="left"><a href="/">RENTV.com News</a><a href="/review">The REview</a><a href="https://sublease.com/" target="_blank" rel="noopener">Sublease.com</a></div>
    <div class="acts"><a href="https://www.rentvreview.com/Account/Login" target="_blank" rel="noopener">Log In</a><a href="https://www.rentvreview.com/ContactUs" target="_blank" rel="noopener">Advertise</a><a class="sub" href="https://www.rentvreview.com/Account/Register" target="_blank" rel="noopener">Post a Video</a></div>
  </div></div>

  <header class="mast"><div class="wrap">
    <div class="logo">REN<span>TV</span>.com<small>Commercial Real Estate</small></div>
    <div class="datebox"><span>The REview · CRE Video</span><br><span id="today"></span></div>
  </div></header>

  <nav><div class="wrap">
    <a href="/">Home</a><a href="/sales">Sales</a><a href="/leases">Leases</a><a href="/financing">Financing</a><a href="/development">Development</a><a href="/multifamily">Multifamily</a><a href="/industrial">Industrial</a><a href="/retail">Retail</a><a class="on" href="/review">The REview</a>
  </div></nav>

  <section class="rhero"><div class="wrap">
    <div>
      <div class="k">The REview · by RENTV.com</div>
      <h1>Commercial Real Estate, on video.</h1>
      <p>Market analysis, technology, property showcases and industry-event coverage — the free CRE video hub from RENTV.com. Post your own, or advertise to the industry.</p>
    </div>
    <div class="cta">
      <a class="p" href="https://www.rentvreview.com/Account/Register" target="_blank" rel="noopener">Post a Video</a>
      <a class="g" href="https://www.rentvreview.com/ContactUs" target="_blank" rel="noopener">Advertise</a>
    </div>
  </div></section>

  <div class="wrap">
    <div class="toolbar">
      <input id="q" placeholder="Search The REview — companies, topics, markets…" autocomplete="off">
      <span class="live"><span class="dot"></span><span id="freshness">live</span></span>
    </div>
    <div class="chips" id="chips"></div>
    <div id="rails"><div class="empty">Loading The REview video catalog…</div></div>
  </div>

  <footer><div class="wrap"><div class="cols">
    <div><div class="logo">REN<span style="color:var(--red)">TV</span>.com</div><p style="max-width:36ch">The REview — free commercial real estate video from RENTV.com. Serving the Western U.S. CRE community since 1998.</p></div>
    <div><h5>The REview</h5><a href="/review">All Video</a><a href="https://www.rentvreview.com/Search" target="_blank" rel="noopener">Search</a><a href="https://www.rentvreview.com/Instructions" target="_blank" rel="noopener">How to Post</a></div>
    <div><h5>RENTV Network</h5><a href="/">RENTV.com News</a><a href="https://sublease.com/" target="_blank" rel="noopener">Sublease.com</a><a href="https://www.rentvreview.com/ContactUs" target="_blank" rel="noopener">Advertise</a></div>
    <div><h5>Company</h5><a href="https://www.rentvreview.com/ContactUs" target="_blank" rel="noopener">Contact</a><a href="https://www.rentvreview.com/Terms" target="_blank" rel="noopener">Terms</a><a href="https://www.rentvreview.com/Privacy" target="_blank" rel="noopener">Privacy</a></div>
  </div><div class="fine">© 2026 RENTV.com · The REview video catalog synced live from rentvreview.com · <span id="src"></span></div></div></footer>

  <div class="modal" id="modal">
    <span class="x" id="mx">×</span>
    <div class="panel">
      <div class="video"><iframe id="mframe" allow="accelerometer;autoplay;clipboard-write;encrypted-media;gyroscope;picture-in-picture" allowfullscreen></iframe></div>
      <div class="meta"><span class="rcat" id="mcat"></span><h3 id="mtitle"></h3><p id="mdesc"></p>
        <div class="row"><a id="mlink" target="_blank" rel="noopener">Open on The REview ↗</a></div>
      </div>
    </div>
  </div>

<script>
document.getElementById('today').textContent = new Date().toLocaleDateString(undefined,{weekday:'long',month:'long',day:'numeric',year:'numeric'});
let ALL=[], CATS=[], cat='all', q='';
const esc=s=>(s||'').replace(/[&<>"]/g,c=>({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;'}[c]));

function chips(){
  const all=['all',...CATS];
  document.getElementById('chips').innerHTML=all.map(c=>
    '<button data-cat="'+esc(c)+'"'+(c===cat?' class="on"':'')+'>'+(c==='all'?'All Video':esc(c))+'</button>').join('');
}
function match(v){
  if(cat!=='all' && v.cat!==cat) return false;
  if(q){const t=(v.title+' '+v.desc+' '+v.cat).toLowerCase(); if(!t.includes(q)) return false;}
  return true;
}
function cardHTML(v){
  return '<button class="vcard" data-id="'+esc(v.id)+'">'
    +'<div class="thumb"><img loading="lazy" src="'+esc(v.thumb)+'" alt="'+esc(v.title)+'" onerror="this.style.display=\'none\'"></div>'
    +'<span class="rcat">'+esc(v.cat)+'</span><h4>'+esc(v.title)+'</h4>'
    +(v.desc?'<div class="d">'+esc(v.desc)+'</div>':'')+'</button>';
}
function render(){
  const box=document.getElementById('rails');
  const items=ALL.filter(match);
  if(!items.length){box.innerHTML='<div class="empty">No videos match — try another search or category.</div>';return;}
  // when browsing "all" with no query, group by rail; otherwise one flat result grid
  if(cat==='all' && !q){
    box.innerHTML=CATS.map(c=>{
      const list=ALL.filter(v=>v.cat===c);
      if(!list.length) return '';
      return '<section class="rail"><div class="sechead"><h2>'+esc(c)+'</h2><span class="count">'+list.length+' video'+(list.length>1?'s':'')+'</span></div><div class="cards">'+list.map(cardHTML).join('')+'</div></section>';
    }).join('');
  }else{
    box.innerHTML='<section class="rail"><div class="sechead"><h2>'+(q?'Results':esc(cat))+'</h2><span class="count">'+items.length+' video'+(items.length>1?'s':'')+'</span></div><div class="cards">'+items.map(cardHTML).join('')+'</div></section>';
  }
}
function openVideo(id){
  const v=ALL.find(x=>x.id===id); if(!v) return;
  const box=document.querySelector('.modal .video');
  if(v.mp4){ // self-hosted RENTV Original — play a real <video>, not a YouTube iframe
    box.innerHTML='<video id="mvid" src="'+esc(v.mp4)+'" poster="'+esc(v.thumb||'')+'" controls autoplay playsinline style="width:100%;height:100%;background:#000"></video>';
  }else{
    box.innerHTML='<iframe id="mframe" allow="accelerometer;autoplay;clipboard-write;encrypted-media;gyroscope;picture-in-picture" allowfullscreen></iframe>';
    document.getElementById('mframe').src=v.embed?v.embed+'?autoplay=1&rel=0':'';
  }
  document.getElementById('mcat').textContent=v.cat;
  document.getElementById('mtitle').textContent=v.title;
  document.getElementById('mdesc').textContent=v.desc||'';
  const link=document.getElementById('mlink'); if(link){ link.href=v.view_url||'#'; link.style.display=v.view_url?'':'none'; }
  document.getElementById('modal').classList.add('open');
}
function closeVideo(){
  document.getElementById('modal').classList.remove('open');
  const box=document.querySelector('.modal .video'); if(box) box.innerHTML=''; // stop any playing media
}

document.getElementById('rails').addEventListener('click',e=>{const b=e.target.closest('.vcard');if(b)openVideo(b.dataset.id);});
document.getElementById('chips').addEventListener('click',e=>{const b=e.target.closest('button[data-cat]');if(!b)return;cat=b.dataset.cat;chips();render();});
document.getElementById('q').addEventListener('input',e=>{q=e.target.value.trim().toLowerCase();render();});
document.getElementById('mx').onclick=closeVideo;
document.getElementById('modal').addEventListener('click',e=>{if(e.target.id==='modal')closeVideo();});
document.addEventListener('keydown',e=>{if(e.key==='Escape')closeVideo();});

async function load(){
  try{
    const d=await (await fetch('/api/videos')).json();
    ALL=d.items||[]; CATS=d.cats||[...new Set(ALL.map(v=>v.cat))];
    chips(); render();
    if(d.fetched_at){
      const mins=Math.max(0,Math.round((Date.now()-new Date(d.fetched_at))/60000));
      document.getElementById('freshness').textContent=mins<2?'synced just now':('synced '+mins+' min ago');
      document.getElementById('src').textContent='last sync '+new Date(d.fetched_at).toLocaleTimeString();
    }
  }catch(e){document.getElementById('rails').innerHTML='<div class="empty">The REview catalog is temporarily unavailable — retrying…</div>';}
}
load(); setInterval(load, 300000); // re-sync every 5 min
</script>
</body>
</html>