{"id":24278,"date":"2026-05-06T13:47:48","date_gmt":"2026-05-06T11:47:48","guid":{"rendered":"https:\/\/cortez-engineering.com\/?page_id=24278"},"modified":"2026-05-07T17:38:59","modified_gmt":"2026-05-07T15:38:59","slug":"test-calculadora-impresion-3d","status":"publish","type":"page","link":"https:\/\/cortez-engineering.com\/es\/test-calculadora-impresion-3d\/","title":{"rendered":"Test calculadora impresi\u00f3n 3D"},"content":{"rendered":"\t\t<div data-elementor-type=\"wp-page\" data-elementor-id=\"24278\" class=\"elementor elementor-24278\" data-elementor-post-type=\"page\">\n\t\t\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-a2123ff elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"a2123ff\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-faa6677\" data-id=\"faa6677\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-575d474 elementor-widget elementor-widget-html\" data-id=\"575d474\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<!--\r\nELEMENTOR READY \u2014 Cortez Engineering 3D Calculator\r\n\r\nPega este bloque en un widget HTML de Elementor.\r\nNo incluye <!DOCTYPE>, <html>, <head> ni <body>.\r\n-->\r\n\r\n<div id=\"ce-3d-calculator\" class=\"no-file\">\r\n  <style>\r\n    #ce-3d-calculator{--bg:#fff;--bg-s:#f5f6f7;--bg-s2:#eef0f2;--bd:#e3e5e8;--bds:#c8ccd0;--tx:#111;--tx2:#555c62;--tx3:#9199a0;--ac:#18f07e;--acd:#0ec46a;--acs:rgba(24,240,126,.10);--bk:#0d0d0d;--r:14px;--rl:22px;--pill:9999px;--mx:1180px;background:var(--bg);color:var(--tx);font-family:Outfit,system-ui,sans-serif;font-size:16px;line-height:1.6;-webkit-font-smoothing:antialiased}\r\n    #ce-3d-calculator *{box-sizing:border-box}\r\n    #ce-3d-calculator a{color:inherit;text-decoration:none}\r\n    #ce-3d-calculator .intro{max-width:var(--mx);margin:0 auto;padding:72px 40px 0}\r\n    #ce-3d-calculator .intro h1{font-size:clamp(36px,4.5vw,54px);font-weight:800;letter-spacing:-.025em;line-height:1.08;margin:0 0 20px}\r\n    #ce-3d-calculator .intro p{font-size:17px;color:var(--tx2);max-width:720px;line-height:1.65;margin:0}\r\n    #ce-3d-calculator .co{max-width:var(--mx);margin:0 auto;padding:48px 40px 0;overflow:visible}\r\n    #ce-3d-calculator .cgrid{display:grid;grid-template-columns:1fr 340px;gap:20px;align-items:start;overflow:visible}\r\n    #ce-3d-calculator .cleft{display:flex;flex-direction:column;gap:20px}\r\n    #ce-3d-calculator .dz{border:2px dashed var(--bds);border-radius:var(--rl);background:var(--bg-s);padding:80px 40px;text-align:center;cursor:pointer;transition:border-color .25s,background .25s}\r\n    #ce-3d-calculator .dz:hover,#ce-3d-calculator .dz.over,#ce-3d-calculator .dz.loading{border-color:var(--acd);background:var(--acs)}\r\n    #ce-3d-calculator .dz-icon{width:56px;height:56px;margin:0 auto 20px;color:var(--tx3)}\r\n    #ce-3d-calculator .dz h3{font-size:20px;font-weight:700;margin:0 0 8px}\r\n    #ce-3d-calculator .dz p{font-size:15px;color:var(--tx2);margin:0 0 18px}\r\n    #ce-3d-calculator .brbtn{display:inline-flex;align-items:center;gap:8px;padding:11px 24px;border-radius:var(--pill);background:var(--bk);color:#fff;font-size:14px;font-weight:600}\r\n    #ce-3d-calculator .dfmt{margin-top:14px;font-size:12px;color:var(--tx3);letter-spacing:.04em}\r\n    #ce-3d-calculator .dzstatus{margin-top:12px;font-size:13px;font-weight:700;color:var(--acd);display:none}\r\n    #ce-3d-calculator .dz.loading .dzstatus{display:block}\r\n    #ce-3d-calculator input[type=file]{display:none}\r\n    #ce-3d-calculator .priv{display:flex;align-items:flex-start;gap:10px;font-size:13px;color:var(--tx3);line-height:1.55}\r\n    #ce-3d-calculator .priv svg{flex-shrink:0;margin-top:2px}\r\n    #ce-3d-calculator .fcard{display:none;background:#fff;border:1px solid var(--bd);border-radius:var(--r);overflow:hidden}\r\n    #ce-3d-calculator .fcard.show{display:block}\r\n    #ce-3d-calculator .fchead{display:flex;align-items:center;justify-content:space-between;padding:16px 22px;border-bottom:1px solid var(--bd);background:var(--bg-s);gap:14px}\r\n    #ce-3d-calculator .fcname{display:flex;align-items:center;gap:10px;font-weight:600;font-size:15px;min-width:0}\r\n    #ce-3d-calculator .fcname span{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\r\n    #ce-3d-calculator .fcname svg{color:var(--acd);flex-shrink:0}\r\n    #ce-3d-calculator .factions{display:flex;align-items:center;gap:10px;flex-shrink:0;flex-wrap:wrap}\r\n    #ce-3d-calculator .fstatus{display:inline-flex;padding:5px 10px;border-radius:var(--pill);background:var(--acs);color:var(--acd);font-size:11px;font-weight:800;text-transform:uppercase;letter-spacing:.05em;white-space:nowrap}\r\n    #ce-3d-calculator .fcrep{padding:6px 14px;border-radius:var(--pill);border:1px solid var(--bd);background:#fff;font-size:12px;font-weight:500;cursor:pointer;color:var(--tx2);font-family:inherit}\r\n    #ce-3d-calculator .fstats{display:grid;grid-template-columns:repeat(4,1fr);padding:18px 22px;gap:16px}\r\n    #ce-3d-calculator .fstat .sl{font-size:12px;color:var(--tx3);margin-bottom:4px}\r\n    #ce-3d-calculator .fstat .sv{font-size:15px;font-weight:600;color:var(--tx)}\r\n    #ce-3d-calculator .fileslist{display:grid;gap:8px;padding:0 22px 18px}\r\n    #ce-3d-calculator .loadedTitle{font-size:12px;font-weight:800;text-transform:uppercase;letter-spacing:.08em;color:var(--tx2);padding:16px 22px 8px}\r\n    #ce-3d-calculator .multiNote{font-size:12px;color:var(--tx3);padding:0 22px 10px;line-height:1.45}\r\n    #ce-3d-calculator .fileitem{display:grid;grid-template-columns:auto 1fr auto;gap:12px;align-items:center;padding:10px 12px;border:1px solid var(--bd);border-radius:var(--r);background:#fff;cursor:pointer}\r\n    #ce-3d-calculator .fileitem:hover{background:var(--bg-s)}\r\n    #ce-3d-calculator .fileitem.active{border-color:var(--acd);background:var(--acs)}\r\n    #ce-3d-calculator .filebadge{width:28px;height:28px;border-radius:var(--pill);background:var(--bk);color:#fff;display:flex;align-items:center;justify-content:center;font-size:12px;font-weight:800;flex-shrink:0}\r\n    #ce-3d-calculator .fileitem.active .filebadge{background:var(--acd);color:var(--bk)}\r\n    #ce-3d-calculator .fileitem .fn{font-size:13px;font-weight:800;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\r\n    #ce-3d-calculator .fileitem .fm{font-size:12px;color:var(--tx2);margin-top:1px}\r\n    #ce-3d-calculator .fileitem .fp{font-size:12px;font-weight:800;color:var(--tx);white-space:nowrap}\r\n    #ce-3d-calculator .viewer{display:none;background:#fff;border:1px solid var(--bd);border-radius:var(--r);overflow:hidden}\r\n    #ce-3d-calculator .viewer.show{display:block}\r\n    #ce-3d-calculator .vhead{display:flex;justify-content:space-between;align-items:center;gap:16px;padding:14px 18px;border-bottom:1px solid var(--bd);background:var(--bg-s)}\r\n    #ce-3d-calculator .vtitle{font-size:13px;font-weight:800;text-transform:uppercase;letter-spacing:.08em;color:var(--tx2)}\r\n    #ce-3d-calculator .vhint{font-size:12px;color:var(--tx3);text-align:right}\r\n    #ce-3d-calculator .vbox{height:360px;background:linear-gradient(180deg,#fafafa,#eef0f2);position:relative}\r\n    #ce-3d-calculator .vbox canvas{display:block;width:100%;height:100%;cursor:grab}\r\n    #ce-3d-calculator .vbox canvas:active{cursor:grabbing}\r\n    #ce-3d-calculator .vmsg{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;text-align:center;padding:30px;color:var(--tx2);font-size:14px;line-height:1.55}\r\n    #ce-3d-calculator .vmsg strong{display:block;color:var(--tx);font-size:16px;margin-bottom:6px}\r\n    #ce-3d-calculator .cpanel{display:none;background:#fff;border:1px solid var(--bd);border-radius:var(--r)}\r\n    #ce-3d-calculator .cpanel.show{display:block}\r\n    #ce-3d-calculator .csec{padding:24px 24px 0}\r\n    #ce-3d-calculator .csec:last-child{padding-bottom:24px}\r\n    #ce-3d-calculator .csec+.csec{border-top:1px solid var(--bd);padding-top:20px}\r\n    #ce-3d-calculator .clbl{font-size:12px;font-weight:700;text-transform:uppercase;letter-spacing:.1em;color:var(--tx2);margin-bottom:14px;display:block}\r\n    #ce-3d-calculator .mgrid{display:grid;grid-template-columns:repeat(2,1fr);gap:8px}\r\n    #ce-3d-calculator .mbtn,#ce-3d-calculator .obtn{border:1.5px solid var(--bd);border-radius:var(--r);background:#fff;cursor:pointer;font-family:inherit;transition:all .2s}\r\n    #ce-3d-calculator .mbtn{padding:14px 16px;text-align:left}\r\n    #ce-3d-calculator .mbtn:hover,#ce-3d-calculator .obtn:hover{border-color:var(--bds);background:var(--bg-s)}\r\n    #ce-3d-calculator .mbtn.sel,#ce-3d-calculator .obtn.sel{border-color:var(--acd);background:var(--acs)}\r\n    #ce-3d-calculator .mbtn.disabled{opacity:.55;cursor:not-allowed;background:#f8f9fa}\r\n    #ce-3d-calculator .mbtn.disabled:hover{border-color:var(--bd);background:#f8f9fa}\r\n    #ce-3d-calculator .mbtn.disabled .mp{background:#e5e7eb;color:#6b7280}\r\n    #ce-3d-calculator .mbtn .mn{font-size:15px;font-weight:700;color:var(--tx);margin-bottom:2px}\r\n    #ce-3d-calculator .mbtn .ms{font-size:12px;color:var(--tx2)}\r\n    #ce-3d-calculator .mbtn .mp{display:inline-flex;margin-top:8px;padding:4px 9px;border-radius:var(--pill);background:var(--bg-s2);color:var(--tx2);font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.04em}\r\n    #ce-3d-calculator .orow{display:flex;flex-wrap:wrap;gap:8px}\r\n    #ce-3d-calculator .obtn{padding:10px 16px}\r\n    #ce-3d-calculator .obtn .on{font-size:14px;font-weight:700}\r\n    #ce-3d-calculator .obtn .os{font-size:11px;color:var(--tx2);margin-top:2px}\r\n    #ce-3d-calculator .qrow{display:flex;align-items:center;gap:6px;flex-wrap:wrap}\r\n    #ce-3d-calculator .qm,#ce-3d-calculator .qp{width:40px;height:40px;border:1.5px solid var(--bd);border-radius:var(--pill);background:#fff;font-size:18px;cursor:pointer;display:flex;align-items:center;justify-content:center;font-family:inherit}\r\n    #ce-3d-calculator #qtyInput{width:72px;height:40px;text-align:center;border:1.5px solid var(--bd);border-radius:var(--r);background:#fff;font-size:15px;font-weight:700;font-family:inherit;outline:none}\r\n    #ce-3d-calculator .qlbl{font-size:14px;color:var(--tx2)}\r\n    #ce-3d-calculator .optbox{display:none;margin-top:14px;padding:18px;border:1px solid var(--bd);border-radius:var(--r);background:var(--bg-s)}\r\n    #ce-3d-calculator .optbox.show{display:block}\r\n    #ce-3d-calculator .optbox h4{font-size:15px;font-weight:800;margin:0 0 6px}\r\n    #ce-3d-calculator .optbox p{font-size:13px;color:var(--tx2);line-height:1.55;margin:0 0 14px}\r\n    #ce-3d-calculator .optgrid{display:grid;grid-template-columns:repeat(2,1fr);gap:12px}\r\n    #ce-3d-calculator .optfield{display:grid;gap:5px}\r\n    #ce-3d-calculator .optfield label{font-size:12px;font-weight:600;color:var(--tx2)}\r\n    #ce-3d-calculator .optfield input,#ce-3d-calculator .optfield select,#ce-3d-calculator .optfield textarea{width:100%;padding:11px 12px;border:1.5px solid var(--bd);border-radius:var(--r);background:#fff;font-family:inherit;font-size:14px;outline:none}\r\n    #ce-3d-calculator .optfield textarea{min-height:76px;resize:vertical}\r\n    #ce-3d-calculator .optnote{margin-top:12px;font-size:12px;color:var(--tx3);line-height:1.5}\r\n    #ce-3d-calculator .qfsec{display:none}\r\n    #ce-3d-calculator .qfsec.show{display:block}\r\n    #ce-3d-calculator .qfform{display:grid;gap:14px}\r\n    #ce-3d-calculator .qffield{display:grid;gap:6px}\r\n    #ce-3d-calculator .qffield label{font-size:13px;font-weight:700;color:var(--tx2)}\r\n    #ce-3d-calculator .qffield input,#ce-3d-calculator .qffield textarea{width:100%;padding:13px 16px;border:1.5px solid var(--bd);border-radius:var(--r);background:var(--bg-s);font-family:inherit;font-size:15px;outline:none}\r\n    #ce-3d-calculator .qffield textarea{resize:vertical;min-height:120px;line-height:1.55}\r\n    #ce-3d-calculator .qfrow{display:grid;grid-template-columns:1fr 1fr;gap:12px}\r\n    #ce-3d-calculator .checkrow{display:flex;align-items:flex-start;gap:10px;padding:14px 16px;border:1px solid var(--bd);border-radius:var(--r);background:var(--bg-s)}\r\n    #ce-3d-calculator .checkrow input[type=\"checkbox\"]{display:inline-grid!important;appearance:auto!important;-webkit-appearance:checkbox!important;width:16px!important;height:16px!important;min-width:16px!important;min-height:16px!important;margin:4px 0 0!important;opacity:1!important;visibility:visible!important;position:static!important;accent-color:var(--acd);flex-shrink:0}\r\n    #ce-3d-calculator .checkrow span{font-size:14px;color:var(--tx2);line-height:1.45}\r\n    #ce-3d-calculator .hiddenfield{display:none}\r\n    #ce-3d-calculator .hiddenfield.show{display:grid}\r\n    #ce-3d-calculator .filesmall{font-size:12px;color:var(--tx3);line-height:1.45;margin-top:4px}\r\n    #ce-3d-calculator .filepick{display:flex;align-items:center;justify-content:center;gap:8px;width:100%;padding:13px 18px;border-radius:var(--pill);background:var(--bk);color:#fff;font-size:14px;font-weight:700;cursor:pointer}\r\n    #ce-3d-calculator .filepicked{display:none;margin-top:8px;padding:9px 12px;border-radius:var(--r);background:var(--acs);color:var(--acd);font-size:12px;font-weight:700;line-height:1.35;word-break:break-word}\r\n    #ce-3d-calculator .filepicked.show{display:block}\r\n    #ce-3d-calculator .cright{position:-webkit-sticky;position:sticky;top:170px;align-self:flex-start;background:var(--bg-s);border:1px solid var(--bd);border-radius:var(--rl);overflow:hidden;z-index:5}\r\n    #ce-3d-calculator.no-file .cright{position:static;top:auto}\r\n    #ce-3d-calculator .shead{padding:22px 24px 18px;border-bottom:1px solid var(--bd);background:#fff}\r\n    #ce-3d-calculator .shead h3{font-size:15px;font-weight:700;text-transform:uppercase;letter-spacing:.06em;color:var(--tx2);margin:0}\r\n    #ce-3d-calculator .bdown{padding:18px 24px 0}\r\n    #ce-3d-calculator .br{display:flex;justify-content:space-between;align-items:center;padding:10px 0;font-size:14px;border-bottom:1px dashed var(--bd);gap:14px}\r\n    #ce-3d-calculator .br .bl{color:var(--tx2)}\r\n    #ce-3d-calculator .br .bv{font-weight:600;text-align:right}\r\n    #ce-3d-calculator .tblock{margin:18px 24px 0;padding:20px;background:#fff;border:1px solid var(--bd);border-radius:var(--r)}\r\n    #ce-3d-calculator .tlbl{font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.1em;color:var(--tx3);margin-bottom:6px}\r\n    #ce-3d-calculator .tamt{font-size:46px;font-weight:800;letter-spacing:-.03em;line-height:1}\r\n    #ce-3d-calculator .tvat{font-size:12px;color:var(--tx3);margin-top:4px}\r\n    #ce-3d-calculator .tunit{font-size:13px;color:var(--tx2);margin-top:4px;font-weight:500}\r\n    #ce-3d-calculator .shipPromo{display:none;margin-top:14px;padding:12px 14px;border-radius:var(--r);background:var(--acs);border:1px solid rgba(24,240,126,.35);color:var(--tx);font-size:13px;font-weight:800;line-height:1.35}\r\n    #ce-3d-calculator .shipPromo.show{display:block}\r\n    #ce-3d-calculator .shipPromo .small{display:block;margin-top:3px;font-size:11px;font-weight:600;color:var(--tx2)}\r\n    #ce-3d-calculator .shipPromo.free{background:var(--ac);border-color:var(--ac);color:var(--bk)}\r\n    #ce-3d-calculator .shipPromo.review{background:#fff;border-color:var(--bd);color:var(--tx2)}\r\n    #ce-3d-calculator .sndbtn{display:block;width:calc(100% - 48px);margin:16px 24px;padding:15px;text-align:center;background:var(--ac);color:var(--bk);font-weight:700;font-size:15px;border-radius:var(--pill);border:none;cursor:pointer;font-family:inherit;transition:all .25s}\r\n    #ce-3d-calculator .sndbtn:hover{background:var(--acd);color:#fff;box-shadow:0 6px 20px rgba(24,240,126,.3);transform:translateY(-1px)}\r\n    #ce-3d-calculator .sndbtn:disabled{opacity:.45;pointer-events:none}\r\n    #ce-3d-calculator .uploadProgress{display:none;margin:0 24px 18px;padding:14px;border:1px solid var(--bd);border-radius:var(--r);background:#fff}\r\n    #ce-3d-calculator .uploadProgress.show{display:block}\r\n    #ce-3d-calculator .uploadProgressTop{display:flex;justify-content:space-between;align-items:center;gap:12px;margin-bottom:8px;font-size:12px;font-weight:800;color:var(--tx2)}\r\n    #ce-3d-calculator .uploadBar{height:9px;border-radius:var(--pill);background:var(--bg-s2);overflow:hidden}\r\n    #ce-3d-calculator .uploadBarFill{height:100%;width:0%;border-radius:var(--pill);background:var(--ac);transition:width .15s ease}\r\n    #ce-3d-calculator .uploadProgressNote{margin-top:8px;font-size:11px;color:var(--tx3);line-height:1.4}\r\n    #ce-3d-calculator .price-pending .tamt{color:var(--tx3)}\r\n    #ce-3d-calculator .price-pending .bdown{opacity:.65}\r\n    #ce-3d-calculator .nfsec{max-width:var(--mx);margin:0 auto;padding:48px 40px 100px}\r\n    #ce-3d-calculator .nfcard{border:1px solid var(--bd);border-radius:var(--rl);overflow:hidden}\r\n    #ce-3d-calculator .nfhead{background:var(--bg-s);padding:40px 48px;border-bottom:1px solid var(--bd)}\r\n    #ce-3d-calculator .nfhead h2{font-size:28px;font-weight:800;letter-spacing:-.02em;margin:0 0 8px}\r\n    #ce-3d-calculator .nfhead p{font-size:16px;color:var(--tx2);max-width:620px;line-height:1.6;margin:0}\r\n    #ce-3d-calculator .nfbody{padding:40px 48px;display:grid;grid-template-columns:1fr 1fr;gap:48px}\r\n    #ce-3d-calculator .nfform{display:grid;gap:14px}\r\n    #ce-3d-calculator .nfform input,#ce-3d-calculator .nfform textarea{width:100%;padding:13px 16px;border:1.5px solid var(--bd);border-radius:var(--r);background:var(--bg-s);font-family:inherit;font-size:15px;outline:none}\r\n    #ce-3d-calculator .nfform textarea{resize:vertical;min-height:160px}\r\n    #ce-3d-calculator .nflbl{font-size:13px;font-weight:600;color:var(--tx2);margin-bottom:6px;display:block}\r\n    #ce-3d-calculator .nfsub{padding:14px 32px;border-radius:var(--pill);background:var(--bk);color:#fff;font-size:15px;font-weight:700;border:none;cursor:pointer;font-family:inherit}\r\n    #ce-3d-calculator .nfinfo p{font-size:15px;color:var(--tx2);line-height:1.7;margin:0 0 12px}\r\n    #ce-3d-calculator .nfinfo p:first-child{font-size:16px;font-weight:600;color:var(--tx);margin-bottom:10px}\r\n    #ce-3d-calculator .nfsvcbtn{display:inline-flex;align-items:center;justify-content:center;margin-top:10px;padding:13px 24px;border-radius:var(--pill);background:var(--ac);color:var(--bk);font-size:14px;font-weight:800;line-height:1;text-decoration:none;transition:all .25s}\r\n    #ce-3d-calculator .nfsvcbtn:hover{background:var(--acd);color:#fff;box-shadow:0 6px 20px rgba(24,240,126,.3);transform:translateY(-1px)}\r\n    @media(max-width:1024px){#ce-3d-calculator .cgrid{grid-template-columns:1fr}#ce-3d-calculator .cright{position:static;top:auto}#ce-3d-calculator .nfbody{grid-template-columns:1fr;gap:32px}}\r\n    @media(max-width:720px){#ce-3d-calculator .optgrid,#ce-3d-calculator .qfrow{grid-template-columns:1fr}#ce-3d-calculator .intro,#ce-3d-calculator .co,#ce-3d-calculator .nfsec{padding-left:20px;padding-right:20px}#ce-3d-calculator .nfhead,#ce-3d-calculator .nfbody{padding:28px 24px}#ce-3d-calculator .mgrid{grid-template-columns:1fr}#ce-3d-calculator .fstats{grid-template-columns:repeat(2,1fr)}#ce-3d-calculator .tamt{font-size:38px}}\r\n  <\/style>\r\n\r\n  <div class=\"intro\"><h1>Calculadora de precio<br>de impresi\u00f3n 3D<\/h1><p>A\u00f1ade tu archivo y obt\u00e9n una estimaci\u00f3n orientativa al instante. Si te encaja, puedes enviarnos los datos para revisar el presupuesto final.<\/p><\/div>\r\n  <div class=\"co\"><div class=\"cgrid\"><div class=\"cleft\"><div class=\"dz\" id=\"dz\"><svg class=\"dz-icon\" viewBox=\"0 0 56 56\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\"><path d=\"M28 10v28M16 26l12 12 12-12\"\/><path d=\"M8 42v6h40v-6\"\/><\/svg><h3>Arrastra tus archivos 3D aqu\u00ed<\/h3><p>o haz clic para buscar en tu equipo<\/p><div class=\"brbtn\" id=\"brbtn\">Seleccionar archivo<\/div><div class=\"dfmt\">STL \u00b7 OBJ con c\u00e1lculo autom\u00e1tico \u00b7 STEP \/ 3MF para revisi\u00f3n t\u00e9cnica<\/div><div class=\"dzstatus\" id=\"dzstatus\">Procesando archivo\u2026<\/div><input type=\"file\" id=\"fi\" accept=\".stl,.obj,.step,.stp,.3mf\" multiple><\/div><div class=\"priv\"><svg width=\"15\" height=\"15\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><path d=\"M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z\"\/><\/svg><span>STL y OBJ se procesan localmente en tu navegador para calcular una estimaci\u00f3n. STEP y 3MF se aceptan para revisi\u00f3n t\u00e9cnica manual. El archivo solo se enviar\u00e1 si decides enviar la solicitud.<\/span><\/div><div class=\"fcard\" id=\"fcard\"><div class=\"fchead\"><div class=\"fcname\"><svg width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><path d=\"M13 2H6a2 2 0 00-2 2v16a2 2 0 002 2h12a2 2 0 002-2V9z\"\/><polyline points=\"13 2 13 9 20 9\"\/><\/svg><span id=\"fcname\">\u2014<\/span><\/div><div class=\"factions\"><span class=\"fstatus\" id=\"fstatus\">Archivo cargado<\/span><button class=\"fcrep\" id=\"fadd\" type=\"button\">+ A\u00f1adir archivo<\/button><button class=\"fcrep\" id=\"fdel\" type=\"button\">Eliminar<\/button><\/div><\/div><div class=\"fstats\"><div class=\"fstat\"><div class=\"sl\">Volumen<\/div><div class=\"sv\" id=\"svol\">\u2014<\/div><\/div><div class=\"fstat\"><div class=\"sl\">Dimensiones mm<\/div><div class=\"sv\" id=\"sdim\">\u2014<\/div><\/div><div class=\"fstat\"><div class=\"sl\">Tri\u00e1ngulos<\/div><div class=\"sv\" id=\"stri\">\u2014<\/div><\/div><div class=\"fstat\"><div class=\"sl\">Tama\u00f1o<\/div><div class=\"sv\" id=\"ssz\">\u2014<\/div><\/div><\/div><div class=\"fileslist\" id=\"fileslist\"><\/div><\/div><div class=\"viewer\" id=\"viewer\"><div class=\"vhead\"><div class=\"vtitle\">Vista previa 3D<\/div><div class=\"vhint\" id=\"vhint\">Arrastra para girar \u00b7 rueda para zoom<\/div><\/div><div class=\"vbox\" id=\"vbox\"><div class=\"vmsg\" id=\"vmsg\"><div><strong>Vista previa del modelo<\/strong>Sube un STL u OBJ para interactuar con la pieza.<\/div><\/div><\/div><\/div><div class=\"cpanel\" id=\"cpanel\"><div class=\"csec\"><span class=\"clbl\">Material<\/span><div class=\"mgrid\" id=\"mgrid\"><\/div><\/div><div class=\"csec\"><span class=\"clbl\">Calidad de capa<\/span><div class=\"orow\" id=\"qrow\"><\/div><\/div><div class=\"csec\"><span class=\"clbl\">Relleno \/ Infill<\/span><div class=\"orow\" id=\"irow\"><\/div><div class=\"optbox\" id=\"optbox\"><h4>Optimizaci\u00f3n estructural del relleno<\/h4><p>Esta opci\u00f3n no es un infill est\u00e1ndar ni simplemente imprimir al 100%. Incluye optimizaci\u00f3n FEM, an\u00e1lisis t\u00e9cnico de la pieza y un informe PDF breve con las mejoras obtenidas en peso, rigidez o distribuci\u00f3n de material.<\/p><div class=\"optgrid\"><div class=\"optfield\"><label for=\"forceInput\">Fuerza principal estimada (N)<\/label><input type=\"number\" id=\"forceInput\" min=\"0\" step=\"10\" placeholder=\"Ej. 10000\"><\/div><div class=\"optfield\"><label for=\"loadPointsInput\">Puntos de carga<\/label><input type=\"number\" id=\"loadPointsInput\" min=\"0\" step=\"1\" placeholder=\"Ej. 2\"><\/div><div class=\"optfield\"><label for=\"supportPointsInput\">Puntos de apoyo\/fijaci\u00f3n<\/label><input type=\"number\" id=\"supportPointsInput\" min=\"0\" step=\"1\" placeholder=\"Ej. 4\"><\/div><div class=\"optfield\"><label for=\"objectiveInput\">Objetivo principal<\/label><select id=\"objectiveInput\"><option>Reducir peso manteniendo rigidez<\/option><option>Aumentar rigidez<\/option><option>Reducir deformaci\u00f3n<\/option><option>Reforzar zonas cr\u00edticas<\/option><\/select><\/div><div class=\"optfield\" style=\"grid-column:1\/-1\"><label for=\"loadDescInput\">Descripci\u00f3n de cargas y uso de la pieza<\/label><textarea id=\"loadDescInput\" placeholder=\"Ej. fuerza vertical sobre esta cara, pieza atornillada por 4 agujeros, uso funcional, temperatura aproximada, etc.\"><\/textarea><\/div><\/div><div class=\"optnote\">El relleno adaptativo busca reforzar las zonas que m\u00e1s trabajan y reducir material donde no aporta tanto. Puede ayudar a mejorar la relaci\u00f3n peso\/rigidez, reducir deformaciones locales y evitar una pieza maciza innecesariamente pesada.<\/div><\/div><\/div><div class=\"csec\"><span class=\"clbl\">Cantidad<\/span><div class=\"qrow\"><button class=\"qm\" id=\"qm\" type=\"button\">\u2212<\/button><input type=\"number\" id=\"qtyInput\" value=\"1\" min=\"1\" max=\"10000\"><button class=\"qp\" id=\"qp\" type=\"button\">+<\/button><span class=\"qlbl\">unidades<\/span><\/div><\/div><div class=\"csec\"><span class=\"clbl\">Destino de env\u00edo<\/span><div class=\"orow\" id=\"shiprowopts\"><\/div><\/div><div class=\"csec qfsec\" id=\"qfsec\"><form class=\"qfform\" id=\"qfform\"><div style=\"position:absolute;left:-9999px;top:auto;width:1px;height:1px;overflow:hidden;\" aria-hidden=\"true\"><label for=\"ceWebsite\">Website<\/label><input type=\"text\" id=\"ceWebsite\" name=\"website\" tabindex=\"-1\" autocomplete=\"off\"><\/div><div class=\"qfrow\"><div class=\"qffield\"><label for=\"qfe\">Email *<\/label><input type=\"email\" id=\"qfe\" placeholder=\"tu@email.com\" required><\/div><div class=\"qffield\"><label for=\"qfp\">Tel\u00e9fono *<\/label><input type=\"tel\" id=\"qfp\" placeholder=\"+49 \u2026\" required><\/div><\/div><div class=\"checkrow\"><input type=\"checkbox\" id=\"isCompany\"><span>\u00bfCompras como empresa?<\/span><\/div><div class=\"hiddenfield\" id=\"companyFields\"><div class=\"qfrow\"><div class=\"qffield\"><label for=\"companyName\">Nombre de empresa *<\/label><input type=\"text\" id=\"companyName\" placeholder=\"Ej. Cortez Engineering\"><\/div><div class=\"qffield\"><label for=\"billingCountry\">Pa\u00eds de facturaci\u00f3n *<\/label><input type=\"text\" id=\"billingCountry\" placeholder=\"Ej. Alemania, Francia, Espa\u00f1a\u2026\"><\/div><\/div><\/div><div class=\"qffield\"><label for=\"qfd\">Detalles de la pieza \/ proyecto *<\/label><textarea id=\"qfd\" placeholder=\"Ej. uso de la pieza, si es decorativa o funcional, zonas cr\u00edticas, tolerancias, acabado deseado, plazo, condiciones de uso\u2026\" required><\/textarea><\/div><div class=\"checkrow\"><input type=\"checkbox\" id=\"specificColor\"><span>Quiero un color espec\u00edfico. Si no marcas esta opci\u00f3n, usaremos un color est\u00e1ndar disponible, normalmente blanco, negro o el m\u00e1s adecuado seg\u00fan material y disponibilidad.<\/span><\/div><div class=\"qffield hiddenfield\" id=\"colorField\"><label for=\"colorText\">Color deseado<\/label><input type=\"text\" id=\"colorText\" placeholder=\"Ej. negro mate, blanco, rojo, gris oscuro, similar a RAL 9005\u2026\"><\/div><div class=\"qffield\"><label>Plano, PDF o documentaci\u00f3n adicional opcional<\/label><label for=\"qfpdf\" class=\"filepick\">Adjuntar PDF \/ imagen opcional<\/label><input type=\"file\" id=\"qfpdf\" accept=\".pdf,.png,.jpg,.jpeg\"><div class=\"filepicked\" id=\"pdfStatus\">Documento adjuntado<\/div><div class=\"filesmall\">Opcional. Puedes a\u00f1adir un plano, croquis, captura o documento t\u00e9cnico si ayuda a entender mejor la pieza.<\/div><\/div><\/form><\/div><\/div><\/div><div class=\"cright price-pending\" id=\"cright\"><div class=\"shead\"><h3>Resumen de precio<\/h3><\/div><div class=\"bdown\"><div class=\"br\"><span class=\"bl\">Material<\/span><span class=\"bv\" id=\"bmat\">\u2014<\/span><\/div><div class=\"br\"><span class=\"bl\">Calidad<\/span><span class=\"bv\" id=\"bqual\">\u2014<\/span><\/div><div class=\"br\"><span class=\"bl\">Relleno<\/span><span class=\"bv\" id=\"binfill\">\u2014<\/span><\/div><div class=\"br\" id=\"bcolorrow\" style=\"display:none\"><span class=\"bl\">Color espec\u00edfico<\/span><span class=\"bv\" id=\"bcolor\">\u2014<\/span><\/div><div class=\"br\"><span class=\"bl\" id=\"bweightlbl\">Peso estimado<\/span><span class=\"bv\" id=\"bweight\">\u2014<\/span><\/div><div class=\"br\"><span class=\"bl\">Preparaci\u00f3n incluida<\/span><span class=\"bv\" id=\"bsetup\">\u2014<\/span><\/div><div class=\"br\"><span class=\"bl\">Cantidad<\/span><span class=\"bv\" id=\"bqty\">1 ud.<\/span><\/div><div class=\"br\" id=\"borderrow\" style=\"display:none\"><span class=\"bl\">Subtotal piezas<\/span><span class=\"bv\" id=\"border\">\u2014<\/span><\/div><div class=\"br\" id=\"shiprow\" style=\"display:none\"><span class=\"bl\">Env\u00edo<\/span><span class=\"bv\" id=\"bship\">\u2014<\/span><\/div><\/div><div class=\"tblock\"><div class=\"tlbl\">Total estimado<\/div><div class=\"tamt\" id=\"tamt\">\u2014 \u20ac<\/div><div class=\"tvat\">Sin IVA \u00b7 precio orientativo<\/div><div class=\"tunit\" id=\"tunit\"><\/div><div class=\"shipPromo\" id=\"shipPromo\"><\/div><\/div><button class=\"sndbtn\" id=\"sndbtn\" type=\"button\" disabled>Enviar consulta \u2192<\/button><div class=\"uploadProgress\" id=\"uploadProgress\"><div class=\"uploadProgressTop\"><span id=\"uploadStatusText\">Subiendo archivos\u2026<\/span><span id=\"uploadPercent\">0%<\/span><\/div><div class=\"uploadBar\"><div class=\"uploadBarFill\" id=\"uploadBarFill\"><\/div><\/div><div class=\"uploadProgressNote\">No cierres esta ventana hasta que termine el env\u00edo.<\/div><\/div><\/div><\/div><\/div><div class=\"nfsec\"><div class=\"nfcard\" id=\"nfcard\"><div class=\"nfhead\"><h2>\u00bfNo tienes archivo 3D todav\u00eda?<\/h2><p>Si necesitas dise\u00f1o, redise\u00f1o, ingenier\u00eda inversa, optimizaci\u00f3n o consultor\u00eda t\u00e9cnica antes de fabricar, cu\u00e9ntanos tu idea y te orientamos sobre el siguiente paso.<\/p><\/div><div class=\"nfbody\"><form class=\"nfform\" id=\"nfform\"><div style=\"position:absolute;left:-9999px;top:auto;width:1px;height:1px;overflow:hidden;\" aria-hidden=\"true\"><label for=\"ceNoFileWebsite\">Website<\/label><input type=\"text\" id=\"ceNoFileWebsite\" name=\"website\" tabindex=\"-1\" autocomplete=\"off\"><\/div><div class=\"nfield\"><label class=\"nflbl\" for=\"nfe\">Email *<\/label><input type=\"email\" id=\"nfe\" placeholder=\"tu@email.com\" required><\/div><div class=\"nfield\"><label class=\"nflbl\" for=\"nfp\">Tel\u00e9fono *<\/label><input type=\"tel\" id=\"nfp\" placeholder=\"+49 \u2026\" required><\/div><div class=\"nfield\"><label class=\"nflbl\" for=\"nfd\">Cu\u00e9ntanos qu\u00e9 necesitas *<\/label><textarea id=\"nfd\" placeholder=\"Ej. necesito dise\u00f1ar una pieza desde cero, redise\u00f1ar una pieza existente, hacer ingenier\u00eda inversa, optimizar peso, validar resistencia\u2026\" required><\/textarea><\/div><button type=\"submit\" class=\"nfsub\">Enviar consulta<\/button><\/form><div class=\"nfinfo\"><p>\u00bfNecesitas algo m\u00e1s?<\/p><p>Adem\u00e1s de impresi\u00f3n 3D, en Cortez Engineering ofrecemos an\u00e1lisis FEM, optimizaci\u00f3n topol\u00f3gica e ingenier\u00eda inversa. Si tu pieza necesita ser redise\u00f1ada antes de imprimir, te lo indicamos.<\/p><p>Respondemos en menos de 24h laborables. Hablamos espa\u00f1ol, alem\u00e1n e ingl\u00e9s.<\/p><a class=\"nfsvcbtn\" href=\"https:\/\/cortez-engineering.com\/es\/servicios\/\">Ver servicios \u2192<\/a><\/div><\/div><\/div><\/div>\r\n\r\n  <script type=\"module\">\r\n    import * as THREE from 'https:\/\/esm.sh\/three@0.160.0';\r\n\r\n    const CE_ROOT = document.getElementById('ce-3d-calculator');\r\n    const $ = (id) => CE_ROOT.querySelector('#' + id);\r\n    const setText = (id, value) => { const el = $(id); if (el) el.textContent = value; };\r\n    const setHTML = (id, value) => { const el = $(id); if (el) el.innerHTML = value; };\r\n\r\n    const MATS={pla:{name:'PLA',sub:'Prototipos visuales y piezas simples',tag:'R\u00e1pido y econ\u00f3mico',price:.032,dens:1.24,timeFactor:1,machineRate:1.8,setupExtra:2.9},petg:{name:'PETG',sub:'Piezas funcionales con buena resistencia',tag:'Uso funcional',price:.036,dens:1.28,timeFactor:1.05,machineRate:2.2,setupExtra:3.9},abs:{name:'ASA \/ ABS',sub:'Exterior, temperatura y automoci\u00f3n',tag:'Exterior y calor',price:.048,dens:1.05,timeFactor:1.18,machineRate:3.2,setupExtra:6.9},nylon:{name:'PA6-GF \/ Nylon',sub:'Piezas t\u00e9cnicas con carga mec\u00e1nica',tag:'Ingenier\u00eda t\u00e9cnica',price:.105,dens:1.09,timeFactor:1.4,machineRate:5.5,setupExtra:14.9},pacf:{name:'PA-CF \/ PAHT-CF',sub:'Alta rigidez y baja deformaci\u00f3n',tag:'Alto rendimiento',price:.175,dens:1.1,timeFactor:1.55,machineRate:6.9,setupExtra:19.9},tpu:{name:'TPU 95A',sub:'Flexible, agarre y absorci\u00f3n de impacto',tag:'Flexible funcional',price:.06,dens:1.22,timeFactor:1.55,machineRate:4.8,setupExtra:9.9},peek:{name:'PEEK',sub:'Alta temperatura y entornos exigentes',tag:'M\u00e1ximo rendimiento',price:1,dens:1.32,timeFactor:2.2,machineRate:18,setupExtra:50},multi:{name:'Multimaterial',sub:'Combinaci\u00f3n de materiales',tag:'Revisi\u00f3n t\u00e9cnica',reviewOnly:true},continuousCarbon:{name:'Fibra de carbono continua',sub:'Impresi\u00f3n composite de alto rendimiento',tag:'Pr\u00f3ximamente',comingSoon:true},metal:{name:'Metal',sub:'Fabricaci\u00f3n aditiva met\u00e1lica',tag:'Pr\u00f3ximamente',comingSoon:true}};\r\n    const QUALS={draft:{name:'Borrador',sub:'0,30 mm',qf:.85,tf:.7},std:{name:'Est\u00e1ndar',sub:'0,20 mm',qf:1,tf:1},fine:{name:'Alta',sub:'0,10 mm',qf:1.3,tf:1.8},ultra:{name:'Ultra',sub:'0,05 mm',qf:1.8,tf:3.5}};\r\n    const INFILLS={i15:{name:'15%',sub:'ligero',ratio:.15},i30:{name:'30%',sub:'equilibrado',ratio:.3},i60:{name:'60%',sub:'alta resistencia',ratio:.6},i100:{name:'100%',sub:'m\u00e1xima densidad',ratio:1},opt:{name:'Optimizado',sub:'Relleno adaptativo',ratio:.35}};\r\n    const SHELL_FACTOR=.58,PROCESS_FACTOR=1.04,BASE_PRINT_SPEED_CM3_H=13.5,OPTIMIZED_VOLUME_FACTOR=.52,OPTIMIZED_WORK_HOURS=8,OPTIMIZED_HOURLY_RATE=60,OPTIMIZED_ENGINEERING_FEE=OPTIMIZED_WORK_HOURS*OPTIMIZED_HOURLY_RATE;\r\n    const SHIPPING={de:{name:'Alemania',price:6.90,freeFrom:75,note:'Gratis desde 75 \u20ac'},eu:{name:'Uni\u00f3n Europea',price:16.90,freeFrom:150,note:'Gratis desde 150 \u20ac'},other:{name:'Fuera UE',price:null,freeFrom:null,note:'A confirmar'}};\r\n    const CE_QUOTE_ENDPOINT='\/wp-json\/cortez\/v1\/3d-quote';\r\n    const CE_CONSULT_ENDPOINT='\/wp-json\/cortez\/v1\/technical-consultation';\r\n    const MAX_TOTAL_UPLOAD_BYTES=500*1024*1024;\r\n    const LARGE_FILE_MESSAGE='Para archivos superiores a 500 MB, env\u00edanos la solicitud y te facilitaremos un enlace de carga seguro.';\r\n    let items=[],activeIndex=-1,S=defaultItem();\r\n    let V={renderer:null,scene:null,camera:null,model:null,animation:null,rotX:.52,rotZ:.75,dist:250,drag:false,lastX:0,lastY:0};\r\n\r\n    function defaultItem(){return{vol:0,mat:'pla',qual:'std',infill:'i30',qty:1,shipping:'de',file:null,fileExt:'',reviewOnly:false,colorSpecific:false,colorFee:5,colorText:'',tri:null,dimText:'',triCount:0}}\r\n    function parseBin(buf){const v=new DataView(buf),n=v.getUint32(80,true);if(84+n*50!==buf.byteLength)return null;const t=[];let o=84;for(let i=0;i<n;i++){o+=12;const a=[v.getFloat32(o,true),v.getFloat32(o+4,true),v.getFloat32(o+8,true)];o+=12;const b=[v.getFloat32(o,true),v.getFloat32(o+4,true),v.getFloat32(o+8,true)];o+=12;const c=[v.getFloat32(o,true),v.getFloat32(o+4,true),v.getFloat32(o+8,true)];o+=14;t.push([a,b,c])}return t}\r\n    function parseAscii(txt){const t=[],vb=[];for(const line of txt.split('\\n')){const s=line.trim();if(s.startsWith('vertex ')){const p=s.split(\/\\s+\/);vb.push([+p[1],+p[2],+p[3]]);if(vb.length===3){t.push([...vb]);vb.length=0}}}return t}\r\n    function parseOBJ(txt){const vs=[],t=[];for(const line of txt.split('\\n')){const s=line.trim();if(s.startsWith('v ')){const p=s.split(\/\\s+\/);vs.push([+p[1],+p[2],+p[3]])}else if(s.startsWith('f ')){const p=s.split(\/\\s+\/).slice(1).map(x=>+x.split('\/')[0]-1);for(let i=1;i<p.length-1;i++){if(vs[p[0]]&&vs[p[i]]&&vs[p[i+1]])t.push([vs[p[0]],vs[p[i]],vs[p[i+1]]])}}}return t}\r\n    function vol(tri){let s=0;for(const[a,b,c]of tri)s+=a[0]*(b[1]*c[2]-b[2]*c[1])+a[1]*(b[2]*c[0]-b[0]*c[2])+a[2]*(b[0]*c[1]-b[1]*c[0]);return Math.abs(s)\/6}\r\n    function bnds(tri){const mn=[1e9,1e9,1e9],mx=[-1e9,-1e9,-1e9];for(const face of tri)for(const p of face)for(let i=0;i<3;i++){mn[i]=Math.min(mn[i],p[i]);mx[i]=Math.max(mx[i],p[i])}return[mx[0]-mn[0],mx[1]-mn[1],mx[2]-mn[2]]}\r\n    function calcItem(it){if(!it||!it.vol||it.reviewOnly||MATS[it.mat]?.reviewOnly||MATS[it.mat]?.comingSoon)return null;const m=MATS[it.mat],q=QUALS[it.qual],f=INFILLS[it.infill],isOpt=it.infill==='opt';const vf=isOpt?OPTIMIZED_VOLUME_FACTOR:Math.min(1,(SHELL_FACTOR+(1-SHELL_FACTOR)*f.ratio)*PROCESS_FACTOR);const ev=it.vol*vf,mc=ev*m.price,ph=(ev\/BASE_PRINT_SPEED_CM3_H)*q.tf*m.timeFactor*(isOpt?1.15:1),mach=ph*m.machineRate,setup=isOpt?(12+m.setupExtra):m.setupExtra,eng=isOpt?OPTIMIZED_ENGINEERING_FEE:0;let discount=1;if(it.qty>=1000)discount=.6;else if(it.qty>=200)discount=.72;else if(it.qty>=50)discount=.82;else if(it.qty>=10)discount=.92;const colorFee=it.colorSpecific?it.colorFee:0,min=isOpt?OPTIMIZED_ENGINEERING_FEE:8.9,total=Math.max((((mc+mach)*q.qf+setup)*it.qty*discount)+eng+colorFee,min);return{optimized:isOpt,ph,w:(ev*m.dens).toFixed(1),total:total.toFixed(2),pu:(total\/it.qty).toFixed(2),colorFee:colorFee.toFixed(2)}}\r\n    function calc(){return calcItem(S)}\r\n    function calcShipping(subtotal){const cfg=SHIPPING[S.shipping||'de'];if(!cfg||cfg.price===null)return{label:'A confirmar',price:null,remaining:null,free:false};const free=subtotal>=cfg.freeFrom&&subtotal>0,price=free?0:cfg.price,remaining=free?0:Math.max(0,cfg.freeFrom-subtotal);return{label:free?'Gratis':`${price.toFixed(2).replace('.',',')} \u20ac`,price,remaining,free}}\r\n    function calcOrder(){let subtotal=0,review=0;for(const it of items){const r=calcItem(it);if(r)subtotal+=Number(r.total);else if(it.reviewOnly||MATS[it.mat]?.reviewOnly||MATS[it.mat]?.comingSoon)review++}const ship=calcShipping(subtotal),total=ship.price===null?subtotal:subtotal+ship.price;return{subtotal,review,shipping:ship,subtotalText:subtotal.toFixed(2),total:total.toFixed(2)}}\r\n    function eu(v){return String(v).replace('.',',')+'&nbsp;\u20ac'}\r\n    function updateColorRow(r){const row=$('bcolorrow'),val=$('bcolor');if(!row||!val)return;if(S.colorSpecific){const txt=($('colorText')?.value||'').trim(),fee=(r?.colorFee||S.colorFee.toFixed(2)).replace('.',',');row.style.display='flex';val.textContent=txt?`${txt} \u00b7 +${fee} \u20ac`:`S\u00ed \u00b7 +${fee} \u20ac`}else{row.style.display='none';val.textContent='\u2014'}}\r\n    function updateShippingPromo(order){const el=$('shipPromo');if(!el)return;el.className='shipPromo';el.innerHTML='';if(!S.file){el.classList.remove('show');return}const cfg=SHIPPING[S.shipping||'de'];if(!cfg||order.shipping.price===null){el.classList.add('show','review');el.innerHTML='Env\u00edo a confirmar<span class=\"small\">Para este destino lo revisamos seg\u00fan peso, tama\u00f1o y pa\u00eds.<\/span>';return}if(order.shipping.free){el.classList.add('show','free');el.innerHTML='\u2713 Env\u00edo gratis aplicado<span class=\"small\">Se ha alcanzado el m\u00ednimo para '+cfg.name+'.<\/span>';return}const remaining=order.shipping.remaining.toFixed(2).replace('.',',');el.classList.add('show');el.innerHTML='Te faltan '+remaining+' \u20ac para env\u00edo gratis<span class=\"small\">A\u00f1ade otra pieza o aumenta la cantidad para ahorrar el env\u00edo en '+cfg.name+'.<\/span>'}\r\n    function syncActive(){if(activeIndex>=0&&items[activeIndex])items[activeIndex]={...S}}\r\n    function showOptBox(){const box=$('optbox');if(box)box.classList.toggle('show',S.infill==='opt')}\r\n    function syncControls(){CE_ROOT.querySelectorAll('.mbtn').forEach((b,i)=>b.classList.toggle('sel',Object.keys(MATS)[i]===S.mat));CE_ROOT.querySelectorAll('#qrow .obtn').forEach((b,i)=>b.classList.toggle('sel',Object.keys(QUALS)[i]===S.qual));CE_ROOT.querySelectorAll('#irow .obtn').forEach((b,i)=>b.classList.toggle('sel',Object.keys(INFILLS)[i]===S.infill));CE_ROOT.querySelectorAll('#shiprowopts .obtn').forEach((b,i)=>b.classList.toggle('sel',Object.keys(SHIPPING)[i]===S.shipping));$('qtyInput').value=S.qty;$('specificColor').checked=!!S.colorSpecific;$('colorField').classList.toggle('show',!!S.colorSpecific);$('colorText').value=S.colorText||'';showOptBox()}\r\n    function renderFilesList(){const list=$('fileslist');if(!list)return;list.innerHTML='';if(!items.length)return;const title=document.createElement('div');title.className='loadedTitle';title.textContent=items.length===1?'1 archivo cargado':`${items.length} archivos cargados`;list.appendChild(title);if(items.length>1){const note=document.createElement('div');note.className='multiNote';note.textContent='Cada archivo se suma al pedido y puede tener su propio material, relleno, cantidad y color. Selecciona una pieza para editarla.';list.appendChild(note)}let html='';items.forEach((it,idx)=>{const r=calcItem(it),needsReview=it.reviewOnly||MATS[it.mat]?.reviewOnly||MATS[it.mat]?.comingSoon,price=needsReview?'Revisi\u00f3n':(r?eu(r.total).replace('&nbsp;',' '):'\u2014'),active=idx===activeIndex?' active':'',plural=it.qty>1?'s':'';html+=`<div class=\"fileitem${active}\" data-idx=\"${idx}\"><div class=\"filebadge\">${idx+1}<\/div><div><div class=\"fn\">Archivo ${idx+1} cargado \u00b7 ${it.file.name}<\/div><div class=\"fm\">${MATS[it.mat].name} \u00b7 ${INFILLS[it.infill].name} \u00b7 ${it.qty} ud${plural}<\/div><\/div><div class=\"fp\">${price}<\/div><\/div>`});list.insertAdjacentHTML('beforeend',html);list.querySelectorAll('.fileitem').forEach(row=>row.addEventListener('click',()=>selectItem(Number(row.dataset.idx))))}\r\n    function upd(){if(S.file)syncActive();CE_ROOT.classList.toggle('no-file',!S.file);const r=calc(),cr=$('cright'),order=calcOrder();renderFilesList();updateColorRow(r);updateShippingPromo(order);const orderRow=$('borderrow');if(orderRow){orderRow.style.display=S.file?'flex':'none';setText('border',`${items.length} archivo(s) \u00b7 ${order.subtotalText.replace('.',',')} \u20ac`)}const shipRow=$('shiprow');if(shipRow){shipRow.style.display=S.file?'flex':'none';setText('bship',order.shipping.label)}if(!S.file){cr.classList.add('price-pending');setText('tamt','\u2014 \u20ac');$('sndbtn').disabled=true;return}setText('bmat',MATS[S.mat].name);setText('bqual',`${QUALS[S.qual].name} \u00b7 ${QUALS[S.qual].sub}`);setText('binfill',S.infill==='opt'?'Optimizado \u00b7 FEM':INFILLS[S.infill].name);setText('bqty',S.qty+' ud'+(S.qty>1?'s':'')+'.');$('sndbtn').disabled=false;if(!r){cr.classList.add('price-pending');setText('bweight','Revisi\u00f3n');setText('bsetup',(MATS[S.mat]?.reviewOnly||MATS[S.mat]?.comingSoon||S.reviewOnly)?'Revisi\u00f3n t\u00e9cnica':'Incluida');if(items.length>1&&order.subtotal>0){setHTML('tamt',eu(order.total));setText('tunit','Pieza activa: revisi\u00f3n t\u00e9cnica')}else{setText('tamt','Revisi\u00f3n');setText('tunit',(MATS[S.mat]?.reviewOnly||MATS[S.mat]?.comingSoon)?'Este material requiere revisi\u00f3n t\u00e9cnica.':'')}return}cr.classList.remove('price-pending');setText('binfill',r.optimized?'Optimizado \u00b7 FEM':INFILLS[S.infill].name);setText('bweightlbl',r.optimized?'Peso optimizado estimado':'Peso estimado');setText('bweight',r.w.replace('.',',')+' g');setText('bsetup',r.optimized?'Optimizaci\u00f3n FEM + PDF':'Incluida');setHTML('tamt',eu(order.total));const unitText=items.length>1?`Subtotal piezas: ${order.subtotalText.replace('.',',')} \u20ac \u00b7 Pieza activa: ${r.total.replace('.',',')} \u20ac`:(S.qty>1?`${r.pu.replace('.',',')} \u20ac\/ud. \u00b7 descuento por volumen aplicado`:(S.colorSpecific?`Color espec\u00edfico: +${r.colorFee.replace('.',',')} \u20ac`:''));setText('tunit',unitText)}\r\n    function buildMats(){const g=$('mgrid');g.innerHTML='';Object.entries(MATS).forEach(([k,m])=>{const b=document.createElement('button');b.type='button';b.className='mbtn'+(k===S.mat?' sel':'')+(m.comingSoon?' disabled':'');b.innerHTML=`<div class=\"mn\">${m.name}<\/div><div class=\"ms\">${m.sub}<\/div><div class=\"mp\">${m.tag}<\/div>`;b.onclick=()=>{if(m.comingSoon)return;S.mat=k;syncActive();syncControls();upd()};g.appendChild(b)})}\r\n    function buildQuals(){const r=$('qrow');r.innerHTML='';Object.entries(QUALS).forEach(([k,q])=>{const b=document.createElement('button');b.type='button';b.className='obtn'+(k===S.qual?' sel':'');b.innerHTML=`<div class=\"on\">${q.name}<\/div><div class=\"os\">${q.sub}<\/div>`;b.onclick=()=>{S.qual=k;syncActive();syncControls();upd()};r.appendChild(b)})}\r\n    function buildInfills(){const r=$('irow');r.innerHTML='';Object.entries(INFILLS).forEach(([k,f])=>{const b=document.createElement('button');b.type='button';b.className='obtn'+(k===S.infill?' sel':'');b.innerHTML=`<div class=\"on\">${f.name}<\/div><div class=\"os\">${f.sub}<\/div>`;b.onclick=()=>{S.infill=k;syncActive();syncControls();upd()};r.appendChild(b)})}\r\n    function buildShipping(){const r=$('shiprowopts');if(!r)return;r.innerHTML='';Object.entries(SHIPPING).forEach(([k,s])=>{const b=document.createElement('button');b.type='button';b.className='obtn'+(k===S.shipping?' sel':'');b.innerHTML=`<div class=\"on\">${s.name}<\/div><div class=\"os\">${s.note}<\/div>`;b.onclick=()=>{S.shipping=k;syncActive();syncControls();upd()};r.appendChild(b)})}\r\n    function clearViewer(){if(V.animation)cancelAnimationFrame(V.animation);if(V.renderer){V.renderer.dispose();V.renderer.domElement.remove()}V={renderer:null,scene:null,camera:null,model:null,animation:null,rotX:.52,rotZ:.75,dist:250,drag:false,lastX:0,lastY:0};$('viewer')?.classList.remove('show');if($('vmsg')){$('vmsg').style.display='flex';$('vmsg').innerHTML='<div><strong>Vista previa del modelo<\/strong>Sube un STL u OBJ para interactuar con la pieza.<\/div>'}}\r\n    function showViewerMessage(title,text){clearViewer();$('viewer')?.classList.add('show');setText('vhint','Vista previa no disponible');if($('vmsg')){$('vmsg').style.display='flex';$('vmsg').innerHTML=`<div><strong>${title}<\/strong>${text}<\/div>`}}\r\n    function renderPreview(tri){const box=$('vbox'),viewer=$('viewer'),msg=$('vmsg');if(!box||!tri?.length)return;clearViewer();viewer.classList.add('show');if(msg)msg.style.display='none';setText('vhint','Arrastra para girar \u00b7 rueda para zoom');const w=box.clientWidth||700,h=box.clientHeight||360,scene=new THREE.Scene();scene.background=new THREE.Color(0xf7f7f7);const camera=new THREE.PerspectiveCamera(45,w\/h,.1,100000),renderer=new THREE.WebGLRenderer({antialias:true});renderer.setPixelRatio(Math.min(window.devicePixelRatio||1,2));renderer.setSize(w,h);box.appendChild(renderer.domElement);const verts=[];for(const face of tri)for(const p of face)verts.push(p[0],p[1],p[2]);const geo=new THREE.BufferGeometry();geo.setAttribute('position',new THREE.Float32BufferAttribute(verts,3));geo.computeVertexNormals();geo.computeBoundingBox();const mat=new THREE.MeshPhysicalMaterial({color:0x18f07e,roughness:.34,metalness:.06,clearcoat:.30,clearcoatRoughness:.20,side:THREE.DoubleSide});const mesh=new THREE.Mesh(geo,mat),bb=geo.boundingBox,center=new THREE.Vector3();bb.getCenter(center);mesh.position.sub(center);scene.add(mesh);const size=new THREE.Vector3();bb.getSize(size);const maxDim=Math.max(size.x,size.y,size.z)||100;const grid=new THREE.GridHelper(Math.max(120,Math.ceil(maxDim*1.6\/10)*10),20,0xb8bdc2,0xd9dcdf);grid.rotation.x=Math.PI\/2;grid.position.z=-(size.z\/2);scene.add(grid);scene.add(new THREE.AmbientLight(0xffffff,.78));const d1=new THREE.DirectionalLight(0xffffff,1);d1.position.set(maxDim,maxDim,maxDim*1.6);scene.add(d1);const d2=new THREE.DirectionalLight(0xffffff,.38);d2.position.set(-maxDim,-maxDim,maxDim);scene.add(d2);const d3=new THREE.DirectionalLight(0xffffff,.22);d3.position.set(0,maxDim*1.5,maxDim*.6);scene.add(d3);V={renderer,scene,camera,model:mesh,animation:null,rotX:.52,rotZ:.78,dist:maxDim*2.35,drag:false,lastX:0,lastY:0};function placeCamera(){const x=V.dist*Math.cos(V.rotX)*Math.cos(V.rotZ),y=V.dist*Math.cos(V.rotX)*Math.sin(V.rotZ),z=V.dist*Math.sin(V.rotX);camera.position.set(x,y,z);camera.up.set(0,0,1);camera.lookAt(0,0,size.z*.03)}placeCamera();renderer.domElement.onpointerdown=e=>{V.drag=true;V.lastX=e.clientX;V.lastY=e.clientY;renderer.domElement.setPointerCapture(e.pointerId)};renderer.domElement.onpointermove=e=>{if(!V.drag)return;const dx=e.clientX-V.lastX,dy=e.clientY-V.lastY;V.lastX=e.clientX;V.lastY=e.clientY;V.rotZ-=dx*.008;V.rotX=Math.max(-1.45,Math.min(1.45,V.rotX+dy*.008));placeCamera()};renderer.domElement.onpointerup=()=>{V.drag=false};renderer.domElement.onwheel=e=>{e.preventDefault();V.dist=Math.max(maxDim*.6,Math.min(maxDim*8,V.dist*(1+e.deltaY*.001)));placeCamera()};function resize(){const nw=box.clientWidth||700,nh=box.clientHeight||360;camera.aspect=nw\/nh;camera.updateProjectionMatrix();renderer.setSize(nw,nh)}window.addEventListener('resize',resize,{passive:true});function animate(){V.animation=requestAnimationFrame(animate);renderer.render(scene,camera)}animate()}\r\n    function makeItem(file,ext){return{...defaultItem(),mat:S.mat||'pla',qual:S.qual||'std',infill:S.infill||'i30',file,fileExt:ext,fileKey:getFileKey(file)}}\r\n    function getFileKey(file){return`${file.name}|${file.size}|${file.lastModified||0}`}\r\n    function selectItem(idx){if(idx<0||idx>=items.length)return;syncActive();activeIndex=idx;S=items[idx];setText('fcname',S.file.name);setText('ssz',formatSize(S.file.size));setText('fstatus',S.reviewOnly?'Archivo para revisi\u00f3n':'Archivo cargado');if(S.reviewOnly){setText('svol','Revisi\u00f3n');setText('sdim','Manual');setText('stri','\u2014');showViewerMessage('Vista previa no disponible para este formato.','STEP y 3MF se aceptan para revisi\u00f3n t\u00e9cnica manual. El archivo se tendr\u00e1 en cuenta al confirmar el presupuesto final.')}else{setText('svol',S.vol.toFixed(2).replace('.',',')+' cm\u00b3');setText('sdim',S.dimText||'\u2014');setText('stri',S.triCount?S.triCount.toLocaleString('es-ES'):'\u2014');if(S.tri)renderPreview(S.tri)}syncControls();upd()}\r\n    async function processFile(file){const ext=file.name.split('.').pop().toLowerCase(),item=makeItem(file,ext);if(['step','stp','3mf'].includes(ext)){item.reviewOnly=true;return item}let tri=null;if(ext==='stl'){const buf=await file.arrayBuffer();tri=parseBin(buf);if(!tri)tri=parseAscii(new TextDecoder().decode(buf))}else if(ext==='obj'){tri=parseOBJ(await file.text())}else throw new Error('Sube un archivo STL, OBJ, STEP o 3MF.');if(!tri?.length)throw new Error('No se pudieron leer tri\u00e1ngulos del archivo.');item.tri=tri;item.vol=vol(tri)\/1000;const sz=bnds(tri);item.dimText=`${sz[0].toFixed(0)}\u00d7${sz[1].toFixed(0)}\u00d7${sz[2].toFixed(0)}`;item.triCount=tri.length;return item}\r\n    async function handleFiles(fileList,{replace=false}={}){const incoming=Array.from(fileList||[]);if(!incoming.length)return;const incomingTotal=incoming.reduce((sum,file)=>sum+file.size,0);const currentTotal=replace?0:items.reduce((sum,it)=>sum+(it.file?.size||0),0);if(currentTotal+incomingTotal>MAX_TOTAL_UPLOAD_BYTES){alert(LARGE_FILE_MESSAGE);return;}const existingKeys=replace?new Set():new Set(items.map(it=>it.fileKey||getFileKey(it.file)));const seenInThisBatch=new Set();const files=incoming.filter(file=>{const key=getFileKey(file);if(existingKeys.has(key)||seenInThisBatch.has(key))return false;seenInThisBatch.add(key);return true});if(!files.length){alert('Ese archivo ya est\u00e1 cargado. Si necesitas m\u00e1s unidades, aumenta la cantidad de esa pieza.');return}const dz=$('dz');dz.classList.add('loading');setText('dzstatus',files.length>1?'Procesando archivos\u2026':'Procesando archivo\u2026');try{if(replace){items=[];activeIndex=-1;S=defaultItem()}else syncActive();const firstNewIndex=items.length,newItems=[];for(const file of files)newItems.push(await processFile(file));items=items.concat(newItems);activeIndex=firstNewIndex;S=items[activeIndex];$('dz').style.display='none';$('fcard').classList.add('show');$('cpanel').classList.add('show');$('qfsec').classList.add('show');dz.classList.remove('loading');selectItem(activeIndex);renderFilesList();upd()}catch(e){dz.classList.remove('loading');alert('Error: '+e.message)}}\r\n    function formatSize(s){return s<1048576?(s\/1024).toFixed(0)+' KB':(s\/1048576).toFixed(2).replace('.',',')+' MB'}\r\n    function resetFile(){items=[];activeIndex=-1;S=defaultItem();$('fi').value='';$('dz').style.display='';$('dz').classList.remove('loading');$('fcard').classList.remove('show');$('fileslist').innerHTML='';clearViewer();$('cpanel').classList.remove('show');$('qfsec').classList.remove('show');['bmat','bqual','binfill','bweight','bsetup'].forEach(id=>setText(id,'\u2014'));setText('bweightlbl','Peso estimado');setText('bqty','1 ud.');setText('tamt','\u2014 \u20ac');setText('tunit','');$('bcolorrow').style.display='none';const promo=$('shipPromo');if(promo){promo.className='shipPromo';promo.innerHTML=''}syncControls();upd()}\r\n    function deleteActive(){if(activeIndex<0)return;items.splice(activeIndex,1);if(!items.length){resetFile();return}activeIndex=Math.min(activeIndex,items.length-1);S=items[activeIndex];selectItem(activeIndex)}\r\n    function openFilePicker(mode){const input=document.createElement('input');input.type='file';input.accept='.stl,.obj,.step,.stp,.3mf';input.multiple=true;input.style.display='none';CE_ROOT.appendChild(input);input.addEventListener('change',()=>{const selected=input.files;if(selected&&selected[0])handleFiles(selected,{replace:mode==='replace'});input.remove()},{once:true});input.click()}\r\n    function bindEvents(){const dz=$('dz'),fi=$('fi');$('brbtn').onclick=e=>{e.preventDefault();e.stopPropagation();openFilePicker('replace')};dz.onclick=e=>{if(e.target.closest('button'))return;openFilePicker('replace')};fi.onchange=e=>{if(e.target.files[0])handleFiles(e.target.files,{replace:true});fi.value=''};dz.addEventListener('dragover',e=>{e.preventDefault();dz.classList.add('over')});dz.addEventListener('dragleave',()=>dz.classList.remove('over'));dz.addEventListener('drop',e=>{e.preventDefault();dz.classList.remove('over');if(e.dataTransfer.files[0])handleFiles(e.dataTransfer.files,{replace:!items.length})});$('fadd').onclick=e=>{e.preventDefault();e.stopPropagation();openFilePicker('add')};$('fdel').onclick=deleteActive;$('qm').onclick=()=>{S.qty=Math.max(1,S.qty-1);$('qtyInput').value=S.qty;syncActive();upd()};$('qp').onclick=()=>{S.qty=Math.min(10000,S.qty+1);$('qtyInput').value=S.qty;syncActive();upd()};$('qtyInput').oninput=e=>{S.qty=Math.max(1,Math.min(10000,+e.target.value||1));e.target.value=S.qty;syncActive();upd()};$('specificColor').onchange=e=>{S.colorSpecific=e.target.checked;$('colorField').classList.toggle('show',S.colorSpecific);syncActive();upd()};$('isCompany').onchange=e=>{const checked=e.target.checked;$('companyFields').classList.toggle('show',checked);$('companyName').required=checked;$('billingCountry').required=checked;if(!checked){$('companyName').value='';$('billingCountry').value=''}};$('colorText').oninput=()=>{S.colorText=$('colorText').value;syncActive();upd()};$('qfpdf').onchange=e=>{const f=e.target.files[0],st=$('pdfStatus');if(f){st.textContent='Documento adjuntado: '+f.name;st.classList.add('show')}else st.classList.remove('show')};$('sndbtn').onclick=()=>{syncActive();if(!items.length)return;$('qfsec').classList.add('show');const form=$('qfform');if(!$('qfe').value||!$('qfp').value||!$('qfd').value){$('qfd').focus({preventScroll:false});form.reportValidity();return}form.requestSubmit()};$('qfform').onsubmit=submitQuoteRequest;$('nfform').onsubmit=submitNoFileConsultation}\r\n    function buildSubmissionSummary(){const order=calcOrder();const lines=[];lines.push('RESUMEN DE LA CALCULADORA');lines.push('Total estimado: '+order.total.replace('.',',')+' \u20ac sin IVA');lines.push('Subtotal piezas: '+order.subtotalText.replace('.',',')+' \u20ac');lines.push('Env\u00edo: '+order.shipping.label);lines.push('Destino de env\u00edo: '+(SHIPPING[S.shipping||'de']?.name||'\u2014'));lines.push('');items.forEach((it,idx)=>{const r=calcItem(it);lines.push('Archivo '+(idx+1)+': '+it.file.name);lines.push('- Formato: '+(it.fileExt||'\u2014').toUpperCase());lines.push('- Material: '+MATS[it.mat].name);lines.push('- Calidad: '+QUALS[it.qual].name+' \u00b7 '+QUALS[it.qual].sub);lines.push('- Relleno: '+(it.infill==='opt'?'Optimizado \u00b7 FEM':INFILLS[it.infill].name));lines.push('- Cantidad: '+it.qty);lines.push('- Color espec\u00edfico: '+(it.colorSpecific?(it.colorText||'S\u00ed, pendiente de especificar'):'No'));lines.push('- Volumen: '+((it.reviewOnly||MATS[it.mat]?.reviewOnly||MATS[it.mat]?.comingSoon)?'Revisi\u00f3n t\u00e9cnica':it.vol.toFixed(2).replace('.',',')+' cm\u00b3'));lines.push('- Dimensiones: '+(it.dimText||'\u2014'));lines.push('- Peso estimado: '+(r?r.w.replace('.',',')+' g':'Revisi\u00f3n t\u00e9cnica'));lines.push('- Precio orientativo pieza: '+(r?r.total.replace('.',',')+' \u20ac':'Revisi\u00f3n t\u00e9cnica'));lines.push('')});if($('isCompany').checked){lines.push('DATOS EMPRESA');lines.push('Nombre de empresa: '+$('companyName').value);lines.push('Pa\u00eds de facturaci\u00f3n: '+$('billingCountry').value);lines.push('')}return lines.join('\\n')}\r\n    async function submitQuoteRequest(e){e.preventDefault();syncActive();const form=$('qfform');if(!form.reportValidity())return;if(!items.length){alert('Primero sube al menos un archivo 3D.');return}const uploadTotal=items.reduce((sum,it)=>sum+(it.file?.size||0),0)+(($('qfpdf').files[0]?.size)||0);if(uploadTotal>MAX_TOTAL_UPLOAD_BYTES){alert(LARGE_FILE_MESSAGE);return}const btn=$('sndbtn'),oldText=btn.textContent,progress=$('uploadProgress'),bar=$('uploadBarFill'),pct=$('uploadPercent'),status=$('uploadStatusText');btn.disabled=true;btn.textContent='Subiendo archivos\u2026';if(progress)progress.classList.add('show');if(bar)bar.style.width='0%';if(pct)pct.textContent='0%';if(status)status.textContent='Preparando env\u00edo\u2026';try{const fd=new FormData();fd.append('email',$('qfe').value.trim());fd.append('phone',$('qfp').value.trim());fd.append('details',$('qfd').value.trim());fd.append('is_company',$('isCompany').checked?'yes':'no');fd.append('company_name',$('companyName').value.trim());fd.append('billing_country',$('billingCountry').value.trim());fd.append('summary',buildSubmissionSummary());fd.append('website',$('ceWebsite') ? $('ceWebsite').value : '');items.forEach(it=>fd.append('files[]',it.file,it.file.name));const pdf=$('qfpdf').files[0];if(pdf)fd.append('attachment',pdf,pdf.name);const data=await sendQuoteWithProgress(fd,(percent)=>{if(bar)bar.style.width=percent+'%';if(pct)pct.textContent=percent+'%';if(status)status.textContent=percent<100?'Subiendo archivos\u2026':'Procesando solicitud\u2026'});if(!data?.success)throw new Error(data?.message||'No se pudo enviar la solicitud.');if(bar)bar.style.width='100%';if(pct)pct.textContent='100%';if(status)status.textContent='Solicitud enviada correctamente';alert('Solicitud enviada correctamente. Te responderemos lo antes posible.');btn.textContent='Solicitud enviada \u2713'}catch(err){alert(err.message||'No se pudo enviar la solicitud. Int\u00e9ntalo de nuevo o cont\u00e1ctanos por email.');btn.disabled=false;btn.textContent=oldText;if(status)status.textContent='No se pudo enviar la solicitud'}}\r\n    function sendQuoteWithProgress(formData,onProgress){return new Promise((resolve,reject)=>{const xhr=new XMLHttpRequest();xhr.open('POST',CE_QUOTE_ENDPOINT,true);xhr.upload.onprogress=(event)=>{if(event.lengthComputable){const percent=Math.max(1,Math.min(99,Math.round((event.loaded\/event.total)*100)));onProgress(percent)}};xhr.onload=()=>{let data=null;try{data=JSON.parse(xhr.responseText)}catch(_e){}if(xhr.status>=200&&xhr.status<300){onProgress(100);resolve(data)}else{reject(new Error(data?.message||'No se pudo enviar la solicitud.'))}};xhr.onerror=()=>reject(new Error('Error de conexi\u00f3n al enviar la solicitud.'));xhr.send(formData)})}\r\n    async function submitNoFileConsultation(e){e.preventDefault();const form=$('nfform');if(!form.reportValidity())return;const btn=form.querySelector('.nfsub'),oldText=btn.textContent;btn.disabled=true;btn.textContent='Enviando consulta\u2026';try{const fd=new FormData();fd.append('email',$('nfe').value.trim());fd.append('phone',$('nfp').value.trim());fd.append('details',$('nfd').value.trim());fd.append('website',$('ceNoFileWebsite') ? $('ceNoFileWebsite').value : '');const res=await fetch(CE_CONSULT_ENDPOINT,{method:'POST',body:fd});let data=null;try{data=await res.json()}catch(_e){}if(!res.ok||!data?.success)throw new Error(data?.message||'No se pudo enviar la consulta.');alert('Consulta enviada correctamente. Te responderemos lo antes posible.');btn.textContent='Consulta enviada \u2713';form.reset()}catch(err){alert(err.message||'No se pudo enviar la consulta. Int\u00e9ntalo de nuevo o cont\u00e1ctanos por email.');btn.disabled=false;btn.textContent=oldText}}\r\n    function prepareElementorSticky(){let el=CE_ROOT.parentElement,steps=0;while(el&&steps<8){const tag=(el.tagName||'').toLowerCase();if(tag==='body'||tag==='html')break;el.style.overflow='visible';el.style.overflowX='visible';el.style.overflowY='visible';steps++;el=el.parentElement}}\r\n    function runTests(){console.assert($('fadd'),'TEST: bot\u00f3n a\u00f1adir archivo existe');console.assert($('fileslist'),'TEST: lista multiarchivo existe');console.assert($('borderrow'),'TEST: fila subtotal pedido existe');console.assert($('shiprow'),'TEST: fila de env\u00edo existe');console.assert($('shiprowopts'),'TEST: selector de env\u00edo existe');console.assert($('shipPromo'),'TEST: promo visual de env\u00edo existe');console.assert(SHIPPING.de.freeFrom===75,'TEST: env\u00edo gratis Alemania desde 75 \u20ac');console.assert(SHIPPING.eu.freeFrom===150,'TEST: env\u00edo gratis UE desde 150 \u20ac');console.assert(OPTIMIZED_ENGINEERING_FEE===480,'TEST: precio base optimizado = 8h x 60\u20ac');console.assert($('bmat'),'TEST: bmat existe');console.assert($('isCompany'),'TEST: checkbox empresa existe');console.assert($('companyFields'),'TEST: campos empresa existen');console.assert($('viewer'),'TEST: visor 3D existe');console.assert(typeof THREE.Scene==='function','TEST: THREE cargado desde URL absoluta');console.assert(buildSubmissionSummary().includes('RESUMEN DE LA CALCULADORA'),'TEST: resumen de env\u00edo se genera sin token inv\u00e1lido');console.assert($('ceWebsite'),'TEST: honeypot anti-bot existe');console.assert($('ceNoFileWebsite'),'TEST: honeypot anti-bot sin archivo existe');console.assert(typeof submitNoFileConsultation==='function','TEST: formulario sin archivo conectado');console.assert(MATS.multi.reviewOnly===true,'TEST: Multimaterial requiere revisi\u00f3n t\u00e9cnica');console.assert(MATS.continuousCarbon.comingSoon===true,'TEST: fibra de carbono continua est\u00e1 pr\u00f3ximamente');console.assert(MATS.metal.comingSoon===true,'TEST: metal est\u00e1 pr\u00f3ximamente')}\r\n    prepareElementorSticky();buildMats();buildQuals();buildInfills();buildShipping();showOptBox();bindEvents();upd();runTests();\r\n  <\/script>\r\n<\/div>\r\n\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<\/div>\n\t\t<\/section>\n\t\t\t\t<\/div>\n\t\t","protected":false},"excerpt":{"rendered":"<p>Calculadora de preciode impresi\u00f3n 3D A\u00f1ade tu archivo y obt\u00e9n una estimaci\u00f3n orientativa al instante. Si te encaja, puedes enviarnos los datos para revisar el presupuesto final. Arrastra tus archivos 3D aqu\u00ed o haz clic para buscar en tu equipo Seleccionar&#8230;<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"elementor_header_footer","meta":{"om_disable_all_campaigns":false,"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"footnotes":""},"class_list":["post-24278","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/cortez-engineering.com\/es\/wp-json\/wp\/v2\/pages\/24278","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/cortez-engineering.com\/es\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/cortez-engineering.com\/es\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/cortez-engineering.com\/es\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/cortez-engineering.com\/es\/wp-json\/wp\/v2\/comments?post=24278"}],"version-history":[{"count":97,"href":"https:\/\/cortez-engineering.com\/es\/wp-json\/wp\/v2\/pages\/24278\/revisions"}],"predecessor-version":[{"id":24429,"href":"https:\/\/cortez-engineering.com\/es\/wp-json\/wp\/v2\/pages\/24278\/revisions\/24429"}],"wp:attachment":[{"href":"https:\/\/cortez-engineering.com\/es\/wp-json\/wp\/v2\/media?parent=24278"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}