{"id":1642,"date":"2026-05-08T05:40:08","date_gmt":"2026-05-08T05:40:08","guid":{"rendered":"https:\/\/thefiniteearth.org\/?page_id=1642"},"modified":"2026-05-08T05:43:38","modified_gmt":"2026-05-08T05:43:38","slug":"test-portal-tracker","status":"publish","type":"page","link":"https:\/\/thefiniteearth.org\/hindi\/test-portal-tracker\/","title":{"rendered":"Test portal tracker"},"content":{"rendered":"<p>Portal Daily Tracker[tcb-script src=&#8221;https:\/\/cdnjs.cloudflare.com\/ajax\/libs\/xlsx\/0.18.5\/xlsx.full.min.js&#8221;][\/tcb-script]            <\/p>\n<h1>Portal Daily Tracker<\/h1>\n<p>              <span id=\"today-chip\"><\/span>        <span><img decoding=\"async\" role=\"img\" alt=\"\ud83d\udcc2\" src=\"https:\/\/s.w.org\/images\/core\/emoji\/17.0.2\/svg\/1f4c2.svg\"><\/span>          <\/p>\n<p id=\"ustrip-main\"><strong>Upload new CSV \/ Excel<\/strong> to update data<\/p>\n<p>      Columns: Name \u00b7 City \u00b7 Used Referral Code \u00b7 Referral Code \u00b7 Created (IST)        Browse              <span><img decoding=\"async\" role=\"img\" alt=\"\ud83d\udcc1\" src=\"https:\/\/s.w.org\/images\/core\/emoji\/17.0.2\/svg\/1f4c1.svg\"><\/span>    <span id=\"fname\"><\/span>    <span id=\"tbdg\"><\/span>            DATE:        \u2398 Copy Summary            <\/p>\n<h3><img decoding=\"async\" role=\"img\" alt=\"\ud83c\udfd9\" src=\"https:\/\/s.w.org\/images\/core\/emoji\/17.0.2\/svg\/1f3d9.svg\"> Top 3 Cities \u2014 All Time<\/h3>\n<ul id=\"top-c\"><\/ul>\n<h3><img decoding=\"async\" role=\"img\" alt=\"\ud83d\uddfa\" src=\"https:\/\/s.w.org\/images\/core\/emoji\/17.0.2\/svg\/1f5fa.svg\"> Top 3 States \u2014 All Time<\/h3>\n<ul id=\"top-s\"><\/ul>\n<h3><img decoding=\"async\" role=\"img\" alt=\"\ud83d\udd17\" src=\"https:\/\/s.w.org\/images\/core\/emoji\/17.0.2\/svg\/1f517.svg\"> Top 3 Referrers \u2014 All Time<\/h3>\n<ul id=\"top-r\"><\/ul>\n<p>              <span id=\"tbl-title\">Pledges<\/span>      <span id=\"tbl-badge\"><\/span>              <\/p>\n<table>\n<thead id=\"thead\"><\/thead>\n<tbody id=\"tbody\"><\/tbody>\n<\/table>\n<p>      No records for this date.      [tcb-script]\/\/ \u2500\u2500 ALL CONSTANTS DEFINED FIRST \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500const ALIASES = {  &#8216;bengaluru&#8217;:&#8217;Bangalore&#8217;,&#8217;banglore&#8217;:&#8217;Bangalore&#8217;,&#8217;bangaluru&#8217;:&#8217;Bangalore&#8217;,&#8217;benagluru&#8217;:&#8217;Bangalore&#8217;,  &#8216;bangalore rural&#8217;:&#8217;Bangalore&#8217;,&#8217;bengaluru urban&#8217;:&#8217;Bangalore&#8217;,&#8217;basavanapura&#8217;:&#8217;Bangalore&#8217;,  &#8216;new delhi&#8217;:&#8217;Delhi&#8217;,&#8217;east delhi&#8217;:&#8217;Delhi&#8217;,&#8217;north west delhi&#8217;:&#8217;Delhi&#8217;,&#8217;shahdara&#8217;:&#8217;Delhi&#8217;,&#8217;east patel nagar&#8217;:&#8217;Delhi&#8217;,  &#8216;khandws&#8217;:&#8217;Khandwa&#8217;,  &#8216;khargon&#8217;:&#8217;Khargone&#8217;,&#8217;khargon mp&#8217;:&#8217;Khargone&#8217;,&#8217;gogawa dist khargone&#8217;:&#8217;Khargone&#8217;,  &#8216;bhikangav&#8217;:&#8217;Bhikangaon&#8217;,&#8217;bhingav&#8217;:&#8217;Bhikangaon&#8217;,&#8217;bhikangoa&#8217;:&#8217;Bhikangaon&#8217;,&#8217;bhikangoan&#8217;:&#8217;Bhikangaon&#8217;,&#8217;bhinakngaon&#8217;:&#8217;Bhikangaon&#8217;,  &#8216;vaikom p o&#8217;:&#8217;Vaikom&#8217;,&#8217;kottayam district&#8217;:&#8217;Kottayam&#8217;,&#8217;kottayam vaikom&#8217;:&#8217;Kottayam&#8217;,  &#8216;thalayolapparambu&#8217;:&#8217;Thalayolaparambu&#8217;,&#8217;thalayolaparamb&#8217;:&#8217;Thalayolaparambu&#8217;,  &#8216;prayagaraj&#8217;:&#8217;Prayagraj&#8217;,&#8217;allahabad&#8217;:&#8217;Prayagraj&#8217;,&#8217;prayagraj (up)&#8217;:&#8217;Prayagraj&#8217;,  &#8216;gurugram haryana&#8217;:&#8217;Gurugram&#8217;,&#8217;gurgaon&#8217;:&#8217;Gurugram&#8217;,  &#8216;sringar&#8217;:&#8217;Srinagar&#8217;,  &#8216;kanpur nagar&#8217;:&#8217;Kanpur&#8217;,  &#8216;iit mandi&#8217;:&#8217;Mandi&#8217;,&#8217;kamand&#8217;:&#8217;Mandi&#8217;,  &#8216;trivandrum&#8217;:&#8217;Thiruvananthapuram&#8217;,  &#8216;calicut&#8217;:&#8217;Kozhikode&#8217;,&#8217;mangalore&#8217;:&#8217;Mangaluru&#8217;,  &#8216;trichy&#8217;:&#8217;Tiruchirappalli&#8217;,&#8217;tirupur&#8217;:&#8217;Tiruppur&#8217;,  &#8216;shimogga&#8217;:&#8217;Shimoga&#8217;,&#8217;simla&#8217;:&#8217;Shimla&#8217;,  &#8216;dehra dun&#8217;:&#8217;Dehradun&#8217;,&#8217;narmadapuram&#8217;:&#8217;Hoshangabad&#8217;,  &#8216;rajkot gujarat&#8217;:&#8217;Rajkot&#8217;,&#8217;bhopal mp&#8217;:&#8217;Bhopal&#8217;,  &#8216;greater noida west&#8217;:&#8217;Noida&#8217;,&#8217;greater noida&#8217;:&#8217;Noida&#8217;,  &#8216;indoor&#8217;:&#8217;Indore&#8217;,&#8217;purnia&#8217;:&#8217;Purnea&#8217;,&#8217;mandsour&#8217;:&#8217;Mandsaur&#8217;,&#8217;gorkhpur up&#8217;:&#8217;Gorakhpur&#8217;,  &#8216;port blair south andamans&#8217;:&#8217;Port Blair&#8217;,&#8217;south andaman&#8217;:&#8217;Port Blair&#8217;,  &#8216;avadi thiruvallur&#8217;:&#8217;Thiruvallur&#8217;,&#8217;kamrup metropolitan&#8217;:&#8217;Guwahati&#8217;,&#8217;ashok nagar&#8217;:&#8217;Ashoknagar&#8217;,};const STATE_MAP = {  &#8216;delhi&#8217;:&#8217;Delhi&#8217;,&#8217;new delhi&#8217;:&#8217;Delhi&#8217;,  &#8216;mumbai&#8217;:&#8217;Maharashtra&#8217;,&#8217;pune&#8217;:&#8217;Maharashtra&#8217;,&#8217;nagpur&#8217;:&#8217;Maharashtra&#8217;,&#8217;nashik&#8217;:&#8217;Maharashtra&#8217;,&#8217;aurangabad&#8217;:&#8217;Maharashtra&#8217;,&#8217;thane&#8217;:&#8217;Maharashtra&#8217;,&#8217;navi mumbai&#8217;:&#8217;Maharashtra&#8217;,&#8217;kolhapur&#8217;:&#8217;Maharashtra&#8217;,&#8217;solapur&#8217;:&#8217;Maharashtra&#8217;,  &#8216;bengaluru&#8217;:&#8217;Karnataka&#8217;,&#8217;bangalore&#8217;:&#8217;Karnataka&#8217;,&#8217;mysuru&#8217;:&#8217;Karnataka&#8217;,&#8217;mysore&#8217;:&#8217;Karnataka&#8217;,&#8217;hubli&#8217;:&#8217;Karnataka&#8217;,&#8217;mangaluru&#8217;:&#8217;Karnataka&#8217;,&#8217;shimoga&#8217;:&#8217;Karnataka&#8217;,&#8217;tumkur&#8217;:&#8217;Karnataka&#8217;,  &#8216;hyderabad&#8217;:&#8217;Telangana&#8217;,&#8217;warangal&#8217;:&#8217;Telangana&#8217;,&#8217;karimnagar&#8217;:&#8217;Telangana&#8217;,&#8217;nizamabad&#8217;:&#8217;Telangana&#8217;,  &#8216;chennai&#8217;:&#8217;Tamil Nadu&#8217;,&#8217;coimbatore&#8217;:&#8217;Tamil Nadu&#8217;,&#8217;madurai&#8217;:&#8217;Tamil Nadu&#8217;,&#8217;tiruchirappalli&#8217;:&#8217;Tamil Nadu&#8217;,&#8217;tiruppur&#8217;:&#8217;Tamil Nadu&#8217;,&#8217;salem&#8217;:&#8217;Tamil Nadu&#8217;,&#8217;tirunelveli&#8217;:&#8217;Tamil Nadu&#8217;,&#8217;vellore&#8217;:&#8217;Tamil Nadu&#8217;,&#8217;erode&#8217;:&#8217;Tamil Nadu&#8217;,&#8217;thiruvallur&#8217;:&#8217;Tamil Nadu&#8217;,  &#8216;kolkata&#8217;:&#8217;West Bengal&#8217;,&#8217;howrah&#8217;:&#8217;West Bengal&#8217;,&#8217;durgapur&#8217;:&#8217;West Bengal&#8217;,&#8217;asansol&#8217;:&#8217;West Bengal&#8217;,&#8217;siliguri&#8217;:&#8217;West Bengal&#8217;,  &#8216;ahmedabad&#8217;:&#8217;Gujarat&#8217;,&#8217;surat&#8217;:&#8217;Gujarat&#8217;,&#8217;vadodara&#8217;:&#8217;Gujarat&#8217;,&#8217;rajkot&#8217;:&#8217;Gujarat&#8217;,&#8217;bhavnagar&#8217;:&#8217;Gujarat&#8217;,&#8217;jamnagar&#8217;:&#8217;Gujarat&#8217;,&#8217;gandhinagar&#8217;:&#8217;Gujarat&#8217;,  &#8216;jaipur&#8217;:&#8217;Rajasthan&#8217;,&#8217;jodhpur&#8217;:&#8217;Rajasthan&#8217;,&#8217;udaipur&#8217;:&#8217;Rajasthan&#8217;,&#8217;kota&#8217;:&#8217;Rajasthan&#8217;,&#8217;bikaner&#8217;:&#8217;Rajasthan&#8217;,&#8217;ajmer&#8217;:&#8217;Rajasthan&#8217;,  &#8216;lucknow&#8217;:&#8217;Uttar Pradesh&#8217;,&#8217;kanpur&#8217;:&#8217;Uttar Pradesh&#8217;,&#8217;agra&#8217;:&#8217;Uttar Pradesh&#8217;,&#8217;varanasi&#8217;:&#8217;Uttar Pradesh&#8217;,&#8217;prayagraj&#8217;:&#8217;Uttar Pradesh&#8217;,&#8217;meerut&#8217;:&#8217;Uttar Pradesh&#8217;,&#8217;ghaziabad&#8217;:&#8217;Uttar Pradesh&#8217;,&#8217;noida&#8217;:&#8217;Uttar Pradesh&#8217;,&#8217;gorakhpur&#8217;:&#8217;Uttar Pradesh&#8217;,&#8217;gonda&#8217;:&#8217;Uttar Pradesh&#8217;,&#8217;aligarh&#8217;:&#8217;Uttar Pradesh&#8217;,&#8217;bareilly&#8217;:&#8217;Uttar Pradesh&#8217;,&#8217;banda&#8217;:&#8217;Uttar Pradesh&#8217;,  &#8216;bhopal&#8217;:&#8217;Madhya Pradesh&#8217;,&#8217;indore&#8217;:&#8217;Madhya Pradesh&#8217;,&#8217;gwalior&#8217;:&#8217;Madhya Pradesh&#8217;,&#8217;jabalpur&#8217;:&#8217;Madhya Pradesh&#8217;,&#8217;ujjain&#8217;:&#8217;Madhya Pradesh&#8217;,&#8217;khandwa&#8217;:&#8217;Madhya Pradesh&#8217;,&#8217;khargone&#8217;:&#8217;Madhya Pradesh&#8217;,&#8217;bhikangaon&#8217;:&#8217;Madhya Pradesh&#8217;,&#8217;neemuch&#8217;:&#8217;Madhya Pradesh&#8217;,&#8217;mandsaur&#8217;:&#8217;Madhya Pradesh&#8217;,&#8217;hoshangabad&#8217;:&#8217;Madhya Pradesh&#8217;,&#8217;sehore&#8217;:&#8217;Madhya Pradesh&#8217;,&#8217;ashoknagar&#8217;:&#8217;Madhya Pradesh&#8217;,  &#8216;patna&#8217;:&#8217;Bihar&#8217;,&#8217;gaya&#8217;:&#8217;Bihar&#8217;,&#8217;bhagalpur&#8217;:&#8217;Bihar&#8217;,&#8217;muzaffarpur&#8217;:&#8217;Bihar&#8217;,&#8217;purnea&#8217;:&#8217;Bihar&#8217;,&#8217;saran&#8217;:&#8217;Bihar&#8217;,  &#8216;ranchi&#8217;:&#8217;Jharkhand&#8217;,&#8217;jamshedpur&#8217;:&#8217;Jharkhand&#8217;,&#8217;dhanbad&#8217;:&#8217;Jharkhand&#8217;,  &#8216;bhubaneswar&#8217;:&#8217;Odisha&#8217;,&#8217;cuttack&#8217;:&#8217;Odisha&#8217;,&#8217;rourkela&#8217;:&#8217;Odisha&#8217;,  &#8216;thiruvananthapuram&#8217;:&#8217;Kerala&#8217;,&#8217;kochi&#8217;:&#8217;Kerala&#8217;,&#8217;kozhikode&#8217;:&#8217;Kerala&#8217;,&#8217;thrissur&#8217;:&#8217;Kerala&#8217;,&#8217;kollam&#8217;:&#8217;Kerala&#8217;,&#8217;kottayam&#8217;:&#8217;Kerala&#8217;,&#8217;thalayolaparambu&#8217;:&#8217;Kerala&#8217;,&#8217;vaikom&#8217;:&#8217;Kerala&#8217;,&#8217;ernakulam&#8217;:&#8217;Kerala&#8217;,  &#8216;chandigarh&#8217;:&#8217;Punjab&#8217;,&#8217;ludhiana&#8217;:&#8217;Punjab&#8217;,&#8217;amritsar&#8217;:&#8217;Punjab&#8217;,&#8217;jalandhar&#8217;:&#8217;Punjab&#8217;,&#8217;patiala&#8217;:&#8217;Punjab&#8217;,&#8217;rupnagar&#8217;:&#8217;Punjab&#8217;,  &#8216;gurugram&#8217;:&#8217;Haryana&#8217;,&#8217;faridabad&#8217;:&#8217;Haryana&#8217;,  &#8216;dehradun&#8217;:&#8217;Uttarakhand&#8217;,&#8217;haridwar&#8217;:&#8217;Uttarakhand&#8217;,&#8217;roorkee&#8217;:&#8217;Uttarakhand&#8217;,  &#8216;shimla&#8217;:&#8217;Himachal Pradesh&#8217;,&#8217;mandi&#8217;:&#8217;Himachal Pradesh&#8217;,&#8217;dharamshala&#8217;:&#8217;Himachal Pradesh&#8217;,  &#8216;guwahati&#8217;:&#8217;Assam&#8217;,&#8217;dibrugarh&#8217;:&#8217;Assam&#8217;,  &#8216;srinagar&#8217;:&#8217;Jammu &amp; Kashmir&#8217;,&#8217;jammu&#8217;:&#8217;Jammu &amp; Kashmir&#8217;,  &#8216;panaji&#8217;:&#8217;Goa&#8217;,  &#8216;port blair&#8217;:&#8217;Andaman &amp; Nicobar&#8217;,  &#8216;visakhapatnam&#8217;:&#8217;Andhra Pradesh&#8217;,&#8217;vijayawada&#8217;:&#8217;Andhra Pradesh&#8217;,&#8217;guntur&#8217;:&#8217;Andhra Pradesh&#8217;,&#8217;tirupati&#8217;:&#8217;Andhra Pradesh&#8217;,  &#8216;raipur&#8217;:&#8217;Chhattisgarh&#8217;,};\/\/ \u2500\u2500 Default embedded data \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500const DEFAULT_DATA = [];\/\/ \u2500\u2500 State \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500let ALL = DEFAULT_DATA.slice();let DM = {}, DATES = [];\/\/ \u2500\u2500 Helper functions \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500function normCity(raw){  if(!raw) return &#8221;;  const sl = raw.toLowerCase().trim();  if(ALIASES[sl]) return ALIASES[sl];  return raw.trim().split(&#8216; &#8216;).map(w=&gt;w.charAt(0).toUpperCase()+w.slice(1).toLowerCase()).join(&#8216; &#8216;);}function inferState(city){  return STATE_MAP[city.toLowerCase()] || &#8221;;}function cap(s){  return s ? s.split(&#8216; &#8216;).map(w=&gt;w.charAt(0).toUpperCase()+w.slice(1)).join(&#8216; &#8216;) : &#8221;;}function parseDate(val){  if(!val) return &#8221;;  const s = String(val).trim();  \/\/ YYYY-MM-DD or YYYY\/MM\/DD (with optional time): &#8220;2026-05-07 20:51:03&#8221;  const m1 = s.match(\/^(d{4})[\/-](d{2})[\/-](d{2})\/);  if(m1) return m1[1]+&#8217;-&#8216;+m1[2]+&#8217;-&#8216;+m1[3];  \/\/ M\/D\/YY or M\/D\/YYYY: &#8220;5\/7\/26&#8221; or &#8220;5\/7\/2026&#8243; \u2014 browser XLSX.js outputs this  const m2 = s.match(\/^(d{1,2})[\/-](d{1,2})[\/-](d{2,4})\/);  if(m2){    let yr = m2[3];    if(yr.length===2) yr = (parseInt(yr)&gt;=50?&#8217;19&#8217;:&#8217;20&#8217;)+yr;    return yr+&#8217;-&#8216;+m2[1].padStart(2,&#8217;0&#8242;)+&#8217;-&#8216;+m2[2].padStart(2,&#8217;0&#8217;);  }  return &#8221;;}function findCol(keys, patterns){  for(const p of patterns){    \/\/ exact match first (case-insensitive)    let k = keys.find(k=&gt;k.toLowerCase()===p.toLowerCase());    if(k) return k;    \/\/ then partial match    k = keys.find(k=&gt;k.toLowerCase().includes(p.toLowerCase()));    if(k) return k;  }  return null;}function showErr(msg){  const b = document.getElementById(&#8216;err-box&#8217;);  b.textContent = &#8216;<img decoding=\"async\" role=\"img\" alt=\"\u26a0\" src=\"https:\/\/s.w.org\/images\/core\/emoji\/17.0.2\/svg\/26a0.svg\"> &#8216; + msg;  b.style.display = &#8216;block&#8217;;}\/\/ \u2500\u2500 Init \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500const now = new Date();const todayStr = now.toISOString().slice(0,10);document.getElementById(&#8216;today-chip&#8217;).textContent = todayStr;document.getElementById(&#8216;sub-lbl&#8217;).textContent = now.toLocaleDateString(&#8216;en-IN&#8217;,{weekday:&#8217;long&#8217;,year:&#8217;numeric&#8217;,month:&#8217;long&#8217;,day:&#8217;numeric&#8217;});const ustrip = document.getElementById(&#8216;ustrip&#8217;);ustrip.addEventListener(&#8216;dragover&#8217;, e=&gt;{e.preventDefault();ustrip.style.borderColor=&#8217;var(&#8211;acc)&#8217;;});ustrip.addEventListener(&#8216;dragleave&#8217;, ()=&gt;ustrip.style.borderColor=&#8221;);ustrip.addEventListener(&#8216;drop&#8217;, e=&gt;{e.preventDefault();ustrip.style.borderColor=&#8221;;handleFile(e.dataTransfer.files[0]);});document.getElementById(&#8216;fi&#8217;).addEventListener(&#8216;change&#8217;, e=&gt;handleFile(e.target.files[0]));showEmptyState();\/\/ \u2500\u2500 File Upload \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500function handleFile(file){  if(!file) return;  document.getElementById(&#8216;err-box&#8217;).style.display=&#8217;none&#8217;;  const ext = file.name.split(&#8216;.&#8217;).pop().toLowerCase();  const reader = new FileReader();  reader.onload = e =&gt; {    try{      let rows;      if(ext===&#8217;csv&#8217;){        const wb = XLSX.read(e.target.result,{type:&#8217;string&#8217;,raw:false,cellDates:true});        rows = XLSX.utils.sheet_to_json(wb.Sheets[wb.SheetNames[0]],{raw:false,defval:&#8221;});      } else {        const wb = XLSX.read(new Uint8Array(e.target.result),{type:&#8217;array&#8217;,cellDates:true});        rows = XLSX.utils.sheet_to_json(wb.Sheets[wb.SheetNames[0]],{raw:false,defval:&#8221;});      }      processRows(rows, file.name);    } catch(err){ showErr(&#8216;Could not parse file: &#8216;+err.message); }  };  if(ext===&#8217;csv&#8217;) reader.readAsText(file);  else reader.readAsArrayBuffer(file);}function processRows(rows, fname){  if(!rows.length){ showErr(&#8216;File is empty.&#8217;); return; }  const keys = Object.keys(rows[0]);  \/\/ \u2500\u2500 Column detection \u2014 supports your exact sheet format \u2500\u2500\u2500\u2500\u2500\u2500  \/\/ Date: &#8220;Created (IST)&#8221;, &#8220;Created&#8221;, &#8220;Date&#8221;, &#8220;Timestamp&#8221;, etc.  const COL_DATE    = findCol(keys, [&#8216;Created (IST)&#8217;, &#8216;Created&#8217;, &#8216;Date&#8217;, &#8216;Timestamp&#8217;, &#8216;Time&#8217;, &#8216;created&#8217;, &#8216;date&#8217;]);  \/\/ Name  const COL_NAME    = findCol(keys, [&#8216;Name&#8217;, &#8216;Full Name&#8217;, &#8216;Fullname&#8217;, &#8216;name&#8217;]);  \/\/ City  const COL_CITY    = findCol(keys, [&#8216;City&#8217;, &#8216;Location&#8217;, &#8216;Town&#8217;, &#8216;District&#8217;, &#8216;city&#8217;]);  \/\/ State (may not exist in sheet \u2014 will infer from city)  const COL_STATE   = findCol(keys, [&#8216;State&#8217;, &#8216;Province&#8217;, &#8216;Region&#8217;, &#8216;state&#8217;]);  \/\/ Used Referral Code  const COL_USEDREF = findCol(keys, [&#8216;Used Referral Code&#8217;, &#8216;Used Referral&#8217;, &#8216;Used Ref&#8217;, &#8216;Referral Code Used&#8217;, &#8216;used referral&#8217;]);  \/\/ Own Referral Code  const COL_MYREF   = findCol(keys, [&#8216;Referral Code&#8217;, &#8216;My Referral&#8217;, &#8216;Ref Code&#8217;, &#8216;referral code&#8217;]);  \/\/ Volunteer  const COL_VOL     = findCol(keys, [&#8216;Volunteer&#8217;, &#8216;volunteer&#8217;]);  if(!COL_DATE){    showErr(&#8216;No date column found. Expected &#8220;Created (IST)&#8221;, &#8220;Created&#8221;, or &#8220;Date&#8221; column. Found: &#8216; + keys.join(&#8216;, &#8216;));    return;  }  const parsed = rows.map(r=&gt;{    const cityRaw = COL_CITY ? String(r[COL_CITY]||&#8221;).trim() : &#8221;;    const c = normCity(cityRaw);    const sFromSheet = COL_STATE ? String(r[COL_STATE]||&#8221;).trim() : &#8221;;    const s = sFromSheet &amp;&amp; sFromSheet !== &#8216;-&#8216; ? sFromSheet : inferState(c);    const used = COL_USEDREF ? String(r[COL_USEDREF]||&#8221;).trim() : &#8221;;    const volRaw = COL_VOL ? String(r[COL_VOL]||&#8221;).trim().toLowerCase() : &#8221;;    return {      n: COL_NAME ? String(r[COL_NAME]||&#8221;).trim() : &#8221;,      c, s,      r: COL_MYREF ? String(r[COL_MYREF]||&#8221;).trim() : &#8221;,      u: (used===&#8217;-&#8216; || used===&#8221;) ? &#8221; : used,      d: parseDate(r[COL_DATE]),      v: (volRaw===&#8217;yes&#8217; || volRaw===&#8217;true&#8217; || volRaw===&#8217;1&#8242;) ? 1 : 0,    };  }).filter(r=&gt;r.d);  if(!parsed.length){    showErr(&#8216;No valid date rows found. Date column &#8220;&#8216; + COL_DATE + &#8216;&#8221; values look like: &#8216; + rows.slice(0,3).map(r=&gt;String(r[COL_DATE]||&#8221;)).join(&#8216; | &#8216;));    return;  }  document.getElementById(&#8216;fname&#8217;).textContent = fname;  document.getElementById(&#8216;tbdg&#8217;).textContent = parsed.length+&#8217; records&#8217;;  document.getElementById(&#8216;fbar&#8217;).style.display=&#8217;flex&#8217;;  document.getElementById(&#8216;ustrip-main&#8217;).innerHTML = &#8216;&lt;strong&gt;&#8217;+fname+'&lt;\/strong&gt; \u2014 uploaded \u2713&#8217;;  buildDash(parsed, fname);}function resetToDefault(){  document.getElementById(&#8216;fbar&#8217;).style.display=&#8217;none&#8217;;  document.getElementById(&#8216;ustrip-main&#8217;).innerHTML='&lt;strong&gt;Upload new CSV \/ Excel&lt;\/strong&gt; to update data&#8217;;  document.getElementById(&#8216;fi&#8217;).value=&#8221;;  document.getElementById(&#8216;err-box&#8217;).style.display=&#8217;none&#8217;;  showEmptyState();}\/\/ \u2500\u2500 Build dashboard \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500function showEmptyState(){  ALL = [];  DM = {};  DATES = [];  document.getElementById(&#8216;dsel&#8217;).innerHTML = &#8216;&lt;option value=&#8221;&#8221;&gt;\u2014 Upload a sheet \u2014&lt;\/option&gt;&#8217;;  document.getElementById(&#8216;mrow&#8217;).innerHTML = &#8216;&lt;div style=&#8221;grid-column:1\/-1;text-align:center;padding:2.5rem&#8221;&gt;&lt;div&gt;No data loaded&lt;\/div&gt;&lt;div style=&#8221;font-size:13px;color:var(&#8211;mut);margin-top:8px&#8221;&gt;Upload your CSV \/ Excel sheet above to see the dashboard&lt;\/div&gt;&lt;\/div&gt;&#8217;;  document.getElementById(&#8216;outbox&#8217;).innerHTML = &#8216;&lt;span style=&#8221;color:var(&#8211;mut)&#8221;&gt;Summary will appear here after upload&#8230;&lt;\/span&gt;&#8217;;  document.getElementById(&#8216;top-c&#8217;).innerHTML = &#8216;&lt;li style=&#8221;color:var(&#8211;mut);font-size:13px;padding:12px 0&#8243;&gt;Upload data to see cities&lt;\/li&gt;&#8217;;  document.getElementById(&#8216;top-s&#8217;).innerHTML = &#8216;&lt;li style=&#8221;color:var(&#8211;mut);font-size:13px;padding:12px 0&#8243;&gt;Upload data to see states&lt;\/li&gt;&#8217;;  document.getElementById(&#8216;top-r&#8217;).innerHTML = &#8216;&lt;li style=&#8221;color:var(&#8211;mut);font-size:13px;padding:12px 0&#8243;&gt;Upload data to see referrers&lt;\/li&gt;&#8217;;  document.getElementById(&#8216;tbl-title&#8217;).textContent = &#8216;Pledges&#8217;;  document.getElementById(&#8216;tbl-badge&#8217;).textContent = &#8216;0 records&#8217;;  document.getElementById(&#8216;thead&#8217;).innerHTML = &#8221;;  document.getElementById(&#8216;tbody&#8217;).innerHTML = &#8221;;  document.getElementById(&#8217;emp&#8217;).style.display = &#8216;block&#8217;;  document.getElementById(&#8217;emp&#8217;).textContent = &#8216;Upload a sheet to view records.&#8217;;}function buildDash(data, fname){  ALL = data;  DM = {};  ALL.forEach(r=&gt;{ if(!DM[r.d]) DM[r.d]=[]; DM[r.d].push(r); });  DATES = Object.keys(DM).sort().reverse();  const sel = document.getElementById(&#8216;dsel&#8217;);  sel.innerHTML = &#8221;;  DATES.forEach(d=&gt;{    const o = document.createElement(&#8216;option&#8217;);    o.value = d;    o.textContent = d===todayStr ? d+&#8217; (Today)&#8217; : d;    sel.appendChild(o);  });  if(DATES.length) sel.value = DATES[0];  render();}\/\/ \u2500\u2500 Top helpers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500function topN(arr, keyFn, n){  const m = {};  arr.forEach(r=&gt;{ const v=keyFn(r); if(v) m[v]=(m[v]||0)+1; });  return Object.entries(m).sort((a,b)=&gt;b[1]-a[1]).slice(0,n);}function topRefs(n){  const m = {};  ALL.forEach(r=&gt;{    if(!r.u) return;    if(!m[r.u]) m[r.u]={code:r.u,count:0,name:&#8221;};    m[r.u].count++;  });  ALL.forEach(r=&gt;{ if(r.r &amp;&amp; m[r.r] &amp;&amp; !m[r.r].name) m[r.r].name=r.n; });  return Object.values(m).sort((a,b)=&gt;b.count-a.count).slice(0,n);}function mkList(entries, getName, getCount, getSub){  if(!entries.length) return &#8216;&lt;li style=&#8221;color:var(&#8211;mut);font-size:13px;padding:12px 0&#8243;&gt;No data&lt;\/li&gt;&#8217;;  const max = getCount(entries[0]) || 1;  return entries.map((e,i)=&gt;`    &lt;li&gt;      &lt;span&gt;${i+1}&lt;\/span&gt;      &lt;div&gt;        &lt;div&gt;${getName(e)||&#8217;\u2014&#8217;}&lt;\/div&gt;        ${getSub&amp;&amp;getSub(e)?`&lt;div&gt;${getSub(e)}&lt;\/div&gt;`:&#8221;}      &lt;\/div&gt;      &lt;div&gt;&lt;div style=&#8221;width:${Math.round(getCount(e)\/max*100)}%&#8221;&gt;&lt;\/div&gt;&lt;\/div&gt;      &lt;span&gt;${getCount(e)}&lt;\/span&gt;    &lt;\/li&gt;`).join(&#8221;);}\/\/ \u2500\u2500 Render \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500let _outRaw = &#8221;;function render(){  const d = document.getElementById(&#8216;dsel&#8217;).value;  const SD = DM[d] || [];  const total = ALL.length, cnt = SD.length;  const pct = total&gt;0 ? ((cnt\/total)*100).toFixed(1) : &#8216;0.0&#8217;;  const cm={}, sm={};  SD.forEach(r=&gt;{ if(r.c) cm[r.c]=(cm[r.c]||0)+1; if(r.s) sm[r.s]=(sm[r.s]||0)+1; });  const lc = Object.entries(cm).sort((a,b)=&gt;b[1]-a[1])[0];  const ls = Object.entries(sm).sort((a,b)=&gt;b[1]-a[1])[0];  document.getElementById(&#8216;mrow&#8217;).innerHTML=`    &lt;div&gt;      &lt;div&gt;Pledges \u2014 Selected Date&lt;\/div&gt;      &lt;div&gt;${cnt}&lt;\/div&gt;      &lt;div&gt;${pct}% of total&lt;\/div&gt;    &lt;\/div&gt;    &lt;div&gt;      &lt;div&gt;Total Pledges&lt;\/div&gt;      &lt;div&gt;${total}&lt;\/div&gt;      &lt;div&gt;All dates combined&lt;\/div&gt;    &lt;\/div&gt;    &lt;div&gt;      &lt;div&gt;Leading City (Selected)&lt;\/div&gt;      &lt;div&gt;${lc?cap(lc[0]):&#8217;\u2014&#8217;}&lt;\/div&gt;      &lt;div&gt;${lc?lc[1]+&#8217; pledges&#8217;:&#8217;No data&#8217;}&lt;\/div&gt;    &lt;\/div&gt;    &lt;div&gt;      &lt;div&gt;Leading State (Selected)&lt;\/div&gt;      &lt;div&gt;${ls?ls[0]:&#8217;\u2014&#8217;}&lt;\/div&gt;      &lt;div&gt;${ls?ls[1]+&#8217; pledges&#8217;:&#8217;No data&#8217;}&lt;\/div&gt;    &lt;\/div&gt;`;  const c3 = topN(ALL, r=&gt;r.c, 3);  const s3 = topN(ALL, r=&gt;r.s, 3);  const r3 = topRefs(3);  document.getElementById(&#8216;top-c&#8217;).innerHTML = mkList(c3, e=&gt;cap(e[0]), e=&gt;e[1], e=&gt;inferState(e[0])||&#8221;);  document.getElementById(&#8216;top-s&#8217;).innerHTML = mkList(s3, e=&gt;e[0], e=&gt;e[1], null);  document.getElementById(&#8216;top-r&#8217;).innerHTML = r3.length    ? mkList(r3, e=&gt;e.name||e.code, e=&gt;e.count, e=&gt;e.name?&#8217;Code: &#8216;+e.code:null)    : &#8216;&lt;li style=&#8221;color:var(&#8211;mut);font-size:13px;padding:12px 0&#8243;&gt;No referral data&lt;\/li&gt;&#8217;;  const lines = [    `Portal Daily Tracker \u2014 ${d}`, &#8220;,    `No of pledges registered today: ${cnt}`,    `Total pledges registered: ${total}`, &#8220;,    `Top 3 Cities:`,    &#8230;c3.map((e,i)=&gt;`${i+1}. ${cap(e[0])} &#8211; ${e[1]}`), &#8220;,    `Top 3 States:`,    &#8230;s3.map((e,i)=&gt;`${i+1}. ${e[0]} &#8211; ${e[1]}`), &#8220;,    `Top 3 Referrers:`,    &#8230;r3.map((e,i)=&gt;`${i+1}. ${e.name||e.code} &#8211; ${e.count}`),  ];  _outRaw = lines.join(&#8216;n&#8217;);  document.getElementById(&#8216;outbox&#8217;).innerHTML = lines.map((l,i)=&gt;{    if(i===0) return `&lt;span&gt;${l}&lt;\/span&gt;`;    if(l.match(\/^(No of|Total|Top 3)\/)) return `&lt;span&gt;${l}&lt;\/span&gt;`;    if(l.match(\/^d.\/)) return `&lt;span&gt;${l}&lt;\/span&gt;`;    if(l.match(\/:s*d+$\/)) return l.replace(\/:s*(d+)$\/,&#8217;: &lt;span&gt;$1&lt;\/span&gt;&#8217;);    return l||&#8217; &#8216;;  }).join(&#8216;n&#8217;);  const tblTitle = d===todayStr ? &#8220;Today&#8217;s Pledges&#8221; : d+&#8217; Pledges&#8217;;  document.getElementById(&#8216;tbl-title&#8217;).textContent = tblTitle;  document.getElementById(&#8216;tbl-badge&#8217;).textContent = cnt+&#8217; records&#8217;;  const tbody = document.getElementById(&#8216;tbody&#8217;);  const thead = document.getElementById(&#8216;thead&#8217;);  const emp = document.getElementById(&#8217;emp&#8217;);  if(!SD.length){ tbody.innerHTML=&#8221;; thead.innerHTML=&#8221;; emp.style.display=&#8217;block&#8217;; return; }  emp.style.display = &#8216;none&#8217;;  thead.innerHTML = `&lt;tr&gt;&lt;th&gt;#&lt;\/th&gt;&lt;th&gt;Name&lt;\/th&gt;&lt;th&gt;City&lt;\/th&gt;&lt;th&gt;State&lt;\/th&gt;&lt;th&gt;Ref Code&lt;\/th&gt;&lt;th&gt;Used Ref&lt;\/th&gt;&lt;th&gt;Volunteer&lt;\/th&gt;&lt;\/tr&gt;`;  tbody.innerHTML = SD.map((r,i)=&gt;`    &lt;tr&gt;      &lt;td&gt;${i+1}&lt;\/td&gt;      &lt;td style=&#8221;color:var(&#8211;txt)&#8221;&gt;${r.n||&#8217;\u2014&#8217;}&lt;\/td&gt;      &lt;td&gt;${cap(r.c)||&#8217;\u2014&#8217;}&lt;\/td&gt;      &lt;td&gt;${r.s||&#8217;\u2014&#8217;}&lt;\/td&gt;      &lt;td&gt;&lt;span&gt;${r.r||&#8217;\u2014&#8217;}&lt;\/span&gt;&lt;\/td&gt;      &lt;td&gt;${r.u?`&lt;span&gt;${r.u}&lt;\/span&gt;`:&#8217;\u2014&#8217;}&lt;\/td&gt;      &lt;td&gt;${r.v?'&lt;span&gt;Yes&lt;\/span&gt;&#8217;:&#8217;No&#8217;}&lt;\/td&gt;    &lt;\/tr&gt;`).join(&#8221;);}function copyOut(){  if(!_outRaw) return;  navigator.clipboard.writeText(_outRaw).then(()=&gt;{    const b = document.getElementById(&#8216;cbtn&#8217;);    b.textContent = &#8216;\u2713 Copied!&#8217;; b.classList.add(&#8216;done&#8217;);    setTimeout(()=&gt;{ b.textContent=&#8217;\u2398 Copy Summary&#8217;; b.classList.remove(&#8216;done&#8217;); }, 2000);  });}[\/tcb-script]<\/p>\n<h2 style=\"\">\u200b<br \/><\/h2>\n","protected":false},"excerpt":{"rendered":"<p>Portal Daily Tracker[tcb-script src=&#8221;https:\/\/cdnjs.cloudflare.com\/ajax\/libs\/xlsx\/0.18.5\/xlsx.full.min.js&#8221;][\/tcb-script] Portal Daily Tracker Upload new CSV \/ Excel to update data Columns: Name \u00b7 City \u00b7 Used Referral Code \u00b7 Referral Code \u00b7 Created (IST) Browse DATE: \u2398 Copy Summary Top 3 Cities \u2014 All Time Top 3 States \u2014 All Time Top 3 Referrers \u2014 All Time Pledges No records [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":"","tve_updated_post":"<div class=\"thrv_wrapper thrv_contentbox_shortcode thrv-content-box tve-elem-default-pad\">\n\t<div class=\"tve-content-box-background\"><\/div>\n\t<div class=\"tve-cb\"><\/div>\n<\/div><div class=\"thrv_wrapper thrv_contentbox_shortcode thrv-content-box tve-elem-default-pad\" style=\"\" data-css=\"tve-u-19e061bbe7b\" data-ct-name=\"Styled Box 05\" data-ct=\"stylebox-76191\" data-element-name=\"Styled Box\" data-form-settings=\"__TCB_FORM__{&quot;form_identifier&quot;:&quot;test-portal-tracker-form-oy7h0x&quot;}__TCB_FORM__\">\n\t<div class=\"tve-content-box-background\" data-css=\"tve-u-19e061bbe7c\" style=\"\"><\/div>\n\t<div class=\"tve-cb\" style=\"\" data-css=\"tve-u-19e061bbe7d\"><div class=\"thrv_wrapper thrv_custom_html_shortcode\">\n\n\n<meta charset=\"UTF-8\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n<title>Portal Daily Tracker<\/title>\n<link href=\"https:\/\/fonts.googleapis.com\/css2?family=Syne:wght@400;600;700;800&amp;family=DM+Mono:wght@400;500&amp;family=DM+Sans:wght@300;400;500&amp;display=swap\" rel=\"stylesheet\">\n<code class=\"tve_js_placeholder\">[tcb-script src=\"https:\/\/cdnjs.cloudflare.com\/ajax\/libs\/xlsx\/0.18.5\/xlsx.full.min.js\"][\/tcb-script]<\/code>\n<style>\n:root{\n  --bg:#0C0E13;--surf:#13161E;--surf2:#1A1E29;--bdr:#232736;\n  --acc:#4EFFC5;--acc2:#7B61FF;--gold:#FFD166;--red:#FF6B6B;\n  --txt:#F0F2FF;--mut:#6B7280;--mut2:#9CA3AF;\n}\n*{box-sizing:border-box;margin:0;padding:0;}\nbody{font-family:'DM Sans',sans-serif;background:var(--bg);color:var(--txt);min-height:100vh;overflow-x:hidden;}\nbody::before{content:'';position:fixed;inset:0;background-image:linear-gradient(rgba(78,255,197,.03) 1px,transparent 1px),linear-gradient(90deg,rgba(78,255,197,.03) 1px,transparent 1px);background-size:40px 40px;pointer-events:none;z-index:0;}\n.wrap{max-width:1020px;margin:0 auto;padding:2rem 1.25rem 4rem;position:relative;z-index:1;}\n.hdr{display:flex;align-items:flex-start;justify-content:space-between;margin-bottom:1.75rem;flex-wrap:wrap;gap:12px;}\n.hdr h1{font-family:'Syne',sans-serif;font-size:26px;font-weight:800;letter-spacing:-.5px;background:linear-gradient(135deg,var(--txt) 40%,var(--acc));-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text;}\n.hdr-sub{font-size:12px;color:var(--mut);margin-top:3px;font-family:'DM Mono',monospace;}\n.date-chip{font-family:'DM Mono',monospace;font-size:12px;padding:5px 14px;border-radius:100px;background:var(--surf2);border:1px solid var(--bdr);color:var(--mut2);white-space:nowrap;}\n.ustrip{display:flex;align-items:center;gap:10px;background:var(--surf);border:1px solid var(--bdr);border-radius:14px;padding:.75rem 1.1rem;margin-bottom:1.5rem;flex-wrap:wrap;cursor:pointer;transition:border-color .15s;}\n.ustrip:hover{border-color:var(--acc);}\n.ustrip input{display:none;}\n.ustrip-icon{font-size:18px;}\n.ustrip-text{flex:1;min-width:0;}\n.ustrip-text p{font-size:13px;color:var(--mut2);}\n.ustrip-text p strong{color:var(--txt);}\n.ustrip-text small{font-size:11px;color:var(--mut);font-family:'DM Mono',monospace;}\n.ustrip-btn{font-size:12px;padding:6px 14px;border-radius:8px;border:1px solid var(--acc);background:rgba(78,255,197,.08);color:var(--acc);cursor:pointer;font-family:'DM Mono',monospace;white-space:nowrap;transition:background .15s;}\n.ustrip-btn:hover{background:rgba(78,255,197,.18);}\n.fbar{display:flex;align-items:center;gap:8px;margin-bottom:.5rem;flex-wrap:wrap;}\n.fname{font-family:'DM Mono',monospace;font-size:12px;color:var(--mut2);}\n.bdg{font-size:11px;padding:3px 10px;border-radius:100px;background:rgba(78,255,197,.1);color:var(--acc);font-family:'DM Mono',monospace;font-weight:500;}\n.bdg.red{background:rgba(255,107,107,.1);color:var(--red);}\n.err-box{background:rgba(255,107,107,.08);border:1px solid rgba(255,107,107,.3);border-radius:10px;padding:.65rem 1rem;font-size:13px;color:var(--red);margin-bottom:1rem;display:none;}\n.top-bar{display:flex;align-items:center;gap:10px;margin-bottom:1.5rem;flex-wrap:wrap;}\n.top-bar label{font-size:12px;color:var(--mut);font-family:'DM Mono',monospace;}\nselect{font-size:13px;padding:7px 14px;border-radius:10px;border:1px solid var(--bdr);background:var(--surf2);color:var(--txt);cursor:pointer;font-family:'DM Mono',monospace;outline:none;}\nselect:focus{border-color:var(--acc);}\n.copy-btn{margin-left:auto;font-size:12px;padding:7px 16px;border-radius:10px;border:1px solid var(--acc);background:rgba(78,255,197,.08);color:var(--acc);cursor:pointer;font-family:'DM Mono',monospace;transition:all .15s;display:flex;align-items:center;gap:6px;}\n.copy-btn:hover{background:rgba(78,255,197,.18);}\n.copy-btn.done{background:rgba(78,255,197,.22);}\n.mrow{display:grid;grid-template-columns:repeat(auto-fit,minmax(160px,1fr));gap:12px;margin-bottom:1.5rem;}\n.mc{background:var(--surf);border:1px solid var(--bdr);border-radius:16px;padding:1.1rem 1.2rem;position:relative;overflow:hidden;transition:transform .15s,border-color .15s;}\n.mc:hover{transform:translateY(-2px);border-color:#2e3347;}\n.mc.hi{border-color:rgba(78,255,197,.25);}\n.mc.hi::before{content:'';position:absolute;top:0;left:0;right:0;height:2px;background:linear-gradient(90deg,transparent,var(--acc),transparent);}\n.ml{font-size:10px;text-transform:uppercase;letter-spacing:.1em;color:var(--mut);margin-bottom:8px;font-weight:500;}\n.mv{font-family:'Syne',sans-serif;font-size:32px;font-weight:800;line-height:1;color:var(--acc);}\n.mc:not(.hi) .mv{color:var(--txt);}\n.ms{font-size:11px;color:var(--mut);margin-top:5px;font-family:'DM Mono',monospace;}\n.mv-sm{font-family:'Syne',sans-serif;font-size:18px;font-weight:700;line-height:1.2;color:var(--gold);text-transform:capitalize;}\n.mv-sm.purple{color:var(--acc2);}\n.out-box{background:var(--surf);border:1px solid var(--bdr);border-radius:16px;padding:1.25rem 1.5rem;margin-bottom:1.5rem;font-family:'DM Mono',monospace;font-size:13px;line-height:2;color:var(--mut2);white-space:pre-wrap;}\n.out-box .hl{color:var(--txt);font-weight:500;}\n.out-box .ac{color:var(--acc);}\n.out-box .gd{color:var(--gold);}\n.g3{display:grid;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));gap:12px;margin-bottom:1.5rem;}\n.card{background:var(--surf);border:1px solid var(--bdr);border-radius:16px;padding:1.1rem 1.2rem;}\n.card h3{font-size:10px;font-weight:600;text-transform:uppercase;letter-spacing:.12em;color:var(--mut);margin-bottom:1rem;}\n.tl{list-style:none;}\n.ti{display:flex;align-items:center;gap:10px;padding:9px 0;border-bottom:1px solid var(--bdr);}\n.ti:last-child{border-bottom:none;}\n.rk{width:24px;height:24px;border-radius:50%;display:flex;align-items:center;justify-content:center;font-size:11px;font-weight:700;flex-shrink:0;font-family:'DM Mono',monospace;}\n.r1{background:rgba(255,209,102,.15);color:var(--gold);border:1px solid rgba(255,209,102,.3);}\n.r2{background:rgba(160,160,180,.1);color:#9CA3AF;border:1px solid rgba(160,160,180,.2);}\n.r3{background:rgba(160,160,180,.06);color:#6B7280;border:1px solid rgba(160,160,180,.15);}\n.ii{flex:1;min-width:0;}\n.in{font-size:13px;font-weight:500;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;text-transform:capitalize;color:var(--txt);}\n.is{font-size:11px;color:var(--mut);margin-top:1px;font-family:'DM Mono',monospace;}\n.bt{width:44px;height:4px;border-radius:2px;background:var(--bdr);flex-shrink:0;overflow:hidden;}\n.bf{height:100%;border-radius:2px;background:var(--acc);}\n.ic{font-size:13px;font-weight:600;min-width:28px;text-align:right;color:var(--txt);font-family:'DM Mono',monospace;}\n.tc{background:var(--surf);border:1px solid var(--bdr);border-radius:16px;overflow:hidden;}\n.th{display:flex;align-items:center;justify-content:space-between;padding:.9rem 1.25rem;border-bottom:1px solid var(--bdr);flex-wrap:wrap;gap:8px;}\n.tt{font-family:'Syne',sans-serif;font-size:14px;font-weight:700;color:var(--txt);}\n.tw{overflow-x:auto;}\ntable{width:100%;border-collapse:collapse;font-size:13px;}\nthead th{text-align:left;padding:9px 14px;font-size:10px;font-weight:600;text-transform:uppercase;letter-spacing:.1em;color:var(--mut);border-bottom:1px solid var(--bdr);background:var(--surf2);font-family:'DM Mono',monospace;white-space:nowrap;}\ntbody td{padding:10px 14px;border-bottom:1px solid var(--bdr);color:var(--mut2);white-space:nowrap;}\ntbody tr:last-child td{border-bottom:none;}\ntbody tr:hover td{background:var(--surf2);color:var(--txt);}\n.num{color:var(--mut);font-family:'DM Mono',monospace;font-size:11px;}\n.rtag{font-family:'DM Mono',monospace;font-size:11px;padding:2px 8px;border-radius:6px;background:rgba(123,97,255,.1);color:#a78bfa;border:1px solid rgba(123,97,255,.2);}\n.rtag.green{background:rgba(78,255,197,.08);color:var(--acc);border-color:rgba(78,255,197,.2);}\n.vtag{font-size:10px;padding:1px 7px;border-radius:100px;background:rgba(78,255,197,.08);color:var(--acc);border:1px solid rgba(78,255,197,.2);font-family:'DM Mono',monospace;}\n.emp{text-align:center;padding:2.5rem;color:var(--mut);font-size:14px;}\n::-webkit-scrollbar{width:5px;height:5px;}\n::-webkit-scrollbar-track{background:var(--surf);}\n::-webkit-scrollbar-thumb{background:var(--bdr);border-radius:10px;}\n<\/style>\n\n\n<div class=\"wrap\">\n\n  <div class=\"hdr\">\n    <div>\n      <h1>Portal Daily Tracker<\/h1>\n      <div class=\"hdr-sub\" id=\"sub-lbl\"><\/div>\n    <\/div>\n    <span class=\"date-chip\" id=\"today-chip\"><\/span>\n  <\/div>\n\n  <div class=\"ustrip\" id=\"ustrip\" onclick=\"document.getElementById('fi').click()\">\n    <span class=\"ustrip-icon\"><img role=\"img\" class=\"emoji\" alt=\"\ud83d\udcc2\" src=\"https:\/\/s.w.org\/images\/core\/emoji\/17.0.2\/svg\/1f4c2.svg\"><\/span>\n    <div class=\"ustrip-text\">\n      <p id=\"ustrip-main\"><strong>Upload new CSV \/ Excel<\/strong> to update data<\/p>\n      <small id=\"ustrip-hint\">Columns: Name \u00b7 City \u00b7 Used Referral Code \u00b7 Referral Code \u00b7 Created (IST)<\/small>\n    <\/div>\n    <button class=\"ustrip-btn\" onclick=\"event.stopPropagation();document.getElementById('fi').click()\">Browse<\/button>\n    <input type=\"file\" id=\"fi\" accept=\".xlsx,.xls,.csv\">\n  <\/div>\n  <div class=\"err-box\" id=\"err-box\"><\/div>\n\n  <div class=\"fbar\" id=\"fbar\" style=\"display:none\">\n    <span><img role=\"img\" class=\"emoji\" alt=\"\ud83d\udcc1\" src=\"https:\/\/s.w.org\/images\/core\/emoji\/17.0.2\/svg\/1f4c1.svg\"><\/span>\n    <span class=\"fname\" id=\"fname\"><\/span>\n    <span class=\"bdg\" id=\"tbdg\"><\/span>\n    \n  <\/div>\n\n  <div class=\"top-bar\">\n    <label>DATE:<\/label>\n    <select id=\"dsel\" onchange=\"render()\"><\/select>\n    <button class=\"copy-btn\" id=\"cbtn\" onclick=\"copyOut()\">\u2398 Copy Summary<\/button>\n  <\/div>\n\n  <div class=\"mrow\" id=\"mrow\"><\/div>\n  <div class=\"out-box\" id=\"outbox\"><\/div>\n\n  <div class=\"g3\">\n    <div class=\"card\"><h3><img role=\"img\" class=\"emoji\" alt=\"\ud83c\udfd9\" src=\"https:\/\/s.w.org\/images\/core\/emoji\/17.0.2\/svg\/1f3d9.svg\"> Top 3 Cities \u2014 All Time<\/h3><ul class=\"tl\" id=\"top-c\"><\/ul><\/div>\n    <div class=\"card\"><h3><img role=\"img\" class=\"emoji\" alt=\"\ud83d\uddfa\" src=\"https:\/\/s.w.org\/images\/core\/emoji\/17.0.2\/svg\/1f5fa.svg\"> Top 3 States \u2014 All Time<\/h3><ul class=\"tl\" id=\"top-s\"><\/ul><\/div>\n    <div class=\"card\"><h3><img role=\"img\" class=\"emoji\" alt=\"\ud83d\udd17\" src=\"https:\/\/s.w.org\/images\/core\/emoji\/17.0.2\/svg\/1f517.svg\"> Top 3 Referrers \u2014 All Time<\/h3><ul class=\"tl\" id=\"top-r\"><\/ul><\/div>\n  <\/div>\n\n  <div class=\"tc\">\n    <div class=\"th\">\n      <span class=\"tt\" id=\"tbl-title\">Pledges<\/span>\n      <span class=\"bdg\" id=\"tbl-badge\"><\/span>\n    <\/div>\n    <div class=\"tw\">\n      <table><thead id=\"thead\"><\/thead><tbody id=\"tbody\"><\/tbody><\/table>\n      <div class=\"emp\" id=\"emp\" style=\"display:none\">No records for this date.<\/div>\n    <\/div>\n  <\/div>\n\n<\/div>\n\n<code class=\"tve_js_placeholder\">[tcb-script]\n\/\/ \u2500\u2500 ALL CONSTANTS DEFINED FIRST \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nconst ALIASES = {\n  'bengaluru':'Bangalore','banglore':'Bangalore','bangaluru':'Bangalore','benagluru':'Bangalore',\n  'bangalore rural':'Bangalore','bengaluru urban':'Bangalore','basavanapura':'Bangalore',\n  'new delhi':'Delhi','east delhi':'Delhi','north west delhi':'Delhi','shahdara':'Delhi','east patel nagar':'Delhi',\n  'khandws':'Khandwa',\n  'khargon':'Khargone','khargon mp':'Khargone','gogawa dist khargone':'Khargone',\n  'bhikangav':'Bhikangaon','bhingav':'Bhikangaon','bhikangoa':'Bhikangaon','bhikangoan':'Bhikangaon','bhinakngaon':'Bhikangaon',\n  'vaikom p o':'Vaikom','kottayam district':'Kottayam','kottayam vaikom':'Kottayam',\n  'thalayolapparambu':'Thalayolaparambu','thalayolaparamb':'Thalayolaparambu',\n  'prayagaraj':'Prayagraj','allahabad':'Prayagraj','prayagraj (up)':'Prayagraj',\n  'gurugram haryana':'Gurugram','gurgaon':'Gurugram',\n  'sringar':'Srinagar',\n  'kanpur nagar':'Kanpur',\n  'iit mandi':'Mandi','kamand':'Mandi',\n  'trivandrum':'Thiruvananthapuram',\n  'calicut':'Kozhikode','mangalore':'Mangaluru',\n  'trichy':'Tiruchirappalli','tirupur':'Tiruppur',\n  'shimogga':'Shimoga','simla':'Shimla',\n  'dehra dun':'Dehradun','narmadapuram':'Hoshangabad',\n  'rajkot gujarat':'Rajkot','bhopal mp':'Bhopal',\n  'greater noida west':'Noida','greater noida':'Noida',\n  'indoor':'Indore','purnia':'Purnea','mandsour':'Mandsaur','gorkhpur up':'Gorakhpur',\n  'port blair south andamans':'Port Blair','south andaman':'Port Blair',\n  'avadi thiruvallur':'Thiruvallur','kamrup metropolitan':'Guwahati','ashok nagar':'Ashoknagar',\n};\n\nconst STATE_MAP = {\n  'delhi':'Delhi','new delhi':'Delhi',\n  'mumbai':'Maharashtra','pune':'Maharashtra','nagpur':'Maharashtra','nashik':'Maharashtra','aurangabad':'Maharashtra','thane':'Maharashtra','navi mumbai':'Maharashtra','kolhapur':'Maharashtra','solapur':'Maharashtra',\n  'bengaluru':'Karnataka','bangalore':'Karnataka','mysuru':'Karnataka','mysore':'Karnataka','hubli':'Karnataka','mangaluru':'Karnataka','shimoga':'Karnataka','tumkur':'Karnataka',\n  'hyderabad':'Telangana','warangal':'Telangana','karimnagar':'Telangana','nizamabad':'Telangana',\n  'chennai':'Tamil Nadu','coimbatore':'Tamil Nadu','madurai':'Tamil Nadu','tiruchirappalli':'Tamil Nadu','tiruppur':'Tamil Nadu','salem':'Tamil Nadu','tirunelveli':'Tamil Nadu','vellore':'Tamil Nadu','erode':'Tamil Nadu','thiruvallur':'Tamil Nadu',\n  'kolkata':'West Bengal','howrah':'West Bengal','durgapur':'West Bengal','asansol':'West Bengal','siliguri':'West Bengal',\n  'ahmedabad':'Gujarat','surat':'Gujarat','vadodara':'Gujarat','rajkot':'Gujarat','bhavnagar':'Gujarat','jamnagar':'Gujarat','gandhinagar':'Gujarat',\n  'jaipur':'Rajasthan','jodhpur':'Rajasthan','udaipur':'Rajasthan','kota':'Rajasthan','bikaner':'Rajasthan','ajmer':'Rajasthan',\n  'lucknow':'Uttar Pradesh','kanpur':'Uttar Pradesh','agra':'Uttar Pradesh','varanasi':'Uttar Pradesh','prayagraj':'Uttar Pradesh','meerut':'Uttar Pradesh','ghaziabad':'Uttar Pradesh','noida':'Uttar Pradesh','gorakhpur':'Uttar Pradesh','gonda':'Uttar Pradesh','aligarh':'Uttar Pradesh','bareilly':'Uttar Pradesh','banda':'Uttar Pradesh',\n  'bhopal':'Madhya Pradesh','indore':'Madhya Pradesh','gwalior':'Madhya Pradesh','jabalpur':'Madhya Pradesh','ujjain':'Madhya Pradesh','khandwa':'Madhya Pradesh','khargone':'Madhya Pradesh','bhikangaon':'Madhya Pradesh','neemuch':'Madhya Pradesh','mandsaur':'Madhya Pradesh','hoshangabad':'Madhya Pradesh','sehore':'Madhya Pradesh','ashoknagar':'Madhya Pradesh',\n  'patna':'Bihar','gaya':'Bihar','bhagalpur':'Bihar','muzaffarpur':'Bihar','purnea':'Bihar','saran':'Bihar',\n  'ranchi':'Jharkhand','jamshedpur':'Jharkhand','dhanbad':'Jharkhand',\n  'bhubaneswar':'Odisha','cuttack':'Odisha','rourkela':'Odisha',\n  'thiruvananthapuram':'Kerala','kochi':'Kerala','kozhikode':'Kerala','thrissur':'Kerala','kollam':'Kerala','kottayam':'Kerala','thalayolaparambu':'Kerala','vaikom':'Kerala','ernakulam':'Kerala',\n  'chandigarh':'Punjab','ludhiana':'Punjab','amritsar':'Punjab','jalandhar':'Punjab','patiala':'Punjab','rupnagar':'Punjab',\n  'gurugram':'Haryana','faridabad':'Haryana',\n  'dehradun':'Uttarakhand','haridwar':'Uttarakhand','roorkee':'Uttarakhand',\n  'shimla':'Himachal Pradesh','mandi':'Himachal Pradesh','dharamshala':'Himachal Pradesh',\n  'guwahati':'Assam','dibrugarh':'Assam',\n  'srinagar':'Jammu &amp; Kashmir','jammu':'Jammu &amp; Kashmir',\n  'panaji':'Goa',\n  'port blair':'Andaman &amp; Nicobar',\n  'visakhapatnam':'Andhra Pradesh','vijayawada':'Andhra Pradesh','guntur':'Andhra Pradesh','tirupati':'Andhra Pradesh',\n  'raipur':'Chhattisgarh',\n};\n\n\/\/ \u2500\u2500 Default embedded data \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nconst DEFAULT_DATA = [];\n\n\/\/ \u2500\u2500 State \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nlet ALL = DEFAULT_DATA.slice();\nlet DM = {}, DATES = [];\n\n\/\/ \u2500\u2500 Helper functions \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nfunction normCity(raw){\n  if(!raw) return '';\n  const sl = raw.toLowerCase().trim();\n  if(ALIASES[sl]) return ALIASES[sl];\n  return raw.trim().split(' ').map(w=&gt;w.charAt(0).toUpperCase()+w.slice(1).toLowerCase()).join(' ');\n}\n\nfunction inferState(city){\n  return STATE_MAP[city.toLowerCase()] || '';\n}\n\nfunction cap(s){\n  return s ? s.split(' ').map(w=&gt;w.charAt(0).toUpperCase()+w.slice(1)).join(' ') : '';\n}\n\nfunction parseDate(val){\n  if(!val) return '';\n  const s = String(val).trim();\n  \/\/ YYYY-MM-DD or YYYY\/MM\/DD (with optional time): \"2026-05-07 20:51:03\"\n  const m1 = s.match(\/^(\\d{4})[\\\/-](\\d{2})[\\\/-](\\d{2})\/);\n  if(m1) return m1[1]+'-'+m1[2]+'-'+m1[3];\n  \/\/ M\/D\/YY or M\/D\/YYYY: \"5\/7\/26\" or \"5\/7\/2026\" \u2014 browser XLSX.js outputs this\n  const m2 = s.match(\/^(\\d{1,2})[\\\/-](\\d{1,2})[\\\/-](\\d{2,4})\/);\n  if(m2){\n    let yr = m2[3];\n    if(yr.length===2) yr = (parseInt(yr)&gt;=50?'19':'20')+yr;\n    return yr+'-'+m2[1].padStart(2,'0')+'-'+m2[2].padStart(2,'0');\n  }\n  return '';\n}\n\nfunction findCol(keys, patterns){\n  for(const p of patterns){\n    \/\/ exact match first (case-insensitive)\n    let k = keys.find(k=&gt;k.toLowerCase()===p.toLowerCase());\n    if(k) return k;\n    \/\/ then partial match\n    k = keys.find(k=&gt;k.toLowerCase().includes(p.toLowerCase()));\n    if(k) return k;\n  }\n  return null;\n}\n\nfunction showErr(msg){\n  const b = document.getElementById('err-box');\n  b.textContent = '<img role=\"img\" class=\"emoji\" alt=\"\u26a0\" src=\"https:\/\/s.w.org\/images\/core\/emoji\/17.0.2\/svg\/26a0.svg\"> ' + msg;\n  b.style.display = 'block';\n}\n\n\/\/ \u2500\u2500 Init \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nconst now = new Date();\nconst todayStr = now.toISOString().slice(0,10);\ndocument.getElementById('today-chip').textContent = todayStr;\ndocument.getElementById('sub-lbl').textContent = now.toLocaleDateString('en-IN',{weekday:'long',year:'numeric',month:'long',day:'numeric'});\n\nconst ustrip = document.getElementById('ustrip');\nustrip.addEventListener('dragover', e=&gt;{e.preventDefault();ustrip.style.borderColor='var(--acc)';});\nustrip.addEventListener('dragleave', ()=&gt;ustrip.style.borderColor='');\nustrip.addEventListener('drop', e=&gt;{e.preventDefault();ustrip.style.borderColor='';handleFile(e.dataTransfer.files[0]);});\ndocument.getElementById('fi').addEventListener('change', e=&gt;handleFile(e.target.files[0]));\n\nshowEmptyState();\n\n\/\/ \u2500\u2500 File Upload \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nfunction handleFile(file){\n  if(!file) return;\n  document.getElementById('err-box').style.display='none';\n  const ext = file.name.split('.').pop().toLowerCase();\n  const reader = new FileReader();\n  reader.onload = e =&gt; {\n    try{\n      let rows;\n      if(ext==='csv'){\n        const wb = XLSX.read(e.target.result,{type:'string',raw:false,cellDates:true});\n        rows = XLSX.utils.sheet_to_json(wb.Sheets[wb.SheetNames[0]],{raw:false,defval:''});\n      } else {\n        const wb = XLSX.read(new Uint8Array(e.target.result),{type:'array',cellDates:true});\n        rows = XLSX.utils.sheet_to_json(wb.Sheets[wb.SheetNames[0]],{raw:false,defval:''});\n      }\n      processRows(rows, file.name);\n    } catch(err){ showErr('Could not parse file: '+err.message); }\n  };\n  if(ext==='csv') reader.readAsText(file);\n  else reader.readAsArrayBuffer(file);\n}\n\nfunction processRows(rows, fname){\n  if(!rows.length){ showErr('File is empty.'); return; }\n  const keys = Object.keys(rows[0]);\n\n  \/\/ \u2500\u2500 Column detection \u2014 supports your exact sheet format \u2500\u2500\u2500\u2500\u2500\u2500\n  \/\/ Date: \"Created (IST)\", \"Created\", \"Date\", \"Timestamp\", etc.\n  const COL_DATE    = findCol(keys, ['Created (IST)', 'Created', 'Date', 'Timestamp', 'Time', 'created', 'date']);\n  \/\/ Name\n  const COL_NAME    = findCol(keys, ['Name', 'Full Name', 'Fullname', 'name']);\n  \/\/ City\n  const COL_CITY    = findCol(keys, ['City', 'Location', 'Town', 'District', 'city']);\n  \/\/ State (may not exist in sheet \u2014 will infer from city)\n  const COL_STATE   = findCol(keys, ['State', 'Province', 'Region', 'state']);\n  \/\/ Used Referral Code\n  const COL_USEDREF = findCol(keys, ['Used Referral Code', 'Used Referral', 'Used Ref', 'Referral Code Used', 'used referral']);\n  \/\/ Own Referral Code\n  const COL_MYREF   = findCol(keys, ['Referral Code', 'My Referral', 'Ref Code', 'referral code']);\n  \/\/ Volunteer\n  const COL_VOL     = findCol(keys, ['Volunteer', 'volunteer']);\n\n  if(!COL_DATE){\n    showErr('No date column found. Expected \"Created (IST)\", \"Created\", or \"Date\" column. Found: ' + keys.join(', '));\n    return;\n  }\n\n  const parsed = rows.map(r=&gt;{\n    const cityRaw = COL_CITY ? String(r[COL_CITY]||'').trim() : '';\n    const c = normCity(cityRaw);\n    const sFromSheet = COL_STATE ? String(r[COL_STATE]||'').trim() : '';\n    const s = sFromSheet &amp;&amp; sFromSheet !== '-' ? sFromSheet : inferState(c);\n    const used = COL_USEDREF ? String(r[COL_USEDREF]||'').trim() : '';\n    const volRaw = COL_VOL ? String(r[COL_VOL]||'').trim().toLowerCase() : '';\n    return {\n      n: COL_NAME ? String(r[COL_NAME]||'').trim() : '',\n      c, s,\n      r: COL_MYREF ? String(r[COL_MYREF]||'').trim() : '',\n      u: (used==='-' || used==='') ? '' : used,\n      d: parseDate(r[COL_DATE]),\n      v: (volRaw==='yes' || volRaw==='true' || volRaw==='1') ? 1 : 0,\n    };\n  }).filter(r=&gt;r.d);\n\n  if(!parsed.length){\n    showErr('No valid date rows found. Date column \"' + COL_DATE + '\" values look like: ' + rows.slice(0,3).map(r=&gt;String(r[COL_DATE]||'')).join(' | '));\n    return;\n  }\n\n  document.getElementById('fname').textContent = fname;\n  document.getElementById('tbdg').textContent = parsed.length+' records';\n  document.getElementById('fbar').style.display='flex';\n  document.getElementById('ustrip-main').innerHTML = '&lt;strong&gt;'+fname+'&lt;\/strong&gt; \u2014 uploaded \u2713';\n\n  buildDash(parsed, fname);\n}\n\nfunction resetToDefault(){\n  document.getElementById('fbar').style.display='none';\n  document.getElementById('ustrip-main').innerHTML='&lt;strong&gt;Upload new CSV \/ Excel&lt;\/strong&gt; to update data';\n  document.getElementById('fi').value='';\n  document.getElementById('err-box').style.display='none';\n  showEmptyState();\n}\n\n\/\/ \u2500\u2500 Build dashboard \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nfunction showEmptyState(){\n  ALL = [];\n  DM = {};\n  DATES = [];\n  document.getElementById('dsel').innerHTML = '&lt;option value=\"\"&gt;\u2014 Upload a sheet \u2014&lt;\/option&gt;';\n  document.getElementById('mrow').innerHTML = '&lt;div class=\"mc\" style=\"grid-column:1\/-1;text-align:center;padding:2.5rem\"&gt;&lt;div class=\"ml\"&gt;No data loaded&lt;\/div&gt;&lt;div style=\"font-size:13px;color:var(--mut);margin-top:8px\"&gt;Upload your CSV \/ Excel sheet above to see the dashboard&lt;\/div&gt;&lt;\/div&gt;';\n  document.getElementById('outbox').innerHTML = '&lt;span style=\"color:var(--mut)\"&gt;Summary will appear here after upload...&lt;\/span&gt;';\n  document.getElementById('top-c').innerHTML = '&lt;li class=\"ti\" style=\"color:var(--mut);font-size:13px;padding:12px 0\"&gt;Upload data to see cities&lt;\/li&gt;';\n  document.getElementById('top-s').innerHTML = '&lt;li class=\"ti\" style=\"color:var(--mut);font-size:13px;padding:12px 0\"&gt;Upload data to see states&lt;\/li&gt;';\n  document.getElementById('top-r').innerHTML = '&lt;li class=\"ti\" style=\"color:var(--mut);font-size:13px;padding:12px 0\"&gt;Upload data to see referrers&lt;\/li&gt;';\n  document.getElementById('tbl-title').textContent = 'Pledges';\n  document.getElementById('tbl-badge').textContent = '0 records';\n  document.getElementById('thead').innerHTML = '';\n  document.getElementById('tbody').innerHTML = '';\n  document.getElementById('emp').style.display = 'block';\n  document.getElementById('emp').textContent = 'Upload a sheet to view records.';\n}\n\nfunction buildDash(data, fname){\n  ALL = data;\n  DM = {};\n  ALL.forEach(r=&gt;{ if(!DM[r.d]) DM[r.d]=[]; DM[r.d].push(r); });\n  DATES = Object.keys(DM).sort().reverse();\n\n  const sel = document.getElementById('dsel');\n  sel.innerHTML = '';\n  DATES.forEach(d=&gt;{\n    const o = document.createElement('option');\n    o.value = d;\n    o.textContent = d===todayStr ? d+' (Today)' : d;\n    sel.appendChild(o);\n  });\n  if(DATES.length) sel.value = DATES[0];\n  render();\n}\n\n\/\/ \u2500\u2500 Top helpers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nfunction topN(arr, keyFn, n){\n  const m = {};\n  arr.forEach(r=&gt;{ const v=keyFn(r); if(v) m[v]=(m[v]||0)+1; });\n  return Object.entries(m).sort((a,b)=&gt;b[1]-a[1]).slice(0,n);\n}\n\nfunction topRefs(n){\n  const m = {};\n  ALL.forEach(r=&gt;{\n    if(!r.u) return;\n    if(!m[r.u]) m[r.u]={code:r.u,count:0,name:''};\n    m[r.u].count++;\n  });\n  ALL.forEach(r=&gt;{ if(r.r &amp;&amp; m[r.r] &amp;&amp; !m[r.r].name) m[r.r].name=r.n; });\n  return Object.values(m).sort((a,b)=&gt;b.count-a.count).slice(0,n);\n}\n\nfunction mkList(entries, getName, getCount, getSub){\n  if(!entries.length) return '&lt;li class=\"ti\" style=\"color:var(--mut);font-size:13px;padding:12px 0\"&gt;No data&lt;\/li&gt;';\n  const max = getCount(entries[0]) || 1;\n  return entries.map((e,i)=&gt;`\n    &lt;li class=\"ti\"&gt;\n      &lt;span class=\"rk r${i+1}\"&gt;${i+1}&lt;\/span&gt;\n      &lt;div class=\"ii\"&gt;\n        &lt;div class=\"in\"&gt;${getName(e)||'\u2014'}&lt;\/div&gt;\n        ${getSub&amp;&amp;getSub(e)?`&lt;div class=\"is\"&gt;${getSub(e)}&lt;\/div&gt;`:''}\n      &lt;\/div&gt;\n      &lt;div class=\"bt\"&gt;&lt;div class=\"bf\" style=\"width:${Math.round(getCount(e)\/max*100)}%\"&gt;&lt;\/div&gt;&lt;\/div&gt;\n      &lt;span class=\"ic\"&gt;${getCount(e)}&lt;\/span&gt;\n    &lt;\/li&gt;`).join('');\n}\n\n\/\/ \u2500\u2500 Render \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nlet _outRaw = '';\n\nfunction render(){\n  const d = document.getElementById('dsel').value;\n  const SD = DM[d] || [];\n  const total = ALL.length, cnt = SD.length;\n  const pct = total&gt;0 ? ((cnt\/total)*100).toFixed(1) : '0.0';\n\n  const cm={}, sm={};\n  SD.forEach(r=&gt;{ if(r.c) cm[r.c]=(cm[r.c]||0)+1; if(r.s) sm[r.s]=(sm[r.s]||0)+1; });\n  const lc = Object.entries(cm).sort((a,b)=&gt;b[1]-a[1])[0];\n  const ls = Object.entries(sm).sort((a,b)=&gt;b[1]-a[1])[0];\n\n  document.getElementById('mrow').innerHTML=`\n    &lt;div class=\"mc hi\"&gt;\n      &lt;div class=\"ml\"&gt;Pledges \u2014 Selected Date&lt;\/div&gt;\n      &lt;div class=\"mv\"&gt;${cnt}&lt;\/div&gt;\n      &lt;div class=\"ms\"&gt;${pct}% of total&lt;\/div&gt;\n    &lt;\/div&gt;\n    &lt;div class=\"mc\"&gt;\n      &lt;div class=\"ml\"&gt;Total Pledges&lt;\/div&gt;\n      &lt;div class=\"mv\"&gt;${total}&lt;\/div&gt;\n      &lt;div class=\"ms\"&gt;All dates combined&lt;\/div&gt;\n    &lt;\/div&gt;\n    &lt;div class=\"mc\"&gt;\n      &lt;div class=\"ml\"&gt;Leading City (Selected)&lt;\/div&gt;\n      &lt;div class=\"mv-sm\"&gt;${lc?cap(lc[0]):'\u2014'}&lt;\/div&gt;\n      &lt;div class=\"ms\"&gt;${lc?lc[1]+' pledges':'No data'}&lt;\/div&gt;\n    &lt;\/div&gt;\n    &lt;div class=\"mc\"&gt;\n      &lt;div class=\"ml\"&gt;Leading State (Selected)&lt;\/div&gt;\n      &lt;div class=\"mv-sm purple\"&gt;${ls?ls[0]:'\u2014'}&lt;\/div&gt;\n      &lt;div class=\"ms\"&gt;${ls?ls[1]+' pledges':'No data'}&lt;\/div&gt;\n    &lt;\/div&gt;`;\n\n  const c3 = topN(ALL, r=&gt;r.c, 3);\n  const s3 = topN(ALL, r=&gt;r.s, 3);\n  const r3 = topRefs(3);\n\n  document.getElementById('top-c').innerHTML = mkList(c3, e=&gt;cap(e[0]), e=&gt;e[1], e=&gt;inferState(e[0])||'');\n  document.getElementById('top-s').innerHTML = mkList(s3, e=&gt;e[0], e=&gt;e[1], null);\n  document.getElementById('top-r').innerHTML = r3.length\n    ? mkList(r3, e=&gt;e.name||e.code, e=&gt;e.count, e=&gt;e.name?'Code: '+e.code:null)\n    : '&lt;li class=\"ti\" style=\"color:var(--mut);font-size:13px;padding:12px 0\"&gt;No referral data&lt;\/li&gt;';\n\n  const lines = [\n    `Portal Daily Tracker \u2014 ${d}`, ``,\n    `No of pledges registered today: ${cnt}`,\n    `Total pledges registered: ${total}`, ``,\n    `Top 3 Cities:`,\n    ...c3.map((e,i)=&gt;`${i+1}. ${cap(e[0])} - ${e[1]}`), ``,\n    `Top 3 States:`,\n    ...s3.map((e,i)=&gt;`${i+1}. ${e[0]} - ${e[1]}`), ``,\n    `Top 3 Referrers:`,\n    ...r3.map((e,i)=&gt;`${i+1}. ${e.name||e.code} - ${e.count}`),\n  ];\n  _outRaw = lines.join('\\n');\n  document.getElementById('outbox').innerHTML = lines.map((l,i)=&gt;{\n    if(i===0) return `&lt;span class=\"hl\"&gt;${l}&lt;\/span&gt;`;\n    if(l.match(\/^(No of|Total|Top 3)\/)) return `&lt;span class=\"hl\"&gt;${l}&lt;\/span&gt;`;\n    if(l.match(\/^\\d\\.\/)) return `&lt;span class=\"gd\"&gt;${l}&lt;\/span&gt;`;\n    if(l.match(\/:\\s*\\d+$\/)) return l.replace(\/:\\s*(\\d+)$\/,': &lt;span class=\"ac\"&gt;$1&lt;\/span&gt;');\n    return l||' ';\n  }).join('\\n');\n\n  const tblTitle = d===todayStr ? \"Today's Pledges\" : d+' Pledges';\n  document.getElementById('tbl-title').textContent = tblTitle;\n  document.getElementById('tbl-badge').textContent = cnt+' records';\n\n  const tbody = document.getElementById('tbody');\n  const thead = document.getElementById('thead');\n  const emp = document.getElementById('emp');\n\n  if(!SD.length){ tbody.innerHTML=''; thead.innerHTML=''; emp.style.display='block'; return; }\n  emp.style.display = 'none';\n  thead.innerHTML = `&lt;tr&gt;&lt;th&gt;#&lt;\/th&gt;&lt;th&gt;Name&lt;\/th&gt;&lt;th&gt;City&lt;\/th&gt;&lt;th&gt;State&lt;\/th&gt;&lt;th&gt;Ref Code&lt;\/th&gt;&lt;th&gt;Used Ref&lt;\/th&gt;&lt;th&gt;Volunteer&lt;\/th&gt;&lt;\/tr&gt;`;\n  tbody.innerHTML = SD.map((r,i)=&gt;`\n    &lt;tr&gt;\n      &lt;td class=\"num\"&gt;${i+1}&lt;\/td&gt;\n      &lt;td style=\"color:var(--txt)\"&gt;${r.n||'\u2014'}&lt;\/td&gt;\n      &lt;td&gt;${cap(r.c)||'\u2014'}&lt;\/td&gt;\n      &lt;td&gt;${r.s||'\u2014'}&lt;\/td&gt;\n      &lt;td&gt;&lt;span class=\"rtag\"&gt;${r.r||'\u2014'}&lt;\/span&gt;&lt;\/td&gt;\n      &lt;td&gt;${r.u?`&lt;span class=\"rtag green\"&gt;${r.u}&lt;\/span&gt;`:'\u2014'}&lt;\/td&gt;\n      &lt;td&gt;${r.v?'&lt;span class=\"vtag\"&gt;Yes&lt;\/span&gt;':'No'}&lt;\/td&gt;\n    &lt;\/tr&gt;`).join('');\n}\n\nfunction copyOut(){\n  if(!_outRaw) return;\n  navigator.clipboard.writeText(_outRaw).then(()=&gt;{\n    const b = document.getElementById('cbtn');\n    b.textContent = '\u2713 Copied!'; b.classList.add('done');\n    setTimeout(()=&gt;{ b.textContent='\u2398 Copy Summary'; b.classList.remove('done'); }, 2000);\n  });\n}\n[\/tcb-script]<\/code>\n\n<\/div><div class=\"thrv_wrapper thrv_text_element\" style=\"z-index: 3 !important;\" data-css=\"tve-u-19e061bbe84\"><h2 class=\"\" style=\"\" data-css=\"tve-u-19e061bbe85\"><br><\/h2><\/div><\/div>\n<\/div>","tve_custom_css":"@media (min-width: 300px){[data-css=\"tve-u-19e061bbe7b\"] { max-width: unset; --tve-alignment: center; float: none; margin-left: auto !important; margin-right: auto !important; padding: 45px 45px 100px !important; --tve-applied-max-width: unset !important; margin-top: -69px !important; }[data-css=\"tve-u-19e061bbe7d\"] { min-height: 10px; --tve-color: rgb(255,255,255); --tve-applied---tve-color: rgb(255,255,255); --tve-applied-min-height: unset !important; }[data-css=\"tve-u-19e061bbe7c\"] { --tve-border-radius: 47px; border-radius: 47px; overflow: hidden; background-image: url(\"\/\/thefiniteearth.org\/wp-content\/uploads\/tcb_content_templates\/stylebox\/images\/Styled-Box_deco1_03_03.png\"), url(\"\/\/thefiniteearth.org\/wp-content\/uploads\/tcb_content_templates\/stylebox\/images\/Styled-Box_deco2_03.png\"), linear-gradient(rgb(23, 23, 23), rgb(23, 23, 23)) !important; background-size: auto, auto, auto !important; background-position: 100% 0%, 0% 100%, 50% 50% !important; background-attachment: scroll, scroll, scroll !important; background-repeat: no-repeat, no-repeat, no-repeat !important; --background-image: url(\"\/\/thefiniteearth.org\/wp-content\/uploads\/tcb_content_templates\/stylebox\/images\/Styled-Box_deco1_03_03.png\"),url(\"\/\/thefiniteearth.org\/wp-content\/uploads\/tcb_content_templates\/stylebox\/images\/Styled-Box_deco2_03.png\"),linear-gradient(rgb(23,23,23),rgb(23,23,23)) !important; --background-size: auto,auto,auto !important; --background-position: 100% 0%,0% 100%,50% 50% !important; --background-attachment: scroll,scroll,scroll !important; --background-repeat: no-repeat,no-repeat,no-repeat !important; --tve-applied-background-image: url(\"\/\/thefiniteearth.org\/wp-content\/uploads\/tcb_content_templates\/stylebox\/images\/Styled-Box_deco1_03_03.png\"),url(\"\/\/thefiniteearth.org\/wp-content\/uploads\/tcb_content_templates\/stylebox\/images\/Styled-Box_deco2_03.png\"),linear-gradient(rgb(23,23,23),rgb(23,23,23)) !important; }[data-css=\"tve-u-19e061bbe7b\"] > .tve-cb { display: block; }:not(#tve) .thrv-content-box [data-css=\"tve-u-19e061bbe7d\"] p, :not(#tve) .thrv-content-box [data-css=\"tve-u-19e061bbe7d\"] li, :not(#tve) .thrv-content-box [data-css=\"tve-u-19e061bbe7d\"] blockquote, :not(#tve) .thrv-content-box [data-css=\"tve-u-19e061bbe7d\"] address, :not(#tve) .thrv-content-box [data-css=\"tve-u-19e061bbe7d\"] .tcb-plain-text, :not(#tve) .thrv-content-box [data-css=\"tve-u-19e061bbe7d\"] label, :not(#tve) .thrv-content-box [data-css=\"tve-u-19e061bbe7d\"] h1, :not(#tve) .thrv-content-box [data-css=\"tve-u-19e061bbe7d\"] h2, :not(#tve) .thrv-content-box [data-css=\"tve-u-19e061bbe7d\"] h3, :not(#tve) .thrv-content-box [data-css=\"tve-u-19e061bbe7d\"] h4, :not(#tve) .thrv-content-box [data-css=\"tve-u-19e061bbe7d\"] h5, :not(#tve) .thrv-content-box [data-css=\"tve-u-19e061bbe7d\"] h6 { color: var(--tve-color,rgb(255,255,255)); --tve-applied-color: var$(--tve-color,rgb(255,255,255)); --tcb-applied-color: rgb(255,255,255); }[data-css=\"tve-u-19e061bbe84\"] { margin-top: 20px !important; margin-bottom: 20px !important; }:not(#tve) [data-css=\"tve-u-19e061bbe85\"] { letter-spacing: 0px; padding-bottom: 0px !important; margin-bottom: 0px !important; padding-top: 0px !important; margin-top: 0px !important; font-weight: var(--g-regular-weight,normal) !important; font-size: 24px !important; line-height: 1.5em !important; }}@media (max-width: 767px){[data-css=\"tve-u-19e061bbe7b\"] { max-width: 100%; padding-top: 80px !important; --tve-applied-max-width: 100% !important; padding-left: 30px !important; padding-right: 30px !important; }}","tve_user_custom_css":"","tve_globals":{"e":"1","font_cls":[]},"tcb2_ready":1,"tcb_editor_enabled":1,"tve_landing_page":"","_tve_header":"","_tve_footer":""},"class_list":["post-1642","page","type-page","status-publish","hentry","post-wrapper","thrv_wrapper"],"_links":{"self":[{"href":"https:\/\/thefiniteearth.org\/hindi\/wp-json\/wp\/v2\/pages\/1642","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/thefiniteearth.org\/hindi\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/thefiniteearth.org\/hindi\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/thefiniteearth.org\/hindi\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/thefiniteearth.org\/hindi\/wp-json\/wp\/v2\/comments?post=1642"}],"version-history":[{"count":11,"href":"https:\/\/thefiniteearth.org\/hindi\/wp-json\/wp\/v2\/pages\/1642\/revisions"}],"predecessor-version":[{"id":1654,"href":"https:\/\/thefiniteearth.org\/hindi\/wp-json\/wp\/v2\/pages\/1642\/revisions\/1654"}],"wp:attachment":[{"href":"https:\/\/thefiniteearth.org\/hindi\/wp-json\/wp\/v2\/media?parent=1642"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}