Calculator

Enter your text here...

<!-- SKRYTÍ SLEVY 5 % – pouze vizuálně, funkčnost ponechána --><style>/* Schovat tlačítko 'Zavřít' pod kalkulátorem */button[onclick="closeDeliveryAddressModal()"] { display: none !important; }#prepaymentDiscountCheckbox,label[for="prepaymentDiscountCheckbox"],#prepaymentDiscountCheckbox-90x13,label[for="prepaymentDiscountCheckbox-90x13"],#prepaymentDiscountCheckbox-150x12,label[for="prepaymentDiscountCheckbox-150x12"] {display: none !important;}</style><!--DŮLEŽITÉ PRO EMAILJS ŠABLONY:Aby se HTML (rekapitulace, vstupní tabulka, kalkulace) nerenderovalo jako prostý text,použijte v EmailJS šablonách TROJITÉ složené závorky:{{{summary_html}}}{{{entry_table_html}}}{{{calculation_html}}}Upravte to v admin i zákaznické šabloně.--><style>.clickable-pickup { cursor: pointer; }.clickable-pickup:hover { text-decoration: underline; }</style><style>/* --- STYLY PRO MODÁLNÍ OKNO OBJEDNÁVKY --- */.modal-overlay {position: fixed;top: 0;left: 0;width: 100%;height: 100%;background-color: rgba(0, 0, 0, 0.5);display: none; /* Skryto defaultně */justify-content: center;align-items: flex-start;z-index: 2000;opacity: 0;transition: opacity 0.3s ease;overflow-y: auto;}.modal-overlay.open {display: flex;opacity: 1;}.modal-content-slide {background-color: #fff;padding: 2.5rem;border-radius: 0 0 16px 16px;box-shadow: 0 15px 30px rgba(0, 0, 0, 0.4);width: 95%;max-width: 800px;margin-top: 50px;transform: translateY(-100vh);opacity: 0;transition: transform 0.4s ease-out, opacity 0.4s ease-out;max-height: calc(100vh - 100px);overflow-y: auto;}.modal-overlay.open .modal-content-slide {transform: translateY(0);opacity: 1;}/* --- KONEC STYLŮ MODÁLU --- */.company-fields-animated {transition: max-height 0.4s ease-in-out, opacity 0.4s ease-in-out, padding 0.4s ease-in-out;max-height: 0;opacity: 0;overflow: hidden;padding-top: 0 !important;padding-bottom: 0 !important;}.company-fields-animated.open {max-height: 800px;opacity: 1;padding-top: 1rem !important;padding-bottom: 1rem !important;}.delivery-fields-inner-animated {transition: max-height 0.4s ease-in-out, opacity 0.4s ease-in-out, margin 0.4s ease-in-out;max-height: 0;opacity: 0;overflow: hidden;margin-top: 0 !important;margin-bottom: 0 !important;}.delivery-fields-inner-animated.open {max-height: 500px;opacity: 1;margin-top: 1rem !important;margin-bottom: 1rem !important;}/* Message box used by showMessage() */.message-box {position: fixed;bottom: 20px;left: 50%;transform: translateX(-50%);background-color: #22c55e;color: white;padding: 1rem 2rem;border-radius: 10px;box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);z-index: 3000;opacity: 0;transition: opacity 0.5s ease-in-out;}/* jednotný vzhled všech tlačítek */.calculate-button,.highlighted-button,#terraceSaveToPdfButton,#fence90x13SaveToPdfButton,#fence150x12SaveToPdfButton {font-family: 'Inter', sans-serif;background-image: linear-gradient(0deg, var(--lw-green) 0%, #ffffff 100%);color: #0b3d0b;border: 1px solid rgba(106,170,61,0.25);transition: transform .2s, box-shadow .2s, background-position .3s;background-size: 100% 200%;background-position: 0% 100%;}.calculate-button:hover,.highlighted-button:hover,#terraceSaveToPdfButton:hover,#fence90x13SaveToPdfButton:hover,#fence150x12SaveToPdfButton:hover {background-image: linear-gradient(0deg, var(--lw-green-2) 0%, #ffffff 100%);transform: translateY(-1px);box-shadow: 0 6px 16px rgba(106,170,61,0.25);background-position: 0% 0%;}</style><link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" crossorigin=""><script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js" crossorigin="">'use strict';</script><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Kalkulátor WPC</title><script src="https://cdnjs.cloudflare.com/ajax/libs/html2canvas/1.4.1/html2canvas.min.js"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js"></script><script src="https://cdn.tailwindcss.com"></script><style>@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap');:root{/* Lambowood brand – uprav podle manuálu, pokud máš přesné HEX */--lw-green: #6AAA3D;--lw-green-2: #8CCB4A; /* pro hover */}body { font-family: 'Inter', sans-serif; background-color: #f7fafc; }.container { max-width: 1000px; margin: 0 auto; padding: 2rem; }.card { background-color: #ffffff; border-radius: 12px; box-shadow: 0 10px 15px -3px rgba(0,0,0,0.1), 0 4px 6px -2px rgba(0,0,0,0.05); padding: 2rem; }/* sjednocený brand vzhled pro všechna NE-PDF tlačítka (vč. navigace) */.nav-link-box,.calculate-button,.highlighted-button {font-family: 'Inter', sans-serif;/*⬇️přechod zdola nahoru */background-image: linear-gradient(0deg, var(--lw-green) 0%, #ffffff 100%);color: #0b3d0b;border: 1px solid rgba(106,170,61,0.25);transition: transform .2s, box-shadow .2s, background-position .3s;background-size: 100% 200%;background-position: 0% 100%; /* start – zelená dole */}.nav-link-box:hover,.calculate-button:hover,.highlighted-button:hover {/*⬇️hover varianta, taky zdola nahoru */background-image: linear-gradient(0deg, var(--lw-green-2) 0%, #ffffff 100%);transform: translateY(-1px);box-shadow: 0 6px 16px rgba(106,170,61,0.25);background-position: 0% 0%; /* animace posunu nahoru */}/* aktivní záložka */.nav-link-box.active-link {background-image: none;background-color: var(--lw-green);color: #ffffff;border-color: transparent;box-shadow: 0 6px 14px rgba(106,170,61,0.28);}/* PDF tlačítka ponechána modrá */#terraceSaveToPdfButton,#fence90x13SaveToPdfButton,#fence150x12SaveToPdfButton {background-color: #2563eb; /* Tailwind blue-600 */color: #ffffff;transition: background-color .2s, box-shadow .2s;}#terraceSaveToPdfButton:hover,#fence90x13SaveToPdfButton:hover,#fence150x12SaveToPdfButton:hover {background-color: #1d4ed8; /* blue-700 */box-shadow: 0 6px 14px rgba(37, 99, 235, 0.25);}input[type="number"]::-webkit-inner-spin-button,input[type="number"]::-webkit-outer-spin-button { -webkit-appearance: none; margin: 0; }.hint { font-size: 12px; color: #6b7280; }/* jednotný vzhled všech tlačítek */.calculate-button,.highlighted-button,#terraceSaveToPdfButton,#fence90x13SaveToPdfButton,#fence150x12SaveToPdfButton {font-family: 'Inter', sans-serif;background-image: linear-gradient(0deg, var(--lw-green) 0%, #ffffff 100%);color: #0b3d0b;border: 1px solid rgba(106,170,61,0.25);transition: transform .2s, box-shadow .2s, background-position .3s;background-size: 100% 200%;background-position: 0% 100%;}.calculate-button:hover,.highlighted-button:hover,#terraceSaveToPdfButton:hover,#fence90x13SaveToPdfButton:hover,#fence150x12SaveToPdfButton:hover {background-image: linear-gradient(0deg, var(--lw-green-2) 0%, #ffffff 100%);transform: translateY(-1px);box-shadow: 0 6px 16px rgba(106,170,61,0.25);background-position: 0% 0%;}</style><div class="container py-8 px-4"><div class="card"><nav class="mb-8"><ul class="flex flex-col md:flex-row justify-around text-center font-semibold space-y-2 md:space-y-0"><li><a class="nav-link-box inline-block p-2 rounded-lg" data-target="terrace-calculator">Kalkulátor teras</a></li><li><a class="nav-link-box inline-block p-2 rounded-lg" data-target="fence-90x13-calculator">Kalkulátor plotových profilů 90x13 mm</a></li><li><a class="nav-link-box inline-block p-2 rounded-lg" data-target="fence-150x12-calculator">Kalkulátor plotových profilů 150x12 mm</a></li></ul></nav><!-- TERASA --><div id="terrace-calculator"><h1 class="text-3xl font-bold text-center text-gray-900 mb-6">Orientační cenová kalkulace terasy</h1><p class="text-center text-gray-600 mb-8">Zadejte prosím parametry terasy pro výpočet orientační ceny.</p><div class="bg-blue-50 p-4 rounded-lg border-l-4 border-blue-600 mb-6"><p class="text-blue-800 font-semibold">Před objednáním si zkontrolujte dostupnost materiálu <a href="https://drive.google.com/file/d/14ysyAVzcd852sDX1GcnUqTGFJEvCUPOm/view" target="_blank" rel="noopener" class="underline text-blue-800">zde</a>.</p></div><!-- EMAIL (povinné)terasy --><!-- EMAIL (povinné)styl sjednocenýs ostatnímiřádky --><div class="flex flex-col md:flex-row items-center justify-between bg-gray-50 p-4 rounded-lg mb-2"><label for="userEmailTerrace" class="text-sm font-medium text-gray-900 w-full md:w-1/2">Email (povinné)</label><input type="email" id="userEmailTerrace" data-email-required="" class="mt-1 block w-full md:w-1/2 px-3 py-2 bg-white border border-gray-300 rounded-md shadow-sm focus:outline-none" placeholder="např. jan.novak@email.cz"></div><p class="text-xs text-gray-500 mb-6">Bez vyplněného emailu nenímožnéspočítat kalkulaci.</p><form id="calculatorForm"><div class="space-y-6"><div class="flex flex-col md:flex-row items-center justify-between bg-gray-50 p-4 rounded-lg"><label for="vymera" class="text-sm font-medium text-gray-900 w-full md:w-1/2">Výměra terasy v m²</label><input type="number" id="vymera" min="0" step="0.01" value="0" class="mt-1 block w-full md:w-1/2 px-3 py-2 bg-white border border-gray-300 rounded-md shadow-sm focus:outline-none"></div><div class="flex flex-col md:flex-row items-center justify-between bg-gray-50 p-4 rounded-lg"><label for="obvod" class="text-sm font-medium text-gray-900 w-full md:w-1/2">Výměra obvodu terasy k lištování v bm</label><input type="number" id="obvod" min="0" step="0.01" value="0" class="mt-1 block w-full md:w-1/2 px-3 py-2 bg-white border border-gray-300 rounded-md shadow-sm focus:outline-none"></div><div class="flex flex-col md:flex-row items-center justify-between bg-gray-50 p-4 rounded-lg"><label for="terraceColorSelection" class="text-sm font-medium text-gray-900 w-full md:w-1/2">Vyberte odstín terasy:</label><select id="terraceColorSelection" class="mt-1 block w-full md:w-1/2 px-3 py-2 border border-gray-300 rounded-md"><option value="original-wood">Original wood</option><option value="teak">Teak</option><option value="brownisch-red">Brownisch red</option><option value="chocolate">Chocolate</option><option value="stone-grey">Stone grey</option><option value="dark-grey">Dark grey</option></select></div><div class="flex items-center bg-gray-50 p-4 rounded-lg"><label for="montazCheckbox" class="text-sm font-medium text-gray-900 mr-2">Montáž na ideální podloží viz. montážní návod</label><input type="checkbox" id="montazCheckbox" class="h-5 w-5 text-stone-800 border-gray-300 rounded focus:ring-stone-800"></div><p class="text-red-600 text-sm mt-2"><strong>Celková částka se může lišit v závislosti na stavu podloží — pro přesnou kalkulaci je nutné objednat zaměření.</strong></p><div class="flex items-center bg-gray-50 p-4 rounded-lg"><label for="prepaymentDiscountCheckbox" class="text-sm font-medium text-gray-900 mr-2">Sleva 5 % při platbě předem</label><input type="checkbox" id="prepaymentDiscountCheckbox" class="h-5 w-5 text-stone-800 border-gray-300 rounded focus:ring-stone-800"></div></div><button type="submit" class="calculate-button w-full mt-8 flex justify-center py-2 px-4 border border-transparent rounded-md shadow-sm text-sm font-medium">Spočítat cenu</button></form><div id="terrace-results" class="mt-8 hidden"><h2 class="text-2xl font-bold text-gray-900 mb-4">Výsledná kalkulace</h2><div class="bg-amber-50 p-4 rounded-lg border-l-4 border-amber-500 mb-6"><p class="font-bold text-amber-800">Všechny uvedené ceny jsou pouze orientační.</p></div><div class="overflow-x-auto"><table class="min-w-full divide-y divide-gray-200"><thead class="bg-gray-50"><tr><th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Položka</th><th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Počet kusů</th><th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Cena bez DPH (Kč)</th></tr></thead><tbody class="bg-white divide-y divide-gray-200" id="terraceCalculationTableBody"></tbody><tfoot class="bg-gray-50"><tr><td colspan="2" class="px-6 py-3 text-left font-bold text-gray-900 uppercase">Celkem bez DPH</td><td id="terraceTotalPrice" class="px-6 py-3 text-right font-bold text-gray-900">0 Kč</td></tr><tr><td colspan="2" class="px-6 py-3 text-left font-bold text-gray-900 uppercase">Celkem s DPH</td><td id="terraceTotalPriceVAT" class="px-6 py-3 text-right font-bold text-gray-900">0 Kč</td></tr></tfoot></table></div><div class="flex flex-col md:flex-row justify-center space-y-4 md:space-y-0 md:space-x-4 mt-6"><button id="terraceNewButton1" class="w-full md:w-auto py-2 px-4 border border-transparent rounded-md shadow-sm text-sm font-medium highlighted-button">Objednat materiál</button><button id="terraceSaveToPdfButton" class="w-full md:w-auto py-2 px-4 border border-transparent rounded-md shadow-sm text-sm font-medium text-white">Uložit jako PDF</button><button id="terraceNewButton2" class="w-full md:w-auto py-2 px-4 border border-transparent rounded-md shadow-sm text-sm font-medium highlighted-button">Objednat zaměření</button></div></div></div><!-- PLOT 90x13 --><div id="fence-90x13-calculator" class="hidden"><h1 class="text-3xl font-bold text-center text-gray-900 mb-6">Orientační cenová kalkulace plotových profilů 90x13 mm (svislé použití)</h1><div class="bg-red-50 p-4 rounded-lg border-l-4 border-red-600 mb-6"><p class="text-red-800 font-extrabold uppercase tracking-wide">UPOZORNĚNÍ: Jedná se POUZE o cenovou kalkulaci plotové výplně a montáže WPC</p></div><div class="bg-blue-50 p-4 rounded-lg border-l-4 border-blue-600 mb-6"><p class="text-blue-800 font-semibold">Před objednáním si zkontrolujte dostupnost materiálu <a href="https://drive.google.com/file/d/14ysyAVzcd852sDX1GcnUqTGFJEvCUPOm/view" target="_blank" rel="noopener" class="underline text-blue-800">zde</a>.</p></div><!-- EMAIL (povinné)plot 90x13 --><!-- EMAIL (povinné)styl sjednocenýs ostatnímiřádky --><div class="flex flex-col md:flex-row items-center justify-between bg-gray-50 p-4 rounded-lg mb-2"><label for="userEmail90x13" class="text-sm font-medium text-gray-900 w-full md:w-1/2">Email (povinné)</label><input type="email" id="userEmail90x13" data-email-required="" class="mt-1 block w-full md:w-1/2 px-3 py-2 bg-white border border-gray-300 rounded-md shadow-sm focus:outline-none" placeholder="např. jan.novak@email.cz"></div><p class="text-xs text-gray-500 mb-6">Bez vyplněného emailu nenímožnéspočítat kalkulaci.</p><p class="text-center text-gray-600 mb-8">Zadejte prosím parametry plotu pro výpočet orientační ceny.</p><form id="fence90x13Form"><div id="fencePanelsContainer-90x13" class="space-y-8"></div><div class="flex items-center mt-4"><button type="button" id="addFencePanelBtn-90x13" class="highlighted-button w-full md:w-auto flex-1 py-2 px-4 border border-transparent rounded-md shadow-sm text-sm font-medium">+ Přidat další pole</button></div><div class="space-y-6 mt-8"><div class="bg-gray-50 p-4 rounded-lg flex items-center"><label for="triangularHeadCheckbox-90x13" class="text-sm font-medium text-gray-900 mr-2">Příplatek za tříhrannou hlavu (pro všechna pole)</label><input type="checkbox" id="triangularHeadCheckbox-90x13" class="h-5 w-5 text-stone-800 border-gray-300 rounded focus:ring-stone-800"></div><div class="bg-gray-50 p-4 rounded-lg flex items-center"><label for="montazFenceCheckbox-90x13" class="text-sm font-medium text-gray-900 mr-2">Montáž (pro všechna pole)</label><input type="checkbox" id="montazFenceCheckbox-90x13" class="h-5 w-5 text-stone-800 border-gray-300 rounded focus:ring-stone-800"></div><div class="flex items-center bg-gray-50 p-4 rounded-lg"><label for="prepaymentDiscountCheckbox-90x13" class="text-sm font-medium text-gray-900 mr-2">Sleva 5 % při platbě předem</label><input type="checkbox" id="prepaymentDiscountCheckbox-90x13" class="h-5 w-5 text-stone-800 border-gray-300 rounded focus:ring-stone-800"></div></div><button type="submit" class="calculate-button w-full mt-8 flex justify-center py-2 px-4 border border-transparent rounded-md shadow-sm text-sm font-medium">Spočítat celkovou cenu</button></form><div id="fence-90x13-results" class="mt-8 hidden"><h2 class="text-2xl font-bold text-gray-900 mb-4">Výsledná kalkulace</h2><div class="bg-amber-50 p-4 rounded-lg border-l-4 border-amber-500 mb-6"><p class="font-bold text-amber-800">Všechny uvedené ceny jsou pouze orientační.</p></div><div class="overflow-x-auto"><table class="min-w-full divide-y divide-gray-200"><thead class="bg-gray-50"><tr><th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Položka</th><th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Počet kusů</th><th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Běžných metrů</th><th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Cena bez DPH (Kč)</th></tr></thead><tbody class="bg-white divide-y divide-gray-200" id="fence90x13CalculationTableBody"></tbody><tfoot class="bg-gray-50"><tr><td colspan="3" class="px-6 py-3 text-left font-bold text-gray-900 uppercase">Celkem bez DPH</td><td id="fence90x13TotalPrice" class="px-6 py-3 text-right font-bold text-gray-900">0 Kč</td></tr><tr><td colspan="3" class="px-6 py-3 text-left font-bold text-gray-900 uppercase">Celkem s DPH (12%)</td><td id="fence90x13TotalPriceVAT" class="px-6 py-3 text-right font-bold text-gray-900">0 Kč</td></tr></tfoot></table></div><div class="flex flex-col md:flex-row justify-center space-y-4 md:space-y-0 md:space-x-4 mt-6"><button id="fence90x13NewButton1" class="w-full md:w-auto py-2 px-4 border border-transparent rounded-md shadow-sm text-sm font-medium highlighted-button">Objednat materiál</button><button id="fence90x13SaveToPdfButton" class="w-full md:w-auto py-2 px-4 border border-transparent rounded-md shadow-sm text-sm font-medium text-white">Uložit jako PDF</button><button id="fence90x13NewButton2" class="w-full md:w-auto py-2 px-4 border border-transparent rounded-md shadow-sm text-sm font-medium highlighted-button">Objednat zaměření</button></div></div></div><!-- PLOT 150x12 --><div id="fence-150x12-calculator" class="hidden"><h1 class="text-3xl font-bold text-center text-gray-900 mb-6">Orientační cenová kalkulace plotových profilů 150x12 mm (svislé použití)</h1><div class="bg-red-50 p-4 rounded-lg border-l-4 border-red-600 mb-6"><p class="text-red-800 font-extrabold uppercase tracking-wide">UPOZORNĚNÍ: Jedná se POUZE o cenovou kalkulaci plotové výplně a montáže WPC</p></div><div class="bg-blue-50 p-4 rounded-lg border-l-4 border-blue-600 mb-6"><p class="text-blue-800 font-semibold">Před objednáním si zkontrolujte dostupnost materiálu <a href="https://drive.google.com/file/d/14ysyAVzcd852sDX1GcnUqTGFJEvCUPOm/view" target="_blank" rel="noopener" class="underline text-blue-800">zde</a>.</p></div><!-- EMAIL (povinné)plot 150x12 --><!-- EMAIL (povinné)styl sjednocenýs ostatnímiřádky --><div class="flex flex-col md:flex-row items-center justify-between bg-gray-50 p-4 rounded-lg mb-2"><label for="userEmail150x12" class="text-sm font-medium text-gray-900 w-full md:w-1/2">Email (povinné)</label><input type="email" id="userEmail150x12" data-email-required="" class="mt-1 block w-full md:w-1/2 px-3 py-2 bg-white border border-gray-300 rounded-md shadow-sm focus:outline-none" placeholder="např. jan.novak@email.cz"></div><p class="text-xs text-gray-500 mb-6">Bez vyplněného emailu nenímožnéspočítat kalkulaci.</p><p class="text-center text-gray-600 mb-8">Zadejte prosím parametry plotu pro výpočet orientační ceny.</p><form id="fence150x12Form"><div id="fencePanelsContainer-150x12" class="space-y-8"></div><div class="flex items-center mt-4"><button type="button" id="addFencePanelBtn-150x12" class="highlighted-button w-full md:w-auto flex-1 py-2 px-4 border border-transparent rounded-md shadow-sm text-sm font-medium">+ Přidat další pole</button></div><div class="space-y-6 mt-8"><div class="bg-gray-50 p-4 rounded-lg flex items-center"><label for="triangularHeadCheckbox-150x12" class="text-sm font-medium text-gray-900 mr-2">Příplatek za tříhrannou hlavu (pro všechna pole)</label><input type="checkbox" id="triangularHeadCheckbox-150x12" class="h-5 w-5 text-stone-800 border-gray-300 rounded focus:ring-stone-800"></div><div class="bg-gray-50 p-4 rounded-lg flex items-center"><label for="montazFenceCheckbox-150x12" class="text-sm font-medium text-gray-900 mr-2">Montáž (pro všechna pole)</label><input type="checkbox" id="montazFenceCheckbox-150x12" class="h-5 w-5 text-stone-800 border-gray-300 rounded focus:ring-stone-800"></div><div class="flex items-center bg-gray-50 p-4 rounded-lg"><label for="prepaymentDiscountCheckbox-150x12" class="text-sm font-medium text-gray-900 mr-2">Sleva 5 % při platbě předem</label><input type="checkbox" id="prepaymentDiscountCheckbox-150x12" class="h-5 w-5 text-stone-800 border-gray-300 rounded focus:ring-stone-800"></div></div><button type="submit" class="calculate-button w-full mt-8 flex justify-center py-2 px-4 border border-transparent rounded-md shadow-sm text-sm font-medium">Spočítat celkovou cenu</button></form><div id="fence-150x12-results" class="mt-8 hidden"><h2 class="text-2xl font-bold text-gray-900 mb-4">Výsledná kalkulace</h2><div class="bg-amber-50 p-4 rounded-lg border-l-4 border-amber-500 mb-6"><p class="font-bold text-amber-800">Všechny uvedené ceny jsou pouze orientační.</p></div><div class="overflow-x-auto"><table class="min-w-full divide-y divide-gray-200"><thead class="bg-gray-50"><tr><th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Položka</th><th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Počet kusů</th><th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Běžných metrů</th><th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Cena bez DPH (Kč)</th></tr></thead><tbody class="bg-white divide-y divide-gray-200" id="fence150x12CalculationTableBody"></tbody><tfoot class="bg-gray-50"><tr><td colspan="3" class="px-6 py-3 text-left font-bold text-gray-900 uppercase">Celkem bez DPH</td><td id="fence150x12TotalPrice" class="px-6 py-3 text-right font-bold text-gray-900">0 Kč</td></tr><tr><td colspan="3" class="px-6 py-3 text-left font-bold text-gray-900 uppercase">Celkem s DPH (12%)</td><td id="fence150x12TotalPriceVAT" class="px-6 py-3 text-right font-bold text-gray-900">0 Kč</td></tr></tfoot></table></div><div class="flex flex-col md:flex-row justify-center space-y-4 md:space-y-0 md:space-x-4 mt-6"><button id="fence150x12NewButton1" class="w-full md:w-auto py-2 px-4 border border-transparent rounded-md shadow-sm text-sm font-medium highlighted-button">Objednat materiál</button><button id="fence150x12SaveToPdfButton" class="w-full md:w-auto py-2 px-4 border border-transparent rounded-md shadow-sm text-sm font-medium text-white">Uložit jako PDF</button><button id="fence150x12NewButton2" class="w-full md:w-auto py-2 px-4 border border-transparent rounded-md shadow-sm text-sm font-medium highlighted-button">Objednat zaměření</button></div></div></div></div></div><script>let selectedPickupPoint = null;function formatPrice(price) {return new Intl.NumberFormat('cs-CZ', { minimumFractionDigits: 2, maximumFractionDigits: 2 }).format(price);}document.addEventListener('DOMContentLoaded', () => {const activeLink = document.querySelector('a[data-target="terrace-calculator"]');if (activeLink) activeLink.classList.add('active-link');// Default 1 panel v každém plotovém kalkulátoruaddFencePanel90x13();addFencePanel150x12();});let panelCounter90x13 = 0;let panelCounter150x12 = 0;// Panel s křížkem + max výška 4 m + editovatelný "Počet stejných polí"function createFencePanelHTML(panelIndex, prefix, initialValues = {}) {const { length = '0', height = '0', plankGap = '0', color = 'original-wood' } = initialValues;return `<div id="${prefix}Panel-${panelIndex}" class="bg-gray-100 p-6 rounded-lg shadow-inner"><div class="flex items-center justify-between mb-4"><h3 class="text-xl font-semibold text-gray-800">Plotové pole ${panelIndex + 1}</h3><button type="button" aria-label="Zavřít pole" title="Zavřít pole"class="w-8 h-8 inline-flex items-center justify-center rounded-full text-gray-500 hover:text-red-600 hover:bg-red-50 border border-transparent hover:border-red-200"onclick="removeFencePanel('${prefix}', ${panelIndex})">×</button></div><div class="space-y-4"><div class="flex flex-col md:flex-row items-center justify-between bg-white p-4 rounded-lg"><label for="${prefix}Length-${panelIndex}" class="text-sm font-medium text-gray-900 w-full md:w-1/2">Požadovaná délka pole v metrech:</label><input type="number" id="${prefix}Length-${panelIndex}" min="0" step="0.01" value="${length}" class="mt-1 block w-full md:w-1/2 px-3 py-2 border border-gray-300 rounded-md"></div><div class="flex flex-col md:flex-row items-center justify-between bg-white p-4 rounded-lg"><label for="${prefix}Height-${panelIndex}" class="text-sm font-medium text-gray-900 w-full md:w-1/2">Výška plotu v metrech <span class="hint">(max. 4,0 m)</span>:</label><input type="number" id="${prefix}Height-${panelIndex}" min="0" max="4" step="0.01" value="${height}" class="mt-1 block w-full md:w-1/2 px-3 py-2 border border-gray-300 rounded-md" inputmode="decimal"></div><div class="flex flex-col md:flex-row items-center justify-between bg-white p-4 rounded-lg"><label class="text-sm font-medium text-gray-900 w-full md:w-1/2">Doporučený počet vodorovných nosných profilů (ryglů):</label><span id="${prefix}NosneProfilyDisplay-${panelIndex}" class="mt-1 block w-full md:w-1/2 px-3 py-2 bg-white border border-gray-300 rounded-md shadow-sm sm:text-sm font-bold text-gray-900">0 ks</span><input type="hidden" id="${prefix}NosneProfily-${panelIndex}" value="0"></div><div class="flex flex-col md:flex-row items-center justify-between bg-white p-4 rounded-lg"><label for="${prefix}PlankGap-${panelIndex}" class="text-sm font-medium text-gray-900 w-full md:w-1/2">Mezera mezi plaňkami (mm):</label><input type="number" id="${prefix}PlankGap-${panelIndex}" min="0" step="1" value="${plankGap}" class="mt-1 block w-full md:w-1/2 px-3 py-2 border border-gray-300 rounded-md"></div><div class="flex flex-col md:flex-row items-center justify-between bg-white p-4 rounded-lg"><label for="${prefix}ColorSelection-${panelIndex}" class="text-sm font-medium text-gray-900 w-full md:w-1/2">Vyberte odstín plotu:</label><select id="${prefix}ColorSelection-${panelIndex}" class="mt-1 block w-full md:w-1/2 px-3 py-2 border border-gray-300 rounded-md"><option value="original-wood" ${color === 'original-wood' ? 'selected' : ''}>Original wood</option><option value="teak" ${color === 'teak' ? 'selected' : ''}>Teak</option><option value="brownisch-red" ${color === 'brownisch-red' ? 'selected' : ''}>Brownisch red</option><option value="chocolate" ${color === 'chocolate' ? 'selected' : ''}>Chocolate</option><option value="stone-grey" ${color === 'stone-grey' ? 'selected' : ''}>Stone grey</option><option value="dark-grey" ${color === 'dark-grey' ? 'selected' : ''}>Dark grey</option></select></div><!-- Editovatelný počet stejných polí + tučný label --><div class="flex flex-col md:flex-row items-center justify-between bg-white p-4 rounded-lg"><label for="${prefix}DuplicateCount-${panelIndex}" class="text-sm font-bold text-gray-900 w-full md:w-1/2">Počet stejných polí:</label><input type="number" id="${prefix}DuplicateCount-${panelIndex}" min="1" value="1" class="mt-1 block w-full md:w-1/2 px-3 py-2 bg-white border border-gray-300 rounded-md text-gray-900"></div></div></div>`;}// Ořez výšky + přepočet nosných profilůfunction clampHeightInput(prefix, panelIndex) {const el = document.getElementById(`${prefix}Height-${panelIndex}`);if (!el) return;let v = parseFloat(el.value);if (isNaN(v)) return;if (v > 4) { v = 4; el.value = '4.00'; }if (v < 0) { v = 0; el.value = '0'; }updateNosneProfily(prefix, panelIndex);}// Odebrání pole (přes křížek)function removeFencePanel(prefix, index) {const el = document.getElementById(`${prefix}Panel-${index}`);if (el) el.remove();}window.removeFencePanel = removeFencePanel;// Přidání panelůfunction addFencePanel90x13() {const panelIndex = panelCounter90x13;const container = document.getElementById('fencePanelsContainer-90x13');container.insertAdjacentHTML('beforeend', createFencePanelHTML(panelIndex, 'fence90x13'));const heightInput = document.getElementById(`fence90x13Height-${panelIndex}`);if (heightInput) {heightInput.addEventListener('input', () => clampHeightInput('fence90x13', panelIndex));clampHeightInput('fence90x13', panelIndex);}panelCounter90x13++;}function addFencePanel150x12() {const panelIndex = panelCounter150x12;const container = document.getElementById('fencePanelsContainer-150x12');container.insertAdjacentHTML('beforeend', createFencePanelHTML(panelIndex, 'fence150x12'));const heightInput = document.getElementById(`fence150x12Height-${panelIndex}`);if (heightInput) {heightInput.addEventListener('input', () => clampHeightInput('fence150x12', panelIndex));clampHeightInput('fence150x12', panelIndex);}panelCounter150x12++;}function updateNosneProfily(prefix, panelIndex) {const valEl = document.getElementById(`${prefix}Height-${panelIndex}`);let fenceHeight = valEl ? parseFloat(valEl.value) : 0;if (isNaN(fenceHeight)) fenceHeight = 0;fenceHeight = Math.min(Math.max(fenceHeight, 0), 4);let nosneProfilyCount = Math.ceil(fenceHeight / 0.64);if (nosneProfilyCount < 2) nosneProfilyCount = 2;const displayEl = document.getElementById(`${prefix}NosneProfilyDisplay-${panelIndex}`);const hiddenEl = document.getElementById(`${prefix}NosneProfily-${panelIndex}`);if (displayEl) displayEl.textContent = `${nosneProfilyCount} ks`;if (hiddenEl) hiddenEl.value = nosneProfilyCount;}/* ===== TERASA (výpočet) ===== */document.getElementById('calculatorForm').addEventListener('submit', function(event) {event.preventDefault();if(!_ensureEmailOrWarn()) { return; }const vymera = parseFloat(document.getElementById('vymera').value) || 0;const obvod = parseFloat(document.getElementById('obvod').value) || 0;const montazSelected = document.getElementById('montazCheckbox').checked;const prepaymentDiscountSelected = document.getElementById('prepaymentDiscountCheckbox').checked;const terraceColor = document.getElementById('terraceColorSelection')?.value || 'original-wood';const prices = {podlahovyProfil: { countPerM2: 2.5, pricePerPiece: 669.00 },klipSpojovaci: { countPerM2: 29, price: 8.30 },nosnyProfil: { countPerM2: 1.8, pricePerPiece: 297.00 },zakoncovaciLista: { price: 239.00 },podlozkaGumova3mm: { price: 1059.00 },podlozkaGumova6mm: { price: 1035.00 },podlozkaGumova8mm: { price: 1029.00 },vrutStartovaci: { countPerM2: 1.5, price: 5.45 },vrutDoList: { price: 3.49 },doprava: { count: 1, price: 991.74 },montazWPC: { price: 745 },montazList: { price: 155 }};const taxRate = montazSelected ? 0.12 : 0.21; // upraveno: při montáži 12 %, jinak 21 %const listaCount = Math.ceil((obvod / 2.9) + 1);const nosnyProfilCount = Math.ceil(vymera * prices.nosnyProfil.countPerM2);const materialCalculations = [{ name: 'Podlahový profil – ' + terraceColor, count: Math.ceil(vymera * prices.podlahovyProfil.countPerM2), price: Math.ceil(vymera * prices.podlahovyProfil.countPerM2) * prices.podlahovyProfil.pricePerPiece },{ name: 'Nosný profil', count: nosnyProfilCount, price: nosnyProfilCount * prices.nosnyProfil.pricePerPiece },{ name: 'Klip spojovací nerez včetně vrutu', count: vymera * prices.klipSpojovaci.countPerM2, price: vymera * prices.klipSpojovaci.countPerM2 * prices.klipSpojovaci.price },{ name: 'Zakončovací lišta – ' + terraceColor, count: listaCount, price: listaCount * prices.zakoncovaciLista.price },{ name: 'Podložka gumová 3mm (10m)', count: 1, price: prices.podlozkaGumova3mm.price },{ name: 'Podložka gumová 6mm (5m)', count: 1, price: prices.podlozkaGumova6mm.price },{ name: 'Podložka gumová 8mm (5m)', count: 1, price: prices.podlozkaGumova8mm.price },{ name: 'Vrut 5x50 - startovací', count: Math.ceil(vymera * prices.vrutStartovaci.countPerM2), price: Math.ceil(vymera * prices.vrutStartovaci.countPerM2) * prices.vrutStartovaci.price },{ name: 'Vrut 3,5x35 - do lišt', count: Math.ceil(listaCount * 2.9 * 7), price: Math.ceil(listaCount * 2.9 * 7) * prices.vrutDoList.price },];let materialPrice = materialCalculations.reduce((s, i) => s + i.price, 0);let nonMaterialPrice = 0;const finalCalculations = [...materialCalculations];if (!montazSelected) {finalCalculations.push({ name: 'Doprava', count: prices.doprava.count, price: prices.doprava.price });nonMaterialPrice += prices.doprava.price;}if (montazSelected) {finalCalculations.push({ name: 'Montáž WPC profilů', count: vymera, price: vymera * prices.montazWPC.price });finalCalculations.push({ name: 'Montáž lišt', count: obvod, price: obvod * prices.montazList.price });const montazNaklady = materialPrice * 0.10;finalCalculations.push({ name: 'Ostatní montážní náklady', count: 1, price: montazNaklady });nonMaterialPrice += (vymera * prices.montazWPC.price) + (obvod * prices.montazList.price) + montazNaklady;}if (prepaymentDiscountSelected) {const discountAmount = materialPrice * 0.05;materialPrice -= discountAmount;finalCalculations.push({ name: 'Sleva za platbu předem (5%) - materiál', count: 1, price: -discountAmount });}const totalPrice = materialPrice + nonMaterialPrice;const totalPriceVAT = totalPrice * (1 + taxRate);const tableBody = document.getElementById('terraceCalculationTableBody');tableBody.innerHTML = '';finalCalculations.forEach(item => {const row = document.createElement('tr');const isPhysicalItem = !item.name.includes('Montáž') && !item.name.includes('Doprava') && !item.name.includes('Ostatní') && !item.name.includes('Sleva');const countDisplay = isPhysicalItem ? Math.ceil(item.count) : (item.count < 0 ? item.count : item.count.toFixed(2));const priceClass = item.price < 0 ? 'text-red-600' : 'text-gray-900';const countClass = item.count < 0 ? 'text-red-600' : 'text-gray-900';row.innerHTML = `<td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900">${item.name}</td><td class="px-6 py-4 whitespace-nowrap text-sm ${countClass}">${countDisplay}</td><td class="px-6 py-4 whitespace-nowrap text-sm text-right ${priceClass}">${formatPrice(item.price)} Kč</td>`;tableBody.appendChild(row);});document.getElementById('terraceTotalPrice').textContent = `${formatPrice(totalPrice)} Kč`;document.getElementById('terraceTotalPriceVAT').textContent = `${formatPrice(totalPriceVAT)} Kč`;const _terrRes = document.getElementById('terrace-results');_terrRes.classList.remove('hidden');_terrRes.scrollIntoView({ behavior: 'smooth', block: 'start' });});/* ===== FENCE 90x13 ===== */document.getElementById('fence90x13Form').addEventListener('submit', function(event) {event.preventDefault();if(!_ensureEmailOrWarn()) { return; }const fencePanels = document.querySelectorAll('#fence-90x13-calculator .bg-gray-100');const montazSelected = document.getElementById('montazFenceCheckbox-90x13')?.checked || false;const triangularHeadSelected = document.getElementById('triangularHeadCheckbox-90x13')?.checked || false;const prepaymentDiscountSelected = document.getElementById('prepaymentDiscountCheckbox-90x13')?.checked || false;const prices = {plotovyProfil: { pricePerPiece: 156.00, length: 1.5, width: 0.09 },texScrew: { price: 3.49 },doprava: { price: 991.74 },montaz: { pricePerPlank2Rails: 60.00, pricePerPlank3Rails: 90.00, pricePerPlank4Rails: 120.00 },ostatniNaklady: 0.10,};const rezaniNaMiruPricePerPiece = triangularHeadSelected ? 12.00 : 4.00;let totalMaterialPrice = 0;let totalMontazPrice = 0;const finalCalculations = [];let totalPlankCount = 0;let totalMeters = 0;let totalTexScrews = 0;fencePanels.forEach(panel => {const idParts = panel.id.split('-');const index = parseInt(idParts[idParts.length - 1], 10);const length = parseFloat(document.getElementById(`fence90x13Length-${index}`).value) || 0;let height = parseFloat(document.getElementById(`fence90x13Height-${index}`).value) || 0;height = Math.min(Math.max(height, 0), 4); // limit 0..4 mconst plankGap = (parseFloat(document.getElementById(`fence90x13PlankGap-${index}`).value) || 0) / 1000;const nosneProfilyCount = parseInt(document.getElementById(`fence90x13NosneProfily-${index}`).value, 10) || 2;const duplicateCount = Math.max(1, parseInt(document.getElementById(`fence90x13DuplicateCount-${index}`).value, 10) || 1);const roundedHeight = Math.ceil(height * 10) / 10;const plankCount = Math.ceil(length / (prices.plotovyProfil.width + plankGap));totalPlankCount += plankCount * duplicateCount;totalMeters += plankCount * roundedHeight * duplicateCount;const plotovyProfilPrice = (plankCount * roundedHeight * duplicateCount) * (prices.plotovyProfil.pricePerPiece / prices.plotovyProfil.length);totalMaterialPrice += plotovyProfilPrice;const colorSelect90 = document.getElementById(`fence90x13ColorSelection-${index}`);const colorText90 = colorSelect90 ? colorSelect90.options[colorSelect90.selectedIndex].text : '';finalCalculations.push({ name: `Plotový profil 90x13 mm – ${colorText90}, délka ${roundedHeight.toFixed(1)} m`, count: plankCount * duplicateCount, meters: plankCount * roundedHeight * duplicateCount, price: plotovyProfilPrice });const texScrewsCountForPanel = plankCount * nosneProfilyCount * duplicateCount;totalTexScrews += texScrewsCountForPanel;if (montazSelected) {let montazPricePerPlank = 0;if (nosneProfilyCount === 2) montazPricePerPlank = prices.montaz.pricePerPlank2Rails;else if (nosneProfilyCount === 3) montazPricePerPlank = prices.montaz.pricePerPlank3Rails;else if (nosneProfilyCount === 4) montazPricePerPlank = prices.montaz.pricePerPlank4Rails;totalMontazPrice += plankCount * montazPricePerPlank * duplicateCount; // opraveno: výška se už nezapočítává}});const rezaniNaMiruPrice = totalPlankCount * rezaniNaMiruPricePerPiece;const rezaniName = triangularHeadSelected ? 'Řezání na míru (tříhranná hlava)' : 'Řezání na míru';finalCalculations.push({ name: rezaniName, count: totalPlankCount, meters: 0, price: rezaniNaMiruPrice });totalMaterialPrice += rezaniNaMiruPrice;const texScrewsPrice = totalTexScrews * prices.texScrew.price;finalCalculations.push({ name: 'TEX 6,3x32 zápustná hlava', count: totalTexScrews, meters: 0, price: texScrewsPrice });totalMaterialPrice += texScrewsPrice;let totalNonMaterialPrice = 0;if (!montazSelected) {finalCalculations.push({ name: 'Doprava', count: 1, meters: 0, price: prices.doprava.price });totalNonMaterialPrice += prices.doprava.price;}if (montazSelected) {finalCalculations.push({ name: 'Montáž WPC plotových profilů', count: totalPlankCount, meters: totalMeters, price: totalMontazPrice });const ostatniNaklady = (totalMaterialPrice + totalMontazPrice) * prices.ostatniNaklady;finalCalculations.push({ name: 'Ostatní montážní náklady', count: 1, meters: 0, price: ostatniNaklady });totalNonMaterialPrice += ostatniNaklady;}if (prepaymentDiscountSelected) {const discountAmount = totalMaterialPrice * 0.05;finalCalculations.push({ name: 'Sleva za platbu předem (5%)', count: 1, meters: 0, price: -discountAmount });totalMaterialPrice -= discountAmount;}const totalPrice = totalMaterialPrice + totalMontazPrice + totalNonMaterialPrice;const taxRate = montazSelected ? 0.12 : 0.21; // upraveno: při montáži 12 %, jinak 21 %const totalPriceVAT = totalPrice * (1 + taxRate);const tableBody = document.getElementById('fence90x13CalculationTableBody');tableBody.innerHTML = '';finalCalculations.forEach(item => {const row = document.createElement('tr');let countDisplay = item.count;if (item.name.includes('Plotové profily')) countDisplay = `${Math.ceil(item.count)} ks`;const priceClass = item.price < 0 ? 'text-red-600' : 'text-gray-900';const countClass = item.count < 0 ? 'text-red-600' : 'text-gray-900';const metersDisplay = item.meters > 0 ? formatPrice(item.meters) + ' bm' : '-';row.innerHTML = `<td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900">${item.name}</td><td class="px-6 py-4 whitespace-nowrap text-sm ${countClass}">${countDisplay}</td><td class="px-6 py-4 whitespace-nowrap text-sm text-left text-gray-900">${metersDisplay}</td><td class="px-6 py-4 whitespace-nowrap text-sm text-right ${priceClass}">${formatPrice(item.price)} Kč</td>`;tableBody.appendChild(row);});document.getElementById('fence90x13TotalPrice').textContent = `${formatPrice(totalPrice)} Kč`;document.getElementById('fence90x13TotalPriceVAT').textContent = `${formatPrice(totalPriceVAT)} Kč`;const _f9013Res = document.getElementById('fence-90x13-results');_f9013Res.classList.remove('hidden');_f9013Res.scrollIntoView({ behavior: 'smooth', block: 'start' });});/* ===== FENCE 150x12 ===== */document.getElementById('fence150x12Form').addEventListener('submit', function(event) {event.preventDefault();if(!_ensureEmailOrWarn()) { return; }const fencePanels = document.querySelectorAll('#fence-150x12-calculator .bg-gray-100');const montazSelected = document.getElementById('montazFenceCheckbox-150x12')?.checked || false;const triangularHeadSelected = document.getElementById('triangularHeadCheckbox-150x12')?.checked || false;const prepaymentDiscountSelected = document.getElementById('prepaymentDiscountCheckbox-150x12')?.checked || false;const prices = {plotovyProfil: { pricePerPiece: 241.50, length: 1.5, width: 0.15 },texScrew: { price: 3.49 },doprava: { price: 991.74 },montaz: { pricePerPlank2Rails: 90.00, pricePerPlank3Rails: 135.00, pricePerPlank4Rails: 180.00 },ostatniNaklady: 0.10,};const rezaniNaMiruPricePerPiece = triangularHeadSelected ? 12.00 : 4.00;let totalMaterialPrice = 0;let totalMontazPrice = 0;const finalCalculations = [];let totalPlankCount = 0;let totalMeters = 0;let totalTexScrews = 0;fencePanels.forEach(panel => {const idParts = panel.id.split('-');const index = parseInt(idParts[idParts.length - 1], 10);const length = parseFloat(document.getElementById(`fence150x12Length-${index}`).value) || 0;let height = parseFloat(document.getElementById(`fence150x12Height-${index}`).value) || 0;height = Math.min(Math.max(height, 0), 4); // limit 0..4 mconst plankGap = (parseFloat(document.getElementById(`fence150x12PlankGap-${index}`).value) || 0) / 1000;const nosneProfilyCount = parseInt(document.getElementById(`fence150x12NosneProfily-${index}`).value, 10) || 2;const duplicateCount = Math.max(1, parseInt(document.getElementById(`fence150x12DuplicateCount-${index}`).value, 10) || 1);const roundedHeight = Math.ceil(height * 10) / 10;const plankCount = Math.ceil(length / (prices.plotovyProfil.width + plankGap));totalPlankCount += plankCount * duplicateCount;totalMeters += plankCount * roundedHeight * duplicateCount;const plotovyProfilPrice = (plankCount * roundedHeight * duplicateCount) * (prices.plotovyProfil.pricePerPiece / prices.plotovyProfil.length);totalMaterialPrice += plotovyProfilPrice;const colorSelect150 = document.getElementById(`fence150x12ColorSelection-${index}`);const colorText150 = colorSelect150 ? colorSelect150.options[colorSelect150.selectedIndex].text : '';finalCalculations.push({ name: `Plotový profil 150x12 mm – ${colorText150}, délka ${roundedHeight.toFixed(1)} m`, count: plankCount * duplicateCount, meters: plankCount * roundedHeight * duplicateCount, price: plotovyProfilPrice });// TEX: 2 šrouby na plotovku na každý ryglconst texScrewsCountForPanel = plankCount * (nosneProfilyCount * 2) * duplicateCount;totalTexScrews += texScrewsCountForPanel;if (montazSelected) {let montazPricePerPlank = 0;if (nosneProfilyCount === 2) montazPricePerPlank = prices.montaz.pricePerPlank2Rails;else if (nosneProfilyCount === 3) montazPricePerPlank = prices.montaz.pricePerPlank3Rails;else if (nosneProfilyCount === 4) montazPricePerPlank = prices.montaz.pricePerPlank4Rails;totalMontazPrice += plankCount * montazPricePerPlank * duplicateCount; // opraveno: výška se už nezapočítává}});const rezaniNaMiruPrice = totalPlankCount * rezaniNaMiruPricePerPiece;const rezaniName = triangularHeadSelected ? 'Řezání na míru (tříhranná hlava)' : 'Řezání na míru';finalCalculations.push({ name: rezaniName, count: totalPlankCount, meters: 0, price: rezaniNaMiruPrice });totalMaterialPrice += rezaniNaMiruPrice;const texScrewsPrice = totalTexScrews * prices.texScrew.price;finalCalculations.push({ name: 'TEX 6,3x32 zápustná hlava', count: totalTexScrews, meters: 0, price: texScrewsPrice });totalMaterialPrice += texScrewsPrice;let totalNonMaterialPrice = 0;if (!montazSelected) {finalCalculations.push({ name: 'Doprava', count: 1, meters: 0, price: prices.doprava.price });totalNonMaterialPrice += prices.doprava.price;}if (montazSelected) {finalCalculations.push({ name: 'Montáž WPC plotových profilů', count: totalPlankCount, meters: totalMeters, price: totalMontazPrice });const ostatniNaklady = (totalMaterialPrice + totalMontazPrice) * prices.ostatniNaklady;finalCalculations.push({ name: 'Ostatní montážní náklady', count: 1, meters: 0, price: ostatniNaklady });totalNonMaterialPrice += ostatniNaklady;}if (prepaymentDiscountSelected) {const discountAmount = totalMaterialPrice * 0.05;finalCalculations.push({ name: 'Sleva za platbu předem (5%)', count: 1, meters: 0, price: -discountAmount });totalMaterialPrice -= discountAmount;}const totalPrice = totalMaterialPrice + totalMontazPrice + totalNonMaterialPrice;const taxRate = montazSelected ? 0.12 : 0.21; // upraveno: při montáži 12 %, jinak 21 %const totalPriceVAT = totalPrice * (1 + taxRate);const tableBody = document.getElementById('fence150x12CalculationTableBody');tableBody.innerHTML = '';finalCalculations.forEach(item => {const row = document.createElement('tr');let countDisplay = item.count;if (item.name.includes('Plotové profily')) countDisplay = `${Math.ceil(item.count)} ks`;const priceClass = item.price < 0 ? 'text-red-600' : 'text-gray-900';const countClass = item.count < 0 ? 'text-red-600' : 'text-gray-900';const metersDisplay = item.meters > 0 ? formatPrice(item.meters) + ' bm' : '-';row.innerHTML = `<td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900">${item.name}</td><td class="px-6 py-4 whitespace-nowrap text-sm ${countClass}">${countDisplay}</td><td class="px-6 py-4 whitespace-nowrap text-sm text-left text-gray-900">${metersDisplay}</td><td class="px-6 py-4 whitespace-nowrap text-sm text-right ${priceClass}">${formatPrice(item.price)} Kč</td>`;tableBody.appendChild(row);});document.getElementById('fence150x12TotalPrice').textContent = `${formatPrice(totalPrice)} Kč`;document.getElementById('fence150x12TotalPriceVAT').textContent = `${formatPrice(totalPriceVAT)} Kč`;const _f15012Res = document.getElementById('fence-150x12-results');_f15012Res.classList.remove('hidden');_f15012Res.scrollIntoView({ behavior: 'smooth', block: 'start' });});/* PDF export */document.getElementById('terraceSaveToPdfButton').addEventListener('click', () => exportDivToPdf('terrace-results','kalkulace_terasy.pdf'));document.getElementById('fence90x13SaveToPdfButton').addEventListener('click', () => exportDivToPdf('fence-90x13-results','kalkulace_plotu_90x13.pdf'));document.getElementById('fence150x12SaveToPdfButton').addEventListener('click', () => exportDivToPdf('fence-150x12-results','kalkulace_plotu_150x12.pdf'));function exportDivToPdf(divId, filename) {const resultsDiv = document.getElementById(divId);const originalWidth = resultsDiv.style.width;// Zmenšíme šířku pro menší canvas (nižší rozlišení => menší PDF)resultsDiv.style.width = '900px';const MAX_BYTES = 4 * 1024 * 1024; // 4 MBconst qualities = [0.85, 0.75, 0.65, 0.55, 0.45, 0.35]; // postupné snižování kvality, když je soubor moc velkýhtml2canvas(resultsDiv, { scale: 1 }).then(canvas => {const { jsPDF } = window.jspdf;const pdfWidthMm = 200; // šířka obrázku v PDF (mm)const pdfPageHeightMm = 295; // výška stránky A4 (mm)const leftMarginMm = 5;// Výška jedné PDF stránky přepočtená do pixelů dle poměru šířkyconst pageHeightPx = Math.floor(canvas.width * (pdfPageHeightMm / pdfWidthMm));function buildPdf(quality) {const doc = new jsPDF('p', 'mm', 'a4');for (let y = 0, page = 0; y < canvas.height; y += pageHeightPx, page++) {const sliceHeightPx = Math.min(pageHeightPx, canvas.height - y);// připravit dočasný canvas s výškou jen pro danou stránkuconst pageCanvas = document.createElement('canvas');pageCanvas.width = canvas.width;pageCanvas.height = sliceHeightPx;const ctx = pageCanvas.getContext('2d');ctx.drawImage(canvas, 0, y, canvas.width, sliceHeightPx, 0, 0, canvas.width, sliceHeightPx);// JPEG s danou kvalitou (mnohem menší než PNG)const imgData = pageCanvas.toDataURL('image/jpeg', quality);// přepočet výšky slice do mm při zachování poměru stranconst sliceHeightMm = (sliceHeightPx / canvas.width) * pdfWidthMm;if (page > 0) doc.addPage();doc.addImage(imgData, 'JPEG', leftMarginMm, 0, pdfWidthMm, sliceHeightMm);}return doc;}let pdf, blob;for (const q of qualities) {pdf = buildPdf(q);blob = pdf.output('blob');if (blob.size <= MAX_BYTES) break;}pdf.save(filename);resultsDiv.style.width = originalWidth;});}/* Přepínání kalkulátorů */document.querySelectorAll('nav a').forEach(link => {link.addEventListener('click', function() {const targetId = this.getAttribute('data-target');const allCalculators = document.querySelectorAll('#terrace-calculator, #fence-90x13-calculator, #fence-150x12-calculator');allCalculators.forEach(calc => calc.classList.add('hidden'));document.getElementById(targetId).classList.remove('hidden');document.querySelectorAll('nav a').forEach(navLink => navLink.classList.remove('active-link'));this.classList.add('active-link');});});/* Připojení tlačítek pro přidání panelů */document.getElementById('addFencePanelBtn-90x13').addEventListener('click', addFencePanel90x13);document.getElementById('addFencePanelBtn-150x12').addEventListener('click', addFencePanel150x12);</script><!-- VLOŽTE NA ÚPLNÝ KONEC HTML BLOKU NA WEBNODE (nahradí předchozí patch) --><!-- EmailJS SDK --><!-- VLOŽTE NA ÚPLNÝ KONEC HTML BLOKU NA WEBNODE (nahradí předchozí patch) --><!-- EmailJS SDK --><!-- VLOŽTE NA ÚPLNÝ KONEC HTML BLOKU NA WEBNODE (nahraďte tím úplně všechny staré skripty) --><!-- EmailJS SDK --><!-- POZNÁMKY k EmailJS:- TEMPLATE_ADMIN (template_3dooxrd): To = info@..., Subject = {{subject}}, Reply-To = {{reply_to}}, tělo {{{html_message}}}. Bez Bcc/Cc.- TEMPLATE_CUSTOMER (template_zgj478t): To = {{to_email}}, Subject = {{subject}}, Reply-To = info@..., tělo {{{html_message}}}. Bez Bcc/Cc na admin.- V HTML musí zůstat JEN tento skript (hledejte "EmailJS SDK"). Staré bloky odstraňte.--><!-- EmailJS SDK — ponechat jen JEDNOU --><div id="messageBox" class="message-box"></div><div id="orderModal" class="modal-overlay" onclick="if(event.target.id === 'orderModal') closeOrderModal();"><div class="modal-content-slide"><div class="flex justify-between items-start mb-6"><h2 class="text-2xl font-bold text-gray-900">Kontaktní údaje pro závaznou objednávku</h2><button onclick="closeOrderModal()" class="text-gray-400 hover:text-gray-600 text-4xl font-light leading-none transition-colors">×</button></div><form id="orderForm"><input type="hidden" id="modalEmailSource" value=""><div class="space-y-6"><div class="flex items-center pb-4"><input id="isCompany" type="checkbox" onchange="handleCompanyToggle()" class="h-5 w-5 text-stone-800 border-gray-300 rounded focus:ring-stone-800"><label for="isCompany" class="ml-2 block text-base font-medium text-gray-900">Nakupuji na firmu</label></div><br><div id="companyFields" class="space-y-4 bg-gray-50 p-4 rounded-lg border border-gray-200 company-fields-animated"><h3 class="text-xl font-semibold text-gray-900">Fakturační údaje (Firma)</h3><div><label for="orderCompanyName" class="block text-sm font-medium text-gray-700">Název společnosti *</label><input type="text" id="orderCompanyName" class="mt-1 block w-full px-4 py-2 border border-gray-300 rounded-md shadow-sm focus:ring-amber-500 focus:border-amber-500"></div><div><label for="orderICO" class="block text-sm font-medium text-gray-700">IČO *</label><input type="text" id="orderICO" class="mt-1 block w-full px-4 py-2 border border-gray-300 rounded-md shadow-sm focus:ring-amber-500 focus:border-amber-500"></div><hr class="border-t border-gray-300 mt-4 pt-4"><h3 class="text-lg font-semibold text-gray-800">Kontaktní osoba (pro komunikaci ohledně objednávky) *</h3><div class="grid grid-cols-1 md:grid-cols-2 gap-6"><div><label for="orderContactName" class="block text-sm font-medium text-gray-700">Jméno *</label><input type="text" id="orderContactName" class="mt-1 block w-full px-4 py-2 border border-gray-300 rounded-md shadow-sm focus:ring-amber-500 focus:border-amber-500"></div><div><label for="orderContactSurname" class="block text-sm font-medium text-gray-700">Příjmení *</label><input type="text" id="orderContactSurname" class="mt-1 block w-full px-4 py-2 border border-gray-300 rounded-md shadow-sm focus:ring-amber-500 focus:border-amber-500"></div></div><div><label for="orderContactPhone" class="block text-sm font-medium text-gray-700">Telefonní číslo *</label><input type="tel" id="orderContactPhone" class="mt-1 block w-full px-4 py-2 border border-gray-300 rounded-md shadow-sm focus:ring-amber-500 focus:border-amber-500"><div><label for="orderContactEmail" class="block text-sm font-medium text-gray-700">E-mail *</label><input type="email" id="orderContactEmail" required="" class="mt-1 block w-full px-4 py-2 border border-gray-300 rounded-md"></div></div></div><div id="deliverySection" class="company-fields-animated"><div class="flex items-center pt-2 pb-4"><input id="isSameAddress" type="checkbox" checked="" onchange="handleSameAddressToggle()" class="h-5 w-5 text-stone-800 border-gray-300 rounded focus:ring-stone-800"><label for="isSameAddress" class="ml-2 block text-base font-medium text-gray-900">Dodat na fakturační adresu</label></div><br><div id="deliveryFields" class="space-y-4 bg-yellow-50 p-4 rounded-lg border border-gray-200 delivery-fields-inner-animated"><h3 class="text-lg font-semibold text-gray-800">Dodací adresa *</h3><div class="grid grid-cols-1 md:grid-cols-3 gap-6"><div class="md:col-span-2"><label for="deliveryAddressStreet" class="block text-sm font-medium text-gray-700">Ulice a číslo popisné *</label><input type="text" id="deliveryAddressStreet" class="mt-1 block w-full px-4 py-2 border border-gray-300 rounded-md shadow-sm focus:ring-amber-500 focus:border-amber-500"></div><div><label for="deliveryAddressZip" class="block text-sm font-medium text-gray-700">PSČ *</label><input type="text" id="deliveryAddressZip" class="mt-1 block w-full px-4 py-2 border border-gray-300 rounded-md shadow-sm focus:ring-amber-500 focus:border-amber-500"></div></div><div><label for="deliveryAddressCity" class="block text-sm font-medium text-gray-700">Město *</label><input type="text" id="deliveryAddressCity" class="mt-1 block w-full px-4 py-2 border border-gray-300 rounded-md shadow-sm focus:ring-amber-500 focus:border-amber-500"></div></div></div><div id="privateCustomerGroup" class="space-y-4"><h3 class="text-xl font-semibold text-gray-900 pt-6">Kontaktní a fakturační údaje (Soukromá osoba)</h3><div class="grid grid-cols-1 md:grid-cols-2 gap-6"><div><label for="orderName" class="block text-sm font-medium text-gray-700">Jméno *</label><input type="text" id="orderName" required="" class="mt-1 block w-full px-4 py-2 border border-gray-300 rounded-md shadow-sm focus:ring-amber-500 focus:border-amber-500"></div><div><label for="orderSurname" class="block text-sm font-medium text-gray-700">Příjmení *</label><input type="text" id="orderSurname" required="" class="mt-1 block w-full px-4 py-2 border border-gray-300 rounded-md shadow-sm focus:ring-amber-500 focus:border-amber-500"></div></div><div><label for="orderPhone" class="block text-sm font-medium text-gray-700">Telefonní číslo *</label><input type="tel" id="orderPhone" required="" class="mt-1 block w-full px-4 py-2 border border-gray-300 rounded-md shadow-sm focus:ring-amber-500 focus:border-amber-500"></div><div class="grid grid-cols-1 md:grid-cols-3 gap-6"><div class="md:col-span-2"><label for="orderAddressStreet" class="block text-sm font-medium text-gray-700">Ulice a číslo popisné *</label><input type="text" id="orderAddressStreet" required="" class="mt-1 block w-full px-4 py-2 border border-gray-300 rounded-md shadow-sm focus:ring-amber-500 focus:border-amber-500"></div><div><label for="orderAddressZip" class="block text-sm font-medium text-gray-700">PSČ *</label><input type="text" id="orderAddressZip" required="" class="mt-1 block w-full px-4 py-2 border border-gray-300 rounded-md shadow-sm focus:ring-amber-500 focus:border-amber-500"></div></div><div><label for="orderAddressCity" class="block text-sm font-medium text-gray-700">Město *</label><input type="text" id="orderAddressCity" required="" class="mt-1 block w-full px-4 py-2 border border-gray-300 rounded-md shadow-sm focus:ring-amber-500 focus:border-amber-500"></div></div><div id="shippingOptions" class="space-y-6 mt-8"><h3 class="text-xl font-semibold text-gray-900">Způsob dopravy *</h3><div class="space-y-4 bg-gray-50 p-4 rounded-lg border border-gray-200"><div id="pickupPointOption" class="flex items-center"><input id="shipping_pickup_point" name="shippingMethod" type="radio" value="Výdejní místo" required="" onchange="handleShippingChange()" class="h-4 w-4 text-stone-800 border-gray-300 focus:ring-stone-800"><label for="shipping_pickup_point" class="ml-3 block text-base font-medium text-gray-700">Výdejní místo <span id="selectedPickupPointName" class="ml-2 font-bold text-green-700 cursor-pointer underline underline-offset-2"></span></label></div><br><!-- MAPA VÝDEJNÍCH MÍST (LAMBOPONT) --><div id="pickupPointMapContainer" class="mt-6 hidden"><h4 class="text-lg font-semibold text-gray-900 mb-3">Vyberte prosím výdejní místo na mapě:</h4><div class="mb-4"><input type="text" id="pickupPointInput" placeholder="Např. Liberec" class="mt-1 block w-full px-4 py-2 border border-gray-300 rounded-md shadow-sm focus:ring-amber-500 focus:border-amber-500" readonly=""></div><div class="bg-white rounded-lg shadow-xl p-3"><div id="leafletMap" class="w-full" style="height:560px;"></div><div id="changePickupWrapper" class="mt-3" style="display:none;"><button id="changePickupBtn" type="button" class="calculate-button py-2 px-4 rounded-md" onclick="editPickupPoint()">Změnit výdejní místo</button></div><div id="pickupPointSummary" class="mt-3 hidden items-center justify-between bg-green-50 border border-green-200 rounded-md p-3"><div class="text-sm md:text-base"><strong>Vybrané výdejní místo:</strong><span id="pickupPointSummaryName" class="font-semibold"></span></div><div><button type="button" class="calculate-button py-2 px-4 rounded-md" onclick="editPickupPoint()">Změnit</button></div></div><div id="selectedPickupPointDisplay" class="mt-3 text-center text-lg font-bold" style="color:#15803d; display:none;">Vybrané výdejní místo: </div><input type="hidden" id="orderPickupPointId" name="orderPickupPointId" value=""><input type="hidden" id="orderPickupPointName" name="orderPickupPointName" value=""><div class="mt-4 flex justify-center"><button id="confirmPickupBtnModal" type="button" class="px-4 py-2 rounded-md highlighted-button" onclick="confirmPickupPoint()">Vybrat</button></div></div></div><!-- /MAPA VÝDEJNÍCH MÍST --><div class="flex items-center"><input id="shipping_personal_pickup" name="shippingMethod" type="radio" value="Osobní odběr" required="" onchange="handleShippingChange()" class="h-4 w-4 text-stone-800 border-gray-300 focus:ring-stone-800"><label for="shipping_personal_pickup" class="ml-3 block text-base font-medium text-gray-700">Osobní odběr</label></div><br><div class="flex items-center"><input id="shipping_delivery" name="shippingMethod" type="radio" value="Doprava na adresu" required="" onchange="handleShippingChange()" class="h-4 w-4 text-stone-800 border-gray-300 focus:ring-stone-800"><label for="shipping_delivery" class="ml-3 block text-base font-medium text-gray-700">Doprava na adresu</label></div><br></div></div><div id="pickupPointMapContainer" class="mt-6 hidden"><h4 class="text-lg font-semibold text-gray-900 mb-3">Vyberte prosím výdejní místo na mapě:</h4><div class="mb-4"><input type="text" id="pickupPointInput" placeholder="Např. Liberec" class="mt-1 block w-full px-4 py-2 border border-gray-300 rounded-md shadow-sm focus:ring-amber-500 focus:border-amber-500" readonly=""></div><div id="leafletMap" class="w-full" style="height: 560px;"></div><div id="selectedPickupPointDisplay" class="mt-2 text-center text-lg font-bold" style="color:#15803d; display:none;">Vybrané výdejní místo: </div><input type="hidden" id="orderPickupPointId" name="orderPickupPointId" value=""><input type="hidden" id="orderPickupPointName" name="orderPickupPointName" value=""><div id="pickupSummary" style="margin:12px 0; padding:10px 12px; border:1px solid #e2e8f0; border-radius:10px; display:none;"><span id="pickupSummaryText" style="color:#15803d; font-weight:700; display:block;">Vybrané výdejní místo: —</span><a id="changePickupPointLink" href="javascript:void(0)" style="display:inline-block;color:#dc2626;font-weight:700;text-decoration:none;margin-top:6px;">Změnit výdejní místo</a></div><div class="mt-3 flex justify-center"><button id="confirmPickupBtnModal" type="button" class="px-4 py-2 rounded-md highlighted-button" onclick="confirmPickupPoint()">Vybrat</button></div></div><!-- ZPŮSOB PLATBY --><div id="paymentOptions" class="space-y-6" style="margin-top: 1rem;"><h3 class="text-xl font-semibold text-gray-900">Způsob platby *</h3><div class="space-y-4 bg-gray-50 p-4 rounded-lg border border-gray-200"><label class="flex items-center"><input id="pay_qr" name="paymentMethod" type="radio" value="QR kódem" class="h-4 w-4 text-stone-800"><span class="ml-3">QR kódem</span></label><label class="flex items-center"><input id="pay_transfer" name="paymentMethod" type="radio" value="Převodním příkazem" class="h-4 w-4 text-stone-800"><span class="ml-3">Převodním příkazem</span></label><label class="flex items-center"><input id="pay_cash" name="paymentMethod" type="radio" value="Při předání v hotovosti" class="h-4 w-4 text-stone-800"><span class="ml-3">Při předání v hotovosti</span></label></div><br></div><!-- /ZPŮSOB PLATBY --><!-- POZNÁMKA PRO OBJEDNÁVKU --><div id="orderNoteBlock" class="space-y-2 bg-gray-50 p-4 rounded-lg border border-gray-200 mt-4"><label for="orderNote" class="text-sm font-medium text-gray-900">Poznámka k objednávce (nepovinné)</label><textarea id="orderNote" name="orderNote" rows="3" class="mt-1 block w-full px-3 py-2 bg-white border border-gray-300 rounded-md shadow-sm" placeholder="Zde můžete uvést doplňující informace…"></textarea></div><button type="submit" class="calculate-button w-full mt-8 py-3 px-6 rounded-md shadow-lg text-lg font-bold transition-colors">Odeslat závaznou objednávku</button></div></form></div></div><script>document.getElementById('orderForm').addEventListener('submit', function(e){e.preventDefault();document.getElementById('orderModal').classList.remove('open');const thx = document.getElementById('thankYouMessage');thx.style.display = 'block';thx.scrollIntoView({ behavior: 'smooth' });submitOrderForm();location.reload();});</script><script>window.pickupPointsRaw = [{"id": "wpc-centrum-s-r-o-centralni-sklad", "name": "WPC centrum s.r.o. - centrální sklad", "address": "Heřmanice v Podještědí 135 Jablonné v Podještědí 47125"}, {"id": "evmat-stavby-s-r-o", "name": "EVMAT stavby s.r.o.", "address": "Budějovická 130 Jesenice u Prahy 252 42"}, {"id": "ploty-hradec-kralove-s-r-o", "name": "Ploty Hradec Králové s.r.o.", "address": "Cukrovarská 341 Hradec Králové-Smiřice 500 02"}, {"id": "ploty-pardubice-s-r-o", "name": "Ploty Pardubice s.r.o.", "address": "Průmyslová 344 Pardubice 530 01 AREÁL STERA 3000"}, {"id": "bc-jaroslav-nerusil", "name": "Bc. Jaroslav Nerušil", "address": "Rataje 89, Těšetice 783 46"}, {"id": "woodterrass", "name": "WoodTerrass", "address": "Kounice 5 Kounice 289 15"}, {"id": "gardina-cz-s-r-o", "name": "GARDINA.cz, s.r.o.", "address": "Poličany 54 Kutná Hora 284 01"}, {"id": "adh-ploty-s-r-o", "name": "ADH-PLOTY s.r.o.", "address": "Dolní Město 361 Dolní Město 282 33"}, {"id": "dluhos-s-r-o", "name": "DLUHOŠ s.r.o.", "address": "Hradecká 2714/68 Opava 746 01"}, {"id": "radim-jegla", "name": "Radim Jegla", "address": "Babice 38, Uherské Hradiště 687 03"}, {"id": "wpc-centrum-s-r-o-rozdrojovice", "name": "WPC centrum s.r.o. - Rozdrojovice", "address": "Žleby 194 Rozdrojovice 664 34"}, {"id": "stabo-mb-s-r-o", "name": "STABO MB s.r.o.", "address": "Pražská 1543 Moravské Budějovice 676 02"}, {"id": "bdj-interiery-s-r-o", "name": "BDJ INTERIÉRY s.r.o.", "address": "Štěchovice 336 Štěchovice 252 07"}, {"id": "mk-parkett-s-r-o", "name": "MK Parkett s.r.o.", "address": "Jiráskova 2042 Benešov 256 01"}, {"id": "jama-cz-s-r-o", "name": "JAMA CZ s.r.o.", "address": "Drachkov 86 Drachkov 386 01"}, {"id": "jaroslav-jirchar", "name": "Jaroslav Jirchář", "address": "Zahradní 334 Roudné 370 07"}, {"id": "bekera-s-r-o", "name": "BEKERA s.r.o.", "address": "Za nádrražím Zliv 373 44"}, {"id": "p-plast-lom-s-r-o", "name": "P-PLAST Lom s.r.o.", "address": "Lom 61 Lom 390 02"}, {"id": "ploty-vlasim-s-r-o", "name": "Ploty Vlašim s.r.o.", "address": "Vlasákova 222 Vlašim 258 01"}, {"id": "martin-kveton-drevoobchod-klatovy", "name": "Martin Květoň ( Dřevoobchod Klatovy )", "address":"Plzeňská 925 Klatovy 339 01"}, {"id": "drevoobchod-k-c-karlovy-vary-a-s", "name": "Dřevoobchod K&C Karlovy Vary, a.s.", "address": "Rosnice 66 Karlovy Vary 360 17"}, {"id": "drevak-k-c-s-r-o", "name": "K&C Dřevoobchod Oldřichov", "address": "Oldřichov 227, 417 24 Oldřichov"}, {"id": "palubky-koten-s-r-o", "name": "PALUBKY KOTEN s.r.o.", "address": "Pávoská 5679/25d Jihlava 586 01"}, {"id": "wpc-centrum-s-r-o-liberec", "name": "WPC centrum s.r.o. - Liberec", "address": "Cyrila a Metoděje 495/2 Liberec 460 01"}, {"id": "aqua-program-s-r-o-vzorova-terasa", "name": "AQUA Program s.r.o. - vzorová terasa", "address": "Ohrazenice 255 Ohrazenice 511 01"}, {"id": "podlahy-blanket-s-r-o", "name": "PODLAHY BLANKET s.r.o.", "address": "Pod Loretou 885 Kosmonosy 293 06"}, {"id": "vladeko-spol-s-r-o", "name": "VLADEKO spol. s r.o.", "address": "Karlštejnská 97 Tachlovice 252 17"}, {"id": "drevak-k-c-s-r-o", "name": "K&C Dřevoobchod Oldřichov", "address": "Oldřichov 227, 417 24 Oldřichov"}, {"id": "drevospektrum-rakovnik-s-r-o", "name": "DŘEVOSPEKTRUM Rakovník s.r.o.", "address": "Lišanská 2760 Rakovník 269 01"}, {"id": "stavebni-sdruzeni-bostik-s-r-o", "name": "Stavební sdružení Boštík s.r.o.", "address": "Poříčí u Litomyšle 117 Poříčí u Litomyšle 570 01"}, {"id": "drevoobchod-ceska-lipa-s-r-o", "name": "DŘEVOOBCHOD - ČESKÁ LÍPA, s. r. o.", "address": "U Obecního lesa 3044 Česká Lípa Dubice 470 01"}, {"id": "drevoobchod-melnik-s-r-o", "name": "Dřevoobchod Mělník s.r.o.", "address": "Nad Oborou 4154 Mělník 576 01"}, {"id": "drevoobchod-premier-vaclav-sladky", "name": "Dřevoobchod Premier Václav Sladký", "address": "Americká 2486/20 Cheb 350 02"}, {"id": "podlahy-a-dvere-s-r-o", "name": "PODLAHY A DVEŘE s.r.o.", "address": "Jičínská 169 Volanov 541 01"}, {"id": "stafikr-spol-s-r-o", "name": "STAFIKR, spol. s.r.o.", "address": "Bratislavská 587/16 Hustopeče 693 01"}, {"id": "translignum-bm-s-r-o", "name": "Translignum BM, s.r.o.", "address": "Návsí 975 Návsí 739 92"}, {"id": "strnad-podlahy-dvere-s-r-o", "name": "STRNAD podlahy, dveře s.r.o.", "address": "Rohovládova Bělá 143 Pardubice 533 43"}, {"id": "petr-vsechovsky-drevotyp", "name": "Petr Všechovský - Dřevotyp", "address": "Netovická 875 Slaný 274 01"}, {"id": "petr-vsechovsky-drevotyp", "name": "Petr Všechovský - Dřevotyp", "address": "Květoslava Mašity 219 Všenory 252 31"}, {"id": "pavel-behavy", "name": "Pavel Běhavý", "address": "Škvorecká 388 Úvaly 250 82"}, {"id": "lm-zelezarstvi-a-hutni-material-s-r-o", "name": "LM - Železářství a hutní materiál s.r.o.", "address": "Zámecká 10 Kunštát na Moravě 679 72"}, {"id": "drevoobchod-k-c-oldrichov", "name": "Dřevoobchod K&C Oldřichov", "address": "Oldřichov 227 Oldřichov 417 24"}, {"id": "df-technik-s-r-o", "name": "DF Technik s.r.o.", "address": "Novohospodská 135 Příbram 261 01"}];</script><script>(function(){function ready(fn){ if(document.readyState!=='loading') fn(); else document.addEventListener('DOMContentLoaded', fn); }function ensureLeaflet(fn){ if(window.L) return fn(); var h=document.head||document.getElementsByTagName('head')[0];var link=document.createElement('link'); link.rel='stylesheet'; link.href='https://unpkg.com/leaflet@1.9.4/dist/leaflet.css'; link.crossOrigin=''; h.appendChild(link);var s=document.createElement('script'); s.src='https://unpkg.com/leaflet@1.9.4/dist/leaflet.js'; s.crossOrigin=''; s.onload=function(){ setTimeout(fn,50); }; h.appendChild(s);setTimeout(fn, 1000);}ready(function(){ensureLeaflet(function(){var mapEl=document.getElementById('leafletMap'); if(!mapEl) return;var map=L.map(mapEl,{scrollWheelZoom:false,dragging:true,tap:true,tapTolerance:25,attributionControl:true});var tiles=L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',{maxZoom:19,attribution:'&copy; OpenStreetMap'}).addTo(map);var group=L.featureGroup().addTo(map);var bounds=[]; window._selectedPickupPoint=null;function fit(){ if(bounds.length) map.fitBounds(bounds,{padding:[40,40],maxZoom:8}); else map.setView([49.8,15.5],7); }fit();var retry=0,timer=setInterval(function(){ retry++; map.invalidateSize(); fit(); if(retry>=10) clearInterval(timer); },200);map.once('movestart', function(){ if(timer){ clearInterval(timer); timer=null; } });map.once('zoomstart', function(){ if(timer){ clearInterval(timer); timer=null; } });tiles.on('load', function(){ setTimeout(function(){ map.invalidateSize(); fit(); },120); });var list=window.pickupPointsRaw||[]; var i=0;function addNext(){ if(i>=list.length) return; var p=list[i++];function place(lat,lng){var m=L.circleMarker([lat,lng],{radius:9,weight:2});m.on('mousedown', function(ev){ if(ev.originalEvent && ev.originalEvent.stopPropagation) ev.originalEvent.stopPropagation(); });m.on('click', function(){window._selectedPickupPoint = p;var __v = document.getElementById('pickupPointInput');if(__v){ __v.readOnly=false; __v.value = p.name || ''; try{ __v.dispatchEvent(new Event('input',{bubbles:true})); __v.dispatchEvent(new Event('change',{bubbles:true})); }catch(e){__orderEmailSent = false;} __v.readOnly=true; }var out = document.getElementById('selectedPickupPointDisplay');if(out){ out.innerHTML = 'Vybrané výdejní místo: <strong>' + (p.name || '') + '</strong>'; out.style.display = 'block'; }L.popup().setLatLng([lat,lng]).setContent('<strong>'+p.name+'</strong>').openOn(map);var btn=document.getElementById('confirmPickupBtnModal'); if(btn) btn.disabled=false;});group.addLayer(m); bounds.push([lat,lng]); fit();}var cm = /(-?\d{1,2}\.\d+)[,\s]+(-?\d{1,3}\.\d+)/.exec(p.address||'');if(cm){ place(parseFloat(cm[1]), parseFloat(cm[2])); setTimeout(addNext,50); return; }var url='https://nominatim.openstreetmap.org/search?format=json&q='+encodeURIComponent(p.address)+'&limit=1&addressdetails=0';fetch(url,{headers:{'Accept':'application/json'}}).then(function(r){return r.ok?r.json():[];}).then(function(a){if(Array.isArray(a)&&a.length){ var lat=parseFloat(a[0].lat),lng=parseFloat(a[0].lon); if(!isNaN(lat)&&!isNaN(lng)) place(lat,lng); }}).catch(function(){__orderEmailSent = false;}).finally(function(){ setTimeout(addNext,750); });}addNext();// Override confirmPickupSelection to use selected marker from mapwindow.confirmPickupSelection = function(){var sel = window._selectedPickupPoint;if(!sel){ var inp=document.getElementById('pickupPointInput'); if(inp && inp.value.trim()){ sel={id:'', name:inp.value.trim()}; } else { return; } }var out = document.getElementById('selectedPickupPointDisplay');if(out){ out.innerHTML = 'Vybrané výdejní místo: <strong>' + (sel.name || '') + '</strong>'; out.style.display = 'block'; }var hidId = document.getElementById('orderPickupPointId');var hidName = document.getElementById('orderPickupPointName');if(hidId) hidId.value = sel.id || '';if(hidName) hidName.value = sel.name || '';var vis = document.getElementById('pickupPointInput');if(vis){vis.readOnly = false;vis.value = sel.name || '';try{vis.dispatchEvent(new Event('input', {bubbles:true}));vis.dispatchEvent(new Event('change', {bubbles:true}));}catch(e){__orderEmailSent = false;}vis.readOnly = true;}var txtEl = document.getElementById('pickupSummaryText');if(txtEl){ txtEl.textContent = 'Vybrané výdejní místo: ' + (sel.name || ''); }var sum = document.getElementById('pickupSummary'); if(sum){ sum.style.display = 'block'; }};});});})();// === MODAL + LOGIKA (injected) ===function showMessage(text, type = 'success') {const box = document.getElementById('messageBox') || (function(){const el = document.createElement('div');el.id = 'messageBox';el.className = 'message-box';document.body.appendChild(el);return el;})();box.textContent = text;box.style.backgroundColor = (type === 'error') ? '#dc2626' : '#22c55e';box.style.opacity = '1';setTimeout(() => box.style.opacity = '0', 2400);}function openOrderModal(sourceEmailInputId) {const modal = document.getElementById('orderModal');if (!modal) return;const hidden = document.getElementById('modalEmailSource');if (hidden) hidden.value = sourceEmailInputId || '';modal.classList.add('open');document.body.style.overflow = 'hidden';document.addEventListener('keydown', escCloseHandler);}function closeOrderModal() {const modal = document.getElementById('orderModal');if (!modal) return;modal.classList.remove('open');document.body.style.overflow = '';document.removeEventListener('keydown', escCloseHandler);}function escCloseHandler(e) {if (e.key === 'Escape') closeOrderModal();}function handleCompanyToggle() {const check = document.getElementById('isCompany');const box = document.getElementById('companyFields');if (check && box) {box.classList.toggle('open', !!check.checked);}}function handleSameAddressToggle() {const same = document.getElementById('isSameAddress');const inner = document.getElementById('deliveryFields');const wrapper = document.getElementById('deliverySection');if (!same || !inner || !wrapper) return;if (same.checked) {inner.classList.remove('open');wrapper.classList.remove('open');} else {wrapper.classList.add('open');setTimeout(() => inner.classList.add('open'), 10);}}function handleShippingChange() {}function submitOrderForm() {const name = (document.getElementById('orderName') || {}).value || (document.getElementById('orderContactName') || {}).value || '';const phone = (document.getElementById('orderPhone') || {}).value || (document.getElementById('orderContactPhone') || {}).value || '';if (!name.trim() || !phone.trim()) {showMessage('Doplňte prosím povinné údaje (jméno a telefon).', 'error');return;}showMessage('Objednávka byla odeslána. Ozveme se vám co nejdříve.');closeOrderModal();}document.addEventListener('DOMContentLoaded', () => {const pairs = [['terraceNewButton1', 'contactEmail-terrace'],['terraceNewButton2', 'contactEmail-terrace'],['fence90x13NewButton1', 'contactEmail-90x13'],['fence90x13NewButton2', 'contactEmail-90x13'],['fence150x12NewButton1', 'contactEmail-150x12'],['fence150x12NewButton2', 'contactEmail-150x12'],];pairs.forEach(([btnId, emailId]) => {const btn = document.getElementById(btnId);if (btn) btn.addEventListener('click', () => openOrderModal(emailId));});handleCompanyToggle();handleSameAddressToggle();});// === /MODAL + LOGIKA ===</script><!-- MODAL OBJEDNÁVKY --><div id="orderModal" class="modal-overlay" onclick="if(event.target.id==='orderModal') closeOrderModal();"><div class="modal-content-slide" role="dialog" aria-modal="true" aria-labelledby="orderModalTitle"><div class="flex justify-between items-start mb-6"><h2 id="orderModalTitle" class="text-2xl font-bold text-gray-900">Kontaktní údaje pro závaznou objednávku</h2><button type="button" onclick="closeOrderModal()" class="text-gray-400 hover:text-gray-600 text-4xl font-light leading-none">×</button></div><form id="orderForm"><input type="hidden" id="modalEmailSource" value=""><!-- Firma toggle --><div class="flex items-center pb-4"><input id="isCompany" type="checkbox" onchange="handleCompanyToggle()" class="h-5 w-5 text-stone-800 border-gray-300 rounded focus:ring-stone-800"><label for="isCompany" class="ml-2 block text-base font-medium text-gray-900">Nakupuji na firmu</label></div><br><!-- Firemní pole --><div id="companyFields" class="space-y-4 bg-gray-50 p-4 rounded-lg border border-gray-200 company-fields-animated"><h3 class="text-xl font-semibold text-gray-900">Fakturační údaje (Firma)</h3><div><label for="orderCompanyName" class="block text-sm font-medium text-gray-700">Název společnosti *</label><input type="text" id="orderCompanyName" class="mt-1 block w-full px-4 py-2 border border-gray-300 rounded-md"></div><div><label for="orderICO" class="block text-sm font-medium text-gray-700">IČO *</label><input type="text" id="orderICO" class="mt-1 block w-full px-4 py-2 border border-gray-300 rounded-md"></div><hr class="border-t border-gray-300 mt-4 pt-4"><h3 class="text-lg font-semibold text-gray-800">Kontaktní osoba *</h3><div class="grid grid-cols-1 md:grid-cols-2 gap-6"><div><label for="orderContactName" class="block text-sm font-medium text-gray-700">Jméno *</label><input type="text" id="orderContactName" class="mt-1 block w-full px-4 py-2 border border-gray-300 rounded-md"></div><div><label for="orderContactSurname" class="block text-sm font-medium text-gray-700">Příjmení *</label><input type="text" id="orderContactSurname" class="mt-1 block w-full px-4 py-2 border border-gray-300 rounded-md"></div></div><div><label for="orderContactPhone" class="block text-sm font-medium text-gray-700">Telefon *</label><input type="tel" id="orderContactPhone" class="mt-1 block w-full px-4 py-2 border border-gray-300 rounded-md"><div><label for="orderContactEmail" class="block text-sm font-medium text-gray-700">E-mail *</label><input type="email" id="orderContactEmail" required="" class="mt-1 block w-full px-4 py-2 border border-gray-300 rounded-md"></div></div></div><!-- Soukromá osoba --><div id="privateCustomerGroup" class="space-y-4"><h3 class="text-xl font-semibold text-gray-900 pt-6">Kontaktní a fakturační údaje</h3><div class="grid grid-cols-1 md:grid-cols-2 gap-6"><div><label for="orderName" class="block text-sm font-medium text-gray-700">Jméno *</label><input type="text" id="orderName" class="mt-1 block w-full px-4 py-2 border border-gray-300 rounded-md"></div><div><label for="orderSurname" class="block text-sm font-medium text-gray-700">Příjmení *</label><input type="text" id="orderSurname" class="mt-1 block w-full px-4 py-2 border border-gray-300 rounded-md"></div></div><div><label for="orderPhone" class="block text-sm font-medium text-gray-700">Telefon *</label><input type="tel" id="orderPhone" class="mt-1 block w-full px-4 py-2 border border-gray-300 rounded-md"></div><div class="grid grid-cols-1 md:grid-cols-3 gap-6"><div class="md:col-span-2"><label for="orderAddressStreet" class="block text-sm font-medium text-gray-700">Ulice a č.p. *</label><input type="text" id="orderAddressStreet" class="mt-1 block w-full px-4 py-2 border border-gray-300 rounded-md"></div><div><label for="orderAddressZip" class="block text-sm font-medium text-gray-700">PSČ *</label><input type="text" id="orderAddressZip" class="mt-1 block w-full px-4 py-2 border border-gray-300 rounded-md"></div></div><div><label for="orderAddressCity" class="block text-sm font-medium text-gray-700">Město *</label><input type="text" id="orderAddressCity" class="mt-1 block w-full px-4 py-2 border border-gray-300 rounded-md"></div></div><!-- Dodací adresa – animovaný blok --><div id="deliverySection" class="company-fields-animated"><div class="flex items-center pt-2 pb-4"><input id="isSameAddress" type="checkbox" checked="" onchange="handleSameAddressToggle()" class="h-5 w-5 text-stone-800 border-gray-300 rounded focus:ring-stone-800"><label for="isSameAddress" class="ml-2 block text-base font-medium text-gray-900">Dodat na fakturační adresu</label></div><br><div id="deliveryFields" class="space-y-4 bg-yellow-50 p-4 rounded-lg border border-gray-200 delivery-fields-inner-animated"><h3 class="text-lg font-semibold text-gray-900">Dodací adresa *</h3><div class="grid grid-cols-1 md:grid-cols-3 gap-6"><div class="md:col-span-2"><label for="deliveryAddressStreet" class="block text-sm font-medium text-gray-700">Ulice a č.p. *</label><input type="text" id="deliveryAddressStreet" class="mt-1 block w-full px-4 py-2 border border-gray-300 rounded-md"></div><div><label for="deliveryAddressZip" class="block text-sm font-medium text-gray-700">PSČ *</label><input type="text" id="deliveryAddressZip" class="mt-1 block w-full px-4 py-2 border border-gray-300 rounded-md"></div></div><div><label for="deliveryAddressCity" class="block text-sm font-medium text-gray-700">Město *</label><input type="text" id="deliveryAddressCity" class="mt-1 block w-full px-4 py-2 border border-gray-300 rounded-md"></div></div></div><!-- Doprava --><div id="shippingOptions" class="space-y-6 mt-8"><h3 class="text-xl font-semibold text-gray-900">Způsob dopravy *</h3><div class="space-y-4 bg-gray-50 p-4 rounded-lg border border-gray-200"><label class="flex items-center"><input id="shipping_pickup_point" name="shippingMethod" type="radio" value="Výdejní místo" onchange="handleShippingChange()" class="h-4 w-4 text-stone-800"><span class="ml-3">Výdejní místo <span id="selectedPickupPointName" class="ml-2 font-bold text-green-700 cursor-pointer underline underline-offset-2"></span></span></label><label class="flex items-center"><input id="shipping_personal_pickup" name="shippingMethod" type="radio" value="Osobní odběr" onchange="handleShippingChange()" class="h-4 w-4 text-stone-800"><span class="ml-3">Osobní odběr</span></label><label class="flex items-center"><input id="shipping_delivery" name="shippingMethod" type="radio" value="Doprava na adresu" onchange="handleShippingChange()" class="h-4 w-4 text-stone-800"><span class="ml-3">Doprava na adresu</span></label></div><br></div><!-- Poznámka --><div class="mt-6"><label for="orderNote" class="block text-sm font-medium text-gray-700">Poznámka k objednávce</label><textarea id="orderNote" rows="3" class="mt-1 block w-full px-4 py-2 border border-gray-300 rounded-md"></textarea></div><div class="mt-8 flex flex-col md:flex-row gap-3"><button type="submit" class="highlighted-button w-full md:w-auto py-2 px-4 rounded-md">Odeslat objednávku</button><button type="button" class="calculate-button w-full md:w-auto py-2 px-4 rounded-md" onclick="closeOrderModal()">Zavřít</button></div></form></div></div><!-- /MODAL --><script>window.pickupPointsRaw = [{"id": "wpc-centrum-s-r-o-centralni-sklad", "name": "WPC centrum s.r.o. - centrální sklad", "address": "Heřmanice v Podještědí 135 Jablonné v Podještědí 47125"}, {"id": "evmat-stavby-s-r-o", "name": "EVMAT stavby s.r.o.", "address": "Budějovická 130 Jesenice u Prahy 252 42"}, {"id": "ploty-hradec-kralove-s-r-o", "name": "Ploty Hradec Králové s.r.o.", "address": "Cukrovarská 341 Hradec Králové-Smiřice 500 02"}, {"id": "ploty-pardubice-s-r-o", "name": "Ploty Pardubice s.r.o.", "address": "Průmyslová 344 Pardubice 530 01 AREÁL STERA 3000"}, {"id": "bc-jaroslav-nerusil", "name": "Bc. Jaroslav Nerušil", "address": "Rataje 89, Těšetice 783 46"}, {"id": "woodterrass", "name": "WoodTerrass", "address": "Kounice 5 Kounice 289 15"}, {"id": "gardina-cz-s-r-o", "name": "GARDINA.cz, s.r.o.", "address": "Poličany 54 Kutná Hora 284 01"}, {"id": "adh-ploty-s-r-o", "name": "ADH-PLOTY s.r.o.", "address": "Dolní Město 361 Dolní Město 282 33"}, {"id": "dluhos-s-r-o", "name": "DLUHOŠ s.r.o.", "address": "Hradecká 2714/68 Opava 746 01"}, {"id": "radim-jegla", "name": "Radim Jegla", "address": "Babice 38, Uherské Hradiště 687 03"}, {"id": "wpc-centrum-s-r-o-rozdrojovice", "name": "WPC centrum s.r.o. - Rozdrojovice", "address": "Žleby 194 Rozdrojovice 664 34"}, {"id": "stabo-mb-s-r-o", "name": "STABO MB s.r.o.", "address": "Pražská 1543 Moravské Budějovice 676 02"}, {"id": "bdj-interiery-s-r-o", "name": "BDJ INTERIÉRY s.r.o.", "address": "Štěchovice 336 Štěchovice 252 07"}, {"id": "mk-parkett-s-r-o", "name": "MK Parkett s.r.o.", "address": "Jiráskova 2042 Benešov 256 01"}, {"id": "jama-cz-s-r-o", "name": "JAMA CZ s.r.o.", "address": "Drachkov 86 Drachkov 386 01"}, {"id":"jaroslav-jirchar", "name": "Jaroslav Jirchář", "address": "Zahradní 334 Roudné 370 07"}, {"id": "bekera-s-r-o", "name": "BEKERA s.r.o.", "address": "Za nádrražím Zliv 373 44"}, {"id": "p-plast-lom-s-r-o", "name": "P-PLAST Lom s.r.o.", "address": "Lom 61 Lom 390 02"}, {"id": "ploty-vlasim-s-r-o", "name": "Ploty Vlašim s.r.o.", "address": "Vlasákova 222 Vlašim 258 01"}, {"id": "martin-kveton-drevoobchod-klatovy", "name": "Martin Květoň ( Dřevoobchod Klatovy )", "address": "Plzeňská 925 Klatovy 339 01"}, {"id": "drevoobchod-k-c-karlovy-vary-a-s", "name": "Dřevoobchod K&C Karlovy Vary, a.s.", "address": "Rosnice 66 Karlovy Vary 360 17"}, {"id": "drevak-k-c-s-r-o", "name": "Dřevák K & C s.r.o.", "address": "Tovární 5954 Chomutov 430 01"}, {"id": "palubky-koten-s-r-o", "name": "PALUBKY KOTEN s.r.o.", "address": "Pávoská 5679/25d Jihlava 586 01"}, {"id": "wpc-centrum-s-r-o-liberec", "name": "WPC centrum s.r.o. - Liberec", "address": "Cyrila a Metoděje 495/2 Liberec 460 01"}, {"id": "aqua-program-s-r-o-vzorova-terasa", "name": "AQUA Program s.r.o. - vzorová terasa", "address": "Ohrazenice 255 Ohrazenice 511 01"}, {"id": "podlahy-blanket-s-r-o", "name": "PODLAHY BLANKET s.r.o.", "address": "Pod Loretou 885 Kosmonosy 293 06"}, {"id": "vladeko-spol-s-r-o", "name": "VLADEKO spol. s r.o.", "address": "Karlštejnská 97 Tachlovice 252 17"}, {"id": "drevak-k-c-s-r-o", "name": "Dřevák K & C s.r.o.", "address": "Borská 93 Plzeň 301 00"}, {"id": "drevospektrum-rakovnik-s-r-o", "name": "DŘEVOSPEKTRUM Rakovník s.r.o.", "address": "Lišanská 2760 Rakovník 269 01"}, {"id": "stavebni-sdruzeni-bostik-s-r-o", "name": "Stavební sdružení Boštík s.r.o.", "address": "Poříčí u Litomyšle 117 Poříčí u Litomyšle 570 01"}, {"id": "drevoobchod-ceska-lipa-s-r-o", "name": "DŘEVOOBCHOD - ČESKÁ LÍPA, s. r. o.", "address": "U Obecního lesa 3044 Česká Lípa Dubice 470 01"}, {"id": "drevoobchod-melnik-s-r-o", "name": "Dřevoobchod Mělník s.r.o.", "address": "Nad Oborou 4154 Mělník 576 01"}, {"id": "drevoobchod-premier-vaclav-sladky", "name": "Dřevoobchod Premier Václav Sladký", "address": "Americká 2486/20 Cheb 350 02"}, {"id": "podlahy-a-dvere-s-r-o", "name": "PODLAHY A DVEŘE s.r.o.", "address": "Jičínská 169 Volanov 541 01"}, {"id": "stafikr-spol-s-r-o", "name": "STAFIKR, spol. s.r.o.", "address": "Bratislavská 587/16 Hustopeče 693 01"}, {"id": "translignum-bm-s-r-o", "name": "Translignum BM, s.r.o.", "address": "Návsí 975 Návsí 739 92"}, {"id": "strnad-podlahy-dvere-s-r-o", "name": "STRNAD podlahy, dveře s.r.o.", "address": "Rohovládova Bělá 143 Pardubice 533 43"}, {"id": "petr-vsechovsky-drevotyp", "name": "Petr Všechovský - Dřevotyp", "address": "Netovická 875 Slaný 274 01"}, {"id": "petr-vsechovsky-drevotyp", "name": "Petr Všechovský - Dřevotyp", "address": "Květoslava Mašity 219 Všenory 252 31"}, {"id": "pavel-behavy", "name": "Pavel Běhavý", "address": "Škvorecká 388 Úvaly 250 82"}, {"id": "lm-zelezarstvi-a-hutni-material-s-r-o", "name": "LM - Železářství a hutní materiál s.r.o.", "address": "Zámecká 10 Kunštát na Moravě 679 72"}, {"id": "drevoobchod-k-c-oldrichov", "name": "Dřevoobchod K&C Oldřichov", "address": "Oldřichov 227 Oldřichov 417 24"}, {"id": "df-technik-s-r-o", "name": "DF Technik s.r.o.", "address": "Novohospodská 135 Příbram 261 01"}];</script><script>(function(){function ready(fn){ if(document.readyState!=='loading') fn(); else document.addEventListener('DOMContentLoaded', fn); }function ensureLeaflet(fn){if(window.L){ fn(); return; }var h=document.head||document.getElementsByTagName('head')[0];var link=document.createElement('link'); link.rel='stylesheet'; link.href='https://unpkg.com/leaflet@1.9.4/dist/leaflet.css'; link.crossOrigin=''; h.appendChild(link);var s=document.createElement('script'); s.src='https://unpkg.com/leaflet@1.9.4/dist/leaflet.js'; s.crossOrigin=''; s.onload=function(){ fn(); }; h.appendChild(s);}ready(function(){ensureLeaflet(function(){var el = document.getElementById('leafletMap');if(!el) return;var map = L.map(el, { preferCanvas: true, scrollWheelZoom: false });window.__pickupMap = map;window.__pickupMapFitDone = false; // fit only onceL.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {maxZoom: 19,attribution: '&copy; OpenStreetMap'}).addTo(map);var group = L.featureGroup().addTo(map);var bounds = [];var points = Array.isArray(window.pickupPointsRaw) ? window.pickupPointsRaw : [];for (var i = 0; i < points.length; i++) {var p = points[i];if (typeof p.lat === 'number' && typeof p.lng === 'number') {var marker = L.circleMarker([p.lat, p.lng], { radius: 8, weight: 2 });(function(pp){marker.on('click', function(){window._selectedPickupPoint = pp;var inp = document.getElementById('pickupPointInput');if(inp){ inp.value = pp.name || ''; }var out = document.getElementById('selectedPickupPointDisplay');if(out){ out.innerHTML = 'Vybrané výdejní místo: <strong>' + (pp.name || '') + '</strong>'; out.style.display = 'block'; }var btn=document.getElementById('confirmPickupBtnModal'); if(btn) btn.disabled=false;if (typeof pp.lat === 'number' && typeof pp.lng === 'number') {L.popup().setLatLng([pp.lat, pp.lng]).setContent('<strong>'+ (pp.name||'') +'</strong>').openOn(map);}});})(p);group.addLayer(marker);bounds.push([p.lat, p.lng]);}}// Initial view: fit once if we have bounds, else center CZ.if (!window.__pickupMapFitDone) {if (bounds.length) {map.fitBounds(bounds, { padding: [40, 40], maxZoom: 8 });} else {map.setView([49.8, 15.5], 7);}window.__pickupMapFitDone = true;}// Fix container sizing once after render; no auto-fit here.setTimeout(function(){ try{ map.invalidateSize(false); }catch(e){__orderEmailSent = false;} }, 120);});});})();</script><script>// Confirm selection stays identical; kept for completeness if previous block was replaced accidentally.// (No changes to external API or other code.)function confirmPickupSelection(){var sel = window._selectedPickupPoint;if(!sel) return;var out = document.getElementById('selectedPickupPointDisplay');if(out){ out.innerHTML = 'Vybrané výdejní místo: <strong>' + (sel.name || '') + '</strong>'; out.style.display = 'block'; }var hidId = document.getElementById('orderPickupPointId');var hidName = document.getElementById('orderPickupPointName');if(hidId) hidId.value = sel.id || '';if(hidName) hidName.value = sel.name || '';var vis = document.getElementById('pickupPointInput');if(vis){ vis.value = sel.name || ''; }var nameSpan = document.getElementById('selectedPickupPointName');if(nameSpan){ nameSpan.textContent = ': ' + (sel.name || ''); }}</script><script>function handleShippingChange(){var radio = document.getElementById('shipping_pickup_point');var box = document.getElementById('pickupPointMapContainer');var mapEl = document.getElementById('leafletMap');var nameSpan = document.getElementById('selectedPickupPointName');if(!radio || !box) return;if(radio.checked){// Pokud už je potvrzeno, neotvírej mapu; jen zobraz názevif(selectedPickupPoint){if(box){ box.classList.remove('hidden'); }if(mapEl){ mapEl.style.display = 'none'; }if(nameSpan){ nameSpan.textContent = ': ' + selectedPickupPoint; }} else {if(box){ box.classList.remove('hidden'); }if(mapEl){ mapEl.style.display = 'block'; try{ setTimeout(function(){ if(window.__pickupMap){ __pickupMap.invalidateSize(false); } }, 80);}catch(e){__orderEmailSent = false;} }if(nameSpan){ nameSpan.textContent = ''; }}} else {if(box){ box.classList.add('hidden'); }}}</script><script>document.addEventListener('DOMContentLoaded', function(){var input = document.getElementById('pickupPointInput');var btn = document.getElementById('confirmPickupBtnModal');if(!input || !btn) return;btn.disabled = false;function tryMatch(){var val = input.value || '';var list = Array.isArray(window.pickupPointsRaw) ? window.pickupPointsRaw : [];var t = val.toLowerCase().trim();var sel = null;if(t){sel = list.find(function(p){ return (p.name||'').toLowerCase().trim() === t; }) ||list.find(function(p){ return (p.name||'').toLowerCase().indexOf(t) !== -1; });}if(sel){window._selectedPickupPoint = sel;btn.disabled = false;} else {btn.disabled = (val.trim().length === 0);}}input.addEventListener('input', tryMatch);// On focus, allow editing if previously readOnlyinput.addEventListener('focus', function(){ input.readOnly = false; });});</script><script>// --- Hard override: robust confirm that always runs and supports typed selection ---window.confirmPickupSelection = function(){try {var sel = window._selectedPickupPoint;if(!sel){var typed = (document.getElementById('pickupPointInput')||{}).value || '';if(typed){var list = Array.isArray(window.pickupPointsRaw) ? window.pickupPointsRaw : [];var t = typed.toLowerCase().trim();sel = list.find(function(p){ return (p.name||'').toLowerCase().trim() === t; }) ||list.find(function(p){ return (p.name||'').toLowerCase().indexOf(t) !== -1; });if(sel){ window._selectedPickupPoint = sel; }}}if(!sel){(window.showMessage ? showMessage : alert)('Vyberte prosím výdejní místo kliknutím na mapu nebo napište jeho název a stiskněte Vybrat.');return;}var out = document.getElementById('selectedPickupPointDisplay');if(out){ out.innerHTML = 'Vybrané výdejní místo: <strong>' + (sel.name || '') + '</strong>'; out.style.display = 'block'; }var hidId = document.getElementById('orderPickupPointId');var hidName = document.getElementById('orderPickupPointName');if(hidId) hidId.value = sel.id || '';if(hidName) hidName.value = sel.name || '';var vis = document.getElementById('pickupPointInput');if(vis){ vis.value = sel.name || ''; }var nameSpan = document.getElementById('selectedPickupPointName');if(nameSpan){ nameSpan.textContent = ': ' + (sel.name || ''); }var summaryName = document.getElementById('pickupPointSummaryName');if(summaryName){ summaryName.textContent = sel.name || ''; }if (typeof showPickupSummary === 'function') { showPickupSummary(); }} catch (e) {__orderEmailSent = false;try { console.error('confirmPickupSelection error:', e); } catch(_){__orderEmailSent = false;}(window.showMessage ? showMessage : alert)('Něco se pokazilo při potvrzení výdejního místa.');}};document.addEventListener('DOMContentLoaded', function(){var btn = document.getElementById('confirmPickupBtnModal');if(btn){ btn.disabled = false; btn.addEventListener('click', window.confirmPickupSelection); }});</script><script>// --- Hard override: confirm hides map and shows summary ---(function(){function slugify(str){try {return (str || '').normalize('NFKD').replace(/[\u0300-\u036f]/g,'').replace(/[^a-zA-Z0-9]+/g,'-').replace(/^[-]+|[-]+$/g,'').toLowerCase() || 'vydejni-misto';} catch(e) {__orderEmailSent = false;return (str || '').toString().trim().toLowerCase().replace(/\s+/g,'-') || 'vydejni-misto';}}function showSummaryUI(sel){var out = document.getElementById('selectedPickupPointDisplay');if(out){ out.innerHTML = 'Vybrané výdejní místo: <strong>' + (sel.name || '') + '</strong>'; out.style.display = 'block'; }var nameSpan = document.getElementById('selectedPickupPointName');if(nameSpan){ nameSpan.textContent = ': ' + (sel.name || ''); }var summaryName = document.getElementById('pickupPointSummaryName');if(summaryName){ summaryName.textContent = sel.name || ''; }var mapEl = document.getElementById('leafletMap');var sum = document.getElementById('pickupPointSummary');var cont = document.getElementById('pickupPointMapContainer');// Keep container visible (so user can "Změnit"), hide only the map areaif(mapEl){ mapEl.style.display = 'none'; }if(sum){ sum.style.display = 'flex'; }if(cont){ cont.classList.remove('hidden'); }}window.confirmPickupSelection = function(){try {var sel = window._selectedPickupPoint;var inputEl = document.getElementById('pickupPointInput');var typed = (inputEl && inputEl.value) ? inputEl.value.trim() : '';if(!sel){var list = Array.isArray(window.pickupPointsRaw) ? window.pickupPointsRaw : [];var t = typed.toLowerCase();if(t){sel = list.find(function(p){ return (p.name||'').toLowerCase().trim() === t; }) ||list.find(function(p){ return (p.name||'').toLowerCase().indexOf(t) !== -1; });}}if(!sel && typed){sel = { id: slugify(typed), name: typed };window._selectedPickupPoint = sel;}if(!sel){(window.showMessage ? showMessage : alert)('Vyberte prosím výdejní místo: klikněte na mapu nebo napište název a dejte Vybrat.');return;}// Persist selection to hidden fields & inputvar hidId = document.getElementById('orderPickupPointId');var hidName = document.getElementById('orderPickupPointName');if(hidId) hidId.value = sel.id || '';if(hidName) hidName.value = sel.name || '';if(inputEl){ inputEl.value = sel.name || ''; }// Show summary and hide map areashowSummaryUI(sel);} catch (e) {__orderEmailSent = false;try { console.error('confirmPickupSelection error:', e); } catch(_){__orderEmailSent = false;}(window.showMessage ? showMessage : alert)('Něco se pokazilo při potvrzení výdejního místa.');}};// Ensure button is wired and enableddocument.addEventListener('DOMContentLoaded', function(){var btn = document.getElementById('confirmPickupBtnModal');if(btn){btn.disabled = false;btn.addEventListener('click', window.confirmPickupSelection);}});})();</script><script>function confirmPickupPoint(){var inp = document.getElementById('pickupPointInput');var name = (inp && typeof inp.value === 'string') ? inp.value.trim() : '';if (!name) {try { (window.showMessage || window.showToast || alert)('Prosím, vyberte výdejní místo na mapě a stiskněte Vybrat.'); } catch(_) {}try { if (inp) inp.focus(); } catch(_) {}return;}// uložit zvolený název do globáluwindow.selectedPickupPoint = name;// schovat výběr/mapuvar mapWrap = document.getElementById('pickupPointMapContainer');if (mapWrap) mapWrap.style.display = 'none';// zobrazit wrapper se změnou, pokud existujevar changeWrap = document.getElementById('changePickupWrapper');if (changeWrap) changeWrap.style.display = 'block';// propsat zelené jméno vedle "Výdejní místo" + učinit klikatelnévar nameSpan = document.getElementById('selectedPickupPointName');if (nameSpan) {nameSpan.textContent = name;nameSpan.classList.remove('hidden');nameSpan.classList.add('cursor-pointer','text-green-700','font-bold','underline','underline-offset-2');nameSpan.setAttribute('title', 'Změnit výdejní místo');nameSpan.setAttribute('tabindex','0');var open = function(e){ if(e) e.preventDefault(); if (typeof editPickupPoint === 'function') editPickupPoint(); };nameSpan.onclick = open;nameSpan.onkeydown = function(e){ if (e.key === 'Enter' || e.key === ' ') open(e); };}}document.addEventListener('DOMContentLoaded', makePickupNameClickableOnce);</script><script>// === FINAL OVERRIDE (self-contained) ===(function(){function safeMsg(msg, type){try { (window.showMessage || window.showToast || alert)(msg); } catch(_){ __orderEmailSent = false;alert(msg); }}function makeNameClickable(){var nameSpan = document.getElementById('selectedPickupPointName');if(!nameSpan) return;try {nameSpan.classList.add('clickable-pickup');nameSpan.setAttribute('title','Změnit výdejní místo');nameSpan.setAttribute('tabindex','0');var _handler = function(e){ if(e) e.preventDefault(); if(typeof editPickupPoint==='function') editPickupPoint(); };nameSpan.onclick = _handler;nameSpan.onkeydown = function(e){ if(e.key==='Enter' || e.key===' '){ _handler(e); } };} catch(e){__orderEmailSent = false;}}window.confirmPickupPointFinal = function(){try {var input = document.getElementById('pickupPointInput');var val = (input && input.value ? input.value.trim() : '');if(!val){safeMsg('Prosím, vyberte výdejní místo na mapě a stiskněte Vybrat.');if(input){ try{ input.focus(); }catch(_e){__orderEmailSent = false;} }return;}// Persist selectionwindow.selectedPickupPoint = val;// Update label next to shippingvar nameSpan = document.getElementById('selectedPickupPointName');if(nameSpan){ nameSpan.textContent = ': ' + val; }// Lock value into the input (read-only)if(input){ input.value = val; }// Hide full selection UI (title + input + map container)var mapWrap = document.getElementById('pickupPointMapContainer');if(mapWrap){ mapWrap.style.display = 'none'; }// Ensure change button wrapper exists; if not, create minimal one under shipping optionsvar changeWrap = document.getElementById('changePickupWrapper');if(!changeWrap){var ship = document.getElementById('shippingOptions') || document.body;changeWrap = document.createElement('div');changeWrap.id = 'changePickupWrapper';changeWrap.style.marginTop = '8px';changeWrap.innerHTML = '<button id="changePickupBtn" type="button" class="calculate-button py-2 px-4 rounded-md">Změnit výdejní místo</button>';ship.parentNode.insertBefore(changeWrap, ship.nextSibling);}changeWrap.style.display = 'block';// Wire change button to reopen UIvar changeBtn = document.getElementById('changePickupBtn');if(changeBtn){changeBtn.onclick = function(){// Show full UI againvar mapWrap2 = document.getElementById('pickupPointMapContainer');if(mapWrap2){ mapWrap2.style.display = 'block'; }var mapEl = document.getElementById('leafletMap');if(mapEl){ mapEl.style.display = 'block'; setTimeout(function(){ if(window.__pickupMap){ try{ __pickupMap.invalidateSize(false); }catch(e){__orderEmailSent = false;} } }, 80); }// Hide change button wrappervar cw = document.getElementById('changePickupWrapper');if(cw){ cw.style.display = 'none'; }// Allow editing name againvar inp = document.getElementById('pickupPointInput'); if(inp){ /* ponecháváme readOnly */ }catch(_e){__orderEmailSent = false;} }};}// Make the name clickable as a second change affordancemakeNameClickable();// User feedbacksafeMsg('Výdejní místo bylo potvrzeno.');} catch (err) {__orderEmailSent = false;try { console.error('confirmPickupPointFinal error:', err); } catch(_){__orderEmailSent = false;}safeMsg('Něco se pokazilo při potvrzení výdejního místa.');}};// Wire the button on DOM readydocument.addEventListener('DOMContentLoaded', function(){var btn = document.getElementById('confirmPickupBtnModal');if(btn){btn.disabled = false;btn.removeAttribute('disabled');btn.onclick = function(e){ e && e.preventDefault && e.preventDefault(); window.confirmPickupPointFinal(); };}});})();</script><!-- EMAILJS PATCH START — 2025-10-21 11:11:30 --><!-- Tento blok přidává odeslání objednávky přes EmailJS (admin + zákazník).Pokud máte na stránce jiné staré EmailJS skripty, ponechte v DOM pouze JEDEN<!-- EMAILJS PATCH END --><script>// ====== SBĚR DAT Z FORMULÁŘE (robustní) ======function getOrderFormData() {const g = id => (document.getElementById(id)?.value || "").trim();// Pokud je otevřen modal z tlačítka u kalkulačky, uložené je ID zdrojového emailového inputu.const sourceId = g("modalEmailSource");const emailFromSource = sourceId ? (document.getElementById(sourceId)?.value || "").trim() : "";const data = {isCompany: document.getElementById("isCompany")?.checked || false,company_name: g("orderCompanyName"),company_id: g("orderICO"),company_vat: g("orderDIC") || "",// Jméno / příjmení (kontakt nebo soukromá)name: g("orderContactName") || g("orderName"),surname: g("orderContactSurname") || g("orderSurname"),// Kontakt – teď i fallback na původní input z kalkulačkyphone: g("orderContactPhone") || g("orderPhone"),email: g("orderContactEmail") || g("orderEmail") || emailFromSource,// Adresa – bere fakturační i dodací + starší aliasystreet: g("orderAddressStreet") || g("deliveryAddressStreet") || g("orderStreet") || g("billingStreet") || g("shippingStreet"),city: g("orderAddressCity") || g("deliveryAddressCity") || g("orderCity") || g("billingCity") || g("shippingCity"),zip: g("orderAddressZip") || g("deliveryAddressZip") || g("orderZip") || g("billingZip") || g("shippingZip"),note: g("orderNote"),source: sourceId,};data.delivery_date = g("deliveryDate");data.delivery_time = g("deliveryTime");// Validace (přísná)const errs = [];if (!data.name) errs.push("Jméno");if (!data.surname) errs.push("Příjmení");if (!data.phone) errs.push("Telefon");if (!data.email) errs.push("Email");if (!data.street) errs.push("Ulice a č.p.");if (!data.city) errs.push("Město");if (!data.zip) errs.push("PSČ");if (data.isCompany) {if (!data.company_name) errs.push("Název společnosti");if (!data.company_id) errs.push("IČO");}if (errs.length) throw new Error("Chybí povinná pole: " + errs.join(", "));data.customer_name = [data.name, data.surname].filter(Boolean).join(" ");data.customer_fullname = data.customer_name;data.address_combined = [data.street, (data.zip && data.city) ? (data.zip + " " + data.city) : (data.city || data.zip)].filter(Boolean).join(", ");// --- Shipping & Payment (from modal) ---const checkedShipping = document.querySelector('input[name="shippingMethod"]:checked');const checkedPayment = document.querySelector('input[name="paymentMethod"]:checked');const pickupName =(document.getElementById('orderPickupPointName')?.value || '').trim() ||(document.getElementById('pickupPointInput')?.value || '').trim() ||(window.selectedPickupPoint || '').toString().trim();data.delivery_method = checkedShipping ? checkedShipping.value : '';data.payment_method = checkedPayment ? checkedPayment.value : '';data.pickup_point = pickupName || '';// validationif (!data.delivery_method) errs.push('Způsob dopravy');if (!data.payment_method) errs.push('Způsob platby');if (data.delivery_method === 'Výdejní místo' && !data.pickup_point) errs.push('Vybrané výdejní místo');return data;}// Export do globálu pro EmailJS bloktry { window.getOrderFormData = getOrderFormData; } catch(_) {}</script><!-- EmailJS – jediný blok (ponechte jen tento) --><script src="https://cdn.jsdelivr.net/npm/@emailjs/browser@3/dist/email.min.js"></script><script>(function(){// Konfiguracewindow.EMAILJS_PUBLIC_KEY = "-0oqNlTtogS-lRrz8";window.EMAILJS_SERVICE_ID = "service_l8ht2wb";window.EMAILJS_TEMPLATE_ADMIN = "template_dln84ob";window.EMAILJS_TEMPLATE_CUSTOMER = "template_81qfpho";window.EMAILJS_ADMIN_EMAIL = "wpccentrum@gmail.com";try { emailjs.init(window.EMAILJS_PUBLIC_KEY); } catch(e){ console.warn("emailjs.init:", e); }// Helpers pro mailfunction qs(s){ try { return document.querySelector(s); } catch(_){ return null; } }function text(el){ return (el ? (el.value ?? el.textContent ?? "") : "").toString().trim(); }function htmlOf(el){ return el ? (el.outerHTML || el.innerHTML || "") : ""; }function grabEntryTableHtml(){const el = qs('[data-entry-table]') || qs('#entryTable') || qs('.entry-table') || qs('#vstupniTabulka') || qs('.input-table');return htmlOf(el);}function grabCalculationHtml(){const blocks = [document.getElementById("terrace-results"),document.getElementById("fence-90x13-results"),document.getElementById("fence-150x12-results"),];for (const el of blocks) if (el && !el.classList.contains("hidden")) return el.outerHTML;return "";}function grabTotalPrice(){const el = qs("#terraceTotalPriceVAT") || qs("#fence90x13TotalPriceVAT") || qs("#fence150x12TotalPriceVAT") || qs("[data-total-price]");return text(el);}function buildAdminSummaryHTML(data, entryHtml, calcHtml){const row = (k,v) => `<tr><td style="padding:6px 10px; border-bottom:1px solid #eee; color:#6b7280; width:200px;">${k}</td><td style="padding:6px 10px; border-bottom:1px solid #eee;">${v||""}</td></tr>`;let h = `<div style="font-family:system-ui,-apple-system,Segoe UI,Roboto,Arial,sans-serif; font-size:14px; color:#111;">`;h += `<h2 style="margin:0 0 10px;">Zákazník</h2><table cellpadding="0" cellspacing="0" style="width:100%; border-collapse:collapse;">`;h += row("Jméno", data.name||"");h += row("Příjmení", data.surname||"");h += row("Email", data.email||"");h += row("Telefon", data.phone||"");h += row("Datum doručení", data.delivery_date || "");h += row("Čas doručení", data.delivery_time || "");h +=h += row("Způsob dopravy", data.delivery_method || "");if (data.pickup_point) h += row("Výdejní místo", data.pickup_point);h += row("Způsob platby", data.payment_method || "");row("Adresa", data.address_combined||"");if (data.isCompany) {h += row("Firma", data.company_name||"");h += row("IČ", data.company_id||"");if (data.company_vat) h += row("DIČ", data.company_vat);}h += `</table>`;if (entryHtml) h += `<h3 style="margin:16px 0 8px;">Vstupní zadávací tabulka</h3>${entryHtml}`;if (calcHtml) h += `<h3 style="margin:16px 0 8px;">Kalkulace</h3>${calcHtml}`;h += `<div style="margin-top:16px; font-size:12px; color:#6b7280;">Email vygenerován automaticky z kalkulátoru.</div>`;h += `</div>`;return h;}function genOrderNo(){const d=new Date(); const p=n=> (n<10?'0':'')+n;return d.getFullYear()+''+p(d.getMonth()+1)+p(d.getDate())+'-'+p(d.getHours())+p(d.getMinutes())+p(d.getSeconds());}window.sendOrderEmails = async function(ev){try{if (ev && ev.preventDefault) ev.preventDefault();if (!window.emailjs) { alert('EmailJS SDK se nenačetl.'); return; }if (typeof window.getOrderFormData !== 'function'){ alert('Chybí getOrderFormData().'); return; }const data = window.getOrderFormData();const entryHtml = grabEntryTableHtml();const calcHtml = grabCalculationHtml();const summaryHtml = buildAdminSummaryHTML(data, entryHtml, calcHtml);const totalPrice = grabTotalPrice();const orderNo = genOrderNo();const adminParams = {delivery_date: data.delivery_date,delivery_time: data.delivery_time,note: data.note,customer_fullname: data.customer_fullname,subject: "Nová objednávka #" + orderNo,reply_to: data.email,to_email: window.EMAILJS_ADMIN_EMAIL,customer_name: data.name,customer_surname: data.surname,customer_email: data.email,customer_phone: data.phone,address_street: data.street,address_city: data.city,address_zip: data.zip,address_combined: data.address_combined,company_name: data.company_name,company_id: data.company_id,company_vat: data.company_vat,summary_html: summaryHtml,entry_table_html: entryHtml,calculation_html: calcHtml,delivery_method: data.delivery_method || '',pickup_point: data.pickup_point || '',payment_method: data.payment_method || '',total_price: totalPrice,order_number: orderNo,order_note: data.note || ""};console.log('ADMIN PARAMS >>', adminParams);// === ADMIN EMAIL PAYLOAD (strictly matching template + strings only) ===const S = v => (v == null ? "" : String(v));const esc = s => S(s).replace(/[&<>"]/g, c => ({'&':'&amp;','<':'&lt;','>':'&gt;'}[c] || c));const pickup_point_line = data.pickup_point? `<div style="margin:4px 0;"><span style="color:#6b7280;">Výdejní místo:</span> ${esc(data.pickup_point)}</div>`: "";const delivery_address_line = data.delivery_address? `<div style="margin:4px 0;"><span style="color:#6b7280;">Dodací adresa:</span> ${esc(data.delivery_address)}</div>`: "";const customer_address = data.address_combined? S(data.address_combined): [data.street, data.city, data.zip].filter(Boolean).join(", ");const adminPayload = {delivery_date: data.delivery_date,delivery_time: data.delivery_time,note: data.note,customer_fullname: data.customer_fullname,// routing in EmailJS template (To: {{to_email}})to_email: S(window.EMAILJS_ADMIN_EMAIL),reply_to: S(data.email),// subject + metasubject: S(`Nová objednávka #${orderNo}`),order_number: S(orderNo),// customercustomer_name: S(data.name),customer_surname: S(data.surname),customer_phone: S(data.phone),customer_email: S(data.email),customer_address: S(customer_address),// companycompany_name: S(data.company_name),company_id: S(data.company_id),company_vat: S(data.company_vat),// deliverydelivery_method: S(data.delivery_method),pickup_point: S(data.pickup_point), // kept for compatibilitydelivery_address: S(data.delivery_address), // kept for compatibility// pre-rendered conditional lines for the template (use {{{...}}} in EmailJS)pickup_point_line: S(pickup_point_line),delivery_address_line: S(delivery_address_line),// paymentpayment_method: S(data.payment_method),// big HTML fragmentssummary_html: S(summaryHtml),entry_table_html: S(entryHtml),calculation_html: S(calcHtml),// totalstotal_price: S(totalPrice)};// optional debugtry { console.log('adminPayload', adminPayload); } catch(e) {}await emailjs.send(window.EMAILJS_SERVICE_ID, window.EMAILJS_TEMPLATE_ADMIN, adminPayload);if (data.email){const customerHtml =`<div style="font-family:Arial, Helvetica, sans-serif; font-size:14px; line-height:1.5; color:#111;">`+`<p>Dobrý den ${data.name} ${data.surname||""},</p>`+`<p>vaši objednávku jsme přijali. Níže posíláme rekapitulaci:</p>`+summaryHtml + `</div>`;await emailjs.send(window.EMAILJS_SERVICE_ID, window.EMAILJS_TEMPLATE_CUSTOMER, { delivery_method: data.delivery_method || '', pickup_point: data.pickup_point || '', payment_method: data.payment_method || '',to_email: data.email,reply_to: window.EMAILJS_ADMIN_EMAIL,subject: "Potvrzení přijaté objednávky #" + orderNo,summary_html: customerHtml,entry_table_html: entryHtml,calculation_html: calcHtml,total_price: totalPrice,order_number: orderNo,customer_name: data.name,customer_surname: data.surname});}document.getElementById('orderModal').classList.add('hidden');document.getElementById('thankYouMessage').style.display='block';} catch(err){console.error(err);alert('Nepodařilo se odeslat email: ' + (err && (err.message || err.text) || 'neznámáchyba'));}};// Napojení POUZE na #orderForm a #confirmOrderSubmitdocument.addEventListener('DOMContentLoaded', function(){const btn = document.getElementById('confirmOrderSubmit');const form = document.getElementById('orderForm');if (btn && !btn.__wiredEmail){btn.__wiredEmail = true;btn.addEventListener('click', function(ev){ ev.preventDefault(); window.sendOrderEmails(ev); });}if (form && !form.__wiredEmail){form.__wiredEmail = true;form.addEventListener('submit', function(ev){ ev.preventDefault(); window.sendOrderEmails(ev); });}});})();</script><!-- Hard lock for pickupPointInput to disallow manual typing while allowing programmatic updates --><script>document.addEventListener('DOMContentLoaded', function () {var inp = document.getElementById('pickupPointInput');if (!inp) return;// Enforce readOnlyinp.setAttribute('readonly', '');inp.readOnly = true;// Block any manual editing methods['beforeinput', 'paste', 'drop'].forEach(function (ev) {inp.addEventListener(ev, function (e) { e.preventDefault(); }, true);});inp.addEventListener('keydown', function (e) {var allowed = ['Tab', 'ArrowLeft', 'ArrowRight', 'Home', 'End'];if (allowed.indexOf(e.key) === -1) e.preventDefault();}, true);// If some script removes readonly later, put it backvar mo = new MutationObserver(function () {if (!inp.readOnly) inp.readOnly = true;if (!inp.hasAttribute('readonly')) inp.setAttribute('readonly', '');});mo.observe(inp, { attributes: true });});// Helper you can call from the map click handlerfunction setSelectedLambopont(name) {var inp = document.getElementById('pickupPointInput');if (inp) { inp.value = name || ''; }}</script><script>function editPickupPoint(){// show map container (remove hidden class if present)var wrap = document.getElementById('pickupPointMapContainer');if (wrap) {wrap.classList.remove('hidden');wrap.style.display = ''; // reset any inline style}// optional: hide change wrapper if existsvar cwrap = document.getElementById('changePickupWrapper');if (cwrap) { cwrap.classList.add('hidden'); }// Invalidate Leaflet map size if availableif (window._pickupMap && typeof window._pickupMap.invalidateSize === 'function'){setTimeout(function(){ try { window._pickupMap.invalidateSize(false); } catch(_) {} }, 50);}}</script><script>function makePickupNameClickableOnce(){var span = document.getElementById('selectedPickupPointName');if (!span) return;span.classList.add('cursor-pointer','text-green-700','font-bold','underline','underline-offset-2');span.setAttribute('title','Změnit výdejní místo');span.setAttribute('tabindex','0');var open = function(e){ if (e) e.preventDefault(); if (typeof editPickupPoint === 'function') editPickupPoint(); };span.onclick = open;span.onkeydown = function(e){ if (e.key === 'Enter' || e.key === ' ') open(e); };}document.addEventListener('DOMContentLoaded', makePickupNameClickableOnce);</script><script>// Helper that ensures the pickup map is visiblefunction openPickupMap(){if (typeof editPickupPoint === 'function') {editPickupPoint();return;}var wrap = document.getElementById('pickupPointMapContainer');if (wrap){wrap.classList.remove('hidden');wrap.style.display = '';}var cwrap = document.getElementById('changePickupWrapper');if (cwrap){ cwrap.classList.add('hidden'); }if (window._pickupMap && typeof window._pickupMap.invalidateSize === 'function'){setTimeout(function(){ try { window._pickupMap.invalidateSize(false); } catch(_){} }, 50);}}// When user toggles delivery method back to "Výdejní místo", reopen the mapdocument.addEventListener('change', function(e){var t = e.target;if (!t || t.type !== 'radio' || !t.checked) return;var id = (t.id || '').toLowerCase();var val = (t.value || '').toLowerCase();// Try to read label textvar labelText = '';var lbl = t.id ? document.querySelector('label[for="' + t.id + '"]') : null;if (lbl) labelText = (lbl.textContent || '').trim().toLowerCase();// Heuristics: if it looks like the "pickup point" option, open the mapvar isPickup = /vydej|výdej|zasilkovna|pickup|lambopont/.test(id + ' ' + val + ' ' + labelText) && !/osobni|osobní|odber|odběr/.test(id + ' ' + val + ' ' + labelText);if (isPickup) {openPickupMap();}});</script><script>(function(){// Utility: show/hide helpersfunction show(el){ if(!el) return; el.classList.remove('hidden'); el.style.display=''; }function hide(el){ if(!el) return; el.classList.add('hidden'); el.style.display='none'; }// Handle "same as billing" checkbox: hide inner fields when checkedfunction wireSameAsBilling(){var cb = document.getElementById('sameAsBilling');var inner = document.getElementById('deliveryAddressInner');if(!cb || !inner) return;var apply = function(){ if (cb.checked) hide(inner); else show(inner); };cb.addEventListener('change', apply);apply();}document.addEventListener('DOMContentLoaded', wireSameAsBilling);// Extend the existing radio change handler logic to also manage address fieldsdocument.addEventListener('change', function(e){var t = e.target;if (!t || t.type !== 'radio' || !t.checked) return;var id = (t.id || '').toLowerCase();var val = (t.value || '').toLowerCase();var labelText = '';var lbl = t.id ? document.querySelector('label[for=\"' + t.id + '\"]') : null;if (lbl) labelText = (lbl.textContent || '').trim().toLowerCase();var isPickup = /vydej|výdej|zasilkovna|pickup|lambopont/.test(id + ' ' + val + ' ' + labelText) && !/osobni|osobní|odber|odběr/.test(id + ' ' + val + ' ' + labelText);var isAddress = /adresa|adresu|address|doprava na adresu/.test(id + ' ' + val + ' ' + labelText);var mapWrap = document.getElementById('pickupPointMapContainer');var changeWrap = document.getElementById('changePickupWrapper');var addr = document.getElementById('deliveryAddressFields');if (isPickup){// open pickup map and hide address fieldsif (typeof openPickupMap === 'function') openPickupMap();hide(addr);} else if (isAddress){// show address fields and hide pickup map UIshow(addr);hide(mapWrap);if (changeWrap) show(changeWrap); // necháme vidět název místa, ať je jasné co bylo vybráno předtím}});})();</script><div class="mt-6 flex justify-end space-x-3"><button type="button" onclick="closeDeliveryAddressModal()" class="px-4 py-2 rounded-md border">Zavřít</button></div><!-- DODÁNÍ NA ADRESU — INLINE (vkládá se přímo pod 'Doprava na adresu') --><section id="deliveryAddressInline" class="mt-4 hidden"><div class="bg-gray-50 p-4 rounded-lg border border-gray-200"><label class="inline-flex items-center space-x-2 mb-3"><input id="sameAsBilling" type="checkbox" class="h-5 w-5 text-stone-800 border-gray-300 rounded focus:ring-stone-800" checked=""><span class="text-sm text-gray-800">Dodací adresa je stejná jako fakturační</span></label><!-- Datum a čas doručení --><div id="deliveryDateTime" class="mt-3 hidden"><label class="block text-sm font-medium text-gray-900">Požadovaný datum doručení *</label><input type="date" id="deliveryDate" class="mt-1 block w-full px-3 py-2 border border-gray-300 rounded-md"><label class="block text-sm font-medium text-gray-900 mt-3">Požadovaný čas doručení *</label><select id="deliveryTime" class="mt-1 block w-full px-3 py-2 border border-gray-300 rounded-md"></select><p style="color:#d00; font-size:13px; margin-top:6px;">Čas doručení bude potvrzen s potvrzením objednávky.</p></div><div id="deliveryAddressInner" class="grid grid-cols-1 md:grid-cols-2 gap-4 mt-3 hidden"><div class="md:col-span-2"><label for="shipStreet" class="block text-sm font-medium text-gray-700">Ulice a č.p. *</label><input id="shipStreet" type="text" class="mt-1 block w-full px-4 py-2 border border-gray-300 rounded-md shadow-sm focus:ring-amber-500 focus:border-amber-500" placeholder="Např. Hlavní 123"></div><div><label for="shipCity" class="block text-sm font-medium text-gray-700">Město *</label><input id="shipCity" type="text" class="mt-1 block w-full px-4 py-2 border border-gray-300 rounded-md shadow-sm focus:ring-amber-500 focus:border-amber-500" placeholder="Např. Liberec"></div><div><label for="shipZip" class="block text-sm font-medium text-gray-700">PSČ *</label><input id="shipZip" type="text" inputmode="numeric" class="mt-1 block w-full px-4 py-2 border border-gray-300 rounded-md shadow-sm focus:ring-amber-500 focus:border-amber-500" placeholder="Např. 460 01"></div></div></div></section><script>(function(){function show(el){ if(!el) return; el.classList.remove('hidden'); el.style.display=''; }function hide(el){ if(!el) return; el.classList.add('hidden'); el.style.display='none'; }function isPickupCandidate(id,val,label){var s = (id + ' ' + val + ' ' + label).toLowerCase();return /vydej|výdej|zasilkovna|pickup|lambopont/.test(s) && !/osobni|osobní|odber|odběr/.test(s);}function isAddressCandidate(id,val,label){var s = (id + ' ' + val + ' ' + label).toLowerCase();return /adresa|adresu|address|doprava na adresu/.test(s);}function wireSameAsBilling(){var cb = document.getElementById('sameAsBilling');var inner = document.getElementById('deliveryAddressInner');if(!cb || !inner) return;var apply = function(){ if (cb.checked) hide(inner); else show(inner); };cb.addEventListener('change', apply);apply();}function mountAddressUnderAddressRadio(){var radios = Array.from(document.querySelectorAll('input[type="radio"]'));var addrRadio = radios.find(function(r){var id=r.id||'', val=r.value||'';var lblEl = r.id ? document.querySelector('label[for="'+r.id+'"]') : null;var label = lblEl ? lblEl.textContent.trim() : '';return isAddressCandidate(id,val,label);});if (!addrRadio) return;var section = document.getElementById('deliveryAddressInline');if (!section) return;// Find the whole row container that holds the radio + its label (most likely the shared parent)var labelEl = addrRadio.id ? document.querySelector('label[for="'+addrRadio.id+'"]') : null;var row = (labelEl && labelEl.parentElement) || addrRadio.parentElement;// If there is a higher-level row container (e.g., .form-group), prefer itif (row && row.closest) {var candidates = row.closest('.form-group, .flex, .grid, .bg-gray-50, .radio-row');if (candidates) row = candidates;}// Insert the section directly AFTER the entire row so it appears *under* itif (row && row.parentNode) {row.insertAdjacentElement('afterend', section);}}document.addEventListener('DOMContentLoaded', function(){mountAddressUnderAddressRadio();wireSameAsBilling();});// Toggle visibility based on radio selectiondocument.addEventListener('change', function(e){var t = e.target;if (!t || t.type !== 'radio' || !t.checked) return;var id = (t.id || '');var val = (t.value || '');var lbl = t.id ? document.querySelector('label[for="'+t.id+'"]') : null;var labelText = lbl ? (lbl.textContent || '').trim() : '';var isPickup = isPickupCandidate(id,val,labelText);var isAddress = isAddressCandidate(id,val,labelText);var section = document.getElementById('deliveryAddressInline');var mapWrap = document.getElementById('pickupPointMapContainer');var changeWrap = document.getElementById('changePickupWrapper');if (isAddress){show(section);// hide pickup UI when switching to addressif (mapWrap) hide(mapWrap);// necháme change-wrap klidně viditelný/skrýt dle preferencí, zde ho skryjeme:if (changeWrap) hide(changeWrap);} else if (isPickup){hide(section);// open map for pickupif (typeof openPickupMap === 'function') openPickupMap();} else {// other options (e.g., osobní odběr): hide address sectionhide(section);}});})();</script><script>function _getUserEmail(){ return (document.getElementById('userEmail')?.value || '').trim(); }function _isValidEmail(v){if (!v) return false;// Simple but solid RFC 5322-ish patternreturn /^[^\s@]+@[^\s@]+\.[^\s@]{2,}$/.test(v);}function _ensureEmailOrWarn(){var v = _getUserEmail();if (!v){alert('Prosím vyplňte email, bez něj nelze spočítat kalkulaci.');try { document.getElementById('userEmail')?.focus(); } catch(e){}return false;}if (!_isValidEmail(v)){alert('Zadejte platný email.');try { document.getElementById('userEmail')?.focus(); } catch(e){}return false;}return true;}</script><script>function _getActiveEmailInput(){var inputs = Array.from(document.querySelectorAll('input[data-email-required]'));return inputs.find(function(i){ return i && i.offsetParent !== null; }) || inputs[0] || null;}function _getUserEmail(){ var el=_getActiveEmailInput(); return (el ? el.value : '').trim(); }function _isValidEmail(v){if (!v) return false;return /^[^\s@]+@[^\s@]+\.[^\s@]{2,}$/.test(v);}function _ensureEmailOrWarn(){var el = _getActiveEmailInput();var v = (el ? el.value : '').trim();if (!v){alert('Prosím vyplňte email, bez něj nelze spočítat kalkulaci.');try { el && el.focus(); } catch(e){}return false;}if (!_isValidEmail(v)){alert('Zadejte platný email.');try { el && el.focus(); } catch(e){}return false;}return true;}</script><!-- FAST pickup points v7: precomputed WebMercator + OffscreenCanvas + ultra sampling --><script>(function(){if (window.__pickupFastV7) return; window.__pickupFastV7 = true;function onReady(fn){if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', fn, {once:true});else fn();}function wait(cond, cb, limit){let n=0, lim = limit||400;(function loop(){ if (cond()) return cb(); if (++n>lim) return; setTimeout(loop, 50); })();}function htmlSafe(s){ return (''+s).replace(/[&<>"]/g,c=>({ '&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;' }[c])); }function normalizePoint(p){if (!p || typeof p!=='object') return null;let lat = p.lat ?? p.latitude ?? p.y ?? p.gpsY;let lng = p.lng ?? p.longitude ?? p.x ?? p.gpsX;if (typeof lat === 'number' && typeof lng === 'number') return {lat,lng,name:p.name||p.title||p.id||'Výdejní místo', raw:p};let s = p.latlon || p.coords || '';let m = /(-?\d{1,2}\.\d+)[,\s]+(-?\d{1,3}\.\d+)/.exec(s);if (m) return {lat:parseFloat(m[1]), lng:parseFloat(m[2]), name:p.name||p.title||p.id||'Výdejní místo', raw:p};return null;}onReady(function(){wait(()=>window.L && window.map, function start(){const Map = window.map;const DPR = (window.devicePixelRatio || 1);// --- DATA ---let raw = [];if (Array.isArray(window.pickupPointsRaw)) raw = window.pickupPointsRaw.slice();else if (Array.isArray(window.pickupPoints)) raw = window.pickupPoints.slice();else if (Array.isArray(window.PICKUPS)) raw = window.PICKUPS.slice();const items = [];for (const p of raw){const np = normalizePoint(p);if (np) items.push(np);}if (!items.length){console.warn('Žádné výdejní místo se souřadnicemi. Doplň lat/lng do dat na serveru.');return;}// Precompute WebMercator normalized coords (zoom-independent)function lat2ny(lat){const s = Math.sin(lat*Math.PI/180);const y = 0.5 - Math.log((1+s)/(1-s)) / (4*Math.PI);return Math.min(1, Math.max(0, y));}function lng2nx(lng){ return (lng + 180) / 360; }for (const it of items){it.__nx = lng2nx(it.lng); // 0..1it.__ny = lat2ny(it.lat); // 0..1}// --- CANVAS (onscreen + offscreen) ---const cont = Map.getContainer();const canvas = document.createElement('canvas');canvas.style.cssText = 'position:absolute; left:0; top:0; width:100%; height:100%; pointer-events:auto; z-index:350;';cont.appendChild(canvas);const ctx = canvas.getContext('2d');let off = null, octx = null;try{off = new OffscreenCanvas(1,1);octx = off.getContext('2d');}catch(e){off = null; octx = null;}function resize(){const r = cont.getBoundingClientRect();canvas.width = r.width * DPR;canvas.height = r.height * DPR;canvas.style.width = r.width + 'px';canvas.style.height = r.height + 'px';if (off){off.width = canvas.width;off.height = canvas.height;}}resize();window.addEventListener('resize', resize);// parametersconst MAX_RENDER = 90;const CELL_PX = 72;const RADIUS = 5 * DPR;const LINEW = 2 * DPR;let displayList = []; // {pt, x, y}let rafId = 0, needRecompute = true;function computeDisplayList(){const z = Map.getZoom();const scale = 256 * Math.pow(2, z);const origin = Map.getPixelOrigin();const bounds = Map.getBounds();const sw = bounds.getSouthWest(), ne = bounds.getNorthEast();// quick prefilter by lat/lngconst vis = items.filter(pt => pt.lat >= sw.lat && pt.lat <= ne.lat && pt.lng >= sw.lng && pt.lng <= ne.lng);const src = vis.length ? vis : items;// grid sampling in pixel space using precomputed nx/nyconst cell = new Map();for (const pt of src){const px = pt.__nx * scale - origin.x;const py = pt.__ny * scale - origin.y;const gx = Math.floor((px*DPR) / CELL_PX);const gy = Math.floor((py*DPR) / CELL_PX);const key = gx + ':' + gy;let arr = cell.get(key);if (!arr){ arr = []; cell.set(key, arr); }if (arr.length < 1) arr.push({pt, x:px*DPR, y:py*DPR});}const list = [];for (const arr of cell.values()){for (const it of arr){list.push(it);if (list.length >= MAX_RENDER) break;}if (list.length >= MAX_RENDER) break;}displayList = list;}function draw(){const targetCtx = octx || ctx;const w = (octx ? off.width : canvas.width), h = (octx ? off.height : canvas.height);targetCtx.clearRect(0,0,w,h);targetCtx.save();targetCtx.lineWidth = LINEW;for (const it of displayList){targetCtx.beginPath();targetCtx.arc(it.x, it.y, RADIUS, 0, Math.PI*2);targetCtx.stroke();targetCtx.fill();}targetCtx.restore();if (octx){ctx.clearRect(0,0,canvas.width,canvas.height);ctx.drawImage(off, 0, 0);}}function scheduleDraw(){if (rafId) cancelAnimationFrame(rafId);rafId = requestAnimationFrame(function(){if (needRecompute){ computeDisplayList(); needRecompute=false; }draw();});}// Recompute only after interactions finish; draw during move for smoothnessMap.on('move', function(){ scheduleDraw(); });Map.on('zoom', function(){ scheduleDraw(); });Map.on('moveend zoomend', function(){ needRecompute=true; scheduleDraw(); });// initialneedRecompute = true;scheduleDraw();// --- CLICK HIT TEST ---const popup = L.popup();canvas.addEventListener('click', function(ev){const r = cont.getBoundingClientRect();const px = (ev.clientX - r.left) * DPR;const py = (ev.clientY - r.top) * DPR;let best = null, bestD = Infinity;const maxD = RADIUS + 4*DPR;for (const it of displayList){const dx = it.x - px, dy = it.y - py;const d = Math.hypot(dx,dy);if (d < bestD && d <= maxD){ bestD = d; best = it; }}if (best){const latlng = L.latLng(best.pt.lat, best.pt.lng);popup.setLatLng(latlng).setContent('<strong>'+htmlSafe(best.pt.name)+'</strong>').openOn(Map);window._selectedPickupPoint = best.pt.raw;const btn=document.getElementById('confirmPickupBtnModal'); if(btn) btn.disabled=false;}});// Fit to initial batchsetTimeout(function(){try {const latlngs = displayList.map(d=>[d.pt.lat,d.pt.lng]);if (latlngs.length) Map.fitBounds(latlngs, {padding:[20,20]});} catch(e){}}, 50);});});})();</script><style>/* Režim firma: skryj soukromou sekci bez ohledu na strukturu */.is-company #privateCustomerGroup,.is-company [data-role="private-customer"],.is-company .private-customer-section {display: none !important;}</style><script>// Robustní přepínač firma/soukromá – zaručí skrytí "Soukromá osoba" při zaškrtnutí firmy(function(){const root = document.getElementById('orderModal') || document.body;function setRequired(ids, on) {ids.forEach(id => {const el = document.getElementById(id);if (!el) return;if (on) el.setAttribute('required','');else el.removeAttribute('required');});}function findPrivateSection() {let sec = document.getElementById('privateCustomerGroup');if (sec) return sec;const heads = (root || document).querySelectorAll('h1,h2,h3,h4,h5,h6');for (const h of heads) {const t = (h.textContent || '').toLowerCase();if (t.includes('soukromá osoba') || t.includes('soukroma osoba') || t.includes('soukromá') || t.includes('soukroma')) {sec = h.closest('.group, .section, .card, .fieldset, .modal-section, form, div') || h.parentElement;if (sec) {sec.classList.add('private-customer-section');sec.setAttribute('data-role', 'private-customer');return sec;}}}return null;}function applyCompanyMode(on) {if (!root) return;root.classList.toggle('is-company', on);const priv = findPrivateSection();if (priv) priv.style.display = on ? 'none' : '';const companyBox = document.getElementById('companyFields');if (companyBox) companyBox.classList.toggle('open', on);// Uprav required (upravte ID dle potřeby)setRequired(['orderCompanyName','orderICO','orderContactEmail'], on);setRequired(['orderName','orderSurname','orderPhone','orderAddressStreet','orderAddressZip','orderAddressCity'], !on);}function handle() {const cb = document.getElementById('isCompany');applyCompanyMode(!!(cb && cb.checked));}window.handleCompanyToggle = handle;document.addEventListener('DOMContentLoaded', function(){const cb = document.getElementById('isCompany');if (cb) cb.addEventListener('change', handle);// synchronizace při otevření modalu (Bootstrap / vlastní overlay)const modal = document.getElementById('orderModal');if (modal) {modal.addEventListener('shown.bs.modal', handle);modal.addEventListener('show.bs.modal', handle);// i při manuálním přidání .open třídyconst mo = new MutationObserver(handle);mo.observe(modal, { attributes: true, attributeFilter: ['class','style'] });}handle();});})();</script><script>// Přesné skrytí pouze sekce Soukromá osoba (nezasáhne dopravu ani výdejní místa)(function(){const root = document.getElementById('orderModal') || document.body;// Vrátí nejmenší obal, který obsahuje hlavičku "Soukromá osoba" a zároveň// aspoň jedno z polí soukromé osoby (jméno/adresa...). Tím se vyhneme skrytí celé formy.function findPrivateSectionPrecise() {// Preferuj výslovné IDlet sec = document.getElementById('privateCustomerGroup');if (sec) return sec;const privateFieldSelector = ['#orderName','#orderSurname','#orderPhone','#orderAddressStreet','#orderAddressZip','#orderAddressCity'].join(',');const heads = (root || document).querySelectorAll('h1,h2,h3,h4,h5,h6');for (const h of heads) {const t = (h.textContent || '').toLowerCase();if (t.includes('soukromá osoba') || t.includes('soukroma osoba') || t.includes('soukromá') || t.includes('soukroma')) {// vystoupej nahoru po DOM a hledej nejmenší předka, který zároveň obsahuje alespoň jedno private polelet cand = h;while (cand && cand !== document.body) {if (cand.querySelector && cand.querySelector(privateFieldSelector)) {// máme minimální rozumný obal sekce soukromé osobycand.classList.add('private-customer-section');return cand;}cand = cand.parentElement;}// fallback – nejbližší vizuální blokconst fallback = h.closest('.group, .section, .card, .fieldset') || h.parentElement;if (fallback) {fallback.classList.add('private-customer-section');return fallback;}}}return null;}function setRequired(ids, on) {ids.forEach(id => {const el = document.getElementById(id);if (!el) return;if (on) el.setAttribute('required','');else el.removeAttribute('required');});}function applyCompanyModePrecise(on) {const priv = findPrivateSectionPrecise();if (priv) priv.style.display = on ? 'none' : '';const companyBox = document.getElementById('companyFields');if (companyBox) companyBox.classList.toggle('open', on);setRequired(['orderCompanyName','orderICO','orderContactEmail'], on);setRequired(['orderName','orderSurname','orderPhone','orderAddressStreet','orderAddressZip','orderAddressCity'], !on);}// přepiš global toggle, pokud existujewindow.handleCompanyToggle = function(){const cb = document.getElementById('isCompany');applyCompanyModePrecise(!!(cb && cb.checked));};document.addEventListener('DOMContentLoaded', function(){const cb = document.getElementById('isCompany');if (cb) cb.addEventListener('change', window.handleCompanyToggle);const modal = document.getElementById('orderModal');if (modal) {modal.addEventListener('shown.bs.modal', window.handleCompanyToggle);modal.addEventListener('show.bs.modal', window.handleCompanyToggle);}window.handleCompanyToggle();});})();</script><script>// Blokace dopravy na výdejní místo při nákupu na firmu(function(){const root = document.getElementById('orderModal') || document;// heuristika: rozpoznání "výdejní místo" u inputu nebo jeho labelufunction isPickupInput(input){if (!input) return false;const parts = ((input.value||'') + ' ' + (input.id||'')).toLowerCase();let label = null;if (input.labels && input.labels.length) label = input.labels[0];if (!label && input.id) label = root.querySelector('label[for="'+input.id+'"]');const txt = ((label && (label.textContent||'')) || '').toLowerCase();const all = parts + ' ' + txt;// WHITE-LIST: osobní vyzvednutí nesmí být blokovánoif (all.includes('osobní') || all.includes('osobni')) return false;// Hledáme explicitně výdejní místa dopravců (vyhneme se obecnému "pickup")const needles = ['výdej', 'vydej', 'zasilkovna', 'packeta', 'balikovna', 'parcelshop', 'pickup point', 'pickup-point'];return needles.some(n => all.indexOf(n) !== -1);}function getShippingRadios(){// hledej obecně všechny radio buttony v oblasti dopravy// priorita: wrapper s id/class obsahující 'shipping' nebo 'doprava'const wrappers = Array.from(root.querySelectorAll('#shippingOptions, .shipping, .doprava, [data-role="shipping"]'));let scope = wrappers.length ? wrappers : [root];const radios = [];scope.forEach(w => {radios.push(...w.querySelectorAll('input[type="radio"], input[type="checkbox"]'));});// fallback: pokud nic nenašli, vezmeme všechny rádia na stráncereturn radios.length ? radios : Array.from(root.querySelectorAll('input[type="radio"], input[type="checkbox"]'));}function hideRowFor(input, on){// najdi rozumný obal položky dopravy a skryj/odskryjlet row = input.closest('.form-check, .option, .row, .list-group-item, .radio, .checkbox, li, .shipping-item, .method') || input.parentElement;if (row){row.style.display = on ? 'none' : '';row.classList.toggle('hidden', on);// také pro select-like custom komponenty}input.disabled = on;if (on) input.checked = false;}function ensureValidSelection(){const radios = getShippingRadios();const allowed = radios.filter(r => !isPickupInput(r) && !r.disabled && r.offsetParent !== null);if (!allowed.length) return;const anyChecked = allowed.some(r => r.checked);if (!anyChecked){allowed[0].checked = true;try{allowed[0].dispatchEvent(new Event('change', {bubbles:true}));allowed[0].dispatchEvent(new Event('input', {bubbles:true}));}catch(e){}}}function applyShippingRules(){const isCompany = !!(document.getElementById('isCompany') && document.getElementById('isCompany').checked);const radios = getShippingRadios();radios.forEach(r => {const pickup = isPickupInput(r);hideRowFor(r, isCompany && pickup);});if (isCompany) ensureValidSelection();}// napojení na přepínač "Nakupuji na firmu"function handleCompanyToggleShipping(){applyShippingRules();}document.addEventListener('DOMContentLoaded', function(){const cb = document.getElementById('isCompany');if (cb) cb.addEventListener('change', handleCompanyToggleShipping);// při otevření modalu znovu aplikuj pravidlaconst modal = document.getElementById('orderModal');if (modal) {modal.addEventListener('shown.bs.modal', handleCompanyToggleShipping);modal.addEventListener('show.bs.modal', handleCompanyToggleShipping);}// první aplikaceapplyShippingRules();});})();</script><script>\//\ SAFE\ rename\ in\ shipping\ only:\ "Osobní\ odběr"\ \->\ "Osobní\ odběr\ na\ centrálním\ skladu"\\(function\(\)\{\\ \ const\ FROM_RX\ =\ /\(\^\|\b\)osobní\s\+odběr\(\b\|\$\)/i;\\ \ const\ REPLACED\ =\ 'Osobní\ odběr\ na\ centrálním\ skladu';\\\ \ function\ shippingScopes\(root\)\{\\ \ \ \ const\ scopes\ =\ Array\.from\(\(root\|\|document\)\.querySelectorAll\('\#shippingOptions,\ \.shipping,\ \.doprava,\ \[data\-role="shipping"\]'\)\);\\ \ \ \ return\ scopes\.length\ \?\ scopes\ :\ \[\(root\|\|document\)\];\\ \ \}\\\ \ function\ replaceTextNode\(node\)\{\\ \ \ \ const\ t\ =\ node\.nodeValue\ \|\|\ '';\\ \ \ \ if\ \(!FROM_RX\.test\(t\)\)\ return\ false;\\ \ \ \ const\ newT\ =\ t\.replace\(FROM_RX,\ REPLACED\);\\ \ \ \ if\ \(newT\ ===\ t\)\ return\ false;\\ \ \ \ node\.nodeValue\ =\ newT;\\ \ \ \ return\ true;\\ \ \}\\\ \ function\ replaceInElem\(el\)\{\\ \ \ \ let\ changed\ =\ false;\\ \ \ \ const\ walker\ =\ document\.createTreeWalker\(el,\ NodeFilter\.SHOW_TEXT,\ null\);\\ \ \ \ let\ n;\ \\ \ \ \ while\ \(\(n\ =\ walker\.nextNode\(\)\)\)\{\\ \ \ \ \ \ if\ \(replaceTextNode\(n\)\)\ changed\ =\ true;\\ \ \ \ \}\\ \ \ \ el\.querySelectorAll\('\[aria\-label\],\ \[title\]'\)\.forEach\(node=>\{\\ \ \ \ \ \ if\ \(node\.hasAttribute\('aria\-label'\)\)\{\\ \ \ \ \ \ \ \ const\ v\ =\ node\.getAttribute\('aria\-label'\);\\ \ \ \ \ \ \ \ if\ \(FROM_RX\.test\(v\)\)\ node\.setAttribute\('aria\-label',\ v\.replace\(FROM_RX,\ REPLACED\)\);\\ \ \ \ \ \ \}\\ \ \ \ \ \ if\ \(node\.hasAttribute\('title'\)\)\{\\ \ \ \ \ \ \ \ const\ v\ =\ node\.getAttribute\('title'\);\\ \ \ \ \ \ \ \ if\ \(FROM_RX\.test\(v\)\)\ node\.setAttribute\('title',\ v\.replace\(FROM_RX,\ REPLACED\)\);\\ \ \ \ \ \ \}\\ \ \ \ \}\);\\ \ \ \ return\ changed;\\ \ \}\\\ \ function\ applyOnce\(root\)\{\\ \ \ \ try\{\\ \ \ \ \ \ let\ any\ =\ false;\\ \ \ \ \ \ shippingScopes\(root\)\.forEach\(scope=>\{\\ \ \ \ \ \ \ \ scope\.querySelectorAll\('label,\ option,\ button,\ \.btn,\ \.form\-check\-label'\)\.forEach\(el=>\{\\ \ \ \ \ \ \ \ \ \ if\ \(replaceInElem\(el\)\)\ any\ =\ true;\\ \ \ \ \ \ \ \ \}\);\\ \ \ \ \ \ \}\);\\ \ \ \ \ \ return\ any;\\ \ \ \ \}catch\(e\)\{\\ \ \ \ \ \ console\.error\('Rename\ shipping\ label\ error:',\ e\);\\ \ \ \ \ \ return\ false;\\ \ \ \ \}\\ \ \}\\\ \ function\ observeUntilDone\(scope\)\{\\ \ \ \ let\ timer\ =\ null,\ tries\ =\ 0;\\ \ \ \ const\ mo\ =\ new\ MutationObserver\(\(\)=>\{\\ \ \ \ \ \ clearTimeout\(timer\);\\ \ \ \ \ \ timer\ =\ setTimeout\(\(\)=>\{\\ \ \ \ \ \ \ \ tries\+\+;\\ \ \ \ \ \ \ \ const\ changed\ =\ applyOnce\(scope\);\\ \ \ \ \ \ \ \ if\ \(changed\ \|\|\ tries\ >\ 10\)\{\\ \ \ \ \ \ \ \ \ \ mo\.disconnect\(\);\\ \ \ \ \ \ \ \ \}\\ \ \ \ \ \ \},\ 50\);\\ \ \ \ \}\);\\ \ \ \ mo\.observe\(scope,\ \{childList:true,\ subtree:true,\ characterData:true\}\);\\ \ \ \ applyOnce\(scope\);\\ \ \ \ setTimeout\(\(\)=>mo\.disconnect\(\),\ 5000\);\\ \ \}\\\ \ function\ init\(root\)\{\\ \ \ \ const\ scopes\ =\ shippingScopes\(root\);\\ \ \ \ scopes\.forEach\(sc=>observeUntilDone\(sc\)\);\\ \ \}\\\ \ document\.addEventListener\('DOMContentLoaded',\ \(\)=>init\(document\)\);\\ \ const\ modal\ =\ document\.getElementById\('orderModal'\);\\ \ if\ \(modal\)\{\\ \ \ \ modal\.addEventListener\('show\.bs\.modal',\ \(\)=>init\(modal\)\);\\ \ \ \ modal\.addEventListener\('shown\.bs\.modal',\ \(\)=>init\(modal\)\);\\ \ \}\\}\)\(\);\</script><style>/* Schovej běžné geolokační/„zaměření“ ovladače Leafletu */.leaflet-control-locate,.leaflet-control-geolocate,.leaflet-control-geolocation,.leaflet-geolocation-button,.leaflet-bar .leaflet-control-locate,.leaflet-bar .leaflet-control-geolocate {display: none !important;}/* fallback: skryj tlačítka s příslušným titulkem */button[title*="Zaměření"],button[title*="zaměření"],button[title*="Zameření"],button[title*="zamereni"],button[aria-label*="Zaměření"],button[aria-label*="zaměření"],button[aria-label*="Zameření"],button[aria-label*="zamereni"],.leaflet-control button[title*="Locate"],.leaflet-control button[aria-label*="Locate"] {display: none !important;}</style><script>// JS pojistka: po načtení i po otevření modalu skryj geolokační (zaměření) tlačítko(function(){function hideLocate(root){const sel = ['.leaflet-control-locate','.leaflet-control-geolocate','.leaflet-control-geolocation','.leaflet-geolocation-button','button[title*="Zaměření"]','button[title*="zaměření"]','button[title*="Zameření"]','button[title*="zamereni"]','button[aria-label*="Zaměření"]','button[aria-label*="zaměření"]','button[aria-label*="Zameření"]','button[aria-label*="zamereni"]','.leaflet-control button[title*="Locate"]','.leaflet-control button[aria-label*="Locate"]'].join(',');(root||document).querySelectorAll(sel).forEach(el=>{// schovej nejbližší ovladač (container), ať nezůstane prázdná mezeraconst ctrl = el.closest('.leaflet-control') || el.closest('.leaflet-bar') || el;ctrl.style.display = 'none';ctrl.classList.add('hidden');});}document.addEventListener('DOMContentLoaded', function(){hideLocate(document);const modal = document.getElementById('orderModal');if (modal){modal.addEventListener('show.bs.modal', ()=>hideLocate(modal));modal.addEventListener('shown.bs.modal', ()=>hideLocate(modal));}});})();</script><style>/* Schovat tlačítka pro objednání zaměření podle běžných tříd/id */#orderMeasurement, #orderSurvey, #btnZamereni,.btn-zamereni, .btnZamereni, .order-zamereni {display: none !important;}</style><script>// Skryj "Objednat zaměření" (tlačítko/odkaz) podle textu i atributů(function(){function hideByText(root){const candidates = (root||document).querySelectorAll('button, a, input[type="button"], input[type="submit"]');const needles = ['zaměření','zamereni'];candidates.forEach(el=>{// 1) input[value]if (el.tagName === 'INPUT'){const v = (el.value || '').toLowerCase();if (needles.some(n => v.includes(n))){ el.style.display='none'; el.classList.add('hidden'); }return;}// 2) button/anchor visible textconst t = (el.textContent || '').toLowerCase().trim();if (t && needles.some(n => t.includes(n))){el.style.display='none';el.classList.add('hidden');}});}document.addEventListener('DOMContentLoaded', function(){hideByText(document);// pokud se tlačítka vkládají dynamicky, sleduj kontejner kalkulátoruconst host = document.getElementById('calculator') || document.body;try{const mo = new MutationObserver(()=>hideByText(host));mo.observe(host, {childList:true, subtree:true});// automaticky odpoj po 5s (už budeme mít hotovo)setTimeout(()=>mo.disconnect(), 5000);}catch(e){}});})();</script><script>// === EMAIL ROUTING OVERRIDE ===// Pozastavit e-maily zákazníkovi (admin maily běží dál)window.DISABLE_CUSTOMER_EMAIL = true;// Globální no-op pro případné přímé voláníwindow.sendCustomerEmail = function(){try { console.info('Customer email suppressed'); } catch(e){}return Promise.resolve('suppressed');};</script><script>// Hide only the EmailJS template/failed-send alerts; keep other alerts intact.(function(){const _origAlert = window.alert;window.alert = function(msg){try{const s = (msg == null ? '' : String(msg)).toLowerCase();if (s.includes('nepodařilo se odeslat e-mail') || s.includes('template id not found') || s.includes('emailjs')){console.warn('Email alert suppressed:', msg);return;}}catch(e){}return _origAlert.apply(this, arguments);};})();</script><script>document.addEventListener('change', function(e){const shippingDelivery = document.getElementById('shipping_delivery');const same = document.getElementById('sameAsBilling');const block = document.getElementById('deliveryDateTime');if(!shippingDelivery || !same || !block) return;const addr = shippingDelivery.checked && !same.checked;block.classList.toggle('hidden', !addr);});</script><script>document.addEventListener("change", () => {const deliveryRadio = document.getElementById("shipping_delivery");const dateTimeBlock = document.getElementById("deliveryDateTime");if (!deliveryRadio || !dateTimeBlock) return;if (deliveryRadio.checked) {dateTimeBlock.classList.remove("hidden");} else {dateTimeBlock.classList.add("hidden");}});</script><script>document.addEventListener("DOMContentLoaded", function () {const select = document.getElementById("deliveryTime");if (!select) return;select.innerHTML = "";let start = 7 * 60;let end = 14 * 60;for (let min = start; min <= end; min += 30) {let h = String(Math.floor(min / 60)).padStart(2, "0");let m = String(min % 60).padStart(2, "0");let t = `${h}:${m}`;let opt = document.createElement("option");opt.value = t;opt.textContent = t;select.appendChild(opt);}});</script><script>// Omezit výběr datumu pouze na pracovní dnydocument.addEventListener("DOMContentLoaded", function () {const dateInput = document.getElementById("deliveryDate");if (!dateInput) return;function isWeekend(d) {const day = d.getDay();return day === 0 || day === 6;}const today = new Date();let minDate = today;if (isWeekend(minDate)) {while (isWeekend(minDate)) {minDate.setDate(minDate.getDate() + 1);}}dateInput.min = minDate.toISOString().split("T")[0];dateInput.addEventListener("change", function () {const chosen = new Date(this.value);if (isWeekend(chosen)) {while (isWeekend(chosen)) {chosen.setDate(chosen.getDate() + 1);}this.value = chosen.toISOString().split("T")[0];}});});</script>