����JFIF��`�`�����Viewing File: /home/u820193700/domains/thereown.com/public_html/temp_script_py.js
/* ══════════ DATA ══════════ */
/* hue = actual RE paint colour of that variant (approx), hue2 = accent/pinstripe */
const BIKES=[
 {id:1,acc:["Engine guard","Touring seat","Tank pad"],km:"9,842 km",owner:"1st Owner",insValid:"Mar 2027",shortlisted:9,year:2021,arrived:"2026-07-07",name:"Classic 350",variant:"Halcyon Green",div:"Bengaluru",reg:"KA05LF1457",cc:350,asking:128000,market:155000,newPrice:240000,newRef:"Classic 350",hue:"#2E5C43",hue2:"#C9A84C",type:"Cruiser",power:"20.2 bhp"},
 {id:2,acc:["Sump guard","Handlebar brace","Fog lamps"],km:"7,210 km",owner:"1st Owner",insValid:"Jul 2027",shortlisted:7,year:2022,arrived:"2026-07-06",name:"Scram 411",variant:"Graphite Yellow",div:"Bengaluru",reg:"KA05LJ4716",cc:411,asking:118000,market:145000,newPrice:270000,newRef:"Scram 440",hue:"#E8B400",hue2:"#2b2b2e",type:"Scrambler",power:"24.3 bhp"},
 {id:3,acc:["Panniers + stays","Windscreen","Engine guard"],km:"11,480 km",owner:"1st Owner",insValid:"Jan 2027",shortlisted:5,year:2022,arrived:"2026-07-04",name:"Himalayan",variant:"Granite Black",div:"Bengaluru",reg:"KA05LN0602",cc:411,asking:155000,market:190000,newPrice:390000,newRef:"Himalayan 450",hue:"#26262a",hue2:"#7a7a80",type:"Adventure",power:"24.3 bhp"},
 {id:4,acc:["Crash guard","Bar-end mirrors"],km:"6,950 km",owner:"1st Owner",insValid:"Sep 2027",shortlisted:3,year:2022,arrived:"2026-06-28",name:"Hunter 350",variant:"Rebel Black",div:"Bengaluru",reg:"KA05LM6876",cc:350,asking:118000,market:145000,newPrice:177000,newRef:"Hunter 350",hue:"#191919",hue2:"#C8102E",type:"Roadster",power:"20.2 bhp"},
 {id:5,acc:["Backrest","Windscreen","Touring mirrors"],km:"14,320 km",owner:"1st Owner",insValid:"Nov 2026",shortlisted:10,year:2020,status:"sold",arrived:"2026-06-25",name:"Meteor 350",variant:"Supernova Brown",div:"Bengaluru",reg:"KA05LB4129",cc:350,asking:108000,market:135000,newPrice:260000,newRef:"Meteor 350",hue:"#6E3F23",hue2:"#D8A868",type:"Tourer",power:"20.2 bhp"},
 {id:6,acc:["Engine guard","Pillion backrest"],km:"8,610 km",owner:"1st Owner",insValid:"Apr 2027",shortlisted:8,year:2021,arrived:"2026-07-08",name:"Classic 350",variant:"Halcyon Green",div:"Bengaluru",reg:"KA05LF1459",cc:350,asking:130000,market:158000,newPrice:240000,newRef:"Classic 350",hue:"#2E5C43",hue2:"#C9A84C",type:"Cruiser",power:"20.2 bhp"},
 {id:7,acc:["Crash guard","Tank strap"],km:"16,780 km",owner:"1st Owner",insValid:"Aug 2026",shortlisted:6,year:2020,arrived:"2026-06-20",name:"Bullet 350",variant:"EFI Black",div:"Bengaluru",reg:"KA05LB3819",cc:350,asking:88000,market:110000,newPrice:210000,newRef:"Bullet 350",hue:"#141414",hue2:"#C9A84C",type:"Classic",power:"19.1 bhp"},
 {id:8,acc:["Sump guard","Fog lamps"],km:"7,890 km",owner:"1st Owner",insValid:"Jun 2027",shortlisted:4,year:2022,arrived:"2026-06-18",name:"Scram 411",variant:"Graphite Yellow",div:"Bengaluru",reg:"KAO5LJ4715",cc:411,asking:122000,market:148000,newPrice:270000,newRef:"Scram 440",hue:"#E8B400",hue2:"#2b2b2e",type:"Scrambler",power:"24.3 bhp"},
 {id:9,acc:["Panniers + stays","Touring windscreen","Sump guard"],km:"10,102 km",owner:"1st Owner",insValid:"Feb 2027",shortlisted:2,year:2022,status:"booked",bookedOn:"2026-07-06",arrived:"2026-07-05",name:"Himalayan",variant:"Lake Blue",div:"Bengaluru",reg:"KA05LM8712",cc:411,asking:162000,market:195000,newPrice:390000,newRef:"Himalayan 450",hue:"#3E7CB8",hue2:"#1c3a58",type:"Adventure",power:"24.3 bhp"},
 {id:10,acc:["Crash guard","Tank pad"],km:"7,340 km",owner:"1st Owner",insValid:"Oct 2027",shortlisted:9,year:2022,arrived:"2026-06-15",name:"Hunter 350",variant:"Rebel Black",div:"Bengaluru",reg:"KA05LM6886",cc:350,asking:122000,market:148000,newPrice:177000,newRef:"Hunter 350",hue:"#191919",hue2:"#C8102E",type:"Roadster",power:"20.2 bhp"},
 {id:11,acc:["Engine guard","Flyscreen","Bar-end mirrors"],km:"9,120 km",owner:"1st Owner",insValid:"May 2027",shortlisted:7,year:2022,arrived:"2026-07-02",name:"Interceptor 650",variant:"Downtown Drag",div:"Bengaluru",reg:"KAO5LM8668",cc:650,asking:242000,market:290000,newPrice:425000,newRef:"Interceptor 650",hue:"#55565a",hue2:"#1b1b1d",type:"Roadster",power:"47 bhp"},
 {id:12,acc:["Flyscreen","Bar-end mirrors","Seat cowl"],km:"5,480 km",owner:"1st Owner",insValid:"Dec 2027",shortlisted:5,year:2023,arrived:"2026-06-30",name:"GT 640 Rocker",variant:"Red",div:"Bengaluru",reg:"KA05LR1555",cc:640,asking:268000,market:310000,newPrice:450000,newRef:"Continental GT 650",hue:"#B01E28",hue2:"#F2E6C8",type:"Café Racer",power:"47 bhp"},
];
// photos live in memory: {gallery:[dataURL...], spin:[dataURL...]}
const media={}; BIKES.forEach(b=>media[b.id]={gallery:[],spin:[],videos:[]});

const fmt=n=>"₹"+Number(n).toLocaleString("en-IN");
function listId(b){return "REO-"+String(b.id).padStart(3,"0");}
function maskReg(r){return r.slice(0,2)+"-"+r.slice(2,4)+"-******";}
function dispReg(b){return admin?b.reg:maskReg(b.reg);}
const CHECKS=[
 {t:"Engine & compression",pts:38,subs:["Cold-start test","Compression reading","Oil condition & leak check","Abnormal noise / vibration","Clutch engagement & play"]},
 {t:"Chain & sprocket",pts:16,subs:["Chain slack & lubrication","Sprocket teeth wear","Chain stretch measurement","Rear hub & cush drive"]},
 {t:"Brakes & pads",pts:24,subs:["Front & rear pad depth","Disc condition & thickness","Brake fluid level & colour","ABS function test","Lever & pedal free play"]},
 {t:"Tyres & tread",pts:14,subs:["Tread depth (both tyres)","Sidewall cracks & tyre age","Correct pressure","Rim trueness — no bends"]},
 {t:"Battery health",pts:10,subs:["Voltage & load test","Terminal corrosion check","Charging output (regulator)"]},
 {t:"Electricals & lights",pts:30,subs:["Headlamp, tail & indicators","Horn & switches","Console & warning lights","Wiring, fuses & starter motor"]},
 {t:"Frame & body",pts:26,subs:["Chassis straightness","Accident / re-weld marks","Rust & corrosion points","Tank dents & paint condition"]},
 {t:"Suspension",pts:18,subs:["Front fork seals & travel","Rear shock damping & leaks","Steering bearing play"]},
 {t:"Odometer verified",pts:10,subs:["Km matched with service records","Tampering inspection","Full service history reviewed"]},
 {t:"RC & insurance",pts:14,subs:["Original RC — chassis no. matched","Insurance validity","No hypothecation or pending challans","Ownership count verified"]},
];

let admin=false, chip="all";

/* ══════════ PLACEHOLDER ART ══════════ */
function art(b){
 const c=b.hue, a=b.hue2||"#C9A84C";
 return `<svg class="ph-art" viewBox="0 0 400 240" fill="none" style="opacity:.95;">
  <defs>
   <linearGradient id="tank${b.id}" x1="0" y1="0" x2="0" y2="1">
    <stop offset="0%" stop-color="${c}"/><stop offset="55%" stop-color="${c}"/><stop offset="100%" stop-color="#000" stop-opacity=".45"/>
   </linearGradient>
   <radialGradient id="glow${b.id}" cx="50%" cy="60%" r="65%">
    <stop offset="0%" stop-color="${c}" stop-opacity=".14"/><stop offset="100%" stop-color="${c}" stop-opacity="0"/>
   </radialGradient>
  </defs>
  <rect x="0" y="0" width="400" height="240" fill="url(#glow${b.id})" rx="16"/>
  <ellipse cx="205" cy="212" rx="185" ry="12" fill="#000" opacity=".08"/>
  <circle cx="95" cy="175" r="52" stroke="#1c1c1e" stroke-width="8"/>
  <circle cx="95" cy="175" r="26" stroke="#8a8a90" stroke-width="2.5"/>
  <circle cx="95" cy="175" r="6" fill="#1c1c1e"/>
  <circle cx="315" cy="175" r="52" stroke="#1c1c1e" stroke-width="8"/>
  <circle cx="315" cy="175" r="26" stroke="#8a8a90" stroke-width="2.5"/>
  <circle cx="315" cy="175" r="6" fill="#1c1c1e"/>
  <path d="M95 123 L145 78 L215 62 L275 72 L315 123" stroke="#232326" stroke-width="6"/>
  <path d="M145 78 L172 123 L95 123" stroke="#232326" stroke-width="4.5"/>
  <ellipse cx="222" cy="72" rx="58" ry="21" fill="url(#tank${b.id})" stroke="#141414" stroke-width="2.5"/>
  <ellipse cx="222" cy="70" rx="34" ry="9" fill="#fff" opacity=".18"/>
  <path d="M170 74 Q222 60 274 74" stroke="${a}" stroke-width="2.5" opacity=".95"/>
  <circle cx="222" cy="72" r="7" fill="${a}" opacity=".9"/>
  <path d="M160 84 Q222 70 284 84" stroke="#141414" stroke-width="4.5"/>
  <path d="M275 72 L302 48 L330 44" stroke="#232326" stroke-width="4"/>
  <circle cx="322" cy="86" r="13" fill="#F2E9CE" stroke="#232326" stroke-width="3"/>
  <rect x="168" y="102" width="66" height="46" rx="7" fill="#3a3a3e" stroke="#141414" stroke-width="2"/>
  <rect x="176" y="108" width="50" height="6" rx="3" fill="#6a6a70"/>
  <rect x="176" y="120" width="50" height="6" rx="3" fill="#6a6a70"/>
  <path d="M172 162 Q130 158 100 182" stroke="#9a9aa0" stroke-width="5"/>
  <path d="M330 82 L348 82" stroke="${a}" stroke-width="3"/>
 </svg>`;
}

/* ══════════ GRID ══════════ */
function matches(b){
 if(chip==="all")return true;
 if(chip==="350")return b.cc===350;
 if(chip==="411")return b.cc===411;
 if(chip==="650")return b.cc>=640;
 if(chip==="under15")return b.asking<150000;
 return true;
}
function setChip(f,el){chip=f;document.querySelectorAll(".chip").forEach(c=>c.classList.remove("on"));el.classList.add("on");renderGrid();}

/* status: available (default) | booked (20% paid, 7-day hold) | sold */
function stat(b){return b.status||"available";}
function holdDaysLeft(b){
 if(stat(b)!=="booked"||!b.bookedOn)return 0;
 return Math.max(0,7-Math.floor((Date.now()-new Date(b.bookedOn))/864e5));
}
const STATUS_ORDER={available:0,booked:1,sold:2};

function visibleToPublic(b){return b.approval!=="pending"&&b.approval!=="denied";}
function renderGrid(){
 const g=document.getElementById("grid");
 const pool=BIKES.filter(b=>admin?true:visibleToPublic(b));
 const APPR_ORDER={pending:0,undefined:1,approved:1,denied:2};
 const sorted=pool.filter(matches).sort((a,b)=>
  (admin?(APPR_ORDER[a.approval]-APPR_ORDER[b.approval]):0)||(STATUS_ORDER[stat(a)]-STATUS_ORDER[stat(b)]));
 g.innerHTML=sorted.map((b,i)=>{
  const m=media[b.id];
  const cover=m.gallery[0]||m.spin[0];
  const nPhotos=m.gallery.length+m.spin.length;
  return `<div class="card ${admin?'admin':''} st-${stat(b)}" style="animation-delay:${i*.04}s" onclick="openDetail(${b.id})">
   <div class="card-media">
    ${cover?`<img src="${cover}" alt="${b.name}"/>`:art(b)}
    ${stat(b)==="available"?'<div class="card-tag">Available</div>':''}
    ${stat(b)==="booked"?`<div class="card-tag tag-booked">Booked · ${holdDaysLeft(b)}d hold</div>`:''}
    ${stat(b)==="sold"?'<div class="card-tag tag-sold">Sold</div>':''}
    ${admin&&b.approval==="pending"?'<div class="card-tag" style="top:44px;color:#a06a00;">⏳ Pending approval</div>':''}
    ${admin&&b.approval==="denied"?'<div class="card-tag tag-sold" style="top:44px;">✕ Denied</div>':''}
    ${m.spin.length>1?`<div class="tag-360">↺ 360°</div>`:''}
    ${m.videos&&m.videos.length?`<div class="tag-360" style="top:${m.spin.length>1?'42':'14'}px;">▶ Video</div>`:''}
    ${nPhotos?`<div class="photo-count">${nPhotos} photos</div>`:''}
    ${admin?`<div class="upload-hint" onclick="event.stopPropagation();openUpload(${b.id})">
      <svg fill="none" stroke-width="2" viewBox="0 0 24 24"><path d="M3 16.5V19a2 2 0 002 2h14a2 2 0 002-2v-2.5M12 3v13m0-13l-4 4m4-4l4 4" stroke-linecap="round" stroke-linejoin="round"/></svg>
      ${nPhotos?'Manage photos':'Add photos'}
    </div>`:''}
   </div>
   <div class="card-body">
    <div class="card-name">${b.name} <span class="card-variant">${b.variant}</span></div>
    <div class="card-meta"><span style="color:var(--gold);font-weight:700;">${listId(b)}</span><span>·</span><span><b style="color:var(--ink2);">${b.year}</b></span><span>·</span><span>${b.km}</span><span>·</span><span>${b.owner}</span><span>·</span><span>${dispReg(b)}</span></div>
    ${b.acc&&b.acc.length?`<div class="acc-chips">${b.acc.map(a=>`<span class="acc-chip">+ ${a}</span>`).join("")}</div>`:''}
    <div class="card-foot">
     <div>
      <div class="card-was">New: ${fmt(b.newPrice)} on-road</div>
      <div class="card-price">${fmt(b.asking)}</div>
      <div class="card-save">${Math.round((1-b.asking/b.newPrice)*100)}% below new · save ${fmt(b.newPrice-b.asking)}</div>
     </div>
     <button class="btn btn-dark btn-sm" onclick="event.stopPropagation();openDetail(${b.id})">View</button>
    </div>
    ${admin&&can.approve()&&b.approval==="pending"?`
     <div style="display:flex;gap:8px;margin-top:12px;" onclick="event.stopPropagation()">
      <button class="btn btn-sm" style="flex:1;background:var(--green);color:#fff;justify-content:center;" onclick="approveBike(${b.id})">✓ Approve</button>
      <button class="btn btn-sm" style="flex:1;background:#b03030;color:#fff;justify-content:center;" onclick="denyBike(${b.id})">✕ Deny</button>
     </div>`:''}
    ${admin&&can.del()&&b.approval!=="pending"?`
     <div style="display:flex;gap:8px;margin-top:12px;" onclick="event.stopPropagation()">
      <button class="btn btn-sm btn-light" style="flex:1;justify-content:center;" onclick="editPrice(${b.id})">✎ Price</button>
      <button class="btn btn-sm" style="background:transparent;border:1.5px solid #ecc0c0;color:#b03030;" onclick="deleteBike(${b.id})">🗑</button>
     </div>`:''}
   </div>
  </div>`;
 }).join('');
}


/* ══════════ STAFF: SHARE BIKE DETAILS ══════════ */
function shareBike(id){
 const b=BIKES.find(x=>x.id===id);
 const dep=fmt(Math.round(b.asking*0.2/500)*500);
 const msg=[
  "🏍️ *REOWN · Avahan Motors — Bengaluru*","",
  "*"+b.name+" "+b.variant+"*",
  "Listing ID: "+listId(b),
  "————————————",
  "📅 Model Year: "+b.year,
  "🛣️ Kms Driven: "+b.km,
  "👤 Owner: "+b.owner,
  "🛡️ Insurance valid till: "+b.insValid,
  "📋 Reg No: "+b.reg,
  (b.acc&&b.acc.length?"🎁 Accessories FREE: "+b.acc.join(", "):null),
  "————————————",
  "💰 *Price: "+fmt(b.asking)+"*",
  "🆕 Same bike new (on-road): "+fmt(b.newPrice)+" — you save "+fmt(b.newPrice-b.asking),
  "💳 EMI from ~"+fmt(Math.round((b.asking*0.8*0.0108*Math.pow(1.0108,36))/(Math.pow(1.0108,36)-1)))+"/mo",
  "🔒 Block + test ride: 10% ("+fmt(Math.round(b.asking*0.1/500)*500)+") — love it? top up 10% to reserve · not convinced? 10% auto-refunded",
  "🔒 Reserve 7 days (finance & delivery): 20% ("+dep+") — auto-refund if not completed",
  "————————————",
  "✅ Reown 200-checkpoint certified",
  "⚡ Delivered in 100 mins (Bengaluru)",
  "↩️ 6-month buyback @ 80% (under 5,000 km)",
  "",
  "📞 Re-Own Expert Line: +91 90350 45535",
 ].filter(Boolean).join("\n");
 logEvt("Shared bike details",b.name+" ("+listId(b)+")");
 window.open("https://wa.me/?text="+encodeURIComponent(msg),"_blank");
}


/* ══════════ PHONE DIALER ══════════ */
const PHONE="+919035045535";
function callUs(){
 logEvt("Call tapped","");
 try{window.location.href="tel:"+PHONE;}
 catch(err){window.open("tel:"+PHONE,"_self");}
}

/* ══════════ STAFF ROLES (password-protected) ══════════ */
/* ← change passwords here */
const ROLE_PINS={"exec2026":"Executive","mgr2026":"Manager","dir2026":"Director","reown2026":"Manager"};
let role=null;
const can={
 upload:()=>!!role,
 addBike:()=>!!role,
 approve:()=>role==="Manager"||role==="Director",
 edit:()=>role==="Manager"||role==="Director",
 del:()=>role==="Manager"||role==="Director",
 monitor:()=>role==="Director",
};
/* activity log */
const activity=[];
function logEvt(action,detail){
 activity.push({t:new Date(),role:role||"Visitor",action,detail:detail||""});
 const reqs=JSON.parse(localStorage.getItem("requests")||"[]");
 reqs.push({t:new Date().toISOString(),action,detail});
 localStorage.setItem("requests",JSON.stringify(reqs));
}
logEvt("Site opened","");

function toggleAdmin(){
 if(!admin && !role){
  document.getElementById("pinInput").value="";
  document.getElementById("pinErr").style.display="none";
  document.getElementById("pinOv").classList.add("open");
  setTimeout(()=>document.getElementById("pinInput").focus(),100);
  return;
 }
 if(admin){logEvt("Logout",role);role=null;}
 setAdmin(!admin);
}
function checkPin(){
 const v=document.getElementById("pinInput").value;
 if(ROLE_PINS[v]){
  role=ROLE_PINS[v];
  logEvt("Login",role);
  document.getElementById("pinOv").classList.remove("open");
  setAdmin(true);
 }else{
  const err=document.getElementById("pinErr");
  err.style.display="block";
  const sh=document.getElementById("pinSheet");
  sh.style.animation="none";sh.offsetHeight;
  sh.style.animation="shake .4s";
 }
}
function setAdmin(on){
 admin=on;
 document.getElementById("adminBtn").classList.toggle("on",admin);
 document.getElementById("adminLabel").textContent=admin?(role+" · logout"):"Staff login";
 renderGrid();
 document.getElementById("heroUploadBtn").style.display=admin?"block":"none";
 const da=document.getElementById("dwallAdd");if(da)da.style.display=admin?"inline-flex":"none";
 const ab=document.getElementById("addBikeBtn");if(ab)ab.style.display=admin?"inline-flex":"none";
 const mb=document.getElementById("monitorBtn");if(mb)mb.style.display=(admin&&can.monitor())?"inline-flex":"none";
 showToast(admin?("Signed in as "+role):"Signed out");
}

/* ══════════ UPLOAD MANAGER ══════════ */
let upBikeId=null, upTab="gallery";
function openUpload(id){
 upBikeId=id; upTab="gallery";
 const b=BIKES.find(x=>x.id===id);
 document.getElementById("upTitle").textContent=b.name+" · "+b.variant;
 document.getElementById("upSub").textContent=b.reg+" — photos appear instantly on the listing";
 renderStPills(b);
 setUpTab("gallery");
 document.getElementById("uploadOv").classList.add("open");
}
function closeUpload(){document.getElementById("uploadOv").classList.remove("open");renderGrid();}
function setUpTab(t){
 upTab=t;
 document.getElementById("tabGal").classList.toggle("on",t==="gallery");
 document.getElementById("tab360").classList.toggle("on",t==="spin");
 document.getElementById("tabVid").classList.toggle("on",t==="video");
 const f=document.getElementById("upFile");
 f.accept=t==="video"?"video/*":"image/*";
 document.getElementById("dzTitle").textContent=
   t==="gallery"?"Drop gallery photos here":t==="spin"?"Drop your 360° frame sequence here":"Drop a walkaround / start-up video here";
 document.getElementById("dzSub").innerHTML=
   t==="gallery"?'or <b>browse</b> — JPG / PNG. Tap the star on any photo to make it the cover.'
   :t==="spin"?'or <b>browse</b> — select all 24–36 frames at once. They sort by filename automatically.'
   :'or <b>browse</b> — MP4 / MOV, up to ~60s works best. Engine start-up + walkaround sells bikes.';
 document.getElementById("tipText").textContent=
   t==="gallery"?"Shoot landscape, consistent height, plain background. 6–10 photos per bike is ideal."
   :t==="spin"?"Shoot 1 frame every 10–15° on a turntable (24–36 total). Name files 01.jpg, 02.jpg… and the spin plays perfectly."
   :"One take, phone in landscape: cold start, exhaust note, slow walkaround, close-up of odometer. 30–60 seconds.";
 renderUpPreviews();
}
// drag & drop
const upDrop=document.getElementById("upDrop");
["dragover","dragenter"].forEach(e=>upDrop.addEventListener(e,ev=>{ev.preventDefault();upDrop.classList.add("drag");}));
["dragleave","drop"].forEach(e=>upDrop.addEventListener(e,ev=>{ev.preventDefault();upDrop.classList.remove("drag");}));
upDrop.addEventListener("drop",ev=>handleUpload(ev.dataTransfer.files));

function handleUpload(files){
 if(!files||!files.length)return;
 if(upTab==="video"){
  const vids=[...files].filter(f=>f.type.startsWith("video/"));
  let n=0;
  vids.forEach(f=>{
   const r=new FileReader();
   r.onload=e=>{media[upBikeId].videos.push(e.target.result);n++;
    if(n===vids.length){renderUpPreviews();showToast(n+" video"+(n>1?"s":"")+" added");}};
   r.readAsDataURL(f);
  });
  document.getElementById("upFile").value="";
  return;
 }
 const arr=[...files].filter(f=>f.type.startsWith("image/"));
 arr.sort((a,b)=>a.name.localeCompare(b.name,undefined,{numeric:true}));
 let loaded=0;
 arr.forEach(f=>{
  const r=new FileReader();
  r.onload=e=>{
   media[upBikeId][upTab==="gallery"?"gallery":"spin"].push(e.target.result);
   loaded++;
   if(loaded===arr.length){renderUpPreviews();logEvt("Uploaded "+(upTab==="gallery"?"photos":"360 frames"),loaded+" file(s) — bike #"+upBikeId);showToast(loaded+(upTab==="gallery"?" photo":" frame")+(loaded>1?"s":"")+" added");}
  };
  r.readAsDataURL(f);
 });
 document.getElementById("upFile").value="";
}
function removeMedia(kind,i){media[upBikeId][kind].splice(i,1);renderUpPreviews();}
function renderUpPreviews(){
 const m=media[upBikeId]||{gallery:[],spin:[],videos:[]};
 document.getElementById("cntGal").textContent=m.gallery.length;
 document.getElementById("cnt360").textContent=m.spin.length;
 document.getElementById("cntVid").textContent=(m.videos||[]).length;
 if(upTab==="video"){
  document.getElementById("upPreviews").innerHTML=(m.videos||[]).map((src,i)=>`
   <div class="pv" style="aspect-ratio:16/9;">
    <video src="${src}" muted style="width:100%;height:100%;object-fit:cover;"></video>
    <div class="pv-n">▶ Video ${i+1}</div>
    <button class="pv-x" onclick="removeMedia('videos',${i})">✕</button>
   </div>`).join('');
  return;
 }
 const list=upTab==="gallery"?m.gallery:m.spin;
 document.getElementById("upPreviews").innerHTML=list.map((src,i)=>`
  <div class="pv">
   <img src="${src}"/>
   ${upTab==="gallery"?(i===0?'<div class="pv-cover">★ COVER</div>':`<button class="pv-star" onclick="setCover(${i})" title="Make this the cover">☆ Set cover</button>`):''}
   ${upTab==="spin"?`<div class="pv-n">${i+1}</div>`:''}
   <button class="pv-x" onclick="removeMedia('${upTab==="gallery"?"gallery":"spin"}',${i})">✕</button>
  </div>`).join('');
}
function setCover(i){
 const g=media[upBikeId].gallery;
 g.unshift(g.splice(i,1)[0]);
 renderUpPreviews();
 showToast("Cover photo updated");
}

/* ══════════ DETAIL + VIEWER ══════════ */
let curId=null, mode="gallery", galIdx=0, spinIdx=0, dragging=false, dragX=0, dragStart=0;

function openDetail(id){
 curId=id;
 const _b=BIKES.find(x=>x.id===id);if(_b){_b.views=(_b.views||0)+1;logEvt("Viewed bike",_b.name+" ("+_b.reg+")");} galIdx=0; spinIdx=0;
 const b=BIKES.find(x=>x.id===id);
 const m=media[id];
 mode=m.spin.length>1?"spin":"gallery";


 document.getElementById("detailInner").innerHTML=`
  <div class="viewer">
   <div class="stage" id="stage"></div>
   <div class="mode-pill">
    <button class="mode-btn ${mode==='gallery'?'on':''}" id="mGal" onclick="setMode('gallery')">Photos</button>
    <button class="mode-btn ${mode==='spin'?'on':''}" id="mSpin" onclick="setMode('spin')">360° spin</button>
    ${media[b.id].videos&&media[b.id].videos.length?`<button class="mode-btn" id="mVid" onclick="setMode('video')">▶ Video</button>`:''}
   </div>
   <div class="deg-badge" id="degBadge" style="display:none;">0°</div>
   <button class="gallery-nav gnav-l" id="gnavL" onclick="galStep(-1)">‹</button>
   <button class="gallery-nav gnav-r" id="gnavR" onclick="galStep(1)">›</button>
   <div class="drag-hint" id="dragHint" style="display:none;">↺ &nbsp;Drag to spin</div>
   <div class="frame-bar" id="frameBar" style="display:none;"><div class="frame-fill" id="frameFill"></div></div>
  </div>
  <div class="thumbs" id="thumbs"></div>
  <div class="detail-body">
   <div class="detail-left">
    <div class="d-name">${b.name}</div>
    <div class="d-variant"><span style="color:var(--gold);font-weight:700;">${listId(b)}</span> · ${b.variant} · ${b.year} model · Bengaluru</div>
    <div style="display:flex;align-items:center;gap:10px;margin:-8px 0 16px;">
     <button style="font-size:20px;line-height:1;" id="heartBtn" onclick="toggleShortlist(${b.id})">${b.hearted?'❤️':'🤍'}</button>
     <span style="font-size:12.5px;font-weight:600;color:var(--gold);" id="shortCount">${b.shortlisted} people have shortlisted this bike</span>
    </div>
    <div class="spec-row" style="grid-template-columns:repeat(3,1fr);">
     <div class="spec"><b>${b.km}</b><span>Kms Driven</span></div>
     <div class="spec"><b>${b.year}</b><span>Model Year</span></div>
     <div class="spec"><b>${b.owner}</b><span>Owner</span></div>
     <div class="spec"><b>${b.insValid}</b><span>Insurance Valid</span></div>
     <div class="spec"><b>${b.cc}cc</b><span>Engine</span></div>
     <div class="spec"><b>${dispReg(b)}</b><span>Reg No</span></div>
    </div>
    ${b.acc&&b.acc.length?`
    <div class="d-label">Accessories included — free with this bike</div>
    <div class="acc-chips" style="margin:-4px 0 22px;">${b.acc.map(a=>`<span class="acc-chip acc-chip-lg">+ ${a}</span>`).join("")}</div>`:''}
    <div class="d-label">Reown 200-checkpoint certification — all passed · 10 categories, tap to expand</div>
    <div class="acc">
     ${CHECKS.map((c,i)=>`
      <div class="acc-item" id="acc${i}">
       <button class="acc-head" onclick="toggleAcc(${i})">
        <span style="display:flex;align-items:center;gap:10px;">
         <svg fill="none" stroke-width="2.5" viewBox="0 0 24 24" style="width:17px;height:17px;stroke:var(--green);flex-shrink:0;"><path d="M5 13l4 4L19 7" stroke-linecap="round" stroke-linejoin="round"/></svg>
         ${c.t}
        </span>
        <span style="display:flex;align-items:center;gap:8px;">
         <span style="font-size:10.5px;font-weight:700;background:var(--green-bg);color:var(--green);padding:3px 9px;border-radius:980px;">${c.pts} checks</span>
         <span class="acc-plus">+</span>
        </span>
       </button>
       <div class="acc-body">
        ${c.subs.map(s=>`<div class="acc-sub">· ${s}</div>`).join('')}
       </div>
      </div>`).join('')}
    </div>
   </div>
   <div class="detail-right">
    <div class="d-label">Price</div>
    <div class="d-price">${fmt(b.asking)}</div>
    <div class="d-was"><s>${fmt(b.market)}</s><span class="d-save">used market avg</span></div>
    <div style="margin-top:14px;background:#fff;border:1.5px solid var(--line);border-radius:var(--radius-sm);padding:14px 16px;">
     <div style="display:flex;justify-content:space-between;font-size:13px;padding:5px 0;">
      <span style="color:var(--ink3);">New ${b.newRef} (on-road, BLR)</span><b>${fmt(b.newPrice)}</b>
     </div>
     <div style="display:flex;justify-content:space-between;font-size:13px;padding:5px 0;border-top:1px solid var(--line);">
      <span style="color:var(--ink3);">This bike</span><b>${fmt(b.asking)}</b>
     </div>
     <div style="display:flex;justify-content:space-between;font-size:13.5px;padding:7px 0 2px;border-top:1px solid var(--line);">
      <b style="color:var(--green);">You save vs new</b><b style="color:var(--green);">${fmt(b.newPrice-b.asking)} (${Math.round((1-b.asking/b.newPrice)*100)}%)</b>
     </div>
    </div>
    <div class="emi-box">
     <div class="d-label" style="margin-bottom:4px;">EMI calculator</div>
     <div class="emi-num" id="emiNum"></div>
     <div style="margin-top:10px;">
      <div style="display:flex;justify-content:space-between;font-size:11.5px;font-weight:600;color:var(--ink3);"><span>Down payment</span><span id="dpLabel"></span></div>
      <input type="range" id="dpSlider" min="10" max="60" step="5" value="20" oninput="calcEmi(${b.asking})"/>
      <div style="display:flex;justify-content:space-between;font-size:11.5px;font-weight:600;color:var(--ink3);"><span>Tenure</span><span id="tenLabel"></span></div>
      <input type="range" id="tenSlider" min="6" max="48" step="6" value="24" oninput="calcEmi(${b.asking})"/>
      <div style="display:flex;justify-content:space-between;font-size:11.5px;font-weight:600;color:var(--ink3);"><span>Interest rate</span><span id="rateLabel"></span></div>
      <input type="range" id="rateSlider" min="9" max="18" step="0.5" value="13" oninput="calcEmi(${b.asking})"/>
     </div>
     <div class="emi-note" id="emiBreak"></div>
    </div>
    ${stat(b)==="booked"?`<div class="status-banner sb-booked">⏳ Reserved — 20% received. ${holdDaysLeft(b)} day${holdDaysLeft(b)===1?"":"s"} left to complete finance/payment & delivery. If not completed, the amount is auto-refunded and the bike returns to Available.</div>`:''}
    ${stat(b)==="sold"?'<div class="status-banner sb-sold">✕ Sold — this motorcycle has found its rider. Similar stock arrives weekly.</div>':''}
    <div class="stack">
     ${stat(b)==="available"?`<button class="btn btn-gold btn-block" style="background:var(--gold);" onclick="openRules(${b.id})">⚡ Buy online (RTGS) · Delivered in 100 mins</button>`:''}
     ${stat(b)==="available"?`<button class="btn btn-block" style="background:var(--mustard);color:#141412;justify-content:center;" onclick="openRules(${b.id})">Block + test ride · 10% (${fmt(Math.round(b.asking*0.1/500)*500)}) — refundable</button>`:''}
     ${stat(b)==="available"?`<button class="btn btn-block btn-light" style="justify-content:center;" onclick="openRules(${b.id})">Reserve 7 days · 20% (${fmt(Math.round(b.asking*0.2/500)*500)}) — finance & delivery</button>`:''}
     ${stat(b)==="available"?`<button class="btn btn-dark btn-block" style="background:var(--ink);" onclick="openBook(${b.id})">Book test ride</button>`:''}
     ${stat(b)==="booked"?`<button class="btn btn-light btn-block" onclick="showToast('Added to waitlist — we\\'ll message if this booking releases')">Join waitlist — notify if released</button>`:''}
     ${stat(b)==="sold"?`<button class="btn btn-light btn-block" onclick="showToast('Noted! We\\'ll WhatsApp you when a similar ${b.name} arrives')">Notify me when similar arrives</button>`:''}
     <a class="btn btn-light btn-block" style="justify-content:center;text-decoration:none;" href="tel:+919035045535" onclick="callUs();return false;">📞 Call +91 90350 45535</a>
     ${admin?`<button class="btn btn-block" style="background:#141412;color:#fff;justify-content:center;" onclick="shareBike(${b.id})">📤 Send bike details on WhatsApp</button>`:''}
     <button class="btn btn-gold btn-block" onclick="window.open('https://wa.me/919035045535?text='+encodeURIComponent('Hi! I\\'m interested in the ${b.name} ${b.variant} (${dispReg(b)}) at ${fmt(b.asking)}.'),'_blank')">Enquire on WhatsApp</button>
     ${admin?`<button class="btn btn-light btn-block" onclick="closeDetail();openUpload(${b.id})">⬆ Manage photos (dealer)</button>`:''}
    </div>
    <div style="display:flex;flex-wrap:wrap;gap:6px;margin-top:16px;">
     <span style="font-size:11px;font-weight:700;background:var(--gold-bg);color:var(--gold-dark);padding:5px 11px;border-radius:var(--pill);">⚡ 100-min BLR delivery</span>
     <span style="font-size:11px;font-weight:700;background:var(--mustard-bg);color:#7a5c00;padding:5px 11px;border-radius:var(--pill);">↺ 6-mo buyback @ 80%</span>
     <span style="font-size:11px;font-weight:700;background:var(--green-bg);color:var(--green);padding:5px 11px;border-radius:var(--pill);">⇄ Instant exchange</span>
    </div>
    <div style="margin-top:12px;" class="mono">Reown Certified · Chassis-verified · Ref 11269V</div>
    <button style="margin-top:8px;font-size:12.5px;font-weight:600;color:var(--gold);text-decoration:underline;" onclick="openRules()">How booking works — the Re-Own rules →</button>
   </div>
  </div>`;

 document.getElementById("detailOv").classList.add("open");
 document.getElementById("detailOv").scrollTop=0;
 bindStage();
 setMode(mode);
 calcEmi(b.asking);
}
function closeDetail(){document.getElementById("detailOv").classList.remove("open");}

function setMode(m){
 const b=BIKES.find(x=>x.id===curId), md=media[curId];
 mode=m;
 document.getElementById("mGal").classList.toggle("on",m==="gallery");
 document.getElementById("mSpin").classList.toggle("on",m==="spin");
 const mv=document.getElementById("mVid"); if(mv)mv.classList.toggle("on",m==="video");
 const hasSpin=md.spin.length>1, hasGal=md.gallery.length>0;
 document.getElementById("degBadge").style.display=m==="spin"&&hasSpin?"block":"none";
 document.getElementById("dragHint").style.display=m==="spin"&&hasSpin?"flex":"none";
 document.getElementById("frameBar").style.display=m==="spin"&&hasSpin?"block":"none";
 document.getElementById("gnavL").style.display=m==="gallery"&&md.gallery.length>1?"flex":"none";
 document.getElementById("gnavR").style.display=m==="gallery"&&md.gallery.length>1?"flex":"none";
 renderStage(); renderThumbs();
}

function renderStage(){
 const b=BIKES.find(x=>x.id===curId), md=media[curId], st=document.getElementById("stage");
 if(mode==="video"){
  st.innerHTML=md.videos.length
   ?`<video src="${md.videos[0]}" controls playsinline style="width:100%;height:100%;object-fit:contain;background:#000;"></video>`
   :`<div class="empty-stage">${art(b)}<p>No video yet</p></div>`;
  return;
 }
 if(mode==="spin"){
  if(md.spin.length>1){
   st.innerHTML=`<img src="${md.spin[spinIdx]}" draggable="false"/>`;
   const deg=Math.round(spinIdx/md.spin.length*360);
   document.getElementById("degBadge").textContent=deg+"°";
   document.getElementById("frameFill").style.width=(spinIdx/(md.spin.length-1)*100)+"%";
  }else{
   st.innerHTML=`<div class="empty-stage">${art(b)}<p>No 360° frames yet${admin?' — switch to dealer upload to add a spin':''}</p>
    ${admin?`<button class="btn btn-gold btn-sm" onclick="closeDetail();openUpload(${b.id})">Upload 360° frames</button>`:''}</div>`;
  }
 }else{
  if(md.gallery.length){
   st.innerHTML=`<img src="${md.gallery[galIdx]}" draggable="false"/>`;
  }else{
   st.innerHTML=`<div class="empty-stage">${art(b)}<p>Professional photos coming soon${admin?'':' — enquire for a live video call inspection'}</p>
    ${admin?`<button class="btn btn-gold btn-sm" onclick="closeDetail();openUpload(${b.id})">Upload photos</button>`:''}</div>`;
  }
 }
}
function renderThumbs(){
 const md=media[curId], t=document.getElementById("thumbs");
 if(mode==="video"){
  t.innerHTML=md.videos.map((src,i)=>`<div class="thumb ${i===0?'on':''}" onclick="playVid(${i})"><video src="${src}" muted style="width:100%;height:100%;object-fit:cover;"></video></div>`).join('')
   +(admin?`<div class="thumb thumb-add" onclick="closeDetail();openUpload(${curId})"><span style="font-size:16px;">+</span><span>Add</span></div>`:'');
  return;
 }
 if(mode==="gallery"){
  t.innerHTML=md.gallery.map((src,i)=>`<div class="thumb ${i===galIdx?'on':''}" onclick="galIdx=${i};renderStage();renderThumbs();"><img src="${src}"/></div>`).join('')
   +(admin?`<div class="thumb thumb-add" onclick="closeDetail();openUpload(${curId})"><span style="font-size:16px;">+</span><span>Add</span></div>`:'');
 }else{
  t.innerHTML=md.spin.length>1
   ?`<div style="font-size:12.5px;color:var(--ink3);padding:6px 4px;font-weight:500;">↺ ${md.spin.length} frames · drag the image left or right to rotate</div>`
   :(admin?`<div class="thumb thumb-add" onclick="closeDetail();openUpload(${curId})" style="width:auto;padding:0 16px;"><span>+ Upload 360° frame set</span></div>`
          :`<div style="font-size:12.5px;color:var(--ink3);padding:6px 4px;">360° spin being photographed — check back soon</div>`);
 }
}
function galStep(d){
 const md=media[curId]; if(!md.gallery.length)return;
 galIdx=(galIdx+d+md.gallery.length)%md.gallery.length;
 renderStage();renderThumbs();
}
function bindStage(){
 const st=document.getElementById("stage");
 const start=x=>{if(mode!=="spin")return;dragging=true;dragX=x;dragStart=spinIdx;st.classList.add("grabbing");};
 const move=x=>{
  if(!dragging||mode!=="spin")return;
  const md=media[curId]; if(md.spin.length<2)return;
  const per=Math.max(4, 320/md.spin.length); // px per frame
  let idx=Math.round(dragStart+(x-dragX)/per);
  spinIdx=((idx%md.spin.length)+md.spin.length)%md.spin.length;
  renderStage();
 };
 const end=()=>{dragging=false;st.classList.remove("grabbing");};
 st.onmousedown=e=>start(e.clientX);
 window.onmousemove=e=>move(e.clientX);
 window.onmouseup=end;
 st.ontouchstart=e=>start(e.touches[0].clientX);
 st.ontouchmove=e=>{move(e.touches[0].clientX);};
 st.ontouchend=end;
 // gallery swipe
 let gx=null;
 st.addEventListener("touchstart",e=>{if(mode==="gallery")gx=e.touches[0].clientX;});
 st.addEventListener("touchend",e=>{
  if(mode==="gallery"&&gx!==null){
   const dx=e.changedTouches[0].clientX-gx;
   if(Math.abs(dx)>40)galStep(dx<0?1:-1);
   gx=null;
  }
 });
}
function toggleAcc(i){
 document.getElementById("acc"+i).classList.toggle("open");
}
function emi(p,mo){const r=.014;return Math.round(p*.8*r*Math.pow(1+r,mo)/(Math.pow(1+r,mo)-1));}
function pickEmi(btn,mo,price){
 btn.parentElement.querySelectorAll("button").forEach(b=>b.classList.remove("on"));
 btn.classList.add("on");
 document.getElementById("emiNum").innerHTML=fmt(emi(price,mo))+'<span style="font-size:14px;font-weight:600;color:var(--ink3);">/mo</span>';
}

/* ══════════ BOOKING ══════════ */
const bookSel=document.getElementById("bookBike");
BIKES.forEach(b=>{const o=document.createElement("option");o.value=b.id;o.textContent=`${b.name} ${b.variant} — ${maskReg(b.reg)}`;bookSel.appendChild(o);});
function openBook(id){
 logEvt("Booking opened",id?("bike #"+id):"general");
 if(id)bookSel.value=id;
 closeDetail();
 document.getElementById("bookOv").classList.add("open");
}

/* ══════════ SELL FLOW ══════════ */
const sellPhotos=[];
function sellNext(step){
 [1,2,3].forEach(s=>{
  document.getElementById("sellStep"+s).style.display=s===step?"block":"none";
  const el=document.getElementById("st"+s);
  el.classList.toggle("on",s===step);
  el.classList.toggle("done",s<step);
 });
 if(step===1){sellPhotos.length=0;document.getElementById("sellPreviews").innerHTML="";}
}
const sellDrop=document.getElementById("sellDrop");
["dragover","dragenter"].forEach(e=>sellDrop.addEventListener(e,ev=>{ev.preventDefault();sellDrop.classList.add("drag");}));
["dragleave","drop"].forEach(e=>sellDrop.addEventListener(e,ev=>{ev.preventDefault();sellDrop.classList.remove("drag");}));
sellDrop.addEventListener("drop",ev=>addSellPhotos(ev.dataTransfer.files));
function addSellPhotos(files){
 [...files].filter(f=>f.type.startsWith("image/")).forEach(f=>{
  const r=new FileReader();
  r.onload=e=>{sellPhotos.push(e.target.result);renderSellPreviews();};
  r.readAsDataURL(f);
 });
  const cam = document.getElementById("sellFileCam"); if(cam) cam.value="";
  const gal = document.getElementById("sellFileGal"); if(gal) gal.value="";
}
function renderSellPreviews(){
 document.getElementById("sellPreviews").innerHTML=sellPhotos.map((src,i)=>`
  <div class="pv"><img src="${src}"/><button class="pv-x" onclick="sellPhotos.splice(${i},1);renderSellPreviews();">✕</button></div>`).join('');
}
function computeEstimate(){
 const base={"Classic 350":128000,"Bullet 350":92000,"Hunter 350":115000,"Meteor 350":112000,"Scram 411":120000,"Himalayan":150000,"Interceptor 650":235000,"Continental GT 650":245000,"Other":100000};
 const yr={"2025":1.06,"2024":1.0,"2023":.92,"2022":.84,"2021":.76,"2020":.68,"2019":.6,"2018 or older":.5};
 const km={"Under 5,000 km":1.05,"5,000 – 15,000 km":1.0,"15,000 – 30,000 km":.92,"30,000 – 50,000 km":.82,"50,000+ km":.7};
 const cond={"Excellent — like new":1.06,"Good — minor wear":1.0,"Fair — visible wear":.88,"Needs work":.72};
 const v=Math.round(base[val("sModel")]*yr[val("sYear")]*km[val("sKm")]*cond[val("sCond")]/1000)*1000;
 document.getElementById("estValue").textContent=fmt(v);
 document.getElementById("estRange").textContent=`Range: ${fmt(Math.round(v*.94/1000)*1000)} – ${fmt(Math.round(v*1.06/1000)*1000)}`;
 sellNext(3);
}
function val(id){return document.getElementById(id).value;}

let SELL_REQUESTS = JSON.parse(localStorage.getItem('reown_sell_reqs')||'[]');
function submitSell(){
 const n=val("sName");
 const req = {
  id: Date.now(),
  name: n || "Unknown",
  phone: val("sPhone") || "N/A",
  model: val("sModel"),
  year: val("sYear"),
  km: val("sKm"),
  cond: val("sCond"),
  estimate: document.getElementById("estValue").textContent,
  photos: [...sellPhotos],
  status: "new",
  date: new Date().toISOString()
 };
 SELL_REQUESTS.unshift(req);
 localStorage.setItem('reown_sell_reqs', JSON.stringify(SELL_REQUESTS));
 showToast((n?n.split(" ")[0]+", your":"Your")+" estimate is locked — we'll call within 2 hours");
 sellNext(1);
 window.scrollTo({top:document.getElementById("sell").offsetTop-80,behavior:"smooth"});
}

let BOOKING_REQUESTS = JSON.parse(localStorage.getItem('reown_book_reqs')||'[]');

function submitBooking(){
 const bBikeId = val("bookBike");
 const bBike = BIKES.find(x => x.id == bBikeId) || {};
 const req = {
  id: Date.now(),
  bikeName: `${bBike.name} ${bBike.variant} (${bBike.reg})`,
  date: val("bookDate"),
  time: val("bookTime"),
  name: val("bookName") || "Unknown",
  phone: val("bookPhone") || "N/A",
  status: "new",
  submittedOn: new Date().toISOString()
 };
 BOOKING_REQUESTS.unshift(req);
 localStorage.setItem('reown_book_reqs', JSON.stringify(BOOKING_REQUESTS));
 document.getElementById('bookOv').classList.remove('open');
 showToast("Test ride booked — we'll confirm on WhatsApp");
}

function openStaffDashboard(){
 document.getElementById("staffDashOv").classList.add("open");
 switchDashTab('sell');
}

function switchDashTab(tab){
 const tSell = document.getElementById("tabSell");
 const tBook = document.getElementById("tabBook");
 const bSell = document.getElementById("sellReqBody");
 const bBook = document.getElementById("bookReqBody");
 if(tab === 'sell'){
  tSell.style.color = "var(--gold)"; tBook.style.color = "var(--ink3)";
  bSell.style.display = "block"; bBook.style.display = "none";
  renderSellRequests();
 } else {
  tSell.style.color = "var(--ink3)"; tBook.style.color = "var(--gold)";
  bSell.style.display = "none"; bBook.style.display = "block";
  renderBookings();
 }
}

function updateSellReqStatus(id, st){
 const r = SELL_REQUESTS.find(x => x.id === id);
 if(r){ r.status = st; localStorage.setItem('reown_sell_reqs', JSON.stringify(SELL_REQUESTS)); renderSellRequests(); }
}
function updateBookReqStatus(id, st){
 const r = BOOKING_REQUESTS.find(x => x.id === id);
 if(r){ r.status = st; localStorage.setItem('reown_book_reqs', JSON.stringify(BOOKING_REQUESTS)); renderBookings(); }
}

function renderBookings(){
 const body = document.getElementById("bookReqBody");
 if(BOOKING_REQUESTS.length===0){
  body.innerHTML = "<div style='color:var(--ink3);text-align:center;padding:40px;'>No booking requests yet.</div>"; return;
 }
 body.innerHTML = BOOKING_REQUESTS.map(r => `
  <div style="background:#f9f9f9;border-radius:var(--radius);padding:20px;border:1px solid var(--line);margin-bottom:16px;">
   <div style="display:flex;justify-content:space-between;align-items:flex-start;flex-wrap:wrap;gap:12px;">
    <div>
     <h3 style="margin:0;">${r.name} · <a href="tel:${r.phone}" style="color:var(--gold);text-decoration:none;">${r.phone}</a></h3>
     <div style="color:var(--ink3);font-size:14px;margin-top:6px;"><b>${r.bikeName}</b></div>
     <div style="font-weight:700;color:var(--mustard-dark);margin-top:6px;">Schedule: ${r.date} at ${r.time}</div>
    </div>
    <div style="text-align:right;">
     <div style="font-size:12px;color:var(--ink3);margin-bottom:12px;">${new Date(r.submittedOn).toLocaleString()}</div>
     ${r.status==='new' ? `<button class="btn btn-sm btn-dark" onclick="updateBookReqStatus(${r.id}, 'contacted')">Mark Contacted</button>` : 
       r.status==='contacted' ? `<span style="display:inline-block;padding:4px 8px;background:var(--mustard-bg);color:var(--mustard-dark);border-radius:4px;font-size:12px;font-weight:600;">Contacted</span> <button class="btn btn-sm btn-light" style="margin-left:8px;" onclick="updateBookReqStatus(${r.id}, 'closed')">Close</button>` : 
       `<span style="color:var(--green);font-weight:700;font-size:13px;">✓ Closed</span>`}
    </div>
   </div>
  </div>
 `).join('');
}

function renderSellRequests(){
 const body = document.getElementById("sellReqBody");
 if(SELL_REQUESTS.length===0){
  body.innerHTML = "<div style='color:var(--ink3);text-align:center;padding:40px;'>No sell requests yet.</div>"; return;
 }
 body.innerHTML = SELL_REQUESTS.map(r => `
  <div style="background:#f9f9f9;border-radius:var(--radius);padding:20px;border:1px solid var(--line);margin-bottom:16px;">
   <div style="display:flex;justify-content:space-between;align-items:flex-start;flex-wrap:wrap;gap:12px;">
    <div>
     <h3 style="margin:0;">${r.name} · <a href="tel:${r.phone}" style="color:var(--gold);text-decoration:none;">${r.phone}</a></h3>
     <div style="color:var(--ink3);font-size:14px;margin-top:6px;"><b>${r.model}</b> (${r.year}) · ${r.km} · ${r.cond}</div>
     <div style="font-weight:700;color:var(--green);margin-top:6px;">Est: ${r.estimate}</div>
    </div>
    <div style="text-align:right;">
     <div style="font-size:12px;color:var(--ink3);margin-bottom:12px;">${new Date(r.date).toLocaleString()}</div>
     ${r.status==='new' ? `<button class="btn btn-sm btn-dark" onclick="updateSellReqStatus(${r.id}, 'contacted')">Mark Contacted</button>` : 
       r.status==='contacted' ? `<span style="display:inline-block;padding:4px 8px;background:var(--mustard-bg);color:var(--mustard-dark);border-radius:4px;font-size:12px;font-weight:600;">Contacted</span> <button class="btn btn-sm btn-light" style="margin-left:8px;" onclick="updateSellReqStatus(${r.id}, 'closed')">Close</button>` : 
       `<span style="color:var(--green);font-weight:700;font-size:13px;">✓ Closed</span>`}
    </div>
   </div>
   ${r.photos.length > 0 ? `
   <div style="display:flex;gap:8px;margin-top:16px;overflow-x:auto;">
    ${r.photos.map(p => `<a href="${p}" target="_blank"><img src="${p}" style="height:80px;border-radius:4px;object-fit:cover;width:100px;border:1px solid var(--line);"/></a>`).join('')}
   </div>` : '<div style="margin-top:12px;font-size:13px;color:var(--ink3);">No photos provided.</div>'}
  </div>
 `).join('');
}

function formatReg(el) {
 let v = el.value.toUpperCase().replace(/[^A-Z0-9]/g, '');
 let res = '';
 if (v.length > 0) res += v.slice(0, 2);
 if (v.length > 2) res += ' ' + v.slice(2, 4);
 if (v.length > 4) res += ' ' + v.slice(4, 6);
 if (v.length > 6) res += ' ' + v.slice(6, 10);
 el.value = res;
}

/* ══════════ MISC ══════════ */
function go(id,el){
 document.getElementById(id).scrollIntoView({behavior:"smooth"});
 if(el){document.querySelectorAll(".nav-item").forEach(n=>n.classList.remove("on"));el.classList.add("on");}
}
let toastT;
function showToast(msg){
 document.getElementById("toastMsg").textContent=msg;
 const t=document.getElementById("toast");
 t.classList.add("show");
 clearTimeout(toastT);
 toastT=setTimeout(()=>t.classList.remove("show"),3500);
}

renderGrid();





function playVid(i){
 const md=media[curId];
 const st=document.getElementById("stage");
 st.innerHTML=`<video src="${md.videos[i]}" controls autoplay playsinline style="width:100%;height:100%;object-fit:contain;background:#000;"></video>`;
}
/* ══════════ REOWN PDP FEATURES ══════════ */
function calcEmi(price){
 const dp=Number(document.getElementById("dpSlider").value);
 const ten=Number(document.getElementById("tenSlider").value);
 const rate=Number(document.getElementById("rateSlider").value);
 document.getElementById("dpLabel").textContent=dp+"% ("+fmt(Math.round(price*dp/100))+")";
 document.getElementById("tenLabel").textContent=ten+" months";
 document.getElementById("rateLabel").textContent=rate+"% p.a.";
 const P=price*(1-dp/100), r=rate/1200;
 const e=Math.round(P*r*Math.pow(1+r,ten)/(Math.pow(1+r,ten)-1));
 document.getElementById("emiNum").innerHTML=fmt(e)+'<span style="font-size:14px;font-weight:600;color:var(--ink3);">/mo</span>';
 document.getElementById("emiBreak").textContent="Loan "+fmt(Math.round(P))+" | Total interest "+fmt(Math.round(e*ten-P));
}
function toggleShortlist(id){
 const b=BIKES.find(x=>x.id===id);
 b.hearted=!b.hearted;
 b.shortlisted+=b.hearted?1:-1;
 const h=document.getElementById("heartBtn"),c=document.getElementById("shortCount");
 if(h)h.textContent=b.hearted?"❤️":"🤍";
 if(c)c.textContent=b.shortlisted+" people have shortlisted this bike";
 showToast(b.hearted?"Added to your shortlist":"Removed from shortlist");
}



/* ══════════ WORKFLOW: ADD / APPROVE / EDIT / DELETE ══════════ */
const MODEL_DEFAULTS={
 "Classic 350":{cc:350,power:"20.2 bhp",type:"Cruiser",hue:"#2E5C43",hue2:"#C9A84C",newPrice:240000,newRef:"Classic 350"},
 "Bullet 350":{cc:350,power:"19.1 bhp",type:"Classic",hue:"#141414",hue2:"#C9A84C",newPrice:210000,newRef:"Bullet 350"},
 "Hunter 350":{cc:350,power:"20.2 bhp",type:"Roadster",hue:"#191919",hue2:"#C8102E",newPrice:177000,newRef:"Hunter 350"},
 "Meteor 350":{cc:350,power:"20.2 bhp",type:"Tourer",hue:"#6E3F23",hue2:"#D8A868",newPrice:260000,newRef:"Meteor 350"},
 "Scram 411":{cc:411,power:"24.3 bhp",type:"Scrambler",hue:"#E8B400",hue2:"#2b2b2e",newPrice:270000,newRef:"Scram 440"},
 "Himalayan":{cc:411,power:"24.3 bhp",type:"Adventure",hue:"#3E7CB8",hue2:"#1c3a58",newPrice:390000,newRef:"Himalayan 450"},
 "Interceptor 650":{cc:650,power:"47 bhp",type:"Roadster",hue:"#55565a",hue2:"#1b1b1d",newPrice:425000,newRef:"Interceptor 650"},
 "Continental GT 650":{cc:650,power:"47 bhp",type:"Café Racer",hue:"#B01E28",hue2:"#F2E6C8",newPrice:450000,newRef:"Continental GT 650"},
};
function openAddBike(){
 document.getElementById("addOv").classList.add("open");
}
function submitBike(){
 const g=id=>document.getElementById(id).value;
 const model=g("abModel"),variant=g("abVariant")||"Standard",reg=g("abReg").toUpperCase()||"KA00XX0000";
 const yr=Number(g("abYear")),km=g("abKm")||"—",price=Number(g("abPrice"))||100000;
 const d=MODEL_DEFAULTS[model]||MODEL_DEFAULTS["Classic 350"];
 const id=Math.max(...BIKES.map(b=>b.id))+1;
 BIKES.push({id,km:km+(/km/i.test(km)?"":" km"),owner:g("abOwner"),insValid:g("abIns")||"—",
  shortlisted:2,year:yr,name:model,variant,div:"Bengaluru",reg,
  cc:d.cc,asking:price,market:Math.round(price*1.15),newPrice:d.newPrice,newRef:d.newRef,
  hue:d.hue,hue2:d.hue2,type:d.type,power:d.power,
  approval:can.approve()?"approved":"pending",addedBy:role,acc:(g("abAcc")||"").split(",").map(s=>s.trim()).filter(Boolean)});
 media[id]={gallery:[],spin:[],videos:[]};
 logEvt("Added motorcycle",model+" "+variant+" ("+reg+")"+(can.approve()?"":" — pending"));
 document.getElementById("addOv").classList.remove("open");
 renderGrid();
 showToast(can.approve()?"Motorcycle published to showroom":"Submitted — waiting for Manager approval");
}
function approveBike(id){
 const b=BIKES.find(x=>x.id===id);
 b.approval="approved";
 logEvt("Approved listing",b.name+" ("+b.reg+")");
 renderGrid();showToast(b.name+" approved & live");
}
function denyBike(id){
 const b=BIKES.find(x=>x.id===id);
 b.approval="denied";
 logEvt("Denied listing",b.name+" ("+b.reg+")");
 renderGrid();showToast(b.name+" denied");
}
function deleteBike(id){
 const b=BIKES.find(x=>x.id===id);
 if(!confirm("Delete "+b.name+" "+b.variant+" ("+b.reg+") permanently?"))return;
 BIKES.splice(BIKES.indexOf(b),1);
 logEvt("Deleted listing",b.name+" ("+b.reg+")");
 renderGrid();showToast("Listing deleted");
}
function editPrice(id){
 const b=BIKES.find(x=>x.id===id);
 const v=prompt("New asking price for "+b.name+" ("+b.reg+"):",b.asking);
 if(v===null)return;
 const old=b.asking;b.asking=Number(v)||b.asking;
 logEvt("Changed price",b.name+": "+fmt(old)+" → "+fmt(b.asking));
 renderGrid();showToast("Price updated to "+fmt(b.asking));
}

/* ══════════ DIRECTOR DASHBOARD ══════════ */
function openMonitor(){
 const d=document.getElementById("monBody");
 const logins=activity.filter(a=>a.action==="Login").length;
 const views=activity.filter(a=>a.action==="Viewed bike").length;
 const uploads=activity.filter(a=>a.action.includes("Upload")||a.action.includes("photo")).length;
 const adds=activity.filter(a=>a.action==="Added motorcycle").length;
 const appr=activity.filter(a=>a.action==="Approved listing"||a.action==="Denied listing").length;
 const wa=activity.filter(a=>a.action==="WhatsApp enquiry"||a.action==="Booking opened").length;
 const topViewed=[...BIKES].filter(b=>b.views).sort((a,b)=>(b.views||0)-(a.views||0)).slice(0,5);
 const byRole={};activity.forEach(a=>{byRole[a.role]=(byRole[a.role]||0)+1;});
 d.innerHTML=`
  <div style="display:grid;grid-template-columns:repeat(3,1fr);gap:10px;margin-bottom:20px;">
   ${[["Logins",logins],["Bike views",views],["Enquiries",wa],["Bikes added",adds],["Approvals/denials",appr],["Total events",activity.length]].map(([l,v])=>`
    <div style="background:#f6f5f0;border-radius:12px;padding:14px;text-align:center;">
     <div style="font-family:'Oswald',sans-serif;font-size:24px;font-weight:700;color:var(--gold);">${v}</div>
     <div style="font-size:10px;font-weight:700;letter-spacing:1.5px;text-transform:uppercase;color:var(--ink3);margin-top:2px;">${l}</div>
    </div>`).join("")}
  </div>
  <div class="d-label">Activity by role</div>
  <div style="display:flex;gap:8px;flex-wrap:wrap;margin-bottom:20px;">
   ${Object.entries(byRole).map(([r,c])=>`<span style="font-size:12px;font-weight:700;background:var(--gold-bg);color:var(--gold-dark);padding:6px 14px;border-radius:980px;">${r}: ${c} actions</span>`).join("")}
  </div>
  <div class="d-label">Most viewed bikes</div>
  ${topViewed.length?topViewed.map(b=>`
   <div style="display:flex;justify-content:space-between;padding:8px 0;border-bottom:1px solid var(--line);font-size:13.5px;">
    <span><b>${b.name}</b> ${b.variant} · ${b.reg}</span><b style="color:var(--gold);">${b.views} views</b>
   </div>`).join(""):'<div style="font-size:13px;color:var(--ink3);padding:8px 0;">No bike views yet this session.</div>'}
  <div class="d-label" style="margin-top:20px;">Activity log (latest first)</div>
  <div style="max-height:260px;overflow-y:auto;border:1.5px solid var(--line);border-radius:12px;">
   ${[...activity].reverse().map(a=>`
    <div style="display:flex;gap:10px;padding:9px 14px;border-bottom:1px solid var(--line);font-size:12.5px;align-items:baseline;">
     <span style="color:var(--ink3);white-space:nowrap;font-variant-numeric:tabular-nums;">${a.t.toLocaleTimeString()}</span>
     <b style="color:${a.role==="Director"?"#6a3a8a":a.role==="Manager"?"var(--gold)":a.role==="Executive"?"var(--green)":"var(--ink3)"};white-space:nowrap;">${a.role}</b>
     <span><b>${a.action}</b>${a.detail?" — "+a.detail:""}</span>
    </div>`).join("")}
  </div>`;
 document.getElementById("monOv").classList.add("open");
}

/* ══════════ DELIVERY WALL ══════════ */
const deliveries=[
 {img:null,bikeId:12,name:"GT 640 Rocker",sub:"Delivered · Indiranagar · \u2605\u2605\u2605\u2605\u2605"},
 {img:null,bikeId:11,name:"Interceptor 650",sub:"Delivered in 100 mins · Whitefield"},
 {img:null,bikeId:1,name:"Classic 350",sub:"First bike! · Koramangala · \u2605\u2605\u2605\u2605\u2605"},
 {img:null,bikeId:9,name:"Himalayan",sub:"Ladakh-ready · HSR Layout"},
 {img:null,bikeId:4,name:"Hunter 350",sub:"Same-day delivery · JP Nagar"},
 {img:null,bikeId:5,name:"Meteor 350",sub:"Weekend cruiser · Hebbal · \u2605\u2605\u2605\u2605\u2605"},
 {img:null,bikeId:2,name:"Scram 411",sub:"Trail time · Sarjapur"},
 {img:null,bikeId:7,name:"Bullet 350",sub:"The classic choice · Jayanagar"},
];
function renderDeliveries(){
 const t=document.getElementById("dwallTrack");
 if(!t)return;
 const card=d=>{
  const b=BIKES.find(x=>x.id===d.bikeId)||BIKES[0];
  return `<div class="dcard">
   <div class="dcard-img">${d.img?`<img src="${d.img}"/>`:art(b)}<div class="dcard-tick">\u2713 Delivered</div></div>
   <div class="dcard-cap"><div class="dcard-name">${d.name}</div><div class="dcard-sub">${d.sub}</div></div>
  </div>`;
 };
 const half=deliveries.map(card).join("");
 t.innerHTML=half+half; /* duplicate for seamless loop */
}
function addDeliveries(files){
 const imgs=[...files].filter(f=>f.type.startsWith("image/"));
 let n=0;
 imgs.forEach(f=>{
  const r=new FileReader();
  r.onload=e=>{
   deliveries.unshift({img:e.target.result,bikeId:1,name:"Happy Rider",sub:"Delivered · Bengaluru · \u2605\u2605\u2605\u2605\u2605"});
   n++;
   if(n===imgs.length){renderDeliveries();showToast(n+" delivery photo"+(n>1?"s":"")+" added to the wall");}
  };
  r.readAsDataURL(f);
 });
 document.getElementById("dwallFile").value="";
}

/* ══════════ HERO PHOTO (dealer) ══════════ */
function setHeroPhoto(files){
 if(!files||!files[0])return;
 const r=new FileReader();
 r.onload=e=>{
  const bg=document.getElementById("heroBg");
  bg.style.backgroundImage=`url(${e.target.result})`;
  bg.querySelector(".hero-bike").style.display="none";
  localStorage.setItem("reown_hero", e.target.result);
  showToast("Hero photo updated");
 };
 r.readAsDataURL(files[0]);
}

/* ══════════ DEALER STATUS CONTROL ══════════ */
function renderStPills(b){
 const el=document.getElementById("stPills");
 if(!el)return;
 const s=stat(b);
 el.innerHTML=["available","booked","sold"].map(x=>
  `<button class="st-pill ${s===x?'on-'+x:''}" onclick="setStatus(${b.id},'${x}')">${x==="booked"?"Booked (20%)":x}</button>`).join("");
}
function setStatus(id,s){
 const b=BIKES.find(x=>x.id===id);
 b.status=s;
 if(s==="booked")b.bookedOn=new Date().toISOString().slice(0,10);
 if(s!=="booked")delete b.bookedOn;
 renderStPills(b);renderGrid();
 showToast(b.name+" marked "+(s==="booked"?"Booked — 7-day hold started":s.charAt(0).toUpperCase()+s.slice(1)));
}
function openRules(bikeId){
 closeDetail();
 document.getElementById("rulesOv").classList.add("open");
 document.getElementById("rulesOv").scrollTop=0;
}

/* ══════════ NEW ARRIVALS ══════════ */
function daysAgo(d){return Math.max(0,Math.floor((Date.now()-new Date(d))/(864e5)));}
function isFresh(b){return daysAgo(b.arrived)<=10;}
function renderArrivals(){
 const row=document.getElementById("arrivalsRow");
 if(!row)return;
 const recent=[...BIKES].filter(b=>stat(b)!=="sold").sort((a,b)=>new Date(b.arrived)-new Date(a.arrived)).slice(0,6);
 row.innerHTML=recent.map(b=>{
  const m=media[b.id];const cover=m.gallery[0]||m.spin[0];const d=daysAgo(b.arrived);
  return `<div class="arr-card" onclick="openDetail(${b.id})">
   <div class="arr-media">
    ${cover?`<img src="${cover}"/>`:art(b)}
    ${isFresh(b)?'<div class="arr-new">New</div>':''}
    ${m.spin.length>1?'<div class="tag-360" style="top:10px;right:10px;">↺ 360°</div>':''}
   </div>
   <div class="arr-body">
    <div class="arr-name">${b.name}</div>
    <div class="arr-meta">${b.year} · ${b.variant} · ${b.reg}</div>
    <div class="arr-price">${fmt(b.asking)}</div>
    <div class="arr-days">${d===0?"Arrived today":d===1?"Arrived yesterday":"Arrived "+d+" days ago"}</div>
   </div>
  </div>`;
 }).join("");
}

renderDeliveries();
(function(){
 const savedHero=localStorage.getItem("reown_hero");
 if(savedHero){
  const bg=document.getElementById("heroBg");
  if(bg){
   bg.style.backgroundImage=`url(${savedHero})`;
   const b=bg.querySelector(".hero-bike");
   if(b) b.style.display="none";
  }
 }
})();
Back to Directory �������}�!1AQa"q2���#B��R��$3br� %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz�������������������������������������������������������������������������������� ������w�!1AQaq"2�B���� #3R�br� $4�%�&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz������������������������������������������������������������������������ ��?��_��+��?��(���(���(���(���(���(���(���(���(���(���(���(���(���(���(���(���(���(���(���(���(���(���(���(���(���(���(���(���(���(���(���(���(���(���(���(���(���(���(���(���(���(���(���(���(���(���(���(�����