Puzzle: Click all crown points to unlock.
Upload Art (Locked)
Clear Gallery
×
Upload Art
Add JPG, PNG, or GIF. Multiple files allowed.
Add to Carousel
.mkm-wrap{–bg:#0f0f10;–panel:#17181b;–muted:#a1a1aa;–ring:#e11d48;–text:#f5f5f5;–brand:#f2c94c;–btn:#222;–ghost:#2b2b2b; font-family:system-ui,-apple-system,Segoe UI,Roboto,Inter,Arial,sans-serif;color:var(–text);background:var(–bg);padding:24px;border-radius:16px;box-shadow:0 8px 30px rgba(0,0,0,.35)}
.mkm-header h2{margin:0 0 6px;font-size:clamp(22px,4vw,34px)}
.mkm-sub{margin:0 0 16px;color:var(–muted)}
.mkm-puzzle{background:var(–panel);border:1px solid #222;border-radius:14px;padding:18px;margin-bottom:16px}
.mkm-puzzle-instructions{margin-bottom:10px;color:var(–muted)}
.mkm-crown-wrap{display:grid;gap:10px;justify-items:center}
.mkm-crown{width:min(720px,100%);height:auto;display:block;filter:drop-shadow(0 6px 14px rgba(0,0,0,.35))}
.mkm-hit{cursor:pointer}
.mkm-progress{display:flex;gap:10px;align-items:center}
.mkm-progress #mkm-progress-count{font-weight:700}
.mkm-unlock{display:flex;justify-content:center;margin-top:8px}
.mkm-btn{background:var(–btn);color:var(–text);border:1px solid #333;border-radius:12px;padding:10px 14px;font-weight:600;cursor:pointer;transition:.2s;box-shadow:0 2px 0 rgba(0,0,0,.4)}
.mkm-btn:hover{transform:translateY(-1px)}
.mkm-btn[disabled],.mkm-btn[aria-disabled=”true”]{opacity:.45;cursor:not-allowed}
.mkm-ghost{background:var(–ghost)}
.mkm-carousel-wrap{position:relative;background:var(–panel);border:1px solid #222;border-radius:14px;padding:12px}
.mkm-carousel{position:relative;overflow:hidden;border-radius:12px;aspect-ratio:16/9;background:#0b0b0c}
.mkm-slide{position:absolute;inset:0;opacity:0;transition:opacity .35s ease}
.mkm-slide.is-active{opacity:1}
.mkm-slide img{width:100%;height:100%;object-fit:contain;background:radial-gradient(ellipse at center, #111 0%, #0b0b0c 60%)}
.mkm-controls{display:flex;justify-content:space-between;padding:10px}
.mkm-dots{display:flex;gap:8px;justify-content:center;flex-wrap:wrap;padding:8px}
.mkm-dot{width:10px;height:10px;border-radius:50%;background:#3a3a3a;border:1px solid #555;cursor:pointer}
.mkm-dot.is-active{background:var(–ring);box-shadow:0 0 0 3px rgba(225,29,72,.25)}
.mkm-utility{display:flex;justify-content:flex-end;margin-top:10px}
/* Modal */
.mkm-modal{position:fixed;inset:0;background:rgba(0,0,0,.6);display:none;place-items:center;padding:20px;z-index:9999}
.mkm-modal[aria-hidden=”false”]{display:grid}
.mkm-modal-inner{background:#111;border:1px solid #333;border-radius:14px;padding:18px;max-width:520px;width:100%;box-shadow:0 12px 40px rgba(0,0,0,.45)}
.mkm-modal h3{margin:0 0 8px}
.mkm-modal p{margin:0 0 12px;color:var(–muted)}
.mkm-modal-close{position:absolute;margin-left:auto;margin-right:-8px;margin-top:-8px;right:calc(50% – 260px);background:#1c1c1c;color:#fff;border:1px solid #333;border-radius:50%;width:34px;height:34px;font-size:20px;cursor:pointer}
.mkm-modal-actions{display:flex;gap:10px;justify-content:flex-end;margin-top:12px}
/* Visual feedback when a point is solved */
.mkm-solved{filter: drop-shadow(0 0 0 rgba(0,0,0,0)) hue-rotate(12deg)}
.mkm-solved .mkm-point-lit{animation: mkm-ping 700ms ease-out forwards}
@keyframes mkm-ping{0%{opacity:.2;transform:scale(.8)} 100%{opacity:1;transform:scale(1)}}
(function(){
const STORAGE_KEY = ‘mkm_gallery_v1’;
const hitPoints = new Set();
const required = [‘p1′,’p2′,’p3′,’p4′,’p5’];
let slides = [];
let index = 0;
const els = {
progress: document.getElementById(‘mkm-progress-count’),
openUpload: document.getElementById(‘mkm-open-upload’),
resetPuzzle: document.getElementById(‘mkm-reset-puzzle’),
carousel: document.getElementById(‘mkm-carousel’),
dots: document.getElementById(‘mkm-dots’),
prev: document.getElementById(‘mkm-prev’),
next: document.getElementById(‘mkm-next’),
modal: document.getElementById(‘mkm-modal’),
closeModal: document.getElementById(‘mkm-close-modal’),
file: document.getElementById(‘mkm-file’),
addFiles: document.getElementById(‘mkm-add-files’),
clearGallery: document.getElementById(‘mkm-clear-gallery’)
};
// Load persisted images
try {
const saved = JSON.parse(localStorage.getItem(STORAGE_KEY)||'[]’);
if (Array.isArray(saved)) slides = saved;
} catch(e){ slides = []; }
// Build carousel UI
function renderCarousel(){
els.carousel.innerHTML = ”;
els.dots.innerHTML = ”;
if(slides.length === 0){
els.carousel.innerHTML = ‘
)+')
‘;
els.dots.innerHTML = ”;
index = 0;
return;
}
slides.forEach((src,i)=>{
const slide = document.createElement(‘div’);
slide.className = ‘mkm-slide’+(i===index?’ is-active’:”);
const img = document.createElement(‘img’);
img.loading = ‘lazy’;
img.alt = ‘Gallery image ‘+(i+1);
img.src = src;
slide.appendChild(img);
els.carousel.appendChild(slide);
const dot = document.createElement(‘button’);
dot.className = ‘mkm-dot’+(i===index?’ is-active’:”);
dot.type = ‘button’;
dot.setAttribute(‘role’,’tab’);
dot.setAttribute(‘aria-label’,’Go to slide ‘+(i+1));
dot.addEventListener(‘click’, ()=>goTo(i));
els.dots.appendChild(dot);
});
}
function goTo(i){
if(slides.length===0) return;
index = (i+slides.length)%slides.length;
[…els.carousel.children].forEach((el,idx)=>{
el.classList.toggle(‘is-active’, idx===index);
});
[…els.dots.children].forEach((el,idx)=>{
el.classList.toggle(‘is-active’, idx===index);
});
}
els.prev.addEventListener(‘click’, ()=>goTo(index-1));
els.next.addEventListener(‘click’, ()=>goTo(index+1));
function placeholderSVG(){
return `
Your uploads will appear here
`;
}
// Puzzle logic
document.querySelectorAll(‘.mkm-hit’).forEach(hit=>{
hit.addEventListener(‘click’, ()=>{
const id = hit.dataset.id;
hitPoints.add(id);
// brief visual ping: add a small circle overlay
const svg = hit.closest(‘svg’);
const cx = hit.getAttribute(‘cx’), cy = hit.getAttribute(‘cy’);
const ping = document.createElementNS(‘http://www.w3.org/2000/svg’,’circle’);
ping.setAttribute(‘cx’, cx); ping.setAttribute(‘cy’, cy); ping.setAttribute(‘r’, 12);
ping.setAttribute(‘fill’, ‘#e11d48’); ping.setAttribute(‘class’,’mkm-point-lit’);
svg.appendChild(ping);
setTimeout(()=>ping.remove(), 650);
updateProgress();
});
});
function updateProgress(){
els.progress.textContent = `${hitPoints.size} / ${required.length}`;
const solved = required.every(x=>hitPoints.has(x));
if(solved){
els.openUpload.disabled = false;
els.openUpload.setAttribute(‘aria-disabled’,’false’);
els.openUpload.textContent = ‘Upload Art’;
document.querySelector(‘.mkm-crown’).classList.add(‘mkm-solved’);
}
}
els.resetPuzzle.addEventListener(‘click’, ()=>{
hitPoints.clear();
els.progress.textContent = ‘0 / 5’;
els.openUpload.disabled = true;
els.openUpload.setAttribute(‘aria-disabled’,’true’);
els.openUpload.textContent = ‘Upload Art (Locked)’;
document.querySelector(‘.mkm-crown’).classList.remove(‘mkm-solved’);
});
// Modal controls
function openModal(){ els.modal.setAttribute(‘aria-hidden’,’false’); }
function closeModal(){ els.modal.setAttribute(‘aria-hidden’,’true’); els.file.value = ”; }
els.openUpload.addEventListener(‘click’, openModal);
els.closeModal.addEventListener(‘click’, closeModal);
els.modal.addEventListener(‘click’, (e)=>{ if(e.target === els.modal) closeModal(); });
// Add files to carousel
els.addFiles.addEventListener(‘click’, async ()=>{
const files = Array.from(els.file.files||[]);
if(!files.length){ alert(‘Choose one or more images.’); return; }
for(const f of files){
if(!f.type.startsWith(‘image/’)) continue;
const dataUrl = await fileToDataURL(f);
slides.push(dataUrl);
}
persist();
renderCarousel();
closeModal();
goTo(slides.length-1);
});
function fileToDataURL(file){
return new Promise((res,rej)=>{
const fr = new FileReader();
fr.onload = ()=>res(fr.result);
fr.onerror = rej;
fr.readAsDataURL(file);
});
}
function persist(){
try { localStorage.setItem(STORAGE_KEY, JSON.stringify(slides)); } catch(e){ /* storage might be full */ }
}
els.clearGallery.addEventListener(‘click’, ()=>{
if(confirm(‘Remove all saved images from this browser?’)){
slides = [];
persist();
renderCarousel();
}
});
// Init
renderCarousel();
})();