{"id":2089,"date":"2026-05-13T20:09:45","date_gmt":"2026-05-13T20:09:45","guid":{"rendered":"https:\/\/millepiani.com\/nuova-pagina-elevators\/"},"modified":"2026-09-11T00:29:16","modified_gmt":"2026-09-11T00:29:16","slug":"nuova-pagina-elevators","status":"publish","type":"page","link":"https:\/\/millepiani.com\/en\/","title":{"rendered":"Nuova pagina elevators"},"content":{"rendered":"\t\t<div data-elementor-type=\"wp-page\" data-elementor-id=\"2089\" class=\"elementor elementor-2089 elementor-219\" data-elementor-post-type=\"page\">\n\t\t\t\t<div class=\"elementor-element elementor-element-3046b07 e-con-full e-flex e-con e-parent\" data-id=\"3046b07\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t<div class=\"elementor-element elementor-element-148a94c elementor-widget elementor-widget-html\" data-id=\"148a94c\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t\t<!-- GOOGLE FONTS -->\r\n<link rel=\"preconnect\" href=\"https:\/\/fonts.googleapis.com\">\r\n<link rel=\"preconnect\" href=\"https:\/\/fonts.gstatic.com\" crossorigin>\r\n<link\r\n  href=\"https:\/\/fonts.googleapis.com\/css2?family=Afacad+Flux:wght@100..1000&display=swap\"\r\n  rel=\"stylesheet\"\r\n>\r\n\r\n<div id=\"mp-fullpage-wrapper\">\r\n\r\n  <!-- SLIDE 01: HOME -->\r\n  <section class=\"section mp-slide-section mp-dark-slide active\">\r\n    <div\r\n      class=\"mp-bg\"\r\n      style=\"background-image: url('https:\/\/millepiani.com\/wp-content\/uploads\/2026\/06\/millepiani.jpg');\"\r\n    ><\/div>\r\n\r\n    <div class=\"mp-overlay mp-overlay-home\"><\/div>\r\n\r\n    <div class=\"mp-content mp-home-content\">\r\n      <p class=\"mp-kicker\">\r\n        WE DESIGN AND MANUFACTURE\r\n      <\/p>\r\n\r\n      <h1>\r\n        LIFTS, GOODS LIFTS AND ESCALATORS FOR EFFICIENT\r\n        AND SAFE MOBILITY\r\n      <\/h1>\r\n\r\n      <p class=\"mp-desc\">\r\n        We assess the requirements of every type of building and\r\n        provide the most suitable solution for each customer, from\r\n        design through to final installation.\r\n      <\/p>\r\n    <\/div>\r\n  <\/section>\r\n\r\n  <!-- SLIDE 02: ASCENSORI -->\r\n  <section class=\"section mp-slide-section mp-dark-slide\">\r\n    <div\r\n      class=\"mp-bg\"\r\n      style=\"background-image: url('https:\/\/millepiani.com\/wp-content\/uploads\/2026\/06\/Experience-copia-1-1.png');\"\r\n    ><\/div>\r\n\r\n    <div class=\"mp-overlay\"><\/div>\r\n\r\n    <div class=\"mp-content\">\r\n      <h2>LIFTS<\/h2>\r\n\r\n      <p class=\"mp-desc\">\r\n        We design and manufacture lifts that combine design,\r\n        comfort and outstanding reliability. Solutions developed for\r\n        residential and commercial buildings and public facilities,\r\n        delivering maximum safety, energy savings and lasting\r\n        quality.\r\n      <\/p>\r\n\r\n      <a\r\n        href=\"https:\/\/millepiani.com\/ascensori\/\"\r\n        class=\"mp-btn\"\r\n      >\r\n        FIND OUT MORE\r\n\r\n        <span>\r\n          <img decoding=\"async\"\r\n            src=\"https:\/\/millepiani.com\/wp-content\/uploads\/2026\/05\/lsicon_arrow-left-outline.png\"\r\n            alt=\"\"\r\n          >\r\n        <\/span>\r\n      <\/a>\r\n    <\/div>\r\n  <\/section>\r\n\r\n  <!-- SLIDE 03: PIATTAFORME ELEVATRICI -->\r\n  <section class=\"section mp-slide-section mp-dark-slide\">\r\n    <div\r\n      class=\"mp-bg\"\r\n      style=\"background-image: url('https:\/\/millepiani.com\/wp-content\/uploads\/2026\/05\/image-7-1.jpg');\"\r\n    ><\/div>\r\n\r\n    <div class=\"mp-overlay\"><\/div>\r\n\r\n    <div class=\"mp-content\">\r\n      <h2>\r\n        PLATFORM<br>\r\n        <span>LIFTS<\/span>\r\n      <\/h2>\r\n\r\n      <p class=\"mp-desc\">\r\n        Designed for intuitive operation and compliance with\r\n        safety standards, Millepiani platform lifts can\r\n        be operated independently.\r\n      <\/p>\r\n\r\n      <a\r\n        href=\"https:\/\/millepiani.com\/piattaforme-elevatrici\/\"\r\n        class=\"mp-btn\"\r\n      >\r\n        FIND OUT MORE\r\n\r\n        <span>\r\n          <img decoding=\"async\"\r\n            src=\"https:\/\/millepiani.com\/wp-content\/uploads\/2026\/05\/lsicon_arrow-left-outline.png\"\r\n            alt=\"\"\r\n          >\r\n        <\/span>\r\n      <\/a>\r\n    <\/div>\r\n  <\/section>\r\n\r\n  <!-- SLIDE 04: MONTACARICHI -->\r\n  <section class=\"section mp-slide-section mp-dark-slide\">\r\n    <div\r\n      class=\"mp-bg\"\r\n      style=\"background-image: url('https:\/\/millepiani.com\/wp-content\/uploads\/2026\/05\/Rectangle_3.png');\"\r\n    ><\/div>\r\n\r\n    <div class=\"mp-overlay\"><\/div>\r\n\r\n    <div class=\"mp-content\">\r\n      <h2>GOODS LIFTS<\/h2>\r\n\r\n      <p class=\"mp-desc\">\r\n        Simple, robust and safe: Hercules is the ideal solution\r\n        for transporting goods and people between floors.\r\n      <\/p>\r\n\r\n      <a\r\n        href=\"https:\/\/millepiani.com\/montacarichi\/\"\r\n        class=\"mp-btn\"\r\n      >\r\n        FIND OUT MORE\r\n\r\n        <span>\r\n          <img decoding=\"async\"\r\n            src=\"https:\/\/millepiani.com\/wp-content\/uploads\/2026\/05\/lsicon_arrow-left-outline.png\"\r\n            alt=\"\"\r\n          >\r\n        <\/span>\r\n      <\/a>\r\n    <\/div>\r\n  <\/section>\r\n\r\n  <!-- SLIDE 05: TAPPETI E SCALE MOBILI -->\r\n  <section class=\"section mp-slide-section mp-dark-slide\">\r\n    <div\r\n      class=\"mp-bg\"\r\n      style=\"background-image: url('https:\/\/millepiani.com\/wp-content\/uploads\/2026\/05\/image_8.png');\"\r\n    ><\/div>\r\n\r\n    <div class=\"mp-overlay\"><\/div>\r\n\r\n    <div class=\"mp-content\">\r\n      <h2>MOVING WALKWAYS AND ESCALATORS<\/h2>\r\n\r\n      <p class=\"mp-desc\">\r\n        A range of escalators offering vertical transport\r\n        and automated mobility solutions for public\r\n        and private settings.\r\n      <\/p>\r\n\r\n      <a\r\n        href=\"https:\/\/millepiani.com\/tappeti-e-scale-mobili\/\"\r\n        class=\"mp-btn\"\r\n      >\r\n        FIND OUT MORE\r\n\r\n        <span>\r\n          <img decoding=\"async\"\r\n            src=\"https:\/\/millepiani.com\/wp-content\/uploads\/2026\/05\/lsicon_arrow-left-outline.png\"\r\n            alt=\"\"\r\n          >\r\n        <\/span>\r\n      <\/a>\r\n    <\/div>\r\n  <\/section>\r\n\r\n  <!-- SLIDE 06: SERVOSCALE -->\r\n  <section class=\"section mp-slide-section mp-dark-slide\">\r\n    <div\r\n      class=\"mp-bg\"\r\n      style=\"background-image: url('https:\/\/millepiani.com\/wp-content\/uploads\/2026\/05\/image_9.png');\"\r\n    ><\/div>\r\n\r\n    <div class=\"mp-overlay\"><\/div>\r\n\r\n    <div class=\"mp-content\">\r\n      <h2>STAIRLIFTS<\/h2>\r\n\r\n      <p class=\"mp-desc\">\r\n        A practical and safe solution for comfortable travel\r\n        between floors: a new standard in automated mobility\r\n        for modern buildings.\r\n      <\/p>\r\n\r\n      <a\r\n        href=\"https:\/\/millepiani.com\/servoscale\/\"\r\n        class=\"mp-btn\"\r\n      >\r\n        FIND OUT MORE\r\n\r\n        <span>\r\n          <img decoding=\"async\"\r\n            src=\"https:\/\/millepiani.com\/wp-content\/uploads\/2026\/05\/lsicon_arrow-left-outline.png\"\r\n            alt=\"\"\r\n          >\r\n        <\/span>\r\n      <\/a>\r\n    <\/div>\r\n  <\/section>\r\n\r\n  <!-- SLIDE 07: MODERNIZZAZIONE ASCENSORI -->\r\n  <section class=\"section mp-slide-section mp-dark-slide\">\r\n    <div\r\n      class=\"mp-bg\"\r\n      style=\"background-image: url('https:\/\/millepiani.com\/wp-content\/uploads\/2026\/05\/image_10.png');\"\r\n    ><\/div>\r\n\r\n    <div class=\"mp-overlay\"><\/div>\r\n\r\n    <div class=\"mp-content\">\r\n      <h2>LIFT MODERNISATION<\/h2>\r\n\r\n      <p class=\"mp-desc\">\r\n        A comprehensive consultancy and system upgrade service\r\n        designed to improve the performance and safety of\r\n        vertical transport.\r\n      <\/p>\r\n\r\n      <a\r\n        href=\"https:\/\/millepiani.com\/modernizzazioni-ascensori\/\"\r\n        class=\"mp-btn\"\r\n      >\r\n        FIND OUT MORE\r\n\r\n        <span>\r\n          <img decoding=\"async\"\r\n            src=\"https:\/\/millepiani.com\/wp-content\/uploads\/2026\/05\/lsicon_arrow-left-outline.png\"\r\n            alt=\"\"\r\n          >\r\n        <\/span>\r\n      <\/a>\r\n    <\/div>\r\n  <\/section>\r\n\r\n  <!-- SLIDE 08: PARTI ELETTRICHE -->\r\n  <section class=\"section mp-slide-section mp-dark-slide\">\r\n    <div\r\n      class=\"mp-bg\"\r\n      style=\"background-image: url('https:\/\/millepiani.com\/wp-content\/uploads\/2026\/05\/image-5-1-1-1.jpg');\"\r\n    ><\/div>\r\n\r\n    <div class=\"mp-overlay\"><\/div>\r\n\r\n    <div class=\"mp-content\">\r\n      <h2>ELECTRICAL COMPONENTS<\/h2>\r\n\r\n      <p class=\"mp-desc\">\r\n        Versatile, space-saving control panels and electrical\r\n        components designed to simplify the system and improve\r\n        automated mobility.\r\n      <\/p>\r\n\r\n      <a\r\n        href=\"https:\/\/millepiani.com\/parti-elettriche\/\"\r\n        class=\"mp-btn\"\r\n      >\r\n        FIND OUT MORE\r\n\r\n        <span>\r\n          <img decoding=\"async\"\r\n            src=\"https:\/\/millepiani.com\/wp-content\/uploads\/2026\/05\/lsicon_arrow-left-outline.png\"\r\n            alt=\"\"\r\n          >\r\n        <\/span>\r\n      <\/a>\r\n    <\/div>\r\n  <\/section>\r\n\r\n  <!-- SLIDE 09: SERVIZI -->\r\n  <section class=\"section mp-slide-section mp-services-section\">\r\n    <div class=\"mp-services-wrap\">\r\n\r\n      <div class=\"mp-services-left\">\r\n        <p class=\"mp-about\">ABOUT US<\/p>\r\n\r\n        <h2>\r\n          OUR<br>\r\n          <strong>SERVICES<\/strong>\r\n        <\/h2>\r\n\r\n        <div class=\"mp-tabs\">\r\n          <button\r\n            class=\"mp-tab is-active\"\r\n            type=\"button\"\r\n            data-tab=\"assistenza\"\r\n          >\r\n            SUPPORT\r\n          <\/button>\r\n\r\n          <button\r\n            class=\"mp-tab\"\r\n            type=\"button\"\r\n            data-tab=\"manutenzione\"\r\n          >\r\n            MAINTENANCE\r\n          <\/button>\r\n\r\n          <button\r\n            class=\"mp-tab\"\r\n            type=\"button\"\r\n            data-tab=\"agevolazioni\"\r\n          >\r\n            TAX INCENTIVES\r\n          <\/button>\r\n        <\/div>\r\n\r\n        <div class=\"mp-tab-panels\">\r\n          <div\r\n            class=\"mp-tab-panel is-active\"\r\n            data-panel=\"assistenza\"\r\n          >\r\n            A properly functioning system provides\r\n            safety and peace of mind and ensures\r\n            freedom of movement. Prompt service\r\n            minimises disruption, while regular\r\n            inspections keep the system performing\r\n            consistently.\r\n          <\/div>\r\n\r\n          <div\r\n            class=\"mp-tab-panel\"\r\n            data-panel=\"manutenzione\"\r\n          >\r\n            A scheduled maintenance service helps\r\n            preserve the system's efficiency, safety and\r\n            reliability over time. Our specialist technicians\r\n            carry out regular inspections,\r\n            functional checks and preventive maintenance.\r\n          <\/div>\r\n\r\n          <div\r\n            class=\"mp-tab-panel\"\r\n            data-panel=\"agevolazioni\"\r\n          >\r\n            We offer dedicated advice to identify the\r\n            tax incentives available for the\r\n            installation, replacement or modernisation\r\n            of systems.\r\n          <\/div>\r\n        <\/div>\r\n\r\n        <a href=\"#preventivo\" class=\"mp-info-btn\">\r\n          REQUEST INFORMATION\r\n        <\/a>\r\n      <\/div>\r\n\r\n      <div\r\n        class=\"mp-services-image\"\r\n        style=\"background-image: url('https:\/\/millepiani.com\/wp-content\/uploads\/2026\/05\/IMG_5885-scaled.jpg');\"\r\n      ><\/div>\r\n\r\n    <\/div>\r\n  <\/section>\r\n\r\n  <!-- SLIDE 10: PREVENTIVO -->\r\n  <section\r\n    class=\"section mp-quote-section mp-quote-compact mp-quote-desktop-stack\"\r\n    id=\"preventivo\"\r\n  >\r\n    <div class=\"mp-quote-bg\"><\/div>\r\n    <div class=\"mp-quote-overlay\"><\/div>\r\n\r\n    <div class=\"mp-quote-inner\">\r\n\r\n      <!-- INFORMAZIONI E CONTATTI -->\r\n      <div class=\"mp-quote-info\">\r\n        <p class=\"mp-quote-kicker\">Contact us<\/p>\r\n\r\n        <h2 class=\"mp-quote-title\">\r\n          Request a<br>\r\n          free<br>\r\n          quote\r\n        <\/h2>\r\n\r\n        <p class=\"mp-quote-description\">\r\n          Are you interested in our products or looking for\r\n          a personalised solution designed specifically\r\n          for you? Get in touch: we are here\r\n          to assist you and help you choose\r\n          the solution that best meets your needs.\r\n        <\/p>\r\n\r\n        <div class=\"mp-quote-contacts\">\r\n\r\n          <a\r\n            href=\"tel:+390296690901\"\r\n            class=\"mp-quote-contact\"\r\n          >\r\n            <span class=\"mp-quote-contact-icon\">\r\n              <svg viewBox=\"0 0 24 24\" aria-hidden=\"true\">\r\n                <path\r\n                  d=\"M22 16.92v3a2 2 0 0 1-2.18 2A19.86 19.86 0 0 1 11.19 19 19.5 19.5 0 0 1 5 12.81 19.86 19.86 0 0 1 2.08 4.18 2 2 0 0 1 4.06 2h3a2 2 0 0 1 2 1.72c.12.9.33 1.78.62 2.63a2 2 0 0 1-.45 2.11L8 9.69a16 16 0 0 0 6.31 6.31l1.23-1.23a2 2 0 0 1 2.11-.45c.85.29 1.73.5 2.63.62A2 2 0 0 1 22 16.92z\"\r\n                ><\/path>\r\n              <\/svg>\r\n            <\/span>\r\n\r\n            <span>\r\n              <strong>Phone<\/strong>\r\n              +39 02 96690901\r\n            <\/span>\r\n          <\/a>\r\n\r\n          <a\r\n            href=\"mailto:info@millepiani.com\"\r\n            class=\"mp-quote-contact\"\r\n          >\r\n            <span class=\"mp-quote-contact-icon\">\r\n              <svg viewBox=\"0 0 24 24\" aria-hidden=\"true\">\r\n                <path\r\n                  d=\"M4 4h16a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2z\"\r\n                ><\/path>\r\n                <path d=\"m22 6-10 7L2 6\"><\/path>\r\n              <\/svg>\r\n            <\/span>\r\n\r\n            <span>\r\n              <strong>E-mail<\/strong>\r\n              info@millepiani.com\r\n            <\/span>\r\n          <\/a>\r\n\r\n          <div class=\"mp-quote-contact\">\r\n            <span class=\"mp-quote-contact-icon\">\r\n              <svg viewBox=\"0 0 24 24\" aria-hidden=\"true\">\r\n                <path\r\n                  d=\"M21 10c0 7-9 12-9 12S3 17 3 10a9 9 0 0 1 18 0z\"\r\n                ><\/path>\r\n                <circle cx=\"12\" cy=\"10\" r=\"3\"><\/circle>\r\n              <\/svg>\r\n            <\/span>\r\n\r\n            <span>\r\n              <strong>Office<\/strong>\r\n              Via Della Longura, 21 Misinto MB\r\n            <\/span>\r\n          <\/div>\r\n\r\n        <\/div>\r\n      <\/div>\r\n\r\n      <!-- MODULO PREVENTIVO -->\r\n      <div class=\"mp-quote-form-card\">\r\n        <form\r\n          class=\"mp-quote-form\"\r\n          id=\"mpQuoteForm\"\r\n          enctype=\"multipart\/form-data\"\r\n          data-success-url=\"\/grazie\/\"\r\n          novalidate\r\n        >\r\n          <div\r\n            class=\"mp-form-status\"\r\n            id=\"mpFormStatus\"\r\n            aria-live=\"polite\"\r\n          ><\/div>\r\n\r\n          <!-- DATI PERSONALI E SOCIET\u00c0 -->\r\n          <div class=\"mp-form-grid\">\r\n\r\n            <div class=\"mp-field\">\r\n              <input\r\n                type=\"text\"\r\n                name=\"name\"\r\n                id=\"mpName\"\r\n                placeholder=\" \"\r\n                required\r\n                autocomplete=\"given-name\"\r\n              >\r\n              <label for=\"mpName\">First name *<\/label>\r\n            <\/div>\r\n\r\n            <div class=\"mp-field\">\r\n              <input\r\n                type=\"text\"\r\n                name=\"surname\"\r\n                id=\"mpSurname\"\r\n                placeholder=\" \"\r\n                required\r\n                autocomplete=\"family-name\"\r\n              >\r\n              <label for=\"mpSurname\">Last name *<\/label>\r\n            <\/div>\r\n\r\n            <div class=\"mp-field\">\r\n              <input\r\n                type=\"email\"\r\n                name=\"email\"\r\n                id=\"mpEmail\"\r\n                placeholder=\" \"\r\n                required\r\n                autocomplete=\"email\"\r\n              >\r\n              <label for=\"mpEmail\">E-mail *<\/label>\r\n            <\/div>\r\n\r\n            <div class=\"mp-field\">\r\n              <input\r\n                type=\"tel\"\r\n                name=\"phone\"\r\n                id=\"mpPhone\"\r\n                placeholder=\" \"\r\n                required\r\n                autocomplete=\"tel\"\r\n              >\r\n              <label for=\"mpPhone\">Phone number *<\/label>\r\n            <\/div>\r\n\r\n            <div class=\"mp-field\">\r\n              <select name=\"role\" id=\"mpRole\">\r\n                <option value=\"\" selected>Select<\/option>\r\n                <option value=\"progettista\">Designer<\/option>\r\n\r\n                <option value=\"impresa_di_costruzioni\">\r\n                  Construction company\r\n                <\/option>\r\n\r\n                <option value=\"proprietario_edificio\">\r\n                  Building owner\r\n                <\/option>\r\n\r\n                <option value=\"amministratore_edificio\">\r\n                  Building manager\r\n                <\/option>\r\n\r\n                <option value=\"consulente_ascensori\">\r\n                  Lift consultant\r\n                <\/option>\r\n\r\n                <option value=\"ente_pubblico\">Public body<\/option>\r\n                <option value=\"cerco_lavoro\">Job seeker<\/option>\r\n\r\n                <option value=\"utente_passeggero\">\r\n                  User\/Passenger\r\n                <\/option>\r\n\r\n                <option value=\"studente\">Student<\/option>\r\n                <option value=\"altro\">Other<\/option>\r\n              <\/select>\r\n\r\n              <label for=\"mpRole\">What is your role?<\/label>\r\n            <\/div>\r\n\r\n            <div class=\"mp-field\">\r\n              <input\r\n                type=\"text\"\r\n                name=\"company\"\r\n                id=\"mpCompany\"\r\n                placeholder=\" \"\r\n                autocomplete=\"organization\"\r\n              >\r\n              <label for=\"mpCompany\">Company name<\/label>\r\n            <\/div>\r\n\r\n          <\/div>\r\n\r\n          <!-- PAESE, PROVINCIA E CITT\u00c0 -->\r\n          <div class=\"mp-form-grid mp-location-grid\">\r\n\r\n            <div class=\"mp-field\">\r\n              <select\r\n                name=\"country\"\r\n                id=\"mpCountry\"\r\n                required\r\n                autocomplete=\"country-name\"\r\n              >\r\n                <option value=\"Italia\" selected>Italy<\/option>\r\n                <option value=\"Estero\">Outside Italy<\/option>\r\n              <\/select>\r\n\r\n              <label for=\"mpCountry\">Country\/Region *<\/label>\r\n            <\/div>\r\n\r\n            <div class=\"mp-field\">\r\n              <select\r\n                name=\"province\"\r\n                id=\"mpProvince\"\r\n                required\r\n                autocomplete=\"address-level2\"\r\n              >\r\n                <option value=\"\" selected disabled>Select<\/option>\r\n\r\n                <option value=\"AG\">Agrigento<\/option>\r\n                <option value=\"AL\">Alessandria<\/option>\r\n                <option value=\"AN\">Ancona<\/option>\r\n                <option value=\"AO\">Aosta<\/option>\r\n                <option value=\"AR\">Arezzo<\/option>\r\n                <option value=\"AP\">Ascoli Piceno<\/option>\r\n                <option value=\"AT\">Asti<\/option>\r\n                <option value=\"AV\">Avellino<\/option>\r\n                <option value=\"BA\">Bari<\/option>\r\n                <option value=\"BT\">Barletta-Andria-Trani<\/option>\r\n                <option value=\"BL\">Belluno<\/option>\r\n                <option value=\"BN\">Benevento<\/option>\r\n                <option value=\"BG\">Bergamo<\/option>\r\n                <option value=\"BI\">Biella<\/option>\r\n                <option value=\"BO\">Bologna<\/option>\r\n                <option value=\"BZ\">Bolzano<\/option>\r\n                <option value=\"BS\">Brescia<\/option>\r\n                <option value=\"BR\">Brindisi<\/option>\r\n                <option value=\"CA\">Cagliari<\/option>\r\n                <option value=\"CL\">Caltanissetta<\/option>\r\n                <option value=\"CB\">Campobasso<\/option>\r\n                <option value=\"CE\">Caserta<\/option>\r\n                <option value=\"CT\">Catania<\/option>\r\n                <option value=\"CZ\">Catanzaro<\/option>\r\n                <option value=\"CH\">Chieti<\/option>\r\n                <option value=\"CO\">Como<\/option>\r\n                <option value=\"CS\">Cosenza<\/option>\r\n                <option value=\"CR\">Cremona<\/option>\r\n                <option value=\"KR\">Crotone<\/option>\r\n                <option value=\"CN\">Cuneo<\/option>\r\n                <option value=\"EN\">Enna<\/option>\r\n                <option value=\"FM\">Fermo<\/option>\r\n                <option value=\"FE\">Ferrara<\/option>\r\n                <option value=\"FI\">Florence<\/option>\r\n                <option value=\"FG\">Foggia<\/option>\r\n                <option value=\"FC\">Forl\u00ec-Cesena<\/option>\r\n                <option value=\"FR\">Frosinone<\/option>\r\n                <option value=\"GE\">Genoa<\/option>\r\n                <option value=\"GO\">Gorizia<\/option>\r\n                <option value=\"GR\">Grosseto<\/option>\r\n                <option value=\"IM\">Imperia<\/option>\r\n                <option value=\"IS\">Isernia<\/option>\r\n                <option value=\"SP\">La Spezia<\/option>\r\n                <option value=\"AQ\">L'Aquila<\/option>\r\n                <option value=\"LT\">Latina<\/option>\r\n                <option value=\"LE\">Lecce<\/option>\r\n                <option value=\"LC\">Lecco<\/option>\r\n                <option value=\"LI\">Livorno<\/option>\r\n                <option value=\"LO\">Lodi<\/option>\r\n                <option value=\"LU\">Lucca<\/option>\r\n                <option value=\"MC\">Macerata<\/option>\r\n                <option value=\"MN\">Mantua<\/option>\r\n                <option value=\"MS\">Massa-Carrara<\/option>\r\n                <option value=\"MT\">Matera<\/option>\r\n                <option value=\"ME\">Messina<\/option>\r\n                <option value=\"MI\">Milan<\/option>\r\n                <option value=\"MO\">Modena<\/option>\r\n                <option value=\"MB\">Monza and Brianza<\/option>\r\n                <option value=\"NA\">Naples<\/option>\r\n                <option value=\"NO\">Novara<\/option>\r\n                <option value=\"NU\">Nuoro<\/option>\r\n                <option value=\"OR\">Oristano<\/option>\r\n                <option value=\"PD\">Padua<\/option>\r\n                <option value=\"PA\">Palermo<\/option>\r\n                <option value=\"PR\">Parma<\/option>\r\n                <option value=\"PV\">Pavia<\/option>\r\n                <option value=\"PG\">Perugia<\/option>\r\n                <option value=\"PU\">Pesaro and Urbino<\/option>\r\n                <option value=\"PE\">Pescara<\/option>\r\n                <option value=\"PC\">Piacenza<\/option>\r\n                <option value=\"PI\">Pisa<\/option>\r\n                <option value=\"PT\">Pistoia<\/option>\r\n                <option value=\"PN\">Pordenone<\/option>\r\n                <option value=\"PZ\">Potenza<\/option>\r\n                <option value=\"PO\">Prato<\/option>\r\n                <option value=\"RG\">Ragusa<\/option>\r\n                <option value=\"RA\">Ravenna<\/option>\r\n                <option value=\"RC\">Reggio Calabria<\/option>\r\n                <option value=\"RE\">Reggio Emilia<\/option>\r\n                <option value=\"RI\">Rieti<\/option>\r\n                <option value=\"RN\">Rimini<\/option>\r\n                <option value=\"RM\">Rome<\/option>\r\n                <option value=\"RO\">Rovigo<\/option>\r\n                <option value=\"SA\">Salerno<\/option>\r\n                <option value=\"SS\">Sassari<\/option>\r\n                <option value=\"SV\">Savona<\/option>\r\n                <option value=\"SI\">Siena<\/option>\r\n                <option value=\"SR\">Syracuse<\/option>\r\n                <option value=\"SO\">Sondrio<\/option>\r\n                <option value=\"SU\">South Sardinia<\/option>\r\n                <option value=\"TA\">Taranto<\/option>\r\n                <option value=\"TE\">Teramo<\/option>\r\n                <option value=\"TR\">Terni<\/option>\r\n                <option value=\"TO\">Turin<\/option>\r\n                <option value=\"TP\">Trapani<\/option>\r\n                <option value=\"TN\">Trento<\/option>\r\n                <option value=\"TV\">Treviso<\/option>\r\n                <option value=\"TS\">Trieste<\/option>\r\n                <option value=\"UD\">Udine<\/option>\r\n                <option value=\"VA\">Varese<\/option>\r\n                <option value=\"VE\">Venice<\/option>\r\n                <option value=\"VB\">Verbano-Cusio-Ossola<\/option>\r\n                <option value=\"VC\">Vercelli<\/option>\r\n                <option value=\"VR\">Verona<\/option>\r\n                <option value=\"VV\">Vibo Valentia<\/option>\r\n                <option value=\"VI\">Vicenza<\/option>\r\n                <option value=\"VT\">Viterbo<\/option>\r\n\r\n                <option value=\"estero\">Province outside Italy<\/option>\r\n              <\/select>\r\n\r\n              <label for=\"mpProvince\">Province *<\/label>\r\n            <\/div>\r\n\r\n            <div class=\"mp-field\">\r\n              <input\r\n                type=\"text\"\r\n                name=\"city\"\r\n                id=\"mpCity\"\r\n                placeholder=\" \"\r\n                required\r\n                autocomplete=\"address-level2\"\r\n              >\r\n              <label for=\"mpCity\">City *<\/label>\r\n            <\/div>\r\n\r\n          <\/div>\r\n\r\n          <!-- MOTIVO DELLA RICHIESTA -->\r\n          <div class=\"mp-field mp-field-full\">\r\n            <select\r\n              name=\"contact_reason\"\r\n              id=\"mpContactReason\"\r\n              required\r\n            >\r\n              <option value=\"\" selected disabled>Select<\/option>\r\n\r\n              <option value=\"nuovo_impianto\">\r\n                Installation of a new system in a new\/existing building\r\n              <\/option>\r\n\r\n              <option value=\"sostituzione_ascensore\">\r\n                Replacement of an existing lift\r\n              <\/option>\r\n\r\n              <option value=\"ammodernamento_impianto\">\r\n                Modernisation of a system\r\n              <\/option>\r\n\r\n              <option value=\"assistenza_manutenzione\">\r\n                I am interested in support and maintenance services\r\n              <\/option>\r\n\r\n              <option value=\"ricambi\">\r\n                Spare parts for Millepiani lifts\r\n              <\/option>\r\n\r\n              <option value=\"altro\">\r\n                Other\r\n              <\/option>\r\n            <\/select>\r\n\r\n            <label for=\"mpContactReason\">\r\n              What would you like us to contact you about? *\r\n            <\/label>\r\n          <\/div>\r\n\r\n          <!-- MESSAGGIO -->\r\n          <div class=\"mp-field mp-field-full\">\r\n            <textarea\r\n              name=\"message\"\r\n              id=\"mpMessage\"\r\n              rows=\"4\"\r\n              placeholder=\" \"\r\n            ><\/textarea>\r\n\r\n            <label for=\"mpMessage\">\r\n              How can we help you?\r\n            <\/label>\r\n          <\/div>\r\n\r\n          <!-- PRIVACY, CAPTCHA E INVIO -->\r\n          <div class=\"mp-form-foot\">\r\n\r\n            <div class=\"mp-privacy-box\">\r\n              <label\r\n                class=\"mp-privacy-check\"\r\n                for=\"mpPrivacyAcceptance\"\r\n              >\r\n                <input\r\n                  type=\"checkbox\"\r\n                  name=\"privacy_acceptance\"\r\n                  id=\"mpPrivacyAcceptance\"\r\n                  value=\"accepted\"\r\n                  required\r\n                >\r\n\r\n                <span>\r\n                  I accept the\r\n                  <a\r\n                    href=\"\/privacy-policy\/\"\r\n                    target=\"_blank\"\r\n                    rel=\"noopener noreferrer\"\r\n                  >\r\n                    Privacy Policy\r\n                  <\/a>. *\r\n                <\/span>\r\n              <\/label>\r\n\r\n              <label\r\n                class=\"mp-privacy-check\"\r\n                for=\"mpExistingContract\"\r\n              >\r\n                <input\r\n                  type=\"checkbox\"\r\n                  name=\"existing_contract\"\r\n                  id=\"mpExistingContract\"\r\n                  value=\"yes\"\r\n                >\r\n\r\n                <span>\r\n                  I already have an active contract with Millepiani\r\n                <\/span>\r\n              <\/label>\r\n            <\/div>\r\n\r\n            <div class=\"mp-captcha\">\r\n              <div\r\n                class=\"g-recaptcha\"\r\n                data-sitekey=\"6LfxY6ktAAAAAFBbvnofa2IpjG_zaaX5UdOtJuTS\"\r\n              ><\/div>\r\n            <\/div>\r\n\r\n            <button\r\n              type=\"submit\"\r\n              class=\"mp-submit-btn\"\r\n            >\r\n              <span>Send message<\/span>\r\n            <\/button>\r\n\r\n          <\/div>\r\n        <\/form>\r\n      <\/div>\r\n\r\n    <\/div>\r\n  <\/section>\r\n\r\n<\/div>\r\n\r\n<!-- GSAP: mantieni un solo caricamento, prima del nuovo JavaScript. -->\r\n<script src=\"https:\/\/cdnjs.cloudflare.com\/ajax\/libs\/gsap\/3.12.5\/gsap.min.js\"><\/script>\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-60597c6 elementor-widget elementor-widget-shortcode\" data-id=\"60597c6\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"shortcode.default\">\n\t\t\t\t\t\t\t<div class=\"elementor-shortcode\"><script>\/*\r\n * MILLEPIANI FULLSCREEN\r\n *\r\n * Desktop: navigazione a sezioni con fade all'arrivo.\r\n * Mobile: tutte le sezioni visibili e scorrimento normale.\r\n *\r\n * Sostituisce completamente il JavaScript precedente.\r\n * Mantieni HTML, CSS e caricamento di GSAP.\r\n *\/\r\n\r\n(() => {\r\n  'use strict';\r\n\r\n  function boot() {\r\n    const wrapper = document.querySelector('#mp-fullpage-wrapper');\r\n\r\n    if (!wrapper) return;\r\n    if (wrapper.dataset.mpNativeReady === 'v2-mobile') return;\r\n\r\n    if (wrapper.dataset.mpNativeReady) {\r\n      console.error(\r\n        'Millepiani: rimuovere il vecchio JavaScript prima di caricare questa versione.'\r\n      );\r\n      return;\r\n    }\r\n\r\n    wrapper.dataset.mpNativeReady = 'v2-mobile';\r\n\r\n    const originalParent = wrapper.parentNode;\r\n    const originalNext = wrapper.nextSibling;\r\n\r\n    let configured = false;\r\n    let desktopMode = false;\r\n    let pointerActive = false;\r\n    let resizeTimer = 0;\r\n\r\n    \/\/ Conserva gli stili modificati su mobile per ripristinarli su desktop.\r\n    const mobileStyleBackup = new Map();\r\n\r\n    \/* CSS DI FUNZIONAMENTO *\/\r\n\r\n    const mechanics = document.createElement('style');\r\n\r\n    mechanics.id = 'mp-fullscreen-v2-style';\r\n\r\n    mechanics.textContent = `\r\n      \/* DESKTOP *\/\r\n\r\n      html.mp-viewport-mode,\r\n      html.mp-viewport-mode body.mp-native-ready {\r\n        height: 100% !important;\r\n        overflow: hidden !important;\r\n        overscroll-behavior: none;\r\n      }\r\n\r\n      html.mp-viewport-mode body.mp-native-ready #mp-fullpage-wrapper {\r\n        position: fixed !important;\r\n        inset: var(--mp-fullscreen-top, 0px) 0 0 0 !important;\r\n        display: block !important;\r\n        height: calc(100vh - var(--mp-fullscreen-top, 0px)) !important;\r\n        height: calc(100dvh - var(--mp-fullscreen-top, 0px)) !important;\r\n        width: 100% !important;\r\n        min-height: 0 !important;\r\n        max-height: none !important;\r\n        margin: 0 !important;\r\n        padding: 0 !important;\r\n        border: 0 !important;\r\n        transform: none !important;\r\n        overflow-x: hidden !important;\r\n        overflow-y: auto !important;\r\n        overscroll-behavior: contain;\r\n        scroll-behavior: auto !important;\r\n        scroll-snap-type: none !important;\r\n        overflow-anchor: none;\r\n        z-index: var(--mp-fullscreen-layer, 1);\r\n      }\r\n\r\n      html.mp-viewport-mode body.mp-native-ready #mp-fullpage-wrapper > .section {\r\n        position: relative !important;\r\n        width: 100% !important;\r\n        height: auto !important;\r\n        min-height: var(--mp-screen-height, 100vh) !important;\r\n        max-height: none !important;\r\n        margin-top: 0 !important;\r\n        margin-bottom: 0 !important;\r\n        box-sizing: border-box;\r\n      }\r\n\r\n      html.mp-viewport-mode body.mp-native-ready #mp-fullpage-wrapper > .mp-footer,\r\n      html.mp-viewport-mode body.mp-native-ready #mp-fullpage-wrapper > .mp-footer-section {\r\n        min-height: 0 !important;\r\n        height: auto !important;\r\n      }\r\n\r\n      html.mp-viewport-mode body.mp-native-ready .mp-services-wrap,\r\n      html.mp-viewport-mode body.mp-native-ready #preventivo.mp-quote-desktop-stack .mp-quote-inner {\r\n        min-height: var(--mp-screen-height, 100vh) !important;\r\n        height: auto !important;\r\n      }\r\n\r\n      html.mp-viewport-mode body.mp-native-ready #mp-fullpage-wrapper .mp-quote-section {\r\n        overflow: visible !important;\r\n      }\r\n\r\n      html.mp-viewport-mode body.mp-native-ready #mp-fullpage-wrapper .mp-quote-bg,\r\n      html.mp-viewport-mode body.mp-native-ready #mp-fullpage-wrapper .mp-quote-overlay {\r\n        transform: none !important;\r\n      }\r\n\r\n      html.mp-viewport-mode body.mp-native-ready #mp-fullpage-wrapper .section:focus {\r\n        outline: none;\r\n      }\r\n\r\n      \/* MOBILE: PAGINA NORMALE E TUTTE LE SEZIONI VISIBILI *\/\r\n\r\n      html.mp-free-mobile,\r\n      html.mp-free-mobile body.mp-native-ready {\r\n        position: static !important;\r\n        height: auto !important;\r\n        max-height: none !important;\r\n        transform: none !important;\r\n        touch-action: auto !important;\r\n        scroll-snap-type: none !important;\r\n        overscroll-behavior: auto !important;\r\n      }\r\n\r\n      html.mp-free-mobile {\r\n        overflow-x: hidden !important;\r\n        overflow-y: auto !important;\r\n      }\r\n\r\n      html.mp-free-mobile body.mp-native-ready {\r\n        overflow: visible !important;\r\n      }\r\n\r\n      html.mp-free-mobile body.mp-native-ready #mp-fullpage-wrapper {\r\n        display: block !important;\r\n        position: relative !important;\r\n        inset: auto !important;\r\n        height: auto !important;\r\n        min-height: 0 !important;\r\n        max-height: none !important;\r\n        overflow: visible !important;\r\n        transform: none !important;\r\n        touch-action: auto !important;\r\n        scroll-snap-type: none !important;\r\n        overscroll-behavior: auto !important;\r\n      }\r\n\r\n      html.mp-free-mobile body.mp-native-ready #mp-fullpage-wrapper .section {\r\n        display: block !important;\r\n        position: relative !important;\r\n        inset: auto !important;\r\n        width: 100% !important;\r\n        height: auto !important;\r\n        min-height: 100vh !important;\r\n        min-height: 100svh !important;\r\n        max-height: none !important;\r\n        flex: none !important;\r\n        float: none !important;\r\n        opacity: 1 !important;\r\n        visibility: visible !important;\r\n        transform: none !important;\r\n        transition: none !important;\r\n        animation: none !important;\r\n        touch-action: auto !important;\r\n        overflow: hidden !important;\r\n        content-visibility: visible !important;\r\n      }\r\n\r\n      html.mp-free-mobile body.mp-native-ready #mp-fullpage-wrapper .mp-content {\r\n        display: flex !important;\r\n        position: relative !important;\r\n        inset: auto !important;\r\n        width: 100% !important;\r\n        max-width: none !important;\r\n        height: auto !important;\r\n        min-height: 100svh !important;\r\n        max-height: none !important;\r\n        margin: 0 !important;\r\n        padding: 100px 24px 80px !important;\r\n        flex-direction: column !important;\r\n        align-items: flex-start !important;\r\n        justify-content: flex-start !important;\r\n        transform: none !important;\r\n        z-index: 3;\r\n      }\r\n\r\n      html.mp-free-mobile body.mp-native-ready #mp-fullpage-wrapper .mp-services-wrap,\r\n      html.mp-free-mobile body.mp-native-ready #mp-fullpage-wrapper .mp-quote-inner,\r\n      html.mp-free-mobile body.mp-native-ready #mp-fullpage-wrapper .mp-news-inner,\r\n      html.mp-free-mobile body.mp-native-ready #mp-fullpage-wrapper .mp-quote-form-card {\r\n        position: relative !important;\r\n        height: auto !important;\r\n        max-height: none !important;\r\n      }\r\n\r\n      html.mp-free-mobile body.mp-native-ready #mp-fullpage-wrapper .mp-mobile-reveal {\r\n        opacity: 1 !important;\r\n        visibility: visible !important;\r\n        transform: none !important;\r\n        transition: none !important;\r\n        animation: none !important;\r\n      }\r\n\r\n      html.mp-free-mobile body.mp-native-ready #mp-fullpage-wrapper .mp-footer,\r\n      html.mp-free-mobile body.mp-native-ready #mp-fullpage-wrapper .mp-footer-section {\r\n        min-height: 0 !important;\r\n        height: auto !important;\r\n      }\r\n\r\n      html.mp-free-mobile #mp-section-nav,\r\n      html.mp-free-mobile .mp-desktop-fixed-quote-btn {\r\n        display: none !important;\r\n      }\r\n    `;\r\n\r\n    document.head.append(mechanics);\r\n\r\n    \/* CONFIGURAZIONE *\/\r\n\r\n    const mobileQuery = window.matchMedia('(max-width: 1024px)');\r\n\r\n    const reducedQuery = window.matchMedia(\r\n      '(prefers-reduced-motion: reduce)'\r\n    );\r\n\r\n    const quote = wrapper.querySelector(\r\n      '.mp-quote-section, #preventivo'\r\n    );\r\n\r\n    const footer = document.querySelector('.mp-footer');\r\n    const footerParent = footer?.parentNode;\r\n    const footerNext = footer?.nextSibling;\r\n    const footerClasses = footer?.className;\r\n\r\n    const languageSegment = window.location.pathname\r\n      .split('\/')\r\n      .filter(Boolean)[0];\r\n\r\n    const language = ['en', 'fr', 'ru'].includes(languageSegment)\r\n      ? languageSegment\r\n      : 'it';\r\n\r\n    const labels = {\r\n      it: [\r\n        'Richiedi preventivo gratuito',\r\n        'Navigazione sezioni',\r\n        'Sezione',\r\n        'Pi\u00e8 di pagina'\r\n      ],\r\n      en: [\r\n        'Request a free quote',\r\n        'Section navigation',\r\n        'Section',\r\n        'Footer'\r\n      ],\r\n      fr: [\r\n        'Demander un devis gratuit',\r\n        'Navigation des sections',\r\n        'Section',\r\n        'Pied de page'\r\n      ],\r\n      ru: [\r\n        '\u0417\u0430\u043f\u0440\u043e\u0441\u0438\u0442\u044c \u0431\u0435\u0441\u043f\u043b\u0430\u0442\u043d\u044b\u0439 \u0440\u0430\u0441\u0447\u0451\u0442 \u0441\u0442\u043e\u0438\u043c\u043e\u0441\u0442\u0438',\r\n        '\u041d\u0430\u0432\u0438\u0433\u0430\u0446\u0438\u044f \u043f\u043e \u0440\u0430\u0437\u0434\u0435\u043b\u0430\u043c',\r\n        '\u0420\u0430\u0437\u0434\u0435\u043b',\r\n        '\u041f\u043e\u0434\u0432\u0430\u043b'\r\n      ]\r\n    }[language];\r\n\r\n    const animatedSelector =\r\n      '.mp-kicker, .mp-content h1, .mp-content h2, .mp-desc, ' +\r\n      '.mp-btn, .mp-services-left, .mp-services-image, ' +\r\n      '.mp-quote-info, .mp-quote-form-card, ' +\r\n      '.mp-news-heading, .mp-news-card';\r\n\r\n    const wheelControls =\r\n      'input, textarea, select, ' +\r\n      '[contenteditable]:not([contenteditable=\"false\"]), ' +\r\n      '[role=\"dialog\"], .mp-captcha, .g-recaptcha';\r\n\r\n    const interactive =\r\n      'input, textarea, select, button, a, ' +\r\n      '[contenteditable]:not([contenteditable=\"false\"]), ' +\r\n      '[role=\"slider\"], [role=\"dialog\"], ' +\r\n      '.mp-captcha, .g-recaptcha';\r\n\r\n    let sections = [];\r\n    let active = -1;\r\n    let nav;\r\n\r\n    let animationFrame = 0;\r\n    let scrollFrame = 0;\r\n    let settleTimer = 0;\r\n\r\n    let wheelLast = 0;\r\n    let wheelConsumed = false;\r\n    let wheelSum = 0;\r\n\r\n    let moving = false;\r\n    let suppressSettleUntil = 0;\r\n\r\n    let sectionFadeObserver = null;\r\n\r\n    const preparedSections = new WeakSet();\r\n\r\n    const mobileObserver = new IntersectionObserver(\r\n      entries => {\r\n        entries.forEach(entry => {\r\n          if (entry.isIntersecting) {\r\n            entry.target.classList.add('is-visible');\r\n          }\r\n        });\r\n      },\r\n      {\r\n        threshold: 0,\r\n        rootMargin: '0px 0px -30px 0px'\r\n      }\r\n    );\r\n\r\n    \/* MISURE E SCORRIMENTO *\/\r\n\r\n    function scrollY() {\r\n      return desktopMode ? wrapper.scrollTop : window.scrollY;\r\n    }\r\n\r\n    function viewportHeight() {\r\n      return desktopMode\r\n        ? wrapper.clientHeight\r\n        : window.innerHeight;\r\n    }\r\n\r\n    function topOf(element) {\r\n      const rect = element.getBoundingClientRect();\r\n\r\n      return desktopMode\r\n        ? rect.top -\r\n            wrapper.getBoundingClientRect().top +\r\n            wrapper.scrollTop\r\n        : rect.top + window.scrollY;\r\n    }\r\n\r\n    function maxScroll() {\r\n      return desktopMode\r\n        ? Math.max(\r\n            0,\r\n            wrapper.scrollHeight - wrapper.clientHeight\r\n          )\r\n        : Math.max(\r\n            0,\r\n            document.documentElement.scrollHeight -\r\n              window.innerHeight\r\n          );\r\n    }\r\n\r\n    function clamp(value) {\r\n      return Math.max(0, Math.min(maxScroll(), value));\r\n    }\r\n\r\n    function writeScroll(value) {\r\n      const scroller = desktopMode ? wrapper : window;\r\n\r\n      scroller.scrollTo({\r\n        top: clamp(value),\r\n        behavior: 'instant'\r\n      });\r\n    }\r\n\r\n    function syncViewport() {\r\n      if (desktopMode) {\r\n        wrapper.style.setProperty(\r\n          '--mp-screen-height',\r\n          wrapper.clientHeight + 'px'\r\n        );\r\n      } else {\r\n        wrapper.style.removeProperty('--mp-screen-height');\r\n      }\r\n    }\r\n\r\n    function insidePage() {\r\n      return desktopMode;\r\n    }\r\n\r\n    \/* ELEMENTI DA ANIMARE *\/\r\n\r\n    function targets(section) {\r\n      return [...section.querySelectorAll(animatedSelector)];\r\n    }\r\n\r\n    function prepareSection(section) {\r\n      if (\r\n        !section ||\r\n        !window.gsap ||\r\n        mobileQuery.matches ||\r\n        reducedQuery.matches\r\n      ) {\r\n        return;\r\n      }\r\n\r\n      const items = targets(section);\r\n\r\n      if (!items.length) return;\r\n\r\n      window.gsap.killTweensOf(items);\r\n\r\n      window.gsap.set(items, {\r\n        autoAlpha: 0,\r\n        clearProps: 'transform'\r\n      });\r\n\r\n      preparedSections.add(section);\r\n    }\r\n\r\n    function setupSectionFades() {\r\n      sectionFadeObserver?.disconnect();\r\n      sectionFadeObserver = null;\r\n\r\n      if (\r\n        !window.gsap ||\r\n        mobileQuery.matches ||\r\n        reducedQuery.matches\r\n      ) {\r\n        sections.forEach(section => {\r\n          showSection(section, false);\r\n        });\r\n\r\n        return;\r\n      }\r\n\r\n      function outsideViewport(section) {\r\n        const rect = section.getBoundingClientRect();\r\n        const viewport = wrapper.getBoundingClientRect();\r\n\r\n        return (\r\n          rect.bottom <= viewport.top ||\r\n          rect.top >= viewport.bottom\r\n        );\r\n      }\r\n\r\n      sections.forEach(section => {\r\n        if (outsideViewport(section)) {\r\n          prepareSection(section);\r\n        }\r\n      });\r\n\r\n      sectionFadeObserver = new IntersectionObserver(\r\n        entries => {\r\n          entries.forEach(entry => {\r\n            if (\r\n              !entry.isIntersecting &&\r\n              outsideViewport(entry.target)\r\n            ) {\r\n              prepareSection(entry.target);\r\n            }\r\n          });\r\n        },\r\n        {\r\n          root: wrapper,\r\n          threshold: 0\r\n        }\r\n      );\r\n\r\n      sections.forEach(section => {\r\n        sectionFadeObserver.observe(section);\r\n      });\r\n    }\r\n\r\n    function showSection(section, animate = true) {\r\n      if (!section) return;\r\n\r\n      section.classList.add('is-visible');\r\n\r\n      const gsap = window.gsap;\r\n\r\n      if (!gsap) return;\r\n\r\n      const items = targets(section);\r\n\r\n      const bg = section.querySelector(\r\n        '.mp-bg, .mp-quote-bg'\r\n      );\r\n\r\n      if (bg) {\r\n        gsap.killTweensOf(bg);\r\n\r\n        gsap.set(bg, {\r\n          clearProps: 'transform,opacity,visibility'\r\n        });\r\n      }\r\n\r\n      preparedSections.delete(section);\r\n\r\n      if (!items.length) return;\r\n\r\n      gsap.killTweensOf(items);\r\n\r\n      if (\r\n        !animate ||\r\n        mobileQuery.matches ||\r\n        reducedQuery.matches\r\n      ) {\r\n        gsap.set(items, {\r\n          autoAlpha: 1,\r\n          clearProps: 'transform,opacity,visibility'\r\n        });\r\n\r\n        return;\r\n      }\r\n\r\n      \/\/ Mantiene l'opacit\u00e0 preparata prima dello scorrimento.\r\n      gsap.set(items, {\r\n        clearProps: 'transform'\r\n      });\r\n\r\n      gsap.to(items, {\r\n        autoAlpha: 1,\r\n        duration: 0.85,\r\n        stagger: 0.07,\r\n        ease: 'sine.out',\r\n        overwrite: true,\r\n        clearProps: 'opacity,visibility'\r\n      });\r\n    }\r\n\r\n    \/* SEZIONE ATTIVA *\/\r\n\r\n    function setActive(index, animate = true) {\r\n      if (\r\n        moving ||\r\n        index < 0 ||\r\n        !sections[index]\r\n      ) {\r\n        return;\r\n      }\r\n\r\n      const changed = active !== index;\r\n\r\n      active = index;\r\n\r\n      sections.forEach((section, i) => {\r\n        section.classList.toggle('active', i === index);\r\n      });\r\n\r\n      const section = sections[index];\r\n\r\n      document.body.classList.toggle(\r\n        'mp-dark-dots',\r\n        section.matches(\r\n          '.mp-services-section, .mp-news-section, ' +\r\n          '.mp-footer, .mp-footer-section'\r\n        )\r\n      );\r\n\r\n      document.body.classList.toggle(\r\n        'mp-on-quote-section',\r\n        section === quote\r\n      );\r\n\r\n      document\r\n        .querySelectorAll(\r\n          '.mp-desktop-fixed-quote-btn, ' +\r\n          '.mp-mobile-fixed-quote-btn'\r\n        )\r\n        .forEach(button => {\r\n          button.hidden = section === quote;\r\n        });\r\n\r\n      nav?.querySelectorAll('a').forEach((link, i) => {\r\n        link.classList.toggle('active', i === index);\r\n\r\n        if (i === index) {\r\n          link.setAttribute('aria-current', 'true');\r\n        } else {\r\n          link.removeAttribute('aria-current');\r\n        }\r\n      });\r\n\r\n      if (\r\n        changed ||\r\n        preparedSections.has(section)\r\n      ) {\r\n        showSection(section, animate);\r\n      }\r\n    }\r\n\r\n    function detectSection() {\r\n      if (!sections.length) return -1;\r\n\r\n      const y = scrollY();\r\n      const last = sections.at(-1);\r\n\r\n      if (\r\n        last.matches('.mp-footer, .mp-footer-section') &&\r\n        y >= maxScroll() - 3 &&\r\n        topOf(last) - y < viewportHeight()\r\n      ) {\r\n        return sections.length - 1;\r\n      }\r\n\r\n      const probe =\r\n        y + Math.min(140, viewportHeight() * 0.2);\r\n\r\n      let index = 0;\r\n\r\n      sections.forEach((section, i) => {\r\n        if (topOf(section) <= probe) {\r\n          index = i;\r\n        }\r\n      });\r\n\r\n      return index;\r\n    }\r\n\r\n    \/* SPOSTAMENTO TRA SEZIONI *\/\r\n\r\n    function stopMotion() {\r\n      cancelAnimationFrame(animationFrame);\r\n\r\n      animationFrame = 0;\r\n      moving = false;\r\n    }\r\n\r\n    function ease(t) {\r\n      return t < 0.5\r\n        ? 8 * t ** 4\r\n        : 1 - ((-2 * t + 2) ** 4) \/ 2;\r\n    }\r\n\r\n    function moveTo(index, focus = false) {\r\n      const section = sections[index];\r\n\r\n      if (!section) return;\r\n\r\n      stopMotion();\r\n      clearTimeout(settleTimer);\r\n\r\n      \/\/ MOBILE: scorrimento nativo del browser.\r\n      if (mobileQuery.matches) {\r\n        section.scrollIntoView({\r\n          behavior: reducedQuery.matches ? 'auto' : 'smooth',\r\n          block: 'start'\r\n        });\r\n\r\n        if (focus) {\r\n          if (!section.hasAttribute('tabindex')) {\r\n            section.tabIndex = -1;\r\n          }\r\n\r\n          section.focus({\r\n            preventScroll: true\r\n          });\r\n        }\r\n\r\n        return;\r\n      }\r\n\r\n      \/\/ DESKTOP: nasconde la destinazione prima dello scroll.\r\n      if (index !== active) {\r\n        prepareSection(section);\r\n      }\r\n\r\n      const startY = scrollY();\r\n      const endY = clamp(topOf(section));\r\n\r\n      const started = performance.now();\r\n      const duration = reducedQuery.matches ? 0 : 820;\r\n\r\n      moving = true;\r\n\r\n      function finish() {\r\n        moving = false;\r\n        animationFrame = 0;\r\n\r\n        suppressSettleUntil = performance.now() + 200;\r\n\r\n        setActive(index);\r\n\r\n        if (focus) {\r\n          if (!section.hasAttribute('tabindex')) {\r\n            section.tabIndex = -1;\r\n          }\r\n\r\n          section.focus({\r\n            preventScroll: true\r\n          });\r\n        }\r\n      }\r\n\r\n      function step(now) {\r\n        const t = duration\r\n          ? Math.min(1, (now - started) \/ duration)\r\n          : 1;\r\n\r\n        writeScroll(\r\n          startY + (endY - startY) * ease(t)\r\n        );\r\n\r\n        if (t < 1) {\r\n          animationFrame = requestAnimationFrame(step);\r\n        } else {\r\n          finish();\r\n        }\r\n      }\r\n\r\n      animationFrame = requestAnimationFrame(step);\r\n    }\r\n\r\n    function nextDestination(direction) {\r\n      const y = scrollY();\r\n      const index = detectSection();\r\n      const section = sections[index];\r\n\r\n      if (!section) return -1;\r\n\r\n      const top = topOf(section);\r\n      const bottom = top + section.offsetHeight;\r\n\r\n      \/\/ Consente la lettura delle sezioni pi\u00f9 alte della finestra.\r\n      if (section.offsetHeight > viewportHeight() + 4) {\r\n        if (\r\n          direction > 0 &&\r\n          y < bottom - viewportHeight() - 4\r\n        ) {\r\n          return -1;\r\n        }\r\n\r\n        if (\r\n          direction < 0 &&\r\n          y > top + 4\r\n        ) {\r\n          return -1;\r\n        }\r\n      }\r\n\r\n      if (\r\n        direction < 0 &&\r\n        y > top + 8\r\n      ) {\r\n        return index;\r\n      }\r\n\r\n      const next = index + direction;\r\n\r\n      return next >= 0 && next < sections.length\r\n        ? next\r\n        : -1;\r\n    }\r\n\r\n    \/* ROTELLA E AREE INTERNE SCORREVOLI *\/\r\n\r\n    function hasScrollableParent(element, direction) {\r\n      for (\r\n        let node = element;\r\n        node &&\r\n        node !== wrapper &&\r\n        node !== document.body;\r\n        node = node.parentElement\r\n      ) {\r\n        const style = getComputedStyle(node);\r\n\r\n        if (\r\n          \/(auto|scroll)\/.test(style.overflowY) &&\r\n          node.scrollHeight > node.clientHeight + 2\r\n        ) {\r\n          const canScroll = direction > 0\r\n            ? node.scrollTop + node.clientHeight <\r\n              node.scrollHeight - 2\r\n            : node.scrollTop > 2;\r\n\r\n          if (canScroll) return true;\r\n        }\r\n      }\r\n\r\n      return false;\r\n    }\r\n\r\n    function wheel(event) {\r\n      if (\r\n        mobileQuery.matches ||\r\n        event.ctrlKey ||\r\n        event.metaKey ||\r\n        Math.abs(event.deltaX) > Math.abs(event.deltaY) ||\r\n        !event.deltaY ||\r\n        !insidePage()\r\n      ) {\r\n        return;\r\n      }\r\n\r\n      const direction = Math.sign(event.deltaY);\r\n\r\n      if (\r\n        event.target.closest(wheelControls) ||\r\n        hasScrollableParent(event.target, direction)\r\n      ) {\r\n        return;\r\n      }\r\n\r\n      const now = performance.now();\r\n\r\n      if (now - wheelLast > 180) {\r\n        wheelConsumed = false;\r\n        wheelSum = 0;\r\n      }\r\n\r\n      wheelLast = now;\r\n\r\n      if (moving || wheelConsumed) {\r\n        event.preventDefault();\r\n        return;\r\n      }\r\n\r\n      const destination = nextDestination(direction);\r\n\r\n      if (\r\n        destination < 0 ||\r\n        Math.abs(\r\n          clamp(topOf(sections[destination])) - scrollY()\r\n        ) < 2\r\n      ) {\r\n        return;\r\n      }\r\n\r\n      const delta = event.deltaY * (\r\n        event.deltaMode === 1\r\n          ? 16\r\n          : event.deltaMode === 2\r\n            ? viewportHeight()\r\n            : 1\r\n      );\r\n\r\n      if (Math.sign(wheelSum) !== direction) {\r\n        wheelSum = 0;\r\n      }\r\n\r\n      wheelSum += delta;\r\n\r\n      event.preventDefault();\r\n\r\n      if (Math.abs(wheelSum) < 24) return;\r\n\r\n      wheelConsumed = true;\r\n\r\n      moveTo(destination);\r\n    }\r\n\r\n    \/* ALLINEAMENTO DESKTOP *\/\r\n\r\n    function snapDestination() {\r\n      const y = scrollY();\r\n      const height = viewportHeight();\r\n\r\n      for (const section of sections) {\r\n        const top = topOf(section);\r\n\r\n        const bottomPosition =\r\n          top + section.offsetHeight - height;\r\n\r\n        if (\r\n          section.offsetHeight > height + 4 &&\r\n          y >= top - 2 &&\r\n          y <= bottomPosition + 2\r\n        ) {\r\n          return -1;\r\n        }\r\n      }\r\n\r\n      let nearest = -1;\r\n      let distance = Infinity;\r\n\r\n      sections.forEach((section, index) => {\r\n        const delta = Math.abs(\r\n          clamp(topOf(section)) - y\r\n        );\r\n\r\n        if (delta < distance) {\r\n          nearest = index;\r\n          distance = delta;\r\n        }\r\n      });\r\n\r\n      return distance > 2 ? nearest : -1;\r\n    }\r\n\r\n    function settle() {\r\n      if (\r\n        !desktopMode ||\r\n        moving ||\r\n        pointerActive\r\n      ) {\r\n        return;\r\n      }\r\n\r\n      const remaining =\r\n        suppressSettleUntil - performance.now();\r\n\r\n      if (remaining > 0) {\r\n        settleTimer = setTimeout(\r\n          settle,\r\n          remaining + 20\r\n        );\r\n        return;\r\n      }\r\n\r\n      if (\r\n        document.activeElement?.closest(wheelControls)\r\n      ) {\r\n        return;\r\n      }\r\n\r\n      const nearest = snapDestination();\r\n\r\n      if (nearest >= 0) {\r\n        moveTo(nearest);\r\n      }\r\n    }\r\n\r\n    function onScroll() {\r\n      if (!scrollFrame) {\r\n        scrollFrame = requestAnimationFrame(() => {\r\n          scrollFrame = 0;\r\n\r\n          if (moving) return;\r\n\r\n          const index = detectSection();\r\n          const section = sections[index];\r\n\r\n          if (!section) return;\r\n\r\n          const y = scrollY();\r\n          const top = topOf(section);\r\n          const height = viewportHeight();\r\n\r\n          const aligned =\r\n            Math.abs(y - clamp(top)) <= 3;\r\n\r\n          const insideTallSection =\r\n            section.offsetHeight > height + 4 &&\r\n            y >= top - 3 &&\r\n            y <= top + section.offsetHeight - height + 3;\r\n\r\n          if (\r\n            !desktopMode ||\r\n            aligned ||\r\n            insideTallSection\r\n          ) {\r\n            setActive(index);\r\n          }\r\n        });\r\n      }\r\n\r\n      clearTimeout(settleTimer);\r\n\r\n      if (!moving && desktopMode) {\r\n        settleTimer = setTimeout(settle, 180);\r\n      }\r\n    }\r\n\r\n    wrapper.addEventListener(\r\n      'wheel',\r\n      wheel,\r\n      { passive: false }\r\n    );\r\n\r\n    wrapper.addEventListener(\r\n      'scroll',\r\n      () => {\r\n        if (desktopMode) {\r\n          onScroll();\r\n        }\r\n      },\r\n      { passive: true }\r\n    );\r\n\r\n    window.addEventListener(\r\n      'scroll',\r\n      () => {\r\n        if (!desktopMode) {\r\n          onScroll();\r\n        }\r\n      },\r\n      { passive: true }\r\n    );\r\n\r\n    \/* TASTIERA *\/\r\n\r\n    window.addEventListener('keydown', event => {\r\n      if (event.key === 'Escape') {\r\n        stopMotion();\r\n        return;\r\n      }\r\n\r\n      if (\r\n        mobileQuery.matches ||\r\n        event.defaultPrevented ||\r\n        event.altKey ||\r\n        event.ctrlKey ||\r\n        event.metaKey ||\r\n        event.target.closest(interactive) ||\r\n        !insidePage()\r\n      ) {\r\n        return;\r\n      }\r\n\r\n      let destination = -1;\r\n\r\n      if (event.key === 'Home') {\r\n        destination = 0;\r\n      } else if (event.key === 'End') {\r\n        destination = sections.length - 1;\r\n      } else {\r\n        const direction =\r\n          ['ArrowDown', 'PageDown'].includes(event.key) ||\r\n          (event.key === ' ' && !event.shiftKey)\r\n            ? 1\r\n            : ['ArrowUp', 'PageUp'].includes(event.key) ||\r\n              (event.key === ' ' && event.shiftKey)\r\n              ? -1\r\n              : 0;\r\n\r\n        if (!direction) return;\r\n\r\n        if (moving) {\r\n          event.preventDefault();\r\n          return;\r\n        }\r\n\r\n        destination = nextDestination(direction);\r\n\r\n        if (destination < 0 && desktopMode) {\r\n          event.preventDefault();\r\n\r\n          const section = sections[detectSection()];\r\n\r\n          if (\r\n            section &&\r\n            section.offsetHeight > viewportHeight() + 4\r\n          ) {\r\n            const top = topOf(section);\r\n\r\n            const lastPosition =\r\n              top +\r\n              section.offsetHeight -\r\n              viewportHeight();\r\n\r\n            const step = event.key.startsWith('Arrow')\r\n              ? 60\r\n              : viewportHeight() * 0.85;\r\n\r\n            writeScroll(\r\n              Math.max(\r\n                top,\r\n                Math.min(\r\n                  lastPosition,\r\n                  scrollY() + direction * step\r\n                )\r\n              )\r\n            );\r\n          }\r\n\r\n          return;\r\n        }\r\n      }\r\n\r\n      if (destination >= 0) {\r\n        event.preventDefault();\r\n        moveTo(destination);\r\n      }\r\n    });\r\n\r\n    \/* POINTER, TOUCH E FOCUS *\/\r\n\r\n    function pointerStart() {\r\n      pointerActive = true;\r\n\r\n      stopMotion();\r\n      clearTimeout(settleTimer);\r\n    }\r\n\r\n    function pointerEnd() {\r\n      pointerActive = false;\r\n\r\n      clearTimeout(settleTimer);\r\n\r\n      if (desktopMode) {\r\n        settleTimer = setTimeout(settle, 200);\r\n      }\r\n    }\r\n\r\n    wrapper.addEventListener(\r\n      'pointerdown',\r\n      pointerStart,\r\n      { passive: true }\r\n    );\r\n\r\n    window.addEventListener(\r\n      'pointerup',\r\n      pointerEnd,\r\n      { passive: true }\r\n    );\r\n\r\n    window.addEventListener(\r\n      'pointercancel',\r\n      pointerEnd,\r\n      { passive: true }\r\n    );\r\n\r\n    wrapper.addEventListener(\r\n      'touchstart',\r\n      pointerStart,\r\n      { passive: true }\r\n    );\r\n\r\n    window.addEventListener(\r\n      'touchend',\r\n      pointerEnd,\r\n      { passive: true }\r\n    );\r\n\r\n    window.addEventListener(\r\n      'touchcancel',\r\n      pointerEnd,\r\n      { passive: true }\r\n    );\r\n\r\n    wrapper.addEventListener('focusin', event => {\r\n      stopMotion();\r\n      clearTimeout(settleTimer);\r\n\r\n      const section = event.target.closest('.section');\r\n\r\n      if (section) {\r\n        setActive(\r\n          sections.indexOf(section),\r\n          false\r\n        );\r\n      }\r\n    });\r\n\r\n    \/* PULSANTI PREVENTIVO *\/\r\n\r\n    function createButtons() {\r\n      if (!quote) return;\r\n\r\n      for (const type of ['desktop', 'mobile']) {\r\n        const className =\r\n          `mp-${type}-fixed-quote-btn`;\r\n\r\n        if (document.querySelector(`.${className}`)) {\r\n          continue;\r\n        }\r\n\r\n        const link = document.createElement('a');\r\n\r\n        link.href = '#preventivo';\r\n        link.className = className;\r\n\r\n        link.textContent = type === 'desktop'\r\n          ? labels[0].toUpperCase()\r\n          : labels[0];\r\n\r\n        if (type === 'desktop') {\r\n          const span = document.createElement('span');\r\n          const image = document.createElement('img');\r\n\r\n          image.src =\r\n            'https:\/\/millepiani.com\/wp-content\/uploads\/2026\/05\/lsicon_arrow-left-outline.png';\r\n\r\n          image.alt = '';\r\n\r\n          span.append(image);\r\n          link.append(span);\r\n        }\r\n\r\n        document.body.append(link);\r\n      }\r\n    }\r\n\r\n    document.addEventListener('click', event => {\r\n      const link = event.target.closest(\r\n        'a[href=\"#preventivo\"]'\r\n      );\r\n\r\n      if (\r\n        !link ||\r\n        !quote ||\r\n        event.defaultPrevented ||\r\n        event.button !== 0 ||\r\n        event.ctrlKey ||\r\n        event.metaKey ||\r\n        event.shiftKey ||\r\n        event.altKey\r\n      ) {\r\n        return;\r\n      }\r\n\r\n      event.preventDefault();\r\n\r\n      moveTo(\r\n        sections.indexOf(quote),\r\n        true\r\n      );\r\n    });\r\n\r\n    \/* PALLINI DESKTOP *\/\r\n\r\n    function buildNav() {\r\n      nav?.remove();\r\n\r\n      nav = document.createElement('nav');\r\n\r\n      nav.id = 'mp-section-nav';\r\n      nav.setAttribute('aria-label', labels[1]);\r\n\r\n      const list = document.createElement('ul');\r\n\r\n      sections.forEach((section, index) => {\r\n        if (!section.id) {\r\n          let id = `mp-section-${index + 1}`;\r\n\r\n          while (document.getElementById(id)) {\r\n            id += '-native';\r\n          }\r\n\r\n          section.id = id;\r\n        }\r\n\r\n        const li = document.createElement('li');\r\n        const link = document.createElement('a');\r\n\r\n        const title = section\r\n          .querySelector('h1, h2, h3')\r\n          ?.textContent\r\n          .replace(\/\\s+\/g, ' ')\r\n          .trim();\r\n\r\n        link.href = `#${section.id}`;\r\n\r\n        link.setAttribute(\r\n          'aria-label',\r\n          title ||\r\n            (\r\n              section === footer\r\n                ? labels[3]\r\n                : `${labels[2]} ${index + 1}`\r\n            )\r\n        );\r\n\r\n        link.title = link.getAttribute('aria-label');\r\n\r\n        const dot = document.createElement('span');\r\n\r\n        dot.setAttribute('aria-hidden', 'true');\r\n\r\n        link.append(dot);\r\n\r\n        link.addEventListener('click', event => {\r\n          if (\r\n            event.ctrlKey ||\r\n            event.metaKey ||\r\n            event.shiftKey ||\r\n            event.altKey ||\r\n            event.button !== 0\r\n          ) {\r\n            return;\r\n          }\r\n\r\n          event.preventDefault();\r\n\r\n          moveTo(index, true);\r\n        });\r\n\r\n        li.append(link);\r\n        list.append(li);\r\n      });\r\n\r\n      nav.append(list);\r\n      document.body.append(nav);\r\n    }\r\n\r\n    \/* SBLOCCO COMPLETO DEL LAYOUT MOBILE *\/\r\n\r\n    function forceMobileStyles(element, properties) {\r\n      if (!element?.style) return;\r\n\r\n      let saved = mobileStyleBackup.get(element);\r\n\r\n      if (!saved) {\r\n        saved = new Map();\r\n        mobileStyleBackup.set(element, saved);\r\n      }\r\n\r\n      \/\/ Salva solo le propriet\u00e0 che questa funzione modifica.\r\n      Object.keys(properties).forEach(property => {\r\n        if (!saved.has(property)) {\r\n          saved.set(property, {\r\n            value: element.style.getPropertyValue(property),\r\n            priority: element.style.getPropertyPriority(property)\r\n          });\r\n        }\r\n      });\r\n\r\n      Object.entries(properties).forEach(([property, value]) => {\r\n        element.style.setProperty(\r\n          property,\r\n          value,\r\n          'important'\r\n        );\r\n      });\r\n    }\r\n\r\n    function restoreMobileStyles() {\r\n      mobileStyleBackup.forEach((saved, element) => {\r\n        saved.forEach((original, property) => {\r\n          if (original.value) {\r\n            element.style.setProperty(\r\n              property,\r\n              original.value,\r\n              original.priority\r\n            );\r\n          } else {\r\n            element.style.removeProperty(property);\r\n          }\r\n        });\r\n      });\r\n\r\n      mobileStyleBackup.clear();\r\n    }\r\n\r\n    function enableMobileFlow() {\r\n      const normalFlow = {\r\n        position: 'relative',\r\n        inset: 'auto',\r\n        height: 'auto',\r\n        'min-height': '0',\r\n        'max-height': 'none',\r\n        overflow: 'visible',\r\n        transform: 'none',\r\n        'touch-action': 'auto',\r\n        'scroll-snap-type': 'none',\r\n        'overscroll-behavior': 'auto'\r\n      };\r\n\r\n      \/\/ Sblocca lo scorrimento del documento.\r\n      forceMobileStyles(document.documentElement, {\r\n        ...normalFlow,\r\n        position: 'static',\r\n        'overflow-x': 'hidden',\r\n        'overflow-y': 'auto'\r\n      });\r\n\r\n      forceMobileStyles(document.body, {\r\n        ...normalFlow,\r\n        position: 'static'\r\n      });\r\n\r\n      \/*\r\n       * Sblocca anche gli antenati del wrapper.\r\n       * Un contenitore del tema alto 100vh con overflow hidden\r\n       * pu\u00f2 impedire di raggiungere le sezioni successive.\r\n       *\/\r\n      for (\r\n        let parent = wrapper.parentElement;\r\n        parent && parent !== document.body;\r\n        parent = parent.parentElement\r\n      ) {\r\n        forceMobileStyles(parent, {\r\n          ...normalFlow,\r\n          display: 'block',\r\n          contain: 'none',\r\n          'content-visibility': 'visible'\r\n        });\r\n      }\r\n\r\n      forceMobileStyles(wrapper, {\r\n        ...normalFlow,\r\n        display: 'block'\r\n      });\r\n\r\n      \/\/ Tutte le sezioni occupano spazio nel documento.\r\n      sections.forEach(section => {\r\n        forceMobileStyles(section, {\r\n          display: 'block',\r\n          position: 'relative',\r\n          inset: 'auto',\r\n          width: '100%',\r\n          height: 'auto',\r\n          'max-height': 'none',\r\n          flex: 'none',\r\n          float: 'none',\r\n          transform: 'none',\r\n          opacity: '1',\r\n          visibility: 'visible',\r\n          'touch-action': 'auto'\r\n        });\r\n\r\n        targets(section).forEach(item => {\r\n          item.classList.add('mp-mobile-reveal');\r\n        });\r\n      });\r\n\r\n      \/\/ Ripulisce eventuali contenitori di vecchi layout.\r\n      wrapper\r\n        .querySelectorAll(\r\n          '.fp-tableCell, .fp-overflow, .fp-scrollable, .fp-scroller'\r\n        )\r\n        .forEach(element => {\r\n          forceMobileStyles(element, {\r\n            ...normalFlow,\r\n            display: 'block'\r\n          });\r\n        });\r\n    }\r\n\r\n    \/* CONFIGURAZIONE DESKTOP \/ MOBILE *\/\r\n\r\n    function configure() {\r\n      const previous = sections[active];\r\n\r\n      stopMotion();\r\n      clearTimeout(settleTimer);\r\n\r\n      const mobile = mobileQuery.matches;\r\n\r\n      restoreMobileStyles();\r\n\r\n      desktopMode = !mobile;\r\n\r\n      document.documentElement.classList.toggle(\r\n        'mp-free-mobile',\r\n        mobile\r\n      );\r\n\r\n      document.documentElement.classList.add(\r\n        'mp-native-page'\r\n      );\r\n\r\n      document.documentElement.classList.toggle(\r\n        'mp-viewport-mode',\r\n        !mobile\r\n      );\r\n\r\n      document.body.classList.remove(\r\n        'mp-fullpage-ready'\r\n      );\r\n\r\n      document.body.classList.add(\r\n        'mp-native-ready'\r\n      );\r\n\r\n      document.body.classList.toggle(\r\n        'mp-mobile-layout',\r\n        mobile\r\n      );\r\n\r\n      document.body.classList.toggle(\r\n        'mp-native-desktop',\r\n        !mobile\r\n      );\r\n\r\n      \/\/ Desktop: contenitore a tutto schermo.\r\n      if (\r\n        !mobile &&\r\n        wrapper.parentNode !== document.body\r\n      ) {\r\n        document.body.append(wrapper);\r\n      }\r\n\r\n      \/\/ Mobile: ripristina la posizione originale nel documento.\r\n      if (\r\n        mobile &&\r\n        wrapper.parentNode !== originalParent\r\n      ) {\r\n        originalParent.insertBefore(\r\n          wrapper,\r\n          originalNext?.parentNode === originalParent\r\n            ? originalNext\r\n            : null\r\n        );\r\n      }\r\n\r\n      if (footer && !mobile) {\r\n        footer.classList.add(\r\n          'section',\r\n          'mp-footer-section'\r\n        );\r\n\r\n        if (footer.parentElement !== wrapper) {\r\n          wrapper.append(footer);\r\n        }\r\n      } else if (\r\n        footer &&\r\n        footerParent !== wrapper\r\n      ) {\r\n        footerParent.insertBefore(\r\n          footer,\r\n          footerNext?.parentNode === footerParent\r\n            ? footerNext\r\n            : null\r\n        );\r\n\r\n        footer.className = footerClasses;\r\n      }\r\n\r\n      sections = [...wrapper.children].filter(\r\n        element => element.matches('.section')\r\n      );\r\n\r\n      syncViewport();\r\n\r\n      mobileObserver.disconnect();\r\n\r\n      \/* MOBILE: NESSUNA NAVIGAZIONE FULLSCREEN *\/\r\n\r\n      if (mobile) {\r\n        sectionFadeObserver?.disconnect();\r\n        sectionFadeObserver = null;\r\n\r\n        nav?.remove();\r\n        nav = null;\r\n\r\n        sections.forEach(section => {\r\n          section.classList.remove('mp-mobile-fade');\r\n          section.classList.add('is-visible');\r\n\r\n          showSection(section, false);\r\n        });\r\n\r\n        \/\/ Applica il reset di altezze, overflow e visibilit\u00e0.\r\n        enableMobileFlow();\r\n\r\n        createButtons();\r\n\r\n        let mobileTarget = configured && previous\r\n          ? sections.indexOf(previous)\r\n          : detectSection();\r\n\r\n        if (mobileTarget < 0) {\r\n          mobileTarget = 0;\r\n        }\r\n\r\n        active = -1;\r\n\r\n        setActive(mobileTarget, false);\r\n\r\n        if (\r\n          configured &&\r\n          previous &&\r\n          sections.includes(previous)\r\n        ) {\r\n          writeScroll(topOf(previous));\r\n        }\r\n\r\n        configured = true;\r\n        wheelConsumed = false;\r\n        pointerActive = false;\r\n\r\n        return;\r\n      }\r\n\r\n      \/* DESKTOP *\/\r\n\r\n      sections.forEach(section => {\r\n        showSection(section, false);\r\n\r\n        section.classList.toggle(\r\n          'mp-mobile-fade',\r\n          mobile\r\n        );\r\n\r\n        if (mobile) {\r\n          mobileObserver.observe(section);\r\n        }\r\n      });\r\n\r\n      createButtons();\r\n      buildNav();\r\n\r\n      let target = configured && previous\r\n        ? sections.indexOf(previous)\r\n        : -1;\r\n\r\n      if (!configured && window.location.hash) {\r\n        try {\r\n          target = sections.findIndex(\r\n            section =>\r\n              section.id ===\r\n              decodeURIComponent(\r\n                window.location.hash.slice(1)\r\n              )\r\n          );\r\n        } catch (_) {\r\n          \/* Hash malformato: prima sezione. *\/\r\n        }\r\n      }\r\n\r\n      if (target < 0) {\r\n        target = mobile ? detectSection() : 0;\r\n      }\r\n\r\n      active = -1;\r\n\r\n      setActive(target, false);\r\n\r\n      if (desktopMode || configured) {\r\n        writeScroll(\r\n          topOf(sections[target])\r\n        );\r\n      }\r\n\r\n      configured = true;\r\n      wheelConsumed = false;\r\n      pointerActive = false;\r\n\r\n      window.mpFullscreen = {\r\n        version: '2.1',\r\n\r\n        moveTo: number => {\r\n          moveTo(Number(number) - 1, true);\r\n        },\r\n\r\n        refresh: syncViewport,\r\n\r\n        getState: () => ({\r\n          version: '2.1',\r\n          mode: desktopMode ? 'desktop' : 'mobile',\r\n          sections: sections.length,\r\n          activeSection: active + 1,\r\n          scrollTop: scrollY(),\r\n          viewportHeight: viewportHeight(),\r\n          moving\r\n        })\r\n      };\r\n\r\n      setupSectionFades();\r\n    }\r\n\r\n    mobileQuery.addEventListener(\r\n      'change',\r\n      configure\r\n    );\r\n\r\n    reducedQuery.addEventListener('change', () => {\r\n      stopMotion();\r\n\r\n      sections.forEach(section => {\r\n        showSection(section, false);\r\n      });\r\n\r\n      setupSectionFades();\r\n    });\r\n\r\n    window.addEventListener('resize', () => {\r\n      stopMotion();\r\n\r\n      clearTimeout(settleTimer);\r\n      clearTimeout(resizeTimer);\r\n\r\n      resizeTimer = setTimeout(() => {\r\n        syncViewport();\r\n\r\n        \/\/ Su mobile non riporta la pagina all'inizio della sezione.\r\n        if (desktopMode && sections[active]) {\r\n          writeScroll(\r\n            topOf(sections[active])\r\n          );\r\n        }\r\n\r\n        setActive(\r\n          detectSection(),\r\n          false\r\n        );\r\n      }, 150);\r\n    });\r\n\r\n    window.addEventListener(\r\n      'load',\r\n      () => {\r\n        syncViewport();\r\n\r\n        if (desktopMode && sections[active]) {\r\n          writeScroll(\r\n            topOf(sections[active])\r\n          );\r\n        }\r\n      },\r\n      { once: true }\r\n    );\r\n\r\n    window.addEventListener('hashchange', () => {\r\n      try {\r\n        const index = sections.findIndex(\r\n          section =>\r\n            section.id ===\r\n            decodeURIComponent(\r\n              window.location.hash.slice(1)\r\n            )\r\n        );\r\n\r\n        if (index >= 0) {\r\n          moveTo(index, true);\r\n        }\r\n      } catch (_) {\r\n        \/* Nessuna navigazione per un hash malformato. *\/\r\n      }\r\n    });\r\n\r\n    configure();\r\n\r\n    showSection(sections[active]);\r\n\r\n    initTabs();\r\n    initQuoteForm();\r\n    initNews();\r\n\r\n    \/* TAB SERVIZI *\/\r\n\r\n    function initTabs() {\r\n      const tabs = [\r\n        ...wrapper.querySelectorAll('.mp-tab')\r\n      ];\r\n\r\n      const panels = [\r\n        ...wrapper.querySelectorAll('.mp-tab-panel')\r\n      ];\r\n\r\n      tabs.forEach(tab => {\r\n        tab.addEventListener('click', event => {\r\n          event.preventDefault();\r\n\r\n          const panel = panels.find(\r\n            item => item.dataset.panel === tab.dataset.tab\r\n          );\r\n\r\n          if (!panel) return;\r\n\r\n          tabs.forEach(item => {\r\n            item.classList.toggle(\r\n              'is-active',\r\n              item === tab\r\n            );\r\n          });\r\n\r\n          panels.forEach(item => {\r\n            item.classList.toggle(\r\n              'is-active',\r\n              item === panel\r\n            );\r\n          });\r\n\r\n          if (\r\n            window.gsap &&\r\n            !reducedQuery.matches\r\n          ) {\r\n            window.gsap.fromTo(\r\n              panel,\r\n              {\r\n                autoAlpha: 0,\r\n                y: 8\r\n              },\r\n              {\r\n                autoAlpha: 1,\r\n                y: 0,\r\n                duration: 0.28,\r\n                ease: 'power3.out',\r\n                overwrite: true\r\n              }\r\n            );\r\n          }\r\n        });\r\n      });\r\n    }\r\n\r\n    \/* MODULO PREVENTIVO *\/\r\n\r\n    function initQuoteForm() {\r\n      const form = document.querySelector('#mpQuoteForm');\r\n      const status = document.querySelector('#mpFormStatus');\r\n\r\n      if (!form || !status) return;\r\n\r\n      const fileInput = form.querySelector('#mpFile');\r\n      const fileName = form.querySelector('#mpFileName');\r\n\r\n      const privacy = form.querySelector(\r\n        '#mpPrivacyAcceptance'\r\n      );\r\n\r\n      let submitting = false;\r\n\r\n      const ajaxUrl =\r\n        form.dataset.ajaxUrl ||\r\n        window.location.origin +\r\n          '\/wp-admin\/admin-ajax.php';\r\n\r\n      function setStatus(message, type) {\r\n        status.textContent = message;\r\n\r\n        status.className =\r\n          `mp-form-status is-visible is-${type}`;\r\n      }\r\n\r\n      function clearStatus() {\r\n        status.textContent = '';\r\n        status.className = 'mp-form-status';\r\n      }\r\n\r\n      function updateLabels() {\r\n        form.querySelectorAll('.mp-field').forEach(field => {\r\n          const input = field.querySelector(\r\n            'input, textarea, select'\r\n          );\r\n\r\n          if (\r\n            input &&\r\n            !['checkbox', 'file'].includes(input.type)\r\n          ) {\r\n            field.classList.toggle(\r\n              'is-filled',\r\n              input.value.trim() !== ''\r\n            );\r\n          }\r\n        });\r\n      }\r\n\r\n      function captchaId() {\r\n        const id = form.dataset.captchaWidgetId;\r\n\r\n        return id !== undefined && id !== ''\r\n          ? Number(id)\r\n          : undefined;\r\n      }\r\n\r\n      function resetCaptcha() {\r\n        try {\r\n          window.grecaptcha?.reset(\r\n            captchaId()\r\n          );\r\n        } catch (_) {\r\n          \/* Widget non pronto. *\/\r\n        }\r\n      }\r\n\r\n      form.addEventListener(\r\n        'input',\r\n        updateLabels\r\n      );\r\n\r\n      form.addEventListener(\r\n        'change',\r\n        updateLabels\r\n      );\r\n\r\n      updateLabels();\r\n\r\n      fileInput?.addEventListener('change', () => {\r\n        const file = fileInput.files[0];\r\n\r\n        if (\r\n          file &&\r\n          file.size > 10 * 1024 * 1024\r\n        ) {\r\n          fileInput.value = '';\r\n\r\n          if (fileName) {\r\n            fileName.textContent = '';\r\n          }\r\n\r\n          setStatus(\r\n            'Il file supera il limite massimo di 10 MB.',\r\n            'error'\r\n          );\r\n        } else {\r\n          if (fileName) {\r\n            fileName.textContent = file?.name || '';\r\n          }\r\n\r\n          clearStatus();\r\n        }\r\n      });\r\n\r\n      form.addEventListener('submit', async event => {\r\n        event.preventDefault();\r\n\r\n        if (submitting) return;\r\n\r\n        stopMotion();\r\n        clearStatus();\r\n\r\n        const submit = form.querySelector(\r\n          '.mp-submit-btn'\r\n        );\r\n\r\n        const text = submit?.querySelector('span');\r\n        const originalText = text?.textContent;\r\n\r\n        const empty = [\r\n          ...form.querySelectorAll(\r\n            'input[required], textarea[required]'\r\n          )\r\n        ].find(field => {\r\n          return (\r\n            !['checkbox', 'file', 'radio'].includes(\r\n              field.type\r\n            ) &&\r\n            !field.value.trim()\r\n          );\r\n        });\r\n\r\n        if (empty) {\r\n          setStatus(\r\n            'Compila tutti i campi obbligatori prima di inviare.',\r\n            'error'\r\n          );\r\n\r\n          empty.focus();\r\n          return;\r\n        }\r\n\r\n        if (privacy && !privacy.checked) {\r\n          setStatus(\r\n            'Per inviare il modulo devi dichiarare di aver letto l\u2019informativa privacy.',\r\n            'error'\r\n          );\r\n\r\n          privacy.focus();\r\n          return;\r\n        }\r\n\r\n        if (!form.checkValidity()) {\r\n          setStatus(\r\n            'Compila correttamente tutti i campi obbligatori prima di inviare.',\r\n            'error'\r\n          );\r\n\r\n          form.reportValidity();\r\n          return;\r\n        }\r\n\r\n        let token;\r\n\r\n        try {\r\n          if (!window.grecaptcha?.getResponse) {\r\n            throw new Error('Captcha non disponibile');\r\n          }\r\n\r\n          token = window.grecaptcha.getResponse(\r\n            captchaId()\r\n          );\r\n        } catch (_) {\r\n          setStatus(\r\n            'Il CAPTCHA non \u00e8 stato caricato correttamente. Ricarica la pagina e riprova.',\r\n            'error'\r\n          );\r\n\r\n          return;\r\n        }\r\n\r\n        if (!token) {\r\n          setStatus(\r\n            'Completa la verifica CAPTCHA prima di inviare il modulo.',\r\n            'error'\r\n          );\r\n\r\n          return;\r\n        }\r\n\r\n        const data = new FormData(form);\r\n\r\n        data.set(\r\n          'action',\r\n          'mp_send_quote_request'\r\n        );\r\n\r\n        data.set(\r\n          'g-recaptcha-response',\r\n          token\r\n        );\r\n\r\n        submitting = true;\r\n\r\n        if (submit) {\r\n          submit.disabled = true;\r\n        }\r\n\r\n        if (text) {\r\n          text.textContent = 'Invio in corso...';\r\n        }\r\n\r\n        try {\r\n          const response = await fetch(\r\n            ajaxUrl,\r\n            {\r\n              method: 'POST',\r\n              body: data,\r\n              credentials: 'same-origin'\r\n            }\r\n          );\r\n\r\n          const result = await response.json();\r\n\r\n          if (\r\n            !response.ok ||\r\n            !result?.success\r\n          ) {\r\n            setStatus(\r\n              result?.data?.message ||\r\n                'Si \u00e8 verificato un errore durante l\u2019invio. Riprova tra poco.',\r\n              'error'\r\n            );\r\n\r\n            resetCaptcha();\r\n            return;\r\n          }\r\n\r\n          setStatus(\r\n            'Messaggio inviato correttamente. Reindirizzamento in corso...',\r\n            'success'\r\n          );\r\n\r\n          form.reset();\r\n\r\n          if (fileName) {\r\n            fileName.textContent = '';\r\n          }\r\n\r\n          updateLabels();\r\n          resetCaptcha();\r\n\r\n          window.location.assign(\r\n            form.dataset.successUrl ||\r\n              result.data?.redirect_url ||\r\n              '\/grazie\/'\r\n          );\r\n        } catch (_) {\r\n          setStatus(\r\n            'Errore di connessione o risposta non valida. Riprova tra poco.',\r\n            'error'\r\n          );\r\n\r\n          resetCaptcha();\r\n        } finally {\r\n          submitting = false;\r\n\r\n          if (submit) {\r\n            submit.disabled = false;\r\n          }\r\n\r\n          if (text) {\r\n            text.textContent = originalText;\r\n          }\r\n        }\r\n      });\r\n    }\r\n\r\n    \/* NEWS WORDPRESS *\/\r\n\r\n    function initNews() {\r\n      const grid = document.querySelector('#mpNewsGrid');\r\n\r\n      if (!grid) return;\r\n\r\n      const fallbacks = [\r\n        'https:\/\/images.unsplash.com\/photo-1600607687920-4e2a09cf159d?auto=format&fit=crop&w=1200&q=85',\r\n        'https:\/\/images.unsplash.com\/photo-1600566752355-35792bedcfea?auto=format&fit=crop&w=1200&q=85',\r\n        'https:\/\/images.unsplash.com\/photo-1600566753190-17f0baa2a6c3?auto=format&fit=crop&w=1200&q=85'\r\n      ];\r\n\r\n      function plain(html) {\r\n        return new DOMParser()\r\n          .parseFromString(\r\n            html || '',\r\n            'text\/html'\r\n          )\r\n          .body.textContent || '';\r\n      }\r\n\r\n      function safeUrl(value, fallback) {\r\n        try {\r\n          const url = new URL(\r\n            value,\r\n            window.location.origin\r\n          );\r\n\r\n          return ['http:', 'https:'].includes(url.protocol)\r\n            ? url.href\r\n            : fallback;\r\n        } catch (_) {\r\n          return fallback;\r\n        }\r\n      }\r\n\r\n      function element(tag, className, text) {\r\n        const node = document.createElement(tag);\r\n\r\n        node.className = className;\r\n\r\n        if (text !== undefined) {\r\n          node.textContent = text;\r\n        }\r\n\r\n        return node;\r\n      }\r\n\r\n      function render(posts) {\r\n        grid.replaceChildren();\r\n\r\n        if (!posts.length) {\r\n          grid.append(\r\n            element(\r\n              'div',\r\n              'mp-news-empty',\r\n              'Al momento non ci sono notizie disponibili.'\r\n            )\r\n          );\r\n\r\n          return;\r\n        }\r\n\r\n        for (const [index, post] of posts.entries()) {\r\n          const title = plain(\r\n            post.title?.rendered\r\n          );\r\n\r\n          const excerpt = plain(\r\n            post.excerpt?.rendered\r\n          );\r\n\r\n          const media =\r\n            post._embedded?.['wp:featuredmedia']?.[0];\r\n\r\n          const sizes = media?.media_details?.sizes;\r\n\r\n          const imageUrl =\r\n            sizes?.large?.source_url ||\r\n            sizes?.medium_large?.source_url ||\r\n            sizes?.full?.source_url ||\r\n            media?.source_url;\r\n\r\n          const card = element(\r\n            'a',\r\n            'mp-news-card'\r\n          );\r\n\r\n          card.href = safeUrl(\r\n            post.link || '#',\r\n            '#'\r\n          );\r\n\r\n          card.setAttribute(\r\n            'aria-label',\r\n            `Leggi articolo: ${title}`\r\n          );\r\n\r\n          const cover = element(\r\n            'div',\r\n            'mp-news-image'\r\n          );\r\n\r\n          const img = document.createElement('img');\r\n\r\n          const fallback =\r\n            fallbacks[index % fallbacks.length];\r\n\r\n          img.src = safeUrl(\r\n            imageUrl || fallback,\r\n            fallback\r\n          );\r\n\r\n          img.alt = title;\r\n          img.loading = 'lazy';\r\n\r\n          cover.append(img);\r\n\r\n          const body = element(\r\n            'div',\r\n            'mp-news-body'\r\n          );\r\n\r\n          const date = new Date(post.date);\r\n\r\n          body.append(\r\n            element(\r\n              'span',\r\n              'mp-news-date',\r\n              Number.isNaN(date.getTime())\r\n                ? ''\r\n                : date.toLocaleDateString(\r\n                    'it-IT',\r\n                    {\r\n                      day: '2-digit',\r\n                      month: 'long',\r\n                      year: 'numeric'\r\n                    }\r\n                  )\r\n            ),\r\n\r\n            element(\r\n              'h3',\r\n              '',\r\n              title\r\n            ),\r\n\r\n            element(\r\n              'div',\r\n              'mp-news-divider'\r\n            ),\r\n\r\n            element(\r\n              'p',\r\n              '',\r\n              excerpt.length > 145\r\n                ? excerpt.substring(0, 145).trim() + ' [...]'\r\n                : excerpt\r\n            )\r\n          );\r\n\r\n          card.append(cover, body);\r\n          grid.append(card);\r\n        }\r\n      }\r\n\r\n      async function load() {\r\n        const endpoint = new URL(\r\n          grid.dataset.endpoint ||\r\n            '\/wp-json\/wp\/v2\/posts',\r\n          window.location.origin\r\n        );\r\n\r\n        endpoint.searchParams.set(\r\n          'per_page',\r\n          '3'\r\n        );\r\n\r\n        endpoint.searchParams.set(\r\n          '_embed',\r\n          '1'\r\n        );\r\n\r\n        if (grid.dataset.categoryId) {\r\n          endpoint.searchParams.set(\r\n            'categories',\r\n            grid.dataset.categoryId\r\n          );\r\n        }\r\n\r\n        try {\r\n          const response = await fetch(\r\n            endpoint,\r\n            {\r\n              credentials: 'same-origin'\r\n            }\r\n          );\r\n\r\n          if (!response.ok) {\r\n            throw new Error('News non disponibili');\r\n          }\r\n\r\n          const posts = await response.json();\r\n\r\n          if (!Array.isArray(posts)) {\r\n            throw new Error('Risposta non valida');\r\n          }\r\n\r\n          render(posts);\r\n        } catch (_) {\r\n          grid.replaceChildren(\r\n            element(\r\n              'div',\r\n              'mp-news-empty',\r\n              'Non \u00e8 stato possibile caricare le ultime notizie. Riprova pi\u00f9 tardi.'\r\n            )\r\n          );\r\n        }\r\n\r\n        requestAnimationFrame(onScroll);\r\n      }\r\n\r\n      load();\r\n    }\r\n  }\r\n\r\n  \/* AVVIO *\/\r\n\r\n  function start() {\r\n    if (\r\n      document.querySelector('#mp-fullpage-wrapper')\r\n    ) {\r\n      boot();\r\n      return;\r\n    }\r\n\r\n    const observer = new MutationObserver(() => {\r\n      if (\r\n        document.querySelector('#mp-fullpage-wrapper')\r\n      ) {\r\n        observer.disconnect();\r\n        boot();\r\n      }\r\n    });\r\n\r\n    observer.observe(\r\n      document.body,\r\n      {\r\n        childList: true,\r\n        subtree: true\r\n      }\r\n    );\r\n\r\n    setTimeout(() => {\r\n      observer.disconnect();\r\n    }, 15000);\r\n  }\r\n\r\n  if (document.readyState === 'loading') {\r\n    document.addEventListener(\r\n      'DOMContentLoaded',\r\n      start,\r\n      { once: true }\r\n    );\r\n  } else {\r\n    start();\r\n  }\r\n})();\r\n\r\n\/* FADE DEGLI ELEMENTI SU MOBILE \u2014 SCORRIMENTO NATIVO *\/\r\n\r\n(() => {\r\n  'use strict';\r\n\r\n  function initMobileFade() {\r\n    const wrapper = document.querySelector(\r\n      '#mp-fullpage-wrapper'\r\n    );\r\n\r\n    if (!wrapper) return;\r\n\r\n    if (\r\n      document.getElementById('mp-mobile-content-fade-style')\r\n    ) {\r\n      return;\r\n    }\r\n\r\n    const mobileQuery = window.matchMedia(\r\n      '(max-width: 1024px)'\r\n    );\r\n\r\n    const reducedQuery = window.matchMedia(\r\n      '(prefers-reduced-motion: reduce)'\r\n    );\r\n\r\n    const selector =\r\n      '.mp-kicker, .mp-content h1, .mp-content h2, ' +\r\n      '.mp-desc, .mp-btn, .mp-services-left, ' +\r\n      '.mp-services-image, .mp-quote-info, ' +\r\n      '.mp-quote-form-card, .mp-news-heading, .mp-news-card';\r\n\r\n    const style = document.createElement('style');\r\n\r\n    style.id = 'mp-mobile-content-fade-style';\r\n\r\n    style.textContent = `\r\n      html.mp-free-mobile body.mp-native-ready\r\n      #mp-fullpage-wrapper .mp-mobile-fade-item {\r\n        opacity: 1 !important;\r\n        visibility: visible !important;\r\n        transform: none !important;\r\n        animation: none !important;\r\n\r\n        transition:\r\n          opacity 800ms ease\r\n          var(--mp-mobile-fade-delay, 0ms) !important;\r\n      }\r\n\r\n      html.mp-free-mobile body.mp-native-ready\r\n      #mp-fullpage-wrapper\r\n      .mp-mobile-fade-item.mp-mobile-fade-hidden {\r\n        opacity: 0 !important;\r\n        transition: none !important;\r\n      }\r\n\r\n      html.mp-free-mobile body.mp-native-ready\r\n      #mp-fullpage-wrapper\r\n      .mp-mobile-fade-item.mp-mobile-fade-instant {\r\n        opacity: 1 !important;\r\n        transition: none !important;\r\n      }\r\n\r\n      @media (prefers-reduced-motion: reduce) {\r\n        html.mp-free-mobile body.mp-native-ready\r\n        #mp-fullpage-wrapper .mp-mobile-fade-item {\r\n          opacity: 1 !important;\r\n          transition: none !important;\r\n        }\r\n      }\r\n    `;\r\n\r\n    document.head.append(style);\r\n\r\n    const trackedItems = new Set();\r\n\r\n    let entryObserver = null;\r\n    let exitObserver = null;\r\n    let contentObserver = null;\r\n    let scanFrame = 0;\r\n\r\n    function reveal(item) {\r\n      item.classList.remove('mp-mobile-fade-hidden');\r\n    }\r\n\r\n    function resetItem(item) {\r\n      item.classList.remove(\r\n        'mp-mobile-fade-item',\r\n        'mp-mobile-fade-hidden',\r\n        'mp-mobile-fade-instant'\r\n      );\r\n\r\n      item.style.removeProperty(\r\n        '--mp-mobile-fade-delay'\r\n      );\r\n    }\r\n\r\n    function cleanup() {\r\n      entryObserver?.disconnect();\r\n      exitObserver?.disconnect();\r\n      contentObserver?.disconnect();\r\n\r\n      entryObserver = null;\r\n      exitObserver = null;\r\n      contentObserver = null;\r\n\r\n      cancelAnimationFrame(scanFrame);\r\n      scanFrame = 0;\r\n\r\n      trackedItems.forEach(resetItem);\r\n      trackedItems.clear();\r\n    }\r\n\r\n    function scanItems() {\r\n      scanFrame = 0;\r\n\r\n      if (!entryObserver || !exitObserver) return;\r\n\r\n      \/\/ Rimuove eventuali elementi sostituiti, ad esempio le news.\r\n      trackedItems.forEach(item => {\r\n        if (!wrapper.contains(item)) {\r\n          entryObserver.unobserve(item);\r\n          exitObserver.unobserve(item);\r\n\r\n          resetItem(item);\r\n          trackedItems.delete(item);\r\n        }\r\n      });\r\n\r\n      wrapper.querySelectorAll('.section').forEach(section => {\r\n        section.querySelectorAll(selector).forEach((item, index) => {\r\n          if (trackedItems.has(item)) return;\r\n\r\n          trackedItems.add(item);\r\n\r\n          item.classList.add('mp-mobile-fade-item');\r\n\r\n          item.style.setProperty(\r\n            '--mp-mobile-fade-delay',\r\n            `${Math.min(index, 3) * 45}ms`\r\n          );\r\n\r\n          const rect = item.getBoundingClientRect();\r\n\r\n          const alreadyVisible =\r\n            rect.bottom > 0 &&\r\n            rect.top < window.innerHeight;\r\n\r\n          \/*\r\n           * Non nasconde contenuti gi\u00e0 visibili quando\r\n           * lo script si avvia: evita il flash iniziale.\r\n           *\/\r\n          if (!alreadyVisible) {\r\n            item.classList.add('mp-mobile-fade-hidden');\r\n          }\r\n\r\n          entryObserver.observe(item);\r\n          exitObserver.observe(item);\r\n        });\r\n      });\r\n    }\r\n\r\n    function setup() {\r\n      cleanup();\r\n\r\n      if (\r\n        !mobileQuery.matches ||\r\n        reducedQuery.matches ||\r\n        !('IntersectionObserver' in window)\r\n      ) {\r\n        return;\r\n      }\r\n\r\n      \/*\r\n       * Rivela gli elementi quando entrano nella\r\n       * parte visibile della finestra.\r\n       *\/\r\n      entryObserver = new IntersectionObserver(\r\n        entries => {\r\n          entries.forEach(entry => {\r\n            if (entry.isIntersecting) {\r\n              reveal(entry.target);\r\n            }\r\n          });\r\n        },\r\n        {\r\n          root: null,\r\n          threshold: 0,\r\n          rootMargin: '-6% 0px -8% 0px'\r\n        }\r\n      );\r\n\r\n      \/*\r\n       * Nasconde di nuovo un elemento solamente quando\r\n       * \u00e8 completamente fuori dallo schermo.\r\n       *\/\r\n      exitObserver = new IntersectionObserver(\r\n        entries => {\r\n          entries.forEach(entry => {\r\n            if (entry.isIntersecting) return;\r\n\r\n            const item = entry.target;\r\n            const rect = item.getBoundingClientRect();\r\n\r\n            const completelyOutside =\r\n              rect.bottom <= 0 ||\r\n              rect.top >= window.innerHeight;\r\n\r\n            if (\r\n              completelyOutside &&\r\n              !item.contains(document.activeElement)\r\n            ) {\r\n              item.classList.remove(\r\n                'mp-mobile-fade-instant'\r\n              );\r\n\r\n              item.classList.add(\r\n                'mp-mobile-fade-hidden'\r\n              );\r\n            }\r\n          });\r\n        },\r\n        {\r\n          root: null,\r\n          threshold: 0\r\n        }\r\n      );\r\n\r\n      scanItems();\r\n\r\n      \/\/ Include anche eventuali contenuti caricati successivamente.\r\n      contentObserver = new MutationObserver(() => {\r\n        if (!scanFrame) {\r\n          scanFrame = requestAnimationFrame(scanItems);\r\n        }\r\n      });\r\n\r\n      contentObserver.observe(wrapper, {\r\n        childList: true,\r\n        subtree: true\r\n      });\r\n    }\r\n\r\n    \/*\r\n     * Un elemento che riceve il focus deve essere\r\n     * immediatamente visibile, anche usando la tastiera.\r\n     *\/\r\n    wrapper.addEventListener('focusin', event => {\r\n      trackedItems.forEach(item => {\r\n        if (item.contains(event.target)) {\r\n          item.classList.add('mp-mobile-fade-instant');\r\n          reveal(item);\r\n        }\r\n      });\r\n    });\r\n\r\n    mobileQuery.addEventListener('change', setup);\r\n    reducedQuery.addEventListener('change', setup);\r\n\r\n    setup();\r\n  }\r\n\r\n  if (document.readyState === 'loading') {\r\n    document.addEventListener(\r\n      'DOMContentLoaded',\r\n      initMobileFade,\r\n      { once: true }\r\n    );\r\n  } else {\r\n    initMobileFade();\r\n  }\r\n})();<\/script><\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t","protected":false},"excerpt":{"rendered":"<p>WE DESIGN AND MANUFACTURE LIFTS, GOODS LIFTS AND ESCALATORS FOR EFFICIENT AND SAFE MOBILITY We assess the requirements of every type of building and provide the most suitable solution for each customer, from design through to final installation. LIFTS We design and manufacture lifts that combine design, comfort and outstanding reliability. Solutions developed for residential [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"elementor_header_footer","meta":{"footnotes":""},"class_list":["post-2089","page","type-page","status-publish","hentry"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.1.1 - aioseo.com -->\n\t<meta name=\"description\" content=\"Millepiani designs and manufactures lifts, goods lifts, platform lifts, stairlifts and escalators: safe, efficient and tailor-made solutions.\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<link rel=\"canonical\" href=\"https:\/\/millepiani.com\/en\/\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.1.1\" \/>\n\t\t<meta property=\"og:locale\" content=\"en_US\" \/>\n\t\t<meta property=\"og:site_name\" content=\"millepiani.com -\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"Lifts, Goods Lifts and Vertical Mobility | Millepiani\" \/>\n\t\t<meta property=\"og:description\" content=\"Millepiani designs and manufactures lifts, goods lifts, platform lifts, stairlifts and escalators: safe, efficient and tailor-made solutions.\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/millepiani.com\/en\/\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2026-05-13T20:09:45+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2026-09-11T00:29:16+00:00\" \/>\n\t\t<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n\t\t<meta name=\"twitter:title\" content=\"Lifts, Goods Lifts and Vertical Mobility | Millepiani\" \/>\n\t\t<meta name=\"twitter:description\" content=\"Millepiani designs and manufactures lifts, goods lifts, platform lifts, stairlifts and escalators: safe, efficient and tailor-made solutions.\" \/>\n\t\t<script type=\"application\/ld+json\" class=\"aioseo-schema\">\n\t\t\t{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/millepiani.com\\\/en\\\/#breadcrumblist\",\"itemListElement\":[{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/millepiani.com\\\/en\\\/#listItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/millepiani.com\\\/en\\\/\",\"nextItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/millepiani.com\\\/en\\\/#listItem\",\"name\":\"Nuova pagina elevators\"}},{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/millepiani.com\\\/en\\\/#listItem\",\"position\":2,\"name\":\"Nuova pagina elevators\",\"previousItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/millepiani.com\\\/en\\\/#listItem\",\"name\":\"Home\"}}]},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/millepiani.com\\\/en\\\/#organization\",\"name\":\"millepiani.com\",\"url\":\"https:\\\/\\\/millepiani.com\\\/en\\\/\"},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/millepiani.com\\\/en\\\/#webpage\",\"url\":\"https:\\\/\\\/millepiani.com\\\/en\\\/\",\"name\":\"Lifts, Goods Lifts and Vertical Mobility | Millepiani\",\"description\":\"Millepiani designs and manufactures lifts, goods lifts, platform lifts, stairlifts and escalators: safe, efficient and tailor-made solutions.\",\"inLanguage\":\"en-US\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/millepiani.com\\\/en\\\/#website\"},\"breadcrumb\":{\"@id\":\"https:\\\/\\\/millepiani.com\\\/en\\\/#breadcrumblist\"},\"datePublished\":\"2026-05-13T20:09:45+00:00\",\"dateModified\":\"2026-09-11T00:29:16+00:00\"},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/millepiani.com\\\/en\\\/#website\",\"url\":\"https:\\\/\\\/millepiani.com\\\/en\\\/\",\"name\":\"millepiani.com\",\"inLanguage\":\"en-US\",\"publisher\":{\"@id\":\"https:\\\/\\\/millepiani.com\\\/en\\\/#organization\"}}]}\n\t\t<\/script>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"Lifts, Goods Lifts and Vertical Mobility | Millepiani","description":"Millepiani designs and manufactures lifts, goods lifts, platform lifts, stairlifts and escalators: safe, efficient and tailor-made solutions.","canonical_url":"https:\/\/millepiani.com\/en\/","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"BreadcrumbList","@id":"https:\/\/millepiani.com\/en\/#breadcrumblist","itemListElement":[{"@type":"ListItem","@id":"https:\/\/millepiani.com\/en\/#listItem","position":1,"name":"Home","item":"https:\/\/millepiani.com\/en\/","nextItem":{"@type":"ListItem","@id":"https:\/\/millepiani.com\/en\/#listItem","name":"Nuova pagina elevators"}},{"@type":"ListItem","@id":"https:\/\/millepiani.com\/en\/#listItem","position":2,"name":"Nuova pagina elevators","previousItem":{"@type":"ListItem","@id":"https:\/\/millepiani.com\/en\/#listItem","name":"Home"}}]},{"@type":"Organization","@id":"https:\/\/millepiani.com\/en\/#organization","name":"millepiani.com","url":"https:\/\/millepiani.com\/en\/"},{"@type":"WebPage","@id":"https:\/\/millepiani.com\/en\/#webpage","url":"https:\/\/millepiani.com\/en\/","name":"Lifts, Goods Lifts and Vertical Mobility | Millepiani","description":"Millepiani designs and manufactures lifts, goods lifts, platform lifts, stairlifts and escalators: safe, efficient and tailor-made solutions.","inLanguage":"en-US","isPartOf":{"@id":"https:\/\/millepiani.com\/en\/#website"},"breadcrumb":{"@id":"https:\/\/millepiani.com\/en\/#breadcrumblist"},"datePublished":"2026-05-13T20:09:45+00:00","dateModified":"2026-09-11T00:29:16+00:00"},{"@type":"WebSite","@id":"https:\/\/millepiani.com\/en\/#website","url":"https:\/\/millepiani.com\/en\/","name":"millepiani.com","inLanguage":"en-US","publisher":{"@id":"https:\/\/millepiani.com\/en\/#organization"}}]},"og:locale":"en_US","og:site_name":"millepiani.com -","og:type":"article","og:title":"Lifts, Goods Lifts and Vertical Mobility | Millepiani","og:description":"Millepiani designs and manufactures lifts, goods lifts, platform lifts, stairlifts and escalators: safe, efficient and tailor-made solutions.","og:url":"https:\/\/millepiani.com\/en\/","article:published_time":"2026-05-13T20:09:45+00:00","article:modified_time":"2026-09-11T00:29:16+00:00","twitter:card":"summary_large_image","twitter:title":"Lifts, Goods Lifts and Vertical Mobility | Millepiani","twitter:description":"Millepiani designs and manufactures lifts, goods lifts, platform lifts, stairlifts and escalators: safe, efficient and tailor-made solutions."},"aioseo_meta_data":{"post_id":"2089","title":"Lifts, Goods Lifts and Vertical Mobility | Millepiani","description":"Millepiani designs and manufactures lifts, goods lifts, platform lifts, stairlifts and escalators: safe, efficient and tailor-made solutions.","keywords":null,"keyphrases":{"focus":{"keyphrase":"produttori ascensori","score":0,"analysis":[]},"additional":[]},"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_custom_url":null,"og_image_custom_fields":null,"og_image_url":null,"og_image_width":null,"og_image_height":null,"og_video":"","og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_image_url":null,"twitter_title":null,"twitter_description":null,"schema_type":"default","schema_type_options":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"WebPage","isEnabled":true},"graphs":[]},"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":"-1","robots_max_videopreview":"-1","robots_max_imagepreview":"large","priority":null,"frequency":"default","local_seo":null,"limit_modified_date":false,"ai":{"faqs":[],"keyPoints":[],"schemas":[],"titles":[],"descriptions":[],"socialPosts":{"email":{"subject":"","preview":"","content":""},"linkedin":[],"twitter":[],"facebook":[],"instagram":[]}},"breadcrumb_settings":null,"seo_analyzer_scan_date":null,"created":"2026-09-09 14:13:31","updated":"2026-09-11 07:36:42","focus_keyword":"produttori ascensori","additional_keywords":null,"truseo_locale":null},"aioseo_breadcrumb":"<div class=\"aioseo-breadcrumbs\"><span class=\"aioseo-breadcrumb\">\n\t\t\t<a href=\"https:\/\/millepiani.com\/en\/\" title=\"Home\">Home<\/a>\n\t\t<\/span><span class=\"aioseo-breadcrumb-separator\">&raquo;<\/span><span class=\"aioseo-breadcrumb\">\n\t\t\tNuova pagina elevators\n\t\t<\/span><\/div>","aioseo_breadcrumb_json":[{"label":"Home","link":"https:\/\/millepiani.com\/en\/"},{"label":"Nuova pagina elevators","link":"https:\/\/millepiani.com\/en\/"}],"_hostinger_reach_plugin_has_subscription_block":false,"_hostinger_reach_plugin_is_elementor":false,"_links":{"self":[{"href":"https:\/\/millepiani.com\/en\/wp-json\/wp\/v2\/pages\/2089","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/millepiani.com\/en\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/millepiani.com\/en\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/millepiani.com\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/millepiani.com\/en\/wp-json\/wp\/v2\/comments?post=2089"}],"version-history":[{"count":7,"href":"https:\/\/millepiani.com\/en\/wp-json\/wp\/v2\/pages\/2089\/revisions"}],"predecessor-version":[{"id":2254,"href":"https:\/\/millepiani.com\/en\/wp-json\/wp\/v2\/pages\/2089\/revisions\/2254"}],"wp:attachment":[{"href":"https:\/\/millepiani.com\/en\/wp-json\/wp\/v2\/media?parent=2089"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}