{"id":24997,"date":"2026-10-28T02:41:18","date_gmt":"2026-10-28T02:41:18","guid":{"rendered":"https:\/\/www.mechstream.com\/?p=24997"},"modified":"2026-10-28T02:45:32","modified_gmt":"2026-10-28T02:45:32","slug":"material-weight-change-calculator-temperature-corrosion","status":"publish","type":"post","link":"https:\/\/www.mechstream.com\/fr\/material-weight-change-calculator-temperature-corrosion\/","title":{"rendered":"Material Weight Change Calculator (Temperature &amp; Corrosion)"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">The <strong>Material Weight Change Calculator (Temperature &amp; Corrosion)<\/strong> is a practical online tool designed to help engineers, manufacturers, and material specialists evaluate material mass loss, thermal expansion, and density changes. By entering material density, temperature variations, corrosion rate, exposed surface area, and exposure time, users can estimate corrosion-related weight loss, remaining material mass, and temperature-dependent volume changes. This free calculator supports accurate engineering assessments, material performance analysis, and industrial maintenance planning. It is ideal for metal fabrication, corrosion testing, mechanical engineering, and industrial manufacturing applications.<\/p>\n\n\n\n<div id=\"mwcc-calculator\" class=\"mwcc-root\" data-mwcc-widget=\"material-weight-change\">\n<style>\n#mwcc-calculator,#mwcc-calculator *,#mwcc-calculator *::before,#mwcc-calculator *::after{box-sizing:border-box}\n#mwcc-calculator{\n  --mwcc-bg:#ffffff;--mwcc-card:#ffffff;--mwcc-navy:#132238;--mwcc-text:#2a3442;--mwcc-muted:#566273;--mwcc-soft:#6e7a8a;\n  --mwcc-line:#d3dae3;--mwcc-line-soft:#e4e8ee;--mwcc-panel:#f4f6f9;--mwcc-input:#f7f9fb;--mwcc-accent:#1a4d8f;--mwcc-accent-dark:#123a6d;--mwcc-accent-soft:#e8eff8;\n  --mwcc-err:#b42318;--mwcc-err-soft:#fdecea;--mwcc-warn:#7a4a00;--mwcc-warn-soft:#fff5e1;--mwcc-ok:#14613c;--mwcc-ok-soft:#e7f5ee;\n  --mwcc-c-init:#1a4d8f;--mwcc-c-loss:#c2410c;--mwcc-c-rem:#0f766e;\n  display:block;width:100%;max-width:1220px;margin:24px auto;padding:28px;background:var(--mwcc-bg);color:var(--mwcc-text);\n  border:1px solid var(--mwcc-line-soft);border-radius:20px;font-family:-apple-system,BlinkMacSystemFont,\"Segoe UI\",Roboto,\"Helvetica Neue\",Arial,sans-serif;\n  font-size:16px;line-height:1.55;font-weight:400;letter-spacing:normal;text-transform:none;text-indent:0;word-spacing:normal;-webkit-font-smoothing:antialiased;text-align:left;position:relative\n}\n#mwcc-calculator .mwcc-wrap{container-type:inline-size;container-name:mwcc;width:100%}\n#mwcc-calculator h1,#mwcc-calculator h2,#mwcc-calculator h3,#mwcc-calculator h4,#mwcc-calculator p,#mwcc-calculator ul,#mwcc-calculator ol,#mwcc-calculator li,#mwcc-calculator dl,#mwcc-calculator dt,#mwcc-calculator dd,#mwcc-calculator details,#mwcc-calculator summary,#mwcc-calculator fieldset,#mwcc-calculator legend,#mwcc-calculator label,#mwcc-calculator header,#mwcc-calculator section,#mwcc-calculator article,#mwcc-calculator aside,#mwcc-calculator footer,#mwcc-calculator figure,#mwcc-calculator figcaption,#mwcc-calculator table,#mwcc-calculator thead,#mwcc-calculator tbody,#mwcc-calculator tr,#mwcc-calculator th,#mwcc-calculator td,#mwcc-calculator code,#mwcc-calculator strong,#mwcc-calculator em,#mwcc-calculator b,#mwcc-calculator small{\n  margin:0;padding:0;border:0;background:none;color:inherit;font-family:inherit;font-size:inherit;font-weight:inherit;font-style:normal;line-height:inherit;text-indent:0;text-transform:none;letter-spacing:normal;text-shadow:none;box-shadow:none;float:none;width:auto;max-width:none;min-width:0\n}\n#mwcc-calculator strong,#mwcc-calculator b{font-weight:700}\n#mwcc-calculator em{font-style:italic}\n#mwcc-calculator ul,#mwcc-calculator ol{list-style:none}\n#mwcc-calculator a{color:var(--mwcc-accent);text-decoration:underline}\n#mwcc-calculator sub,#mwcc-calculator sup{font-size:.72em;line-height:0;position:relative;vertical-align:baseline}\n#mwcc-calculator sub{bottom:-.25em}\n#mwcc-calculator sup{top:-.5em}\n#mwcc-calculator [hidden]{display:none!important}\n#mwcc-calculator svg{display:inline-block;max-width:none;height:auto;vertical-align:middle;overflow:visible}\n#mwcc-calculator .mwcc-sr{position:absolute!important;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}\n\/* ---------- header ---------- *\/\n#mwcc-calculator .mwcc-head{padding:4px 2px 18px;border-bottom:1px solid var(--mwcc-line-soft);margin-bottom:18px}\n#mwcc-calculator .mwcc-kicker{display:inline-flex;align-items:center;gap:7px;font-size:12.5px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:var(--mwcc-accent);margin-bottom:6px}\n#mwcc-calculator .mwcc-kicker svg{width:16px;height:16px}\n#mwcc-calculator .mwcc-h1{font-size:clamp(24px,3.4vw,32px);font-weight:750;line-height:1.2;color:var(--mwcc-navy);letter-spacing:-.01em}\n#mwcc-calculator .mwcc-sub{margin-top:8px;color:var(--mwcc-muted);font-size:16px;max-width:820px}\n#mwcc-calculator .mwcc-chips{display:flex;flex-wrap:wrap;gap:6px;margin-top:12px}\n#mwcc-calculator .mwcc-chip{font-size:12.5px;font-weight:600;color:var(--mwcc-muted);background:var(--mwcc-panel);border:1px solid var(--mwcc-line-soft);border-radius:999px;padding:2px 10px}\n\/* ---------- mode tabs ---------- *\/\n#mwcc-calculator .mwcc-modes{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:8px;border:0;margin:0 0 18px;padding:0;position:relative}\n#mwcc-calculator .mwcc-modes legend{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}\n#mwcc-calculator .mwcc-modes input{position:absolute;opacity:0;width:1px;height:1px;margin:0;pointer-events:none}\n#mwcc-calculator .mwcc-modes label{display:flex;align-items:center;gap:10px;min-height:60px;padding:9px 12px;border:1px solid var(--mwcc-line);border-radius:12px;cursor:pointer;background:#fff;transition:border-color .15s,background .15s,box-shadow .15s}\n#mwcc-calculator .mwcc-modes label .mwcc-mi{flex:0 0 30px;width:30px;height:30px;border-radius:8px;display:inline-flex;align-items:center;justify-content:center;background:var(--mwcc-panel);color:var(--mwcc-accent)}\n#mwcc-calculator .mwcc-modes label .mwcc-mi svg{width:18px;height:18px}\n#mwcc-calculator .mwcc-modes label span.mwcc-mt{display:flex;flex-direction:column;min-width:0}\n#mwcc-calculator .mwcc-modes label b{font-weight:650;font-size:14.4px;color:var(--mwcc-navy);line-height:1.25}\n#mwcc-calculator .mwcc-modes label small{font-size:12.3px;color:var(--mwcc-soft);line-height:1.3}\n#mwcc-calculator .mwcc-modes input:checked+label{border-color:var(--mwcc-accent);background:var(--mwcc-accent-soft);box-shadow:inset 0 0 0 1px var(--mwcc-accent)}\n#mwcc-calculator .mwcc-modes input:checked+label .mwcc-mi{background:var(--mwcc-accent);color:#fff}\n#mwcc-calculator .mwcc-modes input:focus-visible+label{outline:3px solid rgba(26,77,143,.4);outline-offset:1px}\n\/* ---------- layout and cards ---------- *\/\n#mwcc-calculator .mwcc-layout{display:grid;grid-template-columns:minmax(0,1fr);gap:18px;align-items:start}\n#mwcc-calculator .mwcc-left,#mwcc-calculator .mwcc-right{min-width:0}\n#mwcc-calculator .mwcc-right{container-type:inline-size;container-name:mwccr}\n#mwcc-calculator .mwcc-left{container-type:inline-size;container-name:mwccl}\n@container mwccl (min-width:720px){#mwcc-calculator .mwcc-modes{grid-template-columns:repeat(4,minmax(0,1fr))}}\n#mwcc-calculator .mwcc-card{background:var(--mwcc-card);border:1px solid var(--mwcc-line-soft);border-radius:16px;padding:20px;box-shadow:0 1px 2px rgba(19,34,56,.04),0 4px 14px rgba(19,34,56,.05);min-width:0}\n#mwcc-calculator .mwcc-card+.mwcc-card{margin-top:14px}\n#mwcc-calculator .mwcc-group{border-top:1px solid var(--mwcc-line);padding-top:22px;margin-top:22px;min-width:0}\n#mwcc-calculator .mwcc-group.mwcc-first{border-top:0;padding-top:0;margin-top:0}\n#mwcc-calculator .mwcc-inputs .mwcc-actions{border-top:1px solid var(--mwcc-line);padding-top:18px;margin-top:22px}\n#mwcc-calculator .mwcc-card-title{margin:0 0 12px;color:var(--mwcc-navy);font-size:17.5px;font-weight:650;line-height:1.3;display:flex;align-items:center;gap:10px}\n#mwcc-calculator .mwcc-ico{display:inline-flex;align-items:center;justify-content:center;flex:0 0 28px;width:28px;height:28px;border-radius:8px;background:var(--mwcc-accent-soft);color:var(--mwcc-accent)}\n#mwcc-calculator .mwcc-ico svg{width:17px;height:17px}\n#mwcc-calculator .mwcc-card-note{color:var(--mwcc-muted);font-size:14px;margin:-4px 0 14px}\n#mwcc-calculator .mwcc-sub-title{font-size:12.8px;font-weight:700;color:var(--mwcc-muted);letter-spacing:.05em;text-transform:uppercase;margin:16px 0 10px;padding-top:14px;border-top:1px solid var(--mwcc-line-soft)}\n\/* ---------- fields ---------- *\/\n#mwcc-calculator .mwcc-grid{display:grid;grid-template-columns:minmax(0,1fr);gap:14px 16px}\n#mwcc-calculator .mwcc-field{min-width:0}\n#mwcc-calculator .mwcc-label{display:flex;flex-wrap:wrap;align-items:center;gap:6px;font-size:14px;font-weight:600;color:var(--mwcc-navy);margin:0 0 6px;line-height:1.3;position:relative}\n#mwcc-calculator .mwcc-opt{font-size:11.5px;font-weight:600;color:var(--mwcc-soft);background:var(--mwcc-panel);border:1px solid var(--mwcc-line-soft);border-radius:999px;padding:0 7px;line-height:1.6}\n#mwcc-calculator .mwcc-tip{display:inline-flex;align-items:center;justify-content:center;width:17px;height:17px;border-radius:50%;background:var(--mwcc-panel);border:1px solid var(--mwcc-line);color:var(--mwcc-muted);font-size:11px;font-weight:700;cursor:help;line-height:1;font-style:normal}\n#mwcc-calculator .mwcc-tip::after{content:attr(data-tip);position:absolute;left:0;right:0;top:calc(100% + 4px);z-index:20;background:var(--mwcc-navy);color:#fff;font-size:12.5px;font-weight:500;line-height:1.45;padding:8px 10px;border-radius:8px;box-shadow:0 6px 18px rgba(0,0,0,.18);opacity:0;visibility:hidden;transition:opacity .12s;pointer-events:none;text-align:left;white-space:normal}\n#mwcc-calculator .mwcc-tip:hover::after,#mwcc-calculator .mwcc-tip:focus::after{opacity:1;visibility:visible}\n#mwcc-calculator .mwcc-tip:focus{outline:2px solid rgba(26,77,143,.45);outline-offset:1px}\n#mwcc-calculator .mwcc-hint{display:block;color:var(--mwcc-soft);font-size:12.8px;margin-top:5px;line-height:1.45}\n#mwcc-calculator .mwcc-error{display:block;color:var(--mwcc-err);font-size:13px;margin-top:4px;line-height:1.4}\n#mwcc-calculator .mwcc-error:empty{display:none}\n#mwcc-calculator .mwcc-row{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:6px;align-items:stretch}\n#mwcc-calculator input[type=number],#mwcc-calculator input[type=text],#mwcc-calculator input[type=search],#mwcc-calculator select{\n  -webkit-appearance:none;appearance:none;display:block;width:100%;min-height:46px;height:auto;margin:0;padding:10px 12px;font:inherit;font-size:16px;line-height:1.3;\n  color:var(--mwcc-text);background-color:var(--mwcc-input);border:1px solid var(--mwcc-line);border-radius:11px;box-shadow:none;outline:none;max-width:none;transition:border-color .15s ease,box-shadow .15s ease,background-color .15s\n}\n#mwcc-calculator input[type=number]{-moz-appearance:textfield}\n#mwcc-calculator input[type=number]::-webkit-inner-spin-button,#mwcc-calculator input[type=number]::-webkit-outer-spin-button{-webkit-appearance:none;margin:0}\n#mwcc-calculator input[type=search]::-webkit-search-decoration{-webkit-appearance:none}\n#mwcc-calculator select{padding-right:34px;background-image:linear-gradient(45deg,transparent 50%,#566273 50%),linear-gradient(135deg,#566273 50%,transparent 50%);background-position:calc(100% - 18px) 20px,calc(100% - 13px) 20px;background-size:5px 5px,5px 5px;background-repeat:no-repeat;cursor:pointer}\n#mwcc-calculator select.mwcc-usel{width:auto;min-width:92px;background-color:#e9eef4;font-weight:600;font-size:14px;color:var(--mwcc-muted)}\n#mwcc-calculator input:focus,#mwcc-calculator select:focus{border-color:var(--mwcc-accent);background-color:#fff;box-shadow:0 0 0 4px rgba(26,77,143,.16)}\n#mwcc-calculator input::placeholder{color:#a3adba;opacity:1}\n#mwcc-calculator .mwcc-invalid{border-color:var(--mwcc-err)!important;box-shadow:0 0 0 3px rgba(180,35,24,.12)!important}\n#mwcc-calculator .mwcc-seg{display:flex;flex-wrap:wrap;border:1px solid var(--mwcc-line);border-radius:10px;overflow:hidden;margin:0 0 12px;padding:0;position:relative;background:#fff}\n#mwcc-calculator .mwcc-seg legend{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}\n#mwcc-calculator .mwcc-seg input{position:absolute;opacity:0;width:1px;height:1px;margin:0;pointer-events:none}\n#mwcc-calculator .mwcc-seg label{flex:1 1 auto;text-align:center;padding:9px 12px;font-size:14px;font-weight:600;color:var(--mwcc-muted);cursor:pointer;background:#fff;line-height:1.3}\n#mwcc-calculator .mwcc-seg label+input+label{border-left:1px solid var(--mwcc-line)}\n#mwcc-calculator .mwcc-seg input:checked+label{background:var(--mwcc-accent);color:#fff}\n#mwcc-calculator .mwcc-seg input:disabled+label{opacity:.45;cursor:not-allowed}\n#mwcc-calculator .mwcc-seg input:focus-visible+label{outline:3px solid rgba(26,77,143,.4);outline-offset:-3px}\n#mwcc-calculator .mwcc-checks{display:grid;grid-template-columns:minmax(0,1fr);gap:6px;margin-top:4px}\n#mwcc-calculator .mwcc-check{display:flex;align-items:flex-start;gap:9px;padding:8px 10px;border:1px solid var(--mwcc-line-soft);border-radius:10px;background:var(--mwcc-input);font-size:14px;cursor:pointer;line-height:1.35}\n#mwcc-calculator .mwcc-check input{width:18px;height:18px;margin:1px 0 0;flex:0 0 18px;accent-color:var(--mwcc-accent)}\n#mwcc-calculator .mwcc-check span small{display:block;color:var(--mwcc-soft);font-size:12.3px}\n#mwcc-calculator .mwcc-info{margin-top:10px;font-size:13.4px;color:var(--mwcc-muted);background:var(--mwcc-panel);border:1px solid var(--mwcc-line-soft);border-radius:10px;padding:10px 12px;line-height:1.5}\n#mwcc-calculator .mwcc-info b{color:var(--mwcc-navy);font-weight:650}\n#mwcc-calculator .mwcc-info:empty{display:none}\n#mwcc-calculator .mwcc-calcout{margin-top:12px;padding:10px 12px;border-radius:10px;background:var(--mwcc-accent-soft);border:1px solid #c6d6ec;font-size:14px;color:var(--mwcc-navy);font-variant-numeric:tabular-nums}\n#mwcc-calculator .mwcc-calcout:empty{display:none}\n#mwcc-calculator .mwcc-badge{display:inline-block;font-size:10.5px;font-weight:700;letter-spacing:.04em;text-transform:uppercase;border-radius:4px;padding:1px 6px;vertical-align:1px;background:var(--mwcc-warn-soft);color:var(--mwcc-warn);border:1px solid #f0d49c}\n#mwcc-calculator .mwcc-badge-ok{background:var(--mwcc-ok-soft);color:var(--mwcc-ok);border-color:#b5dfc8}\n#mwcc-calculator .mwcc-badge-info{background:var(--mwcc-accent-soft);color:var(--mwcc-accent-dark);border-color:#c6d6ec}\n\/* ---------- comparison rows ---------- *\/\n#mwcc-calculator .mwcc-units{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:10px;padding:12px;background:var(--mwcc-panel);border:1px solid var(--mwcc-line-soft);border-radius:12px;margin-bottom:14px}\n#mwcc-calculator .mwcc-units .mwcc-label{font-size:12.5px;margin-bottom:4px}\n#mwcc-calculator .mwcc-units select{min-height:40px;padding-top:7px;padding-bottom:7px;font-size:14px;background-position:calc(100% - 18px) 17px,calc(100% - 13px) 17px}\n#mwcc-calculator .mwcc-crow{border:1px solid var(--mwcc-line);border-radius:14px;padding:14px;margin:0 0 12px;position:relative;background:#fff}\n#mwcc-calculator .mwcc-crow-head{display:flex;align-items:center;justify-content:space-between;gap:10px;margin-bottom:10px}\n#mwcc-calculator .mwcc-crow-head b{font-size:14.5px;color:var(--mwcc-navy);display:inline-flex;align-items:center;gap:8px}\n#mwcc-calculator .mwcc-dot{display:inline-block;width:11px;height:11px;border-radius:3px;background:var(--mwcc-accent)}\n#mwcc-calculator .mwcc-crow .mwcc-grid{gap:10px 12px}\n#mwcc-calculator .mwcc-crow .mwcc-label{font-size:13px;margin-bottom:4px}\n#mwcc-calculator .mwcc-crow input,#mwcc-calculator .mwcc-crow select{min-height:42px;padding-top:8px;padding-bottom:8px;font-size:15px}\n#mwcc-calculator .mwcc-crow select{background-position:calc(100% - 18px) 18px,calc(100% - 13px) 18px}\n\/* ---------- buttons ---------- *\/\n#mwcc-calculator .mwcc-actions{display:flex;flex-wrap:wrap;gap:10px;justify-content:center;margin-top:16px}\n#mwcc-calculator .mwcc-btn{-webkit-appearance:none;appearance:none;display:inline-flex;align-items:center;justify-content:center;gap:7px;min-height:46px;margin:0;padding:10px 18px;border-radius:999px;border:1px solid var(--mwcc-line);background:#fff;color:var(--mwcc-navy);font:inherit;font-size:15px;font-weight:600;line-height:1.2;cursor:pointer;text-decoration:none;text-transform:none;letter-spacing:normal;box-shadow:none;width:auto;height:auto;text-align:center;transition:background .15s,border-color .15s,color .15s}\n#mwcc-calculator .mwcc-btn svg{width:16px;height:16px;flex:0 0 16px}\n#mwcc-calculator .mwcc-btn:hover{border-color:var(--mwcc-accent);color:var(--mwcc-accent-dark)}\n#mwcc-calculator .mwcc-btn[disabled]{opacity:.5;cursor:not-allowed}\n#mwcc-calculator .mwcc-btn-primary{background:var(--mwcc-accent);border-color:var(--mwcc-accent);color:#fff;min-width:200px}\n#mwcc-calculator .mwcc-btn-primary:hover{background:var(--mwcc-accent-dark);border-color:var(--mwcc-accent-dark);color:#fff}\n#mwcc-calculator .mwcc-btn-secondary{background:var(--mwcc-accent-soft);border-color:#c6d6ec;color:var(--mwcc-accent-dark)}\n#mwcc-calculator .mwcc-btn-sm{min-height:38px;padding:7px 14px;font-size:14px}\n#mwcc-calculator .mwcc-btn-danger:hover{border-color:var(--mwcc-err);color:var(--mwcc-err)}\n#mwcc-calculator .mwcc-btn:focus-visible{outline:3px solid rgba(26,77,143,.4);outline-offset:2px}\n#mwcc-calculator .mwcc-form-err{margin-top:12px;color:var(--mwcc-err);background:var(--mwcc-err-soft);border:1px solid #f1b5ae;border-radius:10px;padding:10px 12px;font-size:14px}\n#mwcc-calculator .mwcc-form-err:empty{display:none}\n\/* ---------- results ---------- *\/\n#mwcc-calculator .mwcc-res-head{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:10px;margin-bottom:12px}\n#mwcc-calculator .mwcc-res-head .mwcc-card-title{margin:0}\n#mwcc-calculator .mwcc-tools{display:flex;flex-wrap:wrap;gap:6px}\n#mwcc-calculator .mwcc-runits{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:8px;margin-bottom:14px}\n#mwcc-calculator .mwcc-runits label{display:block;font-size:12px;font-weight:650;color:var(--mwcc-muted);margin-bottom:3px}\n#mwcc-calculator .mwcc-runits select{min-height:38px;padding:6px 30px 6px 10px;font-size:14px;background-position:calc(100% - 16px) 16px,calc(100% - 11px) 16px}\n#mwcc-calculator .mwcc-placeholder{color:var(--mwcc-muted);font-size:14.5px;padding:18px;border:1px dashed var(--mwcc-line);border-radius:12px;background:var(--mwcc-panel)}\n#mwcc-calculator .mwcc-heroes{display:grid;grid-template-columns:minmax(0,1fr);gap:10px}\n#mwcc-calculator .mwcc-hero{border-radius:14px;padding:16px 18px;background:var(--mwcc-accent-soft);border:1px solid #b5cbe8;min-width:0}\n#mwcc-calculator .mwcc-hero.mwcc-t-ok{background:var(--mwcc-ok-soft);border-color:#b5dfc8}\n#mwcc-calculator .mwcc-hero.mwcc-t-loss{background:#fdf0e8;border-color:#f3c7ab}\n#mwcc-calculator .mwcc-hero.mwcc-t-neutral{background:var(--mwcc-panel);border-color:var(--mwcc-line)}\n#mwcc-calculator .mwcc-hero-label{font-size:12.6px;font-weight:700;color:var(--mwcc-accent-dark);letter-spacing:.04em;text-transform:uppercase}\n#mwcc-calculator .mwcc-t-ok .mwcc-hero-label{color:var(--mwcc-ok)}\n#mwcc-calculator .mwcc-t-loss .mwcc-hero-label{color:#9a3412}\n#mwcc-calculator .mwcc-t-neutral .mwcc-hero-label{color:var(--mwcc-muted)}\n#mwcc-calculator .mwcc-hero-value{font-size:clamp(25px,3.1vw,33px);font-weight:750;color:var(--mwcc-navy);letter-spacing:-.015em;line-height:1.15;margin-top:4px;font-variant-numeric:tabular-nums;overflow-wrap:anywhere}\n#mwcc-calculator .mwcc-hero-value span{font-size:.5em;font-weight:650;color:var(--mwcc-muted);letter-spacing:0;margin-left:6px}\n#mwcc-calculator .mwcc-hero-sub{font-size:13px;color:var(--mwcc-muted);margin-top:4px}\n#mwcc-calculator .mwcc-kpis{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:8px;margin-top:12px}\n#mwcc-calculator .mwcc-kpi{border:1px solid var(--mwcc-line-soft);background:#fff;border-radius:12px;padding:10px 12px;min-width:0;border-top:3px solid var(--mwcc-line)}\n#mwcc-calculator .mwcc-kpi.mwcc-k-init{border-top-color:var(--mwcc-c-init)}\n#mwcc-calculator .mwcc-kpi.mwcc-k-loss{border-top-color:var(--mwcc-c-loss)}\n#mwcc-calculator .mwcc-kpi.mwcc-k-rem{border-top-color:var(--mwcc-c-rem)}\n#mwcc-calculator .mwcc-kpi.mwcc-k-therm{border-top-color:#7c3aed}\n#mwcc-calculator .mwcc-kpi dt{font-size:12.3px;font-weight:650;color:var(--mwcc-muted);line-height:1.3}\n#mwcc-calculator .mwcc-kpi dd{font-size:17px;font-weight:700;color:var(--mwcc-navy);font-variant-numeric:tabular-nums;overflow-wrap:anywhere;margin-top:3px;line-height:1.25}\n#mwcc-calculator .mwcc-kpi dd small{display:block;font-size:12px;font-weight:500;color:var(--mwcc-soft);margin-top:2px}\n#mwcc-calculator .mwcc-sec{margin-top:18px}\n#mwcc-calculator .mwcc-sec-title{font-size:14.5px;font-weight:700;color:var(--mwcc-navy);margin-bottom:8px}\n#mwcc-calculator .mwcc-dl{border:1px solid var(--mwcc-line-soft);border-radius:12px;overflow:hidden}\n#mwcc-calculator .mwcc-dl div{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:4px 14px;padding:8px 13px;font-size:14px;align-items:baseline}\n#mwcc-calculator .mwcc-dl div:nth-child(odd){background:var(--mwcc-panel)}\n#mwcc-calculator .mwcc-dl dt{color:var(--mwcc-muted);min-width:0}\n#mwcc-calculator .mwcc-dl dd{color:var(--mwcc-navy);font-weight:650;text-align:right;font-variant-numeric:tabular-nums;overflow-wrap:anywhere}\n#mwcc-calculator .mwcc-msgs{display:grid;gap:8px;margin-top:12px}\n#mwcc-calculator .mwcc-msg{display:flex;gap:9px;align-items:flex-start;border-radius:10px;padding:10px 12px;font-size:14px;line-height:1.5;border:1px solid transparent}\n#mwcc-calculator .mwcc-msg svg{flex:0 0 17px;width:17px;height:17px;margin-top:2px}\n#mwcc-calculator .mwcc-msg.mwcc-t-warn{background:var(--mwcc-warn-soft);border-color:#f0d49c;color:#5c3300}\n#mwcc-calculator .mwcc-msg.mwcc-t-bad{background:var(--mwcc-err-soft);border-color:#f1b5ae;color:#7a1a12}\n#mwcc-calculator .mwcc-msg.mwcc-t-ok{background:var(--mwcc-ok-soft);border-color:#b5dfc8;color:#124d31}\n#mwcc-calculator .mwcc-msg.mwcc-t-info{background:var(--mwcc-accent-soft);border-color:#c6d6ec;color:#143a6b}\n#mwcc-calculator .mwcc-steps{counter-reset:mwccstep;display:grid;gap:8px}\n#mwcc-calculator .mwcc-steps li{counter-increment:mwccstep;position:relative;padding:9px 12px 9px 42px;border:1px solid var(--mwcc-line-soft);border-radius:10px;background:#fff;font-size:14px}\n#mwcc-calculator .mwcc-steps li::before{content:counter(mwccstep);position:absolute;left:11px;top:9px;width:22px;height:22px;border-radius:50%;background:var(--mwcc-accent-soft);color:var(--mwcc-accent);font-size:12px;font-weight:700;display:flex;align-items:center;justify-content:center}\n#mwcc-calculator .mwcc-steps b{display:block;color:var(--mwcc-navy);font-weight:650}\n#mwcc-calculator .mwcc-steps code{display:block;margin-top:3px;font-family:ui-monospace,SFMono-Regular,Consolas,\"Liberation Mono\",monospace;font-size:13px;color:#33415a;overflow-wrap:anywhere;white-space:normal}\n#mwcc-calculator .mwcc-steps-wrap{margin-top:8px}\n#mwcc-calculator .mwcc-toggle{display:inline-flex;align-items:center;gap:6px;background:none;border:0;padding:0;margin:0;color:var(--mwcc-accent);font:inherit;font-size:14px;font-weight:650;cursor:pointer;min-height:32px}\n#mwcc-calculator .mwcc-toggle:focus-visible{outline:3px solid rgba(26,77,143,.4);outline-offset:2px;border-radius:4px}\n#mwcc-calculator .mwcc-toggle svg{width:14px;height:14px;transition:transform .15s}\n#mwcc-calculator .mwcc-toggle[aria-expanded=true] svg{transform:rotate(180deg)}\n\/* ---------- charts ---------- *\/\n#mwcc-calculator .mwcc-charts{display:grid;grid-template-columns:minmax(0,1fr);gap:12px}\n#mwcc-calculator .mwcc-chart{border:1px solid var(--mwcc-line-soft);border-radius:12px;padding:12px 12px 10px;background:#fff;min-width:0}\n#mwcc-calculator .mwcc-chart-head{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:8px;margin-bottom:6px}\n#mwcc-calculator .mwcc-chart-title{font-size:14px;font-weight:700;color:var(--mwcc-navy)}\n#mwcc-calculator .mwcc-chart-box{width:100%;min-height:200px;position:relative}\n#mwcc-calculator .mwcc-chart-box svg{display:block;width:100%;height:auto}\n#mwcc-calculator .mwcc-chart-box svg:focus{outline:none}\n#mwcc-calculator .mwcc-chart-box .mwcc-ov:focus{outline:2px solid rgba(26,77,143,.5)}\n#mwcc-calculator .mwcc-legend{display:flex;flex-wrap:wrap;gap:12px;font-size:12.5px;color:var(--mwcc-muted);margin-top:6px}\n#mwcc-calculator .mwcc-legend span{display:inline-flex;align-items:center;gap:6px}\n#mwcc-calculator .mwcc-legend i{display:inline-block;width:16px;height:4px;border-radius:2px}\n#mwcc-calculator .mwcc-legend i.mwcc-dash{background:repeating-linear-gradient(90deg,#8a96a8 0 4px,transparent 4px 7px)!important}\n#mwcc-calculator .mwcc-chart-cap{font-size:12.4px;color:var(--mwcc-soft);margin-top:4px}\n#mwcc-calculator .mwcc-mini-seg{display:inline-flex;border:1px solid var(--mwcc-line);border-radius:8px;overflow:hidden}\n#mwcc-calculator .mwcc-mini-seg button{-webkit-appearance:none;appearance:none;border:0;background:#fff;color:var(--mwcc-muted);font:inherit;font-size:12.5px;font-weight:650;padding:5px 9px;cursor:pointer;margin:0;min-height:30px;line-height:1.2;border-radius:0}\n#mwcc-calculator .mwcc-mini-seg button+button{border-left:1px solid var(--mwcc-line)}\n#mwcc-calculator .mwcc-mini-seg button[aria-pressed=true]{background:var(--mwcc-accent);color:#fff}\n#mwcc-calculator .mwcc-mini-seg button:focus-visible{outline:2px solid rgba(26,77,143,.5);outline-offset:-2px}\n\/* ---------- comparison table ---------- *\/\n#mwcc-calculator .mwcc-table{width:100%;border-collapse:collapse;font-size:13.6px;font-variant-numeric:tabular-nums}\n#mwcc-calculator .mwcc-table th{font-weight:700;color:var(--mwcc-muted);font-size:12.3px;text-align:right;padding:8px;border-bottom:1px solid var(--mwcc-line);background:var(--mwcc-panel);line-height:1.3}\n#mwcc-calculator .mwcc-table th:first-child,#mwcc-calculator .mwcc-table td:first-child{text-align:left}\n#mwcc-calculator .mwcc-table td{padding:8px;border-bottom:1px solid var(--mwcc-line-soft);text-align:right;color:var(--mwcc-navy);overflow-wrap:anywhere}\n#mwcc-calculator .mwcc-table td:first-child{font-weight:650}\n#mwcc-calculator .mwcc-tablewrap{border:1px solid var(--mwcc-line-soft);border-radius:12px;overflow:hidden}\n\/* ---------- content sections ---------- *\/\n#mwcc-calculator .mwcc-content{margin-top:28px;display:grid;gap:16px}\n#mwcc-calculator .mwcc-content h2{font-size:21px;font-weight:700;color:var(--mwcc-navy);line-height:1.3;margin:0 0 10px}\n#mwcc-calculator .mwcc-content h3{font-size:16.5px;font-weight:700;color:var(--mwcc-navy);line-height:1.35;margin:16px 0 6px}\n#mwcc-calculator .mwcc-content p{margin:0 0 10px;color:var(--mwcc-text)}\n#mwcc-calculator .mwcc-content p:last-child{margin-bottom:0}\n#mwcc-calculator .mwcc-list{display:grid;gap:5px;margin:4px 0 10px}\n#mwcc-calculator .mwcc-list li{position:relative;padding-left:18px}\n#mwcc-calculator .mwcc-list li::before{content:\"\";position:absolute;left:3px;top:.62em;width:6px;height:6px;border-radius:50%;background:var(--mwcc-accent)}\n#mwcc-calculator .mwcc-cols{display:grid;grid-template-columns:minmax(0,1fr);gap:4px 24px}\n#mwcc-calculator .mwcc-formula{display:block;margin:8px 0 12px;padding:10px 14px;border-left:3px solid var(--mwcc-accent);background:var(--mwcc-panel);border-radius:0 10px 10px 0;font-family:ui-monospace,SFMono-Regular,Consolas,\"Liberation Mono\",monospace;font-size:14px;color:var(--mwcc-navy);overflow-wrap:anywhere}\n#mwcc-calculator .mwcc-examples{display:grid;grid-template-columns:minmax(0,1fr);gap:12px}\n#mwcc-calculator .mwcc-ex{border:1px solid var(--mwcc-line-soft);border-radius:14px;padding:16px;background:var(--mwcc-panel);display:flex;flex-direction:column;gap:6px;min-width:0}\n#mwcc-calculator .mwcc-ex h3{margin:0 0 4px}\n#mwcc-calculator .mwcc-ex dl{display:grid;gap:3px;font-size:13.6px}\n#mwcc-calculator .mwcc-ex dl div{display:flex;justify-content:space-between;gap:10px;border-bottom:1px dashed var(--mwcc-line);padding:3px 0}\n#mwcc-calculator .mwcc-ex dt{color:var(--mwcc-muted)}\n#mwcc-calculator .mwcc-ex dd{font-weight:650;color:var(--mwcc-navy);text-align:right;font-variant-numeric:tabular-nums}\n#mwcc-calculator .mwcc-ex p{font-size:13.6px;color:var(--mwcc-muted);margin:4px 0 0}\n#mwcc-calculator .mwcc-ex .mwcc-ex-res{font-size:15px;font-weight:700;color:var(--mwcc-navy);margin-top:6px}\n#mwcc-calculator .mwcc-ex .mwcc-btn{margin-top:auto;align-self:flex-start}\n#mwcc-calculator .mwcc-disclaimer{border:1px solid #f0d49c;background:var(--mwcc-warn-soft);color:#5c3300;border-radius:14px;padding:14px 16px;font-size:14px;line-height:1.55}\n#mwcc-calculator .mwcc-faq{display:grid;gap:8px}\n#mwcc-calculator .mwcc-faq details{border:1px solid var(--mwcc-line-soft);border-radius:12px;background:#fff;overflow:hidden}\n#mwcc-calculator .mwcc-faq summary{list-style:none;cursor:pointer;padding:12px 44px 12px 14px;font-weight:650;color:var(--mwcc-navy);position:relative;font-size:15px}\n#mwcc-calculator .mwcc-faq summary::-webkit-details-marker{display:none}\n#mwcc-calculator .mwcc-faq summary::after{content:\"+\";position:absolute;right:16px;top:50%;transform:translateY(-50%);font-size:20px;font-weight:500;color:var(--mwcc-accent)}\n#mwcc-calculator .mwcc-faq details[open] summary::after{content:\"\u2212\"}\n#mwcc-calculator .mwcc-faq summary:focus-visible{outline:3px solid rgba(26,77,143,.4);outline-offset:-3px}\n#mwcc-calculator .mwcc-faq details>div{padding:0 14px 13px;color:var(--mwcc-text);font-size:14.6px}\n#mwcc-calculator .mwcc-toast{position:fixed;left:50%;bottom:24px;transform:translateX(-50%) translateY(20px);background:var(--mwcc-navy);color:#fff;font-size:14px;padding:10px 16px;border-radius:999px;opacity:0;visibility:hidden;transition:opacity .2s,transform .2s;z-index:99999;box-shadow:0 8px 24px rgba(0,0,0,.2);max-width:calc(100vw - 32px);text-align:center}\n#mwcc-calculator .mwcc-toast.mwcc-show{opacity:1;visibility:visible;transform:translateX(-50%) translateY(0)}\n\/* ---------- responsive ---------- *\/\n@container mwcc (min-width:560px){\n  #mwcc-calculator .mwcc-grid-2{grid-template-columns:repeat(2,minmax(0,1fr))}\n  #mwcc-calculator .mwcc-grid-3{grid-template-columns:repeat(3,minmax(0,1fr))}\n  #mwcc-calculator .mwcc-checks{grid-template-columns:repeat(2,minmax(0,1fr))}\n  #mwcc-calculator .mwcc-units{grid-template-columns:repeat(3,minmax(0,1fr))}\n  #mwcc-calculator .mwcc-cols{grid-template-columns:repeat(2,minmax(0,1fr))}\n}\n@container mwcc (min-width:760px){\n  #mwcc-calculator .mwcc-examples{grid-template-columns:repeat(3,minmax(0,1fr))}\n}\n@container mwccr (min-width:480px){\n  #mwcc-calculator .mwcc-heroes.mwcc-two{grid-template-columns:repeat(2,minmax(0,1fr))}\n}\n@container mwccr (min-width:560px){\n  #mwcc-calculator .mwcc-kpis{grid-template-columns:repeat(3,minmax(0,1fr))}\n}\n@container mwcc (min-width:940px){\n  #mwcc-calculator .mwcc-crow .mwcc-grid-4{grid-template-columns:repeat(2,minmax(0,1fr))}\n}\n@container mwccr (max-width:640px){\n  #mwcc-calculator .mwcc-table thead{display:none}\n  #mwcc-calculator .mwcc-table,#mwcc-calculator .mwcc-table tbody,#mwcc-calculator .mwcc-table tr,#mwcc-calculator .mwcc-table td{display:block;width:100%}\n  #mwcc-calculator .mwcc-table tr{border-bottom:1px solid var(--mwcc-line);padding:6px 0}\n  #mwcc-calculator .mwcc-table td{display:flex;justify-content:space-between;gap:12px;border:0;padding:4px 12px;text-align:right}\n  #mwcc-calculator .mwcc-table td::before{content:attr(data-label);color:var(--mwcc-muted);font-weight:600;text-align:left}\n  #mwcc-calculator .mwcc-table td:first-child{font-size:15px;justify-content:flex-start;align-items:center}\n  #mwcc-calculator .mwcc-table td:first-child::before{content:\"\"}\n}\n@media (max-width:700px){\n  #mwcc-calculator{padding:18px 14px;border-radius:16px;margin:12px auto}\n  #mwcc-calculator .mwcc-card{padding:16px 14px;border-radius:14px}\n  #mwcc-calculator .mwcc-runits{grid-template-columns:minmax(0,1fr)}\n}\n@media (prefers-reduced-motion:reduce){#mwcc-calculator *{transition:none!important}}\n@media print{\n  #mwcc-calculator{border:0;padding:0}\n  #mwcc-calculator .mwcc-actions,#mwcc-calculator .mwcc-tools,#mwcc-calculator .mwcc-modes{display:none!important}\n  #mwcc-calculator .mwcc-card{box-shadow:none;break-inside:avoid}\n}\n<\/style>\n<div class=\"mwcc-wrap\">\n<div class=\"mwcc-layout\">\n<form class=\"mwcc-left\" id=\"mwcc-form\" novalidate onsubmit=\"return false;\">\n<div class=\"mwcc-card mwcc-inputs\">\n<fieldset class=\"mwcc-modes\" id=\"mwcc-modes\">\n<legend>Calculation mode<\/legend>\n<input type=\"radio\" id=\"mwcc-m1\" name=\"mwcc-mode\" value=\"1\" checked><label for=\"mwcc-m1\"><span class=\"mwcc-mi\" aria-hidden=\"true\"><svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M14 14.8V4a2 2 0 1 0-4 0v10.8a4 4 0 1 0 4 0z\"\/><\/svg><\/span><span class=\"mwcc-mt\"><b>Temperature Effect<\/b><small>Volume and density change<\/small><\/span><\/label>\n<input type=\"radio\" id=\"mwcc-m2\" name=\"mwcc-mode\" value=\"2\"><label for=\"mwcc-m2\"><span class=\"mwcc-mi\" aria-hidden=\"true\"><svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M12 3c3 4 6 7.3 6 11a6 6 0 0 1-12 0c0-3.7 3-7 6-11z\"\/><path d=\"M9.5 15.5a2.5 2.5 0 0 0 2.5 2.5\"\/><\/svg><\/span><span class=\"mwcc-mt\"><b>Corrosion Weight Loss<\/b><small>Uniform material removal<\/small><\/span><\/label>\n<input type=\"radio\" id=\"mwcc-m3\" name=\"mwcc-mode\" value=\"3\"><label for=\"mwcc-m3\"><span class=\"mwcc-mi\" aria-hidden=\"true\"><svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M4 12h6M7 9v6M14 12h6\"\/><rect x=\"2.5\" y=\"4.5\" width=\"19\" height=\"15\" rx=\"3\"\/><\/svg><\/span><span class=\"mwcc-mt\"><b>Combined Analysis<\/b><small>Temperature + corrosion<\/small><\/span><\/label>\n<input type=\"radio\" id=\"mwcc-m4\" name=\"mwcc-mode\" value=\"4\"><label for=\"mwcc-m4\"><span class=\"mwcc-mi\" aria-hidden=\"true\"><svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M4 20V10M10 20V4M16 20v-7M22 20H2\"\/><\/svg><\/span><span class=\"mwcc-mt\"><b>Material Comparison<\/b><small>Up to five materials<\/small><\/span><\/label>\n<\/fieldset>\n<section class=\"mwcc-group\" id=\"mwcc-sec-mat\" aria-labelledby=\"mwcc-h-mat\">\n<h2 class=\"mwcc-card-title\" id=\"mwcc-h-mat\"><span class=\"mwcc-ico\" aria-hidden=\"true\"><svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M12 2l9 5v10l-9 5-9-5V7z\"\/><path d=\"M12 22V12M21 7l-9 5-9-5\"\/><\/svg><\/span>Material<\/h2>\n<div class=\"mwcc-grid mwcc-grid-2\">\n<div class=\"mwcc-field\">\n<label class=\"mwcc-label\" for=\"mwcc-cat\">Material category<\/label>\n<select id=\"mwcc-cat\"><\/select>\n<\/div>\n<div class=\"mwcc-field\">\n<label class=\"mwcc-label\" for=\"mwcc-search\">Search materials<\/label>\n<input id=\"mwcc-search\" type=\"search\" placeholder=\"e.g. 316, 6061, PEEK\" autocomplete=\"off\" aria-describedby=\"mwcc-search-hint\">\n<span class=\"mwcc-hint\" id=\"mwcc-search-hint\" aria-live=\"polite\"><\/span>\n<\/div>\n<div class=\"mwcc-field\">\n<label class=\"mwcc-label\" for=\"mwcc-mat\">Material type \/ grade<\/label>\n<select id=\"mwcc-mat\"><\/select>\n<\/div>\n<div class=\"mwcc-field\" id=\"mwcc-f-cname\" hidden>\n<label class=\"mwcc-label\" for=\"mwcc-cname\">Custom material name <span class=\"mwcc-opt\">Optional<\/span><\/label>\n<input id=\"mwcc-cname\" type=\"text\" maxlength=\"80\" placeholder=\"e.g. Duplex 2205\" autocomplete=\"off\">\n<\/div>\n<div class=\"mwcc-field\">\n<label class=\"mwcc-label\" for=\"mwcc-dens\">Material density (\u03c1\u2080) <span class=\"mwcc-tip\" tabindex=\"0\" role=\"note\" aria-label=\"Density at the reference temperature, about 20 \u00b0C. Preset values are approximate and editable.\" data-tip=\"Density at the reference temperature (about 20 \u00b0C). Preset values are approximate; enter the value for your exact grade when known.\">i<\/span><\/label>\n<div class=\"mwcc-row\"><input id=\"mwcc-dens\" type=\"number\" inputmode=\"decimal\" step=\"any\" min=\"0\" aria-describedby=\"mwcc-dens-err\"><select class=\"mwcc-usel\" id=\"mwcc-dens-u\" aria-label=\"Density unit\"><option value=\"kgm3\" selected>kg\/m\u00b3<\/option><option value=\"gcm3\">g\/cm\u00b3<\/option><option value=\"lbft3\">lb\/ft\u00b3<\/option><option value=\"lbin3\">lb\/in\u00b3<\/option><\/select><\/div>\n<span class=\"mwcc-error\" id=\"mwcc-dens-err\" aria-live=\"polite\"><\/span>\n<\/div>\n<div class=\"mwcc-field\" id=\"mwcc-f-alpha\">\n<label class=\"mwcc-label\" for=\"mwcc-alpha\">Linear expansion coefficient (\u03b1) <span class=\"mwcc-tip\" tabindex=\"0\" role=\"note\" aria-label=\"Mean linear thermal expansion coefficient over your temperature range.\" data-tip=\"Mean linear coefficient over your temperature range. 12 \u00d7 10\u207b\u2076 \/\u00b0C means 12 \u00b5m of growth per metre per \u00b0C.\">i<\/span><\/label>\n<div class=\"mwcc-row\"><input id=\"mwcc-alpha\" type=\"number\" inputmode=\"decimal\" step=\"any\" aria-describedby=\"mwcc-alpha-err\"><select class=\"mwcc-usel\" id=\"mwcc-alpha-u\" aria-label=\"Expansion coefficient unit\"><option value=\"uC\" selected>\u00d710\u207b\u2076 \/\u00b0C<\/option><option value=\"uK\">\u00d710\u207b\u2076 \/K<\/option><option value=\"uF\">\u00d710\u207b\u2076 \/\u00b0F<\/option><\/select><\/div>\n<span class=\"mwcc-error\" id=\"mwcc-alpha-err\" aria-live=\"polite\"><\/span>\n<\/div>\n<\/div>\n<div class=\"mwcc-info\" id=\"mwcc-matinfo\" aria-live=\"polite\"><\/div>\n<\/section>\n<section class=\"mwcc-group\" id=\"mwcc-sec-prop\" aria-labelledby=\"mwcc-h-prop\">\n<h2 class=\"mwcc-card-title\" id=\"mwcc-h-prop\"><span class=\"mwcc-ico\" aria-hidden=\"true\"><svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M6.5 8h11l2.5 12H4z\"\/><circle cx=\"12\" cy=\"5\" r=\"2.5\"\/><\/svg><\/span>Initial material properties<\/h2>\n<fieldset class=\"mwcc-seg\" id=\"mwcc-basis-seg\">\n<legend>Initial quantity input<\/legend>\n<input type=\"radio\" id=\"mwcc-b-mass\" name=\"mwcc-basis\" value=\"mass\" checked><label for=\"mwcc-b-mass\">Enter mass<\/label>\n<input type=\"radio\" id=\"mwcc-b-vol\" name=\"mwcc-basis\" value=\"volume\"><label for=\"mwcc-b-vol\">Enter volume<\/label>\n<input type=\"radio\" id=\"mwcc-b-geo\" name=\"mwcc-basis\" value=\"geom\"><label for=\"mwcc-b-geo\">From geometry<\/label>\n<\/fieldset>\n<div class=\"mwcc-grid mwcc-grid-2\">\n<div class=\"mwcc-field\" id=\"mwcc-f-mass\">\n<label class=\"mwcc-label\" for=\"mwcc-mass\">Initial material mass (m\u2080)<\/label>\n<div class=\"mwcc-row\"><input id=\"mwcc-mass\" type=\"number\" inputmode=\"decimal\" step=\"any\" min=\"0\" aria-describedby=\"mwcc-mass-hint mwcc-mass-err\"><select class=\"mwcc-usel\" id=\"mwcc-mass-u\" aria-label=\"Mass unit\"><option value=\"mg\">mg<\/option><option value=\"g\">g<\/option><option value=\"kg\" selected>kg<\/option><option value=\"t\">metric t<\/option><option value=\"oz\">oz<\/option><option value=\"lb\">lb<\/option><\/select><\/div>\n<span class=\"mwcc-hint\" id=\"mwcc-mass-hint\">Initial volume is derived as V\u2080 = m\u2080 \/ \u03c1\u2080.<\/span>\n<span class=\"mwcc-error\" id=\"mwcc-mass-err\" aria-live=\"polite\"><\/span>\n<\/div>\n<div class=\"mwcc-field\" id=\"mwcc-f-vol\" hidden>\n<label class=\"mwcc-label\" for=\"mwcc-vol\">Initial material volume (V\u2080)<\/label>\n<div class=\"mwcc-row\"><input id=\"mwcc-vol\" type=\"number\" inputmode=\"decimal\" step=\"any\" min=\"0\" aria-describedby=\"mwcc-vol-hint mwcc-vol-err\"><select class=\"mwcc-usel\" id=\"mwcc-vol-u\" aria-label=\"Volume unit\"><option value=\"mm3\">mm\u00b3<\/option><option value=\"cm3\">cm\u00b3<\/option><option value=\"m3\" selected>m\u00b3<\/option><option value=\"mL\">mL<\/option><option value=\"L\">L<\/option><option value=\"in3\">in\u00b3<\/option><option value=\"ft3\">ft\u00b3<\/option><\/select><\/div>\n<span class=\"mwcc-hint\" id=\"mwcc-vol-hint\">Initial mass is derived as m\u2080 = \u03c1\u2080 \u00d7 V\u2080.<\/span>\n<span class=\"mwcc-error\" id=\"mwcc-vol-err\" aria-live=\"polite\"><\/span>\n<\/div>\n<\/div>\n<div id=\"mwcc-f-geo\" hidden>\n<div class=\"mwcc-grid mwcc-grid-2\">\n<div class=\"mwcc-field\">\n<label class=\"mwcc-label\" for=\"mwcc-shape\">Shape<\/label>\n<select id=\"mwcc-shape\">\n<option value=\"plate\" selected>Rectangular plate<\/option>\n<option value=\"block\">Rectangular block<\/option>\n<option value=\"cyl\">Solid cylinder<\/option>\n<option value=\"hcyl\">Hollow cylinder (pipe)<\/option>\n<option value=\"sphere\">Solid sphere<\/option>\n<option value=\"bar\">Round bar<\/option>\n<option value=\"rtube\">Rectangular tube<\/option>\n<\/select>\n<\/div>\n<div class=\"mwcc-field\">\n<label class=\"mwcc-label\" for=\"mwcc-g-u\">Dimension unit<\/label>\n<select id=\"mwcc-g-u\"><option value=\"mm\" selected>mm<\/option><option value=\"cm\">cm<\/option><option value=\"m\">m<\/option><option value=\"in\">in<\/option><option value=\"ft\">ft<\/option><\/select>\n<\/div>\n<div class=\"mwcc-field\" data-mwcc-dim=\"L\"><label class=\"mwcc-label\" for=\"mwcc-g-L\">Length (L)<\/label><input id=\"mwcc-g-L\" type=\"number\" inputmode=\"decimal\" step=\"any\" min=\"0\" aria-describedby=\"mwcc-g-L-err\"><span class=\"mwcc-error\" id=\"mwcc-g-L-err\" aria-live=\"polite\"><\/span><\/div>\n<div class=\"mwcc-field\" data-mwcc-dim=\"W\"><label class=\"mwcc-label\" for=\"mwcc-g-W\">Width (W)<\/label><input id=\"mwcc-g-W\" type=\"number\" inputmode=\"decimal\" step=\"any\" min=\"0\" aria-describedby=\"mwcc-g-W-err\"><span class=\"mwcc-error\" id=\"mwcc-g-W-err\" aria-live=\"polite\"><\/span><\/div>\n<div class=\"mwcc-field\" data-mwcc-dim=\"T\"><label class=\"mwcc-label\" for=\"mwcc-g-T\">Thickness (t)<\/label><input id=\"mwcc-g-T\" type=\"number\" inputmode=\"decimal\" step=\"any\" min=\"0\" aria-describedby=\"mwcc-g-T-err\"><span class=\"mwcc-error\" id=\"mwcc-g-T-err\" aria-live=\"polite\"><\/span><\/div>\n<div class=\"mwcc-field\" data-mwcc-dim=\"H\"><label class=\"mwcc-label\" for=\"mwcc-g-H\">Height (H)<\/label><input id=\"mwcc-g-H\" type=\"number\" inputmode=\"decimal\" step=\"any\" min=\"0\" aria-describedby=\"mwcc-g-H-err\"><span class=\"mwcc-error\" id=\"mwcc-g-H-err\" aria-live=\"polite\"><\/span><\/div>\n<div class=\"mwcc-field\" data-mwcc-dim=\"R\"><label class=\"mwcc-label\" for=\"mwcc-g-R\">Radius (r)<\/label><input id=\"mwcc-g-R\" type=\"number\" inputmode=\"decimal\" step=\"any\" min=\"0\" aria-describedby=\"mwcc-g-R-err\"><span class=\"mwcc-error\" id=\"mwcc-g-R-err\" aria-live=\"polite\"><\/span><\/div>\n<div class=\"mwcc-field\" data-mwcc-dim=\"Ro\"><label class=\"mwcc-label\" for=\"mwcc-g-Ro\">Outer radius (R\u2080)<\/label><input id=\"mwcc-g-Ro\" type=\"number\" inputmode=\"decimal\" step=\"any\" min=\"0\" aria-describedby=\"mwcc-g-Ro-err\"><span class=\"mwcc-error\" id=\"mwcc-g-Ro-err\" aria-live=\"polite\"><\/span><\/div>\n<div class=\"mwcc-field\" data-mwcc-dim=\"Ri\"><label class=\"mwcc-label\" for=\"mwcc-g-Ri\">Inner radius (R\u1d62)<\/label><input id=\"mwcc-g-Ri\" type=\"number\" inputmode=\"decimal\" step=\"any\" min=\"0\" aria-describedby=\"mwcc-g-Ri-err\"><span class=\"mwcc-error\" id=\"mwcc-g-Ri-err\" aria-live=\"polite\"><\/span><\/div>\n<div class=\"mwcc-field\" data-mwcc-dim=\"D\"><label class=\"mwcc-label\" for=\"mwcc-g-D\">Diameter (D)<\/label><input id=\"mwcc-g-D\" type=\"number\" inputmode=\"decimal\" step=\"any\" min=\"0\" aria-describedby=\"mwcc-g-D-err\"><span class=\"mwcc-error\" id=\"mwcc-g-D-err\" aria-live=\"polite\"><\/span><\/div>\n<div class=\"mwcc-field\" data-mwcc-dim=\"OW\"><label class=\"mwcc-label\" for=\"mwcc-g-OW\">Outer width<\/label><input id=\"mwcc-g-OW\" type=\"number\" inputmode=\"decimal\" step=\"any\" min=\"0\" aria-describedby=\"mwcc-g-OW-err\"><span class=\"mwcc-error\" id=\"mwcc-g-OW-err\" aria-live=\"polite\"><\/span><\/div>\n<div class=\"mwcc-field\" data-mwcc-dim=\"OH\"><label class=\"mwcc-label\" for=\"mwcc-g-OH\">Outer height<\/label><input id=\"mwcc-g-OH\" type=\"number\" inputmode=\"decimal\" step=\"any\" min=\"0\" aria-describedby=\"mwcc-g-OH-err\"><span class=\"mwcc-error\" id=\"mwcc-g-OH-err\" aria-live=\"polite\"><\/span><\/div>\n<div class=\"mwcc-field\" data-mwcc-dim=\"IW\"><label class=\"mwcc-label\" for=\"mwcc-g-IW\">Inner width<\/label><input id=\"mwcc-g-IW\" type=\"number\" inputmode=\"decimal\" step=\"any\" min=\"0\" aria-describedby=\"mwcc-g-IW-err\"><span class=\"mwcc-error\" id=\"mwcc-g-IW-err\" aria-live=\"polite\"><\/span><\/div>\n<div class=\"mwcc-field\" data-mwcc-dim=\"IH\"><label class=\"mwcc-label\" for=\"mwcc-g-IH\">Inner height<\/label><input id=\"mwcc-g-IH\" type=\"number\" inputmode=\"decimal\" step=\"any\" min=\"0\" aria-describedby=\"mwcc-g-IH-err\"><span class=\"mwcc-error\" id=\"mwcc-g-IH-err\" aria-live=\"polite\"><\/span><\/div>\n<\/div>\n<p class=\"mwcc-calcout\" id=\"mwcc-geo-out\" aria-live=\"polite\"><\/p>\n<\/div>\n<div class=\"mwcc-grid mwcc-grid-2\" style=\"margin-top:14px\">\n<div class=\"mwcc-field\" id=\"mwcc-f-len\">\n<label class=\"mwcc-label\" for=\"mwcc-len\">Initial length (L\u2080) <span class=\"mwcc-opt\">Optional<\/span><\/label>\n<div class=\"mwcc-row\"><input id=\"mwcc-len\" type=\"number\" inputmode=\"decimal\" step=\"any\" min=\"0\" placeholder=\"For \u0394L = \u03b1\u00b7L\u2080\u00b7\u0394T\" aria-describedby=\"mwcc-len-hint mwcc-len-err\"><select class=\"mwcc-usel\" id=\"mwcc-len-u\" aria-label=\"Length unit\"><option value=\"mm\" selected>mm<\/option><option value=\"cm\">cm<\/option><option value=\"m\">m<\/option><option value=\"in\">in<\/option><option value=\"ft\">ft<\/option><\/select><\/div>\n<span class=\"mwcc-hint\" id=\"mwcc-len-hint\">Used for the length change. With geometry input, a blank field uses the component length.<\/span>\n<span class=\"mwcc-error\" id=\"mwcc-len-err\" aria-live=\"polite\"><\/span>\n<\/div>\n<\/div>\n<div id=\"mwcc-f-areagrp\">\n<h3 class=\"mwcc-sub-title\">Exposed surface area<\/h3>\n<fieldset class=\"mwcc-seg\" id=\"mwcc-abasis-seg\">\n<legend>Exposed area input<\/legend>\n<input type=\"radio\" id=\"mwcc-a-man\" name=\"mwcc-abasis\" value=\"manual\" checked><label for=\"mwcc-a-man\">Enter area<\/label>\n<input type=\"radio\" id=\"mwcc-a-geo\" name=\"mwcc-abasis\" value=\"geom\"><label for=\"mwcc-a-geo\">Select exposed surfaces<\/label>\n<\/fieldset>\n<div class=\"mwcc-field\" id=\"mwcc-f-area\">\n<label class=\"mwcc-label\" for=\"mwcc-area\">Effective exposed surface area (A) <span class=\"mwcc-tip\" tabindex=\"0\" role=\"note\" aria-label=\"Only the area actually wetted by the corrosive environment.\" data-tip=\"Only the area actually in contact with the corrosive environment. Coated, sealed or contacting faces are usually excluded.\">i<\/span><\/label>\n<div class=\"mwcc-row\"><input id=\"mwcc-area\" type=\"number\" inputmode=\"decimal\" step=\"any\" min=\"0\" aria-describedby=\"mwcc-area-err\"><select class=\"mwcc-usel\" id=\"mwcc-area-u\" aria-label=\"Area unit\"><option value=\"mm2\">mm\u00b2<\/option><option value=\"cm2\">cm\u00b2<\/option><option value=\"m2\" selected>m\u00b2<\/option><option value=\"in2\">in\u00b2<\/option><option value=\"ft2\">ft\u00b2<\/option><\/select><\/div>\n<span class=\"mwcc-error\" id=\"mwcc-area-err\" aria-live=\"polite\"><\/span>\n<\/div>\n<div id=\"mwcc-f-surfs\" hidden>\n<p class=\"mwcc-hint\" style=\"margin:0 0 6px\">Tick only the surfaces exposed to the corrosive environment. Not every surface is assumed to corrode.<\/p>\n<div class=\"mwcc-checks\" id=\"mwcc-surfs\"><\/div>\n<span class=\"mwcc-error\" id=\"mwcc-surfs-err\" aria-live=\"polite\"><\/span>\n<p class=\"mwcc-calcout\" id=\"mwcc-surf-out\" aria-live=\"polite\"><\/p>\n<\/div>\n<\/div>\n<\/section>\n<section class=\"mwcc-group\" id=\"mwcc-sec-temp\" aria-labelledby=\"mwcc-h-temp\">\n<h2 class=\"mwcc-card-title\" id=\"mwcc-h-temp\"><span class=\"mwcc-ico\" aria-hidden=\"true\"><svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M14 14.8V4a2 2 0 1 0-4 0v10.8a4 4 0 1 0 4 0z\"\/><path d=\"M12 9v8\"\/><\/svg><\/span>Temperature parameters<\/h2>\n<div class=\"mwcc-grid mwcc-grid-3\">\n<div class=\"mwcc-field\">\n<label class=\"mwcc-label\" for=\"mwcc-tu\">Temperature unit<\/label>\n<select id=\"mwcc-tu\"><option value=\"C\" selected>Celsius (\u00b0C)<\/option><option value=\"F\">Fahrenheit (\u00b0F)<\/option><option value=\"K\">Kelvin (K)<\/option><\/select>\n<\/div>\n<div class=\"mwcc-field\">\n<label class=\"mwcc-label\" for=\"mwcc-t1\">Initial (reference) temp. T\u2081<\/label>\n<input id=\"mwcc-t1\" type=\"number\" inputmode=\"decimal\" step=\"any\" aria-describedby=\"mwcc-t1-err\">\n<span class=\"mwcc-error\" id=\"mwcc-t1-err\" aria-live=\"polite\"><\/span>\n<\/div>\n<div class=\"mwcc-field\">\n<label class=\"mwcc-label\" for=\"mwcc-t2\">Final (operating) temp. T\u2082<\/label>\n<input id=\"mwcc-t2\" type=\"number\" inputmode=\"decimal\" step=\"any\" aria-describedby=\"mwcc-t2-err\">\n<span class=\"mwcc-error\" id=\"mwcc-t2-err\" aria-live=\"polite\"><\/span>\n<\/div>\n<\/div>\n<p class=\"mwcc-calcout\" id=\"mwcc-dt-out\" aria-live=\"polite\"><\/p>\n<\/section>\n<section class=\"mwcc-group\" id=\"mwcc-sec-corr\" aria-labelledby=\"mwcc-h-corr\">\n<h2 class=\"mwcc-card-title\" id=\"mwcc-h-corr\"><span class=\"mwcc-ico\" aria-hidden=\"true\"><svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M3 17h18M3 21h18\"\/><path d=\"M5 17V9l3-2 3 3 3-4 3 3 2-2v10\"\/><\/svg><\/span>Corrosion parameters<\/h2>\n<p class=\"mwcc-card-note\">Simplified uniform corrosion model: constant rate, constant exposed area, uniform material removal.<\/p>\n<div class=\"mwcc-grid mwcc-grid-2\">\n<div class=\"mwcc-field\">\n<label class=\"mwcc-label\" for=\"mwcc-rate\">Corrosion rate (CR) <span class=\"mwcc-tip\" tabindex=\"0\" role=\"note\" aria-label=\"Uniform penetration rate from tests, inspection data or a verified source.\" data-tip=\"Uniform penetration rate from coupon tests, inspection history or a verified source for your environment. No rate is assumed from the material type.\">i<\/span><\/label>\n<div class=\"mwcc-row\"><input id=\"mwcc-rate\" type=\"number\" inputmode=\"decimal\" step=\"any\" min=\"0\" aria-describedby=\"mwcc-rate-hint mwcc-rate-err\"><select class=\"mwcc-usel\" id=\"mwcc-rate-u\" aria-label=\"Corrosion rate unit\"><option value=\"mmy\" selected>mm\/year<\/option><option value=\"umy\">\u00b5m\/year<\/option><option value=\"mpy\">MPY<\/option><option value=\"ipy\">in\/year<\/option><\/select><\/div>\n<span class=\"mwcc-hint\" id=\"mwcc-rate-hint\">1 mm\/year = 1000 \u00b5m\/year \u2248 39.37 MPY; 1 MPY = 0.0254 mm\/year.<\/span>\n<span class=\"mwcc-error\" id=\"mwcc-rate-err\" aria-live=\"polite\"><\/span>\n<\/div>\n<div class=\"mwcc-field\">\n<label class=\"mwcc-label\" for=\"mwcc-dur\">Exposure duration (t)<\/label>\n<div class=\"mwcc-row\"><input id=\"mwcc-dur\" type=\"number\" inputmode=\"decimal\" step=\"any\" min=\"0\" aria-describedby=\"mwcc-dur-hint mwcc-dur-err\"><select class=\"mwcc-usel\" id=\"mwcc-dur-u\" aria-label=\"Exposure duration unit\"><option value=\"h\">Hours<\/option><option value=\"d\">Days<\/option><option value=\"mo\">Months<\/option><option value=\"y\" selected>Years<\/option><\/select><\/div>\n<span class=\"mwcc-hint\" id=\"mwcc-dur-hint\">1 year = 365 days = 8,760 h; 1 month = 1\/12 year.<\/span>\n<span class=\"mwcc-error\" id=\"mwcc-dur-err\" aria-live=\"polite\"><\/span>\n<\/div>\n<\/div>\n<\/section>\n<section class=\"mwcc-group\" id=\"mwcc-sec-cmp\" aria-labelledby=\"mwcc-h-cmp\" hidden>\n<h2 class=\"mwcc-card-title\" id=\"mwcc-h-cmp\"><span class=\"mwcc-ico\" aria-hidden=\"true\"><svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M4 20V10M10 20V4M16 20v-7M22 20H2\"\/><\/svg><\/span>Materials to compare<\/h2>\n<p class=\"mwcc-card-note\">Enter a verified corrosion rate for each material in its own environment. Default rows use identical illustrative conditions so that only the material properties differ.<\/p>\n<div class=\"mwcc-units\" id=\"mwcc-cunits\">\n<div><label class=\"mwcc-label\" for=\"mwcc-cu-dens\">Density unit<\/label><select id=\"mwcc-cu-dens\"><option value=\"kgm3\" selected>kg\/m\u00b3<\/option><option value=\"gcm3\">g\/cm\u00b3<\/option><option value=\"lbft3\">lb\/ft\u00b3<\/option><option value=\"lbin3\">lb\/in\u00b3<\/option><\/select><\/div>\n<div><label class=\"mwcc-label\" for=\"mwcc-cu-alpha\">\u03b1 unit<\/label><select id=\"mwcc-cu-alpha\"><option value=\"uC\" selected>\u00d710\u207b\u2076 \/\u00b0C<\/option><option value=\"uK\">\u00d710\u207b\u2076 \/K<\/option><option value=\"uF\">\u00d710\u207b\u2076 \/\u00b0F<\/option><\/select><\/div>\n<div><label class=\"mwcc-label\" for=\"mwcc-cu-mass\">Mass unit<\/label><select id=\"mwcc-cu-mass\"><option value=\"mg\">mg<\/option><option value=\"g\">g<\/option><option value=\"kg\" selected>kg<\/option><option value=\"t\">metric t<\/option><option value=\"oz\">oz<\/option><option value=\"lb\">lb<\/option><\/select><\/div>\n<div><label class=\"mwcc-label\" for=\"mwcc-cu-rate\">Rate unit<\/label><select id=\"mwcc-cu-rate\"><option value=\"mmy\" selected>mm\/year<\/option><option value=\"umy\">\u00b5m\/year<\/option><option value=\"mpy\">MPY<\/option><option value=\"ipy\">in\/year<\/option><\/select><\/div>\n<div><label class=\"mwcc-label\" for=\"mwcc-cu-area\">Area unit<\/label><select id=\"mwcc-cu-area\"><option value=\"mm2\">mm\u00b2<\/option><option value=\"cm2\">cm\u00b2<\/option><option value=\"m2\" selected>m\u00b2<\/option><option value=\"in2\">in\u00b2<\/option><option value=\"ft2\">ft\u00b2<\/option><\/select><\/div>\n<div><label class=\"mwcc-label\" for=\"mwcc-cu-dur\">Duration unit<\/label><select id=\"mwcc-cu-dur\"><option value=\"h\">Hours<\/option><option value=\"d\">Days<\/option><option value=\"mo\">Months<\/option><option value=\"y\" selected>Years<\/option><\/select><\/div>\n<div><label class=\"mwcc-label\" for=\"mwcc-cu-dt\">\u0394T unit<\/label><select id=\"mwcc-cu-dt\"><option value=\"C\" selected>\u0394\u00b0C (= \u0394K)<\/option><option value=\"F\">\u0394\u00b0F<\/option><\/select><\/div>\n<\/div>\n<div id=\"mwcc-crows\"><\/div>\n<div class=\"mwcc-actions\" style=\"justify-content:flex-start;margin-top:4px\"><button type=\"button\" class=\"mwcc-btn mwcc-btn-secondary mwcc-btn-sm\" id=\"mwcc-cadd\"><svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.2\" stroke-linecap=\"round\" aria-hidden=\"true\"><path d=\"M12 5v14M5 12h14\"\/><\/svg>Add material<\/button><\/div>\n<\/section>\n<p class=\"mwcc-form-err\" id=\"mwcc-form-err\" role=\"alert\"><\/p>\n<div class=\"mwcc-actions\">\n<button type=\"button\" class=\"mwcc-btn mwcc-btn-primary\" id=\"mwcc-calc\">Calculate<\/button>\n<\/div>\n<\/div>\n<\/form>\n<div class=\"mwcc-right\">\n<section class=\"mwcc-card\" id=\"mwcc-results\" aria-labelledby=\"mwcc-h-res\" tabindex=\"-1\" hidden>\n<div class=\"mwcc-res-head\">\n<h2 class=\"mwcc-card-title\" id=\"mwcc-h-res\"><span class=\"mwcc-ico\" aria-hidden=\"true\"><svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M3 3v18h18\"\/><path d=\"M7 15l4-4 3 3 5-6\"\/><\/svg><\/span>Calculation results<\/h2>\n<\/div>\n<div class=\"mwcc-runits\" id=\"mwcc-runits\">\n<div><label for=\"mwcc-ru-mass\">Show mass in<\/label><select id=\"mwcc-ru-mass\"><option value=\"mg\">mg<\/option><option value=\"g\">g<\/option><option value=\"kg\" selected>kg<\/option><option value=\"t\">metric t<\/option><option value=\"oz\">oz<\/option><option value=\"lb\">lb<\/option><\/select><\/div>\n<div><label for=\"mwcc-ru-vol\">Show volume in<\/label><select id=\"mwcc-ru-vol\"><option value=\"mm3\">mm\u00b3<\/option><option value=\"cm3\">cm\u00b3<\/option><option value=\"m3\" selected>m\u00b3<\/option><option value=\"mL\">mL<\/option><option value=\"L\">L<\/option><option value=\"in3\">in\u00b3<\/option><option value=\"ft3\">ft\u00b3<\/option><\/select><\/div>\n<div><label for=\"mwcc-ru-dens\">Show density in<\/label><select id=\"mwcc-ru-dens\"><option value=\"kgm3\" selected>kg\/m\u00b3<\/option><option value=\"gcm3\">g\/cm\u00b3<\/option><option value=\"lbft3\">lb\/ft\u00b3<\/option><option value=\"lbin3\">lb\/in\u00b3<\/option><\/select><\/div>\n<\/div>\n<div id=\"mwcc-res-body\"><\/div>\n<p class=\"mwcc-sr\" id=\"mwcc-live\" aria-live=\"polite\"><\/p>\n<\/section>\n<\/div>\n<\/div>\n<div class=\"mwcc-toast\" id=\"mwcc-toast\" role=\"status\" aria-live=\"polite\"><\/div>\n<\/div>\n<script>\n(function () {\n  \"use strict\";\n  \/* =====================================================================\n     UNIT CONVERSIONS \u2014 every value is converted to SI before calculation\n       mass -> kg, volume -> m3, area -> m2, length -> m, density -> kg\/m3,\n       expansion coefficient -> 1\/K, corrosion rate -> mm\/year, time -> years,\n       temperature -> K (differences: 1 K = 1 degC = 1.8 degF)\n     ===================================================================== *\/\n  var MASS = { mg: 1e-6, g: 1e-3, kg: 1, t: 1000, oz: 0.028349523125, lb: 0.45359237 };\n  var MASS_L = { mg: \"mg\", g: \"g\", kg: \"kg\", t: \"t\", oz: \"oz\", lb: \"lb\" };\n  var VOL = { mm3: 1e-9, cm3: 1e-6, m3: 1, mL: 1e-6, L: 1e-3, in3: 1.6387064e-5, ft3: 0.028316846592 };\n  var VOL_L = { mm3: \"mm\u00b3\", cm3: \"cm\u00b3\", m3: \"m\u00b3\", mL: \"mL\", L: \"L\", in3: \"in\u00b3\", ft3: \"ft\u00b3\" };\n  var AREA = { mm2: 1e-6, cm2: 1e-4, m2: 1, in2: 6.4516e-4, ft2: 0.09290304 };\n  var AREA_L = { mm2: \"mm\u00b2\", cm2: \"cm\u00b2\", m2: \"m\u00b2\", in2: \"in\u00b2\", ft2: \"ft\u00b2\" };\n  var LEN = { mm: 1e-3, cm: 1e-2, m: 1, \"in\": 0.0254, ft: 0.3048 };\n  var LEN_L = { mm: \"mm\", cm: \"cm\", m: \"m\", \"in\": \"in\", ft: \"ft\" };\n  var DENS = { kgm3: 1, gcm3: 1000, lbft3: 16.018463373960138, lbin3: 27679.904710203125 };\n  var DENS_L = { kgm3: \"kg\/m\u00b3\", gcm3: \"g\/cm\u00b3\", lbft3: \"lb\/ft\u00b3\", lbin3: \"lb\/in\u00b3\" };\n  \/* alpha entered as \"x 10^-6 per unit\"; factor converts to 1\/K (1\/degF = 1.8\/K) *\/\n  var ALPHA = { uC: 1e-6, uK: 1e-6, uF: 1.8e-6 };\n  var ALPHA_L = { uC: \"\u00d7 10\u207b\u2076 \/\u00b0C\", uK: \"\u00d7 10\u207b\u2076 \/K\", uF: \"\u00d7 10\u207b\u2076 \/\u00b0F\" };\n  \/* corrosion rate -> mm\/year: 1 MPY = 0.0254 mm\/y, 1 in\/y = 25.4 mm\/y, 1 um\/y = 0.001 mm\/y *\/\n  var RATE = { mmy: 1, umy: 0.001, mpy: 0.0254, ipy: 25.4 };\n  var RATE_L = { mmy: \"mm\/year\", umy: \"\u00b5m\/year\", mpy: \"MPY\", ipy: \"in\/year\" };\n  \/* time -> years: 1 year = 365 d = 8760 h (consistent with the 87.6 constant) *\/\n  var TIME = { h: 1 \/ 8760, d: 1 \/ 365, mo: 1 \/ 12, y: 1 };\n  var TIME_L = { h: \"h\", d: \"days\", mo: \"months\", y: \"years\" };\n  var TU_L = { C: \"\u00b0C\", F: \"\u00b0F\", K: \"K\" };\n  var DT = { C: 1, F: 1 \/ 1.8 };\n  var DT_L = { C: \"\u0394\u00b0C\", F: \"\u0394\u00b0F\" };\n  var MODE_NAMES = { 1: \"Temperature Effect Analysis\", 2: \"Corrosion Weight Loss\", 3: \"Combined Temperature and Corrosion Analysis\", 4: \"Material Weight Comparison\" };\n  \/* =====================================================================\n     MATERIAL DATABASE \u2014 approximate reference properties at 20 degC.\n     rho: kg\/m3; a: mean linear expansion coefficient (x10^-6 \/degC, ~20-100 degC);\n     lo\/hi: approximate range (degC) where the constant-alpha value is a reasonable\n     screening value; max: approximate melting \/ decomposition \/ softening limit (degC).\n     No corrosion rates are stored: rates must always be entered by the user.\n     ===================================================================== *\/\n  var SRC_M = \"Typical published handbook value (approximate). Verify against the supplier data sheet for your grade and temper.\";\n  var SRC_P = \"Typical handbook value for an unfilled grade (approximate). Polymer properties vary widely with grade, filler, crystallinity and moisture.\";\n  var MATERIALS = [\n    { id: \"cs\", cat: \"Carbon Steel\", name: \"Carbon Steel\", rho: 7850, a: 12.0, lo: -50, hi: 300, max: 1400 },\n    { id: \"ms\", cat: \"Carbon Steel\", name: \"Mild Steel\", rho: 7850, a: 12.0, lo: -50, hi: 300, max: 1400 },\n    { id: \"1018\", cat: \"Carbon Steel\", name: \"AISI 1018\", rho: 7870, a: 11.7, lo: -50, hi: 300, max: 1400 },\n    { id: \"1045\", cat: \"Carbon Steel\", name: \"AISI 1045\", rho: 7850, a: 11.5, lo: -50, hi: 300, max: 1400 },\n    { id: \"304\", cat: \"Stainless Steel\", name: \"Stainless Steel 304\", rho: 8000, a: 17.3, lo: -100, hi: 300, max: 1400 },\n    { id: \"316\", cat: \"Stainless Steel\", name: \"Stainless Steel 316\", rho: 8000, a: 16.0, lo: -100, hi: 300, max: 1370 },\n    { id: \"430\", cat: \"Stainless Steel\", name: \"Stainless Steel 430\", rho: 7750, a: 10.4, lo: -50, hi: 300, max: 1425 },\n    { id: \"321\", cat: \"Stainless Steel\", name: \"Stainless Steel 321\", rho: 7920, a: 16.6, lo: -100, hi: 300, max: 1370 },\n    { id: \"6061\", cat: \"Aluminum Alloys\", name: \"Aluminum 6061\", rho: 2700, a: 23.6, lo: -50, hi: 150, max: 580 },\n    { id: \"6063\", cat: \"Aluminum Alloys\", name: \"Aluminum 6063\", rho: 2690, a: 23.4, lo: -50, hi: 150, max: 615 },\n    { id: \"5052\", cat: \"Aluminum Alloys\", name: \"Aluminum 5052\", rho: 2680, a: 23.8, lo: -50, hi: 150, max: 605 },\n    { id: \"7075\", cat: \"Aluminum Alloys\", name: \"Aluminum 7075\", rho: 2810, a: 23.4, lo: -50, hi: 120, max: 475 },\n    { id: \"cu\", cat: \"Copper Alloys\", name: \"Copper\", rho: 8960, a: 16.8, lo: -50, hi: 300, max: 1080 },\n    { id: \"brass\", cat: \"Copper Alloys\", name: \"Brass\", rho: 8500, a: 19.5, lo: -50, hi: 300, max: 900 },\n    { id: \"bronze\", cat: \"Copper Alloys\", name: \"Bronze\", rho: 8800, a: 18.0, lo: -50, hi: 300, max: 950 },\n    { id: \"ti\", cat: \"Other Metals\", name: \"Titanium\", rho: 4510, a: 8.6, lo: -50, hi: 400, max: 1660 },\n    { id: \"ni\", cat: \"Other Metals\", name: \"Nickel\", rho: 8900, a: 13.3, lo: -50, hi: 300, max: 1450 },\n    { id: \"zn\", cat: \"Other Metals\", name: \"Zinc\", rho: 7140, a: 30.2, lo: -50, hi: 150, max: 419, note: \"Zinc has a hexagonal crystal structure and expands very differently along different axes. For textured or rolled material the isotropic approximation \u03b2 \u2248 3\u03b1 is rough.\" },\n    { id: \"ci\", cat: \"Other Metals\", name: \"Cast Iron (gray)\", rho: 7200, a: 10.8, lo: -50, hi: 300, max: 1150, note: \"Gray cast iron density and expansion vary with graphite content and section size.\" },\n    { id: \"mg\", cat: \"Other Metals\", name: \"Magnesium\", rho: 1740, a: 26.0, lo: -50, hi: 150, max: 650 },\n    { id: \"pvc\", cat: \"Plastics and Polymers\", name: \"PVC (rigid)\", rho: 1400, a: 70, lo: -10, hi: 60, max: 140, poly: true },\n    { id: \"abs\", cat: \"Plastics and Polymers\", name: \"ABS\", rho: 1050, a: 90, lo: -20, hi: 80, max: 105, poly: true },\n    { id: \"pp\", cat: \"Plastics and Polymers\", name: \"Polypropylene (PP)\", rho: 905, a: 120, lo: -10, hi: 90, max: 160, poly: true },\n    { id: \"pe\", cat: \"Plastics and Polymers\", name: \"Polyethylene (HDPE)\", rho: 955, a: 150, lo: -40, hi: 80, max: 130, poly: true },\n    { id: \"pa\", cat: \"Plastics and Polymers\", name: \"Nylon (PA6)\", rho: 1140, a: 85, lo: -30, hi: 80, max: 220, poly: true, note: \"Nylon absorbs several percent of water by mass, so its measured mass and dimensions change with humidity independently of temperature.\" },\n    { id: \"ptfe\", cat: \"Plastics and Polymers\", name: \"PTFE\", rho: 2200, a: 120, lo: 30, hi: 200, max: 327, poly: true, note: \"PTFE has crystalline transitions near 19 \u00b0C and 30 \u00b0C with a step change in volume. A constant \u03b1 is a poor approximation across these transitions.\" },\n    { id: \"peek\", cat: \"Plastics and Polymers\", name: \"PEEK\", rho: 1300, a: 47, lo: -40, hi: 140, max: 343, poly: true, note: \"Above the glass transition (about 143 \u00b0C) the expansion coefficient of PEEK roughly doubles.\" }\n  ];\n  var CATS = [\"Carbon Steel\", \"Stainless Steel\", \"Aluminum Alloys\", \"Copper Alloys\", \"Other Metals\", \"Plastics and Polymers\"];\n  var CUSTOM = { id: \"custom\", cat: \"Custom\", name: \"Custom Material\" };\n  function matById(id) {\n    if (id === \"custom\") { return CUSTOM; }\n    for (var i = 0; i < MATERIALS.length; i++) { if (MATERIALS[i].id === id) { return MATERIALS[i]; } }\n    return null;\n  }\n  \/* =====================================================================\n     NUMBER HELPERS \u2014 adaptive formatting, never shows NaN or Infinity\n     ===================================================================== *\/\n  function isNum(v) { return typeof v === \"number\" ? isFinite(v) : false; }\n  function clean(v) { return isNum(v) ? Number(v.toPrecision(12)) : v; }\n  var SUPS = { \"0\": \"\u2070\", \"1\": \"\u00b9\", \"2\": \"\u00b2\", \"3\": \"\u00b3\", \"4\": \"\u2074\", \"5\": \"\u2075\", \"6\": \"\u2076\", \"7\": \"\u2077\", \"8\": \"\u2078\", \"9\": \"\u2079\", \"-\": \"\u207b\", \"+\": \"\" };\n  function sup(s) { var o = \"\", i, c; for (i = 0; i < s.length; i++) { c = s.charAt(i); o += SUPS[c] !== undefined ? SUPS[c] : c; } return o; }\n  function group(s) {\n    var out = \"\";\n    while (s.length > 3) { out = \",\" + s.slice(-3) + out; s = s.slice(0, -3); }\n    return s + out;\n  }\n  \/* sig significant figures; scientific notation below 1e-4 or from 1e9 *\/\n  function fmt(v, sig) {\n    if (!isNum(v)) { return \"\u2014\"; }\n    if (sig === undefined) { sig = 6; }\n    if (v === 0) { return \"0\"; }\n    var neg = v < 0, a = Math.abs(v), s;\n    if (a < 1e-4 ? true : a >= 1e9) {\n      var p = a.toExponential(sig - 1).split(\"e\");\n      s = String(Number(p[0])) + \" \u00d7 10\" + sup(String(Number(p[1])));\n    } else {\n      s = String(Number(a.toPrecision(sig)));\n      if (s.indexOf(\"e\") < 0) { var parts = s.split(\".\"); parts[0] = group(parts[0]); s = parts.join(\".\"); }\n    }\n    return (neg ? \"\u2212\" : \"\") + s;\n  }\n  function fmtSigned(v, sig) { if (!isNum(v)) { return \"\u2014\"; } return (v > 0 ? \"+\" : \"\") + fmt(v, sig); }\n  function inStr(v) { return isNum(v) ? String(Number(v.toPrecision(10))) : \"\"; }\n  \/* absolute temperature conversions: K = C + 273.15 ; F = C x 9\/5 + 32 *\/\n  function toK(v, u) { if (u === \"C\") { return v + 273.15; } if (u === \"F\") { return (v - 32) * 5 \/ 9 + 273.15; } return v; }\n  function fromK(k, u) { if (u === \"C\") { return k - 273.15; } if (u === \"F\") { return (k - 273.15) * 9 \/ 5 + 32; } return k; }\n  \/* =====================================================================\n     CALCULATION ENGINE \u2014 pure functions, SI units in and out\n     ===================================================================== *\/\n  var Engine = {\n    \/* Thermal expansion of an isotropic solid with constant alpha (small strain):\n         dL = alpha * L0 * dT ; L = L0 * (1 + alpha * dT)\n         beta ~= 3 * alpha ; V = V0 * (1 + beta * dT)\n         mass is constant, so rho = m \/ V                                    *\/\n    thermal: function (V0, m, alpha, dT, L0) {\n      var beta = 3 * alpha, f = 1 + beta * dT, fl = 1 + alpha * dT;\n      if (!(f > 0)) { return { invalid: true }; }\n      if (!(fl > 0)) { return { invalid: true }; }\n      var V = V0 * f;\n      var r = { beta: beta, f: f, fl: fl, V: V, dV: V0 * beta * dT, dVpct: beta * dT * 100, rho0: m \/ V0, rho: m \/ V, drhoPct: (1 \/ f - 1) * 100, eps: alpha * dT, L: null, dL: null };\n      if (isNum(L0)) { r.L = L0 * fl; r.dL = alpha * L0 * dT; }\n      return r;\n    },\n    \/* Uniform corrosion (fixed exposed area, constant rate):\n         depth = CR * t ; volume loss = A * depth ; mass loss = rho * volume loss\n         equivalent weight-loss form: W(mg) = CR(mm\/y) * rho(g\/cm3) * A(cm2) * t(h) \/ 87.6 *\/\n    corrosion: function (rho, A, rate, tY, m0) {\n      var depth = rate * tY \/ 1000;          \/* m *\/\n      var Vl = A * depth;                    \/* m3 *\/\n      var ml = rho * Vl;                     \/* kg *\/\n      var Wmg = rate * (rho \/ 1000) * (A * 1e4) * (tY * 8760) \/ 87.6;\n      var kgY = rho * A * rate \/ 1000;       \/* kg lost per year *\/\n      return { depth: depth, Vl: Vl, ml: ml, Wmg: Wmg, rem: m0 - ml, pct: ml \/ m0 * 100, kgY: kgY, tFull: kgY > 0 ? m0 \/ kgY : null };\n    },\n    \/* Geometry: volume, exposable surfaces, characteristic length and smallest section *\/\n    geometry: function (shape, d) {\n      var PI = Math.PI, g = { V: 0, surf: [], len: null, minSec: null, formula: \"\" };\n      if (shape === \"plate\" ? true : shape === \"block\") {\n        var c = shape === \"plate\" ? d.T : d.H, cn = shape === \"plate\" ? \"t\" : \"H\";\n        g.V = d.L * d.W * c;\n        g.formula = \"V = L \u00d7 W \u00d7 \" + cn;\n        g.surf = [\n          { k: \"top\", label: \"Top face\", sub: \"L \u00d7 W\", a: d.L * d.W, def: true },\n          { k: \"bot\", label: \"Bottom face\", sub: \"L \u00d7 W\", a: d.L * d.W },\n          { k: \"side\", label: \"Long side faces (2)\", sub: \"2 \u00d7 L \u00d7 \" + cn, a: 2 * d.L * c },\n          { k: \"end\", label: \"End faces (2)\", sub: \"2 \u00d7 W \u00d7 \" + cn, a: 2 * d.W * c }\n        ];\n        g.len = d.L;\n        g.minSec = shape === \"plate\" ? d.T : Math.min(d.L, d.W, d.H);\n      } else if (shape === \"cyl\") {\n        g.V = PI * d.R * d.R * d.L; g.formula = \"V = \u03c0 \u00d7 r\u00b2 \u00d7 L\";\n        g.surf = [{ k: \"curv\", label: \"Curved outer surface\", sub: \"2\u03c0 \u00d7 r \u00d7 L\", a: 2 * PI * d.R * d.L, def: true }, { k: \"end\", label: \"End faces (2)\", sub: \"2 \u00d7 \u03c0 \u00d7 r\u00b2\", a: 2 * PI * d.R * d.R }];\n        g.len = d.L; g.minSec = d.R;\n      } else if (shape === \"hcyl\") {\n        g.V = PI * (d.Ro * d.Ro - d.Ri * d.Ri) * d.L; g.formula = \"V = \u03c0 \u00d7 (R\u2080\u00b2 \u2212 R\u1d62\u00b2) \u00d7 L\";\n        g.surf = [{ k: \"out\", label: \"Outer surface\", sub: \"2\u03c0 \u00d7 R\u2080 \u00d7 L\", a: 2 * PI * d.Ro * d.L, def: true }, { k: \"in\", label: \"Inner (bore) surface\", sub: \"2\u03c0 \u00d7 R\u1d62 \u00d7 L\", a: 2 * PI * d.Ri * d.L }, { k: \"end\", label: \"Annular end faces (2)\", sub: \"2\u03c0 \u00d7 (R\u2080\u00b2 \u2212 R\u1d62\u00b2)\", a: 2 * PI * (d.Ro * d.Ro - d.Ri * d.Ri) }];\n        g.len = d.L; g.minSec = d.Ro - d.Ri;\n      } else if (shape === \"sphere\") {\n        g.V = 4 \/ 3 * PI * Math.pow(d.R, 3); g.formula = \"V = (4\/3) \u00d7 \u03c0 \u00d7 r\u00b3\";\n        g.surf = [{ k: \"all\", label: \"Full spherical surface\", sub: \"4\u03c0 \u00d7 r\u00b2\", a: 4 * PI * d.R * d.R, def: true }];\n        g.len = 2 * d.R; g.minSec = d.R;\n      } else if (shape === \"bar\") {\n        g.V = PI * d.D * d.D * d.L \/ 4; g.formula = \"V = \u03c0 \u00d7 D\u00b2 \u00d7 L \/ 4\";\n        g.surf = [{ k: \"curv\", label: \"Curved outer surface\", sub: \"\u03c0 \u00d7 D \u00d7 L\", a: PI * d.D * d.L, def: true }, { k: \"end\", label: \"End faces (2)\", sub: \"2 \u00d7 \u03c0 \u00d7 D\u00b2 \/ 4\", a: PI * d.D * d.D \/ 2 }];\n        g.len = d.L; g.minSec = d.D \/ 2;\n      } else if (shape === \"rtube\") {\n        g.V = (d.OW * d.OH - d.IW * d.IH) * d.L; g.formula = \"V = (W\u2080 \u00d7 H\u2080 \u2212 W\u1d62 \u00d7 H\u1d62) \u00d7 L\";\n        g.surf = [{ k: \"out\", label: \"Outer surfaces\", sub: \"2 \u00d7 (W\u2080 + H\u2080) \u00d7 L\", a: 2 * (d.OW + d.OH) * d.L, def: true }, { k: \"in\", label: \"Inner surfaces\", sub: \"2 \u00d7 (W\u1d62 + H\u1d62) \u00d7 L\", a: 2 * (d.IW + d.IH) * d.L }, { k: \"end\", label: \"End faces (2)\", sub: \"2 \u00d7 (W\u2080H\u2080 \u2212 W\u1d62H\u1d62)\", a: 2 * (d.OW * d.OH - d.IW * d.IH) }];\n        g.len = d.L; g.minSec = Math.min((d.OW - d.IW) \/ 2, (d.OH - d.IH) \/ 2);\n      }\n      return g;\n    }\n  };\n  var SHAPE_DIMS = { plate: [\"L\", \"W\", \"T\"], block: [\"L\", \"W\", \"H\"], cyl: [\"R\", \"L\"], hcyl: [\"Ro\", \"Ri\", \"L\"], sphere: [\"R\"], bar: [\"D\", \"L\"], rtube: [\"OW\", \"OH\", \"IW\", \"IH\", \"L\"] };\n  var SHAPE_NAMES = { plate: \"Rectangular plate\", block: \"Rectangular block\", cyl: \"Solid cylinder\", hcyl: \"Hollow cylinder\", sphere: \"Solid sphere\", bar: \"Round bar\", rtube: \"Rectangular tube\" };\n  var DIM_LABEL = { L: \"length\", W: \"width\", T: \"thickness\", H: \"height\", R: \"radius\", Ro: \"outer radius\", Ri: \"inner radius\", D: \"diameter\", OW: \"outer width\", OH: \"outer height\", IW: \"inner width\", IH: \"inner height\" };\n  var DIM_IDS = [\"L\", \"W\", \"T\", \"H\", \"R\", \"Ro\", \"Ri\", \"D\", \"OW\", \"OH\", \"IW\", \"IH\"];\n  var CMP_FIELDS = [\n    { k: \"rho\", label: \"Density\", rule: \"pos\", unit: \"dens\" },\n    { k: \"alpha\", label: \"\u03b1\", rule: \"any\", unit: \"alpha\" },\n    { k: \"mass\", label: \"Initial mass\", rule: \"pos\", unit: \"mass\" },\n    { k: \"rate\", label: \"Corrosion rate\", rule: \"nonneg\", unit: \"rate\" },\n    { k: \"area\", label: \"Exposed area\", rule: \"pos\", unit: \"area\" },\n    { k: \"dur\", label: \"Exposure duration\", rule: \"nonneg\", unit: \"dur\" },\n    { k: \"dT\", label: \"Temperature change \u0394T\", rule: \"any\", unit: \"dt\" }\n  ];\n  var CMP_COLORS = [\"#1a4d8f\", \"#c2410c\", \"#0f766e\", \"#7c3aed\", \"#a16207\"];\n  \/* =====================================================================\n     USER INTERFACE\n     ===================================================================== *\/\n  function init() {\n    var root = document.getElementById(\"mwcc-calculator\");\n    if (!root) { return; }\n    if (root.getAttribute(\"data-mwcc-init\") === \"1\") { return; }\n    root.setAttribute(\"data-mwcc-init\", \"1\");\n    var SVGNS = \"http:\/\/www.w3.org\/2000\/svg\";\n    function q(id) { return root.querySelector(\"#\" + id); }\n    function h(tag, a, kids) {\n      var n = document.createElement(tag);\n      if (a) { Object.keys(a).forEach(function (k) { if (k === \"class\") { n.className = a[k]; } else if (k === \"text\") { n.textContent = a[k]; } else { n.setAttribute(k, a[k]); } }); }\n      add(n, kids);\n      return n;\n    }\n    function add(n, kids) {\n      if (kids === undefined ? true : kids === null) { return; }\n      if (Array.isArray(kids)) { kids.forEach(function (k) { add(n, k); }); return; }\n      if (typeof kids === \"string\" ? true : typeof kids === \"number\") { n.appendChild(document.createTextNode(String(kids))); return; }\n      n.appendChild(kids);\n    }\n    function s(tag, a, text) {\n      var n = document.createElementNS(SVGNS, tag);\n      if (a) { Object.keys(a).forEach(function (k) { n.setAttribute(k, a[k]); }); }\n      if (text !== undefined) { n.textContent = text; }\n      return n;\n    }\n    function clear(n) { while (n.firstChild) { n.removeChild(n.firstChild); } }\n    var ICONS = {\n      warn: \"M12 3l9.5 17H2.5z M12 10v4.5 M12 17.2v.3\",\n      bad: \"M12 3a9 9 0 1 0 0 18a9 9 0 1 0 0-18z M9 9l6 6 M15 9l-6 6\",\n      ok: \"M12 3a9 9 0 1 0 0 18a9 9 0 1 0 0-18z M8 12.5l2.8 2.8L16.5 9.5\",\n      info: \"M12 3a9 9 0 1 0 0 18a9 9 0 1 0 0-18z M12 11v5.5 M12 7.8v.3\"\n    };\n    function icon(tone) {\n      var sv = s(\"svg\", { viewBox: \"0 0 24 24\", fill: \"none\", stroke: \"currentColor\", \"stroke-width\": \"2\", \"stroke-linecap\": \"round\", \"stroke-linejoin\": \"round\", \"aria-hidden\": \"true\" });\n      sv.appendChild(s(\"path\", { d: ICONS[tone] ? ICONS[tone] : ICONS.info }));\n      return sv;\n    }\n    var state = { shown: false, stepsOpen: true, edited: false, surfSel: {}, cmpRows: [], cmpMetric: \"loss\", R: null, touched: {}, liveTimer: null, toastTimer: null, chartTimer: null, lastW: 0 };\n    function mode() { var r = root.querySelector('input[name=\"mwcc-mode\"]:checked'); return r ? Number(r.value) : 1; }\n    function radio(name) { var r = root.querySelector('input[name=\"' + name + '\"]:checked'); return r ? r.value : null; }\n    function setRadio(name, val) { var r = root.querySelector('input[name=\"' + name + '\"][value=\"' + val + '\"]'); if (r) { r.checked = true; } }\n    function val(id) { return q(id).value; }\n    function setVal(id, v) { q(id).value = v; }\n    \/* ---------- material selection ---------- *\/\n    function buildCats() {\n      var sel = q(\"mwcc-cat\");\n      clear(sel);\n      sel.appendChild(h(\"option\", { value: \"all\", text: \"All categories\" }));\n      CATS.forEach(function (c) { sel.appendChild(h(\"option\", { value: c, text: c })); });\n      sel.appendChild(h(\"option\", { value: \"Custom\", text: \"Custom Material\" }));\n    }\n    function buildMats() {\n      var sel = q(\"mwcc-mat\"), cur = sel.value, cat = val(\"mwcc-cat\"), term = String(val(\"mwcc-search\")).trim().toLowerCase(), count = 0, has = false;\n      clear(sel);\n      CATS.forEach(function (c) {\n        if (cat === \"all\" ? false : cat !== c) { return; }\n        var og = null;\n        MATERIALS.forEach(function (m) {\n          if (m.cat !== c) { return; }\n          if (term === \"\" ? false : (m.name.toLowerCase().indexOf(term) < 0 ? m.cat.toLowerCase().indexOf(term) < 0 : false)) { return; }\n          if (!og) { og = h(\"optgroup\", { label: c }); sel.appendChild(og); }\n          og.appendChild(h(\"option\", { value: m.id, text: m.name + \" (\" + fmt(m.rho, 4) + \" kg\/m\u00b3)\" }));\n          count++;\n          if (m.id === cur) { has = true; }\n        });\n      });\n      sel.appendChild(h(\"option\", { value: \"custom\", text: \"Custom Material (enter your own values)\" }));\n      if (cur === \"custom\") { has = true; }\n      q(\"mwcc-search-hint\").textContent = term === \"\" ? \"\" : (count === 0 ? \"No materials match. Custom Material is still available.\" : count + \" material\" + (count === 1 ? \"\" : \"s\") + \" found.\");\n      if (has) { sel.value = cur; return false; }\n      sel.value = count > 0 ? sel.options[0].value : \"custom\";\n      return true;\n    }\n    function applyMaterial() {\n      var m = matById(val(\"mwcc-mat\"));\n      q(\"mwcc-f-cname\").hidden = m.id !== \"custom\";\n      if (m.id !== \"custom\") {\n        setVal(\"mwcc-dens\", inStr(m.rho \/ DENS[val(\"mwcc-dens-u\")]));\n        setVal(\"mwcc-alpha\", inStr(m.a * 1e-6 \/ ALPHA[val(\"mwcc-alpha-u\")]));\n      }\n      state.edited = false;\n      matInfo();\n    }\n    function matInfo() {\n      var box = q(\"mwcc-matinfo\"), m = matById(val(\"mwcc-mat\"));\n      clear(box);\n      if (m.id === \"custom\") {\n        add(box, [h(\"b\", { text: \"Custom material. \" }), \"Enter the density and linear expansion coefficient for your material at the reference temperature. The corrosion rate is always entered separately and is never assumed from the material type.\"]);\n        return;\n      }\n      add(box, [h(\"b\", { text: m.name }), (m.name === m.cat ? \"\" : \" \u00b7 \" + m.cat) + (state.edited ? \" \" : \"\"), state.edited ? h(\"span\", { class: \"mwcc-badge\", text: \"Values edited\" }) : null, h(\"br\"),\n        \"Reference: \u03c1\u2080 \u2248 \" + fmt(m.rho, 4) + \" kg\/m\u00b3 at 20 \u00b0C \u00b7 \u03b1 \u2248 \" + fmt(m.a, 3) + \" \u00d7 10\u207b\u2076 \/\u00b0C \u00b7 approximate range of use \" + fmt(m.lo) + \" to \" + fmt(m.hi) + \" \u00b0C\", h(\"br\"),\n        h(\"span\", { text: \"Source: \" + (m.poly ? SRC_P : SRC_M) })]);\n      if (m.note) { add(box, [h(\"br\"), h(\"span\", { text: \"Note: \" + m.note })]); }\n    }\n    \/* ---------- geometry surfaces ---------- *\/\n    function surfSel(shape) {\n      if (!state.surfSel[shape]) {\n        var o = {};\n        Engine.geometry(shape, { L: 1, W: 1, T: 1, H: 1, R: 1, Ro: 2, Ri: 1, D: 1, OW: 2, OH: 2, IW: 1, IH: 1 }).surf.forEach(function (sf) { o[sf.k] = sf.def ? true : false; });\n        state.surfSel[shape] = o;\n      }\n      return state.surfSel[shape];\n    }\n    function buildSurfs() {\n      var shape = val(\"mwcc-shape\"), box = q(\"mwcc-surfs\"), sel = surfSel(shape);\n      clear(box);\n      Engine.geometry(shape, { L: 1, W: 1, T: 1, H: 1, R: 1, Ro: 2, Ri: 1, D: 1, OW: 2, OH: 2, IW: 1, IH: 1 }).surf.forEach(function (sf) {\n        var cb = h(\"input\", { type: \"checkbox\", id: \"mwcc-sf-\" + sf.k, \"data-mwcc-surf\": sf.k });\n        cb.checked = sel[sf.k] ? true : false;\n        box.appendChild(h(\"label\", { class: \"mwcc-check\", \"for\": \"mwcc-sf-\" + sf.k }, [cb, h(\"span\", {}, [sf.label, h(\"small\", { text: sf.sub })])]));\n      });\n    }\n    \/* ---------- visibility per mode ---------- *\/\n    function updateVisibility() {\n      var m = mode(), basis = radio(\"mwcc-basis\"), shape = val(\"mwcc-shape\");\n      var needT = m === 1 ? true : m === 3, needC = m === 2 ? true : m === 3;\n      q(\"mwcc-sec-mat\").hidden = m === 4;\n      q(\"mwcc-sec-prop\").hidden = m === 4;\n      q(\"mwcc-sec-temp\").hidden = !needT;\n      q(\"mwcc-sec-corr\").hidden = !needC;\n      q(\"mwcc-sec-cmp\").hidden = m !== 4;\n      q(\"mwcc-f-alpha\").hidden = !needT;\n      q(\"mwcc-f-len\").hidden = !needT;\n      q(\"mwcc-f-areagrp\").hidden = !needC;\n      q(\"mwcc-f-mass\").hidden = basis !== \"mass\";\n      q(\"mwcc-f-vol\").hidden = basis !== \"volume\";\n      q(\"mwcc-f-geo\").hidden = basis !== \"geom\";\n      var ag = q(\"mwcc-a-geo\");\n      ag.disabled = basis !== \"geom\";\n      if (ag.disabled ? ag.checked : false) { setRadio(\"mwcc-abasis\", \"manual\"); }\n      var ab = radio(\"mwcc-abasis\");\n      q(\"mwcc-f-area\").hidden = ab !== \"manual\";\n      q(\"mwcc-f-surfs\").hidden = ab !== \"geom\";\n      var dims = SHAPE_DIMS[shape];\n      Array.prototype.forEach.call(root.querySelectorAll(\"[data-mwcc-dim]\"), function (el) { el.hidden = dims.indexOf(el.getAttribute(\"data-mwcc-dim\")) < 0; });\n      q(\"mwcc-runits\").hidden = false;\n      var firstSet = false;\n      Array.prototype.forEach.call(root.querySelectorAll(\".mwcc-inputs > .mwcc-group\"), function (g) { if (!firstSet ? !g.hidden : false) { g.classList.add(\"mwcc-first\"); firstSet = true; } else { g.classList.remove(\"mwcc-first\"); } });\n      q(\"mwcc-cadd\").disabled = state.cmpRows.length >= 5;\n    }\n    \/* ---------- reading and validating inputs ---------- *\/\n    function readRaw(el) {\n      var str = String(el.value).trim();\n      if (str === \"\") { return { empty: true, bad: el.validity ? el.validity.badInput : false, val: null }; }\n      var n = Number(str);\n      if (!isNum(n)) { return { empty: false, bad: true, val: null }; }\n      return { empty: false, bad: false, val: n };\n    }\n    \/* rule: \"pos\" (> 0), \"nonneg\" (>= 0), \"any\" (any finite number) *\/\n    function need(E, missing, id, label, rule, optional) {\n      var r = readRaw(q(id)), cap = label.charAt(0).toUpperCase() + label.slice(1);\n      if (r.bad) { E[id] = \"Enter a valid number for the \" + label + \".\"; return null; }\n      if (r.empty) { if (!optional) { E[id] = \"Enter the \" + label + \".\"; missing.push(label); } return null; }\n      if (rule === \"pos\") { if (r.val < 0) { E[id] = cap + \" cannot be negative.\"; return null; } if (r.val === 0) { E[id] = cap + \" must be greater than zero.\"; return null; } }\n      if (rule === \"nonneg\") { if (r.val < 0) { E[id] = cap + \" cannot be negative.\"; return null; } }\n      return r.val;\n    }\n    function validateMain(m) {\n      var E = {}, missing = [], v = { mode: m, formErr: \"\" }, x;\n      var needT = m === 1 ? true : m === 3, needC = m === 2 ? true : m === 3;\n      v.needT = needT; v.needC = needC;\n      v.mat = matById(val(\"mwcc-mat\"));\n      var cn = String(val(\"mwcc-cname\")).trim();\n      v.matName = v.mat.id === \"custom\" ? (cn === \"\" ? \"Custom Material\" : cn) : v.mat.name + (state.edited ? \" (edited values)\" : \"\");\n      \/* density *\/\n      v.dU = val(\"mwcc-dens-u\");\n      x = need(E, missing, \"mwcc-dens\", \"material density\", \"pos\");\n      v.rho = x === null ? null : x * DENS[v.dU]; v.rhoIn = x;\n      \/* expansion coefficient *\/\n      v.aU = val(\"mwcc-alpha-u\");\n      if (needT) {\n        x = need(E, missing, \"mwcc-alpha\", \"expansion coefficient\", \"any\");\n        if (x !== null) {\n          if (Math.abs(x * ALPHA[v.aU]) > 1e-3) { E[\"mwcc-alpha\"] = \"This coefficient is unrealistically large for a solid. Check the value and unit (the field is in \u00d7 10\u207b\u2076).\"; }\n          else { v.alpha = x * ALPHA[v.aU]; v.alphaIn = x; }\n        }\n      }\n      \/* initial quantity *\/\n      v.basis = radio(\"mwcc-basis\");\n      v.mU = val(\"mwcc-mass-u\"); v.vU = val(\"mwcc-vol-u\");\n      if (v.basis === \"mass\") {\n        x = need(E, missing, \"mwcc-mass\", \"initial mass\", \"pos\");\n        if (x !== null) { v.m0 = x * MASS[v.mU]; v.mIn = x; if (isNum(v.rho)) { v.V0 = v.m0 \/ v.rho; } }\n      } else if (v.basis === \"volume\") {\n        x = need(E, missing, \"mwcc-vol\", \"initial volume\", \"pos\");\n        if (x !== null) { v.V0 = x * VOL[v.vU]; v.vIn = x; if (isNum(v.rho)) { v.m0 = v.rho * v.V0; } }\n      } else {\n        v.shape = val(\"mwcc-shape\"); v.gU = val(\"mwcc-g-u\");\n        var d = {}, okD = true;\n        SHAPE_DIMS[v.shape].forEach(function (k) {\n          var y = need(E, missing, \"mwcc-g-\" + k, DIM_LABEL[k], \"pos\");\n          if (y === null) { okD = false; } else { d[k] = y * LEN[v.gU]; }\n        });\n        if (okD) {\n          if (v.shape === \"hcyl\") { if (d.Ri >= d.Ro) { E[\"mwcc-g-Ri\"] = \"Inner radius must be smaller than the outer radius.\"; okD = false; } }\n          if (v.shape === \"rtube\") {\n            if (d.IW >= d.OW) { E[\"mwcc-g-IW\"] = \"Inner width must be smaller than the outer width.\"; okD = false; }\n            if (d.IH >= d.OH) { E[\"mwcc-g-IH\"] = \"Inner height must be smaller than the outer height.\"; okD = false; }\n          }\n        }\n        if (okD) {\n          v.dims = d;\n          v.G = Engine.geometry(v.shape, d);\n          if (!(v.G.V > 0)) { E[\"mwcc-g-L\"] = \"These dimensions do not give a positive volume.\"; v.G = null; }\n          else { v.V0 = v.G.V; if (isNum(v.rho)) { v.m0 = v.rho * v.V0; } }\n        }\n      }\n      \/* initial length (optional) *\/\n      v.lU = val(\"mwcc-len-u\"); v.L0 = null; v.L0src = null;\n      if (needT) {\n        x = need(E, missing, \"mwcc-len\", \"initial length\", \"pos\", true);\n        if (x !== null) { v.L0 = x * LEN[v.lU]; v.L0src = \"entered\"; }\n        else if (E[\"mwcc-len\"] ? false : (v.G ? true : false)) { v.L0 = v.G.len; v.L0src = v.shape === \"sphere\" ? \"geometry (diameter)\" : \"geometry (length)\"; }\n      }\n      \/* exposed area *\/\n      v.abasis = radio(\"mwcc-abasis\"); v.arU = val(\"mwcc-area-u\");\n      if (needC) {\n        if (v.abasis === \"geom\") {\n          if (v.G) {\n            var sel = surfSel(v.shape), A = 0, names = [];\n            v.G.surf.forEach(function (sf) { if (sel[sf.k]) { A += sf.a; names.push(sf.label); } });\n            if (names.length === 0) { E[\"mwcc-surfs\"] = \"Select at least one exposed surface.\"; }\n            else { v.A = A; v.surfNames = names; }\n          }\n        } else {\n          x = need(E, missing, \"mwcc-area\", \"exposed surface area\", \"pos\");\n          if (x !== null) { v.A = x * AREA[v.arU]; v.aIn = x; }\n        }\n      }\n      \/* temperatures (reject below absolute zero) *\/\n      v.tU = val(\"mwcc-tu\");\n      if (needT) {\n        var t1 = need(E, missing, \"mwcc-t1\", \"initial temperature\", \"any\");\n        var t2 = need(E, missing, \"mwcc-t2\", \"final temperature\", \"any\");\n        var AZ = \"Temperature cannot be below absolute zero (0 K = \u2212273.15 \u00b0C = \u2212459.67 \u00b0F).\";\n        if (t1 !== null) { v.T1K = toK(t1, v.tU); v.t1In = t1; if (v.T1K < 0) { E[\"mwcc-t1\"] = AZ; } }\n        if (t2 !== null) { v.T2K = toK(t2, v.tU); v.t2In = t2; if (v.T2K < 0) { E[\"mwcc-t2\"] = AZ; } }\n        if (isNum(v.T1K) ? isNum(v.T2K) : false) {\n          \/* temperature DIFFERENCE, never an absolute temperature: dK = d degC *\/\n          v.dT = v.T2K - v.T1K;\n          if (v.mat.max) {\n            [[\"mwcc-t1\", v.T1K], [\"mwcc-t2\", v.T2K]].forEach(function (p) {\n              if (p[1] - 273.15 > v.mat.max) { if (!E[p[0]]) { E[p[0]] = \"Above the approximate melting, decomposition or softening limit of \" + v.mat.name + \" (about \" + fmt(v.mat.max, 4) + \" \u00b0C). The solid-state expansion model does not apply.\"; } }\n            });\n          }\n          if (isNum(v.alpha)) {\n            if (!(1 + 3 * v.alpha * v.dT > 0)) { E[\"mwcc-t2\"] = \"This temperature change gives a physically invalid (zero or negative) volume with the entered coefficient.\"; }\n          }\n        }\n      }\n      \/* corrosion *\/\n      v.rU = val(\"mwcc-rate-u\"); v.duU = val(\"mwcc-dur-u\");\n      if (needC) {\n        x = need(E, missing, \"mwcc-rate\", \"corrosion rate\", \"nonneg\");\n        if (x !== null) { v.rate = x * RATE[v.rU]; v.rateIn = x; }\n        x = need(E, missing, \"mwcc-dur\", \"exposure duration\", \"nonneg\");\n        if (x !== null) { v.tY = x * TIME[v.duU]; v.durIn = x; }\n        if ([v.rho, v.A, v.rate, v.tY, v.m0].every(isNum)) {\n          var ml = v.rho * v.A * v.rate * v.tY \/ 1000;\n          if (ml >= v.m0) {\n            v.formErr = \"The estimated corrosion mass loss (\" + fmt(ml, 5) + \" kg) \" + (ml > v.m0 ? \"exceeds\" : \"equals\") + \" the available initial mass (\" + fmt(v.m0, 5) + \" kg). Reduce the corrosion rate, exposure duration or exposed area, or check the units.\";\n            E[\"mwcc-rate\"] = \"Corrosion loss would consume all of the material (see message below).\";\n            E[\"mwcc-dur\"] = \"Reduce the exposure duration or check its unit.\";\n          }\n        }\n      }\n      v.E = E; v.missing = missing; v.ok = Object.keys(E).length === 0;\n      return v;\n    }\n    \/* =====================================================================\n       COMPARISON ROWS (mode 4)\n       ===================================================================== *\/\n    function cmpU() { return { dens: val(\"mwcc-cu-dens\"), alpha: val(\"mwcc-cu-alpha\"), mass: val(\"mwcc-cu-mass\"), rate: val(\"mwcc-cu-rate\"), area: val(\"mwcc-cu-area\"), dur: val(\"mwcc-cu-dur\"), dt: val(\"mwcc-cu-dt\") }; }\n    function cmpRowFromPreset(id, U, base) {\n      var m = matById(id), r = base ? base : { preset: id, name: \"\", rho: \"\", alpha: \"\", mass: \"100\", rate: \"0.1\", area: \"0.5\", dur: \"5\", dT: \"100\" };\n      r.preset = id;\n      if (m.id !== \"custom\") {\n        r.name = m.name;\n        r.rho = inStr(m.rho \/ DENS[U.dens]);\n        r.alpha = inStr(m.a * 1e-6 \/ ALPHA[U.alpha]);\n      }\n      return r;\n    }\n    function defaultCmpRows() {\n      var U = { dens: \"kgm3\", alpha: \"uC\" };\n      return [\"cs\", \"304\", \"6061\"].map(function (id) { return cmpRowFromPreset(id, U); });\n    }\n    function presetOptions(selected) {\n      var sel = h(\"select\", {});\n      CATS.forEach(function (c) {\n        var og = h(\"optgroup\", { label: c });\n        MATERIALS.forEach(function (m) { if (m.cat === c) { og.appendChild(h(\"option\", { value: m.id, text: m.name })); } });\n        sel.appendChild(og);\n      });\n      sel.appendChild(h(\"option\", { value: \"custom\", text: \"Custom Material\" }));\n      sel.value = selected;\n      return sel;\n    }\n    function renderCmpRows() {\n      var box = q(\"mwcc-crows\"), U = cmpU();\n      clear(box);\n      var UL = { dens: DENS_L[U.dens], alpha: ALPHA_L[U.alpha], mass: MASS_L[U.mass], rate: RATE_L[U.rate], area: AREA_L[U.area], dur: TIME_L[U.dur], dt: DT_L[U.dt] };\n      state.cmpRows.forEach(function (r, i) {\n        var pid = \"mwcc-c\" + i + \"-\";\n        var ps = presetOptions(r.preset);\n        ps.id = pid + \"preset\"; ps.setAttribute(\"data-mwcc-c\", i); ps.setAttribute(\"data-mwcc-ck\", \"preset\");\n        var nm = h(\"input\", { type: \"text\", id: pid + \"name\", maxlength: \"60\", autocomplete: \"off\", \"data-mwcc-c\": i, \"data-mwcc-ck\": \"name\", placeholder: \"Material \" + (i + 1) });\n        nm.value = r.name;\n        var rm = h(\"button\", { type: \"button\", class: \"mwcc-btn mwcc-btn-sm mwcc-btn-danger\", \"data-mwcc-crm\": i, \"aria-label\": \"Remove material \" + (i + 1) }, \"Remove\");\n        if (state.cmpRows.length <= 1) { rm.disabled = true; }\n        var fs = h(\"fieldset\", { class: \"mwcc-crow\" }, [\n          h(\"legend\", { class: \"mwcc-sr\", text: \"Material \" + (i + 1) }),\n          h(\"div\", { class: \"mwcc-crow-head\" }, [h(\"b\", {}, [h(\"span\", { class: \"mwcc-dot\", style: \"background:\" + CMP_COLORS[i % 5] }), \"Material \" + (i + 1)]), rm]),\n          h(\"div\", { class: \"mwcc-grid mwcc-grid-2\" }, [\n            h(\"div\", { class: \"mwcc-field\" }, [h(\"label\", { class: \"mwcc-label\", \"for\": pid + \"preset\", text: \"Reference material\" }), ps]),\n            h(\"div\", { class: \"mwcc-field\" }, [h(\"label\", { class: \"mwcc-label\", \"for\": pid + \"name\", text: \"Material name\" }), nm])\n          ])\n        ]);\n        var grid = h(\"div\", { class: \"mwcc-grid mwcc-grid-2 mwcc-grid-4\", style: \"margin-top:10px\" });\n        CMP_FIELDS.forEach(function (f) {\n          var inp = h(\"input\", { type: \"number\", inputmode: \"decimal\", step: \"any\", id: pid + f.k, \"data-mwcc-c\": i, \"data-mwcc-ck\": f.k, \"aria-describedby\": pid + f.k + \"-err\" });\n          if (f.rule !== \"any\") { inp.setAttribute(\"min\", \"0\"); }\n          inp.value = r[f.k];\n          grid.appendChild(h(\"div\", { class: \"mwcc-field\" }, [\n            h(\"label\", { class: \"mwcc-label\", \"for\": pid + f.k, text: f.label + \" (\" + UL[f.unit] + \")\" }),\n            inp,\n            h(\"span\", { class: \"mwcc-error\", id: pid + f.k + \"-err\", \"aria-live\": \"polite\" })\n          ]));\n        });\n        fs.appendChild(grid);\n        box.appendChild(fs);\n      });\n      q(\"mwcc-cadd\").disabled = state.cmpRows.length >= 5;\n    }\n    function validateCmp() {\n      var U = cmpU(), E = {}, missing = [], rows = [], v = { mode: 4, formErr: \"\", U: U };\n      state.cmpRows.forEach(function (r, i) {\n        var pid = \"mwcc-c\" + i + \"-\", o = { i: i, ok: true }, x;\n        o.name = String(r.name).trim() === \"\" ? \"Material \" + (i + 1) : String(r.name).trim();\n        o.preset = r.preset;\n        CMP_FIELDS.forEach(function (f) {\n          x = need(E, missing, pid + f.k, f.label.toLowerCase() + \" for material \" + (i + 1), f.rule);\n          if (x === null) { o.ok = false; } else { o[f.k + \"In\"] = x; }\n        });\n        if (o.ok) {\n          o.rho = o.rhoIn * DENS[U.dens]; o.alpha = o.alphaIn * ALPHA[U.alpha]; o.m0 = o.massIn * MASS[U.mass];\n          o.rate = o.rateIn * RATE[U.rate]; o.A = o.areaIn * AREA[U.area]; o.tY = o.durIn * TIME[U.dur]; o.dT = o.dTIn * DT[U.dt];\n          if (Math.abs(o.alpha) > 1e-3) { E[pid + \"alpha\"] = \"Unrealistically large coefficient (the field is in \u00d7 10\u207b\u2076).\"; o.ok = false; }\n          else if (!(1 + 3 * o.alpha * o.dT > 0)) { E[pid + \"dT\"] = \"Physically invalid thermal result for this \u0394T and \u03b1.\"; o.ok = false; }\n          else if (o.rho * o.A * o.rate * o.tY \/ 1000 >= o.m0) { E[pid + \"rate\"] = \"Estimated corrosion loss reaches or exceeds the initial mass. Check the rate, area, duration and units.\"; o.ok = false; }\n        }\n        rows.push(o);\n      });\n      v.rows = rows; v.E = E; v.missing = missing; v.ok = Object.keys(E).length === 0;\n      return v;\n    }\n    \/* ---------- error display ---------- *\/\n    var MAIN_ERR_IDS = [\"mwcc-dens\", \"mwcc-alpha\", \"mwcc-mass\", \"mwcc-vol\", \"mwcc-len\", \"mwcc-area\", \"mwcc-t1\", \"mwcc-t2\", \"mwcc-rate\", \"mwcc-dur\", \"mwcc-surfs\"].concat(DIM_IDS.map(function (k) { return \"mwcc-g-\" + k; }));\n    function errIds() {\n      var ids = MAIN_ERR_IDS.slice();\n      state.cmpRows.forEach(function (r, i) { CMP_FIELDS.forEach(function (f) { ids.push(\"mwcc-c\" + i + \"-\" + f.k); }); });\n      return ids;\n    }\n    function showErrors(E, force) {\n      errIds().forEach(function (id) {\n        var el = q(id), er = q(id + \"-err\");\n        if (!el) { return; }\n        var msg = E[id] ? (force ? E[id] : (state.touched[id] ? E[id] : \"\")) : \"\";\n        if (er) { er.textContent = msg; }\n        if (el.tagName === \"DIV\") { return; }\n        if (msg) { el.classList.add(\"mwcc-invalid\"); el.setAttribute(\"aria-invalid\", \"true\"); }\n        else { el.classList.remove(\"mwcc-invalid\"); el.removeAttribute(\"aria-invalid\"); }\n      });\n    }\n    \/* ---------- live helper outputs under the inputs ---------- *\/\n    function helpers(v) {\n      var g = q(\"mwcc-geo-out\"), so = q(\"mwcc-surf-out\"), dto = q(\"mwcc-dt-out\");\n      g.textContent = \"\"; so.textContent = \"\"; dto.textContent = \"\";\n      if (v.mode === 4) { return; }\n      if (v.G) {\n        g.textContent = SHAPE_NAMES[v.shape] + \": \" + v.G.formula + \" = \" + fmt(v.G.V, 6) + \" m\u00b3 (\" + fmt(v.G.V * 1e6, 6) + \" cm\u00b3)\" + (isNum(v.m0) ? \" \u00b7 m\u2080 = \u03c1\u2080 \u00d7 V\u2080 = \" + fmt(v.m0, 6) + \" kg\" : \"\");\n      }\n      if (v.needC ? (v.abasis === \"geom\" ? isNum(v.A) : false) : false) {\n        so.textContent = \"Exposed area A = \" + fmt(v.A, 6) + \" m\u00b2 (\" + fmt(v.A * 1e4, 6) + \" cm\u00b2) from: \" + v.surfNames.join(\", \") + \".\";\n      }\n      if (v.needT ? isNum(v.dT) : false) {\n        var u = v.tU, o = u === \"C\" ? [\"F\", \"K\"] : (u === \"F\" ? [\"C\", \"K\"] : [\"C\", \"F\"]);\n        var dtTxt = u === \"F\" ? fmtSigned(v.dT * 1.8, 6) + \" \u0394\u00b0F = \" + fmtSigned(v.dT, 6) + \" K (\u0394\u00b0C)\" : fmtSigned(v.dT, 6) + (u === \"K\" ? \" K\" : \" \u0394\u00b0C\") + \" = \" + fmtSigned(v.dT, 6) + (u === \"K\" ? \" \u0394\u00b0C\" : \" K\") + \" = \" + fmtSigned(v.dT * 1.8, 6) + \" \u0394\u00b0F\";\n        dto.textContent = \"\u0394T = T\u2082 \u2212 T\u2081 = \" + dtTxt + \". T\u2081 = \" + o.map(function (k) { return fmt(fromK(v.T1K, k), 6) + \" \" + TU_L[k]; }).join(\" = \") + \"; T\u2082 = \" + o.map(function (k) { return fmt(fromK(v.T2K, k), 6) + \" \" + TU_L[k]; }).join(\" = \") + \".\";\n      }\n    }\n    \/* =====================================================================\n       REPORT BUILDING\n       ===================================================================== *\/\n    function RU() { return { m: val(\"mwcc-ru-mass\"), v: val(\"mwcc-ru-vol\"), d: val(\"mwcc-ru-dens\") }; }\n    function fm(kg, sig) { var u = RU().m; return fmt(kg \/ MASS[u], sig) + \" \" + MASS_L[u]; }\n    function fmS(kg, sig) { var u = RU().m; return fmtSigned(kg \/ MASS[u], sig) + \" \" + MASS_L[u]; }\n    function fv(m3, sig) { var u = RU().v; return fmt(m3 \/ VOL[u], sig === undefined ? 7 : sig) + \" \" + VOL_L[u]; }\n    function fvS(m3, sig) { var u = RU().v; return fmtSigned(m3 \/ VOL[u], sig === undefined ? 6 : sig) + \" \" + VOL_L[u]; }\n    function fd(kgm3, sig) { var u = RU().d; return fmt(kgm3 \/ DENS[u], sig) + \" \" + DENS_L[u]; }\n    function fdT(dK, u) { return fmtSigned(u === \"F\" ? dK * 1.8 : dK, 6) + \" \" + (u === \"K\" ? \"K\" : \"\u0394\" + TU_L[u]) + (u === \"C\" ? \" (\" + fmtSigned(dK, 6) + \" K)\" : \"\"); }\n    function fT(K, u) { return fmt(fromK(K, u), 6) + \" \" + TU_L[u]; }\n    function fDepth(m) { var mm = m * 1000; return mm < 0.1 ? fmt(mm * 1000, 5) + \" \u00b5m\" : fmt(mm, 5) + \" mm\"; }\n    function fRate(mmy) { return fmt(mmy, 5) + \" mm\/year (\" + fmt(mmy \/ 0.0254, 5) + \" MPY)\"; }\n    function fA(m2) { return fmt(m2, 6) + \" m\u00b2 (\" + fmt(m2 * 1e4, 6) + \" cm\u00b2)\"; }\n    function compute(v) {\n      var R = { mode: v.mode, heroes: [], kpis: [], extra: [], msgs: [], steps: [], charts: [], inputs: [], table: null, v: v };\n      var m = v.mode, th = null, co = null;\n      \/* ---- inputs summary for exports ---- *\/\n      R.inputs.push([\"Calculation mode\", MODE_NAMES[m]]);\n      R.inputs.push([\"Material\", v.matName]);\n      R.inputs.push([\"Reference density \u03c1\u2080\", fmt(v.rhoIn, 6) + \" \" + DENS_L[v.dU] + (v.dU === \"kgm3\" ? \"\" : \" (\" + fmt(v.rho, 6) + \" kg\/m\u00b3)\")]);\n      if (v.needT) { R.inputs.push([\"Linear expansion coefficient \u03b1\", fmt(v.alphaIn, 6) + \" \" + ALPHA_L[v.aU]]); }\n      if (v.basis === \"mass\") { R.inputs.push([\"Initial mass m\u2080 (entered)\", fmt(v.mIn, 8) + \" \" + MASS_L[v.mU]]); }\n      else if (v.basis === \"volume\") { R.inputs.push([\"Initial volume V\u2080 (entered)\", fmt(v.vIn, 8) + \" \" + VOL_L[v.vU]]); }\n      else {\n        R.inputs.push([\"Geometry\", SHAPE_NAMES[v.shape]]);\n        SHAPE_DIMS[v.shape].forEach(function (k) { R.inputs.push([\"Dimension: \" + DIM_LABEL[k], fmt(v.dims[k] \/ LEN[v.gU], 8) + \" \" + LEN_L[v.gU]]); });\n      }\n      if (v.needT) {\n        if (v.L0src === \"entered\") { R.inputs.push([\"Initial length L\u2080\", fmt(v.L0 \/ LEN[v.lU], 8) + \" \" + LEN_L[v.lU]]); }\n        R.inputs.push([\"Initial temperature T\u2081\", fmt(v.t1In, 8) + \" \" + TU_L[v.tU]]);\n        R.inputs.push([\"Final temperature T\u2082\", fmt(v.t2In, 8) + \" \" + TU_L[v.tU]]);\n      }\n      if (v.needC) {\n        R.inputs.push([\"Corrosion rate\", fmt(v.rateIn, 8) + \" \" + RATE_L[v.rU]]);\n        R.inputs.push([\"Exposure duration\", fmt(v.durIn, 8) + \" \" + TIME_L[v.duU]]);\n        R.inputs.push([\"Exposed surface area\", v.abasis === \"geom\" ? fA(v.A) + \" \u2014 \" + v.surfNames.join(\", \") : fmt(v.aIn, 8) + \" \" + AREA_L[v.arU]]);\n      }\n      \/* ---- core calculations ---- *\/\n      if (v.needC) { co = Engine.corrosion(v.rho, v.A, v.rate, v.tY, v.m0); }\n      var VrefRem = co ? v.V0 - co.Vl : v.V0;\n      var mFinal = co ? co.rem : v.m0;\n      if (v.needT) { th = Engine.thermal(VrefRem, mFinal, v.alpha, v.dT, v.L0); }\n      R.co = co; R.th = th; R.VrefRem = VrefRem; R.mFinal = mFinal;\n      var basisStep = v.basis === \"mass\" ? [\"Initial volume from mass\", \"V\u2080 = m\u2080 \/ \u03c1\u2080 = \" + fmt(v.m0, 7) + \" kg \/ \" + fmt(v.rho, 7) + \" kg\/m\u00b3 = \" + fmt(v.V0, 7) + \" m\u00b3\"]\n        : (v.basis === \"volume\" ? [\"Initial mass from volume\", \"m\u2080 = \u03c1\u2080 \u00d7 V\u2080 = \" + fmt(v.rho, 7) + \" kg\/m\u00b3 \u00d7 \" + fmt(v.V0, 7) + \" m\u00b3 = \" + fmt(v.m0, 7) + \" kg\"]\n          : [\"Volume and mass from geometry (\" + SHAPE_NAMES[v.shape] + \")\", v.G.formula + \" = \" + fmt(v.V0, 7) + \" m\u00b3; m\u2080 = \u03c1\u2080 \u00d7 V\u2080 = \" + fmt(v.m0, 7) + \" kg\"]);\n      \/* ---------- MODE 1: temperature effect ---------- *\/\n      if (m === 1) {\n        R.heroes.push({ label: \"Final material mass\", value: fm(v.m0).replace(\/ [^ ]+$\/, \"\"), unit: MASS_L[RU().m] + \" (unchanged)\", sub: \"Actual mass change: 0 \u2014 temperature alone does not change mass\", tone: \"ok\" });\n        R.heroes.push({ label: \"Final estimated density\", value: fd(th.rho).replace(\/ [^ ]+$\/, \"\"), unit: DENS_L[RU().d], sub: \"Change \" + fmtSigned(th.drhoPct, 4) + \"% from \" + fd(th.rho0), tone: \"\" });\n        R.kpis.push({ label: \"Initial material mass\", value: fm(v.m0), cls: \"init\" });\n        R.kpis.push({ label: \"Final material mass\", value: fm(v.m0), sub: \"Unchanged\", cls: \"rem\" });\n        R.kpis.push({ label: \"Actual mass change\", value: fm(0), sub: \"Closed system\" });\n        R.kpis.push({ label: \"Temperature difference \u0394T\", value: fdT(v.dT, v.tU) });\n        R.kpis.push({ label: \"Initial volume V\u2080\", value: fv(v.V0) });\n        R.kpis.push({ label: \"Final volume V\", value: fv(th.V) });\n        R.kpis.push({ label: \"Thermal volume change \u0394V\", value: fvS(th.dV), sub: fmtSigned(th.dVpct, 4) + \"%\", cls: \"therm\" });\n        R.kpis.push({ label: \"Initial density \u03c1\u2080\", value: fd(th.rho0) });\n        R.kpis.push({ label: \"Final estimated density \u03c1\", value: fd(th.rho), sub: fmtSigned(th.drhoPct, 4) + \"%\" });\n        if (isNum(th.dL)) { R.kpis.push({ label: \"Length change \u0394L\", value: fmtSigned(th.dL * 1000, 5) + \" mm\", sub: \"L = \" + fmt(th.L * 1000, 7) + \" mm\" }); }\n        R.steps.push([\"Temperature difference\", \"\u0394T = T\u2082 \u2212 T\u2081 = \" + fT(v.T2K, v.tU) + \" \u2212 \" + fT(v.T1K, v.tU) + \" = \" + fdT(v.dT, v.tU)]);\n        R.steps.push(basisStep);\n        R.steps.push([\"Volumetric expansion coefficient\", \"\u03b2 \u2248 3\u03b1 = 3 \u00d7 \" + fmt(v.alpha, 6) + \" \/K = \" + fmt(th.beta, 6) + \" \/K\"]);\n        R.steps.push([\"Thermally adjusted volume\", \"V = V\u2080 \u00d7 (1 + \u03b2 \u00d7 \u0394T) = \" + fmt(v.V0, 7) + \" \u00d7 (1 + \" + fmt(th.beta * v.dT, 6) + \") = \" + fmt(th.V, 7) + \" m\u00b3\"]);\n        R.steps.push([\"Final density at constant mass\", \"\u03c1 = m \/ V = \" + fmt(v.m0, 7) + \" \/ \" + fmt(th.V, 7) + \" = \" + fmt(th.rho, 7) + \" kg\/m\u00b3\"]);\n        if (isNum(th.dL)) { R.steps.push([\"Linear expansion (L\u2080 from \" + v.L0src + \")\", \"\u0394L = \u03b1 \u00d7 L\u2080 \u00d7 \u0394T = \" + fmt(v.alpha, 6) + \" \u00d7 \" + fmt(v.L0, 7) + \" m \u00d7 \" + fmt(v.dT, 6) + \" = \" + fmtSigned(th.dL, 6) + \" m; L = L\u2080 \u00d7 (1 + \u03b1\u0394T) = \" + fmt(th.L, 8) + \" m\"]); }\n        R.steps.push([\"Mass\", \"m = m\u2080 = \" + fmt(v.m0, 7) + \" kg (no material enters or leaves the system)\"]);\n        R.msgs.push({ tone: \"ok\", text: \"Mass remains constant under the assumed closed-system conditions. Temperature changes affect dimensions, volume, and density rather than material mass.\" });\n        R.msgs.push({ tone: \"info\", text: v.dT === 0 ? \"T\u2081 equals T\u2082, so there is no thermal change.\" : \"A \" + (v.dT > 0 ? \"temperature rise\" : \"temperature drop\") + \" of \" + fdT(Math.abs(v.dT), v.tU) + \" \" + (th.dV >= 0 ? \"increases\" : \"decreases\") + \" the volume by \" + fmt(Math.abs(th.dVpct), 4) + \"% and \" + (th.drhoPct <= 0 ? \"lowers\" : \"raises\") + \" the density by \" + fmt(Math.abs(th.drhoPct), 4) + \"%.\" });\n        R.extra = baseExtra(v, co, th);\n        R.charts.push(massChart(v.m0, 0, v.m0));\n        R.charts.push(tempChart(v, [{ name: \"Material volume\", base: v.V0, color: \"#1a4d8f\" }]));\n      }\n      \/* ---------- MODE 2: corrosion weight loss ---------- *\/\n      if (m === 2) {\n        R.heroes.push({ label: \"Remaining material mass\", value: fm(co.rem).replace(\/ [^ ]+$\/, \"\"), unit: MASS_L[RU().m], sub: \"From \" + fm(v.m0) + \" initial mass\", tone: \"ok\" });\n        R.heroes.push({ label: \"Corrosion mass loss\", value: fm(co.ml).replace(\/ [^ ]+$\/, \"\"), unit: MASS_L[RU().m], sub: fmt(co.pct, 5) + \"% of the initial mass \u00b7 depth \" + fDepth(co.depth), tone: \"loss\" });\n        R.kpis.push({ label: \"Initial material mass\", value: fm(v.m0), cls: \"init\" });\n        R.kpis.push({ label: \"Corrosion mass loss\", value: fm(co.ml), cls: \"loss\" });\n        R.kpis.push({ label: \"Final material mass\", value: fm(co.rem), cls: \"rem\" });\n        R.kpis.push({ label: \"Mass loss percentage\", value: fmt(co.pct, 5) + \"%\" });\n        R.kpis.push({ label: \"Actual mass change\", value: fmS(-co.ml) });\n        R.kpis.push({ label: \"Corrosion penetration depth\", value: fDepth(co.depth) });\n        R.kpis.push({ label: \"Corrosion volume loss\", value: fv(co.Vl, 6) });\n        R.kpis.push({ label: \"Remaining material volume\", value: fv(VrefRem) });\n        R.kpis.push({ label: \"Material density\", value: fd(v.rho), sub: \"Unchanged by uniform loss\" });\n        corrSteps(R, v, co, basisStep);\n        R.extra = baseExtra(v, co, null);\n        corrMsgs(R, v, co);\n        R.charts.push(massChart(v.m0, co.ml, co.rem));\n        R.charts.push(timeChart(v, co));\n      }\n      \/* ---------- MODE 3: combined ---------- *\/\n      if (m === 3) {\n        var thInit = Engine.thermal(v.V0, v.m0, v.alpha, v.dT, null);\n        R.heroes.push({ label: \"Final material mass\", value: fm(mFinal).replace(\/ [^ ]+$\/, \"\"), unit: MASS_L[RU().m], sub: \"Corrosion loss \" + fm(co.ml) + \" (\" + fmt(co.pct, 5) + \"%) \u00b7 temperature adds no mass change\", tone: \"ok\" });\n        R.heroes.push({ label: \"Final estimated density\", value: fd(th.rho).replace(\/ [^ ]+$\/, \"\"), unit: DENS_L[RU().d], sub: \"At T\u2082 = \" + fT(v.T2K, v.tU) + \"; \u03c1\u2080 = \" + fd(v.rho) + \" at T\u2081\", tone: \"\" });\n        R.kpis.push({ label: \"Initial material mass\", value: fm(v.m0), cls: \"init\" });\n        R.kpis.push({ label: \"Corrosion mass loss (actual)\", value: fm(co.ml), sub: fmt(co.pct, 5) + \"% of initial\", cls: \"loss\" });\n        R.kpis.push({ label: \"Remaining material mass\", value: fm(mFinal), cls: \"rem\" });\n        R.kpis.push({ label: \"Corrosion volume loss\", value: fv(co.Vl, 6), sub: \"At reference temperature T\u2081\" });\n        R.kpis.push({ label: \"Remaining reference volume\", value: fv(VrefRem), sub: \"At T\u2081\" });\n        R.kpis.push({ label: \"Thermal volume change\", value: fvS(th.dV), sub: fmtSigned(th.dVpct, 4) + \"% \u00b7 not a mass change\", cls: \"therm\" });\n        R.kpis.push({ label: \"Final volume at T\u2082\", value: fv(th.V) });\n        R.kpis.push({ label: \"Final estimated density\", value: fd(th.rho), sub: fmtSigned(th.drhoPct, 4) + \"% vs \u03c1\u2080\" });\n        R.kpis.push({ label: \"Temperature difference \u0394T\", value: fdT(v.dT, v.tU) });\n        corrSteps(R, v, co, basisStep);\n        R.steps.push([\"Remaining reference volume (at T\u2081)\", \"V_ref = V\u2080 \u2212 \u0394V_corr = \" + fmt(v.V0, 7) + \" \u2212 \" + fmt(co.Vl, 7) + \" = \" + fmt(VrefRem, 7) + \" m\u00b3\"]);\n        R.steps.push([\"Temperature difference and \u03b2\", \"\u0394T = \" + fdT(v.dT, v.tU) + \"; \u03b2 \u2248 3\u03b1 = \" + fmt(th.beta, 6) + \" \/K\"]);\n        R.steps.push([\"Final volume at operating temperature\", \"V = V_ref \u00d7 (1 + \u03b2 \u00d7 \u0394T) = \" + fmt(VrefRem, 7) + \" \u00d7 (1 + \" + fmt(th.beta * v.dT, 6) + \") = \" + fmt(th.V, 7) + \" m\u00b3 (thermal \u0394V = \" + fmtSigned(th.dV, 6) + \" m\u00b3)\"]);\n        R.steps.push([\"Final mass and density\", \"m = m\u2080 \u2212 \u0394m_corr = \" + fmt(mFinal, 7) + \" kg; \u03c1 = m \/ V = \" + fmt(mFinal, 7) + \" \/ \" + fmt(th.V, 7) + \" = \" + fmt(th.rho, 7) + \" kg\/m\u00b3\"]);\n        if (isNum(th.dL)) { R.steps.push([\"Linear expansion (L\u2080 from \" + v.L0src + \")\", \"\u0394L = \u03b1 \u00d7 L\u2080 \u00d7 \u0394T = \" + fmtSigned(th.dL, 6) + \" m (reference length before corrosion)\"]); }\n        R.msgs.push({ tone: \"ok\", text: \"Actual mass loss comes from corrosion only (\" + fm(co.ml) + \"). The thermal volume change (\" + fvS(th.dV) + \") changes volume and density, not mass, and is not added to the mass loss.\" });\n        R.msgs.push({ tone: \"info\", text: \"Corrosion volume loss is calculated with the reference density and reference geometry at T\u2081. Thermal expansion is then applied once to the remaining reference volume, so density and volume changes are not double-counted.\" });\n        corrMsgs(R, v, co);\n        R.extra = baseExtra(v, co, th);\n        R.extra.push([\"Initial volume at T\u2082 without corrosion (reference)\", fv(thInit.V)]);\n        R.charts.push(massChart(v.m0, co.ml, co.rem));\n        R.charts.push(tempChart(v, [{ name: \"Remaining material (after corrosion)\", base: VrefRem, color: \"#1a4d8f\" }, { name: \"Initial material (before corrosion)\", base: v.V0, color: \"#8a96a8\", dash: true }]));\n        R.charts.push(timeChart(v, co));\n      }\n      \/* ---------- shared temperature validity notes ---------- *\/\n      if (v.needT) { thermalMsgs(R, v, th); }\n      if (v.mat.poly) { R.msgs.push({ tone: \"warn\", text: \"Plastics and polymers can gain or lose mass through moisture absorption, plasticizer loss, chemical swelling and thermal degradation. The simplified model may not describe their actual mass changes, and their expansion coefficient varies strongly with grade and temperature.\" }); }\n      if (v.mat.note) { R.msgs.push({ tone: \"info\", text: v.mat.name + \": \" + v.mat.note }); }\n      return R;\n    }\n    function baseExtra(v, co, th) {\n      var e = [[\"Material type\", v.matName]];\n      if (v.needT) {\n        e.push([\"Initial temperature T\u2081\", fT(v.T1K, v.tU) + \" (\" + fmt(v.T1K, 6) + \" K)\"]);\n        e.push([\"Final temperature T\u2082\", fT(v.T2K, v.tU) + \" (\" + fmt(v.T2K, 6) + \" K)\"]);\n        e.push([\"Thermal expansion coefficient \u03b1\", fmt(v.alpha * 1e6, 5) + \" \u00d7 10\u207b\u2076 \/K (\u03b2 \u2248 \" + fmt(3 * v.alpha * 1e6, 5) + \" \u00d7 10\u207b\u2076 \/K)\"]);\n        e.push([\"Linear thermal strain \u03b1\u00b7\u0394T\", fmtSigned(th.eps * 100, 4) + \"%\"]);\n      }\n      if (v.needC) {\n        e.push([\"Corrosion rate\", fRate(v.rate)]);\n        e.push([\"Exposure duration\", fmt(v.durIn, 8) + \" \" + TIME_L[v.duU] + \" (\" + fmt(v.tY, 6) + \" years = \" + fmt(v.tY * 8760, 6) + \" h)\"]);\n        e.push([\"Exposed surface area\", fA(v.A)]);\n        e.push([\"Corrosion penetration depth\", fDepth(co.depth)]);\n        e.push([\"Average mass loss rate\", fm(co.kgY) + \" per year\"]);\n      }\n      e.push([\"Initial volume V\u2080 (reference)\", fv(v.V0)]);\n      e.push([\"Initial density \u03c1\u2080\", fd(v.rho)]);\n      return e;\n    }\n    function corrSteps(R, v, co, basisStep) {\n      R.steps.push([\"Unit conversion\", \"CR = \" + fmt(v.rate, 6) + \" mm\/year; t = \" + fmt(v.tY, 6) + \" years; A = \" + fmt(v.A, 6) + \" m\u00b2; \u03c1\u2080 = \" + fmt(v.rho, 6) + \" kg\/m\u00b3\"]);\n      R.steps.push(basisStep);\n      R.steps.push([\"Corrosion depth (constant penetration rate)\", \"d = CR \u00d7 t = \" + fmt(v.rate, 6) + \" mm\/year \u00d7 \" + fmt(v.tY, 6) + \" years = \" + fmt(co.depth * 1000, 6) + \" mm = \" + fmt(co.depth, 6) + \" m\"]);\n      R.steps.push([\"Corrosion volume loss\", \"\u0394V_corr = A \u00d7 d = \" + fmt(v.A, 6) + \" m\u00b2 \u00d7 \" + fmt(co.depth, 6) + \" m = \" + fmt(co.Vl, 6) + \" m\u00b3\"]);\n      R.steps.push([\"Corrosion mass loss\", \"\u0394m = \u03c1\u2080 \u00d7 \u0394V_corr = \" + fmt(v.rho, 6) + \" \u00d7 \" + fmt(co.Vl, 6) + \" = \" + fmt(co.ml, 7) + \" kg\"]);\n      R.steps.push([\"Cross-check with the weight-loss formula\", \"W = CR \u00d7 \u03c1 \u00d7 A \u00d7 t \/ 87.6 = \" + fmt(v.rate, 6) + \" \u00d7 \" + fmt(v.rho \/ 1000, 6) + \" g\/cm\u00b3 \u00d7 \" + fmt(v.A * 1e4, 6) + \" cm\u00b2 \u00d7 \" + fmt(v.tY * 8760, 6) + \" h \/ 87.6 = \" + fmt(co.Wmg, 7) + \" mg = \" + fmt(co.Wmg \/ 1e6, 7) + \" kg\"]);\n      R.steps.push([\"Remaining mass and loss percentage\", \"m = m\u2080 \u2212 \u0394m = \" + fmt(v.m0, 7) + \" \u2212 \" + fmt(co.ml, 7) + \" = \" + fmt(co.rem, 7) + \" kg; loss = \" + fmt(co.ml, 7) + \" \/ \" + fmt(v.m0, 7) + \" \u00d7 100 = \" + fmt(co.pct, 6) + \"%\"]);\n    }\n    function corrMsgs(R, v, co) {\n      R.msgs.push({ tone: \"info\", text: \"Simplified uniform corrosion model: constant corrosion rate, constant (fixed) exposed area and uniform material removal. It is not an accurate representation of pitting, localized corrosion, erosion-corrosion or geometry-dependent exposure without additional validated data.\" });\n      if (co.ml === 0) { R.msgs.push({ tone: \"info\", text: \"With a zero corrosion rate or zero exposure time, no corrosion mass loss is estimated.\" }); }\n      if (v.G ? co.depth > 0 : false) {\n        var ms = v.G.minSec;\n        if (co.depth >= ms) { R.msgs.push({ tone: \"bad\", text: \"The penetration depth (\" + fDepth(co.depth) + \") reaches or exceeds the smallest section dimension of the part (\" + fmt(ms * 1000, 5) + \" mm). The fixed-area approximation is not valid; parts of the component would be fully consumed.\" }); }\n        else if (co.depth > 0.1 * ms) { R.msgs.push({ tone: \"warn\", text: \"The penetration depth is more than 10% of the smallest section dimension (\" + fmt(ms * 1000, 5) + \" mm). This fixed-area approximation ignores the shrinking geometry, so treat the result as approximate.\" }); }\n      }\n      if (co.pct > 10) { R.msgs.push({ tone: \"warn\", text: \"More than 10% of the material is lost. At this level the exposed area and geometry usually change noticeably, and the remaining section should be assessed by inspection.\" }); }\n      R.msgs.push({ tone: \"info\", text: \"Gravimetric mass change can differ from true metal loss when corrosion products stay attached. This result represents cleaned-specimen metal loss, not the weight of a part that still carries oxide or scale.\" });\n    }\n    function thermalMsgs(R, v, th) {\n      var m = v.mat, t1 = v.T1K - 273.15, t2 = v.T2K - 273.15, hi = Math.max(t1, t2), lo = Math.min(t1, t2);\n      if (Math.abs(th.eps) > 0.01) { R.msgs.push({ tone: \"warn\", text: \"The linear thermal strain is \" + fmt(Math.abs(th.eps) * 100, 3) + \"%, beyond the small-strain range where \u03b2 \u2248 3\u03b1 and a constant \u03b1 are reliable. Use temperature-dependent expansion data.\" }); }\n      if (m.id !== \"custom\") {\n        if (hi > m.hi ? true : lo < m.lo) { R.msgs.push({ tone: \"warn\", text: \"The temperature range extends outside the approximate range of use for the reference \u03b1 of \" + m.name + \" (\" + fmt(m.lo) + \" to \" + fmt(m.hi) + \" \u00b0C). Expansion coefficients change with temperature, so use a mean \u03b1 for your actual range from material-specific data.\" }); }\n        if (m.cat === \"Carbon Steel\" ? hi > 700 : (m.id === \"ci\" ? hi > 700 : false)) { R.msgs.push({ tone: \"bad\", text: \"Above about 700 \u00b0C carbon steels and cast irons approach the ferrite\u2013austenite transformation, which causes a volume contraction. A constant-\u03b1 model is not valid here.\" }); }\n        if (m.cat === \"Stainless Steel\" ? (m.id === \"430\" ? hi > 800 : false) : false) { R.msgs.push({ tone: \"warn\", text: \"Ferritic stainless steels can undergo phase changes and embrittlement at high temperatures. Verify the expansion data for this range.\" }); }\n      }\n      if (v.alpha < 0) { R.msgs.push({ tone: \"info\", text: \"A negative expansion coefficient was entered, so the material contracts on heating. Make sure this matches your material data.\" }); }\n      if (hi > 300 ? (m.poly ? false : true) : false) { R.msgs.push({ tone: \"info\", text: \"At elevated temperature in air, oxidation can add measurable mass (scale). That real mass change is not included in this thermal model.\" }); }\n    }\n    \/* ---------- chart specifications ---------- *\/\n    function massChart(m0, ml, rem) {\n      var u = RU().m;\n      return { type: \"bar\", id: \"mass\", title: \"Material mass change\", unit: MASS_L[u], yLabel: \"Mass (\" + MASS_L[u] + \")\",\n        bars: [{ label: \"Initial mass\", value: m0 \/ MASS[u], color: \"#1a4d8f\" }, { label: \"Corrosion loss\", value: ml \/ MASS[u], color: \"#c2410c\" }, { label: \"Remaining mass\", value: rem \/ MASS[u], color: \"#0f766e\" }],\n        cap: \"Bars start at zero, so a small corrosion loss looks small next to the total mass.\" };\n    }\n    function tempChart(v, series) {\n      var u = v.tU, VU = RU().v, t1 = fromK(v.T1K, u), t2 = fromK(v.T2K, u), lo = Math.min(t1, t2), hi = Math.max(t1, t2), span = hi - lo;\n      if (span === 0) { span = u === \"F\" ? 90 : 50; lo -= span \/ 2; hi += span \/ 2; span = hi - lo; }\n      lo -= span * 0.15; hi += span * 0.15;\n      var absZero = fromK(0, u);\n      if (lo < absZero) { lo = absZero; }\n      var N = 41, k = u === \"F\" ? 5 \/ 9 : 1, out = [];\n      series.forEach(function (sr) {\n        var pts = [];\n        for (var i = 0; i < N; i++) {\n          var T = lo + (hi - lo) * i \/ (N - 1), f = 1 + 3 * v.alpha * (T - t1) * k;\n          pts.push([T, f > 0 ? sr.base * f \/ VOL[VU] : null]);\n        }\n        out.push({ name: sr.name, color: sr.color, dash: sr.dash, pts: pts });\n      });\n      var b = series[0].base, f2 = 1 + 3 * v.alpha * v.dT;\n      return { type: \"line\", id: \"temp\", title: \"Temperature vs material volume\", xLabel: \"Temperature (\" + TU_L[u] + \")\", yLabel: \"Volume (\" + VOL_L[VU] + \")\", series: out,\n        markers: [{ x: t1, y: b \/ VOL[VU], label: \"T\u2081\" }, { x: t2, y: b * f2 \/ VOL[VU], label: \"T\u2082\" }], xFmt: function (x) { return fmt(x, 5) + \" \" + TU_L[u]; }, yFmt: function (y) { return fmt(y, 7) + \" \" + VOL_L[VU]; },\n        cap: \"Estimated with constant \u03b1 (\u03b2 \u2248 3\u03b1). The vertical axis is zoomed and does not start at zero.\" };\n    }\n    function timeChart(v, co) {\n      var MU = RU().m, du = v.duU, tMax = v.durIn > 0 ? v.durIn : 1, N = 41, pts = [];\n      for (var i = 0; i < N; i++) {\n        var t = tMax * i \/ (N - 1), rem = v.m0 - co.kgY * t * TIME[du];\n        pts.push([t, Math.max(0, rem) \/ MASS[MU]]);\n      }\n      return { type: \"line\", id: \"time\", title: \"Exposure time vs remaining mass\", xLabel: \"Exposure time (\" + TIME_L[du] + \")\", yLabel: \"Remaining mass (\" + MASS_L[MU] + \")\",\n        series: [{ name: \"Remaining mass\", color: \"#0f766e\", pts: pts }], markers: [{ x: v.durIn, y: co.rem \/ MASS[MU], label: \"End\" }],\n        xFmt: function (x) { return fmt(x, 5) + \" \" + TIME_L[du]; }, yFmt: function (y) { return fmt(y, 7) + \" \" + MASS_L[MU]; },\n        cap: \"Linear loss at a constant rate over a fixed area. Mass is never shown below zero. The vertical axis is zoomed.\" };\n    }\n    \/* ---------- mode 4 report ---------- *\/\n    function computeCmp(v) {\n      var R = { mode: 4, heroes: [], kpis: [], extra: [], msgs: [], steps: [], charts: [], inputs: [], v: v };\n      var U = v.U, res = [];\n      R.inputs.push([\"Calculation mode\", MODE_NAMES[4]]);\n      v.rows.forEach(function (o) {\n        R.inputs.push([o.name, \"\u03c1\u2080 \" + fmt(o.rhoIn, 6) + \" \" + DENS_L[U.dens] + \"; \u03b1 \" + fmt(o.alphaIn, 6) + \" \" + ALPHA_L[U.alpha] + \"; m\u2080 \" + fmt(o.massIn, 8) + \" \" + MASS_L[U.mass] + \"; CR \" + fmt(o.rateIn, 6) + \" \" + RATE_L[U.rate] + \"; A \" + fmt(o.areaIn, 6) + \" \" + AREA_L[U.area] + \"; t \" + fmt(o.durIn, 6) + \" \" + TIME_L[U.dur] + \"; \u0394T \" + fmt(o.dTIn, 6) + \" \" + DT_L[U.dt]]);\n        if (!o.ok) { return; }\n        var V0 = o.m0 \/ o.rho, co = Engine.corrosion(o.rho, o.A, o.rate, o.tY, o.m0), Vrem = V0 - co.Vl, th = Engine.thermal(Vrem, co.rem, o.alpha, o.dT, null);\n        res.push({ o: o, V0: V0, co: co, Vrem: Vrem, th: th, color: CMP_COLORS[o.i % 5] });\n      });\n      R.res = res;\n      var bad = v.rows.filter(function (o) { return !o.ok; });\n      if (bad.length) { R.msgs.push({ tone: \"warn\", text: \"Not included until corrected: \" + bad.map(function (o) { return o.name; }).join(\", \") + \".\" }); }\n      if (res.length === 0) { return R; }\n      var maxL = res[0], maxP = res[0];\n      res.forEach(function (r) { if (r.co.ml > maxL.co.ml) { maxL = r; } if (r.co.pct > maxP.co.pct) { maxP = r; } });\n      R.heroes.push({ label: \"Largest corrosion mass loss\", value: fm(maxL.co.ml).replace(\/ [^ ]+$\/, \"\"), unit: MASS_L[RU().m], sub: maxL.o.name + \" \u00b7 \" + fmt(maxL.co.pct, 4) + \"% of its initial mass\", tone: \"loss\" });\n      R.heroes.push({ label: \"Highest mass loss percentage\", value: fmt(maxP.co.pct, 4), unit: \"%\", sub: maxP.o.name + \" \u00b7 remaining \" + fm(maxP.co.rem), tone: \"\" });\n      R.table = { head: [\"Material\", \"Initial mass\", \"Corrosion loss\", \"Final mass\", \"Loss %\", \"Depth\", \"Thermal \u0394V\", \"Final density\"], rows: [] };\n      res.forEach(function (r) {\n        R.table.rows.push([r.o.name, fm(r.o.m0), fm(r.co.ml), fm(r.co.rem), fmt(r.co.pct, 5) + \"%\", fDepth(r.co.depth), fvS(r.th.dV, 4), fd(r.th.rho, 6)]);\n      });\n      R.steps.push([\"Initial volume of each material\", \"V\u2080 = m\u2080 \/ \u03c1\u2080\"]);\n      R.steps.push([\"Uniform corrosion loss\", \"d = CR \u00d7 t; \u0394V_corr = A \u00d7 d; \u0394m = \u03c1\u2080 \u00d7 \u0394V_corr; m = m\u2080 \u2212 \u0394m; loss % = \u0394m \/ m\u2080 \u00d7 100\"]);\n      R.steps.push([\"Thermal change of the remaining material\", \"V = (V\u2080 \u2212 \u0394V_corr) \u00d7 (1 + 3\u03b1 \u00d7 \u0394T); thermal \u0394V = V \u2212 (V\u2080 \u2212 \u0394V_corr)\"]);\n      R.steps.push([\"Final density\", \"\u03c1 = m \/ V (mass is unaffected by \u0394T)\"]);\n      res.forEach(function (r) {\n        R.steps.push([r.o.name, \"d = \" + fmt(r.co.depth * 1000, 5) + \" mm; \u0394m = \" + fmt(r.o.rho, 6) + \" \u00d7 \" + fmt(r.o.A, 6) + \" \u00d7 \" + fmt(r.co.depth, 6) + \" = \" + fmt(r.co.ml, 6) + \" kg; V = \" + fmt(r.Vrem, 6) + \" \u00d7 (1 + \" + fmt(3 * r.o.alpha * r.o.dT, 5) + \") = \" + fmt(r.th.V, 6) + \" m\u00b3; \u03c1 = \" + fmt(r.th.rho, 6) + \" kg\/m\u00b3\"]);\n      });\n      R.msgs.push({ tone: \"info\", text: \"Each result uses the corrosion rate you entered for that material. Corrosion rates are never assigned from the material type, because they depend strongly on the environment.\" });\n      var same = res.length > 1 ? res.every(function (r) { return r.o.rate === res[0].o.rate; }) : false;\n      if (same) { R.msgs.push({ tone: \"warn\", text: \"All materials use the same corrosion rate, so the differences shown come only from density, mass and area. Real rates for different alloys in the same environment usually differ by orders of magnitude.\" }); }\n      R.msgs.push({ tone: \"info\", text: \"Simplified uniform corrosion model with constant rate and fixed exposed area. Thermal volume change is reported separately and is not a mass change.\" });\n      if (res.some(function (r) { return r.o.preset !== \"custom\" ? matById(r.o.preset).poly === true : false; })) { R.msgs.push({ tone: \"warn\", text: \"Polymers can change mass by moisture absorption, swelling or degradation, which this model does not capture.\" }); }\n      var metric = state.cmpMetric, MU = RU().m, DU = RU().d;\n      var metricDef = { loss: { t: \"Corrosion mass loss\", u: MASS_L[MU], f: function (r) { return r.co.ml \/ MASS[MU]; } }, pct: { t: \"Mass loss percentage\", u: \"%\", f: function (r) { return r.co.pct; } }, final: { t: \"Final mass\", u: MASS_L[MU], f: function (r) { return r.co.rem \/ MASS[MU]; } }, dens: { t: \"Final density\", u: DENS_L[DU], f: function (r) { return r.th.rho \/ DENS[DU]; } } }[metric];\n      R.charts.push({ type: \"bar\", id: \"cmp\", title: \"Material comparison: \" + metricDef.t.toLowerCase(), unit: metricDef.u, yLabel: metricDef.t + \" (\" + metricDef.u + \")\", metric: metric,\n        bars: res.map(function (r) { return { label: r.o.name, value: metricDef.f(r), color: r.color }; }), cap: \"Estimates under the conditions you entered for each material.\" });\n      R.extra = [[\"Materials compared\", String(res.length)]];\n      return R;\n    }\n    \/* =====================================================================\n       RENDERING\n       ===================================================================== *\/\n    function msgEl(tone, text) { return h(\"div\", { class: \"mwcc-msg mwcc-t-\" + tone }, [icon(tone), h(\"div\", { text: text })]); }\n    function renderPlaceholder(v) {\n      var body = q(\"mwcc-res-body\"), text;\n      clear(body);\n      if (v.missing.length ? v.missing.length === Object.keys(v.E).length : false) { text = \"Enter the required inputs to see results. Still needed: \" + v.missing.join(\", \") + \".\"; }\n      else { text = \"Correct the highlighted inputs to see results.\"; }\n      body.appendChild(h(\"p\", { class: \"mwcc-placeholder\", text: text }));\n    }\n    function renderResults(R) {\n      var body = q(\"mwcc-res-body\");\n      clear(body);\n      if (R.heroes.length === 0) {\n        body.appendChild(h(\"p\", { class: \"mwcc-placeholder\", text: \"Enter valid data for at least one material to see the comparison.\" }));\n        if (R.msgs.length) { var mm = h(\"div\", { class: \"mwcc-msgs\" }); R.msgs.forEach(function (m) { mm.appendChild(msgEl(m.tone, m.text)); }); body.appendChild(mm); }\n        return;\n      }\n      var heroes = h(\"div\", { class: \"mwcc-heroes\" + (R.heroes.length > 1 ? \" mwcc-two\" : \"\") });\n      R.heroes.forEach(function (hr) {\n        var vEl = h(\"div\", { class: \"mwcc-hero-value\" }, [hr.value]);\n        if (hr.unit) { vEl.appendChild(h(\"span\", { text: hr.unit })); }\n        heroes.appendChild(h(\"div\", { class: \"mwcc-hero\" + (hr.tone ? \" mwcc-t-\" + hr.tone : \"\") }, [h(\"div\", { class: \"mwcc-hero-label\", text: hr.label }), vEl, h(\"div\", { class: \"mwcc-hero-sub\", text: hr.sub })]));\n      });\n      body.appendChild(heroes);\n      if (R.kpis.length) {\n        var dl = h(\"dl\", { class: \"mwcc-kpis\", \"aria-label\": \"Main results\" });\n        R.kpis.forEach(function (k) {\n          dl.appendChild(h(\"div\", { class: \"mwcc-kpi\" + (k.cls ? \" mwcc-k-\" + k.cls : \"\") }, [h(\"dt\", { text: k.label }), h(\"dd\", {}, [k.value, k.sub ? h(\"small\", { text: k.sub }) : null])]));\n        });\n        body.appendChild(dl);\n      }\n      if (R.table) {\n        var tb = h(\"table\", { class: \"mwcc-table\" }), thead = h(\"thead\"), trh = h(\"tr\"), tbody = h(\"tbody\");\n        R.table.head.forEach(function (c) { trh.appendChild(h(\"th\", { scope: \"col\", text: c })); });\n        thead.appendChild(trh); tb.appendChild(thead);\n        R.table.rows.forEach(function (row, ri) {\n          var tr = h(\"tr\");\n          row.forEach(function (c, ci) {\n            var td = h(\"td\", { \"data-label\": R.table.head[ci] });\n            if (ci === 0) { td.appendChild(h(\"span\", { class: \"mwcc-dot\", style: \"background:\" + R.res[ri].color + \";margin-right:7px\" })); }\n            td.appendChild(document.createTextNode(c));\n            tr.appendChild(td);\n          });\n          tbody.appendChild(tr);\n        });\n        tb.appendChild(tbody);\n        body.appendChild(h(\"div\", { class: \"mwcc-sec\" }, [h(\"h3\", { class: \"mwcc-sec-title\", text: \"Comparison results\" }), h(\"div\", { class: \"mwcc-tablewrap\" }, [tb])]));\n      }\n      if (R.msgs.length) {\n        var ms = h(\"div\", { class: \"mwcc-msgs\" });\n        R.msgs.forEach(function (m) { ms.appendChild(msgEl(m.tone, m.text)); });\n        body.appendChild(h(\"div\", { class: \"mwcc-sec\" }, [h(\"h3\", { class: \"mwcc-sec-title\", text: \"Engineering interpretation\" }), ms]));\n      }\n      if (R.charts.length) {\n        var cw = h(\"div\", { class: \"mwcc-charts\", id: \"mwcc-charts\" });\n        R.charts.forEach(function (c) {\n          var head = h(\"div\", { class: \"mwcc-chart-head\" }, [h(\"h4\", { class: \"mwcc-chart-title\", text: c.title })]);\n          if (c.id === \"cmp\") {\n            var seg = h(\"div\", { class: \"mwcc-mini-seg\", role: \"group\", \"aria-label\": \"Comparison metric\" });\n            [[\"loss\", \"Mass loss\"], [\"pct\", \"Loss %\"], [\"final\", \"Final mass\"], [\"dens\", \"Density\"]].forEach(function (p) {\n              var b = h(\"button\", { type: \"button\", \"data-mwcc-metric\": p[0], \"aria-pressed\": c.metric === p[0] ? \"true\" : \"false\", text: p[1] });\n              seg.appendChild(b);\n            });\n            head.appendChild(seg);\n          }\n          var fig = h(\"figure\", { class: \"mwcc-chart\" }, [head, h(\"div\", { class: \"mwcc-chart-box\", \"data-mwcc-chart\": c.id })]);\n          if (c.type === \"line\" ? c.series.length > 1 : false) {\n            var lg = h(\"div\", { class: \"mwcc-legend\" });\n            c.series.forEach(function (sr) { lg.appendChild(h(\"span\", {}, [h(\"i\", { class: sr.dash ? \"mwcc-dash\" : \"\", style: \"background:\" + sr.color }), sr.name])); });\n            fig.appendChild(lg);\n          }\n          fig.appendChild(h(\"figcaption\", { class: \"mwcc-chart-cap\", text: c.cap }));\n          cw.appendChild(fig);\n        });\n        body.appendChild(h(\"div\", { class: \"mwcc-sec\" }, [h(\"h3\", { class: \"mwcc-sec-title\", text: \"Visualization\" }), cw]));\n      }\n      if (R.extra.length) {\n        var ex = h(\"dl\", { class: \"mwcc-dl\", \"aria-label\": \"Additional results\" });\n        R.extra.forEach(function (r) { ex.appendChild(h(\"div\", {}, [h(\"dt\", { text: r[0] }), h(\"dd\", { text: r[1] })])); });\n        body.appendChild(h(\"div\", { class: \"mwcc-sec\" }, [h(\"h3\", { class: \"mwcc-sec-title\", text: \"Additional results\" }), ex]));\n      }\n      if (R.steps.length) {\n        var ol = h(\"ol\", { class: \"mwcc-steps\", id: \"mwcc-steps\" });\n        R.steps.forEach(function (st) { ol.appendChild(h(\"li\", {}, [h(\"b\", { text: st[0] }), h(\"code\", { text: st[1] })])); });\n        var tg = h(\"button\", { type: \"button\", class: \"mwcc-toggle\", \"aria-expanded\": state.stepsOpen ? \"true\" : \"false\", \"aria-controls\": \"mwcc-steps-wrap\" }, [\"Calculation formula and steps\", h(\"span\", { \"aria-hidden\": \"true\" }, [chev()])]);\n        var wrap = h(\"div\", { class: \"mwcc-steps-wrap\", id: \"mwcc-steps-wrap\" }, [ol]);\n        wrap.hidden = !state.stepsOpen;\n        tg.addEventListener(\"click\", function () { state.stepsOpen = !state.stepsOpen; tg.setAttribute(\"aria-expanded\", state.stepsOpen ? \"true\" : \"false\"); wrap.hidden = !state.stepsOpen; });\n        body.appendChild(h(\"div\", { class: \"mwcc-sec\" }, [tg, wrap]));\n      }\n      drawCharts();\n    }\n    function chev() { var sv = s(\"svg\", { viewBox: \"0 0 24 24\", fill: \"none\", stroke: \"currentColor\", \"stroke-width\": \"2.4\", \"stroke-linecap\": \"round\", \"stroke-linejoin\": \"round\" }); sv.appendChild(s(\"path\", { d: \"M6 9l6 6 6-6\" })); return sv; }\n    \/* =====================================================================\n       SVG CHARTS (no libraries)\n       ===================================================================== *\/\n    function niceTicks(min, max, count) {\n      if (!(max > min)) { var c0 = min === 0 ? 1 : Math.abs(min) * 0.05; min -= c0; max += c0; }\n      var raw = (max - min) \/ count, mag = Math.pow(10, Math.floor(Math.log(raw) \/ Math.LN10)), n = raw \/ mag;\n      var st = (n < 1.5 ? 1 : (n < 3 ? 2 : (n < 7 ? 5 : 10))) * mag;\n      var a = Math.floor(min \/ st) * st, b = Math.ceil(max \/ st) * st, list = [], i;\n      for (i = 0; a + i * st <= b + st * 1e-6; i++) { list.push(clean(a + i * st)); }\n      return { min: a, max: b, list: list, step: st };\n    }\n    function tickFmt(v, step) {\n      if (v === 0) { return \"0\"; }\n      var a = Math.abs(v);\n      if (a < 1e-3 ? true : a >= 1e7) { return fmt(v, 4); }\n      var dec = Math.max(0, -Math.floor(Math.log(step) \/ Math.LN10 + 1e-9));\n      var str = Math.abs(v).toFixed(Math.min(dec, 8)), p = str.split(\".\");\n      p[0] = group(p[0]);\n      return (v < 0 ? \"\u2212\" : \"\") + p.join(\".\");\n    }\n    var FONT = \"-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Arial,sans-serif\";\n    function svgText(x, y, str, a) {\n      var o = { x: x, y: y, \"font-size\": \"11.5\", fill: \"#566273\", \"font-family\": FONT };\n      if (a) { Object.keys(a).forEach(function (k) { o[k] = a[k]; }); }\n      return s(\"text\", o, str);\n    }\n    function frame(box, c, yt, W, H, P) {\n      var svg = s(\"svg\", { viewBox: \"0 0 \" + W + \" \" + H, width: W, height: H, role: \"img\", \"aria-label\": c.title, xmlns: SVGNS, \"font-family\": FONT });\n      svg.appendChild(s(\"rect\", { x: 0, y: 0, width: W, height: H, fill: \"#ffffff\" }));\n      yt.list.forEach(function (t) {\n        var y = P.t + (P.h - (t - yt.min) \/ (yt.max - yt.min) * P.h);\n        svg.appendChild(s(\"line\", { x1: P.l, x2: P.l + P.w, y1: y, y2: y, stroke: \"#e4e8ee\", \"stroke-width\": \"1\" }));\n        svg.appendChild(svgText(P.l - 8, y + 4, tickFmt(t, yt.step), { \"text-anchor\": \"end\" }));\n      });\n      svg.appendChild(s(\"line\", { x1: P.l, x2: P.l + P.w, y1: P.t + P.h, y2: P.t + P.h, stroke: \"#a3adba\", \"stroke-width\": \"1\" }));\n      var yl = svgText(0, 0, c.yLabel, { \"text-anchor\": \"middle\", transform: \"translate(13 \" + (P.t + P.h \/ 2) + \") rotate(-90)\", fill: \"#132238\", \"font-weight\": \"600\" });\n      svg.appendChild(yl);\n      box.appendChild(svg);\n      return svg;\n    }\n    function leftPad(yt) { var w = 0; yt.list.forEach(function (t) { w = Math.max(w, tickFmt(t, yt.step).length); }); return Math.max(46, Math.min(110, w * 6.6 + 30)); }\n    function barChart(box, c) {\n      var W = Math.max(280, box.clientWidth), H = W < 420 ? 240 : 260;\n      var maxV = 0; c.bars.forEach(function (b) { maxV = Math.max(maxV, b.value); });\n      var yt = niceTicks(0, maxV > 0 ? maxV * 1.12 : 1, 5);\n      var L = leftPad(yt), P = { l: L, t: 20, w: W - L - 12, h: H - 20 - 46 };\n      var svg = frame(box, c, yt, W, H, P);\n      var n = c.bars.length, slot = P.w \/ n, bw = Math.min(78, slot * 0.6);\n      c.bars.forEach(function (b, i) {\n        var x = P.l + slot * i + (slot - bw) \/ 2, hgt = (b.value - yt.min) \/ (yt.max - yt.min) * P.h, y = P.t + P.h - hgt;\n        var g = s(\"g\", { tabindex: \"0\", role: \"img\", \"aria-label\": b.label + \": \" + fmt(b.value, 6) + \" \" + c.unit });\n        var r = s(\"rect\", { x: x, y: y, width: bw, height: Math.max(hgt, b.value > 0 ? 1.5 : 0), rx: 3, fill: b.color });\n        r.appendChild(s(\"title\", {}, b.label + \": \" + fmt(b.value, 6) + \" \" + c.unit));\n        g.appendChild(r);\n        g.appendChild(svgText(x + bw \/ 2, y - 6, fmt(b.value, 6), { \"text-anchor\": \"middle\", fill: \"#132238\", \"font-weight\": \"700\" }));\n        var lbl = b.label.length > 16 ? b.label.slice(0, 15) + \"\u2026\" : b.label;\n        g.appendChild(svgText(x + bw \/ 2, P.t + P.h + 17, lbl, { \"text-anchor\": \"middle\", fill: \"#2a3442\" }));\n        svg.appendChild(g);\n      });\n    }\n    function lineChart(box, c) {\n      var W = Math.max(280, box.clientWidth), H = W < 420 ? 240 : 260;\n      var xs = [], ys = [];\n      c.series.forEach(function (sr) { sr.pts.forEach(function (p) { if (p[1] !== null) { xs.push(p[0]); ys.push(p[1]); } }); });\n      var yMin = Math.min.apply(null, ys), yMax = Math.max.apply(null, ys), pad = (yMax - yMin) * 0.12;\n      if (pad === 0) { pad = Math.abs(yMax) * 0.002; if (pad === 0) { pad = 1; } }\n      var y0 = yMin - pad; if (yMin >= 0 ? y0 < 0 : false) { y0 = 0; }\n      var yt = niceTicks(y0, yMax + pad, 5);\n      var xMin = Math.min.apply(null, xs), xMax = Math.max.apply(null, xs);\n      var xt = niceTicks(xMin, xMax, W < 420 ? 4 : 6);\n      xt.list = xt.list.filter(function (t) { return t >= xMin - 1e-9 ? t <= xMax + 1e-9 : false; });\n      var L = leftPad(yt), P = { l: L, t: 18, w: W - L - 18, h: H - 18 - 50 };\n      var svg = frame(box, c, yt, W, H, P);\n      function X(x) { return P.l + (x - xMin) \/ (xMax - xMin) * P.w; }\n      function Y(y) { return P.t + P.h - (y - yt.min) \/ (yt.max - yt.min) * P.h; }\n      xt.list.forEach(function (t) {\n        svg.appendChild(s(\"line\", { x1: X(t), x2: X(t), y1: P.t + P.h, y2: P.t + P.h + 5, stroke: \"#a3adba\" }));\n        svg.appendChild(svgText(X(t), P.t + P.h + 18, tickFmt(t, xt.step), { \"text-anchor\": \"middle\" }));\n      });\n      svg.appendChild(svgText(P.l + P.w \/ 2, H - 6, c.xLabel, { \"text-anchor\": \"middle\", fill: \"#132238\", \"font-weight\": \"600\" }));\n      c.series.slice().reverse().forEach(function (sr) {\n        var d = \"\", pen = false;\n        sr.pts.forEach(function (p) { if (p[1] === null) { pen = false; return; } d += (pen ? \"L\" : \"M\") + X(p[0]).toFixed(2) + \" \" + Y(p[1]).toFixed(2) + \" \"; pen = true; });\n        var a = { d: d, fill: \"none\", stroke: sr.color, \"stroke-width\": sr.dash ? \"2\" : \"2.6\", \"stroke-linejoin\": \"round\", \"stroke-linecap\": \"round\" };\n        if (sr.dash) { a[\"stroke-dasharray\"] = \"6 5\"; }\n        svg.appendChild(s(\"path\", a));\n      });\n      (c.markers ? c.markers : []).forEach(function (mk) {\n        if (!isNum(mk.y)) { return; }\n        var cx = X(mk.x), cy = Y(mk.y);\n        var dot = s(\"circle\", { cx: cx, cy: cy, r: 4.5, fill: \"#fff\", stroke: c.series[0].color, \"stroke-width\": \"2.4\" });\n        dot.appendChild(s(\"title\", {}, mk.label + \": \" + c.xFmt(mk.x) + \", \" + c.yFmt(mk.y)));\n        svg.appendChild(dot);\n        svg.appendChild(svgText(cx, cy - 10, mk.label, { \"text-anchor\": cx > P.l + P.w - 20 ? \"end\" : \"middle\", fill: \"#132238\", \"font-weight\": \"700\" }));\n      });\n      \/* interactive readout: pointer or arrow keys *\/\n      var pts = c.series[0].pts, guide = s(\"g\", { \"pointer-events\": \"none\", visibility: \"hidden\" });\n      var gl = s(\"line\", { y1: P.t, y2: P.t + P.h, stroke: \"#132238\", \"stroke-width\": \"1\", \"stroke-dasharray\": \"3 3\" });\n      var gd = s(\"circle\", { r: 4.5, fill: c.series[0].color, stroke: \"#fff\", \"stroke-width\": \"2\" });\n      var gb = s(\"rect\", { rx: 6, height: 22, fill: \"#132238\", opacity: \"0.92\" });\n      var gt = svgText(0, 0, \"\", { fill: \"#fff\", \"font-weight\": \"600\" });\n      guide.appendChild(gl); guide.appendChild(gd); guide.appendChild(gb); guide.appendChild(gt);\n      svg.appendChild(guide);\n      var ov = s(\"rect\", { class: \"mwcc-ov\", x: P.l, y: P.t, width: P.w, height: P.h, fill: \"transparent\", tabindex: \"0\", role: \"slider\", \"aria-label\": c.title + \" data readout. Use left and right arrow keys.\", \"aria-valuemin\": \"0\", \"aria-valuemax\": String(pts.length - 1), \"aria-valuenow\": \"0\" });\n      svg.appendChild(ov);\n      var idx = -1;\n      function show(i) {\n        i = Math.max(0, Math.min(pts.length - 1, i));\n        idx = i;\n        var p = pts[i];\n        if (p[1] === null) { guide.setAttribute(\"visibility\", \"hidden\"); return; }\n        var px = X(p[0]), py = Y(p[1]);\n        gl.setAttribute(\"x1\", px); gl.setAttribute(\"x2\", px);\n        gd.setAttribute(\"cx\", px); gd.setAttribute(\"cy\", py);\n        var txt = c.xFmt(p[0]) + \" \u2192 \" + c.yFmt(p[1]);\n        gt.textContent = txt;\n        var tw = txt.length * 6.3 + 14, bx = px + 10;\n        if (bx + tw > P.l + P.w) { bx = px - 10 - tw; }\n        if (bx < 2) { bx = 2; }\n        var by = P.t + 2;\n        gb.setAttribute(\"x\", bx); gb.setAttribute(\"y\", by); gb.setAttribute(\"width\", tw);\n        gt.setAttribute(\"x\", bx + 7); gt.setAttribute(\"y\", by + 15);\n        guide.setAttribute(\"visibility\", \"visible\");\n        ov.setAttribute(\"aria-valuenow\", String(i));\n        ov.setAttribute(\"aria-valuetext\", txt);\n      }\n      function fromEvent(e) {\n        var r = svg.getBoundingClientRect(), sc = W \/ r.width, x = (e.clientX - r.left) * sc;\n        show(Math.round((x - P.l) \/ P.w * (pts.length - 1)));\n      }\n      ov.addEventListener(\"pointermove\", fromEvent);\n      ov.addEventListener(\"pointerdown\", fromEvent);\n      ov.addEventListener(\"pointerleave\", function () { if (document.activeElement !== ov) { guide.setAttribute(\"visibility\", \"hidden\"); } });\n      ov.addEventListener(\"blur\", function () { guide.setAttribute(\"visibility\", \"hidden\"); });\n      ov.addEventListener(\"focus\", function () { show(idx < 0 ? 0 : idx); });\n      ov.addEventListener(\"keydown\", function (e) {\n        var k = e.key;\n        if (k === \"ArrowRight\" ? true : k === \"ArrowUp\") { e.preventDefault(); show(idx + 1); }\n        else if (k === \"ArrowLeft\" ? true : k === \"ArrowDown\") { e.preventDefault(); show(idx - 1); }\n        else if (k === \"Home\") { e.preventDefault(); show(0); }\n        else if (k === \"End\") { e.preventDefault(); show(pts.length - 1); }\n      });\n    }\n    function drawCharts() {\n      var R = state.R;\n      if (!R) { return; }\n      R.charts.forEach(function (c) {\n        var box = root.querySelector('[data-mwcc-chart=\"' + c.id + '\"]');\n        if (!box) { return; }\n        clear(box);\n        if (c.type === \"bar\") { barChart(box, c); } else { lineChart(box, c); }\n      });\n      var cw = q(\"mwcc-charts\");\n      state.lastW = cw ? cw.clientWidth : 0;\n    }\n    \/* =====================================================================\n       RUN \u2014 real-time on every change, forced on Calculate\n       ===================================================================== *\/\n    function run(force) {\n      var m = mode();\n      if (force) { errIds().forEach(function (id) { state.touched[id] = true; }); }\n      updateVisibility();\n      var v = m === 4 ? validateCmp() : validateMain(m);\n      showErrors(v.E, force);\n      helpers(v);\n      q(\"mwcc-form-err\").textContent = v.formErr ? v.formErr : \"\";\n      \/* results stay hidden until Calculate is clicked; afterwards they update live *\/\n      var hasResult = v.ok ? true : (m === 4 ? v.rows.some(function (o) { return o.ok; }) : false);\n      if (force ? hasResult : false) { state.shown = true; q(\"mwcc-results\").hidden = false; }\n      if (!state.shown) {\n        state.R = null;\n        if (force) { var f1 = root.querySelector(\".mwcc-invalid\"); if (f1) { try { f1.focus(); } catch (e) { \/* ignore *\/ } } }\n        return;\n      }\n      if (!v.ok) {\n        if (m === 4 ? v.rows.some(function (o) { return o.ok; }) : false) {\n          state.R = computeCmp(v);\n          state.R.time = new Date();\n          renderResults(state.R);\n        } else {\n          state.R = null;\n          renderPlaceholder(v);\n        }\n        if (force) {\n          var f0 = root.querySelector(\".mwcc-invalid\");\n          if (f0) { try { f0.focus(); } catch (e) { \/* ignore *\/ } }\n        }\n        announce(\"\");\n        return;\n      }\n      state.R = m === 4 ? computeCmp(v) : compute(v);\n      state.R.time = new Date();\n      renderResults(state.R);\n      var h0 = state.R.heroes[0];\n      announce(h0 ? h0.label + \": \" + h0.value + \" \" + h0.unit : \"\");\n      if (force) { scrollToResults(); }\n    }\n    function announce(t) {\n      if (state.liveTimer) { clearTimeout(state.liveTimer); }\n      state.liveTimer = setTimeout(function () { q(\"mwcc-live\").textContent = t; }, 700);\n    }\n    function scrollToResults() {\n      var el = q(\"mwcc-results\"), rect = el.getBoundingClientRect();\n      var vh = window.innerHeight ? window.innerHeight : document.documentElement.clientHeight;\n      if (rect.top < 0 ? true : rect.top > vh * 0.6) { if (el.scrollIntoView) { el.scrollIntoView({ behavior: \"smooth\", block: \"start\" }); } }\n      try { el.focus({ preventScroll: true }); } catch (e) { \/* ignore *\/ }\n    }\n    function toast(t) {\n      var el = q(\"mwcc-toast\");\n      el.textContent = t; el.classList.add(\"mwcc-show\");\n      if (state.toastTimer) { clearTimeout(state.toastTimer); }\n      state.toastTimer = setTimeout(function () { el.classList.remove(\"mwcc-show\"); }, 2400);\n    }\n    \/* =====================================================================\n       EXPORTS \u2014 copy, CSV, print\n       ===================================================================== *\/\n    function resultRows(R) {\n      var rows = [];\n      R.heroes.forEach(function (hr) { rows.push([hr.label, hr.value + \" \" + hr.unit]); });\n      R.kpis.forEach(function (k) { rows.push([k.label, k.value + (k.sub ? \" (\" + k.sub + \")\" : \"\")]); });\n      return rows;\n    }\n    function reportText(R) {\n      var L = [\"Material Weight Change Calculator (Temperature & Corrosion)\", \"Generated: \" + R.time.toLocaleString(), \"\", \"INPUTS\"];\n      R.inputs.forEach(function (r) { L.push(r[0] + \": \" + r[1]); });\n      L.push(\"\"); L.push(\"RESULTS\");\n      resultRows(R).forEach(function (r) { L.push(r[0] + \": \" + r[1]); });\n      if (R.table) { L.push(\"\"); L.push(R.table.head.join(\" | \")); R.table.rows.forEach(function (r) { L.push(r.join(\" | \")); }); }\n      if (R.extra.length) { L.push(\"\"); L.push(\"ADDITIONAL RESULTS\"); R.extra.forEach(function (r) { L.push(r[0] + \": \" + r[1]); }); }\n      L.push(\"\"); L.push(\"CALCULATION STEPS\");\n      R.steps.forEach(function (st, i) { L.push((i + 1) + \". \" + st[0] + \": \" + st[1]); });\n      L.push(\"\"); L.push(\"NOTES\");\n      R.msgs.forEach(function (m) { L.push(\"- \" + m.text); });\n      L.push(\"\"); L.push(\"Disclaimer: Simplified estimates for preliminary engineering calculations and educational purposes only. Critical applications require verified material data, appropriate testing, and qualified engineering evaluation.\");\n      return L.join(\"\\n\");\n    }\n    function needR() { if (!state.R) { toast(\"Enter valid inputs first.\"); return false; } if (state.R.heroes.length === 0) { toast(\"Enter valid inputs first.\"); return false; } return true; }\n    function fallbackCopy(txt) {\n      var ta = document.createElement(\"textarea\");\n      ta.value = txt; ta.setAttribute(\"readonly\", \"\"); ta.style.position = \"fixed\"; ta.style.top = \"-1000px\"; ta.style.opacity = \"0\";\n      root.appendChild(ta); ta.select();\n      var ok = false; try { ok = document.execCommand(\"copy\"); } catch (e) { ok = false; }\n      root.removeChild(ta);\n      toast(ok ? \"Results copied to clipboard\" : \"Copy failed. Please select and copy the results manually.\");\n    }\n    function copyResults() {\n      if (!needR()) { return; }\n      var txt = reportText(state.R);\n      if (navigator.clipboard ? (window.isSecureContext ? typeof navigator.clipboard.writeText === \"function\" : false) : false) {\n        navigator.clipboard.writeText(txt).then(function () { toast(\"Results copied to clipboard\"); }, function () { fallbackCopy(txt); });\n      } else { fallbackCopy(txt); }\n    }\n    function csvCell(x) { x = String(x); return \/[\",\\n\\r]\/.test(x) ? '\"' + x.replace(\/\"\/g, '\"\"') + '\"' : x; }\n    function downloadCsv() {\n      if (!needR()) { return; }\n      var R = state.R, lines = [\"Section,Parameter,Value\"];\n      lines.push([\"Report\", \"Generated\", R.time.toLocaleString()].map(csvCell).join(\",\"));\n      R.inputs.forEach(function (r) { lines.push([\"Input\", r[0], r[1]].map(csvCell).join(\",\")); });\n      resultRows(R).forEach(function (r) { lines.push([\"Result\", r[0], r[1]].map(csvCell).join(\",\")); });\n      if (R.table) { R.table.rows.forEach(function (row) { row.forEach(function (c, i) { if (i > 0) { lines.push([\"Comparison: \" + row[0], R.table.head[i], c].map(csvCell).join(\",\")); } }); }); }\n      R.extra.forEach(function (r) { lines.push([\"Additional\", r[0], r[1]].map(csvCell).join(\",\")); });\n      R.steps.forEach(function (st, i) { lines.push([\"Step \" + (i + 1), st[0], st[1]].map(csvCell).join(\",\")); });\n      R.msgs.forEach(function (m) { lines.push([\"Note\", m.tone, m.text].map(csvCell).join(\",\")); });\n      var text = String.fromCharCode(65279) + lines.join(\"\\r\\n\"), name = \"material-weight-change-results.csv\";\n      try {\n        var blob = new Blob([text], { type: \"text\/csv;charset=utf-8\" });\n        if (window.navigator.msSaveOrOpenBlob) { window.navigator.msSaveOrOpenBlob(blob, name); return; }\n        var url = URL.createObjectURL(blob), a = document.createElement(\"a\");\n        a.href = url; a.download = name; a.style.display = \"none\";\n        root.appendChild(a); a.click(); root.removeChild(a);\n        setTimeout(function () { URL.revokeObjectURL(url); }, 1500);\n        toast(\"CSV downloaded\");\n      } catch (e) { toast(\"Download is not supported in this browser\"); }\n    }\n    function printReport() {\n      if (!needR()) { return; }\n      var R = state.R, fr = document.createElement(\"iframe\");\n      fr.setAttribute(\"aria-hidden\", \"true\"); fr.setAttribute(\"tabindex\", \"-1\"); fr.setAttribute(\"title\", \"Print report\");\n      fr.style.position = \"fixed\"; fr.style.right = \"0\"; fr.style.bottom = \"0\"; fr.style.width = \"0\"; fr.style.height = \"0\"; fr.style.border = \"0\";\n      document.body.appendChild(fr);\n      var doc = fr.contentDocument ? fr.contentDocument : fr.contentWindow.document;\n      doc.open(); doc.write(\"<!DOCTYPE html><html><head><meta charset='utf-8'><title>Material Weight Change Report<\/title><\/head><body><\/body><\/html>\"); doc.close();\n      var st = doc.createElement(\"style\");\n      st.textContent = \"body{font-family:Arial,Helvetica,sans-serif;color:#1b2533;margin:28px;font-size:12.5px;line-height:1.45}h1{font-size:19px;margin:0 0 2px;color:#132238}h2{font-size:14px;margin:18px 0 6px;color:#132238;border-bottom:1px solid #ccd3dc;padding-bottom:3px}.n{color:#5b6675;font-size:11px}.hero{display:inline-block;margin:8px 22px 0 0}.hero b{display:block;font-size:22px;color:#132238}.hero span{font-size:10.5px;text-transform:uppercase;letter-spacing:.04em;color:#1a4d8f;font-weight:700}table{border-collapse:collapse;width:100%}td,th{border-bottom:1px solid #e1e5ea;padding:4px 6px;text-align:left;vertical-align:top}th{background:#f2f4f7;font-size:11.5px}td:first-child{color:#4a5565;width:42%}.cmp td:first-child{width:auto;color:#1b2533;font-weight:700}ol{padding-left:18px;margin:0}li{margin-bottom:5px}code{font-family:Consolas,monospace;font-size:11.5px;color:#33415a;display:block}.charts svg{width:48%;height:auto;margin:0 1% 8px 0;border:1px solid #e1e5ea;border-radius:6px;vertical-align:top}ul{padding-left:18px;margin:0}.disc{margin-top:16px;font-size:10.5px;color:#5b4300;border:1px solid #e8cf96;background:#fff8e6;padding:8px 10px;border-radius:6px}@page{margin:14mm}\";\n      doc.head.appendChild(st);\n      function ad(parent, tag, text, cls) { var e = doc.createElement(tag); if (text !== undefined) { e.textContent = text; } if (cls) { e.className = cls; } parent.appendChild(e); return e; }\n      function table(parent, rows, head, cls) {\n        var t = ad(parent, \"table\", undefined, cls);\n        if (head) { var tr0 = ad(t, \"tr\"); head.forEach(function (c) { ad(tr0, \"th\", c); }); }\n        rows.forEach(function (r) { var tr = ad(t, \"tr\"); r.forEach(function (c) { ad(tr, \"td\", c); }); });\n      }\n      var b = doc.body;\n      ad(b, \"h1\", \"Material Weight Change Calculator \u2014 Engineering Report\");\n      ad(b, \"div\", MODE_NAMES[R.mode] + \" \u00b7 Generated \" + R.time.toLocaleString(), \"n\");\n      R.heroes.forEach(function (hr) { var d = ad(b, \"div\", undefined, \"hero\"); ad(d, \"span\", hr.label); ad(d, \"b\", hr.value + \" \" + hr.unit); ad(d, \"div\", hr.sub, \"n\"); });\n      ad(b, \"h2\", \"Inputs\"); table(b, R.inputs);\n      ad(b, \"h2\", \"Results\");\n      if (R.table) { table(b, R.table.rows, R.table.head, \"cmp\"); }\n      if (R.kpis.length) { table(b, R.kpis.map(function (k) { return [k.label, k.value + (k.sub ? \" (\" + k.sub + \")\" : \"\")]; })); }\n      if (R.extra.length) { ad(b, \"h2\", \"Additional results\"); table(b, R.extra); }\n      var svgs = root.querySelectorAll(\"#mwcc-charts svg\");\n      if (svgs.length) {\n        ad(b, \"h2\", \"Charts\");\n        var cd = ad(b, \"div\", undefined, \"charts\");\n        Array.prototype.forEach.call(svgs, function (sv) { var cl = sv.cloneNode(true); cl.removeAttribute(\"width\"); cl.removeAttribute(\"height\"); cd.appendChild(doc.importNode(cl, true)); });\n      }\n      ad(b, \"h2\", \"Calculation steps\");\n      var ol = ad(b, \"ol\");\n      R.steps.forEach(function (stp) { var li = ad(ol, \"li\", stp[0]); ad(li, \"code\", stp[1]); });\n      ad(b, \"h2\", \"Engineering interpretation\");\n      var ul = ad(b, \"ul\");\n      R.msgs.forEach(function (m) { ad(ul, \"li\", m.text); });\n      ad(b, \"div\", \"Disclaimer: This Material Weight Change Calculator provides simplified estimates of temperature-related volume changes and corrosion-related material mass loss based on user-supplied properties and assumed operating conditions. Actual material behavior may differ due to temperature-dependent properties, oxidation, localized corrosion, environmental exposure, material degradation, and geometric changes. Results are intended for preliminary engineering calculations and educational purposes only. Critical applications require verified material data, appropriate testing, and qualified engineering evaluation.\", \"disc\");\n      var w = fr.contentWindow;\n      setTimeout(function () {\n        try { w.focus(); w.print(); } catch (e) { toast(\"Printing is not available in this browser\"); }\n        setTimeout(function () { if (fr.parentNode) { fr.parentNode.removeChild(fr); } }, 2000);\n      }, 250);\n    }\n    \/* =====================================================================\n       DEFAULTS, EXAMPLES AND RESET\n       ===================================================================== *\/\n    var UNIT_SELECTS = { \"mwcc-dens-u\": \"kgm3\", \"mwcc-alpha-u\": \"uC\", \"mwcc-mass-u\": \"kg\", \"mwcc-vol-u\": \"m3\", \"mwcc-len-u\": \"mm\", \"mwcc-area-u\": \"m2\", \"mwcc-g-u\": \"mm\", \"mwcc-rate-u\": \"mmy\", \"mwcc-dur-u\": \"y\", \"mwcc-tu\": \"C\",\n      \"mwcc-cu-dens\": \"kgm3\", \"mwcc-cu-alpha\": \"uC\", \"mwcc-cu-mass\": \"kg\", \"mwcc-cu-rate\": \"mmy\", \"mwcc-cu-area\": \"m2\", \"mwcc-cu-dur\": \"y\", \"mwcc-cu-dt\": \"C\", \"mwcc-ru-mass\": \"kg\", \"mwcc-ru-vol\": \"m3\", \"mwcc-ru-dens\": \"kgm3\" };\n    function setDefaults(o) {\n      if (!o) { o = {}; }\n      Object.keys(UNIT_SELECTS).forEach(function (id) { var el = q(id); el.value = UNIT_SELECTS[id]; el.setAttribute(\"data-prev\", el.value); });\n      setVal(\"mwcc-cat\", \"all\"); setVal(\"mwcc-search\", \"\"); buildMats();\n      setVal(\"mwcc-mat\", \"cs\"); setVal(\"mwcc-cname\", \"\"); applyMaterial();\n      setRadio(\"mwcc-basis\", \"mass\"); setRadio(\"mwcc-abasis\", \"manual\");\n      setVal(\"mwcc-mass\", o.mass ? o.mass : \"100\"); setVal(\"mwcc-vol\", \"\");\n      setVal(\"mwcc-shape\", \"plate\");\n      var gd = { L: \"1000\", W: \"500\", T: \"10\", H: \"200\", R: \"50\", Ro: \"57\", Ri: \"50\", D: \"50\", OW: \"100\", OH: \"60\", IW: \"90\", IH: \"50\" };\n      DIM_IDS.forEach(function (k) { setVal(\"mwcc-g-\" + k, gd[k]); });\n      state.surfSel = {}; buildSurfs();\n      setVal(\"mwcc-len\", \"\");\n      setVal(\"mwcc-area\", \"0.5\");\n      setVal(\"mwcc-t1\", \"20\"); setVal(\"mwcc-t2\", \"120\");\n      setVal(\"mwcc-rate\", \"0.1\"); setVal(\"mwcc-dur\", \"5\");\n      state.cmpRows = defaultCmpRows(); renderCmpRows();\n      state.touched = {};\n    }\n    function loadExample(n) {\n      setDefaults(n === 1 ? { mass: \"10\" } : {});\n      setRadio(\"mwcc-mode\", String(n));\n      run(false);\n    }\n    \/* =====================================================================\n       EVENTS (bound once)\n       ===================================================================== *\/\n    var GEO_IDS = DIM_IDS.map(function (k) { return \"mwcc-g-\" + k; });\n    var CONVERT = {\n      \"mwcc-dens-u\": [[\"mwcc-dens\"], DENS], \"mwcc-alpha-u\": [[\"mwcc-alpha\"], ALPHA], \"mwcc-mass-u\": [[\"mwcc-mass\"], MASS], \"mwcc-vol-u\": [[\"mwcc-vol\"], VOL],\n      \"mwcc-len-u\": [[\"mwcc-len\"], LEN], \"mwcc-area-u\": [[\"mwcc-area\"], AREA], \"mwcc-g-u\": [GEO_IDS, LEN], \"mwcc-rate-u\": [[\"mwcc-rate\"], RATE], \"mwcc-dur-u\": [[\"mwcc-dur\"], TIME]\n    };\n    var CMP_CONVERT = { \"mwcc-cu-dens\": [\"rho\", DENS], \"mwcc-cu-alpha\": [\"alpha\", ALPHA], \"mwcc-cu-mass\": [\"mass\", MASS], \"mwcc-cu-rate\": [\"rate\", RATE], \"mwcc-cu-area\": [\"area\", AREA], \"mwcc-cu-dur\": [\"dur\", TIME], \"mwcc-cu-dt\": [\"dT\", DT] };\n    \/* automatic unit conversion: switching a unit converts the entered value *\/\n    function convertValue(str, from, to, map) {\n      var t = String(str).trim();\n      if (t === \"\") { return str; }\n      var n = Number(t);\n      if (!isNum(n)) { return str; }\n      return inStr(n * map[from] \/ map[to]);\n    }\n    function onUnitChange(sel) {\n      var prev = sel.getAttribute(\"data-prev\"), now = sel.value, id = sel.id;\n      sel.setAttribute(\"data-prev\", now);\n      if (!prev ? true : prev === now) { return; }\n      if (CONVERT[id]) { CONVERT[id][0].forEach(function (iid) { q(iid).value = convertValue(q(iid).value, prev, now, CONVERT[id][1]); }); }\n      else if (id === \"mwcc-tu\") {\n        [\"mwcc-t1\", \"mwcc-t2\"].forEach(function (iid) {\n          var t = String(q(iid).value).trim(), n = Number(t);\n          if (t === \"\" ? false : isNum(n)) { q(iid).value = String(Number(fromK(toK(n, prev), now).toFixed(6))); }\n        });\n      } else if (CMP_CONVERT[id]) {\n        var key = CMP_CONVERT[id][0], map = CMP_CONVERT[id][1];\n        state.cmpRows.forEach(function (r) { r[key] = convertValue(r[key], prev, now, map); });\n        renderCmpRows();\n      }\n    }\n    var form = q(\"mwcc-form\");\n    form.addEventListener(\"input\", function (e) {\n      var t = e.target;\n      if (!t) { return; }\n      if (t.id) { state.touched[t.id] = true; }\n      if (t.id === \"mwcc-search\") { if (buildMats()) { applyMaterial(); } run(false); return; }\n      if (t.id === \"mwcc-dens\" ? true : t.id === \"mwcc-alpha\") { if (val(\"mwcc-mat\") !== \"custom\") { if (!state.edited) { state.edited = true; matInfo(); } } }\n      var ci = t.getAttribute(\"data-mwcc-c\");\n      if (ci !== null) { var ck = t.getAttribute(\"data-mwcc-ck\"); if (state.cmpRows[Number(ci)]) { state.cmpRows[Number(ci)][ck] = t.value; } }\n      if (t.tagName === \"SELECT\" ? true : t.type === \"checkbox\") { return; }\n      run(false);\n    });\n    form.addEventListener(\"change\", function (e) {\n      var t = e.target;\n      if (!t) { return; }\n      var id = t.id;\n      if (t.tagName === \"SELECT\") {\n        if (t.hasAttribute(\"data-prev\")) { onUnitChange(t); }\n        if (id === \"mwcc-cat\") { if (buildMats()) { applyMaterial(); } }\n        if (id === \"mwcc-mat\") { applyMaterial(); }\n        if (id === \"mwcc-shape\") { buildSurfs(); }\n        var ci = t.getAttribute(\"data-mwcc-c\");\n        if (ci !== null) {\n          var row = state.cmpRows[Number(ci)];\n          if (row) { cmpRowFromPreset(t.value, cmpU(), row); renderCmpRows(); var ps = q(\"mwcc-c\" + ci + \"-preset\"); if (ps) { ps.focus(); } }\n        }\n        run(false);\n        return;\n      }\n      if (t.type === \"checkbox\") {\n        var k = t.getAttribute(\"data-mwcc-surf\");\n        if (k) { surfSel(val(\"mwcc-shape\"))[k] = t.checked; state.touched[\"mwcc-surfs\"] = true; }\n        run(false);\n        return;\n      }\n      if (t.type === \"radio\") { run(false); }\n    });\n    form.addEventListener(\"keydown\", function (e) {\n      if (e.key === \"Enter\" ? (e.target ? e.target.tagName === \"INPUT\" : false) : false) { e.preventDefault(); run(true); }\n    });\n    form.addEventListener(\"click\", function (e) {\n      var b = e.target ? e.target.closest(\"[data-mwcc-crm]\") : null;\n      if (!b) { return; }\n      var i = Number(b.getAttribute(\"data-mwcc-crm\"));\n      if (state.cmpRows.length <= 1) { return; }\n      state.cmpRows.splice(i, 1);\n      state.touched = {};\n      renderCmpRows();\n      run(false);\n      var addBtn = q(\"mwcc-cadd\"); if (addBtn) { try { addBtn.focus(); } catch (er) { \/* ignore *\/ } }\n    });\n    q(\"mwcc-cadd\").addEventListener(\"click\", function () {\n      if (state.cmpRows.length >= 5) { return; }\n      var U = cmpU(), r = cmpRowFromPreset(\"custom\", U);\n      r.mass = convertValue(\"100\", \"kg\", U.mass, MASS); r.rate = convertValue(\"0.1\", \"mmy\", U.rate, RATE); r.area = convertValue(\"0.5\", \"m2\", U.area, AREA);\n      r.dur = convertValue(\"5\", \"y\", U.dur, TIME); r.dT = convertValue(\"100\", \"C\", U.dt, DT);\n      state.cmpRows.push(r);\n      renderCmpRows();\n      run(false);\n      var nm = q(\"mwcc-c\" + (state.cmpRows.length - 1) + \"-preset\"); if (nm) { nm.focus(); }\n    });\n    q(\"mwcc-modes\").addEventListener(\"change\", function () { state.touched = {}; run(false); });\n    q(\"mwcc-runits\").addEventListener(\"change\", function () { run(false); });\n    q(\"mwcc-res-body\").addEventListener(\"click\", function (e) {\n      var b = e.target ? e.target.closest(\"[data-mwcc-metric]\") : null;\n      if (!b) { return; }\n      state.cmpMetric = b.getAttribute(\"data-mwcc-metric\");\n      run(false);\n      var nb = root.querySelector('[data-mwcc-metric=\"' + state.cmpMetric + '\"]'); if (nb) { nb.focus(); }\n    });\n    q(\"mwcc-calc\").addEventListener(\"click\", function () { run(true); });\n    \/* redraw charts when their width changes *\/\n    function onResize() {\n      if (state.chartTimer) { clearTimeout(state.chartTimer); }\n      state.chartTimer = setTimeout(function () { var cw = q(\"mwcc-charts\"); if (cw ? cw.clientWidth !== state.lastW : false) { drawCharts(); } }, 120);\n    }\n    if (window.ResizeObserver) { new window.ResizeObserver(onResize).observe(root); }\n    else { window.addEventListener(\"resize\", onResize); }\n    \/* public hooks for testing *\/\n    root.mwccEngine = Engine;\n    \/* initial state *\/\n    buildCats();\n    setDefaults();\n    setRadio(\"mwcc-mode\", \"1\");\n    run(false);\n  }\n  if (document.getElementById(\"mwcc-calculator\")) { init(); }\n  else if (document.readyState === \"loading\") { document.addEventListener(\"DOMContentLoaded\", init); }\n  else { init(); }\n})();\n<\/script>\n<\/div>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n","protected":false},"excerpt":{"rendered":"<p>The Material Weight Change Calculator (Temperature &amp; Corrosion) is a practical online tool designed to help engineers, manufacturers, and material specialists evaluate material mass loss,&#8230;<\/p>","protected":false},"author":2,"featured_media":24998,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"pmpro_default_level":"","_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_feature_clip_id":0,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_post_was_ever_published":false},"categories":[8647],"tags":[8801,8802,8803,8797,8583],"class_list":["post-24997","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-materials-science-and-properties","tag-corrosion-weight-loss","tag-density-change","tag-material-engineering","tag-material-weight","tag-thermal-expansion","pmpro-has-access"],"acf":[],"jetpack_sharing_enabled":true,"jetpack_featured_media_url":"https:\/\/www.mechstream.com\/wp-content\/uploads\/2026\/10\/Material-Weight-Change-Calculator-Temperature-Corrosion.png","_links":{"self":[{"href":"https:\/\/www.mechstream.com\/fr\/wp-json\/wp\/v2\/posts\/24997","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.mechstream.com\/fr\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.mechstream.com\/fr\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.mechstream.com\/fr\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.mechstream.com\/fr\/wp-json\/wp\/v2\/comments?post=24997"}],"version-history":[{"count":0,"href":"https:\/\/www.mechstream.com\/fr\/wp-json\/wp\/v2\/posts\/24997\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.mechstream.com\/fr\/wp-json\/wp\/v2\/media\/24998"}],"wp:attachment":[{"href":"https:\/\/www.mechstream.com\/fr\/wp-json\/wp\/v2\/media?parent=24997"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.mechstream.com\/fr\/wp-json\/wp\/v2\/categories?post=24997"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.mechstream.com\/fr\/wp-json\/wp\/v2\/tags?post=24997"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}