{"id":2405,"date":"2021-11-29T15:57:59","date_gmt":"2021-11-29T13:57:59","guid":{"rendered":"https:\/\/www.nettipuhelinkauppa.fi\/?page_id=2405"},"modified":"2022-12-21T16:09:50","modified_gmt":"2022-12-21T14:09:50","slug":"3cx-puhelinkeskukset","status":"publish","type":"page","link":"https:\/\/www.perustele.fi\/index.php\/3cx-puhelinkeskukset\/","title":{"rendered":"3CX-PUHELINKESKUKSET"},"content":{"rendered":"<p><img loading=\"lazy\" decoding=\"async\" class=\"alignleft size-medium wp-image-2609\" src=\"https:\/\/www.perustele.fi\/wp-content\/uploads\/2022\/02\/all_communications_slider-1-300x184.webp\" alt=\"\" width=\"300\" height=\"184\" srcset=\"https:\/\/www.perustele.fi\/wp-content\/uploads\/2022\/02\/all_communications_slider-1-300x184.webp 300w, https:\/\/www.perustele.fi\/wp-content\/uploads\/2022\/02\/all_communications_slider-1.webp 391w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/>3CX tarjoaa taitavasti suunnitellun VoIP puhelinj\u00e4rjestelm\u00e4n.3CX PBX muokkautuu mink\u00e4 tahansa kokoisen yrityksen tarpeisiin sopivaksi. 3CX PBX on l\u00e4hes rajattomasti laajennettavissa.<br \/>Ohjelmistot ja laitteet toimivat t\u00e4ydellisess\u00e4 harmoniassa kesken\u00e4\u00e4n, muodostaen laajan alustan yhdistetylle viestinn\u00e4lle.3CX PBX ratkaisu tarjoaa p\u00e4\u00e4telaitteita kaikkiin tarpeisiin &#8211; p\u00f6yt\u00e4puhelimet, langattomat puhelimet ja erikoispuhelimet sek\u00e4 monipuoliset ohjelmistotuotteet. My\u00f6s tavalliset lankapuhelimet ja faksit ilman VoIP-ominaisuuksia toimivat 3CX PBX j\u00e4rjestelm\u00e4ss\u00e4.<img loading=\"lazy\" decoding=\"async\" class=\"alignright size-medium wp-image-2627\" src=\"https:\/\/www.perustele.fi\/wp-content\/uploads\/2022\/02\/video-call-smartphones-300x240.png\" alt=\"\" width=\"300\" height=\"240\" srcset=\"https:\/\/www.perustele.fi\/wp-content\/uploads\/2022\/02\/video-call-smartphones-300x240.png 300w, https:\/\/www.perustele.fi\/wp-content\/uploads\/2022\/02\/video-call-smartphones.png 336w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/p>\r\n<p>Koronaviruksen puhkeamisen my\u00f6t\u00e4 henkil\u00f6kuntasi voi jongleerata todenn\u00e4k\u00f6isesti satunnaisten videosovellusten ja henkil\u00f6kohtaisten matkapuhelimien kanssa. Mit\u00e4, jos voisit tehostaa asiakaspalvelua ja helpottaa henkil\u00f6st\u00f6\u00e4 helppok\u00e4ytt\u00f6isell\u00e4 puhelinj\u00e4rjestelm\u00e4ll\u00e4 \u2013 kaikki yhdess\u00e4 ja samalla s\u00e4\u00e4st\u00e4\u00e4 rahaa? 3CX:n avulla sinulla on t\u00e4ysin varusteltu PABX-j\u00e4rjestelm\u00e4 \u2013 puhelujonot, sis\u00e4\u00e4nrakennetut videopuhelut, verkkoneuvottelut ja paljon muuta. Lis\u00e4ksi voit integroida verkkosivujen <strong><a href=\"https:\/\/www.perustele.fi\/index.php\/chatti\/\">live-chatin<\/a>, <a href=\"https:\/\/www.perustele.fi\/index.php\/faecbook-integratio\/\">Facebookin<\/a><\/strong> ja<a href=\"https:\/\/www.perustele.fi\/index.php\/sms-viestit-katevasti\/\"> <strong>tekstiviestit<\/strong> <\/a>yhteen j\u00e4rjestelm\u00e4\u00e4n. Kaikki n\u00e4m\u00e4 ominaisuudet ovat et\u00e4k\u00e4ytt\u00f6\u00f6n sopivia; tiimisi voi k\u00e4ytt\u00e4\u00e4 niit\u00e4 miss\u00e4 tahansa mobiili- ja selainsovellusten kautta. Se on my\u00f6s avoin alusta ja t\u00e4ysin yhteensopiva useimpien IP-puhelimien kanssa. K\u00e4yt\u00e43cx \u00a0paikan p\u00e4\u00e4ll\u00e4 olemassa olevalla palvelimella, virtuaalikoneena, houstattuna tai omassa pilvipavelussa. 3CX on PBX-j\u00e4rjestelm\u00e4, joka skaalautuu yrityksesi kanssa ja on saatavilla murto-osalla vastaavien ohjelmistoratkaisujen hinnasta.<img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-thumbnail wp-image-2516\" src=\"https:\/\/www.perustele.fi\/wp-content\/uploads\/2022\/01\/3CX-Partner-150x150.jpg\" alt=\"\" width=\"150\" height=\"150\" srcset=\"https:\/\/www.perustele.fi\/wp-content\/uploads\/2022\/01\/3CX-Partner-150x150.jpg 150w, https:\/\/www.perustele.fi\/wp-content\/uploads\/2022\/01\/3CX-Partner-140x140.jpg 140w, https:\/\/www.perustele.fi\/wp-content\/uploads\/2022\/01\/3CX-Partner-370x370.jpg 370w, https:\/\/www.perustele.fi\/wp-content\/uploads\/2022\/01\/3CX-Partner-1200x1200.jpg 1200w\" sizes=\"auto, (max-width: 150px) 100vw, 150px\" \/><\/p>\r\n<p><\/p>\r\n<p><strong>PYYD\u00c4 LIS\u00c4TIETOA:<\/strong><\/p>\r\n<form class=\"accua-form __accua-form__1 accua-form-view-sidebyside\" novalidate=\"novalidate\" action=\"#\" id=\"accua-form___accua-form__1_69e9d6979345b\" method=\"post\"><input type=\"hidden\" name=\"_AccuaForm_ID\" value=\"__accua-form__1\" id=\"accua-form___accua-form__1_69e9d6979345b-element-0\"\/><input type=\"hidden\" name=\"_AccuaForm_buildID\" value=\"accua-form___accua-form__1_69e9d6979345b\" id=\"accua-form___accua-form__1_69e9d6979345b-element-1\"\/><input type=\"hidden\" name=\"_AccuaForm_wpnonce\" value=\"eb54d615e2\" id=\"accua-form___accua-form__1_69e9d6979345b-element-2\"\/><input type=\"hidden\" name=\"_AccuaForm_jsuuid\" id=\"accua-form___accua-form__1_69e9d6979345b-element-3\"\/><input type=\"hidden\" name=\"_AccuaForm_referrer\" id=\"accua-form___accua-form__1_69e9d6979345b-element-4\"\/><input type=\"hidden\" name=\"_AccuaForm_user_agent\" id=\"accua-form___accua-form__1_69e9d6979345b-element-5\"\/><input type=\"hidden\" name=\"_AccuaForm_platform\" id=\"accua-form___accua-form__1_69e9d6979345b-element-6\"\/><input type=\"hidden\" name=\"_AccuaForm_tentatives\" id=\"accua-form___accua-form__1_69e9d6979345b-element-7\"\/><input type=\"hidden\" name=\"_AccuaForm_submit_method\" value=\"normal\" id=\"accua-form___accua-form__1_69e9d6979345b-element-8\"\/><input type=\"hidden\" name=\"_AccuaForm_hash\" id=\"accua-form___accua-form__1_69e9d6979345b-element-9\" value=\"QabhrFaupd\/OFG9soSTznakFu3Y=\"\/><input type=\"hidden\" name=\"_AccuaForm_iv\" id=\"accua-form___accua-form__1_69e9d6979345b-element-10\" value=\"KmhQWD1zISFjcDpUY1NvKD4tNXpAbHk+PGNLQG0+TzoqdVc5JTpyUCNkTlh9T28+Qkc3aztVRmhWWDBEM21bQg==\"\/><input type=\"hidden\" name=\"_AccuaForm_data\" id=\"accua-form___accua-form__1_69e9d6979345b-element-11\" value=\"NG4BN\/bDhBnWeePu39UpoJbHotP\/c2jQmodJNkaax9YDFSH5AEKKbkuNZSQRqt5tiGqkRuTxcOvCSZxa7dDtiJea65TPRlJO5nfj9o2j6emeJifW0jS30bJwVcQ9xUqvIhkUhccnmIkUhGZMzTwHptWbfXIVEv8Xtyz6ji+3rS9Iwfctky0nGaxdlJf1ZdDy4WceBDhZfRxzl6W3EIahVYqfS+HTkXiW49tBX3YIURpUShUhBOZr9dOOYpxU5LdBPaMym+NTWqnC\/3DktT6HTJ41XNDYFGdVvez2J1fNvWzL1zbYa1gcs8\/pocxZ7\/eRGBXn7p6LA4d4qI\/QSyEw1MFtt1PmfaBy5TG5kF7ZOV4pI90JM4+zU1PXktDAg+CjbGLalLiAfQp5bH6JLvnrHALWgrE\/F5sfffHP5plJiM69GMsC7RDVFmVMM9xDKPFjAdX4kBjpLOPt+eRGP8dRyTXCnvhPee7hfYLMr55ARY5qEBg74zLw0\/DT133VLftzCK6hsnrA3knqIzTjZSkOu5nHzE6Ryponhu7Dsrvnp6282X0kGueo1Szcl6jZbQgRM5OOIXyPfl1FQ9uCwsdhr1N\/L78+qf5Z2IxUiPpYxDyeLUogOLwyZ1NqiaITG5RbhHfRxKrdMP36TOUus0nUthGTuKi1MEUaDVC+5lONHkXscZ870GiGTp12lnZcOlULKoVkWMHtsgz6K+7Xx0Z\/y94rkJQyd2TJqBGo+jRs6P2CTdoLzt4pK2bBGPG\/F19yr81RbAxwja8HqPuvxIEoYV4xF42t296ACdPJ9jQazWPMJrOGoVE4gEDNgSiWIF+S\/UsiHDTNhRWdEcB3px09AINGbK3+WvTCixxhE1kUzLWoqaB+FOdsXBzA8deSDlWNdfcQrnKyAULp4+G8wftwSpQmNUkuo0\/a9h5xKT0GcvNL9dcevpYxMTlV4nqehCa3BKc0EpscR8vMGiZZGPm0ug90oYDZyXAjum7B5fMUm8k\/PXJNznFGV8ptt5\/t7rSdrlYXwiPoR5cNtQjdokh+jimgQkbR\/HwzLsLQ1MziJXSWE83QnVp4lyVdHaNoMYeWEXKVypE1qasdRnClT3GUpInK+RftOQgOgk\/hNZyvTaouWVNdgnU\/9SYrfnc10dWQ2FfsjAPM0hfX56vMTSGqnLUGeOwJgwJng8xnUNFUdfjUMw6T\/z3RXraIwBXgXvT+MgZMjKpu3LxRUWhZpWFWjAfQxBk2K\/xFymEJ9jqDXWfRvsCt8pn5SiQ7eShw6vDVR3juSAqN7g2qta5fxwCA1lX91j6M\/xePfoLSEeDcH22ENzdh94XTbTNCDj1vDRMR0nKv7ZiWPt0zPyYEE5rfjYrBQ9OlMNsAWYiTBfq1ETfG8cj\/f1AK6TiAhr4PXYiJHDLGhOf78D+lZ5k+3uswG9nmWnboLa4EpgVXAnmSgWjwJl0Uxu8+m2xbjp0bd7ohqJf0RtNyC8kjjjEj8LqOfyBlLKYAOvOQfrTUljSsXXeW8HhRbAChs7C6jT2mwOJ2\/x4tLDeivzBxTIk8adZSwbgp1evNBDJIbMmuMlzM54+nP83hY12EmTBLZyg1kQAba2wGQIiEo3+x8oxP1YjSKEltK8ymbaHtcMKZ5gL6kQa0H0dLOoSoNyaNglWZClWKIEJm\/sZ4zxJrziJjEzc0JZXBWEnnclao9SUMeHcTXGhXyaxeH6sVC48gCtv\/QjGeE\/jX0tDyMDNyvyFyo8UVGfp1fWWrONC0FL9AVu\/O3UxrlltZ8o5AvVT+XDI+ZJLGFDbmLt5MkkS7yIvpecc4Aagl9M\/vX5R71rQM+JV\/590jmHSv\/QSUGLcopUKg7zKQD50Tu8nm55evezyEjXji0kApTprWibZZEAL5WG04qtF0WzU\/24SThL9Hb5PVqK9DyKruvv9nubC5WXB\/kEdbZ+NAAyFcWV0ccicoz17HvnHtyIMm4CLZG\/oS\/EQ4\/qV0QO4FMvM1xYpd+yXtLJvcXuXDCN6dvFKjnviQjPE9CsM6NuKtQvpeTpIyZbF9TgqwsyKL8iVBFWZJNFuoUxOwCnvSFgfGPav0CNg9QSBAdIQVL\/+ImvKgWEe3TnVaOVqthqzbGRc7Z2kl4T8mHsmFfhyKActYO3RSzDsrXkwiA4E\/g8MLpIDi+6cJV37yeKT4QZRvKIZ94rSg8viPo+pLXtZuiiIAmed60TfY0ISAvliRcX9pVg3mpIZfFb77n3\/DtcREkhPKuVWZnhA0CWInNgM8fDoQ4QSpH+tm01xYZmKj2mWQqxwUjmMXIhAhu2u4r2suYQq60XwqwO32Ttn9QxF4PKcfLnsTKA7arTPJtoUuUfVS+zPLlnG0hvdxbc\/Ik7VT3WBv4RHIQmIfaE0RwukATSod8MF9GbhtFdjoDAc3MtrziJFBPnu61Mx0yZPv\/MQUwwaMnYp9W2hvbNu7N66AD0kepzNFf\/T0b08drJjdKiCKszFRqg82xXkFFUGinLYK6QhrEsoEY8FEjNxszUwnAYunSP0bdL69G0iKB7fkiPkzMXRnmwFVTEj66ujYWr3hsIIxDT0IQviWGL6Hi0GwJCs3O5QZYKbwBo6r8tDC1gVPOqk6zGC4ZrS84i\/8wEPrzFlofyvPa5yxLojYgO3Uq1fbjFGPHcmJZNjCXv5trg4VNKaw1ohyKZAF+JQM8kTGf7TLWoZ7Na80q7VjWGgjP0GpXDmzY5308EAQleAmQMrtrYSCZDU+l+GRlZUSYNTdiGR5PmAM4yQ2Hd+TH3o02vYC4TRk7d1VxB9Jp0XZL2hHCwR2SzGnmbb4A9iT92JpgJRbdLw9cVCHEu4nm5XpplpiBTeImTfVkBpK8ifnW\/bdwaHLDtXjFSHq7jsePBJK1N9lngkhPD8ybe1RWuBDgdxdwXzDBAHMm+\/y5wxlef8HFt6o6bt7L0bugqbG89FA0ynANt9d4JwdZUwT7L1BEP7FeFwuH0ooHBvFcRCBNxGYoGzrThmImlwJOncIiZzjww4uSGL3\/FPLbZ+j8eRIdlYkveuclbUJ0YoKpYbicxDDQIBJdboUhUKxboPa1b+jtjGO7hmkegHSvCNq2Mf0oJ5c8PDPbh4HZrxEP7xa1X9W0AvZy3626g7zMgVZM1fCzWzIOON7eqLy9evp0acpStucvsVH3jTtcgPL2TQOPMPi4Sk9\/VsSvrPL3kwNul3znl55uQwOCI4iqQ6jW7Rk4bq0ddzbQ+IIeMWr2n4FKeNXqvIzmV9U3YgZP\/JQizIzmZCIV4xojyd5tYmrXangRhWDksqLJb163DwMfnY\/Riqg3aD70pz89qfgi6yD2BBQR3durwGkr1AI2Rl\/898owAOWwihLpDEFtdEJy6oDzBGQPJNKsRJqLUig3ZOAaSPwSd9hmYivulKJjmCB\/n4lxK5s5tr3Zp9Hho+J6b7KPLlyqBmGTCCk3B3BDuaMrVatSY6ggpOS2v3n36xutRL3bN6QeqzLlMzAl8eNlEkqEuP\/hXHGa\/oZhaA7EUUtkjZ28cyeO1mIy2KtvR3O5w2Vn7CHGvSrxmjuV6ag0ymTXJjQiftlVf8THFg3i4Z9r1n0JMlKIuvLYwX3VIAt2FIDerMqyC6Db14Z6gHDjsPyuUSkD3MU\/qr63ec018RCw3PhxSnMxg3c7FkY8hss9zFK4\/zpdONMItqIjYieM7IvE7HlvAZYN0EKix8OFkocC6BtRaBCOc7yqKVX+JO2qcIQn4AGRfRyZH7Q\/NfV\/H3d60q1EHGszdSXaizaVcdKN0ivfa1xeDeAKu70RiVL3rngR7UV\/ioQP64p1RVil0ArQROqyxHSD5R4vdsinIM3g01lxi+iP+EyOZPqj\/HJoVesHHdK4x0WW9o2Pq65lL2HB7YY863Bkz76PjfT8tL0daw+i3flvszTHbEFvFA\/zmjqUaNsKxpcG0uwhLgXB0xIM49+yJtKboW89+VUReU5OaJAIFXRwaZi\/A+GjYjWiDbbxXodGZLKe1Rnh0iULHBYEm1OOZ2nke\/9OGYf1Z8BxuY4W3WTfnLTbSHdbn\/XtJY0gliusPHaIWp6LThtyK13bGQDJrQyfoVhX2W+PVyYYZcDPsiVh6hxUYG1pDga05wDdl4bCMmCFwi5spd3rMu1KZC7L6cGY48OUrnNyA0P6es2YwFuXj6ZV2CqF+R7\/Q4\/e3YSez8b2QKQiHqwBw0QYeP7o+0mCbNYH6WyAXFKVd3+rUy7IYYDkpxTh+fi44T6tqMsbhcaoRA41Oag7RIjPQpRuDxYkTfINB1FQgMZic69oLDcqEX\/DrDbZDfGOFA+zlMUUGXTguNBMXd84lM6LB1DCwoWHc6PfuUYJRYi5YJzi+R40Ci2KGBUS\/wycIWQ7tJnPg8jzA9aDGit44j5IMrEe4z77X26HLyATzZHa6FDE5Q35EsTgVxUV3gl8OJi467+sf3aK1hYTzTTSbBeDF8Lp2LIpjBAEQN+s5MzxDyNzI6Z\/cw8R0GLfNElD0aDHV4QKLl3C9ZdpT4lo2YdIDOtmj9aVTRwsjpG2OvPCO9sbTf7Tyf7rYcDW5eutwFreKy\/JDYRDMj1TA9jhEQcG9W4Y3m1Al0JuER+x3053P563x31tn50vTvBI0kX3PpZfyJpdi1cVZ8rpiTBfxzTRda0HtRxLXh742zpOT8lEWQJCVrOJIHYjOLfwlwZGum8cznOSu6HDHrhWf6IqzMF3vCccNIRT6wFFsobFICSXgHZmBZ9YPHVplPuAEVXyFrGJhqiUNKXYDRPfYrnsYw2J92cIWS4xZpDCEX8ttRePvqO4o2bhUtpHxNB4iotk1S181wq2QnDKU3JpWKxJM\/a1Rny2co2ymcb2J3verXjFCwNVuWHjuct6tfePpQalniweE6DoKPCHZhvJnv6LKVxXHBBIcxzeCIFR0GyvwrPQZNyJAuaDRSOURh3rf8yHJaqyRnxRk1SLfBJxi36giZ\/56G6iqNNOTSXCjWoNkUQLa8UUVCuNiVQLOCP6ffwwxhCrzObeQalWq35mFyBK2bVLTOhs\/MiDx7Sy6Nj6ZyUOCIIJjACBEupg4bM0fU43MkErony5+x+LyyVPhzRh5zS2tFvA6\/K4jpX+ToGUdg7oZAuIzLo8TZ+EFG+Dy0BGnKfId\/Upnmtaaz44E1ylJa+gBGt2rLn+m9C1wrqDKQypCXZnu6hwApXDtqkkySk7h5HtJLlDliqwRQ77\/4LG0JUNgk5YNCs6WmlitF3ypyl3otsK3Cn5Z0Z+77ELVFA2407TCepIG7pPV5Q\/x\/7Orc0mPGRijcYCwhad+d5MgQydAgiHJ25rIGAboWKlcAGSYeF8qm8ILnmjbWVDXByd4fwjgjZXK0J5Ou3+wIO0HDRlj+Phzp0MLLxAR8YP0P8X3Gg\/FD4BhqMQfVt3m6AmHHYWITQqXT1zjIr4Q1UmcLBDUpAVM8UJIB5WtN3yr2xjPpYZG+wkhlNd8LpnIXK\/bPspl66MZ+KjMERr33rgiK3qBYgVvdycjK\/KK9wBiYnPNgwr0LlHaS3ccURvzdEONVRwiRqM+guqmSL8SFqW3F3dsAaaP7NAuUfohRSIoPqKPb1HeCQ6viehqzjN2FF3AXlcZrPI5ysmIGtjzQyGFyW7Pu4vSRvj2zCyyuHgswJEZoXlRbmIvf02gH85XHMKcI8cL0TC4nR0BUvKMpUXmox2xpUimdBZeiDv\/7UchanWFZarip8bkEOEzQkSxp2\/aDRqFZxlzUaKo6A0NUhQVPx1kTXbrj3ZdGGSzerEW1\/VxFKICFIEGbSJw1VYbHTVpOQdKQP+jmacbhWhVqIdo25IRoRmNwVclOETixgCbW\/Jo\/MlRTCPKiwztX1z1Sxb0gJPulk2avSjR0aF\/scRczexVVYTnws0e04Ok2UxOjG0\/dteoCU1Pdmfi\/DT2QcRL9wko59v2f53EToeihdI+pyTwkVvePBTDH1QYnrqJkKCiJ8R0YmhTWS\/MnKhz9SPZB+2KMLtzXgGJ7Anfgl+lRzcohrc67osGcyYXHDHOq7m+\/vAlgKzW1289IzeJ4jqeUOCyVxmci6hAM+PXG4Gs7kTDNiJxAa0KmsodmpdTjbflejktQycOAm\/mlvVS07QddA7V0nqEYwvIY587dTtjQ3VPlar+Z1l2Bf9XLACxk+j2WeEJTl92KpSdLYEahlYYytMCGbwBFimoc\/+wLKHoQN3eitSyrUSgFwdYoRkmwuup8XP2Fxx+MN01+Sk2gCSBhrEtjGZZTOtg3x+Af4D8XR\/n3e6uF0quVISUdNHmB1MW0clv8nMO2GkTpDt45ZXn+YN+1000Cqqs10KShuGpEDrHvQb59MQ4gvcP4wNcvlVLHRQU705aobXjjxMSh7jY\/tDhslZEOUsGPLcnSpEFQ1SrI5\/EBFWRG2eoiiovpkhmlc5bzeyoQw8+yqc\/kPGsLcc5H5AiABeIluElqKWkvRoKxFWpQFNyf6YSndF2IX0Z4RXbgDPRVcw2xSNZcwVWmMzFJGGeLgALIJIP3lJynqU\/HEfOaJ6rFjjNDNL6t2C5oJnSNTjTj4MqHAZQ0YhB7XPlixtBQyp9F\/STpncP0td5WWgdR2+a95osfahNAlvWXtYMdFZ5LsHgex0ecqCGW3LOKCOY0J1TSe7kaxL3dpbD\/cRQPU\/MWXuhaX+pC+zi\/eeoDh4yyDSlm8yKjPBC7uYqTfisfRpu5RJTYeoPA1EkDDMjOboyfR07fHpzy0wC3EVbMWR4qWST1NbImAPKBPQlmsL0mHJRqxeHe1TE4JF\/BTdes5r1B4KTkBekTAF1VQayQ6MV9b0jaIiDI9PaKj99PgbXSq0tcXF6ufZ1XVgGwN9jLR3ZoVcPkqEoYa3EvsySHcCXH58zlbMJkLpzBx9jS3MelZiVvUG4YIPifjdArBwoL0lN8rfMfRTuEc80sJLbDjOfY+LflN0LjeBaowpn1ZE6lgBQCF+1sBTQweeYE\/rs6RKaUI\/Z68Uon9Fjmfv9TsP8eNbI+en0\/y477kGOUoqX\/D5xk9nxwDC9Ghqdxp5LI\/NsWNP+iN0g+DNA\/ZC3uvN7zcXprprd40nox05u\/irvt7amIp6SUnCbebYa4RrzMNbNyZWgUD6uAAMvSwBlubmU8WWKYWC\/ow90gF9hdx8by1PvnDOZtd\/P6OYPnnhj0DdZwaYqHcFToxorLBPAxoE2i7Ay5ZgxlfN19CtqfZNUxEcRsWpQRzDAuyI4VtH+ys11XEMEnz9Zg77WWbcW\/TkVypPGiuaUom\/BFSxH9j\/PaZIfoTYEafA6nkECwKrv9jde5VU8a84EQk2YcocK6qwU5JlAvYqlcRwWvRPxrKDs8SYI1ENiS2iIIpKlNtbSz5OS1IpgjTNpi8PkjnyOHKrzOmUYB1lbkjgrfcqJTJBduTUkGmcWUhvx0Cvd43ZLSjr\/T47zUmP50B903N\/QkwMLRr\/sUv3YIsJfqYTF\/mSjkJcC8FOBdIRfhvfCrEWYoQ4nmqOB9JAcQcmLlTQbOUDNxICqXOGsWOesOTm5pu2Epqi\/9IGqF6IbVbRpCb5Zk4mEMBA8YYo2zGXKfd+nKhcK7zRtWlFSW2YqaJVXz5gad2uBpWSIvVsIAt6t4hlZM1MZYY0Y3NaaIW0PZ8kVdan7Y0Rs6YNuGoVSTo+x5kmoP+0vQEy+PJHG0On9FEGAvZ8oNffDjmgn\/S5cwlEcjX8rol9mgNY7HN5R201v+Gm4JlMsRnwvihY5UxoE279yuUtkAfMHVSATMeQDXZxs2QzqzhCUlAUpj6SGNjy7lwi0OOU09Ti94Q+ngmPt9rqTcvnqgaNZokZwjGMQ5odkKdHPpyUszJTUuFP5T1bUHaNgczduH8bWximAGbe9iDAutdnyIQTCBqKSgacvV9IupcfG\/XRB9OxNLW6gwjwS3bfqefDVaROifrzosqGsB\/KOviZhOuhEnLB90gSEYe1jzwFAwmJ\/LVlkh0IONaND3P+55fmDEGEL8FpgwHaFonz5rEiMg4YrUtAi+UitNtsNK8OmMjyvFroQiSkklDlq1vnesJr4hgyx0X0xKVCDv0DbNY1ffnMis96Mvc\/OqxcqJqAbv4Y1XNrAVG9SO9oF0OtJqnMpk6Zp5uQ84iJcxEPGh9g6\/YpsGCUHwXNixqvGEYetEH3Kc5YcX1rd6\/LDdfE3tbEmtboRdWBLNgFehNVXdRcj3bb\/AF7nTKiH5IDw+fQoMZlXQ3e17LonoBBggXtsO6e3fJGiJIjcEo2yB5YNFrAUIq9fc9Efke+wah8OFDaS7UpUIr5RMMK77JFe+OhVwVQOwgKeSJYOQJomMzpdyHwRL8iWNiy0M+qJwmy2Mi1TM\/aTfLDi56Udq41MMypA89QtQvfD4r\/nctsz1ifi7PhRYqGQAORKfRfZe8P7HChk3fnN5BQC8RWMcnLv3OCU330dd8eYOTzDak4auCzmoa3ZMAuGLwZJF3aXqJBHxgvlm5KzwRK9CbkDH9ww1S+Ui0G82sBd044Ppmoc2s2Pp4Lwb4hXhzyPen0x\/Lf\/LJVIGZy41JIsHgmnLbx3ZkBPt2o6APCdtU4N6RgRmXeaPCljpHxSr1YeSnOSoxVylINJNX+2mZxIFyFdKh1A9Ztyd4K6xdT3nGQThGOaHrOdXZz1zu0HzBVN2ZgyIIAWwawE9fwy2YUlTikbWrLw5TP6\/ydgtRV46pPHZBw+4poKgtdM03x8FzvVQrPaJ+WTwfFmrJ5GdsZrovMy0Seiln8gXcwIVxkT1QGo9bG4i7dHbcBWwLVWS4zNqxht0\/anvK7XRYHa4J7j+5hFINHzOFyE3siT\/teLZdqYtK0ZAmq0aQe7Bx\/Htefyn3jFPxd7DLGz4iNtVXKF1EU3IcJ4\/ufTOXG5wlx2+kW9vmBpZBkjd6cjAu2tH4xwUFjFgFTSSanTmv6QeCEn7D6ow381q82y8RO40elvLk92RwcAYgq9F0atMAC9vlQx692PIscwh4G\/0Rp2pakllDhFmo4BOvownM54Xa1iwHvGx9m+2\/+LJBNAxjbX0Jwu9E0qUflBZ7ehN5cOD2V+zC+eCkJF+M0tEhNTsH8AFgt37C4MMxmPKmXUkMnc6DKN9rl+epO0TsRl4b4o3qUjZmXzgmKfmkD8RwOFCDMLnLDv6wwo987Vjs9wrsWlFdn+63vNpMM8GqqjbbDDINm4I21r5sPCrngl8h960IT0stMpq6NZ7DbFXtdrdaTdr8dYGdgczx+G1Meo4u+DI48TWSNNBZeTNdnr1\/QwzWJRgLXBTVFCXxnDE9ZC\/eXE3OV\/CnUY7qD5btXRIOZO\/TelllRzJ8CXWKwgVGESFH79QO0uTiketjp4RkAiQbTR3ELyuIIp\/7OqePA98EIO1XN1+1avuUMQ\/gDXrlPCCEGPfgZKoun7dH\/V\/w9TkZckUXz+DtAt9QEIH8VqdBOr9DaXpjCRmTvE2PErIqPt9YKBHmTh\/CIU2zNchCt6SORLQAXt\/m3xUGaKmaDRXQmSG3F6AWGi+\/1DdLE5TJsWX9m0alKlSKP623Cms8pbW66Pn48UHnU83AkTrsifXvo5wr2UX\/1fTt0OkdwK8npXtoRTXdMIumJrZ+LWlPTmEUnwwCwdsR+TwWVhwN60rtvaRwGoG4Ir7wwujvMlzYeeox\/t9zj0\/y4biiSHLNxRADanwdu\/6gmakWqx7nZ9bK+7DO0TRfs8S+4q97ZJB+M2uxk7dHo+iTyPUXdtCj5odvKLKf5CpUgwIWybkNvbwMut\/SpyiYuZFnic0ZRf7qkpeJ\/CqNJdM8He+X4GVvoxVsf\/O61dRNqfgHExfEaCnYxr2Q1yR2EB1I5CPjz2xsaAKVM3zskH2r2R9yO00w2EaMKUOmXlFZvCxH2Vvgus1hualcj1lobgq+0yD5G+3T5UrhtFc555yG4v7SJsuMllxNuQNK72FVxFF2Efib+pdow3Wng4F0jzcHlR+nQpCMsj\/sVRCoja+VUAyYSRxtTxMz\/9mnZMnbReB6MQaz6rRjhL4oan2DucVNfSckG5CDNoM2nGnChFhAU47UZG008dvfa6RQPFGtKxAxWF7kKdCYD625D93Qi60kxAv40BSjLsQsiBypYuCi0y+lEP8iINxm6FQubUerodIej4Eh+Dw7kjtELpPdMBZuIkW26IkWWp7\/mryLRn4PgBUocwJEMzlEMehQA4t895T\/X9eLylltmfc8EyKUkWBmuPaX+juwNwWa4MZ+uocBRuViXoxBIZyX7CAra0l4+dzduIlwqKFKY8UXzs5OlMDBCRJEEplqB6xpN0wSkYjrYnPOYjVsjGPH2mLUbkhrvCtAmED\/yK97aRpLk\/GziYhnKvQRiOSP8fiMgfcQkJ6YShVR9t2vioxpfE6zHb2Xtpezz210K\/s\/e\/i\/9hAuWL46SCui1CL0ne0S8QXMzguCyCNX5ZEPtOGFTgr8pZbj\/jSS5RXoaDCLQzZozgsddFi3y35NOFqpo9doTOIcVEEHSeHtNcl\/g7j+E4VbXN7k\/S7+xwz3QYYsTRSBuBBT3Ux6T6TFsJAb8jk1ok4A219zxaft6X6+qvPF+jDk8JRvuVYLIwj7pX4tPDu\/S4fxc+7hfShd3rLFXouFmmHFLsk6TBBNezakD6AfnjrBQPI6gxbf0mh0IkQdtVjRuDpSNJG8JNP4ZsIyNh5xbpskgkLQCfk5PtdZaUGDS1rHiB50RUs77V8uuf1MVZY0VDI\/k7EodbYPRPaoWASX94NvWB0T3bZKf1ydDJ6RC9SGuRABbi6w7zHWhUNKGBG+pnm5RJJY\/utztEB\/teCBp\/I3Vz37I2pNjzXm4WFASPftIQTVlnosQFN7p9Gfd\/9FKsBiZfw94SdgXUrsiu5MRrbh9F2frA6KTiPjvLcS7boVuSorHISIT1ny29JIvzxBad3IltIGwyfJGASsI2FFOP98ARwLuwHs5WLn3xXLB+vWmp5hu76GVTtwDfl1DsFAYt2Eo05Ey2LIPsu4ptCDru4SEHdb+YdeBZwUBqNx70j2RaL2i+V4XPZzYuO8ORWDGk18DkP2I9ruNPjvIrencufyA8UK2wgrhjEBQcnmEoxoFgzwL2XsjseYIlh0202y2hVRLC8Jy0\/e3lh6Bv5giFgA\/eNQjU95cjrmV+Ap5c68D4dpF9zwuH3d1IBgVQ6heM9\/YnRI5IV4bAh8xRLiWESGMfAQHIL7pG7EaNGRoOw1U9KyW5bH0AtDIbarctoNRuPMjwAxQ1HZco2XryryyfcPloQ89VucwgtV2fb4wb8f+X8boxBDM9c2EBj9eWrrVfY0NiHLNZAGUQcDOcOShmLlRAIUf\/ZZArvOc4h0Wp15jU7Cy7gi\/VA2MqhD3FMs+0i+gq+PBhF31J5jaSZk7KZnNrXOEs5lA3dSZuCkKyzk7u46U86yr0cDVcGQuPR6bZVj81wKVi0ONNq6q+zSoPpXcfTa\"\/><div class=\"pfbc-element-0 pfbc-element\"><div class=\"pfbc-label\"><label for=\"accua-form___accua-form__1_69e9d6979345b-element-12\">Etunimi <span class=\"pfbc-required\" aria-label=\"required\">*<\/span><\/label><\/div><div class=\"pfbc-fieldwrap\"><input type=\"text\" class=\"pfbc-textbox accuaforms-field-required accuaform-fieldname-first_name accuaform-fieldtype-textfield\" name=\"first_name\" value=\"\" id=\"accua-form___accua-form__1_69e9d6979345b-element-12\" required=\"required\" aria-required=\"true\"\/><\/div><div class=\"pfbc-elementbottom\"><\/div><\/div><div class=\"pfbc-element-1 pfbc-element\"><div class=\"pfbc-label\"><label for=\"accua-form___accua-form__1_69e9d6979345b-element-13\">Sukunimi <span class=\"pfbc-required\" aria-label=\"required\">*<\/span><\/label><\/div><div class=\"pfbc-fieldwrap\"><input type=\"text\" class=\"pfbc-textbox accuaforms-field-required accuaform-fieldname-last_name accuaform-fieldtype-textfield\" name=\"last_name\" value=\"\" id=\"accua-form___accua-form__1_69e9d6979345b-element-13\" required=\"required\" aria-required=\"true\"\/><\/div><div class=\"pfbc-elementbottom\"><\/div><\/div><div class=\"pfbc-element-2 pfbc-element\"><div class=\"pfbc-label\"><label for=\"accua-form___accua-form__1_69e9d6979345b-element-14\">S\u00e4hk\u00f6postiosoite <span class=\"pfbc-required\" aria-label=\"required\">*<\/span><\/label><\/div><div class=\"pfbc-fieldwrap\"><input type=\"email\" class=\"pfbc-textbox accuaforms-field-required accuaform-fieldname-email accuaform-fieldtype-autoreply_email\" name=\"email\" value=\"\" id=\"accua-form___accua-form__1_69e9d6979345b-element-14\" required=\"required\" aria-required=\"true\"\/><\/div><div class=\"pfbc-elementbottom\"><\/div><\/div><div class=\"pfbc-element-3 pfbc-element\"><div class=\"pfbc-label\"><label for=\"accua-form___accua-form__1_69e9d6979345b-element-15\">Puhelinnumero<\/label><\/div><div class=\"pfbc-fieldwrap\"><input type=\"text\" class=\"pfbc-textbox accuaform-fieldname-puhelinnumero accuaform-fieldtype-textfield\" name=\"puhelinnumero\" value=\"\" id=\"accua-form___accua-form__1_69e9d6979345b-element-15\"\/><\/div><div class=\"pfbc-elementbottom\"><\/div><\/div><div class=\"pfbc-element-4 pfbc-element\"><div class=\"pfbc-label\"><label for=\"accua-form___accua-form__1_69e9d6979345b-element-16\">Yritys<\/label><\/div><div class=\"pfbc-fieldwrap\"><input type=\"text\" class=\"pfbc-textbox accuaform-fieldname-yritys accuaform-fieldtype-textfield\" name=\"yritys\" value=\"\" id=\"accua-form___accua-form__1_69e9d6979345b-element-16\"\/><\/div><div class=\"pfbc-elementbottom\"><\/div><\/div><div class=\"pfbc-element-5 pfbc-element\"><div class=\"pfbc-label\"><label for=\"accua-form___accua-form__1_69e9d6979345b-element-17\">Viesti <span class=\"pfbc-required\" aria-label=\"required\">*<\/span><\/label><\/div><div class=\"pfbc-fieldwrap\"><textarea class=\"pfbc-textarea accuaforms-field-required accuaform-fieldname-message accuaform-fieldtype-textarea\" rows=\"5\" name=\"message\" cols=\"50\" id=\"accua-form___accua-form__1_69e9d6979345b-element-17\" required=\"required\" aria-required=\"true\"><\/textarea><\/div><div class=\"pfbc-elementbottom\"><\/div><\/div><div class=\"pfbc-element-6 pfbc-element\">\n\n<!-- ReCaptcha 1 is discontinued, please go to Contact Forms settings page and set reCaptcha v2 keys -->\n\n<div class=\"pfbc-elementbottom\"><\/div><\/div><div class=\"pfbc-element pfbc-buttons\"><button type=\"submit\" value=\"L\u00e4het\u00e4\" name=\"laheta\" class=\"accuaform-fieldname-laheta accuaform-fieldtype-submit\" id=\"accua-form___accua-form__1_69e9d6979345b-element-19\">L\u00e4het\u00e4<\/button><\/div><\/form><script type=\"text\/javascript\">\r\n<!-- \r\njQuery(document).ready(function() {    \r\n    \/\/ If there are errors on page load, focus the error summary or first invalid field\r\n    if (jQuery('.pfbc-error', '#accua-form___accua-form__1_69e9d6979345b').length > 0) {\r\n      setTimeout(function() {\r\n        var errorContainer = jQuery('.pfbc-error', '#accua-form___accua-form__1_69e9d6979345b').first();\r\n        errorContainer.attr('tabindex', '-1').focus();\r\n      }, 100);\r\n    } else if (jQuery('.pfbc-element-has-error', '#accua-form___accua-form__1_69e9d6979345b').length > 0) {\r\n      setTimeout(function() {\r\n        var firstInvalidField = jQuery('.pfbc-element-has-error :input:visible:enabled:first', '#accua-form___accua-form__1_69e9d6979345b').first();\r\n        if (firstInvalidField.length) {\r\n          firstInvalidField.focus();\r\n        }\r\n      }, 100);\r\n    }\r\n    jQuery(\"#accua-form___accua-form__1_69e9d6979345b .pfbc-element:last\").css({ \"margin-bottom\": \"0\", \"padding-bottom\": \"0\", \"border-bottom\": \"none\" });\t});\r\n\/\/ -->\r\n<\/script><script type=\"text\/javascript\">\r\n<!--\r\nvar _handle_ajax_submit_accua_form___accua_form__1_69e9d6979345b = function() {return true;}\r\nvar _handle_ajax_submit_complete_accua_form___accua_form__1_69e9d6979345b = function() {return false;}\r\nvar _handle_ajax_submit_timeout_accua_form___accua_form__1_69e9d6979345b = function() {return false;}\r\nvar _handle_ajax_submit_message_accua_form___accua_form__1_69e9d6979345b = function() {}\r\nvar _handle_ajax_submit_response_accua_form___accua_form__1_69e9d6979345b = function() {}\r\n\r\njQuery(function($) {\r\n  var thisform = $(\"#accua-form___accua-form__1_69e9d6979345b\");\r\n  var ajax_enabled = \"www.perustele.fi\" == location.hostname ;\r\n  var anchor_id = \"1\" ;\r\n\r\n  var response_messages = $(\"#_response_messages_accua-form___accua-form__1_69e9d6979345b\");\r\n  if (! response_messages.length) {\r\n    \/\/ Create all three anchors for success, invalid, and error states\r\n    thisform.before('\\x3Ca id=\"formSubmitSuccess-'+anchor_id+'\" name=\"formSubmitSuccess-'+anchor_id+'\" class=\"accua-form-anchor\" \/\\x3E');\r\n    thisform.before('\\x3Ca id=\"formSubmitInvalid-'+anchor_id+'\" name=\"formSubmitInvalid-'+anchor_id+'\" class=\"accua-form-anchor\" \/\\x3E');\r\n    thisform.before('\\x3Ca id=\"formSubmitError-'+anchor_id+'\" name=\"formSubmitError-'+anchor_id+'\" class=\"accua-form-anchor\" \/\\x3E');\r\n    response_messages = $('\\x3Cdiv id=\"_response_messages_accua-form___accua-form__1_69e9d6979345b\" class=\"accua-form-messages\"\\x3E\\x3C\/div\\x3E');\r\n    thisform.before(response_messages);\r\n  }\r\n  \r\n  \/\/ Smooth scroll helper function - also updates URL hash for GA tracking and bookmarkability\r\n  var smoothScrollToElement = function(elementId) {\r\n    var target = document.getElementById(elementId);\r\n    if (target) {\r\n      target.scrollIntoView({ behavior: 'smooth', block: 'start' });\r\n      \/\/ Update URL hash without adding a browser history entry (replaceState prevents instant jump)\r\n      if (history.replaceState) {\r\n        history.replaceState(null, '', '#' + elementId);\r\n      }\r\n    }\r\n  };\r\n\r\n  var _ajax_submitting_accua_form___accua_form__1_69e9d6979345b = false;\r\n  var timeout_handler = false;\r\n  var timeout_count = 0;\r\n  var fail_count = 0;\r\n  var disabled_fields = false;\r\n  var submitBtn = $('button[type=\"submit\"]', thisform);\r\n  var submitBtnOriginalText = submitBtn.text();\r\n  var submitBtnSendingText = \"Sending...\";\r\n\r\n  var jsuuid_field = $('input[name=\"_AccuaForm_jsuuid\"]', thisform);\r\n  var jsuuid = jsuuid_field.val();\r\n  if (jsuuid == '') {\r\n    var chars = '0123456789abcdefghijklmnopqrstuvwxyz'.split('');\r\n    var radix = chars.length\r\n    for (i = 0; i < 25; i++) {\r\n      jsuuid += chars[0 | Math.random()*radix];\r\n    }\r\n    jsuuid_field.val(jsuuid);\r\n  }\r\n\r\n  var ga_track = {\"title\":\"Lis\\u00e4tietoja\",\"track_submit\":false,\"track_fields\":false} ;\r\n  var ga_event, ga_submit_event, ga_field_event, ga_field_events_fired = {};\r\n  ga_event = function(eventCategory, eventAction){\r\n    \/* matomo *\/ \r\n    if (window._mtm && (typeof window._mtm.push == 'function')) {\r\n      window._mtm.push({'event': 'ContactForms', 'eventAction': eventAction, 'eventCategory': eventCategory, 'eventLabel': ga_track.title});\r\n    }\r\n      \r\n    if (typeof window.gtag == 'function') {\r\n      window.gtag('event', eventAction, {'event_category': eventCategory, 'event_label': ga_track.title});\r\n    } else if (window.dataLayer && (typeof window.dataLayer.push == 'function')) {\r\n      dataLayer.push({'event': 'ContactForms', 'eventAction': eventAction, 'eventCategory': eventCategory, 'eventLabel': ga_track.title});\r\n      \/\/backward compatibility\r\n      var gtag = function(){window.dataLayer.push(arguments);}\r\n      gtag('event', eventAction, {'event_category': eventCategory, 'event_label': ga_track.title});\r\n    } else if (typeof window.ga == 'function') {\r\n      window.ga('send', 'event', eventCategory, eventAction, ga_track.title);\r\n    } else if (window._gaq && (typeof window._gaq.push == 'function')) {\r\n      window._gaq.push(['_trackEvent', eventCategory, eventAction, ga_track.title]);\r\n    } else if (window.gaq && (typeof window.gaq.push == 'function')) {\r\n      window.gaq.push(['_trackEvent', eventCategory, eventAction, ga_track.title]);\r\n    } else if (window.pageTracker && (typeof window.pageTracker._trackEvent == 'function')) {\r\n      window.pageTracker._trackEvent(eventCategory, eventAction, ga_track.title);\r\n    }\r\n  }\r\n  ga_submit_event = function(eventAction){\r\n    if (ga_track.track_submit) {\r\n      ga_event('ContactFormsSubmit', eventAction);\r\n    }\r\n    thisform.trigger('ContactFormsSubmit', [eventAction]);\r\n  }\r\n  ga_field_event = function(field_name){\r\n    if (!ga_field_events_fired[field_name]){\r\n      if (ga_track.track_fields) {\r\n        ga_event('ContactFormsFieldFilledIn', field_name);\r\n        ga_field_events_fired[field_name] = true;\r\n      }\r\n      thisform.trigger('ContactFormsFieldFilledIn', [field_name]);\r\n    }\r\n  }\r\n  $('input, textarea, select', thisform).change(function(){\r\n    ga_field_event($(this).attr('name'));\r\n  });\r\n  \r\n  \/\/ Disable submit button during form submission\r\n  var disableSubmitButton = function() {\r\n    submitBtn.prop('disabled', true).attr('aria-busy', 'true').text(submitBtnSendingText);\r\n  };\r\n  \r\n  \/\/ Re-enable submit button (on failure or completion)\r\n  var enableSubmitButton = function() {\r\n    submitBtn.prop('disabled', false).removeAttr('aria-busy').text(submitBtnOriginalText);\r\n  };\r\n  \r\n  \/\/ Get field label from the field's container element\r\n  var getFieldLabel = function(field) {\r\n    var container = field.closest('.pfbc-element');\r\n    if (!container.length) {\r\n      return '';\r\n    }\r\n    \r\n    \/\/ Try floating label first (inline labels mode)\r\n    var label = container.find('.pfbc-floating-label').first();\r\n    if (!label.length) {\r\n      \/\/ Try standard label in .pfbc-label\r\n      label = container.find('.pfbc-label label').first();\r\n    }\r\n    if (!label.length) {\r\n      \/\/ Try any label element\r\n      label = container.find('label').first();\r\n    }\r\n    \r\n    if (label.length) {\r\n      \/\/ Get text content, removing the required asterisk\r\n      var text = label.clone().find('.pfbc-required').remove().end().text().trim();\r\n      return text;\r\n    }\r\n    \r\n    return '';\r\n  };\r\n  \r\n  \/\/ Build required field error message with field name\r\n  \/\/ Checks per-field data-custom-required-msg attribute first, then falls back to global template\r\n  var getRequiredMessage = function(fieldLabel, field) {\r\n    var template = \"%s is a required field\";\r\n    if (field) {\r\n      var custom = field.attr('data-custom-required-msg');\r\n      if (custom) {\r\n        template = custom;\r\n      }\r\n    }\r\n    if (fieldLabel) {\r\n      return template.replace('%s', fieldLabel);\r\n    }\r\n    return template.replace('%s', '');\r\n  };\r\n  \r\n  \/\/ Build email validation error message with field name\r\n  \/\/ Checks per-field data-custom-format-msg attribute first, then falls back to global template\r\n  var getEmailMessage = function(fieldLabel, field) {\r\n    var template = \"%s: please enter a valid email address\";\r\n    if (field) {\r\n      var custom = field.attr('data-custom-format-msg');\r\n      if (custom) {\r\n        template = custom;\r\n      }\r\n    }\r\n    if (fieldLabel) {\r\n      return template.replace('%s', fieldLabel);\r\n    }\r\n    return template.replace('%s', '');\r\n  };\r\n  \r\n  \/\/ Build phone validation error message with field name\r\n  \/\/ Checks per-field data-custom-format-msg attribute first, then falls back to global template\r\n  var getPhoneMessage = function(fieldLabel, field) {\r\n    var template = \"%s: please enter a valid phone number (e.g. +39 333 1234567)\";\r\n    if (field) {\r\n      var custom = field.attr('data-custom-format-msg');\r\n      if (custom) {\r\n        template = custom;\r\n      }\r\n    }\r\n    if (fieldLabel) {\r\n      return template.replace('%s', fieldLabel);\r\n    }\r\n    return template.replace('%s', '');\r\n  };\r\n  \r\n  \/\/ Check if a telephone field contains only a country prefix (e.g. \"+39\")\r\n  \/\/ These values should be treated as empty \u2014 the user hasn't entered a real number.\r\n  var isTelephonePrefixOnly = function(field) {\r\n    if (!field.hasClass('accuaform-telephone')) return false;\r\n    var val = field.val();\r\n    if (!val) return false;\r\n    val = val.trim();\r\n    if (val === '' || val.charAt(0) !== '+') return false;\r\n    return val.replace(\/\\D\/g, '').length <= 4;\r\n  };\r\n  \r\n  \/\/ Scroll to first invalid field, then focus after scroll completes\r\n  var focusFirstInvalidField = function() {\r\n    var firstInvalidContainer = $('#accua-form___accua-form__1_69e9d6979345b .pfbc-element-has-error').first();\r\n    if (!firstInvalidContainer.length) {\r\n      return;\r\n    }\r\n    \r\n    \/\/ Try to find a focusable element in the invalid container\r\n    var focusTarget = null;\r\n    \r\n    \/\/ Check for radio\/checkbox groups first\r\n    var radioOrCheckbox = firstInvalidContainer.find('input[type=\"radio\"], input[type=\"checkbox\"]').first();\r\n    if (radioOrCheckbox.length) {\r\n      focusTarget = radioOrCheckbox;\r\n    }\r\n    \r\n    \/\/ Check for file input (focus the dropzone button if available)\r\n    if (!focusTarget) {\r\n      var fileDropzone = firstInvalidContainer.find('.accua-file-dropzone');\r\n      if (fileDropzone.length) {\r\n        focusTarget = fileDropzone;\r\n      } else {\r\n        var fileInput = firstInvalidContainer.find('input[type=\"file\"]');\r\n        if (fileInput.length) {\r\n          focusTarget = fileInput;\r\n        }\r\n      }\r\n    }\r\n    \r\n    \/\/ Check for custom select buttons (post select, etc.)\r\n    if (!focusTarget) {\r\n      var customSelectBtn = firstInvalidContainer.find('.pfbc-post-select-trigger, button[aria-haspopup=\"listbox\"]').first();\r\n      if (customSelectBtn.length) {\r\n        focusTarget = customSelectBtn;\r\n      }\r\n    }\r\n    \r\n    \/\/ Standard inputs (text, email, select, textarea)\r\n    if (!focusTarget) {\r\n      focusTarget = firstInvalidContainer.find('input:not([type=\"hidden\"]), textarea, select').first();\r\n    }\r\n    \r\n    if (focusTarget && focusTarget.length) {\r\n      \/\/ Scroll into view first with smooth animation\r\n      if (focusTarget[0].scrollIntoView) {\r\n        focusTarget[0].scrollIntoView({ behavior: 'smooth', block: 'center' });\r\n      }\r\n      \/\/ Focus after scroll animation completes (typical scroll animation is ~300-500ms)\r\n      setTimeout(function() {\r\n        focusTarget.focus();\r\n      }, 500);\r\n    }\r\n  };\r\n  \r\n  \/\/ Scroll to a specific field by ID and focus it\r\n  var scrollToFieldAndFocus = function(fieldId) {\r\n    var element = $('#' + fieldId);\r\n    if (!element.length) {\r\n      return;\r\n    }\r\n    \r\n    var focusTarget = element;\r\n    \r\n    \/\/ If it's already an input\/select\/textarea, use it directly\r\n    if (element.is('input, select, textarea')) {\r\n      focusTarget = element;\r\n    }\r\n    \/\/ For containers (pfbc-element), find the first focusable element\r\n    else if (element.hasClass('pfbc-element')) {\r\n      var radioOrCheckbox = element.find('input[type=\"radio\"], input[type=\"checkbox\"]').first();\r\n      if (radioOrCheckbox.length) {\r\n        focusTarget = radioOrCheckbox;\r\n      } else {\r\n        var fileDropzone = element.find('.accua-file-dropzone');\r\n        if (fileDropzone.length) {\r\n          focusTarget = fileDropzone;\r\n        } else {\r\n          focusTarget = element.find('input:not([type=\"hidden\"]), textarea, select').first();\r\n        }\r\n      }\r\n    }\r\n    \/\/ For file dropzone wrapper, focus the dropzone\r\n    else if (element.find('.accua-file-dropzone').length) {\r\n      focusTarget = element.find('.accua-file-dropzone').first();\r\n    }\r\n    \r\n    if (focusTarget && focusTarget.length) {\r\n      if (focusTarget[0].scrollIntoView) {\r\n        focusTarget[0].scrollIntoView({ behavior: 'smooth', block: 'center' });\r\n      }\r\n      setTimeout(function() {\r\n        focusTarget.focus();\r\n      }, 500);\r\n    }\r\n  };\r\n  \r\n  \/\/ Track if form submission has been attempted\r\n  var submitAttempted = false;\r\n  \r\n  \/\/ Array to collect field errors for summary\r\n  var fieldErrorsList = [];\r\n  \r\n  \/\/ Get the error ID for a radio\/checkbox group (DRY helper)\r\n  var getGroupErrorId = function(field) {\r\n    var groupWrapper = field.closest('.pfbc-radio-buttons, .pfbc-checkboxes').parent();\r\n    var groupId = groupWrapper.attr('id') || field.attr('id');\r\n    return groupId + '-error';\r\n  };\r\n  \r\n  \/\/ Remove an error element with smooth animation (generic helper for any field type)\r\n  var removeErrorAnimated = function(errorId) {\r\n    var errorEl = $('#' + errorId);\r\n    if (errorEl.length) {\r\n      errorEl.addClass('pfbc-error-removing');\r\n      setTimeout(function() {\r\n        errorEl.remove();\r\n      }, 150); \/\/ Match CSS animation duration\r\n    }\r\n  };\r\n  \r\n  \/\/ Remove all existing errors for a group with smooth fade-out (handles both potential IDs)\r\n  var removeGroupErrors = function(field, fieldName, animate) {\r\n    var groupContainer = field.closest('.pfbc-element, .pfbc-fieldwrap');\r\n    var errors = groupContainer.find('.pfbc-inline-error');\r\n    \r\n    \/\/ Also collect errors by potential IDs\r\n    var groupWrapper = field.closest('.pfbc-radio-buttons, .pfbc-checkboxes').parent();\r\n    var wrapperId = groupWrapper.attr('id');\r\n    if (wrapperId) {\r\n      errors = errors.add($('#' + wrapperId + '-error'));\r\n    }\r\n    var firstField = $(\"[name='\"+fieldName+\"']\", thisform).first();\r\n    if (firstField.attr('id')) {\r\n      errors = errors.add($('#' + firstField.attr('id') + '-error'));\r\n    }\r\n    \r\n    if (animate && errors.length) {\r\n      \/\/ Smooth fade-out animation\r\n      errors.addClass('pfbc-error-removing');\r\n      setTimeout(function() {\r\n        errors.remove();\r\n      }, 150); \/\/ Match CSS transition duration\r\n    } else {\r\n      errors.remove();\r\n    }\r\n  };\r\n  \r\n  \/\/ Show or update the error\/success\/loading summary area\r\n  \/\/ state: true (success), false (error), 'loading' (submitting)\r\n  var updateSummaryArea = function(state) {\r\n    var summaryArea = $('#accua-form___accua-form__1_69e9d6979345b-validation-summary');\r\n    \r\n    if (!submitAttempted && state !== 'loading') {\r\n      summaryArea.remove();\r\n      return;\r\n    }\r\n    \r\n    \/\/ Ensure summary area exists\r\n    if (!summaryArea.length) {\r\n      summaryArea = $('<div id=\"accua-form___accua-form__1_69e9d6979345b-validation-summary\" class=\"pfbc-validation-summary\" role=\"status\" aria-live=\"polite\"><\/div>');\r\n      thisform.find('.pfbc-error').remove();\r\n      thisform.append(summaryArea);\r\n    }\r\n    \r\n    if (state === 'loading') {\r\n      \/\/ Show loading state - neutral blue with spinner and text\r\n      summaryArea\r\n        .removeClass('pfbc-validation-error pfbc-validation-success')\r\n        .addClass('pfbc-validation-loading')\r\n        .attr('role', 'status')\r\n        .attr('aria-live', 'polite')\r\n        .attr('aria-busy', 'true')\r\n        .html('<span class=\"pfbc-summary-spinner\" aria-hidden=\"true\"><\/span>' + \"Submitting your form, please wait...\");\r\n    } else if (state === true) {\r\n      \/\/ Show success state\r\n      summaryArea\r\n        .removeClass('pfbc-validation-error pfbc-validation-loading')\r\n        .addClass('pfbc-validation-success')\r\n        .attr('role', 'status')\r\n        .attr('aria-live', 'polite')\r\n        .removeAttr('aria-busy')\r\n        .html('<span class=\"pfbc-summary-icon\">\u2713<\/span> ' + \"All fields are valid. Ready to submit!\");\r\n    } else {\r\n      \/\/ Show error state with field list\r\n      summaryArea\r\n        .removeClass('pfbc-validation-success pfbc-validation-loading')\r\n        .addClass('pfbc-validation-error')\r\n        .attr('role', 'alert')\r\n        .attr('aria-live', 'assertive')\r\n        .removeAttr('aria-busy');\r\n      \r\n      var html = '<p class=\"pfbc-summary-header\">' + \"Check the following fields to continue:\" + '<\/p><ul class=\"pfbc-summary-list\">';\r\n      for (var i = 0; i < fieldErrorsList.length; i++) {\r\n        var err = fieldErrorsList[i];\r\n        html += '<li><a href=\"#\" class=\"pfbc-summary-link\" data-field-id=\"' + err.fieldId + '\">' + err.label + '<\/a> \u2013 ' + err.errorType + '<\/li>';\r\n      }\r\n      html += '<\/ul>';\r\n      summaryArea.html(html);\r\n      \r\n      \/\/ Attach click handlers to links\r\n      summaryArea.find('.pfbc-summary-link').on('click', function(e) {\r\n        e.preventDefault();\r\n        var fieldId = $(this).data('field-id');\r\n        scrollToFieldAndFocus(fieldId);\r\n      });\r\n    }\r\n  };\r\n  \r\n  var show_error_messages = function(message) {\r\n    \/\/ Show error message in the validation summary area\r\n    \/\/ Used when AJAX submission fails (network error, server error, etc.)\r\n    var summaryArea = thisform.find('.pfbc-validation-summary');\r\n    if (summaryArea.length) {\r\n      summaryArea.html('<div class=\"pfbc-validation-error\" role=\"alert\"><strong>' + accua_forms_i18n.check_fields + '<\/strong><ul>' + message + '<\/ul><\/div>').show();\r\n    }\r\n  }\r\n  \r\n  \/\/ Update summary area with server-side errors (called from AJAX error response)\r\n  var updateSummaryWithServerErrors = function(errors, elementErrors) {\r\n    \/\/ Collect server errors for the summary\r\n    fieldErrorsList = [];\r\n    \r\n    if (elementErrors) {\r\n      jQuery.each(elementErrors, function(fieldName, fieldErrors) {\r\n        var field = jQuery('[name=\"' + fieldName + '\"]', thisform);\r\n        var fieldId = field.attr('id') || fieldName;\r\n        var fieldLabel = getFieldLabel(field);\r\n        \r\n        \/\/ If no label found, try to get from the field container or use field name\r\n        if (!fieldLabel || fieldLabel === fieldName) {\r\n          var container = field.closest('.pfbc-element, .pfbc-fieldwrap');\r\n          fieldLabel = container.find('label').first().text().replace(\/\\s*\\*\\s*$\/, '').trim();\r\n          if (!fieldLabel) {\r\n            \/\/ Fallback: humanize the field name\r\n            fieldLabel = fieldName.replace(\/[-_]\/g, ' ').replace(\/\\b\\w\/g, function(l){ return l.toUpperCase(); });\r\n          }\r\n        }\r\n        \r\n        for (var i = 0; i < fieldErrors.length; i++) {\r\n          fieldErrorsList.push({\r\n            fieldId: fieldId,\r\n            label: fieldLabel,\r\n            errorType: fieldErrors[i]\r\n          });\r\n        }\r\n      });\r\n    }\r\n    \r\n    \/\/ Also add any general errors from the errors array\r\n    if (errors && errors.length > 0) {\r\n      for (var i = 0; i < errors.length; i++) {\r\n        \/\/ Check if this error is already in fieldErrorsList\r\n        var alreadyAdded = false;\r\n        for (var j = 0; j < fieldErrorsList.length; j++) {\r\n          if (fieldErrorsList[j].errorType === errors[i]) {\r\n            alreadyAdded = true;\r\n            break;\r\n          }\r\n        }\r\n        if (!alreadyAdded) {\r\n          fieldErrorsList.push({\r\n            fieldId: '',\r\n            label: '',\r\n            errorType: errors[i]\r\n          });\r\n        }\r\n      }\r\n    }\r\n    \r\n    \/\/ Update the summary area to show errors\r\n    if (fieldErrorsList.length > 0) {\r\n      updateSummaryArea(false);\r\n    }\r\n  }\r\n\r\n  _handle_ajax_submit_accua_form___accua_form__1_69e9d6979345b = function() {\r\n    if (_ajax_submitting_accua_form___accua_form__1_69e9d6979345b) {\r\n      return false;\r\n    }\r\njQuery(\"#accua-form___accua-form__1_69e9d6979345b .pfbc-error\").remove();\r\n    \/\/ Mark that submit was attempted\r\n    submitAttempted = true;\r\n    \r\n    var valid_empty = true;\r\n    var valid_mail = true;\r\n    var valid_phone = true;\r\n    var fieldErrors = {};\r\n    \r\n    \/\/ Reset field errors list for summary\r\n    fieldErrorsList = [];\r\n\r\n    $(\"#accua-form___accua-form__1_69e9d6979345b .pfbc-element\").removeClass('pfbc-invalid');\r\n    $(\"#accua-form___accua-form__1_69e9d6979345b .pfbc-element\").removeClass('pfbc-element-has-error');\r\n    $(\"#accua-form___accua-form__1_69e9d6979345b input, #accua-form___accua-form__1_69e9d6979345b textarea, #accua-form___accua-form__1_69e9d6979345b select\").attr('aria-invalid', 'false');\r\n    $(\"#accua-form___accua-form__1_69e9d6979345b .pfbc-inline-error\").remove();\r\n\r\n    var processedGroups = {}; \/\/ Track radio\/checkbox groups to avoid duplicate errors\r\n\r\n    $('.accuaforms-field-required', thisform).each(function(){\r\n      var field = $(this);\r\n      var type = field.attr('type');\r\n      var fieldName = field.attr('name');\r\n\r\n      if (type === 'checkbox' || type === 'radio') {\r\n        \/\/ Skip if we've already processed this group\r\n        if (processedGroups[fieldName]) {\r\n          return true;\r\n        }\r\n        processedGroups[fieldName] = true;\r\n\r\n        if ($(\"[name='\"+fieldName+\"']:checked\", \"#accua-form___accua-form__1_69e9d6979345b\").length > 0) {\r\n          return true;\r\n        }\r\n\r\n        valid_empty = false;\r\n        \r\n        \/\/ Find the container for the radio\/checkbox group\r\n        var groupContainer = field.closest('.pfbc-element, .pfbc-fieldwrap');\r\n        groupContainer.addClass('pfbc-invalid pfbc-element-has-error');\r\n        \r\n        \/\/ Remove any existing errors before adding new one (prevents duplicates)\r\n        removeGroupErrors(field, fieldName);\r\n        \r\n        \/\/ Get consistent error ID using helper\r\n        var errorId = getGroupErrorId(field);\r\n        \r\n        \/\/ Find the last radio\/checkbox in the group\r\n        var lastInGroup = $(\"[name='\"+fieldName+\"']\", \"#accua-form___accua-form__1_69e9d6979345b\").last();\r\n        \r\n        \/\/ Apply ARIA attributes to all inputs in the group\r\n        $(\"[name='\"+fieldName+\"']\", \"#accua-form___accua-form__1_69e9d6979345b\").attr('aria-invalid', 'true');\r\n        $(\"[name='\"+fieldName+\"']\", \"#accua-form___accua-form__1_69e9d6979345b\").attr('aria-describedby', errorId);\r\n        \r\n        \/\/ Get field label and build error message\r\n        var fieldLabel = getFieldLabel(field);\r\n        var firstInput = $(\"[name='\"+fieldName+\"']\", \"#accua-form___accua-form__1_69e9d6979345b\").first();\r\n        var errorMessage = getRequiredMessage(fieldLabel, firstInput);\r\n        \r\n        \/\/ Add to field errors list for summary (use first input ID for focusing)\r\n        fieldErrorsList.push({\r\n          fieldId: firstInput.attr('id'),\r\n          label: fieldLabel,\r\n          errorType: \"required field\"\r\n        });\r\n        \r\n        \/\/ Add error message after the last item in the group\r\n        var inlineError = $('<div class=\"pfbc-inline-error\" id=\"' + errorId + '\" role=\"alert\" aria-live=\"polite\"><div class=\"pfbc-error-message\">' + errorMessage + '<\/div><\/div>');\r\n        \r\n        \/\/ Insert after the last radio\/checkbox wrapper\r\n        var lastWrapper = lastInGroup.closest('.pfbc-radio, .pfbc-checkbox');\r\n        if (lastWrapper.length) {\r\n          lastWrapper.after(inlineError);\r\n        } else {\r\n          lastInGroup.after(inlineError);\r\n        }\r\n      } else {\r\n        var val = field.val();\r\n        if (typeof(val) == \"string\") {\r\n          \/\/ Treat \"-\" and \"Select...\" as invalid only for dropdowns\r\n          \/\/ For telephone fields, prefix-only values (e.g. \"+39\") are also empty\r\n          var isSelect = field.is('select');\r\n          if (! val.match(\/^\\s*$\/) && (!isSelect || (val !== \"Select...\" && val !== \"-\")) && !isTelephonePrefixOnly(field)) {\r\n            return true;\r\n          }\r\n        } else if (Array.isArray(val)) {\r\n          \/\/ Multiselect: empty array means no selection\r\n          if (val.length > 0) {\r\n            return true;\r\n          }\r\n        } else if (val) {\r\n          return true;\r\n        }\r\n\r\n        valid_empty = false;\r\n        var parent = field.closest('.pfbc-element, .pfbc-fieldwrap');\r\n        parent.addClass('pfbc-invalid pfbc-element-has-error');\r\n        \r\n        \/\/ Apply ARIA attributes\r\n        field.attr('aria-invalid', 'true');\r\n        var errorId = field.attr('id') + '-error';\r\n        field.attr('aria-describedby', errorId);\r\n        \r\n        \/\/ Get field label and build error message\r\n        var fieldLabel = getFieldLabel(field);\r\n        var errorMessage = getRequiredMessage(fieldLabel, field);\r\n        fieldErrorsList.push({\r\n          fieldId: field.attr('id'),\r\n          label: fieldLabel,\r\n          errorType: \"required field\"\r\n        });\r\n        \r\n        var inlineError = $('<div class=\"pfbc-inline-error\" id=\"' + errorId + '\" role=\"alert\" aria-live=\"polite\"><div class=\"pfbc-error-message\">' + errorMessage + '<\/div><\/div>');\r\n        \r\n        \/\/ For file inputs with help text, insert error after help text\r\n        var helpText = field.siblings('.pfbc-help').last();\r\n        if (field.is('[type=\"file\"]') && helpText.length) {\r\n          helpText.after(inlineError);\r\n        } else {\r\n          field.after(inlineError);\r\n        }\r\n      }\r\n    });\r\n\r\n    $('.pfbc-textbox[type=\"email\"]', thisform).each(function(){\r\n      var field = $(this);\r\n\r\n      if (field.val().match(\/^\\s*$\/)) {\r\n        return true;\r\n      }\r\n\r\n      if (field.val().match( \/^([a-zA-Z0-9_.+%-])+@(([a-zA-Z0-9-])+\\.)+([a-zA-Z0-9])+$\/ )) {\r\n        return true;\r\n      }\r\n\r\n      valid_mail = false;\r\n      var parent = field.closest('.pfbc-element, .pfbc-fieldwrap');\r\n      parent.addClass('pfbc-invalid pfbc-element-has-error');\r\n      \r\n      \/\/ Apply ARIA attributes\r\n      field.attr('aria-invalid', 'true');\r\n      var errorId = field.attr('id') + '-error';\r\n      field.attr('aria-describedby', errorId);\r\n      \r\n      \/\/ Get field label and build error message\r\n      var fieldLabel = getFieldLabel(field);\r\n      var errorMessage = getEmailMessage(fieldLabel, field);\r\n      \r\n      \/\/ Add to field errors list for summary (use field ID for focusing)\r\n      fieldErrorsList.push({\r\n        fieldId: field.attr('id'),\r\n        label: fieldLabel,\r\n        errorType: \"invalid email address\"\r\n      });\r\n      \r\n      var inlineError = $('<div class=\\\"pfbc-inline-error\\\" id=\\\"' + errorId + '\\\" role=\\\"alert\\\" aria-live=\\\"polite\\\"><div class=\\\"pfbc-error-message\\\">' + errorMessage + '<\/div><\/div>');\r\n      \r\n      \/\/ For file inputs with help text, insert error after help text\r\n      var helpText = field.siblings('.pfbc-help').last();\r\n      if (field.is('[type=\\\"file\\\"]') && helpText.length) {\r\n        helpText.after(inlineError);\r\n      } else {\r\n        field.after(inlineError);\r\n      }\r\n\r\n    });\r\n\r\n    \/\/ Phone validation - runs for all non-empty phone fields\r\n    $('.accuaform-telephone', thisform).each(function(){\r\n        var field = $(this);\r\n        var value = field.val();\r\n        \r\n        \/\/ Skip empty fields (Required validation handles mandatory)\r\n        if (!value || value.trim() === '') {\r\n          return true;\r\n        }\r\n        \r\n        \/\/ Skip prefix-only values (e.g. \"+39\") \u2014 treated as empty\r\n        var phoneTrimmed = value.trim();\r\n        if (phoneTrimmed.charAt(0) === '+' && phoneTrimmed.replace(\/\\D\/g, '').length <= 4) {\r\n          return true;\r\n        }\r\n        \r\n        \/\/ Get country code from data attribute\r\n        var countryCode = field.attr('data-country') || 'IT';\r\n        \r\n        \/\/ Use AccuaPhoneValidation if available, otherwise skip validation\r\n        if (typeof window.AccuaPhoneValidation !== 'undefined' && window.AccuaPhoneValidation.isValid) {\r\n          if (window.AccuaPhoneValidation.isValid(value, countryCode)) {\r\n            return true;\r\n          }\r\n        } else {\r\n          \/\/ Fallback: basic validation matching server-side Phone.php\r\n          var trimmed = value.trim();\r\n          \/\/ Check for invalid characters\r\n          if (!\/^[\\d\\s\\-\\.\\\/\\(\\)\\+]+$\/.test(trimmed)) {\r\n            \/\/ Invalid characters - fail validation\r\n          } else {\r\n            var plusIndex = trimmed.indexOf('+');\r\n            if (plusIndex > 0 || (trimmed.match(\/\\+\/g) || []).length > 1) {\r\n              \/\/ Plus in wrong position or multiple plus signs - fail validation\r\n            } else {\r\n              var digitCount = trimmed.replace(\/\\D\/g, '').length;\r\n              \/\/ Prefix-only (1-4 digits with +) treated as empty\r\n              if (trimmed.charAt(0) === '+' && digitCount <= 4) {\r\n                return true;\r\n              }\r\n              \/\/ Valid if 5-15 digits (matches server-side Phone.php)\r\n              if (digitCount >= 5 && digitCount <= 15) {\r\n                return true;\r\n              }\r\n            }\r\n          }\r\n        }\r\n        \r\n        valid_phone = false;\r\n        var parent = field.closest('.pfbc-element, .pfbc-fieldwrap');\r\n        parent.addClass('pfbc-invalid pfbc-element-has-error');\r\n        \r\n        \/\/ Remove any existing blur validation error to avoid duplicates\r\n        $('#' + field.attr('id') + '-phone-error').remove();\r\n        \r\n        \/\/ Apply ARIA attributes\r\n        field.attr('aria-invalid', 'true');\r\n        var errorId = field.attr('id') + '-error';\r\n        field.attr('aria-describedby', errorId);\r\n        \r\n        \/\/ Get field label and build error message\r\n        var fieldLabel = getFieldLabel(field);\r\n        var errorMessage = getPhoneMessage(fieldLabel, field);\r\n        \r\n        \/\/ Add to field errors list for summary\r\n        fieldErrorsList.push({\r\n          fieldId: field.attr('id'),\r\n          label: fieldLabel,\r\n          errorType: \"invalid phone number\"\r\n        });\r\n        \r\n        var inlineError = $('<div class=\"pfbc-inline-error pfbc-phone-format-error\" id=\"' + errorId + '\" role=\"alert\" aria-live=\"polite\"><div class=\"pfbc-error-message\">' + errorMessage + '<\/div><\/div>');\r\n        \r\n        var helpText = field.siblings('.pfbc-help').last();\r\n        if (helpText.length) {\r\n          helpText.after(inlineError);\r\n        } else {\r\n          field.after(inlineError);\r\n        }\r\n      });\r\n\r\n    if (valid_empty && valid_mail && valid_phone) {\r\n      \/\/ Show loading state in summary during AJAX submission\r\n      updateSummaryArea('loading');\r\n      \r\n      _ajax_submitting_accua_form___accua_form__1_69e9d6979345b = true;\r\n      disableSubmitButton();\r\n      $('input[name=\"_AccuaForm_tentatives\"]', thisform).val(fail_count);\r\n      disabled_fields = $(\"input, textarea, button, select\", thisform).not('[type=\"submit\"]').not(':disabled');\r\n      disabled_fields.attr('readonly','readonly');\r\n      timeout_count = 0;\r\n      if (ajax_enabled) {\r\n        $(\"#submit_target_accua_form___accua_form__1_69e9d6979345b\").attr('src','').removeAttr('src');\r\n        timeout_handler = setTimeout(_handle_ajax_submit_timeout_accua_form___accua_form__1_69e9d6979345b, 5000);\r\n      }\r\n      return true;\r\n    } else {\r\n      ga_submit_event('formSubmitInvalid');\r\n      \r\n      \/\/ Update URL hash to reflect invalid state (for GA tracking and bookmarkability)\r\n      if (history.replaceState) {\r\n        history.replaceState(null, '', '#formSubmitInvalid-'+anchor_id);\r\n      }\r\n      \r\n      \/\/ Update summary area with error list\r\n      updateSummaryArea(false);\r\n      \r\n      \/\/ Focus on first invalid field for accessibility\r\n      focusFirstInvalidField();\r\n      \r\n      return false;\r\n    }\r\n  }\r\n\r\n\r\n  _handle_ajax_submit_timeout_accua_form___accua_form__1_69e9d6979345b = function() {\r\n    if (_ajax_submitting_accua_form___accua_form__1_69e9d6979345b) {\r\n      if (timeout_count < 60) {\r\n        timeout_count++;\r\n        timeout_handler = setTimeout(_handle_ajax_submit_timeout_accua_form___accua_form__1_69e9d6979345b, 500);\r\n        _handle_ajax_submit_complete_accua_form___accua_form__1_69e9d6979345b();\r\n      } else {\r\n        timeout_handler = false;\r\n        _handle_ajax_submit_complete_accua_form___accua_form__1_69e9d6979345b();\r\n        if (_ajax_submitting_accua_form___accua_form__1_69e9d6979345b) {\r\n          _handle_ajax_submit_response_accua_form___accua_form__1_69e9d6979345b(false);\r\n        }\r\n      }\r\n    }\r\n  }\r\n\r\n  _handle_ajax_submit_complete_accua_form___accua_form__1_69e9d6979345b = function() {\r\n    if (_ajax_submitting_accua_form___accua_form__1_69e9d6979345b) {\r\n      var response = false;\r\n      try {\r\n        var responsedoc = frames['submit_target_accua_form___accua_form__1_69e9d6979345b'].document;\r\n        if (responsedoc.getElementById(\"accua-form-ajax-response-loaded\")) {\r\n          response = $.parseJSON(responsedoc.getElementById(\"accua-form-ajax-response\").innerHTML);\r\n        }\r\n      } catch (err) {\r\n        response = false;\r\n      }\r\n      if (response) {\r\n        return _handle_ajax_submit_response_accua_form___accua_form__1_69e9d6979345b (response);\r\n      }\r\n    }\r\n  }\r\n\r\n  _handle_ajax_submit_message_accua_form___accua_form__1_69e9d6979345b = function(message) {\r\n    if (_ajax_submitting_accua_form___accua_form__1_69e9d6979345b) {\r\n      var response = false;\r\n      try {\r\n        response = $.parseJSON(message.data);\r\n        \/\/ Accept response if jsuuid matches AND buildID matches or is null (server rejection)\r\n        if (response.jsuuid != jsuuid || (response.buildID != null && response.buildID != \"accua-form___accua-form__1_69e9d6979345b\")) {\r\n          response = false;\r\n        }\r\n      } catch (err) {\r\n        response = false;\r\n      }\r\n      if (response) {\r\n        return _handle_ajax_submit_response_accua_form___accua_form__1_69e9d6979345b (response);\r\n      }\r\n    }\r\n  }\r\n\r\n  _handle_ajax_submit_response_accua_form___accua_form__1_69e9d6979345b = function(response) {\r\n    if (_ajax_submitting_accua_form___accua_form__1_69e9d6979345b) {\r\n      if(response && typeof(response) == \"object\" && typeof(response.submitted) == \"boolean\") {\r\n        \/\/ Only show message container if there's actual content\r\n        if (response.messages && response.messages.trim() !== '') {\r\n          response_messages.html(response.messages).show();\r\n        } else {\r\n          response_messages.empty().hide();\r\n        }\r\n        if (response.submitted) {\r\n          if (response.valid) {\r\n            var gads_track_code = \"\";\r\n            if(gads_track_code != ''){            \r\n              gtag('event', 'conversion', {'send_to': gads_track_code});\r\n            }\r\n            \r\n            ga_submit_event('formSubmitSuccess');\r\n            smoothScrollToElement('formSubmitSuccess-'+anchor_id);\r\n            \r\n            $('#accua-form___accua-form__1_69e9d6979345b').hide();          } else {\r\n            ga_submit_event('formSubmitInvalid');\r\n            smoothScrollToElement('formSubmitInvalid-'+anchor_id);var errorSize = response.errors.length;\r\nvar errorHTML = '';\r\nfor(e = 0; e < errorSize; ++e) {\r\n  errorHTML += '\\x3Cli\\x3E' + response.errors[e] + '\\x3C\/li\\x3E';\r\n}\r\n\r\n\/* Update summary area with server-side errors *\/\r\nif (typeof updateSummaryWithServerErrors === 'function') {\r\n  updateSummaryWithServerErrors(response.errors, response.elementErrors);\r\n}\r\n\r\n\/* Apply ARIA attributes and inline errors for accessibility *\/\r\nif (response.elementErrors) {\r\n  jQuery.each(response.elementErrors, function(fieldName, fieldErrors) {\r\n    var field = jQuery('[name=\"' + fieldName + '\"]');\r\n    if (field.length) {\r\n      var parent = field.closest('.pfbc-element, .pfbc-fieldwrap');\r\n      var errorId = field.attr('id') + '-error';\r\n      \r\n      \/* Add ARIA attributes *\/\r\n      field.attr('aria-invalid', 'true');\r\n      field.attr('aria-describedby', errorId);\r\n      \r\n      \/* Add error class to parent *\/\r\n      parent.addClass('pfbc-element-has-error');\r\n      \r\n      \/* Remove existing inline error if any *\/\r\n      parent.find('.pfbc-inline-error').remove();\r\n      \r\n      \/* Add inline error message *\/\r\n      var inlineErrorHTML = '<div class=\\\"pfbc-inline-error\\\" id=\\\"' + errorId + '\\\" role=\\\"alert\\\" aria-live=\\\"polite\\\">';\r\n      for (var i = 0; i < fieldErrors.length; i++) {\r\n        inlineErrorHTML += '<div class=\\\"pfbc-error-message\\\">' + fieldErrors[i] + '<\/div>';\r\n      }\r\n      inlineErrorHTML += '<\/div>';\r\n      \r\n      \/* For file inputs with help text, insert error after help text *\/\r\n      var helpText = field.siblings('.pfbc-help').last();\r\n      if (field.is('[type=\\\"file\\\"]') && helpText.length) {\r\n        helpText.after(inlineErrorHTML);\r\n      } else {\r\n        field.after(inlineErrorHTML);\r\n      }\r\n    }\r\n  });\r\n}\r\n            for (var name in response.files) {\r\n              $(\".pfbc-fieldwrap:has(input[type='file'][name='\"+name+\"'])\", thisform).html(response.files[name]);\r\n            }\r\n\r\n            $(\"input[name='_AccuaForm_hash']\",thisform).val(response._AccuaForm_hash);\r\n            $(\"input[name='_AccuaForm_iv']\",  thisform).val(response._AccuaForm_iv);\r\n            $(\"input[name='_AccuaForm_data']\",thisform).val(response._AccuaForm_data);\r\n\r\n            disabled_fields.removeAttr('readonly');\r\n            enableSubmitButton();\r\n          }\r\n        } else {\r\n          \/\/ Server did not recognize the form submission (e.g. expired nonce, stale cached page)\r\n          ga_submit_event('formSubmitError');\r\n          smoothScrollToElement('formSubmitError-'+anchor_id);\r\n          fail_count++;\r\n          if (fail_count > 2) {\r\n            ajax_enabled = false;\r\n            thisform.attr(\"action\", \"https:\\\/\\\/www.perustele.fi:443\\\/index.php\\\/wp-json\\\/wp\\\/v2\\\/pages\\\/2405\" );\r\n            thisform.removeAttr(\"target\");\r\n            $('input[name=\"_AccuaForm_submit_method\"]', thisform).val('fallback');\r\n          }\r\n          show_error_messages( \"\\u003Cli\\u003EForm submission failed. Please try again.\\u003C\\\/li\\u003E\" );\r\n          disabled_fields.removeAttr('readonly');\r\n          enableSubmitButton();\r\n        }\r\n      } else {\r\n        ga_submit_event('formSubmitError');\r\n        smoothScrollToElement('formSubmitError-'+anchor_id);\r\n        fail_count++;\r\n        if (fail_count > 2) {\r\n          ajax_enabled = false;\r\n          thisform.attr(\"action\", \"https:\\\/\\\/www.perustele.fi:443\\\/index.php\\\/wp-json\\\/wp\\\/v2\\\/pages\\\/2405\" );\r\n          thisform.removeAttr(\"target\");\r\n          $('input[name=\"_AccuaForm_submit_method\"]', thisform).val('fallback');\r\n        }\r\n        show_error_messages( \"\\u003Cli\\u003EForm submission failed. Please try again.\\u003C\\\/li\\u003E\" );\r\n        enableSubmitButton();\r\n      }\r\n      $('.accua_forms_show_recaptcha_button', thisform).click();\r\n      if (((typeof accuaform_recaptcha2_initialized) != 'undefined') && accuaform_recaptcha2_initialized) {\r\n        $('.accua_forms_recaptcha2_container', thisform).each(function(){\r\n          accua_forms_reload_recaptcha2($(this).attr('id'));\r\n        });\r\n      }\r\n      _ajax_submitting_accua_form___accua_form__1_69e9d6979345b = false;\r\n      if (timeout_handler) {\r\n        clearTimeout(timeout_handler);\r\n        timeout_handler = false;\r\n      }\r\n    }\r\n  }\r\n\r\n  if (ajax_enabled) {\r\n    thisform.attr(\"action\", \"https:\\\/\\\/www.perustele.fi\\\/wp-admin\\\/admin-ajax.php?action=accua_form_submit\" );\r\n    thisform.attr(\"target\",\"submit_target_accua_form___accua_form__1_69e9d6979345b\");\r\n    try {\r\n      window.addEventListener('message', _handle_ajax_submit_message_accua_form___accua_form__1_69e9d6979345b, false);\r\n    } catch (e) { }\r\n    $('input[name=\"_AccuaForm_submit_method\"]', thisform).val('iframe');\r\n  } else {\r\n    thisform.attr(\"action\", \"https:\\\/\\\/www.perustele.fi:443\\\/index.php\\\/wp-json\\\/wp\\\/v2\\\/pages\\\/2405\" );\r\n  }\r\n  thisform.attr(\"onsubmit\",\"return _handle_ajax_submit_accua_form___accua_form__1_69e9d6979345b()\");\r\n  \r\n  \/\/ Real-time validation for better UX - use change only for checkbox\/radio to avoid double-firing\r\n  $('.accuaforms-field-required', thisform).on('change', function() {\r\n    var field = $(this);\r\n    var type = field.attr('type');\r\n    if (type !== 'checkbox' && type !== 'radio') return; \/\/ Only handle checkbox\/radio on change\r\n    \r\n    var fieldName = field.attr('name');\r\n    var isChecked = $(\"[name='\"+fieldName+\"']:checked\", thisform).length > 0;\r\n    var groupContainer = field.closest('.pfbc-element, .pfbc-fieldwrap');\r\n    var hasError = groupContainer.hasClass('pfbc-element-has-error');\r\n    \r\n    \/\/ Only act if state actually changed to avoid flashing\r\n    if (isChecked && hasError) {\r\n      \/\/ Valid now - remove error with animation\r\n      groupContainer.removeClass('pfbc-invalid pfbc-element-has-error');\r\n      $(\"[name='\"+fieldName+\"']\", thisform).attr('aria-invalid', 'false');\r\n      $(\"[name='\"+fieldName+\"']\", thisform).removeAttr('aria-describedby');\r\n      removeGroupErrors(field, fieldName, true); \/\/ animate=true\r\n    } else if (!isChecked && !hasError && submitAttempted) {\r\n      \/\/ Invalid now and we've attempted submit - show error\r\n      var errorId = getGroupErrorId(field);\r\n      groupContainer.addClass('pfbc-invalid pfbc-element-has-error');\r\n      $(\"[name='\"+fieldName+\"']\", thisform).attr('aria-invalid', 'true');\r\n      $(\"[name='\"+fieldName+\"']\", thisform).attr('aria-describedby', errorId);\r\n      \r\n      var fieldLabel = getFieldLabel(groupContainer);\r\n      var firstField = $(\"[name='\"+fieldName+\"']\", thisform).first();\r\n      var errorMessage = getRequiredMessage(fieldLabel, firstField);\r\n      var inlineError = $('<div class=\"pfbc-inline-error\" id=\"' + errorId + '\" role=\"alert\" aria-live=\"polite\"><div class=\"pfbc-error-message\">' + errorMessage + '<\/div><\/div>');\r\n      \r\n      var lastInGroup = $(\"[name='\"+fieldName+\"']\", thisform).last();\r\n      var lastWrapper = lastInGroup.closest('.pfbc-radio, .pfbc-checkbox');\r\n      if (lastWrapper.length) {\r\n        lastWrapper.after(inlineError);\r\n      } else {\r\n        lastInGroup.after(inlineError);\r\n      }\r\n    }\r\n  });\r\n  \r\n  \/\/ Blur handler for text-like fields only\r\n  $('.accuaforms-field-required', thisform).on('blur', function() {\r\n    var field = $(this);\r\n    var type = field.attr('type');\r\n    var fieldName = field.attr('name');\r\n    var isEmpty = false;\r\n    \r\n    \/\/ Skip checkbox\/radio - handled by change event above\r\n    if (type === 'checkbox' || type === 'radio') return;\r\n    \r\n    var val = field.val();\r\n      if (typeof(val) == \"string\") {\r\n        \/\/ Treat \"-\" and \"Select...\" as invalid only for dropdowns\r\n        \/\/ For telephone fields, prefix-only values (e.g. \"+39\") are also empty\r\n        var isSelect = field.is('select');\r\n        isEmpty = val.match(\/^\\s*$\/) || (isSelect && (val === \"Select...\" || val === \"-\")) || isTelephonePrefixOnly(field);\r\n      } else if (typeof(val) == \"object\") {\r\n        isEmpty = !val || val.length === 0;\r\n      } else {\r\n        isEmpty = !val;\r\n      }\r\n      \r\n      var parent = field.closest('.pfbc-element, .pfbc-fieldwrap');\r\n      var errorId = field.attr('id') + '-error';\r\n      \r\n      if (isEmpty) {\r\n        \/\/ For telephone: phone-validation.js blur handler runs AFTER this one and may\r\n        \/\/ still have pfbc-element-has-error set from a previous format error. Check for\r\n        \/\/ the specific required error div instead of the parent class to avoid skipping.\r\n        var alreadyHasError = field.hasClass('accuaform-telephone')\r\n          ? $('#' + errorId).length > 0\r\n          : parent.hasClass('pfbc-element-has-error');\r\n        if (!alreadyHasError) {\r\n          \/\/ For telephone: remove leftover phone format error since the field is now\r\n          \/\/ empty (required error takes priority). phone-validation.js will also clean\r\n          \/\/ up on its blur, but this handler runs first.\r\n          if (field.hasClass('accuaform-telephone')) {\r\n            $('#' + field.attr('id') + '-phone-error').remove();\r\n          }\r\n          parent.addClass('pfbc-invalid pfbc-element-has-error');\r\n          field.attr('aria-invalid', 'true');\r\n          field.attr('aria-describedby', errorId);\r\n          \r\n          \/\/ Get field label for error message\r\n          var fieldLabel = getFieldLabel(parent);\r\n          var errorMessage = getRequiredMessage(fieldLabel, field);\r\n          var inlineError = $('<div class=\"pfbc-inline-error\" id=\"' + errorId + '\" role=\"alert\" aria-live=\"polite\"><div class=\"pfbc-error-message\">' + errorMessage + '<\/div><\/div>');\r\n          \r\n          \/\/ For file inputs with help text, insert error after help text\r\n          var helpText = field.siblings('.pfbc-help').last();\r\n          if (field.is('[type=\"file\"]') && helpText.length) {\r\n            helpText.after(inlineError);\r\n          } else {\r\n            field.after(inlineError);\r\n          }\r\n        }\r\n      } else {\r\n        \/\/ Field is not empty \u2014 clear required-related errors.\r\n        if (field.hasClass('accuaform-telephone')) {\r\n          \/\/ For telephone fields: clear only the required error ({id}-error).\r\n          \/\/ phone-validation.js has already run on this same blur event and set the\r\n          \/\/ correct error state (phone-error or clean). We must not undo its work.\r\n          \/\/ Only remove the required-error div; preserve phone-validation.js state.\r\n          $('#' + errorId).remove();\r\n          \/\/ If phone-validation.js left no errors, clear the container state too\r\n          if (!parent.find('.pfbc-inline-error').length) {\r\n            parent.removeClass('pfbc-invalid pfbc-element-has-error');\r\n            field.attr('aria-invalid', 'false');\r\n            field.removeAttr('aria-describedby');\r\n          }\r\n        } else {\r\n          \/\/ For non-telephone fields: animated removal for smoother UX\r\n          removeErrorAnimated(errorId);\r\n          parent.removeClass('pfbc-invalid pfbc-element-has-error');\r\n          field.attr('aria-invalid', 'false');\r\n          field.removeAttr('aria-describedby');\r\n        }\r\n      }\r\n  });\r\n  \r\n  $('.pfbc-textbox[type=\"email\"]', thisform).on('blur change', function() {\r\n    var field = $(this);\r\n    var val = field.val();\r\n    \r\n    if (val.match(\/^\\s*$\/)) {\r\n      return; \/\/ Empty is handled by required validation\r\n    }\r\n    \r\n    var isValid = val.match(\/^([a-zA-Z0-9_.+%-])+@(([a-zA-Z0-9-])+\\.)+([a-zA-Z0-9])+$\/);\r\n    var parent = field.closest('.pfbc-element, .pfbc-fieldwrap');\r\n    var errorId = field.attr('id') + '-error';\r\n    \r\n    if (!isValid) {\r\n      if (!parent.hasClass('pfbc-element-has-error')) {\r\n        parent.addClass('pfbc-invalid pfbc-element-has-error');\r\n        field.attr('aria-invalid', 'true');\r\n        field.attr('aria-describedby', errorId);\r\n        \r\n        \/\/ Get field label for error message\r\n        var fieldLabel = getFieldLabel(parent);\r\n        var errorMessage = getEmailMessage(fieldLabel, field);\r\n        var inlineError = $('<div class=\\\"pfbc-inline-error\\\" id=\\\"' + errorId + '\\\" role=\\\"alert\\\" aria-live=\\\"polite\\\"><div class=\\\"pfbc-error-message\\\">' + errorMessage + '<\/div><\/div>');\r\n        \r\n        \/\/ For file inputs with help text, insert error after help text\r\n        var helpText = field.siblings('.pfbc-help').last();\r\n        if (field.is('[type=\\\"file\\\"]') && helpText.length) {\r\n          helpText.after(inlineError);\r\n        } else {\r\n          field.after(inlineError);\r\n        }\r\n      }\r\n    } else {\r\n      parent.removeClass('pfbc-invalid pfbc-element-has-error');\r\n      field.attr('aria-invalid', 'false');\r\n      field.removeAttr('aria-describedby');\r\n      removeErrorAnimated(errorId);\r\n    }\r\n  });\r\n});\r\n\/\/ -->\r\n<\/script>\r\n<iframe id=\"submit_target_accua_form___accua_form__1_69e9d6979345b\" title=\"Notification Message\" name=\"submit_target_accua_form___accua_form__1_69e9d6979345b\" onload=\"_handle_ajax_submit_complete_accua_form___accua_form__1_69e9d6979345b()\" onerror=\"_handle_ajax_submit_complete_accua_form___accua_form__1_69e9d6979345b()\" style=\"width:0;height:0;border:0px solid #fff\"><\/iframe><script type=\"text\/javascript\">\r\n<!--\r\njQuery(function($){\r\n  var referrerfield = $(\"#accua-form___accua-form__1_69e9d6979345b input[name='_AccuaForm_referrer']\");\r\n  if (referrerfield.val() == '') {\r\n    referrerfield.val(document.referrer);\r\n  }\r\n  $(\"#accua-form___accua-form__1_69e9d6979345b input[name='_AccuaForm_user_agent']\").val(navigator.userAgent);\r\n  $(\"#accua-form___accua-form__1_69e9d6979345b input[name='_AccuaForm_platform']\").val(navigator.platform);\r\n});\r\n\/\/ -->\r\n<\/script>","protected":false},"excerpt":{"rendered":"<p>3CX tarjoaa taitavasti suunnitellun VoIP puhelinj\u00e4rjestelm\u00e4n.3CX PBX muokkautuu mink\u00e4 tahansa kokoisen yrityksen tarpeisiin sopivaksi. 3CX PBX on l\u00e4hes rajattomasti laajennettavissa.Ohjelmistot ja laitteet toimivat t\u00e4ydellisess\u00e4 harmoniassa kesken\u00e4\u00e4n, muodostaen laajan alustan yhdistetylle viestinn\u00e4lle.3CX PBX ratkaisu tarjoaa p\u00e4\u00e4telaitteita kaikkiin tarpeisiin &#8211; p\u00f6yt\u00e4puhelimet, langattomat puhelimet ja erikoispuhelimet sek\u00e4 monipuoliset ohjelmistotuotteet. My\u00f6s tavalliset lankapuhelimet ja faksit ilman VoIP-ominaisuuksia toimivat 3CX [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-2405","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/www.perustele.fi\/index.php\/wp-json\/wp\/v2\/pages\/2405","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.perustele.fi\/index.php\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/www.perustele.fi\/index.php\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/www.perustele.fi\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.perustele.fi\/index.php\/wp-json\/wp\/v2\/comments?post=2405"}],"version-history":[{"count":12,"href":"https:\/\/www.perustele.fi\/index.php\/wp-json\/wp\/v2\/pages\/2405\/revisions"}],"predecessor-version":[{"id":2919,"href":"https:\/\/www.perustele.fi\/index.php\/wp-json\/wp\/v2\/pages\/2405\/revisions\/2919"}],"wp:attachment":[{"href":"https:\/\/www.perustele.fi\/index.php\/wp-json\/wp\/v2\/media?parent=2405"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}