Subcribe to our Newsletter

Less scrolling. More shaping. Express By GLSN is for architects, educators, designers, and leaders exploring the world of learning spaces. Subscribe and enjoy front-row access to the world’s most impactful projects, ideas, and insights, curated by GLSN.

(function () { 'use strict'; function boot() { if (!document.getElementById('pulse-reg')) return; if (window.__pulseRegBooted) return; window.__pulseRegBooted = true; ensureRazorpay(start); } function ensureRazorpay(done) { if (window.Razorpay) { done(); return; } var existing = document.querySelector('script[src*="checkout.razorpay.com/v1/checkout.js"]'); if (existing) { existing.addEventListener('load', done); setTimeout(done, 4000); return; } var s = document.createElement('script'); s.src = 'https://checkout.razorpay.com/v1/checkout.js'; s.onload = done; s.onerror = function () { done(); }; document.head.appendChild(s); }function start() { (function darkWatch(){ var root = document.getElementById('pulse-reg'); if (!root) return;function luminance(rgb){ var m = String(rgb).match(/(\d+(?:\.\d+)?)/g); if (!m || m.length < 3) return null; if (m.length > 3 && parseFloat(m[3]) === 0) return null; var r = +m[0], g = +m[1], b = +m[2]; return (0.2126 * r + 0.7152 * g + 0.0722 * b) / 255; } function pageIsDark(){ var el = root.parentNode; while (el && el.nodeType === 1) { var l = luminance(getComputedStyle(el).backgroundColor); if (l !== null) return l < 0.5; el = el.parentNode; } var lb = luminance(getComputedStyle(document.body).backgroundColor); if (lb !== null) return lb < 0.5; return window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches; }function sync(){ try { root.classList.toggle('is-dark', pageIsDark()); } catch (e) {} }sync(); setTimeout(sync, 400); if (window.MutationObserver) { var mo = new MutationObserver(function(){ setTimeout(sync, 30); }); var opts = { attributes:true, attributeFilter:['class','data-scheme','data-theme','style'] }; mo.observe(document.documentElement, opts); if (document.body) mo.observe(document.body, opts); } if (window.matchMedia) { var mq = window.matchMedia('(prefers-color-scheme: dark)'); if (mq.addEventListener) mq.addEventListener('change', sync); } })();const CONFIG = { KEY_ID: '', // server create-order response se aata hai (key_id) ORDER_ENDPOINT: 'https://theglsn.com/wp-json/glsn/v1/create-order', VERIFY_ENDPOINT: 'https://theglsn.com/wp-json/glsn/v1/verify-payment', COUPON_ENDPOINT: 'https://theglsn.com/wp-json/glsn/v1/validate-coupon', THANKYOU_URL: '/pulse-2026-registered/' };const server = (() => { const PASS = { educator_none: { base:12500, label:'Conference pass' }, educator_n1: { base:25000, label:'Regular pass · 1 night' }, educator_n2: { base:35000, label:'Regular Plus pass · 2 nights' }, industry_none: { base:50000, label:'Industry delegate pass' }, industry_n1: { base:62500, label:'Industry pass · 1 night' }, industry_n2: { base:72500, label:'Industry pass · 2 nights' } }; const GST = 0.18; const COUPONS = [ { code:'EARLY20', type:'percent', value:20, applies_to:['*'], valid_until:'2026-09-30', max_redemptions:200, times_used:34, blurb:'20% off any pass', restriction:'Until 30 Sept' },{ code:'CIVOM26', type:'flat', value:5000, applies_to:['*'], valid_until:'2026-10-04', max_redemptions:25, times_used:11, owner:'CIVOM sponsor allocation', blurb:'\u20B95,000 off', restriction:'25 uses, 11 gone' },{ code:'PLUS15', type:'percent', value:15, applies_to:['educator_n2'], valid_until:'2026-10-04', max_redemptions:60, times_used:3, blurb:'15% off', restriction:'Regular Plus only' },{ code:'GROUP6', type:'percent', value:12, applies_to:['*'], min_qty:6, valid_until:'2026-10-04', max_redemptions:999, times_used:0, blurb:'12% off', restriction:'Six delegates or more' },{ code:'SPEAKER26', type:'override', value:0, applies_to:['*'], valid_until:'2026-10-04', max_redemptions:44, times_used:44, blurb:'Full comp', restriction:'All 44 used up' },{ code:'PULSE2025', type:'percent', value:25, applies_to:['*'], valid_until:'2025-11-04', max_redemptions:500, times_used:120, blurb:'25% off', restriction:'Expired last year' } ];const today = () => new Date('2026-09-03'); // fixed so the prototype is stablefunction find(code){ const c = String(code || '').trim().toUpperCase(); return COUPONS.find(x => x.code === c) || null; } function eligible(c, passId, qty){ if (!c) return 'That code isn\u2019t valid for this booking.'; if (new Date(c.valid_until) < today()) return 'That code has expired.'; if (c.times_used >= c.max_redemptions) return 'That code has been fully claimed.'; if (!c.applies_to.includes('*') && !c.applies_to.includes(passId)) return 'That code doesn\u2019t apply to the pass you\u2019ve chosen.'; if (c.min_qty && qty < c.min_qty) return `That code needs ${c.min_qty} delegates or more.`; return null; } function quote({ who, stay, qty, code }){ const passId = `${who}_${stay}`; const pass = PASS[passId]; if (!pass) return { error:'Unknown pass.' };const n = Math.max(1, Math.min(20, parseInt(qty, 10) || 1)); const gross = pass.base * n;let discount = 0, applied = null, reason = null;if (code) { const c = find(code); const bad = eligible(c, passId, n); if (bad) { reason = bad; } else { if (c.type === 'percent') discount = Math.round(gross * c.value / 100); if (c.type === 'flat') discount = Math.min(c.value * 100 / 100, gross); if (c.type === 'override') discount = Math.max(0, gross - c.value * n); applied = { code:c.code, blurb:c.blurb }; } }const net = gross - discount; const gst = Math.round(net * GST);return { pass_id:passId, label:pass.label, qty:n, gross, discount, net, gst, total:net + gst, coupon:applied, reason }; } function createOrder(sel){ const q = quote(sel); if (q.error || q.reason) return { error:q.error || q.reason }; return { order_id:'order_' + Math.random().toString(36).slice(2, 16), amount:q.total * 100, currency:'INR', notes:{ pass_id:q.pass_id, qty:q.qty, coupon:q.coupon?.code || '', discount:q.discount } }; }return { quote, createOrder, catalogue:() => COUPONS }; })();const ROOT = document.getElementById('pulse-reg'); const $ = s => ROOT.querySelector(s); const $$ = s => ROOT.querySelectorAll(s); const inr = n => '\u20B9' + n.toLocaleString('en-IN');const state = { who:'educator', stay:'none', qty:1, code:null };const els = { total:$('#total'), lines:$('#lines'), pay:$('#payBtn'), cInput:$('#cInput'), cApply:$('#cApply'), cMsg:$('#cMsg'), cChip:$('#cChip'), cChipCode:$('#cChipCode'), cChipDesc:$('#cChipDesc'), cRemove:$('#cRemove'), cRow:$('#couponRow'), qOut:$('#qOut'), qMinus:$('#qMinus'), qPlus:$('#qPlus'), groupNote:$('#groupNote') };function render(){ const q = currentQuote();els.total.classList.add('flash'); setTimeout(() => { els.total.textContent = inr(q.total); els.total.classList.remove('flash'); }, 90);const rows = [ `
${q.label}${q.qty > 1 ? ' × ' + q.qty : ''}${inr(q.gross)}
` ]; if (q.discount > 0) { rows.push(`
${q.coupon.code}−${inr(q.discount)}
`); } rows.push(`
GST at 18%${inr(q.gst)}
`); rows.push(`
Total${inr(q.total)}
`); els.lines.innerHTML = rows.join('');els.pay.textContent = 'Pay ' + inr(q.total); els.pay.disabled = q.total === 0 && !q.coupon; if (state.code && q.reason) { showChip(null); msg(q.reason, 'bad'); els.cInput.value = state.code; state.code = null; } else if (q.coupon) { showChip(q.coupon); }els.groupNote.classList.toggle('on', state.qty >= 6 && state.code !== 'GROUP6'); }function msg(text, kind){ els.cMsg.textContent = text || ''; els.cMsg.className = 'cmsg' + (kind ? ' ' + kind : ''); if (text) { try { els.cMsg.scrollIntoView({ block:'center', behavior:'smooth' }); } catch (e) {} } }function showChip(coupon){ if (coupon) { els.cChipCode.textContent = coupon.code; els.cChipDesc.textContent = coupon.blurb; els.cChip.classList.add('on'); els.cRow.style.display = 'none'; els.cInput.value = ''; } else { els.cChip.classList.remove('on'); els.cRow.style.display = 'flex'; } }function selKey(){ return state.who + '|' + state.stay + '|' + state.qty + '|' + (state.code || ''); } function shapeRemote(b){ return { _k:selKey(), label:b.label, qty:b.qty, gross:b.gross, discount:b.discount, gst:b.gst, total:b.total, reason:null, coupon: b.coupon ? { code:b.coupon, blurb:'Discount applied' } : null }; } function currentQuote(){ return (state.remote && state.remote._k === selKey()) ? state.remote : server.quote(state); }async function revalidate(){ if (!state.code || !CONFIG.COUPON_ENDPOINT) { render(); return; } try { const res = await fetch(CONFIG.COUPON_ENDPOINT, { method:'POST', headers:{ 'Content-Type':'application/json' }, credentials:'same-origin', body:JSON.stringify({ who:state.who, stay:state.stay, qty:state.qty, code:state.code }) }); const body = await res.json().catch(() => ({})); if (res.ok) { state.remote = shapeRemote(body); } else { const c = state.code; state.remote = null; state.code = null; showChip(null); els.cInput.value = c; msg(body.message || 'That code no longer applies to this selection.', 'bad'); } } catch (err) { } render(); }function serverMsg(body, res){ var raw = (body && body.message) ? String(body.message) : ''; if (/<[a-z][\s\S]*>/i.test(raw)) { console.error('PULSE server error (HTTP ' + (res ? res.status : '?') + '):', raw); return 'Server par technical error hai. Ye code ki galti nahi hai - hum dekh rahe hain.'; } return raw; }async function apply(){ const raw = els.cInput.value.trim(); if (!raw) { msg('Enter a code first.', 'bad'); els.cInput.focus(); return; }els.cApply.disabled = true; els.cApply.textContent = 'Checking'; const done = () => { els.cApply.disabled = false; els.cApply.textContent = 'Apply'; };if (!CONFIG.COUPON_ENDPOINT) { setTimeout(() => { done(); const test = server.quote({ ...state, code:raw }); if (test.reason) { msg(test.reason, 'bad'); return; } state.code = raw.toUpperCase(); msg('Code applied. ' + inr(test.discount) + ' off before GST.', 'good'); render(); }, 380); return; }try { const res = await fetch(CONFIG.COUPON_ENDPOINT, { method:'POST', headers:{ 'Content-Type':'application/json' }, credentials:'same-origin', body:JSON.stringify({ who:state.who, stay:state.stay, qty:state.qty, code:raw }) }); const body = await res.json().catch(() => ({})); done(); if (!res.ok) { msg(serverMsg(body, res) || 'That code isn\u2019t valid for this booking.', 'bad'); return; } state.code = raw.toUpperCase(); state.remote = shapeRemote(body); msg('Code applied. ' + inr(body.discount) + ' off before GST.', 'good'); render(); } catch (err) { done(); msg('We couldn\u2019t check that code. Try again.', 'bad'); } }$$('input[name=who]').forEach(r => r.addEventListener('change', e => { state.who = e.target.value; revalidate(); }) ); $$('input[name=stay]').forEach(r => r.addEventListener('change', e => { state.stay = e.target.value; revalidate(); }) );els.qMinus.addEventListener('click', () => { state.qty = Math.max(1, state.qty - 1); els.qOut.textContent = state.qty; els.qMinus.disabled = state.qty === 1; revalidate(); }); els.qPlus.addEventListener('click', () => { state.qty = Math.min(20, state.qty + 1); els.qOut.textContent = state.qty; els.qMinus.disabled = false; revalidate(); }); els.qMinus.disabled = true;els.cApply.addEventListener('click', apply); els.cInput.addEventListener('keydown', e => { if (e.key === 'Enter') { e.preventDefault(); apply(); } }); els.cRemove.addEventListener('click', () => { state.code = null; state.remote = null; showChip(null); msg(''); render(); els.cInput.focus(); });function delegate(){ return { name: $('#fName').value.trim(), org: $('#fOrg').value.trim(), email: $('#fEmail').value.trim(), phone: $('#fPhone').value.trim(), role: $('#fRole').value, city: $('#fCity').value.trim() }; }function busy(on, text){ els.pay.disabled = on; els.pay.textContent = on ? (text || 'Opening Razorpay') : 'Pay ' + inr(server.quote(state).total); }async function requestOrder(person){ if (!CONFIG.ORDER_ENDPOINT) return server.createOrder(state);const res = await fetch(CONFIG.ORDER_ENDPOINT, { method:'POST', headers:{ 'Content-Type':'application/json' }, credentials:'same-origin', body:JSON.stringify({ ...state, delegate:person }) }); if (!res.ok) { const body = await res.json().catch(() => ({})); return { error:serverMsg(body, res) || 'We couldn\u2019t start the payment. Try again in a moment.' }; } return res.json(); }function openCheckout(order, person){ const q = currentQuote();const options = { key: order.key_id || CONFIG.KEY_ID, currency: order.currency || 'INR', name: 'PULSE 2026', description: q.label + (q.qty > 1 ? ' \u00D7 ' + q.qty : ''), prefill: { name:person.name, email:person.email, contact:person.phone }, notes: order.notes || {}, theme: { color:'#F68080' }, modal: { ondismiss(){ busy(false); msg('Payment cancelled. Your selection is still here when you\u2019re ready.', 'bad'); } }, handler(response){ busy(true, 'Confirming'); confirmPayment(response); } }; if (order.order_id && CONFIG.ORDER_ENDPOINT) options.order_id = order.order_id; else options.amount = order.amount;const rzp = new Razorpay(options);rzp.on('payment.failed', e => { busy(false); const d = e.error || {}; msg(d.description || 'That payment didn\u2019t go through. Try another method.', 'bad'); console.warn('Razorpay failure', d.code, d.step, d.reason, d.metadata); });rzp.open(); }async function confirmPayment(response){ if (!CONFIG.VERIFY_ENDPOINT) { busy(false); msg('Demo mode: payment id ' + response.razorpay_payment_id + '. No pass issued.', 'good'); return; } try { const res = await fetch(CONFIG.VERIFY_ENDPOINT, { method:'POST', headers:{ 'Content-Type':'application/json' }, credentials:'same-origin', body:JSON.stringify(response) }); const body = await res.json(); if (res.ok && body.verified) { window.location.href = CONFIG.THANKYOU_URL + '?ref=' + encodeURIComponent(body.reference); } else { busy(false); msg('We\u2019ve taken your payment but couldn\u2019t confirm it on our side. ' + 'Keep reference ' + response.razorpay_payment_id + ' and email pulse@theglsn.com.', 'bad'); } } catch (err) { busy(false); msg('Payment went through but confirmation timed out. Keep reference ' + response.razorpay_payment_id + ' \u2014 we\u2019ll email your pass shortly.', 'bad'); } }els.pay.addEventListener('click', async (ev) => { if (ev && ev.preventDefault) ev.preventDefault(); try { const missing = [['#fName','name'],['#fOrg','organisation'],['#fEmail','email'],['#fPhone','phone']] .filter(([sel]) => !$(sel).value.trim()); if (missing.length) { msg('Add your ' + missing.map(m => m[1]).join(', ') + ' to continue.', 'bad'); $(missing[0][0]).focus(); return; } const person = delegate(); if (!/^\S+@\S+\.\S+$/.test(person.email)) { msg('Check that email address \u2014 your pass gets sent there.', 'bad'); $('#fEmail').focus(); return; } if (typeof Razorpay === 'undefined') { msg('Payment couldn\u2019t load. Check your connection or any ad blocker, then try again.', 'bad'); return; }msg(''); busy(true);const order = await requestOrder(person); if (order.error) { busy(false); msg(order.error, 'bad'); return; } if (!order.key_id && !CONFIG.KEY_ID) { busy(false); msg('Server ne Razorpay key nahi bheji. Plugin ki keys check karao.', 'bad'); return; } openCheckout(order, person); } catch (err) { busy(false); msg('Technical error: ' + (err && err.message ? err.message : err), 'bad'); console.error('PULSE pay handler', err); } });(function selfTest(){ const tag = document.createElement('p'); tag.className = 'secure'; tag.style.opacity = '.55'; tag.textContent = 'build v5'; els.pay.parentNode.appendChild(tag); const parentForm = els.pay.closest('form'); if (parentForm) { tag.textContent = 'build v5 — form ke andar hai (handle kar liya)'; console.warn('PULSE: registration block is inside a
', parentForm); }setTimeout(() => { const r = els.pay.getBoundingClientRect(); if (!r.width || !r.height) return; // abhi screen par nahi hai const top = document.elementFromPoint(r.left + r.width / 2, r.top + r.height / 2); if (top && top !== els.pay && !els.pay.contains(top)) { tag.textContent = 'build v5 — button ke upar kuch aur hai: ' + (top.id ? '#' + top.id : top.className || top.tagName); tag.style.color = '#FFA8A8'; tag.style.opacity = '1'; console.warn('PULSE: overlay covering Pay button', top); } }, 1500); })();render();}if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', boot); } else { boot(); } })(); If you are using the jQuery library, then don't forget to wrap your code inside jQuery.ready() as follows:jQuery(document).ready(function( $ ){ // Your code in here });--If you want to link a JavaScript file that resides on another server (similar to ), then please use the "Add HTML Code" page, as this is a HTML code that links a JavaScript file.End of comment */
© 2026 GLSN. All rights reserved.