@import url(‘https://fonts.googleapis.com/css2?family=Instrument+Serif:ital@0;1&family=Inter:wght@400;500;600&family=IBM+Plex+Mono:wght@400;500&display=swap’); #ezh{ –ink:#14161A; –ink-soft:#54595F; –line:#DFDDD6; –paper:#FFFFFF; –stone:#F2F1ED; –red:#C61830; –red-deep:#8E1123; –moss:#3F5D45; –ok:#1E6B4F; –serif:’Instrument Serif’,Georgia,serif; –sans:’Inter’,system-ui,-apple-system,sans-serif; –mono:’IBM Plex Mono’,ui-monospace,monospace; all:initial; display:block; font-family:var(–sans); color:var(–ink); font-size:16px; line-height:1.55; -webkit-font-smoothing:antialiased; text-align:left; } #ezh *,#ezh *::before,#ezh *::after{box-sizing:border-box;} #ezh p,#ezh h1,#ezh h2,#ezh h3,#ezh ul,#ezh li,#ezh figure{margin:0;padding:0;} #ezh ul{list-style:none;} #ezh button{font:inherit;color:inherit;background:none;border:none;cursor:pointer;} #ezh input,#ezh select{font:inherit;color:inherit;} #ezh :focus-visible{outline:2px solid var(–red);outline-offset:2px;} #ezh .wrap{max-width:940px;margin:0 auto;padding:8px 16px 56px;} /* ── masthead ─────────────────────────────────────────────── */ #ezh .top{padding:28px 0 22px;border-bottom:1px solid var(–line);} #ezh .eyebrow{font-family:var(–mono);font-size:11px;letter-spacing:.16em; text-transform:uppercase;color:var(–red);} #ezh .top h2{font-family:var(–serif);font-size:clamp(30px,6vw,46px); line-height:1.05;font-weight:400;margin-top:10px;letter-spacing:-.01em;} #ezh .top p{color:var(–ink-soft);margin-top:10px;max-width:52ch;font-size:15px;} /* ── the search bar ───────────────────────────────────────── */ #ezh .search{background:var(–stone);border:1px solid var(–line); border-radius:3px;padding:18px;margin-top:24px; display:grid;gap:14px;grid-template-columns:1fr 1fr;} #ezh .search .full{grid-column:1/-1;} #ezh label{display:block;font-family:var(–mono);font-size:11px; letter-spacing:.1em;text-transform:uppercase;color:var(–ink-soft); margin-bottom:6px;} #ezh input[type=date],#ezh input[type=text],#ezh input[type=tel], #ezh input[type=email],#ezh select{ width:100%;padding:11px 12px;border:1px solid var(–line); border-radius:2px;background:var(–paper);} #ezh .stepper{display:flex;align-items:stretch;border:1px solid var(–line); border-radius:2px;background:var(–paper);overflow:hidden;} #ezh .stepper button{width:44px;font-size:18px;color:var(–ink-soft);} #ezh .stepper button:hover{background:var(–stone);color:var(–ink);} #ezh .stepper span{flex:1;display:flex;align-items:center;justify-content:center; font-family:var(–mono);font-size:15px;} #ezh .nights{font-family:var(–mono);font-size:12px;color:var(–ink-soft); grid-column:1/-1;margin-top:-4px;} /* ── rooms ────────────────────────────────────────────────── */ #ezh .sec{margin-top:36px;} #ezh .sec > h3{font-family:var(–serif);font-size:26px;font-weight:400; margin-bottom:4px;} #ezh .sec > .note{color:var(–ink-soft);font-size:14px;margin-bottom:18px;} #ezh .rooms{display:grid;gap:14px;grid-template-columns:repeat(auto-fill,minmax(280px,1fr));} #ezh .room{border:1px solid var(–line);border-radius:3px;overflow:hidden; background:var(–paper);display:flex;flex-direction:column; transition:border-color .15s,box-shadow .15s;} #ezh .room.on{border-color:var(–red);box-shadow:0 0 0 1px var(–red);} #ezh .room.out{opacity:.5;} /* the photo slot — a tinted panel until a real photograph exists */ #ezh .shot{aspect-ratio:4/3;background:var(–stone);position:relative; display:flex;align-items:flex-end;padding:12px;overflow:hidden;} #ezh .shot img{position:absolute;inset:0;width:100%;height:100%; object-fit:cover;} #ezh .shot .thinai{position:relative;font-family:var(–serif);font-style:italic; font-size:19px;color:var(–moss);} #ezh .shot.has .thinai{display:none;} #ezh .room .body{padding:14px;display:flex;flex-direction:column;gap:8px;flex:1;} #ezh .room h4{font-family:var(–serif);font-size:23px;font-weight:400;line-height:1;} #ezh .room .kind{font-family:var(–mono);font-size:11px;letter-spacing:.08em; text-transform:uppercase;color:var(–ink-soft);} #ezh .room .blurb{font-size:14px;color:var(–ink-soft);flex:1;} #ezh .tags{display:flex;flex-wrap:wrap;gap:5px;} #ezh .tag{font-family:var(–mono);font-size:10.5px;letter-spacing:.05em; border:1px solid var(–line);border-radius:2px;padding:3px 7px;color:var(–ink-soft);} #ezh .rate{display:flex;align-items:baseline;justify-content:space-between; border-top:1px solid var(–line);padding-top:10px;margin-top:2px;} #ezh .rate b{font-family:var(–mono);font-weight:500;font-size:17px;} #ezh .rate small{font-family:var(–mono);font-size:11px;color:var(–ink-soft);} #ezh .pick{width:100%;padding:11px;border:1px solid var(–ink);border-radius:2px; font-weight:500;font-size:14px;transition:background .15s,color .15s;} #ezh .pick:hover{background:var(–ink);color:var(–paper);} #ezh .room.on .pick{background:var(–red);border-color:var(–red);color:#fff;} #ezh .room.out .pick{border-color:var(–line);color:var(–ink-soft);cursor:not-allowed; background:none;} /* ── extras + total ───────────────────────────────────────── */ #ezh .extras{display:grid;gap:14px;grid-template-columns:1fr 1fr; background:var(–stone);border:1px solid var(–line);border-radius:3px;padding:18px;} #ezh .check{display:flex;gap:10px;align-items:flex-start;grid-column:1/-1; padding:12px;background:var(–paper);border:1px solid var(–line);border-radius:2px;} #ezh .check input{margin-top:3px;width:17px;height:17px;accent-color:var(–red);} #ezh .check .t{font-size:14px;} #ezh .check .s{font-size:13px;color:var(–ink-soft);} #ezh .bill{border:1px solid var(–ink);border-radius:3px;overflow:hidden;margin-top:18px;} #ezh .bill .line{display:flex;justify-content:space-between;gap:16px; padding:9px 16px;font-size:14px;} #ezh .bill .line span:last-child{font-family:var(–mono);} #ezh .bill .line.sub{color:var(–ink-soft);} #ezh .bill .sum{display:flex;justify-content:space-between;align-items:baseline; padding:13px 16px;border-top:1px solid var(–line);} #ezh .bill .sum b{font-family:var(–mono);font-size:19px;font-weight:500;} #ezh .bill .due{background:var(–ink);color:#fff;display:flex; justify-content:space-between;align-items:baseline;padding:14px 16px;} #ezh .bill .due b{font-family:var(–mono);font-size:21px;font-weight:500;} #ezh .bill .due .s{font-size:12px;opacity:.72;display:block;margin-top:2px;} /* ── buttons, messages ────────────────────────────────────── */ #ezh .cta{width:100%;background:var(–red);color:#fff;padding:15px; border-radius:2px;font-weight:600;font-size:16px;margin-top:16px; transition:background .15s;} #ezh .cta:hover{background:var(–red-deep);} #ezh .cta[disabled]{background:var(–line);color:var(–ink-soft);cursor:not-allowed;} #ezh .ghost{width:100%;border:1px solid var(–line);padding:13px;border-radius:2px; font-size:14px;margin-top:8px;} #ezh .ghost:hover{border-color:var(–ink);} #ezh .msg{padding:13px 15px;border-radius:2px;font-size:14px;margin-top:14px; border-left:3px solid;} #ezh .msg.bad{background:#FDF2F3;border-color:var(–red);} #ezh .msg.good{background:#F0F7F3;border-color:var(–ok);} #ezh .msg.info{background:var(–stone);border-color:var(–ink-soft);} #ezh .done{border:1px solid var(–ok);border-radius:3px;padding:26px; text-align:center;margin-top:20px;} #ezh .done h3{font-family:var(–serif);font-size:29px;font-weight:400;} #ezh .done .id{font-family:var(–mono);font-size:23px;color:var(–red); margin:14px 0;letter-spacing:.03em;} #ezh .done p{color:var(–ink-soft);font-size:14px;max-width:44ch;margin:0 auto;} #ezh .upi{border:1px solid var(–line);border-radius:3px;padding:18px;margin-top:14px;} #ezh .vpa{display:flex;gap:8px;align-items:center;margin-top:10px;} #ezh .vpa code{flex:1;font-family:var(–mono);font-size:15px;background:var(–stone); padding:11px 12px;border-radius:2px;overflow-x:auto;white-space:nowrap;} #ezh .vpa button{border:1px solid var(–line);padding:11px 14px;border-radius:2px; font-size:13px;white-space:nowrap;} #ezh .hide{display:none !important;} #ezh .spin{display:inline-block;width:13px;height:13px;border:2px solid rgba(255,255,255,.4); border-top-color:#fff;border-radius:50%;animation:ezhspin .7s linear infinite; vertical-align:-2px;margin-right:7px;} @keyframes ezhspin{to{transform:rotate(360deg);}} @media (prefers-reduced-motion:reduce){#ezh .spin{animation-duration:2.5s;}} @media(max-width:600px){ #ezh .search,#ezh .extras{grid-template-columns:1fr;} #ezh .rooms{grid-template-columns:1fr;} }
Courtallam · Tamil Nadu

Book direct at Kutralam Ezhilagam

Nine rooms, minutes from Five Falls. Booking here costs less than the travel sites — no commission sits between us.

Choose your rooms

Pick your dates to see what is free.

    Anything else

    Air conditioning and extra beds are charged per night.

    Air conditioning Not needed Yes, please
    Extra beds
    0
    Stay until 5 PM instead of 10 AM
    Half a night extra. The room is held for you all day.

    What it comes to

    Every line, before you pay anything.

    Who is staying

    We send the confirmation to your WhatsApp.

    Pay the advance to this UPI ID, then send the screenshot to us on WhatsApp. We confirm the room by reply.
    Send the screenshot on WhatsApp

    Your room is held

    (function(){ “use strict”; /* ── Configuration ──────────────────────────────────────────────────────── * The one thing you may need to change here is EXEC — the Apps Script web * app URL. Everything else, including the Razorpay key, is fetched from the * script at run time so keys can be rotated without touching this page. */ var EXEC = “https://script.google.com/macros/s/AKfycbwUVyNn9AIKvCpF2SQRsTqyepZgqwhOIeWCJt25YT5wyC3pp0fWayuTSDTvlwmD24Ww/exec&#8221;; var HOTEL = { name:”Kutralam Ezhilagam”, whatsapp:”918248320685″, phone:”+918248320685″ }; /* Tariff. These match the sheet — change them in both places or not at all. */ var TARIFF = { acAddOn:{ “Studio Room”:500, “Suite Room”:1000 }, extraBed:{ AC:300, “Non-AC”:200 }, maxExtraBeds:6, advanceFraction:0.5, lateCheckoutUplift:0.5, checkInDefault:”12:00″, checkOutDefault:”10:00″, lateHour:”17:00″ }; /* PHOTOS — until the Room Photos screen is built into the staff app, put a * public image URL in `photo` below and the tinted panel is replaced. Leave * it empty and the room still shows properly, just without a picture. */ var ROOMS = [ {name:”Thillai”, type:”Studio Room”, floor:”Ground Floor”, rate:1899, ac:true, max:4, thinai:”தில்லை”, photo:””, blurb:”Deluxe studio opening onto the garden — the easiest room to reach, and the quietest at night.”, tags:[“Deluxe studio”,”Garden side”,”Ground floor”]}, {name:”Aambal”, type:”Studio Room”, floor:”Ground Floor”, rate:1199, ac:false, max:2, thinai:”ஆம்பல்”, photo:””, blurb:”Our snug standard studio for two, kept naturally cool by the hillside air.”, tags:[“Standard studio”,”Non-AC only”,”Best value”]}, {name:”Vaagai”, type:”Suite Room”, floor:”Ground Floor”, rate:5499, ac:true, max:15, thinai:”வாகை”, photo:””, blurb:”Premium family suite with four cots — built for the whole family travelling together.”, tags:[“Family suite”,”4 cots”,”Sleeps up to 15″]}, {name:”Shenbagam”, type:”Suite Room”, floor:”First Floor”, rate:4599, ac:false, max:10, thinai:”செண்பகம்”, photo:””, blurb:”Premium family suite with its own kitchen — three bedrooms, three bathrooms and a balcony.”, tags:[“3 bedrooms”,”Kitchen”,”Non-AC only”]}, {name:”Mavval”, type:”Suite Room”, floor:”First Floor”, rate:4899, ac:true, max:10, thinai:”மாவ்வல்”, photo:””, blurb:”Premium family suite on the first floor, with room to spread out and a view over the trees.”, tags:[“Family suite”,”First floor”,”Sleeps up to 10″]}, {name:”Kurinji”, type:”Studio Room”, floor:”Second Floor”, rate:2899, ac:true, max:5, thinai:”குறிஞ்சி”, photo:””, blurb:”Deluxe studio with the mountain view — the one guests ask for by name.”, tags:[“Mountain view”,”Deluxe studio”,”Second floor”]}, {name:”Mullai”, type:”Studio Room”, floor:”Second Floor”, rate:2199, ac:true, max:4, thinai:”முல்லை”, photo:””, blurb:”Deluxe studio with a balcony — morning coffee outside, with the hills in front of you.”, tags:[“Private balcony”,”Deluxe studio”,”Second floor”]}, {name:”Marutham”, type:”Studio Room”, floor:”Second Floor”, rate:2099, ac:true, max:4, thinai:”மருதம்”, photo:””, blurb:”Deluxe studio with a balcony, tucked at the quiet end of the second floor.”, tags:[“Private balcony”,”Deluxe studio”,”Quiet corner”]}, {name:”Paalai”, type:”Studio Room”, floor:”Second Floor”, rate:2699, ac:true, max:5, thinai:”பாலை”, photo:””, blurb:”Our largest deluxe studio — comfortable for a small family without taking a whole suite.”, tags:[“Deluxe studio”,”Sleeps up to 5″,”Second floor”]} ]; /* ── State ────────────────────────────────────────────────────────────── */ var S = { checkIn:””, checkOut:””, adults:2, children:0, beds:0, ac:”Non-AC”, late:false, picked:[], busy:{}, pay:null, working:false }; var $ = function(id){ return document.getElementById(id); }; var rupees = function(n){ return “\u20B9” + Math.round(n).toLocaleString(“en-IN”); }; function iso(d){ return d.getFullYear() + “-” + (“0″+(d.getMonth()+1)).slice(-2) + “-” + (“0″+d.getDate()).slice(-2); } function pretty(s){ if(!s) return “”; var d = new Date(s + “T12:00:00”); return d.toLocaleDateString(“en-IN”,{day:”numeric”,month:”short”,year:”numeric”}); } /* Every night the stay occupies. A 5 PM departure holds the last day too — * we must not sell a morning we cannot honour. Same rule as the sheet. */ function nights(){ var out = []; if(!S.checkIn || !S.checkOut) return out; var d = new Date(S.checkIn+”T12:00:00″), end = new Date(S.checkOut+”T12:00:00″), g=0; while(d < end && g++ < 400){ out.push(iso(d)); d.setDate(d.getDate()+1); } return out; } function nightCount(){ return nights().length; } function isFree(room){ var ns = nights(); if(!ns.length) return false; for(var i=0;i1?”s”:””), amount:r.rate * n, sub:rupees(r.rate) + ” a night” }); }); var total = rooms; if(S.ac === “AC”){ var acSum = 0; S.picked.forEach(function(r){ if(r.ac) acSum += TARIFF.acAddOn[r.type] * n; }); if(acSum){ lines.push({label:”Air conditioning”, amount:acSum}); total += acSum; } } if(S.beds > 0){ var bed = TARIFF.extraBed[S.ac] * S.beds * n; lines.push({ label:S.beds + ” extra bed” + (S.beds>1?”s”:””), amount:bed, sub:rupees(TARIFF.extraBed[S.ac]) + ” each a night” }); total += bed; } if(S.late){ var up = 0; S.picked.forEach(function(r){ up += r.rate * TARIFF.lateCheckoutUplift; }); lines.push({ label:”Check out at 5 PM”, amount:up, sub:”half a night” }); total += up; } var advance = Math.round(total * TARIFF.advanceFraction); return { n:n, lines:lines, total:Math.round(total), advance:advance }; } /* ── Rendering ────────────────────────────────────────────────────────── */ function drawRooms(){ var ul = $(“ezh-rooms”), n = nightCount(); ul.innerHTML = “”; ROOMS.forEach(function(r){ var free = n ? isFree(r) : true; var on = S.picked.indexOf(r) !== -1; var li = document.createElement(“li”); li.className = “room” + (on?” on”:””) + (n && !free ? ” out”:””); var shot = r.photo ? ‘
    '+r.name+' at Kutralam Ezhilagam
    ‘ : ‘
    ‘+r.thinai+’
    ‘; li.innerHTML = shot + ‘
    ‘ + ‘

    ‘+r.name+’

    ‘ + ‘
    ‘+r.type+’ · ‘+r.floor+’ · up to ‘+r.max+’
    ‘ + ‘

    ‘+r.blurb+’

    ‘ + ‘
      ‘ + r.tags.map(function(t){ return ‘
    • ‘+t+’
    • ‘; }).join(“”) + ‘
    ‘ + ‘
    ‘+rupees(r.rate)+’a night’ + (r.ac ? ” : ‘ · non-AC only’) + ‘
    ‘ + ‘‘ + ‘
    ‘; if(!n || free){ li.querySelector(“.pick”).addEventListener(“click”, function(){ var i = S.picked.indexOf(r); if(i === -1) S.picked.push(r); else S.picked.splice(i,1); redraw(); }); } ul.appendChild(li); }); } function drawBill(){ var q = quote(), box = $(“ezh-bill”); if(!q.total){ box.innerHTML = “”; return; } var html = q.lines.map(function(l){ return ‘
    ‘+l.label+ (l.sub ? ‘
    ‘+l.sub+’‘ : ”)+ ‘
    ‘+rupees(l.amount)+’
    ‘; }).join(“”); html += ‘
    Total for the stay‘+rupees(q.total)+’
    ‘; html += ‘
    Pay now to hold the room’ + ‘‘+rupees(q.total – q.advance)+’ at check-in‘ + ‘‘+rupees(q.advance)+’
    ‘; box.innerHTML = html; } function redraw(){ var n = nightCount(); $(“ezh-ad-v”).textContent = S.adults; $(“ezh-ch-v”).textContent = S.children; $(“ezh-beds-v”).textContent = S.beds; $(“ezh-nights”).textContent = n ? n + ” night” + (n>1?”s”:””) + ” · ” + pretty(S.checkIn) + ” to ” + pretty(S.checkOut) : “”; $(“ezh-avail-note”).textContent = n ? “Free on your dates. Rooms already taken are marked.” : “Pick your dates to see what is free.”; drawRooms(); var has = S.picked.length > 0 && n > 0; [“ezh-extras-sec”,”ezh-bill-sec”,”ezh-you-sec”].forEach(function(id){ $(id).classList.toggle(“hide”, !has); }); if(has) drawBill(); /* AC only offered when a selected room can actually take it */ var anyAc = S.picked.some(function(r){ return r.ac; }); $(“ezh-ac”).disabled = !anyAc; if(!anyAc && S.ac === “AC”){ S.ac = “Non-AC”; $(“ezh-ac”).value = “Non-AC”; } } function say(kind, text){ $(“ezh-msg”).innerHTML = ‘
    ‘+text+’
    ‘; } function clearSay(){ $(“ezh-msg”).innerHTML = “”; } /* ── Talking to the sheet ─────────────────────────────────────────────── */ function get(action, extra){ var url = EXEC + “?action=” + action + (extra||””) + “&t=” + Date.now(); return fetch(url, {method:”GET”, redirect:”follow”}).then(function(r){ if(!r.ok) throw new Error(action + ” ” + r.status); return r.json(); }); } function post(body){ return fetch(EXEC, { method:”POST”, redirect:”follow”, headers:{“Content-Type”:”text/plain;charset=utf-8″}, body:JSON.stringify(body) }).then(function(r){ if(!r.ok) throw new Error(“request ” + r.status); return r.json(); }); } function loadAvailability(){ return get(“publicAvail”,”&days=120″).then(function(d){ S.busy = (d && d.busy) || {}; redraw(); }).catch(function(){ say(“info”,”We could not check availability just now. You can still book — ” + “we will confirm the room by WhatsApp.”); }); } function loadPayConfig(){ return get(“payConfig”).then(function(d){ S.pay = d; if(d && d.upi && d.upi.vpa) $(“ezh-vpa”).textContent = d.upi.vpa; }).catch(function(){ S.pay = null; }); } /* Razorpay’s script is only fetched when it is actually needed. */ function loadRazorpay(){ return new Promise(function(res, rej){ if(window.Razorpay) return res(); var s = document.createElement(“script”); s.src = “https://checkout.razorpay.com/v1/checkout.js&#8221;; s.onload = res; s.onerror = function(){ rej(new Error(“checkout script”)); }; document.head.appendChild(s); }); } /* ── Booking ──────────────────────────────────────────────────────────── */ function validate(){ var name = $(“ezh-name”).value.trim(); var phone = $(“ezh-phone”).value.replace(/\D/g,””); if(name.length cap) return “Those rooms sleep ” + cap + “. Please add another room, or reduce the guests.”; return null; } function payload(extra){ var q = quote(); var base = { action:”webBooking”, name:$(“ezh-name”).value.trim(), phone:”+91″ + $(“ezh-phone”).value.replace(/\D/g,””).slice(-10), email:$(“ezh-email”).value.trim(), room:S.picked.map(function(r){ return r.name; }).join(“,”), checkIn:S.checkIn, checkOut:S.checkOut, checkInTime:TARIFF.checkInDefault, checkOutTime:S.late ? TARIFF.lateHour : TARIFF.checkOutDefault, adults:S.adults, children:S.children, extraBeds:S.beds, acPreference:S.ac, total:q.total, reservationPaid:q.advance, balance:q.total – q.advance, paymentStatus:”Advance Paid” }; for(var k in extra) base[k] = extra[k]; return base; } function confirmed(res){ $(“ezh-you-sec”).classList.add(“hide”); $(“ezh-bill-sec”).classList.add(“hide”); $(“ezh-extras-sec”).classList.add(“hide”); $(“ezh-done-sec”).classList.remove(“hide”); $(“ezh-done-id”).textContent = res.bookingId || res.serial || “”; $(“ezh-done-text”).textContent = “We have sent the details to your WhatsApp. Keep this number for check-in — ” + “front desk 04633 284004.”; $(“ezh-done-sec”).scrollIntoView({behavior:”smooth”, block:”center”}); } function busy(on, label){ S.working = on; var b = $(“ezh-pay”); b.disabled = on; b.innerHTML = on ? ‘‘ + (label||”Working”) : “Pay the advance and book”; } $(“ezh-pay”).addEventListener(“click”, function(){ if(S.working) return; clearSay(); var bad = validate(); if(bad) return say(“bad”, bad); var q = quote(); if(!q.advance) return say(“bad”,”Please choose your dates and rooms first.”); if(!S.pay || !S.pay.razorpay || !S.pay.razorpay.enabled){ say(“info”,”Card payment is not switched on yet. Please use the UPI option below — ” + “we confirm the room as soon as the screenshot arrives.”); $(“ezh-upi”).classList.remove(“hide”); return; } busy(true,”Opening payment”); loadRazorpay() .then(function(){ return post({ action:”createOrder”, amount:q.advance * 100, receipt:”EZ” + Date.now() }); }) .then(function(order){ if(!order || order.ok === false || !order.orderId) throw new Error((order && order.message) || “Could not start the payment.”); busy(false); var rz = new window.Razorpay({ key: S.pay.razorpay.keyId, order_id: order.orderId, amount: order.amount, currency: order.currency || “INR”, name: HOTEL.name, description: S.picked.map(function(r){ return r.name; }).join(“, “) + ” · ” + pretty(S.checkIn), prefill:{ name:$(“ezh-name”).value.trim(), contact:$(“ezh-phone”).value.replace(/\D/g,””), email:$(“ezh-email”).value.trim() }, theme:{ color:”#C61830″ }, modal:{ ondismiss:function(){ busy(false); say(“info”,”Payment cancelled — nothing has been charged and no room is held. ” + “You can try again whenever you are ready.”); }}, handler:function(r){ busy(true,”Confirming your room”); post(payload({ paymentRef: r.razorpay_payment_id || “”, razorpayOrderId: r.razorpay_order_id || “”, razorpaySignature: r.razorpay_signature || “” })).then(function(res){ busy(false); if(!res || res.ok === false){ return say(“bad”, (res && res.message) || “Your payment went through but we could not hold the room. ” + “Please send us a WhatsApp on ” + HOTEL.phone + ” — you have not been charged twice.”); } confirmed(res); }).catch(function(){ busy(false); say(“bad”,”Your payment went through but we could not reach our system. ” + “Please send us a WhatsApp on ” + HOTEL.phone + ” with this page open — ” + “your money is safe and we will hold the room.”); }); } }); rz.on(“payment.failed”, function(e){ busy(false); var m = e && e.error && e.error.description; say(“bad”,”The payment did not go through” + (m ? ” — ” + m : “”) + “. No room has been held and nothing has been charged.”); }); rz.open(); }) .catch(function(err){ busy(false); say(“bad”, (err && err.message) || “We could not start the payment. Please try the UPI option below.”); $(“ezh-upi”).classList.remove(“hide”); }); }); /* ── UPI fallback ─────────────────────────────────────────────────────── */ $(“ezh-upi-btn”).addEventListener(“click”, function(){ $(“ezh-upi”).classList.toggle(“hide”); var q = quote(); var msg = “Hello, I would like to book ” + S.picked.map(function(r){ return r.name; }).join(“, “) + ” from ” + pretty(S.checkIn) + ” to ” + pretty(S.checkOut) + “. Advance ” + rupees(q.advance) + “. Screenshot attached.”; $(“ezh-wa”).href = “https://wa.me/&#8221; + HOTEL.whatsapp + “?text=” + encodeURIComponent(msg); }); $(“ezh-copy”).addEventListener(“click”, function(){ var v = $(“ezh-vpa”).textContent; var done = function(){ $(“ezh-copy”).textContent = “Copied”; setTimeout(function(){ $(“ezh-copy”).textContent = “Copy”; }, 1800); }; if(navigator.clipboard) navigator.clipboard.writeText(v).then(done, function(){}); else done(); }); /* ── Inputs ───────────────────────────────────────────────────────────── */ document.querySelectorAll(“#ezh [data-step]”).forEach(function(b){ b.addEventListener(“click”, function(){ var p = b.getAttribute(“data-step”).split(“,”), k = p[0], d = parseInt(p[1],10); if(k === “ad”) S.adults = Math.min(30, Math.max(1, S.adults + d)); if(k === “ch”) S.children = Math.min(20, Math.max(0, S.children + d)); if(k === “bed”) S.beds = Math.min(TARIFF.maxExtraBeds, Math.max(0, S.beds + d)); redraw(); }); }); $(“ezh-in”).addEventListener(“change”, function(){ S.checkIn = this.value; if(S.checkOut && S.checkOut <= S.checkIn){ var d = new Date(S.checkIn+"T12:00:00"); d.setDate(d.getDate()+1); S.checkOut = iso(d); $("ezh-out").value = S.checkOut; } $("ezh-out").min = S.checkIn; S.picked = []; redraw(); }); $("ezh-out").addEventListener("change", function(){ S.checkOut = this.value; S.picked = []; redraw(); }); $("ezh-ac").addEventListener("change", function(){ S.ac = this.value; redraw(); }); $("ezh-late").addEventListener("change", function(){ S.late = this.checked; redraw(); }); /* ── Start ────────────────────────────────────────────────────────────── */ (function start(){ var t = new Date(); t.setDate(t.getDate()+1); var t2 = new Date(); t2.setDate(t2.getDate()+2); S.checkIn = iso(t); S.checkOut = iso(t2); $("ezh-in").value = S.checkIn; $("ezh-in").min = iso(new Date()); $("ezh-out").value = S.checkOut; $("ezh-out").min = S.checkIn; redraw(); loadPayConfig(); loadAvailability(); })(); })();