← back to Rentv 2026

public/la-commercial.html

109 lines

<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
<title>LA Commercial Property Intelligence — RENTV.com</title>
<meta name="description" content="Los Angeles commercial real estate property intelligence — marquee assets, recorded activity, and the region's largest brokerages. RENTV.com.">
<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>
  :root{--red:#c8102e;--ink:#14171a;--sub:#5b636b;--line:#e4e7ea;--bg:#fff;--wash:#f5f6f8;--up:#0f8a4d;--dn:#c8102e;--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(--wash);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 .live{display:inline-flex;align-items:center;gap:7px;letter-spacing:.05em;text-transform:uppercase;font-size:11px}
  .util .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)}}
  .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{background:#fff;border-bottom:2px solid var(--ink);padding:16px 0 12px}
  .mast .wrap{display:flex;align-items:center;justify-content:space-between}
  .logo{font-family:var(--serif);font-weight:700;font-size:32px;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)}
  nav{background:#fff;border-bottom:1px solid var(--line)}
  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:13px 8px;border-bottom:3px solid transparent;white-space:nowrap}
  nav a:hover,nav a.on{color:var(--red);border-color:var(--red)}
  .head{padding:30px 0 6px}
  .head h1{font-family:var(--serif);font-size:34px;letter-spacing:-.5px}
  .head p{color:var(--sub);font-size:14px;margin-top:4px;max-width:760px}
  .head .fresh{font-size:12px;color:var(--sub);margin-top:8px}
  section{margin:26px 0}
  h2.sec{font-size:14px;text-transform:uppercase;letter-spacing:.08em;border-top:3px solid var(--ink);padding-top:10px;margin-bottom:14px}
  .assets{display:grid;grid-template-columns:repeat(3,1fr);gap:14px}
  .asset{background:#fff;border:1px solid var(--line);border-radius:8px;padding:16px 18px;display:block;transition:border-color .15s,box-shadow .15s}
  .asset:hover{border-color:var(--red);box-shadow:0 4px 16px rgba(0,0,0,.06)}
  .asset .tag{font-size:11px;color:var(--red);text-transform:uppercase;letter-spacing:.05em;font-weight:700}
  .asset .v{font-family:var(--serif);font-size:26px;font-weight:700;margin:4px 0 2px}
  .asset .a{font-size:14px;font-weight:600}
  .asset .brief{font-size:13px;color:var(--sub);margin-top:8px;line-height:1.5}
  table{width:100%;border-collapse:collapse;background:#fff;border:1px solid var(--line);border-radius:8px;overflow:hidden}
  th,td{text-align:left;padding:10px 14px;font-size:13px;border-bottom:1px solid var(--line)}
  th{background:var(--wash);text-transform:uppercase;font-size:11px;letter-spacing:.05em;color:var(--sub)}
  td.n{font-weight:600} td.v{font-family:var(--serif);font-weight:700}
  .firms{display:grid;grid-template-columns:repeat(4,1fr);gap:12px}
  .firm{background:#fff;border:1px solid var(--line);border-radius:8px;padding:14px;display:block;transition:border-color .15s}
  .firm:hover{border-color:var(--red)}
  .firm .fn{font-size:14px;font-weight:700;line-height:1.25} .firm .fa{font-size:13px;color:var(--red);font-weight:700;margin-top:6px}
  .note{font-size:12px;color:var(--sub);margin-top:8px}
  .ext::after{content:" ↗";font-size:.82em;color:var(--sub);font-weight:400}
  td.n a{color:inherit} td.n a:hover{color:var(--red);text-decoration:underline}
  footer{background:var(--ink);color:#8b939b;margin-top:40px;padding:26px 0;font-size:12px}
  footer .wrap{display:flex;justify-content:space-between;flex-wrap:wrap;gap:10px}
  @media(max-width:860px){.assets,.firms{grid-template-columns:1fr 1fr}}
</style>
</head>
<body>
  <div class="util"><div class="wrap">
    <span class="live"><span class="dot"></span> LA commercial property data</span>
    <div class="acts"><a href="/subscribe">Newsletters</a><a href="/advertise">Advertise</a><a class="sub" href="/subscribe">Subscribe</a></div>
  </div></div>
  <header class="mast"><div class="wrap">
    <a class="logo" href="/">REN<span>TV</span>.com<small>Commercial Real Estate News</small></a>
  </div></header>
  <nav><div class="wrap">
    <a href="/">Home</a><a href="/closings">Closings</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 href="/markets">Markets</a><a href="/la-commercial" class="on">LA Commercial</a><a href="/review">The REview</a><a href="/cre-talk">CRE Talk</a><a href="/conferences">Conferences</a><a href="/blog">Blog</a>
  </div></nav>
  <main class="wrap">
    <div class="head">
      <h1>LA Commercial Property Intelligence</h1>
      <p>Los Angeles County commercial &amp; industrial property intelligence — marquee assets, recorded transfer activity, and the region's largest brokerages. Assessed values from the LA County Assessor; figures are tax assessments, not sale prices.</p>
      <div class="fresh" id="fresh">Loading…</div>
    </div>
    <section><h2 class="sec">Marquee LA Commercial Assets</h2><div class="assets" id="marquee"></div>
      <div class="note">Ranked by assessed value. Each summary is generated from public assessor facts only.</div></section>
    <section><h2 class="sec">Recent Recorded Activity</h2><div id="recent"></div>
      <div class="note">Most recently recorded commercial &amp; industrial transfers in LA County. Sale prices are not in the public roll.</div></section>
    <section><h2 class="sec">Largest LA Brokerages</h2><div class="firms" id="firms"></div>
      <div class="note">Los Angeles firms by licensed-agent count, from the California DRE current-licensee registry.</div></section>
  </main>
  <footer><div class="wrap"><span>© RENTV.com — Commercial Real Estate News</span><span>LA property data · assessor + CA DRE, refreshed daily</span></div></footer>
<script>
const $=s=>document.querySelector(s), usd=n=>n==null?'—':'$'+Number(n).toLocaleString();
function dstr(d){return d?new Date(d).toLocaleDateString(undefined,{year:'numeric',month:'short',day:'numeric'}):'—';}
// Every datum drills to its source (Steve's rule): assets/records → the LA County Assessor
// parcel record (the cited source, keyed by AIN); firms → our CRE Directory filtered to that firm.
const AIN=a=>'https://portal.assessor.lacounty.gov/parceldetail/'+encodeURIComponent(a);
// esc() for HTML text/attribute content — the API's brief/name/address strings are server/LLM-
// generated, so they are untrusted and must be escaped before going into innerHTML (Cody gate).
const esc=s=>String(s==null?'':s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/"/g,'&quot;');
const attr=esc;
(async()=>{
  const d=await (await fetch('/api/la-commercial')).json();
  $('#fresh').textContent=d.fetched_at?('Data as of '+new Date(d.fetched_at).toLocaleString()):'';
  $('#marquee').innerHTML=(d.marquee||[]).slice(0,9).map(r=>`<a class="asset${r.ain?' ext':''}"${r.ain?` href="${AIN(r.ain)}" target="_blank" rel="noopener" title="LA County Assessor parcel ${attr(r.ain)}"`:''}>
    <div class="tag">${esc(r.type_label||'')}</div>
    <div class="v">${usd(r.assessed_total)}</div>
    <div class="a">${esc(r.address||'—')}${r.city?', '+esc(r.city):''}</div>
    ${r.brief?`<div class="brief">${esc(r.brief)}</div>`:''}</a>`).join('');
  $('#recent').innerHTML='<table><thead><tr><th>Recorded</th><th>Address</th><th>Type</th><th>Assessed</th></tr></thead><tbody>'+
    (d.recent||[]).map(r=>{const lbl=r.address?`${esc(r.address)}${r.city?', '+esc(r.city):''}`:(r.ain?`Parcel ${esc(r.ain)}`:'—');const cell=r.ain?`<a class="ext" href="${AIN(r.ain)}" target="_blank" rel="noopener" title="LA County Assessor parcel ${attr(r.ain)}">${lbl}</a>`:lbl;return `<tr><td>${dstr(r.recording_date)}</td><td class="n">${cell}</td><td>${esc(r.type_label||'')}</td><td class="v">${usd(r.assessed_total)}</td></tr>`;}).join('')+'</tbody></table>';
  $('#firms').innerHTML=(d.firms||[]).slice(0,12).map(f=>`<a class="firm" href="/directory?tab=firms&q=${encodeURIComponent(f.name||'')}" title="See ${attr(f.name)} in the CRE Directory">
    <div class="fn">${esc(f.name)}</div><div class="fa">${(f.agent_count||0).toLocaleString()} agents</div></a>`).join('');
})();
</script>
</body>
</html>