(() => {
  'use strict';

  const state = {
    language: localStorage.getItem('inviewra_language') || 'pl',
    market: localStorage.getItem('inviewra_market') || 'PL',
    propertyType: 'residential', area: 80, addons: new Set(),
    config: null, availabilityByMarket: { PL: [], US: [] }, selectedDate: '', selectedSlot: '', lastBookingId: '', appliedMarket: null
  };

  const T = {
    pl: {
      'nav.services':'Usługi','nav.passport':'Space Passport™','nav.pricing':'Cennik','nav.process':'Jak działamy','nav.contact':'Kontakt','nav.book':'Umów skan',
      'hero.eyebrow':'Poznań • Wielkopolska • Teksas','hero.title':'Pokaż przestrzeń.<br><em>Zanim ktoś do niej wejdzie.</em>','hero.lead':'Profesjonalne spacery 3D, cyfrowe bliźniaki i dokumentacja nieruchomości dla sprzedaży, najmu, budowy i zarządzania.','hero.cta':'Wyceń i zarezerwuj','hero.secondary':'Poznaj Space Passport™','hero.trust1':'standardowa dostawa','hero.trust2':'jeden kompletny model','hero.trust3':'obsługa dwóch rynków','hero.ready':'MODEL GOTOWY','hero.hotspot1':'Salon • 28 m²','hero.hotspot2':'Paszport urządzenia','hero.hotspot3':'Historia zmian','hero.scanpoints':'Punkty skanu','hero.area':'Powierzchnia','hero.mode':'Tryb','hero.modeValue':'Publiczny','hero.card1':'pełna nawigacja','hero.card2':'na każde urządzenie',
      'strip.title':'STWORZONE DLA','strip.item1':'NIERUCHOMOŚCI','strip.item2':'DEWELOPERÓW','strip.item3':'HOTELI','strip.item4':'BUDOWNICTWA','strip.item5':'UBEZPIECZEŃ',
      'services.kicker':'JEDEN SKAN. WIELE ZASTOSOWAŃ.','services.title':'Nie tylko spacer.<br><em>Cyfrowa warstwa przestrzeni.</em>','services.lead':'INVIEWRA pomaga sprzedawać szybciej, ograniczać niepotrzebne wizyty, dokumentować stan obiektu i przekazywać wiedzę o nieruchomości.',
      'services.s1t':'Sprzedaż i wynajem','services.s1d':'Wirtualny open house działający 24/7. Klient ogląda układ i przestrzeń przed wizytą.','services.s1a':'Spacer 3D i dollhouse','services.s1b':'Kadry do ogłoszenia','services.s1c':'Link i kod osadzenia',
      'services.s2t':'Deweloperzy i budowa','services.s2d':'Udokumentuj etapy budowy, mieszkanie pokazowe, odbiór i stan przed wykończeniem.','services.s2a':'Porównanie etapów','services.s2b':'Tagi techniczne','services.s2c':'Zdalna współpraca ekip',
      'services.s3t':'Hotele i biznes','services.s3d':'Pozwól gościom i klientom wejść do hotelu, restauracji, showroomu lub lokalu przed rezerwacją.','services.s3a':'Google Street View','services.s3b':'Interaktywne informacje','services.s3c':'Wersje wielojęzyczne',
      'services.s4t':'Ubezpieczenia i szkody','services.s4d':'Cyfrowy zapis stanu przed remontem, po zdarzeniu lub przed przekazaniem obiektu.','services.s4a':'Stan „przed i po”','services.s4b':'Widoczny kontekst szkody','services.s4c':'Prywatny dostęp',
      'services.s5t':'Obiekty wyjątkowe','services.s5d':'Muzea, kościoły, zabytki, jachty, kampery i miejsca, których nie da się opisać samymi zdjęciami.','services.s5a':'Wirtualna dostępność','services.s5b':'Archiwum przestrzeni','services.s5c':'Edukacyjne hotspoty',
      'services.s6t':'Dom rodzinny — Life Archive','services.s6d':'Zachowaj cyfrowo ważne miejsce przed sprzedażą, przeprowadzką, remontem lub zmianą pokoleniową.','services.s6a':'Prywatna pamiątka 3D','services.s6b':'Opis historii i przedmiotów','services.s6c':'Dostęp dla rodziny na świecie',
      'passport.kicker':'FUNKCJA, KTÓRA ZMIENIA SKAN W SYSTEM','passport.lead':'Jeden model nieruchomości, ale różne warstwy dostępu — dla kupującego, właściciela, wykonawcy i ubezpieczyciela.','passport.tab1':'Show Mode','passport.tab2':'Handover Mode','passport.tab3':'TimeLayer™','passport.showTitle':'Publiczna prezentacja bez prywatnych danych','passport.showText':'Czysty spacer sprzedażowy lub hotelowy z opisami, punktami zainteresowania i wezwaniami do działania.','passport.handoverTitle':'Prywatna instrukcja i cyfrowe przekazanie','passport.handoverText':'Gwarancje, numery urządzeń, zawory, filtry, dokumenty i lista usterek przypięte do konkretnych miejsc.','passport.timelineTitle':'Historia obiektu widoczna w czasie','passport.timelineText':'Kolejne skany tworzą oś zmian: przed remontem, po remoncie, przy zmianie najemcy albo po szkodzie.','passport.room1':'SALON','passport.room2':'KUCHNIA','passport.room3':'SYPIALNIA','passport.room4':'ŁAZIENKA','passport.pinPublic':'Naturalne światło','passport.pinPrivate':'Gwarancja pieca • 2029','passport.pinTime':'Zobacz stan przed remontem','passport.layer':'AKTYWNA WARSTWA','passport.b1t':'Więcej wartości','passport.b1d':'Nie jednorazowy spacer, lecz cyfrowy dokument obiektu.','passport.b2t':'Mniej chaosu','passport.b2d':'Informacje techniczne przypięte dokładnie tam, gdzie są potrzebne.',
      'pricing.kicker':'WYCENA BEZ CZEKANIA','pricing.title':'Sprawdź cenę.<br><em>Zarezerwuj w kilka minut.</em>','pricing.lead':'Kalkulator podaje orientacyjną cenę. Ostateczne potwierdzenie następuje po sprawdzeniu zakresu i lokalizacji.','pricing.property':'Twoja przestrzeń','pricing.propertySub':'Wybierz rodzaj i podaj powierzchnię.','pricing.residential':'Dom / mieszkanie','pricing.commercial':'Obiekt komercyjny','pricing.area':'Powierzchnia','pricing.addons':'Dodatki','pricing.addonsSub':'Wybierz tylko to, czego potrzebujesz.','pricing.estimate':'SZACOWANA CENA','pricing.base':'Skan i model 3D','pricing.selected':'Wybrane dodatki','pricing.delivery':'Standardowy termin','pricing.hosting':'Hosting w cenie','pricing.year':'12 miesięcy','pricing.book':'Zarezerwuj ten pakiet','pricing.email':'Wyślij wycenę na e-mail','pricing.note':'Dojazd poza podstawowy obszar działania oraz obiekty o nietypowym układzie mogą wymagać indywidualnej wyceny.','pricing.from':'od',
      'process.kicker':'PROSTO OD PIERWSZEGO KLIKNIĘCIA','process.title':'Od rezerwacji do gotowego linku.<br><em>Bez zbędnego zamieszania.</em>','process.lead':'System prowadzi klienta przez wycenę, termin i przygotowanie obiektu, a operator widzi wszystko w jednym panelu.','process.p1t':'Wyceń i wybierz termin','process.p1d':'Podajesz powierzchnię, adres, dodatki i dogodny termin. Otrzymujesz numer zgłoszenia.','process.p2t':'Przygotuj przestrzeń','process.p2d':'Automatyczna wiadomość przypomina, jak przygotować wnętrze i zabezpieczyć prywatne dane.','process.p3t':'Skanujemy na miejscu','process.p3d':'Operator wykonuje kompletny model, sprawdza przejścia i ustala właściwe warstwy dostępu.','process.p4t':'Odbierasz cyfrową przestrzeń','process.p4d':'Dostajesz link, kod osadzenia i zamówione materiały. Wszystko gotowe do publikacji.',
      'operator.kicker':'PANEL OPERATORA','operator.title':'Rezerwacje, klienci i statusy w jednym miejscu.','operator.text':'Właściciel firmy loguje się do panelu, widzi nowe zgłoszenia, zmienia status realizacji, pobiera kalendarz i eksportuje dane.','operator.cta':'Zobacz panel',
      'ideas.kicker':'GDZIE JESZCZE MOŻNA UŻYĆ SKANU 3D?','ideas.title':'Przestrzenie, których rynek<br><em>jeszcze nie pokazuje wystarczająco dobrze.</em>','ideas.lead':'INVIEWRA może rozwijać osobne produkty dla branż, które potrzebują zdalnego dostępu, dokumentacji albo zachowania przestrzeni.','ideas.i1t':'Jachty, łodzie i kampery','ideas.i1d':'Kupujący może obejrzeć każdą kajutę i schowek bez podróży na drugi koniec kraju.','ideas.i2t':'Dziedzictwo i miejsca pamięci','ideas.i2d':'Cyfrowe zachowanie kościołów, muzeów, zabytków i rodzinnych domów wraz z historią.','ideas.i3t':'Lokacje filmowe','ideas.i3d':'Reżyser, scenograf i producent mogą zdalnie ocenić przestrzeń, zanim wyślą ekipę.','ideas.i4t':'Fabryki i szkolenia','ideas.i4d':'Wirtualne instrukcje, onboarding pracowników i dokumentacja urządzeń osadzona w przestrzeni.',
      'contact.kicker':'ZACZNIJMY OD JEDNEJ PRZESTRZENI','contact.title':'Pokaż nam obiekt.<br><em>My pokażemy jego potencjał.</em>','contact.lead':'Napisz, co chcesz zeskanować. Odpowiemy z rekomendowanym pakietem, zakresem i najbliższym terminem.','contact.coverage':'OBSZAR STARTOWY',
      'form.name':'Imię i nazwisko','form.email':'E-mail','form.phone':'Telefon','form.company':'Firma (opcjonalnie)','form.message':'Co chcesz zeskanować?','form.messagePlaceholder':'Rodzaj obiektu, lokalizacja, metraż i oczekiwany termin...','form.send':'Wyślij zapytanie','form.sending':'Wysyłanie...','form.success':'Dziękujemy. Wiadomość została wysłana.','form.error':'Nie udało się wysłać. Spróbuj ponownie.',
      'footer.tagline':'See every space before you arrive.','footer.services':'Usługi','footer.pricing':'Cennik','footer.company':'Firma','footer.privacy':'Prywatność','footer.terms':'Warunki','footer.rights':'Wszelkie prawa zastrzeżone.','footer.note':'Matterport jest znakiem towarowym jego właściciela. INVIEWRA jest niezależnym dostawcą usług.',
      'booking.kicker':'REZERWACJA ONLINE','booking.step1Title':'Wybierz termin','booking.step1Lead':'Wybierz dzień i godzinę. Termin zostanie ostatecznie potwierdzony po sprawdzeniu lokalizacji.','booking.next':'Dalej','booking.step2Title':'Dane obiektu i kontakt','booking.address':'Adres obiektu','booking.notes':'Dodatkowe informacje','booking.notesPlaceholder':'Piętro, parking, dostęp, szczególne wymagania...','booking.back':'Wstecz','booking.confirm':'Wyślij rezerwację','booking.successTitle':'Rezerwacja została przyjęta','booking.successText':'Potwierdzenie wysłaliśmy e-mailem. Skontaktujemy się po sprawdzeniu zakresu i dojazdu.','booking.reference':'NUMER ZGŁOSZENIA','booking.pay':'Zapłać bezpiecznie online','booking.close':'Zamknij','booking.noSlots':'Brak dostępnych godzin','booking.choose':'Wybierz dzień i godzinę.','booking.sending':'Zapisywanie rezerwacji...','booking.error':'Nie udało się zapisać rezerwacji.','booking.paymentDemo':'Płatności są przygotowane, ale wymagają podłączenia konta Stripe.',
      'emailQuote.title':'Wyślij wycenę','emailQuote.text':'Podaj e-mail, a wyślemy podsumowanie jako zapytanie do zespołu INVIEWRA.','emailQuote.send':'Wyślij','emailQuote.message':'Proszę o potwierdzenie wyceny: {total}. Powierzchnia: {area} {unit}.',
      'coverage.PL':'Poznań i Wielkopolska','coverage.US':'South Texas • Victoria • Port Lavaca • Houston'
    },
    en: {
      'nav.services':'Services','nav.passport':'Space Passport™','nav.pricing':'Pricing','nav.process':'How it works','nav.contact':'Contact','nav.book':'Book a scan',
      'hero.eyebrow':'Poznań • Greater Poland • Texas','hero.title':'Show the space.<br><em>Before anyone steps inside.</em>','hero.lead':'Professional 3D tours, digital twins and property documentation for sales, rentals, construction and operations.','hero.cta':'Price & book','hero.secondary':'Discover Space Passport™','hero.trust1':'standard delivery','hero.trust2':'one complete model','hero.trust3':'two-market service','hero.ready':'MODEL READY','hero.hotspot1':'Living room • 301 ft²','hero.hotspot2':'Equipment passport','hero.hotspot3':'Change history','hero.scanpoints':'Scan points','hero.area':'Area','hero.mode':'Mode','hero.modeValue':'Public','hero.card1':'full navigation','hero.card2':'on every device',
      'strip.title':'BUILT FOR','strip.item1':'REAL ESTATE','strip.item2':'DEVELOPERS','strip.item3':'HOSPITALITY','strip.item4':'CONSTRUCTION','strip.item5':'INSURANCE',
      'services.kicker':'ONE SCAN. MANY USES.','services.title':'More than a tour.<br><em>A digital layer for every space.</em>','services.lead':'INVIEWRA helps properties sell faster, reduces unnecessary visits, documents condition and transfers knowledge about a building.',
      'services.s1t':'Sales & rentals','services.s1d':'A 24/7 virtual open house. Buyers understand the layout and space before visiting.','services.s1a':'3D tour and dollhouse','services.s1b':'Listing-ready snapshots','services.s1c':'Share link and embed code',
      'services.s2t':'Development & construction','services.s2d':'Document construction phases, model units, handovers and pre-finish condition.','services.s2a':'Phase comparison','services.s2b':'Technical tags','services.s2c':'Remote team collaboration',
      'services.s3t':'Hospitality & business','services.s3d':'Let guests enter a hotel, restaurant, showroom or venue before they book.','services.s3a':'Google Street View','services.s3b':'Interactive information','services.s3c':'Multilingual versions',
      'services.s4t':'Insurance & claims','services.s4d':'A digital record before renovation, after an incident or before property handover.','services.s4a':'Before-and-after condition','services.s4b':'Visible claim context','services.s4c':'Private access',
      'services.s5t':'Extraordinary spaces','services.s5d':'Museums, churches, landmarks, yachts, RVs and places ordinary photos cannot explain.','services.s5a':'Virtual access','services.s5b':'Spatial archive','services.s5c':'Educational hotspots',
      'services.s6t':'Family home — Life Archive','services.s6d':'Digitally preserve a meaningful place before a sale, move, renovation or generational change.','services.s6a':'Private 3D keepsake','services.s6b':'Stories and object notes','services.s6c':'Worldwide family access',
      'passport.kicker':'THE FEATURE THAT TURNS A SCAN INTO A SYSTEM','passport.lead':'One property model with different access layers for the buyer, owner, contractor and insurer.','passport.tab1':'Show Mode','passport.tab2':'Handover Mode','passport.tab3':'TimeLayer™','passport.showTitle':'A public presentation without private data','passport.showText':'A clean sales or hospitality tour with descriptions, points of interest and clear calls to action.','passport.handoverTitle':'Private instructions and digital handover','passport.handoverText':'Warranties, serial numbers, valves, filters, documents and punch-list items pinned to their exact locations.','passport.timelineTitle':'See the property evolve over time','passport.timelineText':'Repeat scans create a timeline: before renovation, after completion, at tenant turnover or following damage.','passport.room1':'LIVING','passport.room2':'KITCHEN','passport.room3':'BEDROOM','passport.room4':'BATH','passport.pinPublic':'Natural light','passport.pinPrivate':'Furnace warranty • 2029','passport.pinTime':'View pre-renovation condition','passport.layer':'ACTIVE LAYER','passport.b1t':'More value','passport.b1d':'Not a one-time tour, but a living digital property document.','passport.b2t':'Less confusion','passport.b2d':'Technical knowledge pinned exactly where it is needed.',
      'pricing.kicker':'INSTANT ESTIMATE','pricing.title':'Know the price.<br><em>Book in minutes.</em>','pricing.lead':'The calculator provides an estimate. Final confirmation follows a review of location and project scope.','pricing.property':'Your space','pricing.propertySub':'Choose a type and enter the area.','pricing.residential':'Home / apartment','pricing.commercial':'Commercial property','pricing.area':'Area','pricing.addons':'Add-ons','pricing.addonsSub':'Select only what you need.','pricing.estimate':'ESTIMATED PRICE','pricing.base':'3D scan and model','pricing.selected':'Selected add-ons','pricing.delivery':'Standard delivery','pricing.hosting':'Hosting included','pricing.year':'12 months','pricing.book':'Book this package','pricing.email':'Email this estimate','pricing.note':'Travel outside the core service area and unusually complex properties may require a custom quote.','pricing.from':'from',
      'process.kicker':'SIMPLE FROM THE FIRST CLICK','process.title':'From booking to a live link.<br><em>No unnecessary friction.</em>','process.lead':'The system guides clients through pricing, scheduling and preparation while the operator manages everything in one dashboard.','process.p1t':'Estimate and choose a time','process.p1d':'Enter area, address, add-ons and your preferred appointment. You receive a reference number.','process.p2t':'Prepare the space','process.p2d':'An automatic message explains how to prepare the property and protect private information.','process.p3t':'We scan on site','process.p3d':'The operator creates a complete model, checks navigation and configures the right access layers.','process.p4t':'Receive your digital space','process.p4d':'You receive the link, embed code and ordered deliverables — ready to publish.',
      'operator.kicker':'OPERATOR DASHBOARD','operator.title':'Bookings, customers and statuses in one place.','operator.text':'The business owner logs in, reviews requests, changes job status, downloads calendar files and exports data.','operator.cta':'View dashboard',
      'ideas.kicker':'WHERE ELSE CAN 3D SCANNING CREATE VALUE?','ideas.title':'Spaces the market<br><em>still does not present well enough.</em>','ideas.lead':'INVIEWRA can develop focused products for industries that need remote access, documentation or spatial preservation.','ideas.i1t':'Yachts, boats & RVs','ideas.i1d':'Buyers can explore every cabin and storage area without traveling across the country.','ideas.i2t':'Heritage & memory','ideas.i2d':'Digitally preserve churches, museums, landmarks and family homes together with their stories.','ideas.i3t':'Film locations','ideas.i3d':'Directors, designers and producers can evaluate a location before sending a full crew.','ideas.i4t':'Factories & training','ideas.i4d':'Virtual instructions, employee onboarding and equipment documentation embedded in the space.',
      'contact.kicker':'START WITH ONE SPACE','contact.title':'Show us the property.<br><em>We will reveal its potential.</em>','contact.lead':'Tell us what you want to scan. We will recommend the right package, scope and next available appointment.','contact.coverage':'LAUNCH AREA',
      'form.name':'Full name','form.email':'Email','form.phone':'Phone','form.company':'Company (optional)','form.message':'What would you like scanned?','form.messagePlaceholder':'Property type, location, area and desired date...','form.send':'Send inquiry','form.sending':'Sending...','form.success':'Thank you. Your message has been sent.','form.error':'Could not send the message. Please try again.',
      'footer.tagline':'See every space before you arrive.','footer.services':'Services','footer.pricing':'Pricing','footer.company':'Company','footer.privacy':'Privacy','footer.terms':'Terms','footer.rights':'All rights reserved.','footer.note':'Matterport is a trademark of its owner. INVIEWRA is an independent service provider.',
      'booking.kicker':'ONLINE BOOKING','booking.step1Title':'Choose an appointment','booking.step1Lead':'Select a date and time. We will confirm after reviewing location and scope.','booking.next':'Continue','booking.step2Title':'Property and contact details','booking.address':'Property address','booking.notes':'Additional information','booking.notesPlaceholder':'Floor, parking, access, special requirements...','booking.back':'Back','booking.confirm':'Submit booking','booking.successTitle':'Your request is in','booking.successText':'We sent an email confirmation. We will contact you after reviewing scope and travel.','booking.reference':'BOOKING REFERENCE','booking.pay':'Pay securely online','booking.close':'Close','booking.noSlots':'No available times','booking.choose':'Choose a date and time.','booking.sending':'Saving your booking...','booking.error':'We could not save the booking.','booking.paymentDemo':'Payments are prepared but require a connected Stripe account.',
      'emailQuote.title':'Email this estimate','emailQuote.text':'Enter your email and we will send the estimate as an inquiry to the INVIEWRA team.','emailQuote.send':'Send','emailQuote.message':'Please confirm this estimate: {total}. Area: {area} {unit}.',
      'coverage.PL':'Poznań & Greater Poland','coverage.US':'South Texas • Victoria • Port Lavaca • Houston'
    }
  };

  const $ = (s, p = document) => p.querySelector(s);
  const $$ = (s, p = document) => [...p.querySelectorAll(s)];
  const tr = key => T[state.language][key] ?? key;

  document.addEventListener('DOMContentLoaded', init);

  async function init() {
    bindNavigation();
    bindMarketLanguage();
    bindPassport();
    bindQuoteControls();
    bindForms();
    bindBooking();
    revealOnScroll();
    await loadConfig();
    applyLanguage();
    applyMarket();
    renderQuote();
    renderCalendar();
    showPaymentStatus();
  }

  async function loadConfig() {
    try {
      const res = await fetch('/api/config');
      if (!res.ok) throw new Error('Config error');
      const data = await res.json();
      state.config = data.pricing;
      state.availabilityByMarket = data.availability || { PL: [], US: [] };
    } catch {
      state.config = fallbackPricing();
      state.availabilityByMarket = { PL: fallbackAvailability(), US: fallbackAvailability() };
    }
  }

  function fallbackPricing() {
    return {
      PL:{currency:'PLN',unit:'m²',locale:'pl-PL',taxNote:'ceny netto',tiers:[{max:60,price:499,labelPL:'Mieszkanie do 60 m²',labelEN:'Apartment up to 60 m²'},{max:120,price:699,labelPL:'Mieszkanie 61–120 m²',labelEN:'Apartment 61–120 m²'},{max:200,price:949,labelPL:'Dom / lokal 121–200 m²',labelEN:'House / space 121–200 m²'},{max:350,price:1390,labelPL:'Duży dom 201–350 m²',labelEN:'Large house 201–350 m²'}],overMaxPerUnit:4.5,minimumCommercial:790,addons:{floorplan:{price:149,labelPL:'Plan 2D',labelEN:'2D floor plan'},rush:{price:199,labelPL:'Realizacja do 24 h',labelEN:'24-hour delivery'},google:{price:199,labelPL:'Publikacja Google Street View',labelEN:'Google Street View publishing'},tags:{price:99,labelPL:'Pakiet 10 interaktywnych tagów',labelEN:'10 interactive tags'},hosting:{price:149,labelPL:'Dodatkowy rok hostingu',labelEN:'Additional year of hosting'}}},
      US:{currency:'USD',unit:'ft²',locale:'en-US',taxNote:'before applicable tax',tiers:[{max:1500,price:249,labelPL:'Nieruchomość do 1 500 ft²',labelEN:'Property up to 1,500 ft²'},{max:2500,price:329,labelPL:'Nieruchomość 1 501–2 500 ft²',labelEN:'Property 1,501–2,500 ft²'},{max:4000,price:449,labelPL:'Nieruchomość 2 501–4 000 ft²',labelEN:'Property 2,501–4,000 ft²'},{max:6000,price:649,labelPL:'Nieruchomość 4 001–6 000 ft²',labelEN:'Property 4,001–6,000 ft²'}],overMaxPerUnit:.11,minimumCommercial:299,addons:{floorplan:{price:75,labelPL:'Plan 2D',labelEN:'2D floor plan'},rush:{price:75,labelPL:'Realizacja do 24 h',labelEN:'24-hour delivery'},google:{price:99,labelPL:'Publikacja Google Street View',labelEN:'Google Street View publishing'},tags:{price:59,labelPL:'Pakiet 10 interaktywnych tagów',labelEN:'10 interactive tags'},hosting:{price:79,labelPL:'Dodatkowy rok hostingu',labelEN:'Additional year of hosting'}}}
    };
  }

  function fallbackAvailability() {
    const out = [], now = new Date();
    for (let i=1;i<=28;i++) { const d=new Date(now); d.setDate(d.getDate()+i); if(d.getDay()===0) continue; out.push({date:d.toISOString().slice(0,10),slots:d.getDay()===6?['09:00','12:30']:['09:00','13:00','16:30']}); }
    return out;
  }

  function bindNavigation() {
    addEventListener('scroll', () => $('.site-header').classList.toggle('scrolled', scrollY > 20), { passive: true });
    $('#menuBtn').addEventListener('click', () => { const open=$('#mobileMenu').classList.toggle('open'); $('#menuBtn').setAttribute('aria-expanded', String(open)); });
    $$('#mobileMenu a').forEach(a => a.addEventListener('click', () => $('#mobileMenu').classList.remove('open')));
  }

  function bindMarketLanguage() {
    $$('.market-btn').forEach(btn => btn.addEventListener('click', () => { state.market=btn.dataset.market; localStorage.setItem('inviewra_market',state.market); applyMarket(); renderQuote(); renderCalendar(); }));
    $('#langToggle').addEventListener('click', () => { state.language=state.language==='pl'?'en':'pl'; localStorage.setItem('inviewra_language',state.language); applyLanguage(); renderQuote(); renderCalendar(); });
  }

  function applyLanguage() {
    document.documentElement.lang = state.language;
    $('#langToggle').textContent = state.language === 'pl' ? 'EN' : 'PL';
    $$('[data-i18n]').forEach(el => el.textContent = tr(el.dataset.i18n));
    $$('[data-i18n-html]').forEach(el => el.innerHTML = tr(el.dataset.i18nHtml));
    $$('[data-i18n-placeholder]').forEach(el => el.placeholder = tr(el.dataset.i18nPlaceholder));
    document.title = state.language === 'pl' ? 'INVIEWRA — Spacery 3D i cyfrowe bliźniaki' : 'INVIEWRA — 3D tours and digital twins';
    renderPassportCopy($('.passport-tab.active')?.dataset.mode || 'show');
    updateCoverage();
  }

  function applyMarket() {
    $$('.market-btn').forEach(btn => btn.classList.toggle('active', btn.dataset.market === state.market));
    const isUS = state.market === 'US';
    if (state.appliedMarket && state.appliedMarket !== state.market) {
      state.area = isUS ? Math.max(500, Math.round(state.area * 10.764)) : Math.max(20, Math.round(state.area / 10.764));
    } else if (!state.appliedMarket) {
      state.area = isUS ? 1500 : 80;
    }
    state.appliedMarket = state.market;
    const input = $('#areaInput'), range = $('#areaRange');
    input.value = state.area;
    range.min = isUS ? 300 : 20; range.max = isUS ? 6000 : 350; range.step = isUS ? 100 : 5; range.value = Math.min(Number(range.max), state.area);
    $$('.unit-label').forEach(x => x.textContent = isUS ? 'ft²' : 'm²');
    $('#heroArea').textContent = isUS ? '990 ft²' : '92 m²';
    state.addons.clear();
    updateCoverage();
  }

  function updateCoverage() { $('#coverageText').textContent = tr(`coverage.${state.market}`); }

  function bindPassport() {
    $$('.passport-tab').forEach(btn => btn.addEventListener('click', () => {
      $$('.passport-tab').forEach(b => b.classList.remove('active')); btn.classList.add('active');
      const mode=btn.dataset.mode, canvas=$('#passportCanvas'); canvas.className=`passport-canvas mode-${mode}`;
      $('#modeLabel').textContent = mode==='show'?'SHOW MODE':mode==='handover'?'HANDOVER MODE':'TIMELAYER™';
      renderPassportCopy(mode);
    }));
  }
  function renderPassportCopy(mode) {
    const map = { show:['passport.showTitle','passport.showText'], handover:['passport.handoverTitle','passport.handoverText'], timeline:['passport.timelineTitle','passport.timelineText'] }[mode];
    $('#passportDescription').innerHTML = `<h3>${tr(map[0])}</h3><p>${tr(map[1])}</p>`;
  }

  function bindQuoteControls() {
    $$('#propertyType button').forEach(btn => btn.addEventListener('click', () => { $$('#propertyType button').forEach(b=>b.classList.remove('active')); btn.classList.add('active'); state.propertyType=btn.dataset.type; renderQuote(); }));
    $('#areaInput').addEventListener('input', e => { state.area=Math.max(1,Number(e.target.value)||1); $('#areaRange').value=Math.min(Number($('#areaRange').max),state.area); renderQuote(); });
    $('#areaRange').addEventListener('input', e => { state.area=Number(e.target.value); $('#areaInput').value=state.area; renderQuote(); });
    $('#emailQuote').addEventListener('click', () => $('#emailQuoteModal').showModal());
    $('[data-close-mini]').addEventListener('click', () => $('#emailQuoteModal').close());
  }

  function calculateQuote() {
    const cfg=state.config[state.market], area=state.area;
    let base; const tier=cfg.tiers.find(t=>area<=t.max);
    if(state.propertyType==='commercial') base=Math.max(cfg.minimumCommercial,Math.round(area*cfg.overMaxPerUnit));
    else if(tier) base=tier.price;
    else base=Math.max(cfg.tiers.at(-1).price,Math.round(area*cfg.overMaxPerUnit));
    const addonTotal=[...state.addons].reduce((s,k)=>s+(cfg.addons[k]?.price||0),0);
    return {base,addonTotal,total:base+addonTotal,cfg};
  }
  function formatMoney(value) { const cfg=state.config[state.market]; return new Intl.NumberFormat(cfg.locale,{style:'currency',currency:cfg.currency,maximumFractionDigits:0}).format(value); }
  function renderQuote() {
    if(!state.config) return;
    const {base,addonTotal,total,cfg}=calculateQuote();
    $('#quotePrice').textContent=formatMoney(total); $('#basePrice').textContent=formatMoney(base); $('#addonsPrice').textContent=formatMoney(addonTotal);
    $('#quoteTax').textContent=state.language==='pl'?(state.market==='PL'?'netto':'przed podatkiem'):(state.market==='PL'?'net, VAT excluded':'before applicable tax');
    $('#bookingPriceSummary').textContent=formatMoney(total);
    renderAddons(cfg); renderPriceCards(cfg);
  }
  function renderAddons(cfg) {
    $('#addonList').innerHTML=Object.entries(cfg.addons).map(([key,a])=>`<button type="button" class="addon-item ${state.addons.has(key)?'selected':''}" data-addon="${key}"><div><span class="fake-check">${state.addons.has(key)?'✓':''}</span><b>${state.language==='pl'?a.labelPL:a.labelEN}</b></div><span>+${formatMoney(a.price)}</span></button>`).join('');
    $$('.addon-item').forEach(btn=>btn.addEventListener('click',()=>{ const key=btn.dataset.addon; state.addons.has(key)?state.addons.delete(key):state.addons.add(key); renderQuote(); }));
  }
  function renderPriceCards(cfg) {
    $('#priceCards').innerHTML=cfg.tiers.map((tier,i)=>`<article class="price-card"><span>${i===0?(state.language==='pl'?'START':'START'):`0${i+1}`}</span><b>${formatMoney(tier.price)}</b><small>${state.language==='pl'?tier.labelPL:tier.labelEN}</small></article>`).join('');
  }

  function bindForms() {
    $('#contactForm').addEventListener('submit', async e => {
      e.preventDefault(); const form=e.currentTarget,status=$('.form-status',form),button=$('button[type="submit"]',form); button.disabled=true; status.textContent=tr('form.sending');
      const body=Object.fromEntries(new FormData(form)); Object.assign(body,{market:state.market,language:state.language});
      try { const r=await fetch('/api/contact',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify(body)}); if(!r.ok) throw 0; form.reset(); status.textContent=tr('form.success'); }
      catch { status.textContent=tr('form.error'); }
      finally { button.disabled=false; }
    });
    $('#emailQuoteForm').addEventListener('submit', async e => {
      e.preventDefault(); const form=e.currentTarget,status=$('.form-status',form),{total,cfg}=calculateQuote(),data=Object.fromEntries(new FormData(form));
      const template=tr('emailQuote.message').replace('{total}',formatMoney(total)).replace('{area}',state.area).replace('{unit}',cfg.unit);
      try { const r=await fetch('/api/contact',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({name:data.name,email:data.email,message:template,market:state.market,language:state.language})}); if(!r.ok) throw 0; status.textContent=tr('form.success'); setTimeout(()=>$('#emailQuoteModal').close(),900); }
      catch { status.textContent=tr('form.error'); }
    });
  }

  function bindBooking() {
    $$('[data-open-booking]').forEach(btn=>btn.addEventListener('click',()=>{ resetBooking(); $('#bookingModal').showModal(); }));
    $('#closeBooking').addEventListener('click',()=>$('#bookingModal').close()); $('#finishBooking').addEventListener('click',()=>$('#bookingModal').close());
    $('#toStep2').addEventListener('click',()=>showStep(2)); $('#backStep1').addEventListener('click',()=>showStep(1));
    $('#bookingDetails').addEventListener('submit',submitBooking); $('#paymentButton').addEventListener('click',startPayment);
  }
  function resetBooking() { state.selectedDate=''; state.selectedSlot=''; showStep(1); renderCalendar(); }
  function showStep(step) { $$('.booking-step').forEach(s=>s.classList.toggle('active',Number(s.dataset.step)===step)); $$('.modal-progress i').forEach((i,index)=>i.classList.toggle('active',index<step)); }
  function renderCalendar() {
    const availability = state.availabilityByMarket[state.market] || [];
    if(!availability.length) return;
    const list=availability.slice(0,12), locale=state.language==='pl'?'pl-PL':'en-US';
    $('#calendarDays').innerHTML=list.map(d=>{ const date=new Date(`${d.date}T12:00:00`); return `<button class="day-btn ${state.selectedDate===d.date?'active':''}" data-date="${d.date}"><span>${new Intl.DateTimeFormat(locale,{weekday:'short'}).format(date)}</span><b>${new Intl.DateTimeFormat(locale,{day:'2-digit',month:'short'}).format(date)}</b></button>`; }).join('');
    $$('.day-btn').forEach(btn=>btn.addEventListener('click',()=>{state.selectedDate=btn.dataset.date;state.selectedSlot='';renderCalendar();}));
    const current=availability.find(d=>d.date===state.selectedDate); $('#timeSlots').innerHTML=current?(current.slots||[]).map(s=>`<button class="slot-btn ${state.selectedSlot===s?'active':''}" data-slot="${s}">${s}</button>`).join(''):`<p>${tr('booking.choose')}</p>`;
    $$('.slot-btn').forEach(btn=>btn.addEventListener('click',()=>{state.selectedSlot=btn.dataset.slot;renderCalendar();}));
    $('#toStep2').disabled=!(state.selectedDate&&state.selectedSlot);
    if(state.selectedDate&&state.selectedSlot) { const d=new Date(`${state.selectedDate}T12:00:00`); $('#bookingDateSummary').textContent=`${new Intl.DateTimeFormat(locale,{dateStyle:'medium'}).format(d)} • ${state.selectedSlot}`; }
  }
  async function submitBooking(e) {
    e.preventDefault(); const form=e.currentTarget,button=$('button[type="submit"]',form),original=button.textContent; button.disabled=true; button.textContent=tr('booking.sending');
    const data=Object.fromEntries(new FormData(form)); Object.assign(data,{market:state.market,language:state.language,date:state.selectedDate,slot:state.selectedSlot,area:state.area,propertyType:state.propertyType,addons:[...state.addons]});
    try {
      const r=await fetch('/api/bookings',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify(data)}),out=await r.json(); if(!r.ok) throw new Error(out.error||'Error');
      state.lastBookingId=out.booking.id; $('#bookingReference').textContent=out.booking.reference; $('#paymentButton').hidden=false; $('#paymentButton').dataset.available=out.checkoutAvailable?'yes':'no'; showStep(3); form.reset();
    } catch(err) { toast(err.message||tr('booking.error')); }
    finally { button.disabled=false; button.textContent=original; }
  }
  async function startPayment() {
    if(!state.lastBookingId) return;
    try { const r=await fetch('/api/checkout',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({bookingId:state.lastBookingId})}),out=await r.json(); if(out.url) location.href=out.url; else toast(out.message||tr('booking.paymentDemo')); }
    catch { toast(tr('booking.paymentDemo')); }
  }

  function revealOnScroll() {
    const observer=new IntersectionObserver(entries=>entries.forEach(e=>{if(e.isIntersecting){e.target.classList.add('visible');observer.unobserve(e.target);}}),{threshold:.08}); $$('.reveal').forEach(el=>observer.observe(el));
  }
  function toast(message) { const el=$('#toast'); el.textContent=message; el.classList.add('show'); clearTimeout(toast.timer); toast.timer=setTimeout(()=>el.classList.remove('show'),4200); }
  function showPaymentStatus() { const p=new URLSearchParams(location.search).get('payment'); if(p==='success') toast(state.language==='pl'?'Płatność została rozpoczęta pomyślnie.':'Payment completed successfully.'); if(p==='cancelled') toast(state.language==='pl'?'Płatność została anulowana.':'Payment was cancelled.'); }
})();
