← back to Rentv
auto-save: 2026-07-22T14:14:43 (7 files) — data/markets.json data/news.json data/ticker.json mockups/assets/base.css mockups/admin/
819d5e0449b7fb57fcf7bf2c21b9c4ea2374f3fe · 2026-07-22 14:14:52 -0700 · Steve Abrams
Files touched
M data/markets.jsonM data/news.jsonM data/ticker.jsonA mockups/admin/data/brokers.jsonA mockups/admin/data/firms.jsonA mockups/admin/data/la-commercial.jsonA mockups/admin/data/news.jsonA mockups/admin/data/ticker.jsonA mockups/admin/data/videos.jsonA mockups/admin/index.htmlM mockups/assets/base.cssA mockups/rentv.htmlA mockups/video/build-admin-video.jsA mockups/video/build-frontend-video.jsA mockups/video/build-rentv-video.jsA mockups/video/out/audio/ad-1.mp3A mockups/video/out/audio/ad-intro.mp3A mockups/video/out/audio/api-la.mp3A mockups/video/out/audio/api-news.mp3A mockups/video/out/audio/api-ticker.mp3A mockups/video/out/audio/api-videos.mp3A mockups/video/out/audio/arch.mp3A mockups/video/out/audio/fe-intro.mp3A mockups/video/out/audio/fe-outro.mp3A mockups/video/out/audio/outro.mp3A mockups/video/out/audio/s00.mp3A mockups/video/out/audio/s1.mp3A mockups/video/out/audio/s10.mp3A mockups/video/out/audio/s11.mp3A mockups/video/out/audio/s12.mp3A mockups/video/out/audio/s2.mp3A mockups/video/out/audio/s3.mp3A mockups/video/out/audio/s4.mp3A mockups/video/out/audio/s5.mp3A mockups/video/out/audio/s6.mp3A mockups/video/out/audio/s7.mp3A mockups/video/out/audio/s8.mp3A mockups/video/out/audio/s9.mp3A mockups/video/out/concat-fe.txtA mockups/video/out/concat.txtA mockups/video/out/rentv-build-walkthrough.mp4A mockups/video/out/rentv-frontend-walkthrough.mp4A mockups/video/out/shots/L01-picks.pngA mockups/video/out/shots/L01-x.pngA mockups/video/out/shots/L02-ham.pngA mockups/video/out/shots/L02-x.pngA mockups/video/out/shots/L03-x.pngA mockups/video/out/shots/L04-x.pngA mockups/video/out/shots/L05-x.pngA mockups/video/out/shots/L06-x.pngA mockups/video/out/shots/L07-x.pngA mockups/video/out/shots/L08-x.pngA mockups/video/out/shots/L09-x.pngA mockups/video/out/shots/L10-x.pngA mockups/video/out/shots/ad-1.pngA mockups/video/out/slides/ad-1.mp4A mockups/video/out/slides/ad-1.pngA mockups/video/out/slides/ad-intro.mp4A mockups/video/out/slides/ad-intro.pngA mockups/video/out/slides/api-la.mp4A mockups/video/out/slides/api-la.pngA mockups/video/out/slides/api-news.mp4A mockups/video/out/slides/api-news.pngA mockups/video/out/slides/api-ticker.mp4A mockups/video/out/slides/api-ticker.pngA mockups/video/out/slides/api-videos.mp4A mockups/video/out/slides/api-videos.pngA mockups/video/out/slides/arch.mp4A mockups/video/out/slides/arch.pngA mockups/video/out/slides/fe-intro.mp4A mockups/video/out/slides/fe-intro.pngA mockups/video/out/slides/fe-outro.mp4A mockups/video/out/slides/fe-outro.pngA mockups/video/out/slides/outro.mp4A mockups/video/out/slides/outro.pngA mockups/video/out/slides/s00.mp4A mockups/video/out/slides/s00.pngA mockups/video/out/slides/s01.pngA mockups/video/out/slides/s02.pngA mockups/video/out/slides/s03.pngA mockups/video/out/slides/s04.pngA mockups/video/out/slides/s05.pngA mockups/video/out/slides/s06.pngA mockups/video/out/slides/s07.pngA mockups/video/out/slides/s08.pngA mockups/video/out/slides/s09.pngA mockups/video/out/slides/s1.mp4A mockups/video/out/slides/s10.mp4A mockups/video/out/slides/s10.pngA mockups/video/out/slides/s11.mp4A mockups/video/out/slides/s11.pngA mockups/video/out/slides/s12.mp4A mockups/video/out/slides/s12.pngA mockups/video/out/slides/s2.mp4A mockups/video/out/slides/s3.mp4A mockups/video/out/slides/s4.mp4A mockups/video/out/slides/s5.mp4A mockups/video/out/slides/s6.mp4A mockups/video/out/slides/s7.mp4A mockups/video/out/slides/s8.mp4A mockups/video/out/slides/s9.mp4
Diff
commit 819d5e0449b7fb57fcf7bf2c21b9c4ea2374f3fe
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Wed Jul 22 14:14:52 2026 -0700
auto-save: 2026-07-22T14:14:43 (7 files) — data/markets.json data/news.json data/ticker.json mockups/assets/base.css mockups/admin/
---
data/markets.json | 2 +-
data/news.json | 2 +-
data/ticker.json | 2 +-
mockups/admin/data/brokers.json | 1 +
mockups/admin/data/firms.json | 1 +
mockups/admin/data/la-commercial.json | 1 +
mockups/admin/data/news.json | 1 +
mockups/admin/data/ticker.json | 1 +
mockups/admin/data/videos.json | 1 +
mockups/admin/index.html | 176 ++++++++++++++++++++++
mockups/assets/base.css | 4 +-
mockups/rentv.html | 114 ++++++++++++++
mockups/video/build-admin-video.js | 88 +++++++++++
mockups/video/build-frontend-video.js | 52 +++++++
mockups/video/build-rentv-video.js | 183 +++++++++++++++++++++++
mockups/video/out/audio/ad-1.mp3 | Bin 0 -> 104089 bytes
mockups/video/out/audio/ad-intro.mp3 | Bin 0 -> 51009 bytes
mockups/video/out/audio/api-la.mp3 | Bin 0 -> 95730 bytes
mockups/video/out/audio/api-news.mp3 | Bin 0 -> 54352 bytes
mockups/video/out/audio/api-ticker.mp3 | Bin 0 -> 81938 bytes
mockups/video/out/audio/api-videos.mp3 | Bin 0 -> 55188 bytes
mockups/video/out/audio/arch.mp3 | Bin 0 -> 94058 bytes
mockups/video/out/audio/fe-intro.mp3 | Bin 0 -> 80057 bytes
mockups/video/out/audio/fe-outro.mp3 | Bin 0 -> 50382 bytes
mockups/video/out/audio/outro.mp3 | Bin 0 -> 80684 bytes
mockups/video/out/audio/s00.mp3 | Bin 0 -> 55606 bytes
mockups/video/out/audio/s1.mp3 | Bin 0 -> 89670 bytes
mockups/video/out/audio/s10.mp3 | Bin 0 -> 75250 bytes
mockups/video/out/audio/s11.mp3 | Bin 0 -> 68563 bytes
mockups/video/out/audio/s12.mp3 | Bin 0 -> 72324 bytes
mockups/video/out/audio/s2.mp3 | Bin 0 -> 134182 bytes
mockups/video/out/audio/s3.mp3 | Bin 0 -> 107433 bytes
mockups/video/out/audio/s4.mp3 | Bin 0 -> 80684 bytes
mockups/video/out/audio/s5.mp3 | Bin 0 -> 80057 bytes
mockups/video/out/audio/s6.mp3 | Bin 0 -> 70026 bytes
mockups/video/out/audio/s7.mp3 | Bin 0 -> 55815 bytes
mockups/video/out/audio/s8.mp3 | Bin 0 -> 59159 bytes
mockups/video/out/audio/s9.mp3 | Bin 0 -> 75668 bytes
mockups/video/out/concat-fe.txt | 14 ++
mockups/video/out/concat.txt | 19 +++
mockups/video/out/rentv-build-walkthrough.mp4 | Bin 0 -> 17195059 bytes
mockups/video/out/rentv-frontend-walkthrough.mp4 | Bin 0 -> 14022420 bytes
mockups/video/out/shots/L01-picks.png | Bin 0 -> 177771 bytes
mockups/video/out/shots/L01-x.png | Bin 0 -> 185945 bytes
mockups/video/out/shots/L02-ham.png | Bin 0 -> 585750 bytes
mockups/video/out/shots/L02-x.png | Bin 0 -> 909497 bytes
mockups/video/out/shots/L03-x.png | Bin 0 -> 143312 bytes
mockups/video/out/shots/L04-x.png | Bin 0 -> 518832 bytes
mockups/video/out/shots/L05-x.png | Bin 0 -> 307278 bytes
mockups/video/out/shots/L06-x.png | Bin 0 -> 280435 bytes
mockups/video/out/shots/L07-x.png | Bin 0 -> 646872 bytes
mockups/video/out/shots/L08-x.png | Bin 0 -> 191094 bytes
mockups/video/out/shots/L09-x.png | Bin 0 -> 373128 bytes
mockups/video/out/shots/L10-x.png | Bin 0 -> 137093 bytes
mockups/video/out/shots/ad-1.png | Bin 0 -> 132422 bytes
mockups/video/out/slides/ad-1.mp4 | Bin 0 -> 1025340 bytes
mockups/video/out/slides/ad-1.png | Bin 0 -> 148437 bytes
mockups/video/out/slides/ad-intro.mp4 | Bin 0 -> 343852 bytes
mockups/video/out/slides/ad-intro.png | Bin 0 -> 337141 bytes
mockups/video/out/slides/api-la.mp4 | Bin 0 -> 726930 bytes
mockups/video/out/slides/api-la.png | Bin 0 -> 100366 bytes
mockups/video/out/slides/api-news.mp4 | Bin 0 -> 649204 bytes
mockups/video/out/slides/api-news.png | Bin 0 -> 118195 bytes
mockups/video/out/slides/api-ticker.mp4 | Bin 0 -> 584450 bytes
mockups/video/out/slides/api-ticker.png | Bin 0 -> 79341 bytes
mockups/video/out/slides/api-videos.mp4 | Bin 0 -> 477100 bytes
mockups/video/out/slides/api-videos.png | Bin 0 -> 83518 bytes
mockups/video/out/slides/arch.mp4 | Bin 0 -> 563973 bytes
mockups/video/out/slides/arch.png | Bin 0 -> 350273 bytes
mockups/video/out/slides/fe-intro.mp4 | Bin 0 -> 344586 bytes
mockups/video/out/slides/fe-intro.png | Bin 0 -> 333784 bytes
mockups/video/out/slides/fe-outro.mp4 | Bin 0 -> 206039 bytes
mockups/video/out/slides/fe-outro.png | Bin 0 -> 337469 bytes
mockups/video/out/slides/outro.mp4 | Bin 0 -> 500309 bytes
mockups/video/out/slides/outro.png | Bin 0 -> 340981 bytes
mockups/video/out/slides/s00.mp4 | Bin 0 -> 340757 bytes
mockups/video/out/slides/s00.png | Bin 0 -> 333312 bytes
mockups/video/out/slides/s01.png | Bin 0 -> 904424 bytes
mockups/video/out/slides/s02.png | Bin 0 -> 587037 bytes
mockups/video/out/slides/s03.png | Bin 0 -> 191745 bytes
mockups/video/out/slides/s04.png | Bin 0 -> 197650 bytes
mockups/video/out/slides/s05.png | Bin 0 -> 162260 bytes
mockups/video/out/slides/s06.png | Bin 0 -> 544835 bytes
mockups/video/out/slides/s07.png | Bin 0 -> 318618 bytes
mockups/video/out/slides/s08.png | Bin 0 -> 296714 bytes
mockups/video/out/slides/s09.png | Bin 0 -> 644972 bytes
mockups/video/out/slides/s1.mp4 | Bin 0 -> 1444738 bytes
mockups/video/out/slides/s10.mp4 | Bin 0 -> 995001 bytes
mockups/video/out/slides/s10.png | Bin 0 -> 206431 bytes
mockups/video/out/slides/s11.mp4 | Bin 0 -> 1336532 bytes
mockups/video/out/slides/s11.png | Bin 0 -> 394539 bytes
mockups/video/out/slides/s12.mp4 | Bin 0 -> 1108206 bytes
mockups/video/out/slides/s12.png | Bin 0 -> 155473 bytes
mockups/video/out/slides/s2.mp4 | Bin 0 -> 1335015 bytes
mockups/video/out/slides/s3.mp4 | Bin 0 -> 969756 bytes
mockups/video/out/slides/s4.mp4 | Bin 0 -> 888206 bytes
mockups/video/out/slides/s5.mp4 | Bin 0 -> 1041949 bytes
mockups/video/out/slides/s6.mp4 | Bin 0 -> 1339503 bytes
mockups/video/out/slides/s7.mp4 | Bin 0 -> 1035820 bytes
mockups/video/out/slides/s8.mp4 | Bin 0 -> 967581 bytes
mockups/video/out/slides/s9.mp4 | Bin 0 -> 1290639 bytes
101 files changed, 657 insertions(+), 5 deletions(-)
diff --git a/data/markets.json b/data/markets.json
index 2b678f5d..ecbc209d 100644
--- a/data/markets.json
+++ b/data/markets.json
@@ -1,5 +1,5 @@
{
- "fetched_at": "2026-07-22T20:24:40.875Z",
+ "fetched_at": "2026-07-22T21:04:42.714Z",
"source": "Yahoo Finance — live (CBOE Treasury yields, Dow Jones/MSCI REIT indices)",
"curve": [
{
diff --git a/data/news.json b/data/news.json
index d908bc50..e1d4dd5c 100644
--- a/data/news.json
+++ b/data/news.json
@@ -1,6 +1,6 @@
{
"source": "rentv.com — live",
- "fetched_at": "2026-07-22T20:24:40.153Z",
+ "fetched_at": "2026-07-22T21:04:42.226Z",
"count": 30,
"items": [
{
diff --git a/data/ticker.json b/data/ticker.json
index 7aefba59..cd903641 100644
--- a/data/ticker.json
+++ b/data/ticker.json
@@ -1,5 +1,5 @@
{
- "fetched_at": "2026-07-22T20:24:40.845Z",
+ "fetched_at": "2026-07-22T21:04:42.692Z",
"la_office_vac": {
"label": "LA OFFICE VAC",
"value": "23.1%",
diff --git a/mockups/admin/data/brokers.json b/mockups/admin/data/brokers.json
new file mode 100644
index 00000000..9da35916
--- /dev/null
+++ b/mockups/admin/data/brokers.json
@@ -0,0 +1 @@
+{"total":382944,"limit":120,"offset":0,"rows":[{"id":2738431,"name":"Aadil Iqbal","license_no":"02158856","license_state":"CA","license_type":"Salesperson","license_status":"Licensed","city":"SACRAMENTO","state_code":"CA","source":"ca_dre","firm_name":"Aziz Realty","firm_id":328360},{"id":2677692,"name":"Aadit Sitaula","license_no":"02023960","license_state":"CA","license_type":"Salesperson","license_status":"Licensed","city":"MURRIETA","state_code":"CA","source":"ca_dre","firm_name":"KAM Financial & Realty, Inc.","firm_id":315139},{"id":2754249,"name":"Aahoo Robab Pourang","license_no":"02195125","license_state":"CA","license_type":"Salesperson","license_status":"Licensed","city":"IRVINE","state_code":"CA","source":"ca_dre","firm_name":"E & M Pegasus Investment Group Inc","firm_id":326479},{"id":2772810,"name":"Aaina Babbar","license_no":"02220027","license_state":"CA","license_type":"Salesperson","license_status":"Licensed","city":"RANCHO CUCAMONGA","state_code":"CA","source":"ca_dre","firm_name":"Dynasty R.E. Inc.","firm_id":315771},{"id":2668132,"name":"Aain Abbas Ashary","license_no":"02000444","license_state":"CA","license_type":"Salesperson","license_status":"Licensed NBA","city":"CORONA","state_code":"CA","source":"ca_dre","firm_name":null,"firm_id":null},{"id":2732454,"name":"Aaishmann Kaur Waraich","license_no":"02145281","license_state":"CA","license_type":"Salesperson","license_status":"Licensed","city":"FONTANA","state_code":"CA","source":"ca_dre","firm_name":"Doaba Estate","firm_id":340716},{"id":2772265,"name":"Aakash Bhasin","license_no":"02219187","license_state":"CA","license_type":"Salesperson","license_status":"Licensed NBA","city":"SIMI VALLEY","state_code":"CA","source":"ca_dre","firm_name":null,"firm_id":null},{"id":2805960,"name":"Aakash Girish Shah","license_no":"02339945","license_state":"CA","license_type":"Salesperson","license_status":"Licensed","city":"SAN LUIS OBISPO","state_code":"CA","source":"ca_dre","firm_name":"SB Wealth Inc","firm_id":316054},{"id":2794994,"name":"Aakash Goel","license_no":"02250232","license_state":"CA","license_type":"Salesperson","license_status":"Licensed NBA","city":"SANTA CLARA","state_code":"CA","source":"ca_dre","firm_name":null,"firm_id":null},{"id":2702625,"name":"Aakash Rajesh Kadakia","license_no":"02081668","license_state":"CA","license_type":"Salesperson","license_status":"Licensed","city":"ROCKLIN","state_code":"CA","source":"ca_dre","firm_name":"BWR Real Estate Services","firm_id":314964},{"id":2776185,"name":"Aakashveer Singh Deol","license_no":"02224620","license_state":"CA","license_type":"Salesperson","license_status":"Licensed","city":"HAYWARD","state_code":"CA","source":"ca_dre","firm_name":"Alliance Bay Funding Inc","firm_id":315862},{"id":2645993,"name":"Aako Kori","license_no":"01947032","license_state":"CA","license_type":"Broker","license_status":"Licensed","city":"CORONA","state_code":"CA","source":"ca_dre","firm_name":null,"firm_id":null},{"id":2534398,"name":"A Alejandro Clark","license_no":"01348829","license_state":"CA","license_type":"Broker","license_status":"Licensed","city":"HANFORD","state_code":"CA","source":"ca_dre","firm_name":null,"firm_id":null},{"id":2786680,"name":"Aaliyah Ann Bustamante","license_no":"02239149","license_state":"CA","license_type":"Salesperson","license_status":"Licensed","city":"SAN JOSE","state_code":"CA","source":"ca_dre","firm_name":"Daybreak Real Estate Brokerage","firm_id":345457},{"id":2751969,"name":"Aaliyah Faith Hilario","license_no":"02192141","license_state":"CA","license_type":"Salesperson","license_status":"Licensed","city":"COACHELLA","state_code":"CA","source":"ca_dre","firm_name":"Ruttenberg","firm_id":324343},{"id":2752476,"name":"Aaliyah Faiza Farish","license_no":"02192789","license_state":"CA","license_type":"Salesperson","license_status":"Licensed NBA","city":"FRESNO","state_code":"CA","source":"ca_dre","firm_name":null,"firm_id":null},{"id":2809718,"name":"Aaliyah Juliett Bryant","license_no":"02399198","license_state":"CA","license_type":"Salesperson","license_status":"Licensed","city":"INGLEWOOD","state_code":"CA","source":"ca_dre","firm_name":"LA Real Estate Group, Inc.","firm_id":315868},{"id":2779068,"name":"Aaliyah Marie Norwood-Dymally","license_no":"02228442","license_state":"CA","license_type":"Salesperson","license_status":"Licensed","city":"LOS ANGELES","state_code":"CA","source":"ca_dre","firm_name":"Dynacore Inc","firm_id":315887},{"id":2782000,"name":"Aaliyah Renae Richardson","license_no":"02232629","license_state":"CA","license_type":"Salesperson","license_status":"Licensed","city":"VICTORVILLE","state_code":"CA","source":"ca_dre","firm_name":"Lamoreaux","firm_id":315324},{"id":2800980,"name":"Aaliyah Titiana Marie Cage","license_no":"02282367","license_state":"CA","license_type":"Salesperson","license_status":"Licensed NBA","city":"SAN BERNARDINO","state_code":"CA","source":"ca_dre","firm_name":null,"firm_id":null},{"id":2684085,"name":"Aaliyah Yusuf","license_no":"02040188","license_state":"CA","license_type":"Salesperson","license_status":"Licensed","city":"SAN FRANCISCO","state_code":"CA","source":"ca_dre","firm_name":"Structure Properties, Inc.","firm_id":325830},{"id":2699330,"name":"Aaliya J Mclean","license_no":"02075297","license_state":"CA","license_type":"Salesperson","license_status":"Licensed","city":"RESEDA","state_code":"CA","source":"ca_dre","firm_name":"Side, Inc.","firm_id":314541},{"id":2723473,"name":"Aaliyyah Shahidah Muhammad","license_no":"02124779","license_state":"CA","license_type":"Salesperson","license_status":"Licensed","city":"WALNUT CREEK","state_code":"CA","source":"ca_dre","firm_name":"KB HOME Sales-Northern California","firm_id":318954},{"id":2614186,"name":"Aalok Sikand","license_no":"01855934","license_state":"CA","license_type":"Broker","license_status":"Licensed","city":"LOS ANGELES","state_code":"CA","source":"ca_dre","firm_name":null,"firm_id":null},{"id":2485760,"name":"A Alvarado","license_no":"01106994","license_state":"CA","license_type":"Broker","license_status":"Licensed","city":"SACRAMENTO","state_code":"CA","source":"ca_dre","firm_name":null,"firm_id":null},{"id":2750863,"name":"Aamar Khalid Blair","license_no":"02190458","license_state":"CA","license_type":"Salesperson","license_status":"Licensed","city":"GARDENA","state_code":"CA","source":"ca_dre","firm_name":"eXp Realty of California, Inc.","firm_id":314633},{"id":2775747,"name":"Aamber Aleyna Hickman","license_no":"02224118","license_state":"CA","license_type":"Salesperson","license_status":"Licensed","city":"LONG BEACH","state_code":"CA","source":"ca_dre","firm_name":"Morrison","firm_id":324040},{"id":2629141,"name":"Aamie Dawn McDonald-Johnson","license_no":"01902150","license_state":"CA","license_type":"Salesperson","license_status":"Licensed","city":"SALIDA","state_code":"CA","source":"ca_dre","firm_name":"The Finance Group, Inc.","firm_id":315520},{"id":2760839,"name":"Aamir Javed","license_no":"02204037","license_state":"CA","license_type":"Salesperson","license_status":"Licensed","city":"ROSEVILLE","state_code":"CA","source":"ca_dre","firm_name":"Sadek Real Estate","firm_id":316753},{"id":2539692,"name":"Aamir Khan","license_no":"01367205","license_state":"CA","license_type":"Broker","license_status":"Licensed","city":"STOCKTON","state_code":"CA","source":"ca_dre","firm_name":null,"firm_id":null},{"id":2672974,"name":"Aamir Khan","license_no":"02012022","license_state":"CA","license_type":"Salesperson","license_status":"Licensed","city":"DUBLIN","state_code":"CA","source":"ca_dre","firm_name":"Bloom Real Estate & Lending","firm_id":330913},{"id":2752986,"name":"Aamit Singh Chowdhury","license_no":"02193415","license_state":"CA","license_type":"Salesperson","license_status":"Licensed NBA","city":"SACRAMENTO","state_code":"CA","source":"ca_dre","firm_name":null,"firm_id":null},{"id":2795443,"name":"Aamren Ozaeta","license_no":"02250796","license_state":"CA","license_type":"Salesperson","license_status":"Licensed NBA","city":"FRESNO","state_code":"CA","source":"ca_dre","firm_name":null,"firm_id":null},{"id":2618616,"name":"Aanand V Patel","license_no":"01871669","license_state":"CA","license_type":"Salesperson","license_status":"Licensed","city":"LOS ANGELES","state_code":"CA","source":"ca_dre","firm_name":"All Nations Realty Ontario","firm_id":320783},{"id":2746923,"name":"Aanchal Gulati","license_no":"02180960","license_state":"CA","license_type":"Salesperson","license_status":"Licensed","city":"RANCHO CUCAMONGA","state_code":"CA","source":"ca_dre","firm_name":"Compass California II, Inc.","firm_id":314579},{"id":2718501,"name":"Aanchal Satija","license_no":"02113852","license_state":"CA","license_type":"Salesperson","license_status":"Licensed","city":"IRVINE","state_code":"CA","source":"ca_dre","firm_name":"Evergreen Realty Partners, Inc.","firm_id":314570},{"id":2614794,"name":"Aaradona M Walker","license_no":"01858152","license_state":"CA","license_type":"Salesperson","license_status":"Licensed","city":"SANTA ROSA","state_code":"CA","source":"ca_dre","firm_name":"Pacific Direct Mortgage & Real Estate,","firm_id":333370},{"id":2716675,"name":"Aarambh Shah","license_no":"02109930","license_state":"CA","license_type":"Broker","license_status":"Licensed NBA","city":"PARKLAND","state_code":"FL","source":"ca_dre","firm_name":null,"firm_id":null},{"id":2627560,"name":"Aaram Safai","license_no":"01897821","license_state":"CA","license_type":"Salesperson","license_status":"Licensed","city":"CANYON LAKE","state_code":"CA","source":"ca_dre","firm_name":"Kielty Realty, Inc.","firm_id":315865},{"id":2538915,"name":"Aara Viola Pedersen","license_no":"01364524","license_state":"CA","license_type":"Broker","license_status":"Licensed","city":"SANTA ROSA","state_code":"CA","source":"ca_dre","firm_name":null,"firm_id":null},{"id":2715557,"name":"Aaren Juline Kisner","license_no":"02107595","license_state":"CA","license_type":"Salesperson","license_status":"Licensed","city":"NEWPORT BEACH","state_code":"CA","source":"ca_dre","firm_name":"Bentrott","firm_id":342421},{"id":2669555,"name":"Aareon Jefferson","license_no":"02003844","license_state":"CA","license_type":"Salesperson","license_status":"Licensed NBA","city":"VALENCIA","state_code":"CA","source":"ca_dre","firm_name":null,"firm_id":null},{"id":2643903,"name":"Aarian Wenji Liu","license_no":"01941386","license_state":"CA","license_type":"Broker","license_status":"Licensed","city":"BALDWIN PARK","state_code":"CA","source":"ca_dre","firm_name":null,"firm_id":null},{"id":2794574,"name":"Aarica Maria Sanders","license_no":"02249689","license_state":"CA","license_type":"Salesperson","license_status":"Licensed","city":"RANCHO CUCAMONGA","state_code":"CA","source":"ca_dre","firm_name":"Reliance Real Estate Services of","firm_id":314955},{"id":2787344,"name":"Aarika Grace Flemings","license_no":"02239992","license_state":"CA","license_type":"Salesperson","license_status":"Licensed NBA","city":"IRVINE","state_code":"CA","source":"ca_dre","firm_name":null,"firm_id":null},{"id":2756084,"name":"Aarin Blanche Booker","license_no":"02197770","license_state":"CA","license_type":"Salesperson","license_status":"Licensed","city":"SAINT LOUIS","state_code":"MO","source":"ca_dre","firm_name":"Makn Moves Inc.","firm_id":317646},{"id":2663771,"name":"Aarin Elizabeth Jacobs Chung","license_no":"01989749","license_state":"CA","license_type":"Salesperson","license_status":"Licensed NBA","city":"COVINA","state_code":"CA","source":"ca_dre","firm_name":null,"firm_id":null},{"id":2646370,"name":"Aaron Aalcides","license_no":"01948003","license_state":"CA","license_type":"Salesperson","license_status":"Licensed","city":"TORRANCE","state_code":"CA","source":"ca_dre","firm_name":"Epique Inc","firm_id":319947},{"id":2543618,"name":"Aaron A Boss","license_no":"01381686","license_state":"CA","license_type":"Salesperson","license_status":"Licensed","city":"RANCHO PALOS VERDES","state_code":"CA","source":"ca_dre","firm_name":"Stephen W Cunningham And","firm_id":326143},{"id":2775941,"name":"Aaron Abraham Yazdi","license_no":"02224357","license_state":"CA","license_type":"Salesperson","license_status":"Licensed","city":"LOS ANGELES","state_code":"CA","source":"ca_dre","firm_name":"Ontrack Asset Management Inc","firm_id":332093},{"id":2662368,"name":"Aaron Adam Manji","license_no":"01986233","license_state":"CA","license_type":"Salesperson","license_status":"Licensed","city":"LOS ANGELES","state_code":"CA","source":"ca_dre","firm_name":"Balboa Real Estate, Inc","firm_id":314746},{"id":2777528,"name":"Aaron Adrian Duenez","license_no":"02226370","license_state":"CA","license_type":"Salesperson","license_status":"Licensed","city":"LAGUNA NIGUEL","state_code":"CA","source":"ca_dre","firm_name":"Matthews & Associates","firm_id":321126},{"id":2551458,"name":"Aaron A Gray","license_no":"01411295","license_state":"CA","license_type":"Salesperson","license_status":"Licensed","city":"RIVERSIDE","state_code":"CA","source":"ca_dre","firm_name":"Khorr Realty, Inc.","firm_id":326992},{"id":2696079,"name":"Aaron Aguilera","license_no":"02068828","license_state":"CA","license_type":"Salesperson","license_status":"Licensed","city":"CHULA VISTA","state_code":"CA","source":"ca_dre","firm_name":"Newton","firm_id":337601},{"id":2503174,"name":"Aaron Alan Unger","license_no":"01212784","license_state":"CA","license_type":"Broker","license_status":"Licensed","city":"SALIDA","state_code":"CA","source":"ca_dre","firm_name":null,"firm_id":null},{"id":2661954,"name":"Aaron Alan Whitfield","license_no":"01985258","license_state":"CA","license_type":"Broker","license_status":"Licensed","city":"SOLANA BEACH","state_code":"CA","source":"ca_dre","firm_name":null,"firm_id":null},{"id":2591091,"name":"Aaron Albania Heredia","license_no":"01758457","license_state":"CA","license_type":"Salesperson","license_status":"Licensed NBA","city":"LONG BEACH","state_code":"CA","source":"ca_dre","firm_name":null,"firm_id":null},{"id":2719428,"name":"Aaron Alberto Luna Ruiz","license_no":"02115822","license_state":"CA","license_type":"Broker","license_status":"Licensed","city":"WEST COVINA","state_code":"CA","source":"ca_dre","firm_name":null,"firm_id":null},{"id":2808473,"name":"Aaron Alexander Barclay","license_no":"02377786","license_state":"CA","license_type":"Salesperson","license_status":"Licensed","city":"VISTA","state_code":"CA","source":"ca_dre","firm_name":"Member Development, Inc.","firm_id":315598},{"id":2803008,"name":"Aaron Alexander Campbell","license_no":"02295735","license_state":"CA","license_type":"Salesperson","license_status":"Licensed NBA","city":"NORTH HILLS","state_code":"CA","source":"ca_dre","firm_name":null,"firm_id":null},{"id":2739364,"name":"Aaron Alexander Finley","license_no":"02160921","license_state":"CA","license_type":"Salesperson","license_status":"Licensed NBA","city":"THOUSAND OAKS","state_code":"CA","source":"ca_dre","firm_name":null,"firm_id":null},{"id":2763135,"name":"Aaron Alexander Fonville","license_no":"02206929","license_state":"CA","license_type":"Salesperson","license_status":"Licensed NBA","city":"FORT MACARTHUR","state_code":"CA","source":"ca_dre","firm_name":null,"firm_id":null},{"id":2773857,"name":"Aaron Alexander Levitan","license_no":"02221550","license_state":"CA","license_type":"Salesperson","license_status":"Licensed","city":"AGOURA HILLS","state_code":"CA","source":"ca_dre","firm_name":"Levitan","firm_id":335514},{"id":2812677,"name":"Aaron Alexander Lix","license_no":"02439512","license_state":"CA","license_type":"Salesperson","license_status":"Licensed","city":"LA JOLLA","state_code":"CA","source":"ca_dre","firm_name":"La Jolla Partners Inc.","firm_id":316801},{"id":2803995,"name":"Aaron Alexander Pates","license_no":"02310204","license_state":"CA","license_type":"Salesperson","license_status":"Licensed NBA","city":"SAN DIEGO","state_code":"CA","source":"ca_dre","firm_name":null,"firm_id":null},{"id":2699464,"name":"Aaron Alexis Pardo","license_no":"02075596","license_state":"CA","license_type":"Salesperson","license_status":"Licensed","city":"SANTA ROSA","state_code":"CA","source":"ca_dre","firm_name":"Compass California II, Inc.","firm_id":314579},{"id":2792455,"name":"Aaron Alfred Lahood","license_no":"02246934","license_state":"CA","license_type":"Salesperson","license_status":"Licensed","city":"SAN FRANCISCO","state_code":"CA","source":"ca_dre","firm_name":"Eastdil Secured Advisory Services Inc.","firm_id":319108},{"id":2668695,"name":"Aaron Allen Goodman","license_no":"02001733","license_state":"CA","license_type":"Salesperson","license_status":"Licensed","city":"LOS ANGELES","state_code":"CA","source":"ca_dre","firm_name":"Lyon Stahl Investment Real Estate, Inc.","firm_id":324917},{"id":2703763,"name":"Aaron Allen Klassen","license_no":"02083771","license_state":"CA","license_type":"Salesperson","license_status":"Licensed","city":"BAKERSFIELD","state_code":"CA","source":"ca_dre","firm_name":"Central Valley Property Advisors","firm_id":331875},{"id":2705056,"name":"Aaron Allen Pyne","license_no":"02086325","license_state":"CA","license_type":"Salesperson","license_status":"Licensed","city":"YUCAIPA","state_code":"CA","source":"ca_dre","firm_name":"Real Estate Innovations, Inc.","firm_id":315329},{"id":2621115,"name":"Aaron Allen Young","license_no":"01879935","license_state":"CA","license_type":"Broker","license_status":"Licensed","city":"PLEASANT HILL","state_code":"CA","source":"ca_dre","firm_name":null,"firm_id":null},{"id":2628889,"name":"Aaron Alonso Panuco","license_no":"01901503","license_state":"CA","license_type":"Salesperson","license_status":"Licensed NBA","city":"LOS ANGELES","state_code":"CA","source":"ca_dre","firm_name":null,"firm_id":null},{"id":2519300,"name":"Aaron Anderson","license_no":"01290018","license_state":"CA","license_type":"Salesperson","license_status":"Licensed","city":"MARINA DEL REY","state_code":"CA","source":"ca_dre","firm_name":"Seeds Realty Group, Inc.","firm_id":324252},{"id":2682543,"name":"Aaron Andrew Truitt","license_no":"02036254","license_state":"CA","license_type":"Broker","license_status":"Licensed","city":"LIVERMORE","state_code":"CA","source":"ca_dre","firm_name":null,"firm_id":null},{"id":2636168,"name":"Aaron Anthony Argent","license_no":"01920748","license_state":"CA","license_type":"Salesperson","license_status":"Licensed","city":"MURRIETA","state_code":"CA","source":"ca_dre","firm_name":"Allison James of California Inc","firm_id":315292},{"id":2708874,"name":"Aaron Anthony Blackburn","license_no":"02093989","license_state":"CA","license_type":"Salesperson","license_status":"Licensed","city":"LONG BEACH","state_code":"CA","source":"ca_dre","firm_name":"Platinum Properties Real Estate","firm_id":333238},{"id":2654640,"name":"Aaron Anthony Christian Titolo","license_no":"01968137","license_state":"CA","license_type":"Salesperson","license_status":"Licensed NBA","city":"IRVINE","state_code":"CA","source":"ca_dre","firm_name":null,"firm_id":null},{"id":2744170,"name":"Aaron Anthony Martinez","license_no":"02173930","license_state":"CA","license_type":"Salesperson","license_status":"Licensed","city":"STOCKTON","state_code":"CA","source":"ca_dre","firm_name":"The Finance Group, Inc.","firm_id":315520},{"id":2509490,"name":"Aaron Anthony Meadows","license_no":"01242289","license_state":"CA","license_type":"Broker","license_status":"Licensed","city":"OAKLEY","state_code":"CA","source":"ca_dre","firm_name":null,"firm_id":null},{"id":2685527,"name":"Aaron Anthony Pullano","license_no":"02043729","license_state":"CA","license_type":"Salesperson","license_status":"Licensed","city":"GRASS VALLEY","state_code":"CA","source":"ca_dre","firm_name":"CDL Mortgage Services, Inc.","firm_id":328016},{"id":2812466,"name":"Aaron Ari David Palmer","license_no":"02439167","license_state":"CA","license_type":"Broker","license_status":"Licensed","city":"LONG BEACH","state_code":"CA","source":"ca_dre","firm_name":null,"firm_id":null},{"id":2723629,"name":"Aaron Ariza Arak","license_no":"02125140","license_state":"CA","license_type":"Salesperson","license_status":"Licensed","city":"NEWBURY PARK","state_code":"CA","source":"ca_dre","firm_name":"Pinnacle Estate Properties Inc","firm_id":314606},{"id":2792748,"name":"Aaron Armando Atencio","license_no":"02247344","license_state":"CA","license_type":"Salesperson","license_status":"Licensed","city":"CHULA VISTA","state_code":"CA","source":"ca_dre","firm_name":"LPT Realty, Inc","firm_id":315786},{"id":2648465,"name":"Aaron Arreola Moreno","license_no":"01953659","license_state":"CA","license_type":"Salesperson","license_status":"Licensed","city":"DOWNEY","state_code":"CA","source":"ca_dre","firm_name":"Real Brokerage Technologies","firm_id":315234},{"id":2613258,"name":"Aaron Arthur Avedian","license_no":"01852587","license_state":"CA","license_type":"Salesperson","license_status":"Licensed NBA","city":"NEWPORT BEACH","state_code":"CA","source":"ca_dre","firm_name":null,"firm_id":null},{"id":2547104,"name":"Aaron Arthur Flint","license_no":"01395357","license_state":"CA","license_type":"Broker","license_status":"Licensed","city":"TEMECULA","state_code":"CA","source":"ca_dre","firm_name":null,"firm_id":null},{"id":2808618,"name":"Aaron Arthur Siegler","license_no":"02380545","license_state":"CA","license_type":"Salesperson","license_status":"Licensed","city":"PLACENTIA","state_code":"CA","source":"ca_dre","firm_name":"TNG Real Estate Consultants Inc.","firm_id":315184},{"id":2785420,"name":"Aaron Asher Nazarian","license_no":"02237515","license_state":"CA","license_type":"Salesperson","license_status":"Licensed","city":"BEVERLY HILLS","state_code":"CA","source":"ca_dre","firm_name":"Rashti","firm_id":346802},{"id":2639533,"name":"Aaron Ashmeed Ali","license_no":"01929371","license_state":"CA","license_type":"Salesperson","license_status":"Licensed","city":"TORRANCE","state_code":"CA","source":"ca_dre","firm_name":"Stratton - LFCA, Inc.","firm_id":314522},{"id":2713902,"name":"Aaron Ash Rosen","license_no":"02104183","license_state":"CA","license_type":"Salesperson","license_status":"Licensed","city":"SANTA ROSA","state_code":"CA","source":"ca_dre","firm_name":"Amo Realty, Inc","firm_id":328323},{"id":2668069,"name":"Aaron Ataide Soriano","license_no":"02000277","license_state":"CA","license_type":"Salesperson","license_status":"Licensed","city":"VISALIA","state_code":"CA","source":"ca_dre","firm_name":"eXp Realty of California, Inc.","firm_id":314633},{"id":2815434,"name":"Aaron Aurelio Alvarado","license_no":"02444129","license_state":"CA","license_type":"Salesperson","license_status":"Licensed","city":"FAIRFIELD","state_code":"CA","source":"ca_dre","firm_name":"eXp Realty of Northern California, Inc.","firm_id":315889},{"id":2775535,"name":"Aaron Avraham Daniel","license_no":"02223825","license_state":"CA","license_type":"Salesperson","license_status":"Licensed NBA","city":"ENCINO","state_code":"CA","source":"ca_dre","firm_name":null,"firm_id":null},{"id":2720111,"name":"Aaron Aziz Mansoori-Moayed","license_no":"02117361","license_state":"CA","license_type":"Broker","license_status":"Licensed","city":"ROSEVILLE","state_code":"CA","source":"ca_dre","firm_name":null,"firm_id":null},{"id":2676334,"name":"Aaron Bardya Khosh","license_no":"02020525","license_state":"CA","license_type":"Salesperson","license_status":"Licensed","city":"NEWPORT BEACH","state_code":"CA","source":"ca_dre","firm_name":"Pickford Real Estate Inc","firm_id":314737},{"id":2684687,"name":"Aaron B Collins","license_no":"02041676","license_state":"CA","license_type":"Salesperson","license_status":"Licensed","city":"VALPARAISO","state_code":"IN","source":"ca_dre","firm_name":"San Francisco Real Estate California","firm_id":314548},{"id":2788481,"name":"Aaron Benjamin Acosta","license_no":"02241658","license_state":"CA","license_type":"Salesperson","license_status":"Licensed","city":"SAN DIEGO","state_code":"CA","source":"ca_dre","firm_name":"Ascencio","firm_id":319985},{"id":2581740,"name":"Aaron Benjamin Lerner","license_no":"01717678","license_state":"CA","license_type":"Broker","license_status":"Licensed","city":"LOS ANGELES","state_code":"CA","source":"ca_dre","firm_name":null,"firm_id":null},{"id":2811796,"name":"Aaron Benjamin Miller","license_no":"02434853","license_state":"CA","license_type":"Salesperson","license_status":"Licensed","city":"LIVONIA","state_code":"MI","source":"ca_dre","firm_name":"West Capital Lending, Inc.","firm_id":317102},{"id":2634937,"name":"Aaron Benjamin Sagin","license_no":"01917449","license_state":"CA","license_type":"Salesperson","license_status":"Licensed NBA","city":"SAN FRANCISCO","state_code":"CA","source":"ca_dre","firm_name":null,"firm_id":null},{"id":2777918,"name":"Aaron Benjamin Soto","license_no":"02226924","license_state":"CA","license_type":"Salesperson","license_status":"Licensed NBA","city":"STOCKTON","state_code":"CA","source":"ca_dre","firm_name":null,"firm_id":null},{"id":2645108,"name":"Aaron Berger","license_no":"01944602","license_state":"CA","license_type":"Broker","license_status":"Licensed","city":"SHERMAN OAKS","state_code":"CA","source":"ca_dre","firm_name":null,"firm_id":null},{"id":2717897,"name":"Aaron Bernard Catolico","license_no":"02112566","license_state":"CA","license_type":"Salesperson","license_status":"Licensed","city":"WEST SACRAMENTO","state_code":"CA","source":"ca_dre","firm_name":"William L Lyon & Associates Inc","firm_id":314506},{"id":2496289,"name":"Aaron Bertrand Chan","license_no":"01177287","license_state":"CA","license_type":"Salesperson","license_status":"Licensed NBA","city":"SALINAS","state_code":"CA","source":"ca_dre","firm_name":null,"firm_id":null},{"id":2741365,"name":"Aaron Blair Rose","license_no":"02165433","license_state":"CA","license_type":"Salesperson","license_status":"Licensed","city":"BROWNS VALLEY","state_code":"CA","source":"ca_dre","firm_name":"eXp Realty of California, Inc.","firm_id":314633},{"id":2802790,"name":"Aaron Blake Chavez","license_no":"02292089","license_state":"CA","license_type":"Salesperson","license_status":"Licensed","city":"MODESTO","state_code":"CA","source":"ca_dre","firm_name":"Harold","firm_id":337172},{"id":2762175,"name":"Aaron Boudaie","license_no":"02205692","license_state":"CA","license_type":"Salesperson","license_status":"Licensed NBA","city":"LOS ANGELES","state_code":"CA","source":"ca_dre","firm_name":null,"firm_id":null},{"id":2720118,"name":"Aaron Brandon Es-Haghian","license_no":"02117374","license_state":"CA","license_type":"Salesperson","license_status":"Licensed","city":"TARZANA","state_code":"CA","source":"ca_dre","firm_name":"Marcus & Millichap Real Estate","firm_id":315084},{"id":2499936,"name":"Aaron Brent Cuha","license_no":"01197089","license_state":"CA","license_type":"Broker","license_status":"Licensed","city":"ANTIOCH","state_code":"CA","source":"ca_dre","firm_name":null,"firm_id":null},{"id":2502346,"name":"Aaron Brent Tennison","license_no":"01208987","license_state":"CA","license_type":"Broker","license_status":"Licensed","city":"UPLAND","state_code":"CA","source":"ca_dre","firm_name":null,"firm_id":null},{"id":2520958,"name":"Aaron Brett Kirman","license_no":"01296524","license_state":"CA","license_type":"Salesperson","license_status":"Licensed","city":"BEVERLY HILLS","state_code":"CA","source":"ca_dre","firm_name":"AKGRE Inc","firm_id":317832},{"id":2789079,"name":"Aaron Brian Zidenberg","license_no":"02242450","license_state":"CA","license_type":"Salesperson","license_status":"Licensed","city":"GROVER BEACH","state_code":"CA","source":"ca_dre","firm_name":"First Team Real Estate - Orange","firm_id":314725},{"id":2691209,"name":"Aaron Brook Roberts","license_no":"02057883","license_state":"CA","license_type":"Salesperson","license_status":"Licensed","city":"FOOTHILL RANCH","state_code":"CA","source":"ca_dre","firm_name":"Jones Lang Lasalle Americas Inc","firm_id":315299},{"id":2605471,"name":"Aaron Brown","license_no":"01821230","license_state":"CA","license_type":"Broker","license_status":"Licensed","city":"OAKLAND","state_code":"CA","source":"ca_dre","firm_name":null,"firm_id":null},{"id":2653402,"name":"Aaron Buntin","license_no":"01965324","license_state":"CA","license_type":"Salesperson","license_status":"Licensed","city":"SAN JOSE","state_code":"CA","source":"ca_dre","firm_name":"eXp Realty of California, Inc.","firm_id":314633},{"id":2609178,"name":"Aaron Buxbaum","license_no":"01836760","license_state":"CA","license_type":"Broker","license_status":"Licensed","city":"IRVINE","state_code":"CA","source":"ca_dre","firm_name":null,"firm_id":null},{"id":2763536,"name":"Aaron Caine Hernandez","license_no":"02207430","license_state":"CA","license_type":"Salesperson","license_status":"Licensed","city":"POMONA","state_code":"CA","source":"ca_dre","firm_name":"The Network Realty Group, Inc.","firm_id":325808},{"id":2581000,"name":"Aaron Caleb Young","license_no":"01714552","license_state":"CA","license_type":"Broker","license_status":"Licensed","city":"LONG BEACH","state_code":"CA","source":"ca_dre","firm_name":null,"firm_id":null},{"id":2803822,"name":"Aaron Calimlim","license_no":"02307308","license_state":"CA","license_type":"Salesperson","license_status":"Licensed","city":"SAN MATEO","state_code":"CA","source":"ca_dre","firm_name":"Town & Country Realty Associates, Inc.","firm_id":315636},{"id":2675826,"name":"Aaron Carrillo","license_no":"02019334","license_state":"CA","license_type":"Salesperson","license_status":"Licensed","city":"LOS ANGELES","state_code":"CA","source":"ca_dre","firm_name":"Prime Line Mutual Group","firm_id":323524}]}
\ No newline at end of file
diff --git a/mockups/admin/data/firms.json b/mockups/admin/data/firms.json
new file mode 100644
index 00000000..f1541bc0
--- /dev/null
+++ b/mockups/admin/data/firms.json
@@ -0,0 +1 @@
+{"total":34727,"limit":60,"offset":0,"rows":[{"id":314633,"name":"eXp Realty of California, Inc.","license_no":"01878277","license_state":"CA","hq_city":"SAN RAMON","hq_state":"CA","agent_count":4965,"source":"ca_dre"},{"id":315234,"name":"Real Brokerage Technologies","license_no":"02022092","license_state":"CA","hq_city":"NEWARK","hq_state":"CA","agent_count":4896,"source":"ca_dre"},{"id":314579,"name":"Compass California II, Inc.","license_no":"01527235","license_state":"CA","hq_city":"BEVERLY HILLS","hq_state":"CA","agent_count":3678,"source":"ca_dre"},{"id":314651,"name":"Compass California, Inc.","license_no":"01991628","license_state":"CA","hq_city":"BEVERLY HILLS","hq_state":"CA","agent_count":3444,"source":"ca_dre"},{"id":314624,"name":"NRT West, Inc.","license_no":"01908304","license_state":"CA","hq_city":"CONCORD","hq_state":"CA","agent_count":3311,"source":"ca_dre"},{"id":314515,"name":"Coldwell Banker Residential","license_no":"00616212","license_state":"CA","hq_city":"IRVINE","hq_state":"CA","agent_count":2987,"source":"ca_dre"},{"id":314737,"name":"Pickford Real Estate Inc","license_no":"01317331","license_state":"CA","hq_city":"SAN DIEGO","hq_state":"CA","agent_count":2286,"source":"ca_dre"},{"id":314541,"name":"Side, Inc.","license_no":"02014153","license_state":"CA","hq_city":"SAN FRANCISCO","hq_state":"CA","agent_count":2230,"source":"ca_dre"},{"id":314725,"name":"First Team Real Estate - Orange","license_no":"01008773","license_state":"CA","hq_city":"NEWPORT BEACH","hq_state":"CA","agent_count":1938,"source":"ca_dre"},{"id":314599,"name":"Real Estate Ebroker Inc","license_no":"01522411","license_state":"CA","hq_city":"SAN MARCOS","hq_state":"CA","agent_count":1780,"source":"ca_dre"},{"id":315786,"name":"LPT Realty, Inc","license_no":"02248983","license_state":"CA","hq_city":"LAKE MARY","hq_state":"FL","agent_count":1673,"source":"ca_dre"},{"id":314860,"name":"eXp Realty of Southern California, Inc.","license_no":"02187306","license_state":"CA","hq_city":"SAN DIEGO","hq_state":"CA","agent_count":1396,"source":"ca_dre"},{"id":314595,"name":"Full Realty Services Inc","license_no":"01849354","license_state":"CA","hq_city":"MURRIETA","hq_state":"CA","agent_count":1364,"source":"ca_dre"},{"id":314702,"name":"CBRE, Inc.","license_no":"00409987","license_state":"CA","hq_city":"LOS ANGELES","hq_state":"CA","agent_count":1213,"source":"ca_dre"},{"id":315889,"name":"eXp Realty of Northern California, Inc.","license_no":"02188495","license_state":"CA","hq_city":"ROSEVILLE","hq_state":"CA","agent_count":1175,"source":"ca_dre"},{"id":314522,"name":"Stratton - LFCA, Inc.","license_no":"02211662","license_state":"CA","hq_city":"WHITTIER","hq_state":"CA","agent_count":1147,"source":"ca_dre"},{"id":316240,"name":"eXp Realty of Greater Los Angeles, Inc.","license_no":"02188471","license_state":"CA","hq_city":"BURBANK","hq_state":"CA","agent_count":1083,"source":"ca_dre"},{"id":314570,"name":"Evergreen Realty Partners, Inc.","license_no":"01896421","license_state":"CA","hq_city":"LAGUNA NIGUEL","hq_state":"CA","agent_count":1077,"source":"ca_dre"},{"id":315030,"name":"Compass California III, Inc.","license_no":"01527365","license_state":"CA","hq_city":"BEVERLY HILLS","hq_state":"CA","agent_count":1044,"source":"ca_dre"},{"id":317135,"name":"Navigators Real Estate, Inc.","license_no":"01918023","license_state":"CA","hq_city":"ARCADIA","hq_state":"CA","agent_count":1008,"source":"ca_dre"},{"id":314492,"name":"Sotheby's International Realty Inc","license_no":"00899496","license_state":"CA","hq_city":"BEVERLY HILLS","hq_state":"CA","agent_count":986,"source":"ca_dre"},{"id":314490,"name":"West Edge Inc","license_no":"01481919","license_state":"CA","hq_city":"SAN DIEGO","hq_state":"CA","agent_count":978,"source":"ca_dre"},{"id":314957,"name":"CDH Investments Inc.","license_no":"01983717","license_state":"CA","hq_city":"ARCADIA","hq_state":"CA","agent_count":936,"source":"ca_dre"},{"id":315223,"name":"Dream Team Real Estate Consultants","license_no":"01811831","license_state":"CA","hq_city":"SHERMAN OAKS","hq_state":"CA","agent_count":909,"source":"ca_dre"},{"id":314847,"name":"Evergreen Realty & Associates Inc","license_no":"01814504","license_state":"CA","hq_city":"IRVINE","hq_state":"CA","agent_count":907,"source":"ca_dre"},{"id":314606,"name":"Pinnacle Estate Properties Inc","license_no":"00905345","license_state":"CA","hq_city":"PORTER RANCH","hq_state":"CA","agent_count":886,"source":"ca_dre"},{"id":314908,"name":"Intero Real Estate Services Inc","license_no":"01354442","license_state":"CA","hq_city":"CUPERTINO","hq_state":"CA","agent_count":877,"source":"ca_dre"},{"id":317102,"name":"West Capital Lending, Inc.","license_no":"02022356","license_state":"CA","hq_city":"IRVINE","hq_state":"CA","agent_count":859,"source":"ca_dre"},{"id":315520,"name":"The Finance Group, Inc.","license_no":"01400749","license_state":"CA","hq_city":"MODESTO","hq_state":"CA","agent_count":837,"source":"ca_dre"},{"id":315862,"name":"Alliance Bay Funding Inc","license_no":"01522539","license_state":"CA","hq_city":"NEWARK","hq_state":"CA","agent_count":807,"source":"ca_dre"},{"id":316372,"name":"Redfin Corporation","license_no":"01521930","license_state":"CA","hq_city":"SHERMAN OAKS","hq_state":"CA","agent_count":785,"source":"ca_dre"},{"id":315265,"name":"UMRO Realty Corp.","license_no":"01904054","license_state":"CA","hq_city":"BEVERLY HILLS","hq_state":"CA","agent_count":757,"source":"ca_dre"},{"id":315943,"name":"Filo Real Estate Inc","license_no":"01801668","license_state":"CA","hq_city":"ROCKLIN","hq_state":"CA","agent_count":728,"source":"ca_dre"},{"id":314850,"name":"4 USA Loans Inc","license_no":"01425679","license_state":"CA","hq_city":"SAN DIEGO","hq_state":"CA","agent_count":721,"source":"ca_dre"},{"id":314695,"name":"Coldwell Banker Residential","license_no":"00958424","license_state":"CA","hq_city":"IRVINE","hq_state":"CA","agent_count":694,"source":"ca_dre"},{"id":314542,"name":"Pearson Properties Inc","license_no":"01499008","license_state":"CA","hq_city":"DANVILLE","hq_state":"CA","agent_count":681,"source":"ca_dre"},{"id":314960,"name":"Excellence RE Real Estate Inc.","license_no":"01914184","license_state":"CA","hq_city":"PICO RIVERA","hq_state":"CA","agent_count":662,"source":"ca_dre"},{"id":314524,"name":"Rodeo Realty, Inc.","license_no":"00951359","license_state":"CA","hq_city":"BEVERLY HILLS","hq_state":"CA","agent_count":662,"source":"ca_dre"},{"id":314543,"name":"Sereno Group, Inc.","license_no":"02101181","license_state":"CA","hq_city":"LOS GATOS","hq_state":"CA","agent_count":643,"source":"ca_dre"},{"id":317523,"name":"Wetrust Realty","license_no":"02125613","license_state":"CA","hq_city":"SAN MARINO","hq_state":"CA","agent_count":641,"source":"ca_dre"},{"id":315151,"name":"Norcal United Real Estate Partners","license_no":"02205397","license_state":"CA","hq_city":"SAN MATEO","hq_state":"CA","agent_count":617,"source":"ca_dre"},{"id":314930,"name":"Norcal Gold Inc","license_no":"01215931","license_state":"CA","hq_city":"RANCHO CORDOVA","hq_state":"CA","agent_count":594,"source":"ca_dre"},{"id":314758,"name":"AC2015 Corporation","license_no":"01986798","license_state":"CA","hq_city":"HENDERSON","hq_state":"NV","agent_count":582,"source":"ca_dre"},{"id":318596,"name":"BQ Group Inc","license_no":"01929787","license_state":"CA","hq_city":"SAN JOSE","hq_state":"CA","agent_count":580,"source":"ca_dre"},{"id":316941,"name":"Googain Inc","license_no":"01525887","license_state":"CA","hq_city":"SUNNYVALE","hq_state":"CA","agent_count":573,"source":"ca_dre"},{"id":314981,"name":"License Park Realty, Inc.","license_no":"02166462","license_state":"CA","hq_city":"RESTON","hq_state":"VA","agent_count":562,"source":"ca_dre"},{"id":316205,"name":"ROA California Inc.","license_no":"02248657","license_state":"CA","hq_city":"BERWYN","hq_state":"IL","agent_count":558,"source":"ca_dre"},{"id":316659,"name":"Real Estate Source Inc","license_no":"01869619","license_state":"CA","hq_city":"FOLSOM","hq_state":"CA","agent_count":554,"source":"ca_dre"},{"id":314955,"name":"Reliance Real Estate Services of","license_no":"02014163","license_state":"CA","hq_city":"CORONA","hq_state":"CA","agent_count":550,"source":"ca_dre"},{"id":314613,"name":"JMS Realtors Ltd","license_no":"01100967","license_state":"CA","hq_city":"FRESNO","hq_state":"CA","agent_count":546,"source":"ca_dre"},{"id":314964,"name":"BWR Real Estate Services","license_no":"01522213","license_state":"CA","hq_city":"FREMONT","hq_state":"CA","agent_count":514,"source":"ca_dre"},{"id":315160,"name":"Exp Commercial of California, Inc.","license_no":"02134436","license_state":"CA","hq_city":"SAN RAMON","hq_state":"CA","agent_count":511,"source":"ca_dre"},{"id":315137,"name":"Realty Masters & Associates, Inc","license_no":"01927637","license_state":"CA","hq_city":"RANCHO CUCAMONGA","hq_state":"CA","agent_count":511,"source":"ca_dre"},{"id":316026,"name":"JohnHart Corp","license_no":"01873088","license_state":"CA","hq_city":"LA CRESCENTA","hq_state":"CA","agent_count":506,"source":"ca_dre"},{"id":315184,"name":"TNG Real Estate Consultants Inc.","license_no":"01886242","license_state":"CA","hq_city":"FULLERTON","hq_state":"CA","agent_count":504,"source":"ca_dre"},{"id":316246,"name":"Fathom Realty Group Inc.","license_no":"01901202","license_state":"CA","hq_city":"MISSION VIEJO","hq_state":"CA","agent_count":501,"source":"ca_dre"},{"id":314759,"name":"Award-Superstars","license_no":"01897784","license_state":"CA","hq_city":"EL CAJON","hq_state":"CA","agent_count":500,"source":"ca_dre"},{"id":314979,"name":"Cushman & Wakefield U.S., Inc.","license_no":"01880493","license_state":"CA","hq_city":"SAN DIEGO","hq_state":"CA","agent_count":500,"source":"ca_dre"},{"id":314690,"name":"Paul M Zagaris Inc","license_no":"00405158","license_state":"CA","hq_city":"MODESTO","hq_state":"CA","agent_count":495,"source":"ca_dre"},{"id":315387,"name":"Realty Rise Inc","license_no":"01957687","license_state":"CA","hq_city":"CARLSBAD","hq_state":"CA","agent_count":495,"source":"ca_dre"}]}
\ No newline at end of file
diff --git a/mockups/admin/data/la-commercial.json b/mockups/admin/data/la-commercial.json
new file mode 100644
index 00000000..dc559a2c
--- /dev/null
+++ b/mockups/admin/data/la-commercial.json
@@ -0,0 +1 @@
+{"fetched_at":"2026-07-22T18:31:04.117Z","county":"06037","marquee":[{"ain":"4334007008","address":"121 N LA CIENEGA BLVD","city":"LOS ANGELES","zip":"90048","type":"retail","type_label":"Retail","use_desc":"Shopping Center (Regional)","assessed_total":995837586,"assessed_land":476270150,"assessed_improvement":519567436,"roll_year":"2025","recording_date":"2020-12-29T00:00:00.000Z","sqft":1284654,"year_built":1981,"units":0,"brief":"The 1,284,654 sqft, 1981-built regional shopping center at 121 N La Cienega Blvd in Los Angeles has an assessed value of $995,837,586, last recorded on Dec 29."},{"ain":"2424043022","address":"3900 LANKERSHIM BLVD","city":"LOS ANGELES","zip":"90068","type":"industrial","type_label":"Industrial","use_desc":"Heavy Manufacturing","assessed_total":919928415,"assessed_land":160335677,"assessed_improvement":199521231,"roll_year":"2025","recording_date":"2011-01-28T00:00:00.000Z","sqft":8048,"year_built":1930,"units":0,"brief":"The 1930-built, 8,048 sqft heavy manufacturing property at 3900 Lankershim Blvd in Los Angeles has an assessed value of $919,928,415, last recorded transferring on Jan 28."},{"ain":"5151023400","address":"525 S FLOWER ST","city":"LOS ANGELES","zip":"90071","type":"office","type_label":"Office","use_desc":"Office Building","assessed_total":909370171,"assessed_land":134403685,"assessed_improvement":774966486,"roll_year":"2025","recording_date":"2013-10-01T00:00:00.000Z","sqft":2832748,"year_built":1971,"units":0,"brief":"The 2.8M sqft office building at 525 S Flower St in Los Angeles has an assessed value of $909M and was last transferred on October 1, 1971."},{"ain":"2673021041","address":"15800 ROSCOE BLVD","city":"LOS ANGELES","zip":"91406","type":"industrial","type_label":"Industrial","use_desc":"Food Processing Plant","assessed_total":856465517,"assessed_land":104517723,"assessed_improvement":391931829,"roll_year":"2025","recording_date":"2016-09-21T00:00:00.000Z","sqft":393032,"year_built":1954,"units":0,"brief":"The 393,032 sqft food processing plant at 15800 Roscoe Blvd in Los Angeles has an assessed value of $856,465,517 and last transferred on September 21."},{"ain":"2485021011","address":"4000 WARNER BLVD","city":"BURBANK","zip":"91522","type":"studio","type_label":"Studio / Media","use_desc":"Motion Picture, Radio and Television Industry","assessed_total":737677562,"assessed_land":288849385,"assessed_improvement":448828177,"roll_year":"2025","recording_date":"2022-04-08T00:00:00.000Z","sqft":152217,"year_built":1926,"units":0,"brief":"The 152,217 sqft studio at 4000 Warner Blvd in Burbank, valued at $737,677,562 as of last transfer on April 8, 2022, supports the Motion Picture, Radio and Television Industry."},{"ain":"5151014031","address":"333 S HOPE ST","city":"LOS ANGELES","zip":"90071","type":"office","type_label":"Office","use_desc":"Office Building","assessed_total":729339835,"assessed_land":112546537,"assessed_improvement":616793298,"roll_year":"2025","recording_date":"2013-10-15T00:00:00.000Z","sqft":1392719,"year_built":1974,"units":0,"brief":"The office building located at 333 S HOPE ST in Los Angeles, with a assessed value of $729,339,835 and built in 1974, spans 1,392,719 sqft. Last recorded transfer occurred on Oct 15."},{"ain":"2484024003","address":"3000 W ALAMEDA AVE","city":"BURBANK","zip":"91523","type":"studio","type_label":"Studio / Media","use_desc":"Motion Picture, Radio and Television Industry","assessed_total":726811997,"assessed_land":310816518,"assessed_improvement":415995479,"roll_year":"2025","recording_date":"2007-12-21T00:00:00.000Z","sqft":178427,"year_built":1954,"units":0,"brief":"The motion picture and media property at 3000 W Alameda Ave in Burbank, assessed at $726,811,997 for 178,427 sqft, last transferred on December 21st."},{"ain":"2424043032","address":"100 UNIVERSAL CITY PLAZA","city":"LOS ANGELES","zip":"91608","type":"studio","type_label":"Studio / Media","use_desc":"Motion Picture, Radio and Television Industry","assessed_total":708909993,"assessed_land":178478332,"assessed_improvement":530431661,"roll_year":"2025","recording_date":"2011-01-28T00:00:00.000Z","sqft":65532,"year_built":1924,"units":0,"brief":"The 65,532 sqft 1924-built Universal City Plaza studio property in Los Angeles, valued at $708,909,993, was last transferred on January 28."},{"ain":"5151015012","address":"333 S GRAND AVE","city":"LOS ANGELES","zip":"90071","type":"office","type_label":"Office","use_desc":"Office Building","assessed_total":682082790,"assessed_land":72313693,"assessed_improvement":609769097,"roll_year":"2025","recording_date":"2013-10-15T00:00:00.000Z","sqft":1480365,"year_built":1981,"units":0,"brief":"The office building at 333 S Grand Ave in Los Angeles has an assessed value of $682,082,790 and spans 1,480,365 square feet, last recorded to have transferred on October 15. Built in 1981."},{"ain":"2424043034","address":"3900 LANKERSHIM BLVD","city":"LOS ANGELES","zip":"90068","type":"studio","type_label":"Studio / Media","use_desc":"Motion Picture, Radio and Television Industry","assessed_total":652153484,"assessed_land":134253441,"assessed_improvement":517900043,"roll_year":"2025","recording_date":"2011-01-28T00:00:00.000Z","sqft":21585,"year_built":1965,"units":0,"brief":"The 21,585 sqft studio at 3900 Lankershim Blvd in Los Angeles, valued at $652,153,484 as of last transfer on Jan 28, 1965, supports the motion picture, radio, and television industry."},{"ain":"2424043021","address":"3900 LANKERSHIM BLVD","city":"LOS ANGELES","zip":"90068","type":"industrial","type_label":"Industrial","use_desc":"Heavy Manufacturing","assessed_total":631556702,"assessed_land":73689555,"assessed_improvement":557867147,"roll_year":"2025","recording_date":"2011-01-28T00:00:00.000Z","sqft":125487,"year_built":1981,"units":0,"brief":"The industrial property at 3900 Lankershim Blvd in Los Angeles, used for heavy manufacturing and with a assessed value of $631,556,702, last recorded transferred on January 28, features a building size of 125,487 sqft and was constructed in 1981."},{"ain":"4211010118","address":"5865 S CAMPUS CENTER DR","city":"LOS ANGELES","zip":"90094","type":"office","type_label":"Office","use_desc":"Office Building","assessed_total":583333400,"assessed_land":175581577,"assessed_improvement":407751823,"roll_year":"2025","recording_date":"2016-12-22T00:00:00.000Z","sqft":514260,"year_built":1943,"units":0,"brief":"The 514,260 sqft office building at 5865 S Campus Center Dr in Los Angeles has an assessed value of $583,333,400 and last transferred on Dec 22."}],"recent":[{"ain":"8264005913","address":null,"city":null,"zip":null,"type":"industrial","type_label":"Industrial","use_desc":"Industrial","assessed_total":0,"assessed_land":0,"assessed_improvement":0,"roll_year":"2025","recording_date":"2025-04-02T00:00:00.000Z","sqft":0,"year_built":0,"units":0,"brief":"Last recorded transfer for this industrial property was on April 2nd."},{"ain":"5147007901","address":"501 E 5TH ST","city":"LOS ANGELES","zip":"90013","type":"industrial","type_label":"Industrial","use_desc":"Industrial","assessed_total":0,"assessed_land":0,"assessed_improvement":0,"roll_year":"2025","recording_date":"2025-03-13T00:00:00.000Z","sqft":0,"year_built":0,"units":0,"brief":"The industrial property at 501 E 5th St, Los Angeles, had its last recorded transfer on March 13."},{"ain":"6015036011","address":"1745 W FLORENCE AVE","city":"LOS ANGELES","zip":"90047","type":"retail","type_label":"Retail","use_desc":"Store","assessed_total":405756,"assessed_land":312120,"assessed_improvement":93636,"roll_year":"2025","recording_date":"2025-01-21T00:00:00.000Z","sqft":1350,"year_built":1928,"units":0,"brief":"The retail store at 1745 W Florence Ave in Los Angeles, with a assessed value of $405,756 and 1,350 sqft of building space, was last transferred on January 21. Built in 1928."},{"ain":"7436006923","address":"1667 W 9TH ST","city":"LONG BEACH","zip":"90813","type":"industrial","type_label":"Industrial","use_desc":"Light Manufacturing","assessed_total":0,"assessed_land":0,"assessed_improvement":0,"roll_year":"2025","recording_date":"2025-01-17T00:00:00.000Z","sqft":16500,"year_built":1973,"units":0,"brief":"The 16,500 sqft light manufacturing property at 1667 W 9th St in Long Beach, built in 1973, last recorded transferred on Jan 17."},{"ain":"6239015023","address":null,"city":null,"zip":null,"type":"industrial","type_label":"Industrial","use_desc":"Light Manufacturing","assessed_total":0,"assessed_land":0,"assessed_improvement":0,"roll_year":"2025","recording_date":"2025-01-06T00:00:00.000Z","sqft":0,"year_built":0,"units":0,"brief":"Last recorded transfer for the light manufacturing industrial property was on January 6."},{"ain":"5586035044","address":"5766 HOLLYWOOD BLVD","city":"LOS ANGELES","zip":"90028","type":"retail","type_label":"Retail","use_desc":"Store Combination","assessed_total":78189905,"assessed_land":28000000,"assessed_improvement":50000000,"roll_year":"2025","recording_date":"2024-12-31T00:00:00.000Z","sqft":178421,"year_built":2021,"units":161,"brief":"The retail property at 5766 Hollywood Blvd in Los Angeles, a store combination occupying 178,421 sqft and built in 2021, has an assessed value of $78,189,905 as of last recorded transfer on December 31."},{"ain":"6303019014","address":"3385 LEONIS BLVD","city":"VERNON","zip":"90058","type":"industrial","type_label":"Industrial","use_desc":"Heavy Manufacturing","assessed_total":18724000,"assessed_land":8274000,"assessed_improvement":10450000,"roll_year":"2025","recording_date":"2024-12-31T00:00:00.000Z","sqft":55136,"year_built":1947,"units":0,"brief":"The 55,136 sqft heavy manufacturing property at 3385 Leonis Blvd in Vernon has an assessed value of $18,724,000 and was last recorded to have transferred on December 31st."},{"ain":"5442025039","address":"2965 ALLESANDRO ST","city":"LOS ANGELES","zip":"90039","type":"retail","type_label":"Retail","use_desc":"Store Combination","assessed_total":10404000,"assessed_land":3060000,"assessed_improvement":7344000,"roll_year":"2025","recording_date":"2024-12-31T00:00:00.000Z","sqft":33888,"year_built":2024,"units":25,"brief":"The retail property at 2965 Allesandro St in Los Angeles, with a assessed value of $10,404,000 and a building size of 33,888 sqft, was last recorded to have been transferred on December 31."},{"ain":"2350004070","address":"11410 BURBANK BLVD","city":"LOS ANGELES","zip":"91601","type":"retail","type_label":"Retail","use_desc":"Store","assessed_total":9000000,"assessed_land":9000000,"assessed_improvement":0,"roll_year":"2025","recording_date":"2024-12-31T00:00:00.000Z","sqft":12388,"year_built":1963,"units":6,"brief":"The retail store located at 11410 Burbank Blvd in Los Angeles, with a assessed value of $9,000,000 and a building size of 12,388 sqft, was last recorded to have transferred on December 31st."},{"ain":"2258012026","address":"17257 VENTURA BLVD","city":"LOS ANGELES","zip":"91316","type":"retail","type_label":"Retail","use_desc":"Store","assessed_total":8939799,"assessed_land":5231865,"assessed_improvement":3707934,"roll_year":"2025","recording_date":"2024-12-31T00:00:00.000Z","sqft":30162,"year_built":1980,"units":0,"brief":"The retail store located at 17257 Ventura Blvd in Los Angeles, with a assessed value of $8,939,799 and a building size of 30,162 sqft, was last recorded to have transferred on December 31st."},{"ain":"7432016034","address":"1442 W 16TH ST","city":"LONG BEACH","zip":"90813","type":"industrial","type_label":"Industrial","use_desc":"Light Manufacturing","assessed_total":8500000,"assessed_land":6200000,"assessed_improvement":2300000,"roll_year":"2025","recording_date":"2024-12-31T00:00:00.000Z","sqft":2212,"year_built":1982,"units":1,"brief":"The 2,212 sqft light manufacturing industrial property at 1442 W 16th St in Long Beach, assessed at $8,500,000, last transferred on December 31."},{"ain":"8382005032","address":"440 E ARROW HWY","city":"SAN DIMAS","zip":"91773","type":"industrial","type_label":"Industrial","use_desc":"Light Manufacturing","assessed_total":6869000,"assessed_land":3200000,"assessed_improvement":3669000,"roll_year":"2025","recording_date":"2024-12-31T00:00:00.000Z","sqft":18369,"year_built":1997,"units":0,"brief":"The 18,369 sqft light manufacturing property at 440 E Arrow Hwy in San Dimas has an assessed value of $6,869,000 and was last transferred on December 31st. Built in 1997."},{"ain":"6203022043","address":"4149 TWEEDY BLVD","city":"SOUTH GATE","zip":"90280","type":"retail","type_label":"Retail","use_desc":"Shopping Center (Neighborhood, Community)","assessed_total":5167728,"assessed_land":1118308,"assessed_improvement":4049420,"roll_year":"2025","recording_date":"2024-12-31T00:00:00.000Z","sqft":12321,"year_built":1989,"units":0,"brief":"The 12,321 sqft shopping center at 4149 Tweedy Blvd in South Gate, assessed at $5,167,728, last transferred on December 31st."},{"ain":"5282010030","address":"8966 GARVEY AVE","city":"ROSEMEAD","zip":"91770","type":"retail","type_label":"Retail","use_desc":"Store","assessed_total":5021460,"assessed_land":3258900,"assessed_improvement":1762560,"roll_year":"2025","recording_date":"2024-12-31T00:00:00.000Z","sqft":17745,"year_built":1985,"units":0,"brief":"The retail store located at 8966 Garvey Ave in Rosemead, with a assessed value of $5,021,460 and 17,745 sqft of building space built in 1985, last recorded transferred on December 31."},{"ain":"6213003027","address":"3480 E FLORENCE AVE","city":"HUNTINGTON PARK","zip":"90255","type":"retail","type_label":"Retail","use_desc":"Restaurant, Cocktail Lounge","assessed_total":4500000,"assessed_land":2750000,"assessed_improvement":1750000,"roll_year":"2025","recording_date":"2024-12-31T00:00:00.000Z","sqft":1866,"year_built":2024,"units":1,"brief":"The retail property at 3480 E Florence Ave in Huntington Park, a restaurant and cocktail lounge with a assessed value of $4,500,000 and 1,866 sqft, last recorded transferred on December 31."},{"ain":"6203022045","address":"4161 TWEEDY BLVD","city":"SOUTH GATE","zip":"90280","type":"retail","type_label":"Retail","use_desc":"Shopping Center (Neighborhood, Community)","assessed_total":4229779,"assessed_land":919898,"assessed_improvement":3309881,"roll_year":"2025","recording_date":"2024-12-31T00:00:00.000Z","sqft":10238,"year_built":1989,"units":0,"brief":"The 10,238 sqft shopping center at 4161 Tweedy Blvd in South Gate, assessed at $4,229,779, last transferred on December 31."},{"ain":"7432005047","address":"1501 SANTA FE AVE","city":"LONG BEACH","zip":"90813","type":"retail","type_label":"Retail","use_desc":"Store","assessed_total":4000000,"assessed_land":1325000,"assessed_improvement":2675000,"roll_year":"2025","recording_date":"2024-12-31T00:00:00.000Z","sqft":7760,"year_built":1947,"units":0,"brief":"The retail store located at 1501 Santa Fe Ave in Long Beach, with a assessed value of $4,000,000 and a building size of 7,760 sqft, was last recorded to have transferred on Tue Dec 31, 1947."},{"ain":"5511008002","address":"8240 BEVERLY BLVD","city":"LOS ANGELES","zip":"90048","type":"office","type_label":"Office","use_desc":"Office Building","assessed_total":3899998,"assessed_land":2924999,"assessed_improvement":974999,"roll_year":"2025","recording_date":"2024-12-31T00:00:00.000Z","sqft":6786,"year_built":1955,"units":0,"brief":"The 6,786 sqft office building located at 8240 Beverly Blvd in Los Angeles has an assessed value of $3,899,998 and was last transferred on December 31st. Built in 1955."},{"ain":"5636015189","address":"428 ARDEN AVE","city":"GLENDALE","zip":"91203","type":"office","type_label":"Office","use_desc":"Professional Building","assessed_total":3760000,"assessed_land":2300000,"assessed_improvement":1460000,"roll_year":"2025","recording_date":"2024-12-31T00:00:00.000Z","sqft":8436,"year_built":1985,"units":0,"brief":"The 8,436 sqft professional office building located at 428 Arden Ave in Glendale, assessed at $3,760,000, last transferred on December 31st."},{"ain":"2242027022","address":"15007 OXNARD ST","city":"LOS ANGELES","zip":"91411","type":"industrial","type_label":"Industrial","use_desc":"Light Manufacturing","assessed_total":3659487,"assessed_land":2639941,"assessed_improvement":1019546,"roll_year":"2025","recording_date":"2024-12-31T00:00:00.000Z","sqft":17015,"year_built":1946,"units":1,"brief":"The 17,015 sqft light manufacturing property at 15007 Oxnard St, Los Angeles, has an assessed value of $3,659,487 and was last transferred on December 31st. Built in 1946."}],"firms":[{"name":"CBRE, Inc.","agent_count":1213,"city":"LOS ANGELES","license_no":"00409987"},{"name":"New Star Realty, Inc.","agent_count":366,"city":"LOS ANGELES","license_no":"01096925"},{"name":"Graff Real Estate","agent_count":278,"city":"LOS ANGELES","license_no":"02041450"},{"name":"Forward Wilshire Inc","agent_count":208,"city":"LOS ANGELES","license_no":"01870534"},{"name":"Nourmand & Associates","agent_count":172,"city":"LOS ANGELES","license_no":"00656371"},{"name":"Newmark of Southern California Inc","agent_count":157,"city":"LOS ANGELES","license_no":"01355491"},{"name":"LF Assoc, Inc.","agent_count":146,"city":"LOS ANGELES","license_no":"01430290"},{"name":"Erdelyi Real Estate, Inc.","agent_count":137,"city":"LOS ANGELES","license_no":"01920782"},{"name":"D/Aq Corporation","agent_count":111,"city":"LOS ANGELES","license_no":"01129558"},{"name":"Savills Inc.","agent_count":94,"city":"LOS ANGELES","license_no":"00388260"},{"name":"Dream Realty & Investments Inc","agent_count":91,"city":"LOS ANGELES","license_no":"02205941"},{"name":"Transwestern Property Company West","agent_count":81,"city":"LOS ANGELES","license_no":"01263636"}]}
\ No newline at end of file
diff --git a/mockups/admin/data/news.json b/mockups/admin/data/news.json
new file mode 100644
index 00000000..806e6de7
--- /dev/null
+++ b/mockups/admin/data/news.json
@@ -0,0 +1 @@
+{"source":"rentv.com — live","fetched_at":"2026-07-22T20:20:02.708Z","count":30,"items":[{"id":"34236","title":"The Swig Company Obtains Refi on Office High-Rise in San Franciscos Financial District","url":"https://www.rentv.com/content/homepage/mainnews/news/34236","cat":"Financing","image":"https://www.rentv.com/images/dynamic/news_20294_220MontgomeryStSFNancyAmaralA2N2Jul162026.jpg"},{"id":"34233","title":"Tailwind Investment Group Spends $65 Mil on Two Sacramento Res Properties","url":"https://www.rentv.com/content/homepage/mainnews/news/34233","cat":"Multifamily","image":"https://www.rentv.com/images/dynamic/news_20291_6633ValleyHiDrSacramentoDavidHulmeTailwindJul182026.jpg"},{"id":"34239","title":"Fresno Multifamily Sale Works Out to $177k per Unit","url":"https://www.rentv.com/content/homepage/mainnews/news/34239","cat":"Multifamily","image":"https://www.rentv.com/images/dynamic/news_20297_585WestSierraAveFresnoDaveEbelingJul212026.jpg"},{"id":"34235","title":"Retail Portfolio in Downtown Long Beach Fetches $30 Mil","url":"https://www.rentv.com/content/homepage/mainnews/news/34235","cat":"Retail","image":"https://www.rentv.com/images/dynamic/news_20293_MosiacLongBeachAnneMonaghanJul202026.jpg"},{"id":"34224","title":"Shorenstein Buys 77k sf Bay Area Office Building","url":"https://www.rentv.com/content/homepage/mainnews/news/34224","cat":"Sales","image":"https://www.rentv.com/images/dynamic/news_20283_550AllertonRedwoodCityNickTrombolaNWMKJul162026.jpg"},{"id":"34226","title":"Carson Distribution Facility Acquired by WareSpace in a $23 Mil Deal","url":"https://www.rentv.com/content/homepage/mainnews/news/34226","cat":"Sales","image":"https://www.rentv.com/images/dynamic/news_20285_860SandhillAveCarsonElisabethManvilleSmartJul162026.jpg"},{"id":"34218","title":"Camden Property Trust Buys Gilbert, AZ Res Community in $124 Mil Deal","url":"https://www.rentv.com/content/homepage/mainnews/news/34218","cat":"Multifamily","image":"https://www.rentv.com/images/dynamic/news_20278_3150ERayRdGilbertKimHoidalCBREJul132026.jpg"},{"id":"34225","title":"CentrePoint Properties Spends $30 Mil on Trio of Colorado Retail Assets","url":"https://www.rentv.com/content/homepage/mainnews/news/34225","cat":"Retail","image":""},{"id":"34227","title":"MG Properties Buys 188-Unit Portland Res Asset","url":"https://www.rentv.com/content/homepage/mainnews/news/34227","cat":"Multifamily","image":"https://www.rentv.com/images/dynamic/news_20286_TupeloAlleyPortlandPaulKaseburgMGPropJul162026.jpg"},{"id":"34216","title":"Meta Housing Well Underway with 300-Unit Res Community in Woodland Hills","url":"https://www.rentv.com/content/homepage/mainnews/news/34216","cat":"Multifamily","image":"https://www.rentv.com/images/dynamic/news_20277_21300WOxnardStWHillsHollyJenvyJul152026.jpg"},{"id":"34214","title":"Intercontinental Real Estate Corporation Closes $69 Mil Retail Buy in Washington","url":"https://www.rentv.com/content/homepage/mainnews/news/34214","cat":"Retail","image":"https://www.rentv.com/images/dynamic/news_20274_1402LakeTappsPkwySEAuburnWABruceBeckJul152026.jpg"},{"id":"34208","title":"Eagle Partners and The Vistria Group Spend $132 Mil on Garden Grove Mixed-Income Res Community","url":"https://www.rentv.com/content/homepage/mainnews/news/34208","cat":"Multifamily","image":"https://www.rentv.com/images/dynamic/news_20267_12091BayportStGardenGroveCOSTARAnnieNoebelCornersCommJul142026.jpg"},{"id":"34204","title":"Oceanside Res Community Trades for $77.5 Mil","url":"https://www.rentv.com/content/homepage/mainnews/news/34204","cat":"Multifamily","image":"https://www.rentv.com/images/dynamic/news_20262_3851SherbourneDrOceansideDANKIRKSEYClaudiaLipmannCBREJul142026.jpg"},{"id":"34210","title":"BKM Capital Partners Boosts Pac Northwest Holdings with Purchase of 400k sf Industrial Buy in Washington","url":"https://www.rentv.com/content/homepage/mainnews/news/34210","cat":"Industrial","image":"https://www.rentv.com/images/dynamic/news_20270_SouthcenterWestBusinessParkTukwilaWASuleAygorenConnectJul142026.jpg"},{"id":"34203","title":"The Bascom Group Pays Over $53 Mil for OC Res Community","url":"https://www.rentv.com/content/homepage/mainnews/news/34203","cat":"Multifamily","image":"https://www.rentv.com/images/dynamic/news_20261_6968CampusDrBuenaParkJerryFinkBascomJul132026.jpg"},{"id":"34199","title":"Leasing Assignment for 650k sf San Francisco Office Tower Awarded to CBRE","url":"https://www.rentv.com/content/homepage/mainnews/news/34199","cat":"Sales","image":"https://www.rentv.com/images/dynamic/news_20259_415NatomaSFranciscoIrineSpivakCBREJun162026.jpg"},{"id":"34202","title":"SummerHill Apartment Communities Breaks Ground on New 251-Unit Bay Area Res Development","url":"https://www.rentv.com/content/homepage/mainnews/news/34202","cat":"Development","image":"https://www.rentv.com/images/dynamic/news_20260_11ElcaminoRealSMateoAnneMonaghanJul72026.jpg"},{"id":"34196","title":"Rubicon Point Partners Spends $53 Mil on Silicon Valley Medical/Office Property","url":"https://www.rentv.com/content/homepage/mainnews/news/34196","cat":"Sales","image":""},{"id":"34195","title":"Borstein Enterprises Picks Up 282k sf OC Industrial Asset","url":"https://www.rentv.com/content/homepage/mainnews/news/34195","cat":"Industrial","image":"https://www.rentv.com/images/dynamic/news_20256_15339BarrancaPkwyIrvineSavannahDurbinCWJul62026.jpg"},{"id":"34188","title":"Chino Distribution Facility Leased by Auto Parts Distributor in $42 Mil Deal","url":"https://www.rentv.com/content/homepage/mainnews/news/34188","cat":"Leases","image":"https://www.rentv.com/images/dynamic/news_20252_16380EuclidAveChinoElisabethManvilleSmartJul22026.jpg"},{"id":"34186","title":"Santa Clara Industrial Property Trades for $25.75 Mil","url":"https://www.rentv.com/content/homepage/mainnews/news/34186","cat":"Industrial","image":"https://www.rentv.com/images/dynamic/news_20250_651MartinAveSClaraGraceLewisJLLJul12026.jpg"},{"id":"34181","title":"Redwood West and Panattoni Buy The Pike Destination Center in Long Beach","url":"https://www.rentv.com/content/homepage/mainnews/news/34181","cat":"Retail","image":"https://www.rentv.com/images/dynamic/news_20245_95SPineAveLongBeachJessicaSpauldingJun302026.jpg"},{"id":"34180","title":"Kennedy Wilson and Jamison Form Partnership to Develop 4,000 Units of Affordable Housing in Los Angeles","url":"https://www.rentv.com/content/homepage/mainnews/news/34180","cat":"Development","image":"https://www.rentv.com/images/dynamic/news_20244_350SHopeBruceBeckJune302026.jpg"},{"id":"34086","title":"Oak Park Investments and Arise Investments Acquire Westlake Village Warehouse/Office Building in $19 Mil Transaction","url":"https://www.rentv.com/content/homepage/mainnews/news/34086","cat":"Industrial","image":"https://www.rentv.com/images/dynamic/news_20161_5785LinderoCanyonRdWstlkVillageDannySoroudiAriseJune22026.jpg"},{"id":"34177","title":"Holland Partner Group Closes $105 Mil Bay Area Res Buy","url":"https://www.rentv.com/content/homepage/mainnews/news/34177","cat":"Multifamily","image":"https://www.rentv.com/images/dynamic/news_20242_1432WestSanCarlosSt.jpg"},{"id":"34172","title":"Haven Housing buys 264-Unit Res Community in Austin Metro Area","url":"https://www.rentv.com/content/homepage/mainnews/news/34172","cat":"Multifamily","image":"https://www.rentv.com/images/dynamic/news_20237_15001StrathavenPassPflugervilleTXElliottGolanConnectJun262026.jpg"},{"id":"34174","title":"MG Properties Acquires Two Multifamily Properties in Gresham, OR in Deals Totaling $60.8 Mil","url":"https://www.rentv.com/content/homepage/mainnews/news/34174","cat":"Multifamily","image":"https://www.rentv.com/images/dynamic/news_20239_ParksideApartmentsGreshamORPaulKasebergMGPropJune262026.jpg"},{"id":"34171","title":"Leading AI Firm Leases 1.1 msf of Space at Luke Field in Glendale, AZ","url":"https://www.rentv.com/content/homepage/mainnews/news/34171","cat":"Leases","image":"https://www.rentv.com/images/dynamic/news_20236_7733LitchfieldRdGlendaleAZStaceyHershauerJun242026.jpg"},{"id":"34169","title":"Seattle Area Res Community Refinanced with $82.5 Mil Loan from Mesa West Capital","url":"https://www.rentv.com/content/homepage/mainnews/news/34169","cat":"Financing","image":"https://www.rentv.com/images/dynamic/news_20233_OlinFieldsEverettWABruceBeckJun242026.jpg"},{"id":"34160","title":"Apollo Lands in Gardena","url":"https://www.rentv.com/content/homepage/mainnews/news/34160","cat":"Sales","image":"https://www.rentv.com/images/dynamic/news_20227_12888CrenshawBlvdGardenaJadeTerryCityviewJun232026.jpg"}]}
\ No newline at end of file
diff --git a/mockups/admin/data/ticker.json b/mockups/admin/data/ticker.json
new file mode 100644
index 00000000..d4ae0a07
--- /dev/null
+++ b/mockups/admin/data/ticker.json
@@ -0,0 +1 @@
+{"fetched_at":"2026-07-22T20:20:02.971Z","la_office_vac":{"label":"LA OFFICE VAC","value":"23.1%","as_of":"Q2 2026","source":"CBRE/JLL market reports"},"ie_industrial_cap":{"label":"IE INDUSTRIAL CAP","value":"5.2%","as_of":"Q2 2026","source":"Colliers IE industrial"},"cre_index":{"label":"CRE INDEX","value":"4,159","change_pct":-0.49,"dir":"down","source":"Dow Jones U.S. Real Estate"},"ten_yr":{"label":"10-YR","value":"4.66%","change_bps":3,"dir":"up","source":"CBOE 10-Yr (^TNX)"}}
\ No newline at end of file
diff --git a/mockups/admin/data/videos.json b/mockups/admin/data/videos.json
new file mode 100644
index 00000000..ff1fd4f1
--- /dev/null
+++ b/mockups/admin/data/videos.json
@@ -0,0 +1 @@
+{"source":"rentvreview.com (The REview) — live","fetched_at":"2026-07-20T18:46:15.717Z","count":17,"cats":["RENTV Originals","JLL TV","Most Recent","Industry Events","Featured","Most Viewed"],"items":[{"id":"orig-brand","cat":"RENTV Originals","mp4":"/media/originals/brand.mp4","thumb":"/media/originals/brand.jpg","title":"RENTV.com — The Regional Authority","desc":"Western U.S. commercial real estate news since 1998."},{"id":"orig-deals","cat":"RENTV Originals","mp4":"/media/originals/deals.mp4","thumb":"/media/originals/deals.jpg","title":"The Deals Break Here First","desc":"Financing, leases, development and sales across the Western market."},{"id":"orig-review","cat":"RENTV Originals","mp4":"/media/originals/review.mp4","thumb":"/media/originals/review.jpg","title":"The REview — Face to Face with the Dealmakers","desc":"Interviews and insight from the people shaping CRE."},{"id":"orig-daily","cat":"RENTV Originals","mp4":"/media/originals/daily.mp4","thumb":"/media/originals/daily.jpg","title":"RENTV Daily — In Your Inbox, Free","desc":"Every Western CRE deal each morning."},{"id":"2898","yt":"79WFDGZYos4","title":"JLL’s Supply Chain & Logistics Solutions Overview","desc":"We are at the forefront of supply chain trends, focused on delivering top-down supply chain strategy and ground-up execution to help you save time, reduce costs, improve services and minimize risk.
When it comes to recognizing the ","cat":"JLL TV","view_url":"https://www.rentvreview.com/Videos/View/2898","thumb":"https://img.youtube.com/vi/79WFDGZYos4/hqdefault.jpg","embed":"https://www.youtube.com/embed/79WFDGZYos4"},{"id":"3302","yt":"xKYEQkUG5zM","title":"Commercial Real Estate Tech & AI 2026 with Helen Calvin","desc":"Adoption and investment in tech and AI have accelerated in the commercial real estate industry. Finally, right? How should you pick the right tech, the right system, the right provider? When picking a broker to sell your property should you","cat":"Most Recent","view_url":"https://www.rentvreview.com/Videos/View/3302","thumb":"https://img.youtube.com/vi/xKYEQkUG5zM/hqdefault.jpg","embed":"https://www.youtube.com/embed/xKYEQkUG5zM"},{"id":"3273","yt":"eC-oSUBMjIc","title":"ICSC Southern California Kickoff Panel","desc":"Commercial real estate is a constantly evolving industry, and staying ahead of the curve is crucial for success. Recently, a panel discussion at the Hyatt Regency Huntington Beach Resort & Spa brought together leading developers to share th","cat":"Industry Events","view_url":"https://www.rentvreview.com/Videos/View/3273","thumb":"https://img.youtube.com/vi/eC-oSUBMjIc/hqdefault.jpg","embed":"https://www.youtube.com/embed/eC-oSUBMjIc"},{"id":"3301","yt":"O6Mh2VmXGzg","title":"Office Update with Yardi","desc":"In this episode of America’s Commercial Real Estate Show, host Michael Bull is joined by Doug Ressler and Peter Kolaczynski from Yardi Matrix to break down the evolving office market in 2026.

They explore key trends in of","cat":"Most Recent","view_url":"https://www.rentvreview.com/Videos/View/3301","thumb":"https://img.youtube.com/vi/O6Mh2VmXGzg/hqdefault.jpg","embed":"https://www.youtube.com/embed/O6Mh2VmXGzg"},{"id":"3300","yt":"Wm_dhTl8gn8","title":"Single Tenant Cap Rates and Market Intel with Nancy Miller, CCIM","desc":"Nancy Miller with Bull Realty joins Michael to discuss the latest cap rates, loan rates, and expanding tenants in the single tenant net lease investment sector. Discussions include market intel, cap rates, mistakes to avoid, and investor st","cat":"Featured","view_url":"https://www.rentvreview.com/Videos/View/3300","thumb":"https://img.youtube.com/vi/Wm_dhTl8gn8/hqdefault.jpg","embed":"https://www.youtube.com/embed/Wm_dhTl8gn8"},{"id":"3299","yt":"6EJEWbXFQ-c","title":"People Live in Homes Not Corporations Housing Bill Update with Mitch Roschelle","desc":"The 21st Century ROAD to Housing Act (HR6644) passed by the Senate on March 12th, aims to increase U.S housing supply, reduce costs and modernize financing representing a major federal investment in housing. Part of the bill, with some carv","cat":"Featured","view_url":"https://www.rentvreview.com/Videos/View/3299","thumb":"https://img.youtube.com/vi/6EJEWbXFQ-c/hqdefault.jpg","embed":"https://www.youtube.com/embed/6EJEWbXFQ-c"},{"id":"3298","yt":"_1W6U47VN6g","title":"U.S. Hotel Performance Forecast with Ryan Meliker","desc":"As world events unfold and America first implications impact the economy and travel, how might U.S. hotels perform moving forward? What cities hold promise for investors and developers? Join show host and commercial broker Michael Bull, CCI","cat":"Featured","view_url":"https://www.rentvreview.com/Videos/View/3298","thumb":"https://img.youtube.com/vi/_1W6U47VN6g/hqdefault.jpg","embed":"https://www.youtube.com/embed/_1W6U47VN6g"},{"id":"1034","yt":"ql3qVQNRQJ8","title":"LoopNet vs Crexi: Which is Better for Net Lease Property Sales?","desc":"In this video, we take a deep dive into the comparisons between the leading commercial real estate marketplace platforms, LoopNet and Crexi.

SUBSCRIBE to our newsletter to have the top stories hand-delivered to your inbox","cat":"Most Viewed","view_url":"https://www.rentvreview.com/Videos/View/1034","thumb":"https://img.youtube.com/vi/ql3qVQNRQJ8/hqdefault.jpg","embed":"https://www.youtube.com/embed/ql3qVQNRQJ8"},{"id":"1650","yt":"-_QFDzl48tU","title":"1031 Exchange Explained: 45 Day Rule Checklist","desc":"Looking to invest in real estate and want the 1031 exchange explained? Make sure you understand the 1031 exchange rule with this free 45 day rule checklist! 

The 1031 exchange rule is a complicated but important process f","cat":"Featured","view_url":"https://www.rentvreview.com/Videos/View/1650","thumb":"https://img.youtube.com/vi/-_QFDzl48tU/hqdefault.jpg","embed":"https://www.youtube.com/embed/-_QFDzl48tU"},{"id":"3261","yt":"v8CaeZHpTMM","title":"VeganBurg Now Open at High Desert Gateway","desc":"VeganBurg Now Open at High Desert Gateway
","cat":"Industry Events","view_url":"https://www.rentvreview.com/Videos/View/3261","thumb":"https://img.youtube.com/vi/v8CaeZHpTMM/hqdefault.jpg","embed":"https://www.youtube.com/embed/v8CaeZHpTMM"},{"id":"3237","yt":"ujVQ-m0gEpw","title":"Stater Bros. Markets Grand Opening Celebration at The Collection","desc":"Stater Bros. Markets Grand Opening Celebration at The Collection
","cat":"Featured","view_url":"https://www.rentvreview.com/Videos/View/3237","thumb":"https://img.youtube.com/vi/ujVQ-m0gEpw/hqdefault.jpg","embed":"https://www.youtube.com/embed/ujVQ-m0gEpw"},{"id":"3230","yt":"8UtGSxHYQXY","title":"Project Spotlight: The Commons at Meridian","desc":"Project Spotlight: The Commons at Meridian
","cat":"Featured","view_url":"https://www.rentvreview.com/Videos/View/3230","thumb":"https://img.youtube.com/vi/8UtGSxHYQXY/hqdefault.jpg","embed":"https://www.youtube.com/embed/8UtGSxHYQXY"},{"id":"3229","yt":"HzCoIw71Cv8","title":"ICSC & The Western Conference 2024 with Vicky Hammond","desc":"ICSC & The Western Conference with Vicky Hammond 2024
","cat":"Featured","view_url":"https://www.rentvreview.com/Videos/View/3229","thumb":"https://img.youtube.com/vi/HzCoIw71Cv8/hqdefault.jpg","embed":"https://www.youtube.com/embed/HzCoIw71Cv8"}]}
\ No newline at end of file
diff --git a/mockups/admin/index.html b/mockups/admin/index.html
new file mode 100644
index 00000000..7028977d
--- /dev/null
+++ b/mockups/admin/index.html
@@ -0,0 +1,176 @@
+<!doctype html><html lang="en"><head>
+<meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
+<title>RENTV Admin · Broker & Owner Intelligence</title>
+<link rel="stylesheet" href="../assets/base.css">
+<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&display=swap" rel="stylesheet">
+<style>
+ body{background:#0d1014;color:#e7ecf1;font-family:'Inter',system-ui,sans-serif;font-size:14px}
+ .wrap{max-width:1240px;margin:0 auto;padding:18px}
+ .head{display:flex;align-items:baseline;justify-content:space-between;flex-wrap:wrap;gap:8px;margin-bottom:14px}
+ .head h1{font-size:24px;font-weight:800}.head h1 span{color:#c8102e}
+ .head .fresh{font-size:12px;color:#8b939b}
+ .tabs{display:flex;gap:4px;border-bottom:1px solid #232a32;margin-bottom:14px}
+ .tabs button{background:none;border:0;color:#8b939b;font:800 13px/1 'Inter';letter-spacing:.03em;padding:12px 16px;cursor:pointer;border-bottom:3px solid transparent}
+ .tabs button.on{color:#fff;border-color:#c8102e}
+ .tabs button .c{background:#1a222b;border-radius:20px;padding:2px 8px;font-size:11px;margin-left:6px}
+ .toolbar{display:flex;gap:10px;flex-wrap:wrap;align-items:center;margin-bottom:12px}
+ .toolbar input[type=search]{flex:1;min-width:260px;background:#11161c;border:1px solid #232a32;border-radius:9px;color:#e7ecf1;padding:11px 14px;font:inherit}
+ .toolbar select{background:#11161c;border:1px solid #232a32;border-radius:9px;color:#e7ecf1;padding:11px 12px;font:inherit}
+ .toolbar .n{color:#8b939b;font-size:12px}
+ .toolbar .dens{display:flex;align-items:center;gap:8px;color:#8b939b;font-size:12px}
+ .list{display:flex;flex-direction:column;gap:8px}
+ .row{background:#11161c;border:1px solid #232a32;border-radius:11px;overflow:hidden}
+ .row .r{display:grid;grid-template-columns:1fr auto;gap:12px;padding:13px 16px;cursor:pointer;align-items:center}
+ .row .r:hover{background:#141b22}
+ .who{display:flex;flex-direction:column;gap:3px;min-width:0}
+ .who .nm{font-weight:700;font-size:15px}
+ .who .sub{font-size:12.5px;color:#9aa4ad;display:flex;gap:8px;flex-wrap:wrap}
+ .who .sub a{color:#7cc0ff;text-decoration:none;border-bottom:1px dotted #3a5064}
+ .who .sub a:hover{color:#a9d5ff}
+ .badge{font-size:10px;font-weight:800;letter-spacing:.04em;text-transform:uppercase;padding:2px 7px;border-radius:20px;background:#1a222b;color:#9aa4ad}
+ .badge.lic{color:#37d67a;background:#123020}
+ .metric{text-align:right;white-space:nowrap}.metric b{font-size:16px}.metric span{font-size:11px;color:#8b939b;display:block}
+ .exp{border-top:1px solid #232a32;padding:14px 16px;background:#0e141a;display:none}
+ .row.open .exp{display:block}
+ .row.open{border-color:#3a4652}
+ .acts{display:flex;gap:8px;flex-wrap:wrap}
+ .acts a{display:inline-flex;align-items:center;gap:7px;background:#12161c;border:1px solid #2a333d;border-radius:9px;padding:9px 13px;color:#dbe1e7;text-decoration:none;font-weight:700;font-size:13px}
+ .acts a:hover{border-color:#c8102e;color:#fff}
+ .acts a .i{font-size:15px}
+ .kv{display:flex;gap:20px;flex-wrap:wrap;margin-top:12px;font-size:13px;color:#9aa4ad}
+ .kv b{color:#e7ecf1}
+ .compact .row .r{padding:8px 14px}.compact .who .nm{font-size:14px}
+ .empty{color:#6b747d;padding:30px;text-align:center}
+</style></head>
+<body>
+<div class="wrap">
+ <div class="head" data-eln>
+ <h1>RENTV Admin · <span>Broker & Owner Intelligence</span></h1>
+ <div class="fresh" id="fresh">Loading…</div>
+ </div>
+ <div class="tabs" data-eln id="tabs">
+ <button data-tab="brokers" class="on">Brokers <span class="c" id="cB">0</span></button>
+ <button data-tab="firms">Firms <span class="c" id="cF">0</span></button>
+ <button data-tab="owners">Owners & Assets <span class="c" id="cO">0</span></button>
+ </div>
+ <div class="toolbar" data-eln>
+ <input type="search" id="q" placeholder="Search name, firm, city, license…">
+ <select id="sort" title="Sort">
+ <option value="name">Name A→Z</option>
+ <option value="city">City</option>
+ <option value="firm">Firm</option>
+ <option value="agents">Agents ↓</option>
+ </select>
+ <label class="dens">Density <input type="range" id="dens" min="0" max="1" step="1" value="0"></label>
+ <span class="n" id="count"></span>
+ </div>
+ <div class="list" data-eln id="list"></div>
+</div>
+<script src="../assets/chrome.js"></script>
+<script>
+const A={brokers:[],firms:[],owners:[],tab:'brokers'};
+const enc=encodeURIComponent, esc=RENTV.esc;
+const LI_P=(n,f)=>`https://www.linkedin.com/search/results/people/?keywords=${enc([n,f].filter(Boolean).join(' '))}`;
+const LI_C=f=>`https://www.linkedin.com/search/results/companies/?keywords=${enc(f)}`;
+const WEB=f=>`https://www.google.com/search?q=${enc('"'+f+'" real estate official website')}`;
+const MAPS=q=>`https://www.google.com/maps/search/?api=1&query=${enc(q)}`;
+const DRE=lic=>`https://www2.dre.ca.gov/PublicASP/pplinfo.asp?License_id=${enc(lic)}`;
+const GOOG=q=>`https://www.google.com/search?q=${enc(q)}`;
+const ASSR=ain=>`https://portal.assessor.lacounty.gov/parceldetail/${enc(ain)}`;
+
+function actBtn(href,icon,label){return `<a href="${href}" target="_blank" rel="noopener"><span class="i">${icon}</span>${label}</a>`;}
+
+function rowHTML(kind,x,i){
+ if(kind==='brokers'){
+ const loc=[x.city,x.state_code].filter(Boolean).join(', ');
+ return `<div class="row" data-k="brokers" data-i="${i}">
+ <div class="r"><div class="who">
+ <div class="nm">${esc(x.name)}</div>
+ <div class="sub"><span class="badge">${esc(x.license_type||'Licensee')}</span>
+ ${x.firm_name?`<a href="${LI_C(x.firm_name)}" target="_blank" rel="noopener" onclick="event.stopPropagation()">${esc(x.firm_name)}</a>`:''}
+ ${loc?`<a href="${MAPS(x.firm_name+' '+loc)}" target="_blank" rel="noopener" onclick="event.stopPropagation()">${esc(loc)}</a>`:''}
+ ${x.license_no?`<a href="${DRE(x.license_no)}" target="_blank" rel="noopener" onclick="event.stopPropagation()" class="lic">DRE ${esc(x.license_no)}</a>`:''}
+ </div></div>
+ <div class="metric"><b>${esc((x.license_status||'—'))}</b><span>${esc(x.source||'')}</span></div>
+ </div>
+ <div class="exp"><div class="acts">
+ ${actBtn(LI_P(x.name,x.firm_name),'in','Find on LinkedIn')}
+ ${actBtn(GOOG(x.name+' '+(x.firm_name||'')+' '+loc),'🔎','Google this broker')}
+ ${x.firm_name?actBtn(WEB(x.firm_name),'🌐','Firm website'):''}
+ ${x.firm_name?actBtn(LI_C(x.firm_name),'🏢','Firm on LinkedIn'):''}
+ ${loc?actBtn(MAPS((x.firm_name||x.name)+' '+loc),'📍','Address / Map'):''}
+ ${x.license_no?actBtn(DRE(x.license_no),'🪪','CA DRE license'):''}
+ </div><div class="kv"><span>License <b>${esc(x.license_no||'—')}</b></span><span>Type <b>${esc(x.license_type||'—')}</b></span><span>Firm <b>${esc(x.firm_name||'—')}</b></span><span>City <b>${esc(x.city||'—')}</b></span></div></div>
+ </div>`;
+ }
+ if(kind==='firms'){
+ const loc=[x.hq_city,x.hq_state].filter(Boolean).join(', ');
+ return `<div class="row" data-k="firms" data-i="${i}">
+ <div class="r"><div class="who"><div class="nm">${esc(x.name)}</div>
+ <div class="sub"><span class="badge lic">DRE ${esc(x.license_no||'')}</span>
+ ${loc?`<a href="${MAPS(x.name+' '+loc)}" target="_blank" rel="noopener" onclick="event.stopPropagation()">${esc(loc)}</a>`:''}
+ <a href="${WEB(x.name)}" target="_blank" rel="noopener" onclick="event.stopPropagation()">website</a></div></div>
+ <div class="metric"><b>${(x.agent_count||0).toLocaleString()}</b><span>agents</span></div></div>
+ <div class="exp"><div class="acts">
+ ${actBtn(LI_C(x.name),'🏢','Firm on LinkedIn')}
+ ${actBtn(WEB(x.name),'🌐','Official website')}
+ ${actBtn(MAPS(x.name+' '+loc),'📍','HQ / Map')}
+ ${x.license_no?actBtn(DRE(x.license_no),'🪪','CA DRE (corp)'):''}
+ ${actBtn(GOOG(x.name+' brokers '+loc),'🔎','Google the firm')}
+ </div><div class="kv"><span>Agents <b>${(x.agent_count||0).toLocaleString()}</b></span><span>HQ <b>${esc(loc||'—')}</b></span><span>License <b>${esc(x.license_no||'—')}</b></span></div></div>
+ </div>`;
+ }
+ // owners & assets (marquee)
+ const addr=[x.address,x.city].filter(Boolean).join(', ');
+ return `<div class="row" data-k="owners" data-i="${i}">
+ <div class="r"><div class="who"><div class="nm">${esc(x.address||x.ain)}</div>
+ <div class="sub"><span class="badge">${esc(x.type_label||'')}</span>
+ <a href="${MAPS(addr)}" target="_blank" rel="noopener" onclick="event.stopPropagation()">${esc(addr)}</a>
+ <span>${esc(x.use_desc||'')}</span></div></div>
+ <div class="metric"><b>${RENTV.shortUsd(x.assessed_total)}</b><span>assessed</span></div></div>
+ <div class="exp"><div class="acts">
+ ${actBtn(MAPS(addr),'📍','Map address')}
+ ${actBtn(GOOG(addr+' '+(x.use_desc||'')+' owner'),'🔎','Find owner / deal')}
+ ${actBtn('https://www.google.com/maps/@?api=1&map_action=pano&viewpoint='+enc(addr),'📸','Street View')}
+ ${actBtn(ASSR(x.ain),'🏛️','LA County Assessor')}
+ </div><div class="kv"><span>SqFt <b>${(x.sqft||0).toLocaleString()}</b></span><span>Built <b>${x.year_built||'—'}</b></span><span>AIN <b>${esc(x.ain)}</b></span><span>Recorded <b>${RENTV.dstr(x.recording_date)}</b></span></div></div>
+ </div>`;
+}
+
+function currentRows(){
+ const t=A.tab, q=(document.getElementById('q').value||'').toLowerCase();
+ let rows=A[t].slice();
+ if(q) rows=rows.filter(x=>JSON.stringify(x).toLowerCase().includes(q));
+ const s=document.getElementById('sort').value;
+ const key={name:'name',city:t==='firms'?'hq_city':'city',firm:t==='brokers'?'firm_name':'name',agents:'agent_count'}[s];
+ rows.sort((a,b)=> s==='agents' ? (b.agent_count||0)-(a.agent_count||0) : String(a[key]||'').localeCompare(String(b[key]||'')));
+ return rows;
+}
+function render(){
+ const rows=currentRows();
+ document.getElementById('list').innerHTML = rows.length?rows.map((x,i)=>rowHTML(A.tab,x,i)).join(''):'<div class="empty">No matches.</div>';
+ document.getElementById('count').textContent=rows.length+' shown';
+}
+document.getElementById('tabs').addEventListener('click',e=>{const b=e.target.closest('button');if(!b)return;
+ document.querySelectorAll('#tabs button').forEach(x=>x.classList.remove('on'));b.classList.add('on');A.tab=b.dataset.tab;render();});
+document.getElementById('q').addEventListener('input',render);
+document.getElementById('sort').addEventListener('change',render);
+document.getElementById('dens').addEventListener('input',e=>document.getElementById('list').classList.toggle('compact',e.target.value==='1'));
+document.getElementById('list').addEventListener('click',e=>{const r=e.target.closest('.row');if(!r||e.target.closest('a'))return;r.classList.toggle('open');});
+
+RENTV.mount({dark:true, layout:'A01'}); // hamburger + user chrome + numbered components
+// load the broker/firm registry directly (chrome bundles only the news snapshot):
+(async()=>{
+ const [b,f]=await Promise.all([fetch('data/brokers.json').then(r=>r.json()).catch(()=>({rows:[]})),
+ fetch('data/firms.json').then(r=>r.json()).catch(()=>({rows:[]}))]);
+ A.brokers=b.rows||[]; A.firms=f.rows||[];
+ // owners from the la-commercial snapshot the chrome already fetched
+ A.owners=(RENTV.data&&RENTV.data.la&&RENTV.data.la.marquee)||[];
+ document.getElementById('cB').textContent=(b.total||A.brokers.length).toLocaleString();
+ document.getElementById('cF').textContent=(f.total||A.firms.length).toLocaleString();
+ document.getElementById('cO').textContent=A.owners.length;
+ document.getElementById('fresh').textContent='CA DRE registry · '+A.brokers.length+' brokers loaded of '+(b.total||0).toLocaleString()+' statewide · synced from the usrealestate back-end';
+ render();
+})();
+</script>
+</body></html>
diff --git a/mockups/assets/base.css b/mockups/assets/base.css
index 8769ca31..e11b62dd 100644
--- a/mockups/assets/base.css
+++ b/mockups/assets/base.css
@@ -18,8 +18,8 @@ html,body{margin:0}
.rv-top.dark .rv-burger:hover{background:rgba(255,255,255,.08)}
.rv-burger svg{display:block}
.rv-burger .lbl{font-size:12px;font-weight:800;letter-spacing:.14em;text-transform:uppercase;color:var(--sub)}
-.rv-brand{position:absolute;left:50%;transform:translateX(-50%);font-family:Georgia,'Playfair Display',serif;
- font-weight:700;font-size:20px;letter-spacing:-.5px;color:inherit;text-decoration:none}
+.rv-brand{position:absolute;left:50%;transform:translateX(-50%);font-family:'Playfair Display',Georgia,serif;
+ font-weight:800;font-size:24px;letter-spacing:.02em;color:inherit;text-decoration:none}
.rv-brand b{color:var(--rentv-red)}
.rv-user{width:36px;height:36px;border-radius:50%;border:1.5px solid var(--line);background:#fff;cursor:pointer;
display:inline-flex;align-items:center;justify-content:center;color:var(--ink)}
diff --git a/mockups/rentv.html b/mockups/rentv.html
new file mode 100644
index 00000000..5f8c83b2
--- /dev/null
+++ b/mockups/rentv.html
@@ -0,0 +1,114 @@
+<!doctype html><html lang="en"><head>
+<meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
+<title>RENTV — flagship (no tabs · bottom breaking bar)</title>
+<link rel="stylesheet" href="assets/base.css">
+<link href="https://fonts.googleapis.com/css2?family=Playfair+Display:ital,wght@0,700;0,800;1,600&family=Inter:wght@400;500;600;700;800&display=swap" rel="stylesheet">
+<style>
+ body{background:#fbfbfc;color:#14171a;font-family:'Inter',system-ui,sans-serif}
+ /* HERO = one fold; the breaking bar is pinned to the BOTTOM of the fold */
+ .fold{min-height:calc(100vh - 52px);display:flex;flex-direction:column}
+ .wrap{max-width:1240px;margin:0 auto;padding:0 22px;width:100%}
+ /* signature: a live CRE data strip above the hero (says "this is a CRE data publication") */
+ .datastrip{border-bottom:1px solid #e8e4e0;background:#f7f5f2}
+ .datastrip .in{max-width:1240px;margin:0 auto;display:flex;gap:34px;padding:9px 22px;font-size:11px;font-weight:500;letter-spacing:.06em;color:#4a4f55;overflow:hidden;white-space:nowrap}
+ .datastrip .m b{color:#14171a;font-weight:700;margin-left:6px}.datastrip .m b.dn{color:#c8102e}.datastrip .m b.up{color:#0f8a4d}
+ .hero{flex:1;display:grid;grid-template-columns:1.55fr 1fr;gap:34px;align-items:center;padding:28px 0}
+ .lead{padding-right:34px;border-right:1px solid #e2ded9} /* broadsheet hairline column */
+ .lead .im{position:relative;height:380px;border-radius:6px;display:block;margin-bottom:16px;box-shadow:inset 0 -90px 70px -50px rgba(0,0,0,.35)}
+ .lead .tag{color:var(--rentv-red,#c8102e);font-weight:800;font-size:12px;letter-spacing:.14em;text-transform:uppercase}
+ .lead h1{font-family:'Playfair Display',serif;font-size:clamp(46px,4vw,64px);line-height:1.08;margin:9px 0 12px;font-weight:700;letter-spacing:-.01em}
+ .lead .byl{color:#6b7178;font-size:13px}
+ .aside{display:flex;flex-direction:column;gap:0}
+ .aside a{display:grid;grid-template-columns:80px 1fr;gap:13px;text-decoration:none;color:#14171a;border-bottom:1px solid #e8e4e0;padding:13px 0}
+ .aside a:first-child{padding-top:0}
+ .aside .im{height:58px;border-radius:5px;display:block}
+ .aside .tag{font-size:9px;font-weight:800;letter-spacing:.1em;text-transform:uppercase}
+ .aside h4{font:600 14px/1.32 'Inter';margin-top:3px}
+ /* ── BREAKING BAR — bottom of the fold, scrolling, hover-pause + hover-select ── */
+ .breaking{background:#0b0e12;color:#fff;border-top:3px solid var(--rentv-red,#c8102e)}
+ .breaking .in{max-width:1240px;margin:0 auto;display:flex;align-items:stretch;height:52px}
+ .breaking .lbl{background:var(--rentv-red,#c8102e);display:flex;align-items:center;gap:9px;padding:0 20px;font-weight:800;font-size:12px;letter-spacing:.18em;text-transform:uppercase;white-space:nowrap;flex:none;box-shadow:3px 0 0 rgba(255,255,255,.06)}
+ .breaking .lbl .dot{width:8px;height:8px;border-radius:50%;background:#fff;animation:bpulse 1.1s infinite}
+ @keyframes bpulse{50%{opacity:.3;transform:scale(.8)}}
+ .ticker{position:relative;overflow:hidden;flex:1}
+ .ticker .track{display:flex;align-items:center;gap:0;height:100%;white-space:nowrap;
+ animation:bscroll 52s linear infinite;will-change:transform}
+ .ticker:hover .track{animation-play-state:paused} /* hover ANYWHERE pauses */
+ @keyframes bscroll{from{transform:translateX(0)}to{transform:translateX(-50%)}}
+ .ticker .it{display:inline-flex;align-items:center;gap:11px;padding:0 24px;height:100%;color:#c3cbd3;
+ text-decoration:none;font-size:14px;font-weight:600;cursor:pointer;border-right:1px solid #1a2129;transition:background .14s,color .14s}
+ .ticker .it .c{font-size:10px;font-weight:800;letter-spacing:.06em;text-transform:uppercase;padding:2px 8px;border-radius:20px;background:#161d25;color:#8b939b}
+ .ticker .it:hover{background:rgba(200,16,46,.16);color:#fff} /* full-height red wash = select */
+ .ticker .it:hover .c{background:var(--rentv-red,#c8102e);color:#fff}
+ .ticker .it.sel{background:var(--rentv-red,#c8102e);color:#fff}
+ .ticker .it.sel .c{background:#fff;color:var(--rentv-red,#c8102e)}
+ .ticker .paused{position:absolute;right:16px;top:50%;transform:translateY(-50%);z-index:3;font-size:9px;font-weight:700;
+ letter-spacing:.16em;color:rgba(255,255,255,.5);opacity:0;transition:opacity .3s;pointer-events:none}
+ .ticker:hover .paused{opacity:1}
+ .ticker .fade{position:absolute;top:0;bottom:0;width:64px;pointer-events:none;z-index:2}
+ .ticker .fade.l{left:0;background:linear-gradient(90deg,#0b0e12,transparent)}
+ .ticker .fade.r{right:0;background:linear-gradient(270deg,#0b0e12,transparent)}
+ /* selected-headline reader (opens inline above the bar) */
+ .selbar{max-width:1240px;margin:0 auto;display:none;padding:12px 22px;background:#11161c;color:#e7ecf1;border-top:1px solid #1c232b;align-items:center;gap:14px}
+ .selbar.on{display:flex}
+ .selbar .c{font-size:10px;font-weight:800;text-transform:uppercase;letter-spacing:.05em;background:var(--rentv-red,#c8102e);padding:3px 9px;border-radius:20px}
+ .selbar a{color:#fff;font-weight:700;text-decoration:none}.selbar a:hover{text-decoration:underline}
+ .selbar .x{margin-left:auto;background:none;border:0;color:#8b939b;cursor:pointer;font-size:18px}
+ /* below the fold */
+ .sec{padding:34px 0}
+ h2.rule{font-size:13px;text-transform:uppercase;letter-spacing:.09em;border-top:2px solid #14171a;padding-top:10px;margin-bottom:16px;font-weight:800}
+ .river{display:grid;grid-template-columns:repeat(4,1fr);gap:18px}
+ .river a{text-decoration:none;color:#14171a}.river .im{height:130px;border-radius:5px;display:block;margin-bottom:8px}
+ .river .tag{font-size:10px;font-weight:800;text-transform:uppercase}.river h4{font:600 15px/1.25 'Inter';margin-top:3px}
+ @media(max-width:900px){.hero{grid-template-columns:1fr}.river{grid-template-columns:1fr 1fr}.breaking .in{height:auto}}
+</style></head>
+<body>
+<div class="fold">
+ <div class="datastrip" data-eln><div class="in" id="datastrip"></div></div>
+ <main class="wrap">
+ <section class="hero">
+ <div class="lead" data-eln id="lead"></div>
+ <div class="aside" data-eln id="aside"></div>
+ </section>
+ </main>
+ <div class="selbar" id="selbar" data-eln></div>
+ <div class="breaking" data-eln>
+ <div class="in">
+ <div class="lbl"><span class="dot"></span> Breaking</div>
+ <div class="ticker" id="ticker"><div class="fade l"></div><div class="fade r"></div><span class="paused">Paused · hover to browse</span><div class="track" id="track"></div></div>
+ </div>
+ </div>
+</div>
+<main class="wrap">
+ <section class="sec"><h2 class="rule" data-eln>Across the market</h2><div class="river" data-eln id="river"></div></section>
+</main>
+<script src="assets/chrome.js"></script>
+<script>
+RENTV.mount({layout:'FLAG', render(d){
+ const {esc,imgTag,sectionColor}=RENTV;
+ // signature CRE data strip (real ticker metrics)
+ const t=d.ticker||{};
+ document.getElementById('datastrip').innerHTML=Object.values(t).filter(m=>m&&m.label).map(m=>{
+ const cls=m.dir==='up'?'up':m.dir==='down'?'dn':'';
+ return `<span class="m">${esc(m.label)}<b class="${cls}">${esc(m.value)}${m.change_pct!=null?` ${m.change_pct>0?'+':''}${m.change_pct}%`:''}</b></span>`;
+ }).join('');
+ const it=d.news.items||[], l=it[0];
+ lead.innerHTML=`${imgTag(l.image,'im',l.id)}<span class="tag">${esc(l.cat)} · Western U.S.</span><h1>${esc(l.title)}</h1><div class="byl">By RENTV Staff · live from rentv.com</div>`;
+ aside.innerHTML=it.slice(1,5).map(n=>`<a href="${esc(n.url)}">${imgTag(n.image,'im',n.id)}<div><span class="tag" style="color:${sectionColor(n.cat)}">${esc(n.cat)}</span><h4>${esc(n.title)}</h4></div></a>`).join('');
+ // breaking ticker — duplicate the set so the loop is seamless; hover pauses, hover-item selects
+ const items=it.slice(0,14);
+ const mk=n=>`<a class="it" data-id="${esc(n.id)}" data-cat="${esc(n.cat)}" data-title="${esc(n.title)}" data-url="${esc(n.url)}"><span class="c">${esc(n.cat)}</span>${esc(n.title)}</a>`;
+ track.innerHTML=items.map(mk).join('')+items.map(mk).join('');
+ const selbar=document.getElementById('selbar');
+ track.querySelectorAll('.it').forEach(a=>{
+ a.addEventListener('click',e=>{e.preventDefault();
+ track.querySelectorAll('.it').forEach(x=>x.classList.remove('sel'));
+ track.querySelectorAll('.it[data-id="'+a.dataset.id+'"]').forEach(x=>x.classList.add('sel'));
+ selbar.innerHTML=`<span class="c">${esc(a.dataset.cat)}</span><a href="${esc(a.dataset.url)}">${esc(a.dataset.title)}</a><button class="x" aria-label="close">✕</button>`;
+ selbar.classList.add('on');
+ selbar.querySelector('.x').onclick=()=>{selbar.classList.remove('on');track.querySelectorAll('.it').forEach(x=>x.classList.remove('sel'));};
+ });
+ });
+ river.innerHTML=it.slice(5,13).map(n=>`<a href="${esc(n.url)}">${imgTag(n.image,'im',n.id)}<span class="tag" style="color:${sectionColor(n.cat)}">${esc(n.cat)}</span><h4>${esc(n.title)}</h4></a>`).join('');
+}});
+</script></body></html>
diff --git a/mockups/video/build-admin-video.js b/mockups/video/build-admin-video.js
new file mode 100644
index 00000000..1f0ef5f3
--- /dev/null
+++ b/mockups/video/build-admin-video.js
@@ -0,0 +1,88 @@
+#!/usr/bin/env node
+/* BACK-OFFICE ADMIN walkthrough — the CRCP-style broker & owner directory.
+ Captures the real clickable lists (LinkedIn / website / Maps / firm / CA-DRE),
+ a row expanded to its action buttons, search, and the firms + owners tabs.
+ VO synced to each screen. Never mentions how long the build took. */
+const path = require('path'), fs = require('fs');
+const { execFileSync } = require('child_process');
+const SK = path.join(process.env.HOME, '.claude/skills/app-demo-video');
+const { chromium } = require(path.join(SK, 'node_modules/playwright'));
+let generateVoice, ffprobeDuration;
+try { ({ generateVoice } = require(path.join(SK, 'scripts/tts.js'))); } catch {}
+try { ({ ffprobeDuration } = require(path.join(SK, 'scripts/merge.js'))); } catch {}
+const ADMIN = 'http://127.0.0.1:9719/admin/';
+const OUT = path.resolve(__dirname, 'out'), SHOTS = path.join(OUT, 'shots'), SLIDES = path.join(OUT, 'slides'), AUDIO = path.join(OUT, 'audio');
+[OUT, SHOTS, SLIDES, AUDIO].forEach(d => fs.mkdirSync(d, { recursive: true }));
+const FINAL = path.join(OUT, 'rentv-admin-walkthrough.mp4');
+const RED = '#c8102e', W = 1280, H = 800;
+const esc = s => String(s == null ? '' : s).replace(/[&<>]/g, c => ({ '&': '&', '<': '<', '>': '>' }[c]));
+async function vo(text, out) {
+ try { if (generateVoice) await generateVoice({ text, output: out }); } catch {}
+ if (!fs.existsSync(out) || fs.statSync(out).size < 2048) {
+ const aiff = out.replace(/\.mp3$/, '.aiff'); execFileSync('say', ['-v', 'Samantha', '-o', aiff, text]);
+ execFileSync('ffmpeg', ['-y', '-i', aiff, '-c:a', 'libmp3lame', '-b:a', '192k', out], { stdio: 'ignore' });
+ } return out;
+}
+const dur = m => ffprobeDuration(m);
+function sceneHtml({ b64, kicker, title, i, n }) {
+ const pips = Array.from({ length: n }, (_, k) => `<span class="pip${k <= i ? ' on' : ''}"></span>`).join('');
+ return `<!doctype html><html><head><meta charset=utf-8><style>*{margin:0;box-sizing:border-box}html,body{width:${W}px;height:${H}px;overflow:hidden;background:#0b0e12;font-family:-apple-system,'Inter',system-ui,sans-serif}
+ .stage{position:absolute;inset:0}.stage img{width:100%;height:100%;object-fit:cover;object-position:top center}
+ .bar{position:absolute;left:0;right:0;bottom:0;padding:26px 30px 20px;background:linear-gradient(0deg,rgba(6,9,12,.95),rgba(6,9,12,.7) 55%,transparent);color:#fff}
+ .kick{font-size:12px;font-weight:800;letter-spacing:.16em;text-transform:uppercase;color:${RED}}h2{font-size:26px;font-weight:800;margin-top:5px;max-width:1000px}
+ .prog{position:absolute;top:16px;left:30px;right:30px;display:flex;gap:5px}.pip{flex:1;height:3px;border-radius:2px;background:rgba(255,255,255,.22)}.pip.on{background:${RED}}
+ .brand{position:absolute;top:26px;right:30px;font-weight:800;font-size:13px;color:#fff;text-shadow:0 1px 3px #000}.brand span{color:${RED}}
+ .accent{position:absolute;bottom:0;left:0;height:4px;width:100%;background:${RED}}</style></head><body>
+ <div class="stage"><img src="data:image/png;base64,${b64}"></div><div class="prog">${pips}</div>
+ <div class="brand">REN<span>TV</span> · Admin</div><div class="bar"><div class="kick">${esc(kicker)}</div><h2>${esc(title)}</h2></div><div class="accent"></div></body></html>`;
+}
+function cardHtml(big, sub) {
+ return `<!doctype html><html><head><meta charset=utf-8><style>*{margin:0;box-sizing:border-box}body{width:${W}px;height:${H}px;background:radial-gradient(circle at 50% 35%,#141a22,#0b0e12);color:#fff;font-family:-apple-system,'Inter',system-ui,sans-serif;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:18px}.w{font-size:56px;font-weight:900;letter-spacing:-1.5px;text-align:center}.w span{color:${RED}}.acc{width:80px;height:5px;background:${RED};border-radius:3px}.s{font-size:22px;color:#aab2ba;max-width:860px;text-align:center;line-height:1.5}.foot{position:absolute;bottom:34px;font-size:12px;letter-spacing:.18em;text-transform:uppercase;color:#6b747d}</style></head><body><div class="w">${big}</div><div class="acc"></div><div class="s">${esc(sub)}</div><div class="foot">Back-office · Broker & Owner Intelligence</div></body></html>`;
+}
+function clip(png, mp3, out) {
+ const d = dur(mp3), frames = Math.max(1, Math.round((d + 1.4) * 30));
+ execFileSync('ffmpeg', ['-y', '-loop', '1', '-i', png, '-i', mp3, '-filter_complex',
+ `[0:v]scale=2560:1600,zoompan=z='min(zoom+0.0006,1.05)':d=${frames}:s=${W}x${H}:fps=30[v];[1:a]adelay=400|400,apad=pad_dur=1[a]`,
+ '-map', '[v]', '-map', '[a]', '-c:v', 'libx264', '-pix_fmt', 'yuv420p', '-preset', 'fast', '-crf', '20', '-c:a', 'aac', '-b:a', '192k', '-t', String(d + 1.4), out], { stdio: 'ignore' });
+ return out;
+}
+(async () => {
+ const browser = await chromium.launch();
+ const page = await browser.newPage({ viewport: { width: W, height: H } });
+ const clips = []; let idx = 0;
+ const scenes = [
+ { kicker: 'Back-office · the directory', title: 'Broker & Owner Intelligence', prep: async () => { await page.goto(ADMIN, { waitUntil: 'networkidle' }); await page.waitForTimeout(1400); },
+ narr: "This is the RENTV back office — a broker and owner intelligence desk over the California DRE registry: three hundred eighty-two thousand brokers and thirty-four thousand firms, synced from the real-estate back-end. Every row is live and searchable." },
+ { kicker: 'Every field is a link', title: 'Click a broker → find them anywhere', prep: async () => { await page.click('.row:first-child .r'); await page.waitForTimeout(700); },
+ narr: "Like the CRCP desk, every field is a link and every row opens inline. Click a broker and you get one-tap actions: find them on LinkedIn, open their firm's website, map their address, jump to the firm's own page, or pull their California DRE license — no leaving the list." },
+ { kicker: 'Instant filter', title: 'Search across name, firm, city, license', prep: async () => { await page.click('.row:first-child .r').catch(() => {}); await page.fill('#q', 'realty'); await page.waitForTimeout(700); },
+ narr: "Search filters instantly across name, firm, city and license number — type a firm, a city, or a license and the list narrows in real time, then sort by name, city, firm, or agent count." },
+ { kicker: 'Firms tab', title: 'Firms ranked by licensed agents', prep: async () => { await page.fill('#q', ''); await page.click('button[data-tab=firms]'); await page.waitForTimeout(700); },
+ narr: "Switch to Firms and every brokerage is ranked by licensed-agent count, each linking straight to the company on LinkedIn, its official website, its headquarters on the map, and its corporate DRE record." },
+ { kicker: 'Owners & Assets', title: 'Every marquee asset, mappable', prep: async () => { await page.click('button[data-tab=owners]'); await page.waitForTimeout(500); await page.click('.row:first-child .r'); await page.waitForTimeout(700); },
+ narr: "And Owners and Assets turns the marquee properties into leads — map the address, drop into Street View, open the LA County Assessor record, or search out the owner and the deal behind it." },
+ { kicker: 'One chrome, everywhere', title: 'Same hamburger — all nav + data', prep: async () => { await page.goto(ADMIN, { waitUntil: 'networkidle' }); await page.waitForTimeout(1000); await page.click('#rvBurger'); await page.waitForTimeout(500); },
+ narr: "The admin shares the exact same chrome as the front end — one hamburger holding every tab and the live market snapshot, and the user icon reserved only for sign-in." },
+ ];
+ const total = scenes.length + 2;
+ // intro
+ { const png = path.join(SLIDES, 'ad-intro.png'); await (async () => { await page.setContent(cardHtml('RENTV Admin', 'A back-office broker and owner intelligence desk — every record clickable out to LinkedIn, the firm, the map, and the DRE.'), { waitUntil: 'networkidle' }); await page.screenshot({ path: png }); })();
+ const a = await vo("Here's the RENTV back office — the broker and owner intelligence desk. Let's walk through the clickable lists.", path.join(AUDIO, 'ad-intro.mp3'));
+ clips.push(clip(png, a, path.join(SLIDES, 'ad-intro.mp4'))); idx++; }
+ for (const s of scenes) {
+ await s.prep();
+ const shot = path.join(SHOTS, `ad-${idx}.png`); await page.screenshot({ path: shot });
+ const b64 = fs.readFileSync(shot).toString('base64');
+ const slide = path.join(SLIDES, `ad-${idx}.png`); await page.setContent(sceneHtml({ b64, kicker: s.kicker, title: s.title, i: idx, n: total }), { waitUntil: 'networkidle' }); await page.screenshot({ path: slide });
+ const a = await vo(s.narr, path.join(AUDIO, `ad-${idx}.mp3`));
+ clips.push(clip(slide, a, path.join(SLIDES, `ad-${idx}.mp4`))); console.log(`scene ${idx} done`); idx++;
+ }
+ // outro
+ { const png = path.join(SLIDES, 'ad-outro.png'); await page.setContent(cardHtml('From list to <span>lead</span>', 'Search the registry, click any broker, firm or asset, and reach LinkedIn, the website, the map and the DRE in one tap.'), { waitUntil: 'networkidle' }); await page.screenshot({ path: png });
+ const a = await vo("From a list to a lead in one click — search the registry, open any broker, firm or asset, and reach LinkedIn, the website, the map and the license instantly.", path.join(AUDIO, 'ad-outro.mp3'));
+ clips.push(clip(png, a, path.join(SLIDES, 'ad-outro.mp4'))); }
+ await browser.close();
+ const list = path.join(OUT, 'concat-admin.txt'); fs.writeFileSync(list, clips.map(c => `file '${path.resolve(c)}'`).join('\n'));
+ execFileSync('ffmpeg', ['-y', '-f', 'concat', '-safe', '0', '-i', list, '-c:v', 'libx264', '-pix_fmt', 'yuv420p', '-preset', 'fast', '-crf', '20', '-c:a', 'aac', '-b:a', '192k', FINAL], { stdio: 'ignore' });
+ const d = dur(FINAL); console.log(`ADMIN video: ${FINAL}\n ${d.toFixed(1)}s (${(d / 60).toFixed(2)} min) · ${clips.length} scenes`);
+})().catch(e => { console.error('FATAL', e); process.exit(1); });
diff --git a/mockups/video/build-frontend-video.js b/mockups/video/build-frontend-video.js
new file mode 100644
index 00000000..36434ad6
--- /dev/null
+++ b/mockups/video/build-frontend-video.js
@@ -0,0 +1,52 @@
+#!/usr/bin/env node
+/* FRONT-END-ONLY walkthrough — reuses the 12 already-rendered app-scene clips
+ (s1..s12) so no VO is re-billed; only a front-focused intro + outro are new. */
+const path = require('path'), fs = require('fs');
+const { execFileSync } = require('child_process');
+const SK = path.join(process.env.HOME, '.claude/skills/app-demo-video');
+let generateVoice, ffprobeDuration;
+try { ({ generateVoice } = require(path.join(SK, 'scripts/tts.js'))); } catch {}
+try { ({ ffprobeDuration } = require(path.join(SK, 'scripts/merge.js'))); } catch {}
+const { chromium } = require(path.join(SK, 'node_modules/playwright'));
+const OUT = path.resolve(__dirname, 'out'), SLIDES = path.join(OUT, 'slides'), AUDIO = path.join(OUT, 'audio');
+const FINAL = path.join(OUT, 'rentv-frontend-walkthrough.mp4');
+const RED = '#c8102e', W = 1280, H = 800;
+const esc = s => String(s == null ? '' : s).replace(/[&<>]/g, c => ({ '&': '&', '<': '<', '>': '>' }[c]));
+async function vo(text, outMp3) {
+ try { if (generateVoice) await generateVoice({ text, output: outMp3 }); } catch {}
+ if (!fs.existsSync(outMp3) || fs.statSync(outMp3).size < 2048) {
+ const aiff = outMp3.replace(/\.mp3$/, '.aiff'); execFileSync('say', ['-v', 'Samantha', '-o', aiff, text]);
+ execFileSync('ffmpeg', ['-y', '-i', aiff, '-c:a', 'libmp3lame', '-b:a', '192k', outMp3], { stdio: 'ignore' });
+ } return outMp3;
+}
+const dur = mp3 => ffprobeDuration(mp3);
+function cardHtml(big, sub) {
+ return `<!doctype html><html><head><meta charset=utf-8><style>*{margin:0;box-sizing:border-box}body{width:${W}px;height:${H}px;background:radial-gradient(circle at 50% 35%,#141a22,#0b0e12);color:#fff;font-family:-apple-system,'Inter',system-ui,sans-serif;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:18px}.w{font-size:70px;font-weight:900;letter-spacing:-2px}.w span{color:${RED}}.acc{width:80px;height:5px;background:${RED};border-radius:3px}.s{font-size:22px;color:#aab2ba;max-width:840px;text-align:center;line-height:1.5}.foot{position:absolute;bottom:34px;font-size:12px;letter-spacing:.18em;text-transform:uppercase;color:#6b747d}</style></head><body><div class="w">${big}</div><div class="acc"></div><div class="s">${esc(sub)}</div><div class="foot">Front-End Walkthrough · RENTV.com</div></body></html>`;
+}
+function clip(png, mp3, out) {
+ const d = dur(mp3), frames = Math.max(1, Math.round((d + 1.4) * 30));
+ execFileSync('ffmpeg', ['-y', '-loop', '1', '-i', png, '-i', mp3, '-filter_complex',
+ `[0:v]scale=1280:800,fps=30[v];[1:a]adelay=400|400,apad=pad_dur=1[a]`, '-map', '[v]', '-map', '[a]',
+ '-c:v', 'libx264', '-pix_fmt', 'yuv420p', '-preset', 'fast', '-crf', '20', '-c:a', 'aac', '-b:a', '192k', '-t', String(d + 1.4), out], { stdio: 'ignore' });
+ return out;
+}
+(async () => {
+ const browser = await chromium.launch();
+ const page = await browser.newPage({ viewport: { width: W, height: H } });
+ const shot = async (html, png) => { await page.setContent(html, { waitUntil: 'networkidle' }); await page.screenshot({ path: png }); };
+ const clips = [];
+ // front intro
+ const ip = path.join(SLIDES, 'fe-intro.png'); await shot(cardHtml('REN<span>TV</span>', 'A walkthrough of every front-end component — ten distinct layouts, one shared chrome, all on live data.'), ip);
+ const ia = await vo("Here's a tour of the RENTV front end — ten distinct layout concepts, one shared navigation chrome, every element numbered, all rendering the live market.", path.join(AUDIO, 'fe-intro.mp3'));
+ clips.push(clip(ip, ia, path.join(SLIDES, 'fe-intro.mp4')));
+ // reuse the 12 app-scene clips already rendered
+ for (let i = 1; i <= 12; i++) { const c = path.join(SLIDES, `s${i}.mp4`); if (fs.existsSync(c)) clips.push(c); }
+ // front outro
+ const op = path.join(SLIDES, 'fe-outro.png'); await shot(cardHtml('Pick your <span>10</span>', 'Turn on numbers, click the pieces you want, and the final RENTV front page is assembled from your picks.'), op);
+ const oa = await vo("That's the front end. Turn on numbers, pick the pieces you like across the ten, and the final page is built from your choices.", path.join(AUDIO, 'fe-outro.mp3'));
+ clips.push(clip(op, oa, path.join(SLIDES, 'fe-outro.mp4')));
+ await browser.close();
+ const list = path.join(OUT, 'concat-fe.txt'); fs.writeFileSync(list, clips.map(c => `file '${path.resolve(c)}'`).join('\n'));
+ execFileSync('ffmpeg', ['-y', '-f', 'concat', '-safe', '0', '-i', list, '-c:v', 'libx264', '-pix_fmt', 'yuv420p', '-preset', 'fast', '-crf', '20', '-c:a', 'aac', '-b:a', '192k', FINAL], { stdio: 'ignore' });
+ const d = dur(FINAL); console.log(`FRONT-END video: ${FINAL}\n ${d.toFixed(1)}s (${(d / 60).toFixed(2)} min) · ${clips.length} scenes`);
+})().catch(e => { console.error('FATAL', e); process.exit(1); });
diff --git a/mockups/video/build-rentv-video.js b/mockups/video/build-rentv-video.js
new file mode 100644
index 00000000..1d6d91da
--- /dev/null
+++ b/mockups/video/build-rentv-video.js
@@ -0,0 +1,183 @@
+#!/usr/bin/env node
+/* RENTV build walkthrough — narrated, screen-synced MP4.
+ Captures the REAL redesigned front-end (10 numbered layouts, hamburger chrome,
+ pick-tray) + the REAL backend API responses, and narrates each component.
+ Each scene's on-screen time == its voiceover length → voice stays synced to screen.
+ VO: skill tts chain (clone-voice → edge-tts free-neural → espeak), macOS `say` safety net.
+ $0 (local) — no paid API. Never mentions how long the build took. */
+const path = require('path'), fs = require('fs');
+const { execFileSync } = require('child_process');
+const SK = path.join(process.env.HOME, '.claude/skills/app-demo-video');
+const { chromium } = require(path.join(SK, 'node_modules/playwright'));
+let generateVoice, ffprobeDuration;
+try { ({ generateVoice } = require(path.join(SK, 'scripts/tts.js'))); } catch {}
+try { ({ ffprobeDuration } = require(path.join(SK, 'scripts/merge.js'))); } catch {}
+
+const GALLERY = 'http://127.0.0.1:9719';
+const OUT = path.resolve(__dirname, 'out');
+const SHOTS = path.join(OUT, 'shots'), SLIDES = path.join(OUT, 'slides'), AUDIO = path.join(OUT, 'audio');
+[OUT, SHOTS, SLIDES, AUDIO].forEach(d => fs.mkdirSync(d, { recursive: true }));
+const FINAL = path.join(OUT, 'rentv-build-walkthrough.mp4');
+const RED = '#c8102e', W = 1280, H = 800;
+const data = f => JSON.parse(fs.readFileSync(path.join(__dirname, '..', 'data', f), 'utf8'));
+const esc = s => String(s == null ? '' : s).replace(/[&<>]/g, c => ({ '&': '&', '<': '<', '>': '>' }[c]));
+
+// ── voiceover: reuse the skill chain, fall back to macOS `say` if it yields nothing ──
+async function vo(text, outMp3) {
+ try { if (generateVoice) { await generateVoice({ text, output: outMp3 }); } } catch {}
+ if (!fs.existsSync(outMp3) || fs.statSync(outMp3).size < 2048) {
+ const aiff = outMp3.replace(/\.mp3$/, '.aiff');
+ execFileSync('say', ['-v', 'Samantha', '-o', aiff, text]);
+ execFileSync('ffmpeg', ['-y', '-i', aiff, '-c:a', 'libmp3lame', '-b:a', '192k', outMp3], { stdio: 'ignore' });
+ }
+ return outMp3;
+}
+const dur = mp3 => (ffprobeDuration ? ffprobeDuration(mp3)
+ : parseFloat(execFileSync('ffprobe', ['-v', 'error', '-show_entries', 'format=duration', '-of', 'default=nw=1:nk=1', mp3], { encoding: 'utf8' }).trim()));
+
+// ── scene slide: full-bleed screen + caption bar + progress ──
+function sceneHtml({ shotB64, kicker, title, i, n }) {
+ const pips = Array.from({ length: n }, (_, k) => `<span class="pip${k <= i ? ' on' : ''}"></span>`).join('');
+ return `<!doctype html><html><head><meta charset=utf-8><style>
+ *{margin:0;box-sizing:border-box}html,body{width:${W}px;height:${H}px;overflow:hidden;background:#0b0e12;font-family:-apple-system,'Inter',system-ui,sans-serif}
+ .stage{position:absolute;inset:0}.stage img{width:100%;height:100%;object-fit:cover;object-position:top center}
+ .bar{position:absolute;left:0;right:0;bottom:0;padding:26px 30px 20px;background:linear-gradient(0deg,rgba(6,9,12,.94),rgba(6,9,12,.7) 55%,transparent);color:#fff}
+ .kick{font-size:12px;font-weight:800;letter-spacing:.16em;text-transform:uppercase;color:${RED}}
+ .kick b{color:#fff}
+ h2{font-size:27px;font-weight:800;margin-top:5px;letter-spacing:-.4px;max-width:1000px}
+ .prog{position:absolute;top:16px;left:30px;right:30px;display:flex;gap:5px}
+ .pip{flex:1;height:3px;border-radius:2px;background:rgba(255,255,255,.22)}.pip.on{background:${RED}}
+ .brand{position:absolute;top:16px;right:30px;font-weight:800;font-size:13px;letter-spacing:.02em;color:#fff;text-shadow:0 1px 3px #000;top:26px}
+ .brand span{color:${RED}}
+ .accent{position:absolute;bottom:0;left:0;height:4px;width:100%;background:${RED}}
+ </style></head><body>
+ <div class="stage"><img src="data:image/png;base64,${shotB64}"></div>
+ <div class="prog">${pips}</div>
+ <div class="brand">REN<span>TV</span></div>
+ <div class="bar"><div class="kick"><b>${esc(kicker)}</b></div><h2>${esc(title)}</h2></div>
+ <div class="accent"></div>
+ </body></html>`;
+}
+function cardHtml({ big, sub }) {
+ return `<!doctype html><html><head><meta charset=utf-8><style>
+ *{margin:0;box-sizing:border-box}body{width:${W}px;height:${H}px;background:radial-gradient(circle at 50% 35%,#141a22,#0b0e12);color:#fff;
+ font-family:-apple-system,'Inter',system-ui,sans-serif;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:18px}
+ .w{font-size:72px;font-weight:900;letter-spacing:-2px}.w span{color:${RED}}
+ .acc{width:80px;height:5px;background:${RED};border-radius:3px}
+ .s{font-size:22px;color:#aab2ba;max-width:820px;text-align:center;line-height:1.5}
+ .foot{position:absolute;bottom:34px;font-size:12px;letter-spacing:.18em;text-transform:uppercase;color:#6b747d}
+ </style></head><body><div class="w">${big}</div><div class="acc"></div><div class="s">${esc(sub)}</div>
+ <div class="foot">Commercial Real Estate News · The Regional Authority</div></body></html>`;
+}
+
+// backend "API console" slide from real snapshot JSON
+function apiConsoleHtml({ method, route, note, json }) {
+ const pretty = esc(JSON.stringify(json, null, 2)).split('\n').slice(0, 34).join('\n');
+ return `<!doctype html><html><head><meta charset=utf-8><style>
+ *{margin:0;box-sizing:border-box}body{width:${W}px;height:${H}px;background:#0b0e12;color:#e7ecf1;font-family:'Inter',system-ui,sans-serif;padding:0}
+ .top{padding:22px 30px 14px}.top .k{font-size:12px;font-weight:800;letter-spacing:.16em;text-transform:uppercase;color:${RED}}
+ .top h2{font-size:26px;font-weight:800;margin-top:6px}
+ .req{margin:0 30px;background:#11161c;border:1px solid #232a32;border-radius:10px 10px 0 0;padding:11px 16px;font:700 15px ui-monospace,Menlo,monospace}
+ .req .m{color:#37d67a}.req .r{color:#fff}.req .a{color:#6b747d;float:right;font-weight:500;font-size:13px}
+ pre{margin:0 30px;background:#0e131a;border:1px solid #232a32;border-top:0;border-radius:0 0 10px 10px;padding:16px;font:13px/1.5 ui-monospace,Menlo,monospace;color:#b9c4cf;height:520px;overflow:hidden;white-space:pre-wrap}
+ .note{padding:12px 30px;color:#8b939b;font-size:14px}
+ .brand{position:absolute;top:22px;right:30px;font-weight:800;color:#fff}.brand span{color:${RED}}
+ .accent{position:absolute;bottom:0;left:0;height:4px;width:100%;background:${RED}}
+ </style></head><body>
+ <div class="brand">REN<span>TV</span></div>
+ <div class="top"><div class="k">Back-end · Express API · pm2 :9704</div><h2>${esc(route)}</h2></div>
+ <div class="req"><span class="m">${method}</span> <span class="r">${esc(route)}</span><span class="a">200 · live</span></div>
+ <pre>${pretty}</pre>
+ <div class="note">${esc(note)}</div><div class="accent"></div>
+ </body></html>`;
+}
+
+async function shot(page, html, png) { await page.setContent(html, { waitUntil: 'networkidle' }); await page.screenshot({ path: png }); }
+function clip(png, mp3, out) {
+ const d = dur(mp3), frames = Math.max(1, Math.round((d + 1.4) * 30));
+ execFileSync('ffmpeg', ['-y', '-loop', '1', '-i', png, '-i', mp3,
+ '-filter_complex', `[0:v]scale=2560:1600,zoompan=z='min(zoom+0.0006,1.05)':d=${frames}:s=${W}x${H}:fps=30[v];[1:a]adelay=400|400,apad=pad_dur=1[a]`,
+ '-map', '[v]', '-map', '[a]', '-c:v', 'libx264', '-pix_fmt', 'yuv420p', '-preset', 'fast', '-crf', '20',
+ '-c:a', 'aac', '-b:a', '192k', '-t', String(d + 1.4), out], { stdio: 'ignore' });
+ return out;
+}
+
+(async () => {
+ const browser = await chromium.launch();
+ const page = await browser.newPage({ viewport: { width: W, height: H } });
+ const clips = [];
+ let idx = 0;
+
+ // scene defs: front app captures + backend consoles + cards. TOTAL for progress:
+ const appScenes = [
+ ['L02', null, 'The front end · 10 concepts', 'Editorial Magazine', "We rebuilt the RENTV front page as ten genuinely distinct layouts — different structures, not recolors. Every one renders the real live wire, the real LA County assessments, and the real brokerage data."],
+ ['L02', 'ham', 'Global chrome · every screen', 'One hamburger, upper-left', "The rule holds across all ten. A single modern hamburger in the upper-left carries every navigation tab — Sales, Leases, Financing, Development, Markets, LA Commercial, The REview and more — plus a live snapshot of the market: the CRE index, the ten-year, LA office vacancy, and the top asset."],
+ ['L01', 'picks', 'Pick & choose · numbered', 'Number every element', "Every element is numbered, like L-oh-one dot oh-seven. Turn on numbers, click a badge, and it drops into a Picks tray. Mix the masthead from one layout, the ticker from another, the map from a third — then hand back the list, and the final page is assembled from your picks."],
+ ['L01', null, 'Layout 1 · Trading Desk', 'Trading Desk', "Layout one is a Bloomberg-style trading desk: a live metric rail, a news blotter tape, an LA watchlist and a brokerage league table — maximum density for the deal-watcher."],
+ ['L03', null, 'Layout 3 · Brutalist Grid', 'Brutalist Grid', "Layout three goes brutalist — hard rules, oversized type, and a rigid cell grid where the lead story and the nine-hundred-ninety-five-million-dollar Beverly Center block dominate."],
+ ['L04', null, 'Layout 4 · Card Masonry', 'Card Masonry', "Layout four is the most visual: an image-forward masonry with section filter chips, where stories, assets and firms all become browsable cards."],
+ ['L05', null, 'Layout 5 · Split-Screen', 'Split-Screen', "Layout five splits the screen — the live newsroom scrolls on the left while a dark LA-intelligence panel stays pinned on the right."],
+ ['L06', null, 'Layout 6 · Broadcast', 'Broadcast', "Layout six is broadcast news: a scrolling headline tape, an on-air video hero from The REview, and section columns underneath."],
+ ['L07', null, 'Layout 7 · Map-Anchored', 'Map-Anchored', "Layout seven anchors on an LA map. Each marquee asset is a pin; clicking one drives a live detail panel with the assessment, the square footage and the year built."],
+ ['L08', null, 'Layout 8 · Timeline', 'Timeline Feed', "Layout eight is a single vertical timeline, interleaving live headlines, marquee-asset callouts and recorded property transfers into one running spine of market events."],
+ ['L09', null, 'Layout 9 · Broadsheet', 'The RENTV Daily', "Layout nine is a full newspaper front page — flag, dateline, a two-column lead, a news river, a Property-of-the-Day box and brokerage standings."],
+ ['L10', null, 'Layout 10 · Swiss Index', 'Swiss Index', "And layout ten is pure restraint — a numbered index of every story, the LA market ranked by value, and tabular market data. The market, indexed."],
+ ];
+ const apiScenes = [
+ ['news', 'GET', '/api/news', "The live rentv-dot-com wire, refreshed on a schedule. Thirty stories, each tagged by sector, feeding every layout's headlines.", data('news.json')],
+ ['la', 'GET', '/api/la-commercial', "LA County Assessor parcels, AI-written news briefs, and California DRE brokers — synced in from the usrealestate back-end into the marquee, the recorded-activity table and the league tables.", data('la-commercial.json')],
+ ['ticker', 'GET', '/api/ticker', "The market ticker: the CRE index, the ten-year treasury, LA office vacancy and Inland-Empire industrial cap rates — the data points that also live inside the hamburger.", data('ticker.json')],
+ ['videos', 'GET', '/api/videos', "The REview video catalog, with RENTV Originals merged in on read — so the video sync can never wipe the house-produced promos.", data('videos.json')],
+ ];
+ const total = 1 /*intro*/ + appScenes.length + apiScenes.length + 1 /*arch*/ + 1 /*outro*/;
+
+ // ── intro ──
+ { const png = path.join(SLIDES, 's00.png'); await shot(page, cardHtml({ big: 'REN<span>TV</span>', sub: 'A ground-up redesign of the commercial-real-estate news platform — front end and back end.' }), png);
+ const a = await vo("This is the RENTV rebuild — a commercial real estate news platform, front end and back end. Let's walk through every component.", path.join(AUDIO, 's00.mp3'));
+ clips.push(clip(png, a, path.join(SLIDES, 's00.mp4'))); idx++; console.log('intro done'); }
+
+ // ── app scenes ──
+ for (const [L, mode, kicker, title, narr] of appScenes) {
+ await page.goto(`${GALLERY}/${L}.html`, { waitUntil: 'networkidle' });
+ await page.waitForTimeout(1200); // let live data render
+ if (mode === 'ham') { await page.click('#rvBurger').catch(() => {}); await page.waitForTimeout(500); }
+ if (mode === 'picks') { await page.click('.t-pick').catch(() => {}); await page.waitForTimeout(400); }
+ const appPng = path.join(SHOTS, `${L}-${mode || 'x'}.png`);
+ await page.screenshot({ path: appPng });
+ const b64 = fs.readFileSync(appPng).toString('base64');
+ const slidePng = path.join(SLIDES, `s${String(idx).padStart(2, '0')}.png`);
+ await shot(page, sceneHtml({ shotB64: b64, kicker, title, i: idx, n: total }), slidePng);
+ const a = await vo(narr, path.join(AUDIO, `s${idx}.mp3`));
+ clips.push(clip(slidePng, a, path.join(SLIDES, `s${idx}.mp4`))); console.log(`${L}/${mode || 'full'} done`); idx++;
+ }
+
+ // ── backend scenes ──
+ for (const [id, method, route, note, json] of apiScenes) {
+ const png = path.join(SLIDES, `api-${id}.png`);
+ await shot(page, apiConsoleHtml({ method, route, note, json }), png);
+ const a = await vo(note, path.join(AUDIO, `api-${id}.mp3`));
+ clips.push(clip(png, a, path.join(SLIDES, `api-${id}.mp4`))); console.log(`api ${route} done`); idx++;
+ }
+
+ // ── architecture / cutover card ──
+ { const png = path.join(SLIDES, 'arch.png');
+ await shot(page, cardHtml({ big: 'One canonical site', sub: 'The divergent forks were consolidated: the richer build now serves the canonical domain, with the consulting portal untouched — every future feature lands once.' }), png);
+ const a = await vo("Behind it all, the divergent forks were consolidated. The richer build now serves the canonical domain, the consulting portal stays untouched, and every future feature lands in one place instead of two.", path.join(AUDIO, 'arch.mp3'));
+ clips.push(clip(png, a, path.join(SLIDES, 'arch.mp4'))); idx++; console.log('arch done'); }
+
+ // ── outro ──
+ { const png = path.join(SLIDES, 'outro.png');
+ await shot(page, cardHtml({ big: 'Pick your <span>10</span>', sub: 'Ten front-end concepts, a live back end, and a numbered pick-and-choose workflow — ready to assemble into the final RENTV.' }), png);
+ const a = await vo("That's the full platform — ten front-end concepts over a live back end, every element numbered and pickable. Choose the pieces you want, and the final RENTV comes together from your picks.", path.join(AUDIO, 'outro.mp3'));
+ clips.push(clip(png, a, path.join(SLIDES, 'outro.mp4'))); console.log('outro done'); }
+
+ await browser.close();
+
+ // ── concat ──
+ const list = path.join(OUT, 'concat.txt');
+ fs.writeFileSync(list, clips.map(c => `file '${path.resolve(c)}'`).join('\n'));
+ execFileSync('ffmpeg', ['-y', '-f', 'concat', '-safe', '0', '-i', list,
+ '-c:v', 'libx264', '-pix_fmt', 'yuv420p', '-preset', 'fast', '-crf', '20', '-c:a', 'aac', '-b:a', '192k', FINAL], { stdio: 'ignore' });
+ const d = dur(FINAL), mb = (fs.statSync(FINAL).size / 1048576).toFixed(1);
+ console.log(`\n=== DONE ===\n ${FINAL}\n ${d.toFixed(1)}s (${(d / 60).toFixed(2)} min) · ${mb} MB · ${clips.length} scenes`);
+})().catch(e => { console.error('FATAL', e); process.exit(1); });
diff --git a/mockups/video/out/audio/ad-1.mp3 b/mockups/video/out/audio/ad-1.mp3
new file mode 100644
index 00000000..cb042400
Binary files /dev/null and b/mockups/video/out/audio/ad-1.mp3 differ
diff --git a/mockups/video/out/audio/ad-intro.mp3 b/mockups/video/out/audio/ad-intro.mp3
new file mode 100644
index 00000000..4404b1f4
Binary files /dev/null and b/mockups/video/out/audio/ad-intro.mp3 differ
diff --git a/mockups/video/out/audio/api-la.mp3 b/mockups/video/out/audio/api-la.mp3
new file mode 100644
index 00000000..8b1a77ec
Binary files /dev/null and b/mockups/video/out/audio/api-la.mp3 differ
diff --git a/mockups/video/out/audio/api-news.mp3 b/mockups/video/out/audio/api-news.mp3
new file mode 100644
index 00000000..f411dd63
Binary files /dev/null and b/mockups/video/out/audio/api-news.mp3 differ
diff --git a/mockups/video/out/audio/api-ticker.mp3 b/mockups/video/out/audio/api-ticker.mp3
new file mode 100644
index 00000000..643bcd0e
Binary files /dev/null and b/mockups/video/out/audio/api-ticker.mp3 differ
diff --git a/mockups/video/out/audio/api-videos.mp3 b/mockups/video/out/audio/api-videos.mp3
new file mode 100644
index 00000000..4d43ae44
Binary files /dev/null and b/mockups/video/out/audio/api-videos.mp3 differ
diff --git a/mockups/video/out/audio/arch.mp3 b/mockups/video/out/audio/arch.mp3
new file mode 100644
index 00000000..776d0121
Binary files /dev/null and b/mockups/video/out/audio/arch.mp3 differ
diff --git a/mockups/video/out/audio/fe-intro.mp3 b/mockups/video/out/audio/fe-intro.mp3
new file mode 100644
index 00000000..f87c83c1
Binary files /dev/null and b/mockups/video/out/audio/fe-intro.mp3 differ
diff --git a/mockups/video/out/audio/fe-outro.mp3 b/mockups/video/out/audio/fe-outro.mp3
new file mode 100644
index 00000000..c35cffdf
Binary files /dev/null and b/mockups/video/out/audio/fe-outro.mp3 differ
diff --git a/mockups/video/out/audio/outro.mp3 b/mockups/video/out/audio/outro.mp3
new file mode 100644
index 00000000..b7ce8722
Binary files /dev/null and b/mockups/video/out/audio/outro.mp3 differ
diff --git a/mockups/video/out/audio/s00.mp3 b/mockups/video/out/audio/s00.mp3
new file mode 100644
index 00000000..94e41cc4
Binary files /dev/null and b/mockups/video/out/audio/s00.mp3 differ
diff --git a/mockups/video/out/audio/s1.mp3 b/mockups/video/out/audio/s1.mp3
new file mode 100644
index 00000000..55695dd7
Binary files /dev/null and b/mockups/video/out/audio/s1.mp3 differ
diff --git a/mockups/video/out/audio/s10.mp3 b/mockups/video/out/audio/s10.mp3
new file mode 100644
index 00000000..cc39aa16
Binary files /dev/null and b/mockups/video/out/audio/s10.mp3 differ
diff --git a/mockups/video/out/audio/s11.mp3 b/mockups/video/out/audio/s11.mp3
new file mode 100644
index 00000000..08df0000
Binary files /dev/null and b/mockups/video/out/audio/s11.mp3 differ
diff --git a/mockups/video/out/audio/s12.mp3 b/mockups/video/out/audio/s12.mp3
new file mode 100644
index 00000000..01ed4f29
Binary files /dev/null and b/mockups/video/out/audio/s12.mp3 differ
diff --git a/mockups/video/out/audio/s2.mp3 b/mockups/video/out/audio/s2.mp3
new file mode 100644
index 00000000..a8a9098a
Binary files /dev/null and b/mockups/video/out/audio/s2.mp3 differ
diff --git a/mockups/video/out/audio/s3.mp3 b/mockups/video/out/audio/s3.mp3
new file mode 100644
index 00000000..966d650e
Binary files /dev/null and b/mockups/video/out/audio/s3.mp3 differ
diff --git a/mockups/video/out/audio/s4.mp3 b/mockups/video/out/audio/s4.mp3
new file mode 100644
index 00000000..01c0c44b
Binary files /dev/null and b/mockups/video/out/audio/s4.mp3 differ
diff --git a/mockups/video/out/audio/s5.mp3 b/mockups/video/out/audio/s5.mp3
new file mode 100644
index 00000000..fba992c8
Binary files /dev/null and b/mockups/video/out/audio/s5.mp3 differ
diff --git a/mockups/video/out/audio/s6.mp3 b/mockups/video/out/audio/s6.mp3
new file mode 100644
index 00000000..14b0e384
Binary files /dev/null and b/mockups/video/out/audio/s6.mp3 differ
diff --git a/mockups/video/out/audio/s7.mp3 b/mockups/video/out/audio/s7.mp3
new file mode 100644
index 00000000..a163250a
Binary files /dev/null and b/mockups/video/out/audio/s7.mp3 differ
diff --git a/mockups/video/out/audio/s8.mp3 b/mockups/video/out/audio/s8.mp3
new file mode 100644
index 00000000..6ddb17e8
Binary files /dev/null and b/mockups/video/out/audio/s8.mp3 differ
diff --git a/mockups/video/out/audio/s9.mp3 b/mockups/video/out/audio/s9.mp3
new file mode 100644
index 00000000..be05fba3
Binary files /dev/null and b/mockups/video/out/audio/s9.mp3 differ
diff --git a/mockups/video/out/concat-fe.txt b/mockups/video/out/concat-fe.txt
new file mode 100644
index 00000000..4c645357
--- /dev/null
+++ b/mockups/video/out/concat-fe.txt
@@ -0,0 +1,14 @@
+file '/Users/macstudio3/Projects/rentv-v1/mockups/video/out/slides/fe-intro.mp4'
+file '/Users/macstudio3/Projects/rentv-v1/mockups/video/out/slides/s1.mp4'
+file '/Users/macstudio3/Projects/rentv-v1/mockups/video/out/slides/s2.mp4'
+file '/Users/macstudio3/Projects/rentv-v1/mockups/video/out/slides/s3.mp4'
+file '/Users/macstudio3/Projects/rentv-v1/mockups/video/out/slides/s4.mp4'
+file '/Users/macstudio3/Projects/rentv-v1/mockups/video/out/slides/s5.mp4'
+file '/Users/macstudio3/Projects/rentv-v1/mockups/video/out/slides/s6.mp4'
+file '/Users/macstudio3/Projects/rentv-v1/mockups/video/out/slides/s7.mp4'
+file '/Users/macstudio3/Projects/rentv-v1/mockups/video/out/slides/s8.mp4'
+file '/Users/macstudio3/Projects/rentv-v1/mockups/video/out/slides/s9.mp4'
+file '/Users/macstudio3/Projects/rentv-v1/mockups/video/out/slides/s10.mp4'
+file '/Users/macstudio3/Projects/rentv-v1/mockups/video/out/slides/s11.mp4'
+file '/Users/macstudio3/Projects/rentv-v1/mockups/video/out/slides/s12.mp4'
+file '/Users/macstudio3/Projects/rentv-v1/mockups/video/out/slides/fe-outro.mp4'
\ No newline at end of file
diff --git a/mockups/video/out/concat.txt b/mockups/video/out/concat.txt
new file mode 100644
index 00000000..96ba7046
--- /dev/null
+++ b/mockups/video/out/concat.txt
@@ -0,0 +1,19 @@
+file '/Users/macstudio3/Projects/rentv-v1/mockups/video/out/slides/s00.mp4'
+file '/Users/macstudio3/Projects/rentv-v1/mockups/video/out/slides/s1.mp4'
+file '/Users/macstudio3/Projects/rentv-v1/mockups/video/out/slides/s2.mp4'
+file '/Users/macstudio3/Projects/rentv-v1/mockups/video/out/slides/s3.mp4'
+file '/Users/macstudio3/Projects/rentv-v1/mockups/video/out/slides/s4.mp4'
+file '/Users/macstudio3/Projects/rentv-v1/mockups/video/out/slides/s5.mp4'
+file '/Users/macstudio3/Projects/rentv-v1/mockups/video/out/slides/s6.mp4'
+file '/Users/macstudio3/Projects/rentv-v1/mockups/video/out/slides/s7.mp4'
+file '/Users/macstudio3/Projects/rentv-v1/mockups/video/out/slides/s8.mp4'
+file '/Users/macstudio3/Projects/rentv-v1/mockups/video/out/slides/s9.mp4'
+file '/Users/macstudio3/Projects/rentv-v1/mockups/video/out/slides/s10.mp4'
+file '/Users/macstudio3/Projects/rentv-v1/mockups/video/out/slides/s11.mp4'
+file '/Users/macstudio3/Projects/rentv-v1/mockups/video/out/slides/s12.mp4'
+file '/Users/macstudio3/Projects/rentv-v1/mockups/video/out/slides/api-news.mp4'
+file '/Users/macstudio3/Projects/rentv-v1/mockups/video/out/slides/api-la.mp4'
+file '/Users/macstudio3/Projects/rentv-v1/mockups/video/out/slides/api-ticker.mp4'
+file '/Users/macstudio3/Projects/rentv-v1/mockups/video/out/slides/api-videos.mp4'
+file '/Users/macstudio3/Projects/rentv-v1/mockups/video/out/slides/arch.mp4'
+file '/Users/macstudio3/Projects/rentv-v1/mockups/video/out/slides/outro.mp4'
\ No newline at end of file
diff --git a/mockups/video/out/rentv-build-walkthrough.mp4 b/mockups/video/out/rentv-build-walkthrough.mp4
new file mode 100644
index 00000000..40e6d6b7
Binary files /dev/null and b/mockups/video/out/rentv-build-walkthrough.mp4 differ
diff --git a/mockups/video/out/rentv-frontend-walkthrough.mp4 b/mockups/video/out/rentv-frontend-walkthrough.mp4
new file mode 100644
index 00000000..00692b9a
Binary files /dev/null and b/mockups/video/out/rentv-frontend-walkthrough.mp4 differ
diff --git a/mockups/video/out/shots/L01-picks.png b/mockups/video/out/shots/L01-picks.png
new file mode 100644
index 00000000..872cc779
Binary files /dev/null and b/mockups/video/out/shots/L01-picks.png differ
diff --git a/mockups/video/out/shots/L01-x.png b/mockups/video/out/shots/L01-x.png
new file mode 100644
index 00000000..f1dabd42
Binary files /dev/null and b/mockups/video/out/shots/L01-x.png differ
diff --git a/mockups/video/out/shots/L02-ham.png b/mockups/video/out/shots/L02-ham.png
new file mode 100644
index 00000000..0efbfc8e
Binary files /dev/null and b/mockups/video/out/shots/L02-ham.png differ
diff --git a/mockups/video/out/shots/L02-x.png b/mockups/video/out/shots/L02-x.png
new file mode 100644
index 00000000..6f32971b
Binary files /dev/null and b/mockups/video/out/shots/L02-x.png differ
diff --git a/mockups/video/out/shots/L03-x.png b/mockups/video/out/shots/L03-x.png
new file mode 100644
index 00000000..e2ad0bdd
Binary files /dev/null and b/mockups/video/out/shots/L03-x.png differ
diff --git a/mockups/video/out/shots/L04-x.png b/mockups/video/out/shots/L04-x.png
new file mode 100644
index 00000000..6d389b67
Binary files /dev/null and b/mockups/video/out/shots/L04-x.png differ
diff --git a/mockups/video/out/shots/L05-x.png b/mockups/video/out/shots/L05-x.png
new file mode 100644
index 00000000..c98e9a39
Binary files /dev/null and b/mockups/video/out/shots/L05-x.png differ
diff --git a/mockups/video/out/shots/L06-x.png b/mockups/video/out/shots/L06-x.png
new file mode 100644
index 00000000..cd556884
Binary files /dev/null and b/mockups/video/out/shots/L06-x.png differ
diff --git a/mockups/video/out/shots/L07-x.png b/mockups/video/out/shots/L07-x.png
new file mode 100644
index 00000000..0a14c305
Binary files /dev/null and b/mockups/video/out/shots/L07-x.png differ
diff --git a/mockups/video/out/shots/L08-x.png b/mockups/video/out/shots/L08-x.png
new file mode 100644
index 00000000..e498c891
Binary files /dev/null and b/mockups/video/out/shots/L08-x.png differ
diff --git a/mockups/video/out/shots/L09-x.png b/mockups/video/out/shots/L09-x.png
new file mode 100644
index 00000000..799008f6
Binary files /dev/null and b/mockups/video/out/shots/L09-x.png differ
diff --git a/mockups/video/out/shots/L10-x.png b/mockups/video/out/shots/L10-x.png
new file mode 100644
index 00000000..37d55feb
Binary files /dev/null and b/mockups/video/out/shots/L10-x.png differ
diff --git a/mockups/video/out/shots/ad-1.png b/mockups/video/out/shots/ad-1.png
new file mode 100644
index 00000000..b494e5a5
Binary files /dev/null and b/mockups/video/out/shots/ad-1.png differ
diff --git a/mockups/video/out/slides/ad-1.mp4 b/mockups/video/out/slides/ad-1.mp4
new file mode 100644
index 00000000..00965df1
Binary files /dev/null and b/mockups/video/out/slides/ad-1.mp4 differ
diff --git a/mockups/video/out/slides/ad-1.png b/mockups/video/out/slides/ad-1.png
new file mode 100644
index 00000000..8b926a47
Binary files /dev/null and b/mockups/video/out/slides/ad-1.png differ
diff --git a/mockups/video/out/slides/ad-intro.mp4 b/mockups/video/out/slides/ad-intro.mp4
new file mode 100644
index 00000000..544bada1
Binary files /dev/null and b/mockups/video/out/slides/ad-intro.mp4 differ
diff --git a/mockups/video/out/slides/ad-intro.png b/mockups/video/out/slides/ad-intro.png
new file mode 100644
index 00000000..fcccb03f
Binary files /dev/null and b/mockups/video/out/slides/ad-intro.png differ
diff --git a/mockups/video/out/slides/api-la.mp4 b/mockups/video/out/slides/api-la.mp4
new file mode 100644
index 00000000..e415cdfb
Binary files /dev/null and b/mockups/video/out/slides/api-la.mp4 differ
diff --git a/mockups/video/out/slides/api-la.png b/mockups/video/out/slides/api-la.png
new file mode 100644
index 00000000..4e7924a0
Binary files /dev/null and b/mockups/video/out/slides/api-la.png differ
diff --git a/mockups/video/out/slides/api-news.mp4 b/mockups/video/out/slides/api-news.mp4
new file mode 100644
index 00000000..34fecd2b
Binary files /dev/null and b/mockups/video/out/slides/api-news.mp4 differ
diff --git a/mockups/video/out/slides/api-news.png b/mockups/video/out/slides/api-news.png
new file mode 100644
index 00000000..40741e9c
Binary files /dev/null and b/mockups/video/out/slides/api-news.png differ
diff --git a/mockups/video/out/slides/api-ticker.mp4 b/mockups/video/out/slides/api-ticker.mp4
new file mode 100644
index 00000000..f17bf3b3
Binary files /dev/null and b/mockups/video/out/slides/api-ticker.mp4 differ
diff --git a/mockups/video/out/slides/api-ticker.png b/mockups/video/out/slides/api-ticker.png
new file mode 100644
index 00000000..55cc70da
Binary files /dev/null and b/mockups/video/out/slides/api-ticker.png differ
diff --git a/mockups/video/out/slides/api-videos.mp4 b/mockups/video/out/slides/api-videos.mp4
new file mode 100644
index 00000000..b3f7cc17
Binary files /dev/null and b/mockups/video/out/slides/api-videos.mp4 differ
diff --git a/mockups/video/out/slides/api-videos.png b/mockups/video/out/slides/api-videos.png
new file mode 100644
index 00000000..839f146c
Binary files /dev/null and b/mockups/video/out/slides/api-videos.png differ
diff --git a/mockups/video/out/slides/arch.mp4 b/mockups/video/out/slides/arch.mp4
new file mode 100644
index 00000000..5af49575
Binary files /dev/null and b/mockups/video/out/slides/arch.mp4 differ
diff --git a/mockups/video/out/slides/arch.png b/mockups/video/out/slides/arch.png
new file mode 100644
index 00000000..c7cf42e6
Binary files /dev/null and b/mockups/video/out/slides/arch.png differ
diff --git a/mockups/video/out/slides/fe-intro.mp4 b/mockups/video/out/slides/fe-intro.mp4
new file mode 100644
index 00000000..75f2291d
Binary files /dev/null and b/mockups/video/out/slides/fe-intro.mp4 differ
diff --git a/mockups/video/out/slides/fe-intro.png b/mockups/video/out/slides/fe-intro.png
new file mode 100644
index 00000000..fa92d339
Binary files /dev/null and b/mockups/video/out/slides/fe-intro.png differ
diff --git a/mockups/video/out/slides/fe-outro.mp4 b/mockups/video/out/slides/fe-outro.mp4
new file mode 100644
index 00000000..ab17384a
Binary files /dev/null and b/mockups/video/out/slides/fe-outro.mp4 differ
diff --git a/mockups/video/out/slides/fe-outro.png b/mockups/video/out/slides/fe-outro.png
new file mode 100644
index 00000000..b1c49274
Binary files /dev/null and b/mockups/video/out/slides/fe-outro.png differ
diff --git a/mockups/video/out/slides/outro.mp4 b/mockups/video/out/slides/outro.mp4
new file mode 100644
index 00000000..320adb04
Binary files /dev/null and b/mockups/video/out/slides/outro.mp4 differ
diff --git a/mockups/video/out/slides/outro.png b/mockups/video/out/slides/outro.png
new file mode 100644
index 00000000..8662f15e
Binary files /dev/null and b/mockups/video/out/slides/outro.png differ
diff --git a/mockups/video/out/slides/s00.mp4 b/mockups/video/out/slides/s00.mp4
new file mode 100644
index 00000000..b831d482
Binary files /dev/null and b/mockups/video/out/slides/s00.mp4 differ
diff --git a/mockups/video/out/slides/s00.png b/mockups/video/out/slides/s00.png
new file mode 100644
index 00000000..27f492a1
Binary files /dev/null and b/mockups/video/out/slides/s00.png differ
diff --git a/mockups/video/out/slides/s01.png b/mockups/video/out/slides/s01.png
new file mode 100644
index 00000000..350cc6af
Binary files /dev/null and b/mockups/video/out/slides/s01.png differ
diff --git a/mockups/video/out/slides/s02.png b/mockups/video/out/slides/s02.png
new file mode 100644
index 00000000..49b9bf78
Binary files /dev/null and b/mockups/video/out/slides/s02.png differ
diff --git a/mockups/video/out/slides/s03.png b/mockups/video/out/slides/s03.png
new file mode 100644
index 00000000..06771aec
Binary files /dev/null and b/mockups/video/out/slides/s03.png differ
diff --git a/mockups/video/out/slides/s04.png b/mockups/video/out/slides/s04.png
new file mode 100644
index 00000000..ebef4dba
Binary files /dev/null and b/mockups/video/out/slides/s04.png differ
diff --git a/mockups/video/out/slides/s05.png b/mockups/video/out/slides/s05.png
new file mode 100644
index 00000000..838862e9
Binary files /dev/null and b/mockups/video/out/slides/s05.png differ
diff --git a/mockups/video/out/slides/s06.png b/mockups/video/out/slides/s06.png
new file mode 100644
index 00000000..33765f4a
Binary files /dev/null and b/mockups/video/out/slides/s06.png differ
diff --git a/mockups/video/out/slides/s07.png b/mockups/video/out/slides/s07.png
new file mode 100644
index 00000000..f2779ad2
Binary files /dev/null and b/mockups/video/out/slides/s07.png differ
diff --git a/mockups/video/out/slides/s08.png b/mockups/video/out/slides/s08.png
new file mode 100644
index 00000000..fa0098ef
Binary files /dev/null and b/mockups/video/out/slides/s08.png differ
diff --git a/mockups/video/out/slides/s09.png b/mockups/video/out/slides/s09.png
new file mode 100644
index 00000000..ef70b693
Binary files /dev/null and b/mockups/video/out/slides/s09.png differ
diff --git a/mockups/video/out/slides/s1.mp4 b/mockups/video/out/slides/s1.mp4
new file mode 100644
index 00000000..c41c20c1
Binary files /dev/null and b/mockups/video/out/slides/s1.mp4 differ
diff --git a/mockups/video/out/slides/s10.mp4 b/mockups/video/out/slides/s10.mp4
new file mode 100644
index 00000000..64ac49a0
Binary files /dev/null and b/mockups/video/out/slides/s10.mp4 differ
diff --git a/mockups/video/out/slides/s10.png b/mockups/video/out/slides/s10.png
new file mode 100644
index 00000000..88b8c2b9
Binary files /dev/null and b/mockups/video/out/slides/s10.png differ
diff --git a/mockups/video/out/slides/s11.mp4 b/mockups/video/out/slides/s11.mp4
new file mode 100644
index 00000000..e84fe422
Binary files /dev/null and b/mockups/video/out/slides/s11.mp4 differ
diff --git a/mockups/video/out/slides/s11.png b/mockups/video/out/slides/s11.png
new file mode 100644
index 00000000..b4980a99
Binary files /dev/null and b/mockups/video/out/slides/s11.png differ
diff --git a/mockups/video/out/slides/s12.mp4 b/mockups/video/out/slides/s12.mp4
new file mode 100644
index 00000000..fb4c87e6
Binary files /dev/null and b/mockups/video/out/slides/s12.mp4 differ
diff --git a/mockups/video/out/slides/s12.png b/mockups/video/out/slides/s12.png
new file mode 100644
index 00000000..d49c32c7
Binary files /dev/null and b/mockups/video/out/slides/s12.png differ
diff --git a/mockups/video/out/slides/s2.mp4 b/mockups/video/out/slides/s2.mp4
new file mode 100644
index 00000000..6e16839f
Binary files /dev/null and b/mockups/video/out/slides/s2.mp4 differ
diff --git a/mockups/video/out/slides/s3.mp4 b/mockups/video/out/slides/s3.mp4
new file mode 100644
index 00000000..6971af79
Binary files /dev/null and b/mockups/video/out/slides/s3.mp4 differ
diff --git a/mockups/video/out/slides/s4.mp4 b/mockups/video/out/slides/s4.mp4
new file mode 100644
index 00000000..58c793fc
Binary files /dev/null and b/mockups/video/out/slides/s4.mp4 differ
diff --git a/mockups/video/out/slides/s5.mp4 b/mockups/video/out/slides/s5.mp4
new file mode 100644
index 00000000..699e10ca
Binary files /dev/null and b/mockups/video/out/slides/s5.mp4 differ
diff --git a/mockups/video/out/slides/s6.mp4 b/mockups/video/out/slides/s6.mp4
new file mode 100644
index 00000000..d9a789bd
Binary files /dev/null and b/mockups/video/out/slides/s6.mp4 differ
diff --git a/mockups/video/out/slides/s7.mp4 b/mockups/video/out/slides/s7.mp4
new file mode 100644
index 00000000..5d14cc75
Binary files /dev/null and b/mockups/video/out/slides/s7.mp4 differ
diff --git a/mockups/video/out/slides/s8.mp4 b/mockups/video/out/slides/s8.mp4
new file mode 100644
index 00000000..4baf8334
Binary files /dev/null and b/mockups/video/out/slides/s8.mp4 differ
diff --git a/mockups/video/out/slides/s9.mp4 b/mockups/video/out/slides/s9.mp4
new file mode 100644
index 00000000..434ecdaa
Binary files /dev/null and b/mockups/video/out/slides/s9.mp4 differ
← 5a1f12a0 auto-save: 2026-07-22T13:44:34 (3 files) — data/markets.json
·
back to Rentv
·
Add 10 unique back-office admin layouts (A01-A10) + refined 87435437 →