← back to Rentv 2026

public/2026/index.html

306 lines

<!doctype html><html lang="en"><head>
<meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
<title>RENTV 2026 — Choose the Site · Template Selector</title>
<meta name="description" content="RENTV.com 2026 redesign — preview five UI/UX directions and pick the final site.">
<link rel="preconnect" href="https://fonts.googleapis.com"><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Playfair+Display:wght@700;800&family=Inter:wght@400;500;600;700;800&display=swap" rel="stylesheet">
<style>
  :root{--red:#c8102e;--ink:#14171a;--sub:#5b636b;--line:#e4e7ea;--wash:#f5f6f8;--gold:#c6a24a}
  *{box-sizing:border-box;margin:0}
  body{font-family:Inter,system-ui,sans-serif;color:var(--ink);background:#0b0e12;line-height:1.45}
  a{color:inherit;text-decoration:none}
  .top{position:sticky;top:0;z-index:40;display:flex;align-items:center;justify-content:space-between;gap:16px;
    padding:14px 22px;background:#0b0e12;border-bottom:1px solid #1c232b;color:#e7ecf1}
  .brand{font-family:'Playfair Display',serif;font-weight:800;font-size:22px;letter-spacing:.02em}.brand span{color:var(--red)}
  .top .k{font-size:11px;font-weight:800;letter-spacing:.18em;text-transform:uppercase;color:#7b848d}
  .chosen-tag{font-size:12px;font-weight:700;color:#8b949e}
  .chosen-tag b{color:var(--gold)}
  .hero{max-width:1240px;margin:0 auto;padding:34px 22px 8px;color:#e7ecf1}
  .hero .eye{color:var(--red);font-weight:800;font-size:12px;letter-spacing:.18em;text-transform:uppercase}
  .hero h1{font-family:'Playfair Display',serif;font-weight:800;font-size:clamp(30px,4vw,50px);line-height:1.05;margin:10px 0 10px;letter-spacing:-.01em}
  .hero p{color:#aeb6bd;max-width:70ch;font-size:16px}
  .hero .meta{margin-top:14px;color:#7b848d;font-size:13px}
  .grid{max-width:1240px;margin:0 auto;padding:22px;display:grid;grid-template-columns:repeat(2,1fr);gap:22px}
  @media(max-width:820px){.grid{grid-template-columns:1fr}}
  .card{background:#11161c;border:1px solid #1c232b;border-radius:14px;overflow:hidden;display:flex;flex-direction:column;
    transition:transform .18s,box-shadow .18s,border-color .18s}
  .card:hover{transform:translateY(-3px);box-shadow:0 20px 50px rgba(0,0,0,.5);border-color:#2b3644}
  .card.is-chosen{border-color:var(--gold);box-shadow:0 0 0 2px rgba(198,162,74,.35)}
  .framewrap{position:relative;height:300px;background:#05080c;overflow:hidden;border-bottom:1px solid #1c232b}
  .framewrap iframe{position:absolute;top:0;left:0;width:1400px;height:1050px;border:0;
    transform:scale(.5);transform-origin:top left;pointer-events:none;background:#fff}
  .framewrap .veil{position:absolute;inset:0;cursor:pointer;background:linear-gradient(180deg,rgba(5,8,12,0) 60%,rgba(5,8,12,.55))}
  .framewrap .veil:hover{background:linear-gradient(180deg,rgba(200,16,46,.06),rgba(5,8,12,.5))}
  .framewrap .open{position:absolute;left:14px;bottom:12px;background:rgba(11,14,18,.82);color:#fff;border:1px solid #2b3644;
    border-radius:7px;padding:8px 13px;font-weight:800;font-size:12px;letter-spacing:.03em;backdrop-filter:blur(4px)}
  .framewrap .letter{position:absolute;right:12px;top:12px;width:34px;height:34px;border-radius:8px;background:var(--red);color:#fff;
    display:flex;align-items:center;justify-content:center;font-family:'Playfair Display',serif;font-weight:800;font-size:19px}
  .cbody{padding:16px 18px 18px;color:#e7ecf1;display:flex;flex-direction:column;gap:8px;flex:1}
  .cbody h3{font-family:'Playfair Display',serif;font-size:22px;font-weight:800}
  .cbody .desc{color:#9aa4ad;font-size:14px;flex:1}
  .cbody .tags{display:flex;flex-wrap:wrap;gap:6px}
  .cbody .tags span{font-size:10.5px;font-weight:700;letter-spacing:.04em;text-transform:uppercase;color:#8b949e;background:#0b0e12;border:1px solid #1c232b;border-radius:20px;padding:3px 9px}
  .cbody .actions{display:flex;gap:8px;margin-top:6px}
  .btn{cursor:pointer;border:0;font:inherit;font-weight:800;font-size:13px;border-radius:8px;padding:10px 15px;letter-spacing:.02em}
  .btn.primary{background:var(--red);color:#fff}.btn.primary:hover{filter:brightness(1.08)}
  .btn.ghost{background:transparent;color:#e7ecf1;border:1px solid #2b3644}.btn.ghost:hover{border-color:#3d4a5a}
  .btn.gold{background:var(--gold);color:#1b1a12}.btn.gold:hover{filter:brightness(1.06)}
  .btn.chosen-badge{background:rgba(198,162,74,.15);color:var(--gold);border:1px solid rgba(198,162,74,.4);cursor:default}
  footer{max-width:1240px;margin:0 auto;padding:10px 22px 50px;color:#6b747d;font-size:12.5px}
  footer a{color:#8b949e;text-decoration:underline}
  /* ---------- Full-screen preview MODAL ---------- */
  .ovl{position:fixed;inset:0;z-index:100;background:rgba(4,6,9,.82);backdrop-filter:blur(3px);opacity:0;pointer-events:none;transition:opacity .2s;display:flex;flex-direction:column}
  .ovl.open{opacity:1;pointer-events:auto}
  .mbar{display:flex;align-items:center;gap:12px;flex-wrap:wrap;padding:12px 16px;background:#0b0e12;border-bottom:1px solid #1c232b;color:#e7ecf1}
  .mbar .switch{display:flex;gap:6px;background:#11161c;border:1px solid #1c232b;border-radius:9px;padding:4px}
  .mbar .switch button{cursor:pointer;border:0;background:none;color:#9aa4ad;font:inherit;font-weight:800;font-size:13px;padding:7px 12px;border-radius:6px;display:flex;align-items:center;gap:7px}
  .mbar .switch button .l{width:20px;height:20px;border-radius:5px;background:var(--red);color:#fff;display:flex;align-items:center;justify-content:center;font-family:'Playfair Display',serif;font-size:12px;font-weight:800}
  .mbar .switch button.on{background:var(--red);color:#fff}
  .mbar .switch button.on .l{background:#fff;color:var(--red)}
  .mbar .title{font-family:'Playfair Display',serif;font-weight:800;font-size:18px;margin-right:auto}
  .mbar .title small{font-family:Inter;font-weight:600;font-size:12px;color:#8b949e;margin-left:8px}
  .mbar .dev{display:flex;gap:4px;background:#11161c;border:1px solid #1c232b;border-radius:9px;padding:4px}
  .mbar .dev button{cursor:pointer;border:0;background:none;color:#9aa4ad;font:inherit;font-weight:700;font-size:12px;padding:6px 11px;border-radius:6px}
  .mbar .dev button.on{background:#e7ecf1;color:#0b0e12}
  .mbar .x{cursor:pointer;border:1px solid #2b3644;background:transparent;color:#e7ecf1;font-size:16px;line-height:1;border-radius:8px;width:38px;height:38px}
  .stage{flex:1;overflow:auto;display:flex;justify-content:center;align-items:flex-start;padding:18px;background:#05080c}
  .stage .device{width:100%;max-width:1400px;height:100%;background:#fff;border-radius:8px;overflow:hidden;box-shadow:0 24px 70px rgba(0,0,0,.6);transition:max-width .25s}
  .stage .device.tablet{max-width:834px}.stage .device.phone{max-width:412px}
  .stage .device iframe{width:100%;height:100%;border:0;display:block}
  .toast{position:fixed;left:50%;bottom:26px;transform:translateX(-50%) translateY(20px);z-index:200;background:#0b0e12;color:#fff;border:1px solid var(--gold);
    border-radius:10px;padding:13px 20px;font-weight:700;opacity:0;pointer-events:none;transition:.25s;box-shadow:0 18px 50px rgba(0,0,0,.5)}
  .toast.show{opacity:1;transform:translateX(-50%) translateY(0)}
  .toast b{color:var(--gold)}
</style></head>
<body>
<header class="top">
  <a class="brand" href="/">REN<span>TV</span> <span style="color:#7b848d;font-size:12px;font-family:Inter;font-weight:800;letter-spacing:.14em">/ 2026</span></a>
  <span class="k">Choose the Site</span>
  <span class="chosen-tag" id="chosenTag"></span>
</header>

<section class="hero">
  <div class="eye">2026 Redesign · Ranked · Pick the direction</div>
  <h1>Six ways the new RENTV could look — ranked.</h1>
  <p>A complete 2026 overhaul, video-first to coordinate with <b style="color:#e7ecf1">The REview</b> (rentvreview.com). Every build is a fully working homepage on live data, with the ad-slots system built in — each ranked, with <b style="color:#e7ecf1">why it wins</b> and the competitor it out-designs. Preview any one full-screen, then lock your pick with <b style="color:var(--gold)">“Make this the site.”</b> The field it beats is below ↓</p>
  <div class="meta">Preview is local only — choosing does not deploy. Going live is a separate step. · <a href="/advertise" style="color:var(--red);font-weight:700">See the ad-slots system →</a></div>
</section>

<main class="grid" id="grid"></main>

<section class="rivals-sec">
  <div class="rh"><div class="eye">The field · CRE news-wire &amp; conference competitors</div>
    <h2>Six sites RENTV is up against.</h2>
    <p>The commercial-real-estate news + conference landscape. Every concept above is built to out-design one of these — RENTV’s edge is <b style="color:#e7ecf1">video</b>, which none of them lead with.</p>
  </div>
  <div class="rivals" id="rivals"></div>
</section>

<style>
  /* rank badge on each card */
  .rank{position:absolute;left:12px;top:12px;z-index:2;background:#11161c;border:1px solid #2b3644;color:#c3cbd3;
    font:800 12px ui-monospace,monospace;padding:3px 9px;border-radius:20px}
  .rank.r1{background:var(--gold);border-color:var(--gold);color:#1b1a12}
  .rank.r2{background:#c0c6cc;border-color:#c0c6cc;color:#14171a}
  .rank.r3{background:#b0763a;border-color:#b0763a;color:#fff}
  .cbody h3 .best{margin-left:8px;font-family:Inter;font-size:11px;font-weight:800;letter-spacing:.05em;text-transform:uppercase;
    color:var(--gold);border:1px solid rgba(198,162,74,.5);border-radius:20px;padding:2px 9px;vertical-align:middle}
  .cbody .why{color:#c3cbd3;font-size:13px;line-height:1.5;background:#0b0e12;border:1px solid #1c232b;border-left:3px solid var(--gold);
    border-radius:8px;padding:11px 13px;margin-top:2px}
  .cbody .why b{color:#fff}
  .cbody .ref{display:block;color:#9aa4ad;font-size:12.5px;text-decoration:none;padding:8px 0 2px}
  .cbody .ref b{color:#e7ecf1}.cbody .ref .vs{color:var(--red);font-weight:800;margin-right:4px}
  .cbody .ref:hover b{color:var(--red)}
  /* competitor landscape */
  .rivals-sec{max-width:1240px;margin:8px auto 0;padding:26px 22px 6px;color:#e7ecf1}
  .rivals-sec .rh .eye{color:var(--red);font-weight:800;font-size:12px;letter-spacing:.16em;text-transform:uppercase}
  .rivals-sec .rh h2{font-family:'Playfair Display',serif;font-weight:800;font-size:clamp(22px,3vw,32px);margin:8px 0 6px}
  .rivals-sec .rh p{color:#aeb6bd;max-width:75ch;font-size:15px}
  .rivals{display:grid;grid-template-columns:repeat(3,1fr);gap:14px;margin-top:18px}
  @media(max-width:820px){.rivals{grid-template-columns:1fr}}
  .rival{display:block;background:#11161c;border:1px solid #1c232b;border-radius:12px;padding:15px 16px;text-decoration:none;
    transition:transform .16s,border-color .16s}
  .rival:hover{transform:translateY(-3px);border-color:#2b3644}
  .rival .rt{font-size:10px;font-weight:800;letter-spacing:.08em;text-transform:uppercase;color:var(--red)}
  .rival b{display:block;color:#fff;font-family:'Playfair Display',serif;font-size:19px;margin:3px 0 4px}
  .rival .rn{display:block;color:#9aa4ad;font-size:13px}
  .rival .go{display:inline-block;margin-top:9px;color:#8b949e;font-size:11px;font-weight:800}
  .rival:hover .go{color:var(--red)}
  /* full-screen modal info strip (rank + why-it-wins + competitor) */
  .mbar .title .mrank{display:inline-block;font:800 12px ui-monospace,monospace;padding:2px 8px;border-radius:20px;margin-right:6px;
    background:#11161c;border:1px solid #2b3644;color:#c3cbd3;vertical-align:middle}
  .mbar .title .mrank.r1{background:var(--gold);border-color:var(--gold);color:#1b1a12}
  .mbar .title .mrank.r2{background:#c0c6cc;border-color:#c0c6cc;color:#14171a}
  .mbar .title .mrank.r3{background:#b0763a;border-color:#b0763a;color:#fff}
  .mbar .title .mbest{font-family:Inter;font-size:10px;font-weight:800;letter-spacing:.05em;text-transform:uppercase;color:var(--gold);
    border:1px solid rgba(198,162,74,.5);border-radius:20px;padding:1px 8px;margin-left:6px;vertical-align:middle}
  .minfo{background:#0b0e12;border-bottom:1px solid #1c232b;padding:11px 16px;display:flex;gap:18px;align-items:baseline;flex-wrap:wrap}
  .minfo .mi-why{color:#c3cbd3;font-size:13px;line-height:1.5;flex:1;min-width:280px}
  .minfo .mi-why b{color:#fff}
  .minfo .mi-ref{color:#9aa4ad;font-size:12.5px;text-decoration:none;white-space:nowrap}
  .minfo .mi-ref b{color:#e7ecf1}.minfo .mi-ref .vs{color:var(--red);font-weight:800;margin-right:3px}
  .minfo .mi-ref:hover b{color:var(--red)}
  @media(max-width:700px){.minfo .mi-ref{white-space:normal}}
</style>

<footer>
  RENTV.com 2026 template selector · templates <b>A–E</b> live under <code style="color:#8b949e">/2026/{a…e}.html</code> · ad-slots system at <a href="/advertise">/advertise</a>.
  “Make this the site” records your pick to <code style="color:#8b949e">data/site-template.json</code> (admin-gated); it never publishes on its own.
</footer>

<!-- Full-screen preview modal -->
<div class="ovl" id="ovl" role="dialog" aria-modal="true" aria-label="Template preview">
  <div class="mbar">
    <div class="switch" id="switch"></div>
    <div class="title" id="mtitle"></div>
    <div class="dev" id="dev">
      <button data-w="desktop" class="on">🖥 Desktop</button>
      <button data-w="tablet">▭ Tablet</button>
      <button data-w="phone">▯ Phone</button>
    </div>
    <button class="btn gold" id="makeBtn">★ Make this the site</button>
    <button class="btn ghost" id="openTab">Open ↗</button>
    <button class="x" id="mclose" aria-label="Close">✕</button>
  </div>
  <div class="minfo" id="minfo"></div>
  <div class="stage"><div class="device" id="device"><iframe id="mframe" title="Template preview" loading="lazy"></iframe></div></div>
</div>
<div class="toast" id="toast"></div>

<script>
const TPL=[
  {k:'c',badge:'C',rank:1,name:'Cinematic',url:'/2026/c.html',desc:'Netflix-for-CRE. A full-bleed featured video hero over dark, cinematic category rails you scroll sideways. The most immersive.',tags:['Dark','Cinematic','Rails'],
    why:'THE pick if RENTV is going video-first. It reads like a premium streaming service, not a news site — which is exactly the differentiation none of the CRE news competitors have. It puts CRE Talk + The REview front-and-center and makes every video feel like a show. Highest ad value: full-bleed hero + sponsored rails.',
    ref:{name:'Bisnow video + America’s CRE Show',url:'https://www.bisnow.com',note:'beats their talking-head video — cinematic, branded, bingeable'}},
  {k:'a',badge:'A',rank:2,name:'The Video Wall',url:'/2026/a.html',desc:'A premium streaming-style wall of videos — the whole catalog as a browsable grid. Closest to The REview, video is the hero.',tags:['Video-first','Grid','Streaming'],
    why:'The most direct match to the new RENTV / The REview. One glance = the whole video library, sortable and dense. Easiest for a viewer to find something to watch, and the grid natively doubles as sponsorable ad inventory. Lowest-risk way to go video-first.',
    ref:{name:'The REview / YouTube grid',url:'https://www.rentvreview.com',note:'same idea, made premium + monetized'}},
  {k:'b',badge:'B',rank:3,name:'Editorial Lead',url:'/2026/b.html',desc:'A newspaper-of-record front page: big lead story, a video rail alongside the news, breaking ticker. Serious CRE journalism, elevated.',tags:['News-led','Video rail','Ticker'],
    why:'The safest evolution — keeps RENTV’s 25-year news authority while sliding video in alongside. If the audience still comes for the deals + headlines first, this wins on trust. Goes toe-to-toe with the CRE news leaders on their own turf, then out-videos them.',
    ref:{name:'The Real Deal / GlobeSt',url:'https://therealdeal.com',note:'their authority, plus a video rail they don’t have'}},
  {k:'e',badge:'E',rank:4,name:'Dashboard',url:'/2026/e.html',desc:'A Bloomberg-style CRE terminal: market pulse KPIs, a live-video panel, the deal wire and a video library — dense, live, data-forward.',tags:['Terminal','Data','Live'],
    why:'The power-user play. Positions RENTV as a live market terminal — rates, spreads, deal wire, video — in one screen. Stickiest for daily professional visitors and the strongest “data” story, but the most niche (casual readers may find it dense).',
    ref:{name:'CoStar terminal',url:'https://www.costar.com',note:'the terminal feel — but public, free, and video-first'}},
  {k:'d',badge:'D',rank:5,name:'Magazine',url:'/2026/d.html',desc:'A glossy monthly translated to web — an art-directed bento grid of feature tiles, a Video of the Week, departments and pull-quotes.',tags:['Editorial','Bento','Whitespace'],
    why:'The most beautiful and brand-forward — reads like a premium print title. Best for a prestige/brand impression and big feature storytelling, but the heaviest to keep filled with fresh content week to week.',
    ref:{name:'Commercial Observer',url:'https://commercialobserver.com',note:'glossy editorial — with RENTV’s video baked in'}},
  {k:'classic',badge:'◧',rank:6,name:'Classic',url:'/',desc:'The current live RENTV site — the original news-first front page. Keep it exactly as-is, or use it as the baseline to compare the concepts against.',tags:['Current','News-first','Original'],
    why:'The zero-risk baseline: change nothing. Ranked last only because it doesn’t advance the video-first goal — but it’s a legitimate choice if you want to hold steady while the ad-slots system rolls out underneath.',
    ref:{name:'Current RENTV.com',url:'/',note:'the incumbent — the bar every concept must beat'}}
];
// competitor landscape — the CRE news-wire / conference field RENTV is up against
const RIVALS=[
  {name:'The Real Deal',url:'https://therealdeal.com',tag:'News wire',note:'CRE news leader — editorial authority, huge reach'},
  {name:'Bisnow',url:'https://www.bisnow.com',tag:'News + Conferences',note:'National CRE news + the biggest events machine'},
  {name:'Commercial Observer',url:'https://commercialobserver.com',tag:'Magazine',note:'Glossy CRE news + Power lists + galas'},
  {name:'GlobeSt',url:'https://www.globest.com',tag:'News wire',note:'ALM CRE news wire + national conferences'},
  {name:'CoStar',url:'https://www.costar.com',tag:'Data terminal',note:'The CRE data terminal + CoStar News'},
  {name:'Connect CRE',url:'https://www.connectcre.com',tag:'News + Conferences',note:'Regional CRE news + a full conference calendar'}
];
const tplUrl=k=>{const t=TPL.find(x=>x.k===k);return t?t.url:'/2026/'+k+'.html';};
const byRank=function(a,b){return (a.rank||99)-(b.rank||99);};
const $=s=>document.querySelector(s), esc=s=>(s||'').replace(/[&<>"]/g,c=>({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;'}[c]));
let CHOSEN=null;

function cardHTML(t){
  var rankCls = t.rank===1?'r1':t.rank===2?'r2':t.rank===3?'r3':'';
  return `<div class="card" data-k="${t.k}" id="card-${t.k}">
    <div class="framewrap">
      <iframe src="${t.url}" title="${esc(t.name)} preview" loading="lazy" scrolling="no" aria-hidden="true"></iframe>
      <div class="veil" data-open="${t.k}"></div>
      <span class="rank ${rankCls}">#${t.rank}</span>
      <span class="letter">${t.badge||t.k.toUpperCase()}</span>
      <span class="open" data-open="${t.k}">◱ Preview full-screen</span>
    </div>
    <div class="cbody">
      <h3>${esc(t.name)}${t.rank===1?'<span class="best">★ Recommended</span>':''}</h3>
      <div class="desc">${esc(t.desc)}</div>
      <div class="why"><b>Why it wins:</b> ${esc(t.why)}</div>
      <a class="ref" href="${esc(t.ref.url)}" target="_blank" rel="noopener"><span class="vs">vs</span> <b>${esc(t.ref.name)}</b> — ${esc(t.ref.note)} ↗</a>
      <div class="tags">${t.tags.map(x=>`<span>${esc(x)}</span>`).join('')}</div>
      <div class="actions">
        <button class="btn primary" data-open="${t.k}">Preview</button>
        <button class="btn ghost" data-make="${t.k}">Make this the site</button>
      </div>
    </div>
  </div>`;
}
$('#grid').innerHTML=TPL.slice().sort(byRank).map(cardHTML).join('');
// competitor landscape row
(function(){
  var host=document.getElementById('rivals'); if(!host)return;
  host.innerHTML=RIVALS.map(function(r){
    return '<a class="rival" href="'+esc(r.url)+'" target="_blank" rel="noopener">'+
      '<span class="rt">'+esc(r.tag)+'</span><b>'+esc(r.name)+'</b>'+
      '<span class="rn">'+esc(r.note)+'</span><span class="go">Open ↗</span></a>';
  }).join('');
})();

// switch buttons in modal
$('#switch').innerHTML=TPL.map(t=>`<button data-sw="${t.k}"><span class="l">${t.badge||t.k.toUpperCase()}</span>${esc(t.name)}</button>`).join('');

let cur='a';
function openModal(k){
  cur=k; const t=TPL.find(x=>x.k===k);
  $('#mframe').src=t.url;
  $('#mtitle').innerHTML='<span class="mrank r'+t.rank+'">#'+t.rank+'</span> '+esc(t.name)+(t.rank===1?' <span class="mbest">★ Recommended</span>':'')+' <small>'+(k==='classic'?'Current live site':'Template '+k.toUpperCase())+' · live preview</small>';
  var mi=$('#minfo'); if(mi){ mi.innerHTML='<div class="mi-why"><b>Why it wins:</b> '+esc(t.why)+'</div>'+
    '<a class="mi-ref" href="'+esc(t.ref.url)+'" target="_blank" rel="noopener"><span class="vs">vs</span> <b>'+esc(t.ref.name)+'</b> — '+esc(t.ref.note)+' ↗</a>'; }
  document.querySelectorAll('#switch button').forEach(b=>b.classList.toggle('on',b.dataset.sw===k));
  $('#ovl').classList.add('open'); document.body.style.overflow='hidden';
  refreshMakeBtn();
}
function closeModal(){ $('#ovl').classList.remove('open'); document.body.style.overflow=''; $('#mframe').src='about:blank'; }
function refreshMakeBtn(){
  const b=$('#makeBtn');
  if(CHOSEN===cur){ b.textContent='✓ Current pick'; b.classList.remove('gold'); b.classList.add('chosen-badge'); }
  else { b.textContent='★ Make this the site'; b.classList.add('gold'); b.classList.remove('chosen-badge'); }
}
// delegated clicks
document.addEventListener('click',e=>{
  const o=e.target.closest('[data-open]'); if(o){ openModal(o.dataset.open); return; }
  const m=e.target.closest('[data-make]'); if(m){ makeSite(m.dataset.make); return; }
  const sw=e.target.closest('[data-sw]'); if(sw){ openModal(sw.dataset.sw); return; }
});
$('#mclose').onclick=closeModal;
$('#ovl').addEventListener('click',e=>{ if(e.target===$('#ovl')) closeModal(); });
document.addEventListener('keydown',e=>{ if(e.key==='Escape'&&$('#ovl').classList.contains('open')) closeModal(); });
$('#openTab').onclick=()=>window.open('/2026/'+cur+'.html','_blank');
$('#makeBtn').onclick=()=>makeSite(cur);
// device width toggle
$('#dev').addEventListener('click',e=>{ const b=e.target.closest('button[data-w]'); if(!b)return;
  document.querySelectorAll('#dev button').forEach(x=>x.classList.toggle('on',x===b));
  const d=$('#device'); d.className='device'+(b.dataset.w==='tablet'?' tablet':b.dataset.w==='phone'?' phone':''); });

function toast(html){ const t=$('#toast'); t.innerHTML=html; t.classList.add('show'); clearTimeout(t._t); t._t=setTimeout(()=>t.classList.remove('show'),3400); }

async function makeSite(k){
  const t=TPL.find(x=>x.k===k);
  if(!confirm('Set Template '+k.toUpperCase()+' — “'+t.name+'” — as the chosen RENTV 2026 site?\n\nThis records your pick locally only. It does NOT deploy or publish.')) return;
  try{
    const r=await fetch('/api/ad/admin/site-template',{method:'POST',headers:{'Content-Type':'application/json'},credentials:'same-origin',body:JSON.stringify({chosen:k})});
    if(r.status===401||r.status===403){ toast('🔒 Sign in as admin to lock the pick. Preview still works. (Pick: <b>'+k.toUpperCase()+'</b>)'); return; }
    const j=await r.json();
    if(j&&j.ok){ CHOSEN=k; paintChosen(); refreshMakeBtn(); toast('★ Template <b>'+k.toUpperCase()+' — '+esc(t.name)+'</b> is now the chosen site. (Local pick — deploy is a separate step.)'); }
    else toast('Could not save the pick'+(j&&j.error?': '+esc(j.error):'.'));
  }catch(e){ toast('Network error saving the pick.'); }
}
function paintChosen(){
  document.querySelectorAll('.card').forEach(c=>c.classList.toggle('is-chosen',c.dataset.k===CHOSEN));
  document.querySelectorAll('[data-make]').forEach(b=>{
    const on=b.dataset.make===CHOSEN;
    b.textContent=on?'✓ Chosen site':'Make this the site';
    b.classList.toggle('gold',on); b.classList.toggle('ghost',!on);
  });
  const tag=$('#chosenTag');
  if(CHOSEN){ const t=TPL.find(x=>x.k===CHOSEN); tag.innerHTML='Chosen: <b>'+CHOSEN.toUpperCase()+' · '+esc(t.name)+'</b>'; }
  else tag.textContent='No template chosen yet';
}
(async function initChosen(){
  try{ const r=await fetch('/api/ad/site-template',{credentials:'same-origin'}); const j=await r.json(); CHOSEN=(j&&j.chosen)||null; }catch(e){}
  paintChosen();
})();
</script>
<script src="/2026/elements.js" defer></script>
</body></html>