Sky Lodge – Glass Capsule | Glamping Tents – Campking

₹ 23,98,000
US$24,870

Setup , Shipping & customization are not included in the base price.


4.6 (394)
★★★★★
Occupancy Rate:2–4 Guests
Design for : Resorts / Retreats / Eco Stays / AirBnb

========================================================================== */ (function () { 'use strict';/* ------------------------------------------------------------------------ 0. HELPERS ------------------------------------------------------------------------ *//* The same three breakpoints the stylesheet uses. */ var MQ_PHONE = window.matchMedia('(max-width: 549px)'); var MQ_LAPTOP = window.matchMedia('(max-width: 1099px)'); var REDUCED = window.matchMedia('(prefers-reduced-motion: reduce)').matches; var FINE_POINTER = window.matchMedia('(hover: hover) and (pointer: fine)').matches;function q(sel, root) { return (root || document).querySelector(sel); } function qa(sel, root) { return Array.prototype.slice.call((root || document).querySelectorAll(sel)); }function onMedia(mq, fn) { if (mq.addEventListener) mq.addEventListener('change', fn); else mq.addListener(fn); }function debounce(fn, ms) { var timer; return function () { clearTimeout(timer); timer = setTimeout(fn, ms); }; }/* True when the element takes up space, i.e. its copy is the one showing. */ function isShown(el) { return !!(el && (el.offsetWidth || el.offsetHeight || el.getClientRects().length)); }function pad2(n) { return ('0' + n).slice(-2); }/* Inside the UX Builder editor the page is left as authored: no cloned loop items, so every element on the canvas maps to a real element. */ function inBuilder() { return /(?:\?|&)uxb_iframe/.test(window.location.search) || document.documentElement.classList.contains('uxb-iframe') || (document.body && document.body.classList.contains('uxb-iframe')); }/* A copy used to make a loop seamless: hidden from assistive tech, out of the tab order, and loading its picture straight away (Flatsome's lazy loader only watches the originals). */ function silentCopy(node) { var copy = node.cloneNode(true); copy.setAttribute('aria-hidden', 'true'); copy.removeAttribute('id'); qa('[id]', copy).forEach(function (el) { el.removeAttribute('id'); }); qa('img', copy).forEach(function (img) { img.alt = ''; if (img.getAttribute('data-src')) img.src = img.getAttribute('data-src'); if (img.getAttribute('data-srcset')) img.srcset = img.getAttribute('data-srcset'); }); qa('a, button', copy).forEach(function (el) { el.setAttribute('tabindex', '-1'); }); return copy; }/* Flatsome starts each slider lazily, the first time it scrolls into view, and then fires 'flatsome-flickity-ready' on the slider element. Hand the Flickity instance over as soon as it exists, however late. The short poll covers a slider that was ready before this file ran. */ function whenSlider(root, cb) { var el = q('.slider', root); if (!el || !window.jQuery) return; var $el = window.jQuery(el); var done = false; function take() { if (done) return; var flk = $el.data('flickity'); if (flk) { done = true; cb(flk); } } $el.on('flatsome-flickity-ready', take); take(); var tries = 0; (function poll() { if (done || ++tries > 40) return; take(); setTimeout(poll, 250); })(); }/* Run fn(index) every time the slider settles on a new slide. */ function onSlide(flk, fn) { if (typeof flk.on === 'function') { flk.on('change', fn); } else if (window.jQuery) { window.jQuery(flk.element).on('change.flickity', function (e, index) { fn(index); }); } }/* ------------------------------------------------------------------------ 1. ANCHORS A section's anchor is written as a class (ck-id-centre) because a desktop copy and its phone copy cannot share an id. An empty target is placed at the top of whichever copy is showing, and moved when the screen crosses 549px, so #centre in any link or URL lands on the visible copy. Section ids themselves are left alone: Flatsome uses them. ------------------------------------------------------------------------ */ function initAnchors() { var groups = {}; qa('[class*="ck-id-"]').forEach(function (sec) { var m = sec.className.match(/(?:^|\s)ck-id-([a-z0-9_-]+)/i); if (m) (groups[m[1]] = groups[m[1]] || []).push(sec); });function place() { Object.keys(groups).forEach(function (name) { var secs = groups[name]; var host = secs.filter(isShown)[0] || secs[0]; var target = document.getElementById(name); if (target && !target.classList.contains('ck-anchor')) return; /* id already used elsewhere */ if (!target) { target = document.createElement('span'); target.id = name; target.className = 'ck-anchor'; target.setAttribute('aria-hidden', 'true'); } if (target.parentNode !== host) host.insertBefore(target, host.firstChild); }); }place(); onMedia(MQ_PHONE, place);/* a visit that arrives on a hash (…/#centre) lands once the target exists */ if (window.location.hash.length > 1) { setTimeout(function () { var t = document.getElementById(window.location.hash.slice(1)); if (t && t.classList.contains('ck-anchor')) t.scrollIntoView(); }, 300); } }/* ------------------------------------------------------------------------ 2. HERO The photographs are a Flatsome slider (autoplay 6.5s). Only the headline changes with them; the note, the button and the rule stay put. The bars are built from the number of slides, so a new slide gets a bar on its own (give it a matching headline line in the HTML element too). ------------------------------------------------------------------------ */ function initHero() { qa('.ck-hero').forEach(function (sec) { var lines = qa('.ck-hero__line', sec); var rail = q('.ck-hero__dots', sec); sec.setAttribute('aria-roledescription', 'carousel');whenSlider(sec, function (flk) { var count = flk.cells.length; var bars = [];if (rail) { rail.innerHTML = ''; for (var i = 0; i < count; i++) { var bar = document.createElement('button'); bar.type = 'button'; bar.className = 'ck-hero__dot'; bar.setAttribute('aria-label', 'Slide ' + (i + 1) + ' of ' + count); rail.appendChild(bar); bars.push(bar); } bars.forEach(function (bar, k) { bar.addEventListener('click', function () { flk.select(k); }); bar.addEventListener('keydown', function (e) { var step = (e.key === 'ArrowRight' || e.key === 'ArrowDown') ? 1 : (e.key === 'ArrowLeft' || e.key === 'ArrowUp') ? -1 : 0; if (!step) return; e.preventDefault(); var n = (flk.selectedIndex + step + count) % count; flk.select(n); bars[n].focus(); }); }); /* resting the pointer on the bars holds the current picture */ rail.addEventListener('mouseenter', function () { if (flk.pausePlayer) flk.pausePlayer(); }); rail.addEventListener('mouseleave', function () { if (flk.unpausePlayer && !REDUCED) flk.unpausePlayer(); }); }function paint(index) { lines.forEach(function (line, k) { var on = k === index; line.classList.toggle('is-active', on); line.setAttribute('aria-hidden', on ? 'false' : 'true'); }); bars.forEach(function (bar, k) { bar.setAttribute('aria-current', k === index ? 'true' : 'false'); }); }paint(flk.selectedIndex); onSlide(flk, paint); if (REDUCED && flk.stopPlayer) flk.stopPlayer(); }); }); }/* ------------------------------------------------------------------------ 3. LOOPS · ticker and recognition rail Each rail is authored with one set of items. One silent copy is added so the CSS drift (translateX -50%) lands exactly on it. Hover pauses the drift in CSS. ------------------------------------------------------------------------ */ function initLoops() { if (inBuilder()) return; qa('.ck-ticker__track, .ck-logos__track').forEach(function (track) { if (track.getAttribute('data-ck-looped')) return; var set = q('.ck-ticker__row, .ck-logos__row', track); if (!set) return; track.appendChild(silentCopy(set)); track.setAttribute('data-ck-looped', '1'); }); }/* ------------------------------------------------------------------------ 4. ABOUT CAMPKING Desktop copy: the five frames rise in once, staggered, the first time the arc is on screen. Phone copy: one silent copy of the five photos makes the drifting strip seamless, so only five images are managed in UX Builder. ------------------------------------------------------------------------ */ function initAbout() { qa('.ck-about.ck--desk .ck-about__wave').forEach(function (wave) { if (REDUCED || inBuilder()) return; wave.classList.add('is-armed'); function fire() { if (!isShown(wave)) return; var r = wave.getBoundingClientRect(); if (r.top < window.innerHeight * 0.86 && r.bottom > 0) { wave.classList.remove('is-armed'); window.removeEventListener('scroll', fire); window.removeEventListener('resize', fire); } } window.addEventListener('scroll', fire, { passive: true }); window.addEventListener('resize', fire, { passive: true }); setTimeout(fire, 60); });if (inBuilder()) return; qa('.ck-about.ck--phone .ck-about__wave .col-inner').forEach(function (inner) { if (inner.getAttribute('data-ck-looped')) return; qa('.ck-about__tile', inner).forEach(function (tile) { inner.appendChild(silentCopy(tile)); }); inner.setAttribute('data-ck-looped', '1'); }); }/* ------------------------------------------------------------------------ 5. ARCHITECTURAL PODS The photographs are a Flatsome slider. This builds the name rail from each slide's own name, wires the arrows and the counter, and centres the live name when the rail scrolls (phone). A slide added in UX Builder gets its name and number without touching this file. ------------------------------------------------------------------------ */ function initPods() { qa('.ck-pods').forEach(function (sec) { var rail = q('.ck-pods__tabs', sec); var now = q('.ck-pods__now', sec); var total = q('.ck-pods__total', sec); var prev = q('.ck-pods__nav--prev', sec); var next = q('.ck-pods__nav--next', sec);whenSlider(sec, function (flk) { var tabs = [];/* soft edges on the phone rail step aside at each end */ function edges() { if (!rail) return; var max = rail.scrollWidth - rail.clientWidth; rail.classList.toggle('is-start', max <= 1 || rail.scrollLeft <= 1); rail.classList.toggle('is-end', max <= 1 || rail.scrollLeft >= max - 1); }function paint(index) { tabs.forEach(function (tab, k) { tab.setAttribute('aria-current', k === index ? 'true' : 'false'); }); if (now) now.textContent = pad2(index + 1); var live = tabs[index]; if (live && rail.scrollWidth > rail.clientWidth) { rail.scrollTo({ left: live.offsetLeft - (rail.clientWidth - live.offsetWidth) / 2, behavior: REDUCED ? 'auto' : 'smooth' }); } edges(); }if (rail) { rail.innerHTML = ''; flk.cells.forEach(function (cell, k) { var name = q('.ck-pod__name', cell.element); var tab = document.createElement('button'); tab.type = 'button'; tab.className = 'ck-pods__tab'; tab.textContent = name ? name.textContent.trim() : 'Structure ' + (k + 1); tab.addEventListener('click', function () { flk.select(k); }); rail.appendChild(tab); tabs.push(tab); }); rail.addEventListener('scroll', edges, { passive: true }); window.addEventListener('resize', debounce(edges, 120)); }if (total) total.textContent = pad2(flk.cells.length); if (prev) prev.addEventListener('click', function () { flk.previous(); }); if (next) next.addEventListener('click', function () { flk.next(); });sec.addEventListener('keydown', function (e) { if (e.target.closest && e.target.closest('input, textarea, select')) return; if (e.key === 'ArrowRight') flk.next(); if (e.key === 'ArrowLeft') flk.previous(); });paint(flk.selectedIndex); onSlide(flk, paint);/* a copy that was hidden when Flickity measured it re-measures when it appears */ onMedia(MQ_PHONE, function () { setTimeout(function () { flk.resize(); paint(flk.selectedIndex); }, 60); }); }); }); }/* ------------------------------------------------------------------------ 6. OUR PROCESS Desktop copy: the rule over the live step fills over 5.2s (CSS), then the next step and its photograph take over. Clicking a step jumps to it. Phone copy: tap to open a step; nothing advances on its own, because the steps carry the copy and a timer would close what is being read. ------------------------------------------------------------------------ */ function initProcess() { qa('.ck-proc').forEach(function (sec) { var steps = qa('.ck-step', sec); var shots = qa('.ck-proc__shot', sec); if (!steps.length) return;var phone = sec.classList.contains('ck--phone'); var DWELL = 5200; var at = 0; var timer = null;var group = q('.ck-proc__steps', sec); if (group) { group.setAttribute('role', 'group'); group.setAttribute('aria-label', 'Process stages'); }function show(n) { at = (n + steps.length) % steps.length; steps.forEach(function (s, k) { s.setAttribute('aria-current', k === at ? 'true' : 'false'); }); shots.forEach(function (f, k) { f.classList.toggle('is-active', k === at); }); } function play() { if (phone || REDUCED || timer || !isShown(sec)) return; timer = setInterval(function () { show(at + 1); }, DWELL); } function stop() { if (timer) { clearInterval(timer); timer = null; } }steps.forEach(function (s, k) { s.addEventListener('click', function () { stop(); show(k); play(); }); s.addEventListener('focus', stop); }); document.addEventListener('visibilitychange', function () { if (document.hidden) stop(); else play(); }); onMedia(MQ_PHONE, function () { stop(); play(); });show(0); play(); }); }/* ------------------------------------------------------------------------ 7. BEFORE / AFTER The finished photo shows at rest. Holding the picture shows the site before; a click or tap keeps it there (the only route on a touch screen). Hover and keyboard focus are handled in CSS. ------------------------------------------------------------------------ */ function initBeforeAfter() { qa('.ck-ba').forEach(function (sec) { var plate = q('.ck-ba__plate', sec); if (!plate) return; var stage = plate.closest('.col-inner') || sec; var label = q('.ck-sr', plate);function held(on) { stage.classList.toggle('is-held', on); }plate.addEventListener('pointerdown', function (e) { held(true); /* keep receiving the release even if the finger slides off */ if (e.pointerId !== undefined && plate.setPointerCapture) { try { plate.setPointerCapture(e.pointerId); } catch (err) { /* not capturable */ } } }); ['pointerup', 'pointercancel', 'pointerleave'].forEach(function (type) { plate.addEventListener(type, function () { held(false); }); });plate.addEventListener('click', function () { var on = plate.getAttribute('aria-pressed') !== 'true'; plate.setAttribute('aria-pressed', on ? 'true' : 'false'); stage.classList.toggle('is-stuck', on); if (label) { label.textContent = on ? 'Showing the site as found. Activate to return to the finished view' : 'Hold to see the site as found, before groundwork'; } }); }); }/* ------------------------------------------------------------------------ 8. STATEMENT The sentence is split into words that come up from dim to full ink as the pinned section scrolls past. Reduced motion shows it lit at once. ------------------------------------------------------------------------ */ function initStatement() { qa('.ck-say').forEach(function (sec) { var text = q('.ck-say__text', sec); var mark = q('.ck-say__mark', sec); if (!text || text.getAttribute('data-ck-split')) return;var frag = document.createDocumentFragment(); Array.prototype.slice.call(text.childNodes).forEach(function (node) { if (node.nodeType !== 1 && node.nodeType !== 3) return; var accent = node.nodeType === 1 && node.tagName === 'EM'; (node.textContent || '').split(/(\s+)/).forEach(function (chunk) { if (!chunk) return; if (/^\s+$/.test(chunk)) { frag.appendChild(document.createTextNode(' ')); return; } var word = document.createElement('span'); word.className = 'ck-say__w' + (accent ? ' is-accent' : ''); word.textContent = chunk; frag.appendChild(word); }); }); text.textContent = ''; text.appendChild(frag); text.setAttribute('data-ck-split', '1');var words = qa('.ck-say__w', text);if (REDUCED) { words.forEach(function (w) { w.classList.add('is-on'); }); if (mark) mark.classList.add('is-on'); return; }function paint() { var r = sec.getBoundingClientRect(); var travel = r.height - window.innerHeight; if (travel <= 0) return; var progress = Math.min(1, Math.max(0, -r.top / travel)); var lit = Math.min(1, Math.max(0, (progress - 0.1) / 0.66)) * words.length; words.forEach(function (w, i) { w.classList.toggle('is-on', i < lit); }); if (mark) mark.classList.toggle('is-on', lit >= words.length); }paint(); window.addEventListener('scroll', paint, { passive: true }); window.addEventListener('resize', paint, { passive: true }); window.addEventListener('load', paint); }); }/* ------------------------------------------------------------------------ 9. SOLUTIONS BY PROJECT TYPE Desktop copy: a mouse opens panels by hovering (CSS). Touch screens and keyboards open them with a tap or Enter. Phone copy: one panel open at a time, the first one open at rest. ------------------------------------------------------------------------ */ function initEnvironments() { qa('.ck-env').forEach(function (sec) { var phone = sec.classList.contains('ck--phone'); var cells = qa('.ck-env__row > .col', sec); if (!cells.length) return;function open(target) { cells.forEach(function (cell) { var on = cell === target; cell.classList.toggle('is-open', on); var btn = q('.ck-env__btn', cell); if (btn) btn.setAttribute('aria-expanded', on ? 'true' : 'false'); }); }cells.forEach(function (cell) { cell.addEventListener('click', function (e) { /* e.detail is 0 when the click came from the keyboard */ if (phone || !FINE_POINTER || e.detail === 0) { e.preventDefault(); open(cell); } }); });if (phone) open(cells[0]); }); }/* ------------------------------------------------------------------------ 10. PROJECT POTENTIAL The reader sets structures, nightly rate and occupancy; every figure is derived from those three. Assumptions: ₹11,00,000 per structure, 35% kept, year one ramping from 45% of the set occupancy to 100% by month twelve. Starting values are read from the controls themselves. ------------------------------------------------------------------------ */ function initPotential() { qa('.ck-roi').forEach(function (sec) { var KEY_COST = 1100000, MARGIN = 0.35, MONTHS = 60, RAMP0 = 0.45; var KEY_MIN = 2, KEY_MAX = 12; var RUPEE = '₹', MINUS = '−'; var state = { keys: 6, rate: 10000, occ: 50 };var out = {}; qa('[data-ck-roi]', sec).forEach(function (el) { var key = el.getAttribute('data-ck-roi'); (out[key] = out[key] || []).push(el); }); function put(key, value) { (out[key] || []).forEach(function (el) { el.textContent = value; }); }function model(keys, rate, occ) { var invest = keys * KEY_COST; var gross = keys * rate * 365 * (occ / 100); var profit = gross * MARGIN; var monthly = profit / 12; var series = [], cum = -invest, payback = null; for (var m = 1; m <= MONTHS; m++) { cum += monthly * Math.min(1, RAMP0 + (1 - RAMP0) * (m / 12)); series.push(cum); if (payback === null && cum >= 0) payback = m; } return { invest: invest, gross: gross, profit: profit, monthly: monthly, series: series, payback: payback, five: series[MONTHS - 1] }; }/* lakh and crore, the way these figures are read */ function inr(n) { var sign = n < 0 ? MINUS : '', v = Math.abs(n); if (v >= 1e7) return sign + RUPEE + (v / 1e7).toFixed(2) + ' Cr'; if (v >= 1e5) return sign + RUPEE + (v / 1e5).toFixed(1) + ' L'; return sign + RUPEE + Math.round(v).toLocaleString('en-IN'); }/* sliders: the marigold fill follows the handle through --p */ qa('[data-ck-in]', sec).forEach(function (input) { var key = input.getAttribute('data-ck-in'); state[key] = +input.value; function fill() { input.style.setProperty('--p', (input.value - input.min) / (input.max - input.min) * 100 + '%'); } fill(); input.addEventListener('input', function () { state[key] = +input.value; fill(); paint(); }); });var keysOut = q('[data-ck-roi="keys"]', sec); if (keysOut) state.keys = parseInt(keysOut.textContent, 10) || state.keys;var stepper = q('.ck-roi__step', sec); if (stepper) { qa('button[data-ck-d]', stepper).forEach(function (btn) { btn.addEventListener('click', function () { state.keys = Math.min(KEY_MAX, Math.max(KEY_MIN, state.keys + (+btn.getAttribute('data-ck-d')))); paint(); }); }); }/* The plot is drawn in real pixels, so each milestone label can be placed against the same coordinates as its dot. */ function draw(m) { var box = q('.ck-roi__plot', sec); if (!box) return; var W = box.clientWidth, H = box.clientHeight; if (!W || !H) return; var svg = q('svg', box); svg.setAttribute('viewBox', '0 0 ' + W + ' ' + H);var lo = -m.invest, hi = Math.max(m.five, 1), padT = 96, padB = 40; var pts = [lo].concat(m.series); /* month zero is the build cost going out */ var x = function (i) { return i / (pts.length - 1) * W; }; var y = function (v) { return padT + (hi - v) / (hi - lo) * (H - padT - padB); };var d = ''; pts.forEach(function (v, i) { d += (i ? ' L' : 'M') + x(i).toFixed(1) + ' ' + y(v).toFixed(1); }); q('.ck-roi__line', svg).setAttribute('d', d); q('.ck-roi__area', svg).setAttribute('d', d + ' L' + W + ' ' + y(0).toFixed(1) + ' L0 ' + y(0).toFixed(1) + ' Z');var zero = q('.ck-roi__base', svg); zero.setAttribute('x1', 0); zero.setAttribute('x2', W); zero.setAttribute('y1', y(0).toFixed(1)); zero.setAttribute('y2', y(0).toFixed(1));function dot(sel, i) { var c = q(sel, svg); c.setAttribute('cx', x(i).toFixed(1)); c.setAttribute('cy', y(pts[i]).toFixed(1)); return { x: x(i), y: y(pts[i]) }; } var p0 = dot('.ck-roi__dot--start', 0); var px = dot('.ck-roi__dot--even', m.payback === null ? pts.length - 1 : m.payback); var p5 = dot('.ck-roi__dot--end', pts.length - 1);var cross = q('.ck-roi__cross', svg); cross.setAttribute('x1', px.x.toFixed(1)); cross.setAttribute('x2', px.x.toFixed(1)); cross.setAttribute('y1', px.y.toFixed(1)); cross.setAttribute('y2', H);/* end labels are anchored inward so neither runs off its edge */ function mark(sel, p, dy, shift) { var el = q(sel, box); el.style.left = p.x + 'px'; el.style.top = (p.y - dy) + 'px'; el.style.transform = 'translate(' + shift + ',-100%)'; } mark('.ck-roi__mark--start', p0, 16, '0'); mark('.ck-roi__mark--even', px, 22, px.x < W * 0.18 ? '0' : '-50%'); mark('.ck-roi__mark--end', p5, 22, '-100%');/* Month 0 and Year 5 always show; the inside ticks drop out when they would collide with a neighbour */ var axis = q('.ck-roi__x', box), GAP = 66; var kept = [{ i: 0, t: 'Month 0', a: 'translateX(0)' }]; var last = { i: 60, t: 'Year 5', a: 'translateX(-100%)' }; var maybe = [{ i: 12, t: 'Month 12' }]; axis.innerHTML = ''; if (m.payback !== null && m.payback < 60) maybe.push({ i: m.payback, t: 'Month ' + m.payback }); maybe.sort(function (a, b) { return a.i - b.i; }).forEach(function (tick) { var near = kept.concat([last]).some(function (k) { return Math.abs(x(k.i) - x(tick.i)) < GAP; }); if (!near) kept.push(tick); }); kept.push(last); kept.forEach(function (tick) { var s = document.createElement('span'); s.textContent = tick.t; s.style.left = x(tick.i) + 'px'; if (tick.a) s.style.transform = tick.a; axis.appendChild(s); }); }function paint() { var m = model(state.keys, state.rate, state.occ); if (stepper) { qa('button[data-ck-d]', stepper).forEach(function (btn) { btn.disabled = (+btn.getAttribute('data-ck-d') < 0) ? state.keys <= KEY_MIN : state.keys >= KEY_MAX; }); } put('keys', state.keys); put('rate', RUPEE + state.rate.toLocaleString('en-IN')); put('occ', state.occ + '%'); put('invest', inr(m.invest)); put('gross', inr(m.gross)); put('profit', inr(m.profit)); put('monthly', inr(m.monthly)); put('five', inr(m.five)); put('paybackN', m.payback === null ? '60+' : m.payback); put('paybackL', m.payback === null ? 'beyond 5 years' : m.payback + ' months'); draw(m); }paint(); window.addEventListener('resize', debounce(paint, 60), { passive: true }); window.addEventListener('load', paint); }); }/* ------------------------------------------------------------------------ 11. AMENITIES The cards are a Flatsome slider with its own arrows and dots switched off. These arrows sit in lanes beside it (below it on a phone) and the dashes count pages, not cards: five cards with three in view is three positions, so three dashes. ------------------------------------------------------------------------ */ function initAmenities() { qa('.ck-am').forEach(function (sec) { var prev = q('.ck-am__nav--prev', sec); var next = q('.ck-am__nav--next', sec); var dotsBox = q('.ck-am__dots', sec);whenSlider(sec, function (flk) { var dots = [];function perView() { var cell = flk.cells[0]; if (!cell || !cell.size || !cell.size.outerWidth) return 1; return Math.max(1, Math.round(flk.size.innerWidth / cell.size.outerWidth)); } function pages() { return Math.max(1, flk.cells.length - perView() + 1); } function sync() { var last = pages() - 1; var i = Math.min(flk.selectedIndex, last); dots.forEach(function (dot, k) { dot.setAttribute('aria-current', k === i ? 'true' : 'false'); }); if (prev) prev.disabled = flk.selectedIndex <= 0; if (next) next.disabled = flk.selectedIndex >= last; } function build() { if (!dotsBox) { sync(); return; } var n = pages(); if (dots.length !== n) { dotsBox.innerHTML = ''; dots = []; for (var i = 0; i < n; i++) { var dot = document.createElement('button'); dot.type = 'button'; dot.className = 'ck-am__dot'; dot.setAttribute('aria-label', 'Show amenity ' + (i + 1)); (function (k) { dot.addEventListener('click', function () { flk.select(k); }); })(i); dotsBox.appendChild(dot); dots.push(dot); } } sync(); }if (prev) prev.addEventListener('click', function () { flk.select(Math.max(0, flk.selectedIndex - 1)); }); if (next) next.addEventListener('click', function () { flk.select(Math.min(pages() - 1, flk.selectedIndex + 1)); }); onSlide(flk, sync); window.addEventListener('resize', debounce(build, 150)); build(); }); }); }/* ------------------------------------------------------------------------ 12. MOMENTS Each column is authored with its photos once. One silent copy of them is added so translateY(-50%) lands exactly on the copy and the drift never shows a seam. Alternate columns run the other way (CSS). ------------------------------------------------------------------------ */ function initMoments() { if (inBuilder()) return; qa('.ck-mom .ck-mom__col > .col-inner').forEach(function (inner) { if (inner.getAttribute('data-ck-looped')) return; qa('.ck-mom__fig', inner).forEach(function (fig) { inner.appendChild(silentCopy(fig)); }); inner.setAttribute('data-ck-looped', '1'); }); }/* ------------------------------------------------------------------------ 13. EXPERIENCE CENTRE · dot world map The land is a packed 240x96 one-bit mask, so the map paints on the first frame with no network call. Bangalore is held at 66% of the width. Wide screens: the copy sits on the map, so dots fade toward the left. Below 1100px: the map is its own band and draws at full strength. ------------------------------------------------------------------------ */ var MASK64 = 'AAAAAAAAAAA/+AA//4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB///////74AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP//z/////gAAAeAAEAAAAfAAAAAAAAAAAAAAAAAO3/8/////+AAAfgAAAAAAAHgAAAAAAAAAAAAAADgAAfw/////+AAAHMAAAAAAAAOAAAAAAAAAAAAAAG/jvXAP////+AAAAAAAAH4AAf/8AAPAAAAAAAAAAcOAN/gAD///+AAAAAAAAcAAD//wAAIAAAAAAAAAAf4zu/4AB///4AAAAAAABwDA/////wHAAAAgAAAAA9/xs//AB///4AAAAAAABgH//////z/+AAAAB//gPA/++f/4A///4AAAAf8AAAP/////////+AggD//////43nH4Af//gAAAB//wBf/////////////6D/////////N/A//wAAAAH//5v///////////////n////////4D7A//AP4AAP/+X///////////////CH/////////P+Af4AHwAAf3////////////////+AD///////+AA+APwAAAAD/v/////////////////AH///////8APgAHwAAAAH/P////////////////wAD/5/////4APyAAgAAAAH/Hf/////////////h9AAAvAD////8AP/AAAAAAMDfD////////////+ADAAAANAAf////gH/gAAAAAOAuP////////////4APgAABQAAP////8P/wAAAAAOBsP////////////gAPAAAAAAAX////+f/8AAAAAzB7/////////////8AOAAAAAAAD/////f/+AAAAB3n///////////////AMAAAAAAAB///////+AAAAAH////////////////AIAAAAAAAB//////9mAAAAAA///////////////9AAAAAAAAAAf/////+PgAAAAH///////////////6AAAAAAAAAAf/////+AgAAAAD///////////////zAAAAAAAAAAf//////wAAAAAB///zfz/////////wAAAAAAAAAAf/////yAAAAAAB/7/gPz/////////DgAAAAAAAAAf/////gAAAAAA/wc/gDx////////4HAAAAAAAAAAf/////AAAAAAA/gHf//4////////wEAAAAAAAAAAf////+AAAAAAA/Ajc//5///////1gGAAAAAAAAAAP////8AAAAAAA/AMM//4///////hwEAAAAAAAAAAH////8AAAAAAAe/gA//////////4wcAAAAAAAAAAH////4AAAAAAAP/gAC/////////wz8AAAAAAAAAAB////wAAAAAAAf/gAA/////////wHgAAAAAAAAAAA////AAAAAAAA//8cB/////////4EAAAAAAAAAAAA3///AAAAAAAB///f//////////4AAAAAAAAAAAAAX/5DAAAAAAAB//////3///////8AAAAAAAAAAAAAb/gBgAAAAAAH//////7///////4AAAAAAAAAAAAAN/gBgAAAAAAP////+/8v//////wAAAAAAAAAAAAAE/gAAAAAAAAP////+f+xP/////gAAAAAAAAAAAAACfgAAAAAAAAf/////f/4H/////IAAAAAAAAAAAAAAfgB4AAAAAAf/////v/8D//f/8IAAAAAAAAAAAAAAfgwOAAAAAAf/////v/4B/8f+AAAAAAAAAACAAAAAPxwBwAAAAAf/////n/wA/4P+wAAAAAAAAAAAAAAAD/gAAAAAAAf/////z/gAfwH+AMAAAAAAAAAAAAAAA/kAAAAAAAf/////z+AAfgF/AIAAAAAAAAAAAAAAAD+AAAAAAA///////8AAfAB/gIAAAAAAAAAAAAAAAA+AAAAAAAf//////gAAPAB/gGAAAAAAAAAAAAAAAAMBwAAAAAf/////+EAAOABvgBAAAAAAAAAAAAAAAAGD/gAAAAP//////8AAGAAHASAAAAAAAAAAAAAAAAD//wAAAAH//////8AAHABgABAAAAAAAAAAAAAAAAAv/4AAAAH//////4AABgAgAHAAAAAAAAAAAAAAAAAP//AAAAB/n////4AABAAYBhAAAAAAAAAAAAAAAAAP//wAAAAwD////wAAAADYDgAAAAAAAAAAAAAAAAAP//wAAAAAA////gAAAAB4HgAAAAAAAAAAAAAAAAAf//4AAAAAAf///AAAAAB8fgQAAAAAAAAAAAAAAAA///4AAAAAA///+AAAAAA4/uQAAAAAAAAAAAAAAAA////AAAAAA///8AAAAAAcfcHAAAAAAAAAAAAAAAA////8AAAAA///4AAAAAAefcb+AAAAAAAAAAAAAAA////+AAAAAf//wAAAAAAOAcA/gAAAAAAAAAAAAAA/////gAAAAP//wAAAAAAHAAAP2AAAAAAAAAAAAAAf////gAAAAP//wAAAAAAB8AAPwEAAAAAAAAAAAAAf////gAAAAH//wAAAAAAAGpAHYCAAAAAAAAAAAAAP////AAAAAH//4AAAAAAAACAAMAAAAAAAAAAAAAAP///+AAAAAH//4AAAAAAAAACAAAAAAAAAAAAAAAAH///+AAAAAP//4IAAAAAAAAHjAAAAAAAAAAAAAAAH///8AAAAAP//4MAAAAAAAA/jgAAAAAAAAAAAAAAD///8AAAAAP//44AAAAAAAB/zgAAAAAAAAAAAAAAA///8AAAAAP//x4AAAAAAAH//wAACAAAAAAAAAAAAf//8AAAAAP//B4AAAAAAAH//wAAAAAAAAAAAAAAAf//4AAAAAH/+B4AAAAAAA///4AAAAAAAAAAAAAAAf//4AAAAAH//BwAAAAAAD///8AIAAAAAAAAAAAAAf//wAAAAAH//BwAAAAAAD///+AAAAAAAAAAAAAAAf/+AAAAAAD/+BwAAAAAAH////AAAAAAAAAAAAAAAf/8AAAAAAD/8AAAAAAAAD////AAAAAAAAAAAAAAAf/8AAAAAAD/8AAAAAAAAD////AAAAAAAAAAAAAAA//4AAAAAAB/4AAAAAAAAD////AAAAAAAAAAAAAAA//4AAAAAAB/4AAAAAAAAB////AAAAAAAAAAAAAAA//wAAAAAAA/wAAAAAAAAB/z//AAAAAAAAAAAAAAA//gAAAAAAA/AAAAAAAAAB+A/+AAAAAAAAAAAAAAA//AAAAAAAAQAAAAAAAAABgAv+AAAAAAAAAAAAAAB/8AAAAAAAAAAAAAAAAAAAAAH8AAIAAAAAAAAAAAB/8AAAAAAAAAAAAAAAAAAAAAH8AAOAAAAAAAAAAAB/gAAAAAAAAAAAAAAAAAAAAAAAAAOAAAAAAAAAAAB/gAAAAAAAAAAAAAAAAAAAAAAIAAMAAAAAAAAAAAD/AAAAAAAAAAAAAAAAAAAAAAAYAAwAAAAAAAAAAAB+AAAAAAAAAAAAAAAAAAAAAAAQABgAAAAAAAAAAAD8AAAAAAAAAAAAAAAAAAAAAAAAAHAAAAAAAAAAAAD4AAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAD8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH4AAAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAAADwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADwYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcAAAAAAAAAAAAAAAAAAAAAAAAAAA'; var MASK_W = 240, MASK_H = 96, LAT0 = 84, LAT1 = -56; var BANGALORE = [77.5946, 12.9716], PIN_AT = 0.66; var maskBits = null;function isLand(lng, lat) { if (!maskBits) { var bin = window.atob(MASK64); maskBits = new Uint8Array(bin.length); for (var i = 0; i < bin.length; i++) maskBits[i] = bin.charCodeAt(i); } if (lat > LAT0 || lat < LAT1) return false; var mx = Math.floor((lng + 180) / 360 * MASK_W); var my = Math.floor((LAT0 - lat) / (LAT0 - LAT1) * MASK_H); if (mx < 0 || mx >= MASK_W || my < 0 || my >= MASK_H) return false; var idx = my * MASK_W + mx; return (maskBits[idx >> 3] & (128 >> (idx & 7))) !== 0; }function initCentreMap() { qa('.ck-vc__map').forEach(function (map) { var canvas = q('canvas', map); var pin = q('.ck-vc__pin', map); var label = q('.ck-vc__lbl', map); if (!canvas || !canvas.getContext) return;function paintMap() { var W = map.clientWidth, H = map.clientHeight; if (!W || !H) return; var dpr = Math.min(window.devicePixelRatio || 1, 2); canvas.width = Math.round(W * dpr); canvas.height = Math.round(H * dpr); var ctx = canvas.getContext('2d'); ctx.setTransform(dpr, 0, 0, dpr, 0, 0); ctx.clearRect(0, 0, W, H);var k = Math.cos(((LAT0 + LAT1) / 2) * Math.PI / 180); var s = Math.max(W / 360, H / ((LAT0 - LAT1) / k)); /* solve the offset so Bangalore lands on PIN_AT whatever the shape */ var offX = PIN_AT * W - (BANGALORE[0] + 180) * s; offX = Math.min(0, Math.max(W - 360 * s, offX)); var offY = (H - ((LAT0 - LAT1) / k) * s) / 2;var band = MQ_LAPTOP.matches; var spacing = band ? 6 : 7, radius = band ? 1.7 : 1.5; for (var y = spacing / 2; y < H; y += spacing) { var lat = LAT0 - (y - offY) / s * k; for (var x = spacing / 2; x < W; x += spacing) { if (!isLand((x - offX) / s - 180, lat)) continue; var t = x / W; var alpha = band ? 0.66 : t < 0.30 ? 0.05 : t < 0.62 ? 0.05 + (t - 0.30) / 0.32 * 0.57 : 0.62; ctx.fillStyle = 'rgba(205,186,150,' + alpha.toFixed(3) + ')'; ctx.beginPath(); ctx.arc(x, y, radius, 0, 6.2832); ctx.fill(); } }var pinX = (BANGALORE[0] + 180) * s + offX; var pinY = (LAT0 - BANGALORE[1]) / k * s + offY; if (pin) { pin.style.left = pinX + 'px'; pin.style.top = pinY + 'px'; } if (label) { label.style.top = pinY + 'px'; if (pinX > W - 190) { label.style.left = 'auto'; label.style.right = (W - pinX + 16) + 'px'; label.style.flexDirection = 'row-reverse'; } else { label.style.right = 'auto'; label.style.left = (pinX + 16) + 'px'; label.style.flexDirection = 'row'; } } }paintMap(); window.addEventListener('resize', debounce(paintMap, 180)); window.addEventListener('load', paintMap); }); }/* ------------------------------------------------------------------------ 14. START Each module runs in its own try/catch, so one failing section never stops the others. The FAQ needs no script: Flatsome's accordion already keeps one answer open at a time. ------------------------------------------------------------------------ */ function start() { [ initAnchors, initHero, initLoops, initAbout, initPods, initProcess, initBeforeAfter, initStatement, initEnvironments, initPotential, initAmenities, initMoments, initCentreMap ].forEach(function (fn) { try { fn(); } catch (err) { if (window.console) window.console.warn('[campking] ' + (fn.name || 'module') + ' failed:', err); } }); }if (document.readyState !== 'loading') start(); else document.addEventListener('DOMContentLoaded', start); })();