{"id":42290,"date":"2026-06-02T14:20:07","date_gmt":"2026-06-02T14:20:07","guid":{"rendered":"https:\/\/cficompany.com\/?page_id=42290"},"modified":"2026-07-20T20:50:56","modified_gmt":"2026-07-20T20:50:56","slug":"tco-interno","status":"publish","type":"page","link":"https:\/\/cficompany.com\/es\/intranet-post-2\/tco-internal\/","title":{"rendered":"TCO-Interno"},"content":{"rendered":"\t\t<div data-elementor-type=\"wp-page\" data-elementor-id=\"42290\" class=\"elementor elementor-42290\" data-elementor-post-type=\"page\">\n\t\t\t\t<div class=\"elementor-element elementor-element-2f1770c e-flex e-con-boxed e-con e-parent\" data-id=\"2f1770c\" data-element_type=\"container\" data-e-type=\"container\" data-settings=\"{&quot;background_background&quot;:&quot;classic&quot;,&quot;_ob_use_container_extras&quot;:&quot;no&quot;,&quot;_ob_glider_is_slider&quot;:&quot;no&quot;}\">\n\t\t\t\t\t<div class=\"e-con-inner\">\n\t\t\t\t<div class=\"elementor-element elementor-element-ab6217f elementor-widget elementor-widget-html\" data-id=\"ab6217f\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"UTF-8\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, viewport-fit=cover\">\n<meta name=\"theme-color\" content=\"#0B0B0B\">\n<meta name=\"apple-mobile-web-app-capable\" content=\"yes\">\n<meta name=\"mobile-web-app-capable\" content=\"yes\">\n<meta name=\"apple-mobile-web-app-status-bar-style\" content=\"black\">\n<meta name=\"apple-mobile-web-app-title\" content=\"CFI TCO\">\n<title>CFI Portfolio TCO Suite v1.6<\/title>\n<style>\n:root{\n  --yellow:#FFCE2E; --black:#0B0B0B; --white:#FFFFFF;\n  --tricon:#E63C2F; --ultra:#1C4BA7; --steel:#222222;\n  --paper:#F6F5F2; --line:#DDD9D2; --ink:#1A1A1A; --ink2:#5A5751;\n  --pass:#1E7B34; --warn:#A15C00;\n}\n*{box-sizing:border-box; margin:0; padding:0;}\nbody{font-family:Arial,'Arial Nova',Helvetica,sans-serif; background:var(--paper); color:var(--ink); font-size:14px; line-height:1.45;}\n\n\/* Header *\/\nheader{background:var(--black); color:var(--white); border-bottom:4px solid var(--yellow); padding:20px 28px;}\n.hd-row{display:flex; align-items:baseline; justify-content:space-between; flex-wrap:wrap; gap:8px; max-width:1240px; margin:0 auto;}\n.hd-brand{font-weight:900; font-size:22px; letter-spacing:0.06em;}\n.hd-brand span{color:var(--yellow);}\n.hd-title{font-size:14px; color:#CFCBC2;}\n.hd-gov{font-size:11px; color:#9A968E; margin-top:6px; max-width:1240px; margin-left:auto; margin-right:auto;}\n.hd-gov b{color:var(--yellow); font-weight:700;}\n\n\/* Tabs *\/\nnav{background:var(--black); padding:0 28px;}\n.tabs{display:flex; gap:4px; max-width:1240px; margin:0 auto; overflow-x:auto; -webkit-overflow-scrolling:touch; scrollbar-width:none;}\n.tabs::-webkit-scrollbar{display:none;}\n.tab{appearance:none; border:none; background:#1C1C1C; color:#CFCBC2; font:inherit; font-weight:700; font-size:13px; letter-spacing:0.04em; padding:13px 18px 11px; min-height:44px; cursor:pointer; border-top:3px solid transparent; white-space:nowrap; touch-action:manipulation;}\n.tab:hover{color:var(--white);}\n.tab:focus-visible{outline:2px solid var(--yellow); outline-offset:-2px;}\n.tab.active{background:var(--paper); color:var(--ink); border-top-color:var(--yellow);}\n.tab .acc{display:inline-block; width:8px; height:8px; margin-right:7px; border-radius:1px; vertical-align:baseline;}\n.tab[data-tab=\"plate\"] .acc{background:var(--tricon);}\n.tab[data-tab=\"pkg\"] .acc{background:var(--tricon);}\n.tab[data-tab=\"slide\"] .acc{background:var(--tricon);}\n.tab[data-tab=\"pipe\"] .acc{background:var(--ultra);}\n.tab[data-tab=\"cat\"] .acc{background:var(--ultra);}\n\nmain{max-width:1240px; margin:0 auto; padding:22px 28px 60px;}\n.panel{display:none;}\n.panel.active{display:block;}\n.mod-head{display:flex; align-items:baseline; gap:12px; margin:6px 0 4px;}\n.mod-head h1{font-size:19px; font-weight:900; letter-spacing:0.02em;}\n.mod-head .rule{flex:1; height:3px;}\n#plate .mod-head .rule,#pkg .mod-head .rule,#slide .mod-head .rule{background:var(--tricon);}\n#pipe .mod-head .rule,#cat .mod-head .rule{background:var(--ultra);}\n.mod-sub{color:var(--ink2); font-size:12.5px; margin-bottom:16px;}\n\n\/* Customer info + report actions *\/\n.cust{background:var(--white); border:1px solid var(--line); border-left:4px solid var(--yellow); padding:14px 16px; margin:0 0 20px;}\n.cust h2{font-size:12px; font-weight:900; letter-spacing:0.10em; text-transform:uppercase; color:var(--ink2); margin-bottom:10px;}\n.cust-grid{display:grid; grid-template-columns:repeat(auto-fit,minmax(200px,1fr)); gap:10px;}\n.cust-grid .field{margin-bottom:0;}\n.cust-grid input{width:100%; font:inherit; font-size:16px; min-height:44px; padding:8px 10px; border:1px solid var(--line); background:var(--paper);}\n.cust-grid input:focus{outline:2px solid var(--yellow);}\n.actions{display:flex; gap:10px; flex-wrap:wrap; align-items:center; margin-top:12px; padding-top:12px; border-top:1px solid var(--line);}\n.actions .lbl{font-size:11px; font-weight:900; letter-spacing:0.08em; text-transform:uppercase; color:var(--ink2); margin-right:2px;}\n.btn{appearance:none; font:inherit; font-size:13px; font-weight:700; min-height:44px; padding:10px 16px; cursor:pointer; border:1px solid var(--black); background:var(--black); color:var(--white); touch-action:manipulation;}\n.btn:hover{background:#2A2A2A;}\n.btn:focus-visible{outline:2px solid var(--yellow); outline-offset:1px;}\n.btn.primary{background:var(--yellow); color:var(--black); border-color:var(--yellow);}\n.btn.primary:hover{background:#F5C114;}\n.actions .hint{font-size:10.5px; color:var(--ink2); flex-basis:100%;}\n\n\/* Layout *\/\n.grid{display:grid; grid-template-columns:330px 1fr; gap:20px; align-items:start;}\n@media(max-width:900px){.grid{grid-template-columns:1fr;}}\n\n\/* Inputs card *\/\n.card{background:var(--white); border:1px solid var(--line); padding:16px 16px 14px;}\n.card h2{font-size:12px; font-weight:900; letter-spacing:0.10em; text-transform:uppercase; color:var(--ink2); margin-bottom:12px; border-bottom:2px solid var(--yellow); padding-bottom:6px;}\n.field{margin-bottom:12px;}\n.field label{display:block; font-size:12px; font-weight:700; margin-bottom:4px;}\n.field .note{font-size:11px; color:var(--ink2); margin-top:3px;}\n.field select,.field input[type=number]{width:100%; font:inherit; font-size:16px; min-height:44px; padding:8px 10px; border:1px solid var(--line); background:var(--paper);}\n.field select:focus,.field input:focus{outline:2px solid var(--yellow);}\n.two{display:grid; grid-template-columns:1fr 1fr; gap:10px;}\n.warnp{font-size:11px; color:var(--warn); font-weight:700;}\n\n\/* Results *\/\n.res-cards{display:grid; grid-template-columns:repeat(auto-fit,minmax(170px,1fr)); gap:12px; margin-bottom:16px;}\n.rc{background:var(--white); border:1px solid var(--line); border-top:3px solid var(--steel); padding:12px 14px;}\n.rc .l{font-size:11px; font-weight:700; letter-spacing:0.06em; text-transform:uppercase; color:var(--ink2);}\n.rc .v{font-size:24px; font-weight:900; margin:2px 0;}\n.rc .s{font-size:11px; color:var(--ink2);}\n.rc.win{border-top-color:var(--yellow); background:#FFFDF4;}\n\n\/* Gradient bars \u2014 signature element *\/\n.gb-wrap{background:var(--white); border:1px solid var(--line); padding:16px; margin-bottom:16px;}\n.gb-wrap h3{font-size:12px; font-weight:900; letter-spacing:0.10em; text-transform:uppercase; color:var(--ink2); margin-bottom:4px;}\n.gb-cap{font-size:11px; color:var(--ink2); margin-bottom:12px;}\n.gb-row{display:grid; grid-template-columns:150px 1fr 130px; gap:12px; align-items:center; margin-bottom:9px;}\n.gb-name{font-size:12.5px; font-weight:700;}\n.gb-name .tag{display:block; font-size:10.5px; font-weight:400; color:var(--ink2);}\n.gb-bar{position:relative; height:22px; border:1px solid var(--line); background:#EEE;}\n.gb-fill{position:absolute; inset:0;}\n.gb-val{font-size:13px; font-weight:900; text-align:right; white-space:nowrap;}\n.gb-val .sub{display:block; font-size:10.5px; font-weight:400; color:var(--ink2);}\n.gb-legend{display:flex; gap:14px; font-size:10.5px; color:var(--ink2); margin-top:10px; flex-wrap:wrap;}\n.sw{display:inline-block; width:11px; height:11px; vertical-align:-1px; margin-right:4px; border:1px solid var(--line);}\n\n\/* Tables *\/\n#p_tblwrap,#s_tblwrap,#q_tblwrap,#c_tblwrap{overflow-x:auto; -webkit-overflow-scrolling:touch;}\ntable{width:100%; min-width:560px; border-collapse:collapse; background:var(--white); border:1px solid var(--line); font-size:12.5px;}\nth{background:var(--black); color:var(--white); text-align:left; font-size:11px; letter-spacing:0.06em; text-transform:uppercase; padding:8px 10px;}\ntd{padding:7px 10px; border-top:1px solid var(--line);}\ntr.win td{background:#FFFDF4; font-weight:700;}\ntd.num,th.num{text-align:right; font-variant-numeric:tabular-nums;}\n.tbl-cap{font-size:11px; color:var(--ink2); margin:6px 0 16px;}\n\n.callout{border-left:4px solid var(--yellow); background:var(--white); border-top:1px solid var(--line); border-right:1px solid var(--line); border-bottom:1px solid var(--line); padding:10px 14px; font-size:12px; margin-bottom:16px;}\n.callout b{font-weight:900;}\n.callout.red{border-left-color:var(--tricon);}\n.callout.blue{border-left-color:var(--ultra);}\n\n\/* Footer governance strip *\/\nfooter{background:var(--black); color:#CFCBC2; border-top:4px solid var(--yellow); padding:14px 28px; font-size:11px;}\n.ft{max-width:1240px; margin:0 auto; display:flex; justify-content:space-between; gap:16px; flex-wrap:wrap;}\n.selftest{font-weight:900;}\n.selftest.ok{color:#7CCB8B;}\n.selftest.bad{color:#FF7B6E;}\n@media(prefers-reduced-motion:no-preference){.rc,.gb-row{transition:opacity .15s ease;}}\n@media(max-width:640px){\n  header{padding:14px 14px;}\n  nav{padding:0 8px;}\n  main{padding:16px 12px 48px;}\n  footer{padding:12px 14px;}\n  .hd-brand{font-size:18px;}\n  .gb-row{grid-template-columns:96px 1fr 84px; gap:8px;}\n  .gb-name{font-size:11.5px;}\n  .gb-val{font-size:12px;}\n  .res-cards{grid-template-columns:1fr 1fr; gap:8px;}\n  .rc .v{font-size:20px;}\n  .two{grid-template-columns:1fr;}\n  .cust-grid{grid-template-columns:1fr;}\n  .actions .btn{flex:1 1 100%;}\n  .mod-head h1{font-size:16px;}\n}\n<\/style>\n<\/head>\n<body>\n\n<header>\n  <div class=\"hd-row\">\n    <div class=\"hd-brand\">CFI <span>PORTFOLIO TCO SUITE<\/span><\/div>\n    <div class=\"hd-title\">Plate + Pipe &nbsp;|&nbsp; v1.6 &nbsp;|&nbsp; Internal sales tool<\/div>\n  <\/div>\n  <div class=\"hd-gov\">Governed by <b>CFI TCO Model Standard v1.8<\/b> (July 2026). Wear model: life ratio = (HB \/ 160)<sup>1.25<\/sup> vs A36 baseline. All claims state the baseline by name. Certified reps only.<\/div>\n<\/header>\n\n<nav>\n  <div class=\"tabs\" role=\"tablist\">\n    <button class=\"tab active\" data-tab=\"plate\" role=\"tab\" aria-selected=\"true\"><span class=\"acc\"><\/span>AR vs TRI-BRAZE (PLATE BASIS)<\/button>\n    <button class=\"tab\" data-tab=\"pkg\" role=\"tab\" aria-selected=\"false\"><span class=\"acc\"><\/span>AR vs TRI-BRAZE (PACKAGE BASIS)<\/button>\n    <button class=\"tab\" data-tab=\"slide\" role=\"tab\" aria-selected=\"false\"><span class=\"acc\"><\/span>AR 550\/600 vs CCO<\/button>\n    <button class=\"tab\" data-tab=\"pipe\" role=\"tab\" aria-selected=\"false\"><span class=\"acc\"><\/span>PIPE: UT600 vs ESSER 700\/900<\/button>\n    <button class=\"tab\" data-tab=\"cat\" role=\"tab\" aria-selected=\"false\"><span class=\"acc\"><\/span>UT600 CATALOG (ASME)<\/button>\n  <\/div>\n<\/nav>\n\n<main>\n\n<div class=\"cust\" id=\"custpanel\">\n  <h2>Customer Information (appears on every report)<\/h2>\n  <div class=\"cust-grid\">\n    <div class=\"field\"><label for=\"ci_company\">Company<\/label><input type=\"text\" id=\"ci_company\" placeholder=\"Customer company\"><\/div>\n    <div class=\"field\"><label for=\"ci_contact\">Contact name<\/label><input type=\"text\" id=\"ci_contact\" placeholder=\"Name\"><\/div>\n    <div class=\"field\"><label for=\"ci_email\">Contact email<\/label><input type=\"email\" id=\"ci_email\" placeholder=\"name@company.com\"><\/div>\n    <div class=\"field\"><label for=\"ci_site\">Site \/ location<\/label><input type=\"text\" id=\"ci_site\" placeholder=\"Plant, city\"><\/div>\n    <div class=\"field\"><label for=\"ci_app\">Application<\/label><input type=\"text\" id=\"ci_app\" placeholder=\"e.g. crusher discharge chute\"><\/div>\n    <div class=\"field\"><label for=\"ci_rep\">Prepared by<\/label><input type=\"text\" id=\"ci_rep\" placeholder=\"Rep name\"><\/div>\n    <div class=\"field\"><label for=\"ci_date\">Date<\/label><input type=\"text\" id=\"ci_date\"><\/div>\n  <\/div>\n  <div class=\"actions\">\n    <span class=\"lbl\">Report (active tab):<\/span>\n    <button class=\"btn\" id=\"btn_html\" type=\"button\">Download report file<\/button>\n    <button class=\"btn\" id=\"btn_pdf\" type=\"button\">Save as PDF<\/button>\n    <button class=\"btn primary\" id=\"btn_mail\" type=\"button\">Email to customer<\/button>\n    <span class=\"hint\">Save as PDF opens the print dialog: choose \"Save as PDF\" (Android\/desktop) or pinch-zoom the preview then share\/save as PDF (iPhone\/iPad). Downloads land in Files (Apple) or Downloads (Android). Email opens your mail app pre-addressed; attach the saved PDF before sending. Customer data lives only in this session and is never stored.<\/span>\n  <\/div>\n<\/div>\n\n<!-- \u2550\u2550\u2550\u2550\u2550\u2550 TAB A: IMPACT + ABRASION \u2550\u2550\u2550\u2550\u2550\u2550 -->\n<section id=\"plate\" class=\"panel active\" role=\"tabpanel\">\n  <div class=\"mod-head\"><h1>AR 400 \/ 450 \/ 500 vs Tri-Braze: Plate Basis<\/h1><div class=\"rule\"><\/div><\/div>\n  <div class=\"mod-sub\">Tricon Wear Solutions. Impact + abrasion use model. TCO basis: plate thickness, plate count, and price per pound. For a quoted installed liner package, use the Package Basis tab. AR400 through AR500 modeled as gradient products (AR400 = 375 HB guaranteed minimum; midline = 90% of surface), layer-integrated through 80% usable depth. Tri-Braze through-hardened at 470 HB with certified field impact multipliers vs the reference grade. For sliding-abrasion-only service, use the AR 550\/600 vs CCO tab.<\/div>\n\n  <div class=\"grid\">\n    <div>\n      <div class=\"card\">\n        <h2>Application Inputs<\/h2>\n        <div class=\"field\"><label for=\"p_thick\">Plate thickness (in)<\/label>\n          <input type=\"number\" id=\"p_thick\" value=\"0.500\" min=\"0.125\" max=\"3\" step=\"0.0625\"><\/div>\n        <div class=\"field\"><label for=\"p_duty\">Duty tier<\/label>\n          <select id=\"p_duty\"><\/select><div class=\"note\" id=\"p_dutynote\"><\/div><\/div>\n        <div class=\"field\"><label for=\"p_wear\">A36 baseline wear rate (in\/yr at Moderate)<\/label>\n          <input type=\"number\" id=\"p_wear\" value=\"1.000\" min=\"0.05\" max=\"5\" step=\"0.05\">\n          <div class=\"note\">Source this from the customer's mild steel history. Do not invent it.<\/div><\/div>\n        <div class=\"field\"><label for=\"p_ref\">Tri-Braze reference AR grade<\/label>\n          <select id=\"p_ref\"><option>AR400<\/option><option selected>AR450<\/option><option>AR500<\/option><\/select>\n          <div class=\"note\">Field impact multipliers are certified for these three references.<\/div><\/div>\n      <\/div>\n      <div class=\"card\" style=\"margin-top:14px;\">\n        <h2>Fleet Economics<\/h2>\n        <div class=\"two\">\n          <div class=\"field\"><label for=\"p_fleet\">Plates in fleet<\/label><input type=\"number\" id=\"p_fleet\" value=\"20\" min=\"1\" max=\"500\"><\/div>\n          <div class=\"field\"><label for=\"p_horiz\">Horizon (months)<\/label><input type=\"number\" id=\"p_horiz\" value=\"36\" min=\"12\" max=\"120\" step=\"12\"><\/div>\n        <\/div>\n        <div class=\"two\">\n          <div class=\"field\"><label for=\"p_labor\">Labor per changeout ($)<\/label><input type=\"number\" id=\"p_labor\" value=\"2500\" min=\"0\" step=\"250\"><\/div>\n          <div class=\"field\"><label for=\"p_down\">Downtime per changeout ($)<\/label><input type=\"number\" id=\"p_down\" value=\"3500\" min=\"0\" step=\"500\"><\/div>\n        <\/div>\n        <div class=\"field\"><label>Material price ($\/lb)<\/label>\n          <div class=\"two\">\n            <div><input type=\"number\" id=\"p_priceRef\" value=\"1.35\" min=\"0.1\" step=\"0.01\"><div class=\"note\" id=\"p_priceRefLbl\">AR450<\/div><\/div>\n            <div><input type=\"number\" id=\"p_priceTB\" value=\"1.39\" min=\"0.1\" step=\"0.01\"><div class=\"note\">Tri-Braze<\/div><\/div>\n          <\/div>\n        <\/div>\n      <\/div>\n    <\/div>\n\n    <div>\n      <div class=\"gb-wrap\">\n        <h3>Relative Wear Life vs A36 Mild Steel (160 HB)<\/h3>\n        <div class=\"gb-cap\">Bar fill maps hardness through the usable wear depth: darker = harder. Value = layer-integrated life multiple at the selected thickness. Every claim is &ldquo;&times; the life of A36 mild steel.&rdquo;<\/div>\n        <div id=\"p_bars\"><\/div>\n      <\/div>\n\n      <div class=\"res-cards\" id=\"p_cards\"><\/div>\n      <div id=\"p_tblwrap\"><\/div>\n\n      <div class=\"callout red\" id=\"p_tbnote\"><\/div>\n      <div class=\"callout red\"><b>Use-model rule (Standard Sec. 12):<\/b> this tab is for combined impact and abrasion service, where AR 400\/450\/500 and Tri-Braze belong. Comparing these grades to CCO is not a sanctioned comparison; CCO is a sliding-abrasion product. If the application is sliding abrasion only, switch tabs.<\/div>\n    <\/div>\n  <\/div>\n<\/section>\n\n<!-- \u2550\u2550\u2550\u2550\u2550\u2550 TAB A2: PACKAGE BASIS \u2550\u2550\u2550\u2550\u2550\u2550 -->\n<section id=\"pkg\" class=\"panel\" role=\"tabpanel\">\n  <div class=\"mod-head\"><h1>AR 400 \/ 450 \/ 500 vs Tri-Braze: Liner Package Basis<\/h1><div class=\"rule\"><\/div><\/div>\n  <div class=\"mod-sub\">Tricon Wear Solutions. Impact + abrasion use model. TCO basis: total installed liner package cost. Wear life basis: plate thickness through the gradient-integrated wear model (default), or customer-measured package field life. Tri-Braze life = AR life &times; the certified field impact multiplier (Tri-Braze Fleet TCO v2.9.4). Use this tab when the job is quoted as a complete liner package rather than by plate.<\/div>\n\n  <div class=\"grid\">\n    <div class=\"card\">\n      <h2>Package Inputs<\/h2>\n      <div class=\"field\"><label for=\"k_ref\">AR reference grade<\/label>\n        <select id=\"k_ref\"><option>AR400<\/option><option selected>AR450<\/option><option>AR500<\/option><\/select>\n        <div class=\"note\">Field impact multipliers are certified for these three references.<\/div><\/div>\n      <div class=\"field\"><label for=\"k_duty\">Duty tier<\/label>\n        <select id=\"k_duty\"><\/select><div class=\"note\" id=\"k_dutynote\"><\/div><\/div>\n      <div class=\"field\"><label for=\"k_basis\">Wear life basis<\/label>\n        <select id=\"k_basis\">\n          <option value=\"model\" selected>Model-calculated (thickness + wear rate)<\/option>\n          <option value=\"field\">Customer field life (months)<\/option>\n        <\/select>\n        <div class=\"note\">Default: the locked wear model computes life from plate thickness. Switch to field life when the customer has measured liner history.<\/div><\/div>\n      <div class=\"field\" id=\"k_f_thick\"><label for=\"k_thick\">Plate thickness (in)<\/label>\n        <input type=\"number\" id=\"k_thick\" value=\"0.500\" min=\"0.125\" max=\"3\" step=\"0.0625\">\n        <div class=\"note\">Drives wear life through the gradient-integrated model, 80% usable depth.<\/div><\/div>\n      <div class=\"field\" id=\"k_f_wear\"><label for=\"k_wear\">A36 baseline wear rate (in\/yr at Moderate)<\/label>\n        <input type=\"number\" id=\"k_wear\" value=\"1.000\" min=\"0.05\" max=\"5\" step=\"0.05\">\n        <div class=\"note\">Source from the customer's mild steel history. Do not invent it.<\/div><\/div>\n      <div class=\"field\" id=\"k_f_life\" style=\"display:none;\"><label for=\"k_life\">AR package field life (months)<\/label>\n        <input type=\"number\" id=\"k_life\" value=\"6\" min=\"0.5\" max=\"60\" step=\"0.5\">\n        <div class=\"note\" id=\"k_lifenote\">Prefilled from certified field data for the grade and duty. Replace with the customer's actual liner life whenever they have it.<\/div><\/div>\n      <div class=\"field\"><label for=\"k_costAR\">AR liner package installed cost ($)<\/label>\n        <input type=\"number\" id=\"k_costAR\" min=\"0\" step=\"500\" placeholder=\"Enter installed package cost\">\n        <div class=\"note\">Complete package: material, fabrication, hardware, installation.<\/div><\/div>\n      <div class=\"field\"><label for=\"k_costTB\">Tri-Braze liner package installed cost ($)<\/label>\n        <input type=\"number\" id=\"k_costTB\" min=\"0\" step=\"500\" placeholder=\"Enter installed package cost\"><\/div>\n      <div class=\"field\"><label for=\"k_horiz\">Horizon (months)<\/label>\n        <input type=\"number\" id=\"k_horiz\" value=\"36\" min=\"12\" max=\"120\" step=\"12\"><\/div>\n      <div class=\"two\">\n        <div class=\"field\"><label for=\"k_labor\">Labor per changeout ($)<\/label><input type=\"number\" id=\"k_labor\" value=\"2500\" min=\"0\" step=\"250\"><\/div>\n        <div class=\"field\"><label for=\"k_down\">Downtime per changeout ($)<\/label><input type=\"number\" id=\"k_down\" value=\"3500\" min=\"0\" step=\"500\"><\/div>\n      <\/div>\n    <\/div>\n\n    <div>\n      <div class=\"gb-wrap\">\n        <h3>Package Life at This Duty<\/h3>\n        <div class=\"gb-cap\">Tri-Braze life is the AR package life times the certified field impact multiplier. The life input is customer-sourced; the multiplier is locked.<\/div>\n        <div id=\"k_bars\"><\/div>\n      <\/div>\n\n      <div class=\"res-cards\" id=\"k_cards\"><\/div>\n      <div id=\"k_tblwrap\"><\/div>\n\n      <div class=\"callout red\" id=\"k_note\"><\/div>\n      <div class=\"callout red\"><b>Use-model rule (Standard Sec. 12):<\/b> this tab is for combined impact and abrasion service. For sliding abrasion only, use the AR 550\/600 vs CCO tab.<\/div>\n    <\/div>\n  <\/div>\n<\/section>\n\n<!-- \u2550\u2550\u2550\u2550\u2550\u2550 TAB B: SLIDING ABRASION \u2550\u2550\u2550\u2550\u2550\u2550 -->\n<section id=\"slide\" class=\"panel\" role=\"tabpanel\">\n  <div class=\"mod-head\"><h1>Sliding Abrasion Service: AR 550 \/ 600 vs CCO<\/h1><div class=\"rule\"><\/div><\/div>\n  <div class=\"mod-sub\">Tricon Wear Solutions. Use model: sliding abrasion only, no significant impact. AR550\/AR600 modeled as gradient products under the plate gradient rule, layer-integrated through 80% usable depth (hardness power law). CCO governed by carbide volume fraction; the hardness law does not apply; 50% of overlay is usable. Wear life comparison plus a package-basis TCO on quoted installed costs. No certified economics exist for this pairing, so the TCO is a Director of Product Management ruling pending VP Sales TWS price confirmation and every output is flagged commercially uncertified.<\/div>\n\n  <div class=\"grid\">\n    <div>\n      <div class=\"card\">\n        <h2>Application Inputs<\/h2>\n        <div class=\"field\"><label for=\"s_thick\">AR plate thickness (in)<\/label>\n          <input type=\"number\" id=\"s_thick\" value=\"0.500\" min=\"0.125\" max=\"2\" step=\"0.0625\"><\/div>\n        <div class=\"field\"><label for=\"s_duty\">Duty tier<\/label>\n          <select id=\"s_duty\"><\/select><div class=\"note\" id=\"s_dutynote\"><\/div><\/div>\n        <div class=\"field\"><label for=\"s_wear\">A36 baseline wear rate (in\/yr at Moderate)<\/label>\n          <input type=\"number\" id=\"s_wear\" value=\"1.000\" min=\"0.05\" max=\"5\" step=\"0.05\">\n          <div class=\"note\">Source from the customer's mild steel history.<\/div><\/div>\n        <div class=\"field\"><label for=\"s_ccototal\">CCO clad total thickness (in)<\/label>\n          <input type=\"number\" id=\"s_ccototal\" value=\"0.500\" min=\"0.25\" max=\"2\" step=\"0.0625\"><\/div>\n        <div class=\"field\"><label for=\"s_overlay\">Overlay share of total (%)<\/label>\n          <input type=\"number\" id=\"s_overlay\" value=\"50\" min=\"30\" max=\"70\" step=\"5\">\n          <div class=\"note\">Balance is the mild steel substrate.<\/div><\/div>\n        <div class=\"field\"><label for=\"s_carb\">CCO carbide volume fraction (%)<\/label>\n          <input type=\"number\" id=\"s_carb\" value=\"47.5\" min=\"35\" max=\"60\" step=\"0.5\">\n          <div class=\"note\">Standard band 43&ndash;52%. Default 47.5. This governs CCO life, not hardness.<\/div><\/div>\n      <\/div>\n\n      <div class=\"card\" style=\"margin-top:14px;\">\n        <h2>Package TCO Inputs<\/h2>\n        <div class=\"warnp\" style=\"margin-bottom:10px;\">Commercially uncertified pairing. Dir. PM ruling, pending VP Sales TWS price confirmation. Quoted installed costs only; no default prices exist.<\/div>\n        <div class=\"field\"><label for=\"s_tco_basis\">Wear life basis<\/label>\n          <select id=\"s_tco_basis\">\n            <option value=\"model\" selected>Model-calculated (geometry above)<\/option>\n            <option value=\"field\">Customer field life (months)<\/option>\n          <\/select>\n          <div class=\"note\">Default: life from the geometry inputs above. Switch to field life when the customer has measured liner history; measured data governs.<\/div><\/div>\n        <div id=\"s_tco_fieldlife\" style=\"display:none;\">\n          <div class=\"two\">\n            <div class=\"field\"><label for=\"s_life550\">AR550 field life (mo)<\/label><input type=\"number\" id=\"s_life550\" min=\"0.5\" max=\"120\" step=\"0.5\"><\/div>\n            <div class=\"field\"><label for=\"s_life600\">AR600 field life (mo)<\/label><input type=\"number\" id=\"s_life600\" min=\"0.5\" max=\"120\" step=\"0.5\"><\/div>\n          <\/div>\n          <div class=\"field\"><label for=\"s_lifecco\">CCO field life (mo)<\/label><input type=\"number\" id=\"s_lifecco\" min=\"0.5\" max=\"120\" step=\"0.5\">\n            <div class=\"note\">Prefilled from the model estimate. Replace with measured liner life whenever it exists.<\/div><\/div>\n        <\/div>\n        <div class=\"field\"><label for=\"s_cost550\">AR550 installed package cost ($)<\/label>\n          <input type=\"number\" id=\"s_cost550\" min=\"0\" step=\"500\" placeholder=\"Enter quoted installed cost\">\n          <div class=\"note\">Complete package: material, fabrication, hardware, installation. Leave blank to omit a product.<\/div><\/div>\n        <div class=\"field\"><label for=\"s_cost600\">AR600 installed package cost ($)<\/label>\n          <input type=\"number\" id=\"s_cost600\" min=\"0\" step=\"500\" placeholder=\"Enter quoted installed cost\"><\/div>\n        <div class=\"field\"><label for=\"s_costcco\">CCO installed package cost ($)<\/label>\n          <input type=\"number\" id=\"s_costcco\" min=\"0\" step=\"500\" placeholder=\"Enter quoted installed cost\"><\/div>\n        <div class=\"field\"><label for=\"s_tco_horiz\">Horizon (months)<\/label>\n          <input type=\"number\" id=\"s_tco_horiz\" value=\"36\" min=\"12\" max=\"120\" step=\"12\"><\/div>\n        <div class=\"two\">\n          <div class=\"field\"><label for=\"s_tco_labor\">Labor per changeout ($)<\/label><input type=\"number\" id=\"s_tco_labor\" value=\"2500\" min=\"0\" step=\"250\"><\/div>\n          <div class=\"field\"><label for=\"s_tco_down\">Downtime per changeout ($)<\/label><input type=\"number\" id=\"s_tco_down\" value=\"3500\" min=\"0\" step=\"500\"><\/div>\n        <\/div>\n      <\/div>\n    <\/div>\n\n    <div>\n      <div class=\"gb-wrap\">\n        <h3>Relative Wear Life vs A36 Mild Steel (160 HB)<\/h3>\n        <div class=\"gb-cap\">AR bars map the surface-to-midline gradient; the hatched CCO bar is carbide-governed, not a hardness gradient. Values are life multiples vs A36.<\/div>\n        <div id=\"s_bars\"><\/div>\n        <div class=\"gb-legend\">\n          <span><span class=\"sw\" style=\"background:linear-gradient(90deg,#3b3b3b,#c9c9c9);\"><\/span>Hardness gradient (surface &rarr; core)<\/span>\n          <span><span class=\"sw\" style=\"background:repeating-linear-gradient(45deg,#8a8a8a 0 4px,#c9c9c9 4px 8px);\"><\/span>Carbide-governed (hardness law does not apply)<\/span>\n        <\/div>\n      <\/div>\n\n      <div class=\"res-cards\" id=\"s_cards\"><\/div>\n      <div id=\"s_tblwrap\"><\/div>\n\n      <div class=\"gb-wrap\" style=\"margin-top:16px;\">\n        <h3>Package TCO: Life at This Duty<\/h3>\n        <div class=\"gb-cap\">Commercially uncertified pairing (Dir. PM ruling, pending VP Sales price confirmation). Life from the wear model by default, or the customer&rsquo;s measured field life. TCO computes only for products with a quoted installed cost.<\/div>\n        <div id=\"s_tco_bars\"><\/div>\n      <\/div>\n      <div class=\"res-cards\" id=\"s_tco_cards\"><\/div>\n      <div id=\"s_tco_tblwrap\"><\/div>\n      <div class=\"callout red\" id=\"s_tco_note\"><\/div>\n\n      <div class=\"callout red\"><b>Use-model rule (Standard Sec. 12):<\/b> this tab is for sliding abrasion only. AR550, AR600, and CCO are not impact products. If the application sees significant impact or gouging, switch to the AR 400\/450\/500 vs Tri-Braze tab; recommending CCO or AR600 into impact service is a misapplication regardless of what the life numbers say.<\/div>\n      <div class=\"callout\"><b>CCO rule (Standard Sec. 7):<\/b> quote the carbide band, not a BHN. Usable depth = 50% of overlay thickness; the bond margin is retained. Changeout planning runs on wear-through of the effective overlay, not the full clad thickness.<\/div>\n      <div class=\"callout red\"><b>Pricing note (Dir. PM ruling):<\/b> the standard freeze on TCO for this pairing (Standard Sec. 11 and 12) is overridden by the standard owner, pending VP Sales TWS price confirmation. The package TCO above runs on quoted installed costs only; AR550\/AR600 carry no verified standard price and CCO has no locked price, so the pairing is commercially uncertified and every report is flagged as such. Confirm the VP Sales ruling before quoting a customer.<\/div>\n    <\/div>\n  <\/div>\n<\/section>\n\n<!-- \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 PIPE METRIC \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\n<section id=\"pipe\" class=\"panel\" role=\"tabpanel\">\n  <div class=\"mod-head\"><h1>Pipe Portfolio: UT600 vs ESSER Twin 700 \/ 900<\/h1><div class=\"rule\"><\/div><\/div>\n  <div class=\"mod-sub\">Ultra Tech induction-hardened (650 BHN ID &rarr; 250 BHN OD gradient, PF8050H profile, layer-integrated) vs ESSER twin-wall (720 HB &times; 0.92 two-layer correction; 850 HB white iron floor-and-range) vs A36 mild steel. Metric DN sizing. Duty-tier model; velocity\/erosion-regime corrections are outside model validity per Standard v1.4 and are excluded.<\/div>\n\n  <div class=\"grid\">\n    <div class=\"card\">\n      <h2>Application Inputs<\/h2>\n      <div class=\"field\"><label for=\"q_dn\">Pipe size (DN)<\/label><select id=\"q_dn\"><\/select><div class=\"note\" id=\"q_walls\"><\/div><\/div>\n      <div class=\"field\"><label for=\"q_duty\">Duty tier<\/label><select id=\"q_duty\"><\/select><div class=\"note\" id=\"q_dutynote\"><\/div><\/div>\n      <div class=\"field\"><label for=\"q_wear\">A36 baseline wear rate (in\/yr at Moderate)<\/label>\n        <input type=\"number\" id=\"q_wear\" value=\"0.250\" min=\"0.025\" max=\"2\" step=\"0.025\">\n        <div class=\"note\">Source from customer history on mild steel line pipe.<\/div><\/div>\n      <div class=\"field\"><label for=\"q_retire\">Wall retirement fraction (%)<\/label>\n        <input type=\"number\" id=\"q_retire\" value=\"25\" min=\"10\" max=\"50\" step=\"5\">\n        <div class=\"note\">Minimum remaining wall per pressure rating. Usable wall = 100% &minus; retirement.<\/div><\/div>\n      <div class=\"two\">\n        <div class=\"field\"><label for=\"q_len\">Line length (m)<\/label><input type=\"number\" id=\"q_len\" value=\"500\" min=\"10\" step=\"10\"><\/div>\n        <div class=\"field\"><label for=\"q_horiz\">Horizon (yr)<\/label><input type=\"number\" id=\"q_horiz\" value=\"10\" min=\"1\" max=\"25\"><\/div>\n      <\/div>\n      <div class=\"field\"><label>Installed cost ($\/m)<\/label>\n        <div class=\"two\">\n          <div><input type=\"number\" id=\"q_cms\" value=\"95\" min=\"1\"><div class=\"note\">Mild steel<\/div><\/div>\n          <div><input type=\"number\" id=\"q_cut\" value=\"265\" min=\"1\"><div class=\"note\">UT600<\/div><\/div>\n        <\/div>\n        <div class=\"two\" style=\"margin-top:8px;\">\n          <div><input type=\"number\" id=\"q_c7\" value=\"320\" min=\"1\"><div class=\"note\">ESSER 700<\/div><\/div>\n          <div><input type=\"number\" id=\"q_c9\" value=\"480\" min=\"1\"><div class=\"note\">ESSER 900<\/div><\/div>\n        <\/div>\n      <\/div>\n      <div class=\"two\">\n        <div class=\"field\"><label for=\"q_down\">Downtime ($\/hr)<\/label><input type=\"number\" id=\"q_down\" value=\"5000\" min=\"0\" step=\"500\"><\/div>\n        <div class=\"field\"><label for=\"q_labor\">Labor per change ($\/50 m)<\/label><input type=\"number\" id=\"q_labor\" value=\"4500\" min=\"0\" step=\"250\"><\/div>\n      <\/div>\n      <div class=\"note\">Downtime per changeout = 8 hr per 200 m of line.<\/div>\n    <\/div>\n\n    <div>\n      <div class=\"gb-wrap\">\n        <h3>Relative Wear Life vs A36 Mild Steel (160 HB)<\/h3>\n        <div class=\"gb-cap\">UT600 bar shows the actual ID&rarr;OD hardness gradient; its value is the layer-integrated multiple through the usable wall. ESSER 900 shows the model floor; field range 40&ndash;70&times; per TWS G65 data for A532 Class 3.<\/div>\n        <div id=\"q_bars\"><\/div>\n      <\/div>\n\n      <div class=\"res-cards\" id=\"q_cards\"><\/div>\n      <div id=\"q_tblwrap\"><\/div>\n\n      <div class=\"callout blue\"><b>White iron rule (Standard Sec. 7):<\/b> present ESSER Twin 900 as a floor and a range, never a single number: &ldquo;the hardness model floor is <span id=\"q_e9floor\"><\/span> the life of A36 mild steel; measured G65 field data for this class of white iron runs 40&ndash;70&times;.&rdquo; Do not oversell the range or undersell the floor.<\/div>\n      <div class=\"callout blue\"><b>Gradient rule:<\/b> UT600 is a gradient product. Quote the wear-face hardness (650 BHN) and let the tool produce the life number. Never quote one hardness for a gradient product.<\/div>\n    <\/div>\n  <\/div>\n<\/section>\n\n<!-- \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 UT600 CATALOG \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 -->\n<section id=\"cat\" class=\"panel\" role=\"tabpanel\">\n  <div class=\"mod-head\"><h1>UT600 Catalog: ASME Sizing, Pressure &amp; TCO<\/h1><div class=\"rule\"><\/div><\/div>\n  <div class=\"mod-sub\">Ultra Tech UT600 part-number match by NPS and schedule, pressure rating at selected safety factor, gradient-integrated wear life, and TCO vs A36 mild steel of the same schedule.<\/div>\n\n  <div class=\"grid\">\n    <div class=\"card\">\n      <h2>Selection &amp; Economics<\/h2>\n      <div class=\"field\"><label for=\"c_dia\">Nominal pipe size<\/label><select id=\"c_dia\"><\/select><\/div>\n      <div class=\"field\"><label for=\"c_sched\">Schedule<\/label><select id=\"c_sched\"><\/select><\/div>\n      <div class=\"field\"><label for=\"c_sf\">Safety factor<\/label>\n        <select id=\"c_sf\"><option value=\"3\">3:1<\/option><option value=\"4\" selected>4:1<\/option><option value=\"5\">5:1<\/option><\/select><\/div>\n      <div class=\"field\"><label for=\"c_duty\">Duty tier<\/label><select id=\"c_duty\"><\/select><div class=\"note\" id=\"c_dutynote\"><\/div><\/div>\n      <div class=\"field\"><label for=\"c_wear\">A36 baseline wear rate (in\/yr at Moderate)<\/label>\n        <input type=\"number\" id=\"c_wear\" value=\"0.250\" min=\"0.025\" max=\"2\" step=\"0.025\"><\/div>\n      <div class=\"field\"><label for=\"c_retire\">Wall retirement fraction (%)<\/label>\n        <input type=\"number\" id=\"c_retire\" value=\"25\" min=\"10\" max=\"50\" step=\"5\"><\/div>\n      <div class=\"two\">\n        <div class=\"field\"><label for=\"c_len\">Line length (ft)<\/label><input type=\"number\" id=\"c_len\" value=\"500\" min=\"10\" step=\"10\"><\/div>\n        <div class=\"field\"><label for=\"c_horiz\">Horizon (yr)<\/label><input type=\"number\" id=\"c_horiz\" value=\"5\" min=\"1\" max=\"25\"><\/div>\n      <\/div>\n      <div class=\"field\"><label>UT600 cost ($\/ft)<\/label>\n        <div class=\"two\">\n          <div><input type=\"number\" id=\"c_utp\" value=\"90\" min=\"1\"><div class=\"note\">Pipe<\/div><\/div>\n          <div><input type=\"number\" id=\"c_uti\" value=\"20\" min=\"1\"><div class=\"note\">Install<\/div><\/div>\n        <\/div><\/div>\n      <div class=\"field\"><label>Mild steel cost ($\/ft)<\/label>\n        <div class=\"two\">\n          <div><input type=\"number\" id=\"c_msp\" value=\"30\" min=\"1\"><div class=\"note\">Pipe<\/div><\/div>\n          <div><input type=\"number\" id=\"c_msi\" value=\"15\" min=\"1\"><div class=\"note\">Install<\/div><\/div>\n        <\/div><\/div>\n      <div class=\"two\">\n        <div class=\"field\"><label for=\"c_down\">Downtime ($\/hr)<\/label><input type=\"number\" id=\"c_down\" value=\"5000\" min=\"0\" step=\"500\"><\/div>\n        <div class=\"field\"><label for=\"c_labor\">Labor per change ($\/50 ft)<\/label><input type=\"number\" id=\"c_labor\" value=\"4500\" min=\"0\" step=\"250\"><\/div>\n      <\/div>\n    <\/div>\n\n    <div>\n      <div class=\"res-cards\" id=\"c_cards\"><\/div>\n      <div class=\"gb-wrap\">\n        <h3>UT600 Hardness Through the Wall (ID &rarr; OD)<\/h3>\n        <div class=\"gb-cap\">PF8050H qualification profile, affinely rescaled to locked anchors 650 BHN (ID) \/ 250 BHN (OD). Standard v1.2.<\/div>\n        <div id=\"c_profile\"><\/div>\n      <\/div>\n      <div id=\"c_tblwrap\"><\/div>\n    <\/div>\n  <\/div>\n<\/section>\n\n<\/main>\n\n<footer>\n  <div class=\"ft\">\n    <div>CFI Portfolio TCO Suite v1.6 &nbsp;|&nbsp; Model: CFI TCO Model Standard v1.8 &nbsp;|&nbsp; Sources: AR Material TCO v5.8, Tri-Braze Fleet v2.9.4, AR\/CCO v9, UT600\/ESSER v8, Ultra 600 v17 &nbsp;|&nbsp; Field validation log per Standard Sec. 10<\/div>\n    <div class=\"selftest\" id=\"selftest\">Self-test: running&hellip;<\/div>\n  <\/div>\n<\/footer>\n\n<script>\n\/\/ ============================================================================\n\/\/ CFI PORTFOLIO TCO SUITE \u2014 CALCULATION ENGINE\n\/\/ Governed by CFI TCO Model Standard v1.8 (July 2026). Pure functions only.\n\/\/ ============================================================================\n\n\/\/ \u2500\u2500 Locked constants (Standard v1.4) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nconst WRI_N        = 1.25;        \/\/ hardness power-law exponent, locked\nconst BHN_BASE     = 160;         \/\/ A36 mild steel baseline, locked\nconst LAYER_IN     = 1\/32;        \/\/ layer integration resolution\nconst AR_WEAR_FRAC = 0.80;        \/\/ usable wear fraction, AR plate\nconst CCO_WEAR_FRAC= 0.50;        \/\/ usable fraction of CCO overlay\nconst PLATE_L_IN   = 288;\nconst PLATE_W_IN   = 96;\nconst STEEL_DENSITY= 0.2836;      \/\/ lb\/in^3, locked\n\nconst DUTY_MAP = {\n  light:    {mult:0.4, label:'Light',    desc:'Fine\/rounded particles, low impact, low velocity'},\n  moderate: {mult:1.0, label:'Moderate', desc:'Mixed ore\/aggregate, typical mining'},\n  severe:   {mult:2.2, label:'Severe',   desc:'Coarse\/angular abrasive, high throughput'},\n  extreme:  {mult:4.5, label:'Extreme',  desc:'Hard rock, high-velocity, sustained gouging'}\n};\nconst DUTY_ORDER = ['light','moderate','severe','extreme'];\n\n\/\/ \u2500\u2500 Product hardness registry (Standard v1.4) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\/\/ Plate gradient rule (v1.3): surface = nominal - 25, midline = 0.90 x surface.\n\/\/ AR400 exception (v1.4): surface = 375 HB guaranteed minimum.\nconst PLATE_GRADES = {\n  AR400: {label:'AR400', surf:375, mid:337, priceDefault:1.04, priceVerified:true},\n  AR450: {label:'AR450', surf:425, mid:382, priceDefault:1.35, priceVerified:true},\n  AR500: {label:'AR500', surf:475, mid:427, priceDefault:1.45, priceVerified:true},\n  AR550: {label:'AR550', surf:525, mid:472, priceDefault:1.55, priceVerified:false},\n  AR600: {label:'AR600', surf:575, mid:517, priceDefault:1.70, priceVerified:false}\n};\nconst TRIBRAZE_BHN   = 470;      \/\/ through-hardened, no gradient penalty\nconst TRIBRAZE_PRICE = 1.39;\n\n\/\/ Tri-Braze field impact multipliers vs reference AR grade, by duty.\n\/\/ Certified for AR400\/AR450\/AR500 references only (Tri-Braze Fleet TCO v2.9.4).\nconst TB_MULT = {\n  AR400: {light:1.00, moderate:1.25, severe:1.375, extreme:1.50},\n  AR450: {light:1.25, moderate:1.50, severe:1.625, extreme:1.75},\n  AR500: {light:1.50, moderate:1.625, severe:1.75, extreme:2.00}\n};\n\n\/\/ Certified AR field life defaults (months) by grade and duty tier,\n\/\/ carried from Tri-Braze Fleet TCO v2.9.4. Editable prefills, customer-sourced final.\nconst TB_FIELD_LIFE = {\n  AR400: {light:2, moderate:4,  severe:6,  extreme:8},\n  AR450: {light:3, moderate:6,  severe:9,  extreme:12},\n  AR500: {light:4, moderate:8,  severe:12, extreme:16}\n};\n\n\/\/ Use-model segmentation (Standard v1.6): sanctioned comparisons only.\n\/\/ Impact + abrasion service: AR400\/AR450\/AR500 vs Tri-Braze.\n\/\/ Sliding abrasion only:     AR550\/AR600 vs CCO.\nconst SEGMENTATION = {\n  impact:  {grades:['AR400','AR450','AR500'], versus:'Tri-Braze'},\n  sliding: {grades:['AR550','AR600'],         versus:'CCO'}\n};\n\n\/\/ CCO life ratio vs A36, indexed to carbide volume fraction.\n\/\/ Calibrated to TWS Technical Reference 6.1: 45-50 pct carbide = 15-25x.\nfunction ccoLifeRatio(pct){\n  if (pct <= 35) return 8.0;\n  if (pct <= 45) return 8.0  + (pct - 35) * 1.4;\n  if (pct <= 50) return 22.0 + (pct - 45) * 1.2;\n  if (pct <= 60) return 28.0 + (pct - 50) * 0.4;\n  return 32.0;\n}\n\n\/\/ \u2500\u2500 Wear model core \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nconst R = bhn => Math.pow(bhn \/ BHN_BASE, WRI_N);   \/\/ relative resistance vs A36\n\n\/\/ Parabolic through-thickness plate profile: surface hardness at both faces,\n\/\/ midline hardness at plate center (Standard v1.3 plate gradient rule).\nfunction plateBHN(x, surf, mid, T){\n  return mid + (surf - mid) * Math.pow((x - T\/2) \/ (T\/2), 2);\n}\n\n\/\/ Layer-integrated life multiple for an AR plate wearing from one face\n\/\/ through the usable depth (80 pct of thickness), 1\/32 in layers.\nfunction plateIntegratedMultiple(surf, mid, T){\n  const usable = T * AR_WEAR_FRAC;\n  let sum = 0, n = 0, d = 0;\n  while (d + 1e-9 < usable){\n    const end = Math.min(d + LAYER_IN, usable);\n    const xm = (d + end) \/ 2;\n    sum += R(plateBHN(xm, surf, mid, T)) * (end - d);\n    n += (end - d);\n    d = end;\n  }\n  return sum \/ n;   \/\/ thickness-weighted average relative resistance\n}\n\n\/\/ \u2500\u2500 UT600 induction-hardened gradient (Standard v1.2) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\/\/ PF8050H qualification profile (HRC vs pct of wall, 0 = ID wear face),\n\/\/ affinely rescaled in BHN to locked anchors 650 BHN ID \/ 250 BHN OD.\nconst HRC_PROFILE = [\n  {p:0,h:52.0},{p:5,h:52.0},{p:10,h:52.5},{p:15,h:52.0},{p:20,h:51.5},\n  {p:25,h:47.5},{p:30,h:43.0},{p:35,h:38.5},{p:40,h:35.0},{p:45,h:32.5},\n  {p:50,h:30.5},{p:55,h:28.0},{p:60,h:27.0},{p:65,h:26.0},{p:70,h:25.5},\n  {p:75,h:25.0},{p:80,h:25.0},{p:85,h:24.5},{p:90,h:24.5},{p:95,h:24.5},{p:100,h:24.0}\n];\nconst hrcToBhn = hrc => Math.round(10 * hrc + 50);\nfunction interpHRC(pct){\n  for (let i = 0; i < HRC_PROFILE.length - 1; i++){\n    if (pct >= HRC_PROFILE[i].p && pct <= HRC_PROFILE[i+1].p){\n      const t = (pct - HRC_PROFILE[i].p) \/ (HRC_PROFILE[i+1].p - HRC_PROFILE[i].p);\n      return HRC_PROFILE[i].h + t * (HRC_PROFILE[i+1].h - HRC_PROFILE[i].h);\n    }\n  }\n  return HRC_PROFILE[HRC_PROFILE.length - 1].h;\n}\n\/\/ Anchors: raw profile 570 BHN at ID, 290 BHN at OD -> rescale to 650 \/ 250.\nconst UT_SCALE = (650 - 250) \/ (570 - 290);\nfunction ut600BHN(pctOfWall){\n  return 250 + (hrcToBhn(interpHRC(pctOfWall)) - 290) * UT_SCALE;\n}\n\/\/ Integrated life multiple through usable fraction of wall (from ID).\nfunction ut600IntegratedMultiple(usableFrac){\n  const steps = 96;\n  let sum = 0;\n  for (let i = 0; i < steps; i++){\n    const pct = ((i + 0.5) \/ steps) * usableFrac * 100;\n    sum += R(ut600BHN(pct));\n  }\n  return sum \/ steps;\n}\n\n\/\/ \u2500\u2500 ESSER twin-wall (Standard v1.2 registry) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nconst ESSER700_HB   = 720;   \/\/ 63 HRC anchor\nconst ESSER700_CORR = 0.92;  \/\/ two-layer quenched gradient correction\nconst ESSER900_HB   = 850;   \/\/ 67 HRC CCI anchor\n\/\/ White iron rule: HB^1.25 is the FLOOR; carbide fraction governs in the field.\n\/\/ TWS G65 data for ASTM A532 Class 3: 40-70x vs mild steel.\nconst ESSER900_FIELD_RANGE = [40, 70];\n\nconst esser700Multiple = () => ESSER700_CORR * R(ESSER700_HB);\nconst esser900Floor    = () => R(ESSER900_HB);\n\n\/\/ \u2500\u2500 Pipe dimensional data \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nconst PIPE_OD_MM = {60:60.3,80:88.9,100:114.3,125:139.7,150:168.3,200:219.1,\n  250:273.1,300:323.9,350:355.6,400:406.4,450:457.2,500:508.0};\nconst UT600_WALLS = {60:[7.0],80:[7.6],100:[6.0,8.6],125:[6.6,9.5],150:[7.1,11.0],\n  200:[8.1,12.7],250:[9.3,12.7],300:[9.5,12.7],350:[9.5,12.7],400:[9.5,12.7],450:[12.7],500:[12.7]};\nconst ESSER700_WALLS = {80:[7.2],100:[4.0,7.7],125:[4.5,8.2],150:[9.0],200:[8.0]};\nconst ESSER900_WALLS = {80:[12.2],100:[14.0],125:[10.2],150:[11.0],200:[12.0]};\nconst MILD_WALLS = {60:[5.5,8.7],80:[5.5,7.6],100:[6.0,8.6],125:[6.6,9.5],150:[7.1,11.0],\n  200:[8.2,12.7],250:[9.3,12.7],300:[9.5,12.7],350:[9.5,12.7],400:[9.5,12.7]};\n\n\/\/ UT600 imperial catalog (Ultra 600 Pipe TCO v17 data)\nconst ASME = {\n  '2\\u00BD\"':{'Sch 10':0.120,'Sch 20':0.141,'Sch 40':0.203,'Sch 80':0.276,'Sch 160':0.375,'XXS':0.552},\n  '3\"':{'Sch 10':0.120,'Sch 20':0.156,'Sch 40':0.216,'Sch 80':0.300,'Sch 160':0.438,'XXS':0.600},\n  '4\"':{'Sch 10':0.120,'Sch 20':0.156,'Sch 40':0.237,'Sch 60':0.281,'Sch 80':0.337,'Sch 120':0.438,'Sch 160':0.531,'XXS':0.674},\n  '5\"':{'Sch 10':0.134,'Sch 20':0.156,'Sch 40':0.258,'Sch 60':0.375,'Sch 80':0.375,'Sch 120':0.500,'Sch 160':0.625,'XXS':0.750},\n  '6\"':{'Sch 10':0.134,'Sch 20':0.156,'Sch 40':0.280,'Sch 60':0.432,'Sch 80':0.432,'Sch 120':0.562,'Sch 140':0.719,'Sch 160':0.719,'XXS':0.864},\n  '8\"':{'Sch 10':0.148,'Sch 20':0.250,'Sch 30':0.277,'Sch 40':0.322,'Sch 60':0.406,'Sch 80':0.500,'Sch 100':0.594,'Sch 120':0.719,'Sch 140':0.812,'Sch 160':0.906,'XXS':0.875},\n  '10\"':{'Sch 10':0.165,'Sch 20':0.250,'Sch 30':0.307,'Sch 40':0.365,'Sch 60':0.500,'Sch 80':0.594,'Sch 100':0.719,'Sch 120':1.000,'Sch 140':1.125,'Sch 160':1.312},\n  '12\"':{'Sch 10':0.180,'Sch 20':0.250,'Sch 30':0.330,'Sch 40':0.406,'Sch 60':0.562,'Sch 80':0.688,'Sch 100':0.844,'Sch 120':1.000,'Sch 140':1.125,'Sch 160':1.312},\n  '14\"':{'Sch 10':0.188,'Sch 20':0.250,'Sch 30':0.312,'Sch 40':0.375,'Sch 60':0.500,'Sch 80':0.594,'Sch 100':0.750,'Sch 120':0.938,'Sch 140':1.094,'Sch 160':1.250},\n  '16\"':{'Sch 10':0.188,'Sch 20':0.250,'Sch 30':0.312,'Sch 40':0.375,'Sch 60':0.500,'Sch 80':0.656,'Sch 100':0.844,'Sch 120':1.031,'Sch 140':1.219,'Sch 160':1.438},\n  '18\"':{'Sch 10':0.188,'Sch 20':0.250,'Sch 30':0.312,'Sch 40':0.438,'Sch 60':0.562,'Sch 80':0.750,'Sch 100':0.938,'Sch 120':1.156,'Sch 140':1.375,'Sch 160':1.562},\n  '20\"':{'Sch 10':0.188,'Sch 20':0.250,'Sch 30':0.375,'Sch 40':0.500,'Sch 60':0.594,'Sch 80':0.812,'Sch 100':1.031,'Sch 120':1.281,'Sch 140':1.500,'Sch 160':1.750},\n  '24\"':{'Sch 10':0.218,'Sch 20':0.250,'Sch 30':0.375,'Sch 40':0.562,'Sch 60':0.688,'Sch 80':0.969,'Sch 100':1.219,'Sch 120':1.531,'Sch 140':1.812,'Sch 160':2.062}\n};\nconst OD_MAP = {'2\\u00BD\"':2.875,'3\"':3.500,'4\"':4.500,'5\"':5.563,'6\"':6.625,'8\"':8.625,\n  '10\"':10.750,'12\"':12.750,'14\"':14.000,'16\"':16.000,'18\"':18.000,'20\"':20.000,'24\"':24.000};\nconst UT600_CATALOG = [\n  {pn:'PP2527H',nps:'2\\u00BD\"',nomWall:0.276,sf3:4592.6,sf4:3444.5,sf5:2755.6},\n  {pn:'PP3030H',nps:'3\"',nomWall:0.300,sf3:4069.1,sf4:3051.9,sf5:2441.5},\n  {pn:'PP4023H',nps:'4\"',nomWall:0.237,sf3:2440.2,sf4:1830.2,sf5:1464.1},\n  {pn:'PD4033H',nps:'4\"',nomWall:0.337,sf3:3526.8,sf4:2645.1,sf5:2116.1},\n  {pn:'PP5025H',nps:'5\"',nomWall:0.258,sf3:2139.3,sf4:1604.4,sf5:1283.6},\n  {pn:'PE5037H',nps:'5\"',nomWall:0.375,sf3:3157.4,sf4:2368.1,sf5:1894.5},\n  {pn:'PF5050H',nps:'5\"',nomWall:0.500,sf3:4280.6,sf4:3210.4,sf5:2568.3},\n  {pn:'PP6028H',nps:'6\"',nomWall:0.280,sf3:1943.5,sf4:1457.7,sf5:1166.1},\n  {pn:'PE6043H',nps:'6\"',nomWall:0.432,sf3:3049.1,sf4:2286.8,sf5:1829.4},\n  {pn:'PD8032H',nps:'8\"',nomWall:0.322,sf3:1710.7,sf4:1283.0,sf5:1026.4},\n  {pn:'PF8050H',nps:'8\"',nomWall:0.500,sf3:2696.4,sf4:2022.3,sf5:1617.8},\n  {pn:'PE1036H',nps:'10\"',nomWall:0.365,sf3:1552.1,sf4:1164.0,sf5:931.2},\n  {pn:'PF1050H',nps:'10\"',nomWall:0.500,sf3:2145.4,sf4:1609.1,sf5:1287.3},\n  {pn:'PE1237H',nps:'12\"',nomWall:0.375,sf3:1340.1,sf4:1005.1,sf5:804.1},\n  {pn:'PF1250H',nps:'12\"',nomWall:0.500,sf3:1798.5,sf4:1348.9,sf5:1079.1},\n  {pn:'PE1437H',nps:'14\"',nomWall:0.375,sf3:1218.2,sf4:913.6,sf5:730.9},\n  {pn:'PF1450H',nps:'14\"',nomWall:0.500,sf3:1634.6,sf4:1226.0,sf5:980.8},\n  {pn:'PE1637H',nps:'16\"',nomWall:0.375,sf3:1063.3,sf4:797.5,sf5:638.0},\n  {pn:'PF1650H',nps:'16\"',nomWall:0.500,sf3:1425.7,sf4:1069.3,sf5:855.4},\n  {pn:'PF1850H',nps:'18\"',nomWall:0.500,sf3:1264.2,sf4:948.1,sf5:758.5},\n  {pn:'PF2050H',nps:'20\"',nomWall:0.500,sf3:1135.5,sf4:851.6,sf5:681.3},\n  {pn:'PF2450H',nps:'24\"',nomWall:0.500,sf3:943.4,sf4:707.6,sf5:566.1}\n];\nfunction matchUT600(nps, w){\n  const c = UT600_CATALOG.filter(r => r.nps === nps);\n  if (!c.length) return null;\n  return c.reduce((b, r) => Math.abs(r.nomWall - w) < Math.abs(b.nomWall - w) ? r : b);\n}\n\n\/\/ \u2500\u2500 Life and TCO \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\/\/ Plate life in months. msWearRate in in\/yr at Moderate duty on A36.\nfunction plateLifeYears(usableDepthIn, multiple, msWearRateInYr, dutyMult){\n  return usableDepthIn * multiple \/ (msWearRateInYr * dutyMult);\n}\nconst plateWeightLb = t => PLATE_L_IN * PLATE_W_IN * t * STEEL_DENSITY;\n\n\/\/ Generic replacement-cycle TCO\nfunction cycleTCO(lifeYears, horizonYears, unitInstalledCost, laborPerChange, downtimePerChange){\n  if (!isFinite(lifeYears) || lifeYears <= 0) return null;\n  const replacements = Math.max(0, Math.ceil(horizonYears \/ lifeYears) - 1);\n  const material = unitInstalledCost * (1 + replacements);\n  const labor = replacements * laborPerChange;\n  const downtime = replacements * downtimePerChange;\n  return {replacements, material, labor, downtime, total: material + labor + downtime};\n}\n\n\/\/ Pipe life in years, metric. Wear rate input in in\/yr on A36 at Moderate.\nfunction pipeLifeYears(wallMm, usableFrac, multiple, msWearRateInYr, dutyMult){\n  const usableMm = wallMm * usableFrac;\n  const rateMm = msWearRateInYr * 25.4 * dutyMult;\n  return usableMm * multiple \/ rateMm;\n}\n\n\/\/ \u2500\u2500 Regression suite (Standard v1.4 anchors) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nconst REGRESSION = [\n  {name:'Exponent locked 1.25', got:()=>WRI_N, want:1.25, tol:0},\n  {name:'Baseline A36 160 HB', got:()=>BHN_BASE, want:160, tol:0},\n  {name:'UT600 surface 5.77x', got:()=>R(ut600BHN(0)), want:5.77, tol:0.03},\n  {name:'UT600 ID anchor 650 BHN', got:()=>ut600BHN(0), want:650, tol:0.5},\n  {name:'UT600 OD anchor 250 BHN', got:()=>ut600BHN(100), want:250, tol:0.5},\n  {name:'UT600 integrated 75pct ~3.8x', got:()=>ut600IntegratedMultiple(0.75), want:3.81, tol:0.06},\n  {name:'ESSER 700 6.0x (0.92 corr)', got:()=>esser700Multiple(), want:6.03, tol:0.03},\n  {name:'ESSER 900 floor 8.1x', got:()=>esser900Floor(), want:8.07, tol:0.03},\n  {name:'Tri-Braze hardness law 3.85x', got:()=>R(TRIBRAZE_BHN), want:3.85, tol:0.02},\n  {name:'CCO 47.5pct carbide 25x', got:()=>ccoLifeRatio(47.5), want:25.0, tol:0.01},\n  {name:'AR450 surface 3.39x', got:()=>R(425), want:3.39, tol:0.02},\n  {name:'AR400 surface 375 HB ruling', got:()=>PLATE_GRADES.AR400.surf, want:375, tol:0},\n  {name:'AR600 gradient surface 575', got:()=>PLATE_GRADES.AR600.surf, want:575, tol:0},\n  {name:'Duty tiers 0.4\/1.0\/2.2\/4.5', got:()=>DUTY_MAP.light.mult+DUTY_MAP.moderate.mult+DUTY_MAP.severe.mult+DUTY_MAP.extreme.mult, want:8.1, tol:0.001},\n  {name:'TB multipliers locked to AR400\/450\/500', got:()=>Object.keys(TB_MULT).join()==='AR400,AR450,AR500'?1:0, want:1, tol:0},\n  {name:'Sliding tab set AR550\/AR600 vs CCO', got:()=>(SEGMENTATION.sliding.grades.join()==='AR550,AR600'&&SEGMENTATION.sliding.versus==='CCO')?1:0, want:1, tol:0},\n  {name:'Certified field life defaults intact', got:()=>TB_FIELD_LIFE.AR400.moderate+TB_FIELD_LIFE.AR450.moderate+TB_FIELD_LIFE.AR500.extreme, want:26, tol:0}\n];\nfunction runRegression(){\n  const results = REGRESSION.map(t => {\n    const got = t.got();\n    return {name:t.name, got, want:t.want, pass: Math.abs(got - t.want) <= (t.tol || 1e-9)};\n  });\n  return {results, passed: results.filter(r=>r.pass).length, total: results.length};\n}\n\n\n<\/script>\n\n<script>\n\/\/ ============================================================================\n\/\/ UI LAYER\n\/\/ ============================================================================\nconst $ = id => document.getElementById(id);\nconst fmt$ = v => '$' + Math.round(v).toLocaleString();\nconst fmtX = v => v.toFixed(2) + '\\u00D7';\nconst fmtYr = v => v >= 10 ? v.toFixed(1) : v.toFixed(2);\n\n\/\/ Hardness -> grayscale for gradient bars (160 HB light, 850 HB near-black)\nfunction hbShade(hb){\n  const t = Math.max(0, Math.min(1, (hb - 160) \/ (850 - 160)));\n  const g = Math.round(210 - t * 165);\n  return 'rgb(' + g + ',' + g + ',' + g + ')';\n}\nfunction gradientCSS(bhnFn){ \/\/ bhnFn(frac 0..1) -> BHN\n  const stops = [];\n  for (let i = 0; i <= 10; i++){\n    stops.push(hbShade(bhnFn(i \/ 10)) + ' ' + (i * 10) + '%');\n  }\n  return 'linear-gradient(90deg,' + stops.join(',') + ')';\n}\nfunction gbRow(name, tag, css, valMain, valSub){\n  return '<div class=\"gb-row\"><div class=\"gb-name\">' + name +\n    (tag ? '<span class=\"tag\">' + tag + '<\/span>' : '') +\n    '<\/div><div class=\"gb-bar\"><div class=\"gb-fill\" style=\"background:' + css + '\"><\/div><\/div>' +\n    '<div class=\"gb-val\">' + valMain + (valSub ? '<span class=\"sub\">' + valSub + '<\/span>' : '') + '<\/div><\/div>';\n}\nfunction dutySelect(sel, noteEl){\n  sel.innerHTML = DUTY_ORDER.map(k =>\n    '<option value=\"' + k + '\"' + (k === 'moderate' ? ' selected' : '') + '>' +\n    DUTY_MAP[k].label + ' (' + DUTY_MAP[k].mult.toFixed(1) + '\\u00D7)<\/option>').join('');\n  const upd = () => { noteEl.textContent = DUTY_MAP[sel.value].desc; };\n  sel.addEventListener('change', upd); upd();\n}\nfunction card(label, value, sub, win){\n  return '<div class=\"rc' + (win ? ' win' : '') + '\"><div class=\"l\">' + label +\n    '<\/div><div class=\"v\">' + value + '<\/div><div class=\"s\">' + sub + '<\/div><\/div>';\n}\n\n\/\/ \u2500\u2500 TAB A: IMPACT + ABRASION (AR400\/450\/500 vs Tri-Braze) \u2500\u2500\nfunction calcPlate(){\n  const T = parseFloat($('p_thick').value) || 0.5;\n  const dutyKey = $('p_duty').value;\n  const duty = DUTY_MAP[dutyKey].mult;\n  const wear = parseFloat($('p_wear').value) || 1.0;\n  const ref = $('p_ref').value;\n  const fleet = parseInt($('p_fleet').value) || 1;\n  const horizM = parseInt($('p_horiz').value) || 36;\n  const labor = parseFloat($('p_labor').value) || 0;\n  const down = parseFloat($('p_down').value) || 0;\n  const priceRef = parseFloat($('p_priceRef').value) || PLATE_GRADES[ref].priceDefault;\n  const priceTB = parseFloat($('p_priceTB').value) || TRIBRAZE_PRICE;\n  $('p_priceRefLbl').textContent = ref;\n\n  const usable = T * AR_WEAR_FRAC;\n  const rows = [];\n  rows.push({name:'A36 mild steel', tag:'160 HB baseline', mult:1,\n    css:hbShade(160), lifeYr:plateLifeYears(usable, 1, wear, duty), kind:'base'});\n\n  for (const g of SEGMENTATION.impact.grades){\n    const gr = PLATE_GRADES[g];\n    const m = plateIntegratedMultiple(gr.surf, gr.mid, T);\n    rows.push({name:gr.label, tag:gr.surf + ' HB surface \/ ' + gr.mid + ' HB midline',\n      mult:m, css:gradientCSS(f => plateBHN(f * usable, gr.surf, gr.mid, T)),\n      lifeYr:plateLifeYears(usable, m, wear, duty), kind:'ar', grade:g});\n  }\n\n  const tbMult = TB_MULT[ref][dutyKey];\n  const refRow = rows.find(r => r.grade === ref);\n  const tbLifeYr = refRow.lifeYr * tbMult;\n  const tbEquiv = refRow.mult * tbMult;\n  rows.push({name:'Tri-Braze', tag:'470 HB through-hardened, ' + tbMult.toFixed(3) + '\\u00D7 vs ' + ref,\n    mult:tbEquiv, css:hbShade(470), lifeYr:tbLifeYr, kind:'tb'});\n\n  const maxM = Math.max(...rows.map(r => r.mult));\n  $('p_bars').innerHTML = rows.map(r => {\n    const w = Math.max(6, (r.mult \/ maxM) * 100);\n    return gbRow(r.name, r.tag, r.css, fmtX(r.mult), fmtYr(r.lifeYr) + ' yr at this duty')\n      .replace('class=\"gb-bar\"', 'class=\"gb-bar\" style=\"width:' + w + '%\"');\n  }).join('');\n\n  const wt = plateWeightLb(T);\n  const horizYr = horizM \/ 12;\n  const refT = cycleTCO(refRow.lifeYr, horizYr, wt * priceRef, labor, down);\n  const tbT  = cycleTCO(tbLifeYr, horizYr, wt * priceTB, labor, down);\n  const refTotal = refT.total * fleet, tbTotal = tbT.total * fleet;\n  const savings = refTotal - tbTotal;\n\n  $('p_cards').innerHTML =\n    card(ref + ' fleet TCO', fmt$(refTotal), fleet + ' plates, ' + horizM + ' mo, ' + refT.replacements + ' changeouts\/plate', false) +\n    card('Tri-Braze fleet TCO', fmt$(tbTotal), fleet + ' plates, ' + horizM + ' mo, ' + tbT.replacements + ' changeouts\/plate', savings > 0) +\n    card(savings >= 0 ? 'Tri-Braze savings' : 'Tri-Braze premium', fmt$(Math.abs(savings)),\n      'vs ' + ref + ' over horizon, all-in', savings > 0);\n\n  let tbl = '<table><tr><th>Product<\/th><th class=\"num\">Life vs A36<\/th><th class=\"num\">Life (yr)<\/th><th>Basis<\/th><\/tr>';\n  const maxLife = Math.max(...rows.map(x => x.lifeYr));\n  for (const r of rows){\n    const basis = r.kind === 'base' ? 'Baseline, 80% usable depth'\n      : r.kind === 'ar' ? 'Gradient, layer-integrated (HB<sup>1.25<\/sup>)'\n      : 'Certified field multiplier \\u00D7 ' + ref + ' life';\n    tbl += '<tr' + (r.lifeYr === maxLife ? ' class=\"win\"' : '') + '><td>' + r.name +\n      '<\/td><td class=\"num\">' + fmtX(r.mult) + '<\/td><td class=\"num\">' + fmtYr(r.lifeYr) +\n      '<\/td><td>' + basis + '<\/td><\/tr>';\n  }\n  tbl += '<\/table><div class=\"tbl-cap\">Life at ' + T.toFixed(3) + '&Prime; thickness, ' +\n    DUTY_MAP[dutyKey].label + ' duty, customer-sourced A36 rate of ' + wear.toFixed(3) +\n    ' in\/yr. Every multiple is vs A36 mild steel (160 HB).<\/div>';\n  $('p_tblwrap').innerHTML = tbl;\n\n  $('p_tbnote').innerHTML = '<b>Tri-Braze rule:<\/b> the impact advantage is certified relative to ' + ref +\n    ' at this duty (' + tbMult.toFixed(3) + '\\u00D7), not relative to A36. The implied A36 multiple shown (' + fmtX(tbEquiv) +\n    ') is derived, not measured. Quote the certified comparison.';\n}\n\n\/\/ \u2500\u2500 TAB A2: PACKAGE BASIS (AR400\/450\/500 vs Tri-Braze, liner package cost) \u2500\u2500\nfunction pkgLifeDefault(){\n  $('k_life').value = TB_FIELD_LIFE[$('k_ref').value][$('k_duty').value];\n}\nfunction pkgBasisToggle(){\n  const model = $('k_basis').value === 'model';\n  $('k_f_thick').style.display = model ? '' : 'none';\n  $('k_f_wear').style.display = model ? '' : 'none';\n  $('k_f_life').style.display = model ? 'none' : '';\n}\nfunction calcPkg(){\n  const ref = $('k_ref').value;\n  const gr = PLATE_GRADES[ref];\n  const dutyKey = $('k_duty').value;\n  const duty = DUTY_MAP[dutyKey].mult;\n  const mult = TB_MULT[ref][dutyKey];\n  const basis = $('k_basis').value;\n  const costAR = parseFloat($('k_costAR').value) || 0;\n  const costTB = parseFloat($('k_costTB').value) || 0;\n  const horiz = parseFloat($('k_horiz').value) || 36;\n  const labor = parseFloat($('k_labor').value) || 0;\n  const down = parseFloat($('k_down').value) || 0;\n\n  let lifeAR, arTag, arSub, arCss, intM = null, T = null, wear = null;\n  if (basis === 'model'){\n    T = parseFloat($('k_thick').value) || 0.5;\n    wear = parseFloat($('k_wear').value) || 1.0;\n    const usable = T * AR_WEAR_FRAC;\n    intM = plateIntegratedMultiple(gr.surf, gr.mid, T);\n    lifeAR = plateLifeYears(usable, intM, wear, duty) * 12;\n    arCss = gradientCSS(f => plateBHN(f * usable, gr.surf, gr.mid, T));\n    arTag = gr.surf + ' HB surface \/ ' + gr.mid + ' HB midline, ' + T.toFixed(3) + '\\u2033';\n    arSub = fmtX(intM) + ' the life of A36 mild steel';\n  } else {\n    lifeAR = parseFloat($('k_life').value) || 0;\n    arCss = hbShade(gr.surf);\n    arTag = 'Customer-sourced field life';\n    arSub = DUTY_MAP[dutyKey].label + ' duty';\n  }\n  const lifeTB = lifeAR * mult;\n\n  const maxL = Math.max(lifeTB, lifeAR, 1);\n  $('k_bars').innerHTML =\n    gbRow(ref + ' package', arTag, arCss, lifeAR.toFixed(1) + ' mo', arSub)\n      .replace('class=\"gb-bar\"', 'class=\"gb-bar\" style=\"width:' + Math.max(6,(lifeAR\/maxL)*100) + '%\"') +\n    gbRow('Tri-Braze package', mult.toFixed(3) + '\\u00D7 vs ' + ref + ' (certified)', hbShade(470),\n      lifeTB.toFixed(1) + ' mo', 'Derived from ' + ref + ' life')\n      .replace('class=\"gb-bar\"', 'class=\"gb-bar\" style=\"width:' + Math.max(6,(lifeTB\/maxL)*100) + '%\"');\n\n  $('k_note').innerHTML = '<b>Basis:<\/b> ' + (basis === 'model'\n    ? ref + ' life is model-calculated: ' + T.toFixed(3) + '\\u2033 plate, 80% usable depth, gradient-integrated at ' +\n      fmtX(intM) + ' vs A36 (160 HB), customer-sourced A36 rate of ' + wear.toFixed(3) + ' in\/yr, ' +\n      DUTY_MAP[dutyKey].label + ' duty. '\n    : ref + ' life is the customer\\u2019s measured package field life. ') +\n    'Tri-Braze life applies the certified field impact multiplier for ' + ref + ' at ' +\n    DUTY_MAP[dutyKey].label + ' duty: ' + mult.toFixed(3) + '\\u00D7 (Tri-Braze Fleet TCO v2.9.4, Standard Sec. 6). The multiplier is locked.';\n\n  if (!(lifeAR > 0) || !(costAR > 0) || !(costTB > 0)){\n    $('k_cards').innerHTML = card('Awaiting inputs', '\\u2014',\n      'Enter both installed package costs' + (basis === 'field' ? ' and the AR package field life' : '') +\n      ' to compute TCO. No default costs exist; use quoted numbers.', false);\n    $('k_tblwrap').innerHTML = '';\n    return;\n  }\n\n  const horizYr = horiz \/ 12;\n  const arT = cycleTCO(lifeAR \/ 12, horizYr, costAR, labor, down);\n  const tbT = cycleTCO(lifeTB \/ 12, horizYr, costTB, labor, down);\n  const savings = arT.total - tbT.total;\n\n  $('k_cards').innerHTML =\n    card(ref + ' package TCO', fmt$(arT.total), fmt$(arT.total \/ horiz) + '\/mo of protection, ' + arT.replacements + ' changeouts in ' + horiz + ' mo', false) +\n    card('Tri-Braze package TCO', fmt$(tbT.total), fmt$(tbT.total \/ horiz) + '\/mo of protection, ' + tbT.replacements + ' changeouts in ' + horiz + ' mo', savings > 0) +\n    card(savings >= 0 ? 'Tri-Braze savings' : 'Tri-Braze premium', fmt$(Math.abs(savings)),\n      'vs ' + ref + ' over ' + horiz + ' months, all-in', savings > 0);\n\n  let tbl = '<table><tr><th>Package<\/th><th class=\"num\">Installed cost<\/th><th class=\"num\">Life (mo)<\/th><th class=\"num\">Changeouts<\/th><th class=\"num\">Material<\/th><th class=\"num\">Labor<\/th><th class=\"num\">Downtime<\/th><th class=\"num\">TCO<\/th><th class=\"num\">$\/month<\/th><\/tr>';\n  for (const [nm, cost, life, t, win] of [[ref, costAR, lifeAR, arT, tbT.total >= arT.total], ['Tri-Braze', costTB, lifeTB, tbT, tbT.total < arT.total]]){\n    tbl += '<tr' + (win ? ' class=\"win\"' : '') + '><td>' + nm + '<\/td><td class=\"num\">' + fmt$(cost) +\n      '<\/td><td class=\"num\">' + life.toFixed(1) + '<\/td><td class=\"num\">' + t.replacements +\n      '<\/td><td class=\"num\">' + fmt$(t.material) + '<\/td><td class=\"num\">' + fmt$(t.labor) +\n      '<\/td><td class=\"num\">' + fmt$(t.downtime) + '<\/td><td class=\"num\">' + fmt$(t.total) +\n      '<\/td><td class=\"num\">' + fmt$(t.total \/ horiz) + '<\/td><\/tr>';\n  }\n  tbl += '<\/table><div class=\"tbl-cap\">' + horiz + '-month horizon, ' + DUTY_MAP[dutyKey].label +\n    ' duty, life basis: ' + (basis === 'model' ? 'wear model (thickness-driven)' : 'customer field life') +\n    '. Tri-Braze life = ' + ref + ' life \\u00D7 ' + mult.toFixed(3) +\n    ' (certified). Changeout labor and downtime are per event; downtime cost is customer-sourced.<\/div>';\n  $('k_tblwrap').innerHTML = tbl;\n}\n\n\/\/ \u2500\u2500 TAB B: SLIDING ABRASION (AR550\/600 vs CCO) \u2500\u2500\nfunction calcSlide(){\n  const T = parseFloat($('s_thick').value) || 0.5;\n  const dutyKey = $('s_duty').value;\n  const duty = DUTY_MAP[dutyKey].mult;\n  const wear = parseFloat($('s_wear').value) || 1.0;\n  const ccoTotal = parseFloat($('s_ccototal').value) || 0.5;\n  const overlayPct = parseFloat($('s_overlay').value) || 50;\n  const carb = parseFloat($('s_carb').value) || 47.5;\n\n  const usable = T * AR_WEAR_FRAC;\n  const rows = [];\n  rows.push({name:'A36 mild steel', tag:'160 HB baseline', mult:1,\n    css:hbShade(160), lifeYr:plateLifeYears(usable, 1, wear, duty), kind:'base'});\n\n  for (const g of SEGMENTATION.sliding.grades){\n    const gr = PLATE_GRADES[g];\n    const m = plateIntegratedMultiple(gr.surf, gr.mid, T);\n    rows.push({name:gr.label, tag:gr.surf + ' HB surface \/ ' + gr.mid + ' HB midline',\n      mult:m, css:gradientCSS(f => plateBHN(f * usable, gr.surf, gr.mid, T)),\n      lifeYr:plateLifeYears(usable, m, wear, duty), kind:'ar'});\n  }\n\n  const ccR = ccoLifeRatio(carb);\n  const overlay = ccoTotal * (overlayPct \/ 100);\n  const effOverlay = overlay * CCO_WEAR_FRAC;\n  const ccoLifeYr = effOverlay * ccR \/ (wear * duty);\n  rows.push({name:'CCO overlay', tag:carb.toFixed(1) + '% carbide, ' + overlayPct + '\/' + (100 - overlayPct) + ' clad, ' + ccoTotal.toFixed(3) + '\\u2033 total',\n    mult:ccR, css:'repeating-linear-gradient(45deg,#6f6f6f 0 5px,#c9c9c9 5px 10px)',\n    lifeYr:ccoLifeYr, kind:'cco'});\n\n  const maxM = Math.max(...rows.map(r => r.mult));\n  $('s_bars').innerHTML = rows.map(r => {\n    const w = Math.max(6, (r.mult \/ maxM) * 100);\n    return gbRow(r.name, r.tag, r.css, fmtX(r.mult), fmtYr(r.lifeYr) + ' yr at this duty')\n      .replace('class=\"gb-bar\"', 'class=\"gb-bar\" style=\"width:' + w + '%\"');\n  }).join('');\n\n  const best = rows.reduce((b, r) => r.lifeYr > b.lifeYr ? r : b, rows[0]);\n  const ar600 = rows.find(r => r.name === 'AR600');\n  $('s_cards').innerHTML =\n    card('CCO life ratio', fmtX(ccR), carb.toFixed(1) + '% carbide vs A36 mild steel (carbide-governed)', best.kind === 'cco') +\n    card('CCO effective overlay', effOverlay.toFixed(3) + '\\u2033', '50% of ' + overlay.toFixed(3) + '\\u2033 overlay; bond margin retained', false) +\n    card('CCO vs AR600', fmtX(ccoLifeYr \/ ar600.lifeYr), 'Life ratio at these geometries and this duty', false);\n\n  let tbl = '<table><tr><th>Product<\/th><th class=\"num\">Life vs A36<\/th><th class=\"num\">Usable depth<\/th><th class=\"num\">Life (yr)<\/th><th>Basis<\/th><\/tr>';\n  const maxLife = Math.max(...rows.map(x => x.lifeYr));\n  for (const r of rows){\n    const depth = r.kind === 'cco' ? effOverlay : usable;\n    const basis = r.kind === 'base' ? 'Baseline, 80% usable depth'\n      : r.kind === 'ar' ? 'Gradient, layer-integrated (HB<sup>1.25<\/sup>)'\n      : 'Carbide fraction (hardness law does not apply)';\n    tbl += '<tr' + (r.lifeYr === maxLife ? ' class=\"win\"' : '') + '><td>' + r.name +\n      '<\/td><td class=\"num\">' + fmtX(r.mult) + '<\/td><td class=\"num\">' + depth.toFixed(3) + '\\u2033' +\n      '<\/td><td class=\"num\">' + fmtYr(r.lifeYr) + '<\/td><td>' + basis + '<\/td><\/tr>';\n  }\n  tbl += '<\/table><div class=\"tbl-cap\">Sliding abrasion only, ' + DUTY_MAP[dutyKey].label +\n    ' duty, customer-sourced A36 rate of ' + wear.toFixed(3) + ' in\/yr. Life reflects both wear resistance and usable depth: a thicker AR section can outlast a higher-multiple CCO overlay. Relative wear comparison; the package TCO below is commercially uncertified.<\/div>';\n  $('s_tblwrap').innerHTML = tbl;\n  calcSlideTCO();\n}\n\n\/\/ \u2500\u2500 TAB B TCO: PACKAGE BASIS (AR550\/600 vs CCO) \u2500\u2500\n\/\/ Dir. PM ruling, pending VP Sales TWS price confirmation. Standard freeze on this\n\/\/ pairing (Sec. 11\/12) overridden by the standard owner. TCO runs on quoted installed\n\/\/ package costs only; no default prices exist; pairing is commercially uncertified.\n\/\/ Modeled on the AR vs Tri-Braze package-basis calculator (calcPkg).\nfunction slideModelLifeYears(){\n  const T = parseFloat($('s_thick').value) || 0.5;\n  const duty = DUTY_MAP[$('s_duty').value].mult;\n  const wear = parseFloat($('s_wear').value) || 1.0;\n  const usable = T * AR_WEAR_FRAC;\n  const ccoTotal = parseFloat($('s_ccototal').value) || 0.5;\n  const overlayPct = parseFloat($('s_overlay').value) || 50;\n  const carb = parseFloat($('s_carb').value) || 47.5;\n  const effOverlay = ccoTotal * (overlayPct \/ 100) * CCO_WEAR_FRAC;\n  const g5 = PLATE_GRADES.AR550, g6 = PLATE_GRADES.AR600;\n  return {\n    AR550: plateLifeYears(usable, plateIntegratedMultiple(g5.surf, g5.mid, T), wear, duty),\n    AR600: plateLifeYears(usable, plateIntegratedMultiple(g6.surf, g6.mid, T), wear, duty),\n    CCO:   effOverlay * ccoLifeRatio(carb) \/ (wear * duty)\n  };\n}\nfunction slideTcoBasisToggle(){\n  $('s_tco_fieldlife').style.display = ($('s_tco_basis').value === 'field') ? '' : 'none';\n}\nfunction slideTcoLifePrefill(){\n  \/\/ Prefill empty field-life inputs from the model estimate; never overwrite entered (measured) values.\n  const m = slideModelLifeYears();\n  const round = v => Math.round(v * 12 * 2) \/ 2;\n  const set = (id, val) => { if (!$(id).value) $(id).value = val; };\n  set('s_life550', round(m.AR550));\n  set('s_life600', round(m.AR600));\n  set('s_lifecco', round(m.CCO));\n}\nfunction calcSlideTCO(){\n  const basis   = $('s_tco_basis').value;\n  const dutyLbl = DUTY_MAP[$('s_duty').value].label;\n  const horiz   = parseFloat($('s_tco_horiz').value) || 36;   \/\/ months\n  const labor   = parseFloat($('s_tco_labor').value) || 0;\n  const down    = parseFloat($('s_tco_down').value) || 0;\n  const model   = slideModelLifeYears();\n\n  const lifeMo = (basis === 'field')\n    ? {AR550: parseFloat($('s_life550').value) || 0, AR600: parseFloat($('s_life600').value) || 0, CCO: parseFloat($('s_lifecco').value) || 0}\n    : {AR550: model.AR550 * 12, AR600: model.AR600 * 12, CCO: model.CCO * 12};\n\n  const cost = {\n    AR550: parseFloat($('s_cost550').value) || 0,\n    AR600: parseFloat($('s_cost600').value) || 0,\n    CCO:   parseFloat($('s_costcco').value) || 0\n  };\n  const meta = {\n    AR550: {name:'AR550 package',       css:hbShade(PLATE_GRADES.AR550.surf)},\n    AR600: {name:'AR600 package',       css:hbShade(PLATE_GRADES.AR600.surf)},\n    CCO:   {name:'CCO overlay package', css:'repeating-linear-gradient(45deg,#6f6f6f 0 5px,#c9c9c9 5px 10px)'}\n  };\n  const keys = ['AR550','AR600','CCO'];\n\n  $('s_tco_note').innerHTML = '<b>Basis:<\/b> ' + (basis === 'model'\n    ? 'wear life is model-calculated from the geometry inputs above (AR550\/AR600 gradient-integrated through the 80% usable depth; CCO by carbide fraction with 50% usable overlay), customer-sourced A36 rate, ' + dutyLbl + ' duty. '\n    : 'wear life is the customer\\u2019s measured field life. Prefilled from the model estimate; measured data governs (Standard Sec. 10). ') +\n    'Installed package costs are quoted numbers; no standard defaults exist for this pairing. <b>Commercially uncertified<\/b> pending the VP Sales TWS price ruling.';\n\n  const maxL = Math.max(lifeMo.AR550, lifeMo.AR600, lifeMo.CCO, 1);\n  $('s_tco_bars').innerHTML = keys.map(k =>\n    gbRow(meta[k].name, basis === 'field' ? 'Customer-sourced field life' : 'Model estimate', meta[k].css,\n      lifeMo[k].toFixed(1) + ' mo', dutyLbl + ' duty')\n      .replace('class=\"gb-bar\"', 'class=\"gb-bar\" style=\"width:' + Math.max(6, (lifeMo[k] \/ maxL) * 100) + '%\"')\n  ).join('');\n\n  const priced = keys.filter(k => cost[k] > 0 && lifeMo[k] > 0);\n  if (!priced.length){\n    $('s_tco_cards').innerHTML = card('Awaiting inputs', '\\u2014',\n      'Enter at least one quoted installed package cost (and a life > 0) to compute TCO. No default prices exist for this pairing.', false);\n    $('s_tco_tblwrap').innerHTML = '';\n    return;\n  }\n\n  const horizYr = horiz \/ 12;\n  const t = {};\n  priced.forEach(k => { t[k] = cycleTCO(lifeMo[k] \/ 12, horizYr, cost[k], labor, down); });\n  const best = priced.reduce((b, k) => t[k].total < t[b].total ? k : b, priced[0]);\n  const worstTotal = Math.max(...priced.map(k => t[k].total));\n\n  $('s_tco_cards').innerHTML = priced.map(k =>\n    card(meta[k].name + ' TCO', fmt$(t[k].total),\n      fmt$(t[k].total \/ horiz) + '\/mo of protection, ' + t[k].replacements + ' changeouts in ' + horiz + ' mo',\n      k === best)\n  ).join('') + (priced.length > 1\n    ? card('Lowest all-in', meta[best].name.replace(' package','').replace(' overlay',''),\n        fmt$(worstTotal - t[best].total) + ' below the highest option over ' + horiz + ' mo', true)\n    : '');\n\n  let tbl = '<table><tr><th>Package<\/th><th class=\"num\">Installed cost<\/th><th class=\"num\">Life (mo)<\/th><th class=\"num\">Changeouts<\/th><th class=\"num\">Material<\/th><th class=\"num\">Labor<\/th><th class=\"num\">Downtime<\/th><th class=\"num\">TCO<\/th><th class=\"num\">$\/month<\/th><\/tr>';\n  priced.forEach(k => {\n    tbl += '<tr' + (k === best ? ' class=\"win\"' : '') + '><td>' + meta[k].name + '<\/td><td class=\"num\">' + fmt$(cost[k]) +\n      '<\/td><td class=\"num\">' + lifeMo[k].toFixed(1) + '<\/td><td class=\"num\">' + t[k].replacements +\n      '<\/td><td class=\"num\">' + fmt$(t[k].material) + '<\/td><td class=\"num\">' + fmt$(t[k].labor) +\n      '<\/td><td class=\"num\">' + fmt$(t[k].downtime) + '<\/td><td class=\"num\">' + fmt$(t[k].total) +\n      '<\/td><td class=\"num\">' + fmt$(t[k].total \/ horiz) + '<\/td><\/tr>';\n  });\n  tbl += '<\/table><div class=\"tbl-cap\">' + horiz + '-month horizon, ' + dutyLbl +\n    ' duty, life basis: ' + (basis === 'model' ? 'wear model (geometry-driven)' : 'customer field life') +\n    '. Changeout labor and downtime are per event; downtime cost is customer-sourced. Commercially uncertified pairing, pending VP Sales price ruling.<\/div>';\n  $('s_tco_tblwrap').innerHTML = tbl;\n}\n\n\/\/ \u2500\u2500 PIPE METRIC MODULE \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nfunction calcPipe(){\n  const dn = parseInt($('q_dn').value);\n  const duty = DUTY_MAP[$('q_duty').value].mult;\n  const wear = parseFloat($('q_wear').value) || 0.25;\n  const usableFrac = 1 - (parseFloat($('q_retire').value) || 25) \/ 100;\n  const len = parseFloat($('q_len').value) || 500;\n  const horiz = parseFloat($('q_horiz').value) || 10;\n  const costs = {ms:+$('q_cms').value, ut:+$('q_cut').value, e7:+$('q_c7').value, e9:+$('q_c9').value};\n  const downHr = parseFloat($('q_down').value) || 0;\n  const laborPer = parseFloat($('q_labor').value) || 0;\n  const downPerChange = downHr * 8 * (len \/ 200);\n  const laborPerChange = laborPer * Math.ceil(len \/ 50);\n\n  const wallOf = tbl => (tbl[dn] && tbl[dn].length) ? Math.max(...tbl[dn]) : null;\n  const w = {ms:wallOf(MILD_WALLS), ut:wallOf(UT600_WALLS), e7:wallOf(ESSER700_WALLS), e9:wallOf(ESSER900_WALLS)};\n\n  $('q_walls').innerHTML = 'OD ' + PIPE_OD_MM[dn] + ' mm. Walls: ' +\n    ['ms','ut','e7','e9'].map(k => ({ms:'MS',ut:'UT600',e7:'E700',e9:'E900'})[k] + ' ' +\n      (w[k] !== null ? w[k] + ' mm' : '\\u2014')).join(' \/ ');\n\n  const utM = ut600IntegratedMultiple(usableFrac);\n  const e7M = esser700Multiple();\n  const e9M = esser900Floor();\n  $('q_e9floor').textContent = fmtX(e9M);\n\n  const defs = [\n    {key:'ms', name:'A36 mild steel', tag:'160 HB baseline', mult:1, css:hbShade(160), cost:costs.ms},\n    {key:'ut', name:'UT600', tag:'650 BHN ID \\u2192 250 BHN OD gradient', mult:utM,\n      css:gradientCSS(f => ut600BHN(f * usableFrac * 100)), cost:costs.ut},\n    {key:'e7', name:'ESSER Twin 700', tag:'720 HB (63 HRC), 0.92 two-layer corr.', mult:e7M, css:hbShade(720), cost:costs.e7},\n    {key:'e9', name:'ESSER Twin 900', tag:'850 HB (67 HRC) white iron', mult:e9M, css:hbShade(850), cost:costs.e9, range:ESSER900_FIELD_RANGE}\n  ];\n\n  const rows = defs.map(d => {\n    const wall = w[d.key];\n    const lifeYr = wall !== null ? pipeLifeYears(wall, usableFrac, d.mult, wear, duty) : null;\n    const tco = wall !== null ? cycleTCO(lifeYr, horiz, d.cost * len, laborPerChange, downPerChange) : null;\n    return {...d, wall, lifeYr, tco};\n  });\n\n  const maxM = Math.max(...rows.map(r => r.mult));\n  $('q_bars').innerHTML = rows.map(r => {\n    const wpct = Math.max(6, (r.mult \/ maxM) * 100);\n    const sub = r.range ? 'model floor; field 40\\u201370\\u00D7 (G65)'\n      : (r.lifeYr !== null ? fmtYr(r.lifeYr) + ' yr at this duty' : 'not listed at DN' + dn);\n    return gbRow(r.name, r.tag, r.css, fmtX(r.mult), sub)\n      .replace('class=\"gb-bar\"', 'class=\"gb-bar\" style=\"width:' + wpct + '%\"');\n  }).join('');\n\n  const avail = rows.filter(r => r.tco);\n  const best = avail.reduce((b, r) => r.tco.total < b.tco.total ? r : b, avail[0]);\n  $('q_cards').innerHTML = avail.map(r =>\n    card(r.name + ' TCO', fmt$(r.tco.total),\n      fmtYr(r.lifeYr) + ' yr life, ' + r.tco.replacements + ' replacement' + (r.tco.replacements === 1 ? '' : 's') + ' in ' + horiz + ' yr',\n      r === best)).join('');\n\n  let tbl = '<table><tr><th>Product<\/th><th class=\"num\">Wall (mm)<\/th><th class=\"num\">Life vs A36<\/th><th class=\"num\">Life (yr)<\/th><th class=\"num\">Replacements<\/th><th class=\"num\">Material<\/th><th class=\"num\">Labor<\/th><th class=\"num\">Downtime<\/th><th class=\"num\">TCO<\/th><\/tr>';\n  for (const r of rows){\n    if (r.wall === null){\n      tbl += '<tr><td>' + r.name + '<\/td><td class=\"num\">\\u2014<\/td><td class=\"num\">' + fmtX(r.mult) + '<\/td><td class=\"num\" colspan=\"6\">Not listed at DN' + dn + '<\/td><\/tr>';\n      continue;\n    }\n    tbl += '<tr' + (r === best ? ' class=\"win\"' : '') + '><td>' + r.name + '<\/td><td class=\"num\">' + r.wall.toFixed(1) +\n      '<\/td><td class=\"num\">' + fmtX(r.mult) + '<\/td><td class=\"num\">' + fmtYr(r.lifeYr) +\n      '<\/td><td class=\"num\">' + r.tco.replacements + '<\/td><td class=\"num\">' + fmt$(r.tco.material) +\n      '<\/td><td class=\"num\">' + fmt$(r.tco.labor) + '<\/td><td class=\"num\">' + fmt$(r.tco.downtime) +\n      '<\/td><td class=\"num\">' + fmt$(r.tco.total) + '<\/td><\/tr>';\n  }\n  tbl += '<\/table><div class=\"tbl-cap\">DN' + dn + ', ' + len + ' m line, ' + horiz + '-yr horizon, ' +\n    DUTY_MAP[$('q_duty').value].label + ' duty, ' + Math.round((1-usableFrac)*100) + '% wall retirement. ESSER 900 life and TCO use the model floor; field data supports 40\\u201370\\u00D7. All multiples vs A36 mild steel (160 HB).<\/div>';\n  $('q_tblwrap').innerHTML = tbl;\n}\n\n\/\/ \u2500\u2500 UT600 CATALOG MODULE \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nfunction fillCatSelectors(){\n  const diaSel = $('c_dia');\n  diaSel.innerHTML = Object.keys(ASME).map(d => '<option' + (d === '8\"' ? ' selected' : '') + '>' + d + '<\/option>').join('');\n  fillSched();\n}\nfunction fillSched(){\n  const dia = $('c_dia').value, sel = $('c_sched'), prev = sel.value;\n  sel.innerHTML = Object.keys(ASME[dia]).map(s =>\n    '<option value=\"' + s + '\">' + s + ' \\u2014 ' + ASME[dia][s].toFixed(3) + '\\u2033<\/option>').join('');\n  if ([...sel.options].some(o => o.value === prev)) sel.value = prev;\n  else if ([...sel.options].some(o => o.value === 'Sch 80')) sel.value = 'Sch 80';\n}\nfunction calcCat(){\n  const dia = $('c_dia').value, sched = $('c_sched').value;\n  const wall = ASME[dia][sched];\n  const sf = parseInt($('c_sf').value);\n  const duty = DUTY_MAP[$('c_duty').value].mult;\n  const wear = parseFloat($('c_wear').value) || 0.25;\n  const usableFrac = 1 - (parseFloat($('c_retire').value) || 25) \/ 100;\n  const len = parseFloat($('c_len').value) || 500;\n  const horiz = parseFloat($('c_horiz').value) || 5;\n  const utCost = (+$('c_utp').value) + (+$('c_uti').value);\n  const msCost = (+$('c_msp').value) + (+$('c_msi').value);\n  const downHr = parseFloat($('c_down').value) || 0;\n  const laborPer = parseFloat($('c_labor').value) || 0;\n  const downPerChange = downHr * 8 * (len \/ 200);\n  const laborPerChange = laborPer * Math.ceil(len \/ 50);\n\n  const row = matchUT600(dia, wall);\n  const utM = ut600IntegratedMultiple(usableFrac);\n  const usableIn = wall * usableFrac;\n  const utLife = usableIn * utM \/ (wear * duty);\n  const msLife = usableIn \/ (wear * duty);\n  const utT = cycleTCO(utLife, horiz, utCost * len, laborPerChange, downPerChange);\n  const msT = cycleTCO(msLife, horiz, msCost * len, laborPerChange, downPerChange);\n  const press = row ? (sf === 3 ? row.sf3 : sf === 4 ? row.sf4 : row.sf5) : null;\n\n  $('c_cards').innerHTML =\n    card('Matched part', row ? row.pn : 'No match', row ? row.nps + ' nominal, ' + row.nomWall.toFixed(3) + '\\u2033 wall (nearest to ' + wall.toFixed(3) + '\\u2033)' : 'No UT600 catalog entry for ' + dia, false) +\n    card('Pressure rating', press ? Math.round(press).toLocaleString() + ' psi' : '\\u2014', sf + ':1 safety factor', false) +\n    card('Wear life vs A36', fmtX(utM), 'Layer-integrated through ' + Math.round(usableFrac * 100) + '% usable wall (surface ' + fmtX(R(ut600BHN(0))) + ')', false) +\n    card('UT600 TCO', fmt$(utT.total), fmtYr(utLife) + ' yr life, ' + utT.replacements + ' replacements in ' + horiz + ' yr', utT.total < msT.total) +\n    card('Mild steel TCO', fmt$(msT.total), fmtYr(msLife) + ' yr life, ' + msT.replacements + ' replacements in ' + horiz + ' yr', msT.total <= utT.total) +\n    card(utT.total <= msT.total ? 'UT600 saves' : 'UT600 premium', fmt$(Math.abs(msT.total - utT.total)), 'over ' + horiz + '-yr horizon, ' + len + ' ft', utT.total < msT.total);\n\n  \/\/ Profile bar with BHN ticks\n  let prof = gbRow('UT600 wall', dia + ' ' + sched + ', ' + wall.toFixed(3) + '\\u2033',\n    gradientCSS(f => ut600BHN(f * 100)), '650 \\u2192 250 BHN', 'ID wear face \\u2192 OD');\n  prof += '<div class=\"gb-legend\">' + [0,25,50,75,100].map(p =>\n    '<span>' + p + '% wall: <b>' + Math.round(ut600BHN(p)) + ' BHN<\/b><\/span>').join('') + '<\/div>';\n  $('c_profile').innerHTML = prof;\n\n  let tbl = '<table><tr><th>Line<\/th><th class=\"num\">Life (yr)<\/th><th class=\"num\">Replacements<\/th><th class=\"num\">Material<\/th><th class=\"num\">Labor<\/th><th class=\"num\">Downtime<\/th><th class=\"num\">TCO<\/th><\/tr>';\n  for (const [nm, life, t, win] of [['UT600 ' + (row ? row.pn : ''), utLife, utT, utT.total <= msT.total], ['A36 mild steel', msLife, msT, msT.total < utT.total]]){\n    tbl += '<tr' + (win ? ' class=\"win\"' : '') + '><td>' + nm + '<\/td><td class=\"num\">' + fmtYr(life) +\n      '<\/td><td class=\"num\">' + t.replacements + '<\/td><td class=\"num\">' + fmt$(t.material) +\n      '<\/td><td class=\"num\">' + fmt$(t.labor) + '<\/td><td class=\"num\">' + fmt$(t.downtime) +\n      '<\/td><td class=\"num\">' + fmt$(t.total) + '<\/td><\/tr>';\n  }\n  tbl += '<\/table><div class=\"tbl-cap\">' + len + ' ft line, ' + DUTY_MAP[$('c_duty').value].label +\n    ' duty, A36 rate ' + wear.toFixed(3) + ' in\/yr, ' + Math.round((1 - usableFrac) * 100) + '% wall retirement. Same schedule wall assumed for both lines.<\/div>';\n  $('c_tblwrap').innerHTML = tbl;\n}\n\n\/\/ \u2500\u2500 REPORTS: customer info, download, PDF, email \u2500\u2500\nconst TAB_REPORT = {\n  plate: {title:'AR 400\/450\/500 vs Tri-Braze: Plate Basis (impact + abrasion)', accent:'#E63C2F',\n    blocks:['p_bars','p_cards','p_tblwrap','p_tbnote'],\n    inputs:[['Plate thickness','p_thick','in'],['Duty tier','p_duty',''],['A36 wear rate','p_wear','in\/yr'],\n      ['Tri-Braze reference','p_ref',''],['Fleet size','p_fleet','plates'],['Horizon','p_horiz','months'],\n      ['Labor per changeout','p_labor','$'],['Downtime per changeout','p_down','$'],\n      ['Reference price','p_priceRef','$\/lb'],['Tri-Braze price','p_priceTB','$\/lb']],\n    note:'Use model: combined impact and abrasion (CFI TCO Model Standard v1.8, Sec. 12).'},\n  pkg: {title:'AR 400\/450\/500 vs Tri-Braze: Liner Package Basis (impact + abrasion)', accent:'#E63C2F',\n    blocks:['k_bars','k_cards','k_tblwrap','k_note'],\n    inputs: function(){\n      const base = [['AR reference grade','k_ref',''],['Duty tier','k_duty',''],['Wear life basis','k_basis','']];\n      const life = $('k_basis').value === 'model'\n        ? [['Plate thickness','k_thick','in'],['A36 wear rate','k_wear','in\/yr']]\n        : [['AR package field life','k_life','months']];\n      return base.concat(life, [['AR package installed cost','k_costAR','$'],['Tri-Braze package installed cost','k_costTB','$'],\n        ['Horizon','k_horiz','months'],['Labor per changeout','k_labor','$'],['Downtime per changeout','k_down','$']]);\n    },\n    note:'Certified fleet model basis (Tri-Braze Fleet TCO v2.9.4): Tri-Braze life = customer-sourced AR package life times the certified field impact multiplier. Use model: combined impact and abrasion (Standard v1.8, Sec. 12).'},\n  slide: {title:'Sliding Abrasion Service: AR 550\/600 vs CCO', accent:'#E63C2F',\n    blocks:['s_bars','s_cards','s_tblwrap','s_tco_bars','s_tco_cards','s_tco_tblwrap','s_tco_note'],\n    inputs: function(){\n      const base = [['AR plate thickness','s_thick','in'],['Duty tier','s_duty',''],['A36 wear rate','s_wear','in\/yr'],\n        ['CCO clad total','s_ccototal','in'],['Overlay share','s_overlay','%'],['Carbide fraction','s_carb','%'],\n        ['TCO wear life basis','s_tco_basis','']];\n      const life = $('s_tco_basis').value === 'field'\n        ? [['AR550 field life','s_life550','mo'],['AR600 field life','s_life600','mo'],['CCO field life','s_lifecco','mo']]\n        : [];\n      return base.concat(life, [['AR550 installed cost','s_cost550','$'],['AR600 installed cost','s_cost600','$'],\n        ['CCO installed cost','s_costcco','$'],['Horizon','s_tco_horiz','months'],\n        ['Labor per changeout','s_tco_labor','$'],['Downtime per changeout','s_tco_down','$']]);\n    },\n    note:'Use model: sliding abrasion only. Wear life comparison plus package-basis TCO on quoted installed costs. TCO for this pairing is a Director of Product Management ruling pending VP Sales TWS price confirmation and is commercially uncertified (Standard Sec. 11\/12).'},\n  pipe: {title:'Pipe Portfolio: UT600 vs ESSER Twin 700\/900', accent:'#1C4BA7',\n    blocks:['q_bars','q_cards','q_tblwrap'],\n    inputs:[['Pipe size','q_dn','DN'],['Duty tier','q_duty',''],['A36 wear rate','q_wear','in\/yr'],\n      ['Wall retirement','q_retire','%'],['Line length','q_len','m'],['Horizon','q_horiz','yr'],\n      ['Mild steel cost','q_cms','$\/m'],['UT600 cost','q_cut','$\/m'],['ESSER 700 cost','q_c7','$\/m'],\n      ['ESSER 900 cost','q_c9','$\/m'],['Downtime','q_down','$\/hr'],['Labor per change','q_labor','$\/50 m']],\n    note:'ESSER Twin 900 life and TCO use the model floor; measured G65 field data for this class of white iron runs 40-70x vs A36 (Standard v1.8, Sec. 7).'},\n  cat: {title:'UT600 Catalog: ASME Sizing, Pressure and TCO', accent:'#1C4BA7',\n    blocks:['c_cards','c_profile','c_tblwrap'],\n    inputs:[['Nominal size','c_dia',''],['Schedule','c_sched',''],['Safety factor','c_sf',':1'],\n      ['Duty tier','c_duty',''],['A36 wear rate','c_wear','in\/yr'],['Wall retirement','c_retire','%'],\n      ['Line length','c_len','ft'],['Horizon','c_horiz','yr'],['UT600 pipe','c_utp','$\/ft'],\n      ['UT600 install','c_uti','$\/ft'],['MS pipe','c_msp','$\/ft'],['MS install','c_msi','$\/ft'],\n      ['Downtime','c_down','$\/hr'],['Labor per change','c_labor','$\/50 ft']],\n    note:'Part match and pressure ratings per UT600 catalog; wear life per the 650\/250 BHN gradient (Standard v1.8, Sec. 8).'}\n};\n\nconst REPORT_CSS = `\nbody{font-family:Arial,Helvetica,sans-serif;color:#1A1A1A;font-size:13px;line-height:1.45;margin:0;padding:32px;-webkit-print-color-adjust:exact;print-color-adjust:exact;}\n.rh{border-bottom:4px solid #FFCE2E;padding-bottom:12px;margin-bottom:18px;}\n.rh .b{font-weight:900;font-size:20px;letter-spacing:0.05em;}\n.rh .b span{color:#B58F00;}\n.rh .t{font-size:13px;color:#5A5751;margin-top:2px;}\nh2{font-size:13px;font-weight:900;letter-spacing:0.08em;text-transform:uppercase;border-bottom:2px solid #FFCE2E;padding-bottom:4px;margin:20px 0 10px;}\n.ci{display:grid;grid-template-columns:1fr 1fr 1fr;gap:6px 20px;font-size:12.5px;}\n.ci b{font-weight:700;}\ntable{width:100%;border-collapse:collapse;font-size:12px;margin:6px 0;}\nth{background:#0B0B0B;color:#fff;text-align:left;font-size:10.5px;letter-spacing:0.05em;text-transform:uppercase;padding:6px 8px;}\ntd{padding:6px 8px;border-top:1px solid #DDD9D2;}\ntr.win td{background:#FFFDF4;font-weight:700;}\ntd.num,th.num{text-align:right;font-variant-numeric:tabular-nums;}\n.tbl-cap{font-size:10.5px;color:#5A5751;margin:4px 0 12px;}\n.res-cards{display:grid;grid-template-columns:repeat(3,1fr);gap:10px;margin:8px 0 14px;}\n.rc{border:1px solid #DDD9D2;border-top:3px solid #222;padding:10px 12px;}\n.rc.win{border-top-color:#FFCE2E;background:#FFFDF4;}\n.rc .l{font-size:10px;font-weight:700;letter-spacing:0.05em;text-transform:uppercase;color:#5A5751;}\n.rc .v{font-size:19px;font-weight:900;margin:2px 0;}\n.rc .s{font-size:10.5px;color:#5A5751;}\n.gb-row{display:grid;grid-template-columns:150px 1fr 130px;gap:12px;align-items:center;margin-bottom:8px;}\n.gb-name{font-size:12px;font-weight:700;}\n.gb-name .tag{display:block;font-size:10px;font-weight:400;color:#5A5751;}\n.gb-bar{position:relative;height:20px;border:1px solid #DDD9D2;background:#EEE;}\n.gb-fill{position:absolute;top:0;left:0;right:0;bottom:0;}\n.gb-val{font-size:12.5px;font-weight:900;text-align:right;white-space:nowrap;}\n.gb-val .sub{display:block;font-size:10px;font-weight:400;color:#5A5751;}\n.gb-legend{display:flex;gap:12px;font-size:10px;color:#5A5751;margin-top:8px;flex-wrap:wrap;}\n.sw{display:inline-block;width:10px;height:10px;vertical-align:-1px;margin-right:4px;border:1px solid #DDD9D2;}\n.callout{border-left:4px solid #FFCE2E;border-top:1px solid #DDD9D2;border-right:1px solid #DDD9D2;border-bottom:1px solid #DDD9D2;padding:8px 12px;font-size:11px;margin:0 0 10px;}\n.callout.red{border-left-color:#E63C2F;}\n.callout.blue{border-left-color:#1C4BA7;}\n.rfoot{border-top:4px solid #FFCE2E;margin-top:22px;padding-top:10px;font-size:10px;color:#5A5751;}\n@page{margin:14mm;}\n`;\n\nfunction activeTab(){\n  const t = document.querySelector('.tab.active');\n  return t ? t.dataset.tab : 'plate';\n}\nfunction custInfo(){\n  const g = id => ($(id).value || '').trim();\n  return {company:g('ci_company'), contact:g('ci_contact'), email:g('ci_email'),\n    site:g('ci_site'), app:g('ci_app'), rep:g('ci_rep'), date:g('ci_date') || new Date().toLocaleDateString()};\n}\nfunction esc(t){ return String(t).replace(\/&\/g,'&amp;').replace(\/<\/g,'&lt;').replace(\/>\/g,'&gt;'); }\nfunction inputLabel(id){\n  const el = $(id);\n  if (el.tagName === 'SELECT' && el.selectedIndex >= 0) return el.options[el.selectedIndex].text;\n  return el.value;\n}\nfunction buildReport(tab){\n  const cfg = TAB_REPORT[tab];\n  const ci = custInfo();\n  const selfTest = $('selftest').textContent;\n  let inputRows = '';\n  const inputList = (typeof cfg.inputs === 'function') ? cfg.inputs() : cfg.inputs;\n  for (const [label, id, unit] of inputList){\n    inputRows += '<tr><td>' + esc(label) + '<\/td><td class=\"num\">' + esc(inputLabel(id)) + (unit ? ' ' + unit : '') + '<\/td><\/tr>';\n  }\n  const blocks = cfg.blocks.map(id => {\n    const el = $(id);\n    if (!el || !el.innerHTML.trim()) return '';\n    const cls = el.className && el.className.indexOf('callout') >= 0 ? ' class=\"' + el.className + '\"' : '';\n    return '<div' + cls + '>' + el.innerHTML + '<\/div>';\n  }).join('\\n');\n  const uncertBanner = (tab === 'slide')\n    ? '<div class=\"callout red\" style=\"margin:0 0 12px;\"><b>Commercially uncertified pairing.<\/b> This AR550\/AR600 vs CCO TCO is provided under a Director of Product Management ruling, pending VP Sales TWS price confirmation. AR550\/AR600 prices are unverified and CCO carries no locked price. Treat the economics as directional until the commercial ruling lands.<\/div>'\n    : '';\n  const uncertFoot = (tab === 'slide')\n    ? ' | AR550\/600 vs CCO TCO is commercially uncertified: Dir. PM ruling pending VP Sales price confirmation'\n    : '';\n  return '<!DOCTYPE html><html><head><meta charset=\"UTF-8\"><title>CFI TCO Analysis - ' + esc(ci.company || 'Customer') + '<\/title>' +\n    '<style>' + REPORT_CSS + 'h2{border-bottom-color:' + cfg.accent + ';}<\/style><\/head><body>' +\n    '<div class=\"rh\"><div class=\"b\">CFI <span>WEAR SOLUTIONS<\/span> | TCO ANALYSIS<\/div>' +\n    '<div class=\"t\">' + esc(cfg.title) + ' &nbsp;|&nbsp; Prepared ' + esc(ci.date) + '<\/div><\/div>' +\n    '<h2>Customer<\/h2><div class=\"ci\">' +\n    '<div><b>Company:<\/b> ' + esc(ci.company || '-') + '<\/div>' +\n    '<div><b>Contact:<\/b> ' + esc(ci.contact || '-') + '<\/div>' +\n    '<div><b>Email:<\/b> ' + esc(ci.email || '-') + '<\/div>' +\n    '<div><b>Site:<\/b> ' + esc(ci.site || '-') + '<\/div>' +\n    '<div><b>Application:<\/b> ' + esc(ci.app || '-') + '<\/div>' +\n    '<div><b>Prepared by:<\/b> ' + esc(ci.rep || '-') + '<\/div><\/div>' +\n    '<h2>Inputs<\/h2><table><tr><th>Parameter<\/th><th class=\"num\">Value<\/th><\/tr>' + inputRows + '<\/table>' +\n    '<div class=\"tbl-cap\">' + esc(cfg.note) + ' Wear rate and downtime inputs are customer-sourced.<\/div>' +\n    '<h2>Results<\/h2>' + uncertBanner + blocks +\n    '<div class=\"rfoot\">CFI Portfolio TCO Suite v1.6 | Governed by CFI TCO Model Standard v1.8 | Wear model: life ratio = (HB \/ 160)^1.25 vs A36 mild steel baseline, stated by name in every claim | ' + esc(selfTest) + uncertFoot +\n    ' | Life estimates are engineering estimates from a locked, versioned model, not guarantees; CFI invites validation against measured field wear data.<\/div>' +\n    '<\/body><\/html>';\n}\nfunction reportFilename(ext){\n  const ci = custInfo();\n  const safe = t => (t || '').replace(\/[^A-Za-z0-9]+\/g, '_').replace(\/^_+|_+$\/g, '') || 'Customer';\n  return 'CFI_TCO_' + safe(ci.company) + '_' + activeTab() + '_' + new Date().toISOString().slice(0,10) + '.' + ext;\n}\nfunction downloadReportFile(){\n  const html = buildReport(activeTab());\n  const blob = new Blob([html], {type:'text\/html'});\n  const a = document.createElement('a');\n  a.href = URL.createObjectURL(blob);\n  a.download = reportFilename('html');\n  document.body.appendChild(a); a.click();\n  setTimeout(() => { URL.revokeObjectURL(a.href); a.remove(); }, 500);\n}\nfunction saveReportPDF(){\n  const html = buildReport(activeTab());\n  const old = document.getElementById('printframe');\n  if (old) old.remove();\n  const fr = document.createElement('iframe');\n  fr.id = 'printframe';\n  fr.style.cssText = 'position:fixed;right:0;bottom:0;width:0;height:0;border:0;visibility:hidden;';\n  document.body.appendChild(fr);\n  const fd = fr.contentDocument || fr.contentWindow.document;\n  fd.open(); fd.write(html); fd.close();\n  fd.title = reportFilename('pdf').replace('.pdf','');\n  setTimeout(() => {\n    try { fr.contentWindow.focus(); fr.contentWindow.print(); }\n    catch(e){ alert('Print failed to open. Use Download report file instead, then print it to PDF from your browser.'); }\n  }, 400);\n}\nfunction emailReport(){\n  const ci = custInfo();\n  const cfg = TAB_REPORT[activeTab()];\n  const subject = 'CFI TCO Analysis' + (ci.company ? ' - ' + ci.company : '') + (ci.app ? ' - ' + ci.app : '');\n  const body = (ci.contact ? ci.contact + ',\\n\\n' : '') +\n    'Attached is the total cost of ownership analysis we discussed' + (ci.app ? ' for the ' + ci.app : '') +\n    (ci.site ? ' at ' + ci.site : '') + '.\\n\\n' +\n    'Scope: ' + cfg.title + '.\\n' +\n    'Every life claim is stated against the A36 mild steel baseline (160 HB) under a locked, versioned model, and the wear rate and downtime figures are the ones you provided. If any input should change, send the number and I will rerun it.\\n\\n' +\n    (ci.rep ? ci.rep + '\\n' : '') + 'CFI Wear Solutions';\n  window.location.href = 'mailto:' + encodeURIComponent(ci.email || '') +\n    '?subject=' + encodeURIComponent(subject) + '&body=' + encodeURIComponent(body);\n}\n\n\/\/ \u2500\u2500 WIRING \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\ndocument.querySelectorAll('.tab').forEach(t => t.addEventListener('click', () => {\n  document.querySelectorAll('.tab').forEach(x => { x.classList.remove('active'); x.setAttribute('aria-selected','false'); });\n  document.querySelectorAll('.panel').forEach(x => x.classList.remove('active'));\n  t.classList.add('active'); t.setAttribute('aria-selected','true');\n  document.getElementById(t.dataset.tab).classList.add('active');\n}));\n\ndutySelect($('p_duty'), $('p_dutynote'));\ndutySelect($('k_duty'), $('k_dutynote'));\ndutySelect($('s_duty'), $('s_dutynote'));\ndutySelect($('q_duty'), $('q_dutynote'));\ndutySelect($('c_duty'), $('c_dutynote'));\n\n$('q_dn').innerHTML = Object.keys(PIPE_OD_MM).map(dn =>\n  '<option value=\"' + dn + '\"' + (dn === '150' ? ' selected' : '') + '>DN ' + dn + '<\/option>').join('');\nfillCatSelectors();\n$('c_dia').addEventListener('change', () => { fillSched(); calcCat(); });\n\n['p_thick','p_duty','p_wear','p_ref','p_fleet','p_horiz','p_labor','p_down','p_priceRef','p_priceTB']\n  .forEach(id => { $(id).addEventListener('input', calcPlate); $(id).addEventListener('change', calcPlate); });\n['s_thick','s_duty','s_wear','s_ccototal','s_overlay','s_carb']\n  .forEach(id => { $(id).addEventListener('input', calcSlide); $(id).addEventListener('change', calcSlide); });\n['s_life550','s_life600','s_lifecco','s_cost550','s_cost600','s_costcco','s_tco_horiz','s_tco_labor','s_tco_down']\n  .forEach(id => { $(id).addEventListener('input', calcSlideTCO); $(id).addEventListener('change', calcSlideTCO); });\n$('s_tco_basis').addEventListener('change', () => { slideTcoBasisToggle(); if ($('s_tco_basis').value === 'field') slideTcoLifePrefill(); calcSlideTCO(); });\n['k_life','k_thick','k_wear','k_costAR','k_costTB','k_horiz','k_labor','k_down']\n  .forEach(id => { $(id).addEventListener('input', calcPkg); $(id).addEventListener('change', calcPkg); });\n$('k_ref').addEventListener('change', () => { pkgLifeDefault(); calcPkg(); });\n$('k_duty').addEventListener('change', () => { pkgLifeDefault(); calcPkg(); });\n$('k_basis').addEventListener('change', () => { pkgBasisToggle(); calcPkg(); });\n$('p_ref').addEventListener('change', () => { $('p_priceRef').value = PLATE_GRADES[$('p_ref').value].priceDefault; calcPlate(); });\n['q_dn','q_duty','q_wear','q_retire','q_len','q_horiz','q_cms','q_cut','q_c7','q_c9','q_down','q_labor']\n  .forEach(id => { $(id).addEventListener('input', calcPipe); $(id).addEventListener('change', calcPipe); });\n['c_sched','c_sf','c_duty','c_wear','c_retire','c_len','c_horiz','c_utp','c_uti','c_msp','c_msi','c_down','c_labor']\n  .forEach(id => { $(id).addEventListener('input', calcCat); $(id).addEventListener('change', calcCat); });\n\n$('ci_date').value = new Date().toLocaleDateString();\n$('btn_html').addEventListener('click', downloadReportFile);\n$('btn_pdf').addEventListener('click', saveReportPDF);\n$('btn_mail').addEventListener('click', emailReport);\n\n\/\/ Self-test on load\n(function(){\n  const r = runRegression();\n  const el = $('selftest');\n  el.textContent = 'Self-test: ' + r.passed + '\/' + r.total + ' passed';\n  el.className = 'selftest ' + (r.passed === r.total ? 'ok' : 'bad');\n  if (r.passed !== r.total) console.error('REGRESSION FAILURES', r.results.filter(x => !x.pass));\n})();\n\npkgLifeDefault(); pkgBasisToggle();\nslideTcoBasisToggle();\ncalcPlate(); calcPkg(); calcSlide(); calcPipe(); calcCat();\n<\/script>\n<\/body>\n<\/html>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t","protected":false},"excerpt":{"rendered":"<p>CFI Portfolio TCO Suite v1.6 CFI PORTFOLIO TCO SUITE Plate + Pipe &nbsp;|&nbsp; v1.6 &nbsp;|&nbsp; Internal sales tool Governed by CFI TCO Model Standard v1.8 (July 2026). Wear model: life ratio = (HB \/ 160)1.25 vs A36 baseline. All claims state the baseline by name. Certified reps only. AR vs TRI-BRAZE (PLATE BASIS) AR vs [&hellip;]<\/p>\n","protected":false},"author":19,"featured_media":0,"parent":42006,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-42290","page","type-page","status-publish","hentry"],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v28.0 (Yoast SEO v28.0) - https:\/\/yoast.com\/product\/yoast-seo-premium-wordpress\/ -->\n<title>TCO-Internal - CFI<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/cficompany.com\/es\/publicacion-2-en-la-intranet\/tco-interno\/\" \/>\n<meta property=\"og:locale\" content=\"es_MX\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"TCO-Internal\" \/>\n<meta property=\"og:description\" content=\"CFI Portfolio TCO Suite v1.6 CFI PORTFOLIO TCO SUITE Plate + Pipe &nbsp;|&nbsp; v1.6 &nbsp;|&nbsp; Internal sales tool Governed by CFI TCO Model Standard v1.8 (July 2026). Wear model: life ratio = (HB \/ 160)1.25 vs A36 baseline. All claims state the baseline by name. Certified reps only. AR vs TRI-BRAZE (PLATE BASIS) AR vs [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/cficompany.com\/es\/publicacion-2-en-la-intranet\/tco-interno\/\" \/>\n<meta property=\"og:site_name\" content=\"CFI\" \/>\n<meta property=\"article:modified_time\" content=\"2026-07-20T20:50:56+00:00\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Tiempo de lectura\" \/>\n\t<meta name=\"twitter:data1\" content=\"7 minutos\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/cficompany.com\\\/intranet-post-2\\\/tco-internal\\\/\",\"url\":\"https:\\\/\\\/cficompany.com\\\/intranet-post-2\\\/tco-internal\\\/\",\"name\":\"TCO-Internal - CFI\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/cficompany.com\\\/#website\"},\"datePublished\":\"2026-06-02T14:20:07+00:00\",\"dateModified\":\"2026-07-20T20:50:56+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/cficompany.com\\\/intranet-post-2\\\/tco-internal\\\/#breadcrumb\"},\"inLanguage\":\"es\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/cficompany.com\\\/intranet-post-2\\\/tco-internal\\\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/cficompany.com\\\/intranet-post-2\\\/tco-internal\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/cficompany.com\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Intranet Home\",\"item\":\"https:\\\/\\\/cficompany.com\\\/intranet-post-2\\\/\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"TCO-Internal\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/cficompany.com\\\/#website\",\"url\":\"https:\\\/\\\/cficompany.com\\\/\",\"name\":\"CFI\",\"description\":\"\",\"publisher\":{\"@id\":\"https:\\\/\\\/cficompany.com\\\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/cficompany.com\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"es\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/cficompany.com\\\/#organization\",\"name\":\"CFI\",\"url\":\"https:\\\/\\\/cficompany.com\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"es\",\"@id\":\"https:\\\/\\\/cficompany.com\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/cficompany.com\\\/wp-content\\\/uploads\\\/2023\\\/07\\\/CFI-Logo.png\",\"contentUrl\":\"https:\\\/\\\/cficompany.com\\\/wp-content\\\/uploads\\\/2023\\\/07\\\/CFI-Logo.png\",\"width\":1080,\"height\":1080,\"caption\":\"CFI\"},\"image\":{\"@id\":\"https:\\\/\\\/cficompany.com\\\/#\\\/schema\\\/logo\\\/image\\\/\"},\"sameAs\":[\"https:\\\/\\\/www.linkedin.com\\\/company\\\/cfi-company\"]}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"TCO-Interno - CFI","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/cficompany.com\/es\/publicacion-2-en-la-intranet\/tco-interno\/","og_locale":"es_MX","og_type":"article","og_title":"TCO-Internal","og_description":"CFI Portfolio TCO Suite v1.6 CFI PORTFOLIO TCO SUITE Plate + Pipe &nbsp;|&nbsp; v1.6 &nbsp;|&nbsp; Internal sales tool Governed by CFI TCO Model Standard v1.8 (July 2026). Wear model: life ratio = (HB \/ 160)1.25 vs A36 baseline. All claims state the baseline by name. Certified reps only. AR vs TRI-BRAZE (PLATE BASIS) AR vs [&hellip;]","og_url":"https:\/\/cficompany.com\/es\/publicacion-2-en-la-intranet\/tco-interno\/","og_site_name":"CFI","article_modified_time":"2026-07-20T20:50:56+00:00","twitter_card":"summary_large_image","twitter_misc":{"Tiempo de lectura":"7 minutos"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/cficompany.com\/intranet-post-2\/tco-internal\/","url":"https:\/\/cficompany.com\/intranet-post-2\/tco-internal\/","name":"TCO-Interno - CFI","isPartOf":{"@id":"https:\/\/cficompany.com\/#website"},"datePublished":"2026-06-02T14:20:07+00:00","dateModified":"2026-07-20T20:50:56+00:00","breadcrumb":{"@id":"https:\/\/cficompany.com\/intranet-post-2\/tco-internal\/#breadcrumb"},"inLanguage":"es","potentialAction":[{"@type":"ReadAction","target":["https:\/\/cficompany.com\/intranet-post-2\/tco-internal\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/cficompany.com\/intranet-post-2\/tco-internal\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/cficompany.com\/"},{"@type":"ListItem","position":2,"name":"Intranet Home","item":"https:\/\/cficompany.com\/intranet-post-2\/"},{"@type":"ListItem","position":3,"name":"TCO-Internal"}]},{"@type":"WebSite","@id":"https:\/\/cficompany.com\/#website","url":"https:\/\/cficompany.com\/","name":"CFI","description":"","publisher":{"@id":"https:\/\/cficompany.com\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/cficompany.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"es"},{"@type":"Organization","@id":"https:\/\/cficompany.com\/#organization","name":"CFI","url":"https:\/\/cficompany.com\/","logo":{"@type":"ImageObject","inLanguage":"es","@id":"https:\/\/cficompany.com\/#\/schema\/logo\/image\/","url":"https:\/\/cficompany.com\/wp-content\/uploads\/2023\/07\/CFI-Logo.png","contentUrl":"https:\/\/cficompany.com\/wp-content\/uploads\/2023\/07\/CFI-Logo.png","width":1080,"height":1080,"caption":"CFI"},"image":{"@id":"https:\/\/cficompany.com\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.linkedin.com\/company\/cfi-company"]}]}},"_links":{"self":[{"href":"https:\/\/cficompany.com\/es\/wp-json\/wp\/v2\/pages\/42290","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/cficompany.com\/es\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/cficompany.com\/es\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/cficompany.com\/es\/wp-json\/wp\/v2\/users\/19"}],"replies":[{"embeddable":true,"href":"https:\/\/cficompany.com\/es\/wp-json\/wp\/v2\/comments?post=42290"}],"version-history":[{"count":15,"href":"https:\/\/cficompany.com\/es\/wp-json\/wp\/v2\/pages\/42290\/revisions"}],"predecessor-version":[{"id":43722,"href":"https:\/\/cficompany.com\/es\/wp-json\/wp\/v2\/pages\/42290\/revisions\/43722"}],"up":[{"embeddable":true,"href":"https:\/\/cficompany.com\/es\/wp-json\/wp\/v2\/pages\/42006"}],"wp:attachment":[{"href":"https:\/\/cficompany.com\/es\/wp-json\/wp\/v2\/media?parent=42290"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}