Minimalist Photo Studio Rental

Book clean, light-filled studios by the hour. No hidden fees. Fully equipped, distraction-free spaces for creators.

High-contrast, accessible, and SEO-optimized. luminasip.click

Why creators pick LuminaSip

Transparent pricing

Clear hourly rates. Instant totals in your cart.

Natural light

Consistent daylight planning with availability previews.

Essential amenities

Seamless backdrops, Wi‑Fi, changing area, props shelf.

Instant booking

Reserve in minutes. Manage favorites and compare.

Featured studios (teaser)

See all

Get studio updates

Sign up for clean release notes and availability drops.

We send no spam. Unsubscribe anytime.

'; initHeaderInteractions(); initFooterInteractions(); } })(); async function loadFeatured() { const wrap = document.getElementById('featured-teaser'); if(!wrap) return; const skeleton = () => { wrap.innerHTML = Array.from({length:3}).map(()=>`
`).join(''); }; skeleton(); try { const res = await fetch('catalog.json', {cache:'no-store'}); if(!res.ok) throw new Error('catalog.json not available'); const data = await res.json(); const safe = Array.isArray(data) ? data : []; const top = safe.slice(0,3); wrap.innerHTML = top.map(item => { const name = String(item.name || 'Studio'); const short = String(item.short || 'Minimal, flexible studio built for clean sets.'); const capacity = String(item.capacity ?? '—'); const sizeSqm = String(item.sizeSqm ?? '—'); const pricePerHour = Number(item.pricePerHour ?? 0); const id = Number(item.id ?? 0); return `

${escapeHtml(name)}

${escapeHtml(short)}

Capacity: ${escapeHtml(capacity)} · ${escapeHtml(sizeSqm)} m² · $${Number.isFinite(pricePerHour)?pricePerHour.toFixed(0):'0'}/h

`; }).join(''); wrap.querySelectorAll('.js-open-details').forEach(b=>{ b.addEventListener('click', async e=>{ const id = parseInt(e.currentTarget.dataset.id,10); const item = safe.find(x=>Number(x.id)===id); if (item && typeof window.openStudioDetails === 'function') window.openStudioDetails(item); }); }); wrap.querySelectorAll('.js-add-fav').forEach(b=>{ b.addEventListener('click', e=>{ const id = parseInt(e.currentTarget.dataset.id,10); const fav = safeJsonArray(localStorage.getItem('psr_favorites')); if (!fav.includes(id)) fav.push(id); localStorage.setItem('psr_favorites', JSON.stringify(fav)); if (typeof window.toast === 'function') window.toast('Added to favorites'); }); }); if(top.length===0){ wrap.innerHTML = `
Featured studios will appear here once the catalog is available.
`; } } catch(e){ console.error(e); wrap.innerHTML = `

Featured studios

We couldn’t load the catalog right now. Try again later or browse the full list.

Open Catalog
`; } } document.addEventListener('DOMContentLoaded', loadFeatured); function initHeaderInteractions(){ const root = document.documentElement; const saved = localStorage.getItem('psr_theme') || 'light'; if (saved==='dark') root.classList.add('dark'); else root.classList.remove('dark'); document.querySelectorAll('[data-open-modal]').forEach(btn=>{ btn.addEventListener('click', ()=>{ const id = btn.getAttribute('data-open-modal'); const m = document.getElementById(id); if(m){ m.classList.remove('hidden'); m.setAttribute('aria-hidden','false'); const focusable = m.querySelector('button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'); if (focusable) focusable.focus(); } }); }); document.querySelectorAll('[data-close-modal]').forEach(btn=>{ btn.addEventListener('click', ()=>{ const id = btn.getAttribute('data-close-modal'); const m = document.getElementById(id); if(m){ m.classList.add('hidden'); m.setAttribute('aria-hidden','true'); } }); }); document.addEventListener('keydown', (e)=>{ if(e.key !== 'Escape') return; const open = document.querySelector('[role="dialog"]:not(.hidden), dialog[open]'); if(open){ open.classList.add('hidden'); open.setAttribute('aria-hidden','true'); if (open.tagName === 'DIALOG' && typeof open.close === 'function') open.close(); } }); window.openStudioDetails = function(item){ const m = document.getElementById('studio-details-modal'); if(!m) return; const titleEl = m.querySelector('[data-mdl-title]'); const bodyEl = m.querySelector('[data-mdl-body]'); const addEl = m.querySelector('[data-mdl-addcart]'); const name = String(item.name || 'Studio'); const description = String(item.description || item.short || 'Minimal studio with flexible setup.'); const capacity = String(item.capacity ?? '—'); const sizeSqm = String(item.sizeSqm ?? '—'); const amenities = Array.isArray(item.amenities) ? item.amenities.map(x=>String(x)) : []; const availability = Array.isArray(item.availability) ? item.availability.map(x=>String(x)) : []; const price = Number(item.pricePerHour ?? 0); const rating = Number(item.rating ?? 0); if(titleEl) titleEl.textContent = name; if(bodyEl){ bodyEl.innerHTML = `

${escapeHtml(description)}

$${Number.isFinite(price)?price.toFixed(0):'0'}/hour · Rating ${Number.isFinite(rating)?rating.toFixed(1):'0.0'}

`; } if(addEl) addEl.setAttribute('data-id', String(item.id ?? '')); m.classList.remove('hidden'); m.setAttribute('aria-hidden','false'); const first = m.querySelector('button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'); if(first) first.focus(); }; window.toast = function(msg){ const t = document.getElementById('toast'); if(!t) return; t.textContent = String(msg || ''); t.classList.remove('hidden'); t.setAttribute('aria-hidden','false'); clearTimeout(window.__psrToastTimer); window.__psrToastTimer = setTimeout(()=>{ t.classList.add('hidden'); t.setAttribute('aria-hidden','true'); }, 1600); }; document.body.addEventListener('click', e=>{ const add = e.target && e.target.closest && e.target.closest('[data-mdl-addcart]'); if(add){ const id = parseInt(add.getAttribute('data-id'),10); if(!Number.isFinite(id)) return; const cart = safeJsonArray(localStorage.getItem('psr_cart')).map(x=>{ if(x && typeof x === 'object') return x; return null; }).filter(Boolean); const found = cart.find(i=>Number(i.id)===id); if(found) found.qty = Number(found.qty || 1) + 1; else cart.push({id:id, qty:1}); localStorage.setItem('psr_cart', JSON.stringify(cart)); if (typeof window.toast === 'function') window.toast('Added to cart'); return; } const modalBackdrop = e.target && e.target.matches && e.target.matches('[role="dialog"]'); if(modalBackdrop){ const closeBtn = modalBackdrop.querySelector('[data-close-modal]'); if(closeBtn) closeBtn.click(); } }); const newsletterForm = document.getElementById('newsletter-form'); const newsletterEmail = document.getElementById('newsletter-email'); const newsletterConsent = document.getElementById('newsletter-consent'); const newsletterHint = document.getElementById('newsletter-hint'); if(newsletterForm && newsletterEmail && newsletterConsent){ const setHint = (text, ok) => { if(!newsletterHint) return; newsletterHint.textContent = text; newsletterHint.className = ok ? 'mt-2 text-xs text-gray-600' : 'mt-2 text-xs text-red-700'; }; const validate = () => { const v = String(newsletterEmail.value || '').trim(); const okEmail = /^[^\s@]+@[^\s@]+\.[^\s@]{2,}$/i.test(v); const okConsent = !!newsletterConsent.checked; if(!okEmail){ newsletterEmail.setAttribute('aria-invalid','true'); setHint('Enter a valid email address (e.g., [email protected]).', false); return false; } newsletterEmail.removeAttribute('aria-invalid'); if(!okConsent){ setHint('Please confirm consent to receive updates.', false); return false; } setHint('We send no spam. Unsubscribe anytime.', true); return true; }; newsletterEmail.addEventListener('input', validate); newsletterConsent.addEventListener('change', validate); newsletterForm.addEventListener('submit', (e)=>{ if(!validate()){ e.preventDefault(); newsletterEmail.focus(); return; } try{ localStorage.setItem('psr_newsletter_email', String(newsletterEmail.value || '').trim()); localStorage.setItem('psr_newsletter_ts', String(Date.now())); }catch(_){} if (typeof window.toast === 'function') window.toast('Subscription ready'); }); } } function initFooterInteractions(){ const key='psr_cookie_ok'; const b = document.getElementById('cookie-banner'); if (b && localStorage.getItem(key)==='1') { b.classList.add('hidden'); b.setAttribute('aria-hidden','true'); } document.querySelectorAll('[data-accept-cookies]').forEach(btn=>{ btn.addEventListener('click', ()=>{ localStorage.setItem(key,'1'); if(b){ b.classList.add('hidden'); b.setAttribute('aria-hidden','true'); } if (typeof window.toast === 'function') window.toast('Cookie preferences saved'); }); }); document.querySelectorAll('[data-decline-cookies]').forEach(btn=>{ btn.addEventListener('click', ()=>{ localStorage.setItem(key,'0'); if(b){ b.classList.add('hidden'); b.setAttribute('aria-hidden','true'); } if (typeof window.toast === 'function') window.toast('Non-essential cookies declined'); }); }); const off = document.getElementById('offline-note'); function sync(){ if(off) off.classList.toggle('hidden', navigator.onLine); } window.addEventListener('online', sync); window.addEventListener('offline', sync); sync(); const year = document.getElementById('footer-year'); if(year) year.textContent = String(new Date().getFullYear()); const countdownEl = document.getElementById('next-drop-countdown'); if(countdownEl){ const now = new Date(); const target = new Date(now); target.setHours(18,0,0,0); if(target.getTime() <= now.getTime()) target.setDate(target.getDate()+1); const tick = ()=>{ const t = target.getTime() - Date.now(); if(t <= 0){ countdownEl.textContent = "00:00:00"; return; } const s = Math.floor(t/1000); const hh = String(Math.floor(s/3600)).padStart(2,'0'); const mm = String(Math.floor((s%3600)/60)).padStart(2,'0'); const ss = String(s%60).padStart(2,'0'); countdownEl.textContent = `${hh}:${mm}:${ss}`; }; tick(); window.__psrCountdownTimer && clearInterval(window.__psrCountdownTimer); window.__psrCountdownTimer = setInterval(tick, 1000); } } function safeJsonArray(s){ try{ const v = JSON.parse(s || '[]'); return Array.isArray(v) ? v : []; } catch(e){ return []; } } function escapeHtml(str){ return String(str) .replaceAll('&','&') .replaceAll('<','<') .replaceAll('>','>') .replaceAll('"','"') .replaceAll("'","'"); }