{"id":12982,"date":"2026-07-16T16:26:49","date_gmt":"2026-07-16T14:26:49","guid":{"rendered":"https:\/\/modulina.eu\/fr\/free-estimate\/"},"modified":"2026-07-16T16:28:52","modified_gmt":"2026-07-16T14:28:52","slug":"free-estimate","status":"publish","type":"page","link":"https:\/\/modulina.eu\/fr\/free-estimate\/","title":{"rendered":"Devis gratuit"},"content":{"rendered":"\t\t<div data-elementor-type=\"wp-page\" data-elementor-id=\"12982\" class=\"elementor elementor-12982\" data-elementor-post-type=\"page\">\n\t\t\t\t<div class=\"elementor-element elementor-element-e4d6f0d e-flex e-con-boxed e-con e-parent\" data-id=\"e4d6f0d\" data-element_type=\"container\" data-e-type=\"container\" data-settings=\"{&quot;background_background&quot;:&quot;classic&quot;}\">\n\t\t\t\t\t<div class=\"e-con-inner\">\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-2dcc14e e-flex e-con-boxed e-con e-parent\" data-id=\"2dcc14e\" data-element_type=\"container\" data-e-type=\"container\" data-settings=\"{&quot;background_background&quot;:&quot;classic&quot;}\">\n\t\t\t\t\t<div class=\"e-con-inner\">\n\t\t\t\t<div class=\"elementor-element elementor-element-9f615f9 elementor-widget elementor-widget-html\" data-id=\"9f615f9\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<!-- ============================================================\n  Modulina intake form \u2014 Elementor HTML widget content.\n  Source of truth: www-multisite\/intake-form\/contact-intake-form.html\n  Contract: ai-first-modulina\/l1-skp-storage\/intake-spec.md (\u00a75, \u00a711)\n  WordPress serves this markup only. No PHP, no nonce, no secrets.\n  The browser talks directly to API_BASE (files.modulina.eu).\n============================================================= -->\n<link rel=\"stylesheet\" href=\"https:\/\/fonts.googleapis.com\/css2?family=Cabin:wght@400;500&display=swap\">\n<link rel=\"preconnect\" href=\"https:\/\/challenges.cloudflare.com\">\n\n<div class=\"contact-us-form mdl-intake\" id=\"mdl-intake\">\n\n  <div class=\"mdl-intro\">\n    <h3 class=\"mdl-intro-title\" id=\"mdl-intro-title\">Let&rsquo;s look at your project together<\/h3>\n    <p class=\"mdl-intro-text\" id=\"mdl-intro-text\">Every building is different, so we don&rsquo;t do off-the-shelf quotes. Our engineers personally review each project and work out how Modulina straw panels fit your design. Get in touch for a consultation or a free estimate &mdash; and drawings are very welcome: attach your IFC, DWG or PDF files below and we&rsquo;ll come back with a much more precise answer.<\/p>\n  <\/div>\n\n  <noscript>\n    <div class=\"mdl-nojs\">\n      <p>Our contact form needs JavaScript. You can reach us directly:<\/p>\n      <p class=\"mdl-nojs-contact\"><a href=\"mailto:info@modulina.eu\">info@modulina.eu<\/a> \u00b7 <a href=\"tel:+37069831898\">+370 698 31898<\/a><\/p>\n    <\/div>\n  <\/noscript>\n\n  <form id=\"mdl-form\" hidden novalidate autocomplete=\"on\">\n    <div class=\"mdl-fields\">\n\n      <div class=\"mdl-group\">\n        <select id=\"mdl-theme\" name=\"theme\" aria-label=\"Topic\" required>\n          <option value=\"\">Please choose a topic<\/option>\n          <option value=\"Free estimate\" selected>Free estimate<\/option>\n          <option value=\"Technical request\">Technical request<\/option>\n          <option value=\"Other\">Other<\/option>\n        <\/select>\n        <div class=\"mdl-field-error\" id=\"mdl-err-theme\" hidden><\/div>\n      <\/div>\n\n      <div class=\"mdl-group mdl-w50\">\n        <input type=\"text\" id=\"mdl-name\" name=\"name\" maxlength=\"100\"\n               placeholder=\"Name\" aria-label=\"Name\" autocomplete=\"name\">\n      <\/div>\n\n      <div class=\"mdl-group mdl-w50\">\n        <input type=\"tel\" id=\"mdl-phone\" name=\"phone\" maxlength=\"40\" required\n               placeholder=\"Phone number\" aria-label=\"Phone number\" autocomplete=\"tel\">\n        <div class=\"mdl-field-error\" id=\"mdl-err-phone\" hidden><\/div>\n      <\/div>\n\n      <div class=\"mdl-group\">\n        <input type=\"email\" id=\"mdl-email\" name=\"email\" maxlength=\"254\" required\n               placeholder=\"Email\" aria-label=\"Email\" autocomplete=\"email\">\n        <div class=\"mdl-field-error\" id=\"mdl-err-email\" hidden><\/div>\n      <\/div>\n\n      <div class=\"mdl-group\">\n        <textarea id=\"mdl-message\" name=\"message\" rows=\"10\" maxlength=\"5000\"\n                  placeholder=\"Message\" aria-label=\"Message\"><\/textarea>\n      <\/div>\n\n      <div class=\"mdl-group\">\n        <div class=\"mdl-upload\">\n          <label class=\"mdl-upload-btn\" for=\"mdl-files\">\n            <span id=\"mdl-upload-label\">Attach drawings (optional)<\/span>\n            <input type=\"file\" id=\"mdl-files\" multiple\n                   accept=\".dwg,.dxf,.dwf,.ifc,.ifczip,.skp,.rvt,.rfa,.step,.stp,.iges,.igs,.3dm,.obj,.stl,.pdf,.zip,.7z,.rar\">\n          <\/label>\n          <div class=\"mdl-upload-hint\" id=\"mdl-upload-hint\">Up to 5 files: ifc, dwg, dxf, skp, rvt, step, pdf, zip\u2026<\/div>\n          <ul class=\"mdl-file-list\" id=\"mdl-file-list\"><\/ul>\n        <\/div>\n      <\/div>\n\n      <!-- honeypot: must stay empty; sent as-is -->\n      <div class=\"mdl-hp-wrap\" aria-hidden=\"true\">\n        <input type=\"text\" id=\"mdl-hp\" name=\"hp\" value=\"\" tabindex=\"-1\" autocomplete=\"off\">\n      <\/div>\n\n      <div class=\"mdl-group\">\n        <label class=\"mdl-consent\">\n          <input type=\"checkbox\" id=\"mdl-consent\" required>\n          <span id=\"mdl-consent-text\">I agree that Modulina processes my data to answer this enquiry, as described in the <a href=\"\/privacy-policy\/\" target=\"_blank\" rel=\"noopener\" id=\"mdl-privacy-link\">privacy policy<\/a>.<\/span>\n        <\/label>\n        <div class=\"mdl-field-error\" id=\"mdl-err-consent\" hidden><\/div>\n      <\/div>\n\n      <div class=\"mdl-group\">\n        <div id=\"mdl-turnstile\"><\/div>\n      <\/div>\n\n      <div class=\"mdl-group\">\n        <button type=\"submit\" class=\"mdl-submit\" id=\"mdl-submit\">Send<\/button>\n      <\/div>\n\n      <div class=\"mdl-group\">\n        <div class=\"mdl-form-error\" id=\"mdl-form-error\" hidden><\/div>\n      <\/div>\n\n    <\/div>\n  <\/form>\n\n  <div class=\"mdl-success\" id=\"mdl-success\" hidden>\n    <p class=\"mdl-success-title\" id=\"mdl-success-title\"><\/p>\n    <p class=\"mdl-success-ref\" id=\"mdl-success-ref\"><\/p>\n  <\/div>\n<\/div>\n\n<style>\n.mdl-intake{font-family:\"Cabin\",sans-serif;color:#201D1D;}\n.mdl-intro{margin-bottom:28px;}\n.mdl-intro-title{font-family:\"Cabin\",sans-serif;font-size:26px;font-weight:500;color:#201D1D;margin:0 0 10px;}\n.mdl-intro-text{font-family:\"Cabin\",sans-serif;font-size:18px;line-height:1.55;color:#201D1D;margin:0;max-width:820px;}\n.mdl-fields{display:flex;flex-wrap:wrap;margin:0 -7px -14px;}\n.mdl-group{width:100%;padding:0 7px;margin-bottom:14px;box-sizing:border-box;}\n.mdl-w50{width:50%;}\n@media (max-width:767px){.mdl-w50{width:100%;}}\n.mdl-intake input[type=text],\n.mdl-intake input[type=tel],\n.mdl-intake input[type=email],\n.mdl-intake select,\n.mdl-intake textarea{\n  width:100%;box-sizing:border-box;display:block;\n  background-color:#ffffff;border:0;border-radius:0;\n  font-family:\"Cabin\",sans-serif;font-size:20px;font-weight:400;color:#201D1D;\n  min-height:59px;padding:7px 20px;outline:0;\n}\n.mdl-intake textarea{padding-top:25px;min-height:0;resize:vertical;}\n.mdl-intake ::placeholder{color:#666;opacity:1;}\n.mdl-intake select:invalid{color:#666;}\n.mdl-intake input:focus,.mdl-intake select:focus,.mdl-intake textarea:focus{box-shadow:0 0 0 1px #B2D235 inset;}\n.mdl-field-error{font-size:15px;color:#c0392b;margin-top:4px;}\n.mdl-form-error{font-size:16px;color:#c0392b;background:#fff;padding:12px 20px;}\n.mdl-form-error a{color:#201D1D;text-decoration:underline;font-weight:500;}\n\n.mdl-upload-btn{display:inline-block;cursor:pointer;background:#fff;border:1px dashed #9aa38f;\n  padding:14px 24px;font-size:18px;font-weight:500;color:#201D1D;}\n.mdl-upload-btn:hover{border-color:#B2D235;}\n.mdl-upload-btn input[type=file]{position:absolute;width:1px;height:1px;opacity:0;overflow:hidden;}\n.mdl-upload-hint{font-size:14px;color:#666;margin-top:6px;}\n.mdl-file-list{list-style:none;margin:10px 0 0;padding:0;}\n.mdl-file-item{background:#fff;padding:10px 16px;margin-bottom:8px;font-size:16px;}\n.mdl-file-row{display:flex;align-items:center;gap:10px;flex-wrap:wrap;}\n.mdl-file-name{flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}\n.mdl-file-size{color:#666;font-size:14px;flex:0 0 auto;}\n.mdl-file-status{font-size:14px;flex:0 0 auto;}\n.mdl-file-status.is-done{color:#7a9a1e;}\n.mdl-file-status.is-error{color:#c0392b;}\n.mdl-file-action{background:none;border:0;cursor:pointer;font-family:inherit;font-size:14px;\n  color:#201D1D;text-decoration:underline;padding:0;flex:0 0 auto;}\n.mdl-progress{height:4px;background:#e6e6e6;margin-top:8px;}\n.mdl-progress-bar{height:100%;width:0;background:#B2D235;transition:width .15s linear;}\n\n.mdl-hp-wrap{position:absolute;left:-9999px;top:auto;width:1px;height:1px;overflow:hidden;}\n\n.mdl-consent{display:flex;align-items:flex-start;gap:10px;font-size:16px;cursor:pointer;}\n.mdl-consent input{margin-top:3px;flex:0 0 auto;width:18px;height:18px;accent-color:#B2D235;}\n.mdl-consent a{color:#201D1D;text-decoration:underline;}\n\n.mdl-submit{background-color:#FFFFFF;color:#B2D235;border:0;border-radius:3px;\n  font-family:\"Cabin\",sans-serif;font-size:18px;font-weight:500;\n  padding:20px 40px;cursor:pointer;transition:color .2s;}\n.mdl-submit:hover{color:#CFCFCF;}\n.mdl-submit[disabled]{opacity:.6;cursor:default;}\n\n.mdl-success{background:#fff;padding:30px;font-size:20px;}\n.mdl-success-title{margin:0 0 8px;font-weight:500;}\n.mdl-success-ref{margin:0;font-size:16px;color:#666;}\n\n.mdl-nojs{font-size:20px;}\n.mdl-nojs-contact a{color:#201D1D;font-weight:500;}\n<\/style>\n\n<script>\n(function () {\n  'use strict';\n\n  \/* ===== Configuration \u2014 the ONLY lines that change at go-live ===== *\/\n  var API_BASE = 'https:\/\/files.modulina.eu';        \/* intake API origin *\/\n  var TURNSTILE_SITE_KEY = '0x4AAAAAAD2XvU6uz3T7Gtor'; \/* PRODUCTION modulina.eu\n        site key (public by design). DEV always-pass key: 1x00000000000000000000AA *\/\n  \/* ================================================================= *\/\n\n  var CONTACT_EMAIL = 'info@modulina.eu';\n  var MAX_FILES = 5;\n  var MAX_FILE_MB = 250; \/* client-side UX cap; the server is authoritative *\/\n  var ALLOWED_EXT = ['dwg','dxf','dwf','ifc','ifczip','skp','rvt','rfa','step','stp',\n                     'iges','igs','3dm','obj','stl','pdf','zip','7z','rar'];\n\n  \/* ---------- i18n ----------\n     consent text = consentBefore + <a>consentLink<\/a> + consentAfter *\/\n  var I18N = {\n    en: {\n      introTitle:'Let\u2019s look at your project together',\n      introText:'Every building is different, so we don\u2019t do off-the-shelf quotes. Our engineers personally review each project and work out how Modulina straw panels fit your design. Get in touch for a consultation or a free estimate \u2014 and drawings are very welcome: attach your IFC, DWG or PDF files below and we\u2019ll come back with a much more precise answer.',\n      name:'Name', phone:'Phone number', email:'Email',\n      theme:'Topic', message:'Message', send:'Send', sending:'Sending\u2026',\n      uploadingWait:'Uploading files\u2026',\n      themePlaceholder:'Please choose a topic',\n      themeOptions:{'Free estimate':'Free estimate',\n        'Technical request':'Technical request','Other':'Other'},\n      uploadLabel:'Attach drawings (optional)',\n      uploadHint:'Up to 5 files: ifc, dwg, dxf, skp, rvt, step, pdf, zip\u2026',\n      consentBefore:'I agree that Modulina processes my data to answer this enquiry, as described in the ',\n      consentLink:'privacy policy', consentAfter:'.',\n      required:'This field is required.', emailInvalid:'Please enter a valid email address.',\n      consentRequired:'Please confirm the privacy consent.',\n      fileTooMany:'Up to '+MAX_FILES+' files can be attached.',\n      fileBadType:'This file type is not accepted.',\n      fileTooLarge:'The file is too large (max '+MAX_FILE_MB+' MB).',\n      fileUploading:'Uploading\u2026', fileDone:'Attached \u2713', fileFailed:'Upload failed.',\n      retry:'Try again', remove:'Remove',\n      success:'Thank you! Your enquiry has been received.', reference:'Reference: {ref}',\n      mailtoLabel:'Send by email', filesNote:'Note: attachments could not be included; we will ask for them by reply.',\n      errNetwork:'Could not reach the server. Please try again.',\n      errCodes:{ invalid_request:'Please check the form fields and try again.',\n        bad_session:'The session expired. Please try again.',\n        origin_rejected:'Something went wrong. Please try again later.',\n        turnstile_failed:'Verification failed. Please complete the check and try again.',\n        ticket_not_found:'Upload failed.', ticket_consumed:'Upload failed.',\n        ticket_expired:'Upload timed out.', too_large:'The file is too large.',\n        type_rejected:'This file type is not accepted.',\n        scan_pending:'The file is still being checked. Please try again in a moment.',\n        scan_failed:'The file could not be attached.',\n        rate_limited:'Too many attempts. Please try again later.' }\n    },\n    lt: {\n      introTitle:'Pa\u017evelkime \u012f j\u016bs\u0173 projekt\u0105 kartu',\n      introText:'Kiekvienas pastatas skirtingas, tod\u0117l standartini\u0173 pasi\u016blym\u0173 neteikiame. M\u016bs\u0173 in\u017einieriai asmeni\u0161kai per\u017ei\u016bri kiekvien\u0105 projekt\u0105 ir \u012fvertina, kaip Modulina \u0161iaud\u0173 plok\u0161t\u0117s pritaikomos b\u016btent j\u016bs\u0173 sprendiniui. Kreipkit\u0117s konsultacijos arba nemokamos s\u0105matos \u2014 o br\u0117\u017einiai labai laukiami: prisekite IFC, DWG ar PDF failus \u017eemiau, ir atsakymas bus gerokai tikslesnis.',\n      name:'Vardas', phone:'Telefono numeris', email:'El. pa\u0161tas',\n      theme:'Tema', message:'\u017dinut\u0117', send:'Si\u0173sti', sending:'Siun\u010diama\u2026',\n      uploadingWait:'\u012ekeliami failai\u2026',\n      themePlaceholder:'Pasirinkite tem\u0105',\n      themeOptions:{'Free estimate':'Nemokamas \u012fvertinimas',\n        'Technical request':'Technin\u0117 u\u017eklausa','Other':'Kita'},\n      uploadLabel:'Prid\u0117ti br\u0117\u017einius (neb\u016btina)',\n      uploadHint:'Iki 5 fail\u0173: ifc, dwg, dxf, skp, rvt, step, pdf, zip\u2026',\n      consentBefore:'Sutinku, kad Modulina tvarkyt\u0173 mano duomenis atsakymui \u012f \u0161i\u0105 u\u017eklaus\u0105, kaip apra\u0161yta ',\n      consentLink:'privatumo politikoje', consentAfter:'.',\n      required:'\u0160is laukas privalomas.', emailInvalid:'\u012eveskite galiojant\u012f el. pa\u0161to adres\u0105.',\n      consentRequired:'Patvirtinkite sutikim\u0105 d\u0117l duomen\u0173 tvarkymo.',\n      fileTooMany:'Galima prid\u0117ti iki '+MAX_FILES+' fail\u0173.',\n      fileBadType:'\u0160is failo tipas nepriimamas.',\n      fileTooLarge:'Failas per didelis (maks. '+MAX_FILE_MB+' MB).',\n      fileUploading:'\u012ekeliama\u2026', fileDone:'\u012ekelta \u2713', fileFailed:'\u012ekelti nepavyko.',\n      retry:'Bandyti dar kart\u0105', remove:'Pa\u0161alinti',\n      success:'A\u010di\u016b! J\u016bs\u0173 u\u017eklausa gauta.', reference:'Numeris: {ref}',\n      mailtoLabel:'Si\u0173sti el. pa\u0161tu', filesNote:'Pastaba: pried\u0173 prid\u0117ti nepavyko; j\u0173 papra\u0161ysime atsakydami.',\n      errNetwork:'Nepavyko pasiekti serverio. Bandykite dar kart\u0105.',\n      errCodes:{ invalid_request:'Patikrinkite formos laukus ir bandykite dar kart\u0105.',\n        bad_session:'Sesija baig\u0117si. Bandykite dar kart\u0105.',\n        origin_rejected:'\u012evyko klaida. Bandykite v\u0117liau.',\n        turnstile_failed:'Patikra nepavyko. Pakartokite patikr\u0105 ir bandykite dar kart\u0105.',\n        ticket_not_found:'\u012ekelti nepavyko.', ticket_consumed:'\u012ekelti nepavyko.',\n        ticket_expired:'\u012ek\u0117limo laikas baig\u0117si.', too_large:'Failas per didelis.',\n        type_rejected:'\u0160is failo tipas nepriimamas.',\n        scan_pending:'Failas dar tikrinamas. Pabandykite po akimirkos.',\n        scan_failed:'Failo prid\u0117ti nepavyko.',\n        rate_limited:'Per daug bandym\u0173. Bandykite v\u0117liau.' }\n    },\n    sv: {\n      introTitle:'L\u00e5t oss titta p\u00e5 ditt projekt tillsammans',\n      introText:'Varje byggnad \u00e4r unik, s\u00e5 vi ger inga standardofferter. V\u00e5ra ingenj\u00f6rer g\u00e5r personligen igenom varje projekt och bed\u00f6mer hur Modulinas halmpaneler passar just din design. H\u00f6r av dig f\u00f6r en konsultation eller en kostnadsfri offert \u2014 ritningar \u00e4r mycket v\u00e4lkomna: bifoga dina IFC-, DWG- eller PDF-filer nedan s\u00e5 f\u00e5r du ett betydligt mer exakt svar.',\n      name:'Namn', phone:'Telefonnummer', email:'E-post',\n      theme:'\u00c4mne', message:'Meddelande', send:'Skicka', sending:'Skickar\u2026',\n      uploadingWait:'Laddar upp filer\u2026',\n      themePlaceholder:'V\u00e4lj \u00e4mne',\n      themeOptions:{'Free estimate':'Kostnadsfri offert',\n        'Technical request':'Teknisk f\u00f6rfr\u00e5gan','Other':'\u00d6vrigt'},\n      uploadLabel:'Bifoga ritningar (valfritt)',\n      uploadHint:'Upp till 5 filer: ifc, dwg, dxf, skp, rvt, step, pdf, zip\u2026',\n      consentBefore:'Jag godk\u00e4nner att Modulina behandlar mina uppgifter f\u00f6r att besvara denna f\u00f6rfr\u00e5gan, enligt ',\n      consentLink:'integritetspolicyn', consentAfter:'.',\n      required:'Detta f\u00e4lt \u00e4r obligatoriskt.', emailInvalid:'Ange en giltig e-postadress.',\n      consentRequired:'Bekr\u00e4fta samtycket till databehandling.',\n      fileTooMany:'H\u00f6gst '+MAX_FILES+' filer kan bifogas.',\n      fileBadType:'Filtypen accepteras inte.',\n      fileTooLarge:'Filen \u00e4r f\u00f6r stor (max '+MAX_FILE_MB+' MB).',\n      fileUploading:'Laddar upp\u2026', fileDone:'Bifogad \u2713', fileFailed:'Uppladdningen misslyckades.',\n      retry:'F\u00f6rs\u00f6k igen', remove:'Ta bort',\n      success:'Tack! Din f\u00f6rfr\u00e5gan har tagits emot.', reference:'Referens: {ref}',\n      mailtoLabel:'Skicka via e-post', filesNote:'Obs: bilagorna kunde inte inkluderas; vi ber om dem i v\u00e5rt svar.',\n      errNetwork:'Kunde inte n\u00e5 servern. F\u00f6rs\u00f6k igen.',\n      errCodes:{ invalid_request:'Kontrollera f\u00e4lten och f\u00f6rs\u00f6k igen.',\n        bad_session:'Sessionen har g\u00e5tt ut. F\u00f6rs\u00f6k igen.',\n        origin_rejected:'N\u00e5got gick fel. F\u00f6rs\u00f6k senare.',\n        turnstile_failed:'Verifieringen misslyckades. Slutf\u00f6r kontrollen och f\u00f6rs\u00f6k igen.',\n        ticket_not_found:'Uppladdningen misslyckades.', ticket_consumed:'Uppladdningen misslyckades.',\n        ticket_expired:'Uppladdningen tog f\u00f6r l\u00e5ng tid.', too_large:'Filen \u00e4r f\u00f6r stor.',\n        type_rejected:'Filtypen accepteras inte.',\n        scan_pending:'Filen kontrolleras fortfarande. F\u00f6rs\u00f6k strax igen.',\n        scan_failed:'Filen kunde inte bifogas.',\n        rate_limited:'F\u00f6r m\u00e5nga f\u00f6rs\u00f6k. F\u00f6rs\u00f6k senare.' }\n    },\n    pl: {\n      introTitle:'Przyjrzyjmy si\u0119 Twojemu projektowi razem',\n      introText:'Ka\u017cdy budynek jest inny, dlatego nie przygotowujemy szablonowych wycen. Nasi in\u017cynierowie osobi\u015bcie analizuj\u0105 ka\u017cdy projekt i oceniaj\u0105, jak panele s\u0142omiane Modulina pasuj\u0105 do Twojego rozwi\u0105zania. Skontaktuj si\u0119 po konsultacj\u0119 lub bezp\u0142atn\u0105 wycen\u0119 \u2014 rysunki s\u0105 bardzo mile widziane: za\u0142\u0105cz pliki IFC, DWG lub PDF poni\u017cej, a odpowied\u017a b\u0119dzie znacznie dok\u0142adniejsza.',\n      name:'Imi\u0119', phone:'Numer telefonu', email:'E-mail',\n      theme:'Temat', message:'Wiadomo\u015b\u0107', send:'Wy\u015blij', sending:'Wysy\u0142anie\u2026',\n      uploadingWait:'Przesy\u0142anie plik\u00f3w\u2026',\n      themePlaceholder:'Wybierz temat',\n      themeOptions:{'Free estimate':'Bezp\u0142atna wycena',\n        'Technical request':'Zapytanie techniczne','Other':'Inne'},\n      uploadLabel:'Za\u0142\u0105cz rysunki (opcjonalnie)',\n      uploadHint:'Do 5 plik\u00f3w: ifc, dwg, dxf, skp, rvt, step, pdf, zip\u2026',\n      consentBefore:'Zgadzam si\u0119, aby Modulina przetwarza\u0142a moje dane w celu odpowiedzi na to zapytanie, zgodnie z ',\n      consentLink:'polityk\u0105 prywatno\u015bci', consentAfter:'.',\n      required:'To pole jest wymagane.', emailInvalid:'Podaj prawid\u0142owy adres e-mail.',\n      consentRequired:'Potwierd\u017a zgod\u0119 na przetwarzanie danych.',\n      fileTooMany:'Mo\u017cna za\u0142\u0105czy\u0107 maksymalnie '+MAX_FILES+' plik\u00f3w.',\n      fileBadType:'Ten typ pliku nie jest akceptowany.',\n      fileTooLarge:'Plik jest za du\u017cy (maks. '+MAX_FILE_MB+' MB).',\n      fileUploading:'Przesy\u0142anie\u2026', fileDone:'Za\u0142\u0105czono \u2713', fileFailed:'Przesy\u0142anie nie powiod\u0142o si\u0119.',\n      retry:'Spr\u00f3buj ponownie', remove:'Usu\u0144',\n      success:'Dzi\u0119kujemy! Twoje zapytanie zosta\u0142o przyj\u0119te.', reference:'Numer: {ref}',\n      mailtoLabel:'Wy\u015blij e-mailem', filesNote:'Uwaga: za\u0142\u0105cznik\u00f3w nie uda\u0142o si\u0119 do\u0142\u0105czy\u0107; poprosimy o nie w odpowiedzi.',\n      errNetwork:'Nie mo\u017cna po\u0142\u0105czy\u0107 si\u0119 z serwerem. Spr\u00f3buj ponownie.',\n      errCodes:{ invalid_request:'Sprawd\u017a pola formularza i spr\u00f3buj ponownie.',\n        bad_session:'Sesja wygas\u0142a. Spr\u00f3buj ponownie.',\n        origin_rejected:'Co\u015b posz\u0142o nie tak. Spr\u00f3buj p\u00f3\u017aniej.',\n        turnstile_failed:'Weryfikacja nie powiod\u0142a si\u0119. Uko\u0144cz weryfikacj\u0119 i spr\u00f3buj ponownie.',\n        ticket_not_found:'Przesy\u0142anie nie powiod\u0142o si\u0119.', ticket_consumed:'Przesy\u0142anie nie powiod\u0142o si\u0119.',\n        ticket_expired:'Przekroczono czas przesy\u0142ania.', too_large:'Plik jest za du\u017cy.',\n        type_rejected:'Ten typ pliku nie jest akceptowany.',\n        scan_pending:'Plik jest jeszcze sprawdzany. Spr\u00f3buj za chwil\u0119.',\n        scan_failed:'Nie uda\u0142o si\u0119 za\u0142\u0105czy\u0107 pliku.',\n        rate_limited:'Zbyt wiele pr\u00f3b. Spr\u00f3buj p\u00f3\u017aniej.' }\n    },\n    fr: {\n      introTitle:'Regardons votre projet ensemble',\n      introText:'Chaque b\u00e2timent est unique : nous ne faisons pas de devis standardis\u00e9s. Nos ing\u00e9nieurs examinent personnellement chaque projet et \u00e9tudient comment les panneaux de paille Modulina s\u2019adaptent \u00e0 votre conception. Contactez-nous pour une consultation ou un devis gratuit \u2014 vos plans sont les bienvenus : joignez vos fichiers IFC, DWG ou PDF ci-dessous et vous recevrez une r\u00e9ponse bien plus pr\u00e9cise.',\n      name:'Nom', phone:'Num\u00e9ro de t\u00e9l\u00e9phone', email:'E-mail',\n      theme:'Sujet', message:'Message', send:'Envoyer', sending:'Envoi\u2026',\n      uploadingWait:'T\u00e9l\u00e9versement des fichiers\u2026',\n      themePlaceholder:'Choisissez un sujet',\n      themeOptions:{'Free estimate':'Devis gratuit',\n        'Technical request':'Demande technique','Other':'Autre'},\n      uploadLabel:'Joindre des plans (facultatif)',\n      uploadHint:'Jusqu\u2019\u00e0 5 fichiers : ifc, dwg, dxf, skp, rvt, step, pdf, zip\u2026',\n      consentBefore:'J\u2019accepte que Modulina traite mes donn\u00e9es pour r\u00e9pondre \u00e0 cette demande, conform\u00e9ment \u00e0 la ',\n      consentLink:'politique de confidentialit\u00e9', consentAfter:'.',\n      required:'Ce champ est obligatoire.', emailInvalid:'Veuillez saisir une adresse e-mail valide.',\n      consentRequired:'Veuillez confirmer le consentement.',\n      fileTooMany:'Vous pouvez joindre au maximum '+MAX_FILES+' fichiers.',\n      fileBadType:'Ce type de fichier n\u2019est pas accept\u00e9.',\n      fileTooLarge:'Le fichier est trop volumineux (max '+MAX_FILE_MB+' Mo).',\n      fileUploading:'T\u00e9l\u00e9versement\u2026', fileDone:'Joint \u2713', fileFailed:'\u00c9chec du t\u00e9l\u00e9versement.',\n      retry:'R\u00e9essayer', remove:'Supprimer',\n      success:'Merci ! Votre demande a bien \u00e9t\u00e9 re\u00e7ue.', reference:'R\u00e9f\u00e9rence : {ref}',\n      mailtoLabel:'Envoyer par e-mail', filesNote:'Remarque : les pi\u00e8ces jointes n\u2019ont pas pu \u00eatre incluses ; nous vous les demanderons par retour.',\n      errNetwork:'Impossible de joindre le serveur. Veuillez r\u00e9essayer.',\n      errCodes:{ invalid_request:'Veuillez v\u00e9rifier les champs du formulaire et r\u00e9essayer.',\n        bad_session:'La session a expir\u00e9. Veuillez r\u00e9essayer.',\n        origin_rejected:'Une erreur est survenue. Veuillez r\u00e9essayer plus tard.',\n        turnstile_failed:'La v\u00e9rification a \u00e9chou\u00e9. Compl\u00e9tez le contr\u00f4le et r\u00e9essayez.',\n        ticket_not_found:'\u00c9chec du t\u00e9l\u00e9versement.', ticket_consumed:'\u00c9chec du t\u00e9l\u00e9versement.',\n        ticket_expired:'D\u00e9lai de t\u00e9l\u00e9versement d\u00e9pass\u00e9.', too_large:'Le fichier est trop volumineux.',\n        type_rejected:'Ce type de fichier n\u2019est pas accept\u00e9.',\n        scan_pending:'Le fichier est encore en cours de v\u00e9rification. R\u00e9essayez dans un instant.',\n        scan_failed:'Le fichier n\u2019a pas pu \u00eatre joint.',\n        rate_limited:'Trop de tentatives. Veuillez r\u00e9essayer plus tard.' }\n    }\n  };\n\n  var htmlLang = (document.documentElement.lang || 'en').slice(0, 2).toLowerCase();\n  var T = I18N[htmlLang] || I18N.en;\n  var LOCALE = { en:'en_US', lt:'lt_LT', sv:'sv_SE', pl:'pl_PL', fr:'fr_FR' }[htmlLang] || 'en_US';\n  \/* \/fr\/ is path-based on the .eu origin *\/\n  if (location.pathname.indexOf('\/fr\/') === 0) { T = I18N.fr; LOCALE = 'fr_FR'; }\n\n  \/* ---------- DOM ---------- *\/\n  function $(id) { return document.getElementById(id); }\n  function clearEl(el) { while (el.firstChild) el.removeChild(el.firstChild); }\n  var form = $('mdl-form'), submitBtn = $('mdl-submit'), fileInput = $('mdl-files'),\n      fileListEl = $('mdl-file-list'), formErrorEl = $('mdl-form-error');\n  if (!form) return;\n\n  \/* apply translations *\/\n  var privacyLink = $('mdl-privacy-link');\n  var privacyHref = privacyLink ? privacyLink.getAttribute('href') : '\/privacy-policy\/';\n  \/* path-based FR lives under \/fr\/, so its privacy page is \/fr\/privacy-policy\/ *\/\n  if (location.pathname.indexOf('\/fr\/') === 0) privacyHref = '\/fr\/privacy-policy\/';\n  $('mdl-intro-title').textContent = T.introTitle;\n  $('mdl-intro-text').textContent = T.introText;\n  $('mdl-name').placeholder = T.name; $('mdl-phone').placeholder = T.phone;\n  $('mdl-email').placeholder = T.email;\n  $('mdl-message').placeholder = T.message;\n  var themeSel = $('mdl-theme');\n  themeSel.setAttribute('aria-label', T.theme);\n  themeSel.options[0].text = T.themePlaceholder;\n  for (var i = 1; i < themeSel.options.length; i++) {\n    var v = themeSel.options[i].value;\n    if (T.themeOptions[v]) themeSel.options[i].text = T.themeOptions[v];\n  }\n  $('mdl-upload-label').textContent = T.uploadLabel;\n  $('mdl-upload-hint').textContent = T.uploadHint;\n  (function localizeConsent() {\n    var span = $('mdl-consent-text');\n    clearEl(span);\n    span.appendChild(document.createTextNode(T.consentBefore));\n    var a = document.createElement('a');\n    a.href = privacyHref; a.target = '_blank'; a.rel = 'noopener';\n    a.id = 'mdl-privacy-link'; a.textContent = T.consentLink;\n    span.appendChild(a);\n    span.appendChild(document.createTextNode(T.consentAfter));\n  })();\n  submitBtn.textContent = T.send;\n\n  form.hidden = false; \/* JS is running \u2014 reveal the form *\/\n\n  \/* ---------- Turnstile ---------- *\/\n  var tsWidgetId = null, tsToken = '', tsWaiters = [];\n\n  window.mdlTurnstileReady = function () {\n    tsWidgetId = window.turnstile.render('#mdl-turnstile', {\n      sitekey: TURNSTILE_SITE_KEY,\n      callback: function (token) {\n        tsToken = token;\n        var w = tsWaiters; tsWaiters = [];\n        w.forEach(function (fn) { fn(token); });\n      },\n      'expired-callback': function () { tsToken = ''; },\n      'error-callback': function () { tsToken = ''; }\n    });\n  };\n\n  function getTurnstileToken(forceFresh) {\n    if (tsToken && !forceFresh) return Promise.resolve(tsToken);\n    return new Promise(function (resolve, reject) {\n      tsWaiters.push(resolve);\n      try {\n        if (window.turnstile && tsWidgetId !== null) window.turnstile.reset(tsWidgetId);\n      } catch (e) {}\n      setTimeout(function () {\n        var idx = tsWaiters.indexOf(resolve);\n        if (idx !== -1) { tsWaiters.splice(idx, 1); reject(mkErr('turnstile_failed', 0)); }\n      }, 30000);\n    });\n  }\n\n  \/* ---------- API helpers ---------- *\/\n  function mkErr(code, status, message) {\n    return { code: code || 'network', status: status || 0, message: message || '' };\n  }\n\n  function apiPost(path, body, sessionToken) {\n    var headers = { 'Content-Type': 'application\/json' };\n    if (sessionToken) headers['Authorization'] = 'Bearer ' + sessionToken;\n    return fetch(API_BASE + path, {\n      method: 'POST', headers: headers, body: JSON.stringify(body)\n    }).then(function (resp) {\n      return resp.json().catch(function () { return {}; }).then(function (data) {\n        if (!resp.ok) throw mkErr(data.code, resp.status, data.message);\n        return data;\n      });\n    }, function () { throw mkErr('network', 0); });\n  }\n\n  function errText(err) {\n    return (err && err.code && T.errCodes[err.code]) || T.errNetwork;\n  }\n\n  \/* ---------- Session (capability token) ---------- *\/\n  var session = null, sessionExp = 0, sessionPromise = null;\n\n  function ensureSession(forceNew) {\n    if (!forceNew && session && Date.now() < sessionExp - 60000) return Promise.resolve(session);\n    if (!forceNew && sessionPromise) return sessionPromise;\n    session = null;\n    sessionPromise = getTurnstileToken(forceNew)\n      .then(function (token) {\n        tsToken = ''; \/* single-verify: token is consumed by \/v1\/session *\/\n        return apiPost('\/v1\/session', { turnstile_token: token });\n      })\n      .then(function (r) {\n        session = r.session_token;\n        sessionExp = Date.parse(r.expires_at) || (Date.now() + 25 * 60000);\n        sessionPromise = null;\n        try { if (window.turnstile && tsWidgetId !== null) window.turnstile.reset(tsWidgetId); } catch (e) {}\n        return session;\n      })\n      .catch(function (err) {\n        sessionPromise = null;\n        if (err.code === 'turnstile_failed' && !forceNew) return ensureSession(true); \/* one transparent retry *\/\n        throw err;\n      });\n    return sessionPromise;\n  }\n\n  \/* ---------- Files ---------- *\/\n  var files = []; \/* { id, file, status: pending|uploading|done|error|removed, file_id, pct, errMsg, promise } *\/\n  var fileSeq = 0;\n\n  function fmtSize(bytes) {\n    if (bytes >= 1048576) return (bytes \/ 1048576).toFixed(1) + ' MB';\n    if (bytes >= 1024) return Math.round(bytes \/ 1024) + ' KB';\n    return bytes + ' B';\n  }\n\n  function extOf(name) {\n    var m = String(name || '').match(\/\\.([a-z0-9]+)$\/i);\n    return m ? m[1].toLowerCase() : '';\n  }\n\n  fileInput.addEventListener('change', function () {\n    var chosen = Array.prototype.slice.call(fileInput.files || []);\n    fileInput.value = '';\n    chosen.forEach(function (f) {\n      var active = files.filter(function (x) { return x.status !== 'removed'; });\n      if (active.length >= MAX_FILES) { showFormError(T.fileTooMany); return; }\n      var entry = { id: 'f' + (++fileSeq), file: f, status: 'pending', file_id: null, pct: 0, errMsg: '' };\n      if (ALLOWED_EXT.indexOf(extOf(f.name)) === -1) {\n        entry.status = 'error'; entry.errMsg = T.fileBadType;\n      } else if (f.size > MAX_FILE_MB * 1048576) {\n        entry.status = 'error'; entry.errMsg = T.fileTooLarge;\n      }\n      files.push(entry);\n      renderFile(entry);\n      if (entry.status === 'pending') startUpload(entry);\n    });\n  });\n\n  function renderFile(entry) {\n    var li = document.getElementById('mdl-fi-' + entry.id);\n    if (entry.status === 'removed') { if (li) li.parentNode.removeChild(li); return; }\n    if (!li) {\n      li = document.createElement('li');\n      li.className = 'mdl-file-item'; li.id = 'mdl-fi-' + entry.id;\n      fileListEl.appendChild(li);\n    }\n    clearEl(li);\n    var row = document.createElement('div'); row.className = 'mdl-file-row';\n    var name = document.createElement('span'); name.className = 'mdl-file-name';\n    name.textContent = entry.file.name; row.appendChild(name);\n    var size = document.createElement('span'); size.className = 'mdl-file-size';\n    size.textContent = fmtSize(entry.file.size); row.appendChild(size);\n    var status = document.createElement('span'); status.className = 'mdl-file-status';\n    if (entry.status === 'uploading') status.textContent = T.fileUploading + ' ' + entry.pct + '%';\n    else if (entry.status === 'done') { status.textContent = T.fileDone; status.className += ' is-done'; }\n    else if (entry.status === 'error') { status.textContent = entry.errMsg || T.fileFailed; status.className += ' is-error'; }\n    row.appendChild(status);\n    if (entry.status === 'error' && ALLOWED_EXT.indexOf(extOf(entry.file.name)) !== -1\n        && entry.file.size <= MAX_FILE_MB * 1048576) {\n      var retryBtn = document.createElement('button');\n      retryBtn.type = 'button'; retryBtn.className = 'mdl-file-action'; retryBtn.textContent = T.retry;\n      retryBtn.onclick = function () { startUpload(entry); };\n      row.appendChild(retryBtn);\n    }\n    var rmBtn = document.createElement('button');\n    rmBtn.type = 'button'; rmBtn.className = 'mdl-file-action'; rmBtn.textContent = T.remove;\n    rmBtn.onclick = function () { entry.status = 'removed'; renderFile(entry); };\n    row.appendChild(rmBtn);\n    li.appendChild(row);\n    if (entry.status === 'uploading') {\n      var prog = document.createElement('div'); prog.className = 'mdl-progress';\n      var bar = document.createElement('div'); bar.className = 'mdl-progress-bar';\n      bar.style.width = entry.pct + '%'; prog.appendChild(bar); li.appendChild(prog);\n    }\n  }\n\n  function putFile(entry, uploadUrl) {\n    return new Promise(function (resolve, reject) {\n      var xhr = new XMLHttpRequest();\n      xhr.open('PUT', uploadUrl, true);\n      xhr.setRequestHeader('Content-Type', 'application\/octet-stream');\n      xhr.upload.onprogress = function (e) {\n        if (e.lengthComputable) {\n          entry.pct = Math.min(99, Math.round(e.loaded \/ e.total * 100));\n          renderFile(entry);\n        }\n      };\n      xhr.onload = function () {\n        var data = {};\n        try { data = JSON.parse(xhr.responseText || '{}'); } catch (e) {}\n        if (xhr.status >= 200 && xhr.status < 300) resolve(data);\n        else reject(mkErr(data.code, xhr.status, data.message));\n      };\n      xhr.onerror = function () { reject(mkErr('network', 0)); };\n      xhr.onabort = function () { reject(mkErr('network', 0)); };\n      xhr.send(entry.file);\n    });\n  }\n\n  function startUpload(entry) {\n    entry.status = 'uploading'; entry.pct = 0; entry.errMsg = ''; entry.file_id = null;\n    renderFile(entry);\n    entry.promise = attemptUpload(entry, false)\n      .then(function (res) {\n        if (entry.status === 'removed') return;\n        entry.file_id = res.file_id; entry.status = 'done'; entry.pct = 100;\n        renderFile(entry);\n      })\n      .catch(function (err) {\n        if (entry.status === 'removed') return;\n        entry.status = 'error'; entry.errMsg = errText(err);\n        renderFile(entry); \/* per draft \u00a79: upload error never blocks submit *\/\n      });\n    return entry.promise;\n  }\n\n  function attemptUpload(entry, retried) {\n    return ensureSession()\n      .then(function (s) {\n        return apiPost('\/v1\/tickets', {\n          filename: entry.file.name,\n          size: entry.file.size,\n          mime: entry.file.type || 'application\/octet-stream'\n        }, s);\n      })\n      .then(function (t) { return putFile(entry, t.upload_url); })\n      .catch(function (err) {\n        \/* one transparent retry: expired session or expired ticket *\/\n        if (!retried && (err.code === 'bad_session' || err.code === 'ticket_expired')) {\n          if (err.code === 'bad_session') { session = null; }\n          return attemptUpload(entry, true);\n        }\n        throw err;\n      });\n  }\n\n  \/* ---------- Validation ---------- *\/\n  function setFieldError(id, msg) {\n    var el = $(id);\n    if (msg) { el.textContent = msg; el.hidden = false; } else { el.hidden = true; }\n  }\n\n  function validate() {\n    var ok = true;\n    var email = $('mdl-email').value.trim();\n    var phone = $('mdl-phone').value.trim();\n    if (!themeSel.value) { setFieldError('mdl-err-theme', T.required); ok = false; }\n    else setFieldError('mdl-err-theme', '');\n    if (!phone) { setFieldError('mdl-err-phone', T.required); ok = false; }\n    else setFieldError('mdl-err-phone', '');\n    if (!email) { setFieldError('mdl-err-email', T.required); ok = false; }\n    else if (!\/^[^\\s@]+@[^\\s@]+\\.[^\\s@]{2,}$\/.test(email)) { setFieldError('mdl-err-email', T.emailInvalid); ok = false; }\n    else setFieldError('mdl-err-email', '');\n    if (!$('mdl-consent').checked) { setFieldError('mdl-err-consent', T.consentRequired); ok = false; }\n    else setFieldError('mdl-err-consent', '');\n    return ok;\n  }\n\n  function showFormError(msg, withMailto) {\n    clearEl(formErrorEl);\n    var p = document.createElement('span');\n    p.textContent = msg + ' ';\n    formErrorEl.appendChild(p);\n    if (withMailto) {\n      var a = document.createElement('a');\n      a.href = buildMailto(); a.textContent = T.mailtoLabel;\n      formErrorEl.appendChild(a);\n    }\n    formErrorEl.hidden = false;\n    scrollToStable(formErrorEl, 'center'); \/* form stays visible here, no collapse *\/\n  }\n\n  function clearFormError() { formErrorEl.hidden = true; }\n\n  \/* Scroll to a stable anchor in one frame. On success we call this BEFORE\n     hiding the tall form: scrolling while the layout is still settled avoids\n     the trap where an animated scroll (the page sets scroll-behavior:smooth)\n     lands on the wrong offset because the form collapse + lazy-loaded map\n     reflow the page mid-animation. We bypass smooth for an instant commit and\n     target the widget top, whose position depends only on the (already loaded)\n     content above it \u2014 so no header-height magic number and it holds on every\n     screen size. *\/\n  function scrollToStable(el, block) {\n    if (!el) return;\n    var root = document.documentElement, prev = root.style.scrollBehavior;\n    root.style.scrollBehavior = 'auto';\n    el.scrollIntoView({ block: block || 'start' });\n    root.style.scrollBehavior = prev;\n  }\n\n  function buildMailto() {\n    var themeVal = themeSel.value;\n    var subject = 'Enquiry from ' + location.hostname + (themeVal ? ' \u2014 ' + themeVal : '');\n    var lines = [];\n    if ($('mdl-name').value.trim()) lines.push(T.name + ': ' + $('mdl-name').value.trim());\n    lines.push(T.phone + ': ' + $('mdl-phone').value.trim());\n    lines.push(T.email + ': ' + $('mdl-email').value.trim());\n    if (themeVal) lines.push(T.theme + ': ' + themeVal);\n    if ($('mdl-message').value.trim()) lines.push('', $('mdl-message').value.trim());\n    var hasFiles = files.some(function (f) { return f.status !== 'removed'; });\n    if (hasFiles) lines.push('', T.filesNote);\n    return 'mailto:' + CONTACT_EMAIL +\n      '?subject=' + encodeURIComponent(subject) +\n      '&body=' + encodeURIComponent(lines.join('\\n'));\n  }\n\n  \/* ---------- Submit ---------- *\/\n  var submitting = false;\n\n  form.addEventListener('submit', function (ev) {\n    ev.preventDefault();\n    if (submitting) return;\n    clearFormError();\n    if (!validate()) return;\n    submitting = true;\n    submitBtn.disabled = true;\n\n    var inflight = files\n      .filter(function (f) { return f.status === 'uploading' && f.promise; })\n      .map(function (f) { return f.promise; });\n    if (inflight.length) submitBtn.textContent = T.uploadingWait;\n\n    Promise.all(inflight.map(function (p) { return p.catch(function () {}); }))\n      .then(function () {\n        submitBtn.textContent = T.sending;\n        return sendSubmission(false);\n      })\n      .then(function (r) {\n        scrollToStable($('mdl-intake'), 'start'); \/* scroll while form is still laid out... *\/\n        form.hidden = true;                       \/* ...then collapse below the fold *\/\n        $('mdl-success-title').textContent = T.success;\n        $('mdl-success-ref').textContent = r && r.reference ? T.reference.replace('{ref}', r.reference) : '';\n        $('mdl-success').hidden = false;\n      })\n      .catch(function (err) {\n        \/* entered data is preserved; offer the mailto fallback *\/\n        showFormError(errText(err), true);\n      })\n      .then(function () {\n        submitting = false;\n        submitBtn.disabled = false;\n        submitBtn.textContent = T.send;\n      });\n  });\n\n  function sendSubmission(retried) {\n    return ensureSession(retried)\n      .then(function (s) {\n        var extra = {};\n        if (themeSel.value) extra.theme = themeSel.value;\n        var body = {\n          email: $('mdl-email').value.trim(),\n          phone: $('mdl-phone').value.trim(),\n          name: $('mdl-name').value.trim(),\n          message: $('mdl-message').value.trim(),\n          consent: $('mdl-consent').checked,\n          file_ids: files.filter(function (f) { return f.status === 'done' && f.file_id; })\n                         .map(function (f) { return f.file_id; }),\n          hp: $('mdl-hp').value,\n          locale: LOCALE\n        };\n        if (Object.keys(extra).length) body.extra = extra;\n        return apiPost('\/v1\/submissions', body, s);\n      })\n      .catch(function (err) {\n        if (!retried && err.code === 'bad_session') { session = null; return sendSubmission(true); }\n        throw err;\n      });\n  }\n})();\n<\/script>\n<script src=\"https:\/\/challenges.cloudflare.com\/turnstile\/v0\/api.js?onload=mdlTurnstileReady&render=explicit\" async defer><\/script>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-cdf5ec6 e-con-full e-flex e-con e-parent\" data-id=\"cdf5ec6\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t<div class=\"elementor-element elementor-element-24de102 elementor-widget elementor-widget-google_maps\" data-id=\"24de102\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"google_maps.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<div class=\"elementor-custom-embed\">\n\t\t\t<iframe loading=\"lazy\"\n\t\t\t\t\tsrc=\"https:\/\/maps.google.com\/maps?q=Klaip%C4%97dos%20Universiteto%20verslo%20inkubatorius&#038;t=m&#038;z=18&#038;output=embed&#038;iwloc=near\"\n\t\t\t\t\ttitle=\"Klaip\u0117dos Universiteto verslo inkubatorius\"\n\t\t\t\t\taria-label=\"Klaip\u0117dos Universiteto verslo inkubatorius\"\n\t\t\t><\/iframe>\n\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t","protected":false},"excerpt":{"rendered":"","protected":false},"author":0,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"elementor_header_footer","meta":{"_acf_changed":false,"footnotes":""},"class_list":["post-12982","page","type-page","status-publish","hentry"],"acf":[],"_links":{"self":[{"href":"https:\/\/modulina.eu\/fr\/wp-json\/wp\/v2\/pages\/12982","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/modulina.eu\/fr\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/modulina.eu\/fr\/wp-json\/wp\/v2\/types\/page"}],"replies":[{"embeddable":true,"href":"https:\/\/modulina.eu\/fr\/wp-json\/wp\/v2\/comments?post=12982"}],"version-history":[{"count":1,"href":"https:\/\/modulina.eu\/fr\/wp-json\/wp\/v2\/pages\/12982\/revisions"}],"predecessor-version":[{"id":12983,"href":"https:\/\/modulina.eu\/fr\/wp-json\/wp\/v2\/pages\/12982\/revisions\/12983"}],"wp:attachment":[{"href":"https:\/\/modulina.eu\/fr\/wp-json\/wp\/v2\/media?parent=12982"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}