BIN
static/assets/android-chrome-192x192.png
Normal file
|
After Width: | Height: | Size: 58 KiB |
BIN
static/assets/android-chrome-512x512.png
Normal file
|
After Width: | Height: | Size: 353 KiB |
BIN
static/assets/apple-touch-icon.png
Normal file
|
After Width: | Height: | Size: 52 KiB |
BIN
static/assets/favicon-16x16.png
Normal file
|
After Width: | Height: | Size: 896 B |
BIN
static/assets/favicon-32x32.png
Normal file
|
After Width: | Height: | Size: 2.4 KiB |
BIN
static/assets/favicon.ico
Normal file
|
After Width: | Height: | Size: 15 KiB |
11
static/assets/js/ga-init.js
Normal file
@@ -0,0 +1,11 @@
|
||||
(function () {
|
||||
const script = document.currentScript;
|
||||
const id = script && script.getAttribute('data-ga-id');
|
||||
if (!id) return;
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
function gtag(...args) {
|
||||
window.dataLayer.push(...args);
|
||||
}
|
||||
gtag('js', new Date());
|
||||
gtag('config', id, { anonymize_ip: true });
|
||||
})();
|
||||
108
static/assets/js/script.js
Normal file
@@ -0,0 +1,108 @@
|
||||
// --- theme toggle ---
|
||||
const toggle = document.getElementById('theme-toggle');
|
||||
const root = document.documentElement;
|
||||
const saved = window?.localStorage?.getItem('dark-mode');
|
||||
const sysDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
|
||||
if (saved === 'true') {
|
||||
root.classList.add('dark');
|
||||
root.classList.remove('light');
|
||||
} else if (saved === 'false') {
|
||||
root.classList.add('light');
|
||||
root.classList.remove('dark');
|
||||
} else {
|
||||
if (sysDark) {
|
||||
root.classList.add('dark');
|
||||
root.classList.remove('light');
|
||||
} else {
|
||||
root.classList.add('light');
|
||||
root.classList.remove('dark');
|
||||
}
|
||||
}
|
||||
toggle?.addEventListener('click', () => {
|
||||
const isDark = root.classList.contains('dark');
|
||||
root.classList.toggle('dark', !isDark);
|
||||
root.classList.toggle('light', isDark);
|
||||
window?.localStorage?.setItem('dark-mode', String(!isDark));
|
||||
});
|
||||
|
||||
const { body } = document;
|
||||
|
||||
// --- lightbox base ---
|
||||
const lb = document.getElementById('lightbox');
|
||||
const lbCnt = document.getElementById('lb-content');
|
||||
const lbCap = document.getElementById('lb-caption');
|
||||
document.getElementById('lb-close')?.addEventListener('click', () => {
|
||||
lb?.setAttribute('aria-hidden', 'true');
|
||||
body.classList.remove('lightbox-open');
|
||||
if (lbCnt) lbCnt.innerHTML = '';
|
||||
});
|
||||
|
||||
// Build picture element for lightbox (name, type only)
|
||||
function createPicture(name, type) {
|
||||
const pic = document.createElement('picture');
|
||||
const breakpoints = [
|
||||
{ bp: 'desktop', minWidth: 1024 },
|
||||
{ bp: 'tablet', minWidth: 768 },
|
||||
{ bp: 'mobile', minWidth: 0 }
|
||||
];
|
||||
for (const { bp, minWidth } of breakpoints) {
|
||||
const src = document.createElement('source');
|
||||
src.media = `(min-width:${minWidth}px)`;
|
||||
if (type === 'image') {
|
||||
src.srcset =
|
||||
`/assets/media/${bp}/${name}@1x.webp 1x, /assets/media/${bp}/${name}.webp 2x`;
|
||||
} else {
|
||||
src.srcset =
|
||||
`/assets/media/${bp}/${name}_still@1x.webp 1x, /assets/media/${bp}/${name}_still.webp 2x`;
|
||||
}
|
||||
pic.appendChild(src);
|
||||
}
|
||||
const img = document.createElement('img');
|
||||
img.src = `/assets/media/thumbnail/${name}.webp`;
|
||||
img.alt = '';
|
||||
pic.appendChild(img);
|
||||
return pic;
|
||||
}
|
||||
|
||||
function openLightbox(item) {
|
||||
if (!lbCnt || !lbCap || !lb) return;
|
||||
lbCnt.innerHTML = '';
|
||||
if (item.type === 'video') {
|
||||
const v = document.createElement('video');
|
||||
v.src = `/assets/media/videos/${item.name}.mp4`;
|
||||
v.controls = true;
|
||||
v.autoplay = true;
|
||||
lbCnt.appendChild(v);
|
||||
} else {
|
||||
lbCnt.appendChild(createPicture(item.name, item.type));
|
||||
}
|
||||
lbCap.textContent = item.caption;
|
||||
body.classList.add('lightbox-open');
|
||||
lb.setAttribute('aria-hidden', 'false');
|
||||
}
|
||||
|
||||
// --- bind to pre-rendered gallery ---
|
||||
document.querySelectorAll('.gallery-item').forEach((fig) => {
|
||||
const name = fig.getAttribute('data-name');
|
||||
const type = fig.getAttribute('data-type');
|
||||
const caption = fig.getAttribute('data-caption');
|
||||
if (!name || !type || !caption) return;
|
||||
const item = { name, type, caption };
|
||||
fig.addEventListener('click', () => openLightbox(item));
|
||||
fig.addEventListener('keydown', (e) => {
|
||||
if (e.key === 'Enter') openLightbox(item);
|
||||
});
|
||||
});
|
||||
|
||||
// --- video toggle ---
|
||||
const videoTgl = document.getElementById('show_video');
|
||||
videoTgl?.addEventListener('click', () => {
|
||||
const videoFig = document.querySelector('.gallery-item.video');
|
||||
if (videoFig) {
|
||||
openLightbox({
|
||||
name: videoFig.getAttribute('data-name'),
|
||||
type: videoFig.getAttribute('data-type'),
|
||||
caption: videoFig.getAttribute('data-caption')
|
||||
});
|
||||
}
|
||||
});
|
||||
BIN
static/assets/media/desktop/backyard_parking.webp
Normal file
|
After Width: | Height: | Size: 1.2 MiB |
BIN
static/assets/media/desktop/backyard_parking@1x.webp
Normal file
|
After Width: | Height: | Size: 347 KiB |
BIN
static/assets/media/desktop/bedroom_suite_1.webp
Normal file
|
After Width: | Height: | Size: 826 KiB |
BIN
static/assets/media/desktop/bedroom_suite_1@1x.webp
Normal file
|
After Width: | Height: | Size: 130 KiB |
BIN
static/assets/media/desktop/bedroom_suite_2.webp
Normal file
|
After Width: | Height: | Size: 903 KiB |
BIN
static/assets/media/desktop/bedroom_suite_2@1x.webp
Normal file
|
After Width: | Height: | Size: 146 KiB |
BIN
static/assets/media/desktop/bedroom_suite_3.webp
Normal file
|
After Width: | Height: | Size: 637 KiB |
BIN
static/assets/media/desktop/bedroom_suite_3@1x.webp
Normal file
|
After Width: | Height: | Size: 100 KiB |
BIN
static/assets/media/desktop/coat_closet.webp
Normal file
|
After Width: | Height: | Size: 630 KiB |
BIN
static/assets/media/desktop/coat_closet@1x.webp
Normal file
|
After Width: | Height: | Size: 92 KiB |
BIN
static/assets/media/desktop/deck_1.webp
Normal file
|
After Width: | Height: | Size: 494 KiB |
BIN
static/assets/media/desktop/deck_1@1x.webp
Normal file
|
After Width: | Height: | Size: 135 KiB |
BIN
static/assets/media/desktop/deck_2.webp
Normal file
|
After Width: | Height: | Size: 618 KiB |
BIN
static/assets/media/desktop/deck_2@1x.webp
Normal file
|
After Width: | Height: | Size: 167 KiB |
BIN
static/assets/media/desktop/exterior.webp
Normal file
|
After Width: | Height: | Size: 294 KiB |
BIN
static/assets/media/desktop/exterior@1x.webp
Normal file
|
After Width: | Height: | Size: 142 KiB |
BIN
static/assets/media/desktop/guest_bath.webp
Normal file
|
After Width: | Height: | Size: 315 KiB |
BIN
static/assets/media/desktop/guest_bath@1x.webp
Normal file
|
After Width: | Height: | Size: 85 KiB |
BIN
static/assets/media/desktop/kitchen.webp
Normal file
|
After Width: | Height: | Size: 373 KiB |
BIN
static/assets/media/desktop/kitchen@1x.webp
Normal file
|
After Width: | Height: | Size: 64 KiB |
BIN
static/assets/media/desktop/laundry.webp
Normal file
|
After Width: | Height: | Size: 1005 KiB |
BIN
static/assets/media/desktop/laundry@1x.webp
Normal file
|
After Width: | Height: | Size: 188 KiB |
BIN
static/assets/media/desktop/living_room_1.webp
Normal file
|
After Width: | Height: | Size: 538 KiB |
BIN
static/assets/media/desktop/living_room_1@1x.webp
Normal file
|
After Width: | Height: | Size: 113 KiB |
BIN
static/assets/media/desktop/living_room_2.webp
Normal file
|
After Width: | Height: | Size: 748 KiB |
BIN
static/assets/media/desktop/living_room_2@1x.webp
Normal file
|
After Width: | Height: | Size: 144 KiB |
BIN
static/assets/media/desktop/office_fitness_guest_1.webp
Normal file
|
After Width: | Height: | Size: 800 KiB |
BIN
static/assets/media/desktop/office_fitness_guest_1@1x.webp
Normal file
|
After Width: | Height: | Size: 129 KiB |
BIN
static/assets/media/desktop/office_fitness_guest_2.webp
Normal file
|
After Width: | Height: | Size: 770 KiB |
BIN
static/assets/media/desktop/office_fitness_guest_2@1x.webp
Normal file
|
After Width: | Height: | Size: 115 KiB |
BIN
static/assets/media/desktop/office_fitness_guest_3.webp
Normal file
|
After Width: | Height: | Size: 826 KiB |
BIN
static/assets/media/desktop/office_fitness_guest_3@1x.webp
Normal file
|
After Width: | Height: | Size: 126 KiB |
BIN
static/assets/media/desktop/office_fitness_guest_4.webp
Normal file
|
After Width: | Height: | Size: 688 KiB |
BIN
static/assets/media/desktop/office_fitness_guest_4@1x.webp
Normal file
|
After Width: | Height: | Size: 97 KiB |
BIN
static/assets/media/desktop/onsuite_1.webp
Normal file
|
After Width: | Height: | Size: 423 KiB |
BIN
static/assets/media/desktop/onsuite_1@1x.webp
Normal file
|
After Width: | Height: | Size: 72 KiB |
BIN
static/assets/media/desktop/onsuite_2.webp
Normal file
|
After Width: | Height: | Size: 176 KiB |
BIN
static/assets/media/desktop/onsuite_2@1x.webp
Normal file
|
After Width: | Height: | Size: 35 KiB |
BIN
static/assets/media/desktop/tour_still.webp
Normal file
|
After Width: | Height: | Size: 127 KiB |
BIN
static/assets/media/desktop/tour_still@1x.webp
Normal file
|
After Width: | Height: | Size: 59 KiB |
BIN
static/assets/media/mobile/backyard_parking.webp
Normal file
|
After Width: | Height: | Size: 96 KiB |
BIN
static/assets/media/mobile/backyard_parking@1x.webp
Normal file
|
After Width: | Height: | Size: 26 KiB |
BIN
static/assets/media/mobile/backyard_parking_mobile.webp
Normal file
|
After Width: | Height: | Size: 137 KiB |
BIN
static/assets/media/mobile/bedroom_suite_1.webp
Normal file
|
After Width: | Height: | Size: 37 KiB |
BIN
static/assets/media/mobile/bedroom_suite_1@1x.webp
Normal file
|
After Width: | Height: | Size: 13 KiB |
BIN
static/assets/media/mobile/bedroom_suite_1_mobile.webp
Normal file
|
After Width: | Height: | Size: 51 KiB |
BIN
static/assets/media/mobile/bedroom_suite_2.webp
Normal file
|
After Width: | Height: | Size: 37 KiB |
BIN
static/assets/media/mobile/bedroom_suite_2@1x.webp
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
static/assets/media/mobile/bedroom_suite_2_mobile.webp
Normal file
|
After Width: | Height: | Size: 52 KiB |
BIN
static/assets/media/mobile/bedroom_suite_3.webp
Normal file
|
After Width: | Height: | Size: 32 KiB |
BIN
static/assets/media/mobile/bedroom_suite_3@1x.webp
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
static/assets/media/mobile/bedroom_suite_3_mobile.webp
Normal file
|
After Width: | Height: | Size: 42 KiB |
BIN
static/assets/media/mobile/coat_closet.webp
Normal file
|
After Width: | Height: | Size: 27 KiB |
BIN
static/assets/media/mobile/coat_closet@1x.webp
Normal file
|
After Width: | Height: | Size: 9.6 KiB |
BIN
static/assets/media/mobile/coat_closet_mobile.webp
Normal file
|
After Width: | Height: | Size: 19 KiB |
BIN
static/assets/media/mobile/deck_1.webp
Normal file
|
After Width: | Height: | Size: 43 KiB |
BIN
static/assets/media/mobile/deck_1@1x.webp
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
static/assets/media/mobile/deck_1_mobile.webp
Normal file
|
After Width: | Height: | Size: 30 KiB |
BIN
static/assets/media/mobile/deck_2.webp
Normal file
|
After Width: | Height: | Size: 54 KiB |
BIN
static/assets/media/mobile/deck_2@1x.webp
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
static/assets/media/mobile/deck_2_mobile.webp
Normal file
|
After Width: | Height: | Size: 74 KiB |
BIN
static/assets/media/mobile/exterior.webp
Normal file
|
After Width: | Height: | Size: 59 KiB |
BIN
static/assets/media/mobile/exterior@1x.webp
Normal file
|
After Width: | Height: | Size: 19 KiB |
BIN
static/assets/media/mobile/exterior_mobile.webp
Normal file
|
After Width: | Height: | Size: 80 KiB |
BIN
static/assets/media/mobile/guest_bath.webp
Normal file
|
After Width: | Height: | Size: 30 KiB |
BIN
static/assets/media/mobile/guest_bath@1x.webp
Normal file
|
After Width: | Height: | Size: 10 KiB |
BIN
static/assets/media/mobile/guest_bath_mobile.webp
Normal file
|
After Width: | Height: | Size: 21 KiB |
BIN
static/assets/media/mobile/kitchen.webp
Normal file
|
After Width: | Height: | Size: 27 KiB |
BIN
static/assets/media/mobile/kitchen@1x.webp
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
static/assets/media/mobile/kitchen_mobile.webp
Normal file
|
After Width: | Height: | Size: 34 KiB |
BIN
static/assets/media/mobile/laundry.webp
Normal file
|
After Width: | Height: | Size: 56 KiB |
BIN
static/assets/media/mobile/laundry@1x.webp
Normal file
|
After Width: | Height: | Size: 19 KiB |
BIN
static/assets/media/mobile/laundry_mobile.webp
Normal file
|
After Width: | Height: | Size: 39 KiB |
BIN
static/assets/media/mobile/living_room_1.webp
Normal file
|
After Width: | Height: | Size: 40 KiB |
BIN
static/assets/media/mobile/living_room_1@1x.webp
Normal file
|
After Width: | Height: | Size: 15 KiB |
BIN
static/assets/media/mobile/living_room_1_mobile.webp
Normal file
|
After Width: | Height: | Size: 54 KiB |
BIN
static/assets/media/mobile/living_room_2.webp
Normal file
|
After Width: | Height: | Size: 45 KiB |
BIN
static/assets/media/mobile/living_room_2@1x.webp
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
static/assets/media/mobile/living_room_2_mobile.webp
Normal file
|
After Width: | Height: | Size: 60 KiB |
BIN
static/assets/media/mobile/office_fitness_guest_1.webp
Normal file
|
After Width: | Height: | Size: 39 KiB |
BIN
static/assets/media/mobile/office_fitness_guest_1@1x.webp
Normal file
|
After Width: | Height: | Size: 13 KiB |
BIN
static/assets/media/mobile/office_fitness_guest_1_mobile.webp
Normal file
|
After Width: | Height: | Size: 51 KiB |
BIN
static/assets/media/mobile/office_fitness_guest_2.webp
Normal file
|
After Width: | Height: | Size: 38 KiB |
BIN
static/assets/media/mobile/office_fitness_guest_2@1x.webp
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
static/assets/media/mobile/office_fitness_guest_2_mobile.webp
Normal file
|
After Width: | Height: | Size: 50 KiB |
BIN
static/assets/media/mobile/office_fitness_guest_3.webp
Normal file
|
After Width: | Height: | Size: 38 KiB |
BIN
static/assets/media/mobile/office_fitness_guest_3@1x.webp
Normal file
|
After Width: | Height: | Size: 13 KiB |
BIN
static/assets/media/mobile/office_fitness_guest_3_mobile.webp
Normal file
|
After Width: | Height: | Size: 51 KiB |
BIN
static/assets/media/mobile/office_fitness_guest_4.webp
Normal file
|
After Width: | Height: | Size: 31 KiB |
BIN
static/assets/media/mobile/office_fitness_guest_4@1x.webp
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
static/assets/media/mobile/office_fitness_guest_4_mobile.webp
Normal file
|
After Width: | Height: | Size: 43 KiB |
BIN
static/assets/media/mobile/onsuite_1.webp
Normal file
|
After Width: | Height: | Size: 25 KiB |