{"id":21836,"date":"2026-04-28T16:50:13","date_gmt":"2026-04-28T16:50:13","guid":{"rendered":"https:\/\/www.salvatorerobuschi.com\/area-riservata\/"},"modified":"2026-05-20T20:29:52","modified_gmt":"2026-05-20T20:29:52","slug":"reserved-area","status":"publish","type":"page","link":"https:\/\/www.salvatorerobuschi.com\/en\/reserved-area\/","title":{"rendered":"Reserved area"},"content":{"rendered":"\t\t<div data-elementor-type=\"wp-page\" data-elementor-id=\"21836\" class=\"elementor elementor-21836 elementor-19335\" data-elementor-post-type=\"page\">\n\t\t\t\t<div class=\"elementor-element elementor-element-e96c763 e-con-full e-flex e-con e-parent\" data-id=\"e96c763\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t<div class=\"elementor-element elementor-element-b6e3c51 elementor-widget__width-initial elementor-widget-mobile__width-inherit elementor-widget elementor-widget-heading\" data-id=\"b6e3c51\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t\t<h1 class=\"elementor-heading-title elementor-size-default\"><span style=\"color: #e4002b\">Download<\/span> technical resources and documentation<\/h1>\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-ffc2c1a e-con-full e-flex e-con e-child\" data-id=\"ffc2c1a\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t<div class=\"elementor-element elementor-element-2b190e2 e-con-full e-flex e-con e-child\" data-id=\"2b190e2\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t<div class=\"elementor-element elementor-element-5c03715 elementor-button-align-start elementor-mobile-button-align-start elementor-widget elementor-widget-form\" data-id=\"5c03715\" data-element_type=\"widget\" data-e-type=\"widget\" data-settings=\"{&quot;step_next_label&quot;:&quot;Successivo&quot;,&quot;step_previous_label&quot;:&quot;Precedente&quot;,&quot;step_icon_shape&quot;:&quot;none&quot;,&quot;step_type&quot;:&quot;none&quot;,&quot;button_width&quot;:&quot;100&quot;}\" data-widget_type=\"form.default\">\n\t\t\t\t\t\t\t<form class=\"elementor-form\" method=\"post\" name=\"Download\" aria-label=\"Download\">\n\t\t\t<input type=\"hidden\" name=\"post_id\" value=\"21836\"\/>\n\t\t\t<input type=\"hidden\" name=\"form_id\" value=\"5c03715\"\/>\n\t\t\t<input type=\"hidden\" name=\"referer_title\" value=\"Reserved area: technical drawings &amp; CAD | Salvatore Robuschi\" \/>\n\n\t\t\t\t\t\t\t<input type=\"hidden\" name=\"queried_id\" value=\"21836\"\/>\n\t\t\t\n\t\t\t<div class=\"elementor-form-fields-wrapper elementor-labels-above\">\n\t\t\t\t\t\t\t\t<div class=\"elementor-field-type-select elementor-field-group elementor-column elementor-field-group-seltipo elementor-col-100\">\n\t\t\t\t\t\t\t\t\t\t\t\t<label for=\"form-field-seltipo\" class=\"elementor-field-label\">\n\t\t\t\t\t\t\t\tPump series\t\t\t\t\t\t\t<\/label>\n\t\t\t\t\t\t\t\t<div class=\"elementor-field elementor-select-wrapper remove-before \">\n\t\t\t<div class=\"select-caret-down-wrapper\">\n\t\t\t\t<svg aria-hidden=\"true\" class=\"e-font-icon-svg e-eicon-caret-down\" viewBox=\"0 0 571.4 571.4\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\"><path d=\"M571 393Q571 407 561 418L311 668Q300 679 286 679T261 668L11 418Q0 407 0 393T11 368 36 357H536Q550 357 561 368T571 393Z\"><\/path><\/svg>\t\t\t<\/div>\n\t\t\t<select name=\"form_fields[seltipo]\" id=\"form-field-seltipo\" class=\"elementor-field-textual elementor-size-md\">\n\t\t\t\t\t\t\t\t\t<option value=\"\"><\/option>\n\t\t\t\t\t\t\t<\/select>\n\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t\t\t\t\t<div class=\"elementor-field-type-select elementor-field-group elementor-column elementor-field-group-selgrandezza elementor-col-100\">\n\t\t\t\t\t\t\t\t\t\t\t\t<label for=\"form-field-selgrandezza\" class=\"elementor-field-label\">\n\t\t\t\t\t\t\t\tPump size\t\t\t\t\t\t\t<\/label>\n\t\t\t\t\t\t\t\t<div class=\"elementor-field elementor-select-wrapper remove-before \">\n\t\t\t<div class=\"select-caret-down-wrapper\">\n\t\t\t\t<svg aria-hidden=\"true\" class=\"e-font-icon-svg e-eicon-caret-down\" viewBox=\"0 0 571.4 571.4\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\"><path d=\"M571 393Q571 407 561 418L311 668Q300 679 286 679T261 668L11 418Q0 407 0 393T11 368 36 357H536Q550 357 561 368T571 393Z\"><\/path><\/svg>\t\t\t<\/div>\n\t\t\t<select name=\"form_fields[selgrandezza]\" id=\"form-field-selgrandezza\" class=\"elementor-field-textual elementor-size-md\">\n\t\t\t\t\t\t\t\t\t<option value=\"\"><\/option>\n\t\t\t\t\t\t\t<\/select>\n\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t\t\t\t\t<div class=\"elementor-field-type-html elementor-field-group elementor-column elementor-field-group-field_701aa40 elementor-col-100\">\n\t\t\t\t\t<div class=\"elementor-field-label\" id=\"label-montaggio\">Mounting options<\/div>\n<span class=\"elementor-field-option\">\n   <input type=\"checkbox\" id=\"checkbasamento\" \/>\n   <label for=\"checkbasamento\">Baseplate<\/label>\n<\/span>\n<span class=\"elementor-field-option\">\n   <input type=\"checkbox\" id=\"checkgiunto\" \/>\n   <label for=\"checkgiunto\">Coupling<\/label>\n<\/span>\t\t\t\t<\/div>\n\t\t\t\t\t\t\t\t<div class=\"elementor-field-type-select elementor-field-group elementor-column elementor-field-group-selpotenza elementor-col-100\">\n\t\t\t\t\t\t\t\t\t\t\t\t<label for=\"form-field-selpotenza\" class=\"elementor-field-label\">\n\t\t\t\t\t\t\t\tPower (kW)\t\t\t\t\t\t\t<\/label>\n\t\t\t\t\t\t\t\t<div class=\"elementor-field elementor-select-wrapper remove-before \">\n\t\t\t<div class=\"select-caret-down-wrapper\">\n\t\t\t\t<svg aria-hidden=\"true\" class=\"e-font-icon-svg e-eicon-caret-down\" viewBox=\"0 0 571.4 571.4\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\"><path d=\"M571 393Q571 407 561 418L311 668Q300 679 286 679T261 668L11 418Q0 407 0 393T11 368 36 357H536Q550 357 561 368T571 393Z\"><\/path><\/svg>\t\t\t<\/div>\n\t\t\t<select name=\"form_fields[selpotenza]\" id=\"form-field-selpotenza\" class=\"elementor-field-textual elementor-size-md\">\n\t\t\t\t\t\t\t\t\t<option value=\"\"><\/option>\n\t\t\t\t\t\t\t<\/select>\n\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t\t\t\t\t<div class=\"elementor-field-type-select elementor-field-group elementor-column elementor-field-group-selpolarita elementor-col-100\">\n\t\t\t\t\t\t\t\t\t\t\t\t<label for=\"form-field-selpolarita\" class=\"elementor-field-label\">\n\t\t\t\t\t\t\t\tNumber of poles\t\t\t\t\t\t\t<\/label>\n\t\t\t\t\t\t\t\t<div class=\"elementor-field elementor-select-wrapper remove-before \">\n\t\t\t<div class=\"select-caret-down-wrapper\">\n\t\t\t\t<svg aria-hidden=\"true\" class=\"e-font-icon-svg e-eicon-caret-down\" viewBox=\"0 0 571.4 571.4\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\"><path d=\"M571 393Q571 407 561 418L311 668Q300 679 286 679T261 668L11 418Q0 407 0 393T11 368 36 357H536Q550 357 561 368T571 393Z\"><\/path><\/svg>\t\t\t<\/div>\n\t\t\t<select name=\"form_fields[selpolarita]\" id=\"form-field-selpolarita\" class=\"elementor-field-textual elementor-size-md\">\n\t\t\t\t\t\t\t\t\t<option value=\"\"><\/option>\n\t\t\t\t\t\t\t<\/select>\n\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t\t\t\t\t<div class=\"elementor-field-type-html elementor-field-group elementor-column elementor-field-group-field_cd54335 elementor-col-100\">\n\t\t\t\t\t<div class=\"elementor-field-label\" id=\"label-dimensionale\">Flange standard<\/div>\n<div class=\"elementor-field-subgroup elementor-subgroup-inline\">\n   <span class=\"elementor-field-option\"><input type=\"radio\" name=\"standard_dim\" id=\"radiostandard\" value=\"standard\" checked disabled \/> <label for=\"radiostandard\">Standard<\/label><\/span>\n   <span class=\"elementor-field-option\"><input type=\"radio\" name=\"standard_dim\" id=\"radioansi\" value=\"ansi\" disabled \/> <label for=\"radioansi\">ANSI<\/label><\/span>\n   <span class=\"elementor-field-option\"><input type=\"radio\" name=\"standard_dim\" id=\"radiopn16\" value=\"pn16\" disabled \/> <label for=\"radiopn16\">PN16<\/label><\/span>\n<\/div>\t\t\t\t<\/div>\n\t\t\t\t\t\t\t\t<div class=\"elementor-field-type-html elementor-field-group elementor-column elementor-field-group-field_1328b7d elementor-col-100\">\n\t\t\t\t\t<div class=\"elementor-field-label\" id=\"label-formato\">File format<\/div>\n<span class=\"elementor-field-option\">\n   <input type=\"checkbox\" id=\"dl-cb-step\" \/>\n   <label for=\"dl-cb-step\">STEP<\/label>\n<\/span>\n<span class=\"elementor-field-option\">\n   <input type=\"checkbox\" id=\"dl-cb-dwg\" \/>\n   <label for=\"dl-cb-dwg\">DWG<\/label>\n<\/span>\n<span class=\"elementor-field-option\">\n   <input type=\"checkbox\" id=\"dl-cb-dxf\" \/>\n   <label for=\"dl-cb-dxf\">DXF<\/label>\n<\/span>\n<span class=\"elementor-field-option\">\n   <input type=\"checkbox\" id=\"dl-cb-pdf\" \/>\n   <label for=\"dl-cb-pdf\">PDF<\/label>\n<\/span>\t\t\t\t<\/div>\n\t\t\t\t\t\t\t\t<div class=\"elementor-field-type-html elementor-field-group elementor-column elementor-field-group-field_54d6a9f elementor-col-100\">\n\t\t\t\t\t<button class=\"bt-download\" id=\"dl-selected-formats\">Download<\/button>\t\t\t\t<\/div>\n\t\t\t\t\t\t\t\t<div class=\"elementor-field-group elementor-column elementor-field-type-submit elementor-col-100 e-form__buttons\">\n\t\t\t\t\t<button class=\"elementor-button elementor-size-sm\" type=\"submit\" id=\"hidden_submit_button\">\n\t\t\t\t\t\t<span class=\"elementor-button-content-wrapper\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<span class=\"elementor-button-text\">Scarica<\/span>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<\/span>\n\t\t\t\t\t<\/button>\n\t\t\t\t<\/div>\n\t\t\t<\/div>\n\t\t<\/form>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-cd8cc8e elementor-hidden-desktop elementor-hidden-tablet elementor-hidden-mobile elementor-widget elementor-widget-shortcode\" data-id=\"cd8cc8e\" 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\ndocument.addEventListener(\"DOMContentLoaded\", function () {\r\n    \/\/ ==========================================\r\n    \/\/ 1. DOM ELEMENT TARGETING & IMMEDIATE LOCKDOWN\r\n    \/\/ ==========================================\r\n    \r\n    \/\/ Select Dropdowns\r\n    const selTipo = document.getElementById(\"form-field-seltipo\");\r\n    const selGrandezza = document.getElementById(\"form-field-selgrandezza\");\r\n    const selPotenza = document.getElementById(\"form-field-selpotenza\");\r\n    const selPolarita = document.getElementById(\"form-field-selpolarita\");\r\n\r\n    \/\/ UI Checkboxes (Options)\r\n    const checkBasamento = document.getElementById(\"checkbasamento\");\r\n    const checkGiunto = document.getElementById(\"checkgiunto\");\r\n    \r\n    \/\/ Nuovi Radio Buttons per i Dimensionali (Flange)\r\n    const radioStandard = document.getElementById(\"radiostandard\");\r\n    const radioAnsi = document.getElementById(\"radioansi\");\r\n    const radioPn16 = document.getElementById(\"radiopn16\");\r\n\r\n    \/\/ Section Labels\r\n    const labelMontaggio = document.getElementById(\"label-montaggio\");\r\n    const labelDimensionale = document.getElementById(\"label-dimensionale\");\r\n    const labelFormato = document.getElementById(\"label-formato\");\r\n\r\n    \/\/ Bulk Download Button\r\n    const btnBulkDownload = document.getElementById(\"dl-selected-formats\"); \r\n        \r\n    \/\/ Download Checkboxes\r\n    const cbStep = document.getElementById(\"dl-cb-step\");\r\n    const cbDwg = document.getElementById(\"dl-cb-dwg\");\r\n    const cbDxf = document.getElementById(\"dl-cb-dxf\");\r\n    const cbIdw = document.getElementById(\"dl-cb-idw\");\r\n    const cbPdf = document.getElementById(\"dl-cb-pdf\");\r\n\t\r\n\t\/\/ Recupera le prime due lettere dell'attributo lang (es: \"it\" da \"it-IT\")  ----------------------------------------------------------------------- ASSA\r\n\tconst linguaCorrente = document.documentElement.lang.substring(0, 2);\r\n\tconsole.log(\"La lingua attualmente impostata \u00e8: \", linguaCorrente);\r\n\t\/\/ ------------------------------------------------------------------------------------------------------------------------------------------------ ASSA\r\n\r\n    \/\/ IMMEDIATELY DISABLE EVERYTHING ON LOAD\r\n    if (selTipo) selTipo.disabled = true;\r\n    if (selGrandezza) selGrandezza.disabled = true;\r\n    if (selPotenza) selPotenza.disabled = true;\r\n    if (selPolarita) selPolarita.disabled = true;\r\n\r\n    if (checkBasamento) checkBasamento.disabled = true;\r\n    if (checkGiunto) checkGiunto.disabled = true;\r\n    \r\n    if (radioStandard) { radioStandard.disabled = true; radioStandard.checked = true; } \r\n    if (radioAnsi) { radioAnsi.disabled = true; radioAnsi.checked = false; }\r\n    if (radioPn16) { radioPn16.disabled = true; radioPn16.checked = false; }\r\n\r\n    if (btnBulkDownload) btnBulkDownload.disabled = true;\r\n    \r\n    if (cbStep) cbStep.disabled = true;\r\n    if (cbDwg) cbDwg.disabled = true;\r\n    if (cbDxf) cbDxf.disabled = true;\r\n    if (cbIdw) cbIdw.disabled = true;\r\n    if (cbPdf) cbPdf.disabled = true;\r\n\r\n    \/\/ Hidden submit prevention (if embedded in a standard Elementor form)\r\n    const hiddenSubmit = document.getElementById(\"hidden_submit_button\");\r\n    if (hiddenSubmit) hiddenSubmit.addEventListener(\"click\", (e) => e.preventDefault());\r\n    \r\n\r\n\r\n    \/\/ ==========================================\r\n    \/\/ 2. STATE MANAGEMENT & MAPPING TABLES\r\n    \/\/ ==========================================\r\n    \r\n    let folderState = {\r\n        sb: null, cb: null, st: null, sp: null, sn: null, \r\n        finalMotor: null, baseD: null, ansiD: null, pn16D: null,\r\n        \r\n        expSb: null, expCb: null, expSt: null, expSp: null, expSn: null,\r\n        expFinalMotor: null, expBaseE: null, expAnsiE: null, expPn16E: null,\r\n        \r\n        tipoName: null, grandezzaName: null, basamentoName: null, giuntoName: null, motorName: null\r\n    };\r\n\r\n    let exportRootId = null;\r\n    let tabelleRootId = null;\r\n    \r\n    let exportTipos = [];\r\n    let exportGrandezze = [];\r\n    let exportBasamenti = []; \r\n    let exportGiunti = []; \r\n    let exportMotors = []; \r\n    let tabelleFolders = []; \r\n\r\n    let currentValidSpecs = []; \r\n    let availableFiles = {\r\n        step: null, dwg: null, dxf: null, idw: null, pdf: null\r\n    };\r\n\r\n    const checkboxes = { basamento: checkBasamento, giunto: checkGiunto };\r\n    const downloadCheckboxes = { step: cbStep, dwg: cbDwg, dxf: cbDxf, idw: cbIdw, pdf: cbPdf };\r\n\r\n    const SPECIAL_PUMP_EXACT_MATCHES = [];\r\n    const SPECIAL_PUMP_ENDINGS = [\"M\", \"M4\", \"A\", \"L\"];\r\n\r\n    const SIZE_TO_CODE = [\r\n        { code: \"01\", size: \"80\" }, { code: \"02\", size: \"90S\" }, { code: \"03\", size: \"90L\" }, \r\n        { code: \"04\", size: \"100L\" }, { code: \"05\", size: \"112M\" }, { code: \"06\", size: \"132S\" }, \r\n        { code: \"07\", size: \"132M\" }, { code: \"08\", size: \"160M\" }, { code: \"09\", size: \"160L\" }, \r\n        { code: \"10\", size: \"180M\" }, { code: \"11\", size: \"180L\" }, { code: \"12\", size: \"200L\" }, \r\n        { code: \"13\", size: \"225S\" }, { code: \"14\", size: \"225M\" }, { code: \"15\", size: \"250M\" }, \r\n        { code: \"16\", size: \"280S\" }, { code: \"17\", size: \"280M\" }, { code: \"18\", size: \"315S\" }, \r\n        { code: \"19\", size: \"315M\" }, { code: \"20\", size: \"315L\" }, { code: \"21\", size: \"355L\" }, \r\n        { code: \"22\", size: \"71\" }\r\n    ];\r\n    \r\n    const RNM_SIZE_TO_CODE = [\r\n        { code: \"50\", size: \"80\" }, { code: \"52\", size: \"90L\" }, { code: \"53\", size: \"100\" },\r\n        { code: \"54\", size: \"112\" }, { code: \"55\", size: \"132S\" }, { code: \"56\", size: \"132M\" },\r\n        { code: \"57\", size: \"160M\" }, { code: \"58\", size: \"180M\" }, { code: \"60\", size: \"200\" },\r\n        { code: \"61\", size: \"225S\" }, { code: \"62\", size: \"225M\" }, { code: \"63\", size: \"250M\" },\r\n        { code: \"64\", size: \"280S\" }\r\n    ];\r\n\r\n    const RNM4_SIZE_TO_CODE = [\r\n        { code: \"50\", size: \"80\" }, { code: \"51\", size: \"90S\" }, { code: \"52\", size: \"90L\" },\r\n        { code: \"53\", size: \"100\" }, { code: \"54\", size: \"112\" }, { code: \"56\", size: \"132M\" },\r\n        { code: \"57\", size: \"160M\" }, { code: \"58\", size: \"180M\" }, { code: \"59\", size: \"180L\" },\r\n        { code: \"60\", size: \"200\" }, { code: \"61\", size: \"225S\" }, { code: \"62\", size: \"225M\" },\r\n        { code: \"63\", size: \"250M\" }, { code: \"64\", size: \"280S\" }\r\n    ];\r\n\r\n    const CODE_TO_SPECS = [\r\n        { potenza: \"0.75\", npoli: \"2\", code: \"01\" }, { potenza: \"1.1\", npoli: \"2\", code: \"01\" },\r\n        { potenza: \"1.5\", npoli: \"2\", code: \"02\" }, { potenza: \"2.2\", npoli: \"2\", code: \"03\" },\r\n        { potenza: \"3\", npoli: \"2\", code: \"04\" }, { potenza: \"4\", npoli: \"2\", code: \"05\" },\r\n        { potenza: \"5.5\", npoli: \"2\", code: \"06\" }, { potenza: \"7.5\", npoli: \"2\", code: \"06\" },\r\n        { potenza: \"9.2\", npoli: \"2\", code: \"07\" }, { potenza: \"11\", npoli: \"2\", code: \"08\" },\r\n        { potenza: \"15\", npoli: \"2\", code: \"08\" }, { potenza: \"18.5\", npoli: \"2\", code: \"09\" },\r\n        { potenza: \"22\", npoli: \"2\", code: \"10\" }, { potenza: \"30\", npoli: \"2\", code: \"12\" },\r\n        { potenza: \"37\", npoli: \"2\", code: \"12\" }, { potenza: \"45\", npoli: \"2\", code: \"14\" },\r\n        { potenza: \"55\", npoli: \"2\", code: \"15\" }, { potenza: \"75\", npoli: \"2\", code: \"16\" },\r\n        { potenza: \"90\", npoli: \"2\", code: \"17\" }, { potenza: \"110\", npoli: \"2\", code: \"18\" },\r\n        { potenza: \"132\", npoli: \"2\", code: \"19\" },\r\n        { potenza: \"0.55\", npoli: \"4\", code: \"01\" }, { potenza: \"0.75\", npoli: \"4\", code: \"01\" },\r\n        { potenza: \"1.1\", npoli: \"4\", code: \"02\" }, { potenza: \"1.5\", npoli: \"4\", code: \"03\" },\r\n        { potenza: \"2.2\", npoli: \"4\", code: \"04\" }, { potenza: \"3\", npoli: \"4\", code: \"04\" },\r\n        { potenza: \"4\", npoli: \"4\", code: \"05\" }, { potenza: \"5.5\", npoli: \"4\", code: \"06\" },\r\n        { potenza: \"7.5\", npoli: \"4\", code: \"07\" }, { potenza: \"9.2\", npoli: \"4\", code: \"07\" },\r\n        { potenza: \"11\", npoli: \"4\", code: \"08\" }, { potenza: \"15\", npoli: \"4\", code: \"09\" },\r\n        { potenza: \"18.5\", npoli: \"4\", code: \"10\" }, { potenza: \"22\", npoli: \"4\", code: \"11\" },\r\n        { potenza: \"30\", npoli: \"4\", code: \"12\" }, { potenza: \"37\", npoli: \"4\", code: \"13\" },\r\n        { potenza: \"45\", npoli: \"4\", code: \"14\" }, { potenza: \"55\", npoli: \"4\", code: \"15\" },\r\n        { potenza: \"75\", npoli: \"4\", code: \"16\" }, { potenza: \"90\", npoli: \"4\", code: \"17\" },\r\n        { potenza: \"110\", npoli: \"4\", code: \"18\" }, { potenza: \"132\", npoli: \"4\", code: \"19\" },\r\n        { potenza: \"160\", npoli: \"4\", code: \"19\" }, { potenza: \"200\", npoli: \"4\", code: \"20\" },\r\n        { potenza: \"250\", npoli: \"4\", code: \"21\" }, { potenza: \"315\", npoli: \"4\", code: \"21\" },\r\n        { potenza: \"0.37\", npoli: \"6\", code: \"01\" }, { potenza: \"0.55\", npoli: \"6\", code: \"01\" },\r\n        { potenza: \"0.75\", npoli: \"6\", code: \"02\" }, { potenza: \"1.1\", npoli: \"6\", code: \"03\" },\r\n        { potenza: \"1.5\", npoli: \"6\", code: \"04\" }, { potenza: \"2.2\", npoli: \"6\", code: \"05\" },\r\n        { potenza: \"3\", npoli: \"6\", code: \"06\" }, { potenza: \"4\", npoli: \"6\", code: \"07\" },\r\n        { potenza: \"5.5\", npoli: \"6\", code: \"07\" }, { potenza: \"7.5\", npoli: \"6\", code: \"08\" },\r\n        { potenza: \"9.2\", npoli: \"6\", code: \"08\" }, { potenza: \"11\", npoli: \"6\", code: \"09\" },\r\n        { potenza: \"15\", npoli: \"6\", code: \"11\" }, { potenza: \"18.5\", npoli: \"6\", code: \"12\" },\r\n        { potenza: \"22\", npoli: \"6\", code: \"12\" }, { potenza: \"30\", npoli: \"6\", code: \"14\" },\r\n        { potenza: \"37\", npoli: \"6\", code: \"15\" }, { potenza: \"45\", npoli: \"6\", code: \"16\" },\r\n        { potenza: \"55\", npoli: \"6\", code: \"17\" }, { potenza: \"75\", npoli: \"6\", code: \"18\" }\r\n    ];\r\n    \r\n    const RNM_CODE_TO_SPECS = [\r\n        { potenza: \"0.55\", npoli: \"2\", code: \"50\" }, { potenza: \"0.75\", npoli: \"2\", code: \"50\" },\r\n        { potenza: \"1.1\", npoli: \"2\", code: \"50\" }, { potenza: \"1.5\", npoli: \"2\", code: \"50\" },\r\n        { potenza: \"2.2\", npoli: \"2\", code: \"52\" }, { potenza: \"3\", npoli: \"2\", code: \"53\" },\r\n        { potenza: \"4\", npoli: \"2\", code: \"53\" }, { potenza: \"5.5\", npoli: \"2\", code: \"54\" },\r\n        { potenza: \"7.5\", npoli: \"2\", code: \"54\" }, { potenza: \"9.2\", npoli: \"2\", code: \"55\" },\r\n        { potenza: \"11\", npoli: \"2\", code: \"56\" }, { potenza: \"15\", npoli: \"2\", code: \"57\" },\r\n        { potenza: \"18.5\", npoli: \"2\", code: \"57\" }, { potenza: \"22\", npoli: \"2\", code: \"58\" },\r\n        { potenza: \"30\", npoli: \"2\", code: \"60\" }, { potenza: \"37\", npoli: \"2\", code: \"61\" },\r\n        { potenza: \"45\", npoli: \"2\", code: \"62\" }, { potenza: \"55\", npoli: \"2\", code: \"63\" },\r\n        { potenza: \"75\", npoli: \"2\", code: \"64\" },\r\n        { potenza: \"0.37\", npoli: \"4\", code: \"50\" }, { potenza: \"0.55\", npoli: \"4\", code: \"50\" },\r\n        { potenza: \"0.75\", npoli: \"4\", code: \"51\" }, { potenza: \"1.1\", npoli: \"4\", code: \"52\" },\r\n        { potenza: \"1.5\", npoli: \"4\", code: \"53\" }, { potenza: \"2.2\", npoli: \"4\", code: \"53\" },\r\n        { potenza: \"3\", npoli: \"4\", code: \"53\" }, { potenza: \"4\", npoli: \"4\", code: \"53\" },\r\n        { potenza: \"5.5\", npoli: \"4\", code: \"54\" }, { potenza: \"7.5\", npoli: \"4\", code: \"54\" },\r\n        { potenza: \"9.2\", npoli: \"4\", code: \"56\" }, { potenza: \"11\", npoli: \"4\", code: \"57\" },\r\n        { potenza: \"15\", npoli: \"4\", code: \"57\" }, { potenza: \"18.5\", npoli: \"4\", code: \"58\" },\r\n        { potenza: \"22\", npoli: \"4\", code: \"59\" }, { potenza: \"30\", npoli: \"4\", code: \"60\" },\r\n        { potenza: \"37\", npoli: \"4\", code: \"61\" }, { potenza: \"45\", npoli: \"4\", code: \"62\" },\r\n        { potenza: \"55\", npoli: \"4\", code: \"63\" }, { potenza: \"75\", npoli: \"4\", code: \"64\" }\r\n    ];\r\n    \r\n    const displayNameMapping = {\r\n        \"RD\": \"RDB\", \"RC\": \"RCB\", \"RG\": \"RGB\", \"RB\": \"RBB\", \r\n        \"RN\": \"RNB\", \"HD\": \"HDM\", \"HG\": \"HGM\", \"RS\": \"RSM\"\r\n    };\r\n\r\n    \/\/ ==========================================\r\n    \/\/ 3. CORE HELPER FUNCTIONS & NETWORK\r\n    \/\/ ==========================================\r\n\r\n    \/\/ Funzione Fetch con retry automatico in caso di errore 429\r\n    const fetchWithRetry = async (url, options, maxRetries = 5) => {\r\n        let attempts = 0;\r\n        while (attempts < maxRetries) {\r\n            try {\r\n                const response = await fetch(url, options);\r\n                if (response.status === 429) {\r\n                    attempts++;\r\n                    console.warn(`Errore 429 (Too Many Requests). Ritentativo ${attempts}\/${maxRetries} tra 1 secondo... URL: ${url}`);\r\n                    await new Promise(resolve => setTimeout(resolve, 1000));\r\n                    continue; \/\/ Riprova il ciclo\r\n                }\r\n                return response; \/\/ Se non \u00e8 429, restituisci la risposta (anche se fosse un 404\/500, la gestione \u00e8 delegata alla funzione chiamante)\r\n            } catch (error) {\r\n                \/\/ Se \u00e8 un errore di rete puro (es. offline) lancia subito l'errore\r\n                throw error;\r\n            }\r\n        }\r\n        throw new Error(`Superato il limite massimo di tentativi (${maxRetries}) per l'URL: ${url}`);\r\n    };\r\n\r\n    const getAuthHeaders = () => {\r\n        const token = localStorage.getItem(\"mnemosyne_jwt\");\r\n        return { \"Accept\": \"*\/*\", \"Authorization\": `${token}` };\r\n    };\r\nconst resetSelect = (selectElement, defaultText = \"Seleziona\") => {\r\n        if (!selectElement) return;\r\n        selectElement.disabled = true;\r\n        selectElement.innerHTML = `<option value=\"\">${defaultText}<\/option>`;\r\n        updateLabelsState(); \/\/ Aggiorna la UI dopo il reset\r\n    };\r\n\r\n    const populateSelect = (selectElement, optionsArray, defaultText = \"Seleziona\") => {\r\n    if (!selectElement) return;\r\n    selectElement.innerHTML = `<option value=\"\">${defaultText}<\/option>`;\r\n    \r\n    \/\/ Add this safety guard:\r\n    if (!optionsArray || optionsArray.length === 0) {\r\n        selectElement.disabled = true;\r\n        updateLabelsState();\r\n        return;\r\n    }\r\n\r\n    optionsArray.forEach(opt => {\r\n            const optionTag = document.createElement(\"option\");\r\n            optionTag.value = opt.id; \r\n            optionTag.setAttribute(\"data-origname\", opt.name);\r\n            optionTag.textContent = displayNameMapping[opt.name] || opt.name;\r\n            selectElement.appendChild(optionTag);\r\n        });\r\n        \r\n        selectElement.disabled = false;\r\n\r\n        if (optionsArray.length === 1) {\r\n            selectElement.value = optionsArray[0].id; \r\n            selectElement.disabled = true;            \r\n            selectElement.dispatchEvent(new Event(\"change\", { bubbles: true }));\r\n        }\r\n        updateLabelsState(); \/\/ Aggiorna la UI dopo il popolamento\r\n    };\r\n\r\n    const updateLabelsState = () => {\r\n        \/\/ 1. Aggiorna le label singole delle Select (Dropdown)\r\n        [selTipo, selGrandezza, selPotenza, selPolarita].forEach(el => {\r\n            if (el) {\r\n                const label = document.querySelector(`label[for=\"${el.id}\"]`);\r\n                if (label) label.classList.toggle(\"disabled\", el.disabled);\r\n            }\r\n        });\r\n\r\n        \/\/ 2. Aggiorna le label singole dei Checkbox (Montaggio)\r\n        [checkBasamento, checkGiunto].forEach(el => {\r\n            if (el) {\r\n                const label = document.querySelector(`label[for=\"${el.id}\"]`);\r\n                if (label) label.classList.toggle(\"disabled\", el.disabled);\r\n            }\r\n        });\r\n\r\n        \/\/ 3. Aggiorna le label singole dei Radio Button (Standard Dimensionale)\r\n        [radioStandard, radioAnsi, radioPn16].forEach(el => {\r\n            if (el) {\r\n                const label = document.querySelector(`label[for=\"${el.id}\"]`);\r\n                if (label) label.classList.toggle(\"disabled\", el.disabled);\r\n            }\r\n        });\r\n\r\n        \/\/ 4. Aggiorna le label singole dei formati (Download)\r\n        Object.values(downloadCheckboxes).forEach(el => {\r\n            if (el) {\r\n                const label = document.querySelector(`label[for=\"${el.id}\"]`);\r\n                if (label) label.classList.toggle(\"disabled\", el.disabled);\r\n            }\r\n        });\r\n\r\n        \/\/ 5. Aggiorna i titoli generali delle sezioni\r\n        if (labelMontaggio) {\r\n            const isEnabled = (!checkBasamento?.disabled) || (!checkGiunto?.disabled);\r\n            labelMontaggio.classList.toggle(\"disabled\", !isEnabled);\r\n        }\r\n        if (labelDimensionale) {\r\n            const isEnabled = (!radioStandard?.disabled) || (!radioAnsi?.disabled) || (!radioPn16?.disabled);\r\n            labelDimensionale.classList.toggle(\"disabled\", !isEnabled);\r\n        }\r\n        if (labelFormato) {\r\n            const isEnabled = Object.values(downloadCheckboxes).some(cb => cb && !cb.disabled);\r\n            labelFormato.classList.toggle(\"disabled\", !isEnabled);\r\n        }\r\n    };\r\n\r\n    const disableCheckboxes = () => {\r\n        Object.values(checkboxes).forEach(cb => { \r\n            if (cb) { cb.disabled = true; cb.checked = false; } \r\n        });\r\n        updateLabelsState();\r\n    };\r\n\r\n    const resetRadioButtons = () => {\r\n        if (radioStandard) { radioStandard.disabled = true; radioStandard.checked = true; }\r\n        if (radioAnsi) { radioAnsi.disabled = true; radioAnsi.checked = false; }\r\n        if (radioPn16) { radioPn16.disabled = true; radioPn16.checked = false; }\r\n    };\r\n\r\n    const disableDownloadElements = () => {\r\n        if (btnBulkDownload) btnBulkDownload.disabled = true;\r\n        Object.values(downloadCheckboxes).forEach(cb => { \r\n            if (cb) { cb.disabled = true; cb.checked = false; } \r\n        });\r\n        updateLabelsState();\r\n    };\r\n\r\n    const updateDownloadButtonState = () => {\r\n        if (!btnBulkDownload) return;\r\n        const hasChecked = Object.values(downloadCheckboxes).some(cb => cb && cb.checked && !cb.disabled);\r\n        btnBulkDownload.disabled = !hasChecked;\r\n    };\r\n\r\n    const fetchFolderContents = async (folderId) => {\r\n        if (!folderId) return [];\r\n        try {\r\n            \/\/ USIAMO IL WRAPPER QUI\r\n            const response = await fetchWithRetry(`https:\/\/drawings.salvatorerobuschi.com\/data\/${folderId}`, { \r\n                method: \"GET\", headers: getAuthHeaders() \r\n            });\r\n            if (!response.ok) return [];\r\n            return await response.json();\r\n        } catch (error) {\r\n            console.error(`Error fetching folder ${folderId}:`, error);\r\n            return [];\r\n        }\r\n    };\r\n\r\n    \/\/ ==========================================\r\n    \/\/ 4. CASCADE STEP FUNCTIONS\r\n    \/\/ ==========================================\r\n\r\n    const initForm = async () => {\r\n        disableCheckboxes();\r\n        disableDownloadElements();\r\n        resetRadioButtons();\r\n        updateLabelsState(); \r\n\r\n        try {\r\n            \/\/ USIAMO IL WRAPPER QUI\r\n            const rootsRes = await fetchWithRetry(\"https:\/\/drawings.salvatorerobuschi.com\/info\/roots\", { method: \"GET\", headers: getAuthHeaders() });\r\n            const rootsData = await rootsRes.json();\r\n            \r\n            const definitivoObj = rootsData.find(item => item.name && item.name.toUpperCase().includes(\"DEFINITIVO\"));\r\n\t\t\tconst exportObj = rootsData.find(item => item.name && item.name.toUpperCase().includes(\"---EXPORT---\"));\r\n            const tabelleObj = rootsData.find(item => item.name && item.name.toUpperCase().includes(\"TABELLE\"));\r\n            \r\n            const fetchPromises = [];\r\n\r\n            if (exportObj) {\r\n                exportRootId = exportObj.id;\r\n                fetchPromises.push(\r\n                    fetchFolderContents(exportRootId).then(data => { exportTipos = data; })\r\n                );\r\n            }\r\n            \r\n            if (tabelleObj) {\r\n                tabelleRootId = tabelleObj.id;\r\n                fetchPromises.push(\r\n                    fetchFolderContents(tabelleRootId).then(data => { tabelleFolders = data; })\r\n                );\r\n            }\r\n\r\n            if (definitivoObj) {\r\n                fetchPromises.push(\r\n                    fetchFolderContents(definitivoObj.id).then(data => {\r\n                        let filteredData = data.filter(item => !item.name.includes(\"logFTP\") && !item.name.includes(\"lockfile\"));\r\n                        filteredData.sort((a, b) => a.name.localeCompare(b.name));\r\n                        if ((selTipo) && (linguaCorrente=='it'))\r\n\t\t\t\t\t\t{ populateSelect(selTipo, filteredData, \"Seleziona\"); }\r\n\t\t\t\t\t\telse\r\n\t\t\t\t\t\t{ populateSelect(selTipo, filteredData, \"Select\"); }\r\n                    })\r\n                );\r\n            }\r\n\r\n            await Promise.all(fetchPromises);\r\n\r\n            \/\/ ==========================================\r\n            \/\/ LOGICA AUTOLOAD DAL PARAMETRO URL\r\n            \/\/ ==========================================\r\n            const urlParams = new URLSearchParams(window.location.search);\r\n            const pumpTypeParam = urlParams.get('pumptype');\r\n\r\n            if (selTipo && pumpTypeParam) {\r\n                const targetPump = pumpTypeParam.toUpperCase();\r\n                let foundOption = null;\r\n                \r\n                for (let i = 0; i < selTipo.options.length; i++) {\r\n                    let opt = selTipo.options[i];\r\n                    let origName = opt.getAttribute(\"data-origname\") || \"\";\r\n                    if (opt.text.toUpperCase() === targetPump || origName.toUpperCase() === targetPump) {\r\n                        foundOption = opt;\r\n                        break;\r\n                    }\r\n                }\r\n                \r\n                if (foundOption) {\r\n                    selTipo.value = foundOption.value;\r\n                    selTipo.dispatchEvent(new Event(\"change\", { bubbles: true }));\r\n                }\r\n            }\r\n            \/\/ ==========================================\r\n\r\n        } catch (err) { console.error(\"Initialization error:\", err); }\r\n    };\r\n\r\n    const loadGrandezza = async (tipoId) => {\r\n        const data = await fetchFolderContents(tipoId);\r\n        const filteredData = data.filter(item => !item.name.includes(\"logFTP\") && !item.name.includes(\"lockfile\"));\r\n        filteredData.sort((a, b) => a.name.localeCompare(b.name, undefined, { numeric: true, sensitivity: 'base' }));\r\n        if (linguaCorrente=='it') { populateSelect(selGrandezza, filteredData, \"Seleziona\");}\r\n\t\telse { populateSelect(selGrandezza, filteredData, \"Select\");}\r\n    };\r\n\r\n    const loadBasamento = async (grandezzaId) => {\r\n        const data = await fetchFolderContents(grandezzaId);\r\n        \r\n        const sbFolder = data.find(f => f.name === \"SB\");\r\n        const cbFolder = data.find(f => f.name === \"CB\");\r\n        folderState.sb = sbFolder ? sbFolder.id : null;\r\n        folderState.cb = cbFolder ? cbFolder.id : null;\r\n\r\n        const expSbFolder = exportBasamenti.find(f => f.name === \"SB\");\r\n        const expCbFolder = exportBasamenti.find(f => f.name === \"CB\");\r\n        folderState.expSb = expSbFolder ? expSbFolder.id : null;\r\n        folderState.expCb = expCbFolder ? expCbFolder.id : null;\r\n\r\n        if (cbFolder && !sbFolder) {\r\n            checkBasamento.checked = true; checkBasamento.disabled = true;\r\n        } else if (sbFolder && !cbFolder) {\r\n            checkBasamento.checked = false; checkBasamento.disabled = true;\r\n        } else if (cbFolder && sbFolder) {\r\n            checkBasamento.checked = false; checkBasamento.disabled = false;\r\n        } else {\r\n            checkBasamento.checked = false; checkBasamento.disabled = true;\r\n            updateLabelsState();\r\n            return null; \r\n        }\r\n        \r\n        updateLabelsState();\r\n        folderState.basamentoName = checkBasamento.checked ? \"CB\" : \"SB\";\r\n\r\n        const activeExpSbCbId = checkBasamento.checked ? folderState.expCb : folderState.expSb;\r\n        exportGiunti = activeExpSbCbId ? await fetchFolderContents(activeExpSbCbId) : [];\r\n\r\n        return checkBasamento.checked ? folderState.cb : folderState.sb;\r\n    };\r\n    \r\n    const loadGiuntoAndAsseNudo = async (activeSbCbId) => {\r\n        const data = await fetchFolderContents(activeSbCbId);\r\n        \r\n        const stFolder = data.find(f => f.name === \"ST\");\r\n        const spFolder = data.find(f => f.name === \"SP\");\r\n        const snFolder = data.find(f => f.name === \"SN\");\r\n\r\n        folderState.st = stFolder ? stFolder.id : null;\r\n        folderState.sp = spFolder ? spFolder.id : null;\r\n        folderState.sn = snFolder ? snFolder.id : null;\r\n\r\n        const expStFolder = exportGiunti.find(f => f.name === \"ST\");\r\n        const expSpFolder = exportGiunti.find(f => f.name === \"SP\");\r\n        const expSnFolder = exportGiunti.find(f => f.name === \"SN\");\r\n        folderState.expSt = expStFolder ? expStFolder.id : null;\r\n        folderState.expSp = expSpFolder ? expSpFolder.id : null;\r\n        folderState.expSn = expSnFolder ? expSnFolder.id : null;\r\n\r\n        if (spFolder && !stFolder) {\r\n            checkGiunto.checked = true; checkGiunto.disabled = true;\r\n        } else if (stFolder && !spFolder) {\r\n            checkGiunto.checked = false; checkGiunto.disabled = true;\r\n        } else if (stFolder && spFolder) {\r\n            checkGiunto.checked = false; checkGiunto.disabled = false;\r\n        } else {\r\n            checkGiunto.checked = false; checkGiunto.disabled = true;\r\n        }\r\n\r\n        updateLabelsState();\r\n        folderState.giuntoName = checkGiunto.checked ? \"SP\" : \"ST\";\r\n        \r\n        const selectedTypeOption = selTipo.options[selTipo.selectedIndex];\r\n        const selectedTypeName = selectedTypeOption ? selectedTypeOption.text.trim() : \"\";\r\n        const isSpecialType = SPECIAL_PUMP_EXACT_MATCHES.includes(selectedTypeName) || \r\n                              SPECIAL_PUMP_ENDINGS.some(ending => selectedTypeName.endsWith(ending));\r\n\r\n        let powerSourceId = checkGiunto.checked ? folderState.sp : folderState.st;\r\n        let exportPowerSourceId = checkGiunto.checked ? folderState.expSp : folderState.expSt;\r\n        \r\n        if (isSpecialType && folderState.sn) powerSourceId = folderState.sn;\r\n        if (isSpecialType && folderState.expSn) exportPowerSourceId = folderState.expSn;\r\n\r\n        exportMotors = exportPowerSourceId ? await fetchFolderContents(exportPowerSourceId) : [];\r\n\r\n        await loadPowerAndPolarity(powerSourceId);\r\n    };\r\n\r\n    const loadPowerAndPolarity = async (activeStSpId) => {\r\n        currentValidSpecs = [];\r\n        const selectedTypeOption = selTipo.options[selTipo.selectedIndex];\r\n        const selectedTypeName = selectedTypeOption ? selectedTypeOption.text.trim() : \"\";\r\n\r\n        let activeSizeToCodeTable = SIZE_TO_CODE;\r\n        let activeCodeToSpecsTable = CODE_TO_SPECS;\r\n        let restrictedPoles = null;\r\n\r\n        if (selectedTypeName === \"RNM\") {\r\n            activeSizeToCodeTable = RNM_SIZE_TO_CODE;\r\n            activeCodeToSpecsTable = RNM_CODE_TO_SPECS;\r\n            restrictedPoles = \"2\"; \r\n        } else if (selectedTypeName === \"RNM4\") {\r\n            activeSizeToCodeTable = RNM4_SIZE_TO_CODE;\r\n            activeCodeToSpecsTable = RNM_CODE_TO_SPECS;\r\n            restrictedPoles = \"4\"; \r\n        }\r\n\r\n        if (activeStSpId) {\r\n            const folders = await fetchFolderContents(activeStSpId);\r\n            folders.forEach(folder => {\r\n                const matchingCodes = activeSizeToCodeTable.filter(item => item.size.startsWith(folder.name)).map(item => item.code);\r\n                matchingCodes.forEach(code => {\r\n                    const specs = activeCodeToSpecsTable.filter(spec => spec.code === code);\r\n                    specs.forEach(s => {\r\n                        if (restrictedPoles && s.npoli !== restrictedPoles) return;\r\n                        currentValidSpecs.push({ ...s, folderId: folder.id, folderName: folder.name });\r\n                    });\r\n                });\r\n            });\r\n        }\r\n\r\n        const uniquePotenze = [...new Set(currentValidSpecs.map(s => s.potenza))].sort((a,b) => parseFloat(a) - parseFloat(b));\r\n        const powerOptions = uniquePotenze.map(p => ({ id: p, name: p }));\r\n\r\n        const isSpecialType = SPECIAL_PUMP_EXACT_MATCHES.includes(selectedTypeName) || \r\n                              SPECIAL_PUMP_ENDINGS.some(ending => selectedTypeName.endsWith(ending));\r\n\r\n        if (folderState.sn && !isSpecialType) {\r\n\t\t\tif (linguaCorrente=='it') { powerOptions.unshift({ id: \"0\", name: \"Asse Nudo\" });}\r\n\t\t\telse { powerOptions.unshift({ id: \"0\", name: \"Bare Shaft\" });}\r\n        }\r\n\t\tif (linguaCorrente=='it') {\r\n\t\t\tresetSelect(selPolarita, \"Seleziona\");\r\n        \tpopulateSelect(selPotenza, powerOptions, \"Seleziona\");\r\n\t\t\t}\r\n\t\t\telse {\r\n\t\t\tresetSelect(selPolarita, \"Select\");\r\n        \tpopulateSelect(selPotenza, powerOptions, \"Select\");\r\n\t\t\t}\r\n        \r\n    };\r\n\r\n    const checkFinalFolder = async (isAsseNudo = false) => {\r\n        if (isAsseNudo) {\r\n            folderState.finalMotor = folderState.sn;\r\n            folderState.expFinalMotor = folderState.expSn;\r\n        } else {\r\n            const finalSpecMatch = currentValidSpecs.find(s => s.potenza === selPotenza.value && s.npoli === selPolarita.value);\r\n            \r\n            if (!finalSpecMatch) {\r\n                folderState.finalMotor = null;\r\n                folderState.expFinalMotor = null;\r\n                disableDownloadElements();\r\n                resetRadioButtons();\r\n                updateLabelsState();\r\n                return;\r\n            }\r\n            folderState.finalMotor = finalSpecMatch.folderId;\r\n            folderState.motorName = finalSpecMatch.folderName;\r\n\r\n            const matchedExp = exportMotors.find(f => f.name === folderState.motorName);\r\n            folderState.expFinalMotor = matchedExp ? matchedExp.id : null;\r\n        }\r\n\r\n        const data = await fetchFolderContents(folderState.finalMotor);\r\n        const baseDFolder = data.find(f => f.name === \"D\");\r\n        const ansiFolder = data.find(f => f.name === \"ANSI\");\r\n        const pn16Folder = data.find(f => f.name === \"PN16\");\r\n\r\n        folderState.baseD = baseDFolder ? baseDFolder.id : null;\r\n        if (radioStandard) radioStandard.disabled = !folderState.baseD;\r\n\r\n        let expData = [];\r\n        if (folderState.expFinalMotor) {\r\n            expData = await fetchFolderContents(folderState.expFinalMotor);\r\n        }\r\n        const expBaseEFolder = expData.find(f => f.name === \"E\");\r\n        const expAnsiFolder = expData.find(f => f.name === \"ANSI\");\r\n        const expPn16Folder = expData.find(f => f.name === \"PN16\");\r\n        \r\n        folderState.expBaseE = expBaseEFolder ? expBaseEFolder.id : null;\r\n\r\n        \/\/ -- ANSI Check --\r\n        folderState.ansiD = null;\r\n        folderState.expAnsiE = null;\r\n        let ansiValid = false;\r\n\r\n        if (ansiFolder) {\r\n            const ansiData = await fetchFolderContents(ansiFolder.id);\r\n            const ansiDFolder = ansiData.find(f => f.name === \"D\");\r\n            if (ansiDFolder) {\r\n                const filesD = await fetchFolderContents(ansiDFolder.id);\r\n                if (filesD.some(f => f.type === \"FILE\")) {\r\n                    folderState.ansiD = ansiDFolder.id;\r\n                    ansiValid = true;\r\n                }\r\n            }\r\n            if (expAnsiFolder) {\r\n                const expAnsiData = await fetchFolderContents(expAnsiFolder.id);\r\n                const expAnsiEFolder = expAnsiData.find(f => f.name === \"E\");\r\n                folderState.expAnsiE = expAnsiEFolder ? expAnsiEFolder.id : null;\r\n            }\r\n        }\r\n\r\n        if (radioAnsi) {\r\n            radioAnsi.disabled = !ansiValid;\r\n            if (!ansiValid && radioAnsi.checked) {\r\n                radioAnsi.checked = false;\r\n                if (radioStandard && !radioStandard.disabled) radioStandard.checked = true;\r\n            }\r\n        }\r\n\r\n        \/\/ -- PN16 Check --\r\n        folderState.pn16D = null;\r\n        folderState.expPn16E = null;\r\n        let pn16Valid = false;\r\n\r\n        if (pn16Folder) {\r\n            const pn16Data = await fetchFolderContents(pn16Folder.id);\r\n            const pn16DFolder = pn16Data.find(f => f.name === \"D\");\r\n            if (pn16DFolder) {\r\n                const filesD = await fetchFolderContents(pn16DFolder.id);\r\n                if (filesD.some(f => f.type === \"FILE\")) {\r\n                    folderState.pn16D = pn16DFolder.id;\r\n                    pn16Valid = true;\r\n                }\r\n            }\r\n            if (expPn16Folder) {\r\n                const expPn16Data = await fetchFolderContents(expPn16Folder.id);\r\n                const expPn16EFolder = expPn16Data.find(f => f.name === \"E\");\r\n                folderState.expPn16E = expPn16EFolder ? expPn16EFolder.id : null;\r\n            }\r\n        }\r\n\r\n        if (radioPn16) {\r\n            radioPn16.disabled = !pn16Valid;\r\n            if (!pn16Valid && radioPn16.checked) {\r\n                radioPn16.checked = false;\r\n                if (radioStandard && !radioStandard.disabled) radioStandard.checked = true;\r\n            }\r\n        }\r\n\r\n        updateLabelsState();\r\n        await evaluateFinalFiles();\r\n    };\r\n\r\n    const evaluateFinalFiles = async () => {\r\n        disableDownloadElements();\r\n        availableFiles = { step: null, dwg: null, dxf: null, idw: null, pdf: null };\r\n\r\n        let targetDFolderId = folderState.baseD;\r\n        let targetEFolderId = folderState.expBaseE;\r\n\r\n        if (radioAnsi && radioAnsi.checked) {\r\n            targetDFolderId = folderState.ansiD;\r\n            targetEFolderId = folderState.expAnsiE;\r\n        } else if (radioPn16 && radioPn16.checked) {\r\n            targetDFolderId = folderState.pn16D;\r\n            targetEFolderId = folderState.expPn16E;\r\n        }\r\n\r\n        if (targetDFolderId) {\r\n            const filesD = await fetchFolderContents(targetDFolderId);\r\n            const getFileByExtD = (ext) => filesD.find(f => f.type === \"FILE\" && f.name.toLowerCase().endsWith(ext));\r\n            availableFiles.dwg = getFileByExtD(\".dwg\");\r\n            availableFiles.dxf = getFileByExtD(\".dxf\");\r\n            availableFiles.idw = getFileByExtD(\".idw\");\r\n            availableFiles.pdf = getFileByExtD(\".pdf\");\r\n        }\r\n\r\n        if (targetEFolderId) {\r\n            const filesE = await fetchFolderContents(targetEFolderId);\r\n            const getFileByExtE = (ext) => filesE.find(f => f.type === \"FILE\" && f.name.toLowerCase().endsWith(ext));\r\n            const zipFile = getFileByExtE(\".zip\");\r\n            const stepFile = getFileByExtE(\".step\") || getFileByExtE(\".stp\");\r\n            availableFiles.step = zipFile ? zipFile : stepFile;\r\n        }\r\n\r\n        Object.keys(availableFiles).forEach(format => {\r\n            if (availableFiles[format] && downloadCheckboxes[format]) {\r\n                downloadCheckboxes[format].disabled = false;\r\n            }\r\n        });\r\n\r\n        updateLabelsState();\r\n        updateDownloadButtonState();\r\n    };\r\n\r\n\r\n    \/\/ ==========================================\r\n    \/\/ 5. EVENT LISTENERS\r\n    \/\/ ==========================================\r\n\r\n    if (selTipo) {\r\n        selTipo.addEventListener(\"change\", async (e) => {\r\n\t\t\tif (linguaCorrente=='it') {\r\n            \tresetSelect(selGrandezza, \"Seleziona\");\r\n            \tresetSelect(selPotenza, \"Seleziona\");\r\n            \tresetSelect(selPolarita, \"Seleziona\");\r\n\t\t\t}else{\r\n\t\t\t\tresetSelect(selGrandezza, \"Select\");\r\n            \tresetSelect(selPotenza, \"Select\");\r\n            \tresetSelect(selPolarita, \"Select\");\r\n\t\t\t}\r\n            disableCheckboxes();\r\n            disableDownloadElements();\r\n            resetRadioButtons();\r\n            \r\n            window.srCurrentPumpName = null;\r\n\r\n            if (e.target.value) {\r\n                const selectedOpt = e.target.options[e.target.selectedIndex];\r\n                folderState.tipoName = selectedOpt.getAttribute(\"data-origname\"); \r\n                const displayName = selectedOpt.text.trim(); \r\n\r\n                if (tabelleFolders.length > 0) {\r\n                    const baseDisplayName = displayName.replace(\/[0-9]\/g, ''); \r\n                    const baseOrigName = folderState.tipoName.replace(\/[0-9]\/g, '');\r\n\r\n                    let bestMatch = tabelleFolders.find(f => \r\n                        f.name.toUpperCase().includes(displayName.toUpperCase()) ||\r\n                        f.name.toUpperCase().includes(folderState.tipoName.toUpperCase()) ||\r\n                        f.name.toUpperCase().includes(baseDisplayName.toUpperCase()) ||\r\n                        f.name.toUpperCase().includes(baseOrigName.toUpperCase())\r\n                    );\r\n\r\n                    if (bestMatch) {\r\n                        window.srCurrentPumpName = bestMatch.name.substring(0, 2);\r\n                        console.log(\"Variabile globale assegnata window.srCurrentPumpName:\", window.srCurrentPumpName);\r\n                    }\r\n                }\r\n\r\n                const matchedExp = exportTipos.find(f => f.name === folderState.tipoName);\r\n                exportGrandezze = matchedExp ? await fetchFolderContents(matchedExp.id) : [];\r\n\r\n                await loadGrandezza(e.target.value);\r\n            }\r\n        });\r\n    }\r\n\r\n    if (selGrandezza) {\r\n        selGrandezza.addEventListener(\"change\", async (e) => {\r\n\t\t\tif (linguaCorrente=='it') {\r\n            \tresetSelect(selPotenza, \"Seleziona\");\r\n            \tresetSelect(selPolarita, \"Seleziona\");\r\n\t\t\t}else{\r\n\t\t\t\tresetSelect(selPotenza, \"Select\");\r\n            \tresetSelect(selPolarita, \"Select\");\r\n\t\t\t}\r\n            if (checkGiunto) { checkGiunto.checked = false; checkGiunto.disabled = true; }\r\n            resetRadioButtons();\r\n            disableDownloadElements();\r\n\r\n            if (e.target.value) {\r\n                const selectedOpt = e.target.options[e.target.selectedIndex];\r\n                folderState.grandezzaName = selectedOpt.getAttribute(\"data-origname\");\r\n\r\n                const matchedExp = exportGrandezze.find(f => f.name === folderState.grandezzaName);\r\n                exportBasamenti = matchedExp ? await fetchFolderContents(matchedExp.id) : [];\r\n\r\n                const activeSbCbId = await loadBasamento(e.target.value);\r\n                if (activeSbCbId) await loadGiuntoAndAsseNudo(activeSbCbId);\r\n            }\r\n        });\r\n    }\r\n\r\n    if (checkBasamento) {\r\n        checkBasamento.addEventListener(\"change\", async (e) => {\r\n\t\t\tif (linguaCorrente=='it') {\r\n            \t\tresetSelect(selPotenza, \"Seleziona\");\r\n            \t\tresetSelect(selPolarita, \"Seleziona\");\r\n\t\t\t\t}else{\r\n\t\t\t\t\tresetSelect(selPotenza, \"Select\");\r\n            \t\tresetSelect(selPolarita, \"Select\");\r\n\t\t\t\t}\r\n            if (checkGiunto) { checkGiunto.checked = false; checkGiunto.disabled = true; }\r\n            resetRadioButtons();\r\n            disableDownloadElements();\r\n\r\n            folderState.basamentoName = e.target.checked ? \"CB\" : \"SB\";\r\n            const activeSbCbId = e.target.checked ? folderState.cb : folderState.sb;\r\n            const activeExpSbCbId = e.target.checked ? folderState.expCb : folderState.expSb;\r\n\r\n            exportGiunti = activeExpSbCbId ? await fetchFolderContents(activeExpSbCbId) : [];\r\n\r\n            if (activeSbCbId) await loadGiuntoAndAsseNudo(activeSbCbId);\r\n        });\r\n    }\r\n\r\n    if (checkGiunto) {\r\n        checkGiunto.addEventListener(\"change\", async (e) => {\r\n\t\t\tif (linguaCorrente=='it') {\r\n           \t\tresetSelect(selPotenza, \"Seleziona\");\r\n            \tresetSelect(selPolarita, \"Seleziona\");\r\n\t\t\t}else{\r\n\t\t\t\tresetSelect(selPotenza, \"Select\");\r\n            \tresetSelect(selPolarita, \"Select\");\r\n\t\t\t}\r\n            resetRadioButtons();\r\n            disableDownloadElements();\r\n            \r\n            folderState.giuntoName = e.target.checked ? \"SP\" : \"ST\";\r\n            const activeStSpId = e.target.checked ? folderState.sp : folderState.st;\r\n            const activeExpStSpId = e.target.checked ? folderState.expSp : folderState.expSt;\r\n\r\n            exportMotors = activeExpStSpId ? await fetchFolderContents(activeExpStSpId) : [];\r\n\r\n            await loadPowerAndPolarity(activeStSpId);\r\n        });\r\n    }\r\n    \r\n    if (selPotenza) {\r\n        selPotenza.addEventListener(\"change\", async (e) => {\r\n            const selectedPotenza = e.target.value;\r\n            if (linguaCorrente=='it') { resetSelect(selPolarita, \"Seleziona\");}\r\n\t\t\telse{resetSelect(selPolarita, \"Select\");}\r\n\r\n            disableDownloadElements();\r\n            resetRadioButtons();\r\n            folderState.finalMotor = null;\r\n            updateLabelsState();\r\n\r\n            if (!selectedPotenza) return;\r\n\r\n            if (selectedPotenza === \"0\") {\r\n                await checkFinalFolder(true);      \r\n            } else {\r\n                const validSpecsForPower = currentValidSpecs.filter(s => s.potenza === selectedPotenza);\r\n                const uniquePolarita = [...new Set(validSpecsForPower.map(s => s.npoli))].sort((a,b) => parseFloat(a) - parseFloat(b));\r\n                \r\n\t\t\t\tconst polarityOptions = uniquePolarita.map(p => ({\r\n\t\t\t\t\t\/\/id: p, name: `${p} Poli`\r\n\t\t\t\t\tid: p, name: `${p} `\r\n\t\t\t\t}));\r\n\r\n                if (linguaCorrente=='it') {populateSelect(selPolarita, polarityOptions, \"Seleziona\");}\r\n\t\t\t\telse{populateSelect(selPolarita, polarityOptions, \"Select\");}\r\n            }\r\n        });\r\n    }\r\n\r\n    if (selPolarita) {\r\n        selPolarita.addEventListener(\"change\", async (e) => {\r\n            disableDownloadElements();\r\n            resetRadioButtons();\r\n            folderState.finalMotor = null;\r\n            updateLabelsState();\r\n\r\n            if (e.target.value) await checkFinalFolder(false);\r\n        });\r\n    }\r\n\r\n    const onDimensionaleChange = async () => {\r\n        await evaluateFinalFiles();\r\n    };\r\n    if (radioStandard) radioStandard.addEventListener(\"change\", onDimensionaleChange);\r\n    if (radioAnsi) radioAnsi.addEventListener(\"change\", onDimensionaleChange);\r\n    if (radioPn16) radioPn16.addEventListener(\"change\", onDimensionaleChange);\r\n    \r\n    Object.values(downloadCheckboxes).forEach(cb => {\r\n        if (cb) cb.addEventListener(\"change\", updateDownloadButtonState);\r\n    });\r\n\r\n    \/\/ ==========================================\r\n    \/\/ 6. DOWNLOAD EXECUTION\r\n    \/\/ ==========================================\r\n\r\n    const executeDownload = async (fileObj) => {\r\n        if (!fileObj) return;\r\n        \r\n        try {\r\n            console.log(`Executing secure download for: ${fileObj.name}`);\r\n            \r\n            const downloadUrl = `https:\/\/drawings.salvatorerobuschi.com\/data\/${fileObj.id}`; \r\n            \r\n            \/\/ USIAMO IL WRAPPER QUI\r\n            const response = await fetchWithRetry(downloadUrl, {\r\n                method: \"GET\",\r\n                headers: getAuthHeaders()\r\n            });\r\n\r\n            if (!response.ok) throw new Error(`Status ${response.status}`);\r\n\r\n            const blob = await response.blob();\r\n            const objectUrl = window.URL.createObjectURL(blob);\r\n\r\n            const a = document.createElement(\"a\");\r\n            a.href = objectUrl;\r\n            a.download = fileObj.name; \r\n            document.body.appendChild(a);\r\n            a.click();\r\n            \r\n            a.remove();\r\n            window.URL.revokeObjectURL(objectUrl);\r\n\r\n        } catch (error) {\r\n            console.error(`Download error for ${fileObj.name}:`, error);\r\n            alert(`Si \u00e8 verificato un errore durante il download di ${fileObj.name}.`);\r\n        }\r\n    };\r\n\r\n    if (btnBulkDownload) {\r\n        btnBulkDownload.addEventListener(\"click\", async (e) => {\r\n            e.preventDefault();\r\n            \r\n            const formatsToDownload = Object.keys(downloadCheckboxes).filter(format => {\r\n                const cb = downloadCheckboxes[format];\r\n                return cb && cb.checked && !cb.disabled;\r\n            });\r\n\r\n            if (formatsToDownload.length === 0) {\r\n\t\t\t\tif (linguaCorrente=='it') { alert(\"Seleziona almeno un formato da scaricare.\");}\r\n\t\t\t\telse{ alert(\"Select at least one download format.\");}\r\n                return;\r\n            }\r\n\r\n            for (const format of formatsToDownload) {\r\n                await executeDownload(availableFiles[format]);\r\n                await new Promise(resolve => setTimeout(resolve, 500)); \r\n            }\r\n        });\r\n    }\r\n\r\n    \/\/ Start the machine!\r\n    initForm();\r\n});\r\n<\/script>\r\n\r\n<style>\r\n\/* Riduce l'opacit\u00e0 e disabilita le interazioni per le label disattivate *\/\r\n.elementor-field-label.disabled,\r\nlabel.disabled {\r\n    opacity: 0.2;\r\n    pointer-events: none;\r\n    transition: opacity 0.3s ease;\r\n}\r\n<\/style><\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-21d5aa0 elementor-hidden-desktop elementor-hidden-tablet elementor-hidden-mobile elementor-widget elementor-widget-shortcode\" data-id=\"21d5aa0\" 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  (function() {\r\n    const token = localStorage.getItem('mnemosyne_jwt'); \r\n    const loginUrl = '\/en\/reserved-area\/login';\r\n\r\n    \/\/ Helper function to wipe all user data on failure\r\n    const clearAuthData = () => {\r\n      localStorage.removeItem('mnemosyne_jwt');\r\n      localStorage.removeItem('mnemosyne_username');\r\n      localStorage.removeItem('mnemosyne_email');\r\n    };\r\n\r\n    \/\/ 1. Check if token exists or if it accidentally saved the word \"undefined\"\r\n    if (!token || token === \"undefined\" || token === \"null\") {\r\n      console.log(\"No valid JWT found in localStorage!\");\r\n      clearAuthData(); \/\/ Wipe everything\r\n      window.location.href = loginUrl;\r\n      return;\r\n    }\r\n\r\n    try {\r\n      \/\/ 2. Sanity check: A valid JWT must have exactly 3 parts\r\n      const parts = token.split('.');\r\n      if (parts.length !== 3) {\r\n        throw new Error(\"Token does not have 3 parts\");\r\n      }\r\n\r\n      \/\/ 3. Normalize Base64Url to standard Base64\r\n      let base64Url = parts[1];\r\n      let base64 = base64Url.replace(\/-\/g, '+').replace(\/_\/g, '\/');\r\n      \r\n      \/\/ Pad with '=' so the string length is a multiple of 4 (required by some browsers)\r\n      const pad = base64.length % 4;\r\n      if (pad) {\r\n        if (pad === 1) throw new Error(\"Invalid Base64 string length\");\r\n        base64 += new Array(5 - pad).join('=');\r\n      }\r\n\r\n      \/\/ 4. Decode the Base64 string\r\n      \/\/ Note: We use a URI component trick to prevent errors if your payload contains special characters (like accented names)\r\n      const jsonPayload = decodeURIComponent(atob(base64).split('').map(function(c) {\r\n          return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);\r\n      }).join(''));\r\n\r\n      const payload = JSON.parse(jsonPayload);\r\n      const now = Math.floor(Date.now() \/ 1000);\r\n\r\n      \/\/ 5. Check Expiry\r\n      if (payload.exp && payload.exp < now) {\r\n        console.warn(\"JWT has expired!\");\r\n        clearAuthData(); \/\/ Wipe everything\r\n        window.location.href = loginUrl;\r\n      } else {\r\n        console.log(\"JWT is valid and active.\");\r\n      }\r\n\r\n    } catch (e) {\r\n      console.error(\"Malformed JWT error:\", e.message);\r\n      clearAuthData(); \/\/ Wipe everything\r\n      window.location.href = loginUrl;\r\n    }\r\n  })();\r\n<\/script><\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-4068e7b e-con-full e-flex e-con e-child\" data-id=\"4068e7b\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t<div class=\"elementor-element elementor-element-fd818f4 elementor-widget elementor-widget-heading\" data-id=\"fd818f4\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t\t<p class=\"elementor-heading-title elementor-size-default\">Hello <span id=\"sidebar-username\"><\/span><\/p>\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-6f4506a elementor-widget__width-initial elementor-widget elementor-widget-text-editor\" data-id=\"6f4506a\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t\t\t\t\t\t<p>Need to change your password? <a href=\"\/en\/reserved-area\/change-password\/\">Change<\/a><br \/>Ready to leave? <span id=\"logout-button\">Log out<\/span><\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-9d4fdc3 elementor-widget elementor-widget-heading\" data-id=\"9d4fdc3\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t\t<p class=\"elementor-heading-title elementor-size-default\">Documentation<\/p>\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-efd5ffd elementor-widget elementor-widget-text-editor\" data-id=\"efd5ffd\" data-element_type=\"widget\" data-e-type=\"widget\" id=\"placeholder-documentazione\" data-widget_type=\"text-editor.default\">\n\t\t\t\t\t\t\t\t\t<p>Select a pump series to access technical documentation.<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-aac01c4 elementor-widget elementor-widget-n-accordion\" data-id=\"aac01c4\" data-element_type=\"widget\" data-e-type=\"widget\" id=\"mnemosyne-accordion\" data-settings=\"{&quot;n_accordion_animation_duration&quot;:{&quot;unit&quot;:&quot;ms&quot;,&quot;size&quot;:200,&quot;sizes&quot;:[]},&quot;default_state&quot;:&quot;all_collapsed&quot;,&quot;max_items_expended&quot;:&quot;one&quot;}\" data-widget_type=\"nested-accordion.default\">\n\t\t\t\t\t\t\t<div class=\"e-n-accordion\" aria-label=\"Accordion. Open links with Enter or Space, close with Escape, and navigate with Arrow Keys\">\n\t\t\t\t\t\t<details id=\"master-tab\" class=\"e-n-accordion-item\" >\n\t\t\t\t<summary class=\"e-n-accordion-item-title\" data-accordion-index=\"1\" tabindex=\"0\" aria-expanded=\"false\" aria-controls=\"master-tab\" >\n\t\t\t\t\t<span class='e-n-accordion-item-title-header'><p class=\"e-n-accordion-item-title-text\"> Template Elem 1 <\/p><\/span>\n\t\t\t\t\t\t\t<span class='e-n-accordion-item-title-icon'>\n\t\t\t<span class='e-opened' ><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" id=\"a\" data-name=\"Livello 1\" viewBox=\"0 0 300 300\"><path d=\"M150,299c82.29,0,149-66.71,149-149S232.29,1,150,1,1,67.71,1,150s66.71,149,149,149ZM100.7,131.34l41.64-41.73c1.91-1.92,4.52-2.99,7.23-2.98h.49c2.75-.06,5.41,1.01,7.35,2.97l41.61,41.72c4.07,3.91,4.2,10.37.3,14.44-3.91,4.07-10.37,4.2-14.44.3-.1-.09-.19-.19-.29-.29l-24.47-24.44v81.94c0,5.6-4.54,10.14-10.14,10.14s-10.14-4.54-10.14-10.14v-82.14l-24.67,24.67c-4.06,3.92-10.53,3.81-14.45-.25-3.82-3.96-3.82-10.24,0-14.2Z\"><\/path><\/svg><\/span>\n\t\t\t<span class='e-closed'><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" id=\"a\" data-name=\"Livello 1\" viewBox=\"0 0 300 300\"><path d=\"M150,1C67.71,1,1,67.71,1,150s66.71,149,149,149,149-66.71,149-149S232.29,1,150,1ZM199.3,168.66l-41.64,41.73c-1.91,1.92-4.52,2.99-7.23,2.98h-.49c-2.75.06-5.41-1.01-7.35-2.97l-41.61-41.72c-4.07-3.91-4.2-10.37-.3-14.44,3.91-4.07,10.37-4.2,14.44-.3.1.09.19.19.29.29l24.47,24.44v-81.94c0-5.6,4.54-10.14,10.14-10.14s10.14,4.54,10.14,10.14v82.14l24.67-24.67c4.06-3.92,10.53-3.81,14.45.25,3.82,3.96,3.82,10.24,0,14.2Z\"><\/path><\/svg><\/span>\n\t\t<\/span>\n\n\t\t\t\t\t\t<\/summary>\n\t\t\t\t<div role=\"region\" aria-labelledby=\"master-tab\" class=\"elementor-element elementor-element-d03d732 e-con-full e-flex e-con e-child\" data-id=\"d03d732\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t<div class=\"elementor-element elementor-element-39c187d e-n-tabs-none elementor-widget elementor-widget-n-tabs\" data-id=\"39c187d\" data-element_type=\"widget\" data-e-type=\"widget\" data-settings=\"{&quot;tabs_justify_horizontal&quot;:&quot;start&quot;,&quot;horizontal_scroll&quot;:&quot;disable&quot;}\" data-widget_type=\"nested-tabs.default\">\n\t\t\t\t\t\t\t<div class=\"e-n-tabs\" data-widget-number=\"60561533\" aria-label=\"Tabs. Open items with Enter or Space, close with Escape and navigate using the Arrow keys.\">\n\t\t\t<div class=\"e-n-tabs-heading\" role=\"tablist\">\n\t\t\t\t\t<button id=\"master-tabs-widget\" data-tab-title-id=\"e-n-tab-title-605615331\" class=\"e-n-tab-title\" aria-selected=\"true\" data-tab-index=\"1\" role=\"tab\" tabindex=\"0\" aria-controls=\"e-n-tab-content-605615331\" style=\"--n-tabs-title-order: 1;\">\n\t\t\t\t\t\t<span class=\"e-n-tab-title-text\">\n\t\t\t\tSubfolder 1\t\t\t<\/span>\n\t\t<\/button>\n\t\t\t\t<button id=\"e-n-tab-title-605615332\" data-tab-title-id=\"e-n-tab-title-605615332\" class=\"e-n-tab-title\" aria-selected=\"false\" data-tab-index=\"2\" role=\"tab\" tabindex=\"-1\" aria-controls=\"e-n-tab-content-605615332\" style=\"--n-tabs-title-order: 2;\">\n\t\t\t\t\t\t<span class=\"e-n-tab-title-text\">\n\t\t\t\tSubfolder 2\t\t\t<\/span>\n\t\t<\/button>\n\t\t\t\t\t<\/div>\n\t\t\t<div class=\"e-n-tabs-content\">\n\t\t\t\t<div role=\"region tabpanel\" aria-labelledby=\"master-tab master-tabs-widget\" id=\"e-n-tab-content-605615331\" data-tab-index=\"1\" style=\"--n-tabs-title-order: 1;\" class=\"e-active elementor-element elementor-element-88ae0bc e-con-full e-flex e-con e-child\" data-id=\"88ae0bc\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t<div class=\"elementor-element elementor-element-3822b3d elementor-position-inline-end elementor-mobile-position-inline-end elementor-view-default elementor-widget elementor-widget-icon-box\" data-id=\"3822b3d\" data-element_type=\"widget\" data-e-type=\"widget\" id=\"master-file-item\" data-widget_type=\"icon-box.default\">\n\t\t\t\t\t\t\t<div class=\"elementor-icon-box-wrapper\">\n\n\t\t\t\t\t\t<div class=\"elementor-icon-box-icon\">\n\t\t\t\t<span  class=\"elementor-icon\">\n\t\t\t\t<svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" id=\"a\" data-name=\"Livello 1\" viewBox=\"0 0 300 300\"><g id=\"b\" data-name=\"Raggruppa 265\"><path id=\"c\" data-name=\"Tracciato 60\" d=\"M63.81,0C44.25.02,28.39,15.87,28.38,35.43v229.13c.02,19.56,15.87,35.41,35.43,35.43h172.38c19.56-.02,35.41-15.87,35.43-35.43V101.35h-68.52c-15.89-.02-28.76-12.89-28.78-28.78V0H63.81Z\"><\/path><path id=\"d\" data-name=\"Tracciato 61\" d=\"M271.62,77.03h-60.77c-6.71,0-12.16-5.42-12.17-12.13V0l72.93,77.03Z\"><\/path><\/g><\/svg>\t\t\t\t<\/span>\n\t\t\t<\/div>\n\t\t\t\n\t\t\t\t\t\t<div class=\"elementor-icon-box-content\">\n\n\t\t\t\t\t\t\t\t\t<p class=\"elementor-icon-box-title\">\n\t\t\t\t\t\t<span  >\n\t\t\t\t\t\t\tSub-1 Elem 1\t\t\t\t\t\t<\/span>\n\t\t\t\t\t<\/p>\n\t\t\t\t\n\t\t\t\t\n\t\t\t<\/div>\n\t\t\t\n\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-ada57e0 elementor-position-inline-end elementor-mobile-position-inline-end elementor-view-default elementor-widget elementor-widget-icon-box\" data-id=\"ada57e0\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"icon-box.default\">\n\t\t\t\t\t\t\t<div class=\"elementor-icon-box-wrapper\">\n\n\t\t\t\t\t\t<div class=\"elementor-icon-box-icon\">\n\t\t\t\t<span  class=\"elementor-icon\">\n\t\t\t\t<svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" id=\"a\" data-name=\"Livello 1\" viewBox=\"0 0 300 300\"><g id=\"b\" data-name=\"Raggruppa 265\"><path id=\"c\" data-name=\"Tracciato 60\" d=\"M63.81,0C44.25.02,28.39,15.87,28.38,35.43v229.13c.02,19.56,15.87,35.41,35.43,35.43h172.38c19.56-.02,35.41-15.87,35.43-35.43V101.35h-68.52c-15.89-.02-28.76-12.89-28.78-28.78V0H63.81Z\"><\/path><path id=\"d\" data-name=\"Tracciato 61\" d=\"M271.62,77.03h-60.77c-6.71,0-12.16-5.42-12.17-12.13V0l72.93,77.03Z\"><\/path><\/g><\/svg>\t\t\t\t<\/span>\n\t\t\t<\/div>\n\t\t\t\n\t\t\t\t\t\t<div class=\"elementor-icon-box-content\">\n\n\t\t\t\t\t\t\t\t\t<p class=\"elementor-icon-box-title\">\n\t\t\t\t\t\t<span  >\n\t\t\t\t\t\t\tSub-1 Elem 2\t\t\t\t\t\t<\/span>\n\t\t\t\t\t<\/p>\n\t\t\t\t\n\t\t\t\t\n\t\t\t<\/div>\n\t\t\t\n\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div role=\"region tabpanel\" aria-labelledby=\"master-tab e-n-tab-title-605615332\" id=\"e-n-tab-content-605615332\" data-tab-index=\"2\" style=\"--n-tabs-title-order: 2;\" class=\" elementor-element elementor-element-d65daeb e-con-full e-flex e-con e-child\" data-id=\"d65daeb\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t<div class=\"elementor-element elementor-element-76d8a49 elementor-position-inline-end elementor-mobile-position-inline-end elementor-view-default elementor-widget elementor-widget-icon-box\" data-id=\"76d8a49\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"icon-box.default\">\n\t\t\t\t\t\t\t<div class=\"elementor-icon-box-wrapper\">\n\n\t\t\t\t\t\t<div class=\"elementor-icon-box-icon\">\n\t\t\t\t<span  class=\"elementor-icon\">\n\t\t\t\t<svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" id=\"a\" data-name=\"Livello 1\" viewBox=\"0 0 300 300\"><g id=\"b\" data-name=\"Raggruppa 265\"><path id=\"c\" data-name=\"Tracciato 60\" d=\"M63.81,0C44.25.02,28.39,15.87,28.38,35.43v229.13c.02,19.56,15.87,35.41,35.43,35.43h172.38c19.56-.02,35.41-15.87,35.43-35.43V101.35h-68.52c-15.89-.02-28.76-12.89-28.78-28.78V0H63.81Z\"><\/path><path id=\"d\" data-name=\"Tracciato 61\" d=\"M271.62,77.03h-60.77c-6.71,0-12.16-5.42-12.17-12.13V0l72.93,77.03Z\"><\/path><\/g><\/svg>\t\t\t\t<\/span>\n\t\t\t<\/div>\n\t\t\t\n\t\t\t\t\t\t<div class=\"elementor-icon-box-content\">\n\n\t\t\t\t\t\t\t\t\t<p class=\"elementor-icon-box-title\">\n\t\t\t\t\t\t<span  >\n\t\t\t\t\t\t\tSub-2 Elem 1\t\t\t\t\t\t<\/span>\n\t\t\t\t\t<\/p>\n\t\t\t\t\n\t\t\t\t\n\t\t\t<\/div>\n\t\t\t\n\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-21e3ab0 elementor-position-inline-end elementor-mobile-position-inline-end elementor-view-default elementor-widget elementor-widget-icon-box\" data-id=\"21e3ab0\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"icon-box.default\">\n\t\t\t\t\t\t\t<div class=\"elementor-icon-box-wrapper\">\n\n\t\t\t\t\t\t<div class=\"elementor-icon-box-icon\">\n\t\t\t\t<span  class=\"elementor-icon\">\n\t\t\t\t<svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" id=\"a\" data-name=\"Livello 1\" viewBox=\"0 0 300 300\"><g id=\"b\" data-name=\"Raggruppa 265\"><path id=\"c\" data-name=\"Tracciato 60\" d=\"M63.81,0C44.25.02,28.39,15.87,28.38,35.43v229.13c.02,19.56,15.87,35.41,35.43,35.43h172.38c19.56-.02,35.41-15.87,35.43-35.43V101.35h-68.52c-15.89-.02-28.76-12.89-28.78-28.78V0H63.81Z\"><\/path><path id=\"d\" data-name=\"Tracciato 61\" d=\"M271.62,77.03h-60.77c-6.71,0-12.16-5.42-12.17-12.13V0l72.93,77.03Z\"><\/path><\/g><\/svg>\t\t\t\t<\/span>\n\t\t\t<\/div>\n\t\t\t\n\t\t\t\t\t\t<div class=\"elementor-icon-box-content\">\n\n\t\t\t\t\t\t\t\t\t<p class=\"elementor-icon-box-title\">\n\t\t\t\t\t\t<span  >\n\t\t\t\t\t\t\tSub-2 Elem 2\t\t\t\t\t\t<\/span>\n\t\t\t\t\t<\/p>\n\t\t\t\t\n\t\t\t\t\n\t\t\t<\/div>\n\t\t\t\n\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/details>\n\t\t\t\t\t\t<details id=\"e-n-accordion-item-1791\" class=\"e-n-accordion-item\" >\n\t\t\t\t<summary class=\"e-n-accordion-item-title\" data-accordion-index=\"2\" tabindex=\"-1\" aria-expanded=\"false\" aria-controls=\"e-n-accordion-item-1791\" >\n\t\t\t\t\t<span class='e-n-accordion-item-title-header'><p class=\"e-n-accordion-item-title-text\"> Template Elem 2 <\/p><\/span>\n\t\t\t\t\t\t\t<span class='e-n-accordion-item-title-icon'>\n\t\t\t<span class='e-opened' ><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" id=\"a\" data-name=\"Livello 1\" viewBox=\"0 0 300 300\"><path d=\"M150,299c82.29,0,149-66.71,149-149S232.29,1,150,1,1,67.71,1,150s66.71,149,149,149ZM100.7,131.34l41.64-41.73c1.91-1.92,4.52-2.99,7.23-2.98h.49c2.75-.06,5.41,1.01,7.35,2.97l41.61,41.72c4.07,3.91,4.2,10.37.3,14.44-3.91,4.07-10.37,4.2-14.44.3-.1-.09-.19-.19-.29-.29l-24.47-24.44v81.94c0,5.6-4.54,10.14-10.14,10.14s-10.14-4.54-10.14-10.14v-82.14l-24.67,24.67c-4.06,3.92-10.53,3.81-14.45-.25-3.82-3.96-3.82-10.24,0-14.2Z\"><\/path><\/svg><\/span>\n\t\t\t<span class='e-closed'><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" id=\"a\" data-name=\"Livello 1\" viewBox=\"0 0 300 300\"><path d=\"M150,1C67.71,1,1,67.71,1,150s66.71,149,149,149,149-66.71,149-149S232.29,1,150,1ZM199.3,168.66l-41.64,41.73c-1.91,1.92-4.52,2.99-7.23,2.98h-.49c-2.75.06-5.41-1.01-7.35-2.97l-41.61-41.72c-4.07-3.91-4.2-10.37-.3-14.44,3.91-4.07,10.37-4.2,14.44-.3.1.09.19.19.29.29l24.47,24.44v-81.94c0-5.6,4.54-10.14,10.14-10.14s10.14,4.54,10.14,10.14v82.14l24.67-24.67c4.06-3.92,10.53-3.81,14.45.25,3.82,3.96,3.82,10.24,0,14.2Z\"><\/path><\/svg><\/span>\n\t\t<\/span>\n\n\t\t\t\t\t\t<\/summary>\n\t\t\t\t<div role=\"region\" aria-labelledby=\"e-n-accordion-item-1791\" class=\"elementor-element elementor-element-ba6a17e e-con-full e-flex e-con e-child\" data-id=\"ba6a17e\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t<div class=\"elementor-element elementor-element-f3a7487 elementor-position-inline-end elementor-mobile-position-inline-end elementor-view-default elementor-widget elementor-widget-icon-box\" data-id=\"f3a7487\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"icon-box.default\">\n\t\t\t\t\t\t\t<div class=\"elementor-icon-box-wrapper\">\n\n\t\t\t\t\t\t<div class=\"elementor-icon-box-icon\">\n\t\t\t\t<span  class=\"elementor-icon\">\n\t\t\t\t<svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" id=\"a\" data-name=\"Livello 1\" viewBox=\"0 0 300 300\"><g id=\"b\" data-name=\"Raggruppa 265\"><path id=\"c\" data-name=\"Tracciato 60\" d=\"M63.81,0C44.25.02,28.39,15.87,28.38,35.43v229.13c.02,19.56,15.87,35.41,35.43,35.43h172.38c19.56-.02,35.41-15.87,35.43-35.43V101.35h-68.52c-15.89-.02-28.76-12.89-28.78-28.78V0H63.81Z\"><\/path><path id=\"d\" data-name=\"Tracciato 61\" d=\"M271.62,77.03h-60.77c-6.71,0-12.16-5.42-12.17-12.13V0l72.93,77.03Z\"><\/path><\/g><\/svg>\t\t\t\t<\/span>\n\t\t\t<\/div>\n\t\t\t\n\t\t\t\t\t\t<div class=\"elementor-icon-box-content\">\n\n\t\t\t\t\t\t\t\t\t<p class=\"elementor-icon-box-title\">\n\t\t\t\t\t\t<span  >\n\t\t\t\t\t\t\tNosub Elem 1\t\t\t\t\t\t<\/span>\n\t\t\t\t\t<\/p>\n\t\t\t\t\n\t\t\t\t\n\t\t\t<\/div>\n\t\t\t\n\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-e976505 elementor-position-inline-end elementor-mobile-position-inline-end elementor-view-default elementor-widget elementor-widget-icon-box\" data-id=\"e976505\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"icon-box.default\">\n\t\t\t\t\t\t\t<div class=\"elementor-icon-box-wrapper\">\n\n\t\t\t\t\t\t<div class=\"elementor-icon-box-icon\">\n\t\t\t\t<span  class=\"elementor-icon\">\n\t\t\t\t<svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" id=\"a\" data-name=\"Livello 1\" viewBox=\"0 0 300 300\"><g id=\"b\" data-name=\"Raggruppa 265\"><path id=\"c\" data-name=\"Tracciato 60\" d=\"M63.81,0C44.25.02,28.39,15.87,28.38,35.43v229.13c.02,19.56,15.87,35.41,35.43,35.43h172.38c19.56-.02,35.41-15.87,35.43-35.43V101.35h-68.52c-15.89-.02-28.76-12.89-28.78-28.78V0H63.81Z\"><\/path><path id=\"d\" data-name=\"Tracciato 61\" d=\"M271.62,77.03h-60.77c-6.71,0-12.16-5.42-12.17-12.13V0l72.93,77.03Z\"><\/path><\/g><\/svg>\t\t\t\t<\/span>\n\t\t\t<\/div>\n\t\t\t\n\t\t\t\t\t\t<div class=\"elementor-icon-box-content\">\n\n\t\t\t\t\t\t\t\t\t<p class=\"elementor-icon-box-title\">\n\t\t\t\t\t\t<span  >\n\t\t\t\t\t\t\tNosub Elem 2\t\t\t\t\t\t<\/span>\n\t\t\t\t\t<\/p>\n\t\t\t\t\n\t\t\t\t\n\t\t\t<\/div>\n\t\t\t\n\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/details>\n\t\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-40a2000 elementor-widget elementor-widget-html\" data-id=\"40a2000\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t\t<div id=\"mnemosyne-accordion-loading\" style=\"display: none; padding: 30px; text-align: center;\">\r\n    <div class=\"loader-spinner\" style=\"\r\n        width: 40px; \r\n        height: 40px; \r\n        border: 4px solid #e3e6e5; \r\n        border-top: 4px solid #E4002B; \r\n        border-radius: 50%; \r\n        animation: spin 1s linear infinite;\r\n        margin: 0 auto 15px auto;\">\r\n    <\/div>\r\n    <p style=\"font-family: inherit; color: #555; font-size: 20px; margin: 0;\">\r\n        Retrieving technical documents\r\n    <\/p>\r\n<\/div>\r\n\r\n<style>\r\n@keyframes spin {\r\n    0% { transform: rotate(0deg); }\r\n    100% { transform: rotate(360deg); }\r\n}\r\n<\/style>\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-a73e881 elementor-hidden-desktop elementor-hidden-tablet elementor-hidden-mobile elementor-widget elementor-widget-shortcode\" data-id=\"a73e881\" 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\ndocument.addEventListener('DOMContentLoaded', function() {\r\n    const API_BASE = \"https:\/\/drawings.salvatorerobuschi.com\";\r\n    const INITIAL_PUMP_NAME = \"AUTO\";\r\n    const linguaCorrente = document.documentElement.lang.substring(0, 2);\r\n    const placeholderDocumentazione = document.getElementById(\"placeholder-documentazione\");\r\n    \r\n    let container, tabMaster, fileMaster, tabsWidgetMaster, singleTabBtnMaster, singleTabPanelMaster;\r\n\r\n    const apiGet = async (path) => {\r\n        let retries = 0; \r\n        while (true) {\r\n            try { \r\n                const r = await fetch(`${API_BASE}${path}`); \r\n                if (r.status === 429) {\r\n                    console.warn(`Rate limit (429) raggiunto. Attesa di 1 secondo...`);\r\n                    await new Promise(resolve => setTimeout(resolve, 1000));\r\n                    retries++;\r\n                    if (retries > 10) return [];\r\n                    continue; \r\n                }\r\n                return r.ok ? await r.json() : []; \r\n            } catch (e) { \r\n                return []; \r\n            }\r\n        }\r\n    };\r\n\r\n    const normalize = (str) => str ? str.toString().replace(\/\\s+\/g, ' ').trim().toUpperCase() : \"\";\r\n    const sortNatural = (a, b) => a.name.localeCompare(b.name, undefined, { numeric: true, sensitivity: 'base' });\r\n    const exactOrderLang = [\"ITA\", \"ENG\", \"FRA\", \"ESP\", \"DEU\"];\r\n    const sortLanguages = (a, b) => {\r\n        const nameA = a.name.toUpperCase();\r\n        const nameB = b.name.toUpperCase();\r\n        \r\n        const indexA = exactOrderLang.indexOf(nameA);\r\n        const indexB = exactOrderLang.indexOf(nameB);\r\n        \r\n        const isLangA = indexA !== -1;\r\n        const isLangB = indexB !== -1;\r\n        \r\n        if (isLangA && isLangB) return indexA - indexB;\r\n        if (isLangA && !isLangB) return -1;\r\n        if (!isLangA && isLangB) return 1;\r\n        return a.name.localeCompare(b.name, undefined, { numeric: true, sensitivity: 'base' });\r\n    };\r\n    \r\n    const CUSTOM_ORDER = [\"Curve 50Hz\", \"Curve 60Hz\", \"Ingombri\", \"Sezioni\", \"Manuali\", \"Cataloghi\", \"Altri documenti\"];\r\n\r\n    \/\/ --- 1. INIZIALIZZAZIONE DOM ---\r\n    const initDOM = async () => {\r\n        const waitForElement = (id) => new Promise(res => {\r\n            const i = setInterval(() => { const el = document.getElementById(id); if(el){ clearInterval(i); res(el); } }, 100);\r\n            setTimeout(() => { clearInterval(i); res(null); }, 5000);\r\n        });\r\n\r\n        const mainAccordion = await waitForElement('mnemosyne-accordion');\r\n        if (!mainAccordion) return false;\r\n        container = mainAccordion.querySelector('.e-n-accordion') || mainAccordion;\r\n\r\n        \/\/ Fallback robusto nel caso Elementor sposti l'ID master-tab\r\n        const rawTab = document.getElementById('master-tab') || document.querySelector('[aria-controls=\"master-tab\"]') || document.querySelector('[aria-labelledby=\"master-tab\"]');\r\n        const rawTabsBtn = document.getElementById('master-tabs-widget'); \r\n        const rawFileItem = document.getElementById('master-file-item');\r\n\r\n        if (!rawTab || !rawFileItem) {\r\n            container.innerHTML = '<p style=\"color:red; padding:20px;\">Errore: Manca l\\'ID master-tab o master-file-item.<\/p>';\r\n            return false;\r\n        }\r\n\r\n        tabMaster = rawTab.closest('details')?.cloneNode(true);\r\n        fileMaster = rawFileItem.closest('.elementor-widget-icon-box')?.cloneNode(true);\r\n\r\n        if (rawTabsBtn) {\r\n            const innerTabs = rawTabsBtn.closest('.elementor-widget-n-tabs');\r\n            if (innerTabs) {\r\n                tabsWidgetMaster = innerTabs.cloneNode(true);\r\n                singleTabBtnMaster = tabsWidgetMaster.querySelector('.e-n-tab-title')?.cloneNode(true);\r\n                singleTabPanelMaster = tabsWidgetMaster.querySelector('.e-n-tabs-content > div')?.cloneNode(true);\r\n                if (singleTabBtnMaster && singleTabPanelMaster) {\r\n                    tabsWidgetMaster.querySelector('.e-n-tabs-heading').innerHTML = '';\r\n                    tabsWidgetMaster.querySelector('.e-n-tabs-content').innerHTML = '';\r\n                } else {\r\n                    tabsWidgetMaster = null; \r\n                }\r\n            }\r\n        }\r\n\r\n        \/\/ FIX #1: Rimuoviamo il template originale SOLO ALLA FINE, dopo aver clonato tutto in sicurezza\r\n        const originalTemplate = rawTab.closest('details');\r\n        if (originalTemplate) {\r\n            originalTemplate.remove();\r\n        }\r\n\r\n        return true;\r\n    };\r\n\r\n    \/\/ --- 2. LOGICA DI CARICAMENTO DATI ---\r\n    const loadPumpData = async (currentPumpName) => {\r\n        if (!currentPumpName) return;\r\n        \r\n        \/\/ FIX #2: Rimuoviamo solo i details (gli accordion), senza distruggere eventuali Loader di Elementor\r\n        Array.from(container.querySelectorAll('details')).forEach(d => d.remove());\r\n        \r\n        const loaderEl = document.getElementById('mnemosyne-accordion-loading');\r\n        if (loaderEl) {\r\n            loaderEl.style.display = 'block'; \r\n            if (placeholderDocumentazione !== null) placeholderDocumentazione.style.display ='none'; \r\n        }\r\n\r\n        try {\r\n            const roots = await apiGet('\/info\/roots');\r\n            const tabelle = roots.find(n => n.name.toLowerCase() === \"tabelle\");\r\n            if (!tabelle) throw new Error(\"Root 'Tabelle' non trovata.\");\r\n\r\n            const pumpData = await apiGet(`\/data\/${tabelle.id}`);\r\n            const targetName = normalize(currentPumpName);\r\n           \r\n            let pumpFolder = pumpData.find(n => normalize(n.name) === targetName) || \r\n                             pumpData.find(n => normalize(n.name).includes(targetName) || targetName.includes(normalize(n.name)));\r\n                             \r\n            if (!pumpFolder) throw new Error(`Pompa \"${currentPumpName}\" non trovata sul server.`);\r\n\r\n            let categories = await apiGet(`\/data\/${pumpFolder.id}`);\r\n            \r\n            categories.sort((a, b) => {\r\n                const idxA = CUSTOM_ORDER.findIndex(cat => cat.toLowerCase() === a.name.trim().toLowerCase());\r\n                const idxB = CUSTOM_ORDER.findIndex(cat => cat.toLowerCase() === b.name.trim().toLowerCase());\r\n                return (idxA !== -1 ? idxA : 999) - (idxB !== -1 ? idxB : 999);\r\n            });\r\n            \r\n            for (const cat of categories) {\r\n                const contents = await apiGet(`\/data\/${cat.id}`);\r\n                if (!contents || contents.length === 0) continue; \r\n                                \r\n                let accordionItem = tabMaster.cloneNode(true);\r\n                \r\n                accordionItem.removeAttribute('id');\r\n                accordionItem.removeAttribute('open');\r\n                \r\n                const titleText = accordionItem.querySelector('.e-n-accordion-item-title-text');\r\n                if (titleText && cat.name) {\r\n                    \r\n                    let formattedName = cat.name.toLowerCase();\r\n                    formattedName = formattedName.charAt(0).toUpperCase() + formattedName.slice(1);\r\n                    formattedName = formattedName.replace(\/hz\/gi, \"Hz\");\r\n                    formattedName = formattedName.replace(\/varie\/gi, \"Altri documenti\"); \r\n                    \r\n                    if (linguaCorrente != 'it'){\r\n                        formattedName = formattedName.replace(\/curve\\s+50hz\/gi, \"50Hz curves\");\r\n                        formattedName = formattedName.replace(\/curve\\s+60hz\/gi, \"60Hz curves\");\r\n                        formattedName = formattedName.replace(\/ingombri\/gi, \"Dimensions\");\r\n                        formattedName = formattedName.replace(\/sezioni\/gi, \"Cross sections\");\r\n                        formattedName = formattedName.replace(\/manuali\/gi, \"Manuals\");\r\n                        formattedName = formattedName.replace(\/cataloghi\/gi, \"Catalogues\");\r\n                        formattedName = formattedName.replace(\/altri\\s+documenti\/gi, \"Others\");\r\n                    }\r\n                    \r\n                    titleText.textContent = formattedName;\r\n                }\r\n                \r\n                let region = accordionItem.querySelector('[role=\"region\"]');\r\n                \r\n                \/\/ FIX #3: Svuotiamo il contenuto dummy clonato dalla region, altrimenti duplica i file finti ovunque\r\n                if (region) region.innerHTML = '';\r\n                \r\n                let directFiles = contents.filter(item => item.type !== 'DIRECTORY');\r\n                let subFolders = contents.filter(item => item.type === 'DIRECTORY');\r\n                \r\n                directFiles.sort(sortNatural);\r\n                subFolders.sort(sortLanguages);\r\n\r\n                let hasRenderedSomething = false;\r\n\r\n                if (directFiles.length > 0) {\r\n                    directFiles.forEach(f => region.appendChild(createFileItem(f)));\r\n                    hasRenderedSomething = true;\r\n                }\r\n\r\n                if (subFolders.length > 0 && tabsWidgetMaster) {\r\n\r\n                    let tabsWidget = tabsWidgetMaster.cloneNode(true);\r\n                    let headingsCont = tabsWidget.querySelector('.e-n-tabs-heading');\r\n                    let panelsCont = tabsWidget.querySelector('.e-n-tabs-content');\r\n                    let validTabCount = 0;\r\n\r\n                    for (let i = 0; i < subFolders.length; i++) {\r\n                        const sub = subFolders[i];\r\n                        let files = await apiGet(`\/data\/${sub.id}`);\r\n\r\n                        if (!files || files.length === 0) continue;\r\n                        files.sort(sortNatural);\r\n\r\n                        const isFirst = validTabCount === 0;\r\n\r\n                        let btn = singleTabBtnMaster.cloneNode(true);\r\n                        btn.removeAttribute('id');\r\n \r\n                        btn.querySelector('.e-n-tab-title-text').textContent = getLanguageCode(sub.name.toLowerCase());\r\n                        \r\n                        if (linguaCorrente != 'it'){\r\n                            btn.querySelector('.e-n-tab-title-text').textContent = btn.querySelector('.e-n-tab-title-text').textContent.replace(\/poli\/gi, \"poles\");\r\n                        }\r\n                        \r\n                        if (isFirst) { btn.classList.add('e-active'); btn.setAttribute('aria-selected', 'true'); }\r\n                        else { btn.classList.remove('e-active'); btn.setAttribute('aria-selected', 'false'); }\r\n\r\n                        let panel = singleTabPanelMaster.cloneNode(true);\r\n                        panel.removeAttribute('id');\r\n                        panel.innerHTML = '';\r\n                        \r\n                        if (isFirst) panel.classList.add('e-active');\r\n                        else panel.classList.remove('e-active');\r\n\r\n                        files.forEach(f => panel.appendChild(createFileItem(f)));\r\n\r\n                        headingsCont.appendChild(btn);\r\n                        panelsCont.appendChild(panel);\r\n                        validTabCount++;\r\n                    }\r\n                    \r\n                    if (validTabCount > 0) {\r\n                        setupCustomTabsLogic(tabsWidget);\r\n                        region.appendChild(tabsWidget);\r\n                        hasRenderedSomething = true;\r\n                    }\r\n                }\r\n\r\n                if (!hasRenderedSomething) continue;\r\n                container.appendChild(accordionItem);\r\n            }\r\n            \r\n            \/\/ --- INIZIALIZZA LOGICA ACCORDION E ANIMAZIONI ---\r\n            setupExclusiveAccordions();\r\n\r\n        } catch (error) {\r\n            \/\/ Usa appendChild invece di innerHTML per non distruggere l'ambiente\r\n            const errorMsg = document.createElement('p');\r\n            errorMsg.style.padding = '20px';\r\n            errorMsg.style.color = 'red';\r\n            errorMsg.textContent = error.message;\r\n            container.appendChild(errorMsg);\r\n        } finally {\r\n            if (loaderEl) loaderEl.style.display = 'none';\r\n        }\r\n    };\r\n\r\n    \/\/ --- NUOVE FUNZIONI: ANIMAZIONI E CHIUSURA ESCLUSIVA ---\r\n    function setupExclusiveAccordions() {\r\n        const allDetails = Array.from(container.querySelectorAll('details'));\r\n        \r\n        allDetails.forEach(details => {\r\n            const summary = details.querySelector('summary') || details.firstElementChild;\r\n            const content = details.querySelector('[role=\"region\"]');\r\n            \r\n            const newSummary = summary.cloneNode(true);\r\n            summary.parentNode.replaceChild(newSummary, summary);\r\n\r\n            newSummary.addEventListener('click', (e) => {\r\n                e.preventDefault(); \r\n                e.stopPropagation();\r\n\r\n                if (details.dataset.isAnimating === 'true') return;\r\n\r\n                if (details.hasAttribute('open')) {\r\n                    slideUpDetails(details, newSummary);\r\n                } else {\r\n                    allDetails.forEach(otherDetails => {\r\n                        if (otherDetails !== details && otherDetails.hasAttribute('open')) {\r\n                            const otherSummary = otherDetails.querySelector('summary') || otherDetails.firstElementChild;\r\n                            slideUpDetails(otherDetails, otherSummary);\r\n                        }\r\n                    });\r\n                    slideDownDetails(details, newSummary, content);\r\n                }\r\n            });\r\n        });\r\n    }\r\n\r\n    function slideUpDetails(details, summary) {\r\n        details.dataset.isAnimating = 'true';\r\n        details.style.overflow = 'hidden';\r\n        const startHeight = `${details.offsetHeight}px`;\r\n        const endHeight = `${summary.offsetHeight}px`;\r\n\r\n        const animation = details.animate(\r\n            { height: [startHeight, endHeight] }, \r\n            { duration: 300, easing: 'ease-out' }\r\n        );\r\n        \r\n        animation.onfinish = () => {\r\n            details.removeAttribute('open');\r\n            details.style.height = '';\r\n            details.style.overflow = '';\r\n            details.dataset.isAnimating = 'false';\r\n        };\r\n    }\r\n\r\n    function slideDownDetails(details, summary, content) {\r\n        details.dataset.isAnimating = 'true';\r\n        details.style.overflow = 'hidden';\r\n        const startHeight = `${summary.offsetHeight}px`;\r\n        \r\n        details.setAttribute('open', ''); \r\n        \r\n        window.requestAnimationFrame(() => {\r\n            const endHeight = `${summary.offsetHeight + content.scrollHeight}px`;\r\n            \r\n            const animation = details.animate(\r\n                { height: [startHeight, endHeight] }, \r\n                { duration: 300, easing: 'ease-out' }\r\n            );\r\n            \r\n            animation.onfinish = () => {\r\n                details.style.height = '';\r\n                details.style.overflow = '';\r\n                details.dataset.isAnimating = 'false';\r\n            };\r\n        });\r\n    }\r\n\r\n    \/\/ --- HELPER CREAZIONE FILE ---\r\n    function createFileItem(fileData) {\r\n        let item = fileMaster.cloneNode(true);\r\n        item.removeAttribute('id');\r\n        let cleanName = fileData.name.replace(\/\\.[^\/.]+$\/, \"\").replace(\/\\s+\/g, ' ').trim(); \r\n        if (linguaCorrente.toLowerCase() == 'it' && cleanName.includes(';')) {\r\n            cleanName = cleanName.split(';')[0];\r\n        } else if (linguaCorrente.toLowerCase() != 'it' && cleanName.includes(';')){\r\n            cleanName = cleanName.split(';')[1];\r\n        }\r\n        const title = item.querySelector('.elementor-icon-box-title span');\r\n        if (title) title.textContent = cleanName;\r\n        const url = `${API_BASE}\/data\/${fileData.id}`;\r\n        item.style.cursor = 'pointer';\r\n        item.onclick = (e) => { e.preventDefault(); window.open(url, '_blank'); };\r\n        let link = item.querySelector('a');\r\n        if (link) { link.href = url; link.target = \"_blank\"; }\r\n        return item;\r\n    }\r\n\r\n    function setupCustomTabsLogic(tabsWidget) {\r\n        const titles = Array.from(tabsWidget.querySelectorAll('.e-n-tab-title'));\r\n        const panels = Array.from(tabsWidget.querySelectorAll('.e-n-tabs-content > div'));\r\n        titles.forEach((title, index) => {\r\n            title.addEventListener('click', (e) => {\r\n                e.preventDefault(); e.stopPropagation();\r\n                titles.forEach(t => { t.classList.remove('e-active'); t.setAttribute('aria-selected', 'false'); });\r\n                panels.forEach(p => p.classList.remove('e-active'));\r\n                title.classList.add('e-active');\r\n                title.setAttribute('aria-selected', 'true');\r\n                if (panels[index]) panels[index].classList.add('e-active');\r\n            });\r\n        });\r\n    }\r\n\r\n    \/\/ --- 3. START SCRIPT & LISTENER GLOBALE ---\r\n    initDOM().then((isReady) => {\r\n        if (!isReady) return;\r\n\r\n        const accordionElement = document.getElementById('mnemosyne-accordion');\r\n\r\n        if (INITIAL_PUMP_NAME === \"AUTO\") {\r\n            if (accordionElement) accordionElement.style.display = 'none';\r\n\r\n            let internalPumpVal = window.srCurrentPumpName || \"\";\r\n\r\n            Object.defineProperty(window, 'srCurrentPumpName', {\r\n                get: function() { return internalPumpVal; },\r\n                set: function(newValue) {\r\n                    if (newValue && newValue !== internalPumpVal) {\r\n                        internalPumpVal = newValue;\r\n                        if (accordionElement) accordionElement.style.display = 'block';\r\n                        loadPumpData(internalPumpVal);\r\n                    }\r\n                },\r\n                configurable: true\r\n            });\r\n\r\n            if (internalPumpVal) {\r\n                if (accordionElement) accordionElement.style.display = 'block';\r\n                loadPumpData(internalPumpVal);\r\n            }\r\n        } else {\r\n            if (accordionElement) accordionElement.style.display = 'block';\r\n            loadPumpData(INITIAL_PUMP_NAME);\r\n        }\r\n    });\r\n\r\n});\r\n\r\nfunction getLanguageCode(inputString) {\r\n  const langMappings = { \"deu\": \"DE\", \"ita\": \"IT\", \"eng\": \"EN\", \"esp\": \"ES\", \"fra\": \"FR\" };\r\n  return langMappings[inputString] || inputString; \r\n}\r\n<\/script><\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-fcd72fa elementor-hidden-desktop elementor-hidden-tablet elementor-hidden-mobile elementor-widget elementor-widget-shortcode\" data-id=\"fcd72fa\" 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\ndocument.addEventListener(\"DOMContentLoaded\", onPageInitUsers);\r\nconst linguaCorrente = document.documentElement.lang.substring(0, 2);\r\nfunction onPageInitUsers() {\r\n    \/\/ 1. Retrieve the username from local storage\r\n    const storedUsername = localStorage.getItem(\"mnemosyne_username\");\r\n    \r\n    \/\/ 2. Grab the span element\r\n    const usernameSpan = document.getElementById(\"sidebar-username\");\r\n    \r\n    \/\/ 3. If a username was found in storage and the span exists, paste it in\r\n    if (storedUsername && usernameSpan) {\r\n        usernameSpan.textContent = storedUsername;\r\n    }\r\n}\r\n\t\r\n\t\r\n\t\r\n\t\r\ndocument.getElementById(\"logout-button\").addEventListener(\"click\", async function() {\r\n    \/\/ 1. Retrieve the saved JWT from local storage\r\n    const token = localStorage.getItem(\"mnemosyne_jwt\");\r\n    const apiUrl = \"https:\/\/drawings.salvatorerobuschi.com\/auth\/logout\";\r\n\r\n    \/\/ 2. If a token exists, send the POST request to invalidate it on the backend\r\n    if (token) {\r\n        try {\r\n            await fetch(apiUrl, {\r\n                method: \"POST\",\r\n                headers: {\r\n                    \"Authorization\": \"Bearer \" + token,\r\n                    \"Content-Type\": \"application\/json\" \/\/ Good practice, even without a body\r\n                }\r\n            });\r\n            console.log(\"Backend logout successful.\");\r\n        } catch (error) {\r\n            \/\/ Even if the network fails, we still want to log them out locally below\r\n            console.error(\"Network error during backend logout:\", error);\r\n        }\r\n    }\r\n\r\n    \/\/ 3. Wipe the credentials from the browser memory\r\n    localStorage.removeItem(\"mnemosyne_jwt\");\r\n    localStorage.removeItem(\"mnemosyne_username\");\r\n\r\n    \/\/ 4. Redirect the user back to the login page (or refresh the current page)\r\n    \/\/ Update this URL to wherever you want them to go after logging out\r\n    if (linguaCorrente == 'it'){\r\n\t\t window.location.href = \"\/area-riservata\/accesso\/\"; \r\n\t}else{\r\n\t\t window.location.href = \"\/en\/reserved-area\/login\/\"; \r\n\t}\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\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t","protected":false},"excerpt":{"rendered":"<p>Download technical resources and documentation Hello Need to change your password? ChangeReady to leave? Log out Documentation Select a pump series to access technical documentation. Template Elem 1 Subfolder 1 Subfolder 2 Sub-1 Elem 1 Sub-1 Elem 2 Sub-2 Elem 1 Sub-2 Elem 2 Template Elem 2 Nosub Elem 1 Nosub Elem 2 Subfolder 1 [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"_wds_title":"Reserved area: technical drawings & CAD | Salvatore Robuschi","_wds_metadesc":"Access the Salvatore Robuschi reserved area. Find and download technical documentation, 3D CAD models, and manuals for our industrial pumps.","_wds_focus-keywords":"salvatore robuschi reserved area,pump technical documentation,centrifugal pump CAD drawings","_wds_meta-robots-adv":"","_wds_meta-robots-noindex":false,"_wds_meta-robots-nofollow":false,"_wds_meta-robots-index":false,"_wds_meta-robots-follow":false,"_wds_autolinks-exclude":false,"_wds_canonical":"","_wds_opengraph":[],"_wds_twitter":[],"footnotes":""},"class_list":["post-21836","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/www.salvatorerobuschi.com\/en\/wp-json\/wp\/v2\/pages\/21836","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.salvatorerobuschi.com\/en\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/www.salvatorerobuschi.com\/en\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/www.salvatorerobuschi.com\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.salvatorerobuschi.com\/en\/wp-json\/wp\/v2\/comments?post=21836"}],"version-history":[{"count":5,"href":"https:\/\/www.salvatorerobuschi.com\/en\/wp-json\/wp\/v2\/pages\/21836\/revisions"}],"predecessor-version":[{"id":22917,"href":"https:\/\/www.salvatorerobuschi.com\/en\/wp-json\/wp\/v2\/pages\/21836\/revisions\/22917"}],"wp:attachment":[{"href":"https:\/\/www.salvatorerobuschi.com\/en\/wp-json\/wp\/v2\/media?parent=21836"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}