IRG-GDP IRG-GDP
'; const blob=new Blob([html],{type:'text/html'}); const a=document.createElement('a'); a.href=URL.createObjectURL(blob); a.download='IRG-GDP-User-Policy.html'; a.click(); URL.revokeObjectURL(a.href); } function confirmPolicy(){ // Confirm = accept the policy: tick the consent dot and return to Register. REG.consent=true; viewRegisterInfo(); // after the register view re-renders, reflect the consent visually setTimeout(function(){ const d=document.getElementById('rgDot'); if(d) d.classList.add('on'); },0); } async function viewPolicy(){ win('User Policy (Terms of Use)','Read the policy. You can download it, or confirm your acceptance below.', `
${USER_POLICY_HTML}
`); } async function doRegisterSubmit(){ const m=document.getElementById('rgMsg2'); if(!REG.consent){ m.className='msg err'; m.textContent='Read and confirm your acceptance of the policy to use IRG-GDP platform.'; return; } if(!REG.roles.length){ m.className='msg err'; m.textContent='Select at least one role (role selection comes first).'; return; } const body={ roles:REG.roles, first_name:val('rgFn'), last_name:val('rgLn'), email:val('rgEmail').toLowerCase(), mobile:(val('rgCc')||'+91')+val('rgMob'), address_line:val('rgAddr'), city:val('rgCity'), state:val('rgState'), pincode:val('rgPin'), country:val('rgCountry'), constitution:val('rgConst'), pan_number:val('rgPan').toUpperCase(), aadhaar_number:val('rgAadhaar'), registration_certificate_number:val('rgCert'), password:val('rgPw'), confirm_password:val('rgPw2') }; const {status,j}=await api('/api/v1/auth/register/',{method:'POST',body:JSON.stringify(body)}); if(status<300){ S.lastEmail=body.email; S.lastMobile=body.mobile; S.otpPurpose='REGISTER'; viewOtp(body.email,'REGISTER',body.mobile); } else{ m.className='msg err'; m.textContent = j ? Object.entries(j).map(([k,v])=>k+': '+(Array.isArray(v)?v.join(' '):v)).join(' ') : 'Registration failed.'; } } function val(id){ const e=document.getElementById(id); return e?(e.value||'').trim():''; } function viewLater(t){ win(t,'', nodata('The '+esc(t)+' screen ships in a later part of this build.')); } /* ---------- GIC Licensee content (live) ---------- */ async function viewLicDashboard(){ const {status,j}=await api('/api/v1/gic/licence/dashboard/'); if(status===403&&j&&j.error==='not_a_licensee') return viewLicRegister(); if(status!==200||!j) return win('Dashboard','',nodata('Could not load your GIC dashboard.')); S.dash=j; const s=j.summary,b=j.by_stream; win('GIC Licensee — my entitlements', esc(j.licence_number), `
Earned · claimable
${esc(s.earned_claimable_units)} GIC
₹${esc(s.earned_claimable_inr)}
This month
₹${esc(s.this_month_inr)}
accrued value
Lifetime GIC
${esc(s.lifetime_gic_units)}
units accrued
Redeemed
${esc(s.redeemed_units)} GIC
${esc(s.net_gdp_units_received)} GDP units received

A GIC is an entitlement to claimable income — 1 GIC = 1 GDP unit. The downloadable certificate is a system-generated confirmation of the entitlement, not an asset or investment.

Income by stream

${tbl(['Stream','Accrued value ₹'],[['Generation Royalty share',b.royalty], ['Referral Commission share',b.referral]])}

Recent entries

${tbl(j.columns,(j.rows||[]).slice(0,12))}
`); } function viewLicRegister(){ win('Become a GIC Licensee','capacity options per the Licence', `

Fee: USD 300 per household. The withholding-tax rate is recorded at registration and is borne by IRG at redemption — it reduces the GDP entitlement you receive.

`, true); } async function doLicRegister(){ const body={household_capacity:+document.getElementById('rgCap').value, wht_pct:document.getElementById('rgWht').value||'0', residency:document.getElementById('rgRes').value||''}; const {status,j}=await api('/api/v1/gic/licence/register/',{method:'POST',body:JSON.stringify(body)}); const m=document.getElementById('rgMsg'); if(status===201){ m.className='msg ok'; m.textContent='Licence '+j.licence_number+' created (PENDING). First tranche due: USD '+j.first_tranche_due_usd+'.'; const {j:me}=await api('/api/v1/auth/users/me/'); if(me){ S.user=me; SS.set('irg_user',JSON.stringify(me)); } renderRail(); } else { m.className='msg err'; m.textContent=(j&&(j.message||j.error))||'Registration failed.'; } } async function viewEnrolments(){ const {status,j}=await api('/api/v1/gic/licence/enrolments/'); if(status===403) return viewLicRegister(); win('My enrolled households', j?('Capacity '+esc(j.capacity)+' · remaining '+esc(j.remaining)):'', ` ${tbl(j&&j.columns,j&&j.rows)}

Enrol an eligible household

The platform enforces household-level uniqueness — a household already enrolled under any licence or jeweller sub-licence cannot be enrolled again.

`); } async function doEnrol(){ const email=document.getElementById('enEmail').value.trim().toLowerCase(), m=document.getElementById('enMsg'); const {status,j}=await api('/api/v1/gic/licence/enrol/',{method:'POST',body:JSON.stringify({household_email:email})}); if(status===201){ m.className='msg ok'; m.textContent='Enrolled. Sub-licence '+j.sub_licence_number+'. Capacity remaining: '+j.capacity_remaining+'.'; } else{ m.className='msg err'; m.textContent=(j&&(j.message||j.error))||'Enrolment failed.'; } } function viewRedeem(){ const avail=S.dash?S.dash.summary.earned_claimable_units:'—'; win('Claim earned GICs','Benchmark is fixed at the moment of your request', `

Earned and claimable now: ${esc(avail)} GIC. On claiming, the system buys existing GDP units on IRG's behalf at Benchmark and transfers them to your wallet — units are never generated for this. Withholding tax (borne by IRG) reduces the units you receive. If supply is short, the purchase stays pending and fills when supply appears.

`, true); } async function doRedeem(){ const m=document.getElementById('rdMsg'), pend=document.getElementById('rdPending'); const {status,j}=await api('/api/v1/gic/licence/redeem/',{method:'POST',body:JSON.stringify({ gic_units:document.getElementById('rdUnits').value.trim(), accept_market_rate:document.getElementById('rdMkt').checked})}); pend.innerHTML=''; if(status===201){ m.className='msg ok'; m.textContent='Claimed '+j.gic_units_claimed+' GIC at ₹'+j.benchmark_at_request+'/g. Gross ₹'+j.gross_inr+ '; WHT '+j.wht_pct+'% borne by IRG; '+j.net_gdp_units+' GDP unit(s) purchased and transferred to your wallet ('+j.currency+').'; railWallet(); } else if(status===202&&j){ m.className='msg info'; m.textContent=j.message||'Purchase pending.'; if(j.pending_order_id) pend.innerHTML='
'+ '
'; } else { m.className='msg err'; m.textContent=(j&&(j.message||j.error))||'Claim failed.'; } } async function fillOrder(id){ const m=document.getElementById('rdMsg'); const {j}=await api('/api/v1/gic/licence/orders/'+id+'/fill/',{method:'POST',body:JSON.stringify({})}); if(j&&j.status==='filled'){ m.className='msg ok'; m.textContent='Filled. Cost '+j.currency+' '+j.cost+'; units transferred.'; railWallet(); } else{ m.className='msg info'; m.textContent=(j&&j.message)||'Still pending — will fill when supply appears.'; } } async function viewMIS(key,title){ return viewMISPath('/api/v1/mis/licensee/'+key+'/',title); } /* ---------- Admin: set FTR benchmark rates (wires to existing /oracle/benchmark/) ---------- */ const FTR_CATEGORIES = ['Healthcare','Education','Travel','Hospitality','Real Estate','Automobile', 'Electronics','Fashion','Food & Beverage','Entertainment','Fitness','Insurance','Banking','Telecom', 'Utilities','Transport','Logistics','Construction','Home Services','Beauty & Personal Care','Legal', 'Accounting','Consulting','IT Services','Software','Books & Media','Music','Gaming','Sports','Art & Culture']; function isAdminUser(){ return !!(S.user && (S.user.is_staff || S.user.is_superuser || activeRoles().includes('ADMIN'))); } async function viewFtrRates(){ if(!isAdminUser()){ win('FTR benchmark rates','', nodata('This screen is for administrators only.')); return; } win('FTR benchmark rates','Set the INR benchmark rate for each FTR sector. A rate of 0 means swaps for that sector stay safely refused until set.', '
Loading current rates…
'); // fetch current rates grouped by category let current={}; try{ const {j}=await api('/api/v1/oracle/benchmark/by_category/'); if(j&&typeof j==='object') current=j; }catch(e){} const rows = FTR_CATEGORIES.map(cat=>{ const cur = current[cat] && current[cat].value_inr!=null ? current[cat].value_inr : '0'; const id = 'ftr_'+cat.replace(/[^A-Za-z]/g,''); return ` ${esc(cat)} ${esc(cur)} `; }).join(''); document.getElementById('ftrBody').innerHTML = `${rows}
FTR sectorCurrent ₹New rate ₹
`; } async function setFtr(category, inputId){ const el=document.getElementById(inputId); const m=document.getElementById('ftrMsg'); const v=(el.value||'').trim(); if(v==='' || isNaN(Number(v)) || Number(v)<0){ m.textContent='Enter a valid non-negative number for '+category+'.'; return; } const today=new Date().toISOString().slice(0,10); const {status,j}=await api('/api/v1/oracle/benchmark/',{method:'POST', body:JSON.stringify({category:category, subcategory:'', value_inr:v, unit:'INR', effective_from:today})}); if(status<300){ m.textContent='✓ '+category+' set to ₹'+v+' (effective '+today+'). Newest rate wins.'; viewFtrRates(); } else { m.textContent='Could not set '+category+': '+(j&&(j.detail||JSON.stringify(j))||('HTTP '+status)); } } async function viewMISPath(path,title){ setActiveMenu(null); const {status,j}=await api(path); if(status!==200||!j) return win(title,'',nodata('Report unavailable.')); win(esc(j.title||title),'generated '+esc((j.generated_at||'').slice(0,19).replace('T',' ')), ` ${tbl(j.columns,j.rows)}
`); } async function downloadCSVPath(path,name){ const r=await fetch(API+path+'?download=csv',{headers:H()}); const blob=await r.blob(); const a=document.createElement('a'); a.href=URL.createObjectURL(blob); a.download=name+'.csv'; a.click(); URL.revokeObjectURL(a.href); } // ── URGENT notifications shown automatically in the shell window after sign-in ── // Urgent = action/expiry/legal events (curated allowlist) OR priority CRITICAL. const URGENT_EVENTS = new Set([ 'registration.reminder','registration.final_notice', // wallet/registration lapse (30-day expiry) 'gdp.buy_order.open', // buy notification — act to sell 'jeweler.licence_revoked','jeweler.licence_suspended', // legal / licence 'officer.appointed','officer.revoked','dispute.resolved','gdp.deregistered', 'gdp.first_sale.utr_rejected','nominee.signature_requested', 'gdp.bonus.jeweler_subscription_required','gdp.bonus.jeweler_subscription_missed', 'kyc.rejected' ]); function isUrgent(n){ const p=(n.priority||'').toUpperCase(); if(p==='CRITICAL') return true; return URGENT_EVENTS.has(n.event||n.event_key||''); } async function showUrgentAfterLogin(){ try{ const {status,j}=await api('/api/v1/notifications/merged/'); if(status!==200) return false; const list=(j&&(j.notifications||j.results||[]))||[]; const urgent=list.filter(n=>!(n.read||n.is_read) && isUrgent(n)); if(!urgent.length) return false; renderUrgent(urgent,0); return true; }catch(e){ return false; } } function renderUrgent(queue,idx){ if(idx>=queue.length){ setActiveMenu('dashboard'); viewDashboard(); return; } const n=queue[idx]; const when=esc((n.created_at||'').slice(0,16).replace('T',' ')); const link=n.deep_link||n.link||''; const body='
'+ '
'+esc(n.subject||n.event||'Action required')+''+ '
'+when+'
'+ '
'+esc(n.body||'')+'
'+ '
'+ ((link||(n.event||n.event_key)==='gdp.buy_order.open')?(''):'')+ ''+ '
'+ (queue.length>1?('
'+(idx+1)+' of '+queue.length+' urgent
'):''); win('Action required — urgent notification','', body, true); // stash queue+idx on window for the button handlers window.__urgentQueue=queue; window.__urgentIdx=idx; } async function _markRead(id){ try{ await api('/api/v1/notifications/'+id+'/read/',{method:'POST',body:'{}'}); }catch(e){} } async function urgentDismiss(id){ await _markRead(id); const q=window.__urgentQueue,i=window.__urgentIdx; railItems(); renderUrgent(q,i+1); } async function urgentOpen(id,link,ev,ctx){ await _markRead(id); railItems(); // buy-order notification → open the Sale of Inactive GDPs screen (pre-loaded) if((ev||'')==='gdp.buy_order.open'){ const c=ctx||{}; const q=[]; if(c.trade_id) q.push('trade_id='+encodeURIComponent(c.trade_id)); if(c.units) q.push('units='+encodeURIComponent(c.units)); viewPage('Sale of Inactive GDPs','sale-inactive-gdps.html'+(q.length?('?'+q.join('&')):'')); return; } if(link && /\.html/.test(link)){ const src=link.replace(/^https?:\/\/[^/]+\//,''); viewPage('Notification', src); } else if(link && link.indexOf('/')===0){ viewPage('Notification', link.replace(/^\//,'')); } else { viewNotifications(); } } async function viewNotifications(){ setActiveMenu(null); const {status,j}=await api('/api/v1/notifications/merged/'); const list=(j&&(j.notifications||j.results||[]))||[]; if(status!==200) return win('Notifications','',nodata('Could not load notifications.')); if(!list.length) return win('Notifications','',nodata('No notifications to display.')); win('Notifications','', list.map(n=>'
'+ '
'+esc(n.subject||n.event)+'
'+ esc((n.created_at||'').slice(0,16).replace('T',' '))+'
'+ '
'+esc(n.body||'')+'
').join('')+ '
'+ '
'); } async function markAllRead(){ await api('/api/v1/notifications/merged/mark-read/',{method:'POST',body:JSON.stringify({all:true})}); railItems(); viewNotifications(); } /* ---------- Jeweller (live contracts, 6 Jul 2026) ---------- register-customer/ {customer_email,customer_mobile,customer_first_name, customer_last_name,customer_aadhaar(12),customer_pan(10)} draft/ {customer_email} → proposal (or code=register first) /lines/ multipart {item_description,gross_weight_grams,purity(9-24K), huid OR gold_image file} — advisory FLAGGED never blocks /submit/ {jeweler_note} → PROPOSED (operator approves; execution step ships in the next part after the flow walkthrough) */ let PROP=null; function viewJwRegCust(){ setActiveMenu(null); win('Register a customer','the certifying jeweller registers the household', `
`, true); } async function doJwRegCust(){ const m=document.getElementById('jcMsg'); const {status,j}=await api('/api/v1/mint-proposal/register-customer/',{method:'POST',body:JSON.stringify({ customer_first_name:val('jcFn'), customer_last_name:val('jcLn'), customer_email:val('jcEmail').toLowerCase(), customer_mobile:(val('jcCc')||'+91')+val('jcMob'), customer_aadhaar:val('jcAad'), customer_pan:val('jcPan').toUpperCase()})}); if(status<300){ m.className='msg ok'; m.textContent=(j&&(j.message||j.detail))||'Customer registered.'; } else if(j&&j.errors){ m.className='msg err'; m.textContent=Object.entries(j.errors).map(([k,v])=>v).join(' '); } else { m.className='msg err'; m.textContent=(j&&(j.detail||j.message))||'Registration failed.'; } } async function viewJwProposals(){ setActiveMenu(null); const {status,j}=await api('/api/v1/mint-proposal/mine/'); const list=(j&&j.proposals)||[]; const rows=list.map(p=>[String(p.id||'').slice(0,8), esc(p.customer_email||p.customer||'—'), esc(p.status), (p.lines?p.lines.length:(p.line_count!=null?p.line_count:'—')), esc((p.updated_at||p.created_at||'').slice(0,16).replace('T',' '))]); win('My generation proposals','draft → proposed → operator approval', ` ${status===200?tbl(['Ref','Customer','Status','Ornaments','Updated'],rows) :nodata('Could not load proposals.')}

A FLAGGED ornament is an advisory duplicate-check flag — it queues for review and never blocks generation. After operator approval, the generation execution step ships in the next part.

`); } function viewJwNewProposal(){ setActiveMenu(null); PROP=null; win('New generation proposal','step 1 — the registered customer it is for', `
`, true); } async function doOpenDraft(){ const m=document.getElementById('npMsg'); const {status,j}=await api('/api/v1/mint-proposal/draft/',{method:'POST', body:JSON.stringify({customer_email:val('npEmail').toLowerCase()})}); if(status<300&&j&&(j.id||j.proposal)){ PROP=j.proposal||j; viewJwDraft(); } else if(j&&/register/i.test(j.detail||'')){ m.className='msg err'; m.innerHTML=esc(j.detail)+' Register the customer'; } else{ m.className='msg err'; m.textContent=(j&&(j.detail||j.message))||'Could not open a draft.'; } } async function refreshDraft(){ if(!PROP) return; const {j}=await api('/api/v1/mint-proposal/'+PROP.id+'/'); if(j&&(j.proposal||j.id)) PROP=j.proposal||j; } function viewJwDraft(){ const lines=PROP.lines||[]; const rows=lines.map(l=>[esc(l.item_description).slice(0,30), esc(l.gross_weight_grams), esc(l.purity), esc(l.huid||(l.gold_image?'photo':'—')), l.status==='FLAGGED'?'⚑ FLAGGED (advisory)':esc(l.status)]); win('Generation proposal — ornaments','customer: '+esc(PROP.customer_email||PROP.customer||''), ` ${tbl(['Ornament','Gross g','Purity','HUID/photo','Status'],rows)}

Add an ornament

Submit

`); } async function doAddLine(){ const m=document.getElementById('lnMsg'); const fd=new FormData(); fd.append('item_description',val('lnDesc')); fd.append('gross_weight_grams',val('lnGross')); fd.append('purity',val('lnPurity')); if(val('lnHuid')) fd.append('huid',val('lnHuid')); const f=document.getElementById('lnPhoto').files[0]; if(f) fd.append('gold_image',f); const {status,j}=await api('/api/v1/mint-proposal/'+PROP.id+'/lines/',{method:'POST',body:fd}); if(status<300){ m.className='msg ok'; m.textContent='Ornament added.'+(j&&j.line&&j.line.status==='FLAGGED'?' (advisory duplicate flag — queued for review, not blocked)':''); await refreshDraft(); viewJwDraft(); } else{ m.className='msg err'; m.textContent=(j&&(j.detail||j.message))||'Could not add the ornament.'; } } async function doSubmitProposal(){ const m=document.getElementById('npMsg2'); const {status,j}=await api('/api/v1/mint-proposal/'+PROP.id+'/submit/',{method:'POST', body:JSON.stringify({jeweler_note:val('npNote')})}); if(status<300){ m.className='msg ok'; m.textContent='Proposal submitted for operator approval. You will be notified of the outcome.'; } else{ m.className='msg err'; m.textContent=(j&&(j.detail||j.message))||'Submit failed.'; } } /* ---------- Buyer / Holder (live contracts, 6 Jul 2026) ---------- GET /api/v1/gdp/units/portfolio/ {locked_units,tradable_units, pending_first_sale_units,total_units,total_value} GET /api/v1/gdp/units/ my unit rows GET /api/v1/gdp/first-sale/marketplace/ {offers:[…]} POST /api/v1/gdp/first-sale//buy/ → escrow buyer_instructions POST /api/v1/gdp/first-sale//buyer-utr/ {utr,amount} → ops verify GET /api/v1/gdp/trade/orderbook/ {buy_orders,sell_orders} POST /api/v1/gdp/trade/place_order/ {trade_type,units,price_per_unit} POST /api/v1/gdp/transfer/initiate/ {gdp_unit_id,to_email, transfer_type∈GIFT|SPONSOR|INHERITANCE,message} GET /api/v1/gdp/swap/categories/ live FTR category list POST /api/v1/gdp/swap/initiate/ {gdp_unit_ids[],ftr_category} */ async function viewHoldings(){ setActiveMenu('dashboard'); const {status,j}=await api('/api/v1/gdp/units/portfolio/'); if(status!==200||!j) return win('My holdings','',nodata('Could not load your portfolio.')); S.pf=j; const sm=j.summary||j; // R16: breakdown lives in summary const {j:u}=await api('/api/v1/gdp/units/'); const units=(u&&(u.results||u))||[]; const rows=(Array.isArray(units)?units:[]).slice(0,30).map(x=>[ String(x.id||'').slice(0,8), esc(x.gold_grams||x.pure_gold_equivalent), esc(x.total_units), x.first_sale_completed?'YES':'no', esc(x.status)]); win('My holdings','GDP units by tier', `
Active
${esc(sm.active_units)}
valued at Benchmark${sm.active_value_inr?' — ₹'+(+sm.active_value_inr).toLocaleString('en-IN'):''}
Inactive
${esc(sm.inactive_units)}
awaiting first sale · no value
Listed
${esc(sm.listed_units)}
first-sale listing · no value
Reserve
${esc(sm.reserve_units)}
permanent cover · no value
Total units
${esc(sm.total_units)}
only Active carry value

My GDP unit rows

${tbl(['Ref','Gold g','Units','First sale','Status'],rows)}
`); } async function viewMarketplace(){ setActiveMenu(null); const {status,j}=await api('/api/v1/gdp/first-sale/marketplace/'); const offers=(j&&j.offers)||[]; const rows=offers.map(o=>[String(o.id).slice(0,8), esc(o.seller_email), esc(o.units), '₹'+esc(o.price_per_unit), '₹'+esc(o.total_value), ``]); win('First-sale marketplace','buy listed GDP units through IRG escrow', ` ${status===200?tbl(['Ref','Seller','Units','Price/unit','Total',''] ,rows):nodata('Marketplace unavailable.')}

Buying engages the listing in your name and gives you the IRG escrow account details and a payment reference. After you transfer the amount, submit your UTR here; the operations team verifies the credit and the units are released to your wallet.

`); } async function doEngage(id){ const m=document.getElementById('mkMsg'); const {status,j}=await api('/api/v1/gdp/first-sale/'+id+'/buy/',{method:'POST',body:JSON.stringify({})}); if(status<300&&j){ m.className='msg ok'; m.textContent=j.message||'Engaged. Transfer the amount to escrow.'; const bi=j.buyer_instructions||{}; document.getElementById('mkPanel').innerHTML = `
Escrow account
${esc(bi.account_number||bi.account||'—')}
${esc(bi.bank||bi.ifsc||'')}
Payment reference
${esc(bi.reference||j.trade&&j.trade.payment_reference||'—')}
quote this in your transfer
Amount
₹${esc(j.trade?j.trade.total_value:'—')}
for ${esc(j.trade?j.trade.units:'—')} unit(s)
`; } else { m.className='msg err'; m.textContent=(j&&(j.message||j.error))||'Could not engage this offer.'; } } async function doUtr(id){ const m=document.getElementById('mkMsg'); const {status,j}=await api('/api/v1/gdp/first-sale/'+id+'/buyer-utr/',{method:'POST', body:JSON.stringify({utr:val('mkUtr'),amount:val('mkAmt')})}); m.className=status<300?'msg ok':'msg err'; m.textContent=(j&&(j.message||j.error))||(status<300?'UTR submitted for verification.':'Submit failed.'); } async function viewTrade(){ setActiveMenu(null); const {status,j}=await api('/api/v1/gdp/trade/orderbook/'); const buys=(j&&j.buy_orders)||[], sells=(j&&j.sell_orders)||[]; const mk=o=>[esc(o.units),'₹'+esc(o.price_per_unit),esc((o.created_at||'').slice(0,16).replace('T',' '))]; win('Trade GDP — buy order','place a buy order — it is broadcast to inactive-GDP holders for first-sale confirmation', `

Buy orders

${tbl(['Units','Price/unit','Placed'],buys.map(mk))}

Sell orders

${tbl(['Units','Price/unit','Placed'],sells.map(mk))}

Place an order

`, true); } async function doPlaceOrder(){ const m=document.getElementById('trMsg'); const {status,j}=await api('/api/v1/gdp/trade/place_order/',{method:'POST',body:JSON.stringify({ trade_type:val('trSide'),units:parseInt(val('trUnits')||'0'),price_per_unit:val('trPrice')})}); if(status<300){ m.className='msg ok'; m.textContent=(j&&(j.message||('Order placed: '+(j.status||''))))||'Order placed.'; viewTrade(); } else{ m.className='msg err'; m.textContent=(j&&(j.detail||j.message||JSON.stringify(j)))||'Order failed.'; } } async function viewTransfer(){ setActiveMenu(null); const {j:u}=await api('/api/v1/gdp/units/'); const units=((u&&(u.results||u))||[]).filter(x=>x.first_sale_completed); win('Transfer / gift a GDP','locked rule: a unit moves only after its first sale is completed', `
`, true); } async function doTransfer(){ const m=document.getElementById('tfOut'); const {status,j}=await api('/api/v1/gdp/transfer/initiate/',{method:'POST',body:JSON.stringify({ gdp_unit_id:val('tfUnit'),to_email:val('tfTo').toLowerCase(), transfer_type:val('tfType'),message:val('tfMsg')})}); m.className=status<300?'msg ok':'msg err'; m.textContent=(j&&(j.message||j.detail||j.error))||(status<300?'Transfer executed; a personal record is generated for the recipient.':'Transfer failed.'); } async function viewSwap(){ setActiveMenu(null); const [{j:u},{j:c}]=await Promise.all([api('/api/v1/gdp/units/'),api('/api/v1/gdp/swap/categories/')]); const units=((u&&(u.results||u))||[]).filter(x=>x.first_sale_completed); const cats=(c&&(c.categories||c))||[]; win('Swap GDP → FTR','one-way, at the live FTR benchmark for the chosen sector', `
${units.length?units.map(x=> `${String(x.id).slice(0,8)} · ${x.gold_grams||x.pure_gold_equivalent} g`).join('') :'— no swappable units (first sale must be completed) —'}
`, true); } async function doSwap(){ const m=document.getElementById('swMsg'); const ids=[...document.querySelectorAll('.rolechk.on')].map(x=>x.dataset.r); if(!ids.length){ m.className='msg err'; m.textContent='Select at least one unit.'; return; } const {status,j}=await api('/api/v1/gdp/swap/initiate/',{method:'POST', body:JSON.stringify({gdp_unit_ids:ids,ftr_category:val('swCat')})}); m.className=status<300?'msg ok':'msg err'; m.textContent=(j&&(j.message||j.detail||JSON.stringify(j).slice(0,180)))||(status<300?'Swap executed.':'Swap failed.'); } /* ================= JR Holder (RETURNEE) — live contracts ================= */ async function viewJrUnits(){ setActiveMenu('dashboard'); const {status,j}=await api('/api/v1/jr/units/'); const units=((j&&(j.results||j))||[]); const rows=(Array.isArray(units)?units:[]).map(u=>[String(u.id).slice(0,8), esc(u.pure_gold_grams||u.gold_grams), esc(u.jewelry_type||u.jewellery_type||'—'), esc(u.status), esc(u.lock_in_end_date||'—')]); win('My JR notes','Jewellery Rights units — no-loss buyback protected', `${status===200?tbl(['Ref','Pure gold g','Type','Status','Lock-in until'],rows):nodata('Could not load JR notes.')}
`); } async function jrUnitOptions(filterActive){ const {j}=await api('/api/v1/jr/units/'); const u=((j&&(j.results||j))||[]); return (Array.isArray(u)?u:[]).filter(x=>!filterActive||x.status==='ACTIVE'); } async function viewJrTransfer(){ setActiveMenu(null); const units=await jrUnitOptions(true); win('Transfer a JR note','lock-in blocks transfer until it ends', `
`, true); } async function doJrTransfer(){ const m=document.getElementById('jrtOut'); const {status,j}=await api('/api/v1/jr/transfer/initiate/',{method:'POST',body:JSON.stringify({ jr_unit_id:val('jrtU'),to_email:val('jrtTo').toLowerCase(), transfer_type:val('jrtT'),message:val('jrtMsg')})}); m.className=status<300?'msg ok':'msg err'; m.textContent=(j&&(j.message||j.detail||j.error))||(status<300?'JR note transferred.':'Transfer failed.'); } async function viewJrDiscount(){ setActiveMenu(null); const units=await jrUnitOptions(true); win('Redeem JR for discount','tiered: 15% under 50 g · 25% for 50–200 g · 35% above 200 g', `
${units.map(x=>`${String(x.id).slice(0,8)} · ${x.pure_gold_grams||x.gold_grams} g`).join('')||'— no active JR notes —'}
`, true); } async function doJrDiscount(){ const m=document.getElementById('jrdOut'); const ids=[...document.querySelectorAll('.rolechk.on')].map(x=>x.dataset.r); if(!ids.length){ m.className='msg err'; m.textContent='Select at least one JR note.'; return; } const {status,j}=await api('/api/v1/jr/discount/redeem/',{method:'POST',body:JSON.stringify({ jr_unit_ids:ids,jeweler_id:val('jrdJw'),new_purchase_invoice_no:val('jrdInv'), new_purchase_value:val('jrdVal')})}); m.className=status<300?'msg ok':'msg err'; m.textContent=(j&&(j.message||j.detail||JSON.stringify(j).slice(0,180)))||(status<300?'Discount redeemed.':'Redemption failed.'); } async function viewJrSwap(){ setActiveMenu(null); const units=await jrUnitOptions(true); win('Swap JR → GDP','1:1 on pure gold grams · one-way · no fee', `
`, true); } async function doJrSwap(){ const m=document.getElementById('jrsOut'); const {status,j}=await api('/api/v1/jr/swap/to_gdp/',{method:'POST',body:JSON.stringify({jr_unit_id:val('jrsU')})}); m.className=status<300?'msg ok':'msg err'; m.textContent=(j&&(j.message||j.detail||j.error))||(status<300?'Swapped to GDP.':'Swap failed.'); } async function viewJrBuyback(){ setActiveMenu(null); const units=await jrUnitOptions(true); win('Request buyback','no-loss buyback at guarantee value (subject to lock-in)', `
`, true); } async function doJrBuyback(){ const m=document.getElementById('jrbOut'); const {status,j}=await api('/api/v1/jr/buyback/request_buyback/',{method:'POST',body:JSON.stringify({jr_unit_id:val('jrbU')})}); m.className=status<300?'msg ok':'msg err'; m.textContent=(j&&(j.message||j.detail||j.error))||(status<300?'Buyback requested.':'Request failed.'); } /* ================= Designer — live contracts (irg_jdb + Tjdb) ================= */ async function viewDsDesigns(){ setActiveMenu('dashboard'); const {status,j}=await api('/api/v1/jdb/designs/'); const d=((j&&(j.results||j))||[]); const rows=(Array.isArray(d)?d:[]).map(x=>[esc(x.title).slice(0,30),esc(x.category), esc(x.status),esc(x.orders_count!=null?x.orders_count:'—')]); win('My designs','Design Bank — demand decides; no approval gate', `${status===200?tbl(['Title','Category','Status','Orders'],rows):nodata('Could not load designs.')}
`); } async function viewDsReference(){ setActiveMenu(null); win('Add jeweller reference','degreeless designers list 2 enlisted-jeweller references', `
`, true); } async function doDsReference(){ const m=document.getElementById('dsRefOut'); const {status,j}=await api('/api/v1/jdb/designers/references/',{method:'POST',body:JSON.stringify({ referee_jeweler_id:val('dsRefJw'),remark:val('dsRefR')})}); m.className=status<300?'msg ok':'msg err'; m.textContent=(j&&(j.message||j.detail||j.error||('Reference added to '+(j.referee||''))))||(status<300?'Reference added.':'Failed.'); } async function viewDsRankings(){ return viewMISPath('/api/v1/jdb/rankings/','Design rankings (1–10)'); } async function viewDsNegotiations(){ setActiveMenu(null); win('Charge negotiations','a jeweller offers a charge; you accept, counter or decline', ` ${nodata('Your incoming charge offers appear here as jewellers make them. When an offer arrives you can accept (unlocks their download), counter, or decline — you are notified at each step by email and in-app.')}
`); } /* ================= Market Maker — live contracts ================= */ async function viewMmPost(){ setActiveMenu(null); win('Post a two-way quote','bid ≤ ask; posting replaces your live quote', `
`, true); } async function doMmPost(){ const m=document.getElementById('mmOut'); const {status,j}=await api('/api/v1/market-maker/quotes/post/',{method:'POST',body:JSON.stringify({ bid_inr_per_g:val('mmBid'),ask_inr_per_g:val('mmAsk'),size_g:val('mmSize')})}); m.className=status<300?'msg ok':'msg err'; m.textContent=(j&&(j.message||j.error||('Quote v'+(j.version||'')+' posted.')))||(status<300?'Quote posted.':'Failed.'); } async function viewMmQuotes(){ setActiveMenu('dashboard'); const {status,j}=await api('/api/v1/market-maker/quotes/mine/'); win(esc(j&&j.title||'My quotes'),'', `${status===200?tbl(j.columns,j.rows):nodata('Could not load quotes.')}
`); } async function viewMmInventory(){ setActiveMenu(null); const {status,j}=await api('/api/v1/market-maker/inventory/'); if(status!==200||!j) return win('My inventory','',nodata('Inventory unavailable.')); win('My inventory / position','', `
Net position
${esc(j.net_grams)} g
Avg cost
₹${esc(j.avg_cost_inr_per_g)}
per gram
Marked value
₹${esc(j.marked_value_inr||'—')}
at ₹${esc(j.benchmark_now||'—')}/g (${esc(j.rate_source)})
`); } /* ================= Consultant — live contracts ================= */ async function viewCnProfile(){ setActiveMenu(null); const {j}=await api('/api/v1/consultant/profile/'); const p=j||{}; win('My consultant profile','maintain your directory listing', `
`, true); } async function doCnProfile(){ const m=document.getElementById('cnOut'); const {status,j}=await api('/api/v1/consultant/profile/',{method:'POST',body:JSON.stringify({ professional_name:val('cnName'),qualification:val('cnQual'), years_experience:parseInt(val('cnYrs')||'0'),hourly_rate_inr:val('cnRate'), areas_of_practice:val('cnAreas')})}); m.className=status<300?'msg ok':'msg err'; m.textContent=(j&&(j.status?('Profile saved ('+j.status+').'):(j.message||j.error)))||(status<300?'Saved.':'Save failed.'); } async function viewCnDirectory(){ setActiveMenu(null); const {status,j}=await api('/api/v1/consultant/directory/'); win(esc(j&&j.title||'Consultant directory'),'', `${status===200?tbl(j.columns,j.rows):nodata('Directory unavailable.')}
`); } async function viewCnTasks(){ setActiveMenu('dashboard'); const {status,j}=await api('/api/v1/consultant/tasks/'); win(esc(j&&j.title||'My tasks'),'OPEN → IN_PROGRESS → COMPLETED', `${status===200?tbl(j.columns,j.rows):nodata('No profile yet — create your profile first.')}
`); } /* ---------- Ask-me — HOOK wired to the live service ---------- */ const ASKME_ENDPOINT='/api/v1/ask/'; function viewAskme(){ win('Ask me','ask a question — the answer appears here, then ask another', `
Ask anything about the platform. After each answer you can ask another question.
`); renderThread(); const b=document.getElementById('askBody'); b.focus(); b.onkeydown=e=>{ if(e.key==='Enter') submitAsk(); }; } function renderThread(){ const t=document.getElementById('thread'); if(!t) return; t.innerHTML=askThread.map(x=>'
'+esc(x.q)+'
'+esc(x.a)+'
').join(''); t.scrollTop=t.scrollHeight; } async function submitAsk(){ const b=document.getElementById('askBody'); const q=b.value.trim(); if(!q) return; b.value=''; askThread.push({q,a:'…'}); renderThread(); const {j}=await api(ASKME_ENDPOINT,{method:'POST',body:JSON.stringify({question:q,screen_path:location.pathname})}); askThread[askThread.length-1].a=(j&&(j.answer||j.detail))||'The Ask-me service could not answer just now.'; renderThread(); } document.getElementById('askInput').addEventListener('keydown',e=>{ if(e.key==='Enter'){ const q=e.target.value.trim(); if(!q) return; e.target.value=''; setActiveMenu(null); if(!document.getElementById('thread')) viewAskme(); askThread.push({q,a:'…'}); renderThread(); api(ASKME_ENDPOINT,{method:'POST',body:JSON.stringify({question:q,screen_path:location.pathname})}) .then(({j})=>{ askThread[askThread.length-1].a=(j&&(j.answer||j.detail))||'No answer available.'; renderThread(); }); } }); /* ---------- menu routing (menu items IDENTICAL for every user) ---------- */ // Menu pages load the ACTUAL original files unchanged, inside the window (iframe). const MENU_SRC = { 'About':'about.html', 'Governance':'governance.html', 'Products':'landing.html#products', 'How it works':'landing.html#how-it-works', 'Contact':'landing.html#contact', 'FAQs':'landing.html#faqs' }; // Open a real, working standalone page inside the shell window, unchanged (iframe). function viewPage(title, src){ win(title,'', ``); const f=document.getElementById('pageFrame'); if(f) f.onload=function(){ stripFrameChrome(f); }; } function stripFrameChrome(f){ try{ var d=f.contentWindow.document; var css=d.createElement('style'); css.textContent='header,nav,.nav,header.irg-header,.gdp-foot,nav.landing-menu,.legal-footer,.footer-contact,.irg-brand{display:none!important}'+'body{margin:0!important;padding:16px 20px!important;background:#fff!important}'; d.head.appendChild(css); f.style.height=(d.body.scrollHeight+30)+'px'; }catch(e){} } const MENU_HTML={ "About":`

About Us

Intech Research Group (IRG) operates the IRG-FTR exchange in India under a perpetual licence from the IPR holder. The platform is a Blockchain-registered right to buy services or goods at a pre-fixed price any time in the future, designed for households and institutions seeking to hedge tomorrow's costs at today's rates.

Our Objective

To build a trustworthy borderless system through which global households can buy FTRs with an assurance of the underlying assets, goods, and services in the future at their hedged prices — with an option to exit with liquidity at reasonable returns. The platform is operated as a sustainable business with global reach.

How We Achieve It

  • Corpus Fund Escrow. Payments to buy FTR units are credited to a ring-fenced Corpus Fund Escrow bank account. Withdrawals are permitted only for declared and vetted purposes.
  • Recall compensation. Where a service provider defaults, the FTR terms provide for return of investment with a minimum assured return. Multiple system cross-checks safeguard the payment.
  • Vetted projects. A network of reputed professionals — legal, financial, sectoral — vet every project. The platform rates them on performance; rating drives future allocation.
  • Market makers. IRG Portal Associate licences are issued without fee or deposit to qualified parties with earmarked funds in their own Corpus Fund Escrow accounts. They stand as ready buyers of FTRs to assure perpetuity.
  • Ombudsman remedy. Any participant can file a grievance online with the Ombudsman — former judicial persons — whose orders dispose of disputes and claims within the system.
  • System-driven exchange. Cross-checks at every stage validate transactions before they take effect, protecting the retail investor.

Transparency & Security

  • Blockchain registration. Every FTR unit is registered on the chain and dealings are anchored to it; the unit cannot be altered without an on-chain audit trail.
  • Lifetime support. Core technology is sourced from a well-established associate with knowledge-and-data-transfer provisions covering existential events, guaranteeing continuity.
  • Standardised contracts. Every contract is standardised, signed electronically, and deposited in a Digital Locker — reducing dispute surface and protecting both sides.
  • Public reporting. Policies, audit reports, project vetting reports, and contacts are viewable on the portal subject to applicable privacy laws.

Decentralized Management

The platform pursues maximum automation of portal operations. The FTRs, the IRG Portal, and the system with its built-in cross-checks are defined in the treatise IRG System — Redefining the World of Finance. The IPR holder has assigned operational rights perpetually to establish and run the exchange. A standing Trust (see Governance) holds the operating mandate and is bound by the system's hardcoded provisions.

IPR Holder

Rohit Jayant Tidke

Software engineer by profession, with a deep interest in networked businesses and finance. Graduate in Automation & Controls from Moscow Aviation Institute; Master's in Computer Science from the Technical University of Munich, Germany.

His study of multiple industries, service, and trade sectors operating across different business environments shaped the system requirements — with embedded risk assessment and safety measures designed to protect the interest of household retail investors. He is the author of the treatise IRG System — Redefining the World of Finance, and the holder of the Intellectual Property Rights in the IRG-FTR system and its products. The rights have been exclusively assigned to Intech Research Group for operations.

`, "Governance":`

Governance

The IRG-FTR platform is operated by a standing Trust under a perpetual licence from the IPR holder. The Trust is bound by the system's hardcoded provisions, by an independent Advisory Board, and by a regional Ombudsman network — with every parameter change anchored on chain.

Trust Structure

The platform is operated by a Private Irrevocable Specific Trust constituted under the Indian Trusts Act, 1882.

It is framed as a maintenance / obligation trust — not a benefit trust. Royalty inflows are a first charge against the discharge of the maintenance obligations hardcoded into the IRG applications. Only the residue, if any, accrues to the named beneficiaries.

  • The Settlor settles the corpus irrevocably and retains no power of revocation or amendment.
  • The beneficiaries' interest is residual only — they have no right to compel distribution out of step with the maintenance obligation and play no role in management.
  • Income of the Trust is determinate (50:50 between the named beneficiaries) and is assessed in the beneficiaries' hands under section 161(1) of the Income-tax Act, 1961.

Independence from the IPR Holder

The IPR holder, Rohit Jayant Tidke, and the licensor entity hold no office of management in the Trust, exercise no veto, and retain no ongoing approval right over operations.

The licence granted to the Trust is a one-time, perpetual, non-revocable licence. The arrangement creates no agency, employment, or fiduciary relationship between the licensor and the Trust. The IPR holder bears no warranty, support, or indemnity obligation to the Trust or any third party.

Board of Trustees — Structure

The Board of Trustees is composed of independent professionals. The beneficiaries are excluded from management to preserve the determinate-trust character and avoid look-through under sections 60–63 of the Income-tax Act.

  • One Managing Trustee — an independent senior professional (chartered accountant or retired civil servant).
  • Two further independent Trustees of differing professional backgrounds (typically legal and technology).
  • One Trustee-Banker — chartered accountant or banker, who handles the Trust's financial operations.

Advisory Board — Structure

The Advisory Board is composed of noted domain experts drawn from the sectors the platform serves. It advises the Trust on policy and major operational matters. The Advisory Board's resolutions on parameter changes are binding within the system.

  • Members are individually insulated from liability for collective decisions — encouraging prudent, candid counsel.
  • Procedures for meetings, agendas, quorums, decision-making, and record-keeping are pre-defined and audit-anchored.
  • Changes to terms of appointment, remuneration, and removal are subject to an order of the Ombudsman — not to discretion of the management.

The Seven Roles

The system recognises seven operational roles — constitutional, defined in code, and enforced by the Change Protocol.

RoleAuthority
ADMINOperates the platform. May propose; may approve where Admin is the named approver. Must apply approved proposals.
OPERATORDay-to-day operator. May propose; co-signs live-cutover changes.
GOVERNANCE VOTERVotes YES / NO on proposals where the lock-status requires a vote.
DOMAIN CONSULTANTVRF-selected sectoral expert. Signs proposals requiring domain approval.
OMBUDSMANIndependent oversight. Signs proposals reserved to the Ombudsman; adjudicates disputes.
CHAIN COORDINATORValidator-restart coordinator. Co-signs hard-fork proposals.
AUDITORRead-only. Views all parameters, proposals, history, and chain anchors.

Parameter Change Protocol

No parameter, threshold, fee, or rule may be changed except through the protocol: PROPOSE → APPROVE → APPLY. Every transition is anchored on the IRG chain. The protocol cannot be bypassed by direct edits, side letters, or extrinsic agreements.

Lock-statusApproval policy
Editable1 Admin (not the proposer)
Editable (Gov Vote)Majority of registered Governance Voters
Editable (Domain Vote)1 VRF-selected Domain Consultant
Editable (Ombudsman)1 Ombudsman
Editable (Hard fork)1 Admin + 1 Chain Coordinator
Editable (Live cutover)1 Admin + 1 Operator
StatutorySystem auto-applies on gazette publication; Admin confirms
LockedCannot be changed via protocol — requires constitutional supermajority and chain hard-fork

Ombudsman

The Ombudsman is the independent grievance, dispute, and re-mint authority. Appointments are regional and common to every IRG application. Each appointment is registered on chain in the OmbudsmanRegistry — a constitutional act of the Trust under a resolution of the Advisory Board.

  • Case assignment uses on-chain VRF to remove discretion.
  • Orders are final within the system; aggrieved parties retain recourse to a court of competent jurisdiction.
  • Ombudsmen are former judicial persons, appointed for their experience and independence.

Regulatory Position

The Trust is deed-bound to maintain the platform's regulatory disclaimers:

  • SEBI — the FTR is not a Collective Investment Scheme. No returns are promised. The residue release to beneficiaries is a residual distribution after maintenance, not a yield.
  • RBI — the platform is not a payment intermediary or payment aggregator. Settlement roles lie with the seller, the buyer, and the regulated payment service.
  • Virtual Digital Assets — the FTR is not a digital asset or cryptocurrency. It is a registered Right to buy services or goods at a pre-fixed price.

Audit & Disclosure

  • The Trust maintains audited accounts annually, with a summary published on the platform within ninety days of fiscal year-end.
  • Every parameter change, ombudsman order, advisory board resolution, and royalty inflow is published as a chain-anchored event in the public audit trail.
  • Policies, audit reports, and project vetting reports are viewable on the platform subject to applicable privacy laws.
`, "Products":`
IRG-GDP
Gold-Denominated Product — the core
Blockchain-registered Right to swap for any FTR valued at its Benchmark value, or resell it at any time, from anywhere. FTR is your right to buy a service or goods on certain terms and at a pre-fixed rate anytime in the future.
irg_jr
Jewellery Return
Freely tradable right backed by gold from pre-owned jewellery returned for value.
irg_jdb
Jewellery Design Bank
Freely tradable right backed by curated jewellery design templates available to designers and households.
irg_gic
GDP Incentive Coupon
Contractual right to acquire IRG-GDPs on the platform's terms when exercised.
`, "How it works":`

Swap is the heart of it

One IRG-GDP unit can be swapped for any of 45+ FTR categories — to access a wide range of services or goods at a pre-fixed rate, anytime in the future. Or, resell at the published Benchmark, anytime, from anywhere. You stay in control.

`, "Contact":`
Contact: support@trotdfx.com • Website: www.trotdfx.com
`, "FAQs":`

Have a question?

Use the Ask button in the bottom-right corner. It answers any question about IRG-GDP, FTRs, swaps, audits, taxes, security, and how the platform works — drawing from the IRG-GDP whitepaper, taxonomy, and system note.

`, }; function viewGeneric(t){ const html = MENU_HTML[t]; if(!html){ win(t,'', ``); return; } win(t,'', ``); } function setActiveMenu(view){ document.querySelectorAll('#menu a').forEach(a=>a.classList.toggle('active', a.dataset.view===view)); } document.getElementById('menu').addEventListener('click', function(e){ var a = e.target.closest('a[data-view]'); if(!a) return; e.preventDefault(); var v = a.dataset.view; setActiveMenu(v); document.getElementById('menu').classList.remove('open'); if(v==='dashboard') viewDashboard(); else viewGeneric(a.textContent.trim()); }); document.querySelectorAll('.group>button').forEach(b=>{ b.onclick=()=>b.parentElement.classList.toggle('open'); }); document.getElementById('hamb').onclick=()=>document.getElementById('menu').classList.toggle('open'); /* ---------- init ---------- */ renderRail(); // ── Enter-to-submit for all auth forms (inputs are injected into #window dynamically) ── (function(){ // For OTP/verify we need the current email+purpose; doVerify reads them from the DOM/state, // but the button passes them inline — so for Enter we call a wrapper that reconstructs them. function submitForInput(id){ switch(id){ case 'siEmail': case 'siPass': return doLogin(); case 'otpVal': return doVerify(S.lastEmail||'', S.otpPurpose||'LOGIN_2FA'); case 'rgPw': case 'rgPw2': return doRegisterSubmit(); case 'cpEmail': /* on the change-password form, Enter in email sends the code */ return cpSend(); case 'cpOtp': case 'cpNew': case 'cpNew2': return cpApply(); default: return null; } } document.addEventListener('keydown', function(e){ if(e.key !== 'Enter') return; var el = e.target; if(!el || el.tagName !== 'INPUT') return; var id = el.id; // only act on known auth inputs; leave everything else (e.g. Ask box) to its own handler if(['siEmail','siPass','otpVal','rgPw','rgPw2','cpEmail','cpOtp','cpNew','cpNew2'].indexOf(id) === -1) return; e.preventDefault(); try{ submitForInput(id); }catch(_){} }); })(); // Route on load: ?register (or #register) opens registration in the shell; otherwise dashboard/sign-in. (function(){ var q = location.search, h = location.hash; var wantRegister = /(^|[?&])register(=|&|$)/.test(q) || h==='#register'; var wantForgot = /(^|[?&])forgot(=|&|$)/.test(q) || h==='#forgot'; if(S.token){ viewDashboard(); } else if(wantRegister){ viewRegisterInfo(); } else if(wantForgot){ viewSignin(); setTimeout(function(){ try{ viewChangePassword(); }catch(_){} },0); } else { viewSignin(); } })();