WEDDING
Robert & Patricia
WEDDING
Robert & Patricia
10 · 01 · 2026
document.addEventListener( "DOMContentLoaded", function () { const cover = document.getElementById( "inviteCover" ); const button = document.getElementById( "openInvite" ); const background = document.getElementById( "coverBackground" ); const music = document.getElementById( "lumiereMusic" ); if ( !cover || !button ) { return; } const finalVolume = 0.65; if (music) { music.volume = 0; } function fadeInMusic() { if (!music) { return; } let currentVolume = 0; music.volume = 0; const fadeInterval = setInterval( function () { currentVolume += 0.05; if ( currentVolume >= finalVolume ) { music.volume = finalVolume; clearInterval( fadeInterval ); return; } music.volume = currentVolume; }, 70 ); } button.addEventListener( "click", function () { if ( cover.classList.contains( "is-opening" ) ) { return; } if (music) { music.currentTime = 0; music.volume = 0; const musicPromise = music.play(); if ( musicPromise !== undefined ) { musicPromise.catch( function (error) { console.log( "Lumière: audio blocked", error ); } ); } } button.classList.add( "is-pressed" ); setTimeout( function () { button.classList.remove( "is-pressed" ); cover.classList.add( "is-opening" ); }, 220 ); setTimeout( function () { if (background) { background.classList.add( "is-hidden" ); } }, 1750 ); setTimeout( function () { const invitation = document.getElementById( "invitation" ); if (invitation) { invitation.scrollIntoView({ behavior: "smooth", block: "start" }); } else { window.location.hash = "invitation"; } setTimeout( function () { fadeInMusic(); }, 300 ); }, 2050 ); } ); } );
Robert & Patricia
OUR WEDDING
“I choose you, today and always”
COUNTDOWN
00
DAYS
00
HOURS
00
MIN
00
SEC
/* ================================================== EVENT DATE CHANGE FOR EACH CLIENT ================================================== */ const eventDate = new Date( "2026-10-01T18:30:00" ).getTime(); /* ================================================== UPDATE COUNTDOWN ================================================== */ function updateCountdown() { const now = new Date().getTime(); const distance = eventDate - now; if (distance <= 0) { document.getElementById("days").textContent = "00"; document.getElementById("hours").textContent = "00"; document.getElementById("minutes").textContent = "00"; document.getElementById("seconds").textContent = "00"; return; } const days = Math.floor( distance / (1000 * 60 * 60 * 24) ); const hours = Math.floor( ( distance % (1000 * 60 * 60 * 24) ) / (1000 * 60 * 60) ); const minutes = Math.floor( ( distance % (1000 * 60 * 60) ) / (1000 * 60) ); const seconds = Math.floor( ( distance % (1000 * 60) ) / 1000 ); document.getElementById("days").textContent = String(days).padStart(2,"0"); document.getElementById("hours").textContent = String(hours).padStart(2,"0"); document.getElementById("minutes").textContent = String(minutes).padStart(2,"0"); document.getElementById("seconds").textContent = String(seconds).padStart(2,"0"); } updateCountdown(); setInterval( updateCountdown, 1000 );
CEREMONY
10 · 01 · 2026
6:30 PM
The Rooftop
139 Hunter's Grv Ln #400 · Lehi, Utah 84043
GET DIRECTIONS
RECEPTION
10 · 01 · 2026
5:30 PM
The Rooftop
139 Hunter's Grv Ln #400 · Lehi, Utah 84043
GET DIRECTIONS
DRESS CODE
FORMAL
Join us in elegant attire as we celebrate this special occasion together
(function () { const openButton = document.getElementById( "dressMoreButton" ); const modal = document.getElementById( "dressModal" ); const closeButton = document.getElementById( "dressModalClose" ); const overlay = modal ? modal.querySelector( ".dress-modal-overlay" ) : null; if ( !openButton || !modal || !closeButton ) { return; } function openModal() { modal.classList.add( "is-open" ); modal.setAttribute( "aria-hidden", "false" ); document.body.style.overflow = "hidden"; } function closeModal() { modal.classList.remove( "is-open" ); modal.setAttribute( "aria-hidden", "true" ); document.body.style.overflow = ""; } openButton.addEventListener( "click", openModal ); closeButton.addEventListener( "click", closeModal ); if (overlay) { overlay.addEventListener( "click", closeModal ); } document.addEventListener( "keydown", function (event) { if ( event.key === "Escape" && modal.classList.contains( "is-open" ) ) { closeModal(); } } ); })();
(function () { const control = document.getElementById( "lumiereMusicControl" ); const controlWrap = document.getElementById( "lumiereMusicControlWrap" ); const trigger = document.getElementById( "lumiereMusicTrigger" ); if (!control) { console.log( "Lumière: music control not found" ); return; } /* ================================================== SHOW AFTER DRESS CODE ================================================== */ if ( controlWrap && trigger ) { const observer = new IntersectionObserver( function (entries) { entries.forEach( function (entry) { if (entry.isIntersecting) { controlWrap.classList.add( "is-visible" ); observer.disconnect(); } }); }, { threshold: 0, rootMargin: "0px 0px -10% 0px" } ); observer.observe( trigger ); } /* ================================================== CLICK MUSIC NOTE ================================================== */ control.addEventListener( "click", function () { const music = document.getElementById( "lumiereMusic" ); if (!music) { console.log( "Lumière: #lumiereMusic was not found" ); return; } /* ================================================== IF PLAYING → PAUSE ================================================== */ if (!music.paused) { music.pause(); control.classList.add( "is-paused" ); control.setAttribute( "aria-label", "Resume music" ); control.setAttribute( "title", "Resume music" ); return; } /* ================================================== IF PAUSED → RESUME ================================================== */ const playPromise = music.play(); if ( playPromise !== undefined ) { playPromise .then(function () { control.classList.remove( "is-paused" ); control.setAttribute( "aria-label", "Pause music" ); control.setAttribute( "title", "Pause music" ); }) .catch(function (error) { console.log( "Lumière: music could not be resumed", error ); }); } }); })();
MEMORIES
A glimpse of our story
/* ================================================== EMBED 08 — PHOTO POPUP ================================================== */ (function () { const modal = document.getElementById( "momentsModal" ); const modalImage = document.getElementById( "momentsModalImage" ); const closeButton = document.getElementById( "momentsModalClose" ); const overlay = modal ? modal.querySelector( ".moments-modal-overlay" ) : null; const photos = document.querySelectorAll( ".moments-photo" ); if ( !modal || !modalImage || !closeButton ) { return; } function openModal(imageUrl) { modalImage.src = imageUrl; modal.classList.add( "is-open" ); modal.setAttribute( "aria-hidden", "false" ); document.body.style.overflow = "hidden"; } function closeModal() { modal.classList.remove( "is-open" ); modal.setAttribute( "aria-hidden", "true" ); document.body.style.overflow = ""; setTimeout( function () { if ( !modal.classList.contains( "is-open" ) ) { modalImage.src = ""; } }, 300 ); } photos.forEach( function (photo) { photo.addEventListener( "click", function () { const imageUrl = photo.getAttribute( "data-full" ); if (imageUrl) { openModal( imageUrl ); } } ); } ); closeButton.addEventListener( "click", closeModal ); if (overlay) { overlay.addEventListener( "click", closeModal ); } document.addEventListener( "keydown", function (event) { if ( event.key === "Escape" && modal.classList.contains( "is-open" ) ) { closeModal(); } } ); })();
GIFTS
Your presence means the most to us but if you wish to celebrate with a gift you may do so here
GIFT REGISTRY
(function () { /* ================================================== CLIENT CONFIGURATION ================================================== CHANGE ONLY THIS SECTION FOR EACH CLIENT true = show false = hide ================================================== */ const giftConfig = { /* ================================================ GENERAL BLOCK ================================================ */ showSection: true, /* ================================================ MAIN TEXT ================================================ */ description: "Your presence means the most to us but if you wish to celebrate with a gift you may do so here", /* ================================================ GIFT REGISTRY ================================================ */ showRegistry: true, registryUrl: "https://www.amazon.com/wedding/share/robertypatricia", /* ================================================ CASH GIFT ================================================ */ showMoney: true, /* ================================================ VENMO ================================================ */ showVenmo: true, venmo: "@example", /* ================================================ BANK ================================================ */ showBank: true, bank: "Example Bank
Account: XXXX XXXX XXXX XXXX" }; /* ================================================== ELEMENTS ================================================== */ const section = document.getElementById( "lumiereGiftSection" ); const description = document.getElementById( "giftDescription" ); const registryButton = document.getElementById( "giftRegistryButton" ); const moneyButton = document.getElementById( "giftMoneyButton" ); const modal = document.getElementById( "moneyModal" ); const closeButton = document.getElementById( "moneyModalClose" ); const venmoMethod = document.getElementById( "moneyVenmoMethod" ); const venmoText = document.getElementById( "moneyVenmoText" ); const bankMethod = document.getElementById( "moneyBankMethod" ); const bankText = document.getElementById( "moneyBankText" ); const overlay = modal ? modal.querySelector( ".money-modal-overlay" ) : null; /* ================================================== TEXT ================================================== */ if ( description && giftConfig.description ) { description.textContent = giftConfig.description; } /* ================================================== GIFT REGISTRY ================================================== */ if (registryButton) { if ( giftConfig.showRegistry && giftConfig.registryUrl ) { registryButton.style.display = "inline-block"; registryButton.href = giftConfig.registryUrl; } else { registryButton.style.display = "none"; } } /* ================================================== VENMO ================================================== */ if (venmoMethod) { if ( giftConfig.showVenmo && giftConfig.venmo ) { venmoMethod.style.display = "block"; if (venmoText) { venmoText.textContent = giftConfig.venmo; } } else { venmoMethod.style.display = "none"; } } /* ================================================== BANK ================================================== */ if (bankMethod) { if ( giftConfig.showBank && giftConfig.bank ) { bankMethod.style.display = "block"; if (bankText) { bankText.innerHTML = giftConfig.bank; } } else { bankMethod.style.display = "none"; } } /* ================================================== DETERMINE WHETHER A CASH GIFT METHOD EXISTS ================================================== */ const hasMoneyMethod = ( giftConfig.showVenmo && giftConfig.venmo ) || ( giftConfig.showBank && giftConfig.bank ); /* ================================================== CASH GIFT BUTTON ================================================== */ if (moneyButton) { if ( giftConfig.showMoney && hasMoneyMethod ) { moneyButton.style.display = "inline-block"; } else { moneyButton.style.display = "none"; } } /* ================================================== IF NO GIFT OPTION EXISTS HIDE THE ENTIRE BLOCK ================================================== */ const hasRegistry = giftConfig.showRegistry && giftConfig.registryUrl; const hasMoney = giftConfig.showMoney && hasMoneyMethod; if ( section && ( !giftConfig.showSection || (!hasRegistry && !hasMoney) ) ) { section.style.display = "none"; } /* ================================================== IF THERE IS NO CASH GIFT OPTION THE MODAL IS NOT NEEDED ================================================== */ if ( modal && !hasMoney ) { modal.style.display = "none"; } /* ================================================== MODAL FUNCTIONS ================================================== */ function openModal() { if (!modal) { return; } modal.classList.add( "is-open" ); modal.setAttribute( "aria-hidden", "false" ); document.body.style.overflow = "hidden"; } function closeModal() { if (!modal) { return; } modal.classList.remove( "is-open" ); modal.setAttribute( "aria-hidden", "true" ); document.body.style.overflow = ""; } /* ================================================== CLICK CASH GIFT ================================================== */ if ( moneyButton && hasMoney ) { moneyButton.addEventListener( "click", openModal ); } /* ================================================== CLOSE ================================================== */ if (closeButton) { closeButton.addEventListener( "click", closeModal ); } if (overlay) { overlay.addEventListener( "click", closeModal ); } document.addEventListener( "keydown", function (event) { if ( event.key === "Escape" && modal && modal.classList.contains( "is-open" ) ) { closeModal(); } } ); })();
RSVP
We would love to celebrate this special day with you
Please RSVP by September 20
WILL YOU BE JOINING US?
THANK YOU!
(function () { const form = document.getElementById( "rsvpForm" ); const yesOption = document.getElementById( "rsvpYes" ); const noOption = document.getElementById( "rsvpNo" ); const companionsSelect = document.getElementById( "rsvpCompanions" ); const companionNames = document.getElementById( "rsvpCompanionNames" ); const success = document.getElementById( "rsvpSuccess" ); const successText = document.getElementById( "rsvpSuccessText" ); const description = document.getElementById( "rsvpDescription" ); const deadline = document.getElementById( "rsvpDeadline" ); const submitButton = document.getElementById( "rsvpSubmit" ); const hiddenFrame = document.getElementById( "rsvpHiddenFrame" ); if ( !form || !yesOption || !noOption || !companionsSelect || !success || !successText || !submitButton || !hiddenFrame ) { return; } let submitting = false; let submittedAttendance = ""; let submittedCompanions = 0; /* ================================================== IF CHANGED TO NO CLEAR GUESTS ================================================== */ noOption.addEventListener( "change", function () { if (!noOption.checked) { return; } companionsSelect.value = "0"; companionNames.value = ""; companionNames.required = false; } ); /* ================================================== GUEST NAMES REQUIRED IF THERE ARE GUESTS ================================================== */ companionsSelect.addEventListener( "change", function () { const quantity = Number( companionsSelect.value ); companionNames.required = quantity > 0; if (quantity === 0) { companionNames.value = ""; } } ); /* ================================================== SUCCESS MESSAGE ================================================== */ function createSuccessMessage() { if ( submittedAttendance === "No" ) { successText.innerHTML = "Thank you for letting us know.

" + "We will miss celebrating this special day with you"; return; } if ( submittedCompanions > 0 ) { successText.innerHTML = "We have received your RSVP.

" + " We are so excited to celebrate this special day with you and your guests"; return; } successText.innerHTML = "We have received your RSVP.

" + " We are so excited to celebrate this special day with you"; } /* ================================================== GOOGLE RECEIVED THE RESPONSE ================================================== */ hiddenFrame.addEventListener( "load", function () { if (!submitting) { return; } submitting = false; if (description) { description.style.display = "none"; } if (deadline) { deadline.style.display = "none"; } form.style.display = "none"; createSuccessMessage(); success.style.display = "block"; success.scrollIntoView({ behavior: "smooth", block: "center" }); } ); /* ================================================== SUBMIT ================================================== */ form.addEventListener( "submit", function (event) { if (submitting) { event.preventDefault(); return; } if (yesOption.checked) { submittedAttendance = "Yes"; submittedCompanions = Number( companionsSelect.value || 0 ); } else { submittedAttendance = "No"; submittedCompanions = 0; } submitting = true; submitButton.disabled = true; submitButton.textContent = "SENDING..."; } ); })();
IMPORTANT
A few details to help us enjoy this special day together
(function () { const openButton = document.getElementById( "notesMoreButton" ); const modal = document.getElementById( "notesModal" ); const closeButton = document.getElementById( "notesModalClose" ); const overlay = modal ? modal.querySelector( ".notes-modal-overlay" ) : null; if ( !openButton || !modal || !closeButton ) { return; } function openModal() { modal.classList.add( "is-open" ); modal.setAttribute( "aria-hidden", "false" ); document.body.style.overflow = "hidden"; } function closeModal() { modal.classList.remove( "is-open" ); modal.setAttribute( "aria-hidden", "true" ); document.body.style.overflow = ""; } openButton.addEventListener( "click", openModal ); closeButton.addEventListener( "click", closeModal ); if (overlay) { overlay.addEventListener( "click", closeModal ); } document.addEventListener( "keydown", function (event) { if ( event.key === "Escape" && modal.classList.contains( "is-open" ) ) { closeModal(); } } ); })();
Robert & Patricia
Thank you for being part of our story
10 · 01 · 2026
(function () { const section = document.querySelector(".final-section"); if (!section) { return; } if ("IntersectionObserver" in window) { const observer = new IntersectionObserver( function (entries) { entries.forEach( function (entry) { if (entry.isIntersecting) { section.classList.add( "is-visible" ); observer.unobserve( section ); } }); }, { threshold: .25 } ); observer.observe( section ); } else { section.classList.add( "is-visible" ); } })();