!DOCTYPE html
html lang=en
head
meta charset=UTF-8
meta http-equiv=Content-Security-Policy content=frame-src httpswww.youtube.com httpsyoutube-nocookie.com httpsmaps.google.com httpswww.google.com httpsplayer.vimeo.com 'self'
meta http-equiv=Cache-Control content=no-cache, no-store, must-revalidate
meta http-equiv=Pragma content=no-cache
meta http-equiv=Expires content=0
meta name=viewport content=width=device-width, initial-scale=1.0
titleDemand Engine — IGVhopetitle
link rel=icon type=imagex-icon href=imagesimg_001.ico
link href=httpsfonts.googleapis.comcss2family=Montserratwght@300;400;500;600;700&display=swap rel=stylesheet
script src=httpsunpkg.com@elevenlabsconvai-widget-embed async type=textjavascriptscript
script src=httpscdn.jsdelivr.netnpmhls.js@1disthls.min.jsscript
script src=httpsunpkg.commapbox-gl@2.15.0distmapbox-gl.jsscript
link href=httpsunpkg.commapbox-gl@2.15.0distmapbox-gl.css rel=stylesheet
style
, before, after { box-sizing border-box; margin 0; padding 0; }
root {
--teal #1A5C50;
--teal-deep #123D36;
--teal-mid #2B6B5A;
--steel #2C5F7A;
--amber #C8683A;
--amber-light #E8A24A;
--warm-white #F5F1E8;
--white #FFFFFF;
--text-dark #1A2A1A;
--sage-tint #E5F0E6;
}
html, body {
height 100%;
height 100dvh;
width 100%;
overflow hidden;
background #F0EDE6;
font-family 'Montserrat', sans-serif;
}
style
script
if (typeof mapboxgl !== 'undefined') {
mapboxgl.accessToken = 'pk.eyJ1IjoiaWd2aG9wZSIsImEiOiJjbXF2YTIybncwaGthMnNvZWY1djg5YnhyIn0.uzXWiXtI8gMp-iZH2z9arg';
}
var _approxLocationMap = null;
function createApproxCircleGeoJSON(lat, lng, radiusKm, points) {
points = points 64;
var coords = [];
var distanceX = radiusKm (111.320 Math.cos(lat Math.PI 180));
var distanceY = radiusKm 110.574;
for (var i = 0; i points; i++) {
var theta = (i points) (2 Math.PI);
coords.push([lng + distanceX Math.cos(theta), lat + distanceY Math.sin(theta)]);
}
coords.push(coords[0]);
return { type 'Feature', geometry { type 'Polygon', coordinates [coords] } };
}
function renderApproxCircleLayer(map) {
if (map.getLayer('approx-circle-fill')) return;
map.addLayer({ id 'approx-circle-fill', type 'fill', source 'approx-circle', paint { 'fill-color' '#1A5C50', 'fill-opacity' 0.18 } });
map.addLayer({ id 'approx-circle-outline', type 'line', source 'approx-circle', paint { 'line-color' '#1A5C50', 'line-width' 2 } });
}
function updateApproxLocationMap(lat, lng) {
if (typeof mapboxgl === 'undefined') {
var frame = document.getElementById('detail-map-frame');
if (frame) frame.innerHTML = 'div style=width100%;height100%;displayflex;align-itemscenter;justify-contentcenter;background#F5F1E8;color#888;font-size12px;font-familyMontserrat,sans-serif;Map unavailablediv';
return;
}
var circleData = createApproxCircleGeoJSON(lat, lng, 0.5);
try {
if (!_approxLocationMap) {
_approxLocationMap = new mapboxgl.Map({
container 'detail-map-frame',
style 'mapboxstylesmapboxlight-v11',
center [lng, lat],
zoom 13.2,
scrollZoom false,
attributionControl false
});
_approxLocationMap.addControl(new mapboxgl.NavigationControl({ showCompass false }), 'top-right');
_approxLocationMap.on('load', function() {
_approxLocationMap.addSource('approx-circle', { type 'geojson', data circleData });
renderApproxCircleLayer(_approxLocationMap);
_approxLocationMap.resize();
});
if (typeof ResizeObserver !== 'undefined') {
var frameEl = document.getElementById('detail-map-frame');
if (frameEl) {
new ResizeObserver(function() {
if (_approxLocationMap) _approxLocationMap.resize();
}).observe(frameEl);
}
}
} else {
_approxLocationMap.jumpTo({ center [lng, lat], zoom 13.2 });
_approxLocationMap.resize();
var src = _approxLocationMap.getSource('approx-circle');
if (src) {
src.setData(circleData);
} else {
_approxLocationMap.on('load', function() {
_approxLocationMap.addSource('approx-circle', { type 'geojson', data circleData });
renderApproxCircleLayer(_approxLocationMap);
});
}
}
} catch (e) {
console.error('Approx location map failed to render', e);
_approxLocationMap = null;
var frameOnError = document.getElementById('detail-map-frame');
if (frameOnError) {
frameOnError.innerHTML = 'div style=width100%;height100%;displayflex;align-itemscenter;justify-contentcenter;background#F5F1E8;color#888;font-size12px;font-familyMontserrat,sans-serif;text-aligncenter;padding12px;Map unavailable in this browser. Try disabling strict tracking prevention for this site, or view in a different browser.div';
}
}
}
function getListingData(cardEl) {
var title = (cardEl.querySelector('.card-title') {}).textContent 'Home Listing';
var locationEl = cardEl.querySelector('.card-location');
var location = locationEl (locationEl.textContent '').trim() '';
location = location.replace(^[sS](Port AlberniUclueletNanaimoCampbell RiverVictoriaCourtenay)i, '$1');
var priceEl = cardEl.querySelector('.card-price-tag');
var price = priceEl priceEl.textContent.trim() '-';
var rentEl = cardEl.querySelector('.card-rent');
var rent = rentEl rentEl.textContent.trim().replace(s+g,' ') '-';
var metas = Array.from(cardEl.querySelectorAll('.card-meta-item')).map(function(m){ return m.textContent.trim(); });
var beds = metas[0] '-';
var baths = metas[1] '-';
var type = metas[2] '-';
var badgeEl = cardEl.querySelector('.card-badge');
var badge = badgeEl badgeEl.textContent.trim() '';
var region = cardEl.getAttribute('data-region') '';
var titleEl = cardEl.querySelector('.card-title');
var imgUrl = titleEl titleEl.getAttribute('data-img') null;
var imgUrl2 = titleEl titleEl.getAttribute('data-img2') null;
var imgUrl3 = titleEl titleEl.getAttribute('data-img3') null;
var imgUrl4 = titleEl titleEl.getAttribute('data-img4') null;
var imgUrl5 = titleEl titleEl.getAttribute('data-img5') null;
var imgUrl6 = titleEl titleEl.getAttribute('data-img6') null;
var imgUrl7 = titleEl titleEl.getAttribute('data-img7') null;
var imgUrl8 = titleEl titleEl.getAttribute('data-img8') null;
var imgUrl9 = titleEl titleEl.getAttribute('data-img9') null;
var videoUrl = titleEl (titleEl.getAttribute('data-video') '') '';
var gradStyle = (cardEl.querySelector('.card-img') {}).style {};
var gradient = gradStyle.background 'linear-gradient(135deg, #1A4848, #2B6B5A)';
Template lookup
var tpl = listingTemplates[title] listingTemplates['default'];
return {
title title,
location location.replace(^s[u{1F4CD}📍]su, '').trim(),
price price,
rent rent,
beds beds,
baths baths,
type type,
badge badge,
region region,
gradient gradient,
imgUrl imgUrl,
imgUrl2 imgUrl2,
imgUrl3 imgUrl3,
imgUrl4 imgUrl4,
imgUrl5 imgUrl5,
imgUrl6 imgUrl6,
imgUrl7 imgUrl7,
imgUrl8 imgUrl8,
imgUrl9 imgUrl9,
videoUrl videoUrl,
sqft (title.indexOf('- Unit B') !== -1 title.indexOf('- Unit C') !== -1) '777' tpl.sqft,
landSize tpl.landSize,
builtIn tpl.builtIn,
parking title.indexOf('- Unit A') !== -1 '2' tpl.parking,
propertyType tpl.propertyType,
tenure tpl.tenure,
annualTax tpl.annualTax,
moveInDate tpl.moveInDate 'Spring 2027',
description tpl.description,
amenities tpl.amenities,
partners tpl.partners,
neighbourhood tpl.neighbourhood listingTemplates['default'].neighbourhood,
statistics tpl.statistics listingTemplates['default'].statistics,
};
}
function openListingDetail(cardEl) {
var d = getListingData(cardEl);
Nav
if (document.getElementById('detail-nav-title')) document.getElementById('detail-nav-title').textContent = d.title;
if (document.getElementById('detail-nav-badge')) document.getElementById('detail-nav-badge').textContent = d.badge d.type;
Hero gallery
var heroBg = document.getElementById('detail-hero-bg');
if (d.imgUrl) {
heroBg.style.background = '';
heroBg.style.backgroundImage = url(' + d.imgUrl + ');
heroBg.style.backgroundSize = 'cover';
heroBg.style.backgroundPosition = 'center';
} else {
heroBg.style.backgroundImage = '';
heroBg.style.background = d.gradient;
}
Store images for lightbox
_currentListingImages = [];
if (d.imgUrl) _currentListingImages.push(d.imgUrl);
if (d.imgUrl2) _currentListingImages.push(d.imgUrl2);
if (d.imgUrl3) _currentListingImages.push(d.imgUrl3);
if (d.imgUrl4) _currentListingImages.push(d.imgUrl4);
if (d.imgUrl5) _currentListingImages.push(d.imgUrl5);
if (d.imgUrl6) _currentListingImages.push(d.imgUrl6);
if (d.imgUrl7) _currentListingImages.push(d.imgUrl7);
if (d.imgUrl8) _currentListingImages.push(d.imgUrl8);
if (d.imgUrl9) _currentListingImages.push(d.imgUrl9);
var mainGallery = document.getElementById('detail-gallery-main');
if (mainGallery) mainGallery.style.cursor = _currentListingImages.length 'zoom-in' 'default';
var photoCountText = document.getElementById('detail-hero-photocount-text');
var photoCountWrap = document.getElementById('detail-hero-photocount');
if (photoCountText && photoCountWrap) {
photoCountText.textContent = '1 ' + (_currentListingImages.length 1);
photoCountWrap.style.visibility = _currentListingImages.length 1 'visible' 'hidden';
}
Build the secondary thumbnail grid tier 2 (medium, first 2) + tier 3 (small, remaining)
var thumbsWrap = document.getElementById('detail-gallery-thumbs');
if (thumbsWrap) {
var secondary = [];
if (d.imgUrl2) secondary.push(d.imgUrl2);
if (d.imgUrl3) secondary.push(d.imgUrl3);
if (d.imgUrl4) secondary.push(d.imgUrl4);
if (d.imgUrl5) secondary.push(d.imgUrl5);
if (d.imgUrl6) secondary.push(d.imgUrl6);
if (d.imgUrl7) secondary.push(d.imgUrl7);
if (d.imgUrl8) secondary.push(d.imgUrl8);
if (d.imgUrl9) secondary.push(d.imgUrl9);
var tier2 = secondary.slice(0, 2);
var tier3 = secondary.slice(2);
function thumbHtml(url, i) {
return 'div class=gallery-thumb style=background-imageurl('' + url + ''); onclick=event.stopPropagation();lightboxOpen(_currentListingImages,' + (i + 1) + ')div';
}
var html = '';
if (tier2.length) {
html += 'div class=gallery-tier2' + tier2.map(function(url, i) { return thumbHtml(url, i); }).join('') + 'div';
}
if (tier3.length) {
html += 'div class=gallery-tier3' + tier3.map(function(url, i) { return thumbHtml(url, i + tier2.length); }).join('') + 'div';
}
thumbsWrap.innerHTML = html;
thumbsWrap.style.display = secondary.length 'flex' 'none';
}
if (document.getElementById('detail-hero-type')) document.getElementById('detail-hero-type').textContent = d.type + ' u2022 ' + d.region;
if (document.getElementById('detail-hero-title')) document.getElementById('detail-hero-title').textContent = d.title;
if (document.getElementById('detail-hero-loc-text')) document.getElementById('detail-hero-loc-text').textContent = d.location;
Stats
if (document.getElementById('ds-price')) document.getElementById('ds-price').textContent = d.price;
if (document.getElementById('ds-rent')) document.getElementById('ds-rent').textContent = d.rent.replace('mo','');
if (document.getElementById('ds-beds')) document.getElementById('ds-beds').textContent = d.beds.replace(' bed','');
if (document.getElementById('ds-baths')) document.getElementById('ds-baths').textContent = d.baths.replace(' bath','');
if (document.getElementById('ds-sqft')) document.getElementById('ds-sqft').textContent = d.sqft;
Description
if (document.getElementById('detail-desc')) document.getElementById('detail-desc').textContent = d.description;
Amenities
var amenEl = document.getElementById('detail-amenities');
amenEl.innerHTML = d.amenities.map(function(a) {
return 'div class=amenity-pillspan class=amenity-icon' + a.icon + 'spanspan class=amenity-text onclick=handleGatedValueClick()span class=amenity-label' + a.label + 'spanspan class=amenity-detail' + (a.detail '') + 'spanspandiv';
}).join('');
Partners
var parEl = document.getElementById('detail-partners');
parEl.innerHTML = d.partners.map(function(p) {
return 'span class=partner-badgespan class=partner-badge-iconsvg width=10 height=10 viewBox=0 0 24 24 fill=none stroke=white stroke-width=2.5 stroke-linecap=round stroke-linejoin=roundpolyline points=20 6 9 17 4 12svgspan' + p + 'span';
}).join('');
Sidebar
if (document.getElementById('sb-price')) document.getElementById('sb-price').textContent = 'Year 10 Fixed Purchase Price ' + d.price;
if (document.getElementById('sb-rent')) document.getElementById('sb-rent').textContent = d.rent;
var mhBlock = document.getElementById('sb-mortgage-helper');
if (mhBlock) {
mhBlock.style.display = d.title && d.title.indexOf('- Unit A') !== -1 'block' 'none';
var mhLoc = document.getElementById('sb-mh-location');
if (mhLoc) {
var city = (d.location '').replace(,.$, '').trim();
mhLoc.textContent = city 'Estimated rental income for the ' + city + ' area.' 'Estimated rental income for this area.';
}
}
if (document.getElementById('sb-type')) document.getElementById('sb-type').textContent = d.type;
if (document.getElementById('sb-beds')) document.getElementById('sb-beds').innerHTML = d.title && d.title.indexOf('- Unit A') !== -1 '3 bed span style=font-size9px;font-weight400;color#aaa;(2 main + 1 suite)span' d.beds;
if (document.getElementById('sb-baths')) document.getElementById('sb-baths').innerHTML = d.title && d.title.indexOf('- Unit A') !== -1 '2 bath span style=font-size9px;font-weight400;color#aaa;(1 main + 1 suite)span' d.baths;
if (document.getElementById('sb-region')) document.getElementById('sb-region').textContent = d.region;
Property summary fields
if (document.getElementById('ps-property-type')) document.getElementById('ps-property-type').textContent = d.propertyType;
if (document.getElementById('ps-building-type')) document.getElementById('ps-building-type').textContent = d.type;
if (document.getElementById('ps-sqft')) document.getElementById('ps-sqft').textContent = d.sqft + ' sqft';
if (document.getElementById('ps-neighbourhood')) document.getElementById('ps-neighbourhood').textContent = d.location;
if (document.getElementById('ps-tenure')) document.getElementById('ps-tenure').textContent = d.tenure;
if (document.getElementById('ps-land-size')) document.getElementById('ps-land-size').textContent = d.landSize;
if (document.getElementById('ps-built-in')) document.getElementById('ps-built-in').textContent = d.builtIn;
if (document.getElementById('ps-move-in')) document.getElementById('ps-move-in').textContent = d.moveInDate;
if (document.getElementById('ps-parking')) document.getElementById('ps-parking').textContent = d.parking;
Neighbourhood + statistics
populateNeighbourhood(d.neighbourhood);
populateStatistics(d.statistics);
Pre-fill mortgage calculator
mcInit(d.price, d.location);
Reset to Highlights tab (must happen before map init below, so the map container is visible when measured)
document.querySelectorAll('.detail-tab').forEach(function(t, i) { t.classList.toggle('active', i === 0); });
document.querySelectorAll('.tab-panel').forEach(function(p, i) { p.style.display = i === 0 'block' 'none'; });
Location map - GPS coordinates per project (shown as an approximate 500m radius, not an exact pin)
var mapBlock = document.getElementById('detail-map-block');
var mapFrame = document.getElementById('detail-map-frame');
if (mapBlock && mapFrame) {
var PROJECT_COORDS = [
{ match 'Rainforest Drive', coords '48.94206948412843,-125.55545551137537' },
{ match 'Norah Street', coords '48.94206948412843,-125.55545551137537' },
{ match 'Ocean West', coords '48.94144414478106,-125.56628321526729' },
{ match 'River Road', coords '49.266995936872085,-124.8432751576526' },
{ match 'Compton Road',coords '49.27007607198955,-124.83719012185979' },
];
var found = PROJECT_COORDS.find(function(p) { return d.title.indexOf(p.match) !== -1; });
if (found) {
var parts = found.coords.split(',');
var lat = parseFloat(parts[0]);
var lng = parseFloat(parts[1]);
mapBlock.style.display = 'block';
updateApproxLocationMap(lat, lng);
} else {
mapBlock.style.display = 'none';
}
}
Apply lead-gate blurlock state, and prompt Gate 1 if not yet unlocked
applyListingGateState();
if (!gate1Unlocked) {
openGate1(function() { unlockListingDetail(); });
}
Set video for neighbourhood tab (facade pattern poster + play button, real video loads on click)
var videoFrame = document.getElementById('nb-video-frame');
var videoNative = document.getElementById('nb-video-native');
var videoBlock = document.getElementById('nb-video-block');
var videoFacade = document.getElementById('nb-video-facade');
if (videoFrame && videoNative && videoBlock && videoFacade) {
if (window._nbHlsInstance) { window._nbHlsInstance.destroy(); window._nbHlsInstance = null; }
videoNative.pause();
videoNative.removeAttribute('src');
videoNative.load();
videoFrame.setAttribute('src', '');
videoFrame.style.display = 'none';
videoNative.style.display = 'none';
if (d.videoUrl) {
window._nbPendingVideoUrl = d.videoUrl;
var ytMatch = d.videoUrl.match(youtube.comembed([^&]+));
var posterUrl = ytMatch ('httpsimg.youtube.comvi' + ytMatch[1] + 'maxresdefault.jpg') (d.imgUrl '');
videoFacade.style.backgroundImage = posterUrl (url(' + posterUrl + ')) 'none';
videoFacade.style.display = 'flex';
videoBlock.style.display = 'block';
If the YouTube maxres thumbnail doesn't exist, fall back to the property photo
if (ytMatch) {
var probe = new Image();
probe.onerror = function() {
if (d.imgUrl) videoFacade.style.backgroundImage = url(' + d.imgUrl + ');
};
probe.src = posterUrl;
}
} else {
window._nbPendingVideoUrl = '';
videoFacade.style.display = 'none';
videoBlock.style.display = 'none';
}
}
Colour-wipe open sweep in - show panel - sweep out
var wipe = document.getElementById('detail-colour-wipe');
wipe.classList.remove('reveal');
wipe.classList.add('active');
setTimeout(function() {
document.getElementById('detail-body').scrollTop = 0;
document.getElementById('listing-detail').classList.add('open');
var tabsEl = document.getElementById('detail-tabs');
if (tabsEl) tabsEl.scrollLeft = 0;
updateTabsFade();
setTimeout(function() {
wipe.classList.add('reveal');
}, 50);
}, 350);
}
script
script
var listingTemplates = {
default {
sqft '1,344', landSize '1,344 sqft', builtIn '2026', parking '1',
propertyType 'Strata', tenure 'Freehold Strata', annualTax '$3,840', moveInDate 'Spring 2027',
description 'A well-designed home in a growing BC community, built as part of the IGVhope alternative home ownership program. This property offers a rare pathway to ownership for working families - no large down payment required at entry. Residents enjoy stable, predictable monthly costs while building toward full title transfer at Year 10.',
amenities [
{icon'svg width=16 height=16 viewBox=0 0 24 24 fill=none stroke=#1A5C50 stroke-width=2 stroke-linecap=round stroke-linejoin=roundpolygon points=12 2 22 20 2 20polyline points=12 2 8 10 12 14 16 10svg', label'Mountain views', detail'Unobstructed sightlines to surrounding peaks from living areas and primary bedroom.'},
{icon'svg width=16 height=16 viewBox=0 0 24 24 fill=none stroke=#1A5C50 stroke-width=2 stroke-linecap=round stroke-linejoin=roundpath d=M4 4v3path d=M20 4v3path d=M4 7q2 3 4 0t4 0t4 0t4 0path d=M4 7L6 20H18L20 7svg', label'In-suite laundry', detail'Full-size washer and dryer included within the unit , no shared laundry required.'},
{icon'svg width=16 height=16 viewBox=0 0 24 24 fill=none stroke=#1A5C50 stroke-width=2 stroke-linecap=round stroke-linejoin=roundrect x=3 y=3 width=18 height=18 rx=3path d=M9 18V8h5a3 3 0 0 1 0 6H9svg', label'Dedicated parking', detail'One assigned surface parking stall included with the unit.'},
{icon'svg width=16 height=16 viewBox=0 0 24 24 fill=none stroke=#1A5C50 stroke-width=2 stroke-linecap=round stroke-linejoin=roundpath d=m17 14 3 3.3a1 1 0 0 1-.7 1.7H4.7a1 1 0 0 1-.7-1.7L7 14h-.3a1 1 0 0 1-.7-1.7L9 9h-.2A1 1 0 0 1 8 7.3L12 3l4 4.3a1 1 0 0 1-.8 1.7H15l3 3.3a1 1 0 0 1-.7 1.7H17zpath d=M12 22v-3svg', label'Green space nearby', detail'Within easy walking distance of public parks, trails, and open green space.'},
{icon'svg width=16 height=16 viewBox=0 0 24 24 fill=none stroke=#1A5C50 stroke-width=2 stroke-linecap=round stroke-linejoin=roundpath d=M12 2c0 6-6 8-6 14a6 6 0 0 0 12 0c0-6-6-8-6-14zpath d=M12 12c0 3-2 4-2 6a2 2 0 0 0 4 0c0-2-2-3-2-6zsvg', label'Forced-air heating', detail'Ducted forced-air heating system provides fast, even warmth throughout.'},
{icon'svg width=16 height=16 viewBox=0 0 24 24 fill=none stroke=#1A5C50 stroke-width=2 stroke-linecap=round stroke-linejoin=roundpath d=M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16zpolyline points=3.27 6.96 12 12.01 20.73 6.96line x1=12 y1=22.08 x2=12 y2=12svg', label'Storage locker', detail'Assigned storage locker in the building , secure, dry, and easily accessible.'},
],
partners ['District of Ucluelet', 'Vancouver Island Health'],
neighbourhood {
schools [['Elementary School', '400m'], ['Middle School', '1.2km'], ['High School', '2.1km']],
shops [['Grocery Store', '600m'], ['Pharmacy', '800m'], ['Shopping Centre', '3km']],
transit [['Bus Stop', '120m'], ['Regional Transit Hub', '4km'], ['BC Ferries Terminal', '12km']],
parks [['Riverside Park', '300m'], ['Community Trail', '500m'], ['Sports Complex', '1.8km']],
health [['Medical Clinic', '900m'], ['Regional Hospital', '6km']],
community [['Community Centre', '1.1km'], ['Public Library', '1.4km']],
},
statistics {
demographics [
['Total population', '12,400', undefined],
['Median age', '38 years', undefined],
['Families with children', '42%', 42],
['Population growth (5yr)', '+6.2%', undefined],
],
income [
['Median household income', '$74,200', undefined],
['Median individual income', '$41,800', undefined],
['Households earning $100k+', '28%', 28],
['Low-income rate', '11%', 11],
],
housing [
['Owner-occupied', '61%', 61],
['Renter-occupied', '39%', 39],
['Median dwelling value', '$520,000', undefined],
['Average monthly shelter cost', '$1,480', undefined],
['Dwellings built after 2010', '22%', 22],
],
education [
['No certificate diploma', '14%', 14],
['High school diploma', '27%', 27],
['College trades certificate', '31%', 31],
['University degree', '28%', 28],
],
commute [
['Drive alone', '68%', 68],
['Carpool', '9%', 9],
['Transit', '8%', 8],
['Walk or cycle', '11%', 11],
['Median commute time', '22 min', undefined],
],
languages [
['English only at home', '82%', 82],
['French at home', '2%', 2],
['Non-official language at home', '14%', 14],
['Bilingual (EN + FR)', '6%', 6],
],
},
},
'The Pines - Unit 3B' {
sqft '920', landSize '920 sqft', builtIn '2026', parking '1',
propertyType 'Apartment', tenure 'Freehold Strata', annualTax '$2,980', moveInDate 'Spring 2027',
description 'A bright, well-maintained apartment in a quiet residential building. Thoughtful layout, in-suite laundry, and a dedicated parking stall. Part of the IGVhope program - stable monthly costs with a clear path to ownership.',
amenities [
{icon'svg width=16 height=16 viewBox=0 0 24 24 fill=none stroke=#1A5C50 stroke-width=2 stroke-linecap=round stroke-linejoin=roundpath d=M4 4v3path d=M20 4v3path d=M4 7q2 3 4 0t4 0t4 0t4 0path d=M4 7L6 20H18L20 7svg', label'In-suite laundry', detail'Full-size washer and dryer included within the unit , no shared laundry required.'},
{icon'svg width=16 height=16 viewBox=0 0 24 24 fill=none stroke=#1A5C50 stroke-width=2 stroke-linecap=round stroke-linejoin=roundrect x=3 y=3 width=18 height=18 rx=3path d=M9 18V8h5a3 3 0 0 1 0 6H9svg', label'Parking stall', detail'One assigned parking stall included.'},
{icon'svg width=16 height=16 viewBox=0 0 24 24 fill=none stroke=#1A5C50 stroke-width=2 stroke-linecap=round stroke-linejoin=roundpath d=M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16zpolyline points=3.27 6.96 12 12.01 20.73 6.96line x1=12 y1=22.08 x2=12 y2=12svg', label'Storage locker', detail'Assigned storage locker in the building , secure, dry, and easily accessible.'},
{icon'svg width=16 height=16 viewBox=0 0 24 24 fill=none stroke=#1A5C50 stroke-width=2 stroke-linecap=round stroke-linejoin=roundpath d=M12 2c0 6-6 8-6 14a6 6 0 0 0 12 0c0-6-6-8-6-14zpath d=M12 12c0 3-2 4-2 6a2 2 0 0 0 4 0c0-2-2-3-2-6zsvg', label'Baseboard heating', detail'Electric baseboard heating with individual room control for efficiency.'},
{icon'svg width=16 height=16 viewBox=0 0 24 24 fill=none stroke=#1A5C50 stroke-width=2 stroke-linecap=round stroke-linejoin=roundcircle cx=7 cy=7 r=4path d=M10.5 10.5L20 20path d=M17 17v3path d=M20 20v-3svg', label'Courtyard access', detail'Private courtyard shared by a small number of units , maintained by strata.'},
],
partners ['District of Ucluelet', 'Vancouver Island Health'],
},
'Westridge Row House' {
sqft '1,480', landSize '1,480 sqft', builtIn '2026', parking '2',
propertyType 'Townhouse', tenure 'Freehold Strata', annualTax '$4,210', moveInDate 'Spring 2027',
description 'A modern row house in one of Surrey's fastest-growing neighbourhoods. Three storeys, private rooftop deck, double garage, and high-end finishes throughout. Built new in 2020 and enrolled in the IGVhope pathway.',
amenities [
{icon'svg width=16 height=16 viewBox=0 0 24 24 fill=none stroke=#1A5C50 stroke-width=2 stroke-linecap=round stroke-linejoin=roundrect x=3 y=3 width=18 height=18 rx=3path d=M9 18V8h5a3 3 0 0 1 0 6H9svg', label'Double garage', detail'Attached double garage with direct entry into the home.'},
{icon'svg width=16 height=16 viewBox=0 0 24 24 fill=none stroke=#1A5C50 stroke-width=2 stroke-linecap=round stroke-linejoin=roundpath d=M12 22v-7path d=M5 9c0-3.87 3.13-7 7-7s7 3.13 7 7c0 2.65-1.47 4.96-3.64 6.18L12 17l-3.36-1.82A7.001 7.001 0 0 1 5 9zsvg', label'Rooftop deck', detail'Shared rooftop deck with seating and views, accessible to all residents.'},
{icon'svg width=16 height=16 viewBox=0 0 24 24 fill=none stroke=#1A5C50 stroke-width=2 stroke-linecap=round stroke-linejoin=roundpath d=M4 4v3path d=M20 4v3path d=M4 7q2 3 4 0t4 0t4 0t4 0path d=M4 7L6 20H18L20 7svg', label'In-suite laundry', detail'Full-size washer and dryer included within the unit , no shared laundry required.'},
{icon'svg width=16 height=16 viewBox=0 0 24 24 fill=none stroke=#1A5C50 stroke-width=2 stroke-linecap=round stroke-linejoin=roundpath d=M12 2c0 6-6 8-6 14a6 6 0 0 0 12 0c0-6-6-8-6-14zpath d=M12 12c0 3-2 4-2 6a2 2 0 0 0 4 0c0-2-2-3-2-6zsvg', label'Forced-air heating', detail'Ducted forced-air heating system provides fast, even warmth throughout.'},
{icon'svg width=16 height=16 viewBox=0 0 24 24 fill=none stroke=#1A5C50 stroke-width=2 stroke-linecap=round stroke-linejoin=roundpath d=M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16zpolyline points=3.27 6.96 12 12.01 20.73 6.96line x1=12 y1=22.08 x2=12 y2=12svg', label'Storage room', detail'Dedicated storage room within the home , large enough for seasonal items.'},
{icon'svg width=16 height=16 viewBox=0 0 24 24 fill=none stroke=#1A5C50 stroke-width=2 stroke-linecap=round stroke-linejoin=roundpath d=M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2zpolyline points=9 22 9 12 15 12 15 22svg', label'Energy-efficient build', detail'Built to BC Step Code energy efficiency requirements for reduced running costs.'},
],
partners ['District of Ucluelet', 'Vancouver Island Health'],
},
'Oak Bay Garden Suites' {
sqft '1,050', landSize '1,050 sqft', builtIn '2026', parking '1',
propertyType 'Apartment', tenure 'Freehold Strata', annualTax '$3,520', moveInDate 'Spring 2027',
description 'Nestled in Oak Bay, one of Victoria's most sought-after neighbourhoods. Garden-level suite with private patio, updated kitchen, and steps to schools and transit. A rare entry point into Victoria's market.',
amenities [
{icon'svg width=16 height=16 viewBox=0 0 24 24 fill=none stroke=#1A5C50 stroke-width=2 stroke-linecap=round stroke-linejoin=roundpath d=M12 22v-7path d=M5 9c0-3.87 3.13-7 7-7s7 3.13 7 7c0 2.65-1.47 4.96-3.64 6.18L12 17l-3.36-1.82A7.001 7.001 0 0 1 5 9zsvg', label'Private patio', detail'Ground-level private patio with direct outdoor access from the living area.'},
{icon'svg width=16 height=16 viewBox=0 0 24 24 fill=none stroke=#1A5C50 stroke-width=2 stroke-linecap=round stroke-linejoin=roundpath d=M4 4v3path d=M20 4v3path d=M4 7q2 3 4 0t4 0t4 0t4 0path d=M4 7L6 20H18L20 7svg', label'In-suite laundry', detail'Full-size washer and dryer included within the unit , no shared laundry required.'},
{icon'svg width=16 height=16 viewBox=0 0 24 24 fill=none stroke=#1A5C50 stroke-width=2 stroke-linecap=round stroke-linejoin=roundrect x=3 y=3 width=18 height=18 rx=3path d=M9 18V8h5a3 3 0 0 1 0 6H9svg', label'Parking stall', detail'One assigned parking stall included.'},
{icon'svg width=16 height=16 viewBox=0 0 24 24 fill=none stroke=#1A5C50 stroke-width=2 stroke-linecap=round stroke-linejoin=roundpath d=M12 2c0 6-6 8-6 14a6 6 0 0 0 12 0c0-6-6-8-6-14zpath d=M12 12c0 3-2 4-2 6a2 2 0 0 0 4 0c0-2-2-3-2-6zsvg', label'Heat pump', detail'High-efficiency heat pump providing both heating and cooling year-round.'},
{icon'svg width=16 height=16 viewBox=0 0 24 24 fill=none stroke=#1A5C50 stroke-width=2 stroke-linecap=round stroke-linejoin=roundpath d=M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16zpolyline points=3.27 6.96 12 12.01 20.73 6.96line x1=12 y1=22.08 x2=12 y2=12svg', label'Storage locker', detail'Assigned storage locker in the building , secure, dry, and easily accessible.'},
],
partners ['District of Ucluelet', 'Vancouver Island Health'],
},
'Burke Mountain Homes' {
sqft '1,620', landSize '1,620 sqft', builtIn '2026', parking '2',
propertyType 'Townhouse', tenure 'Freehold Strata', annualTax '$4,480', moveInDate 'Spring 2027',
description 'Perched on Burke Mountain with sweeping valley views. Three bedrooms, open-plan main floor, and a generous back yard backing onto green belt. New construction enrolled in the IGVhope pathway from day one.',
amenities [
{icon'svg width=16 height=16 viewBox=0 0 24 24 fill=none stroke=#1A5C50 stroke-width=2 stroke-linecap=round stroke-linejoin=roundpolygon points=12 2 22 20 2 20polyline points=12 2 8 10 12 14 16 10svg', label'Valley views', detail'Sweeping views across the valley floor, visible from the main living area and deck.'},
{icon'svg width=16 height=16 viewBox=0 0 24 24 fill=none stroke=#1A5C50 stroke-width=2 stroke-linecap=round stroke-linejoin=roundrect x=3 y=3 width=18 height=18 rx=3path d=M9 18V8h5a3 3 0 0 1 0 6H9svg', label'Double garage', detail'Attached double garage with direct entry into the home.'},
{icon'svg width=16 height=16 viewBox=0 0 24 24 fill=none stroke=#1A5C50 stroke-width=2 stroke-linecap=round stroke-linejoin=roundpath d=M12 22v-7path d=M5 9c0-3.87 3.13-7 7-7s7 3.13 7 7c0 2.65-1.47 4.96-3.64 6.18L12 17l-3.36-1.82A7.001 7.001 0 0 1 5 9zsvg', label'Green belt backing', detail'Property backs onto protected green belt , no rear neighbours.'},
{icon'svg width=16 height=16 viewBox=0 0 24 24 fill=none stroke=#1A5C50 stroke-width=2 stroke-linecap=round stroke-linejoin=roundpath d=M4 4v3path d=M20 4v3path d=M4 7q2 3 4 0t4 0t4 0t4 0path d=M4 7L6 20H18L20 7svg', label'In-suite laundry', detail'Full-size washer and dryer included within the unit , no shared laundry required.'},
{icon'svg width=16 height=16 viewBox=0 0 24 24 fill=none stroke=#1A5C50 stroke-width=2 stroke-linecap=round stroke-linejoin=roundpath d=M12 2c0 6-6 8-6 14a6 6 0 0 0 12 0c0-6-6-8-6-14zpath d=M12 12c0 3-2 4-2 6a2 2 0 0 0 4 0c0-2-2-3-2-6zsvg', label'Forced-air heating', detail'Ducted forced-air heating system provides fast, even warmth throughout.'},
{icon'svg width=16 height=16 viewBox=0 0 24 24 fill=none stroke=#1A5C50 stroke-width=2 stroke-linecap=round stroke-linejoin=roundpath d=M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2zpolyline points=9 22 9 12 15 12 15 22svg', label'Energy Star certified', detail'Certified to Energy Star standards , lower energy bills and reduced emissions.'},
],
partners ['District of Ucluelet', 'Vancouver Island Health'],
},
'Metrotown Heights' {
sqft '620', landSize '620 sqft', builtIn '2026', parking '1',
propertyType 'Apartment', tenure 'Freehold Strata', annualTax '$2,640', moveInDate 'Spring 2027',
description 'Steps from Metrotown SkyTrain and one of Metro Vancouver's best shopping districts. A smartly designed one-bedroom with floor-to-ceiling windows, city views, and building amenities including a gym and rooftop lounge.',
amenities [
{icon'svg width=16 height=16 viewBox=0 0 24 24 fill=none stroke=#1A5C50 stroke-width=2 stroke-linecap=round stroke-linejoin=roundrect x=1 y=6 width=6 height=18rect x=9 y=2 width=6 height=22rect x=17 y=10 width=6 height=14svg', label'City views', detail'Floor-to-ceiling windows frame the downtown skyline and city lights.'},
{icon'svg width=16 height=16 viewBox=0 0 24 24 fill=none stroke=#1A5C50 stroke-width=2 stroke-linecap=round stroke-linejoin=roundpath d=M4 4v3path d=M20 4v3path d=M4 7q2 3 4 0t4 0t4 0t4 0path d=M4 7L6 20H18L20 7svg', label'In-suite laundry', detail'Full-size washer and dryer included within the unit , no shared laundry required.'},
{icon'svg width=16 height=16 viewBox=0 0 24 24 fill=none stroke=#1A5C50 stroke-width=2 stroke-linecap=round stroke-linejoin=roundrect x=3 y=3 width=18 height=18 rx=3path d=M9 18V8h5a3 3 0 0 1 0 6H9svg', label'Underground parking', detail'Secure underground parking stall with elevator access to the lobby.'},
{icon'svg width=16 height=16 viewBox=0 0 24 24 fill=none stroke=#1A5C50 stroke-width=2 stroke-linecap=round stroke-linejoin=roundline x1=6 y1=5 x2=6 y2=19line x1=18 y1=5 x2=18 y2=19line x1=2 y1=12 x2=22 y2=12line x1=6 y1=8 x2=2 y2=8line x1=6 y1=16 x2=2 y2=16line x1=22 y1=8 x2=18 y2=8line x1=22 y1=16 x2=18 y2=16svg', label'Building gym', detail'Fully equipped fitness centre on-site, available to all residents at no extra cost.'},
{icon'svg width=16 height=16 viewBox=0 0 24 24 fill=none stroke=#1A5C50 stroke-width=2 stroke-linecap=round stroke-linejoin=roundpath d=M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16zpolyline points=3.27 6.96 12 12.01 20.73 6.96line x1=12 y1=22.08 x2=12 y2=12svg', label'Storage locker', detail'Assigned storage locker in the building , secure, dry, and easily accessible.'},
],
partners ['District of Ucluelet', 'Vancouver Island Health'],
},
'Okanagan Lakeview' {
sqft '1,740', landSize '1,740 sqft', builtIn '2026', parking '2',
propertyType 'Single Family', tenure 'Freehold', annualTax '$4,920', moveInDate 'Spring 2027',
description 'A spacious single-family home with partial lake views in the heart of the Okanagan. Mature landscaping, double garage, and a large deck made for BC summers. Enrolled in the IGVhope pathway - ownership transition at Year 10.',
amenities [
{icon'svg width=16 height=16 viewBox=0 0 24 24 fill=none stroke=#1A5C50 stroke-width=2 stroke-linecap=round stroke-linejoin=roundpath d=M2 12c1.5-2 3-2 4.5 0s3 2 4.5 0 3-2 4.5 0 3 2 4.5 0path d=M2 17c1.5-2 3-2 4.5 0s3 2 4.5 0 3-2 4.5 0 3 2 4.5 0path d=M2 7c1.5-2 3-2 4.5 0s3 2 4.5 0 3-2 4.5 0 3 2 4.5 0svg', label'Partial lake views', detail'Glimpses of the lake through mature trees, visible from the living room and deck.'},
{icon'svg width=16 height=16 viewBox=0 0 24 24 fill=none stroke=#1A5C50 stroke-width=2 stroke-linecap=round stroke-linejoin=roundpath d=M12 22v-7path d=M5 9c0-3.87 3.13-7 7-7s7 3.13 7 7c0 2.65-1.47 4.96-3.64 6.18L12 17l-3.36-1.82A7.001 7.001 0 0 1 5 9zsvg', label'Mature landscaping', detail'Established trees and garden beds surrounding the property.'},
{icon'svg width=16 height=16 viewBox=0 0 24 24 fill=none stroke=#1A5C50 stroke-width=2 stroke-linecap=round stroke-linejoin=roundrect x=3 y=3 width=18 height=18 rx=3path d=M9 18V8h5a3 3 0 0 1 0 6H9svg', label'Double garage', detail'Attached double garage with direct entry into the home.'},
{icon'svg width=16 height=16 viewBox=0 0 24 24 fill=none stroke=#1A5C50 stroke-width=2 stroke-linecap=round stroke-linejoin=roundpath d=M4 4v3path d=M20 4v3path d=M4 7q2 3 4 0t4 0t4 0t4 0path d=M4 7L6 20H18L20 7svg', label'In-suite laundry', detail'Full-size washer and dryer included within the unit , no shared laundry required.'},
{icon'svg width=16 height=16 viewBox=0 0 24 24 fill=none stroke=#1A5C50 stroke-width=2 stroke-linecap=round stroke-linejoin=roundpath d=M12 2c0 6-6 8-6 14a6 6 0 0 0 12 0c0-6-6-8-6-14zpath d=M12 12c0 3-2 4-2 6a2 2 0 0 0 4 0c0-2-2-3-2-6zsvg', label'Forced-air + AC', detail'Ducted forced-air system with integrated central air conditioning.'},
{icon'svg width=16 height=16 viewBox=0 0 24 24 fill=none stroke=#1A5C50 stroke-width=2 stroke-linecap=round stroke-linejoin=roundpath d=M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2zpolyline points=9 22 9 12 15 12 15 22svg', label'Large deck', detail'Generous deck off the main living area, suitable for outdoor dining and lounging.'},
],
partners ['District of Ucluelet', 'Vancouver Island Health'],
},
'Silver Star Ridge' {
sqft '1,120', landSize '1,120 sqft', builtIn '2026', parking '2',
propertyType 'Townhouse', tenure 'Freehold Strata', annualTax '$3,180', moveInDate 'Spring 2027',
description 'A mountain-community townhouse steps from Silver Star ski access roads. Two bedrooms, ski locker, and a south-facing deck. Year-round outdoor lifestyle with a genuine pathway to ownership.',
amenities [
{icon'svg width=16 height=16 viewBox=0 0 24 24 fill=none stroke=#1A5C50 stroke-width=2 stroke-linecap=round stroke-linejoin=roundpolygon points=12 2 22 20 2 20polyline points=12 2 8 10 12 14 16 10svg', label'Mountain setting', detail'Located within a mountain community, surrounded by alpine terrain and trail networks.'},
{icon'svg width=16 height=16 viewBox=0 0 24 24 fill=none stroke=#1A5C50 stroke-width=2 stroke-linecap=round stroke-linejoin=roundline x1=5 y1=2 x2=5 y2=22line x1=19 y1=2 x2=19 y2=22path d=M5 22c0-2 2-3 4-3s4 1 4 3path d=M19 22c0-2-2-3-4-3path d=M5 8h6path d=M13 8h6svg', label'Ski storage locker', detail'Heated ski and gear storage locker with boot-drying facilities in the building.'},
{icon'svg width=16 height=16 viewBox=0 0 24 24 fill=none stroke=#1A5C50 stroke-width=2 stroke-linecap=round stroke-linejoin=roundrect x=3 y=3 width=18 height=18 rx=3path d=M9 18V8h5a3 3 0 0 1 0 6H9svg', label'Two parking stalls', detail'Two assigned parking stalls included , surface or covered.'},
{icon'svg width=16 height=16 viewBox=0 0 24 24 fill=none stroke=#1A5C50 stroke-width=2 stroke-linecap=round stroke-linejoin=roundpath d=M4 4v3path d=M20 4v3path d=M4 7q2 3 4 0t4 0t4 0t4 0path d=M4 7L6 20H18L20 7svg', label'In-suite laundry', detail'Full-size washer and dryer included within the unit , no shared laundry required.'},
{icon'svg width=16 height=16 viewBox=0 0 24 24 fill=none stroke=#1A5C50 stroke-width=2 stroke-linecap=round stroke-linejoin=roundpath d=M12 2c0 6-6 8-6 14a6 6 0 0 0 12 0c0-6-6-8-6-14zpath d=M12 12c0 3-2 4-2 6a2 2 0 0 0 4 0c0-2-2-3-2-6zsvg', label'Forced-air heating', detail'Ducted forced-air heating system provides fast, even warmth throughout.'},
],
partners ['District of Ucluelet', 'Vancouver Island Health'],
},
'Kootenay Riverside' {
sqft '2,100', landSize '2,100 sqft', builtIn '2026', parking '2',
propertyType 'Single Family', tenure 'Freehold', annualTax '$3,760', moveInDate 'Spring 2027',
description 'A characterful four-bedroom home on the banks of the Kootenay River in Nelson. Renovated kitchen and bathrooms, wrap-around deck, and a large private lot. Nelson's arts community and outdoor recreation right at your door.',
amenities [
{icon'svg width=16 height=16 viewBox=0 0 24 24 fill=none stroke=#1A5C50 stroke-width=2 stroke-linecap=round stroke-linejoin=roundpath d=M2 12c1.5-2 3-2 4.5 0s3 2 4.5 0 3-2 4.5 0 3 2 4.5 0path d=M2 17c1.5-2 3-2 4.5 0s3 2 4.5 0 3-2 4.5 0 3 2 4.5 0path d=M2 7c1.5-2 3-2 4.5 0s3 2 4.5 0 3-2 4.5 0 3 2 4.5 0svg', label'Riverside setting', detail'Situated backing onto the river corridor with direct access to riverside trails.'},
{icon'svg width=16 height=16 viewBox=0 0 24 24 fill=none stroke=#1A5C50 stroke-width=2 stroke-linecap=round stroke-linejoin=roundpath d=M12 22v-7path d=M5 9c0-3.87 3.13-7 7-7s7 3.13 7 7c0 2.65-1.47 4.96-3.64 6.18L12 17l-3.36-1.82A7.001 7.001 0 0 1 5 9zsvg', label'Large private lot', detail'Generous private lot with space for gardens, outdoor entertaining, and storage.'},
{icon'svg width=16 height=16 viewBox=0 0 24 24 fill=none stroke=#1A5C50 stroke-width=2 stroke-linecap=round stroke-linejoin=roundrect x=3 y=3 width=18 height=18 rx=3path d=M9 18V8h5a3 3 0 0 1 0 6H9svg', label'Double driveway', detail'Wide double driveway accommodating two full-size vehicles.'},
{icon'svg width=16 height=16 viewBox=0 0 24 24 fill=none stroke=#1A5C50 stroke-width=2 stroke-linecap=round stroke-linejoin=roundpath d=M4 4v3path d=M20 4v3path d=M4 7q2 3 4 0t4 0t4 0t4 0path d=M4 7L6 20H18L20 7svg', label'In-suite laundry', detail'Full-size washer and dryer included within the unit , no shared laundry required.'},
{icon'svg width=16 height=16 viewBox=0 0 24 24 fill=none stroke=#1A5C50 stroke-width=2 stroke-linecap=round stroke-linejoin=roundpath d=M12 2c0 6-6 8-6 14a6 6 0 0 0 12 0c0-6-6-8-6-14zpath d=M12 12c0 3-2 4-2 6a2 2 0 0 0 4 0c0-2-2-3-2-6zsvg', label'Forced-air heating', detail'Ducted forced-air heating system provides fast, even warmth throughout.'},
{icon'svg width=16 height=16 viewBox=0 0 24 24 fill=none stroke=#1A5C50 stroke-width=2 stroke-linecap=round stroke-linejoin=roundpath d=M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2zpolyline points=9 22 9 12 15 12 15 22svg', label'Wrap-around deck', detail'Wrap-around deck on two sides of the home, ideal for outdoor entertaining.'},
],
partners ['District of Ucluelet', 'Vancouver Island Health'],
},
'Northern Gateway Estates' {
sqft '1,560', landSize '1,560 sqft', builtIn '2026', parking '2',
propertyType 'Single Family', tenure 'Freehold', annualTax '$3,040', moveInDate 'Spring 2027',
description 'An affordable family home in Prince George with a large lot, double garage, and open-plan living. Close to schools and the university. One of the most accessible price points in the IGVhope portfolio.',
amenities [
{icon'svg width=16 height=16 viewBox=0 0 24 24 fill=none stroke=#1A5C50 stroke-width=2 stroke-linecap=round stroke-linejoin=roundpath d=M12 22v-7path d=M5 9c0-3.87 3.13-7 7-7s7 3.13 7 7c0 2.65-1.47 4.96-3.64 6.18L12 17l-3.36-1.82A7.001 7.001 0 0 1 5 9zsvg', label'Large yard', detail'Spacious fully fenced yard suitable for children, pets, and outdoor living.'},
{icon'svg width=16 height=16 viewBox=0 0 24 24 fill=none stroke=#1A5C50 stroke-width=2 stroke-linecap=round stroke-linejoin=roundrect x=3 y=3 width=18 height=18 rx=3path d=M9 18V8h5a3 3 0 0 1 0 6H9svg', label'Double garage', detail'Attached double garage with direct entry into the home.'},
{icon'svg width=16 height=16 viewBox=0 0 24 24 fill=none stroke=#1A5C50 stroke-width=2 stroke-linecap=round stroke-linejoin=roundpath d=M4 4v3path d=M20 4v3path d=M4 7q2 3 4 0t4 0t4 0t4 0path d=M4 7L6 20H18L20 7svg', label'In-suite laundry', detail'Full-size washer and dryer included within the unit , no shared laundry required.'},
{icon'svg width=16 height=16 viewBox=0 0 24 24 fill=none stroke=#1A5C50 stroke-width=2 stroke-linecap=round stroke-linejoin=roundpath d=M12 2c0 6-6 8-6 14a6 6 0 0 0 12 0c0-6-6-8-6-14zpath d=M12 12c0 3-2 4-2 6a2 2 0 0 0 4 0c0-2-2-3-2-6zsvg', label'Forced-air heating', detail'Ducted forced-air heating system provides fast, even warmth throughout.'},
{icon'svg width=16 height=16 viewBox=0 0 24 24 fill=none stroke=#1A5C50 stroke-width=2 stroke-linecap=round stroke-linejoin=roundpath d=M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16zpolyline points=3.27 6.96 12 12.01 20.73 6.96line x1=12 y1=22.08 x2=12 y2=12svg', label'Basement storage', detail'Full-height basement storage area accessed from inside the home.'},
],
partners ['District of Ucluelet', 'Vancouver Island Health'],
},
'Discovery Passage Homes' {
sqft '1,080', landSize '1,080 sqft', builtIn '2026', parking '1',
propertyType 'Townhouse', tenure 'Freehold Strata', annualTax '$2,820', moveInDate 'Spring 2027',
description 'A compact, well-designed townhouse in Campbell River, gateway to Discovery Passage and world-class fishing. Two bedrooms, private back yard, and a community that's as welcoming as the landscape.',
amenities [
{icon'svg width=16 height=16 viewBox=0 0 24 24 fill=none stroke=#1A5C50 stroke-width=2 stroke-linecap=round stroke-linejoin=roundpath d=M2 12c1.5-2 3-2 4.5 0s3 2 4.5 0 3-2 4.5 0 3 2 4.5 0path d=M2 17c1.5-2 3-2 4.5 0s3 2 4.5 0 3-2 4.5 0 3 2 4.5 0path d=M2 7c1.5-2 3-2 4.5 0s3 2 4.5 0 3-2 4.5 0 3 2 4.5 0svg', label'Near Discovery Passage', detail'Steps from Discovery Passage with easy access to the waterfront trail.'},
{icon'svg width=16 height=16 viewBox=0 0 24 24 fill=none stroke=#1A5C50 stroke-width=2 stroke-linecap=round stroke-linejoin=roundpath d=M12 22v-7path d=M5 9c0-3.87 3.13-7 7-7s7 3.13 7 7c0 2.65-1.47 4.96-3.64 6.18L12 17l-3.36-1.82A7.001 7.001 0 0 1 5 9zsvg', label'Private yard', detail'Fully fenced private yard with lawn and garden space.'},
{icon'svg width=16 height=16 viewBox=0 0 24 24 fill=none stroke=#1A5C50 stroke-width=2 stroke-linecap=round stroke-linejoin=roundrect x=3 y=3 width=18 height=18 rx=3path d=M9 18V8h5a3 3 0 0 1 0 6H9svg', label'Parking stall', detail'One assigned parking stall included.'},
{icon'svg width=16 height=16 viewBox=0 0 24 24 fill=none stroke=#1A5C50 stroke-width=2 stroke-linecap=round stroke-linejoin=roundpath d=M4 4v3path d=M20 4v3path d=M4 7q2 3 4 0t4 0t4 0t4 0path d=M4 7L6 20H18L20 7svg', label'In-suite laundry', detail'Full-size washer and dryer included within the unit , no shared laundry required.'},
{icon'svg width=16 height=16 viewBox=0 0 24 24 fill=none stroke=#1A5C50 stroke-width=2 stroke-linecap=round stroke-linejoin=roundpath d=M12 2c0 6-6 8-6 14a6 6 0 0 0 12 0c0-6-6-8-6-14zpath d=M12 12c0 3-2 4-2 6a2 2 0 0 0 4 0c0-2-2-3-2-6zsvg', label'Baseboard heating', detail'Electric baseboard heating with individual room control for efficiency.'},
],
partners ['District of Ucluelet', 'Vancouver Island Health'],
},
'Fraser Valley Terrace' {
sqft '880', landSize '880 sqft', builtIn '2026', parking '1',
propertyType 'Apartment', tenure 'Freehold Strata', annualTax '$2,760', moveInDate 'Spring 2027',
description 'A bright Fraser Valley apartment with mountain views from the balcony. Updated throughout, in-suite laundry, and easy highway access. Strong community and growing amenities nearby.',
amenities [
{icon'svg width=16 height=16 viewBox=0 0 24 24 fill=none stroke=#1A5C50 stroke-width=2 stroke-linecap=round stroke-linejoin=roundpolygon points=12 2 22 20 2 20polyline points=12 2 8 10 12 14 16 10svg', label'Mountain views', detail'Unobstructed sightlines to surrounding peaks from living areas and primary bedroom.'},
{icon'svg width=16 height=16 viewBox=0 0 24 24 fill=none stroke=#1A5C50 stroke-width=2 stroke-linecap=round stroke-linejoin=roundpath d=M12 22v-7path d=M5 9c0-3.87 3.13-7 7-7s7 3.13 7 7c0 2.65-1.47 4.96-3.64 6.18L12 17l-3.36-1.82A7.001 7.001 0 0 1 5 9zsvg', label'Balcony', detail'Private outdoor balcony off the main living area.'},
{icon'svg width=16 height=16 viewBox=0 0 24 24 fill=none stroke=#1A5C50 stroke-width=2 stroke-linecap=round stroke-linejoin=roundpath d=M4 4v3path d=M20 4v3path d=M4 7q2 3 4 0t4 0t4 0t4 0path d=M4 7L6 20H18L20 7svg', label'In-suite laundry', detail'Full-size washer and dryer included within the unit , no shared laundry required.'},
{icon'svg width=16 height=16 viewBox=0 0 24 24 fill=none stroke=#1A5C50 stroke-width=2 stroke-linecap=round stroke-linejoin=roundrect x=3 y=3 width=18 height=18 rx=3path d=M9 18V8h5a3 3 0 0 1 0 6H9svg', label'Parking stall', detail'One assigned parking stall included.'},
{icon'svg width=16 height=16 viewBox=0 0 24 24 fill=none stroke=#1A5C50 stroke-width=2 stroke-linecap=round stroke-linejoin=roundpath d=M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16zpolyline points=3.27 6.96 12 12.01 20.73 6.96line x1=12 y1=22.08 x2=12 y2=12svg', label'Storage locker', detail'Assigned storage locker in the building , secure, dry, and easily accessible.'},
],
partners ['District of Ucluelet', 'Vancouver Island Health'],
},
'Steveston Harbour Place' {
sqft '1,140', landSize '1,140 sqft', builtIn '2026', parking '1',
propertyType 'Apartment', tenure 'Freehold Strata', annualTax '$3,680', moveInDate 'Spring 2027',
description 'In the heart of historic Steveston, steps from the waterfront, independent restaurants, and the West Coast Express. A two-bedroom with updated finishes and harbour glimpses from the living room.',
amenities [
{icon'svg width=16 height=16 viewBox=0 0 24 24 fill=none stroke=#1A5C50 stroke-width=2 stroke-linecap=round stroke-linejoin=roundpath d=M2 12c1.5-2 3-2 4.5 0s3 2 4.5 0 3-2 4.5 0 3 2 4.5 0path d=M2 17c1.5-2 3-2 4.5 0s3 2 4.5 0 3-2 4.5 0 3 2 4.5 0path d=M2 7c1.5-2 3-2 4.5 0s3 2 4.5 0 3-2 4.5 0 3 2 4.5 0svg', label'Harbour proximity', detail'A short walk to the waterfront and harbour district.'},
{icon'svg width=16 height=16 viewBox=0 0 24 24 fill=none stroke=#1A5C50 stroke-width=2 stroke-linecap=round stroke-linejoin=roundpath d=M4 4v3path d=M20 4v3path d=M4 7q2 3 4 0t4 0t4 0t4 0path d=M4 7L6 20H18L20 7svg', label'In-suite laundry', detail'Full-size washer and dryer included within the unit , no shared laundry required.'},
{icon'svg width=16 height=16 viewBox=0 0 24 24 fill=none stroke=#1A5C50 stroke-width=2 stroke-linecap=round stroke-linejoin=roundrect x=3 y=3 width=18 height=18 rx=3path d=M9 18V8h5a3 3 0 0 1 0 6H9svg', label'Underground parking', detail'Secure underground parking stall with elevator access to the lobby.'},
{icon'svg width=16 height=16 viewBox=0 0 24 24 fill=none stroke=#1A5C50 stroke-width=2 stroke-linecap=round stroke-linejoin=roundpath d=M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16zpolyline points=3.27 6.96 12 12.01 20.73 6.96line x1=12 y1=22.08 x2=12 y2=12svg', label'Storage locker', detail'Assigned storage locker in the building , secure, dry, and easily accessible.'},
{icon'svg width=16 height=16 viewBox=0 0 24 24 fill=none stroke=#1A5C50 stroke-width=2 stroke-linecap=round stroke-linejoin=roundpath d=M12 2c0 6-6 8-6 14a6 6 0 0 0 12 0c0-6-6-8-6-14zpath d=M12 12c0 3-2 4-2 6a2 2 0 0 0 4 0c0-2-2-3-2-6zsvg', label'Baseboard heating', detail'Electric baseboard heating with individual room control for efficiency.'},
],
partners ['District of Ucluelet', 'Vancouver Island Health'],
},
'Abbotsford Meadows' {
sqft '1,680', landSize '1,680 sqft', builtIn '2026', parking '2',
propertyType 'Single Family', tenure 'Freehold', annualTax '$3,920', moveInDate 'Spring 2027',
description 'A solid family home in Abbotsford's Meadows neighbourhood with a large back yard and double garage. Three bedrooms, updated kitchen, and close to schools, parks, and the Trans-Canada.',
amenities [
{icon'svg width=16 height=16 viewBox=0 0 24 24 fill=none stroke=#1A5C50 stroke-width=2 stroke-linecap=round stroke-linejoin=roundpath d=M12 22v-7path d=M5 9c0-3.87 3.13-7 7-7s7 3.13 7 7c0 2.65-1.47 4.96-3.64 6.18L12 17l-3.36-1.82A7.001 7.001 0 0 1 5 9zsvg', label'Large back yard', detail'Deep fully fenced rear yard with established lawn and garden areas.'},
{icon'svg width=16 height=16 viewBox=0 0 24 24 fill=none stroke=#1A5C50 stroke-width=2 stroke-linecap=round stroke-linejoin=roundrect x=3 y=3 width=18 height=18 rx=3path d=M9 18V8h5a3 3 0 0 1 0 6H9svg', label'Double garage', detail'Attached double garage with direct entry into the home.'},
{icon'svg width=16 height=16 viewBox=0 0 24 24 fill=none stroke=#1A5C50 stroke-width=2 stroke-linecap=round stroke-linejoin=roundpath d=M4 4v3path d=M20 4v3path d=M4 7q2 3 4 0t4 0t4 0t4 0path d=M4 7L6 20H18L20 7svg', label'In-suite laundry', detail'Full-size washer and dryer included within the unit , no shared laundry required.'},
{icon'svg width=16 height=16 viewBox=0 0 24 24 fill=none stroke=#1A5C50 stroke-width=2 stroke-linecap=round stroke-linejoin=roundpath d=M12 2c0 6-6 8-6 14a6 6 0 0 0 12 0c0-6-6-8-6-14zpath d=M12 12c0 3-2 4-2 6a2 2 0 0 0 4 0c0-2-2-3-2-6zsvg', label'Forced-air heating', detail'Ducted forced-air heating system provides fast, even warmth throughout.'},
{icon'svg width=16 height=16 viewBox=0 0 24 24 fill=none stroke=#1A5C50 stroke-width=2 stroke-linecap=round stroke-linejoin=roundpath d=M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16zpolyline points=3.27 6.96 12 12.01 20.73 6.96line x1=12 y1=22.08 x2=12 y2=12svg', label'Basement storage', detail'Full-height basement storage area accessed from inside the home.'},
],
partners ['District of Ucluelet', 'Vancouver Island Health'],
},
'Nanaimo Harbourfront' {
sqft '640', landSize '640 sqft', builtIn '2026', parking '1',
propertyType 'Apartment', tenure 'Freehold Strata', annualTax '$2,480', moveInDate 'Spring 2027',
description 'A modern one-bedroom in Nanaimo's revitalized harbourfront district. Floor-to-ceiling windows, contemporary finishes, and building amenities including a rooftop patio with harbour views.',
amenities [
{icon'svg width=16 height=16 viewBox=0 0 24 24 fill=none stroke=#1A5C50 stroke-width=2 stroke-linecap=round stroke-linejoin=roundpath d=M2 12c1.5-2 3-2 4.5 0s3 2 4.5 0 3-2 4.5 0 3 2 4.5 0path d=M2 17c1.5-2 3-2 4.5 0s3 2 4.5 0 3-2 4.5 0 3 2 4.5 0path d=M2 7c1.5-2 3-2 4.5 0s3 2 4.5 0 3-2 4.5 0 3 2 4.5 0svg', label'Harbour views', detail'Direct outlook over the harbour from the main living area and primary bedroom.'},
{icon'svg width=16 height=16 viewBox=0 0 24 24 fill=none stroke=#1A5C50 stroke-width=2 stroke-linecap=round stroke-linejoin=roundpath d=M4 4v3path d=M20 4v3path d=M4 7q2 3 4 0t4 0t4 0t4 0path d=M4 7L6 20H18L20 7svg', label'In-suite laundry', detail'Full-size washer and dryer included within the unit , no shared laundry required.'},
{icon'svg width=16 height=16 viewBox=0 0 24 24 fill=none stroke=#1A5C50 stroke-width=2 stroke-linecap=round stroke-linejoin=roundrect x=3 y=3 width=18 height=18 rx=3path d=M9 18V8h5a3 3 0 0 1 0 6H9svg', label'Underground parking', detail'Secure underground parking stall with elevator access to the lobby.'},
{icon'svg width=16 height=16 viewBox=0 0 24 24 fill=none stroke=#1A5C50 stroke-width=2 stroke-linecap=round stroke-linejoin=roundpath d=M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16zpolyline points=3.27 6.96 12 12.01 20.73 6.96line x1=12 y1=22.08 x2=12 y2=12svg', label'Storage locker', detail'Assigned storage locker in the building , secure, dry, and easily accessible.'},
{icon'svg width=16 height=16 viewBox=0 0 24 24 fill=none stroke=#1A5C50 stroke-width=2 stroke-linecap=round stroke-linejoin=roundpath d=M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2zpolyline points=9 22 9 12 15 12 15 22svg', label'Rooftop patio access', detail'Access to a shared rooftop patio with seating and panoramic views.'},
],
partners ['District of Ucluelet', 'Vancouver Island Health'],
},
'Chilliwack Valley View' {
sqft '2,380', landSize '2,380 sqft', builtIn '2026', parking '3',
propertyType 'Single Family', tenure 'Freehold', annualTax '$4,640', moveInDate 'Spring 2027',
description 'A large four-bedroom family home with sweeping valley and mountain views. Spacious open-plan living, updated throughout, triple garage, and a generous lot backing onto quiet green space.',
amenities [
{icon'svg width=16 height=16 viewBox=0 0 24 24 fill=none stroke=#1A5C50 stroke-width=2 stroke-linecap=round stroke-linejoin=roundpolygon points=12 2 22 20 2 20polyline points=12 2 8 10 12 14 16 10svg', label'Valley & mountain views', detail'Panoramic outlook across the valley floor with backdrop of surrounding mountain ranges.'},
{icon'svg width=16 height=16 viewBox=0 0 24 24 fill=none stroke=#1A5C50 stroke-width=2 stroke-linecap=round stroke-linejoin=roundpath d=M12 22v-7path d=M5 9c0-3.87 3.13-7 7-7s7 3.13 7 7c0 2.65-1.47 4.96-3.64 6.18L12 17l-3.36-1.82A7.001 7.001 0 0 1 5 9zsvg', label'Large green-belt lot', detail'Oversized lot backing onto protected green belt with privacy and outlook.'},
{icon'svg width=16 height=16 viewBox=0 0 24 24 fill=none stroke=#1A5C50 stroke-width=2 stroke-linecap=round stroke-linejoin=roundrect x=3 y=3 width=18 height=18 rx=3path d=M9 18V8h5a3 3 0 0 1 0 6H9svg', label'Triple garage', detail'Attached triple garage with interior access and additional workshop space.'},
{icon'svg width=16 height=16 viewBox=0 0 24 24 fill=none stroke=#1A5C50 stroke-width=2 stroke-linecap=round stroke-linejoin=roundpath d=M4 4v3path d=M20 4v3path d=M4 7q2 3 4 0t4 0t4 0t4 0path d=M4 7L6 20H18L20 7svg', label'In-suite laundry', detail'Full-size washer and dryer included within the unit , no shared laundry required.'},
{icon'svg width=16 height=16 viewBox=0 0 24 24 fill=none stroke=#1A5C50 stroke-width=2 stroke-linecap=round stroke-linejoin=roundpath d=M12 2c0 6-6 8-6 14a6 6 0 0 0 12 0c0-6-6-8-6-14zpath d=M12 12c0 3-2 4-2 6a2 2 0 0 0 4 0c0-2-2-3-2-6zsvg', label'Forced-air + AC', detail'Ducted forced-air system with integrated central air conditioning.'},
{icon'svg width=16 height=16 viewBox=0 0 24 24 fill=none stroke=#1A5C50 stroke-width=2 stroke-linecap=round stroke-linejoin=roundpath d=M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2zpolyline points=9 22 9 12 15 12 15 22svg', label'Covered deck', detail'Large covered deck extending the living space outdoors year-round.'},
],
partners ['District of Ucluelet', 'Vancouver Island Health'],
},
'Kamloops Ridgeview' {
sqft '1,200', landSize '1,200 sqft', builtIn '2026', parking '2',
propertyType 'Townhouse', tenure 'Freehold Strata', annualTax '$3,360', moveInDate 'Spring 2027',
description 'A well-appointed townhouse on the Kamloops ridge with open views and a sunny south-facing deck. Two bedrooms, double parking, and a low-maintenance lifestyle in one of BC's sunniest cities.',
amenities [
{icon'svg width=16 height=16 viewBox=0 0 24 24 fill=none stroke=#1A5C50 stroke-width=2 stroke-linecap=round stroke-linejoin=roundcircle cx=12 cy=12 r=5line x1=12 y1=1 x2=12 y2=3line x1=12 y1=21 x2=12 y2=23line x1=4.22 y1=4.22 x2=5.64 y2=5.64line x1=18.36 y1=18.36 x2=19.78 y2=19.78line x1=1 y1=12 x2=3 y2=12line x1=21 y1=12 x2=23 y2=12line x1=4.22 y1=19.78 x2=5.64 y2=18.36line x1=18.36 y1=5.64 x2=19.78 y2=4.22svg', label'South-facing deck', detail'Covered south-facing deck with all-day sun and shelter from rain.'},
{icon'svg width=16 height=16 viewBox=0 0 24 24 fill=none stroke=#1A5C50 stroke-width=2 stroke-linecap=round stroke-linejoin=roundpolygon points=12 2 22 20 2 20polyline points=12 2 8 10 12 14 16 10svg', label'Ridge views', detail'Elevated position offers long views across the ridge and surrounding landscape.'},
{icon'svg width=16 height=16 viewBox=0 0 24 24 fill=none stroke=#1A5C50 stroke-width=2 stroke-linecap=round stroke-linejoin=roundrect x=3 y=3 width=18 height=18 rx=3path d=M9 18V8h5a3 3 0 0 1 0 6H9svg', label'Two parking stalls', detail'Two assigned parking stalls included , surface or covered.'},
{icon'svg width=16 height=16 viewBox=0 0 24 24 fill=none stroke=#1A5C50 stroke-width=2 stroke-linecap=round stroke-linejoin=roundpath d=M4 4v3path d=M20 4v3path d=M4 7q2 3 4 0t4 0t4 0t4 0path d=M4 7L6 20H18L20 7svg', label'In-suite laundry', detail'Full-size washer and dryer included within the unit , no shared laundry required.'},
{icon'svg width=16 height=16 viewBox=0 0 24 24 fill=none stroke=#1A5C50 stroke-width=2 stroke-linecap=round stroke-linejoin=roundpath d=M12 2c0 6-6 8-6 14a6 6 0 0 0 12 0c0-6-6-8-6-14zpath d=M12 12c0 3-2 4-2 6a2 2 0 0 0 4 0c0-2-2-3-2-6zsvg', label'Forced-air heating', detail'Ducted forced-air heating system provides fast, even warmth throughout.'},
],
partners ['District of Ucluelet', 'Vancouver Island Health'],
},
'The Osprey' {
sqft '1,380', landSize '1,380 sqft', builtIn '2026', parking '2',
propertyType 'Multiplex', tenure 'Freehold Strata', annualTax '$3,920', moveInDate 'Spring 2027',
description 'The Osprey is a 4–6 unit multiplex developed with the District of Ucluelet as the anchor municipal partner. Units are designed for young families and essential workers priced out of the conventional market. Natural light, quality finishes, and a quiet street in a community that knows its neighbours by name.',
amenities [
{icon'svg width=16 height=16 viewBox=0 0 24 24 fill=none stroke=#1A5C50 stroke-width=2 stroke-linecap=round stroke-linejoin=roundpath d=M2 12c1.5-2 3-2 4.5 0s3 2 4.5 0 3-2 4.5 0 3 2 4.5 0path d=M2 17c1.5-2 3-2 4.5 0s3 2 4.5 0 3-2 4.5 0 3 2 4.5 0path d=M2 7c1.5-2 3-2 4.5 0s3 2 4.5 0 3-2 4.5 0 3 2 4.5 0svg', label'Near waterfront', detail'A short walk to the waterfront, parks, and coastal pathways.'},
{icon'svg width=16 height=16 viewBox=0 0 24 24 fill=none stroke=#1A5C50 stroke-width=2 stroke-linecap=round stroke-linejoin=roundpath d=M4 4v3path d=M20 4v3path d=M4 7q2 3 4 0t4 0t4 0t4 0path d=M4 7L6 20H18L20 7svg', label'In-suite laundry', detail'Full-size washer and dryer included within the unit , no shared laundry required.'},
{icon'svg width=16 height=16 viewBox=0 0 24 24 fill=none stroke=#1A5C50 stroke-width=2 stroke-linecap=round stroke-linejoin=roundrect x=3 y=3 width=18 height=18 rx=3path d=M9 18V8h5a3 3 0 0 1 0 6H9svg', label'Two parking stalls', detail'Two assigned parking stalls included , surface or covered.'},
{icon'svg width=16 height=16 viewBox=0 0 24 24 fill=none stroke=#1A5C50 stroke-width=2 stroke-linecap=round stroke-linejoin=roundpath d=M12 22v-7path d=M5 9c0-3.87 3.13-7 7-7s7 3.13 7 7c0 2.65-1.47 4.96-3.64 6.18L12 17l-3.36-1.82A7.001 7.001 0 0 1 5 9zsvg', label'Private yard access', detail'Gated access to a private yard area shared with a small number of units.'},
{icon'svg width=16 height=16 viewBox=0 0 24 24 fill=none stroke=#1A5C50 stroke-width=2 stroke-linecap=round stroke-linejoin=roundpath d=M12 2c0 6-6 8-6 14a6 6 0 0 0 12 0c0-6-6-8-6-14zpath d=M12 12c0 3-2 4-2 6a2 2 0 0 0 4 0c0-2-2-3-2-6zsvg', label'Electric heat pump', detail'All-electric heat pump , efficient, quiet, and eligible for BC Hydro rebates.'},
{icon'svg width=16 height=16 viewBox=0 0 24 24 fill=none stroke=#1A5C50 stroke-width=2 stroke-linecap=round stroke-linejoin=roundpath d=M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.77-3.77a6 6 0 0 1-7.94 7.94l-6.91 6.91a2.12 2.12 0 0 1-3-3l6.91-6.91a6 6 0 0 1 7.94-7.94l-3.76 3.76zsvg', label'Maintenance included', detail'Strata fees cover full exterior maintenance, landscaping, and common area upkeep.'},
{icon'svg width=16 height=16 viewBox=0 0 24 24 fill=none stroke=#1A5C50 stroke-width=2 stroke-linecap=round stroke-linejoin=roundpath d=M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16zpolyline points=3.27 6.96 12 12.01 20.73 6.96line x1=12 y1=22.08 x2=12 y2=12svg', label'Outdoor storage', detail'Lockable outdoor storage shed included on the property.'},
{icon'svg width=16 height=16 viewBox=0 0 24 24 fill=none stroke=#1A5C50 stroke-width=2 stroke-linecap=round stroke-linejoin=roundpath d=M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2zpolyline points=9 22 9 12 15 12 15 22svg', label'Energy-efficient build', detail'Built to BC Step Code energy efficiency requirements for reduced running costs.'},
],
partners ['District of Ucluelet', 'Mark Jewells Mortgage'],
}
};
Real neighbourhood data for 844 Rainforest Drive, Ucluelet, BC
(48.94206948412843, -125.55545551137537). Distances calculated
as straight-line (as the crow flies) from that exact coordinate
to each real, verified place - actual walkingdriving distance
along roads will run somewhat longer than these numbers.
var rainforestDriveNeighbourhood = {
schools [['Ucluelet Secondary School', '850m'], ['Ucluelet Elementary School', '1km']],
shops [['Harbourview Drugstore', '300m'], ['Blackberry Cove Marketplace', '650m'], ['Ucluelet Co-op General Store', '650m']],
transit [['Cedar Road Bus Stop', '650m']],
parks [['Wild Pacific Trail', '550m'], ['Big Beach Picnic Park', '650m'], ['Alder Park', '1.3km'], ['He-Tin-Kis Park', '2.1km'], ['Amphitrite Point Lighthouse', '2.5km']],
health [['Ucluelet Co-op Pharmacy', '650m'], ['Ucluelet Medical Centre', '850m']],
community [['Ucluelet Community Centre', '600m'], ['Vancouver Island Regional Library - Ucluelet', '600m']],
};
listingTemplates['Rainforest Drive - Unit A'] = Object.assign({}, listingTemplates.default, { neighbourhood rainforestDriveNeighbourhood });
listingTemplates['Rainforest Drive - Unit B'] = Object.assign({}, listingTemplates.default, { neighbourhood rainforestDriveNeighbourhood });
listingTemplates['Rainforest Drive - Unit C'] = Object.assign({}, listingTemplates.default, { neighbourhood rainforestDriveNeighbourhood });
listingTemplates['Norah Street - Unit A'] = Object.assign({}, listingTemplates.default, { neighbourhood rainforestDriveNeighbourhood });
listingTemplates['Norah Street - Unit B'] = Object.assign({}, listingTemplates.default, { neighbourhood rainforestDriveNeighbourhood });
listingTemplates['Norah Street - Unit C'] = Object.assign({}, listingTemplates.default, { neighbourhood rainforestDriveNeighbourhood });
Real demographic data for the District of Ucluelet, sourced from
ucluelet.ca (Statistics Canada 2016 Census). Only demographics and
languages are sourcedconfirmed - income, housing, education, and
commute stats are NOT available from this source, so those keep the
generic placeholder figures from the default template. Worth flagging
to Sarah these are 2016 Census figures (the most recent cited on the
official page), not current-year numbers.
var uclueletStatistics = Object.assign({}, listingTemplates.default.statistics, {
demographics [
['Total population (2016 Census)', '1,717', undefined],
['Median age', '39.2 years', undefined],
],
languages [
['English (mother tongue)', '91%', 91],
['Non-official language (mother tongue)', '6%', 6],
['French (mother tongue)', '3%', 3],
],
});
['Rainforest Drive - Unit A', 'Rainforest Drive - Unit B', 'Rainforest Drive - Unit C',
'Norah Street - Unit A', 'Norah Street - Unit B', 'Norah Street - Unit C',
'Ocean West - Unit A', 'Ocean West - Unit B', 'Ocean West - Unit C'].forEach(function(key) {
listingTemplates[key] = Object.assign({}, listingTemplates.default, listingTemplates[key] {}, { statistics uclueletStatistics });
});
Real neighbourhood data for Ocean West, calculated from its exact
GPS coordinate (48.94144414478106, -125.56628321526729). Straight-line
distances to the same set of verified real Ucluelet places used for
Rainforest Drive Norah Street, re-ranked by actual closeness from
this specific coordinate.
var oceanWestNeighbourhood = {
schools [['Ucluelet Secondary School', '1.6km'], ['Ucluelet Elementary School', '1.7km']],
shops [['Harbourview Drugstore', '1km'], ['Blackberry Cove Marketplace', '1.4km'], ['Ucluelet Co-op General Store', '1.4km']],
transit [['Cedar Road Bus Stop', '1.4km']],
parks [['Wild Pacific Trail', '511m'], ['Big Beach Picnic Park', '1.2km'], ['Alder Park', '2km'], ['He-Tin-Kis Park', '2.6km'], ['Amphitrite Point Lighthouse', '2.9km']],
health [['Ucluelet Medical Centre', '560m'], ['Ucluelet Co-op Pharmacy', '1.5km']],
community [['Ucluelet Community Centre', '1.2km'], ['Vancouver Island Regional Library - Ucluelet', '1.2km']],
};
listingTemplates['Ocean West - Unit A'] = Object.assign({}, listingTemplates['Ocean West - Unit A'], { neighbourhood oceanWestNeighbourhood });
listingTemplates['Ocean West - Unit B'] = Object.assign({}, listingTemplates['Ocean West - Unit B'], { neighbourhood oceanWestNeighbourhood });
listingTemplates['Ocean West - Unit C'] = Object.assign({}, listingTemplates['Ocean West - Unit C'], { neighbourhood oceanWestNeighbourhood });
Real demographiceconomic data for the City of Port Alberni, sourced
from Sarah's Statistics Canada 2021 Census Profile CSV. Every category
the site tracks (demographics, income, housing, education, commute,
language) has a genuine sourced figure here, unlike the Ucluelet data
where several categories had to stay as generic placeholders.
var portAlberniStatistics = {
demographics [
['Total population (2021 Census)', '18,259', undefined],
['Population growth (2016-2021)', '+3.3%', undefined],
['Median age', '49.2 years', undefined],
],
income [
['Median household income', '$62,800', undefined],
['Median individual income', '$35,600', undefined],
['Households earning $100k+', '25%', 25],
['Low-income rate (LIM-AT)', '15%', 15],
],
housing [
['Owner-occupied', '69%', 69],
['Renter-occupied', '31%', 31],
['Median dwelling value', '$400,000', undefined],
['Average monthly shelter cost (owned)', '$1,045', undefined],
['Dwellings built 2016-2021', '4%', 4],
],
education [
['No certificate diploma', '22%', 22],
['High school diploma', '32%', 32],
['College trades certificate', '35%', 35],
['University degree', '11%', 11],
],
commute [
['Drive alone', '81%', 81],
['Carpool', '8%', 8],
['Transit', '2%', 2],
['Walk or cycle', '7%', 7],
['Commute under 15 min', '69%', 69],
],
languages [
['English (mother tongue)', '90%', 90],
['Non-official language (mother tongue)', '7%', 7],
['French (mother tongue)', '2%', 2],
],
};
['Compton Road - Unit A', 'Compton Road - Unit B', 'Compton Road - Unit C',
'River Road - Unit A', 'River Road - Unit B', 'River Road - Unit C'].forEach(function(key) {
listingTemplates[key] = Object.assign({}, listingTemplates.default, listingTemplates[key] {}, { statistics portAlberniStatistics });
});
Real neighbourhood data for River Road, Port Alberni, BC
(49.266995936872085, -124.8432751576526). Straight-line distances
to verified real Port Alberni places.
var riverRoadNeighbourhood = {
schools [['Haahuupayak Elementary School', '600m'], ['u1E23uuu02BFas Tsuma-as Elementary School', '2km'], ['Alberni District Secondary School', '3.9km']],
shops [['Save-On-Foods', '4.1km'], ['Tyleru2019s NOFRILLS Port Alberni', '4.2km'], ['Quality Foods Port Alberni', '5.1km']],
transit [['Port Alberni Transit System', '3.8km']],
parks [['River Road Park', '84m'], ['Maplehurst Trails', '3.1km'], ['Stamp River Provincial Park', '9.6km']],
health [['I.D.A. Harbour Pharmacy', '4km'], ['West Coast General Hospital', '4.9km']],
community [['Vancouver Island Regional Library - Port Alberni', '3.9km']],
};
listingTemplates['River Road - Unit A'] = Object.assign({}, listingTemplates['River Road - Unit A'], { neighbourhood riverRoadNeighbourhood });
listingTemplates['River Road - Unit B'] = Object.assign({}, listingTemplates['River Road - Unit B'], { neighbourhood riverRoadNeighbourhood });
listingTemplates['River Road - Unit C'] = Object.assign({}, listingTemplates['River Road - Unit C'], { neighbourhood riverRoadNeighbourhood });
Real neighbourhood data for Compton Road, Port Alberni, BC
(49.27007607198955, -124.83719012185979). Straight-line distances
to the same verified real Port Alberni places, re-ranked by actual
closeness from this specific coordinate.
var comptonRoadNeighbourhood = {
schools [['Haahuupayak Elementary School', '1.2km'], ['u1E23uuu02BFas Tsuma-as Elementary School', '1.5km'], ['Alberni District Secondary School', '3.7km']],
shops [['Tyleru2019s NOFRILLS Port Alberni', '3.8km'], ['Save-On-Foods', '4km'], ['Quality Foods Port Alberni', '5.1km']],
transit [['Port Alberni Transit System', '3.7km']],
parks [['River Road Park', '642m'], ['Maplehurst Trails', '2.6km'], ['Stamp River Provincial Park', '9.6km']],
health [['I.D.A. Harbour Pharmacy', '3.8km'], ['West Coast General Hospital', '4.6km']],
community [['Vancouver Island Regional Library - Port Alberni', '3.7km']],
};
listingTemplates['Compton Road - Unit A'] = Object.assign({}, listingTemplates['Compton Road - Unit A'], { neighbourhood comptonRoadNeighbourhood });
listingTemplates['Compton Road - Unit B'] = Object.assign({}, listingTemplates['Compton Road - Unit B'], { neighbourhood comptonRoadNeighbourhood });
listingTemplates['Compton Road - Unit C'] = Object.assign({}, listingTemplates['Compton Road - Unit C'], { neighbourhood comptonRoadNeighbourhood });
Estimated Annualised Costs, derived from The Osprey's total yearly
operating costs ($3,943.20mo across 4 keys 2x 3-bed + 2x 2-bed),
split by bedroom-count weighting each 3-bed Unit A carries 30% of
total costs ($1,182.96), each 2-bed Unit BC carries 20% ($788.64).
Applied across every development's Unit ABC listings.
['Rainforest Drive', 'Norah Street', 'Ocean West', 'River Road', 'Compton Road'].forEach(function(project) {
listingTemplates[project + ' - Unit A'] = Object.assign({}, listingTemplates[project + ' - Unit A'], { annualTax '$1,182.96' });
listingTemplates[project + ' - Unit B'] = Object.assign({}, listingTemplates[project + ' - Unit B'], { annualTax '$788.64' });
listingTemplates[project + ' - Unit C'] = Object.assign({}, listingTemplates[project + ' - Unit C'], { annualTax '$788.64' });
});
script
script
── LISTING DETAIL DATA TEMPLATES ──
var _currentListingImages = [];
function heroOpenLightbox(startIndex) {
if (_currentListingImages.length) lightboxOpen(_currentListingImages, startIndex 0);
}
function closeListingDetail() {
var wipe = document.getElementById('detail-colour-wipe');
wipe.classList.remove('reveal');
wipe.classList.add('active');
setTimeout(function() {
document.getElementById('listing-detail').classList.remove('open');
setTimeout(function() {
wipe.classList.add('reveal');
setTimeout(function() {
wipe.classList.remove('active');
wipe.classList.remove('reveal');
}, 350);
}, 50);
}, 350);
}
function switchTab(name, btn) {
if (btn.classList.contains('locked')) {
openGate1(function() { unlockListingDetail(); });
return;
}
document.querySelectorAll('.detail-tab').forEach(function(t) { t.classList.remove('active'); });
document.querySelectorAll('.tab-panel').forEach(function(p) { p.style.display = 'none'; });
btn.classList.add('active');
document.getElementById('tab-' + name).style.display = 'block';
if (name === 'highlights' && typeof _approxLocationMap !== 'undefined' && _approxLocationMap) {
setTimeout(function() { _approxLocationMap.resize(); }, 0);
}
}
function populateNbItem(idBase, name, dist) {
var el = document.getElementById(idBase);
var dl = document.getElementById(idBase + '-d');
if (el) el.textContent = name;
if (dl) dl.textContent = dist;
}
function populateNeighbourhood(nb) {
function item(idBase, arr, i) {
var entry = arr && arr[i];
populateNbItem(idBase, entry entry[0] '', entry entry[1] '');
}
item('nb-school-1', nb.schools, 0);
item('nb-school-2', nb.schools, 1);
item('nb-school-3', nb.schools, 2);
item('nb-shop-1', nb.shops, 0);
item('nb-shop-2', nb.shops, 1);
item('nb-shop-3', nb.shops, 2);
item('nb-transit-1', nb.transit, 0);
item('nb-transit-2', nb.transit, 1);
item('nb-transit-3', nb.transit, 2);
item('nb-park-1', nb.parks, 0);
item('nb-park-2', nb.parks, 1);
item('nb-park-3', nb.parks, 2);
item('nb-park-4', nb.parks, 3);
item('nb-park-5', nb.parks, 4);
item('nb-health-1', nb.health, 0);
item('nb-health-2', nb.health, 1);
item('nb-comm-1', nb.community, 0);
item('nb-comm-2', nb.community, 1);
}
function makeStatRow(label, val, pct) {
var bar = pct !== undefined
'div class=stat-bar-wrapdiv class=stat-bar style=width' + pct + '%divdiv'
'';
return 'div class=stat-rowspan class=stat-label' + label + 'span' + bar + 'span class=stat-val' + val + 'spandiv';
}
function populateStatSection(id, rows) {
var el = document.getElementById(id);
if (el) el.innerHTML = rows.map(function(r) { return makeStatRow(r[0], r[1], r[2]); }).join('');
}
function populateStatistics(st) {
populateStatSection('stat-demographics', st.demographics);
populateStatSection('stat-income', st.income);
populateStatSection('stat-housing', st.housing);
populateStatSection('stat-education', st.education);
populateStatSection('stat-commute', st.commute);
populateStatSection('stat-languages', st.languages);
}
── YEAR 10 CALCULATOR ──
function y10Fmt(n) {
return '$' + Math.round(n).toLocaleString('en-CA');
}
function y10CMHC(price, dpPct) {
if (dpPct = 20) return 0;
var loan = price (1 - dpPct 100);
var rate = dpPct 10 0.0400 dpPct 15 0.0310 0.0280;
return loan rate;
}
function y10MarketAt(price, totalRatePct, year) {
Linear interpolation of appreciation over 10 years
return price (1 + (totalRatePct 100) (year 10));
}
function y10SyncSlider(val) {
val = Math.min(160, Math.max(0, parseInt(val) 0));
var slider = document.getElementById('y10-slider');
if (slider) { slider.value = val; y10SliderInput(val); }
}
function y10SliderInput(val) {
val = parseInt(val);
document.getElementById('y10-rate').value = val;
Update slider fill
var slider = document.getElementById('y10-slider');
var pct = val 160 100;
slider.style.background = 'linear-gradient(to right, #1A5C50 0%, #1A5C50 ' + pct + '%, rgba(26,92,80,0.2) ' + pct + '%, rgba(26,92,80,0.2) 100%)';
y10Calc();
}
function y10Calc() {
var raw = (document.getElementById('y10-price').value '').replace([^0-9.]g, '');
var price = parseFloat(raw) 0;
var rate = parseFloat(document.getElementById('y10-rate').value) 0;
if (!price) {
['y10-market-price','y10-locked-price','y10-m1','y10-m3','y10-m5','y10-m7','y10-m10',
'y10-i1','y10-i3','y10-i5','y10-i7','y10-i10'].forEach(function(id) {
var el = document.getElementById(id); if (el) el.textContent = '-';
});
document.getElementById('y10-saving-row').style.display = 'none';
document.getElementById('y10-mortgage-results').style.display = 'none';
var ep = document.getElementById('y10-equity-panel'); if (ep) ep.style.display = 'none';
return;
}
Market projections
var m10 = y10MarketAt(price, rate, 10);
if (document.getElementById('y10-market-price')) document.getElementById('y10-market-price').textContent = y10Fmt(m10);
document.getElementById('y10-m1').textContent = y10Fmt(y10MarketAt(price, rate, 1));
document.getElementById('y10-m3').textContent = y10Fmt(y10MarketAt(price, rate, 3));
document.getElementById('y10-m5').textContent = y10Fmt(y10MarketAt(price, rate, 5));
document.getElementById('y10-m7').textContent = y10Fmt(y10MarketAt(price, rate, 7));
if (document.getElementById('y10-m10')) document.getElementById('y10-m10').textContent = y10Fmt(m10);
IGVhope locked price (stays the same)
if (document.getElementById('y10-locked-price')) document.getElementById('y10-locked-price').textContent = y10Fmt(price);
['y10-i1','y10-i3','y10-i5','y10-i7','y10-i10'].forEach(function(id) {
var el = document.getElementById(id); if (el) el.textContent = y10Fmt(price);
});
Saving
var saving = m10 - price;
if (document.getElementById('y10-saving')) document.getElementById('y10-saving').textContent = y10Fmt(saving) + ' saved';
document.getElementById('y10-saving-row').style.display = 'flex';
Mortgage at Year 10 (at locked price)
var dpPct = 20;
var years = 25;
var freq = 12;
var rateEl = document.getElementById('y10-mrate').value;
var mrate = parseFloat(rateEl);
var dpAmt = price dpPct 100;
var cmhc = y10CMHC(price, dpPct);
var total = price - dpAmt + cmhc;
Equity story does the market gain cover the down payment
var gainCoversDP = saving = dpAmt;
var surplus = saving - dpAmt;
if (document.getElementById('y10-r-gain')) document.getElementById('y10-r-gain').textContent = y10Fmt(saving);
document.getElementById('y10-r-dp').textContent = y10Fmt(dpAmt);
if (document.getElementById('y10-r-dp-pct-label')) document.getElementById('y10-r-dp-pct-label').textContent = dpPct + '% of your locked price';
var verdict;
if (saving = 0) {
verdict = '';
} else if (gainCoversDP) {
verdict = 'Your homeu2019s market gain of ' + y10Fmt(saving) + ' fully covers the ' + y10Fmt(dpAmt) + ' down payment, with ' + y10Fmt(surplus) + ' to spare. You enter your mortgage without needing to save a separate deposit.';
} else {
verdict = 'The market gain of ' + y10Fmt(saving) + ' covers ' + Math.round(saving dpAmt 100) + '% of your ' + y10Fmt(dpAmt) + ' down payment. The remaining ' + y10Fmt(dpAmt - saving) + ' would need to be saved separately.';
}
var verdictEl = document.getElementById('y10-r-verdict');
verdictEl.innerHTML = gainCoversDP && saving 0
'Your homeu2019s market gain of strong' + y10Fmt(saving) + 'strong fully covers the strong' + y10Fmt(dpAmt) + 'strong down payment, with strong' + y10Fmt(surplus) + 'strong to spare. That surplus can be put toward the upfront legal and government costs of purchase property transfer tax, legal fees, and title registration, so you enter ownership without needing additional cash reserves.'
verdict;
document.getElementById('y10-r-cmhc').textContent = cmhc 0 y10Fmt(cmhc) 'None (20%+ down)';
if (document.getElementById('y10-r-total')) document.getElementById('y10-r-total').textContent = y10Fmt(total);
Showhide CMHC row
var cmhcRow = document.getElementById('y10-cmhc-row');
if (cmhcRow) cmhcRow.style.display = cmhc 0 'flex' 'none';
if (!isNaN(mrate) && mrate 0) {
var r = Math.pow(1 + mrate 200, 2 freq) - 1;
var n = years freq;
var pmt = total r (1 - Math.pow(1 + r, -n));
var freqLabel = freq === 12 'mo' freq === 26 '2wk' 'wk';
if (document.getElementById('y10-r-payment')) document.getElementById('y10-r-payment').textContent = y10Fmt(pmt) + freqLabel;
if (document.getElementById('y10-igv-payment')) document.getElementById('y10-igv-payment').textContent = y10Fmt(pmt) + freqLabel;
Compare to market payment
var mTotal = m10 (1 - dpPct 100) + y10CMHC(m10, dpPct);
var mPmt = mTotal r (1 - Math.pow(1 + r, -n));
var pmtSave = mPmt - pmt;
if (document.getElementById('y10-wait-payment')) document.getElementById('y10-wait-payment').textContent = y10Fmt(mPmt) + freqLabel;
if (document.getElementById('y10-igv-saving-note')) document.getElementById('y10-igv-saving-note').textContent = y10Fmt(pmtSave) + freqLabel + ' less';
if (document.getElementById('y10-r-saving')) document.getElementById('y10-r-saving').textContent = y10Fmt(pmtSave) + freqLabel + ' less than buying at market price';
document.getElementById('y10-mortgage-results').style.display = 'block';
} else {
document.getElementById('y10-mortgage-results').style.display = saving 'block' 'none';
if (document.getElementById('y10-r-payment')) document.getElementById('y10-r-payment').textContent = '-';
document.getElementById('y10-r-saving').textContent = '-';
}
Populate new two-column leftright panel
if (document.getElementById('y10-wait-price')) document.getElementById('y10-wait-price').textContent = y10Fmt(m10);
if (document.getElementById('y10-wait-dp')) document.getElementById('y10-wait-dp').textContent = y10Fmt(m10 dpPct 100);
if (document.getElementById('y10-wait-dp-note')) document.getElementById('y10-wait-dp-note').textContent = 'Cash required upfront — ' + dpPct + '% of ' + y10Fmt(m10);
if (document.getElementById('y10-igv-price')) document.getElementById('y10-igv-price').textContent = y10Fmt(price);
if (document.getElementById('y10-igv-dp')) document.getElementById('y10-igv-dp').innerHTML = gainCoversDP 'span style=text-decorationline-through; opacity0.45;' + y10Fmt(dpAmt) + 'span span style=font-size9px; font-weight700; color#da8d27; letter-spacing0.05em;✓ COVEREDspan' y10Fmt(dpAmt) + ' needed';
if (document.getElementById('y10-igv-dp-note')) document.getElementById('y10-igv-dp-note').textContent = gainCoversDP 'Covered by your ' + y10Fmt(saving) + ' market gain' 'Market gain of ' + y10Fmt(saving) + ' covers ' + Math.round(savingdpAmt100) + '%';
Equity LVR insight panel
var eqPanel = document.getElementById(y10-equity-panel);
if (price) {
var igvMortgage = total; locked price mortgage
var igvLvr = (igvMortgage m10) 100; LVR against market value - the key metric
var mktMortgage = m10 (1 - dpPct 100); what they'd borrow at market price
mktLvr calculated below
document.getElementById(eq-lvr-igv).textContent = igvLvr.toFixed(1) + %;
document.getElementById(eq-lvr-igv-note).textContent = Your mortgage of + y10Fmt(igvMortgage) + against a home the market values at + y10Fmt(m10);
var mktLvr = 100 - dpPct; LVR = loan as % of value
document.getElementById(eq-lvr-market).textContent = mktLvr.toFixed(1) + %;
document.getElementById(eq-lvr-market-note).textContent = Borrowing + y10Fmt(mktMortgage) + against a + dpPct + % down payment on the + y10Fmt(m10) + market price;
document.getElementById(eq-lvr-market-warning).textContent = You still need a + dpPct + % down payment ( + y10Fmt(m10 dpPct 100) + ) upfront just to get the mortgage.;
Populate new panel LVR
if (document.getElementById('y10-igv-lvr')) document.getElementById('y10-igv-lvr').textContent = igvLvr.toFixed(1) + '%';
if (document.getElementById('y10-igv-lvr-note')) document.getElementById('y10-igv-lvr-note').textContent = 'Your mortgage of ' + y10Fmt(igvMortgage) + ' against a home worth ' + y10Fmt(m10);
if (document.getElementById('y10-wait-lvr')) document.getElementById('y10-wait-lvr').textContent = mktLvr.toFixed(1) + '%';
if (document.getElementById('y10-wait-lvr-note')) document.getElementById('y10-wait-lvr-note').textContent = 'Borrowing ' + y10Fmt(mktMortgage) + ' on the ' + y10Fmt(m10) + ' market price';
if (document.getElementById('y10-wait-warning')) document.getElementById('y10-wait-warning').textContent = 'You still need ' + y10Fmt(m10 dpPct 100) + ' cash upfront just to qualify.';
if (document.getElementById('y10-wait-warning-cell')) document.getElementById('y10-wait-warning-cell').textContent = y10Fmt(m10 dpPct 100);
if (eqPanel) eqPanel.style.display = block;
} else {
if (eqPanel) eqPanel.style.display = none;
}
}
function mcInit(price, location) {
Pre-fill Year 10 calculator price
var input = document.getElementById('y10-price');
if (input) {
var num = price parseInt(price.replace([^0-9]g, '')) '';
input.value = num num.toLocaleString('en-CA') '';
}
y10Calc();
}
function startApplication() {
if (!gate1Unlocked) { openGate1(function() { startApplication(); }); return; }
if (!gate2Unlocked) { openGate2(function() { startApplication(); }); return; }
if (!gate3Unlocked) { openGate3(function() { startApplication(); }); return; }
openApplicationConfirm();
}
function getCurrentListingName() {
var navTitle = document.getElementById('detail-nav-title');
return navTitle navTitle.textContent.trim() '';
}
function openApplicationConfirm() {
var listingName = getCurrentListingName();
var btn = document.getElementById('app-confirm-submit-btn');
btn.innerHTML = 'Express Interest for ' + (listingName 'this home') + ' span style=font-size0.75em;(No Obligation)span';
btn.disabled = false;
document.getElementById('app-confirm-choice').style.display = 'block';
document.getElementById('app-confirm-done').style.display = 'none';
document.getElementById('app-confirm-overlay').classList.add('open');
}
function closeApplicationConfirm() {
document.getElementById('app-confirm-overlay').classList.remove('open');
}
function handleSubmitApplicationClick() {
var listingName = getCurrentListingName();
var btn = document.getElementById('app-confirm-submit-btn');
btn.disabled = true;
btn.textContent = 'Submitting...';
submitToHubspot(HUBSPOT_GATE3_FORM_GUID, [
{ name 'email', value gate1CapturedEmail },
{ name 'igvhope_applied_listing', value listingName }
]).catch(function() {}).then(function() {
document.getElementById('app-confirm-choice').style.display = 'none';
document.getElementById('app-confirm-done').style.display = 'block';
});
}
var WATERMARK_WORKER_URL = 'REPLACE_WITH_WATERMARK_WORKER_URL';
var DOCUMENT_EVENT_WORKER_URL = 'httpsfloorplan-salesbrochure-event.igvhousing.workers.dev';
function trackDocumentDownload(docType, unit) {
if (!DOCUMENT_EVENT_WORKER_URL DOCUMENT_EVENT_WORKER_URL.indexOf('REPLACE_WITH') === 0) return;
if (!gate1CapturedEmail) return;
fetch(DOCUMENT_EVENT_WORKER_URL, {
method 'POST',
headers { 'Content-Type' 'applicationjson' },
body JSON.stringify({ email gate1CapturedEmail, docType docType, unit unit '' })
}).catch(function(err) { console.warn('Document download tracking failed', err); });
}
function fetchWatermarkedDocument(docType, unit, btnEl) {
if (!WATERMARK_WORKER_URL WATERMARK_WORKER_URL.indexOf('REPLACE_WITH') === 0) {
alert('Document delivery is not configured yet.');
return;
}
var originalLabel = btnEl btnEl.innerHTML null;
if (btnEl) { btnEl.disabled = true; btnEl.innerHTML = 'Preparing your copy...'; }
fetch(WATERMARK_WORKER_URL, {
method 'POST',
headers { 'Content-Type' 'applicationjson' },
body JSON.stringify({
docType docType,
unit unit '',
email gate1CapturedEmail,
name gate1CapturedFirstName
})
})
.then(function(res) {
if (!res.ok) {
return res.json().then(function(data) {
throw new Error(data.error ('Request failed with status ' + res.status));
});
}
return res.blob();
})
.then(function(blob) {
var blobUrl = URL.createObjectURL(blob);
window.open(blobUrl, '_blank');
trackDocumentDownload(docType, unit);
if (btnEl) { btnEl.disabled = false; btnEl.innerHTML = originalLabel; }
})
.catch(function(err) {
console.error('Watermarked document request failed', err);
alert('Something went wrong preparing this document. Please try again.');
if (btnEl) { btnEl.disabled = false; btnEl.innerHTML = originalLabel; }
});
}
function downloadFloorplan(btnEl) {
if (!gate1Unlocked) { openGate1(function() { downloadFloorplan(btnEl); }); return; }
if (!gate2Unlocked) { openGate2(function() { downloadFloorplan(btnEl); }); return; }
var titleEl = document.getElementById('detail-hero-title') document.getElementById('detail-nav-title');
var title = titleEl titleEl.textContent '';
var unitMatch = title.match(-sUnits([A-C])i);
var unitLetter = unitMatch unitMatch[1].toUpperCase() null;
if (!unitLetter) {
alert('Floorplan not available for this listing yet.');
return;
}
fetchWatermarkedDocument('floorplan', unitLetter, btnEl);
}
function downloadBrochure(btnEl) {
if (!gate1Unlocked) { openGate1(function() { downloadBrochure(btnEl); }); return; }
if (!gate2Unlocked) { openGate2(function() { downloadBrochure(btnEl); }); return; }
fetchWatermarkedDocument('brochure', null, btnEl);
}
function bookTour() {
if (!gate1Unlocked) { openGate1(function() { bookTour(); }); return; }
if (!gate2Unlocked) { openGate2(function() { bookTour(); }); return; }
var w = document.querySelector('elevenlabs-convai');
if (!w) return;
var btn = w.shadowRoot && w.shadowRoot.querySelector('button');
if (btn) { btn.click(); } else { w.click(); }
}
Wire up all See more card-apply-btn buttons
── LIGHTBOX ──
var _lbImages = [];
var _lbIndex = 0;
function lightboxOpen(images, startIndex) {
_lbImages = images;
_lbIndex = startIndex 0;
lightboxRender();
document.getElementById('lightbox').classList.add('open');
document.addEventListener('keydown', lightboxKey);
}
function lightboxClose() {
document.getElementById('lightbox').classList.remove('open');
document.removeEventListener('keydown', lightboxKey);
}
function lightboxNav(dir) {
_lbIndex = (_lbIndex + dir + _lbImages.length) % _lbImages.length;
lightboxRender();
}
function lightboxKey(e) {
if (e.key === 'ArrowRight') lightboxNav(1);
if (e.key === 'ArrowLeft') lightboxNav(-1);
if (e.key === 'Escape') lightboxClose();
}
function lightboxRender() {
document.getElementById('lightbox-img').src = _lbImages[_lbIndex];
if (document.getElementById('lightbox-counter')) document.getElementById('lightbox-counter').textContent = (_lbIndex + 1) + ' ' + _lbImages.length;
var dots = document.getElementById('lightbox-dots');
dots.innerHTML = _lbImages.map(function(_, i) {
return 'div class=lightbox-dot' + (i === _lbIndex ' active' '') + ' onclick=lightboxGo(' + i + ')div';
}).join('');
Hide nav arrows if only one image
document.getElementById('lightbox-prev').style.display = _lbImages.length 1 '' 'none';
document.getElementById('lightbox-next').style.display = _lbImages.length 1 '' 'none';
}
function lightboxGo(i) {
_lbIndex = i;
lightboxRender();
}
document.addEventListener('DOMContentLoaded', function() {
Initialise appreciation slider fill at default value (98%)
y10SliderInput(98);
Initialise mortgage rate slider fill at default value (5.5%)
var mrSlider = document.getElementById('y10-mrate');
if (mrSlider) { var p=((5.5-2)6100).toFixed(1); mrSlider.style.background='linear-gradient(to right,#1A5C50 0%,#1A5C50 '+p+'%,rgba(26,92,80,0.2) '+p+'%,rgba(26,92,80,0.2) 100%)'; }
document.querySelectorAll('.listing-card').forEach(function(card) {
var btn = card.querySelector('.card-apply-btn');
if (btn) {
btn.addEventListener('click', function(e) {
e.stopPropagation();
openListingDetail(card);
});
}
card.addEventListener('click', function(e) {
if (!e.target.closest('.card-save-btn') && !e.target.closest('.card-apply-btn')) {
openListingDetail(card);
}
});
});
});
DASHBOARD JS
var cityRegionMap = {
'Vancouver, BC' 'Vancouver Metro', 'Surrey, BC' 'Vancouver Metro',
'Burnaby, BC' 'Vancouver Metro', 'Coquitlam, BC' 'Vancouver Metro',
'Richmond, BC' 'Vancouver Metro', 'Langley, BC' 'Fraser Valley',
'Abbotsford, BC' 'Fraser Valley', 'Chilliwack, BC' 'Fraser Valley',
'Kelowna, BC' 'Okanagan', 'Vernon, BC' 'Okanagan',
'Victoria, BC' 'Vancouver Island', 'Nanaimo, BC' 'Vancouver Island',
'Campbell River, BC' 'Vancouver Island', 'Nelson, BC' 'Northern BC',
'Prince George, BC' 'Northern BC', 'Kamloops, BC' 'Northern BC'
};
var currentRegion = 'Vancouver Island';
var currentType = 'All';
function applyListingFilters() {
document.querySelectorAll('.listing-card').forEach(function(card) {
var r = card.getAttribute('data-region') '';
var regionMatch = (currentRegion === 'Any region' r === currentRegion);
var metaItems = card.querySelectorAll('.card-meta-item');
var type = metaItems.length metaItems[metaItems.length - 1].textContent.trim() '';
var typeMatch = (currentType === 'All' type === currentType);
card.style.display = (regionMatch && typeMatch) '' 'none';
});
}
function filterByRegion(region) {
currentRegion = region;
var sel = document.getElementById('region-select');
if (sel) sel.value = region;
applyListingFilters();
var ov = document.getElementById('dash-map-overlay');
if (ov) ov.textContent = region === 'Any region'
'CLICK TO SEE LISTINGS PER AREA'
'SHOWING ' + region.toUpperCase() + ' u2014 CLICK MAP TO RESET';
var inner = document.getElementById('dash-scroll-inner');
if (inner) inner.scrollIntoView({behavior 'smooth'});
}
function filterByType(type) {
currentType = type;
applyListingFilters();
}
var loadMorePage = 1;
var userLoggedIn = false;
var pendingGate1Callback = null;
var gate1Unlocked = false;
var gate1CapturedEmail = '';
var gate1CapturedFirstName = '';
var gate1SubmissionPromise = null;
var gate1CreateAccountFlow = false;
---------- HubSpot integration ----------
var HUBSPOT_PORTAL_ID = '342997618';
var HUBSPOT_GATE1_FORM_GUID = '6b44e39d-2454-45ac-83d7-507b93fadf6b';
var HUBSPOT_GATE2_FORM_GUID = '14ab3b8d-ec79-439e-a2f6-60ee9c1ddd88';
var HUBSPOT_GATE3_FORM_GUID = '062d7e17-a17a-43a6-ac0e-96c2c4238a70';
var HUBSPOT_SUBSCRIPTION_IGVHOPE_MARKETING = 2209865883;
var HUBSPOT_SUBSCRIPTION_ACCOUNT_CREATION = 3124593253;
var HUBSPOT_SUBSCRIPTION_PHONE_COMMS = 3124581278;
---------- Gate status persistence (returning visitors) ----------
var GATE_STATUS_WORKER_URL = 'httpsgate-status.igvhousing.workers.devgate-status';
var GATE_VISITOR_EMAIL_KEY = 'igvhope_visitor_email';
var GATE_VISITOR_NAME_KEY = 'igvhope_visitor_name';
function saveVisitorEmail(email) {
try {
if (email) localStorage.setItem(GATE_VISITOR_EMAIL_KEY, email.trim().toLowerCase());
} catch (e) {
console.warn('Could not persist visitor email to localStorage', e);
}
}
function getSavedVisitorEmail() {
try {
return localStorage.getItem(GATE_VISITOR_EMAIL_KEY) '';
} catch (e) {
return '';
}
}
function saveVisitorName(name) {
try {
if (name) localStorage.setItem(GATE_VISITOR_NAME_KEY, name.trim());
} catch (e) {
console.warn('Could not persist visitor name to localStorage', e);
}
}
function getSavedVisitorName() {
try {
return localStorage.getItem(GATE_VISITOR_NAME_KEY) '';
} catch (e) {
return '';
}
}
function checkGateStatusOnLoad(attemptsLeft) {
if (typeof attemptsLeft !== 'number') attemptsLeft = 3;
var savedEmail = getSavedVisitorEmail();
if (!savedEmail) return;
gate1CapturedEmail = savedEmail;
gate1CapturedFirstName = getSavedVisitorName();
Optimistically reflect the saved account in the nav right away - the
accountsession already exists locally, no need to wait on a network
round-trip just to show the person's name instead of Log In.
if (!userLoggedIn) {
updateNavForSession({ loggedIn true, firstName gate1CapturedFirstName, email savedEmail });
}
if (!GATE_STATUS_WORKER_URL GATE_STATUS_WORKER_URL.indexOf('REPLACE_WITH') === 0) return;
fetch(GATE_STATUS_WORKER_URL + 'email=' + encodeURIComponent(savedEmail))
.then(function(res) {
if (!res.ok) throw new Error('Gate status check failed ' + res.status);
return res.json();
})
.then(function(data) {
if (data.gate1Complete) {
gate1Unlocked = true;
applyListingGateState();
}
if (data.gate2Complete) {
gate2Unlocked = true;
}
If either gate isn't showing as complete yet, HubSpot may still be
indexing a just-submitted contact - retry a few times before
accepting the negative result.
if ((!data.gate1Complete !data.gate2Complete) && attemptsLeft 0) {
setTimeout(function() { checkGateStatusOnLoad(attemptsLeft - 1); }, 2500);
}
})
.catch(function(err) {
if (attemptsLeft 0) {
setTimeout(function() { checkGateStatusOnLoad(attemptsLeft - 1); }, 2500);
return;
}
console.warn('Gate status check failed, gates will show normally', err);
});
}
document.addEventListener('DOMContentLoaded', function() { checkGateStatusOnLoad(); });
function getHubspotUtk() {
var match = document.cookie.match((^;s)hubspotutk=([^;]+));
return match match[1] null;
}
function submitToHubspot(formGuid, fields, legalConsentOptions) {
if (!formGuid formGuid.indexOf('REPLACE_WITH') === 0) {
console.warn('HubSpot form GUID not set yet - skipping submission. Fields that would have been sent', fields);
return Promise.resolve();
}
var url = 'httpsapi-na3.hsforms.comsubmissionsv3integrationsubmit' + HUBSPOT_PORTAL_ID + '' + formGuid;
var payload = {
fields fields.map(function(f) { return { name f.name, value f.value }; }),
context {
pageUri window.location.href,
pageName document.title
}
};
if (legalConsentOptions) payload.legalConsentOptions = legalConsentOptions;
var utk = getHubspotUtk();
if (utk) payload.context.hutk = utk;
return fetch(url, {
method 'POST',
headers { 'Content-Type' 'applicationjson' },
body JSON.stringify(payload)
}).then(function(res) {
if (!res.ok) {
return res.json().then(function(err) {
console.error('HubSpot submission failed', res.status, err);
throw new Error('HubSpot submission failed ' + res.status);
});
}
}).catch(function(err) {
console.error('HubSpot submission error', err);
throw err;
});
}
------------------------------------------
var GATED_VALUE_IDS = ['ds-rent', 'ds-beds', 'ds-baths', 'ds-sqft', 'sb-rent', 'sb-price', 'sb-beds', 'sb-baths', 'sb-region', 'sb-mh-income'];
function applyListingGateState() {
var locked = !gate1Unlocked;
GATED_VALUE_IDS.forEach(function(id) {
var el = document.getElementById(id);
if (el) el.classList.toggle('gated-blur', locked);
});
document.querySelectorAll('.ps-val').forEach(function(el) {
el.classList.toggle('gated-blur', locked);
el.onclick = locked handleGatedValueClick null;
});
document.querySelectorAll('.amenity-text').forEach(function(el) {
el.classList.toggle('gated-blur', locked);
});
document.querySelectorAll('.detail-tab').forEach(function(tab, i) {
if (i === 0) return; Highlights always stays open
tab.classList.toggle('locked', locked);
});
}
function handleGatedValueClick() {
if (!gate1Unlocked) openGate1(function() { unlockListingDetail(); });
}
function unlockListingDetail() {
gate1Unlocked = true;
applyListingGateState();
}
function openGate1(callback) {
pendingGate1Callback = (typeof callback === 'function') callback null;
document.getElementById('gate1-overlay').classList.add('open');
}
function closeGate1() {
document.getElementById('gate1-overlay').classList.remove('open');
}
function handleGate1Submit(e) {
e.preventDefault();
var honeypot = document.getElementById('gate1-honeypot');
var isBot = honeypot && honeypot.value.trim().length 0;
var segmentInput = document.getElementById('gate1-segment');
var firstNameInput = document.getElementById('gate1-first-name');
var emailInput = document.getElementById('gate1-email');
var postalInput = document.getElementById('gate1-postal');
var consentInput = document.getElementById('gate1-consent');
var consentLabel = document.getElementById('gate1-consent-label');
var segmentValid = segmentInput.value.trim().length 0;
var firstNameValid = firstNameInput.value.trim().length 0;
var emailValid = emailInput.checkValidity() && emailInput.value.trim().length 0;
var postalValid = postalInput.value.trim().length 0;
var consentValid = consentInput.checked;
document.getElementById('gate1-segment-error').classList.toggle('show', !segmentValid);
segmentInput.classList.toggle('gate1-invalid', !segmentValid);
document.getElementById('gate1-first-name-error').classList.toggle('show', !firstNameValid);
firstNameInput.classList.toggle('gate1-invalid', !firstNameValid);
document.getElementById('gate1-email-error').classList.toggle('show', !emailValid);
emailInput.classList.toggle('gate1-invalid', !emailValid);
document.getElementById('gate1-postal-error').classList.toggle('show', !postalValid);
postalInput.classList.toggle('gate1-invalid', !postalValid);
document.getElementById('gate1-consent-error').classList.toggle('show', !consentValid);
consentLabel.classList.toggle('gate1-invalid', !consentValid);
if (!segmentValid !firstNameValid !emailValid !postalValid !consentValid) return;
gate1CapturedEmail = emailInput.value.trim();
gate1CapturedFirstName = firstNameInput.value.trim();
saveVisitorEmail(gate1CapturedEmail);
saveVisitorName(gate1CapturedFirstName);
var marketingInput = document.getElementById('gate1-marketing');
var marketingChecked = !!(marketingInput && marketingInput.checked);
if (!isBot) {
gate1SubmissionPromise = submitToHubspot(HUBSPOT_GATE1_FORM_GUID, [
{ name 'firstname', value firstNameInput.value.trim() },
{ name 'email', value emailInput.value.trim() },
{ name 'zip', value postalInput.value.trim() },
{ name 'igvhope_g1_pathway_type', value segmentInput.value },
{ name 'igvhope_portal_role', value 'Demand' }
], {
consent {
consentToProcess consentInput.checked,
text I consent to IGV Housing collecting, storing and using my personal information in accordance with the Privacy Policy.,
communications [
{
value consentInput.checked,
subscriptionTypeId HUBSPOT_SUBSCRIPTION_ACCOUNT_CREATION,
text I consent to IGV Housing collecting, storing and using my personal information in accordance with the Privacy Policy.
},
{
value marketingChecked,
subscriptionTypeId HUBSPOT_SUBSCRIPTION_IGVHOPE_MARKETING,
text I would like to receive marketing emails from IGVhope about new listings, releases and updates.
}
]
}
});
} else {
gate1SubmissionPromise = Promise.resolve();
console.warn('Gate 1 honeypot triggered - likely a bot submission, skipping HubSpot sync.');
}
closeGate1();
document.getElementById('gate1-form').reset();
document.querySelectorAll('.gate1-error').forEach(function(el) { el.classList.remove('show'); });
segmentInput.classList.remove('gate1-invalid');
firstNameInput.classList.remove('gate1-invalid');
emailInput.classList.remove('gate1-invalid');
postalInput.classList.remove('gate1-invalid');
consentLabel.classList.remove('gate1-invalid');
gate1Unlocked = true;
applyListingGateState();
if (!userLoggedIn) {
updateNavForSession({ loggedIn true, firstName gate1CapturedFirstName, email gate1CapturedEmail });
}
if (!gate1CreateAccountFlow) { openSessionSavedPopup(); }
gate1CreateAccountFlow = false;
if (pendingGate1Callback) pendingGate1Callback();
pendingGate1Callback = null;
}
var pendingGate2Callback = null;
var gate2SubmissionPromise = null;
var pendingGate3Callback = null;
var gate3Unlocked = false;
var gate3SubmissionPromise = null;
var gate2Unlocked = false;
var GATE2_REGION_PLACEHOLDERS = {
'Vancouver Island' { label 'Town or region', placeholder 'e.g. Ucluelet' },
'BC Mainland' { label 'City, town or region', placeholder 'e.g. Kelowna' },
'Another Canadian Province' { label 'City, town and province', placeholder 'e.g. Calgary, AB' },
'Outside Canada' { label 'Location and country', placeholder 'e.g. Seattle, USA' }
};
function gate2UpdateRegionField() {
var typeInput = document.getElementById('gate2-region-type');
var detailInput = document.getElementById('gate2-region-detail');
var config = GATE2_REGION_PLACEHOLDERS[typeInput.value];
if (config) detailInput.setAttribute('placeholder', config.placeholder);
}
function openGate2(callback) {
pendingGate2Callback = (typeof callback === 'function') callback null;
var hiddenEmail = document.getElementById('gate2-email-hidden');
if (hiddenEmail) hiddenEmail.value = gate1CapturedEmail;
document.getElementById('gate2-overlay').classList.add('open');
}
function closeGate2() {
document.getElementById('gate2-overlay').classList.remove('open');
}
function handleGate2Submit(e) {
e.preventDefault();
var honeypot2 = document.getElementById('gate2-honeypot');
var isBot2 = honeypot2 && honeypot2.value.trim().length 0;
var phoneInput = document.getElementById('gate2-phone');
var bedroomsInput = document.getElementById('gate2-bedrooms');
var regionTypeInput = document.getElementById('gate2-region-type');
var regionDetailInput = document.getElementById('gate2-region-detail');
var budgetInput = document.getElementById('gate2-budget');
var timelineInput = document.getElementById('gate2-timeline');
var consentInput = document.getElementById('gate2-consent');
var consentLabel = document.getElementById('gate2-consent-label');
var phoneValid = phoneInput.value.trim().length 0;
var bedroomsValid = bedroomsInput.value.trim().length 0;
var regionTypeValid = regionTypeInput.value.trim().length 0;
var regionDetailValid = regionDetailInput.value.trim().length 0;
var budgetValid = budgetInput.value.trim().length 0;
var timelineValid = timelineInput.value.trim().length 0;
var consentValid = consentInput.checked;
document.getElementById('gate2-phone-error').classList.toggle('show', !phoneValid);
phoneInput.classList.toggle('gate1-invalid', !phoneValid);
document.getElementById('gate2-bedrooms-error').classList.toggle('show', !bedroomsValid);
bedroomsInput.classList.toggle('gate1-invalid', !bedroomsValid);
document.getElementById('gate2-region-type-error').classList.toggle('show', !regionTypeValid);
regionTypeInput.classList.toggle('gate1-invalid', !regionTypeValid);
document.getElementById('gate2-region-detail-error').classList.toggle('show', !regionDetailValid);
regionDetailInput.classList.toggle('gate1-invalid', !regionDetailValid);
document.getElementById('gate2-budget-error').classList.toggle('show', !budgetValid);
budgetInput.classList.toggle('gate1-invalid', !budgetValid);
document.getElementById('gate2-timeline-error').classList.toggle('show', !timelineValid);
timelineInput.classList.toggle('gate1-invalid', !timelineValid);
document.getElementById('gate2-consent-error').classList.toggle('show', !consentValid);
consentLabel.classList.toggle('gate1-invalid', !consentValid);
if (!phoneValid !bedroomsValid !regionTypeValid !regionDetailValid !budgetValid !timelineValid !consentValid) return;
var hiddenEmailInput = document.getElementById('gate2-email-hidden');
var gate2Email = (hiddenEmailInput && hiddenEmailInput.value.trim()) gate1CapturedEmail '';
if (!gate2Email) {
console.error('Gate 2 submit no email available - this submission will not link to a contact record.');
}
if (!isBot2) {
gate2SubmissionPromise = submitToHubspot(HUBSPOT_GATE2_FORM_GUID, [
{ name 'email', value gate2Email },
{ name 'phone', value phoneInput.value.trim() },
{ name 'igvhope_g2__bedrooms_needed', value bedroomsInput.value },
{ name 'igvhope_g2_region_preference_type', value regionTypeInput.value },
{ name 'igvhope_g2_region_detail', value regionDetailInput.value.trim() },
{ name 'igvhope_g2_monthly_housing_budget', value budgetInput.value },
{ name 'igvhope__movein_timeline', value timelineInput.value },
{ name 'igvhope_g2_phone_communications_consent_optin', value consentInput.checked 'true' 'false' }
], {
consent {
consentToProcess true,
text I consent to IGV Housing collecting, storing and using my personal information in accordance with the Privacy Policy.,
communications [
{
value consentInput.checked,
subscriptionTypeId HUBSPOT_SUBSCRIPTION_PHONE_COMMS,
text I consent to phone communications from IGV Housing and can unsubscribe at any time.
}
]
}
});
} else {
gate2SubmissionPromise = Promise.resolve();
console.warn('Gate 2 honeypot triggered - likely a bot submission, skipping HubSpot sync.');
}
closeGate2();
document.getElementById('gate2-form').reset();
document.querySelectorAll('#gate2-form .gate1-error').forEach(function(el) { el.classList.remove('show'); });
phoneInput.classList.remove('gate1-invalid');
bedroomsInput.classList.remove('gate1-invalid');
regionTypeInput.classList.remove('gate1-invalid');
regionDetailInput.classList.remove('gate1-invalid');
budgetInput.classList.remove('gate1-invalid');
timelineInput.classList.remove('gate1-invalid');
consentLabel.classList.remove('gate1-invalid');
regionDetailInput.setAttribute('placeholder', 'Town or region');
gate2Unlocked = true;
if (pendingGate2Callback) pendingGate2Callback();
pendingGate2Callback = null;
}
function openGate3(callback) {
pendingGate3Callback = (typeof callback === 'function') callback null;
var hiddenEmail = document.getElementById('gate3-email-hidden');
if (hiddenEmail) hiddenEmail.value = gate1CapturedEmail;
document.getElementById('gate3-overlay').classList.add('open');
}
function closeGate3() {
document.getElementById('gate3-overlay').classList.remove('open');
}
function handleGate3Submit(e) {
e.preventDefault();
var honeypot3 = document.getElementById('gate3-honeypot');
var isBot3 = honeypot3 && honeypot3.value.trim().length 0;
var residencyInput = document.getElementById('gate3-residency');
var individualIncomeInput = document.getElementById('gate3-individual-income');
var householdIncomeInput = document.getElementById('gate3-household-income');
var debtInput = document.getElementById('gate3-debt');
var workStabilityInput = document.getElementById('gate3-work-stability');
var lastNameInput = document.getElementById('gate3-last-name');
var residencyValid = residencyInput.value.trim().length 0;
var individualIncomeValid = individualIncomeInput.value.trim().length 0;
var householdIncomeValid = householdIncomeInput.value.trim().length 0;
var debtValid = debtInput.value.trim().length 0;
var workStabilityValid = workStabilityInput.value.trim().length 0;
var lastNameValid = lastNameInput.value.trim().length 0;
document.getElementById('gate3-residency-error').classList.toggle('show', !residencyValid);
residencyInput.classList.toggle('gate1-invalid', !residencyValid);
document.getElementById('gate3-individual-income-error').classList.toggle('show', !individualIncomeValid);
individualIncomeInput.classList.toggle('gate1-invalid', !individualIncomeValid);
document.getElementById('gate3-household-income-error').classList.toggle('show', !householdIncomeValid);
householdIncomeInput.classList.toggle('gate1-invalid', !householdIncomeValid);
document.getElementById('gate3-debt-error').classList.toggle('show', !debtValid);
debtInput.classList.toggle('gate1-invalid', !debtValid);
document.getElementById('gate3-work-stability-error').classList.toggle('show', !workStabilityValid);
workStabilityInput.classList.toggle('gate1-invalid', !workStabilityValid);
document.getElementById('gate3-last-name-error').classList.toggle('show', !lastNameValid);
lastNameInput.classList.toggle('gate1-invalid', !lastNameValid);
if (!residencyValid !individualIncomeValid !householdIncomeValid !debtValid !workStabilityValid !lastNameValid) return;
var hiddenEmailInput3 = document.getElementById('gate3-email-hidden');
if (!isBot3) {
gate3SubmissionPromise = submitToHubspot(HUBSPOT_GATE3_FORM_GUID, [
{ name 'email', value (hiddenEmailInput3 hiddenEmailInput3.value gate1CapturedEmail) },
{ name 'lastname', value lastNameInput.value.trim() },
{ name 'igvhope_g3_residency_status', value residencyInput.value },
{ name 'igvhope_g3_individual_income', value individualIncomeInput.value },
{ name 'igvhope_g3_household_income', value householdIncomeInput.value },
{ name 'igvhope_g3_debt_situation', value debtInput.value },
{ name 'igvhope_g3_work_stability', value workStabilityInput.value }
]);
} else {
gate3SubmissionPromise = Promise.resolve();
console.warn('Gate 3 honeypot triggered - likely a bot submission, skipping HubSpot sync.');
}
closeGate3();
document.getElementById('gate3-form').reset();
document.querySelectorAll('#gate3-form .gate1-error').forEach(function(el) { el.classList.remove('show'); });
residencyInput.classList.remove('gate1-invalid');
individualIncomeInput.classList.remove('gate1-invalid');
householdIncomeInput.classList.remove('gate1-invalid');
debtInput.classList.remove('gate1-invalid');
workStabilityInput.classList.remove('gate1-invalid');
lastNameInput.classList.remove('gate1-invalid');
gate3Unlocked = true;
if (pendingGate3Callback) pendingGate3Callback();
pendingGate3Callback = null;
}
var MAGIC_LINK_WORKER_URL = 'httpsmagic-link.igvhousing.workers.dev';
var NOTIFICATIONS_WORKER_URL = 'httpsnotificiations.igvhousing.workers.dev';
var PENDING_SAVE_KEY = 'igvhope_pending_save';
function getListingIdFromSaveButton(btn) {
var card = btn.closest('.listing-card');
if (card) {
var titleEl = card.querySelector('.card-title');
return titleEl titleEl.textContent.trim() null;
}
var navTitle = document.getElementById('detail-nav-title');
return navTitle navTitle.textContent.trim() null;
}
function handleSaveClick(btn) {
var listingId = getListingIdFromSaveButton(btn);
if (!listingId) return;
btn.disabled = true;
fetch(MAGIC_LINK_WORKER_URL + 'session', { credentials 'include' })
.then(function(res) { return res.json(); })
.then(function(session) {
btn.disabled = false;
if (session.loggedIn) {
performToggleSave(btn, listingId);
} else {
openSaveLogin(listingId);
}
})
.catch(function() {
btn.disabled = false;
openSaveLogin(listingId);
});
}
function performToggleSave(btn, listingId) {
fetch(MAGIC_LINK_WORKER_URL + 'toggle-saved-listing', {
method 'POST',
credentials 'include',
headers { 'Content-Type' 'applicationjson' },
body JSON.stringify({ listingId listingId })
})
.then(function(res) { return res.json(); })
.then(function(data) {
btn.classList.toggle('saved', !!data.saved);
})
.catch(function() {
console.error('Saving this listing failed. Please try again.');
});
}
function openSaveLogin(listingId) {
try { localStorage.setItem(PENDING_SAVE_KEY, listingId); } catch (e) {}
document.getElementById('save-login-choices').style.display = 'flex';
document.getElementById('save-login-sent').style.display = 'none';
document.getElementById('save-login-overlay').classList.add('open');
}
function handleSaveLoginGoToLogin() {
pendingId is already saved to localStorage by openSaveLogin(); once the
person logs in on the platform login page and returns, the existing
checkSessionAndSavedListingsOnLoad() flow completes the pending save.
window.location.href = 'httpsplatform.igvhousing.com';
}
function requestMagicLinkWithRetry(email, attemptsLeft) {
return fetch(MAGIC_LINK_WORKER_URL + 'request-login', {
method 'POST',
headers { 'Content-Type' 'applicationjson' },
body JSON.stringify({ email email })
})
.then(function(res) { return res.json().catch(function() { return {}; }).then(function(data) { return { ok res.ok, data data }; }); })
.then(function(result) {
var failed = !result.ok result.data.error result.data.status === 'error' result.data.found === false;
if (failed && attemptsLeft 0) {
return new Promise(function(resolve) { setTimeout(resolve, 2000); })
.then(function() { return requestMagicLinkWithRetry(email, attemptsLeft - 1); });
}
return result;
})
.catch(function(err) {
if (attemptsLeft 0) {
return new Promise(function(resolve) { setTimeout(resolve, 2000); })
.then(function() { return requestMagicLinkWithRetry(email, attemptsLeft - 1); });
}
console.error('Magic link request failed after retries', err);
return { ok false };
});
}
function handleSaveLoginCreateAccount() {
var listingId;
try { listingId = localStorage.getItem(PENDING_SAVE_KEY); } catch (e) { listingId = null; }
closeSaveLogin();
gate1CreateAccountFlow = true;
openGate1(function() {
Gate 1 just completed - immediately open Gate 2 back-to-back so the
Create an account path captures full info in one continuous flow.
openGate2(function() {
var email = gate1CapturedEmail;
if (listingId) {
try { localStorage.setItem(PENDING_SAVE_KEY, listingId); } catch (e) {}
}
document.getElementById('save-login-choices').style.display = 'none';
document.getElementById('save-login-sent').style.display = 'block';
document.getElementById('save-login-overlay').classList.add('open');
Wait for both HubSpot submissions to actually finish, plus a short
buffer for HubSpot to finish indexing, before asking the magic-link
Worker to look the contact up - otherwise the lookup can run before
the contactupdates exist and silently fail.
var gate1Done = gate1SubmissionPromise Promise.resolve();
var gate2Done = gate2SubmissionPromise Promise.resolve();
Promise.all([gate1Done.catch(function() {}), gate2Done.catch(function() {})]).then(function() {
setTimeout(function() {
requestMagicLinkWithRetry(email, 3);
}, 2500);
});
});
});
}
function closeSaveLogin() {
document.getElementById('save-login-overlay').classList.remove('open');
}
function openSessionSavedPopup() {
document.getElementById('session-saved-overlay').classList.add('open');
}
function closeSessionSavedPopup() {
document.getElementById('session-saved-overlay').classList.remove('open');
}
function resendSessionSavedEmail() {
var resendEl = document.getElementById('session-saved-resend');
if (resendEl) resendEl.innerHTML = 'Sending...';
requestMagicLinkWithRetry(gate1CapturedEmail, 2).then(function() {
if (resendEl) resendEl.innerHTML = 'Email sent. Check your inbox.';
});
}
var SUBSCRIPTION_STATUS_WORKER_URL = 'httpsconsent-tracker.igvhousing.workers.dev';
function handleNewReleasesBannerClick() {
if (!userLoggedIn) {
openGate1();
return;
}
if (!gate1CapturedEmail !SUBSCRIPTION_STATUS_WORKER_URL SUBSCRIPTION_STATUS_WORKER_URL.indexOf('REPLACE_WITH') === 0) {
openGate1();
return;
}
fetch(SUBSCRIPTION_STATUS_WORKER_URL + 'check', {
method 'POST',
headers { 'Content-Type' 'applicationjson' },
body JSON.stringify({ email gate1CapturedEmail })
})
.then(function(res) { return res.json(); })
.then(function(data) {
if (data.subscribed) {
openAlreadySubscribed();
} else {
openSubscribePrompt();
}
})
.catch(function(err) {
console.warn('Subscription status check failed', err);
openSubscribePrompt();
});
}
function openSubscribePrompt() {
document.getElementById('subscribe-prompt-overlay').classList.add('open');
}
function closeSubscribePrompt() {
document.getElementById('subscribe-prompt-overlay').classList.remove('open');
}
function openAlreadySubscribed(justSubscribed) {
var titleEl = document.getElementById('already-subscribed-title');
var subEl = document.getElementById('already-subscribed-sub');
if (justSubscribed) {
if (titleEl) titleEl.textContent = You're subscribed!;
if (subEl) subEl.textContent = Thanks for signing up. We'll email you the moment new IGVhope homes become available.;
} else {
if (titleEl) titleEl.textContent = You're already on the list;
if (subEl) subEl.textContent = You're subscribed to release updates, so we'll email you the moment new IGVhope homes become available.;
}
document.getElementById('already-subscribed-overlay').classList.add('open');
}
function closeAlreadySubscribed() {
document.getElementById('already-subscribed-overlay').classList.remove('open');
}
function handleSubscribeConfirm() {
var btn = document.getElementById('subscribe-prompt-btn');
if (btn) { btn.textContent = 'Subscribing...'; btn.disabled = true; }
fetch(SUBSCRIPTION_STATUS_WORKER_URL + 'subscribe', {
method 'POST',
headers { 'Content-Type' 'applicationjson' },
body JSON.stringify({ email gate1CapturedEmail })
})
.then(function(res) {
return res.json().then(function(data) {
if (!res.ok !data.success) {
console.error('Subscribe request did not succeed', res.status, data);
throw new Error(data.error ('Subscribe failed with status ' + res.status));
}
return data;
});
})
.then(function() {
closeSubscribePrompt();
openAlreadySubscribed(true);
})
.catch(function(err) {
console.warn('Subscribe request failed', err);
if (btn) { btn.textContent = 'Something went wrong - try again'; btn.disabled = false; }
});
}
function markSavedListingCards(savedListings) {
if (!savedListings !savedListings.length) return;
document.querySelectorAll('.listing-card').forEach(function(card) {
var titleEl = card.querySelector('.card-title');
if (!titleEl) return;
var title = titleEl.textContent.trim();
if (savedListings.indexOf(title) !== -1) {
var saveBtn = card.querySelector('.card-save-btn');
if (saveBtn) saveBtn.classList.add('saved');
}
});
}
function updateNavForSession(session) {
userLoggedIn = !!(session && session.loggedIn);
var loginDesktop = document.getElementById('nav-login-desktop');
var accountAreaDesktop = document.getElementById('nav-account-area');
var loginMobile = document.getElementById('nav-login-mobile');
var accountAreaMobile = document.getElementById('nav-account-area-mobile');
if (session && session.loggedIn) {
var displayName = session.firstName (session.email session.email.split('@')[0] 'Member');
var initial = displayName.charAt(0).toUpperCase();
if (loginDesktop) loginDesktop.style.display = 'none';
if (accountAreaDesktop) accountAreaDesktop.style.display = 'flex';
var avatarEl = document.getElementById('nav-user-avatar');
var labelEl = document.getElementById('nav-user-label');
var headerNameEl = document.getElementById('dropdown-header-name');
if (avatarEl) avatarEl.textContent = initial;
if (labelEl) labelEl.textContent = displayName;
if (headerNameEl) headerNameEl.textContent = displayName;
if (loginMobile) loginMobile.style.display = 'none';
if (accountAreaMobile) accountAreaMobile.style.display = 'flex';
var mobileNameEl = document.getElementById('mobile-nav-account-name');
if (mobileNameEl) mobileNameEl.textContent = displayName;
} else {
if (loginDesktop) loginDesktop.style.display = '';
if (accountAreaDesktop) accountAreaDesktop.style.display = 'none';
if (loginMobile) loginMobile.style.display = '';
if (accountAreaMobile) accountAreaMobile.style.display = 'none';
}
}
function toggleProfileDropdown(event) {
event.stopPropagation();
document.getElementById('profile-dropdown').classList.toggle('open');
}
document.addEventListener('click', function(event) {
var dropdown = document.getElementById('profile-dropdown');
if (dropdown && dropdown.classList.contains('open') && !event.target.closest('.nav-user')) {
dropdown.classList.remove('open');
}
});
function handleNavLogout(event) {
if (event) event.preventDefault();
function completeClientLogout() {
updateNavForSession({ loggedIn false });
document.querySelectorAll('.card-save-btn.saved').forEach(function(btn) { btn.classList.remove('saved'); });
updateNavBellBadge(0);
accountDataCache = null;
accountDataLoaded = false;
gate1Unlocked = false;
gate1CapturedEmail = '';
gate1CapturedFirstName = '';
try { localStorage.removeItem(GATE_VISITOR_EMAIL_KEY); } catch (e) {}
try { localStorage.removeItem(GATE_VISITOR_NAME_KEY); } catch (e) {}
try { localStorage.removeItem(PENDING_SAVE_KEY); } catch (e) {}
if (document.getElementById('account-view').classList.contains('open')) {
closeAccountView();
}
}
fetch(MAGIC_LINK_WORKER_URL + 'logout', { method 'POST', credentials 'include' })
.then(completeClientLogout)
.catch(function(err) {
console.warn('Logout request failed, logging out client-side anyway', err);
completeClientLogout();
});
}
---------- Account View ----------
var ACCOUNT_TABS = ['applications', 'saved', 'notifications'];
var accountDataLoaded = false;
var accountDataCache = null;
TODO once the Applications pipeline's real stage internal IDs are
confirmed in HubSpot, map them here for exact labelscolors. Until then,
friendlyStageLabel() falls back to a readable version of whatever value
HubSpot returns (e.g. application_received - Application Received).
var DEAL_STAGE_LABELS = {
'3423815623' 'Application Received',
'3423815624' 'Under Review',
'3423815625' 'Additional Info Needed',
'3423815626' 'Approved',
'3423815627' 'Declined',
'3423815628' 'Withdrawn'
};
function openAccountView(tab) {
var wipe = document.getElementById('detail-colour-wipe');
wipe.classList.remove('reveal');
wipe.classList.add('active');
setTimeout(function() {
document.getElementById('account-view').classList.add('open');
switchAccountTab(tab 'applications');
loadAccountData(false);
setTimeout(function() {
wipe.classList.add('reveal');
}, 50);
}, 350);
}
function closeAccountView() {
var wipe = document.getElementById('detail-colour-wipe');
wipe.classList.remove('reveal');
wipe.classList.add('active');
setTimeout(function() {
document.getElementById('account-view').classList.remove('open');
try { history.replaceState(null, '', window.location.pathname + window.location.search); } catch (e) {}
setTimeout(function() {
wipe.classList.add('reveal');
setTimeout(function() {
wipe.classList.remove('active');
wipe.classList.remove('reveal');
}, 350);
}, 50);
}, 350);
}
function switchAccountTab(tab) {
if (ACCOUNT_TABS.indexOf(tab) === -1) tab = 'applications';
document.querySelectorAll('.account-tab').forEach(function(btn) {
btn.classList.toggle('active', btn.getAttribute('data-tab') === tab);
});
document.querySelectorAll('.account-panel').forEach(function(panel) {
panel.classList.toggle('active', panel.id === 'account-panel-' + tab);
});
try { history.replaceState(null, '', '#account-' + tab); } catch (e) {}
}
function loadAccountData(force) {
if (accountDataLoaded && !force) { renderAccountData(accountDataCache); return; }
setAccountLoading(true);
fetch(MAGIC_LINK_WORKER_URL + 'my-account', { credentials 'include' })
.then(function(res) {
if (!res.ok) throw new Error('Account request failed ' + res.status);
return res.json();
})
.then(function(data) {
accountDataCache = data;
accountDataLoaded = true;
renderAccountData(data);
setAccountLoading(false);
})
.catch(function(err) {
console.error('Failed to load account data', err);
renderAccountError();
setAccountLoading(false);
});
}
function setAccountLoading(isLoading) {
var el = document.getElementById('account-loading');
if (el) el.style.display = isLoading 'flex' 'none';
}
function renderAccountError() {
var msg = accountEmptyStateHtml('Something went wrong', We couldn't load your account details. Please refresh and try again.);
document.getElementById('account-panel-applications').innerHTML = msg;
document.getElementById('account-panel-saved').innerHTML = '';
document.getElementById('account-panel-notifications').innerHTML = '';
}
function accountEmptyStateHtml(title, sub) {
return 'div class=account-empty-state' +
'div class=account-empty-title' + escapeHtml(title) + 'div' +
'div class=account-empty-sub' + escapeHtml(sub) + 'div' +
'div';
}
function friendlyStageLabel(stage) {
if (!stage) return 'In Review';
if (DEAL_STAGE_LABELS[stage]) return DEAL_STAGE_LABELS[stage];
return String(stage).replace([_-]+g, ' ').replace(bwg, function(c) { return c.toUpperCase(); });
}
function stagePillClass(label) {
var l = label.toLowerCase();
if (l.indexOf('approved') !== -1) return 'stage-approved';
if (l.indexOf('declin') !== -1) return 'stage-declined';
if (l.indexOf('withdraw') !== -1) return 'stage-withdrawn';
return 'stage-progress';
}
function extractListingNameFromDeal(app) {
if (app.listingAddress) return app.listingAddress;
if (app.name && app.name.indexOf('u2014') !== -1) {
return app.name.split('u2014').slice(1).join('u2014').trim();
}
return app.name 'Application';
}
function formatAccountDate(iso) {
if (!iso) return '';
var d = new Date(iso);
if (isNaN(d.getTime())) return '';
return d.toLocaleDateString('en-CA', { year 'numeric', month 'long', day 'numeric' });
}
function renderAccountData(data) {
renderApplications(data.applications []);
renderSavedListingsPanel(data.savedListings []);
renderNotifications();
}
var CELEBRATED_DEALS_KEY = 'igvhope_celebrated_deals';
function getCelebratedDealIds() {
try {
var raw = localStorage.getItem(CELEBRATED_DEALS_KEY);
return raw raw.split(',').filter(Boolean) [];
} catch (e) {
return [];
}
}
function markDealsCelebrated(ids) {
try {
var existing = getCelebratedDealIds();
var merged = existing.concat(ids.filter(function(id) { return existing.indexOf(id) === -1; }));
localStorage.setItem(CELEBRATED_DEALS_KEY, merged.join(','));
} catch (e) {}
}
function renderApplications(applications) {
var panel = document.getElementById('account-panel-applications');
if (!applications.length) {
panel.innerHTML = accountEmptyStateHtml('No applications yet', When you apply to a home, you'll see its status here.);
return;
}
var celebrated = getCelebratedDealIds();
var newlyApprovedIds = [];
panel.innerHTML = applications.map(function(app) {
var listingName = extractListingNameFromDeal(app);
var label = friendlyStageLabel(app.stage);
var pillClass = stagePillClass(label);
var dateStr = formatAccountDate(app.createdAt);
if (pillClass === 'stage-approved' && celebrated.indexOf(String(app.id)) === -1) {
newlyApprovedIds.push(String(app.id));
}
return 'div class=app-card' +
'div class=app-card-main' +
'div class=app-card-title' + escapeHtml(listingName) + 'div' +
(dateStr 'div class=app-card-dateApplied ' + escapeHtml(dateStr) + 'div' '') +
'div' +
'div class=stage-pill ' + pillClass + '' + escapeHtml(label) + 'div' +
'div';
}).join('');
if (newlyApprovedIds.length) {
triggerApprovalFireworks();
markDealsCelebrated(newlyApprovedIds);
}
}
function findListingCardByTitle(title) {
var match = null;
document.querySelectorAll('.listing-card').forEach(function(card) {
var t = card.querySelector('.card-title');
if (t && t.textContent.trim() === title) match = card;
});
return match;
}
function renderSavedListingsPanel(savedListings) {
var panel = document.getElementById('account-panel-saved');
if (!savedListings.length) {
panel.innerHTML = accountEmptyStateHtml('No saved homes yet', 'Tap the heart on any listing to save it here for later.');
return;
}
panel.innerHTML = savedListings.map(function(title) {
var card = findListingCardByTitle(title);
if (!card) {
return 'div class=saved-account-card saved-account-card-missing' +
'div class=saved-account-body' +
'div class=saved-account-title' + escapeHtml(title) + 'div' +
'div class=saved-account-missing-noteThis listing is no longer available.div' +
'div class=saved-account-actionsbutton class=saved-account-remove onclick=handleUnsaveFromAccount('' + escapeJs(title) + '')Removebuttondiv' +
'div' +
'div';
}
var d = getListingData(card);
var imgStyle = d.imgUrl background-imageurl(' + d.imgUrl + ');background-sizecover;background-positioncenter; background + d.gradient + ;;
return 'div class=saved-account-card' +
'div class=saved-account-img style=' + imgStyle + 'div' +
'div class=saved-account-body' +
'div class=saved-account-title' + escapeHtml(d.title) + 'div' +
'div class=saved-account-meta' + escapeHtml(d.location) + 'div' +
'div class=saved-account-price' + escapeHtml(d.rent) + 'div' +
'div class=saved-account-actions' +
'button class=saved-account-view onclick=openListingDetail(findListingCardByTitle('' + escapeJs(title) + ''));closeAccountView();View homebutton' +
'button class=saved-account-remove onclick=handleUnsaveFromAccount('' + escapeJs(title) + '')Removebutton' +
'div' +
'div' +
'div';
}).join('');
}
function renderNotifications() {
var panel = document.getElementById('account-panel-notifications');
panel.innerHTML = accountEmptyStateHtml('Loading...', '');
loadNotifications(function(data) {
if (!data !data.notifications !data.notifications.length) {
panel.innerHTML = accountEmptyStateHtml(You're all caught up, You'll see updates about your applications and saved homes here.);
return;
}
var hasNewApproval = data.notifications.some(function(n) {
return !n.read && stagePillClass(friendlyStageLabel(n.stage)) === 'stage-approved';
});
panel.innerHTML = data.notifications.map(function(n) {
return 'div class=notification-card' + (n.read '' ' notification-unread') + ' onclick=handleNotificationClick('' + escapeJs(n.id) + '')' +
'div class=notification-dotdiv' +
'div class=notification-body' +
'div class=notification-message' + escapeHtml(n.message) + 'div' +
'div class=notification-date' + escapeHtml(formatAccountDate(n.createdAt)) + 'div' +
'div' +
'div';
}).join('');
if (hasNewApproval) triggerApprovalFireworks();
Opening the Notifications tab marks everything as read
markNotificationsRead(true, null);
});
}
function getNotificationEmail() {
return gate1CapturedEmail getSavedVisitorEmail() '';
}
function loadNotifications(callback) {
var email = getNotificationEmail();
if (!email !NOTIFICATIONS_WORKER_URL NOTIFICATIONS_WORKER_URL.indexOf('REPLACE_WITH') === 0) {
callback(null);
return;
}
fetch(NOTIFICATIONS_WORKER_URL + 'notificationsemail=' + encodeURIComponent(email))
.then(function(res) {
if (!res.ok) throw new Error('Notifications fetch failed ' + res.status);
return res.json();
})
.then(function(data) {
updateNavBellBadge(data.unreadCount 0);
callback(data);
})
.catch(function(err) {
console.warn('Failed to load notifications', err);
callback(null);
});
}
var NAV_BELL_ICON_OUTLINE = 'svg width=18 height=18 viewBox=0 0 24 24 fill=none stroke=rgba(255,255,255,0.75) stroke-width=2 stroke-linecap=round stroke-linejoin=roundpath d=M18 8A6 6 0 0 0 6 8c0 7-3 9-3 9h18s-3-2-3-9path d=M13.73 21a2 2 0 0 1-3.46 0svg';
var NAV_BELL_ICON_FILLED = 'svg width=18 height=18 viewBox=0 0 24 24 fill=#da8d27 stroke=#da8d27 stroke-width=0.5 stroke-linejoin=roundpath d=M12 2C10.34 2 9 3.34 9 5v.29C6.11 6.11 4 8.76 4 12v5l-1.29 1.29A1 1 0 0 0 3.41 20H20.6a1 1 0 0 0 .7-1.71L20 17v-5c0-3.24-2.11-5.89-5-6.71V5c0-1.66-1.34-3-3-3zpath d=M9.5 21a2.5 2.5 0 0 0 5 0h-5zsvg';
function updateNavBellBadge(count) {
var badges = document.querySelectorAll('#nav-bell-count');
badges.forEach(function(el) {
el.textContent = count 0 String(count) '';
});
var icons = document.querySelectorAll('#nav-bell-icon');
icons.forEach(function(el) {
el.innerHTML = count 0 NAV_BELL_ICON_FILLED NAV_BELL_ICON_OUTLINE;
});
}
function markNotificationsRead(all, id) {
var email = getNotificationEmail();
if (!email !NOTIFICATIONS_WORKER_URL NOTIFICATIONS_WORKER_URL.indexOf('REPLACE_WITH') === 0) return;
fetch(NOTIFICATIONS_WORKER_URL + 'notificationsmark-read', {
method 'POST',
headers { 'Content-Type' 'applicationjson' },
body JSON.stringify(all { email email, all true } { email email, id id })
})
.then(function(res) { return res.json(); })
.then(function(data) { updateNavBellBadge(data.unreadCount 0); })
.catch(function() {});
}
function handleNotificationClick(id) {
markNotificationsRead(false, id);
document.querySelectorAll('.notification-card').forEach(function(el) {
if (el.getAttribute('onclick') && el.getAttribute('onclick').indexOf(id) !== -1) {
el.classList.remove('notification-unread');
}
});
}
function handleNavBellClick() {
openAccountView('notifications');
}
function triggerApprovalFireworks() {
var canvas = document.getElementById('fireworks-canvas');
if (!canvas) return;
var dpr = window.devicePixelRatio 1;
canvas.width = window.innerWidth dpr;
canvas.height = window.innerHeight dpr;
canvas.style.width = window.innerWidth + 'px';
canvas.style.height = window.innerHeight + 'px';
canvas.style.display = 'block';
var ctx = canvas.getContext('2d');
ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
var colors = ['#da8d27', '#C8683A', '#1A5C50', '#2B6B5A', '#ffffff'];
var particles = [];
function spawnBurst(x, y) {
var count = 46;
for (var i = 0; i count; i++) {
var angle = (Math.PI 2 i) count + Math.random() 0.2;
var speed = 2.5 + Math.random() 3.5;
particles.push({
x x,
y y,
vx Math.cos(angle) speed,
vy Math.sin(angle) speed,
alpha 1,
color colors[Math.floor(Math.random() colors.length)],
size 2 + Math.random() 2.2
});
}
}
var w = window.innerWidth;
var h = window.innerHeight;
[
{ delay 0, x w 0.3, y h 0.32 },
{ delay 350, x w 0.7, y h 0.25 },
{ delay 700, x w 0.5, y h 0.4 }
].forEach(function(burst) {
setTimeout(function() { spawnBurst(burst.x, burst.y); }, burst.delay);
});
var startTime = Date.now();
function animate() {
ctx.clearRect(0, 0, w, h);
particles.forEach(function(p) {
p.x += p.vx;
p.y += p.vy;
p.vy += 0.045;
p.alpha -= 0.011;
ctx.globalAlpha = Math.max(p.alpha, 0);
ctx.fillStyle = p.color;
ctx.beginPath();
ctx.arc(p.x, p.y, p.size, 0, Math.PI 2);
ctx.fill();
});
particles = particles.filter(function(p) { return p.alpha 0; });
ctx.globalAlpha = 1;
if (Date.now() - startTime 3200 particles.length 0) {
requestAnimationFrame(animate);
} else {
canvas.style.display = 'none';
}
}
requestAnimationFrame(animate);
}
function handleUnsaveFromAccount(title) {
fetch(MAGIC_LINK_WORKER_URL + 'toggle-saved-listing', {
method 'POST',
credentials 'include',
headers { 'Content-Type' 'applicationjson' },
body JSON.stringify({ listingId title })
})
.then(function(res) { return res.json(); })
.then(function(data) {
var card = findListingCardByTitle(title);
if (card) {
var saveBtn = card.querySelector('.card-save-btn');
if (saveBtn) saveBtn.classList.remove('saved');
}
if (accountDataCache) accountDataCache.savedListings = data.savedListings [];
renderSavedListingsPanel(data.savedListings []);
})
.catch(function() {});
}
function escapeHtml(str) {
return String(str).replace([&']g, function(c) {
return { '&' '&', '' '<', '' '>', '' '"', ' ''' }[c];
});
}
function escapeJs(str) {
return String(str).replace(g, '').replace('g, ');
}
document.addEventListener('DOMContentLoaded', function() {
sortListings('rent-asc');
});
document.addEventListener('DOMContentLoaded', function() {
var hash = window.location.hash.replace('#', '');
if (hash.indexOf('account-') === 0) {
var tab = hash.replace('account-', '');
if (ACCOUNT_TABS.indexOf(tab) !== -1) openAccountView(tab);
}
});
function checkSessionAndSavedListingsOnLoad() {
var pendingId;
try { pendingId = localStorage.getItem(PENDING_SAVE_KEY); } catch (e) { pendingId = null; }
fetch(MAGIC_LINK_WORKER_URL + 'session', { credentials 'include' })
.then(function(res) { return res.json(); })
.then(function(session) {
if (session.loggedIn !getSavedVisitorEmail()) {
updateNavForSession(session);
}
if (!session.loggedIn) return;
A valid authenticated session only exists because this person already
completed Gate 1 (and Gate 2, via the create-account flow) when the
account was created - unlock gated content immediately rather than
making a returning, logged-in visitor fill those forms again.
gate1Unlocked = true;
gate2Unlocked = true;
if (session.email) {
gate1CapturedEmail = session.email;
saveVisitorEmail(session.email);
}
if (session.firstName) {
gate1CapturedFirstName = session.firstName;
saveVisitorName(session.firstName);
}
applyListingGateState();
if (pendingId) {
fetch(MAGIC_LINK_WORKER_URL + 'toggle-saved-listing', {
method 'POST',
credentials 'include',
headers { 'Content-Type' 'applicationjson' },
body JSON.stringify({ listingId pendingId })
})
.then(function(res) { return res.json(); })
.then(function(data) {
try { localStorage.removeItem(PENDING_SAVE_KEY); } catch (e) {}
markSavedListingCards(data.savedListings [pendingId]);
})
.catch(function() {});
} else {
fetch(MAGIC_LINK_WORKER_URL + 'my-account', { credentials 'include' })
.then(function(res) { return res.json(); })
.then(function(data) {
markSavedListingCards(data.savedListings);
if (data.email) {
gate1CapturedEmail = data.email;
loadNotifications(function() {});
}
})
.catch(function() {});
}
})
.catch(function() {});
}
document.addEventListener('DOMContentLoaded', checkSessionAndSavedListingsOnLoad);
function updateTabsFade() {
var tabs = document.getElementById('detail-tabs');
var leftFade = document.getElementById('detail-tabs-fade-left');
var rightFade = document.getElementById('detail-tabs-fade-right');
if (!tabs !leftFade !rightFade) return;
var atStart = tabs.scrollLeft = 2;
var atEnd = tabs.scrollLeft + tabs.clientWidth = tabs.scrollWidth - 2;
leftFade.classList.toggle('show', !atStart);
rightFade.classList.toggle('show', !atEnd);
}
window.addEventListener('resize', updateTabsFade);
function playHeroVideo() {
var container = document.getElementById('dash-hero-video');
if (!container) return;
container.innerHTML = 'iframe src=httpsplayer.vimeo.comvideo1209697255autoplay=1&title=0&byline=0&portrait=0 title=What IGVhope Means For Your Future frameborder=0 allow=accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share allowfullscreen style=positionabsolute; inset0; width100%; height100%; border-radius14px;iframe';
container.removeAttribute('onclick');
container.style.cursor = 'default';
container.style.backgroundImage = 'none';
}
function playNeighbourhoodVideo() {
var url = window._nbPendingVideoUrl;
if (!url) return;
var videoFrame = document.getElementById('nb-video-frame');
var videoNative = document.getElementById('nb-video-native');
var videoFacade = document.getElementById('nb-video-facade');
if (!videoFrame !videoNative !videoFacade) return;
videoFacade.style.display = 'none';
if (url.indexOf('.m3u8') !== -1) {
Raw HLS stream - needs HLS.js (or native support in Safari), not an iframe
videoNative.style.display = 'block';
if (videoNative.canPlayType('applicationvnd.apple.mpegurl')) {
videoNative.src = url;
} else if (window.Hls && Hls.isSupported()) {
var hls = new Hls();
hls.loadSource(url);
hls.attachMedia(videoNative);
window._nbHlsInstance = hls;
}
videoNative.play();
} else {
videoFrame.style.display = 'block';
var autoplayUrl = url + (url.indexOf('') !== -1 '&' '') + 'autoplay=1&rel=0';
videoFrame.setAttribute('src', autoplayUrl);
}
}
function scrollToListings() {
var target = document.getElementById('dash-scroll-inner');
var container = document.getElementById('dash-scroll');
var banner = document.getElementById('promo-banner');
if (!target !container) return;
var bannerOffset = (banner && banner.offsetParent !== null) banner.offsetHeight 0;
var targetTop = target.getBoundingClientRect().top - container.getBoundingClientRect().top + container.scrollTop;
container.scrollTo({ top Math.max(0, targetTop - bannerOffset), behavior 'smooth' });
}
function handleViewAllHomesClick() {
if (userLoggedIn) {
window.location.reload();
return;
}
openGate1(function() { loadMoreListings(document.getElementById('dash-load-more-btn')); });
}
function loadMoreListings(btn) {
var totalPages = 3;
var originalText = 'View All Homes';
btn.disabled = true;
btn.textContent = 'Loading...';
setTimeout(function() {
loadMorePage++;
document.querySelectorAll('.dash-page-dot').forEach(function(d, i) {
d.classList.toggle('active', i === loadMorePage - 1);
});
if (loadMorePage = totalPages) {
btn.textContent = You've seen all current listings;
btn.disabled = true;
} else {
btn.textContent = originalText;
btn.disabled = false;
}
}, 600);
}
function toggleFilter(el) {
document.querySelectorAll('.filter-chip').forEach(function(c) { c.classList.remove('active'); });
el.classList.add('active');
}
function sortListings(val) {
document.querySelectorAll('.listings-grid').forEach(function(grid) {
var cards = Array.from(grid.querySelectorAll('.listing-card'));
cards.sort(function(a, b) {
function gP(c) { var t = c.querySelector('.card-price-tag'); return t parseInt(t.textContent.replace([^0-9]g,'')) 0; }
function gR(c) { var r = c.querySelector('.card-rent'); return r parseInt(r.textContent.replace([^0-9]g,'')) 0; }
function gC(c) { var l = c.querySelector('.card-location'); return l l.textContent.trim() ''; }
if (val === 'price-asc') return gP(a) - gP(b);
if (val === 'price-desc') return gP(b) - gP(a);
if (val === 'rent-asc') return gR(a) - gR(b);
if (val === 'rent-desc') return gR(b) - gR(a);
if (val === 'region') return gC(a).localeCompare(gC(b));
return 0;
});
cards.forEach(function(c) { grid.appendChild(c); });
});
}
function toggleMobileNav() {
var panel = document.getElementById('mobile-nav-panel');
var openIcon = document.getElementById('nav-burger-icon-open');
var closeIcon = document.getElementById('nav-burger-icon-close');
var isOpen = panel.classList.toggle('open');
openIcon.style.display = isOpen 'none' 'block';
closeIcon.style.display = isOpen 'block' 'none';
}
function toggleProfileDropdown(e) {
e.stopPropagation();
document.getElementById('profile-dropdown').classList.toggle('open');
}
document.addEventListener('click', function() {
var dd = document.getElementById('profile-dropdown');
if (dd) dd.classList.remove('open');
});
script
head
body
style
#dashboard-view {
display flex;
position absolute;
inset 0;
flex-direction column;
background #F0EDE6;
}
#dashboard-view { font-family 'Montserrat', sans-serif; }
#promo-banner {
background var(--sage-tint);
color #1A2A1A;
font-size 12px;
font-weight 500;
text-align center;
padding 10px 44px;
position relative;
z-index 50;
line-height 1.5;
}
#promo-banner a { color #123D36; font-weight 700; text-decoration underline; }
#promo-banner ahover { color #0A2620; }
#promo-banner-close {
position absolute;
right 14px;
top 50%;
transform translateY(-50%);
background none;
border none;
font-size 18px;
line-height 1;
color #1A2A1A;
opacity 0.6;
cursor pointer;
padding 4px;
}
#promo-banner-closehover { opacity 1; }
#dash-nav {
flex-shrink 0;
height 60px;
background #1a4848;
display flex;
align-items center;
justify-content space-between;
padding 0 32px;
z-index 100;
position relative;
}
.dash-tagline { font-size 9px; font-weight 600; letter-spacing 0.18em; text-transform uppercase; color rgba(255,255,255,0.4); }
.nav-link { font-size 12px; font-weight 500; color rgba(255,255,255,0.75); cursor pointer; letter-spacing 0.02em; transition color 0.18s; text-decoration none; }
.nav-linkhover { color #ffffff; }
.nav-right { display flex; align-items center; gap 22px; }
.nav-right-divider { width 1px; height 20px; background #ce7841; }
.nav-bell { position relative; background none; border none; cursor pointer; padding 6px; display flex; align-items center; justify-content center; }
.nav-bell-count { position absolute; top -3px; right -3px; min-width 15px; height 15px; padding 0 3px; border-radius 999px; background #da8d27; color white; font-size 9px; font-weight 700; line-height 15px; text-align center; display none; box-shadow 0 0 0 2px #1a4848; }
.nav-bell-countnot(empty) { display block; }
.nav-user { position relative; display flex; align-items center; gap 8px; cursor pointer; user-select none; }
.nav-user-avatar { width 28px; height 28px; border-radius 50%; background #da8d27; color white; font-size 12px; font-weight 700; display flex; align-items center; justify-content center; text-transform uppercase; flex-shrink 0; }
#profile-dropdown { display none; position absolute; top calc(100% + 14px); right 0; width 240px; background white; border-radius 12px; box-shadow 0 16px 40px rgba(0,0,0,0.22); overflow hidden; z-index 300; }
#profile-dropdown.open { display block; }
.dropdown-header { padding 14px 16px; background #F5F1E8; border-bottom 1px solid rgba(26,92,80,0.1); }
.dropdown-header-name { font-family 'Montserrat', sans-serif; font-size 13px; font-weight 700; color #123D36; }
.dropdown-header-role { font-family 'Montserrat', sans-serif; font-size 10px; font-weight 500; color #888; margin-top 2px; }
.dropdown-item { display flex; align-items center; gap 10px; padding 10px 16px; font-family 'Montserrat', sans-serif; font-size 12px; font-weight 500; color #333; text-decoration none; cursor pointer; transition background 0.15s; }
.dropdown-itemhover { background #F5F1E8; }
.dropdown-item-icon { display flex; align-items center; justify-content center; color #1A5C50; flex-shrink 0; }
.dropdown-item.danger { color #C0392B; }
.dropdown-item.danger .dropdown-item-icon { color #C0392B; }
.dropdown-divider { height 1px; background rgba(26,92,80,0.1); margin 4px 0; }
.mobile-nav-divider { height 1px; background rgba(255,255,255,0.15); margin 10px 0; }
#nav-burger { display none; background none; border none; cursor pointer; padding 6px; align-items center; justify-content center; }
#mobile-nav-panel { display none; flex-direction column; position absolute; top 100%; left 0; right 0; background #1a4848; padding 8px 24px 20px; box-shadow 0 12px 24px rgba(0,0,0,0.18); z-index 200; }
#mobile-nav-panel.open { display flex; }
.mobile-nav-link { color rgba(255,255,255,0.85); font-size 14px; font-weight 500; padding 14px 0; border-bottom 1px solid rgba(255,255,255,0.1); text-decoration none; display block; }
.mobile-nav-cta { margin-top 16px; font-family 'Montserrat', sans-serif; font-size 13px; font-weight 700; letter-spacing 0.03em; color #123D36; background #E8A24A; border none; border-radius 999px; padding 13px 20px; cursor pointer; }
@media (max-width 640px) {
.nav-right { display none; }
#nav-burger { display flex; }
}
.nav-user { display flex; align-items center; gap 10px; font-size 12px; color rgba(255,255,255,0.7); font-weight 500; cursor pointer; position relative; user-select none; }
.nav-user-avatar { width 32px; height 32px; border-radius 50%; background #C8683A; display flex; align-items center; justify-content center; font-size 13px; font-weight 700; color white; flex-shrink 0; }
.nav-bell { background none; border none; cursor pointer; display flex; align-items center; padding 4px; position relative; transition opacity 0.18s; }
.nav-bellhover { opacity 0.75; }
.nav-login { color rgba(255,255,255,0.85); text-decoration none; }
.nav-signup-btn { font-family 'Montserrat', sans-serif; font-size 12px; font-weight 700; letter-spacing 0.03em; color #123D36; background #E8A24A; border none; border-radius 999px; padding 10px 22px; cursor pointer; transition background 0.18s; }
.nav-signup-btnhover { background #f0b269; }
#profile-dropdown { display none; position absolute; top calc(100% + 10px); right 0; background white; border-radius 12px; box-shadow 0 8px 32px rgba(0,0,0,0.18); min-width 220px; overflow hidden; z-index 999; }
#profile-dropdown.open { display block; animation dropdown-in 0.18s cubic-bezier(0.16,1,0.3,1) both; }
@keyframes dropdown-in { from { opacity0; transformtranslateY(-8px) scale(0.97); } to { opacity1; transformnone; } }
.dd-header { padding 14px 16px 10px; border-bottom 1px solid #F0EDE6; }
.dd-name { font-size 13px; font-weight 700; color #123D36; }
.dd-role { font-size 10px; font-weight 500; color #aaa; letter-spacing 0.06em; text-transform uppercase; margin-top 2px; }
.dd-item { display flex; align-items center; gap 10px; padding 11px 16px; font-size 12px; font-weight 600; color #123D36; cursor pointer; transition background 0.15s; }
.dd-itemhover { background #F5F1E8; }
.dd-icon { width 18px; display flex; align-items center; justify-content center; flex-shrink 0; }
.dd-divider { height 1px; background #F0EDE6; margin 4px 0; }
.dd-item.danger { color #C0392B; }
.dd-item.dangerhover { background #FFF5F5; }
#dash-scroll-inner { position relative; }
#dash-hero { flex-shrink 0; background linear-gradient(160deg, #123D36 0%, #1A5C50 100%); padding 56px 32px 0; }
#dash-hero-inner { max-width 1200px; margin 0 auto; display grid; grid-template-columns 1fr 1fr; gap 48px; align-items center; }
.dash-hero-title { font-family 'Montserrat', sans-serif; font-size 40px; font-weight 700; line-height 1.18; color #FFFFFF; margin-bottom 20px; letter-spacing -0.01em; }
.dash-hero-sub { font-family 'Montserrat', sans-serif; font-size 15px; font-weight 400; line-height 1.6; color rgba(255,255,255,0.75); max-width 460px; margin-bottom 28px; }
.dash-hero-sub-break { display inline; }
@media (max-width 900px) { .dash-hero-sub-break { display none; } }
.dash-hero-ctas { display flex; align-items center; gap 14px; }
.dash-hero-btn-primary { font-family 'Montserrat', sans-serif; font-size 12px; font-weight 700; letter-spacing 0.04em; text-transform uppercase; color #FFFFFF; background #2B6B5A; border none; border-radius 30px; padding 15px 28px; cursor pointer; transition background 0.18s; }
.dash-hero-btn-primaryhover { background #327566; }
.dash-hero-btn-secondary { display inline-block; text-align center; font-family 'Montserrat', sans-serif; font-size 12px; font-weight 700; letter-spacing 0.04em; text-transform uppercase; text-decoration none; color #FFFFFF; background transparent; border 1.5px solid rgba(255,255,255,0.4); border-radius 30px; padding 15px 28px; cursor pointer; transition all 0.18s; }
.dash-hero-btn-secondaryhover { background rgba(255,255,255,0.08); border-color rgba(255,255,255,0.7); }
.dash-hero-video { position relative; aspect-ratio 169; background-size cover; background-position center; overflow hidden; border 1px solid rgba(255,255,255,0.12); border-radius 14px; display flex; flex-direction column; align-items center; justify-content center; gap 16px; cursor pointer; }
.dash-hero-video-overlay { position absolute; inset 0; background linear-gradient(180deg, rgba(18,61,54,0.35) 0%, rgba(18,61,54,0.55) 100%); z-index 0; }
.dash-hero-play { position relative; z-index 1; width 64px; height 64px; border-radius 50%; border 1.5px solid rgba(255,255,255,0.75); background rgba(18,61,54,0.25); display flex; align-items center; justify-content center; transition transform 0.18s; }
.dash-hero-videohover .dash-hero-play { transform scale(1.08); }
.dash-hero-video-caption { position relative; z-index 1; font-family 'Montserrat', sans-serif; font-size 11px; font-weight 600; letter-spacing 0.1em; text-transform uppercase; color rgba(255,255,255,0.9); text-shadow 0 1px 4px rgba(0,0,0,0.4); }
.nb-video-facade { position absolute; inset 0; background-size cover; background-position center; background-color #0d1f1c; cursor pointer; display flex; align-items center; justify-content center; }
.nb-video-facade-overlay { position absolute; inset 0; background linear-gradient(180deg, rgba(18,61,54,0.25) 0%, rgba(18,61,54,0.5) 100%); }
.nb-video-play { position relative; z-index 1; width 56px; height 56px; border-radius 50%; border 1.5px solid rgba(255,255,255,0.75); background rgba(18,61,54,0.3); display flex; align-items center; justify-content center; transition transform 0.18s; }
.nb-video-facadehover .nb-video-play { transform scale(1.08); }
#dash-hero-stats { margin-top 48px; margin-left -32px; margin-right -32px; display grid; grid-template-columns repeat(6, minmax(0, 1fr)); background rgba(0,0,0,0.18); }
.hero-stat-col { padding 26px 20px; text-align center; border-left 1px solid rgba(255,255,255,0.08); min-width 0; }
.hero-stat-colfirst-child { border-left none; }
.hero-stat-num { font-family 'Montserrat', sans-serif; font-size 22px; font-weight 700; color #E8A24A; margin-bottom 8px; overflow-wrap break-word; }
.hero-stat-label { font-family 'Montserrat', sans-serif; font-size 11px; font-weight 500; line-height 1.4; color rgba(255,255,255,0.6); overflow-wrap break-word; }
@media (max-width 900px) {
#dash-hero-inner { grid-template-columns 1fr; }
#dash-hero-stats { grid-template-columns repeat(3, minmax(0, 1fr)); }
.hero-stat-col { border-top 1px solid rgba(255,255,255,0.08); }
.hero-stat-colnth-child(4) { border-left none; }
.hero-stat-colnth-child(-n+3) { border-top none; }
}
@media (max-width 480px) {
#dash-hero-stats { grid-template-columns repeat(2, minmax(0, 1fr)); }
.hero-stat-col { padding 20px 14px; border-top 1px solid rgba(255,255,255,0.08); }
.hero-stat-colnth-child(4) { border-left 1px solid rgba(255,255,255,0.08); }
.hero-stat-colnth-child(odd) { border-left none; }
.hero-stat-colnth-child(-n+2) { border-top none; }
.hero-stat-colnth-child(n+3) { border-top 1px solid rgba(255,255,255,0.08); }
}
#dash-scroll { flex 1; overflow-y auto; }
#dash-scroll-webkit-scrollbar { width 6px; }
#dash-scroll-webkit-scrollbar-thumb { background rgba(26,92,80,0.25); border-radius 3px; }
#dash-scroll-inner { padding 24px 32px 0; max-width 1200px; margin-left auto; margin-right auto; }
#dash-filters { display flex; flex-direction column; gap 12px; margin-bottom 24px; }
.dash-filters-row { display flex; align-items flex-start; gap 10px; flex-wrap wrap; }
.filter-select-group { display flex; flex-wrap wrap; gap 10px; flex 1; min-width 0; }
.filter-label { display inline-block; width 48px; flex-shrink 0; font-size 10px; font-weight 700; letter-spacing 0.1em; text-transform uppercase; color #1A5C50; }
.filter-chip { padding 7px 14px; border-radius 20px; border 1.5px solid rgba(26,92,80,0.25); background white; font-family 'Montserrat', sans-serif; font-size 11px; font-weight 600; color #1A5C50; cursor pointer; transition all 0.18s; }
.filter-chiphover, .filter-chip.active { background #1A5C50; color white; border-color #1A5C50; }
.filter-select { width 200px; padding 7px 28px 7px 14px; border-radius 20px; border 1.5px solid rgba(26,92,80,0.25); background white url(dataimagesvg+xml,%3Csvg xmlns='httpwww.w3.org2000svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath d='M0 0l5 6 5-6z' fill='%231A5C50'%3E%3Csvg%3E) no-repeat right 10px center; font-family 'Montserrat', sans-serif; font-size 11px; font-weight 600; color #1A5C50; cursor pointer; appearance none; outline none; overflow hidden; text-overflow ellipsis; white-space nowrap; }
@media (max-width 640px) {
.dash-filters-row { flex-direction column; align-items flex-start; gap 8px; }
.filter-select-group { display grid; grid-template-columns minmax(0, 1fr) minmax(0, 1fr); gap 8px; width 100%; min-width 0; }
.filter-select { width 100%; min-width 0; }
.filter-select-group .filter-selectonly-child { grid-column 1 -1; }
}
.filter-divider { width 1px; height 24px; background rgba(26,92,80,0.2); flex-shrink 0; }
.dash-section-header { display flex; align-items baseline; justify-content space-between; margin-bottom 14px; margin-top 28px; }
.dash-section-headerfirst-child { margin-top 0; }
.dash-section-title { font-size 15px; font-weight 700; color #123D36; }
.dash-live-title { display inline-flex; align-items center; gap 7px; background var(--sage-tint); border 1px solid rgba(59,143,92,0.35); border-radius 999px; padding 7px 16px 7px 12px; font-size 12px; font-weight 700; color #123D36; }
.dash-live-dot { position relative; width 7px; height 7px; border-radius 50%; background #3B8F5C; flex-shrink 0; }
.dash-live-dotafter {
content '';
position absolute;
inset 0;
border-radius 50%;
background #3B8F5C;
animation dash-live-pulse 1.8s ease-out infinite;
}
@keyframes dash-live-pulse {
0% { transform scale(1); opacity 0.7; }
100% { transform scale(2.8); opacity 0; }
}
.dash-section-sub { font-size 11px; color #999; font-weight 500; margin-top 2px; }
#muni-partnership-bar { display flex; align-items center; justify-content space-between; gap 24px; background var(--sage-tint); border-top 1px solid rgba(26,92,80,0.12); border-bottom 1px solid rgba(26,92,80,0.12); padding 22px calc(max(0px, (100vw - 1200px) 2) + 32px); margin 32px 0; width 100vw; position relative; left 50%; right 50%; margin-left -50vw; margin-right -50vw; box-sizing border-box; }
#muni-partnership-title { font-size 14px; font-weight 700; color #123D36; margin-bottom 6px; }
#muni-partnership-sub { font-size 12px; font-weight 500; color #4A5C50; line-height 1.6; max-width 640px; }
#muni-partnership-btn { flex-shrink 0; font-family 'Montserrat', sans-serif; font-size 11px; font-weight 700; letter-spacing 0.04em; text-transform uppercase; color #FFFFFF; background #1A5C50; border none; border-radius 999px; padding 14px 26px; cursor pointer; transition background 0.18s; }
#muni-partnership-btnhover { background #123D36; }
@media (max-width 700px) {
#muni-partnership-bar { flex-direction column; align-items flex-start; }
}
.dash-see-all { font-size 11px; font-weight 600; color #da8d27; cursor pointer; }
.listings-grid { display grid; grid-template-columns repeat(3, minmax(0, 1fr)); gap 16px; margin-bottom 8px; }
@media (max-width 640px) {
.listings-grid { grid-template-columns 1fr; }
}
#dash-load-more { display flex; flex-direction column; align-items center; gap 14px; padding 28px 0 8px; }
#dash-load-more-btn { font-family 'Montserrat', sans-serif; font-size 12px; font-weight 700; letter-spacing 0.03em; color #1A5C50; background white; border 1.5px solid rgba(26,92,80,0.3); border-radius 999px; padding 12px 28px; cursor pointer; transition all 0.18s; }
#dash-load-more-btnhovernot(disabled) { background #1A5C50; color white; border-color #1A5C50; }
#dash-load-more-btndisabled { cursor default; opacity 0.6; }
#dash-page-dots { display flex; align-items center; gap 6px; }
.dash-page-dot { width 6px; height 6px; border-radius 50%; background rgba(26,92,80,0.2); transition background 0.18s; }
.dash-page-dot.active { background #1A5C50; }
#gate1-overlay, #gate2-overlay, #gate3-overlay, #app-confirm-overlay, #save-login-overlay, #session-saved-overlay, #subscribe-prompt-overlay, #already-subscribed-overlay { display none; position fixed; inset 0; background rgba(18,61,54,0.55); z-index 1000; align-items center; justify-content center; padding 20px; }
#gate1-overlay.open, #gate2-overlay.open, #gate3-overlay.open, #app-confirm-overlay.open, #save-login-overlay.open, #session-saved-overlay.open, #subscribe-prompt-overlay.open, #already-subscribed-overlay.open { display flex; }
#gate1-modal, #gate2-modal, #gate3-modal, #app-confirm-modal, #save-login-modal, #session-saved-modal, #subscribe-prompt-modal, #already-subscribed-modal { position relative; background white; border-radius 16px; padding 32px 28px; width 100%; max-width 380px; max-height 90vh; overflow-y auto; box-shadow 0 24px 60px rgba(0,0,0,0.25); }
#gate1-close, #gate2-close, #gate3-close, #app-confirm-close, #save-login-close, #session-saved-close, #subscribe-prompt-close, #already-subscribed-close { position absolute; top 14px; right 14px; background none; border none; font-size 20px; line-height 1; color #999; cursor pointer; padding 4px; }
#gate1-closehover, #gate2-closehover, #gate3-closehover, #app-confirm-closehover, #save-login-closehover, #session-saved-closehover, #subscribe-prompt-closehover, #already-subscribed-closehover { color #123D36; }
#gate1-title, #gate2-title, #gate3-title, #app-confirm-title, #save-login-title, #session-saved-title, #subscribe-prompt-title, #already-subscribed-title { font-family 'Montserrat', sans-serif; font-size 18px; font-weight 700; color #123D36; margin-bottom 6px; }
#gate1-sub, #gate2-sub, #gate3-sub, #app-confirm-sub, #save-login-sub, #session-saved-sub, #subscribe-prompt-sub, #already-subscribed-sub { font-family 'Montserrat', sans-serif; font-size 12px; font-weight 500; color #666; line-height 1.5; margin-bottom 20px; }
.gate1-field-label { display block; font-family 'Montserrat', sans-serif; font-size 11px; font-weight 700; letter-spacing 0.03em; text-transform uppercase; color #1A5C50; margin-bottom 6px; }
.gate1-input { width 100%; font-family 'Montserrat', sans-serif; font-size 13px; padding 11px 14px; border 1.5px solid rgba(26,92,80,0.25); border-radius 8px; margin-bottom 16px; outline none; color #123D36; }
select.gate1-input { appearance none; background white url(dataimagesvg+xml,%3Csvg xmlns='httpwww.w3.org2000svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath d='M0 0l5 6 5-6z' fill='%231A5C50'%3E%3Csvg%3E) no-repeat right 14px center; padding-right 32px; cursor pointer; }
select.gate1-inputinvalid { color #999; }
.gate1-inputfocus { border-color #1A5C50; }
.gate1-honeypot { position absolute; left -9999px; top -9999px; width 1px; height 1px; opacity 0; overflow hidden; }
.gate1-inputplaceholder { color #A8A8A8; }
.gate1-required { color #C0392B; }
.gate1-input.gate1-invalid { border-color #C0392B; }
#gate1-consent-label.gate1-invalid span, #gate2-consent-label.gate1-invalid span { color #C0392B; }
.gate1-error { display none; font-family 'Montserrat', sans-serif; font-size 11px; font-weight 500; color #C0392B; margin-top -12px; margin-bottom 14px; }
.gate1-error.show { display block; }
#gate1-consent-label, #gate2-consent-label { display flex; align-items flex-start; gap 8px; font-family 'Montserrat', sans-serif; font-size 11px; font-weight 500; color #555; line-height 1.5; margin-bottom 22px; cursor pointer; }
#gate1-consent-label input, #gate2-consent-label input { margin-top 2px; flex-shrink 0; cursor pointer; accent-color #1A5C50; }
#gate1-consent-label a, #gate2-consent-label a { color #1A5C50; font-weight 700; text-decoration underline; }
#gate1-consent-label ahover, #gate2-consent-label ahover { color #123D36; }
#gate1-marketing-label { display flex; align-items flex-start; gap 8px; font-family 'Montserrat', sans-serif; font-size 11px; font-weight 500; color #555; line-height 1.5; margin-bottom 22px; cursor pointer; }
#gate1-marketing-label input { margin-top 2px; flex-shrink 0; cursor pointer; accent-color #1A5C50; }
#gate1-submit-btn, #gate2-submit-btn, #gate3-submit-btn, #app-confirm-submit-btn, #save-login-signin-btn, #save-login-signup-btn, #session-saved-btn, #subscribe-prompt-btn, #already-subscribed-btn { width 100%; font-family 'Montserrat', sans-serif; font-size 13px; font-weight 700; letter-spacing 0.03em; color white; background #1A5C50; border none; border-radius 999px; padding 13px; cursor pointer; transition background 0.18s, opacity 0.18s; }
#gate1-submit-btnhover, #gate2-submit-btnhover, #gate3-submit-btnhover, #app-confirm-submit-btnhover, #save-login-signin-btnhover, #session-saved-btnhover, #subscribe-prompt-btnhover, #already-subscribed-btnhover { background #123D36; }
#save-login-signup-btnhover { opacity 0.75; }
#save-login-sent { display none; text-align center; padding 16px 0 4px; font-size 13px; color #1A5C50; font-weight 500; line-height 1.5; }
#save-login-sent strong { display block; font-size 15px; margin-bottom 4px; font-weight 700; }
#session-saved-icon, #already-subscribed-icon { width 44px; height 44px; border-radius 50%; background #E1F5EE; display flex; align-items center; justify-content center; margin-bottom 16px; }
#subscribe-prompt-icon { width 44px; height 44px; border-radius 50%; background #F5F1E8; display flex; align-items center; justify-content center; margin-bottom 16px; }
#subscribe-prompt-dismiss { text-align center; font-family 'Montserrat', sans-serif; font-size 11px; color #999; text-decoration underline; cursor pointer; margin-top 10px; }
#subscribe-prompt-dismisshover { color #123D36; }
.session-saved-list { display flex; flex-direction column; gap 12px; margin-bottom 24px; }
.session-saved-row { display flex; align-items flex-start; gap 10px; }
.session-saved-row-icon { width 26px; height 26px; border-radius 8px; background #F5F1E8; display flex; align-items center; justify-content center; flex-shrink 0; margin-top 1px; }
.session-saved-row-label { font-family 'Montserrat', sans-serif; font-size 12.5px; color #123D36; font-weight 500; line-height 1.4; padding-top 3px; }
#session-saved-resend { text-align center; font-family 'Montserrat', sans-serif; font-size 11px; color #999; }
#session-saved-resend span { color #1A5C50; text-decoration underline; cursor pointer; }
#session-saved-resend spanhover { color #123D36; }
#dash-scroll-inner .listings-grid-3 { display grid !important; grid-template-columns repeat(3, minmax(0, 1fr)) !important; gap 8px !important; margin-bottom 8px; }
#dash-scroll-inner .listings-grid-3 .listing-card { min-width 0 !important; width 100% !important; }
#dash-scroll-inner .listings-grid-3 .card-title { font-size 11px !important; }
#dash-scroll-inner .listings-grid-3 .card-img { height 120px !important; }
#dash-scroll-inner .listings-grid-3 .card-meta-item { font-size 9px !important; }
#dash-scroll-inner .listings-grid-3 .card-apply-btn { font-size 9px !important; padding 4px 8px !important; }
.listing-card { background white; border-radius 14px; overflow hidden; box-shadow 0 2px 12px rgba(0,0,0,0.07); transition transform 0.2s, box-shadow 0.2s; cursor pointer; }
.listing-cardhover { transform translateY(-3px); box-shadow 0 8px 24px rgba(18,61,54,0.14); }
.card-img { height 200px; position relative; display flex; align-items flex-end; padding 10px 12px; }
.listings-grid-3 .card-img { height 150px; }
.card-img-overlay { position absolute; inset 0; background rgba(0,0,0,0.18); }
.card-save-btn { position absolute; top 10px; left 10px; z-index 2; width 30px; height 30px; border-radius 50%; background rgba(255,255,255,0.18); backdrop-filter blur(4px); border none; cursor pointer; display flex; align-items center; justify-content center; transition background 0.18s, transform 0.15s; padding 0; }
.card-save-btnhover { background rgba(255,255,255,0.32); transform scale(1.1); }
.card-save-btn.saved svg { fill #da8d27; stroke #da8d27; }
.card-badge { position relative; z-index 1; background rgba(18,61,54,0.75); color white; font-size 9px; font-weight 700; letter-spacing 0.1em; text-transform uppercase; padding 3px 8px; border-radius 4px; }
.card-badge.recommended-badge { background #C8683A; }
.card-price-tag { display none; }
.card-body { padding 14px; }
.card-title { font-size 13px; font-weight 700; color #123D36; margin-bottom 3px; line-height 1.3; }
.card-location { font-size 11px; color #888; font-weight 500; margin-bottom 10px; display flex; align-items center; gap 4px; }
.card-meta { display flex; gap 6px; margin-bottom 12px; flex-wrap wrap; }
.card-meta-item { font-size 10px; font-weight 600; color #1A5C50; background rgba(26,92,80,0.07); padding 3px 8px; border-radius 4px; }
.card-footer { display flex; align-items center; justify-content space-between; border-top 1px solid #F0EDE6; padding-top 10px; }
.card-price-block { display flex; flex-direction column; gap 1px; }
.card-rent { font-size 16px; font-weight 700; color #123D36; line-height 1.2; }
.card-rent span { font-size 10px; font-weight 500; color #aaa; margin-left 2px; }
.card-rent-label { font-size 9px; font-weight 600; text-transform uppercase; letter-spacing 0.05em; color #888; margin-bottom 1px; }
.card-purchase-sub { font-size 10px; color #888; margin-top 2px; }
.card-apply-btn { font-size 10px; font-weight 700; letter-spacing 0.06em; color white; background #CC7722; border none; border-radius 6px; padding 5px 12px; cursor pointer; font-family 'Montserrat', sans-serif; transition background 0.18s; }
.card-apply-btnhover { background #A85E17; }
.card-avail {
padding 10px 14px 0;
display flex;
flex-direction column;
gap 5px;
}
.card-avail-label {
font-size 9px;
font-weight 700;
letter-spacing 0.08em;
text-transform uppercase;
color #aaa;
display flex;
justify-content space-between;
}
.card-avail-label span { color #1A5C50; font-weight 700; }
.card-avail-track {
height 5px;
background rgba(26,92,80,0.12);
border-radius 3px;
overflow hidden;
}
.card-avail-fill {
height 100%;
background #CC7722;
border-radius 3px;
transition width 0.4s ease;
}
.card-avail-fill.amber { background #CC7722; }
.card-match-reasons { display flex; flex-wrap wrap; gap 5px; margin-top 10px; }
.card-match-tag { display inline-flex; align-items center; gap 4px; background rgba(26,92,80,0.08); border 1px solid rgba(26,92,80,0.18); border-radius 20px; padding 3px 8px; font-size 9px; font-weight 600; color #1A5C50; line-height 1; }
.card-match-tag svg { flex-shrink 0; }
.reco-grid { display grid; grid-template-columns repeat(5, 1fr); gap 10px; margin-bottom 32px; }
.reco-card { background white; border-radius 12px; padding 18px 16px 16px; cursor pointer; transition box-shadow 0.18s, transform 0.18s; border-top 3px solid #1A5C50; display flex; flex-direction column; gap 8px; }
.reco-cardhover { transform translateY(-2px); box-shadow 0 6px 20px rgba(18,61,54,0.10); }
.reco-title { font-size 12px; font-weight 700; color #123D36; line-height 1.3; }
.reco-desc { font-size 10px; color #7a8c85; font-weight 500; line-height 1.6; flex 1; }
.reco-arrow { margin-top auto; display flex; align-items center; gap 4px; font-size 9px; font-weight 700; letter-spacing 0.05em; color #1A5C50; text-transform uppercase; opacity 0; transition opacity 0.18s; }
.reco-cardhover .reco-arrow { opacity 1; }
#footer-disclosures { padding-top 32px; padding-bottom 32px; }
#disclosures-title { font-family 'Montserrat', sans-serif; font-size 10px; font-weight 700; letter-spacing 0.08em; text-transform uppercase; color rgba(255,255,255,0.55); margin-bottom 8px; }
#footer-disclosures p { font-family 'Montserrat', sans-serif; font-size 9px; font-weight 400; color rgba(255,255,255,0.4); line-height 1.7; margin-bottom 8px; }
#footer-disclosures a { color rgba(255,255,255,0.55); text-decoration underline; }
#footer-disclosures ahover { color #fff; }
#footer-sitemap { padding-top 24px; padding-bottom 24px; display grid; grid-template-columns repeat(4, minmax(0, 1fr)); gap 24px; }
.sitemap-heading { font-family 'Montserrat', sans-serif; font-size 11px; font-weight 700; letter-spacing 0.08em; text-transform uppercase; color #FFFFFF; margin-bottom 14px; }
.sitemap-col { display flex; flex-direction column; gap 12px; }
.sitemap-col a { font-family 'Montserrat', sans-serif; font-size 11px; font-weight 600; letter-spacing 0.03em; text-transform uppercase; color rgba(255,255,255,0.65); text-decoration none; cursor pointer; }
.sitemap-col ahover { color #fff; }
#sitemap-social { display flex; gap 10px; margin-top 4px; }
#sitemap-social a { width 26px; height 26px; border-radius 6px; background rgba(255,255,255,0.12); display flex; align-items center; justify-content center; color #fff; }
#sitemap-social ahover { background rgba(255,255,255,0.22); }
#footer-bottom-bar { padding-top 16px; padding-bottom 14px; display flex; align-items center; justify-content space-between; flex-wrap wrap; gap 10px; }
#footer-copyright { font-size 10px; letter-spacing 0.02em; }
#footer-bottom-links { display flex; gap 20px; }
#footer-bottom-links a { font-family 'Montserrat', sans-serif; font-size 10px; font-weight 500; color rgba(255,255,255,0.55); text-decoration none; }
#footer-bottom-links ahover { color #fff; text-decoration underline; }
@media (max-width 700px) {
#footer-sitemap { grid-template-columns repeat(2, minmax(0, 1fr)); }
}
#dash-footer { width 100%; background #123D36; color rgba(255,255,255,0.55); font-family 'Montserrat', sans-serif; font-size 10px; font-weight 500; letter-spacing 0.04em; display flex; flex-direction column; flex-shrink 0; }
.footer-block { width 100%; box-sizing border-box; }
.footer-divider { border-top 1px solid rgba(255,255,255,0.15); }
#footer-disclosures, #footer-sitemap, #footer-bottom-bar { max-width 1200px; margin 0 auto; padding-left 32px; padding-right 32px; box-sizing border-box; }
#voices-section { position relative; width 100vw; left 50%; right 50%; margin-left -50vw; margin-right -50vw; padding 48px 0; margin-top 32px; margin-bottom 0; text-align center; box-sizing border-box; min-height 710px; background-image url(dataimagesvg+xml,%3Csvg%20xmlns%3D%22http%3Awww.w3.org2000svg%22%20viewBox%3D%220%200%2029%2034%22%3E%3Cpath%20d%3D%22M28.6407%2017.0608L25.4418%202.57192C25.2066%201.49296%2024.156%200.827731%2023.1132%201.09544C22.0705%201.36316%2021.4197%202.46646%2021.6549%203.55353L24.9479%2018.4886C25.1831%2019.5595%2023.8502%2020.2247%2023.1916%2019.3648L14.2223%207.72336C13.5402%206.83909%2012.176%206.52271%2011.196%207.03379C10.2159%207.54488%209.97287%208.68063%2010.655%209.57301L20.1418%2021.8878C20.8082%2022.7477%2019.883%2023.9484%2018.9265%2023.4697L5.64502%2016.8499C4.72771%2016.3956%203.56734%2016.6552%203.04204%2017.5557C2.4305%2018.5941%202.83035%2019.9164%203.85743%2020.4275L17.2408%2027.096C18.1974%2027.5746%2017.8681%2029.0673%2016.8096%2029.0673H1.95224C0.870274%2029.0673%200%2029.9759%200%2031.0874C0%2032.1988%200.870274%2033.1074%201.95224%2033.1074H27.1667C27.9821%2033.1074%2028.6407%2032.4259%2028.6407%2031.5822V17.0608Z%22%20fill%3D%22%23FBB040%22%20fill-opacity%3D%220.12%22%3E%3Csvg%3E); background-repeat no-repeat; background-position bottom right; background-size 600px auto; }
#voices-inner { position relative; z-index 1; max-width 1200px; margin 0 auto; padding 0 32px; box-sizing border-box; }
#voices-eyebrow { font-size 11px; font-weight 700; letter-spacing 0.14em; text-transform uppercase; color #4A5C50; margin-bottom 10px; }
#voices-title { font-family 'Montserrat', sans-serif; font-size 30px; font-weight 500; color #8A9A8E; line-height 1.3; margin-bottom 36px; }
#voices-title-light { color #123D36; font-weight 700; }
#voices-grid { position relative; z-index 1; display grid; grid-template-columns repeat(3, minmax(0, 1fr)); gap 20px; text-align left; }
.voice-card { background #FBF9F3; border-radius 14px; padding 28px 24px 22px; display flex; flex-direction column; }
.voice-quote-mark { font-family Georgia, serif; font-size 44px; font-weight 700; color #C8683A; line-height 1; margin-bottom 8px; }
.voice-text { font-family 'Montserrat', sans-serif; font-size 13px; font-weight 500; font-style italic; color #2C4A52; line-height 1.65; margin-bottom 24px; flex-grow 1; }
.voice-footer { display flex; align-items center; gap 12px; padding-top 16px; border-top 1px solid rgba(26,92,80,0.12); }
.voice-avatar { width 38px; height 38px; border-radius 50%; object-fit cover; flex-shrink 0; }
.voice-name { font-size 12px; font-weight 700; color #123D36; }
.voice-role { font-size 11px; font-weight 500; color #666; margin-top 2px; line-height 1.4; min-height 30px; display flex; align-items center; }
#ecosystem-section { position relative; width 100vw; left 50%; right 50%; margin-left -50vw; margin-right -50vw; background var(--sage-tint); padding 56px 0; margin-top 0; margin-bottom 0; text-align center; box-sizing border-box; }
#ecosystem-inner { max-width 1200px; margin 0 auto; padding 0 32px; box-sizing border-box; }
#ecosystem-title { font-family 'Montserrat', sans-serif; font-size 28px; font-weight 500; color #8A9A8E; margin-bottom 14px; }
#ecosystem-title-bold { color #123D36; font-weight 700; }
#ecosystem-sub { font-family 'Montserrat', sans-serif; font-size 13px; font-weight 500; color #666; line-height 1.7; max-width 640px; margin 0 auto 32px; }
#ecosystem-grid { display grid; grid-template-columns repeat(3, minmax(0, 1fr)); gap 20px; text-align left; }
.ecosystem-card { background #FBF9F3; border-radius 14px; overflow hidden; }
.ecosystem-logo-strip { display flex; align-items center; justify-content center; background #123D36; padding 22px 20px; }
.ecosystem-logo-strip-light { background #FBF9F3; border-bottom 1px solid rgba(26,92,80,0.1); }
.ecosystem-logo-img { max-width 100%; height 32px; width auto; object-fit contain; }
.ecosystem-card-body { padding 22px 24px 26px; }
.ecosystem-card-title { font-family 'Montserrat', sans-serif; font-size 15px; font-weight 700; font-style italic; color #123D36; margin-bottom 8px; }
.ecosystem-card-desc { font-family 'Montserrat', sans-serif; font-size 12px; font-weight 500; color #666; line-height 1.6; }
@media (max-width 900px) {
#ecosystem-grid { grid-template-columns 1fr; }
#ecosystem-title { font-size 22px; }
}
@media (max-width 900px) {
#voices-grid { grid-template-columns 1fr; }
#voices-title { font-size 24px; }
#voices-section { background-size 320px auto; }
}
#dash-footer a { color rgba(255,255,255,0.55); text-decoration none; transition color 0.15s; }
#dash-footer ahover { color #fff; }
.dash-footer-divider { opacity 0.3; }
.d-popup-header { background #1A5C50; padding 10px 14px; }
.d-popup-type { font-size 9px; font-weight 700; letter-spacing 0.12em; text-transform uppercase; color #E8A24A; margin-bottom 2px; }
.d-popup-title { font-size 13px; font-weight 700; color white; line-height 1.2; }
.d-popup-body { padding 10px 14px; }
.d-popup-row { display flex; align-items center; justify-content space-between; font-size 11px; color #666; padding 3px 0; }
.d-popup-row strong { color #1A2A1A; font-weight 600; }
style
div id=dashboard-view
nav id=dash-nav
div onclick=closeListingDetail();filterByRegion('Vancouver Island'); style=cursorpointer;displayflex;align-itemscenter; title=Back to home
svg width=130 height=30 viewBox=0 0 163 38 fill=none xmlns=httpwww.w3.org2000svg
path d=M34.536 0.747925H39.4049V33.0843H32.427V2.93019C32.427 1.72954 33.3678 0.747925 34.536 0.747925Z fill=#ffffff
path d=M88.8771 21.3374L96.2234 2.32986C96.5919 1.37259 97.4857 0.747925 98.4814 0.747925H104.393L91.8329 33.0843H85.9291L73.3611 0.747925H80.9191L88.8771 21.3293V21.3374Z fill=#ffffff
path d=M67.5122 16.6144H72.2478V28.0855C69.1508 31.6631 64.8544 33.4478 59.374 33.4478C54.7874 33.4478 50.93 31.874 47.8174 28.7264C44.7048 25.5787 43.1445 21.6117 43.1445 16.8172C43.1445 12.0227 44.7283 8.02326 47.9036 4.81071C51.0789 1.60628 54.905 0 59.3897 0C63.8743 0 67.7709 1.52515 71.0796 4.57545L68.8294 7.93402C68.1238 8.98865 66.7282 9.28881 65.7089 8.5668C64.9641 8.03949 64.2663 7.64197 63.5921 7.37426C62.416 6.89562 61.138 6.66036 59.766 6.66036C57.116 6.66036 54.8815 7.5933 53.0625 9.45917C51.2436 11.325 50.3341 13.7831 50.3341 16.8334C50.3341 19.8837 51.2044 22.3337 52.9528 24.1671C54.7011 26.0006 56.7788 26.9173 59.1858 26.9173C61.5928 26.9173 63.6156 26.4386 65.2228 25.4814V18.9589C65.2228 17.6528 66.2421 16.5982 67.5044 16.5982L67.5122 16.6144Z fill=#ffffff
path d=M28.6407 17.0608L25.4418 2.57192C25.2066 1.49296 24.156 0.827731 23.1132 1.09544C22.0705 1.36316 21.4197 2.46646 21.6549 3.55353L24.9479 18.4886C25.1831 19.5595 23.8502 20.2247 23.1916 19.3648L14.2223 7.72336C13.5402 6.83909 12.176 6.52271 11.196 7.03379C10.2159 7.54488 9.97287 8.68063 10.655 9.57301L20.1418 21.8878C20.8082 22.7477 19.883 23.9484 18.9265 23.4697L5.64502 16.8499C4.72771 16.3956 3.56734 16.6552 3.04204 17.5557C2.4305 18.5941 2.83035 19.9164 3.85743 20.4275L17.2408 27.096C18.1974 27.5746 17.8681 29.0673 16.8096 29.0673H1.95224C0.870274 29.0673 0 29.9759 0 31.0874C0 32.1988 0.870274 33.1074 1.95224 33.1074H27.1667C27.9821 33.1074 28.6407 32.4259 28.6407 31.5822V17.0608Z fill=#FBB040
path d=M106.699 26.0738V33.2047H104.018V14.8624H106.699V22.4394C107.083 21.6282 107.655 20.9954 108.432 20.533C109.208 20.0706 110.039 19.8434 110.933 19.8434C112.368 19.8434 113.528 20.2977 114.414 21.2063C115.3 22.1149 115.739 23.4292 115.739 25.1409V33.2128H113.057V25.9846C113.057 23.559 112.085 22.3421 110.141 22.3421C109.216 22.3421 108.408 22.6585 107.726 23.2913C107.036 23.924 106.699 24.857 106.699 26.0738Z fill=#ffffff
path d=M130.126 31.4276C128.848 32.7418 127.256 33.3989 125.343 33.3989C123.43 33.3989 121.831 32.7418 120.56 31.4276C119.283 30.1134 118.647 28.5071 118.647 26.6088C118.647 24.7104 119.283 23.1042 120.56 21.7899C121.838 20.4757 123.43 19.8186 125.343 19.8186C127.256 19.8186 128.848 20.4757 130.126 21.7899C131.404 23.1042 132.039 24.7104 132.039 26.6088C132.039 28.5071 131.404 30.1134 130.126 31.4276ZM122.458 29.724C123.218 30.5271 124.175 30.9246 125.343 30.9246C126.511 30.9246 127.468 30.5271 128.228 29.724C128.989 28.9208 129.365 27.8905 129.365 26.6169C129.365 25.3432 128.989 24.3129 128.228 23.5098C127.468 22.7067 126.511 22.3091 125.343 22.3091C124.175 22.3091 123.218 22.7067 122.458 23.5098C121.697 24.3129 121.321 25.3432 121.321 26.6169C121.321 27.8905 121.697 28.9208 122.458 29.724Z fill=#ffffff
path d=M141.894 19.8362C143.603 19.8362 145.062 20.4446 146.277 21.6696C147.484 22.8946 148.096 24.5171 148.096 26.5452C148.096 28.5733 147.492 30.2283 146.292 31.4938C145.085 32.7675 143.682 33.4003 142.082 33.4003C140.483 33.4003 139.04 32.6702 137.762 31.218V38.0001H135.081V20.0228H137.762V22.3267C138.813 20.6637 140.193 19.8281 141.902 19.8281L141.894 19.8362ZM137.707 26.6426C137.707 27.9 138.076 28.9222 138.805 29.7253C139.542 30.5285 140.428 30.926 141.486 30.926C142.545 30.926 143.454 30.5285 144.238 29.7415C145.022 28.9546 145.414 27.9243 145.414 26.6588C145.414 25.3932 145.03 24.3467 144.27 23.5111C143.501 22.6756 142.584 22.2618 141.518 22.2618C140.451 22.2618 139.55 22.6756 138.813 23.5111C138.076 24.3467 137.715 25.3851 137.715 26.6426H137.707Z fill=#ffffff
path d=M163 27.8253H153.019C153.082 28.7826 153.505 29.5532 154.289 30.1373C155.073 30.7214 155.967 31.0135 156.971 31.0135C158.562 31.0135 159.778 30.4943 160.609 29.4559L162.138 31.192C160.766 32.6603 158.978 33.3986 156.775 33.3986C154.987 33.3986 153.466 32.782 152.22 31.557C150.965 30.3239 150.338 28.6771 150.338 26.6084C150.338 24.5397 150.973 22.8929 152.251 21.6679C153.529 20.451 155.026 19.8345 156.759 19.8345C158.492 19.8345 159.958 20.378 161.173 21.457C162.388 22.5359 162.992 24.0286 162.992 25.927V27.8334L163 27.8253ZM153.019 25.6511H160.319C160.319 24.5478 159.981 23.696 159.315 23.1038C158.649 22.5116 157.818 22.2114 156.838 22.2114C155.857 22.2114 154.972 22.5197 154.195 23.1363C153.411 23.7528 153.019 24.5884 153.019 25.6511Z fill=#ffffff
svg
div
div class=nav-right
a class=nav-link href=httpshowitworks.pages.devHow It Worksa
a class=nav-link href=httpsigvhope-faq.pages.devFAQa
div class=nav-right-dividerdiv
a class=nav-link nav-login id=nav-login-desktop href=httpsplatform.igvhousing.comLog Ina
div id=nav-account-area style=displaynone; align-itemscenter; gap14px;
button class=nav-bell id=nav-bell-btn aria-label=Notifications onclick=handleNavBellClick()
span id=nav-bell-iconsvg width=18 height=18 viewBox=0 0 24 24 fill=none stroke=rgba(255,255,255,0.75) stroke-width=2 stroke-linecap=round stroke-linejoin=roundpath d=M18 8A6 6 0 0 0 6 8c0 7-3 9-3 9h18s-3-2-3-9path d=M13.73 21a2 2 0 0 1-3.46 0svgspan
span class=nav-bell-count id=nav-bell-countspan
button
div class=nav-user onclick=toggleProfileDropdown(event)
div class=nav-user-avatar id=nav-user-avatardiv
span id=nav-user-label style=colorrgba(255,255,255,0.85);font-size12px;font-weight600;Accountspan
svg width=12 height=12 viewBox=0 0 24 24 fill=none stroke=rgba(255,255,255,0.5) stroke-width=2.5 stroke-linecap=round stroke-linejoin=round style=margin-left2px;polyline points=6 9 12 15 18 9svg
div id=profile-dropdown
div class=dropdown-header
div class=dropdown-header-name id=dropdown-header-nameIGVhope Memberdiv
div class=dropdown-header-roleIGVhope Participantdiv
div
a class=dropdown-item href=# onclick=openAccountView('applications');return false;
span class=dropdown-item-iconsvg width=15 height=15 viewBox=0 0 24 24 fill=none stroke=currentColor stroke-width=2 stroke-linecap=round stroke-linejoin=roundpath d=M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8zpolyline points=14 2 14 8 20 8svgspan
Previous Applications
a
a class=dropdown-item href=# onclick=openAccountView('saved');return false;
span class=dropdown-item-iconsvg width=15 height=15 viewBox=0 0 24 24 fill=none stroke=currentColor stroke-width=2 stroke-linecap=round stroke-linejoin=roundpath d=M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78zsvgspan
Saved Listings
a
a class=dropdown-item href=# onclick=openAccountView('notifications');return false;
span class=dropdown-item-iconsvg width=15 height=15 viewBox=0 0 24 24 fill=none stroke=currentColor stroke-width=2 stroke-linecap=round stroke-linejoin=roundpath d=M18 8A6 6 0 0 0 6 8c0 7-3 9-3 9h18s-3-2-3-9path d=M13.73 21a2 2 0 0 1-3.46 0svgspan
Notifications
a
div class=dropdown-dividerdiv
a class=dropdown-item href=httpswww.igvhousing.com target=_blank rel=noopener
span class=dropdown-item-iconimg src=imagesimg_001.ico alt= width=15 height=15 style=border-radius3px;span
About IGV
a
div class=dropdown-dividerdiv
a class=dropdown-item danger href=# onclick=handleNavLogout(event)
span class=dropdown-item-iconsvg width=15 height=15 viewBox=0 0 24 24 fill=none stroke=currentColor stroke-width=2 stroke-linecap=round stroke-linejoin=roundpath d=M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4polyline points=16 17 21 12 16 7line x1=21 y1=12 x2=9 y2=12svgspan
Log out
a
div
div
div
button class=nav-signup-btn onclick=scrollToListings();Find Your Placebutton
div
button id=nav-burger onclick=toggleMobileNav() aria-label=Open menu
svg id=nav-burger-icon-open width=22 height=22 viewBox=0 0 24 24 fill=none stroke=#ffffff stroke-width=2 stroke-linecap=round stroke-linejoin=roundline x1=3 y1=6 x2=21 y2=6line x1=3 y1=12 x2=21 y2=12line x1=3 y1=18 x2=21 y2=18svg
svg id=nav-burger-icon-close width=22 height=22 viewBox=0 0 24 24 fill=none stroke=#ffffff stroke-width=2 stroke-linecap=round stroke-linejoin=round style=displaynone;line x1=18 y1=6 x2=6 y2=18line x1=6 y1=6 x2=18 y2=18svg
button
div id=mobile-nav-panel
a class=mobile-nav-link href=httpshowitworks.pages.devHow It Worksa
a class=mobile-nav-link href=httpsigvhope-faq.pages.devFAQa
a class=mobile-nav-link id=nav-login-mobile href=httpsplatform.igvhousing.comLog Ina
div id=nav-account-area-mobile style=displaynone; flex-directioncolumn;
div class=mobile-nav-dividerdiv
div id=mobile-nav-account-name style=color#fff; font-weight700; font-size13px; padding6px 0 2px;div
a class=mobile-nav-link href=# onclick=toggleMobileNav();openAccountView('applications');return false;Previous Applicationsa
a class=mobile-nav-link href=# onclick=toggleMobileNav();openAccountView('saved');return false;Saved Listingsa
a class=mobile-nav-link href=# onclick=toggleMobileNav();openAccountView('notifications');return false;Notificationsa
a class=mobile-nav-link href=httpswww.igvhousing.com target=_blank rel=noopenerAbout IGVa
a class=mobile-nav-link href=# onclick=handleNavLogout(event) style=color#e88;Log outa
div
button class=mobile-nav-cta onclick=toggleMobileNav();scrollToListings();Find Your Placebutton
div
nav
div id=dash-scroll
div id=promo-banner
spanIGVhope homes are coming to Vancouver Island communities. a href=javascriptvoid(0) onclick=handleNewReleasesBannerClick();Be the first to know about new releasesa.span
button id=promo-banner-close onclick=document.getElementById('promo-banner').style.display='none'; aria-label=Dismiss banner×button
div
div id=dash-hero
div id=dash-hero-inner
div id=dash-hero-text
h1 class=dash-hero-titleIGVhope home ownership is built for real lifeh1
p class=dash-hero-subIGVhope is reinventing the process of home ownership, with the purchase price locked at Day Onebr class=dash-hero-sub-break and a Year Ten mortgage transition.p
div class=dash-hero-ctas
button class=dash-hero-btn-primary onclick=scrollToListings();Find Your Placebutton
a class=dash-hero-btn-secondary href=httpshowitworks.pages.devSee How It Worksa
div
div
div class=dash-hero-video id=dash-hero-video style=background-image url('imagesimg_014.jpg'); onclick=playHeroVideo()
div class=dash-hero-video-overlaydiv
div class=dash-hero-play
svg width=20 height=20 viewBox=0 0 24 24 fill=whitepolygon points=6,4 20,12 6,20svg
div
div class=dash-hero-video-captionWatch What IGVhope Means For Your Futurediv
div
div
div id=dash-hero-stats
div class=hero-stat-col
div class=hero-stat-num$0div
div class=hero-stat-labelDown payment needed to lock in your home's price todaydiv
div
div class=hero-stat-col
div class=hero-stat-numCertaintydiv
div class=hero-stat-labelSecure occupancy with capped annual increases and community supportdiv
div
div class=hero-stat-col
div class=hero-stat-numNowdiv
div class=hero-stat-labelDesigned to help everyday people move into homes todaydiv
div
div class=hero-stat-col
div class=hero-stat-num$2B+div
div class=hero-stat-labelHomes delivered internationally by IGV's leadership teamdiv
div
div class=hero-stat-col
div class=hero-stat-num30+div
div class=hero-stat-labelYears of proven property development by IGV's leadership teamdiv
div
div class=hero-stat-col
div class=hero-stat-num$70Mdiv
div class=hero-stat-labelAdvanced manufacturing facility in BC delivering quality homesdiv
div
div
div
div id=dash-scroll-inner
div id=dash-filters
div class=dash-filters-row
span class=filter-labelFilterspan
div class=filter-select-group
select class=filter-select id=type-select onchange=filterByType(this.value)
option value=AllAlloption
option value=MultiplexMultiplexoption
option value=ApartmentApartmentoption
option value=TownhouseTownhouseoption
option value=HouseHouseoption
select
select class=filter-select id=region-select onchange=filterByRegion(this.value)
option value=Any region disabledAny regionoption
option value=Vancouver Metro disabledVancouver Metrooption
option value=Fraser Valley disabledFraser Valleyoption
option value=Okanagan disabledOkanaganoption
option value=Vancouver Island selectedVancouver Islandoption
option value=Northern BC disabledNorthern BCoption
select
select class=filter-select
optionAny priceoption
optionUnder $350,000option
option$350,000 – $450,000option
option$450,000 – $550,000option
option$550,000+option
select
select class=filter-select
optionAny bedroomsoption
option1 bedoption
option2 bedsoption
option3+ bedsoption
select
div
div
div class=dash-filters-row
span class=filter-labelSortspan
div class=filter-select-group
select class=filter-select onchange=sortListings(this.value)
option value=rent-asc selectedMonthly Cost Low to Highoption
option value=rent-descMonthly Cost High to Lowoption
option value=price-ascPurchase Price Low to Highoption
option value=price-descPurchase Price High to Lowoption
select
div
div
div
div class=dash-section-header
div
div class=dash-section-title dash-live-titlespan class=dash-live-dotspanLive Homesdiv
div
div
div class=listings-grid
div class=listing-card data-region=Vancouver Island onclick=if(!event.target.closest('.card-save-btn'))openListingDetail(this)
div class=card-img style=background-image url('imagesimg_008.jpg'); background-size cover; background-position center;
div class=card-img-overlaydiv
div class=card-price-tag$450,000div
button class=card-save-btn onclick=handleSaveClick(this) title=Save listingsvg width=14 height=14 viewBox=0 0 24 24 fill=none stroke=white stroke-width=2.5 stroke-linecap=round stroke-linejoin=roundpath d=M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78zsvgbutton
span class=card-badge recommended-badgeMortgage Helperspan
div
div class=card-body
div class=card-title data-video=httpswww.youtube.comembedSKgFdyuzTrksi=JF2eGde3J2UhgGhH data-img=imagesimg_008.jpg data-img2=imagesimg_003.jpg data-img3=imagesimg_004.jpgCompton Road - Unit Adiv
div class=card-locationsvg width=10 height=10 viewBox=0 0 24 24 fill=none stroke=currentColor stroke-width=2.5 stroke-linecap=round stroke-linejoin=roundpath d=M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0zcircle cx=12 cy=10 r=3svg Port Alberni, BCdiv
div class=card-meta
span class=card-meta-item3 bedspan
span class=card-meta-item2 bathspan
span class=card-meta-itemMultiplexspan
div
div class=card-avail
div class=card-avail-labelAvailability span1 of 1 availablespandiv
div class=card-avail-trackdiv class=card-avail-fill style=width100%divdiv
div
div class=card-footer style=margin-top10pxdiv class=card-rent$3,950spanmospandiv
button class=card-apply-btn onclick=event.stopPropagation();openListingDetail(this.closest('.listing-card'))See morebutton
div
div
div
div class=listing-card data-region=Vancouver Island onclick=if(!event.target.closest('.card-save-btn'))openListingDetail(this)
div class=card-img style=background-image url('imagesimg_006.jpg'); background-size cover; background-position center;
div class=card-img-overlaydiv
div class=card-price-tag$781,000div
button class=card-save-btn onclick=handleSaveClick(this) title=Save listingsvg width=14 height=14 viewBox=0 0 24 24 fill=none stroke=white stroke-width=2.5 stroke-linecap=round stroke-linejoin=roundpath d=M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78zsvgbutton
span class=card-badge recommended-badgeMortgage Helperspan
div
div class=card-body
div class=card-title data-video=httpswww.youtube.comembedXK9raw1l1fI data-img=imagesimg_006.jpg data-img2=imagesrainforest-drive-aerial-1.jpg data-img3=imagesrainforest-drive-aerial-2.jpg data-img4=imagesrainforest-drive-aerial-3.jpg data-img5=imagesrainforest-drive-aerial-4.jpg data-img6=imagesimg_003.jpg data-img7=imagesimg_004.jpg data-img8=imagesimg_001.jpgRainforest Drive - Unit Adiv
div class=card-locationsvg width=10 height=10 viewBox=0 0 24 24 fill=none stroke=currentColor stroke-width=2.5 stroke-linecap=round stroke-linejoin=roundpath d=M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0zcircle cx=12 cy=10 r=3svg Ucluelet, BCdiv
div class=card-meta
span class=card-meta-item3 bedspan
span class=card-meta-item2 bathspan
span class=card-meta-itemMultiplexspan
div
div class=card-avail
div class=card-avail-labelAvailability span2 of 2 availablespandiv
div class=card-avail-trackdiv class=card-avail-fill style=width100%divdiv
div
div class=card-footer style=margin-top10pxdiv class=card-rent$5,000spanmospandiv
button class=card-apply-btn onclick=event.stopPropagation();openListingDetail(this.closest('.listing-card'))See morebutton
div
div
div
div class=listing-card data-region=Vancouver Island onclick=if(!event.target.closest('.card-save-btn'))openListingDetail(this)
div class=card-img style=background-image url('imagesrainforest-drive-aerial-3.jpg'); background-size cover; background-position center;
div class=card-img-overlaydiv
div class=card-price-tag$541,000div
button class=card-save-btn onclick=handleSaveClick(this) title=Save listingsvg width=14 height=14 viewBox=0 0 24 24 fill=none stroke=white stroke-width=2.5 stroke-linecap=round stroke-linejoin=roundpath d=M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78zsvgbutton
span class=card-badgeGround Floorspan
div
div class=card-body
div class=card-title data-video=httpswww.youtube.comembedXK9raw1l1fI data-img=imagesrainforest-drive-aerial-3.jpg data-img2=imagesrainforest-drive-aerial-1.jpg data-img3=imagesrainforest-drive-aerial-2.jpg data-img4=imagesrainforest-drive-aerial-4.jpg data-img5=imagesimg_003.jpg data-img6=imagesimg_004.jpg data-img7=imagesimg_001.jpgRainforest Drive - Unit Bdiv
div class=card-locationsvg width=10 height=10 viewBox=0 0 24 24 fill=none stroke=currentColor stroke-width=2.5 stroke-linecap=round stroke-linejoin=roundpath d=M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0zcircle cx=12 cy=10 r=3svg Ucluelet, BCdiv
div class=card-meta
span class=card-meta-item2 bedspan
span class=card-meta-item1 bathspan
span class=card-meta-itemMultiplexspan
div
div class=card-avail
div class=card-avail-labelAvailability span2 of 2 availablespandiv
div class=card-avail-trackdiv class=card-avail-fill style=width100%divdiv
div
div class=card-footer style=margin-top10pxdiv class=card-rent$3,000spanmospandiv
button class=card-apply-btn onclick=event.stopPropagation();openListingDetail(this.closest('.listing-card'))See morebutton
div
div
div
div class=listing-card data-region=Vancouver Island onclick=if(!event.target.closest('.card-save-btn'))openListingDetail(this)
div class=card-img style=background-image url('imagesimg_001.jpg'); background-size cover; background-position center;
div class=card-img-overlaydiv
div class=card-price-tag$541,000div
button class=card-save-btn onclick=handleSaveClick(this) title=Save listingsvg width=14 height=14 viewBox=0 0 24 24 fill=none stroke=white stroke-width=2.5 stroke-linecap=round stroke-linejoin=roundpath d=M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78zsvgbutton
span class=card-badge1st Floorspan
div
div class=card-body
div class=card-title data-video=httpswww.youtube.comembedXK9raw1l1fI data-img=imagesimg_001.jpg data-img2=imagesrainforest-drive-aerial-1.jpg data-img3=imagesrainforest-drive-aerial-2.jpg data-img4=imagesrainforest-drive-aerial-3.jpg data-img5=imagesimg_003.jpg data-img6=imagesimg_004.jpgRainforest Drive - Unit Cdiv
div class=card-locationsvg width=10 height=10 viewBox=0 0 24 24 fill=none stroke=currentColor stroke-width=2.5 stroke-linecap=round stroke-linejoin=roundpath d=M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0zcircle cx=12 cy=10 r=3svg Ucluelet, BCdiv
div class=card-meta
span class=card-meta-item2 bedspan
span class=card-meta-item1 bathspan
span class=card-meta-itemMultiplexspan
div
div class=card-avail
div class=card-avail-labelAvailability span2 of 2 availablespandiv
div class=card-avail-trackdiv class=card-avail-fill style=width100%divdiv
div
div class=card-footer style=margin-top10pxdiv class=card-rent$3,000spanmospandiv
button class=card-apply-btn onclick=event.stopPropagation();openListingDetail(this.closest('.listing-card'))See morebutton
div
div
div
div class=listing-card data-region=Vancouver Island onclick=if(!event.target.closest('.card-save-btn'))openListingDetail(this)
div class=card-img style=background-image url('imagesrainforest-drive-aerial-1.jpg'); background-size cover; background-position center;
div class=card-img-overlaydiv
div class=card-price-tag$781,000div
button class=card-save-btn onclick=handleSaveClick(this) title=Save listingsvg width=14 height=14 viewBox=0 0 24 24 fill=none stroke=white stroke-width=2.5 stroke-linecap=round stroke-linejoin=roundpath d=M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78zsvgbutton
span class=card-badge recommended-badgeMortgage Helperspan
div
div class=card-body
div class=card-title data-video=httpswww.youtube.comembedXK9raw1l1fI data-img=imagesrainforest-drive-aerial-1.jpg data-img2=imagesrainforest-drive-aerial-2.jpg data-img3=imagesrainforest-drive-aerial-3.jpg data-img4=imagesrainforest-drive-aerial-4.jpg data-img5=imagesimg_003.jpg data-img6=imagesimg_004.jpg data-img7=imagesimg_001.jpgNorah Street - Unit Adiv
div class=card-locationsvg width=10 height=10 viewBox=0 0 24 24 fill=none stroke=currentColor stroke-width=2.5 stroke-linecap=round stroke-linejoin=roundpath d=M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0zcircle cx=12 cy=10 r=3svg Ucluelet, BCdiv
div class=card-meta
span class=card-meta-item2 bedspan
span class=card-meta-item1 bathspan
span class=card-meta-itemMultiplexspan
div
div class=card-avail
div class=card-avail-labelAvailability span1 of 1 availablespandiv
div class=card-avail-trackdiv class=card-avail-fill style=width100%divdiv
div
div class=card-footer style=margin-top10pxdiv class=card-rent$5,000spanmospandiv
button class=card-apply-btn onclick=event.stopPropagation();openListingDetail(this.closest('.listing-card'))See morebutton
div
div
div
div class=listing-card data-region=Vancouver Island onclick=if(!event.target.closest('.card-save-btn'))openListingDetail(this)
div class=card-img style=background-image url('imagesrainforest-drive-aerial-4.jpg'); background-size cover; background-position center;
div class=card-img-overlaydiv
div class=card-price-tag$541,000div
button class=card-save-btn onclick=handleSaveClick(this) title=Save listingsvg width=14 height=14 viewBox=0 0 24 24 fill=none stroke=white stroke-width=2.5 stroke-linecap=round stroke-linejoin=roundpath d=M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78zsvgbutton
span class=card-badgeGround Floorspan
div
div class=card-body
div class=card-title data-video=httpswww.youtube.comembedXK9raw1l1fI data-img=imagesrainforest-drive-aerial-4.jpg data-img2=imagesrainforest-drive-aerial-1.jpg data-img3=imagesrainforest-drive-aerial-2.jpg data-img4=imagesrainforest-drive-aerial-3.jpg data-img5=imagesimg_003.jpg data-img6=imagesimg_004.jpg data-img7=imagesimg_001.jpgNorah Street - Unit Bdiv
div class=card-locationsvg width=10 height=10 viewBox=0 0 24 24 fill=none stroke=currentColor stroke-width=2.5 stroke-linecap=round stroke-linejoin=roundpath d=M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0zcircle cx=12 cy=10 r=3svg Ucluelet, BCdiv
div class=card-meta
span class=card-meta-item2 bedspan
span class=card-meta-item1 bathspan
span class=card-meta-itemMultiplexspan
div
div class=card-avail
div class=card-avail-labelAvailability span1 of 1 availablespandiv
div class=card-avail-trackdiv class=card-avail-fill style=width100%divdiv
div
div class=card-footer style=margin-top10pxdiv class=card-rent$3,000spanmospandiv
button class=card-apply-btn onclick=event.stopPropagation();openListingDetail(this.closest('.listing-card'))See morebutton
div
div
div
div class=listing-card data-region=Vancouver Island onclick=if(!event.target.closest('.card-save-btn'))openListingDetail(this)
div class=card-img style=background-image url('imagesimg_009.jpg'); background-size cover; background-position center;
div class=card-img-overlaydiv
div class=card-price-tag$541,000div
button class=card-save-btn onclick=handleSaveClick(this) title=Save listingsvg width=14 height=14 viewBox=0 0 24 24 fill=none stroke=white stroke-width=2.5 stroke-linecap=round stroke-linejoin=roundpath d=M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78zsvgbutton
span class=card-badge1st Floorspan
div
div class=card-body
div class=card-title data-video=httpswww.youtube.comembedXK9raw1l1fI data-img=imagesimg_009.jpg data-img2=imagesrainforest-drive-aerial-3.jpg data-img3=imagesrainforest-drive-aerial-1.jpg data-img4=imagesrainforest-drive-aerial-2.jpg data-img5=imagesrainforest-drive-aerial-4.jpg data-img6=imagesimg_003.jpg data-img7=imagesimg_004.jpg data-img8=imagesimg_001.jpgNorah Street - Unit Cdiv
div class=card-locationsvg width=10 height=10 viewBox=0 0 24 24 fill=none stroke=currentColor stroke-width=2.5 stroke-linecap=round stroke-linejoin=roundpath d=M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0zcircle cx=12 cy=10 r=3svg Ucluelet, BCdiv
div class=card-meta
span class=card-meta-item2 bedspan
span class=card-meta-item1 bathspan
span class=card-meta-itemMultiplexspan
div
div class=card-avail
div class=card-avail-labelAvailability span1 of 1 availablespandiv
div class=card-avail-trackdiv class=card-avail-fill style=width100%divdiv
div
div class=card-footer style=margin-top10pxdiv class=card-rent$3,000spanmospandiv
button class=card-apply-btn onclick=event.stopPropagation();openListingDetail(this.closest('.listing-card'))See morebutton
div
div
div
div class=listing-card data-region=Vancouver Island onclick=if(!event.target.closest('.card-save-btn'))openListingDetail(this)
div class=card-img style=background-image url('imagesimg_011.jpg'); background-size cover; background-position center;
div class=card-img-overlaydiv
div class=card-price-tag$781,000div
button class=card-save-btn onclick=handleSaveClick(this) title=Save listingsvg width=14 height=14 viewBox=0 0 24 24 fill=none stroke=white stroke-width=2.5 stroke-linecap=round stroke-linejoin=roundpath d=M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78zsvgbutton
span class=card-badge recommended-badgeMortgage Helperspan
div
div class=card-body
div class=card-title data-video=httpsvideo.gumlet.io66041d40603db7e8cad20c31672e4fa71f39ce9ec65b6a9b672e4fa71f39ce9ec65b6a9b_0_540p.m3u8 data-img=imagesimg_011.jpg data-img2=imagesimg_010.jpg data-img3=imagesimg_004.jpg data-img4=imagesweyerhaeuser-aerial.jpg data-img5=imagesweyerhaeuser-site-overview.jpg data-img6=imagesweyerhaeuser-lot-marker.jpg data-img7=imagesweyerhaeuser-town-aerial.jpgOcean West - Unit Adiv
div class=card-locationsvg width=10 height=10 viewBox=0 0 24 24 fill=none stroke=currentColor stroke-width=2.5 stroke-linecap=round stroke-linejoin=roundpath d=M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0zcircle cx=12 cy=10 r=3svg Ucluelet, BCdiv
div class=card-meta
span class=card-meta-item3 bedspan
span class=card-meta-item2 bathspan
span class=card-meta-itemMultiplexspan
div
div class=card-avail
div class=card-avail-labelAvailability span2 of 2 availablespandiv
div class=card-avail-trackdiv class=card-avail-fill style=width100%divdiv
div
div class=card-footer style=margin-top10pxdiv class=card-rent$5,000spanmospandiv
button class=card-apply-btn onclick=event.stopPropagation();openListingDetail(this.closest('.listing-card'))See morebutton
div
div
div
div class=listing-card data-region=Vancouver Island onclick=if(!event.target.closest('.card-save-btn'))openListingDetail(this)
div class=card-img style=background-image url('imagesweyerhaeuser-aerial.jpg'); background-size cover; background-position center;
div class=card-img-overlaydiv
div class=card-price-tag$541,000div
button class=card-save-btn onclick=handleSaveClick(this) title=Save listingsvg width=14 height=14 viewBox=0 0 24 24 fill=none stroke=white stroke-width=2.5 stroke-linecap=round stroke-linejoin=roundpath d=M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78zsvgbutton
span class=card-badgeGround Floorspan
div
div class=card-body
div class=card-title data-video=httpsvideo.gumlet.io66041d40603db7e8cad20c31672e4fa71f39ce9ec65b6a9b672e4fa71f39ce9ec65b6a9b_0_540p.m3u8 data-img=imagesweyerhaeuser-aerial.jpg data-img2=imagesimg_011.jpg data-img3=imagesimg_010.jpg data-img4=imagesimg_004.jpg data-img5=imagesweyerhaeuser-site-overview.jpg data-img6=imagesweyerhaeuser-lot-marker.jpg data-img7=imagesweyerhaeuser-town-aerial.jpgOcean West - Unit Bdiv
div class=card-locationsvg width=10 height=10 viewBox=0 0 24 24 fill=none stroke=currentColor stroke-width=2.5 stroke-linecap=round stroke-linejoin=roundpath d=M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0zcircle cx=12 cy=10 r=3svg Ucluelet, BCdiv
div class=card-meta
span class=card-meta-item2 bedspan
span class=card-meta-item1 bathspan
span class=card-meta-itemMultiplexspan
div
div class=card-avail
div class=card-avail-labelAvailability span2 of 2 availablespandiv
div class=card-avail-trackdiv class=card-avail-fill style=width100%divdiv
div
div class=card-footer style=margin-top10pxdiv class=card-rent$3,000spanmospandiv
button class=card-apply-btn onclick=event.stopPropagation();openListingDetail(this.closest('.listing-card'))See morebutton
div
div
div
div class=listing-card data-region=Vancouver Island onclick=if(!event.target.closest('.card-save-btn'))openListingDetail(this)
div class=card-img style=background-image url('imagesimg_012.jpg'); background-size cover; background-position center;
div class=card-img-overlaydiv
div class=card-price-tag$450,000div
button class=card-save-btn onclick=handleSaveClick(this) title=Save listingsvg width=14 height=14 viewBox=0 0 24 24 fill=none stroke=white stroke-width=2.5 stroke-linecap=round stroke-linejoin=roundpath d=M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78zsvgbutton
span class=card-badge recommended-badgeMortgage Helperspan
div
div class=card-body
div class=card-title data-video=httpswww.youtube.comembedSKgFdyuzTrksi=JF2eGde3J2UhgGhH data-img=imagesimg_012.jpg data-img2=imagesimg_010.jpg data-img3=imagesimg_004.jpgRiver Road - Unit Adiv
div class=card-locationsvg width=10 height=10 viewBox=0 0 24 24 fill=none stroke=currentColor stroke-width=2.5 stroke-linecap=round stroke-linejoin=roundpath d=M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0zcircle cx=12 cy=10 r=3svg Port Alberni, BCdiv
div class=card-meta
span class=card-meta-item3 bedspan
span class=card-meta-item2 bathspan
span class=card-meta-itemMultiplexspan
div
div class=card-avail
div class=card-avail-labelAvailability span1 of 1 availablespandiv
div class=card-avail-trackdiv class=card-avail-fill style=width100%divdiv
div
div class=card-footer style=margin-top10pxdiv class=card-rent$3,950spanmospandiv
button class=card-apply-btn onclick=event.stopPropagation();openListingDetail(this.closest('.listing-card'))See morebutton
div
div
div
div class=listing-card data-region=Vancouver Island onclick=if(!event.target.closest('.card-save-btn'))openListingDetail(this)
div class=card-img style=background-image url('imagesimg_012.jpg'); background-size cover; background-position center;
div class=card-img-overlaydiv
div class=card-price-tag$460,000div
button class=card-save-btn onclick=handleSaveClick(this) title=Save listingsvg width=14 height=14 viewBox=0 0 24 24 fill=none stroke=white stroke-width=2.5 stroke-linecap=round stroke-linejoin=roundpath d=M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78zsvgbutton
span class=card-badgeGround Floorspan
div
div class=card-body
div class=card-title data-video=httpswww.youtube.comembedSKgFdyuzTrksi=JF2eGde3J2UhgGhH data-img=imagesimg_012.jpg data-img2=imagesimg_010.jpg data-img3=imagesimg_004.jpgRiver Road - Unit Bdiv
div class=card-locationsvg width=10 height=10 viewBox=0 0 24 24 fill=none stroke=currentColor stroke-width=2.5 stroke-linecap=round stroke-linejoin=roundpath d=M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0zcircle cx=12 cy=10 r=3svg Port Alberni, BCdiv
div class=card-meta
span class=card-meta-item2 bedspan
span class=card-meta-item1 bathspan
span class=card-meta-itemMultiplexspan
div
div class=card-avail
div class=card-avail-labelAvailability span1 of 1 availablespandiv
div class=card-avail-trackdiv class=card-avail-fill style=width100%divdiv
div
div class=card-footer style=margin-top10pxdiv class=card-rent$2,300spanmospandiv
button class=card-apply-btn onclick=event.stopPropagation();openListingDetail(this.closest('.listing-card'))See morebutton
div
div
div
div class=listing-card data-region=Vancouver Island onclick=if(!event.target.closest('.card-save-btn'))openListingDetail(this)
div class=card-img style=background-image url('imagesimg_006.jpg'); background-size cover; background-position center;
div class=card-img-overlaydiv
div class=card-price-tag$460,000div
button class=card-save-btn onclick=handleSaveClick(this) title=Save listingsvg width=14 height=14 viewBox=0 0 24 24 fill=none stroke=white stroke-width=2.5 stroke-linecap=round stroke-linejoin=roundpath d=M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78zsvgbutton
span class=card-badgeGround Floorspan
div
div class=card-body
div class=card-title data-video=httpswww.youtube.comembedSKgFdyuzTrksi=JF2eGde3J2UhgGhH data-img=imagesimg_006.jpg data-img2=imagesimg_013.jpg data-img3=imagesimg_010.jpg data-img4=imagesimg_004.jpgCompton Road - Unit Bdiv
div class=card-locationsvg width=10 height=10 viewBox=0 0 24 24 fill=none stroke=currentColor stroke-width=2.5 stroke-linecap=round stroke-linejoin=roundpath d=M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0zcircle cx=12 cy=10 r=3svg Port Alberni, BCdiv
div class=card-meta
span class=card-meta-item2 bedspan
span class=card-meta-item1 bathspan
span class=card-meta-itemMultiplexspan
div
div class=card-avail
div class=card-avail-labelAvailability span1 of 1 availablespandiv
div class=card-avail-trackdiv class=card-avail-fill style=width100%divdiv
div
div class=card-footer style=margin-top10pxdiv class=card-rent$2,300spanmospandiv
button class=card-apply-btn onclick=event.stopPropagation();openListingDetail(this.closest('.listing-card'))See morebutton
div
div
div
div class=listing-card data-region=Vancouver Island onclick=if(!event.target.closest('.card-save-btn'))openListingDetail(this)
div class=card-img style=background-image url('imagesweyerhaeuser-community-garden.jpg'); background-size cover; background-position center;
div class=card-img-overlaydiv
div class=card-price-tag$541,000div
button class=card-save-btn onclick=handleSaveClick(this) title=Save listingsvg width=14 height=14 viewBox=0 0 24 24 fill=none stroke=white stroke-width=2.5 stroke-linecap=round stroke-linejoin=roundpath d=M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78zsvgbutton
span class=card-badge1st Floorspan
div
div class=card-body
div class=card-title data-video=httpsvideo.gumlet.io66041d40603db7e8cad20c31672e4fa71f39ce9ec65b6a9b672e4fa71f39ce9ec65b6a9b_0_540p.m3u8 data-img=imagesweyerhaeuser-community-garden.jpg data-img2=imagesimg_011.jpg data-img3=imagesimg_010.jpg data-img4=imagesimg_004.jpg data-img5=imagesweyerhaeuser-aerial.jpg data-img6=imagesweyerhaeuser-site-overview.jpg data-img7=imagesweyerhaeuser-lot-marker.jpg data-img8=imagesweyerhaeuser-town-aerial.jpgOcean West - Unit Cdiv
div class=card-locationsvg width=10 height=10 viewBox=0 0 24 24 fill=none stroke=currentColor stroke-width=2.5 stroke-linecap=round stroke-linejoin=roundpath d=M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0zcircle cx=12 cy=10 r=3svg Ucluelet, BCdiv
div class=card-meta
span class=card-meta-item2 bedspan
span class=card-meta-item1 bathspan
span class=card-meta-itemMultiplexspan
div
div class=card-avail
div class=card-avail-labelAvailability span2 of 2 availablespandiv
div class=card-avail-trackdiv class=card-avail-fill style=width100%divdiv
div
div class=card-footer style=margin-top10pxdiv class=card-rent$3,000spanmospandiv
button class=card-apply-btn onclick=event.stopPropagation();openListingDetail(this.closest('.listing-card'))See morebutton
div
div
div
div class=listing-card data-region=Vancouver Island onclick=if(!event.target.closest('.card-save-btn'))openListingDetail(this)
div class=card-img style=background-image url('imagesimg_004.jpg'); background-size cover; background-position center;
div class=card-img-overlaydiv
div class=card-price-tag$450,000div
button class=card-save-btn onclick=handleSaveClick(this) title=Save listingsvg width=14 height=14 viewBox=0 0 24 24 fill=none stroke=white stroke-width=2.5 stroke-linecap=round stroke-linejoin=roundpath d=M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78zsvgbutton
span class=card-badge1st Floorspan
div
div class=card-body
div class=card-title data-video=httpswww.youtube.comembedSKgFdyuzTrksi=JF2eGde3J2UhgGhH data-img=imagesimg_004.jpg data-img2=imagesimg_012.jpg data-img3=imagesimg_010.jpgRiver Road - Unit Cdiv
div class=card-locationsvg width=10 height=10 viewBox=0 0 24 24 fill=none stroke=currentColor stroke-width=2.5 stroke-linecap=round stroke-linejoin=roundpath d=M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0zcircle cx=12 cy=10 r=3svg Port Alberni, BCdiv
div class=card-meta
span class=card-meta-item2 bedspan
span class=card-meta-item1 bathspan
span class=card-meta-itemMultiplexspan
div
div class=card-avail
div class=card-avail-labelAvailability span1 of 1 availablespandiv
div class=card-avail-trackdiv class=card-avail-fill style=width100%divdiv
div
div class=card-footer style=margin-top10pxdiv class=card-rent$2,300spanmospandiv
button class=card-apply-btn onclick=event.stopPropagation();openListingDetail(this.closest('.listing-card'))See morebutton
div
div
div
div class=listing-card data-region=Vancouver Island onclick=if(!event.target.closest('.card-save-btn'))openListingDetail(this)
div class=card-img style=background-image url('imagesimg_007.jpg'); background-size cover; background-position center;
div class=card-img-overlaydiv
div class=card-price-tag$450,000div
button class=card-save-btn onclick=handleSaveClick(this) title=Save listingsvg width=14 height=14 viewBox=0 0 24 24 fill=none stroke=white stroke-width=2.5 stroke-linecap=round stroke-linejoin=roundpath d=M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78zsvgbutton
span class=card-badge1st Floorspan
div
div class=card-body
div class=card-title data-video=httpswww.youtube.comembedSKgFdyuzTrksi=JF2eGde3J2UhgGhH data-img=imagesimg_007.jpg data-img2=imagesimg_013.jpg data-img3=imagesimg_010.jpg data-img4=imagesimg_004.jpgCompton Road - Unit Cdiv
div class=card-locationsvg width=10 height=10 viewBox=0 0 24 24 fill=none stroke=currentColor stroke-width=2.5 stroke-linecap=round stroke-linejoin=roundpath d=M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0zcircle cx=12 cy=10 r=3svg Port Alberni, BCdiv
div class=card-meta
span class=card-meta-item2 bedspan
span class=card-meta-item1 bathspan
span class=card-meta-itemMultiplexspan
div
div class=card-avail
div class=card-avail-labelAvailability span1 of 1 availablespandiv
div class=card-avail-trackdiv class=card-avail-fill style=width100%divdiv
div
div class=card-footer style=margin-top10pxdiv class=card-rent$2,300spanmospandiv
button class=card-apply-btn onclick=event.stopPropagation();openListingDetail(this.closest('.listing-card'))See morebutton
div
div
div
div
div id=dash-load-more
button id=dash-load-more-btn onclick=handleViewAllHomesClick()View All Homesbutton
div id=dash-page-dots
span class=dash-page-dot activespan
span class=dash-page-dotspan
span class=dash-page-dotspan
div
div
div id=muni-partnership-bar
div id=muni-partnership-text
div id=muni-partnership-titlePartnering with municipalities to solve housing now.div
div id=muni-partnership-subIGVhope is delivering in partnership with the District of Ucluelet and the City of Port Alberni. We work with municipal partners to bring private supply to their housing goals without public subsidy.div
div
button id=muni-partnership-btn onclick=window.open('httpsigvhousing.communicipalities','_blank');Municipal Partnershipsbutton
div
div id=voices-section
div id=voices-inner
div id=voices-eyebrowSupportive Voicesdiv
div id=voices-titleWhat the housing experts are span id=voices-title-lightsaying.spandiv
div id=voices-grid
div class=voice-card
div class=voice-quote-mark“div
div class=voice-textOne of my greatest concerns for the next generation of Canadian homeowners is the ability to accumulate the down payment, even if the monthly payments can be afforded. If a program can solve that problem with genuine legal protections, that is a game-changer for middle-income families.div
div class=voice-footer
a href=httpswww.linkedin.cominmark-jewells-mba-525742b target=_blank rel=noopenerimg class=voice-avatar src=imagesimg_015.jpg alt=Mark Jewellsa
div class=voice-person
div class=voice-nameMark Jewellsdiv
div class=voice-roleFinancing Specialist, Calgary, ABdiv
div
div
div
div class=voice-card
div class=voice-quote-mark“div
div class=voice-textProperty ownership is one of the most powerful wealth-building tools available. Programs that create genuine structural pathways, not tricks, not traps, are precisely what this market needs right now.div
div class=voice-footer
a href=httpsiloverealestate.tvabout target=_blank rel=noopenerimg class=voice-avatar src=imagesimg_016.jpg alt=Dymphna Boholta
div class=voice-person
div class=voice-nameDymphna Boholtdiv
div class=voice-roleProperty Economist & Financial Educatordiv
div
div
div
div class=voice-card
div class=voice-quote-mark“div
div class=voice-textThree decades in real estate teaches you one thing above all homeownership changes lives — not just today, but for the generation that follows. The housing shortage on Vancouver Island is real, and the families who need a path forward deserve more than a waiting game while the market keeps moving out of reach. This is the kind of solution communities like ours have been asking for.div
div class=voice-footer
a href=httpswww.linkedin.cominjudygrayteam target=_blank rel=noopenerimg class=voice-avatar src=imagesimg_017.jpg alt=Judy Graya
div class=voice-person
div class=voice-nameJudy Graydiv
div class=voice-roleREALTOR®, REMAX · Ucluelet, Vancouver Islanddiv
div
div
div
div
div
div
div id=ecosystem-section
div id=ecosystem-inner
div id=ecosystem-titleIGVhope is part of something span id=ecosystem-title-boldbigger.spandiv
div id=ecosystem-subIGVhope is built into a vertically integrated housing platform, from the way homes are manufactured to the way they're financed. Three divisions, one mission to make homes easier to build and possible to own.div
div id=ecosystem-grid
div class=ecosystem-card
a class=ecosystem-logo-strip href=httpswww.igvbuild.com target=_blank rel=noopener
img class=ecosystem-logo-img src=imagesimg_018.png alt=IGV Build Systems
a
div class=ecosystem-card-body
div class=ecosystem-card-descModern construction that makes quality homes faster and more affordable to build.div
div
div
div class=ecosystem-card
a class=ecosystem-logo-strip href=httpswww.igvhousing.com target=_blank rel=noopener
img class=ecosystem-logo-img src=imagesimg_019.png alt=IGV Housing
a
div class=ecosystem-card-body
div class=ecosystem-card-descOur parent company dedicated to solving housing accessibility at scale, delivering hope and opportunity to future generations.div
div
div
div class=ecosystem-card
a class=ecosystem-logo-strip href=httpswww.igvcapital.com target=_blank rel=noopener
img class=ecosystem-logo-img src=imagesimg_020.png alt=IGV Capital
a
div class=ecosystem-card-body
div class=ecosystem-card-descSmarter financial architecture for housing, aligning investors, projects, and ESG impact.div
div
div
div
div
div
div
footer id=dash-footer
div class=footer-block
div id=footer-disclosures
div id=disclosures-titleDisclosuresdiv
pThis site is operated by IGV Housing Inc. (IGVhousing), the parent company of the IGVhope program. IGVhousing is not a licensed real estate brokerage, mortgage lender, or financial advisor, and nothing on this website constitutes legal, tax, financial, or investment advice. Nothing on this site is an offer of tenancy or an agreement of purchase and sale. Participation in the IGVhope program is subject to eligibility, application review, and execution of a formal occupancy and purchase agreement.p
pHomeownership involves financial commitment and risk. By using this site, you acknowledge that 1) housing markets can rise or fall, and the future value of any home is not guaranteed; 2) occupancy contributions and Year 10 purchase terms are illustrative and subject to change based on individual eligibility, property availability, and final agreement terms; 3) IGVhousing does not guarantee mortgage qualification, program eligibility, or that any participant will ultimately complete a home purchase; and 4) you should seek independent legal, financial, and tax advice before entering into any occupancy contribution or home purchase arrangement. Past program outcomes are not indicative of future results.p
pInformation on this site has been prepared in good faith from sources IGVhousing believes to be reliable, but we make no warranty as to its accuracy or completeness and accept no liability for errors or omissions. Hyperlinks to third-party or partner organization sites, including municipal partners, do not constitute an endorsement by IGVhousing of their content. By accessing this site, you agree to IGVhousing's a href=httpsigvhousing.comterms-of-service target=_blank rel=noopenerTerms of Servicea.p
pProperties, developments, and unit counts referenced on this site are subject to council approval, permitting, and other regulatory processes, and are not guaranteed to proceed as described.p
pWe acknowledge and thank the First Nations People, past, present, and future, for their stewardship, care, and leadership on the lands where we live, work and build. We are guests on these lands and acknowledge our responsibility to the land, its resources, and its people.p
div
div
div class=footer-block footer-divider
div id=footer-sitemap
div class=sitemap-col
div class=sitemap-headingIGV Housingdiv
a onclick=scrollToListings();Platforma
a href=httpswww.igvhope.comhowitworksMunicipalitiesa
a href=mailtoinvest@igvhousing.comInvestorsa
div
div class=sitemap-col
div class=sitemap-headingIGV Divisionsdiv
a href=httpswww.igvhousing.com target=_blank rel=noopenerIGV Housinga
a href=httpswww.igvbuild.com target=_blank rel=noopenerIGV Build Systemsa
a href=httpswww.igvcapital.com target=_blank rel=noopenerIGV Capitala
div
div class=sitemap-col
div class=sitemap-headingSitemapdiv
a href=httpshowitworks.pages.devHow It Worksa
a href=httpsigvhope-faq.pages.devFAQa
a href=httpsresources-4bo.pages.devResourcesa
div
div class=sitemap-col
div class=sitemap-headingEnquiriesdiv
a href=mailtoinvest@igvhousing.comInvestor Enquirya
a href=mailtopartners@igvhousing.comDeveloper Partnersa
a href=mailtopress@igvhousing.comPressa
div id=sitemap-social
a href=httpswww.facebook.comigvhope target=_blank rel=noopener aria-label=Facebook
svg width=14 height=14 viewBox=0 0 24 24 fill=currentColorpath d=M22 12.06C22 6.5 17.52 2 12 2S2 6.5 2 12.06c0 5.02 3.66 9.18 8.44 9.94v-7.03H7.9v-2.91h2.54V9.85c0-2.51 1.49-3.9 3.77-3.9 1.09 0 2.24.2 2.24.2v2.46h-1.26c-1.24 0-1.63.77-1.63 1.56v1.89h2.78l-.44 2.91h-2.34V22c4.78-.76 8.44-4.92 8.44-9.94zsvg
a
a href=httpswww.linkedin.comcompanyigvhope target=_blank rel=noopener aria-label=LinkedIn
svg width=14 height=14 viewBox=0 0 24 24 fill=currentColorpath d=M20.45 20.45h-3.55v-5.57c0-1.33-.02-3.04-1.85-3.04-1.85 0-2.14 1.45-2.14 2.94v5.67H9.36V9h3.41v1.56h.05c.48-.9 1.64-1.85 3.38-1.85 3.61 0 4.28 2.38 4.28 5.47zM5.34 7.43a2.06 2.06 0 1 1 0-4.12 2.06 2.06 0 0 1 0 4.12zM7.12 20.45H3.56V9h3.56zsvg
a
a href=httpswww.instagram.comigvhope target=_blank rel=noopener aria-label=Instagram
svg width=14 height=14 viewBox=0 0 24 24 fill=none stroke=currentColor stroke-width=2rect x=3 y=3 width=18 height=18 rx=4circle cx=12 cy=12 r=4circle cx=17.5 cy=6.5 r=1svg
a
div
div
div
div
div class=footer-block footer-divider
div id=footer-bottom-bar
span id=footer-copyright© 2026 IGVhope. All rights reserved.span
div id=footer-bottom-links
a href=httpsigvhousing.comprivacy-policy target=_blank rel=noopenerPrivacya
a href=httpsigvhousing.comterms-of-service target=_blank rel=noopenerTermsa
a href=httpsigvhousing.comaccessibility target=_blank rel=noopenerAccessibilitya
div
div
div
footer
div
div
style
#listing-detail {
position fixed;
inset 0;
z-index 500;
display none;
flex-direction column;
background #F0EDE6;
font-family 'Montserrat', sans-serif;
}
#listing-detail.open {
display flex;
}
---------- Account View ----------
#account-view {
position fixed;
inset 0;
z-index 700;
display none;
flex-direction column;
background #F0EDE6;
font-family 'Montserrat', sans-serif;
overflow-y auto;
}
#account-view.open {
display flex;
}
.account-topbar {
display flex;
align-items center;
justify-content space-between;
background #1a4848;
padding 18px 28px;
flex-shrink 0;
}
.account-back-btn {
display flex;
align-items center;
gap 6px;
background none;
border none;
color rgba(255,255,255,0.85);
font-family 'Montserrat', sans-serif;
font-size 13px;
font-weight 600;
cursor pointer;
padding 6px 8px;
transition color 0.15s;
}
.account-back-btnhover { color #ffffff; }
.account-topbar-title {
color #ffffff;
font-size 16px;
font-weight 700;
letter-spacing 0.01em;
}
.account-topbar-spacer { width 130px; display flex; align-items center; justify-content flex-end; }
.account-tabs {
display flex;
gap 8px;
padding 18px 28px 0;
max-width 900px;
margin 0 auto;
width 100%;
box-sizing border-box;
flex-wrap wrap;
}
.account-tab {
font-family 'Montserrat', sans-serif;
font-size 12px;
font-weight 700;
letter-spacing 0.02em;
color #1A5C50;
background rgba(26,92,80,0.08);
border 1.5px solid transparent;
border-radius 999px;
padding 9px 18px;
cursor pointer;
transition background 0.15s, color 0.15s, border-color 0.15s;
}
.account-tabhover { background rgba(26,92,80,0.15); }
.account-tab.active {
background #1A5C50;
color #ffffff;
}
.account-content {
max-width 900px;
margin 0 auto;
width 100%;
box-sizing border-box;
padding 24px 28px 60px;
flex 1;
}
.account-panel { display none; }
.account-panel.active { display block; }
.account-loading {
display none;
justify-content center;
padding 60px 0;
}
.account-spinner {
width 28px;
height 28px;
border 3px solid rgba(26,92,80,0.15);
border-top-color #1A5C50;
border-radius 50%;
animation account-spin 0.8s linear infinite;
}
@keyframes account-spin { to { transform rotate(360deg); } }
.account-empty-state {
text-align center;
padding 70px 20px;
}
.account-empty-title {
font-family 'Montserrat', sans-serif;
font-size 16px;
font-weight 700;
color #123D36;
margin-bottom 8px;
}
.account-empty-sub {
font-family 'Montserrat', sans-serif;
font-size 13px;
font-weight 500;
color #777;
max-width 360px;
margin 0 auto;
line-height 1.5;
}
.app-card {
display flex;
align-items center;
justify-content space-between;
gap 16px;
background #ffffff;
border-radius 12px;
padding 18px 20px;
margin-bottom 12px;
box-shadow 0 2px 10px rgba(0,0,0,0.05);
}
.app-card-title {
font-family 'Montserrat', sans-serif;
font-size 14px;
font-weight 700;
color #123D36;
margin-bottom 4px;
}
.app-card-date {
font-family 'Montserrat', sans-serif;
font-size 11px;
font-weight 500;
color #999;
}
.stage-pill {
font-family 'Montserrat', sans-serif;
font-size 10px;
font-weight 700;
letter-spacing 0.03em;
text-transform uppercase;
padding 6px 12px;
border-radius 999px;
white-space nowrap;
flex-shrink 0;
}
.stage-pill.stage-progress { background rgba(200,104,58,0.15); color #C8683A; }
.stage-pill.stage-approved { background rgba(26,92,80,0.15); color #1A5C50; }
.stage-pill.stage-declined { background rgba(180,60,60,0.12); color #B43C3C; }
.stage-pill.stage-withdrawn { background rgba(0,0,0,0.08); color #777; }
.saved-account-card {
display flex;
gap 14px;
background #ffffff;
border-radius 12px;
padding 14px;
margin-bottom 12px;
box-shadow 0 2px 10px rgba(0,0,0,0.05);
}
.saved-account-card-missing { opacity 0.7; }
.saved-account-img {
width 110px;
height 82px;
border-radius 8px;
flex-shrink 0;
background linear-gradient(135deg, #1A4848, #2B6B5A);
}
.saved-account-body { flex 1; min-width 0; }
.saved-account-title {
font-family 'Montserrat', sans-serif;
font-size 14px;
font-weight 700;
color #123D36;
margin-bottom 3px;
}
.saved-account-meta {
font-family 'Montserrat', sans-serif;
font-size 11px;
font-weight 500;
color #888;
margin-bottom 3px;
}
.saved-account-price {
font-family 'Montserrat', sans-serif;
font-size 13px;
font-weight 700;
color #C8683A;
margin-bottom 10px;
}
.saved-account-missing-note {
font-family 'Montserrat', sans-serif;
font-size 11px;
font-weight 500;
color #999;
font-style italic;
margin-bottom 10px;
}
.saved-account-actions { display flex; gap 10px; }
.saved-account-view, .saved-account-remove {
font-family 'Montserrat', sans-serif;
font-size 11px;
font-weight 700;
letter-spacing 0.02em;
border-radius 999px;
padding 7px 14px;
cursor pointer;
transition background 0.15s, color 0.15s;
}
.saved-account-view {
background #1A5C50;
color #ffffff;
border none;
}
.saved-account-viewhover { background #123D36; }
.saved-account-remove {
background transparent;
color #999;
border 1.5px solid rgba(0,0,0,0.12);
}
.saved-account-removehover { color #B43C3C; border-color #B43C3C; }
.notification-card {
display flex;
align-items flex-start;
gap 12px;
background #ffffff;
border-radius 12px;
padding 16px 18px;
margin-bottom 10px;
box-shadow 0 2px 10px rgba(0,0,0,0.05);
cursor pointer;
transition background 0.15s;
}
.notification-cardhover { background #fafafa; }
.notification-dot {
width 8px;
height 8px;
border-radius 50%;
background transparent;
margin-top 5px;
flex-shrink 0;
}
.notification-card.notification-unread .notification-dot { background #da8d27; }
.notification-body { flex 1; }
.notification-message {
font-family 'Montserrat', sans-serif;
font-size 13px;
font-weight 600;
color #123D36;
line-height 1.5;
margin-bottom 4px;
}
.notification-card.notification-unread .notification-message { font-weight 700; }
.notification-date {
font-family 'Montserrat', sans-serif;
font-size 11px;
font-weight 500;
color #999;
}
@media (max-width 640px) {
.account-topbar { padding 14px 18px; }
.account-topbar-title { font-size 14px; }
.account-topbar-spacer { display none; }
.account-tabs { padding 14px 18px 0; }
.account-content { padding 18px 18px 50px; }
.saved-account-card { flex-direction column; }
.saved-account-img { width 100%; height 140px; }
}
#detail-colour-wipe {
position fixed;
inset 0;
z-index 750;
pointer-events none;
overflow hidden;
}
#detail-colour-wipe .wipe-strip {
position absolute;
top 0;
bottom 0;
width 25%;
}
#detail-colour-wipe .wipe-strip-1 { left 0%; background var(--amber); transform translateX(-100%); transition transform 0.2s cubic-bezier(0.76,0,0.24,1) 0s; }
#detail-colour-wipe .wipe-strip-2 { left 25%; background var(--teal-mid); transform translateX(-200%); transition transform 0.2s cubic-bezier(0.76,0,0.24,1) 0.04s; }
#detail-colour-wipe .wipe-strip-3 { left 50%; background var(--amber-light); transform translateX(-300%); transition transform 0.2s cubic-bezier(0.76,0,0.24,1) 0.08s; }
#detail-colour-wipe .wipe-strip-4 { left 75%; background var(--teal-deep); transform translateX(-400%); transition transform 0.2s cubic-bezier(0.76,0,0.24,1) 0.12s; }
#detail-colour-wipe.active .wipe-strip-1,
#detail-colour-wipe.active .wipe-strip-2,
#detail-colour-wipe.active .wipe-strip-3,
#detail-colour-wipe.active .wipe-strip-4 { transform translateX(0%); }
#detail-colour-wipe.reveal .wipe-strip-1 { transform translateX(400%); transition transform 0.2s cubic-bezier(0.76,0,0.24,1) 0.12s; }
#detail-colour-wipe.reveal .wipe-strip-2 { transform translateX(300%); transition transform 0.2s cubic-bezier(0.76,0,0.24,1) 0.08s; }
#detail-colour-wipe.reveal .wipe-strip-3 { transform translateX(200%); transition transform 0.2s cubic-bezier(0.76,0,0.24,1) 0.04s; }
#detail-colour-wipe.reveal .wipe-strip-4 { transform translateX(100%); transition transform 0.2s cubic-bezier(0.76,0,0.24,1) 0s; }
#detail-tabs {
display flex;
border-bottom 2px solid rgba(26,92,80,0.1);
margin-bottom 24px;
gap 0;
overflow-x auto;
-webkit-overflow-scrolling touch;
scrollbar-width none;
}
#detail-tabs-webkit-scrollbar { display none; }
#detail-tabs-wrap { position relative; }
.detail-tabs-fade { position absolute; top 0; bottom 2px; width 32px; pointer-events none; opacity 0; transition opacity 0.2s ease; z-index 2; display flex; align-items center; }
.detail-tabs-fade.left { left 0; background linear-gradient(90deg, #F0EDE6 40%, rgba(240,237,230,0)); justify-content flex-start; }
.detail-tabs-fade.right { right 0; background linear-gradient(270deg, #F0EDE6 40%, rgba(240,237,230,0)); justify-content flex-end; }
.detail-tabs-fade.show { opacity 1; }
.detail-tabs-fade svg { flex-shrink 0; }
.tab-label-short { display none; }
@media (max-width 480px) {
.detail-tab { padding 12px 14px; font-size 10px; }
.tab-label-full { display none; }
.tab-label-short { display inline; }
}
.detail-tab {
padding 12px 20px;
font-family 'Montserrat', sans-serif;
font-size 11px;
font-weight 700;
letter-spacing 0.04em;
color #999;
background none;
border none;
border-bottom 2px solid transparent;
margin-bottom -2px;
cursor pointer;
transition color 0.18s, border-color 0.18s;
white-space nowrap;
flex-shrink 0;
}
.detail-tabhover { color #1A5C50; }
.detail-tab.active { color #1A5C50; border-bottom-color #1A5C50; }
.detail-tab.locked { color #bbb; }
.detail-tab.lockedhover { color #999; }
.tab-lock-icon { display none; margin-left 4px; vertical-align -1px; }
.detail-tab.locked .tab-lock-icon { display inline-block; }
.tab-panel { padding-bottom 32px; }
.gated-blur { filter blur(7px); user-select none; cursor pointer; transition filter 0.15s; }
.gated-blurhover { filter blur(5px); }
.nb-grid {
display grid;
grid-template-columns repeat(auto-fill, minmax(220px, 1fr));
gap 16px;
margin-bottom 8px;
}
.nb-category {
background white;
border-radius 10px;
padding 14px 16px;
box-shadow 0 1px 4px rgba(0,0,0,0.06);
}
.nb-cat-header {
display flex;
align-items center;
gap 7px;
font-size 11px;
font-weight 700;
color #123D36;
margin-bottom 10px;
padding-bottom 8px;
border-bottom 1px solid rgba(26,92,80,0.08);
}
.nb-item {
display flex;
justify-content space-between;
align-items center;
padding 4px 0;
font-size 11px;
}
.nb-name { color #555; font-weight 500; }
.nb-dist { color #da8d27; font-weight 700; font-size 10px; }
.stats-section { margin-bottom 28px; }
.stat-rows { display flex; flex-direction column; gap 0; margin-bottom 4px; }
.stat-row {
display flex;
align-items center;
justify-content space-between;
padding 9px 14px;
font-size 11px;
background white;
border-bottom 1px solid rgba(26,92,80,0.06);
}
.stat-rowfirst-child { border-radius 8px 8px 0 0; }
.stat-rowlast-child { border-radius 0 0 8px 8px; border-bottom none; }
.stat-rowonly-child { border-radius 8px; border-bottom none; }
.stat-label { color #666; font-weight 500; }
.stat-val { color #123D36; font-weight 700; }
.stat-bar-wrap {
flex 1;
margin 0 16px;
height 4px;
background rgba(26,92,80,0.1);
border-radius 2px;
overflow hidden;
}
.stat-bar {
height 100%;
background #da8d27;
border-radius 2px;
transition width 0.6s cubic-bezier(0.16,1,0.3,1);
}
.pathway-learn-more {
display inline-flex;
align-items center;
gap 8px;
margin-top 24px;
padding 11px 22px;
background #C8683A;
color white;
font-family 'Montserrat', sans-serif;
font-size 11px;
font-weight 700;
letter-spacing 0.06em;
border-radius 8px;
text-decoration none;
transition background 0.18s;
}
.pathway-learn-morehover { background #B85A2F; }
.stats-source {
font-size 9px;
color #bbb;
font-weight 500;
margin-top 16px;
letter-spacing 0.02em;
}
.mc-start-row {
display grid;
grid-template-columns 1fr 1fr;
gap 12px;
margin-bottom 20px;
}
.mc-label {
font-size 9px;
font-weight 700;
letter-spacing 0.1em;
text-transform uppercase;
color #999;
display block;
margin-bottom 5px;
}
.mc-input-wrap {
display flex;
align-items center;
border 1.5px solid rgba(26,92,80,0.2);
border-radius 8px;
background white;
overflow hidden;
transition border-color 0.18s;
}
.mc-input-wrapfocus-within { border-color #1A5C50; }
.mc-prefix {
padding 0 10px;
font-size 13px;
font-weight 600;
color #123D36;
background #F5F1E8;
height 40px;
display flex;
align-items center;
border-right 1.5px solid rgba(26,92,80,0.12);
}
.mc-suffix {
padding 0 10px;
font-size 12px;
font-weight 600;
color #123D36;
background #F5F1E8;
height 36px;
display flex;
align-items center;
border-left 1.5px solid rgba(26,92,80,0.12);
}
.mc-input {
flex 1;
border none;
outline none;
font-family 'Montserrat', sans-serif;
font-size 13px;
font-weight 600;
color #123D36;
padding 0 12px;
height 40px;
background white;
width 100%;
}
.mc-input-plain { padding 0 12px; }
.mc-input-sm { height 36px; font-size 12px; }
.mc-input-wrap-sm { border-radius 6px; }
.mc-input-webkit-outer-spin-button,
.mc-input-webkit-inner-spin-button { -webkit-appearance none; }
.mc-divider { height 1px; background rgba(26,92,80,0.1); margin 16px 0; }
.mc-section-row {
display flex;
align-items center;
gap 8px;
padding 10px 0;
border-bottom 1px solid rgba(26,92,80,0.06);
}
.mc-section-rowlast-of-type { border-bottom none; }
.mc-row-secondary { background rgba(26,92,80,0.02); border-radius 4px; padding 8px 6px; }
.mc-row-total { background rgba(218,141,39,0.07); border-radius 6px; padding 10px 8px; border-bottom none; margin 4px 0; }
.mc-row-label {
display flex;
align-items center;
gap 6px;
width 160px;
flex-shrink 0;
}
.mc-sign {
font-size 14px;
font-weight 700;
width 16px;
text-align center;
flex-shrink 0;
}
.mc-plus { color #1A5C50; }
.mc-minus { color #C8683A; }
.mc-eq { color #da8d27; }
.mc-row-name { font-size 11px; font-weight 600; color #555; }
.mc-total-name { color #123D36; font-weight 700; }
.mc-cols {
display flex;
flex 1;
gap 8px;
}
.mc-col {
flex 1;
display flex;
flex-direction column;
gap 6px;
}
.mc-select {
width 100%;
height 36px;
padding 0 24px 0 10px;
border 1.5px solid rgba(26,92,80,0.2);
border-radius 6px;
background white;
font-family 'Montserrat', sans-serif;
font-size 11px;
font-weight 600;
color #123D36;
outline none;
cursor pointer;
appearance none;
background-image url(dataimagesvg+xml,%3Csvg xmlns='httpwww.w3.org2000svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath d='M0 0l5 6 5-6z' fill='%231A5C50'%3E%3Csvg%3E);
background-repeat no-repeat;
background-position right 8px center;
}
.mc-calc-val {
font-size 12px;
font-weight 600;
color #555;
padding 4px 2px;
}
.mc-accent { color #1A5C50; }
.mc-bold { font-weight 700; font-size 13px; }
.mc-ltt {
display grid;
grid-template-columns 1fr 1fr;
gap 24px;
margin-top 4px;
}
.mc-ltt-q { font-size 12px; font-weight 600; color #123D36; margin-bottom 8px; }
.mc-toggle-group { display flex; gap 8px; }
.mc-toggle {
flex 1;
padding 8px;
border 1.5px solid rgba(26,92,80,0.2);
border-radius 6px;
background white;
font-family 'Montserrat', sans-serif;
font-size 11px;
font-weight 600;
color #555;
cursor pointer;
transition all 0.18s;
}
.mc-toggle-active {
background #da8d27;
color white;
border-color #1A5C50;
}
.mc-ltt-row {
display flex;
align-items center;
justify-content space-between;
padding 7px 0;
font-size 11px;
border-bottom 1px dashed rgba(26,92,80,0.1);
gap 8px;
}
.mc-ltt-rowlast-child { border-bottom none; }
.mc-ltt-plus, .mc-ltt-minus { gap 4px; }
.mc-ltt-label { color #666; font-weight 500; flex 1; }
.mc-ltt-val { font-weight 600; color #123D36; }
.mc-ltt-divider { height 1.5px; background rgba(26,92,80,0.15); margin 6px 0; }
.mc-ltt-total-row { padding-top 8px; }
.mc-ltt-total-lbl { font-weight 700; color #123D36; }
.y10-header { text-align center; margin-bottom 24px; padding 20px; background #123D36; border-radius 12px; }
.y10-headline { font-size 20px; font-weight 700; color white; margin-bottom 4px; }
.y10-subhead { font-size 13px; font-weight 500; color rgba(255,255,255,0.7); }
.y10-amber { color #da8d27; font-weight 700; }
.y10-inputs { display grid; grid-template-columns 1fr 1fr; gap 12px; margin-bottom 20px; }
.y10-preset-group { grid-column 1 -1; }
.y10-input-group {}
.y10-rate-note { font-weight 500; text-transform none; letter-spacing 0; color #bbb; }
.y10-preset-group { display flex; flex-direction column; justify-content flex-end; }
.y10-slider-wrap { position relative; padding-bottom 46px; padding-top 8px; }
.y10-slider {
-webkit-appearance none;
appearance none;
width 100%;
height 4px;
border-radius 2px;
background linear-gradient(to right, #1A5C50 0%, #1A5C50 49%, rgba(26,92,80,0.2) 49%, rgba(26,92,80,0.2) 100%);
outline none;
cursor pointer;
}
.y10-slider-webkit-slider-thumb {
-webkit-appearance none;
width 20px; height 20px;
border-radius 50%;
background #da8d27;
border 3px solid white;
box-shadow 0 1px 6px rgba(0,0,0,0.25);
cursor grab;
transition transform 0.15s;
position relative;
z-index 2;
}
.y10-slider-webkit-slider-thumbactive { cursor grabbing; transform scale(1.15); }
.y10-slider-moz-range-thumb {
width 20px; height 20px;
border-radius 50%;
background #da8d27;
border 3px solid white;
box-shadow 0 1px 6px rgba(0,0,0,0.25);
cursor grab;
}
.y10-slider-labels { position absolute; top 26px; left 0; right 0; pointer-events none; }
.y10-slider-snap {
position absolute;
transform translateX(-50%);
display flex;
flex-direction column;
align-items center;
width 72px;
}
.y10-snap-tick { display none; }
.y10-snap-pct {
font-size 12px;
font-weight 700;
color #1A5C50;
text-align center;
margin-bottom 1px;
}
.y10-snap-name {
font-size 8px;
font-weight 600;
color #aaa;
letter-spacing 0.05em;
text-transform uppercase;
text-align center;
line-height 1.3;
width 100%;
}
.y10-scenario-legend { display grid; grid-template-columns repeat(2, minmax(0, 1fr)); gap 6px 16px; margin-top 20px; padding-top 20px; border-top 1px solid rgba(26,92,80,0.1); }
.y10-scenario-legend-item { font-size 10px; color #888; line-height 1.4; }
.y10-scenario-legend-item strong { display block; font-size 10px; font-weight 700; color #1A5C50; }
@media (max-width 480px) {
.y10-scenario-legend { grid-template-columns 1fr; }
}
.y10-compare { display grid; grid-template-columns 1fr auto 1fr; gap 12px; align-items start; margin-bottom 16px; }
.y10-card { border-radius 12px; overflow hidden; box-shadow 0 2px 12px rgba(0,0,0,0.08); min-width 0; }
.y10-card-wait { background #2A3A30; }
.y10-card-igv { background #1A5C50; }
.y10-card-header {
display flex; align-items center; gap 8px;
padding 12px 16px; font-size 11px; font-weight 700;
letter-spacing 0.08em; text-transform uppercase;
background rgba(0,0,0,0.2); color rgba(255,255,255,0.7);
}
.y10-igv-header { background rgba(0,0,0,0.15); color rgba(255,255,255,0.85); }
.y10-card-sub { font-size 10px; color rgba(255,255,255,0.5); padding 10px 16px 0; font-weight 500; }
.y10-card-big { font-size 26px; font-weight 700; color #C8683A; padding 4px 16px 12px; overflow-wrap break-word; word-break break-word; }
.y10-card-big-igv { color #da8d27; }
.y10-table { padding 0 0 8px; }
.y10-table-hdr { display flex; justify-content space-between; padding 5px 16px; font-size 9px; font-weight 700; letter-spacing 0.1em; text-transform uppercase; color rgba(255,255,255,0.35); border-bottom 1px solid rgba(255,255,255,0.08); }
.y10-table-row { display flex; justify-content space-between; align-items center; padding 7px 16px; font-size 11px; color rgba(255,255,255,0.6); font-weight 500; border-bottom 1px solid rgba(255,255,255,0.05); gap 6px; }
.y10-table-row spanlast-child { font-weight 700; color rgba(255,255,255,0.85); white-space nowrap; }
.y10-table-final { background rgba(0,0,0,0.15); }
.y10-table-final spanlast-child { color #da8d27 !important; font-size 13px; }
.y10-vs { display flex; align-items center; justify-content center; width 44px; height 44px; background #C8683A; color white; font-size 12px; font-weight 700; border-radius 50%; margin-top 80px; flex-shrink 0; }
@media (max-width 480px) {
.y10-compare { gap 6px; }
.y10-card-big { font-size 19px; padding 4px 10px 10px; }
.y10-card-sub { padding 8px 10px 0; }
.y10-card-header { padding 10px 10px; font-size 10px; }
.y10-table-row { padding 6px 10px; font-size 10px; }
.y10-table-hdr { padding 5px 10px; }
.y10-vs { width 32px; height 32px; font-size 9px; margin-top 64px; }
}
.y10-saving { display flex; align-items center; justify-content space-between; background rgba(218,141,39,0.12); border 1.5px solid rgba(218,141,39,0.3); border-radius 10px; padding 14px 20px; margin-bottom 24px; }
.y10-saving-label { font-size 12px; font-weight 600; color #123D36; }
.y10-saving-val { font-size 22px; font-weight 700; color #da8d27; }
.y10-mortgage-intro { font-size 12px; color #666; line-height 1.6; margin-bottom 16px; }
.y10-mortgage-grid { display grid; grid-template-columns repeat(4, minmax(0, 1fr)); gap 10px; margin-bottom 16px; }
@media (max-width 640px) {
.y10-mortgage-grid { grid-template-columns repeat(2, minmax(0, 1fr)); }
}
.y10-m-field {}
.y10-mortgage-results { border-radius 10px; overflow hidden; }
.y10-mresult-row { display flex; justify-content space-between; align-items center; padding 10px 16px; font-size 11px; border-bottom 1px solid rgba(26,92,80,0.06); }
.y10-mresult-rowlast-child { border-bottom none; }
.y10-mresult-label { color #777; font-weight 500; }
.y10-mresult-val { font-weight 700; color #123D36; }
.y10-mresult-highlight { background rgba(218,141,39,0.07); }
.y10-mresult-big { font-size 16px; color #da8d27; }
.y10-mresult-saving { background rgba(26,92,80,0.04); }
.y10-saving-green { color #1A5C50; }
.y10-mortgage-section { margin-top 8px; }
.y10-equity-story {
background linear-gradient(135deg, #123D36 0%, #1A5C50 100%);
border-radius 10px 10px 0 0;
padding 16px 16px 14px;
margin-bottom 0;
}
.y10-es-title {
font-size 11px; font-weight 700; letter-spacing 0.1em; text-transform uppercase;
color #da8d27; margin-bottom 16px;
}
.y10-es-flow {
display flex; align-items center; gap 8px; margin-bottom 12px;
}
.y10-es-block {
flex 1; display flex; flex-direction column; align-items center; text-align center;
}
.y10-es-label {
font-size 9px; font-weight 500; color rgba(255,255,255,0.45); text-transform uppercase;
letter-spacing 0.07em; margin-bottom 12px; line-height 1.4;
}
.y10-es-val {
font-size 36px; font-weight 700; line-height 1; margin-bottom 10px;
}
.y10-es-val.green { color #6ECFA0; }
.y10-es-val.amber { color #da8d27; }
.y10-es-sub {
font-size 10px; color rgba(255,255,255,0.45); line-height 1.5;
}
.y10-es-arrow {
display flex; flex-direction column; align-items center; gap 3px; flex-shrink 0;
}
.y10-es-arrow-label {
font-size 8px; font-weight 600; color rgba(255,255,255,0.3); text-transform uppercase; letter-spacing 0.08em;
}
.y10-es-verdict {
font-size 10px; font-weight 600; color #1A5C50; text-align center;
line-height 1.5; border-top 1px solid rgba(26,92,80,0.15); padding-top 10px;
}
.y10-es-verdict strong { color #123D36; }
.y10-equity-panel {
margin-top 16px;
background linear-gradient(135deg, #123D36 0%, #1A5C50 100%);
border-radius 12px;
padding 18px 20px;
color white;
}
.y10-equity-title {
font-size 11px; font-weight 700; letter-spacing 0.1em; text-transform uppercase;
color #da8d27; margin-bottom 16px;
}
.y10-lvr-compare {
display flex; align-items stretch; gap 0;
}
.y10-lvr-col {
flex 1; display flex; flex-direction column; align-items center; text-align center; padding 0 16px;
}
.y10-lvr-divider {
width 1px; background rgba(255,255,255,0.12); flex-shrink 0; margin 4px 0;
}
.y10-lvr-col-label {
font-size 12px; font-weight 700; color white; margin-bottom 4px;
}
.y10-lvr-col-sub {
font-size 9px; font-weight 500; color rgba(255,255,255,0.45); text-transform uppercase;
letter-spacing 0.07em; margin-bottom 12px; line-height 1.4;
}
.y10-lvr-big {
font-size 36px; font-weight 700; color rgba(255,255,255,0.9); line-height 1;
margin-bottom 10px;
}
.y10-lvr-big.amber { color #da8d27; }
.y10-lvr-col-note {
font-size 10px; color rgba(255,255,255,0.45); line-height 1.5;
}
.y10-lvr-tagline {
margin-top 14px;
font-size 13px;
font-weight 600;
color #1A5C50;
font-style italic;
text-align center;
line-height 1.5;
}
#detail-nav {
flex-shrink 0;
height 60px;
background #1a4848;
display flex;
align-items center;
padding 0 24px;
gap 16px;
z-index 10;
}
#detail-back {
background none;
border none;
cursor pointer;
display flex;
align-items center;
gap 8px;
color rgba(255,255,255,0.75);
font-family 'Montserrat', sans-serif;
font-size 12px;
font-weight 600;
padding 6px 0;
transition color 0.18s;
}
#detail-backhover { color #fff; }
#detail-nav-title {
font-size 13px;
font-weight 700;
color white;
flex 1;
white-space nowrap;
overflow hidden;
text-overflow ellipsis;
}
#detail-nav-badge {
font-size 9px;
font-weight 700;
letter-spacing 0.12em;
text-transform uppercase;
color #da8d27;
background rgba(218,141,39,0.15);
border 1px solid rgba(218,141,39,0.3);
border-radius 4px;
padding 3px 8px;
white-space nowrap;
flex-shrink 0;
}
#detail-body {
flex 1;
overflow-y auto;
overflow-x hidden;
}
#detail-body-webkit-scrollbar { width 6px; }
#detail-body-webkit-scrollbar-thumb { background rgba(26,92,80,0.25); border-radius 3px; }
#detail-hero {
width 100%;
display grid;
grid-template-columns 1.6fr 1fr;
gap 6px;
height 420px;
flex-shrink 0;
padding 20px 32px 0;
box-sizing border-box;
}
#detail-gallery-main {
position relative;
border-radius 12px;
overflow hidden;
cursor zoom-in;
}
#detail-hero-bg {
position absolute;
inset 0;
background linear-gradient(135deg, #1A4848, #2B6B5A);
background-size cover;
background-position center;
transition transform 0.3s ease;
}
#detail-gallery-mainhover #detail-hero-bg { transform scale(1.03); }
#detail-gallery-thumbs {
display flex;
flex-direction column;
gap 6px;
height 100%;
}
.gallery-tier2 {
display grid;
grid-template-columns repeat(2, 1fr);
gap 6px;
flex 1.6;
}
.gallery-tier3 {
display grid;
grid-template-columns repeat(auto-fill, minmax(50px, 1fr));
gap 6px;
flex 1;
}
.gallery-thumb {
position relative;
border-radius 10px;
overflow hidden;
cursor zoom-in;
background-size cover;
background-position center;
background-color rgba(26,92,80,0.15);
}
.gallery-thumbhoverafter {
content '';
position absolute;
inset 0;
background rgba(0,0,0,0.12);
}
#detail-hero-info { padding 20px 32px 24px; }
#detail-hero-type {
font-size 9px;
font-weight 700;
letter-spacing 0.18em;
text-transform uppercase;
color #da8d27;
margin-bottom 6px;
}
#detail-hero-title {
font-size 26px;
font-weight 700;
color #123D36;
line-height 1.15;
margin-bottom 8px;
}
#detail-hero-location {
font-size 12px;
font-weight 500;
color #666;
display flex;
align-items center;
gap 5px;
}
.detail-hero-save {
position absolute;
top 14px;
right 14px;
z-index 3;
width 36px;
height 36px;
border-radius 50%;
background rgba(18,61,54,0.35);
backdrop-filter blur(4px);
border none;
cursor pointer;
display flex;
align-items center;
justify-content center;
transition background 0.18s, transform 0.15s;
}
.detail-hero-savehover { background rgba(18,61,54,0.55); transform scale(1.08); }
#detail-hero-photocount {
position absolute;
left 14px;
bottom 14px;
z-index 3;
display none;
align-items center;
gap 6px;
padding 6px 12px;
border-radius 999px;
background rgba(18,61,54,0.55);
backdrop-filter blur(4px);
color #ffffff;
font-family 'Montserrat', sans-serif;
font-size 12px;
font-weight 700;
letter-spacing 0.02em;
}
@media (max-width 800px) {
#detail-hero { grid-template-columns 1fr; height auto; padding 16px 16px 0; }
#detail-gallery-main { height 240px; }
#detail-gallery-thumbs { display none !important; }
#detail-hero-photocount { display flex; }
#detail-hero-info { padding 16px 16px 20px; }
}
.detail-hero-save.saved svg { fill #da8d27; stroke #da8d27; }
#detail-stats {
display flex;
background #123D36;
padding 0;
}
.detail-stat {
flex 1;
min-width 0;
padding 16px 20px;
border-right 1px solid rgba(255,255,255,0.08);
text-align center;
}
.detail-statlast-child { border-right none; }
.detail-stat-val {
font-size 18px;
font-weight 700;
color #da8d27;
line-height 1;
margin-bottom 4px;
}
.detail-stat-lbl {
font-size 9px;
font-weight 600;
letter-spacing 0.1em;
text-transform uppercase;
color rgba(255,255,255,0.5);
}
@media (max-width 400px) {
.detail-stat { padding 16px 8px; }
}
#detail-columns {
display grid;
grid-template-columns 1fr 300px;
gap 0;
min-height calc(100vh - 60px - 280px - 62px);
}
@media (max-width 800px) {
#detail-columns { grid-template-columns minmax(0, 1fr); }
#detail-sidebar { order -1; }
}
#detail-main {
padding 28px 32px 48px;
border-right 1px solid rgba(26,92,80,0.1);
}
#detail-sidebar {
padding 24px 20px;
background white;
position sticky;
top 0;
height fit-content;
}
@media (max-width 800px) {
#detail-sidebar { position static; }
}
.sidebar-price-block {
margin-bottom 20px;
}
.sidebar-price-lbl {
font-size 9px;
font-weight 700;
letter-spacing 0.12em;
text-transform uppercase;
color #999;
margin-bottom 4px;
}
.sidebar-price-val {
font-size 28px;
font-weight 700;
color #123D36;
line-height 1;
}
.sidebar-price-sub {
font-size 11px;
font-weight 500;
color #aaa;
margin-top 4px;
}
.sidebar-divider {
height 1px;
background #F0EDE6;
margin 16px 0;
}
.sidebar-meta-row {
display flex;
justify-content space-between;
align-items center;
font-size 11px;
color #888;
font-weight 500;
padding 5px 0;
}
.sidebar-meta-row strong {
color #123D36;
font-weight 600;
}
.sidebar-cta {
width 100%;
padding 13px 16px;
border-radius 8px;
font-family 'Montserrat', sans-serif;
font-size 11px;
font-weight 700;
letter-spacing 0.04em;
cursor pointer;
transition all 0.18s;
display flex;
align-items center;
justify-content center;
gap 8px;
margin-bottom 10px;
border none;
}
.sidebar-cta.primary {
background #C8683A;
color white;
}
.sidebar-cta.primaryhover { background #B85A2F; }
.sidebar-cta.secondary {
background transparent;
color #1A5C50;
border 1.5px solid #1A5C50;
}
.sidebar-cta.secondaryhover { background rgba(26,92,80,0.06); }
.sidebar-advisor {
display flex;
align-items center;
gap 10px;
margin-top 16px;
padding 12px;
background #F5F1E8;
border-radius 8px;
}
.advisor-avatar {
width 36px;
height 36px;
border-radius 50%;
background #da8d27;
display flex;
align-items center;
justify-content center;
font-size 13px;
font-weight 700;
color white;
flex-shrink 0;
}
.advisor-name {
font-size 11px;
font-weight 700;
color #123D36;
}
.advisor-role {
font-size 9px;
font-weight 500;
color #aaa;
letter-spacing 0.04em;
margin-top 1px;
}
.detail-section-title {
font-size 13px;
font-weight 700;
color #123D36;
letter-spacing 0.02em;
margin-bottom 12px;
margin-top 28px;
padding-bottom 8px;
border-bottom 1px solid rgba(26,92,80,0.1);
}
.detail-section-titlefirst-child { margin-top 0; }
.detail-description {
font-size 12px;
line-height 1.75;
color #555;
font-weight 400;
}
.property-summary-grid {
display grid;
grid-template-columns repeat(3, minmax(0, 1fr));
gap 0;
border 1px solid rgba(26,92,80,0.1);
border-radius 10px;
overflow hidden;
margin-bottom 4px;
}
@media (max-width 640px) {
.property-summary-grid { grid-template-columns repeat(2, minmax(0, 1fr)); }
}
@media (max-width 400px) {
.property-summary-grid { grid-template-columns minmax(0, 1fr); }
}
.ps-cell {
padding 12px 16px;
border-right 1px solid rgba(26,92,80,0.08);
border-bottom 1px solid rgba(26,92,80,0.08);
background white;
}
.ps-cellnth-child(even) { background #FAFAF8; }
.ps-label {
font-size 10px;
font-weight 700;
color #123D36;
letter-spacing 0.03em;
margin-bottom 3px;
}
.ps-val {
font-size 12px;
font-weight 500;
color #555;
}
.detail-amenities {
display flex;
flex-direction column;
border 1px solid rgba(26,92,80,0.12);
border-radius 10px;
overflow hidden;
background white;
}
.amenity-pill {
display flex;
align-items flex-start;
gap 14px;
padding 13px 16px;
border-bottom 1px solid rgba(26,92,80,0.07);
}
.amenity-pilllast-child { border-bottom none; }
.amenity-icon {
flex-shrink 0;
display flex;
align-items center;
justify-content center;
width 32px;
height 32px;
border-radius 8px;
background rgba(26,92,80,0.06);
margin-top 1px;
}
.amenity-icon svg { width 16px; height 16px; }
.amenity-text { display flex; flex-direction column; gap 2px; }
.amenity-label {
font-size 12px;
font-weight 700;
color #123D36;
}
.amenity-detail {
font-size 11px;
font-weight 400;
color #888;
line-height 1.5;
}
.pathway-timeline {
position relative;
padding-left 28px;
}
.pathway-timelinebefore {
content '';
position absolute;
left 7px;
top 8px;
bottom 8px;
width 2px;
background linear-gradient(to bottom, #1A5C50, rgba(26,92,80,0.1));
}
.pathway-step {
position relative;
margin-bottom 20px;
}
.pathway-steplast-child { margin-bottom 0; }
.pathway-dot {
position absolute;
left -28px;
top 2px;
width 16px;
height 16px;
border-radius 50%;
background white;
border 2px solid #1A5C50;
display flex;
align-items center;
justify-content center;
}
.pathway-dot.active { background #1A5C50; }
.pathway-dot.milestone { background #da8d27; border-color #da8d27; }
.pathway-step-label {
font-size 9px;
font-weight 700;
letter-spacing 0.12em;
text-transform uppercase;
color #da8d27;
margin-bottom 2px;
}
.pathway-step-title {
font-size 12px;
font-weight 700;
color #123D36;
margin-bottom 3px;
}
.pathway-step-desc {
font-size 11px;
color #888;
font-weight 500;
line-height 1.5;
}
.partner-badge {
display inline-flex;
align-items center;
gap 8px;
padding 8px 14px;
background rgba(26,92,80,0.07);
border 1px solid rgba(26,92,80,0.15);
border-radius 8px;
font-size 11px;
font-weight 600;
color #1A5C50;
margin-right 8px;
margin-bottom 8px;
}
.partner-badge-icon {
width 18px;
height 18px;
border-radius 4px;
background #da8d27;
display flex;
align-items center;
justify-content center;
}
#lightbox {
display none;
position fixed;
inset 0;
z-index 2000;
background rgba(0,0,0,0.92);
align-items center;
justify-content center;
flex-direction column;
}
#lightbox.open { display flex; }
#lightbox-img {
max-width 92vw;
max-height 82vh;
object-fit contain;
border-radius 6px;
box-shadow 0 8px 48px rgba(0,0,0,0.6);
user-select none;
-webkit-user-drag none;
}
#lightbox-close {
position absolute;
top 18px;
right 22px;
background none;
border none;
cursor pointer;
color rgba(255,255,255,0.75);
font-size 28px;
line-height 1;
transition color 0.15s;
z-index 10;
}
#lightbox-closehover { color #fff; }
#lightbox-prev, #lightbox-next {
position absolute;
top 50%;
transform translateY(-50%);
background rgba(255,255,255,0.1);
border none;
border-radius 50%;
width 48px;
height 48px;
cursor pointer;
display flex;
align-items center;
justify-content center;
color white;
transition background 0.18s;
z-index 10;
}
#lightbox-prevhover, #lightbox-nexthover { background rgba(255,255,255,0.25); }
#lightbox-prev { left 20px; }
#lightbox-next { right 20px; }
#lightbox-dots {
display flex;
gap 8px;
margin-top 16px;
}
.lightbox-dot {
width 8px;
height 8px;
border-radius 50%;
background rgba(255,255,255,0.3);
cursor pointer;
transition background 0.18s;
}
.lightbox-dot.active { background #da8d27; }
#lightbox-counter {
position absolute;
top 20px;
left 50%;
transform translateX(-50%);
font-family 'Montserrat', sans-serif;
font-size 11px;
font-weight 600;
color rgba(255,255,255,0.5);
letter-spacing 0.1em;
}
style
div id=detail-colour-wipe
div class=wipe-strip wipe-strip-1div
div class=wipe-strip wipe-strip-2div
div class=wipe-strip wipe-strip-3div
div class=wipe-strip wipe-strip-4div
div
div id=listing-detail
nav id=detail-nav
button id=detail-back onclick=closeListingDetail()
svg width=16 height=16 viewBox=0 0 24 24 fill=none stroke=currentColor stroke-width=2.5 stroke-linecap=round stroke-linejoin=roundpolyline points=15 18 9 12 15 6svg
Back to listings
button
div id=detail-nav-titlediv
div id=detail-nav-badgediv
nav
div id=detail-body
div id=detail-hero
div id=detail-gallery-main onclick=heroOpenLightbox(0)
div id=detail-hero-bgdiv
div id=detail-hero-photocount
svg width=13 height=13 viewBox=0 0 24 24 fill=none stroke=currentColor stroke-width=2 stroke-linecap=round stroke-linejoin=roundrect x=3 y=3 width=18 height=18 rx=2circle cx=8.5 cy=8.5 r=1.5path d=M21 15l-5-5L5 21svg
span id=detail-hero-photocount-textspan
div
button class=detail-hero-save id=detail-save-btn onclick=event.stopPropagation();handleSaveClick(this) title=Save listing
svg width=16 height=16 viewBox=0 0 24 24 fill=none stroke=white stroke-width=2.5 stroke-linecap=round stroke-linejoin=roundpath d=M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78zsvg
button
div
div id=detail-gallery-thumbsdiv
div
div id=detail-hero-info
div id=detail-hero-typediv
div id=detail-hero-titlediv
div id=detail-hero-location
svg width=11 height=11 viewBox=0 0 24 24 fill=none stroke=currentColor stroke-width=2.5 stroke-linecap=round stroke-linejoin=roundpath d=M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0zcircle cx=12 cy=10 r=3svg
span id=detail-hero-loc-textspan
div
div
div id=detail-stats
div class=detail-stat
div class=detail-stat-val id=ds-rent onclick=handleGatedValueClick()div
div class=detail-stat-lblMonthly Occupancy Paymentdiv
div
div class=detail-stat
div class=detail-stat-val id=ds-beds onclick=handleGatedValueClick()div
div class=detail-stat-lblBedroomsdiv
div
div class=detail-stat
div class=detail-stat-val id=ds-baths onclick=handleGatedValueClick()div
div class=detail-stat-lblBathroomsdiv
div
div class=detail-stat
div class=detail-stat-val id=ds-sqft onclick=handleGatedValueClick()div
div class=detail-stat-lblSq Footagediv
div
div
div id=detail-columns
div id=detail-main
div id=detail-tabs-wrap
div id=detail-tabs onscroll=updateTabsFade()
button class=detail-tab active onclick=switchTab('highlights', this)Highlightsbutton
button class=detail-tab onclick=switchTab('pathway', this)span class=tab-label-fullIGVhope Pathwayspanspan class=tab-label-shortPathwayspansvg class=tab-lock-icon width=10 height=10 viewBox=0 0 24 24 fill=currentColorpath d=M12 1a5 5 0 0 0-5 5v3H6a2 2 0 0 0-2 2v9a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-9a2 2 0 0 0-2-2h-1V6a5 5 0 0 0-5-5zm0 2a3 3 0 0 1 3 3v3H9V6a3 3 0 0 1 3-3zsvgbutton
button class=detail-tab onclick=switchTab('neighbourhood', this)Neighbourhoodsvg class=tab-lock-icon width=10 height=10 viewBox=0 0 24 24 fill=currentColorpath d=M12 1a5 5 0 0 0-5 5v3H6a2 2 0 0 0-2 2v9a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-9a2 2 0 0 0-2-2h-1V6a5 5 0 0 0-5-5zm0 2a3 3 0 0 1 3 3v3H9V6a3 3 0 0 1 3-3zsvgbutton
button class=detail-tab onclick=switchTab('statistics', this)Statisticssvg class=tab-lock-icon width=10 height=10 viewBox=0 0 24 24 fill=currentColorpath d=M12 1a5 5 0 0 0-5 5v3H6a2 2 0 0 0-2 2v9a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-9a2 2 0 0 0-2-2h-1V6a5 5 0 0 0-5-5zm0 2a3 3 0 0 1 3 3v3H9V6a3 3 0 0 1 3-3zsvgbutton
button class=detail-tab onclick=switchTab('mortgage', this)span class=tab-label-fullAffordability Calculatorspanspan class=tab-label-shortCalculatorspansvg class=tab-lock-icon width=10 height=10 viewBox=0 0 24 24 fill=currentColorpath d=M12 1a5 5 0 0 0-5 5v3H6a2 2 0 0 0-2 2v9a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-9a2 2 0 0 0-2-2h-1V6a5 5 0 0 0-5-5zm0 2a3 3 0 0 1 3 3v3H9V6a3 3 0 0 1 3-3zsvgbutton
div
div class=detail-tabs-fade left id=detail-tabs-fade-leftsvg width=14 height=14 viewBox=0 0 24 24 fill=none stroke=#1A5C50 stroke-width=3 stroke-linecap=round stroke-linejoin=roundpolyline points=15 6 9 12 15 18svgdiv
div class=detail-tabs-fade right id=detail-tabs-fade-rightsvg width=14 height=14 viewBox=0 0 24 24 fill=none stroke=#1A5C50 stroke-width=3 stroke-linecap=round stroke-linejoin=roundpolyline points=9 6 15 12 9 18svgdiv
div
div class=tab-panel id=tab-highlights
div id=detail-map-block style=displaynone; margin-bottom24px;
div class=detail-section-title style=margin-bottom12px;Locationdiv
div style=border-radius12px; overflowhidden; height260px;
div id=detail-map-frame style=width100%; height100%;div
div
div style=font-size11px; color#888; margin-top8px; font-styleitalic;Shaded area shows the approximate location within 500m. The exact address is shared after application.div
div
div class=detail-section-titleProperty summarydiv
div class=property-summary-grid
div class=ps-celldiv class=ps-labelProperty typedivdiv class=ps-val id=ps-property-typedivdiv
div class=ps-celldiv class=ps-labelBuilding typedivdiv class=ps-val id=ps-building-typedivdiv
div class=ps-celldiv class=ps-labelSquare footagedivdiv class=ps-val id=ps-sqftdivdiv
div class=ps-celldiv class=ps-labelNeighbourhooddivdiv class=ps-val id=ps-neighbourhooddivdiv
div class=ps-celldiv class=ps-labelTitledivdiv class=ps-val id=ps-tenuredivdiv
div class=ps-celldiv class=ps-labelLand sizedivdiv class=ps-val id=ps-land-sizedivdiv
div class=ps-celldiv class=ps-labelBuilt indivdiv class=ps-val id=ps-built-indivdiv
div class=ps-celldiv class=ps-labelMove-in readydivdiv class=ps-val id=ps-move-indivdiv
div class=ps-celldiv class=ps-labelParking spacesdivdiv class=ps-val id=ps-parkingdivdiv
div
div class=detail-section-titleAbout this homediv
div class=detail-description id=detail-descdiv
div class=detail-section-titleAmenitiesdiv
div class=detail-amenities id=detail-amenitiesdiv
div
div class=tab-panel id=tab-pathway style=displaynone
div class=detail-section-titleYour ownership pathwaydiv
div class=pathway-timeline
div class=pathway-step
div class=pathway-dot activediv
div class=pathway-step-labelNow - Year 1div
div class=pathway-step-titleMove indiv
div class=pathway-step-descYou pay capped monthly occupancy rates. A portion goes toward building your future equity stake. No mortgage qualification required at entry.div
div
div class=pathway-step
div class=pathway-dotdiv
div class=pathway-step-labelYear 1 - 5div
div class=pathway-step-titleCredit building & pre-approvaldiv
div class=pathway-step-descWork with our lending partners to strengthen your credit profile and build savings. IGVhope navigators check in quarterly.div
div
div class=pathway-step
div class=pathway-dotdiv
div class=pathway-step-labelYear 5 - 10div
div class=pathway-step-titleTransition window opensdiv
div class=pathway-step-descYou become eligible to purchase your home at the originally agreed price - protected from market appreciation during your tenancy.div
div
div class=pathway-step
div class=pathway-dot milestonediv
div class=pathway-step-labelYear 10div
div class=pathway-step-titleOwnership transferdiv
div class=pathway-step-descTransition to your mortgage. The equity from the market change during the 10 years becomes yours. You are a homeowner.div
div
div
a href=httpswww.igvhope.comhowitworks target=_blank rel=noopener class=pathway-learn-moreLearn more about IGVhopea
div class=detail-section-titleMunicipal & employer partnersdiv
div id=detail-partnersdiv
div
div class=tab-panel id=tab-neighbourhood style=displaynone
div class=detail-section-titleWhat's nearbydiv
div class=nb-grid
div class=nb-category
div class=nb-cat-header
svg width=14 height=14 viewBox=0 0 24 24 fill=none stroke=#1A5C50 stroke-width=2.5 stroke-linecap=round stroke-linejoin=roundpath d=M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2zpolyline points=9 22 9 12 15 12 15 22svg
Schools
div
div class=nb-itemspan class=nb-name id=nb-school-1spanspan class=nb-dist id=nb-school-1-dspandiv
div class=nb-itemspan class=nb-name id=nb-school-2spanspan class=nb-dist id=nb-school-2-dspandiv
div class=nb-itemspan class=nb-name id=nb-school-3spanspan class=nb-dist id=nb-school-3-dspandiv
div
div class=nb-category
div class=nb-cat-header
svg width=14 height=14 viewBox=0 0 24 24 fill=none stroke=#1A5C50 stroke-width=2.5 stroke-linecap=round stroke-linejoin=roundpath d=M3 3h18v4H3zpath d=M3 7v13h18V7path d=M9 21v-8h6v8svg
Shopping & services
div
div class=nb-itemspan class=nb-name id=nb-shop-1spanspan class=nb-dist id=nb-shop-1-dspandiv
div class=nb-itemspan class=nb-name id=nb-shop-2spanspan class=nb-dist id=nb-shop-2-dspandiv
div class=nb-itemspan class=nb-name id=nb-shop-3spanspan class=nb-dist id=nb-shop-3-dspandiv
div
div class=nb-category
div class=nb-cat-header
svg width=14 height=14 viewBox=0 0 24 24 fill=none stroke=#1A5C50 stroke-width=2.5 stroke-linecap=round stroke-linejoin=roundrect x=3 y=3 width=18 height=14 rx=3path d=M3 11h18path d=M7 17l-2 4path d=M17 17l2 4circle cx=8 cy=14.5 r=0.5 fill=#1A5C50circle cx=16 cy=14.5 r=0.5 fill=#1A5C50svg
Transit
div
div class=nb-itemspan class=nb-name id=nb-transit-1spanspan class=nb-dist id=nb-transit-1-dspandiv
div class=nb-itemspan class=nb-name id=nb-transit-2spanspan class=nb-dist id=nb-transit-2-dspandiv
div class=nb-itemspan class=nb-name id=nb-transit-3spanspan class=nb-dist id=nb-transit-3-dspandiv
div
div class=nb-category
div class=nb-cat-header
svg width=14 height=14 viewBox=0 0 24 24 fill=none stroke=#1A5C50 stroke-width=2.5 stroke-linecap=round stroke-linejoin=roundpath d=M12 22s-8-4.5-8-11.8A8 8 0 0 1 12 2a8 8 0 0 1 8 8.2c0 7.3-8 11.8-8 11.8zcircle cx=12 cy=10 r=3svg
Parks & recreation
div
div class=nb-itemspan class=nb-name id=nb-park-1spanspan class=nb-dist id=nb-park-1-dspandiv
div class=nb-itemspan class=nb-name id=nb-park-2spanspan class=nb-dist id=nb-park-2-dspandiv
div class=nb-itemspan class=nb-name id=nb-park-3spanspan class=nb-dist id=nb-park-3-dspandiv
div class=nb-itemspan class=nb-name id=nb-park-4spanspan class=nb-dist id=nb-park-4-dspandiv
div class=nb-itemspan class=nb-name id=nb-park-5spanspan class=nb-dist id=nb-park-5-dspandiv
div
div class=nb-category
div class=nb-cat-header
svg width=14 height=14 viewBox=0 0 24 24 fill=none stroke=#1A5C50 stroke-width=2.5 stroke-linecap=round stroke-linejoin=roundpath d=M22 12h-4l-3 9L9 3l-3 9H2svg
Healthcare
div
div class=nb-itemspan class=nb-name id=nb-health-1spanspan class=nb-dist id=nb-health-1-dspandiv
div class=nb-itemspan class=nb-name id=nb-health-2spanspan class=nb-dist id=nb-health-2-dspandiv
div
div class=nb-category
div class=nb-cat-header
svg width=14 height=14 viewBox=0 0 24 24 fill=none stroke=#1A5C50 stroke-width=2.5 stroke-linecap=round stroke-linejoin=roundpath d=M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2circle cx=9 cy=7 r=4path d=M23 21v-2a4 4 0 0 0-3-3.87path d=M16 3.13a4 4 0 0 1 0 7.75svg
Community
div
div class=nb-itemspan class=nb-name id=nb-comm-1spanspan class=nb-dist id=nb-comm-1-dspandiv
div class=nb-itemspan class=nb-name id=nb-comm-2spanspan class=nb-dist id=nb-comm-2-dspandiv
div
div
div id=nb-video-block style=margin-top24px;
div class=detail-section-title style=margin-bottom12px;Discover the areadiv
div style=positionrelative; padding-bottom56.25%; height0; border-radius10px; overflowhidden; background#f0f0f0;
iframe id=nb-video-frame src= frameborder=0 allow=accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share referrerpolicy=strict-origin-when-cross-origin allowfullscreen style=positionabsolute; top0; left0; width100%; height100%; displaynone;iframe
video id=nb-video-native controls playsinline style=positionabsolute; top0; left0; width100%; height100%; displaynone; background#000;video
div id=nb-video-facade class=nb-video-facade onclick=playNeighbourhoodVideo()
div class=nb-video-facade-overlaydiv
div class=nb-video-play
svg width=20 height=20 viewBox=0 0 24 24 fill=#ffffffpath d=M8 5v14l11-7zsvg
div
div
div
div style=font-size10px; color#aaa; margin-top8px; text-aligncenter; id=nb-video-captiondiv
div
div
div class=tab-panel id=tab-statistics style=displaynone
div class=stats-section
div class=detail-section-titleDemographicsdiv
div class=stat-rows id=stat-demographicsdiv
div
div class=stats-section
div class=detail-section-titleIncomediv
div class=stat-rows id=stat-incomediv
div
div class=stats-section
div class=detail-section-titleHousingdiv
div class=stat-rows id=stat-housingdiv
div
div class=stats-section
div class=detail-section-titleEducationdiv
div class=stat-rows id=stat-educationdiv
div
div class=stats-section
div class=detail-section-titleCommutediv
div class=stat-rows id=stat-commutediv
div
div class=stats-section
div class=detail-section-titleLanguagesdiv
div class=stat-rows id=stat-languagesdiv
div
div class=stats-sourceStatistics Canada, Census 2021. Figures reflect the broader census subdivision.div
div
div class=tab-panel id=tab-mortgage style=displaynone
div class=y10-header
div class=y10-headlineThe Power of 10 Yearsdiv
div class=y10-subheadThe market changes. span class=y10-amberYour price doesn't.spandiv
div
div class=y10-inputs
div class=y10-input-group
label class=mc-labelToday's purchase pricelabel
div class=mc-input-wrap
span class=mc-prefix$span
input class=mc-input id=y10-price type=text placeholder=e.g. 480,000 oninput=var v=this.value.replace([^0-9]g,''); this.value=vparseInt(v).toLocaleString('en-CA')''; y10Calc()
div
div
div class=y10-input-group
label class=mc-labelMarket appreciation rate span class=y10-rate-note(% over 10 years)spanlabel
div class=mc-input-wrap
input class=mc-input id=y10-rate type=number step=1 min=0 max=160 value=98 oninput=y10SyncSlider(this.value); y10Calc();
span class=mc-suffix%span
div
div
div class=y10-input-group y10-preset-group
label class=mc-labelAppreciation scenariolabel
div class=y10-slider-wrap
input class=y10-slider id=y10-slider type=range min=0 max=160 step=1 value=98 oninput=y10SliderInput(this.value)
div class=y10-slider-labels
div class=y10-slider-snap style=left20%
div class=y10-snap-tickdiv
div class=y10-snap-pct32%div
div class=y10-snap-nameLowest growthdiv
div
div class=y10-slider-snap style=left31%
div class=y10-snap-tickdiv
div class=y10-snap-pct50%div
div class=y10-snap-nameConservative growthdiv
div
div class=y10-slider-snap style=left61%
div class=y10-snap-tickdiv
div class=y10-snap-pct98%div
div class=y10-snap-nameAverage growthdiv
div
div class=y10-slider-snap style=left81%
div class=y10-snap-tickdiv
div class=y10-snap-pct130%div
div class=y10-snap-nameHigh growthdiv
div
div
div
div class=y10-scenario-legend
div class=y10-scenario-legend-itemstrongLowest growth (32%)strongBC worst decade in 80 years 1994-2004div
div class=y10-scenario-legend-itemstrongConservative growth (50%)strong1954-1964div
div class=y10-scenario-legend-itemstrongAverage growth (98%)strongAverage decade growth over 1946-2026, BCREAdiv
div class=y10-scenario-legend-itemstrongHigh growth (130%)strongExample 2004-2014, 1974-1984div
div
div style=text-aligncenter; font-size10px; color#aaa; margin-top4px;Enter historical market growth rates to see how the market can change, while your price stays locked. Historical data illustrates how time in market growth changes property value which could help cover your down payment.div
div
div
div class=y10-compare
div class=y10-card y10-card-wait
div class=y10-card-header
svg width=16 height=16 viewBox=0 0 24 24 fill=none stroke=currentColor stroke-width=2 stroke-linecap=round stroke-linejoin=roundcircle cx=12 cy=12 r=10polyline points=12 6 12 12 16 14svg
If you wait
div
div class=y10-card-subMarket price at Year 10div
div class=y10-card-big id=y10-market-price-div
div class=y10-table
div class=y10-table-hdrspanYearspanspanMarket pricespandiv
div class=y10-table-rowspanYear 1spanspan id=y10-m1-spandiv
div class=y10-table-rowspanYear 3spanspan id=y10-m3-spandiv
div class=y10-table-rowspanYear 5spanspan id=y10-m5-spandiv
div class=y10-table-rowspanYear 7spanspan id=y10-m7-spandiv
div class=y10-table-row y10-table-finalspanYear 10spanspan id=y10-m10-spandiv
div
div
div class=y10-vsVS.div
div class=y10-card y10-card-igv
div class=y10-card-header y10-igv-header
svg width=16 height=16 viewBox=0 0 24 24 fill=none stroke=currentColor stroke-width=2 stroke-linecap=round stroke-linejoin=roundpath d=M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2zpolyline points=9 22 9 12 15 12 15 22svg
IGVhope pathway
div
div class=y10-card-subYour locked price at Year 10div
div class=y10-card-big y10-card-big-igv id=y10-locked-price-div
div class=y10-table
div class=y10-table-hdrspanYearspanspanYour pricespandiv
div class=y10-table-rowspanYear 1spanspan id=y10-i1-spandiv
div class=y10-table-rowspanYear 3spanspan id=y10-i3-spandiv
div class=y10-table-rowspanYear 5spanspan id=y10-i5-spandiv
div class=y10-table-rowspanYear 7spanspan id=y10-i7-spandiv
div class=y10-table-row y10-table-finalspanYear 10spanspan id=y10-i10-spandiv
div
div
div
div class=y10-saving id=y10-saving-row style=displaynone
div class=y10-saving-labelIllustration of how a fixed price could change your outcome at Year 10div
div class=y10-saving-val id=y10-saving-div
div
div class=y10-mortgage-section
div class=detail-section-title style=margin-top0Your mortgage at Year 10div
p class=y10-mortgage-introAt Year 10 you transition to a conventional mortgage at your stronglocked purchase pricestrong, not the market rate. Calculations assume a 20% down payment, 25-year amortization, and monthly payments. Here's what that looks like.p
div class=y10-mortgage-grid
div class=y10-m-field style=grid-column 1 -1;
label class=mc-labelMortgage interest rate — span id=y10-mrate-display style=color#1A5C50; font-weight700;5.5%spanlabel
div style=displayflex; align-itemscenter; gap10px; margin-top6px;
span style=font-size10px; color#aaa;2%span
input type=range id=y10-mrate min=2 max=8 step=0.1 value=5.5 class=y10-slider oninput=document.getElementById('y10-mrate-display').textContent=parseFloat(this.value).toFixed(1)+'%'; var pct=((this.value-2)6100).toFixed(1); this.style.background='linear-gradient(to right,#1A5C50 0%,#1A5C50 '+pct+'%,rgba(26,92,80,0.2) '+pct+'%,rgba(26,92,80,0.2) 100%)'; y10Calc();
span style=font-size10px; color#aaa;8%span
div
div
div
div class=y10-mortgage-results id=y10-mortgage-results style=displaynone
div style=displaygrid; grid-template-columns1fr auto 1fr; gap12px; align-itemsstart;
!-- LEFT If You Wait --
div class=y10-card y10-card-wait
div class=y10-card-header
svg width=16 height=16 viewBox=0 0 24 24 fill=none stroke=currentColor stroke-width=2 stroke-linecap=round stroke-linejoin=roundcircle cx=12 cy=12 r=10polyline points=12 6 12 12 16 14svg
If you wait
div
div class=y10-card-subMarket price at Year 10div
div class=y10-card-big id=y10-wait-price-div
div class=y10-table
div class=y10-table-hdrspanCostspanspanAmountspandiv
div class=y10-table-rowspanDown payment neededspanspan id=y10-wait-dp-spandiv
div class=y10-table-rowspanYour new monthly mortgage costspanspan id=y10-wait-payment-spandiv
div class=y10-table-rowspanDebt % still owing on your homespanspan id=y10-wait-lvr-spandiv
div class=y10-table-row y10-table-finalspanCash needed upfrontspanspan id=y10-wait-warning-cell-spandiv
div
div style=font-size10px; colorrgba(255,255,255,0.3); padding8px 16px 12px; line-height1.5; id=y10-wait-lvr-notediv
div
!-- RIGHT IGVhope --
div class=y10-vsVS.div
div class=y10-card y10-card-igv
div class=y10-card-header y10-igv-header
svg width=16 height=16 viewBox=0 0 24 24 fill=none stroke=currentColor stroke-width=2 stroke-linecap=round stroke-linejoin=roundpath d=M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2zpolyline points=9 22 9 12 15 12 15 22svg
IGVhope pathway
div
div class=y10-card-subYour locked price at Year 10div
div class=y10-card-big y10-card-big-igv id=y10-igv-price-div
div class=y10-table
div class=y10-table-hdrspanCostspanspanAmountspandiv
div class=y10-table-rowspanDown payment coveredspanspan id=y10-igv-dp-spandiv
div class=y10-table-rowspanYour new monthly mortgage costspanspan id=y10-igv-payment-spandiv
div class=y10-table-rowspanDebt % still owing on your homespanspan id=y10-igv-lvr-spandiv
div class=y10-table-row y10-table-finalspanMonthly saving vs waitingspanspan id=y10-igv-saving-note-spandiv
div
div style=font-size10px; colorrgba(255,255,255,0.3); padding8px 16px 12px; line-height1.5; id=y10-igv-lvr-notediv
div
div
div class=y10-es-verdict id=y10-r-verdict style=margin-top16px;-div
!-- Hidden elements kept for JS compatibility --
div style=displaynone
span id=y10-r-gain-span
span id=y10-r-dp-span
span id=y10-r-dp-pct-label-span
span id=y10-r-total-span
span id=y10-r-cmhc-span
span id=y10-r-payment-span
span id=y10-r-saving-span
span id=eq-lvr-market-span
span id=eq-lvr-market-note-span
span id=eq-lvr-market-warning-span
span id=eq-lvr-igv-span
span id=eq-lvr-igv-note-span
div
div
div
div class=y10-lvr-taglineEnter home ownership from a position of strength. Not when you're financially stretched.div
div class=stats-source style=margin-top20pxBCREA Statistics Canada. Market appreciation is illustrative. Mortgage estimates assume Canadian semi-annual compounding. Consult a licensed mortgage professional. These figures are estimates based on historical market data and general economic trends. IGVhope does not guarantee future market performance or property appreciation. All real estate investment carries risk, and outcomes may differ materially from projections. This calculator is provided for illustrative purposes only and does not constitute financial, legal, or investment advice. You should consult a licensed mortgage professional, financial advisor, and independent legal counsel before making any property or investment decision.div
div
div
div id=detail-sidebar
div class=sidebar-price-block
div class=sidebar-price-lblMonthly occupancy paymentdiv
div class=sidebar-price-val id=sb-rent onclick=handleGatedValueClick()div
div class=sidebar-price-sub id=sb-price onclick=handleGatedValueClick()div
div
div class=sidebar-dividerdiv
div id=sb-mortgage-helper style=displaynone; padding12px 14px; border0.5px solid rgba(26,92,80,0.2); border-radius8px; margin-bottom4px;
div style=font-size9px; font-weight700; letter-spacing0.1em; text-transformuppercase; color#1A5C50; margin-bottom10px;Mortgage helper incomediv
div style=displaygrid; grid-template-columns1fr 1fr; gap10px; border-top0.5px solid rgba(26,92,80,0.15); padding-top10px;
div
div style=font-size9px; color#888; text-transformuppercase; letter-spacing0.06em; margin-bottom3px;Suite incomediv
div id=sb-mh-income onclick=handleGatedValueClick() style=font-size18px; font-weight700; color#123D36;$1,800span style=font-size10px; font-weight400; color#aaa; margin-left1px;mospandiv
div
div
div style=font-size9px; color#888; text-transformuppercase; letter-spacing0.06em; margin-bottom3px;Suite typediv
div style=font-size13px; font-weight600; color#123D36;1 bed, 1 bathdiv
div style=font-size10px; color#666;Self-containeddiv
div
div
div style=font-size10px; color#1A5C50; font-styleitalic; border-top0.5px solid rgba(26,92,80,0.15); margin-top10px; padding-top8px; id=sb-mh-locationdiv
div
div class=sidebar-meta-rowspanBedroomsspanstrong id=sb-beds onclick=handleGatedValueClick()strongdiv
div class=sidebar-meta-rowspanBathroomsspanstrong id=sb-baths onclick=handleGatedValueClick()strongdiv
div class=sidebar-meta-rowspanRegionspanstrong id=sb-region onclick=handleGatedValueClick()strongdiv
div class=sidebar-meta-rowspanPathwayspanstrongYear 10 transitionstrongdiv
div class=sidebar-dividerdiv
button class=sidebar-cta primary onclick=startApplication()
svg width=14 height=14 viewBox=0 0 24 24 fill=none stroke=currentColor stroke-width=2.5 stroke-linecap=round stroke-linejoin=roundpath d=M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8zpolyline points=14 2 14 8 20 8svg
Express Interest span style=font-size0.75em;(No Obligation)span
button
button class=sidebar-cta secondary onclick=downloadFloorplan(this)
svg width=14 height=14 viewBox=0 0 24 24 fill=none stroke=currentColor stroke-width=2 stroke-linecap=round stroke-linejoin=roundpath d=M4 4h5path d=M13 4h7path d=M9 4l3.5 3.2path d=M20 4v16H4V4path d=M4 14h4path d=M11 14h4path d=M18 14h2path d=M12 14v3path d=M12 19v1svg
Download the floorplan
button
button class=sidebar-cta secondary onclick=downloadBrochure(this)
svg width=14 height=14 viewBox=0 0 24 24 fill=none stroke=currentColor stroke-width=2.5 stroke-linecap=round stroke-linejoin=roundpath d=M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4polyline points=7 10 12 15 17 10line x1=12 y1=15 x2=12 y2=3svg
Download sales brochure
button
button class=sidebar-cta secondary onclick=bookTour()
svg width=14 height=14 viewBox=0 0 24 24 fill=none stroke=currentColor stroke-width=2.5 stroke-linecap=round stroke-linejoin=roundrect x=3 y=4 width=18 height=18 rx=2 ry=2line x1=16 y1=2 x2=16 y2=6line x1=8 y1=2 x2=8 y2=6line x1=3 y1=10 x2=21 y2=10svg
Book a walkthrough
button
div
div
div
div
div id=lightbox
button id=lightbox-close onclick=lightboxClose()✕button
div id=lightbox-counterdiv
button id=lightbox-prev onclick=lightboxNav(-1)
svg width=20 height=20 viewBox=0 0 24 24 fill=none stroke=currentColor stroke-width=2.5 stroke-linecap=round stroke-linejoin=roundpolyline points=15 18 9 12 15 6svg
button
img id=lightbox-img src= alt=
button id=lightbox-next onclick=lightboxNav(1)
svg width=20 height=20 viewBox=0 0 24 24 fill=none stroke=currentColor stroke-width=2.5 stroke-linecap=round stroke-linejoin=roundpolyline points=9 18 15 12 9 6svg
button
div id=lightbox-dotsdiv
div
style
elevenlabs-convai {
position fixed;
bottom 24px;
right 24px;
z-index 9999;
}
style
elevenlabs-convai agent-id=agent_0501kw59avpvfjh8ggc3qhg7rv2zelevenlabs-convai
div id=gate1-overlay onclick=if(event.target===this)closeGate1();
div id=gate1-modal
button id=gate1-close onclick=closeGate1() aria-label=Close×button
div id=gate1-titleLet us serve you bestdiv
div id=gate1-subTell us more about yourself so we can personalize your experience and keep you in the loop.div
form id=gate1-form onsubmit=handleGate1Submit(event) novalidate
input type=text id=gate1-honeypot class=gate1-honeypot name=website tabindex=-1 autocomplete=off aria-hidden=true
label class=gate1-field-label for=gate1-segmentWhich best describes you span class=gate1-requiredspanlabel
select class=gate1-input id=gate1-segment required
option value= disabled selectedSelect oneoption
option value=Own homeI want to own my own homeoption
option value=Help someoneI want to help someone I care about get into a homeoption
option value=BuilderdeveloperI build or develop housingoption
option value=InvestorlandlordI am an investor or landlordoption
option value=Employercommunity leaderI'm an employer or community leaderoption
option value=Learning moreI'm here to learn more about the programoption
select
div class=gate1-error id=gate1-segment-errorPlease select an option.div
label class=gate1-field-label for=gate1-first-nameFirst name span class=gate1-requiredspanlabel
input class=gate1-input type=text id=gate1-first-name placeholder=John required
div class=gate1-error id=gate1-first-name-errorPlease enter your first name.div
label class=gate1-field-label for=gate1-emailEmail span class=gate1-requiredspanlabel
input class=gate1-input type=email id=gate1-email placeholder=john@email.com required
div class=gate1-error id=gate1-email-errorPlease enter a valid email address.div
label class=gate1-field-label for=gate1-postalPostal code span class=gate1-requiredspanlabel
input class=gate1-input type=text id=gate1-postal placeholder=V9Y 1G1 required
div class=gate1-error id=gate1-postal-errorPlease enter your postal code.div
label id=gate1-consent-label for=gate1-consent
input type=checkbox id=gate1-consent required
spanI consent to IGV Housing collecting, storing and using my personal information in accordance with the a href=httpsigvhousing.comprivacy-policy target=_blank rel=noopener onclick=event.stopPropagation();Privacy Policya. span class=gate1-requiredspanspan
label
div class=gate1-error id=gate1-consent-errorPlease confirm your consent to continue.div
label id=gate1-marketing-label for=gate1-marketing
input type=checkbox id=gate1-marketing
spanI would like to receive marketing emails from IGVhope about new listings, releases and updates.span
label
button type=submit id=gate1-submit-btnContinuebutton
form
div
div
div id=gate2-overlay onclick=if(event.target===this)closeGate2();
div id=gate2-modal
button id=gate2-close onclick=closeGate2() aria-label=Close×button
div id=gate2-titleLet's find your perfect fitdiv
div id=gate2-subA few more details helps us match you to the best homes for you.div
form id=gate2-form onsubmit=handleGate2Submit(event) novalidate
input type=text id=gate2-honeypot class=gate1-honeypot name=website tabindex=-1 autocomplete=off aria-hidden=true
input type=hidden id=gate2-email-hidden name=email
label class=gate1-field-label for=gate2-phonePhone number span class=gate1-requiredspanlabel
input class=gate1-input type=tel id=gate2-phone placeholder=(250) 555-0123 required
div class=gate1-error id=gate2-phone-errorPlease enter your phone number.div
label class=gate1-field-label for=gate2-bedroomsHow many bedrooms do you need span class=gate1-requiredspanlabel
select class=gate1-input id=gate2-bedrooms required
option value= disabled selectedSelect oneoption
option value=1 bedroom1 bedroomoption
option value=2 bedrooms2 bedroomsoption
option value=3 bedrooms3 bedroomsoption
option value=4 or more bedrooms4 or more bedroomsoption
select
div class=gate1-error id=gate2-bedrooms-errorPlease select an option.div
label class=gate1-field-label for=gate2-region-typeWhere would you like IGVhope homes to be available span class=gate1-requiredspanlabel
select class=gate1-input id=gate2-region-type onchange=gate2UpdateRegionField() required
option value= disabled selectedSelect oneoption
option value=Vancouver IslandVancouver Islandoption
option value=BC MainlandBC Mainlandoption
option value=Another Canadian ProvinceAnother Canadian Provinceoption
option value=Outside CanadaOutside Canadaoption
select
div class=gate1-error id=gate2-region-type-errorPlease select an option.div
input class=gate1-input type=text id=gate2-region-detail placeholder=Town or region required
div class=gate1-error id=gate2-region-detail-errorPlease tell us the location.div
label class=gate1-field-label for=gate2-budgetWhat is your monthly budget for housing expenses span class=gate1-requiredspanlabel
select class=gate1-input id=gate2-budget required
option value= disabled selectedSelect oneoption
option value=Over $3,000Over $3,000option
option value=$2,200 to $3,000$2,200 to $3,000option
option value=$1,500 to $2,200$1,500 to $2,200option
option value=Under $1,500Under $1,500option
select
div class=gate1-error id=gate2-budget-errorPlease select an option.div
label class=gate1-field-label for=gate2-timelineWhen would you like to move into your new home span class=gate1-requiredspanlabel
select class=gate1-input id=gate2-timeline required
option value= disabled selectedSelect oneoption
option value=I'm ready to move nowI'm ready to move nowoption
option value=I will be ready in 3-6 monthsI will be ready in 3-6 monthsoption
option value=I need 6-12 months to be readyI need 6-12 months to be readyoption
option value=I'm not ready yet but working on itI'm not ready yet but working on itoption
select
div class=gate1-error id=gate2-timeline-errorPlease select an option.div
label id=gate2-consent-label for=gate2-consent
input type=checkbox id=gate2-consent required
spanI consent to phone communications from IGV Housing and can unsubscribe at any time. span class=gate1-requiredspanspan
label
div class=gate1-error id=gate2-consent-errorPlease confirm your consent to continue.div
button type=submit id=gate2-submit-btnContinuebutton
form
div
div
div id=gate3-overlay onclick=if(event.target===this)closeGate3();
div id=gate3-modal
button id=gate3-close onclick=closeGate3() aria-label=Close×button
div id=gate3-titleLet's check your fitdiv
div id=gate3-subA few quick questions to help us understand your expression of interest.div
form id=gate3-form onsubmit=handleGate3Submit(event) novalidate
input type=text id=gate3-honeypot class=gate1-honeypot name=website tabindex=-1 autocomplete=off aria-hidden=true
input type=hidden id=gate3-email-hidden name=email
label class=gate1-field-label for=gate3-last-nameLast name span class=gate1-requiredspanlabel
input class=gate1-input type=text id=gate3-last-name placeholder=Smith required
div class=gate1-error id=gate3-last-name-errorPlease enter your last name.div
label class=gate1-field-label for=gate3-residencyWhat is your residency status span class=gate1-requiredspanlabel
select class=gate1-input id=gate3-residency required
option value= disabled selectedSelect oneoption
option value=Canadian citizenCanadian citizenoption
option value=Permanent residentPermanent residentoption
option value=Work permit holderWork permit holderoption
option value=Newcomer to CanadaNewcomer to Canadaoption
select
div class=gate1-error id=gate3-residency-errorPlease select an option.div
label class=gate1-field-label for=gate3-individual-incomeWhat is your individual annual income before tax span class=gate1-requiredspanlabel
select class=gate1-input id=gate3-individual-income required
option value= disabled selectedSelect oneoption
option value=Over $100,000Over $100,000option
option value=$75,000 to $100,000$75,000 to $100,000option
option value=$50,000 to $75,000$50,000 to $75,000option
option value=Under $50,000Under $50,000option
select
div class=gate1-error id=gate3-individual-income-errorPlease select an option.div
label class=gate1-field-label for=gate3-household-incomeWhat is your total household annual income before tax span class=gate1-requiredspanlabel
select class=gate1-input id=gate3-household-income required
option value= disabled selectedSelect oneoption
option value=Over $140,000Over $140,000option
option value=$100,000 to $140,000$100,000 to $140,000option
option value=$75,000 to $100,000$75,000 to $100,000option
option value=Under $75,000Under $75,000option
select
div class=gate1-error id=gate3-household-income-errorPlease select an option.div
label class=gate1-field-label for=gate3-debtHow would you describe your current debt situation span class=gate1-requiredspanlabel
select class=gate1-input id=gate3-debt required
option value= disabled selectedSelect oneoption
option value=Little or no debt beyond regular billsLittle or no debt beyond regular billsoption
option value=Some debt but I am managing the paymentsSome debt but I am managing the paymentsoption
option value=I have debt that feels heavy but I am working on itI have debt that feels heavy but I am working on itoption
option value=Debt is a significant challenge for me right nowDebt is a significant challenge for me right nowoption
select
div class=gate1-error id=gate3-debt-errorPlease select an option.div
label class=gate1-field-label for=gate3-work-stabilityHow would you describe your current work or income source span class=gate1-requiredspanlabel
select class=gate1-input id=gate3-work-stability required
option value= disabled selectedSelect oneoption
option value=Stable job or income, two or more yearsStable job or income, two or more yearsoption
option value=Steady work, but in a newer role or fieldSteady work, but in a newer role or fieldoption
option value=Variable or contract-based workVariable or contract-based workoption
option value=Between jobs or income is uncertain right nowBetween jobs or income is uncertain right nowoption
select
div class=gate1-error id=gate3-work-stability-errorPlease select an option.div
button type=submit id=gate3-submit-btnContinuebutton
form
div
div
div id=app-confirm-overlay onclick=if(event.target===this)closeApplicationConfirm();
div id=app-confirm-modal
button id=app-confirm-close onclick=closeApplicationConfirm() aria-label=Close×button
div id=app-confirm-titleThank youdiv
div id=app-confirm-subWe'll be in touch within 3 business days about the next steps for your expression of interest.div
div id=app-confirm-choice
button id=app-confirm-submit-btn onclick=handleSubmitApplicationClick()Express Interest span style=font-size0.75em;(No Obligation)spanbutton
div
div id=app-confirm-done style=displaynone; text-aligncenter; padding16px 0 4px; font-size13px; color#1A5C50; font-weight500; line-height1.5;
strong style=displayblock; font-size15px; margin-bottom4px; font-weight700;Interest submitted ✓strong
We've received your expression of interest and will be in touch within 3 business days.
div
div
div
div id=save-login-overlay onclick=if(event.target===this)closeSaveLogin();
div id=save-login-modal
button id=save-login-close onclick=closeSaveLogin() aria-label=Close×button
div id=save-login-titleSave this homediv
div id=save-login-subSign in to save this home to your account.div
div id=save-login-choices style=displayflex; flex-directioncolumn; gap10px; margin-top18px;
button id=save-login-signin-btn onclick=handleSaveLoginGoToLogin()Log Inbutton
button id=save-login-signup-btn onclick=handleSaveLoginCreateAccount() style=backgroundtransparent; border1.5px solid var(--teal, #1A5C50); colorvar(--teal, #1A5C50);Create an accountbutton
div
div id=save-login-sent
strongCheck your inbox ✓strong
span id=save-login-sent-textA sign-in link is on the way. Click it, and this home will be saved to your account automatically.span
div
div
div
div id=session-saved-overlay onclick=if(event.target===this)closeSessionSavedPopup();
div id=session-saved-modal
button id=session-saved-close onclick=closeSessionSavedPopup() aria-label=Close×button
div id=session-saved-icon
svg width=22 height=22 viewBox=0 0 24 24 fill=none stroke=#1A5C50 stroke-width=2.5 stroke-linecap=round stroke-linejoin=round style=displayblock;polyline points=20 6 9 17 4 12svg
div
div id=session-saved-titleYou're all setdiv
div id=session-saved-subWe've saved your account under this email address, so nothing you do gets lost. Just enter your email next time to get a secure sign-in link.div
div class=session-saved-list
div class=session-saved-row
div class=session-saved-row-iconsvg width=13 height=13 viewBox=0 0 24 24 fill=none stroke=#1A5C50 stroke-width=2.5 stroke-linecap=round stroke-linejoin=roundpath d=M4 21v-7path d=M4 10V3path d=M12 21v-9path d=M12 8V3path d=M20 21v-5path d=M20 12V3path d=M1 14h6path d=M9 8h6path d=M17 16h6svgdiv
div class=session-saved-row-labelYour preferencesdiv
div
div class=session-saved-row
div class=session-saved-row-iconsvg width=13 height=13 viewBox=0 0 24 24 fill=none stroke=#1A5C50 stroke-width=2.5 stroke-linecap=round stroke-linejoin=roundpath d=M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78zsvgdiv
div class=session-saved-row-labelHomes you've saveddiv
div
div class=session-saved-row
div class=session-saved-row-iconsvg width=13 height=13 viewBox=0 0 24 24 fill=none stroke=#1A5C50 stroke-width=2.5 stroke-linecap=round stroke-linejoin=roundpath d=M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8zpolyline points=14 2 14 8 20 8svgdiv
div class=session-saved-row-labelHomes you've expressed interest indiv
div
div class=session-saved-row
div class=session-saved-row-iconsvg width=13 height=13 viewBox=0 0 24 24 fill=none stroke=#1A5C50 stroke-width=2.5 stroke-linecap=round stroke-linejoin=roundcircle cx=12 cy=12 r=10polyline points=12 6 12 12 16 14svgdiv
div class=session-saved-row-labelYour progress toward program admissiondiv
div
div
button id=session-saved-btn onclick=closeSessionSavedPopup()Got it, keep browsingbutton
div id=session-saved-resendDidn't get the email span onclick=resendSessionSavedEmail()Resend itspandiv
div
div
div id=subscribe-prompt-overlay onclick=if(event.target===this)closeSubscribePrompt();
div id=subscribe-prompt-modal
button id=subscribe-prompt-close onclick=closeSubscribePrompt() aria-label=Close×button
div id=subscribe-prompt-icon
svg width=20 height=20 viewBox=0 0 24 24 fill=none stroke=#da8d27 stroke-width=2.5 stroke-linecap=round stroke-linejoin=round style=displayblock;path d=M18 8A6 6 0 0 0 6 8c0 7-3 9-3 9h18s-3-2-3-9path d=M13.73 21a2 2 0 0 1-3.46 0svg
div
div id=subscribe-prompt-titleWant to be first in linediv
div id=subscribe-prompt-subYou're not currently subscribed to release updates. Subscribe and we'll email you the moment new IGVhope homes become available.div
button id=subscribe-prompt-btn onclick=handleSubscribeConfirm()Subscribe mebutton
div id=subscribe-prompt-dismiss onclick=closeSubscribePrompt()Not right nowdiv
div
div
div id=already-subscribed-overlay onclick=if(event.target===this)closeAlreadySubscribed();
div id=already-subscribed-modal
button id=already-subscribed-close onclick=closeAlreadySubscribed() aria-label=Close×button
div id=already-subscribed-icon
svg width=22 height=22 viewBox=0 0 24 24 fill=none stroke=#1A5C50 stroke-width=2.5 stroke-linecap=round stroke-linejoin=round style=displayblock;polyline points=20 6 9 17 4 12svg
div
div id=already-subscribed-titleYou're already on the listdiv
div id=already-subscribed-subYou're subscribed to release updates, so we'll email you the moment new IGVhope homes become available.div
button id=already-subscribed-btn onclick=closeAlreadySubscribed()Got itbutton
div
div
div id=account-view
nav class=account-topbar
button class=account-back-btn onclick=closeAccountView() aria-label=Back to homes
svg width=18 height=18 viewBox=0 0 24 24 fill=none stroke=currentColor stroke-width=2.5 stroke-linecap=round stroke-linejoin=roundpolyline points=15 18 9 12 15 6svg
Back to homes
button
div class=account-topbar-titleMy Accountdiv
div class=account-topbar-spacer
svg width=130 height=30 viewBox=0 0 163 38 fill=none xmlns=httpwww.w3.org2000svg
path d=M34.536 0.747925H39.4049V33.0843H32.427V2.93019C32.427 1.72954 33.3678 0.747925 34.536 0.747925Z fill=#ffffff
path d=M88.8771 21.3374L96.2234 2.32986C96.5919 1.37259 97.4857 0.747925 98.4814 0.747925H104.393L91.8329 33.0843H85.9291L73.3611 0.747925H80.9191L88.8771 21.3293V21.3374Z fill=#ffffff
path d=M67.5122 16.6144H72.2478V28.0855C69.1508 31.6631 64.8544 33.4478 59.374 33.4478C54.7874 33.4478 50.93 31.874 47.8174 28.7264C44.7048 25.5787 43.1445 21.6117 43.1445 16.8172C43.1445 12.0227 44.7283 8.02326 47.9036 4.81071C51.0789 1.60628 54.905 0 59.3897 0C63.8743 0 67.7709 1.52515 71.0796 4.57545L68.8294 7.93402C68.1238 8.98865 66.7282 9.28881 65.7089 8.5668C64.9641 8.03949 64.2663 7.64197 63.5921 7.37426C62.416 6.89562 61.138 6.66036 59.766 6.66036C57.116 6.66036 54.8815 7.5933 53.0625 9.45917C51.2436 11.325 50.3341 13.7831 50.3341 16.8334C50.3341 19.8837 51.2044 22.3337 52.9528 24.1671C54.7011 26.0006 56.7788 26.9173 59.1858 26.9173C61.5928 26.9173 63.6156 26.4386 65.2228 25.4814V18.9589C65.2228 17.6528 66.2421 16.5982 67.5044 16.5982L67.5122 16.6144Z fill=#ffffff
path d=M28.6407 17.0608L25.4418 2.57192C25.2066 1.49296 24.156 0.827731 23.1132 1.09544C22.0705 1.36316 21.4197 2.46646 21.6549 3.55353L24.9479 18.4886C25.1831 19.5595 23.8502 20.2247 23.1916 19.3648L14.2223 7.72336C13.5402 6.83909 12.176 6.52271 11.196 7.03379C10.2159 7.54488 9.97287 8.68063 10.655 9.57301L20.1418 21.8878C20.8082 22.7477 19.883 23.9484 18.9265 23.4697L5.64502 16.8499C4.72771 16.3956 3.56734 16.6552 3.04204 17.5557C2.4305 18.5941 2.83035 19.9164 3.85743 20.4275L17.2408 27.096C18.1974 27.5746 17.8681 29.0673 16.8096 29.0673H1.95224C0.870274 29.0673 0 29.9759 0 31.0874C0 32.1988 0.870274 33.1074 1.95224 33.1074H27.1667C27.9821 33.1074 28.6407 32.4259 28.6407 31.5822V17.0608Z fill=#FBB040
path d=M106.699 26.0738V33.2047H104.018V14.8624H106.699V22.4394C107.083 21.6282 107.655 20.9954 108.432 20.533C109.208 20.0706 110.039 19.8434 110.933 19.8434C112.368 19.8434 113.528 20.2977 114.414 21.2063C115.3 22.1149 115.739 23.4292 115.739 25.1409V33.2128H113.057V25.9846C113.057 23.559 112.085 22.3421 110.141 22.3421C109.216 22.3421 108.408 22.6585 107.726 23.2913C107.036 23.924 106.699 24.857 106.699 26.0738Z fill=#ffffff
path d=M130.126 31.4276C128.848 32.7418 127.256 33.3989 125.343 33.3989C123.43 33.3989 121.831 32.7418 120.56 31.4276C119.283 30.1134 118.647 28.5071 118.647 26.6088C118.647 24.7104 119.283 23.1042 120.56 21.7899C121.838 20.4757 123.43 19.8186 125.343 19.8186C127.256 19.8186 128.848 20.4757 130.126 21.7899C131.404 23.1042 132.039 24.7104 132.039 26.6088C132.039 28.5071 131.404 30.1134 130.126 31.4276ZM122.458 29.724C123.218 30.5271 124.175 30.9246 125.343 30.9246C126.511 30.9246 127.468 30.5271 128.228 29.724C128.989 28.9208 129.365 27.8905 129.365 26.6169C129.365 25.3432 128.989 24.3129 128.228 23.5098C127.468 22.7067 126.511 22.3091 125.343 22.3091C124.175 22.3091 123.218 22.7067 122.458 23.5098C121.697 24.3129 121.321 25.3432 121.321 26.6169C121.321 27.8905 121.697 28.9208 122.458 29.724Z fill=#ffffff
path d=M141.894 19.8362C143.603 19.8362 145.062 20.4446 146.277 21.6696C147.484 22.8946 148.096 24.5171 148.096 26.5452C148.096 28.5733 147.492 30.2283 146.292 31.4938C145.085 32.7675 143.682 33.4003 142.082 33.4003C140.483 33.4003 139.04 32.6702 137.762 31.218V38.0001H135.081V20.0228H137.762V22.3267C138.813 20.6637 140.193 19.8281 141.902 19.8281L141.894 19.8362ZM137.707 26.6426C137.707 27.9 138.076 28.9222 138.805 29.7253C139.542 30.5285 140.428 30.926 141.486 30.926C142.545 30.926 143.454 30.5285 144.238 29.7415C145.022 28.9546 145.414 27.9243 145.414 26.6588C145.414 25.3932 145.03 24.3467 144.27 23.5111C143.501 22.6756 142.584 22.2618 141.518 22.2618C140.451 22.2618 139.55 22.6756 138.813 23.5111C138.076 24.3467 137.715 25.3851 137.715 26.6426H137.707Z fill=#ffffff
path d=M163 27.8253H153.019C153.082 28.7826 153.505 29.5532 154.289 30.1373C155.073 30.7214 155.967 31.0135 156.971 31.0135C158.562 31.0135 159.778 30.4943 160.609 29.4559L162.138 31.192C160.766 32.6603 158.978 33.3986 156.775 33.3986C154.987 33.3986 153.466 32.782 152.22 31.557C150.965 30.3239 150.338 28.6771 150.338 26.6084C150.338 24.5397 150.973 22.8929 152.251 21.6679C153.529 20.451 155.026 19.8345 156.759 19.8345C158.492 19.8345 159.958 20.378 161.173 21.457C162.388 22.5359 162.992 24.0286 162.992 25.927V27.8334L163 27.8253ZM153.019 25.6511H160.319C160.319 24.5478 159.981 23.696 159.315 23.1038C158.649 22.5116 157.818 22.2114 156.838 22.2114C155.857 22.2114 154.972 22.5197 154.195 23.1363C153.411 23.7528 153.019 24.5884 153.019 25.6511Z fill=#ffffff
svg
div
nav
div class=account-tabs
button class=account-tab active data-tab=applications onclick=switchAccountTab('applications')Previous Applicationsbutton
button class=account-tab data-tab=saved onclick=switchAccountTab('saved')Saved Listingsbutton
button class=account-tab data-tab=notifications onclick=switchAccountTab('notifications')Notificationsbutton
div
div class=account-content
div id=account-loading class=account-loadingdiv class=account-spinnerdivdiv
div id=account-panel-applications class=account-panel activediv
div id=account-panel-saved class=account-paneldiv
div id=account-panel-notifications class=account-paneldiv
div
div
canvas id=fireworks-canvas style=positionfixed; inset0; z-index2000; pointer-eventsnone; displaynone;canvas
body
html