{"id":25118,"date":"2026-11-13T05:31:34","date_gmt":"2026-11-13T05:31:34","guid":{"rendered":"https:\/\/www.mechstream.com\/?p=25118"},"modified":"2026-11-13T05:41:32","modified_gmt":"2026-11-13T05:41:32","slug":"weld-strength-calculator","status":"publish","type":"post","link":"https:\/\/www.mechstream.com\/fr\/weld-strength-calculator\/","title":{"rendered":"Calculateur de r\u00e9sistance de soudure"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">The <strong>Weld Strength Calculator<\/strong> estimates the load capacity of fillet and butt welds using weld dimensions, effective length, material strength, and applied load. Review estimated capacity and load utilization to support preliminary weld design and fabrication planning. Results depend on joint geometry, load direction, weld quality, and applicable design standards, so verify calculations with the relevant code or a qualified engineer.<\/p>\n\n\n\n<!-- Weld Strength Calculator: paste this whole block into a WordPress \"Custom HTML\" block -->\n<div class=\"wsc-weld-calculator\">\n<template>\n<style>\n  \/* ------------------------------------------------------------------\n     Theme \u2013 neutral steel palette with a blue accent.\n     All rules live inside a Shadow DOM, so they cannot affect the host page.\n     All text\/background pairs below meet WCAG AA contrast (\u2265 4.5:1).\n     ------------------------------------------------------------------ *\/\n  \/* The container element itself sits in the page, so theme rules can still match it.\n     Reset it here, then define everything on .main \u2013 an element inside the Shadow DOM\n     that no theme selector can reach. \"all:initial\" stops inherited theme styles\n     (font, colour, line-height, letter-spacing, text-transform\u2026) from leaking in. *\/\n  :host{all:initial !important;display:block !important}\n  .main{\n    all:initial;\n    display:block;\n    color:#17202b;\n    font-family:system-ui,-apple-system,\"Segoe UI\",Roboto,\"Helvetica Neue\",Arial,sans-serif;\n    line-height:1.5;\n    text-align:left;\n    --bg:#f3f5f8;\n    --card:#ffffff;\n    --ink:#17202b;\n    --steel:#3c4a5b;\n    --muted:#55606e;\n    --line:#cfd6df;\n    --line-strong:#9aa6b4;\n    --accent:#1d4ed8;        \/* blue, 6.7:1 on white *\/\n    --accent-dark:#1e40af;\n    --focus:#0b3a9e;\n    --ok-ink:#14532d;  --ok-bg:#dcfce7;  --ok-line:#86efac;\n    --warn-ink:#7c2d12; --warn-bg:#fff4e0; --warn-line:#f5b971;\n    --bad-ink:#7f1d1d; --bad-bg:#fee2e2; --bad-line:#fca5a5;\n    --radius:10px;\n    --shadow:0 1px 2px rgba(16,24,40,.06),0 4px 14px rgba(16,24,40,.06);\n    font-size:16px;\n  }\n  *,*::before,*::after{box-sizing:border-box}\n  .wrap{max-width:1180px;margin:0 auto}\n  .main{padding:4px 0 8px}\n  .layout{display:grid;grid-template-columns:1fr;gap:24px;align-items:start;max-width:900px;margin:0 auto}\n  .card{background:var(--card);border:1px solid var(--line);border-radius:var(--radius);box-shadow:var(--shadow)}\n  .card > .card-head{padding:16px 20px;border-bottom:1px solid var(--line)}\n  .card > .card-head h2{margin:0;font-size:18.4px}\n  .card > .card-body{padding:20px}\n  form fieldset.group{border:0;margin:0 0 24px;padding:0}\n  form fieldset.group > legend{\n    font-size:12.48px;font-weight:800;letter-spacing:.1em;text-transform:uppercase;color:var(--accent-dark);\n    padding:0;margin:0 0 12px;width:100%;border-bottom:1px solid var(--line);padding-bottom:6.4px;\n  }\n  .grid2{display:grid;grid-template-columns:1fr;gap:16px 20px}\n  @media (min-width:600px){.grid2{grid-template-columns:1fr 1fr}}\n  .span2{grid-column:1\/-1}\n  .field{margin:0}\n  .field > label,.field > .label,fieldset.seg-wrap > legend{\n    display:block;font-weight:650;margin:0 0 5.6px;font-size:15.2px;color:var(--ink);padding:0;\n  }\n  fieldset.seg-wrap{border:0;margin:0;padding:0;min-width:0}\n  .hint{margin:5.6px 0 0;font-size:13.44px;color:var(--muted)}\n  .msg{margin:5.6px 0 0;font-size:13.76px;font-weight:600;min-height:0}\n  .msg:empty{display:none}\n  .msg.error{color:var(--bad-ink)}\n  .msg.error::before{content:\"\u2715 \";}\n  .msg.warn{color:var(--warn-ink)}\n  .msg.warn::before{content:\"\u26a0 \";}\n  input[type=text],select{\n    font:inherit;color:var(--ink);background:#fff;border:1px solid var(--line-strong);border-radius:8px;\n    padding:9.6px 11.2px;width:100%;min-height:44px;\n  }\n  input[type=text]:focus,select:focus{outline:3px solid var(--focus);outline-offset:1px;border-color:var(--focus)}\n  input[readonly]{background:#eef1f5;color:var(--steel)}\n  input[aria-invalid=true]{border-color:#b91c1c;background:#fffafa}\n  .input-group{display:flex}\n  .input-group input{border-top-right-radius:0;border-bottom-right-radius:0;min-width:0}\n  .input-group select,.input-group .unit{\n    width:auto;flex:0 0 auto;border-top-left-radius:0;border-bottom-left-radius:0;border-left:0;background:#f4f6f9;font-weight:600;\n  }\n  .input-group .unit{\n    display:flex;align-items:center;padding:0 12.8px;border:1px solid var(--line-strong);border-left:0;border-radius:0 8px 8px 0;color:var(--steel);\n  }\n  \/* Segmented radio controls \u2013 native radios stay keyboard operable (arrow keys). *\/\n  .seg{display:flex;flex-wrap:wrap;border:1px solid var(--line-strong);border-radius:8px;overflow:hidden;background:#fff}\n  .seg input{position:absolute;opacity:0;width:1px;height:1px;margin:0}\n  .seg label{\n    flex:1 1 0;min-width:max-content;padding:9.6px 13.6px;text-align:center;cursor:pointer;font-weight:600;color:var(--steel);\n    border-right:1px solid var(--line);min-height:44px;display:flex;align-items:center;justify-content:center;font-size:15.2px;\n  }\n  .seg label:last-of-type{border-right:0}\n  .seg label:hover{background:#eef2f6}\n  .seg input:checked + label{background:var(--ink);color:#fff}\n  .seg input:focus-visible + label{outline:3px solid var(--focus);outline-offset:-3px}\n  .check{display:flex;gap:9.6px;align-items:flex-start;font-weight:600}\n  .check input{width:20px;height:20px;margin:2.4px 0 0;accent-color:var(--ink);flex:0 0 auto}\n  .check input:focus-visible{outline:3px solid var(--focus);outline-offset:2px}\n  .explain{background:#f6f8fb;border:1px solid var(--line);border-radius:8px;padding:11.2px 13.6px;font-size:14.08px;color:var(--steel);margin:0}\n  .actions{display:flex;justify-content:center;gap:12px;padding-top:20px;border-top:1px solid var(--line)}\n  button{\n    font:inherit;font-weight:700;border-radius:8px;padding:11.2px 20.8px;min-height:46px;cursor:pointer;border:1px solid transparent;\n  }\n  button:focus-visible{outline:3px solid var(--focus);outline-offset:2px}\n  .btn-primary{background:var(--accent);color:#fff;min-width:220px;font-size:16.8px}\n  .btn-primary:hover{background:var(--accent-dark)}\n  .btn-secondary{background:#fff;color:var(--ink);border-color:var(--line-strong)}\n  .btn-secondary:hover{background:#eef2f6}\n  .form-summary{margin:16px 0 0;padding:12px 16px;border-radius:8px;background:var(--bad-bg);border:1px solid var(--bad-line);color:var(--bad-ink);font-weight:600}\n  .form-summary[hidden]{display:none}\n  \/* Results panel *\/\n  .stale{margin:0 0 16px;padding:9.6px 13.6px;border-radius:8px;background:#eef2ff;border:1px solid #c7d2fe;color:#1e3a8a;font-size:14.4px;font-weight:600}\n  .headline{border-radius:8px;background:#17202b;color:#fff;padding:17.6px 19.2px;margin-bottom:16px}\n  .headline .k{margin:0;font-size:13.6px;letter-spacing:.02em;color:#bfdbfe;font-weight:700}\n  .headline .v{margin:3.2px 0 1.6px;font-size:clamp(28.8px,4vw,38.4px);font-weight:800;line-height:1.15;font-variant-numeric:tabular-nums}\n  .headline .v small{font-size:16px;font-weight:700;color:#dfe5ec;margin-left:4px}\n  .headline .s{margin:0;font-size:13.76px;color:#dfe5ec}\n  .util{border:1px solid var(--line);border-radius:8px;padding:16px;margin-bottom:16px}\n  .util-top{display:flex;justify-content:space-between;align-items:baseline;gap:16px;flex-wrap:wrap}\n  .util-top .pct{font-size:28.8px;font-weight:800;font-variant-numeric:tabular-nums}\n  .meter{position:relative;height:14px;border-radius:7px;background:#e7ebf0;overflow:hidden;margin:9.6px 0 4.8px}\n  .meter > span{position:absolute;left:0;top:0;bottom:0;border-radius:7px}\n  .meter .tick{position:absolute;top:0;bottom:0;width:2px;background:var(--ink);opacity:.55}\n  .meter-scale{display:flex;justify-content:space-between;font-size:12px;color:var(--muted)}\n  .badge{display:inline-flex;align-items:center;gap:6.4px;padding:5.6px 11.2px;border-radius:999px;font-weight:700;font-size:14.4px;border:1px solid}\n  .badge.ok{background:var(--ok-bg);color:var(--ok-ink);border-color:var(--ok-line)}\n  .badge.near{background:var(--warn-bg);color:var(--warn-ink);border-color:var(--warn-line)}\n  .badge.bad{background:var(--bad-bg);color:var(--bad-ink);border-color:var(--bad-line)}\n  .fill-ok{background:#15803d}.fill-near{background:#b45309}.fill-bad{background:#b91c1c}\n  table.kv{width:100%;border-collapse:collapse;font-size:14.4px;margin-bottom:16px}\n  table.kv caption{text-align:left;font-weight:800;font-size:12.48px;letter-spacing:.1em;text-transform:uppercase;color:var(--accent-dark);padding:0 0 6.4px}\n  table.kv th,table.kv td{padding:8px 6.4px;border-bottom:1px solid var(--line);vertical-align:top;text-align:left}\n  table.kv th{font-weight:600;color:var(--steel);width:46%}\n  table.kv td{font-variant-numeric:tabular-nums}\n  table.kv td .f{display:block;font-size:12.8px;color:var(--muted)}\n  .res-list h3{font-size:12.48px;font-weight:800;letter-spacing:.1em;text-transform:uppercase;margin:16px 0 6.4px;color:var(--accent-dark)}\n  .res-list ul{margin:0;padding-left:18.4px;font-size:14.08px;color:var(--steel)}\n  .res-list li{margin:4px 0}\n  .res-list.warns ul{color:var(--warn-ink)}\n  .disclaimer-sm{font-size:13.12px;color:var(--muted);border-top:1px solid var(--line);padding-top:12px;margin:16px 0 0}\n  [hidden]{display:none !important}\n  .sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}\n  @media (prefers-reduced-motion:no-preference){button,.seg label{transition:background-color .15s ease}}\n<\/style>\n<div class=\"main\">\n  <div class=\"wrap\">\n    <div class=\"layout\">\n      <!-- ========================= INPUT FORM ========================= -->\n      <section class=\"card\" aria-labelledby=\"inputs-title\">\n        <div class=\"card-head\"><h2 id=\"inputs-title\">Inputs<\/h2><\/div>\n        <div class=\"card-body\">\n          <form id=\"calc-form\" novalidate>\n            <fieldset class=\"group\">\n              <legend>Calculation<\/legend>\n              <div class=\"grid2\">\n                <fieldset class=\"seg-wrap span2\">\n                  <legend>What do you want to calculate?<\/legend>\n                  <div class=\"seg\">\n                    <input type=\"radio\" id=\"mode-capacity\" name=\"mode\" value=\"capacity\" checked>\n                    <label for=\"mode-capacity\">Estimated weld capacity<\/label>\n                    <input type=\"radio\" id=\"mode-util\" name=\"mode\" value=\"utilization\">\n                    <label for=\"mode-util\">Utilization of an applied load<\/label>\n                  <\/div>\n                <\/fieldset>\n                <fieldset class=\"seg-wrap span2\">\n                  <legend>Weld type<\/legend>\n                  <div class=\"seg\">\n                    <input type=\"radio\" id=\"wt-fillet\" name=\"weldType\" value=\"fillet\" checked>\n                    <label for=\"wt-fillet\">Fillet weld<\/label>\n                    <input type=\"radio\" id=\"wt-butt\" name=\"weldType\" value=\"butt\">\n                    <label for=\"wt-butt\">Butt weld (groove weld)<\/label>\n                  <\/div>\n                <\/fieldset>\n              <\/div>\n            <\/fieldset>\n            <fieldset class=\"group\">\n              <legend>Weld geometry<\/legend>\n              <div class=\"grid2\">\n                <!-- Butt weld only -->\n                <div class=\"field span2\" id=\"row-penetration\" hidden>\n                  <label for=\"penetration\">Joint penetration<\/label>\n                  <select id=\"penetration\" aria-describedby=\"penetration-hint\">\n                    <option value=\"pjp\">Partial joint penetration (PJP) \u2013 enter effective throat<\/option>\n                    <option value=\"cjp\">Complete joint penetration (CJP) \u2013 full thickness<\/option>\n                  <\/select>\n                  <p class=\"hint\" id=\"penetration-hint\">Full penetration is never assumed. Choose CJP only if the joint is designed, welded and inspected as complete-penetration.<\/p>\n                <\/div>\n                <fieldset class=\"seg-wrap span2\" id=\"row-areaInput\" hidden>\n                  <legend>How will you define the weld area?<\/legend>\n                  <div class=\"seg\">\n                    <input type=\"radio\" id=\"ai-dims\" name=\"areaInput\" value=\"dims\" checked>\n                    <label for=\"ai-dims\">From weld dimensions<\/label>\n                    <input type=\"radio\" id=\"ai-area\" name=\"areaInput\" value=\"area\">\n                    <label for=\"ai-area\">Enter effective area directly<\/label>\n                  <\/div>\n                <\/fieldset>\n                <!-- Fillet weld only -->\n                <fieldset class=\"seg-wrap span2\" id=\"row-sizeKind\">\n                  <legend>Fillet weld size is given as<\/legend>\n                  <div class=\"seg\">\n                    <input type=\"radio\" id=\"sk-leg\" name=\"sizeKind\" value=\"leg\" checked>\n                    <label for=\"sk-leg\">Leg size (w)<\/label>\n                    <input type=\"radio\" id=\"sk-throat\" name=\"sizeKind\" value=\"throat\">\n                    <label for=\"sk-throat\">Effective throat (a)<\/label>\n                  <\/div>\n                <\/fieldset>\n                <div class=\"field\" id=\"row-size\">\n                  <label for=\"size\" id=\"size-label\">Weld leg size (w)<\/label>\n                  <div class=\"input-group\">\n                    <input type=\"text\" id=\"size\" inputmode=\"decimal\" autocomplete=\"off\" aria-describedby=\"size-hint size-msg\">\n                    <select id=\"sizeUnit\" aria-label=\"Weld size unit\">\n                      <option value=\"mm\">mm<\/option>\n                      <option value=\"in\">in<\/option>\n                    <\/select>\n                  <\/div>\n                  <p class=\"hint\" id=\"size-hint\">Effective throat = 0.707 \u00d7 leg (equal-leg, 90\u00b0 fillet).<\/p>\n                  <p class=\"msg\" id=\"size-msg\"><\/p>\n                <\/div>\n                <div class=\"field\" id=\"row-length\">\n                  <label for=\"length\">Effective length per weld line<\/label>\n                  <div class=\"input-group\">\n                    <input type=\"text\" id=\"length\" inputmode=\"decimal\" autocomplete=\"off\" aria-describedby=\"length-hint length-msg\">\n                    <select id=\"lengthUnit\" aria-label=\"Weld length unit\">\n                      <option value=\"mm\">mm<\/option>\n                      <option value=\"in\">in<\/option>\n                    <\/select>\n                  <\/div>\n                  <p class=\"hint\" id=\"length-hint\">Exclude end craters \/ run-off; use the effective length only.<\/p>\n                  <p class=\"msg\" id=\"length-msg\"><\/p>\n                <\/div>\n                <div class=\"field\" id=\"row-config\">\n                  <label for=\"config\">Weld configuration<\/label>\n                  <select id=\"config\" aria-describedby=\"config-explain\">\n                    <option value=\"single\">Single weld<\/option>\n                    <option value=\"parallel\">Parallel welds<\/option>\n                    <option value=\"group\">User-defined weld group<\/option>\n                  <\/select>\n                <\/div>\n                <div class=\"field\" id=\"row-lines\">\n                  <label for=\"lines\">Number of weld lines<\/label>\n                  <input type=\"text\" id=\"lines\" inputmode=\"numeric\" autocomplete=\"off\" value=\"1\" aria-describedby=\"lines-msg\">\n                  <p class=\"msg\" id=\"lines-msg\"><\/p>\n                <\/div>\n                <p class=\"explain span2\" id=\"config-explain\" aria-live=\"polite\"><\/p>\n                <!-- Butt weld, direct area -->\n                <div class=\"field span2\" id=\"row-area\" hidden>\n                  <label for=\"area\">Total effective weld area<\/label>\n                  <div class=\"input-group\">\n                    <input type=\"text\" id=\"area\" inputmode=\"decimal\" autocomplete=\"off\" aria-describedby=\"area-hint area-msg\">\n                    <select id=\"areaUnit\" aria-label=\"Area unit\">\n                      <option value=\"mm2\">mm\u00b2<\/option>\n                      <option value=\"in2\">in\u00b2<\/option>\n                    <\/select>\n                  <\/div>\n                  <p class=\"hint\" id=\"area-hint\">Effective throat \u00d7 effective length, summed over all weld lines, as defined by your design method.<\/p>\n                  <p class=\"msg\" id=\"area-msg\"><\/p>\n                <\/div>\n              <\/div>\n            <\/fieldset>\n            <fieldset class=\"group\">\n              <legend>Material &amp; stress basis<\/legend>\n              <div class=\"grid2\">\n                <div class=\"field span2\">\n                  <label for=\"method\">Stress basis \/ design method<\/label>\n                  <select id=\"method\" aria-describedby=\"method-hint\">\n                    <option value=\"aisc_lrfd\">AISC 360 \u2013 LRFD design strength (\u03c6Rn)<\/option>\n                    <option value=\"aisc_asd\">AISC 360 \u2013 ASD allowable strength (Rn\/\u03a9)<\/option>\n                    <option value=\"ec3\">EN 1993-1-8 \u2013 simplified method (Fw,Rd)<\/option>\n                    <option value=\"custom\">User-defined stress coefficient (k \u00d7 strength)<\/option>\n                  <\/select>\n                  <p class=\"hint\" id=\"method-hint\"><\/p>\n                <\/div>\n                <div class=\"field\">\n                  <label for=\"strength\" id=\"strength-label\">Weld metal \/ electrode tensile strength (F<sub>EXX<\/sub>)<\/label>\n                  <div class=\"input-group\">\n                    <input type=\"text\" id=\"strength\" inputmode=\"decimal\" autocomplete=\"off\" aria-describedby=\"strength-hint strength-msg\">\n                    <select id=\"strengthUnit\" aria-label=\"Strength unit\">\n                      <option value=\"MPa\">MPa<\/option>\n                      <option value=\"ksi\">ksi<\/option>\n                    <\/select>\n                  <\/div>\n                  <p class=\"hint\" id=\"strength-hint\"><\/p>\n                  <p class=\"msg\" id=\"strength-msg\"><\/p>\n                <\/div>\n                <div class=\"field\" id=\"row-baseFy\" hidden>\n                  <label for=\"baseFy\">Base metal yield strength (F<sub>y<\/sub>)<\/label>\n                  <div class=\"input-group\">\n                    <input type=\"text\" id=\"baseFy\" inputmode=\"decimal\" autocomplete=\"off\" aria-describedby=\"baseFy-hint baseFy-msg\">\n                    <span class=\"unit js-strength-unit\" aria-hidden=\"true\">MPa<\/span>\n                  <\/div>\n                  <p class=\"hint\" id=\"baseFy-hint\">CJP joints with matching filler are governed by the base metal. Use the weaker connected part.<\/p>\n                  <p class=\"msg\" id=\"baseFy-msg\"><\/p>\n                <\/div>\n                <div class=\"field\" id=\"row-betaW\" hidden>\n                  <label for=\"betaW\">Correlation factor \u03b2<sub>w<\/sub> (steel grade)<\/label>\n                  <select id=\"betaW\" aria-describedby=\"betaW-hint\">\n                    <option value=\"0.80\">S235 \u2013 \u03b2w = 0.80<\/option>\n                    <option value=\"0.85\">S275 \u2013 \u03b2w = 0.85<\/option>\n                    <option value=\"0.90\" selected>S355 \u2013 \u03b2w = 0.90<\/option>\n                    <option value=\"1.00\">S420 \/ S460 \u2013 \u03b2w = 1.00<\/option>\n                  <\/select>\n                  <p class=\"hint\" id=\"betaW-hint\">EN 1993-1-8 Table 4.1, for the weaker connected part.<\/p>\n                <\/div>\n                <div class=\"field\" id=\"row-customK\" hidden>\n                  <label for=\"customK\">Stress coefficient k<\/label>\n                  <input type=\"text\" id=\"customK\" inputmode=\"decimal\" autocomplete=\"off\" value=\"0.30\" aria-describedby=\"customK-hint customK-msg\">\n                  <p class=\"hint\" id=\"customK-hint\">Design stress = k \u00d7 entered strength. Example: 0.30 reproduces the traditional allowable shear stress 0.30\u00b7F<sub>EXX<\/sub> on the fillet throat.<\/p>\n                  <p class=\"msg\" id=\"customK-msg\"><\/p>\n                <\/div>\n              <\/div>\n            <\/fieldset>\n            <fieldset class=\"group\">\n              <legend>Loading<\/legend>\n              <div class=\"grid2\">\n                <div class=\"field\">\n                  <label for=\"direction\">Load direction<\/label>\n                  <select id=\"direction\" aria-describedby=\"direction-hint\">\n                    <option value=\"parallel\">Parallel to weld axis (longitudinal \/ shear)<\/option>\n                    <option value=\"transverse\">Transverse to weld axis<\/option>\n                    <option value=\"custom\">Custom angle<\/option>\n                  <\/select>\n                  <p class=\"hint\" id=\"direction-hint\">Angle \u03b8 is measured between the line of action of the load and the weld longitudinal axis.<\/p>\n                <\/div>\n                <div class=\"field\" id=\"row-angle\" hidden>\n                  <label for=\"angle\">Load angle \u03b8<\/label>\n                  <div class=\"input-group\">\n                    <input type=\"text\" id=\"angle\" inputmode=\"decimal\" autocomplete=\"off\" value=\"45\" aria-describedby=\"angle-msg\">\n                    <span class=\"unit\" aria-hidden=\"true\">degrees<\/span>\n                  <\/div>\n                  <p class=\"msg\" id=\"angle-msg\"><\/p>\n                <\/div>\n                <div class=\"field span2\" id=\"row-applyDir\">\n                  <label class=\"check\" for=\"applyDir\">\n                    <input type=\"checkbox\" id=\"applyDir\" aria-describedby=\"applyDir-hint\">\n                    <span>Apply AISC directional strength increase (1.0 + 0.50 sin<sup>1.5<\/sup>\u03b8)<\/span>\n                  <\/label>\n                  <p class=\"hint\" id=\"applyDir-hint\">Only valid for linear fillet welds, or groups where every element has the same orientation, loaded in-plane through the centre of gravity. Leave off for a conservative estimate.<\/p>\n                <\/div>\n                <div class=\"field\">\n                  <label for=\"forceUnit\">Force unit for results<\/label>\n                  <select id=\"forceUnit\">\n                    <option value=\"N\">N<\/option>\n                    <option value=\"kN\" selected>kN<\/option>\n                    <option value=\"lbf\">lbf<\/option>\n                    <option value=\"kip\">kip<\/option>\n                  <\/select>\n                <\/div>\n                <div class=\"field\" id=\"row-load\" hidden>\n                  <label for=\"load\">Applied load<\/label>\n                  <div class=\"input-group\">\n                    <input type=\"text\" id=\"load\" inputmode=\"decimal\" autocomplete=\"off\" aria-describedby=\"load-hint load-msg\">\n                    <span class=\"unit js-force-unit\" aria-hidden=\"true\">kN<\/span>\n                  <\/div>\n                  <p class=\"hint\" id=\"load-hint\">Use the same load basis as the method (factored for LRFD \/ EN 1993, service for ASD).<\/p>\n                  <p class=\"msg\" id=\"load-msg\"><\/p>\n                <\/div>\n                <div class=\"field\">\n                  <label for=\"factor\">Additional safety \/ design factor <span style=\"font-weight:400;color:var(--muted)\">(optional)<\/span><\/label>\n                  <input type=\"text\" id=\"factor\" inputmode=\"decimal\" autocomplete=\"off\" placeholder=\"1.00\" aria-describedby=\"factor-hint factor-msg\">\n                  <p class=\"hint\" id=\"factor-hint\">Capacity is divided by this factor. Leave blank for 1.00.<\/p>\n                  <p class=\"msg\" id=\"factor-msg\"><\/p>\n                <\/div>\n              <\/div>\n            <\/fieldset>\n            <div class=\"actions\">\n              <button type=\"submit\" class=\"btn-primary\" id=\"btn-calc\">Calculate<\/button>\n            <\/div>\n            <p class=\"form-summary\" id=\"form-summary\" role=\"alert\" hidden><\/p>\n          <\/form>\n        <\/div>\n      <\/section>\n      <!-- ========================= RESULTS ========================= -->\n      <div class=\"results-col\" id=\"results-col\" hidden>\n        <section class=\"card\" aria-labelledby=\"results-title\">\n          <div class=\"card-head\"><h2 id=\"results-title\">Results<\/h2><\/div>\n          <div class=\"card-body\" id=\"results\" aria-live=\"polite\"><\/div>\n        <\/section>\n      <\/div>\n    <\/div>\n  <\/div>\n<\/div>\n<\/template>\n<\/div>\n<script>\n(function () {\n\"use strict\";\n\/* =====================================================================\n   CORE CALCULATION ENGINE (no DOM access)\n   ---------------------------------------------------------------------\n   Internal units are consistent SI: length in mm, stress in MPa (N\/mm\u00b2),\n   area in mm\u00b2, force in N.  MPa \u00d7 mm\u00b2 = N, so no extra factor is needed.\n   All design assumptions live in CONFIG and can be edited.\n   ===================================================================== *\/\nconst CONFIG = {\n  \/* Effective throat of an equal-leg fillet weld with a 90\u00b0 root:\n     a = w \u00b7 sin(45\u00b0) = 0.707 \u00b7 w.  Edit for unequal legs or skewed joints. *\/\n  FILLET_THROAT_FACTOR: 0.707,\n  \/* Unit conversions to internal units. *\/\n  UNITS: {\n    MM_PER_IN: 25.4,               \/\/ 1 in  = 25.4 mm (exact)\n    MM2_PER_IN2: 645.16,           \/\/ 1 in\u00b2 = 645.16 mm\u00b2 (exact)\n    MPA_PER_KSI: 6.894757,         \/\/ 1 ksi = 6.894757 MPa\n    N_PER: { N: 1, kN: 1000, lbf: 4.4482216, kip: 4448.2216 } \/\/ force \u2192 N\n  },\n  \/* Stress basis definitions.  \"coef\" multiplies the strength (FEXX or Fy).\n     LRFD uses a resistance factor \u03c6 (multiply); ASD uses a safety factor \u03a9 (divide). *\/\n  METHODS: {\n    aisc_lrfd: {\n      label: \"AISC 360 \u2013 LRFD\",\n      capacityLabel: \"Design strength \u03c6Rn\",\n      compareWith: \"factored (LRFD) loads\",\n      fillet: { coef: 0.60, phi: 0.75 },\n      pjp: { tension: { coef: 0.60, phi: 0.80 }, shear: { coef: 0.60, phi: 0.75 } },\n      cjp: { tension: { coef: 1.00, phi: 0.90 }, shear: { coef: 0.60, phi: 1.00 } } \/\/ on base metal Fy\n    },\n    aisc_asd: {\n      label: \"AISC 360 \u2013 ASD\",\n      capacityLabel: \"Allowable strength Rn\/\u03a9\",\n      compareWith: \"service (ASD) load combinations\",\n      fillet: { coef: 0.60, omega: 2.00 },\n      pjp: { tension: { coef: 0.60, omega: 1.88 }, shear: { coef: 0.60, omega: 2.00 } },\n      cjp: { tension: { coef: 1.00, omega: 1.67 }, shear: { coef: 0.60, omega: 1.50 } } \/\/ on base metal Fy\n    },\n    ec3: {\n      label: \"EN 1993-1-8 \u2013 simplified method\",\n      capacityLabel: \"Design resistance Fw,Rd\",\n      compareWith: \"ULS design loads\",\n      gammaM2: 1.25,   \/\/ partial factor for welds\n      gammaM0: 1.00    \/\/ partial factor for cross-section resistance (base metal)\n    },\n    custom: {\n      label: \"User-defined coefficient\",\n      capacityLabel: \"Estimated capacity\",\n      compareWith: \"loads on the same basis as your coefficient k\"\n    }\n  },\n  \/* AISC 360 Eq. J2-5 directional strength increase for fillet welds. *\/\n  AISC_DIRECTIONAL: { base: 1.0, coef: 0.50, exp: 1.5 },\n  \/* Practical ranges (internal units).  Values outside trigger a warning only;\n     inputs are never clamped. *\/\n  RANGES: {\n    filletLeg:   [3, 25],       \/\/ mm\n    throat:      [2, 50],       \/\/ mm (fillet throat entered directly, PJP throat)\n    cjpThick:    [3, 100],      \/\/ mm\n    length:      [10, 3000],    \/\/ mm per line\n    lines:       [1, 12],\n    area:        [10, 500000],  \/\/ mm\u00b2\n    strength:    [340, 900],    \/\/ MPa (E60 \u2248 414, E70 \u2248 482, E80 \u2248 551 MPa)\n    baseFy:      [185, 700],    \/\/ MPa\n    customK:     [0.10, 0.60],\n    factor:      [1.0, 5.0]\n  },\n  \/* Utilization status thresholds (%). *\/\n  STATUS: { nearLimit: 90, limit: 100 },\n  \/* Display precision. *\/\n  FORCE_DECIMALS: { N: 0, kN: 2, lbf: 0, kip: 2 }\n};\n\/* ---- Unit conversions (display unit \u21c4 internal unit) ---- *\/\nconst U = CONFIG.UNITS;\nconst toMM    = (v, u) => u === \"in\"  ? v * U.MM_PER_IN   : v;\nconst fromMM  = (v, u) => u === \"in\"  ? v \/ U.MM_PER_IN   : v;\nconst toMM2   = (v, u) => u === \"in2\" ? v * U.MM2_PER_IN2 : v;\nconst fromMM2 = (v, u) => u === \"in2\" ? v \/ U.MM2_PER_IN2 : v;\nconst toMPa   = (v, u) => u === \"ksi\" ? v * U.MPA_PER_KSI : v;\nconst fromMPa = (v, u) => u === \"ksi\" ? v \/ U.MPA_PER_KSI : v;\nconst toN     = (v, u) => v * U.N_PER[u];\nconst fromN   = (v, u) => v \/ U.N_PER[u];\n\/* Load action on a butt weld from the selected direction. *\/\nfunction buttAction(direction) {\n  if (direction === \"parallel\") return \"shear\";\n  if (direction === \"transverse\") return \"tension\";\n  return \"governing\"; \/\/ custom angle \u2192 lower of the two (conservative)\n}\n\/* Resolves the design \/ allowable stress (MPa) for the selected method.\n   Returns { stress, formula, factors, strengthSource, notes[] }. *\/\nfunction getStressBasis(inp) {\n  const notes = [];\n  const m = CONFIG.METHODS[inp.method];\n  const theta = inp.direction === \"parallel\" ? 0 : inp.direction === \"transverse\" ? 90 : inp.angleDeg;\n  const isFillet = inp.weldType === \"fillet\";\n  const isCJP = !isFillet && inp.penetration === \"cjp\";\n  const out = {\n    theta, methodLabel: m.label, capacityLabel: m.capacityLabel, compareWith: m.compareWith,\n    strengthSource: \"weld\", stress: NaN, formula: \"\", factors: \"\", notes\n  };\n  \/* --- User-defined: stress = k \u00d7 entered strength --- *\/\n  if (inp.method === \"custom\") {\n    out.stress = inp.customK * inp.strength;\n    out.formula = \"k \u00d7 entered strength\";\n    out.factors = \"k = \" + inp.customK;\n    notes.push(\"Stress basis is user-defined. The calculator does not check that k matches any design code.\");\n    if (isCJP) notes.push(\"CJP: k is applied to the entered strength. Check the base metal capacity separately.\");\n    return out;\n  }\n  \/* --- EN 1993-1-8 --- *\/\n  if (inp.method === \"ec3\") {\n    if (!isCJP) {\n      \/\/ Simplified method \u00a74.5.3.3: fvw,d = fu \/ (\u221a3 \u00b7 \u03b2w \u00b7 \u03b3M2)\n      out.stress = inp.strength \/ (Math.sqrt(3) * inp.betaW * m.gammaM2);\n      out.formula = \"fu \/ (\u221a3 \u00d7 \u03b2w \u00d7 \u03b3M2)\";\n      out.factors = \"\u03b2w = \" + inp.betaW.toFixed(2) + \", \u03b3M2 = \" + m.gammaM2.toFixed(2);\n      notes.push(\"EN 1993-1-8 simplified method: resistance is independent of load direction. This is conservative; the directional method can give a higher value.\");\n      notes.push(\"fu should be the nominal ultimate tensile strength of the weaker connected part, with \u03b2w matching that steel grade.\");\n      if (!isFillet) notes.push(\"PJP butt weld treated as a deep-penetration fillet weld (EN 1993-1-8 \u00a74.7.2).\");\n      return out;\n    }\n    \/\/ Full-penetration butt weld: resistance of the weaker connected part (\u00a74.7.1)\n    out.strengthSource = \"base\";\n    const t = inp.baseFy \/ m.gammaM0, s = inp.baseFy \/ (Math.sqrt(3) * m.gammaM0);\n    const a = buttAction(inp.direction);\n    if (a === \"tension\") { out.stress = t; out.formula = \"fy \/ \u03b3M0 (normal stress)\"; }\n    else if (a === \"shear\") { out.stress = s; out.formula = \"fy \/ (\u221a3 \u00d7 \u03b3M0) (shear)\"; }\n    else { out.stress = Math.min(t, s); out.formula = \"min[ fy\/\u03b3M0 , fy\/(\u221a3\u00b7\u03b3M0) ]\"; notes.push(\"Custom angle: the lower of the normal and shear resistances is used (conservative). Combined stress interaction is not evaluated.\"); }\n    out.factors = \"\u03b3M0 = \" + m.gammaM0.toFixed(2);\n    notes.push(\"Full-penetration butt weld: assumes matching (overmatching) filler metal, so resistance equals the weaker connected part (EN 1993-1-8 \u00a74.7.1).\");\n    return out;\n  }\n  \/* --- AISC 360 (LRFD or ASD) --- *\/\n  const isLRFD = inp.method === \"aisc_lrfd\";\n  const rf = c => (isLRFD ? c.phi : 1 \/ c.omega);                 \/\/ resistance multiplier\n  const rfText = c => (isLRFD ? \"\u03c6 = \" + c.phi.toFixed(2) : \"\u03a9 = \" + c.omega.toFixed(2));\n  const wrap = (core, c) => (isLRFD ? \"\u03c6 \u00d7 \" + core : core + \" \u00f7 \u03a9\");\n  if (isFillet) {\n    const c = m.fillet;\n    let kds = 1;\n    if (inp.applyDir) {\n      const d = CONFIG.AISC_DIRECTIONAL;\n      kds = d.base + d.coef * Math.pow(Math.sin(theta * Math.PI \/ 180), d.exp);\n    }\n    out.stress = rf(c) * c.coef * inp.strength * kds;\n    out.formula = wrap(\"0.60 \u00d7 FEXX\" + (inp.applyDir ? \" \u00d7 kds\" : \"\"), c);\n    out.factors = rfText(c) + (inp.applyDir ? \", kds = \" + kds.toFixed(3) + \" (\u03b8 = \" + round2(theta) + \"\u00b0)\" : \"\");\n    out.kds = kds;\n    if (inp.applyDir) notes.push(\"Directional increase (AISC Eq. J2-5) applied. Valid only for linear welds or same-orientation groups loaded in-plane through the centroid. Groups that mix longitudinal and transverse welds need AISC Eq. J2-6 (not implemented).\");\n    else notes.push(\"AISC directional strength increase not applied: the fillet is rated as if loaded longitudinally (conservative).\");\n    notes.push(\"Base metal strength at the weld (AISC J4 shear yielding \/ rupture) is not checked.\");\n    return out;\n  }\n  if (!isCJP) {\n    \/\/ PJP groove weld \u2013 AISC Table J2.5, on effective throat\n    const a = buttAction(inp.direction);\n    const ct = m.pjp.tension, cs = m.pjp.shear;\n    const t = rf(ct) * ct.coef * inp.strength, s = rf(cs) * cs.coef * inp.strength;\n    if (a === \"tension\") { out.stress = t; out.formula = wrap(\"0.60 \u00d7 FEXX\", ct) + \" (tension normal to axis)\"; out.factors = rfText(ct); }\n    else if (a === \"shear\") { out.stress = s; out.formula = wrap(\"0.60 \u00d7 FEXX\", cs) + \" (shear)\"; out.factors = rfText(cs); }\n    else {\n      const useT = t <= s;\n      out.stress = Math.min(t, s);\n      out.formula = \"lower of tension-normal and shear values\";\n      out.factors = rfText(useT ? ct : cs);\n      notes.push(\"Custom angle: the lower of the tension-normal and shear values is used (conservative). Combined stress interaction is not evaluated.\");\n    }\n    notes.push(\"PJP groove weld per AISC Table J2.5. Base metal strength (AISC J4) must also be checked. Compression normal to the axis is conservatively taken as tension.\");\n    return out;\n  }\n  \/\/ CJP groove weld \u2013 strength governed by base metal (AISC Table J2.5 \u2192 J4)\n  out.strengthSource = \"base\";\n  const a = buttAction(inp.direction);\n  const ct = m.cjp.tension, cs = m.cjp.shear;\n  const t = rf(ct) * ct.coef * inp.baseFy, s = rf(cs) * cs.coef * inp.baseFy;\n  if (a === \"tension\") { out.stress = t; out.formula = wrap(\"Fy\", ct) + \" (tensile yielding)\"; out.factors = rfText(ct); }\n  else if (a === \"shear\") { out.stress = s; out.formula = wrap(\"0.60 \u00d7 Fy\", cs) + \" (shear yielding)\"; out.factors = rfText(cs); }\n  else {\n    const useT = t <= s;\n    out.stress = Math.min(t, s);\n    out.formula = \"lower of tension and shear yielding\";\n    out.factors = rfText(useT ? ct : cs);\n    notes.push(\"Custom angle: the lower of the tension and shear values is used (conservative). Combined stress interaction is not evaluated.\");\n  }\n  notes.push(\"CJP groove weld with matching filler metal: strength is governed by the base metal (AISC Table J2.5 \/ J4). Rupture limit states are not checked.\");\n  return out;\n}\n\/* Main calculation.  inp values are already in internal units. *\/\nfunction computeWeld(inp) {\n  let throat = null, totalLength = null, area;\n  if (inp.weldType === \"butt\" &#038;&#038; inp.areaInput === \"area\") {\n    area = inp.area;                                     \/\/ entered directly\n  } else {\n    \/\/ Effective throat: fillet leg \u00d7 0.707, otherwise the entered throat \/ CJP thickness\n    throat = (inp.weldType === \"fillet\" &#038;&#038; inp.sizeKind === \"leg\")\n      ? CONFIG.FILLET_THROAT_FACTOR * inp.size\n      : inp.size;\n    totalLength = inp.length * inp.lines;                \/\/ all lines identical\n    area = throat * totalLength;\n  }\n  const basis = getStressBasis(inp);\n  const basisCapacity = area * basis.stress;             \/\/ mm\u00b2 \u00d7 MPa = N\n  const capacity = basisCapacity \/ inp.factor;           \/\/ optional extra factor\n  const utilization = inp.mode === \"utilization\" ? (inp.load \/ capacity) * 100 : null;\n  return { throat, totalLength, area, basis, basisCapacity, capacity, utilization };\n}\nfunction round2(n) { return Math.round(n * 100) \/ 100; }\n\/* ===================== END OF CORE ENGINE ===================== *\/\n\/* =====================================================================\n   USER INTERFACE \u2013 one instance per container.  The calculator is\n   rendered inside a Shadow DOM so its CSS, IDs and markup are fully\n   isolated from the WordPress theme and plugins (in both directions).\n   ===================================================================== *\/\nfunction initCalculator(host) {\n  if (host.shadowRoot || host.dataset.wscReady) return;\n  const tpl = host.querySelector(\"template\");\n  if (!tpl) return;\n  host.dataset.wscReady = \"1\";\n  const root = host.attachShadow({ mode: \"open\" });\n  root.appendChild(tpl.content.cloneNode(true));\n  tpl.remove();\n  const $ = id => root.getElementById(id);\n  const radio = name => root.querySelector('input[name=\"' + name + '\"]:checked').value;\n  const isShown = id => !$(id).closest(\"[hidden]\");\n  const NUM_RE = \/^[+-]?(\\d+\\.?\\d*|\\.\\d+)([eE][+-]?\\d+)?$\/;\n  const NUMERIC_IDS = [\"size\", \"length\", \"lines\", \"area\", \"strength\", \"baseFy\", \"customK\", \"angle\", \"load\", \"factor\"];\n  let hasResult = false;\n  function fmt(n, d) {\n    return Number(n).toLocaleString(\"en-US\", { minimumFractionDigits: d, maximumFractionDigits: d });\n  }\n  function fmtForce(N, unit) { return fmt(fromN(N, unit), CONFIG.FORCE_DECIMALS[unit]); }\n  function lenDec() { return 2; } \/\/ dimensions shown to two decimals\n  \/* Show\/hide fields and update labels for the current selections. *\/\n  function updateUI() {\n    const mode = radio(\"mode\"), wt = radio(\"weldType\");\n    const fillet = wt === \"fillet\";\n    const pen = $(\"penetration\").value;\n    const direct = !fillet && radio(\"areaInput\") === \"area\";\n    const method = $(\"method\").value;\n    const cjp = !fillet && pen === \"cjp\";\n    $(\"row-penetration\").hidden = fillet;\n    $(\"row-areaInput\").hidden = fillet;\n    $(\"row-sizeKind\").hidden = !fillet;\n    [\"row-size\", \"row-length\", \"row-config\", \"row-lines\", \"config-explain\"].forEach(id => { $(id).hidden = direct; });\n    $(\"row-area\").hidden = !direct;\n    \/\/ Size label depends on weld type \/ penetration\n    let lbl, hint;\n    if (fillet && radio(\"sizeKind\") === \"leg\") { lbl = \"Weld leg size (w)\"; hint = \"Effective throat = 0.707 \u00d7 leg (equal-leg, 90\u00b0 fillet).\"; }\n    else if (fillet) { lbl = \"Effective throat (a)\"; hint = \"Throat entered directly; no 0.707 factor is applied.\"; }\n    else if (cjp) { lbl = \"Thickness of thinner connected part (t)\"; hint = \"For CJP, the effective throat equals the thinner part's thickness.\"; }\n    else { lbl = \"Effective throat (E), PJP\"; hint = \"Use the effective throat for your groove type, welding process and position (e.g. AISC Table J2.1).\"; }\n    $(\"size-label\").textContent = lbl;\n    $(\"size-hint\").textContent = hint;\n    \/\/ Method-specific fields\n    $(\"row-customK\").hidden = method !== \"custom\";\n    $(\"row-betaW\").hidden = !(method === \"ec3\" && !cjp);\n    $(\"row-baseFy\").hidden = !(cjp && method !== \"custom\");\n    $(\"row-applyDir\").hidden = !(fillet && (method === \"aisc_lrfd\" || method === \"aisc_asd\"));\n    const mh = {\n      aisc_lrfd: \"Design strength = \u03c6 \u00d7 nominal strength. Compare with factored loads.\",\n      aisc_asd: \"Allowable strength = nominal strength \u00f7 \u03a9. Compare with service loads.\",\n      ec3: \"Design resistance with partial factors \u03b3M2 \/ \u03b3M0. Compare with ULS design loads.\",\n      custom: \"You define the design stress as a fraction k of the entered strength.\"\n    };\n    $(\"method-hint\").textContent = mh[method];\n    const sh = {\n      aisc_lrfd: \"Classification strength FEXX, e.g. E70 = 70 ksi \u2248 482 MPa.\",\n      aisc_asd: \"Classification strength FEXX, e.g. E70 = 70 ksi \u2248 482 MPa.\",\n      ec3: \"EN 1993-1-8 uses fu of the weaker connected part (e.g. S355: 470\u2013510 MPa).\",\n      custom: \"The strength that your coefficient k multiplies.\"\n    };\n    $(\"strength-label\").innerHTML = method === \"ec3\"\n      ? \"Ultimate tensile strength f<sub>u<\/sub> (weaker part)\"\n      : \"Weld metal \/ electrode tensile strength (F<sub>EXX<\/sub>)\";\n    let sHint = sh[method];\n    if (cjp && method !== \"custom\") sHint += \" For CJP it is reported for reference; the base metal governs.\";\n    $(\"strength-hint\").textContent = sHint;\n    $(\"row-angle\").hidden = $(\"direction\").value !== \"custom\";\n    $(\"row-load\").hidden = mode !== \"utilization\";\n    \/\/ Weld configuration \u2194 number of lines\n    const cfg = $(\"config\").value, lines = $(\"lines\");\n    if (cfg === \"single\") { lines.value = \"1\"; lines.readOnly = true; }\n    else {\n      lines.readOnly = false;\n      if (cfg === \"parallel\" && (!NUM_RE.test(lines.value.trim()) || parseFloat(lines.value) < 2)) lines.value = \"2\";\n    }\n    const ex = {\n      single: \"Single weld: one weld line. Total effective length = entered length.\",\n      parallel: \"Parallel welds: two or more identical lines (e.g. both sides of a lap joint) sharing the load equally. Total effective length = length \u00d7 number of lines.\",\n      group: \"User-defined group: any number of identical lines, loaded through the group centroid. Total effective length = length \u00d7 number of lines. Eccentric or torsional loading is not covered.\"\n    };\n    $(\"config-explain\").textContent = ex[cfg];\n    \/\/ Unit labels\n    root.querySelectorAll(\".js-strength-unit\").forEach(el => { el.textContent = $(\"strengthUnit\").value; });\n    root.querySelectorAll(\".js-force-unit\").forEach(el => { el.textContent = $(\"forceUnit\").value; });\n    \/\/ Clear messages of hidden fields\n    NUMERIC_IDS.forEach(id => { if (!isShown(id)) setMsg(id, null); });\n  }\n  function setMsg(id, m) {\n    const el = $(id), out = $(id + \"-msg\");\n    if (!out) return;\n    out.textContent = m ? m.text : \"\";\n    out.className = \"msg\" + (m ? \" \" + m.type : \"\");\n    if (m && m.type === \"error\") el.setAttribute(\"aria-invalid\", \"true\");\n    else el.removeAttribute(\"aria-invalid\");\n  }\n  \/* Parse and validate one numeric field.  Returns { value } or { error }. *\/\n  function parseField(id, opts) {\n    const raw = $(id).value.trim();\n    if (raw === \"\") return opts.optional ? { value: opts.default, empty: true } : { error: \"This field is required.\" };\n    if (!NUM_RE.test(raw)) return { error: \"Enter a valid number (digits only, use \u201c.\u201d for decimals).\" };\n    const v = parseFloat(raw);\n    if (!isFinite(v)) return { error: \"Enter a valid number.\" };\n    if (opts.allowZero ? v < 0 : v <= 0) return { error: opts.allowZero ? \"Value cannot be negative.\" : \"Value must be greater than zero.\" };\n    if (opts.integer &#038;&#038; !Number.isInteger(v)) return { error: \"Enter a whole number.\" };\n    if (opts.minHard !== undefined &#038;&#038; v < opts.minHard) return { error: opts.minMsg };\n    if (opts.maxHard !== undefined &#038;&#038; v > opts.maxHard) return { error: opts.maxMsg };\n    return { value: v };\n  }\n  \/* Reads and validates all visible inputs.\n     onlyId: when set, only that field's inline message is updated (blur validation). *\/\n  function collect(onlyId) {\n    const msgs = {}, warnings = [];\n    let ok = true;\n    const inp = {\n      mode: radio(\"mode\"), weldType: radio(\"weldType\"), sizeKind: radio(\"sizeKind\"),\n      penetration: $(\"penetration\").value, areaInput: radio(\"areaInput\"),\n      config: $(\"config\").value, method: $(\"method\").value,\n      direction: $(\"direction\").value, applyDir: false,\n      betaW: parseFloat($(\"betaW\").value)\n    };\n    const su = $(\"strengthUnit\").value, lu = $(\"lengthUnit\").value, zu = $(\"sizeUnit\").value;\n    const fu = $(\"forceUnit\").value, au = $(\"areaUnit\").value;\n    const fillet = inp.weldType === \"fillet\";\n    const cjp = !fillet && inp.penetration === \"cjp\";\n    const direct = !fillet && inp.areaInput === \"area\";\n    if (!fillet) inp.sizeKind = \"throat\";\n    inp.applyDir = isShown(\"applyDir\") && $(\"applyDir\").checked;\n    const num = (id, opts) => {\n      if (!isShown(id)) return undefined;\n      const r = parseField(id, opts || {});\n      if (r.error) { ok = false; msgs[id] = { type: \"error\", text: r.error }; return undefined; }\n      return r.value;\n    };\n    const warn = (id, text) => {\n      warnings.push(text);\n      if (id && !msgs[id]) msgs[id] = { type: \"warn\", text };\n    };\n    const rangeWarn = (id, val, key, show, label) => {\n      if (val === undefined) return;\n      const [lo, hi] = CONFIG.RANGES[key];\n      if (val < lo || val > hi) warn(id, label + \" is outside the typical range of \" + show(lo) + \"\u2013\" + show(hi) + \". Check the value.\");\n    };\n    const showLen = v => fmt(fromMM(v, zu), lenDec(zu)) + \" \" + zu;\n    const showLenL = v => fmt(fromMM(v, lu), lu === \"in\" ? 2 : 0) + \" \" + lu;\n    const showStr = v => fmt(fromMPa(v, su), su === \"ksi\" ? 1 : 0) + \" \" + su;\n    \/\/ Geometry\n    let s = num(\"size\");\n    if (s !== undefined) {\n      inp.size = toMM(s, zu);\n      if (fillet && inp.sizeKind === \"leg\") rangeWarn(\"size\", inp.size, \"filletLeg\", showLen, \"Leg size\");\n      else if (cjp) rangeWarn(\"size\", inp.size, \"cjpThick\", showLen, \"Thickness\");\n      else rangeWarn(\"size\", inp.size, \"throat\", showLen, \"Effective throat\");\n    }\n    let L = num(\"length\");\n    if (L !== undefined) { inp.length = toMM(L, lu); rangeWarn(\"length\", inp.length, \"length\", showLenL, \"Weld length\"); }\n    if (isShown(\"lines\")) {\n      const parallel = inp.config === \"parallel\";\n      inp.lines = num(\"lines\", { integer: true, minHard: parallel ? 2 : 1, minMsg: \"Parallel welds need at least 2 weld lines.\" });\n      if (inp.lines !== undefined && inp.lines > CONFIG.RANGES.lines[1]) warn(\"lines\", \"More than \" + CONFIG.RANGES.lines[1] + \" weld lines is unusual for a simple group. Check that all lines really share the load equally.\");\n    } else inp.lines = 1;\n    let A = num(\"area\");\n    if (A !== undefined) {\n      inp.area = toMM2(A, au);\n      const [lo, hi] = CONFIG.RANGES.area;\n      if (inp.area < lo || inp.area > hi) warn(\"area\", \"Effective area is outside the typical range of \" + fmt(fromMM2(lo, au), au === \"in2\" ? 3 : 0) + \"\u2013\" + fmt(fromMM2(hi, au), 0) + \" \" + (au === \"in2\" ? \"in\u00b2\" : \"mm\u00b2\") + \".\");\n    }\n    \/\/ Short fillet weld check (length vs. size)\n    if (fillet && !direct && inp.size !== undefined && inp.length !== undefined) {\n      const w = inp.sizeKind === \"leg\" ? inp.size : inp.size \/ CONFIG.FILLET_THROAT_FACTOR;\n      const a = inp.sizeKind === \"leg\" ? inp.size * CONFIG.FILLET_THROAT_FACTOR : inp.size;\n      if (inp.method === \"ec3\") {\n        if (inp.length < Math.max(30, 6 * a)) warn(\"length\", \"EN 1993-1-8 \u00a74.5.1 does not count fillet welds shorter than max(30 mm, 6a) as load-carrying.\");\n      } else if (inp.length < 4 * w) {\n        warn(\"length\", \"Effective length is less than 4 \u00d7 leg size. AISC J2.2b limits the effective weld size for such short welds.\");\n      }\n    }\n    \/\/ Material\n    let fs = num(\"strength\");\n    if (fs !== undefined) { inp.strength = toMPa(fs, su); rangeWarn(\"strength\", inp.strength, \"strength\", showStr, \"Strength\"); }\n    let fy = num(\"baseFy\");\n    if (fy !== undefined) {\n      inp.baseFy = toMPa(fy, su);\n      rangeWarn(\"baseFy\", inp.baseFy, \"baseFy\", showStr, \"Yield strength\");\n      if (inp.strength !== undefined &#038;&#038; inp.baseFy >= inp.strength) warn(\"baseFy\", \"Base metal yield is at or above the entered filler strength. Confirm that the filler metal is matching.\");\n    }\n    let k = num(\"customK\");\n    if (k !== undefined) {\n      inp.customK = k;\n      if (k >= 1) warn(\"customK\", \"k \u2265 1 means the design stress is at or above the entered tensile strength, which is unsafe for design.\");\n      else rangeWarn(\"customK\", k, \"customK\", v => v.toFixed(2), \"Coefficient k\");\n    }\n    \/\/ Loading\n    if (inp.direction === \"custom\") {\n      inp.angleDeg = num(\"angle\", { allowZero: true, maxHard: 90, maxMsg: \"Angle must be between 0\u00b0 and 90\u00b0.\" });\n    } else inp.angleDeg = inp.direction === \"parallel\" ? 0 : 90;\n    let P = num(\"load\");\n    if (P !== undefined) inp.load = toN(P, fu);\n    const fRes = isShown(\"factor\") ? parseField(\"factor\", { optional: true, default: 1 }) : { value: 1 };\n    if (fRes.error) { ok = false; msgs.factor = { type: \"error\", text: fRes.error }; }\n    else {\n      inp.factor = fRes.value;\n      if (inp.factor < 1) warn(\"factor\", \"A factor below 1.00 increases the reported capacity and removes margin.\");\n      else if (inp.factor > CONFIG.RANGES.factor[1]) warn(\"factor\", \"Factor above \" + CONFIG.RANGES.factor[1].toFixed(1) + \" is unusually high. Check the value.\");\n      else if (inp.factor > 1 && inp.method !== \"custom\") warnings.push(\"The selected code method already includes \u03c6 \/ \u03a9 \/ \u03b3 factors. The additional factor of \" + fmt(inp.factor, 2) + \" adds further conservatism on top.\");\n    }\n    NUMERIC_IDS.forEach(id => { if (!onlyId || id === onlyId) setMsg(id, msgs[id] || null); });\n    return { ok, inp, warnings, msgs, units: { su, lu, zu, fu, au } };\n  }\n  function statusFor(u) {\n    if (u > CONFIG.STATUS.limit) return { cls: \"bad\", fill: \"fill-bad\", text: \"Exceeds estimated capacity\", icon: \"\u2715\" };\n    if (u >= CONFIG.STATUS.nearLimit) return { cls: \"near\", fill: \"fill-near\", text: \"Below estimated capacity (small margin)\", icon: \"!\" };\n    return { cls: \"ok\", fill: \"fill-ok\", text: \"Below estimated capacity\", icon: \"\u2713\" };\n  }\n  function row(th, td, sub) {\n    return \"<tr><th scope=\\\"row\\\">\" + th + \"<\/th><td>\" + td + (sub ? \"<span class=\\\"f\\\">\" + sub + \"<\/span>\" : \"\") + \"<\/td><\/tr>\";\n  }\n  function render(c) {\n    const { inp, units, warnings } = c;\n    const r = computeWeld(inp);\n    const { su, lu, zu, fu, au } = units;\n    const fillet = inp.weldType === \"fillet\";\n    const cjp = !fillet && inp.penetration === \"cjp\";\n    const direct = !fillet && inp.areaInput === \"area\";\n    const areaU = direct ? au : (zu === \"in\" && lu === \"in\" ? \"in2\" : \"mm2\");\n    const areaLabel = areaU === \"in2\" ? \"in\u00b2\" : \"mm\u00b2\";\n    const b = r.basis;\n    let h = \"\";\n    h += \"<div class=\\\"headline\\\"><p class=\\\"k\\\">\" + b.capacityLabel + (inp.factor !== 1 ? \" \u00f7 factor\" : \"\") + \"<\/p>\";\n    h += \"<p class=\\\"v\\\">\" + fmtForce(r.capacity, fu) + \"<small>\" + fu + \"<\/small><\/p>\";\n    h += \"<p class=\\\"s\\\">\" + b.methodLabel + \" \u00b7 compare with \" + b.compareWith + \"<\/p><\/div>\";\n    if (inp.mode === \"utilization\") {\n      const u = r.utilization, st = statusFor(u);\n      const w = Math.min(u, 150) \/ 150 * 100;\n      h += \"<div class=\\\"util\\\"><div class=\\\"util-top\\\"><div><div style=\\\"font-size:13.6px;color:var(--muted);font-weight:600\\\">Load utilization<\/div>\";\n      h += \"<div class=\\\"pct\\\">\" + fmt(u, 1) + \"%<\/div><\/div>\";\n      h += \"<span class=\\\"badge \" + st.cls + \"\\\"><span aria-hidden=\\\"true\\\">\" + st.icon + \"<\/span>\" + st.text + \"<\/span><\/div>\";\n      h += \"<div class=\\\"meter\\\" role=\\\"img\\\" aria-label=\\\"Utilization \" + fmt(u, 1) + \" percent of estimated capacity\\\"><span class=\\\"\" + st.fill + \"\\\" style=\\\"width:\" + w.toFixed(2) + \"%\\\"><\/span><i class=\\\"tick\\\" style=\\\"left:\" + (100 \/ 150 * 100).toFixed(2) + \"%\\\"><\/i><\/div>\";\n      h += \"<div class=\\\"meter-scale\\\" aria-hidden=\\\"true\\\"><span>0%<\/span><span style=\\\"margin-left:auto;margin-right:calc(33.3% - 1.5em)\\\">100%<\/span><span>150%+<\/span><\/div>\";\n      h += \"<p style=\\\"margin:9.6px 0 0;font-size:14.4px\\\">Applied load <strong>\" + fmtForce(inp.load, fu) + \" \" + fu + \"<\/strong> vs. estimated capacity <strong>\" + fmtForce(r.capacity, fu) + \" \" + fu + \"<\/strong><\/p><\/div>\";\n    }\n    h += \"<table class=\\\"kv\\\"><caption>Calculation details<\/caption><tbody>\";\n    h += row(\"Calculation mode\", inp.mode === \"utilization\" ? \"Utilization of applied load\" : \"Estimated weld capacity\");\n    h += row(\"Weld type\", fillet ? \"Fillet weld\" : \"Butt (groove) weld \u2013 \" + (cjp ? \"complete joint penetration (CJP)\" : \"partial joint penetration (PJP)\"));\n    if (!direct) {\n      const cfgName = { single: \"Single weld\", parallel: \"Parallel welds\", group: \"User-defined weld group\" }[inp.config];\n      h += row(\"Weld configuration\", cfgName + \" \u2013 \" + inp.lines + \" line\" + (inp.lines > 1 ? \"s\" : \"\"));\n      let thSub = \"\";\n      if (fillet && inp.sizeKind === \"leg\") thSub = \"= \" + CONFIG.FILLET_THROAT_FACTOR + \" \u00d7 leg \" + fmt(fromMM(inp.size, zu), lenDec(zu)) + \" \" + zu;\n      else if (fillet) thSub = \"entered directly\";\n      else if (cjp) thSub = \"= thickness of thinner part\";\n      else thSub = \"PJP effective throat, entered\";\n      h += row(\"Effective throat\", fmt(fromMM(r.throat, zu), lenDec(zu)) + \" \" + zu, thSub);\n      h += row(\"Length per weld line\", fmt(fromMM(inp.length, lu), 2) + \" \" + lu);\n      h += row(\"Total effective length\", fmt(fromMM(r.totalLength, lu), 2) + \" \" + lu, \"= \" + fmt(fromMM(inp.length, lu), 2) + \" \u00d7 \" + inp.lines + \" line\" + (inp.lines > 1 ? \"s\" : \"\"));\n      h += row(\"Effective weld area\", fmt(fromMM2(r.area, areaU), 2) + \" \" + areaLabel, \"= throat \u00d7 total length\");\n    } else {\n      h += row(\"Effective weld area\", fmt(fromMM2(r.area, areaU), 2) + \" \" + areaLabel, \"entered directly\");\n    }\n    h += row(inp.method === \"ec3\" ? \"Ultimate strength fu\" : \"Weld metal strength FEXX\", fmt(fromMPa(inp.strength, su), 2) + \" \" + su,\n             b.strengthSource === \"base\" ? \"reference only; base metal governs\" : \"\");\n    if (b.strengthSource === \"base\") h += row(\"Base metal yield Fy\", fmt(fromMPa(inp.baseFy, su), 2) + \" \" + su);\n    const dirName = { parallel: \"Parallel to weld axis\", transverse: \"Transverse to weld axis\", custom: \"Custom angle\" }[inp.direction];\n    h += row(\"Load direction\", dirName + \" (\u03b8 = \" + fmt(b.theta, 2) + \"\u00b0)\");\n    h += row(\"Stress basis\", b.methodLabel, b.formula + (b.factors ? \"; \" + b.factors : \"\"));\n    h += row(\"Design \/ allowable stress\", fmt(fromMPa(b.stress, su), 2) + \" \" + su);\n    if (inp.factor !== 1) h += row(\"Capacity before extra factor\", fmtForce(r.basisCapacity, fu) + \" \" + fu);\n    h += row(\"Additional safety \/ design factor\", fmt(inp.factor, 2) + (inp.factor === 1 ? \" (none)\" : \"\"));\n    h += row(\"Estimated capacity\", \"<strong>\" + fmtForce(r.capacity, fu) + \" \" + fu + \"<\/strong>\", \"= area \u00d7 stress \u00f7 factor\");\n    if (inp.mode === \"utilization\") {\n      h += row(\"Applied load\", fmtForce(inp.load, fu) + \" \" + fu);\n      h += row(\"Utilization\", \"<strong>\" + fmt(r.utilization, 1) + \"%<\/strong>\", \"= applied load \u00f7 capacity \u00d7 100\");\n    }\n    h += \"<\/tbody><\/table>\";\n    const assumptions = [];\n    if (!direct) assumptions.push(\"All \" + inp.lines + \" weld line\" + (inp.lines > 1 ? \"s have\" : \" has\") + \" the same size and length and share the load equally, with the load acting through the weld group centroid (no eccentricity, torsion or bending).\");\n    else assumptions.push(\"Effective area entered directly; its derivation must follow the selected design method.\");\n    if (fillet && inp.sizeKind === \"leg\") assumptions.push(\"Equal-leg fillet with a 90\u00b0 root: throat = \" + CONFIG.FILLET_THROAT_FACTOR + \" \u00d7 leg. Penetration beyond the root is ignored.\");\n    b.notes.forEach(n => assumptions.push(n));\n    assumptions.push(\"Fatigue, weld quality and defects, joint fit-up and base metal limit states are not evaluated.\");\n    h += \"<div class=\\\"res-list\\\"><h3>Assumptions<\/h3><ul>\" + assumptions.map(a => \"<li>\" + a + \"<\/li>\").join(\"\") + \"<\/ul><\/div>\";\n    if (warnings.length) h += \"<div class=\\\"res-list warns\\\"><h3>Warnings<\/h3><ul>\" + warnings.map(w => \"<li>\" + w + \"<\/li>\").join(\"\") + \"<\/ul><\/div>\";\n    h += \"<p class=\\\"disclaimer-sm\\\">Preliminary estimate only. Verify against the applicable design code and have the design reviewed by a qualified structural or welding engineer.<\/p>\";\n    $(\"results\").innerHTML = h;\n    hasResult = true;\n  }\n  function onCalculate(e) {\n    if (e) e.preventDefault();\n    const c = collect();\n    const summary = $(\"form-summary\");\n    if (!c.ok) {\n      const n = Object.values(c.msgs).filter(m => m.type === \"error\").length;\n      summary.textContent = \"Please correct \" + n + \" field\" + (n > 1 ? \"s\" : \"\") + \" marked below before calculating.\";\n      summary.hidden = false;\n      const first = NUMERIC_IDS.find(id => c.msgs[id] && c.msgs[id].type === \"error\");\n      $(\"results-col\").hidden = true;\n      hasResult = false;\n      if (first) $(first).focus();\n      return;\n    }\n    summary.hidden = true;\n    render(c);\n    $(\"results-col\").hidden = false;          \/\/ results appear only after Calculate\n    $(\"results-title\").scrollIntoView({ behavior: \"smooth\", block: \"start\" });\n  }\n  function markStale() {\n    if (!hasResult || $(\"results\").querySelector(\".stale\")) return;\n    const p = document.createElement(\"p\");\n    p.className = \"stale\";\n    p.textContent = \"Inputs have changed. Press Calculate to update the results.\";\n    $(\"results\").prepend(p);\n  }\n  \/* ---- Wire up events ---- *\/\n  const form = $(\"calc-form\");\n  form.addEventListener(\"submit\", onCalculate);\n  form.addEventListener(\"change\", () => { updateUI(); markStale(); });\n  form.addEventListener(\"input\", markStale);\n  NUMERIC_IDS.forEach(id => {\n    $(id).addEventListener(\"blur\", () => {\n      const el = $(id);\n      if (el.value.trim() !== \"\" || el.getAttribute(\"aria-invalid\") === \"true\") collect(id);\n    });\n  });\n  updateUI();\n}\n\/* Initialise every calculator container on the page (also works when a\n   caching \/ \"delay JS\" plugin moves or defers this script). *\/\nfunction boot() {\n  Array.prototype.forEach.call(document.querySelectorAll(\".wsc-weld-calculator\"), initCalculator);\n}\nif (document.readyState === \"loading\") document.addEventListener(\"DOMContentLoaded\", boot);\nelse boot();\n})();\n<\/script>\n\n\n\n<!-- Weld Strength Calculator: paste this whole block into a WordPress \"Custom HTML\" block -->\n<div class=\"wsc-weld-calculator\">\n<template>\n<style>\n  \/* ------------------------------------------------------------------\n     Theme \u2013 neutral steel palette with a blue accent.\n     All rules live inside a Shadow DOM, so they cannot affect the host page.\n     All text\/background pairs below meet WCAG AA contrast (\u2265 4.5:1).\n     ------------------------------------------------------------------ *\/\n  \/* The container element itself sits in the page, so theme rules can still match it.\n     Reset it here, then define everything on .main \u2013 an element inside the Shadow DOM\n     that no theme selector can reach. \"all:initial\" stops inherited theme styles\n     (font, colour, line-height, letter-spacing, text-transform\u2026) from leaking in. *\/\n  :host{all:initial !important;display:block !important}\n  .main{\n    all:initial;\n    display:block;\n    color:#17202b;\n    font-family:system-ui,-apple-system,\"Segoe UI\",Roboto,\"Helvetica Neue\",Arial,sans-serif;\n    line-height:1.5;\n    text-align:left;\n    --bg:#f3f5f8;\n    --card:#ffffff;\n    --ink:#17202b;\n    --steel:#3c4a5b;\n    --muted:#55606e;\n    --line:#cfd6df;\n    --line-strong:#9aa6b4;\n    --accent:#1d4ed8;        \/* blue, 6.7:1 on white *\/\n    --accent-dark:#1e40af;\n    --focus:#0b3a9e;\n    --ok-ink:#14532d;  --ok-bg:#dcfce7;  --ok-line:#86efac;\n    --warn-ink:#7c2d12; --warn-bg:#fff4e0; --warn-line:#f5b971;\n    --bad-ink:#7f1d1d; --bad-bg:#fee2e2; --bad-line:#fca5a5;\n    --radius:10px;\n    --shadow:0 1px 2px rgba(16,24,40,.06),0 4px 14px rgba(16,24,40,.06);\n    font-size:16px;\n  }\n  *,*::before,*::after{box-sizing:border-box}\n  .wrap{max-width:1180px;margin:0 auto}\n  .main{padding:4px 0 8px}\n  .layout{display:grid;grid-template-columns:1fr;gap:24px;align-items:start;max-width:900px;margin:0 auto}\n  .card{background:var(--card);border:1px solid var(--line);border-radius:var(--radius);box-shadow:var(--shadow)}\n  .card > .card-head{padding:16px 20px;border-bottom:1px solid var(--line)}\n  .card > .card-head h2{margin:0;font-size:18.4px}\n  .card > .card-body{padding:20px}\n  form fieldset.group{border:0;margin:0 0 24px;padding:0}\n  form fieldset.group > legend{\n    font-size:12.48px;font-weight:800;letter-spacing:.1em;text-transform:uppercase;color:var(--accent-dark);\n    padding:0;margin:0 0 12px;width:100%;border-bottom:1px solid var(--line);padding-bottom:6.4px;\n  }\n  .grid2{display:grid;grid-template-columns:1fr;gap:16px 20px}\n  @media (min-width:600px){.grid2{grid-template-columns:1fr 1fr}}\n  .span2{grid-column:1\/-1}\n  .field{margin:0}\n  .field > label,.field > .label,fieldset.seg-wrap > legend{\n    display:block;font-weight:650;margin:0 0 5.6px;font-size:15.2px;color:var(--ink);padding:0;\n  }\n  fieldset.seg-wrap{border:0;margin:0;padding:0;min-width:0}\n  .hint{margin:5.6px 0 0;font-size:13.44px;color:var(--muted)}\n  .msg{margin:5.6px 0 0;font-size:13.76px;font-weight:600;min-height:0}\n  .msg:empty{display:none}\n  .msg.error{color:var(--bad-ink)}\n  .msg.error::before{content:\"\u2715 \";}\n  .msg.warn{color:var(--warn-ink)}\n  .msg.warn::before{content:\"\u26a0 \";}\n  input[type=text],select{\n    font:inherit;color:var(--ink);background:#fff;border:1px solid var(--line-strong);border-radius:8px;\n    padding:9.6px 11.2px;width:100%;min-height:44px;\n  }\n  input[type=text]:focus,select:focus{outline:3px solid var(--focus);outline-offset:1px;border-color:var(--focus)}\n  input[readonly]{background:#eef1f5;color:var(--steel)}\n  input[aria-invalid=true]{border-color:#b91c1c;background:#fffafa}\n  .input-group{display:flex}\n  .input-group input{border-top-right-radius:0;border-bottom-right-radius:0;min-width:0}\n  .input-group select,.input-group .unit{\n    width:auto;flex:0 0 auto;border-top-left-radius:0;border-bottom-left-radius:0;border-left:0;background:#f4f6f9;font-weight:600;\n  }\n  .input-group .unit{\n    display:flex;align-items:center;padding:0 12.8px;border:1px solid var(--line-strong);border-left:0;border-radius:0 8px 8px 0;color:var(--steel);\n  }\n  \/* Segmented radio controls \u2013 native radios stay keyboard operable (arrow keys). *\/\n  .seg{display:flex;flex-wrap:wrap;border:1px solid var(--line-strong);border-radius:8px;overflow:hidden;background:#fff}\n  .seg input{position:absolute;opacity:0;width:1px;height:1px;margin:0}\n  .seg label{\n    flex:1 1 0;min-width:max-content;padding:9.6px 13.6px;text-align:center;cursor:pointer;font-weight:600;color:var(--steel);\n    border-right:1px solid var(--line);min-height:44px;display:flex;align-items:center;justify-content:center;font-size:15.2px;\n  }\n  .seg label:last-of-type{border-right:0}\n  .seg label:hover{background:#eef2f6}\n  .seg input:checked + label{background:var(--ink);color:#fff}\n  .seg input:focus-visible + label{outline:3px solid var(--focus);outline-offset:-3px}\n  .check{display:flex;gap:9.6px;align-items:flex-start;font-weight:600}\n  .check input{width:20px;height:20px;margin:2.4px 0 0;accent-color:var(--ink);flex:0 0 auto}\n  .check input:focus-visible{outline:3px solid var(--focus);outline-offset:2px}\n  .explain{background:#f6f8fb;border:1px solid var(--line);border-radius:8px;padding:11.2px 13.6px;font-size:14.08px;color:var(--steel);margin:0}\n  .actions{display:flex;justify-content:center;gap:12px;padding-top:20px;border-top:1px solid var(--line)}\n  button{\n    font:inherit;font-weight:700;border-radius:8px;padding:11.2px 20.8px;min-height:46px;cursor:pointer;border:1px solid transparent;\n  }\n  button:focus-visible{outline:3px solid var(--focus);outline-offset:2px}\n  .btn-primary{background:var(--accent);color:#fff;min-width:220px;font-size:16.8px}\n  .btn-primary:hover{background:var(--accent-dark)}\n  .btn-secondary{background:#fff;color:var(--ink);border-color:var(--line-strong)}\n  .btn-secondary:hover{background:#eef2f6}\n  .form-summary{margin:16px 0 0;padding:12px 16px;border-radius:8px;background:var(--bad-bg);border:1px solid var(--bad-line);color:var(--bad-ink);font-weight:600}\n  .form-summary[hidden]{display:none}\n  \/* Results panel *\/\n  .stale{margin:0 0 16px;padding:9.6px 13.6px;border-radius:8px;background:#eef2ff;border:1px solid #c7d2fe;color:#1e3a8a;font-size:14.4px;font-weight:600}\n  .headline{border-radius:8px;background:#17202b;color:#fff;padding:17.6px 19.2px;margin-bottom:16px}\n  .headline .k{margin:0;font-size:13.6px;letter-spacing:.02em;color:#bfdbfe;font-weight:700}\n  .headline .v{margin:3.2px 0 1.6px;font-size:clamp(28.8px,4vw,38.4px);font-weight:800;line-height:1.15;font-variant-numeric:tabular-nums}\n  .headline .v small{font-size:16px;font-weight:700;color:#dfe5ec;margin-left:4px}\n  .headline .s{margin:0;font-size:13.76px;color:#dfe5ec}\n  .util{border:1px solid var(--line);border-radius:8px;padding:16px;margin-bottom:16px}\n  .util-top{display:flex;justify-content:space-between;align-items:baseline;gap:16px;flex-wrap:wrap}\n  .util-top .pct{font-size:28.8px;font-weight:800;font-variant-numeric:tabular-nums}\n  .meter{position:relative;height:14px;border-radius:7px;background:#e7ebf0;overflow:hidden;margin:9.6px 0 4.8px}\n  .meter > span{position:absolute;left:0;top:0;bottom:0;border-radius:7px}\n  .meter .tick{position:absolute;top:0;bottom:0;width:2px;background:var(--ink);opacity:.55}\n  .meter-scale{display:flex;justify-content:space-between;font-size:12px;color:var(--muted)}\n  .badge{display:inline-flex;align-items:center;gap:6.4px;padding:5.6px 11.2px;border-radius:999px;font-weight:700;font-size:14.4px;border:1px solid}\n  .badge.ok{background:var(--ok-bg);color:var(--ok-ink);border-color:var(--ok-line)}\n  .badge.near{background:var(--warn-bg);color:var(--warn-ink);border-color:var(--warn-line)}\n  .badge.bad{background:var(--bad-bg);color:var(--bad-ink);border-color:var(--bad-line)}\n  .fill-ok{background:#15803d}.fill-near{background:#b45309}.fill-bad{background:#b91c1c}\n  table.kv{width:100%;border-collapse:collapse;font-size:14.4px;margin-bottom:16px}\n  table.kv caption{text-align:left;font-weight:800;font-size:12.48px;letter-spacing:.1em;text-transform:uppercase;color:var(--accent-dark);padding:0 0 6.4px}\n  table.kv th,table.kv td{padding:8px 6.4px;border-bottom:1px solid var(--line);vertical-align:top;text-align:left}\n  table.kv th{font-weight:600;color:var(--steel);width:46%}\n  table.kv td{font-variant-numeric:tabular-nums}\n  table.kv td .f{display:block;font-size:12.8px;color:var(--muted)}\n  .res-list h3{font-size:12.48px;font-weight:800;letter-spacing:.1em;text-transform:uppercase;margin:16px 0 6.4px;color:var(--accent-dark)}\n  .res-list ul{margin:0;padding-left:18.4px;font-size:14.08px;color:var(--steel)}\n  .res-list li{margin:4px 0}\n  .res-list.warns ul{color:var(--warn-ink)}\n  .disclaimer-sm{font-size:13.12px;color:var(--muted);border-top:1px solid var(--line);padding-top:12px;margin:16px 0 0}\n  [hidden]{display:none !important}\n  .sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}\n  @media (prefers-reduced-motion:no-preference){button,.seg label{transition:background-color .15s ease}}\n<\/style>\n<div class=\"main\">\n  <div class=\"wrap\">\n    <div class=\"layout\">\n      <!-- ========================= INPUT FORM ========================= -->\n      <section class=\"card\" aria-labelledby=\"inputs-title\">\n        <div class=\"card-head\"><h2 id=\"inputs-title\">Inputs<\/h2><\/div>\n        <div class=\"card-body\">\n          <form id=\"calc-form\" novalidate>\n            <fieldset class=\"group\">\n              <legend>Calculation<\/legend>\n              <div class=\"grid2\">\n                <fieldset class=\"seg-wrap span2\">\n                  <legend>What do you want to calculate?<\/legend>\n                  <div class=\"seg\">\n                    <input type=\"radio\" id=\"mode-capacity\" name=\"mode\" value=\"capacity\" checked>\n                    <label for=\"mode-capacity\">Estimated weld capacity<\/label>\n                    <input type=\"radio\" id=\"mode-util\" name=\"mode\" value=\"utilization\">\n                    <label for=\"mode-util\">Utilization of an applied load<\/label>\n                  <\/div>\n                <\/fieldset>\n                <fieldset class=\"seg-wrap span2\">\n                  <legend>Weld type<\/legend>\n                  <div class=\"seg\">\n                    <input type=\"radio\" id=\"wt-fillet\" name=\"weldType\" value=\"fillet\" checked>\n                    <label for=\"wt-fillet\">Fillet weld<\/label>\n                    <input type=\"radio\" id=\"wt-butt\" name=\"weldType\" value=\"butt\">\n                    <label for=\"wt-butt\">Butt weld (groove weld)<\/label>\n                  <\/div>\n                <\/fieldset>\n              <\/div>\n            <\/fieldset>\n            <fieldset class=\"group\">\n              <legend>Weld geometry<\/legend>\n              <div class=\"grid2\">\n                <!-- Butt weld only -->\n                <div class=\"field span2\" id=\"row-penetration\" hidden>\n                  <label for=\"penetration\">Joint penetration<\/label>\n                  <select id=\"penetration\" aria-describedby=\"penetration-hint\">\n                    <option value=\"pjp\">Partial joint penetration (PJP) \u2013 enter effective throat<\/option>\n                    <option value=\"cjp\">Complete joint penetration (CJP) \u2013 full thickness<\/option>\n                  <\/select>\n                  <p class=\"hint\" id=\"penetration-hint\">Full penetration is never assumed. Choose CJP only if the joint is designed, welded and inspected as complete-penetration.<\/p>\n                <\/div>\n                <fieldset class=\"seg-wrap span2\" id=\"row-areaInput\" hidden>\n                  <legend>How will you define the weld area?<\/legend>\n                  <div class=\"seg\">\n                    <input type=\"radio\" id=\"ai-dims\" name=\"areaInput\" value=\"dims\" checked>\n                    <label for=\"ai-dims\">From weld dimensions<\/label>\n                    <input type=\"radio\" id=\"ai-area\" name=\"areaInput\" value=\"area\">\n                    <label for=\"ai-area\">Enter effective area directly<\/label>\n                  <\/div>\n                <\/fieldset>\n                <!-- Fillet weld only -->\n                <fieldset class=\"seg-wrap span2\" id=\"row-sizeKind\">\n                  <legend>Fillet weld size is given as<\/legend>\n                  <div class=\"seg\">\n                    <input type=\"radio\" id=\"sk-leg\" name=\"sizeKind\" value=\"leg\" checked>\n                    <label for=\"sk-leg\">Leg size (w)<\/label>\n                    <input type=\"radio\" id=\"sk-throat\" name=\"sizeKind\" value=\"throat\">\n                    <label for=\"sk-throat\">Effective throat (a)<\/label>\n                  <\/div>\n                <\/fieldset>\n                <div class=\"field\" id=\"row-size\">\n                  <label for=\"size\" id=\"size-label\">Weld leg size (w)<\/label>\n                  <div class=\"input-group\">\n                    <input type=\"text\" id=\"size\" inputmode=\"decimal\" autocomplete=\"off\" aria-describedby=\"size-hint size-msg\">\n                    <select id=\"sizeUnit\" aria-label=\"Weld size unit\">\n                      <option value=\"mm\">mm<\/option>\n                      <option value=\"in\">in<\/option>\n                    <\/select>\n                  <\/div>\n                  <p class=\"hint\" id=\"size-hint\">Effective throat = 0.707 \u00d7 leg (equal-leg, 90\u00b0 fillet).<\/p>\n                  <p class=\"msg\" id=\"size-msg\"><\/p>\n                <\/div>\n                <div class=\"field\" id=\"row-length\">\n                  <label for=\"length\">Effective length per weld line<\/label>\n                  <div class=\"input-group\">\n                    <input type=\"text\" id=\"length\" inputmode=\"decimal\" autocomplete=\"off\" aria-describedby=\"length-hint length-msg\">\n                    <select id=\"lengthUnit\" aria-label=\"Weld length unit\">\n                      <option value=\"mm\">mm<\/option>\n                      <option value=\"in\">in<\/option>\n                    <\/select>\n                  <\/div>\n                  <p class=\"hint\" id=\"length-hint\">Exclude end craters \/ run-off; use the effective length only.<\/p>\n                  <p class=\"msg\" id=\"length-msg\"><\/p>\n                <\/div>\n                <div class=\"field\" id=\"row-config\">\n                  <label for=\"config\">Weld configuration<\/label>\n                  <select id=\"config\" aria-describedby=\"config-explain\">\n                    <option value=\"single\">Single weld<\/option>\n                    <option value=\"parallel\">Parallel welds<\/option>\n                    <option value=\"group\">User-defined weld group<\/option>\n                  <\/select>\n                <\/div>\n                <div class=\"field\" id=\"row-lines\">\n                  <label for=\"lines\">Number of weld lines<\/label>\n                  <input type=\"text\" id=\"lines\" inputmode=\"numeric\" autocomplete=\"off\" value=\"1\" aria-describedby=\"lines-msg\">\n                  <p class=\"msg\" id=\"lines-msg\"><\/p>\n                <\/div>\n                <p class=\"explain span2\" id=\"config-explain\" aria-live=\"polite\"><\/p>\n                <!-- Butt weld, direct area -->\n                <div class=\"field span2\" id=\"row-area\" hidden>\n                  <label for=\"area\">Total effective weld area<\/label>\n                  <div class=\"input-group\">\n                    <input type=\"text\" id=\"area\" inputmode=\"decimal\" autocomplete=\"off\" aria-describedby=\"area-hint area-msg\">\n                    <select id=\"areaUnit\" aria-label=\"Area unit\">\n                      <option value=\"mm2\">mm\u00b2<\/option>\n                      <option value=\"in2\">in\u00b2<\/option>\n                    <\/select>\n                  <\/div>\n                  <p class=\"hint\" id=\"area-hint\">Effective throat \u00d7 effective length, summed over all weld lines, as defined by your design method.<\/p>\n                  <p class=\"msg\" id=\"area-msg\"><\/p>\n                <\/div>\n              <\/div>\n            <\/fieldset>\n            <fieldset class=\"group\">\n              <legend>Material &amp; stress basis<\/legend>\n              <div class=\"grid2\">\n                <div class=\"field span2\">\n                  <label for=\"method\">Stress basis \/ design method<\/label>\n                  <select id=\"method\" aria-describedby=\"method-hint\">\n                    <option value=\"aisc_lrfd\">AISC 360 \u2013 LRFD design strength (\u03c6Rn)<\/option>\n                    <option value=\"aisc_asd\">AISC 360 \u2013 ASD allowable strength (Rn\/\u03a9)<\/option>\n                    <option value=\"ec3\">EN 1993-1-8 \u2013 simplified method (Fw,Rd)<\/option>\n                    <option value=\"custom\">User-defined stress coefficient (k \u00d7 strength)<\/option>\n                  <\/select>\n                  <p class=\"hint\" id=\"method-hint\"><\/p>\n                <\/div>\n                <div class=\"field\">\n                  <label for=\"strength\" id=\"strength-label\">Weld metal \/ electrode tensile strength (F<sub>EXX<\/sub>)<\/label>\n                  <div class=\"input-group\">\n                    <input type=\"text\" id=\"strength\" inputmode=\"decimal\" autocomplete=\"off\" aria-describedby=\"strength-hint strength-msg\">\n                    <select id=\"strengthUnit\" aria-label=\"Strength unit\">\n                      <option value=\"MPa\">MPa<\/option>\n                      <option value=\"ksi\">ksi<\/option>\n                    <\/select>\n                  <\/div>\n                  <p class=\"hint\" id=\"strength-hint\"><\/p>\n                  <p class=\"msg\" id=\"strength-msg\"><\/p>\n                <\/div>\n                <div class=\"field\" id=\"row-baseFy\" hidden>\n                  <label for=\"baseFy\">Base metal yield strength (F<sub>y<\/sub>)<\/label>\n                  <div class=\"input-group\">\n                    <input type=\"text\" id=\"baseFy\" inputmode=\"decimal\" autocomplete=\"off\" aria-describedby=\"baseFy-hint baseFy-msg\">\n                    <span class=\"unit js-strength-unit\" aria-hidden=\"true\">MPa<\/span>\n                  <\/div>\n                  <p class=\"hint\" id=\"baseFy-hint\">CJP joints with matching filler are governed by the base metal. Use the weaker connected part.<\/p>\n                  <p class=\"msg\" id=\"baseFy-msg\"><\/p>\n                <\/div>\n                <div class=\"field\" id=\"row-betaW\" hidden>\n                  <label for=\"betaW\">Correlation factor \u03b2<sub>w<\/sub> (steel grade)<\/label>\n                  <select id=\"betaW\" aria-describedby=\"betaW-hint\">\n                    <option value=\"0.80\">S235 \u2013 \u03b2w = 0.80<\/option>\n                    <option value=\"0.85\">S275 \u2013 \u03b2w = 0.85<\/option>\n                    <option value=\"0.90\" selected>S355 \u2013 \u03b2w = 0.90<\/option>\n                    <option value=\"1.00\">S420 \/ S460 \u2013 \u03b2w = 1.00<\/option>\n                  <\/select>\n                  <p class=\"hint\" id=\"betaW-hint\">EN 1993-1-8 Table 4.1, for the weaker connected part.<\/p>\n                <\/div>\n                <div class=\"field\" id=\"row-customK\" hidden>\n                  <label for=\"customK\">Stress coefficient k<\/label>\n                  <input type=\"text\" id=\"customK\" inputmode=\"decimal\" autocomplete=\"off\" value=\"0.30\" aria-describedby=\"customK-hint customK-msg\">\n                  <p class=\"hint\" id=\"customK-hint\">Design stress = k \u00d7 entered strength. Example: 0.30 reproduces the traditional allowable shear stress 0.30\u00b7F<sub>EXX<\/sub> on the fillet throat.<\/p>\n                  <p class=\"msg\" id=\"customK-msg\"><\/p>\n                <\/div>\n              <\/div>\n            <\/fieldset>\n            <fieldset class=\"group\">\n              <legend>Loading<\/legend>\n              <div class=\"grid2\">\n                <div class=\"field\">\n                  <label for=\"direction\">Load direction<\/label>\n                  <select id=\"direction\" aria-describedby=\"direction-hint\">\n                    <option value=\"parallel\">Parallel to weld axis (longitudinal \/ shear)<\/option>\n                    <option value=\"transverse\">Transverse to weld axis<\/option>\n                    <option value=\"custom\">Custom angle<\/option>\n                  <\/select>\n                  <p class=\"hint\" id=\"direction-hint\">Angle \u03b8 is measured between the line of action of the load and the weld longitudinal axis.<\/p>\n                <\/div>\n                <div class=\"field\" id=\"row-angle\" hidden>\n                  <label for=\"angle\">Load angle \u03b8<\/label>\n                  <div class=\"input-group\">\n                    <input type=\"text\" id=\"angle\" inputmode=\"decimal\" autocomplete=\"off\" value=\"45\" aria-describedby=\"angle-msg\">\n                    <span class=\"unit\" aria-hidden=\"true\">degrees<\/span>\n                  <\/div>\n                  <p class=\"msg\" id=\"angle-msg\"><\/p>\n                <\/div>\n                <div class=\"field span2\" id=\"row-applyDir\">\n                  <label class=\"check\" for=\"applyDir\">\n                    <input type=\"checkbox\" id=\"applyDir\" aria-describedby=\"applyDir-hint\">\n                    <span>Apply AISC directional strength increase (1.0 + 0.50 sin<sup>1.5<\/sup>\u03b8)<\/span>\n                  <\/label>\n                  <p class=\"hint\" id=\"applyDir-hint\">Only valid for linear fillet welds, or groups where every element has the same orientation, loaded in-plane through the centre of gravity. Leave off for a conservative estimate.<\/p>\n                <\/div>\n                <div class=\"field\">\n                  <label for=\"forceUnit\">Force unit for results<\/label>\n                  <select id=\"forceUnit\">\n                    <option value=\"N\">N<\/option>\n                    <option value=\"kN\" selected>kN<\/option>\n                    <option value=\"lbf\">lbf<\/option>\n                    <option value=\"kip\">kip<\/option>\n                  <\/select>\n                <\/div>\n                <div class=\"field\" id=\"row-load\" hidden>\n                  <label for=\"load\">Applied load<\/label>\n                  <div class=\"input-group\">\n                    <input type=\"text\" id=\"load\" inputmode=\"decimal\" autocomplete=\"off\" aria-describedby=\"load-hint load-msg\">\n                    <span class=\"unit js-force-unit\" aria-hidden=\"true\">kN<\/span>\n                  <\/div>\n                  <p class=\"hint\" id=\"load-hint\">Use the same load basis as the method (factored for LRFD \/ EN 1993, service for ASD).<\/p>\n                  <p class=\"msg\" id=\"load-msg\"><\/p>\n                <\/div>\n                <div class=\"field\">\n                  <label for=\"factor\">Additional safety \/ design factor <span style=\"font-weight:400;color:var(--muted)\">(optional)<\/span><\/label>\n                  <input type=\"text\" id=\"factor\" inputmode=\"decimal\" autocomplete=\"off\" placeholder=\"1.00\" aria-describedby=\"factor-hint factor-msg\">\n                  <p class=\"hint\" id=\"factor-hint\">Capacity is divided by this factor. Leave blank for 1.00.<\/p>\n                  <p class=\"msg\" id=\"factor-msg\"><\/p>\n                <\/div>\n              <\/div>\n            <\/fieldset>\n            <div class=\"actions\">\n              <button type=\"submit\" class=\"btn-primary\" id=\"btn-calc\">Calculate<\/button>\n            <\/div>\n            <p class=\"form-summary\" id=\"form-summary\" role=\"alert\" hidden><\/p>\n          <\/form>\n        <\/div>\n      <\/section>\n      <!-- ========================= RESULTS ========================= -->\n      <div class=\"results-col\" id=\"results-col\" hidden>\n        <section class=\"card\" aria-labelledby=\"results-title\">\n          <div class=\"card-head\"><h2 id=\"results-title\">Results<\/h2><\/div>\n          <div class=\"card-body\" id=\"results\" aria-live=\"polite\"><\/div>\n        <\/section>\n      <\/div>\n    <\/div>\n  <\/div>\n<\/div>\n<\/template>\n<\/div>\n<script>\n(function () {\n\"use strict\";\n\/* =====================================================================\n   CORE CALCULATION ENGINE (no DOM access)\n   ---------------------------------------------------------------------\n   Internal units are consistent SI: length in mm, stress in MPa (N\/mm\u00b2),\n   area in mm\u00b2, force in N.  MPa \u00d7 mm\u00b2 = N, so no extra factor is needed.\n   All design assumptions live in CONFIG and can be edited.\n   ===================================================================== *\/\nconst CONFIG = {\n  \/* Effective throat of an equal-leg fillet weld with a 90\u00b0 root:\n     a = w \u00b7 sin(45\u00b0) = 0.707 \u00b7 w.  Edit for unequal legs or skewed joints. *\/\n  FILLET_THROAT_FACTOR: 0.707,\n  \/* Unit conversions to internal units. *\/\n  UNITS: {\n    MM_PER_IN: 25.4,               \/\/ 1 in  = 25.4 mm (exact)\n    MM2_PER_IN2: 645.16,           \/\/ 1 in\u00b2 = 645.16 mm\u00b2 (exact)\n    MPA_PER_KSI: 6.894757,         \/\/ 1 ksi = 6.894757 MPa\n    N_PER: { N: 1, kN: 1000, lbf: 4.4482216, kip: 4448.2216 } \/\/ force \u2192 N\n  },\n  \/* Stress basis definitions.  \"coef\" multiplies the strength (FEXX or Fy).\n     LRFD uses a resistance factor \u03c6 (multiply); ASD uses a safety factor \u03a9 (divide). *\/\n  METHODS: {\n    aisc_lrfd: {\n      label: \"AISC 360 \u2013 LRFD\",\n      capacityLabel: \"Design strength \u03c6Rn\",\n      compareWith: \"factored (LRFD) loads\",\n      fillet: { coef: 0.60, phi: 0.75 },\n      pjp: { tension: { coef: 0.60, phi: 0.80 }, shear: { coef: 0.60, phi: 0.75 } },\n      cjp: { tension: { coef: 1.00, phi: 0.90 }, shear: { coef: 0.60, phi: 1.00 } } \/\/ on base metal Fy\n    },\n    aisc_asd: {\n      label: \"AISC 360 \u2013 ASD\",\n      capacityLabel: \"Allowable strength Rn\/\u03a9\",\n      compareWith: \"service (ASD) load combinations\",\n      fillet: { coef: 0.60, omega: 2.00 },\n      pjp: { tension: { coef: 0.60, omega: 1.88 }, shear: { coef: 0.60, omega: 2.00 } },\n      cjp: { tension: { coef: 1.00, omega: 1.67 }, shear: { coef: 0.60, omega: 1.50 } } \/\/ on base metal Fy\n    },\n    ec3: {\n      label: \"EN 1993-1-8 \u2013 simplified method\",\n      capacityLabel: \"Design resistance Fw,Rd\",\n      compareWith: \"ULS design loads\",\n      gammaM2: 1.25,   \/\/ partial factor for welds\n      gammaM0: 1.00    \/\/ partial factor for cross-section resistance (base metal)\n    },\n    custom: {\n      label: \"User-defined coefficient\",\n      capacityLabel: \"Estimated capacity\",\n      compareWith: \"loads on the same basis as your coefficient k\"\n    }\n  },\n  \/* AISC 360 Eq. J2-5 directional strength increase for fillet welds. *\/\n  AISC_DIRECTIONAL: { base: 1.0, coef: 0.50, exp: 1.5 },\n  \/* Practical ranges (internal units).  Values outside trigger a warning only;\n     inputs are never clamped. *\/\n  RANGES: {\n    filletLeg:   [3, 25],       \/\/ mm\n    throat:      [2, 50],       \/\/ mm (fillet throat entered directly, PJP throat)\n    cjpThick:    [3, 100],      \/\/ mm\n    length:      [10, 3000],    \/\/ mm per line\n    lines:       [1, 12],\n    area:        [10, 500000],  \/\/ mm\u00b2\n    strength:    [340, 900],    \/\/ MPa (E60 \u2248 414, E70 \u2248 482, E80 \u2248 551 MPa)\n    baseFy:      [185, 700],    \/\/ MPa\n    customK:     [0.10, 0.60],\n    factor:      [1.0, 5.0]\n  },\n  \/* Utilization status thresholds (%). *\/\n  STATUS: { nearLimit: 90, limit: 100 },\n  \/* Display precision. *\/\n  FORCE_DECIMALS: { N: 0, kN: 2, lbf: 0, kip: 2 }\n};\n\/* ---- Unit conversions (display unit \u21c4 internal unit) ---- *\/\nconst U = CONFIG.UNITS;\nconst toMM    = (v, u) => u === \"in\"  ? v * U.MM_PER_IN   : v;\nconst fromMM  = (v, u) => u === \"in\"  ? v \/ U.MM_PER_IN   : v;\nconst toMM2   = (v, u) => u === \"in2\" ? v * U.MM2_PER_IN2 : v;\nconst fromMM2 = (v, u) => u === \"in2\" ? v \/ U.MM2_PER_IN2 : v;\nconst toMPa   = (v, u) => u === \"ksi\" ? v * U.MPA_PER_KSI : v;\nconst fromMPa = (v, u) => u === \"ksi\" ? v \/ U.MPA_PER_KSI : v;\nconst toN     = (v, u) => v * U.N_PER[u];\nconst fromN   = (v, u) => v \/ U.N_PER[u];\n\/* Load action on a butt weld from the selected direction. *\/\nfunction buttAction(direction) {\n  if (direction === \"parallel\") return \"shear\";\n  if (direction === \"transverse\") return \"tension\";\n  return \"governing\"; \/\/ custom angle \u2192 lower of the two (conservative)\n}\n\/* Resolves the design \/ allowable stress (MPa) for the selected method.\n   Returns { stress, formula, factors, strengthSource, notes[] }. *\/\nfunction getStressBasis(inp) {\n  const notes = [];\n  const m = CONFIG.METHODS[inp.method];\n  const theta = inp.direction === \"parallel\" ? 0 : inp.direction === \"transverse\" ? 90 : inp.angleDeg;\n  const isFillet = inp.weldType === \"fillet\";\n  const isCJP = !isFillet && inp.penetration === \"cjp\";\n  const out = {\n    theta, methodLabel: m.label, capacityLabel: m.capacityLabel, compareWith: m.compareWith,\n    strengthSource: \"weld\", stress: NaN, formula: \"\", factors: \"\", notes\n  };\n  \/* --- User-defined: stress = k \u00d7 entered strength --- *\/\n  if (inp.method === \"custom\") {\n    out.stress = inp.customK * inp.strength;\n    out.formula = \"k \u00d7 entered strength\";\n    out.factors = \"k = \" + inp.customK;\n    notes.push(\"Stress basis is user-defined. The calculator does not check that k matches any design code.\");\n    if (isCJP) notes.push(\"CJP: k is applied to the entered strength. Check the base metal capacity separately.\");\n    return out;\n  }\n  \/* --- EN 1993-1-8 --- *\/\n  if (inp.method === \"ec3\") {\n    if (!isCJP) {\n      \/\/ Simplified method \u00a74.5.3.3: fvw,d = fu \/ (\u221a3 \u00b7 \u03b2w \u00b7 \u03b3M2)\n      out.stress = inp.strength \/ (Math.sqrt(3) * inp.betaW * m.gammaM2);\n      out.formula = \"fu \/ (\u221a3 \u00d7 \u03b2w \u00d7 \u03b3M2)\";\n      out.factors = \"\u03b2w = \" + inp.betaW.toFixed(2) + \", \u03b3M2 = \" + m.gammaM2.toFixed(2);\n      notes.push(\"EN 1993-1-8 simplified method: resistance is independent of load direction. This is conservative; the directional method can give a higher value.\");\n      notes.push(\"fu should be the nominal ultimate tensile strength of the weaker connected part, with \u03b2w matching that steel grade.\");\n      if (!isFillet) notes.push(\"PJP butt weld treated as a deep-penetration fillet weld (EN 1993-1-8 \u00a74.7.2).\");\n      return out;\n    }\n    \/\/ Full-penetration butt weld: resistance of the weaker connected part (\u00a74.7.1)\n    out.strengthSource = \"base\";\n    const t = inp.baseFy \/ m.gammaM0, s = inp.baseFy \/ (Math.sqrt(3) * m.gammaM0);\n    const a = buttAction(inp.direction);\n    if (a === \"tension\") { out.stress = t; out.formula = \"fy \/ \u03b3M0 (normal stress)\"; }\n    else if (a === \"shear\") { out.stress = s; out.formula = \"fy \/ (\u221a3 \u00d7 \u03b3M0) (shear)\"; }\n    else { out.stress = Math.min(t, s); out.formula = \"min[ fy\/\u03b3M0 , fy\/(\u221a3\u00b7\u03b3M0) ]\"; notes.push(\"Custom angle: the lower of the normal and shear resistances is used (conservative). Combined stress interaction is not evaluated.\"); }\n    out.factors = \"\u03b3M0 = \" + m.gammaM0.toFixed(2);\n    notes.push(\"Full-penetration butt weld: assumes matching (overmatching) filler metal, so resistance equals the weaker connected part (EN 1993-1-8 \u00a74.7.1).\");\n    return out;\n  }\n  \/* --- AISC 360 (LRFD or ASD) --- *\/\n  const isLRFD = inp.method === \"aisc_lrfd\";\n  const rf = c => (isLRFD ? c.phi : 1 \/ c.omega);                 \/\/ resistance multiplier\n  const rfText = c => (isLRFD ? \"\u03c6 = \" + c.phi.toFixed(2) : \"\u03a9 = \" + c.omega.toFixed(2));\n  const wrap = (core, c) => (isLRFD ? \"\u03c6 \u00d7 \" + core : core + \" \u00f7 \u03a9\");\n  if (isFillet) {\n    const c = m.fillet;\n    let kds = 1;\n    if (inp.applyDir) {\n      const d = CONFIG.AISC_DIRECTIONAL;\n      kds = d.base + d.coef * Math.pow(Math.sin(theta * Math.PI \/ 180), d.exp);\n    }\n    out.stress = rf(c) * c.coef * inp.strength * kds;\n    out.formula = wrap(\"0.60 \u00d7 FEXX\" + (inp.applyDir ? \" \u00d7 kds\" : \"\"), c);\n    out.factors = rfText(c) + (inp.applyDir ? \", kds = \" + kds.toFixed(3) + \" (\u03b8 = \" + round2(theta) + \"\u00b0)\" : \"\");\n    out.kds = kds;\n    if (inp.applyDir) notes.push(\"Directional increase (AISC Eq. J2-5) applied. Valid only for linear welds or same-orientation groups loaded in-plane through the centroid. Groups that mix longitudinal and transverse welds need AISC Eq. J2-6 (not implemented).\");\n    else notes.push(\"AISC directional strength increase not applied: the fillet is rated as if loaded longitudinally (conservative).\");\n    notes.push(\"Base metal strength at the weld (AISC J4 shear yielding \/ rupture) is not checked.\");\n    return out;\n  }\n  if (!isCJP) {\n    \/\/ PJP groove weld \u2013 AISC Table J2.5, on effective throat\n    const a = buttAction(inp.direction);\n    const ct = m.pjp.tension, cs = m.pjp.shear;\n    const t = rf(ct) * ct.coef * inp.strength, s = rf(cs) * cs.coef * inp.strength;\n    if (a === \"tension\") { out.stress = t; out.formula = wrap(\"0.60 \u00d7 FEXX\", ct) + \" (tension normal to axis)\"; out.factors = rfText(ct); }\n    else if (a === \"shear\") { out.stress = s; out.formula = wrap(\"0.60 \u00d7 FEXX\", cs) + \" (shear)\"; out.factors = rfText(cs); }\n    else {\n      const useT = t <= s;\n      out.stress = Math.min(t, s);\n      out.formula = \"lower of tension-normal and shear values\";\n      out.factors = rfText(useT ? ct : cs);\n      notes.push(\"Custom angle: the lower of the tension-normal and shear values is used (conservative). Combined stress interaction is not evaluated.\");\n    }\n    notes.push(\"PJP groove weld per AISC Table J2.5. Base metal strength (AISC J4) must also be checked. Compression normal to the axis is conservatively taken as tension.\");\n    return out;\n  }\n  \/\/ CJP groove weld \u2013 strength governed by base metal (AISC Table J2.5 \u2192 J4)\n  out.strengthSource = \"base\";\n  const a = buttAction(inp.direction);\n  const ct = m.cjp.tension, cs = m.cjp.shear;\n  const t = rf(ct) * ct.coef * inp.baseFy, s = rf(cs) * cs.coef * inp.baseFy;\n  if (a === \"tension\") { out.stress = t; out.formula = wrap(\"Fy\", ct) + \" (tensile yielding)\"; out.factors = rfText(ct); }\n  else if (a === \"shear\") { out.stress = s; out.formula = wrap(\"0.60 \u00d7 Fy\", cs) + \" (shear yielding)\"; out.factors = rfText(cs); }\n  else {\n    const useT = t <= s;\n    out.stress = Math.min(t, s);\n    out.formula = \"lower of tension and shear yielding\";\n    out.factors = rfText(useT ? ct : cs);\n    notes.push(\"Custom angle: the lower of the tension and shear values is used (conservative). Combined stress interaction is not evaluated.\");\n  }\n  notes.push(\"CJP groove weld with matching filler metal: strength is governed by the base metal (AISC Table J2.5 \/ J4). Rupture limit states are not checked.\");\n  return out;\n}\n\/* Main calculation.  inp values are already in internal units. *\/\nfunction computeWeld(inp) {\n  let throat = null, totalLength = null, area;\n  if (inp.weldType === \"butt\" &#038;&#038; inp.areaInput === \"area\") {\n    area = inp.area;                                     \/\/ entered directly\n  } else {\n    \/\/ Effective throat: fillet leg \u00d7 0.707, otherwise the entered throat \/ CJP thickness\n    throat = (inp.weldType === \"fillet\" &#038;&#038; inp.sizeKind === \"leg\")\n      ? CONFIG.FILLET_THROAT_FACTOR * inp.size\n      : inp.size;\n    totalLength = inp.length * inp.lines;                \/\/ all lines identical\n    area = throat * totalLength;\n  }\n  const basis = getStressBasis(inp);\n  const basisCapacity = area * basis.stress;             \/\/ mm\u00b2 \u00d7 MPa = N\n  const capacity = basisCapacity \/ inp.factor;           \/\/ optional extra factor\n  const utilization = inp.mode === \"utilization\" ? (inp.load \/ capacity) * 100 : null;\n  return { throat, totalLength, area, basis, basisCapacity, capacity, utilization };\n}\nfunction round2(n) { return Math.round(n * 100) \/ 100; }\n\/* ===================== END OF CORE ENGINE ===================== *\/\n\/* =====================================================================\n   USER INTERFACE \u2013 one instance per container.  The calculator is\n   rendered inside a Shadow DOM so its CSS, IDs and markup are fully\n   isolated from the WordPress theme and plugins (in both directions).\n   ===================================================================== *\/\nfunction initCalculator(host) {\n  if (host.shadowRoot || host.dataset.wscReady) return;\n  const tpl = host.querySelector(\"template\");\n  if (!tpl) return;\n  host.dataset.wscReady = \"1\";\n  const root = host.attachShadow({ mode: \"open\" });\n  root.appendChild(tpl.content.cloneNode(true));\n  tpl.remove();\n  const $ = id => root.getElementById(id);\n  const radio = name => root.querySelector('input[name=\"' + name + '\"]:checked').value;\n  const isShown = id => !$(id).closest(\"[hidden]\");\n  const NUM_RE = \/^[+-]?(\\d+\\.?\\d*|\\.\\d+)([eE][+-]?\\d+)?$\/;\n  const NUMERIC_IDS = [\"size\", \"length\", \"lines\", \"area\", \"strength\", \"baseFy\", \"customK\", \"angle\", \"load\", \"factor\"];\n  let hasResult = false;\n  function fmt(n, d) {\n    return Number(n).toLocaleString(\"en-US\", { minimumFractionDigits: d, maximumFractionDigits: d });\n  }\n  function fmtForce(N, unit) { return fmt(fromN(N, unit), CONFIG.FORCE_DECIMALS[unit]); }\n  function lenDec() { return 2; } \/\/ dimensions shown to two decimals\n  \/* Show\/hide fields and update labels for the current selections. *\/\n  function updateUI() {\n    const mode = radio(\"mode\"), wt = radio(\"weldType\");\n    const fillet = wt === \"fillet\";\n    const pen = $(\"penetration\").value;\n    const direct = !fillet && radio(\"areaInput\") === \"area\";\n    const method = $(\"method\").value;\n    const cjp = !fillet && pen === \"cjp\";\n    $(\"row-penetration\").hidden = fillet;\n    $(\"row-areaInput\").hidden = fillet;\n    $(\"row-sizeKind\").hidden = !fillet;\n    [\"row-size\", \"row-length\", \"row-config\", \"row-lines\", \"config-explain\"].forEach(id => { $(id).hidden = direct; });\n    $(\"row-area\").hidden = !direct;\n    \/\/ Size label depends on weld type \/ penetration\n    let lbl, hint;\n    if (fillet && radio(\"sizeKind\") === \"leg\") { lbl = \"Weld leg size (w)\"; hint = \"Effective throat = 0.707 \u00d7 leg (equal-leg, 90\u00b0 fillet).\"; }\n    else if (fillet) { lbl = \"Effective throat (a)\"; hint = \"Throat entered directly; no 0.707 factor is applied.\"; }\n    else if (cjp) { lbl = \"Thickness of thinner connected part (t)\"; hint = \"For CJP, the effective throat equals the thinner part's thickness.\"; }\n    else { lbl = \"Effective throat (E), PJP\"; hint = \"Use the effective throat for your groove type, welding process and position (e.g. AISC Table J2.1).\"; }\n    $(\"size-label\").textContent = lbl;\n    $(\"size-hint\").textContent = hint;\n    \/\/ Method-specific fields\n    $(\"row-customK\").hidden = method !== \"custom\";\n    $(\"row-betaW\").hidden = !(method === \"ec3\" && !cjp);\n    $(\"row-baseFy\").hidden = !(cjp && method !== \"custom\");\n    $(\"row-applyDir\").hidden = !(fillet && (method === \"aisc_lrfd\" || method === \"aisc_asd\"));\n    const mh = {\n      aisc_lrfd: \"Design strength = \u03c6 \u00d7 nominal strength. Compare with factored loads.\",\n      aisc_asd: \"Allowable strength = nominal strength \u00f7 \u03a9. Compare with service loads.\",\n      ec3: \"Design resistance with partial factors \u03b3M2 \/ \u03b3M0. Compare with ULS design loads.\",\n      custom: \"You define the design stress as a fraction k of the entered strength.\"\n    };\n    $(\"method-hint\").textContent = mh[method];\n    const sh = {\n      aisc_lrfd: \"Classification strength FEXX, e.g. E70 = 70 ksi \u2248 482 MPa.\",\n      aisc_asd: \"Classification strength FEXX, e.g. E70 = 70 ksi \u2248 482 MPa.\",\n      ec3: \"EN 1993-1-8 uses fu of the weaker connected part (e.g. S355: 470\u2013510 MPa).\",\n      custom: \"The strength that your coefficient k multiplies.\"\n    };\n    $(\"strength-label\").innerHTML = method === \"ec3\"\n      ? \"Ultimate tensile strength f<sub>u<\/sub> (weaker part)\"\n      : \"Weld metal \/ electrode tensile strength (F<sub>EXX<\/sub>)\";\n    let sHint = sh[method];\n    if (cjp && method !== \"custom\") sHint += \" For CJP it is reported for reference; the base metal governs.\";\n    $(\"strength-hint\").textContent = sHint;\n    $(\"row-angle\").hidden = $(\"direction\").value !== \"custom\";\n    $(\"row-load\").hidden = mode !== \"utilization\";\n    \/\/ Weld configuration \u2194 number of lines\n    const cfg = $(\"config\").value, lines = $(\"lines\");\n    if (cfg === \"single\") { lines.value = \"1\"; lines.readOnly = true; }\n    else {\n      lines.readOnly = false;\n      if (cfg === \"parallel\" && (!NUM_RE.test(lines.value.trim()) || parseFloat(lines.value) < 2)) lines.value = \"2\";\n    }\n    const ex = {\n      single: \"Single weld: one weld line. Total effective length = entered length.\",\n      parallel: \"Parallel welds: two or more identical lines (e.g. both sides of a lap joint) sharing the load equally. Total effective length = length \u00d7 number of lines.\",\n      group: \"User-defined group: any number of identical lines, loaded through the group centroid. Total effective length = length \u00d7 number of lines. Eccentric or torsional loading is not covered.\"\n    };\n    $(\"config-explain\").textContent = ex[cfg];\n    \/\/ Unit labels\n    root.querySelectorAll(\".js-strength-unit\").forEach(el => { el.textContent = $(\"strengthUnit\").value; });\n    root.querySelectorAll(\".js-force-unit\").forEach(el => { el.textContent = $(\"forceUnit\").value; });\n    \/\/ Clear messages of hidden fields\n    NUMERIC_IDS.forEach(id => { if (!isShown(id)) setMsg(id, null); });\n  }\n  function setMsg(id, m) {\n    const el = $(id), out = $(id + \"-msg\");\n    if (!out) return;\n    out.textContent = m ? m.text : \"\";\n    out.className = \"msg\" + (m ? \" \" + m.type : \"\");\n    if (m && m.type === \"error\") el.setAttribute(\"aria-invalid\", \"true\");\n    else el.removeAttribute(\"aria-invalid\");\n  }\n  \/* Parse and validate one numeric field.  Returns { value } or { error }. *\/\n  function parseField(id, opts) {\n    const raw = $(id).value.trim();\n    if (raw === \"\") return opts.optional ? { value: opts.default, empty: true } : { error: \"This field is required.\" };\n    if (!NUM_RE.test(raw)) return { error: \"Enter a valid number (digits only, use \u201c.\u201d for decimals).\" };\n    const v = parseFloat(raw);\n    if (!isFinite(v)) return { error: \"Enter a valid number.\" };\n    if (opts.allowZero ? v < 0 : v <= 0) return { error: opts.allowZero ? \"Value cannot be negative.\" : \"Value must be greater than zero.\" };\n    if (opts.integer &#038;&#038; !Number.isInteger(v)) return { error: \"Enter a whole number.\" };\n    if (opts.minHard !== undefined &#038;&#038; v < opts.minHard) return { error: opts.minMsg };\n    if (opts.maxHard !== undefined &#038;&#038; v > opts.maxHard) return { error: opts.maxMsg };\n    return { value: v };\n  }\n  \/* Reads and validates all visible inputs.\n     onlyId: when set, only that field's inline message is updated (blur validation). *\/\n  function collect(onlyId) {\n    const msgs = {}, warnings = [];\n    let ok = true;\n    const inp = {\n      mode: radio(\"mode\"), weldType: radio(\"weldType\"), sizeKind: radio(\"sizeKind\"),\n      penetration: $(\"penetration\").value, areaInput: radio(\"areaInput\"),\n      config: $(\"config\").value, method: $(\"method\").value,\n      direction: $(\"direction\").value, applyDir: false,\n      betaW: parseFloat($(\"betaW\").value)\n    };\n    const su = $(\"strengthUnit\").value, lu = $(\"lengthUnit\").value, zu = $(\"sizeUnit\").value;\n    const fu = $(\"forceUnit\").value, au = $(\"areaUnit\").value;\n    const fillet = inp.weldType === \"fillet\";\n    const cjp = !fillet && inp.penetration === \"cjp\";\n    const direct = !fillet && inp.areaInput === \"area\";\n    if (!fillet) inp.sizeKind = \"throat\";\n    inp.applyDir = isShown(\"applyDir\") && $(\"applyDir\").checked;\n    const num = (id, opts) => {\n      if (!isShown(id)) return undefined;\n      const r = parseField(id, opts || {});\n      if (r.error) { ok = false; msgs[id] = { type: \"error\", text: r.error }; return undefined; }\n      return r.value;\n    };\n    const warn = (id, text) => {\n      warnings.push(text);\n      if (id && !msgs[id]) msgs[id] = { type: \"warn\", text };\n    };\n    const rangeWarn = (id, val, key, show, label) => {\n      if (val === undefined) return;\n      const [lo, hi] = CONFIG.RANGES[key];\n      if (val < lo || val > hi) warn(id, label + \" is outside the typical range of \" + show(lo) + \"\u2013\" + show(hi) + \". Check the value.\");\n    };\n    const showLen = v => fmt(fromMM(v, zu), lenDec(zu)) + \" \" + zu;\n    const showLenL = v => fmt(fromMM(v, lu), lu === \"in\" ? 2 : 0) + \" \" + lu;\n    const showStr = v => fmt(fromMPa(v, su), su === \"ksi\" ? 1 : 0) + \" \" + su;\n    \/\/ Geometry\n    let s = num(\"size\");\n    if (s !== undefined) {\n      inp.size = toMM(s, zu);\n      if (fillet && inp.sizeKind === \"leg\") rangeWarn(\"size\", inp.size, \"filletLeg\", showLen, \"Leg size\");\n      else if (cjp) rangeWarn(\"size\", inp.size, \"cjpThick\", showLen, \"Thickness\");\n      else rangeWarn(\"size\", inp.size, \"throat\", showLen, \"Effective throat\");\n    }\n    let L = num(\"length\");\n    if (L !== undefined) { inp.length = toMM(L, lu); rangeWarn(\"length\", inp.length, \"length\", showLenL, \"Weld length\"); }\n    if (isShown(\"lines\")) {\n      const parallel = inp.config === \"parallel\";\n      inp.lines = num(\"lines\", { integer: true, minHard: parallel ? 2 : 1, minMsg: \"Parallel welds need at least 2 weld lines.\" });\n      if (inp.lines !== undefined && inp.lines > CONFIG.RANGES.lines[1]) warn(\"lines\", \"More than \" + CONFIG.RANGES.lines[1] + \" weld lines is unusual for a simple group. Check that all lines really share the load equally.\");\n    } else inp.lines = 1;\n    let A = num(\"area\");\n    if (A !== undefined) {\n      inp.area = toMM2(A, au);\n      const [lo, hi] = CONFIG.RANGES.area;\n      if (inp.area < lo || inp.area > hi) warn(\"area\", \"Effective area is outside the typical range of \" + fmt(fromMM2(lo, au), au === \"in2\" ? 3 : 0) + \"\u2013\" + fmt(fromMM2(hi, au), 0) + \" \" + (au === \"in2\" ? \"in\u00b2\" : \"mm\u00b2\") + \".\");\n    }\n    \/\/ Short fillet weld check (length vs. size)\n    if (fillet && !direct && inp.size !== undefined && inp.length !== undefined) {\n      const w = inp.sizeKind === \"leg\" ? inp.size : inp.size \/ CONFIG.FILLET_THROAT_FACTOR;\n      const a = inp.sizeKind === \"leg\" ? inp.size * CONFIG.FILLET_THROAT_FACTOR : inp.size;\n      if (inp.method === \"ec3\") {\n        if (inp.length < Math.max(30, 6 * a)) warn(\"length\", \"EN 1993-1-8 \u00a74.5.1 does not count fillet welds shorter than max(30 mm, 6a) as load-carrying.\");\n      } else if (inp.length < 4 * w) {\n        warn(\"length\", \"Effective length is less than 4 \u00d7 leg size. AISC J2.2b limits the effective weld size for such short welds.\");\n      }\n    }\n    \/\/ Material\n    let fs = num(\"strength\");\n    if (fs !== undefined) { inp.strength = toMPa(fs, su); rangeWarn(\"strength\", inp.strength, \"strength\", showStr, \"Strength\"); }\n    let fy = num(\"baseFy\");\n    if (fy !== undefined) {\n      inp.baseFy = toMPa(fy, su);\n      rangeWarn(\"baseFy\", inp.baseFy, \"baseFy\", showStr, \"Yield strength\");\n      if (inp.strength !== undefined &#038;&#038; inp.baseFy >= inp.strength) warn(\"baseFy\", \"Base metal yield is at or above the entered filler strength. Confirm that the filler metal is matching.\");\n    }\n    let k = num(\"customK\");\n    if (k !== undefined) {\n      inp.customK = k;\n      if (k >= 1) warn(\"customK\", \"k \u2265 1 means the design stress is at or above the entered tensile strength, which is unsafe for design.\");\n      else rangeWarn(\"customK\", k, \"customK\", v => v.toFixed(2), \"Coefficient k\");\n    }\n    \/\/ Loading\n    if (inp.direction === \"custom\") {\n      inp.angleDeg = num(\"angle\", { allowZero: true, maxHard: 90, maxMsg: \"Angle must be between 0\u00b0 and 90\u00b0.\" });\n    } else inp.angleDeg = inp.direction === \"parallel\" ? 0 : 90;\n    let P = num(\"load\");\n    if (P !== undefined) inp.load = toN(P, fu);\n    const fRes = isShown(\"factor\") ? parseField(\"factor\", { optional: true, default: 1 }) : { value: 1 };\n    if (fRes.error) { ok = false; msgs.factor = { type: \"error\", text: fRes.error }; }\n    else {\n      inp.factor = fRes.value;\n      if (inp.factor < 1) warn(\"factor\", \"A factor below 1.00 increases the reported capacity and removes margin.\");\n      else if (inp.factor > CONFIG.RANGES.factor[1]) warn(\"factor\", \"Factor above \" + CONFIG.RANGES.factor[1].toFixed(1) + \" is unusually high. Check the value.\");\n      else if (inp.factor > 1 && inp.method !== \"custom\") warnings.push(\"The selected code method already includes \u03c6 \/ \u03a9 \/ \u03b3 factors. The additional factor of \" + fmt(inp.factor, 2) + \" adds further conservatism on top.\");\n    }\n    NUMERIC_IDS.forEach(id => { if (!onlyId || id === onlyId) setMsg(id, msgs[id] || null); });\n    return { ok, inp, warnings, msgs, units: { su, lu, zu, fu, au } };\n  }\n  function statusFor(u) {\n    if (u > CONFIG.STATUS.limit) return { cls: \"bad\", fill: \"fill-bad\", text: \"Exceeds estimated capacity\", icon: \"\u2715\" };\n    if (u >= CONFIG.STATUS.nearLimit) return { cls: \"near\", fill: \"fill-near\", text: \"Below estimated capacity (small margin)\", icon: \"!\" };\n    return { cls: \"ok\", fill: \"fill-ok\", text: \"Below estimated capacity\", icon: \"\u2713\" };\n  }\n  function row(th, td, sub) {\n    return \"<tr><th scope=\\\"row\\\">\" + th + \"<\/th><td>\" + td + (sub ? \"<span class=\\\"f\\\">\" + sub + \"<\/span>\" : \"\") + \"<\/td><\/tr>\";\n  }\n  function render(c) {\n    const { inp, units, warnings } = c;\n    const r = computeWeld(inp);\n    const { su, lu, zu, fu, au } = units;\n    const fillet = inp.weldType === \"fillet\";\n    const cjp = !fillet && inp.penetration === \"cjp\";\n    const direct = !fillet && inp.areaInput === \"area\";\n    const areaU = direct ? au : (zu === \"in\" && lu === \"in\" ? \"in2\" : \"mm2\");\n    const areaLabel = areaU === \"in2\" ? \"in\u00b2\" : \"mm\u00b2\";\n    const b = r.basis;\n    let h = \"\";\n    h += \"<div class=\\\"headline\\\"><p class=\\\"k\\\">\" + b.capacityLabel + (inp.factor !== 1 ? \" \u00f7 factor\" : \"\") + \"<\/p>\";\n    h += \"<p class=\\\"v\\\">\" + fmtForce(r.capacity, fu) + \"<small>\" + fu + \"<\/small><\/p>\";\n    h += \"<p class=\\\"s\\\">\" + b.methodLabel + \" \u00b7 compare with \" + b.compareWith + \"<\/p><\/div>\";\n    if (inp.mode === \"utilization\") {\n      const u = r.utilization, st = statusFor(u);\n      const w = Math.min(u, 150) \/ 150 * 100;\n      h += \"<div class=\\\"util\\\"><div class=\\\"util-top\\\"><div><div style=\\\"font-size:13.6px;color:var(--muted);font-weight:600\\\">Load utilization<\/div>\";\n      h += \"<div class=\\\"pct\\\">\" + fmt(u, 1) + \"%<\/div><\/div>\";\n      h += \"<span class=\\\"badge \" + st.cls + \"\\\"><span aria-hidden=\\\"true\\\">\" + st.icon + \"<\/span>\" + st.text + \"<\/span><\/div>\";\n      h += \"<div class=\\\"meter\\\" role=\\\"img\\\" aria-label=\\\"Utilization \" + fmt(u, 1) + \" percent of estimated capacity\\\"><span class=\\\"\" + st.fill + \"\\\" style=\\\"width:\" + w.toFixed(2) + \"%\\\"><\/span><i class=\\\"tick\\\" style=\\\"left:\" + (100 \/ 150 * 100).toFixed(2) + \"%\\\"><\/i><\/div>\";\n      h += \"<div class=\\\"meter-scale\\\" aria-hidden=\\\"true\\\"><span>0%<\/span><span style=\\\"margin-left:auto;margin-right:calc(33.3% - 1.5em)\\\">100%<\/span><span>150%+<\/span><\/div>\";\n      h += \"<p style=\\\"margin:9.6px 0 0;font-size:14.4px\\\">Applied load <strong>\" + fmtForce(inp.load, fu) + \" \" + fu + \"<\/strong> vs. estimated capacity <strong>\" + fmtForce(r.capacity, fu) + \" \" + fu + \"<\/strong><\/p><\/div>\";\n    }\n    h += \"<table class=\\\"kv\\\"><caption>Calculation details<\/caption><tbody>\";\n    h += row(\"Calculation mode\", inp.mode === \"utilization\" ? \"Utilization of applied load\" : \"Estimated weld capacity\");\n    h += row(\"Weld type\", fillet ? \"Fillet weld\" : \"Butt (groove) weld \u2013 \" + (cjp ? \"complete joint penetration (CJP)\" : \"partial joint penetration (PJP)\"));\n    if (!direct) {\n      const cfgName = { single: \"Single weld\", parallel: \"Parallel welds\", group: \"User-defined weld group\" }[inp.config];\n      h += row(\"Weld configuration\", cfgName + \" \u2013 \" + inp.lines + \" line\" + (inp.lines > 1 ? \"s\" : \"\"));\n      let thSub = \"\";\n      if (fillet && inp.sizeKind === \"leg\") thSub = \"= \" + CONFIG.FILLET_THROAT_FACTOR + \" \u00d7 leg \" + fmt(fromMM(inp.size, zu), lenDec(zu)) + \" \" + zu;\n      else if (fillet) thSub = \"entered directly\";\n      else if (cjp) thSub = \"= thickness of thinner part\";\n      else thSub = \"PJP effective throat, entered\";\n      h += row(\"Effective throat\", fmt(fromMM(r.throat, zu), lenDec(zu)) + \" \" + zu, thSub);\n      h += row(\"Length per weld line\", fmt(fromMM(inp.length, lu), 2) + \" \" + lu);\n      h += row(\"Total effective length\", fmt(fromMM(r.totalLength, lu), 2) + \" \" + lu, \"= \" + fmt(fromMM(inp.length, lu), 2) + \" \u00d7 \" + inp.lines + \" line\" + (inp.lines > 1 ? \"s\" : \"\"));\n      h += row(\"Effective weld area\", fmt(fromMM2(r.area, areaU), 2) + \" \" + areaLabel, \"= throat \u00d7 total length\");\n    } else {\n      h += row(\"Effective weld area\", fmt(fromMM2(r.area, areaU), 2) + \" \" + areaLabel, \"entered directly\");\n    }\n    h += row(inp.method === \"ec3\" ? \"Ultimate strength fu\" : \"Weld metal strength FEXX\", fmt(fromMPa(inp.strength, su), 2) + \" \" + su,\n             b.strengthSource === \"base\" ? \"reference only; base metal governs\" : \"\");\n    if (b.strengthSource === \"base\") h += row(\"Base metal yield Fy\", fmt(fromMPa(inp.baseFy, su), 2) + \" \" + su);\n    const dirName = { parallel: \"Parallel to weld axis\", transverse: \"Transverse to weld axis\", custom: \"Custom angle\" }[inp.direction];\n    h += row(\"Load direction\", dirName + \" (\u03b8 = \" + fmt(b.theta, 2) + \"\u00b0)\");\n    h += row(\"Stress basis\", b.methodLabel, b.formula + (b.factors ? \"; \" + b.factors : \"\"));\n    h += row(\"Design \/ allowable stress\", fmt(fromMPa(b.stress, su), 2) + \" \" + su);\n    if (inp.factor !== 1) h += row(\"Capacity before extra factor\", fmtForce(r.basisCapacity, fu) + \" \" + fu);\n    h += row(\"Additional safety \/ design factor\", fmt(inp.factor, 2) + (inp.factor === 1 ? \" (none)\" : \"\"));\n    h += row(\"Estimated capacity\", \"<strong>\" + fmtForce(r.capacity, fu) + \" \" + fu + \"<\/strong>\", \"= area \u00d7 stress \u00f7 factor\");\n    if (inp.mode === \"utilization\") {\n      h += row(\"Applied load\", fmtForce(inp.load, fu) + \" \" + fu);\n      h += row(\"Utilization\", \"<strong>\" + fmt(r.utilization, 1) + \"%<\/strong>\", \"= applied load \u00f7 capacity \u00d7 100\");\n    }\n    h += \"<\/tbody><\/table>\";\n    const assumptions = [];\n    if (!direct) assumptions.push(\"All \" + inp.lines + \" weld line\" + (inp.lines > 1 ? \"s have\" : \" has\") + \" the same size and length and share the load equally, with the load acting through the weld group centroid (no eccentricity, torsion or bending).\");\n    else assumptions.push(\"Effective area entered directly; its derivation must follow the selected design method.\");\n    if (fillet && inp.sizeKind === \"leg\") assumptions.push(\"Equal-leg fillet with a 90\u00b0 root: throat = \" + CONFIG.FILLET_THROAT_FACTOR + \" \u00d7 leg. Penetration beyond the root is ignored.\");\n    b.notes.forEach(n => assumptions.push(n));\n    assumptions.push(\"Fatigue, weld quality and defects, joint fit-up and base metal limit states are not evaluated.\");\n    h += \"<div class=\\\"res-list\\\"><h3>Assumptions<\/h3><ul>\" + assumptions.map(a => \"<li>\" + a + \"<\/li>\").join(\"\") + \"<\/ul><\/div>\";\n    if (warnings.length) h += \"<div class=\\\"res-list warns\\\"><h3>Warnings<\/h3><ul>\" + warnings.map(w => \"<li>\" + w + \"<\/li>\").join(\"\") + \"<\/ul><\/div>\";\n    h += \"<p class=\\\"disclaimer-sm\\\">Preliminary estimate only. Verify against the applicable design code and have the design reviewed by a qualified structural or welding engineer.<\/p>\";\n    $(\"results\").innerHTML = h;\n    hasResult = true;\n  }\n  function onCalculate(e) {\n    if (e) e.preventDefault();\n    const c = collect();\n    const summary = $(\"form-summary\");\n    if (!c.ok) {\n      const n = Object.values(c.msgs).filter(m => m.type === \"error\").length;\n      summary.textContent = \"Please correct \" + n + \" field\" + (n > 1 ? \"s\" : \"\") + \" marked below before calculating.\";\n      summary.hidden = false;\n      const first = NUMERIC_IDS.find(id => c.msgs[id] && c.msgs[id].type === \"error\");\n      $(\"results-col\").hidden = true;\n      hasResult = false;\n      if (first) $(first).focus();\n      return;\n    }\n    summary.hidden = true;\n    render(c);\n    $(\"results-col\").hidden = false;          \/\/ results appear only after Calculate\n    $(\"results-title\").scrollIntoView({ behavior: \"smooth\", block: \"start\" });\n  }\n  function markStale() {\n    if (!hasResult || $(\"results\").querySelector(\".stale\")) return;\n    const p = document.createElement(\"p\");\n    p.className = \"stale\";\n    p.textContent = \"Inputs have changed. Press Calculate to update the results.\";\n    $(\"results\").prepend(p);\n  }\n  \/* ---- Wire up events ---- *\/\n  const form = $(\"calc-form\");\n  form.addEventListener(\"submit\", onCalculate);\n  form.addEventListener(\"change\", () => { updateUI(); markStale(); });\n  form.addEventListener(\"input\", markStale);\n  NUMERIC_IDS.forEach(id => {\n    $(id).addEventListener(\"blur\", () => {\n      const el = $(id);\n      if (el.value.trim() !== \"\" || el.getAttribute(\"aria-invalid\") === \"true\") collect(id);\n    });\n  });\n  updateUI();\n}\n\/* Initialise every calculator container on the page (also works when a\n   caching \/ \"delay JS\" plugin moves or defers this script). *\/\nfunction boot() {\n  Array.prototype.forEach.call(document.querySelectorAll(\".wsc-weld-calculator\"), initCalculator);\n}\nif (document.readyState === \"loading\") document.addEventListener(\"DOMContentLoaded\", boot);\nelse boot();\n})();\n<\/script>\n\n\n\n<!-- Weld Strength Calculator \u2014 self-contained embed. All CSS is scoped to #wsc; all IDs\/classes are prefixed \"wsc-\". -->\n<div id=\"wsc\" class=\"wsc-root\">\n<style>\n  #wsc {\n    --bg: #f3f5f7;\n    --surface: #ffffff;\n    --surface-2: #f7f9fb;\n    --ink: #17212c;\n    --muted: #4a5767;\n    --line: #d3dae2;\n    --line-strong: #aab5c2;\n    --steel: #1f3247;\n    --steel-2: #2b4561;\n    --accent: #1d5fa8;        \n    --accent-hover: #164a84;\n    --accent-soft: #e8f0fa;\n    --ok: #1d6b39;\n    --ok-soft: #e6f4ea;\n    --warn: #1d4f91;\n    --warn-soft: #eaf2fc;\n    --bad: #b3261e;\n    --bad-soft: #fde8e7;\n    --focus: #1a5fb4;\n    --radius: 10px;\n    --shadow: 0 1px 2px rgba(16, 24, 40, .06), 0 2px 8px rgba(16, 24, 40, .05);\n    --font: system-ui, -apple-system, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif;\n    --mono: ui-monospace, SFMono-Regular, Menlo, Consolas, \"Liberation Mono\", monospace; }\n  \/* Isolation: everything is scoped to #wsc so nothing here affects the rest of the page,\n     and this local reset stops theme styles (headings, tables, buttons, inputs) leaking in. *\/\n  #wsc { display: block; max-width: 920px; margin: 0 auto; padding: 0; text-align: left; font-family: var(--font); font-size: 16px; font-weight: 400; line-height: 1.5; letter-spacing: normal; text-transform: none; color: var(--ink); background: transparent; }\n  #wsc :where(h2,h3,p,ul,ol,li,dl,dt,dd,table,caption,tbody,tr,th,td,fieldset,legend,label,form,section,aside,div,span,button,input,select,pre) {\n    margin: 0; padding: 0; border: 0; background: none; box-shadow: none; text-shadow: none; text-transform: none; letter-spacing: normal;\n    font-family: inherit; font-size: inherit; line-height: inherit; color: inherit; float: none; max-width: none; min-width: 0; height: auto; text-decoration: none; font-style: normal; font-variant: normal; }\n  #wsc :where(small, strong, b, sub, sup, code) { font-style: normal; text-transform: none; letter-spacing: normal; }\n  #wsc :where(input[type=\"text\"], select, button) { -webkit-appearance: none; appearance: none; border-radius: 0; transition: none; }\n  #wsc :where(table) { border-collapse: collapse; border-spacing: 0; table-layout: auto; width: auto; }\n  #wsc :where(h2, h3, legend, th, strong, b) { font-weight: 700; }\n  #wsc :where(strong, b) { font-weight: 700; color: inherit; }\n  #wsc :where(sub, sup) { font-size: 75%; line-height: 0; position: relative; vertical-align: baseline; }\n  #wsc :where(sub) { bottom: -0.25em; } #wsc :where(sup) { top: -0.5em; }\n  #wsc :where(ul) { list-style: disc; }\n  #wsc input[type=\"text\"]:focus, #wsc select:focus { outline: 3px solid var(--focus); outline-offset: 1px; box-shadow: none; border-color: var(--focus); }\n  #wsc .wsc-sr-only { position: absolute !important; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }\n  #wsc, #wsc *, #wsc *::before, #wsc *::after { box-sizing: border-box; }\n  #wsc {\n    margin: 0; font-family: var(--font); color: var(--ink); background: var(--bg);\n    line-height: 1.5; font-size: 16px; }\n  #wsc :focus-visible { outline: 3px solid var(--focus); outline-offset: 2px; }\n  #wsc .wsc-layout { display: grid; grid-template-columns: minmax(0, 1fr); gap: 24px; margin: 0; }\n@media (max-width: 960px) {\n  #wsc .wsc-layout { grid-template-columns: 1fr; }\n}\n  #wsc .wsc-card { background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius); box-shadow: var(--shadow); }\n  #wsc .wsc-card-head { padding: 16px 20px; border-bottom: 1px solid var(--line); display: flex; justify-content: space-between; align-items: center; gap: 12px; }\n  #wsc .wsc-card-head h2 { margin: 0; font-size: 17.6px; }\n  #wsc .wsc-card-body { padding: 18px 20px 20px; }\n  #wsc form section + section { margin-top: 22px; padding-top: 20px; border-top: 1px dashed var(--line); }\n  #wsc .wsc-section-title { margin: 0 0 12px; font-size: 12.8px; letter-spacing: .1em; text-transform: uppercase; color: var(--muted); font-weight: 700; }\n  #wsc fieldset { border: 0; padding: 0; margin: 0; min-width: 0; }\n  #wsc legend { padding: 0; font-weight: 600; margin-bottom: 8px; font-size: 15.2px; }\n  #wsc .wsc-segmented { display: grid; grid-auto-flow: column; grid-auto-columns: 1fr; gap: 0; border: 1px solid var(--line-strong); border-radius: 8px; overflow: hidden; background: var(--surface-2); }\n  #wsc .wsc-segmented input { position: absolute; opacity: 0; pointer-events: none; }\n  #wsc .wsc-segmented label { display: block; text-align: center; padding: 10px 12px; cursor: pointer; font-weight: 600; font-size: 14.9px; color: var(--ink); border-left: 1px solid var(--line-strong); user-select: none; }\n  #wsc .wsc-segmented label:first-of-type { border-left: 0; }\n  #wsc .wsc-segmented label small { display: block; font-weight: 400; color: var(--muted); font-size: 12.5px; }\n  #wsc .wsc-segmented input:checked + label { background: var(--steel); color: #fff; }\n  #wsc .wsc-segmented input:checked + label small { color: #d4dde7; }\n  #wsc .wsc-segmented input:focus-visible + label { outline: 3px solid var(--focus); outline-offset: -3px; }\n@media (max-width: 480px) {\n  #wsc .wsc-segmented { grid-auto-flow: row; }\n  #wsc .wsc-segmented label { border-left: 0; border-top: 1px solid var(--line-strong); }\n  #wsc .wsc-segmented label:first-of-type { border-top: 0; }\n}\n  #wsc .wsc-grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }\n@media (max-width: 600px) {\n  #wsc .wsc-grid-2 { grid-template-columns: 1fr; }\n}\n  #wsc .wsc-field { margin-top: 14px; }\n  #wsc .wsc-field:first-child { margin-top: 0; }\n  #wsc .wsc-grid-2 .wsc-field { margin-top: 0; }\n  #wsc .wsc-field label, #wsc .wsc-field .wsc-label { display: block; font-weight: 600; font-size: 14.9px; margin-bottom: 6px; }\n  #wsc .wsc-field .wsc-segmented label { margin-bottom: 0; }\n  #wsc .wsc-field .wsc-opt { font-weight: 400; color: var(--muted); }\n  #wsc .wsc-hint { font-size: 13.3px; color: var(--muted); margin: 6px 0 0; }\n  #wsc .wsc-input-unit { display: flex; align-items: stretch; }\n  #wsc .wsc-input-unit input { flex: 1 1 auto; min-width: 0; border-top-right-radius: 0; border-bottom-right-radius: 0; }\n  #wsc .wsc-input-unit select { flex: 0 0 auto; width: auto; min-width: 84px; border-top-left-radius: 0; border-bottom-left-radius: 0; border-left: 0; background-color: var(--surface-2); }\n  #wsc input[type=\"text\"], #wsc select {\n    width: 100%; font: inherit; color: var(--ink); background: var(--surface);\n    border: 1px solid var(--line-strong); border-radius: 8px; padding: 10px 12px; min-height: 44px; }\n  #wsc select { appearance: none; -webkit-appearance: none; padding-right: 34px;\n    background-image: linear-gradient(45deg, transparent 50%, var(--muted) 50%), linear-gradient(135deg, var(--muted) 50%, transparent 50%);\n    background-position: calc(100% - 18px) 50%, calc(100% - 12px) 50%; background-size: 6px 6px; background-repeat: no-repeat; }\n  #wsc input[readonly] { background: var(--surface-2); color: var(--muted); }\n  #wsc input:disabled, #wsc select:disabled { background: #eef1f4; color: #6b7785; cursor: not-allowed; }\n  #wsc input[aria-invalid=\"true\"] { border-color: var(--bad); box-shadow: 0 0 0 1px var(--bad) inset; }\n  #wsc .wsc-msg { font-size: 13.4px; margin: 6px 0 0; display: none; align-items: flex-start; gap: 6px; }\n  #wsc .wsc-msg.wsc-show { display: flex; }\n  #wsc .wsc-msg.wsc-error { color: var(--bad); font-weight: 600; }\n  #wsc .wsc-msg.wsc-warn { color: var(--warn); }\n  #wsc .wsc-msg::before { flex: 0 0 auto; font-weight: 800; }\n  #wsc .wsc-msg.wsc-error::before { content: \"\u2715\"; }\n  #wsc .wsc-msg.wsc-warn::before { content: \"!\"; display: inline-grid; place-items: center; width: 16px; height: 16px; border-radius: 50%; background: #2f6fbf; color: #fff; font-size: 11.2px; margin-top: 2px; }\n  #wsc .wsc-check { display: flex; gap: 10px; align-items: flex-start; margin-top: 14px; }\n  #wsc .wsc-check input { width: 20px; height: 20px; margin: 2px 0 0; accent-color: var(--steel); flex: 0 0 auto; }\n  #wsc .wsc-check label { font-weight: 600; font-size: 14.9px; }\n  #wsc .wsc-check .wsc-hint { margin-top: 2px; }\n  #wsc .wsc-actions { display: flex; flex-wrap: wrap; justify-content: center; gap: 10px; margin-top: 24px; padding-top: 18px; border-top: 1px solid var(--line); }\n  #wsc .wsc-btn { font: inherit; font-weight: 700; border-radius: 8px; padding: 11px 20px; min-height: 44px; cursor: pointer; border: 1px solid transparent; }\n  #wsc .wsc-btn-primary { background: var(--accent); color: #fff; min-width: 320px; padding: 13px 32px; font-size: 16.8px; }\n  #wsc .wsc-btn-primary:hover { background: var(--accent-hover); }\n  #wsc .wsc-btn-secondary { background: var(--surface); color: var(--steel); border-color: var(--line-strong); }\n  #wsc .wsc-btn-secondary:hover { background: var(--surface-2); border-color: var(--steel); }\n  #wsc .wsc-btn-ghost { background: transparent; color: var(--steel); border-color: transparent; text-decoration: underline; text-underline-offset: 3px; }\n  #wsc .wsc-btn-ghost:hover { background: var(--surface-2); }\n@media (max-width: 480px) {\n  #wsc .wsc-actions .wsc-btn { flex: 1 1 100%; min-width: 0; }\n}\n  #wsc .wsc-formula { font-family: var(--mono); font-size: 13.1px; background: var(--surface-2); border: 1px solid var(--line); border-radius: 6px; padding: 6px 10px; margin-top: 8px; color: var(--steel); overflow-x: auto; }\n  #wsc .wsc-results { scroll-margin-top: 96px; }\n  #wsc .wsc-results[hidden] { display: none; }\n  #wsc .wsc-results .wsc-card-head { background: var(--steel-2); color: #fff; border-radius: var(--radius) var(--radius) 0 0; border-bottom: 0; }\n  #wsc .wsc-results .wsc-card-head h2 { color: #fff; }\n  #wsc .wsc-mode-tag { font-size: 12px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; background: rgba(255,255,255,.14); padding: 4px 8px; border-radius: 99px; }\n  #wsc .wsc-empty { color: var(--muted); text-align: center; padding: 28px 8px; }\n  #wsc .wsc-empty .wsc-big { font-size: 35.2px; color: var(--line-strong); line-height: 1; }\n  #wsc .wsc-headline { text-align: left; }\n  #wsc .wsc-headline .wsc-label { font-size: 13.1px; text-transform: uppercase; letter-spacing: .08em; color: var(--muted); font-weight: 700; }\n  #wsc .wsc-headline .wsc-value { font-size: clamp(30.4px, 4vw, 40px); font-weight: 800; letter-spacing: -.02em; color: var(--ink); line-height: 1.1; margin-top: 4px; font-variant-numeric: tabular-nums; }\n  #wsc .wsc-headline .wsc-value .wsc-unit { font-size: .55em; font-weight: 700; color: var(--muted); margin-left: 4px; }\n  #wsc .wsc-headline .wsc-sub { color: var(--muted); font-size: 14.1px; margin-top: 2px; }\n  #wsc .wsc-util-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; margin-top: 16px; }\n  #wsc .wsc-util-grid div { background: var(--surface-2); border: 1px solid var(--line); border-radius: 8px; padding: 10px; }\n  #wsc .wsc-util-grid dt { font-size: 11.8px; text-transform: uppercase; letter-spacing: .06em; color: var(--muted); font-weight: 700; }\n  #wsc .wsc-util-grid dd { margin: 4px 0 0; font-weight: 800; font-variant-numeric: tabular-nums; font-size: 16.3px; }\n@media (max-width: 420px) {\n  #wsc .wsc-util-grid { grid-template-columns: 1fr; }\n}\n  #wsc .wsc-bar { margin-top: 14px; height: 14px; background: #e6eaef; border-radius: 99px; overflow: hidden; position: relative; }\n  #wsc .wsc-bar span { display: block; height: 100%; border-radius: 99px; transition: width .35s ease; }\n  #wsc .wsc-bar.wsc-ok span { background: var(--ok); }\n  #wsc .wsc-bar.wsc-near span { background: #2f6fbf; }\n  #wsc .wsc-bar.wsc-over span { background: var(--bad); }\n  #wsc .wsc-bar-scale { display: flex; justify-content: space-between; font-size: 11.8px; color: var(--muted); margin-top: 4px; }\n  #wsc .wsc-status { margin-top: 16px; display: flex; gap: 10px; align-items: center; padding: 10px 14px; border-radius: 8px; font-weight: 700; border: 1px solid; }\n  #wsc .wsc-status .wsc-ico { width: 24px; height: 24px; border-radius: 50%; display: grid; place-items: center; color: #fff; font-size: 13.6px; flex: 0 0 auto; }\n  #wsc .wsc-status.wsc-ok { background: var(--ok-soft); color: var(--ok); border-color: #a9d6b7; }\n  #wsc .wsc-status.wsc-ok .wsc-ico { background: var(--ok); }\n  #wsc .wsc-status.wsc-near { background: var(--warn-soft); color: var(--warn); border-color: #b6cdeb; }\n  #wsc .wsc-status.wsc-near .wsc-ico { background: #2f6fbf; }\n  #wsc .wsc-status.wsc-over { background: var(--bad-soft); color: var(--bad); border-color: #f1b3ae; }\n  #wsc .wsc-status.wsc-over .wsc-ico { background: var(--bad); }\n  #wsc .wsc-status.wsc-info { background: var(--surface-2); color: var(--steel); border-color: var(--line); }\n  #wsc .wsc-status.wsc-info .wsc-ico { background: var(--steel); }\n  #wsc .wsc-details { margin-top: 18px; }\n  #wsc .wsc-details h3, #wsc .wsc-result-block h3 { font-size: 12.8px; text-transform: uppercase; letter-spacing: .1em; color: var(--muted); margin: 0 0 8px; }\n  #wsc table.wsc-kv { width: 100%; border-collapse: collapse; font-size: 14.4px; }\n  #wsc table.wsc-kv th, #wsc table.wsc-kv td { padding: 7px 0; border-bottom: 1px solid var(--line); vertical-align: top; }\n  #wsc table.wsc-kv th { text-align: left; font-weight: 500; color: var(--muted); padding-right: 12px; width: 48%; }\n  #wsc table.wsc-kv td { text-align: right; font-weight: 600; font-variant-numeric: tabular-nums; }\n  #wsc table.wsc-kv td .wsc-alt { display: block; font-weight: 400; color: var(--muted); font-size: 12.8px; }\n  #wsc table.wsc-kv tr:last-child th, #wsc table.wsc-kv tr:last-child td { border-bottom: 0; }\n  #wsc .wsc-result-block { margin-top: 18px; }\n  #wsc .wsc-result-block ul { margin: 0; padding-left: 18px; font-size: 13.9px; color: var(--ink); }\n  #wsc .wsc-result-block li + li { margin-top: 4px; }\n  #wsc .wsc-result-block.wsc-warnings { background: var(--warn-soft); border: 1px solid #b6cdeb; border-radius: 8px; padding: 12px 14px; }\n  #wsc .wsc-result-block.wsc-warnings h3 { color: var(--warn); }\n  #wsc .wsc-result-block.wsc-errors { background: var(--bad-soft); border: 1px solid #f1b3ae; border-radius: 8px; padding: 12px 14px; }\n  #wsc .wsc-result-block.wsc-errors h3 { color: var(--bad); }\n  #wsc .wsc-fine { margin-top: 18px; font-size: 12.8px; color: var(--muted); border-top: 1px solid var(--line); padding-top: 12px; }\n@media print {\n  #wsc .wsc-actions { display: none; }\n  #wsc .wsc-layout { grid-template-columns: 1fr; }\n  #wsc .wsc-card { box-shadow: none; }\n}\n@media (prefers-reduced-motion: reduce) {\n  #wsc .wsc-bar span { transition: none; }\n}\n<\/style>\n<div class=\"wsc-layout\">\n    <!-- ======================= INPUT FORM ======================= -->\n    <div class=\"wsc-card\" id=\"wsc-calculator\">\n      <div class=\"wsc-card-head\"><h2>Inputs<\/h2><\/div>\n      <div class=\"wsc-card-body\">\n        <form id=\"wsc-weldForm\" novalidate>\n          <section aria-labelledby=\"wsc-sec-mode\">\n            <h3 class=\"wsc-section-title\" id=\"wsc-sec-mode\">1 \u00b7 What to calculate<\/h3>\n            <fieldset>\n              <legend class=\"wsc-sr-only\">Calculation mode<\/legend>\n              <div class=\"wsc-segmented\">\n                <input type=\"radio\" name=\"mode\" id=\"wsc-mode-capacity\" value=\"capacity\" checked>\n                <label for=\"wsc-mode-capacity\">Estimated Weld Capacity<small>How much load can it carry?<\/small><\/label>\n                <input type=\"radio\" name=\"mode\" id=\"wsc-mode-util\" value=\"utilization\">\n                <label for=\"wsc-mode-util\">Load Utilization<small>Check an applied load<\/small><\/label>\n              <\/div>\n            <\/fieldset>\n            <fieldset style=\"margin-top:16px\">\n              <legend>Weld type<\/legend>\n              <div class=\"wsc-segmented\">\n                <input type=\"radio\" name=\"weldType\" id=\"wsc-type-fillet\" value=\"fillet\" checked>\n                <label for=\"wsc-type-fillet\">Fillet Weld<\/label>\n                <input type=\"radio\" name=\"weldType\" id=\"wsc-type-butt\" value=\"butt\">\n                <label for=\"wsc-type-butt\">Butt Weld (Groove)<\/label>\n              <\/div>\n            <\/fieldset>\n          <\/section>\n          <section aria-labelledby=\"wsc-sec-geom\">\n            <h3 class=\"wsc-section-title\" id=\"wsc-sec-geom\">2 \u00b7 Weld geometry<\/h3>\n            <!-- Butt weld method (butt only) -->\n            <div class=\"wsc-field\" id=\"wsc-buttMethodField\" hidden>\n              <label for=\"wsc-buttMethod\">Butt weld calculation method<\/label>\n              <select id=\"wsc-buttMethod\" aria-describedby=\"wsc-buttMethod-hint\">\n                <option value=\"pjp\" selected>Partial joint penetration (PJP) \u2014 enter effective throat<\/option>\n                <option value=\"cjp\">Complete joint penetration (CJP) \u2014 throat = thinner part<\/option>\n                <option value=\"area\">Enter effective weld area directly<\/option>\n              <\/select>\n              <p class=\"wsc-hint\" id=\"wsc-buttMethod-hint\">Full penetration is <strong>not<\/strong> assumed. Select CJP only if the joint is designed, qualified and inspected as complete joint penetration.<\/p>\n            <\/div>\n            <!-- Fillet size basis (fillet only) -->\n            <fieldset class=\"wsc-field\" id=\"wsc-sizeBasisField\">\n              <legend>Fillet size entered as<\/legend>\n              <div class=\"wsc-segmented\">\n                <input type=\"radio\" name=\"sizeBasis\" id=\"wsc-basis-leg\" value=\"leg\" checked>\n                <label for=\"wsc-basis-leg\">Leg size (w)<\/label>\n                <input type=\"radio\" name=\"sizeBasis\" id=\"wsc-basis-throat\" value=\"throat\">\n                <label for=\"wsc-basis-throat\">Effective throat (a)<\/label>\n              <\/div>\n            <\/fieldset>\n            <div class=\"wsc-grid-2\" style=\"margin-top:14px\">\n              <div class=\"wsc-field\" id=\"wsc-configField\">\n                <label for=\"wsc-config\">Weld configuration<\/label>\n                <select id=\"wsc-config\" aria-describedby=\"wsc-config-hint\">\n                  <option value=\"single\" selected>Single weld<\/option>\n                  <option value=\"parallel\">Parallel welds<\/option>\n                  <option value=\"group\">User-defined weld group<\/option>\n                <\/select>\n              <\/div>\n              <div class=\"wsc-field\" id=\"wsc-linesField\">\n                <label for=\"wsc-lines\">Number of weld lines<\/label>\n                <input type=\"text\" id=\"wsc-lines\" inputmode=\"numeric\" value=\"1\" readonly aria-describedby=\"wsc-lines-error wsc-lines-warn\">\n                <p class=\"wsc-msg wsc-error\" id=\"wsc-lines-error\" role=\"alert\"><\/p>\n                <p class=\"wsc-msg wsc-warn\" id=\"wsc-lines-warn\"><\/p>\n              <\/div>\n            <\/div>\n            <p class=\"wsc-hint\" id=\"wsc-config-hint\"><\/p>\n            <div class=\"wsc-grid-2\" style=\"margin-top:14px\">\n              <div class=\"wsc-field\" id=\"wsc-sizeField\">\n                <label for=\"wsc-size\" id=\"wsc-size-label\">Weld leg size (w)<\/label>\n                <div class=\"wsc-input-unit\">\n                  <input type=\"text\" id=\"wsc-size\" inputmode=\"decimal\" autocomplete=\"off\" aria-describedby=\"wsc-size-hint wsc-size-error wsc-size-warn\">\n                  <select id=\"wsc-sizeUnit\" aria-label=\"Weld size unit\"><option value=\"mm\" selected>mm<\/option><option value=\"in\">in<\/option><\/select>\n                <\/div>\n                <p class=\"wsc-hint\" id=\"wsc-size-hint\">Equal-leg fillet. Throat = 0.707 \u00d7 leg.<\/p>\n                <p class=\"wsc-msg wsc-error\" id=\"wsc-size-error\" role=\"alert\"><\/p>\n                <p class=\"wsc-msg wsc-warn\" id=\"wsc-size-warn\"><\/p>\n              <\/div>\n              <div class=\"wsc-field\" id=\"wsc-lengthField\">\n                <label for=\"wsc-length\">Effective length per weld line<\/label>\n                <div class=\"wsc-input-unit\">\n                  <input type=\"text\" id=\"wsc-length\" inputmode=\"decimal\" autocomplete=\"off\" aria-describedby=\"wsc-length-hint wsc-length-error wsc-length-warn\">\n                  <select id=\"wsc-lengthUnit\" aria-label=\"Weld length unit\"><option value=\"mm\" selected>mm<\/option><option value=\"in\">in<\/option><\/select>\n                <\/div>\n                <p class=\"wsc-hint\" id=\"wsc-length-hint\">Exclude start\/stop craters and returns per your code.<\/p>\n                <p class=\"wsc-msg wsc-error\" id=\"wsc-length-error\" role=\"alert\"><\/p>\n                <p class=\"wsc-msg wsc-warn\" id=\"wsc-length-warn\"><\/p>\n              <\/div>\n            <\/div>\n            <div class=\"wsc-field\" id=\"wsc-areaField\" hidden>\n              <label for=\"wsc-area\">Effective weld area (total)<\/label>\n              <div class=\"wsc-input-unit\">\n                <input type=\"text\" id=\"wsc-area\" inputmode=\"decimal\" autocomplete=\"off\" aria-describedby=\"wsc-area-hint wsc-area-error wsc-area-warn\">\n                <select id=\"wsc-areaUnit\" aria-label=\"Weld area unit\"><option value=\"mm2\" selected>mm\u00b2<\/option><option value=\"in2\">in\u00b2<\/option><\/select>\n              <\/div>\n              <p class=\"wsc-hint\" id=\"wsc-area-hint\">Effective throat \u00d7 effective length, summed over all weld lines, as defined by your design code.<\/p>\n              <p class=\"wsc-msg wsc-error\" id=\"wsc-area-error\" role=\"alert\"><\/p>\n              <p class=\"wsc-msg wsc-warn\" id=\"wsc-area-warn\"><\/p>\n            <\/div>\n          <\/section>\n          <section aria-labelledby=\"wsc-sec-mat\">\n            <h3 class=\"wsc-section-title\" id=\"wsc-sec-mat\">3 \u00b7 Material &amp; design basis<\/h3>\n            <div class=\"wsc-grid-2\">\n              <div class=\"wsc-field\">\n                <label for=\"wsc-electrode\">Electrode \/ filler classification <span class=\"wsc-opt\">(optional preset)<\/span><\/label>\n                <select id=\"wsc-electrode\">\n                  <option value=\"\" selected>Custom value<\/option>\n                  <option value=\"ksi:60\">E60XX \u2014 60 ksi<\/option>\n                  <option value=\"ksi:70\">E70XX \u2014 70 ksi<\/option>\n                  <option value=\"ksi:80\">E80XX \u2014 80 ksi<\/option>\n                  <option value=\"ksi:90\">E90XX \u2014 90 ksi<\/option>\n                  <option value=\"ksi:100\">E100XX \u2014 100 ksi<\/option>\n                  <option value=\"ksi:110\">E110XX \u2014 110 ksi<\/option>\n                  <option value=\"MPa:430\">E43xx (ISO 2560) \u2014 430 MPa<\/option>\n                  <option value=\"MPa:490\">E49xx (ISO 2560) \u2014 490 MPa<\/option>\n                <\/select>\n              <\/div>\n              <div class=\"wsc-field\">\n                <label for=\"wsc-strength\">Weld metal tensile strength (F<sub>EXX<\/sub>)<\/label>\n                <div class=\"wsc-input-unit\">\n                  <input type=\"text\" id=\"wsc-strength\" inputmode=\"decimal\" autocomplete=\"off\" aria-describedby=\"wsc-strength-hint wsc-strength-error wsc-strength-warn\">\n                  <select id=\"wsc-strengthUnit\" aria-label=\"Strength unit\"><option value=\"MPa\" selected>MPa<\/option><option value=\"ksi\">ksi<\/option><\/select>\n                <\/div>\n                <p class=\"wsc-hint\" id=\"wsc-strength-hint\">Classification tensile strength \u2014 not an allowable stress.<\/p>\n                <p class=\"wsc-msg wsc-error\" id=\"wsc-strength-error\" role=\"alert\"><\/p>\n                <p class=\"wsc-msg wsc-warn\" id=\"wsc-strength-warn\"><\/p>\n              <\/div>\n            <\/div>\n            <div class=\"wsc-field\">\n              <label for=\"wsc-stressBasis\">Stress basis<\/label>\n              <select id=\"wsc-stressBasis\" aria-describedby=\"wsc-stressBasis-formula\">\n                <option value=\"asd\" selected>ASD-style allowable stress: 0.60\u00b7F_EXX \u00f7 \u03a9 (\u03a9 = 2.00)<\/option>\n                <option value=\"lrfd\">LRFD-style design stress: \u03c6\u00b70.60\u00b7F_EXX (\u03c6 = 0.75)<\/option>\n                <option value=\"nominal\">Nominal weld shear strength: 0.60\u00b7F_EXX (no factor)<\/option>\n                <option value=\"custom\">Custom coefficient \u00d7 F_EXX<\/option>\n              <\/select>\n              <div class=\"wsc-formula\" id=\"wsc-stressBasis-formula\" aria-live=\"polite\"><\/div>\n            <\/div>\n            <div class=\"wsc-grid-2\" style=\"margin-top:14px\">\n              <div class=\"wsc-field\" id=\"wsc-customKField\" hidden>\n                <label for=\"wsc-customK\">Custom stress coefficient (k)<\/label>\n                <input type=\"text\" id=\"wsc-customK\" inputmode=\"decimal\" autocomplete=\"off\" aria-describedby=\"wsc-customK-hint wsc-customK-error wsc-customK-warn\">\n                <p class=\"wsc-hint\" id=\"wsc-customK-hint\">Stress = k \u00d7 F<sub>EXX<\/sub>. State its source in your records.<\/p>\n                <p class=\"wsc-msg wsc-error\" id=\"wsc-customK-error\" role=\"alert\"><\/p>\n                <p class=\"wsc-msg wsc-warn\" id=\"wsc-customK-warn\"><\/p>\n              <\/div>\n              <div class=\"wsc-field\">\n                <label for=\"wsc-sf\">Additional safety \/ design factor <span class=\"wsc-opt\">(optional)<\/span><\/label>\n                <input type=\"text\" id=\"wsc-sf\" inputmode=\"decimal\" autocomplete=\"off\" placeholder=\"1.00\" aria-describedby=\"wsc-sf-hint wsc-sf-error wsc-sf-warn\">\n                <p class=\"wsc-hint\" id=\"wsc-sf-hint\">Capacity is divided by this factor. Blank = 1.00.<\/p>\n                <p class=\"wsc-msg wsc-error\" id=\"wsc-sf-error\" role=\"alert\"><\/p>\n                <p class=\"wsc-msg wsc-warn\" id=\"wsc-sf-warn\"><\/p>\n              <\/div>\n            <\/div>\n          <\/section>\n          <section aria-labelledby=\"wsc-sec-load\">\n            <h3 class=\"wsc-section-title\" id=\"wsc-sec-load\">4 \u00b7 Load<\/h3>\n            <div class=\"wsc-grid-2\">\n              <div class=\"wsc-field\">\n                <label for=\"wsc-direction\">Load direction<\/label>\n                <select id=\"wsc-direction\">\n                  <option value=\"parallel\" selected>Parallel to weld axis (longitudinal)<\/option>\n                  <option value=\"transverse\">Transverse to weld axis<\/option>\n                  <option value=\"custom\">Custom angle<\/option>\n                <\/select>\n              <\/div>\n              <div class=\"wsc-field\" id=\"wsc-angleField\" hidden>\n                <label for=\"wsc-angle\">Angle from weld axis (\u03b8, degrees)<\/label>\n                <input type=\"text\" id=\"wsc-angle\" inputmode=\"decimal\" autocomplete=\"off\" aria-describedby=\"wsc-angle-hint wsc-angle-error\">\n                <p class=\"wsc-hint\" id=\"wsc-angle-hint\">0\u00b0 = parallel, 90\u00b0 = transverse.<\/p>\n                <p class=\"wsc-msg wsc-error\" id=\"wsc-angle-error\" role=\"alert\"><\/p>\n              <\/div>\n            <\/div>\n            <div class=\"wsc-check\" id=\"wsc-dirFactorWrap\">\n              <input type=\"checkbox\" id=\"wsc-applyDir\">\n              <div>\n                <label for=\"wsc-applyDir\">Apply fillet directional strength increase<\/label>\n                <p class=\"wsc-hint\" id=\"wsc-applyDir-hint\">AISC 360 factor (1.0 + 0.50 sin<sup>1.5<\/sup>\u03b8) for linear fillet weld groups loaded in-plane through the centroid. Off by default (conservative).<\/p>\n              <\/div>\n            <\/div>\n            <div class=\"wsc-grid-2\" style=\"margin-top:14px\">\n              <div class=\"wsc-field\" id=\"wsc-loadField\">\n                <label for=\"wsc-load\">Applied load <span class=\"wsc-opt\" id=\"wsc-load-req\">(utilization mode only)<\/span><\/label>\n                <div class=\"wsc-input-unit\">\n                  <input type=\"text\" id=\"wsc-load\" inputmode=\"decimal\" autocomplete=\"off\" aria-describedby=\"wsc-load-error wsc-load-warn\">\n                  <select id=\"wsc-forceUnit\" aria-label=\"Force unit\"><option value=\"N\">N<\/option><option value=\"kN\" selected>kN<\/option><option value=\"lbf\">lbf<\/option><option value=\"kip\">kip<\/option><\/select>\n                <\/div>\n                <p class=\"wsc-msg wsc-error\" id=\"wsc-load-error\" role=\"alert\"><\/p>\n                <p class=\"wsc-msg wsc-warn\" id=\"wsc-load-warn\"><\/p>\n              <\/div>\n              <div class=\"wsc-field\">\n                <p class=\"wsc-hint\" style=\"margin-top:30px\">The force unit also sets the unit used for the capacity result.<\/p>\n              <\/div>\n            <\/div>\n          <\/section>\n          <div class=\"wsc-actions\">\n            <button type=\"submit\" class=\"wsc-btn wsc-btn-primary\">Calculate<\/button>\n          <\/div>\n        <\/form>\n      <\/div>\n    <\/div>\n    <!-- ======================= RESULTS ======================= -->\n    <aside class=\"wsc-card wsc-results\" id=\"wsc-resultsPanel\" aria-labelledby=\"wsc-results-title\" hidden>\n      <div class=\"wsc-card-head\">\n        <h2 id=\"wsc-results-title\">Results<\/h2>\n        <span class=\"wsc-mode-tag\" id=\"wsc-modeTag\">Capacity<\/span>\n      <\/div>\n      <div class=\"wsc-card-body\" id=\"wsc-results\" aria-live=\"polite\" aria-atomic=\"true\">\n        <div class=\"wsc-empty\">\n          <div class=\"wsc-big\" aria-hidden=\"true\">\u2300<\/div>\n          <p>Enter the weld data and press <strong>Calculate<\/strong>.<\/p>\n        <\/div>\n      <\/div>\n    <\/aside>\n  <\/div>\n<script>\/* Weld Strength Calculator logic (base64-encoded so WordPress cannot alter it; readable source is in weld-strength-calculator.html) *\/(function(){var b=\"CihmdW5jdGlvbiAoKSB7CiAgInVzZSBzdHJpY3QiOwogIC8qID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0KICAgICBFRElUQUJMRSBERVNJR04gQVNTVU1QVElPTlMKICAgICBDaGFuZ2UgdmFsdWVzIGhlcmUgdG8gbWF0Y2ggeW91ciBkZXNpZ24gc3RhbmRhcmQgLyBwcmFjdGljZS4KICAgICA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09ICovCiAgY29uc3QgQ09ORklHID0gewogICAgLy8gRWZmZWN0aXZlIHRocm9hdCBvZiBhbiBlcXVhbC1sZWcgOTDCsCBmaWxsZXQgd2VsZDogYSA9IHNpbig0NcKwKSDDlyB3IOKJiCAwLjcwNyDDlyB3LgogICAgRklMTEVUX1RIUk9BVF9GQUNUT1I6IDAuNzA3LAogICAgLy8gU3RyZXNzIGJhc2lzOiBkZXNpZ24gc3RyZXNzIEYgPSBmYWN0b3Igw5cgRl9FWFguCiAgICAvLyBUaGUgdGVuc2lsZSBzdHJlbmd0aCBGX0VYWCBpcyBuZXZlciB1c2VkIGRpcmVjdGx5IGFzIGFuIGFsbG93YWJsZSBzdHJlc3MuCiAgICBTVFJFU1NfQkFTRVM6IHsKICAgICAgYXNkOiB7CiAgICAgICAgbGFiZWw6ICJBU0Qtc3R5bGUgYWxsb3dhYmxlIHN0cmVzcyIsCiAgICAgICAgbm9taW5hbENvZWZmOiAwLjYwLCBvbWVnYTogMi4wMCwgICAgICAgICAgICAgICAvLyBBSVNDIDM2MCBKMi40IHN0eWxlCiAgICAgICAgZ2V0IGZhY3RvcigpIHsgcmV0dXJuIHRoaXMubm9taW5hbENvZWZmIC8gdGhpcy5vbWVnYTsgfSwKICAgICAgICBmb3JtdWxhOiAiRiA9IDAuNjAgw5cgRl9FWFggw7cgzqksICDOqSA9IDIuMDAgIOKGkiAgRiA9IDAuMzAgw5cgRl9FWFgiLAogICAgICAgIGlzRGVzaWduTGV2ZWw6IHRydWUKICAgICAgfSwKICAgICAgbHJmZDogewogICAgICAgIGxhYmVsOiAiTFJGRC1zdHlsZSBkZXNpZ24gc3RyZXNzIiwKICAgICAgICBub21pbmFsQ29lZmY6IDAuNjAsIHBoaTogMC43NSwKICAgICAgICBnZXQgZmFjdG9yKCkgeyByZXR1cm4gdGhpcy5waGkgKiB0aGlzLm5vbWluYWxDb2VmZjsgfSwKICAgICAgICBmb3JtdWxhOiAiRiA9IM+GIMOXIDAuNjAgw5cgRl9FWFgsICDPhiA9IDAuNzUgIOKGkiAgRiA9IDAuNDUgw5cgRl9FWFgiLAogICAgICAgIGlzRGVzaWduTGV2ZWw6IHRydWUKICAgICAgfSwKICAgICAgbm9taW5hbDogewogICAgICAgIGxhYmVsOiAiTm9taW5hbCB3ZWxkIHNoZWFyIHN0cmVuZ3RoICh1bmZhY3RvcmVkKSIsCiAgICAgICAgbm9taW5hbENvZWZmOiAwLjYwLAogICAgICAgIGdldCBmYWN0b3IoKSB7IHJldHVybiB0aGlzLm5vbWluYWxDb2VmZjsgfSwKICAgICAgICBmb3JtdWxhOiAiRiA9IDAuNjAgw5cgRl9FWFggIChub21pbmFsIOKAlCBubyByZXNpc3RhbmNlIG9yIHNhZmV0eSBmYWN0b3IgYXBwbGllZCkiLAogICAgICAgIGlzRGVzaWduTGV2ZWw6IGZhbHNlCiAgICAgIH0sCiAgICAgIGN1c3RvbTogewogICAgICAgIGxhYmVsOiAiQ3VzdG9tIGNvZWZmaWNpZW50IiwKICAgICAgICBmYWN0b3I6IG51bGwsIC8vIHN1cHBsaWVkIGJ5IHVzZXIgKGspCiAgICAgICAgZm9ybXVsYTogIkYgPSBrIMOXIEZfRVhYICAoayBlbnRlcmVkIGJlbG93KSIsCiAgICAgICAgaXNEZXNpZ25MZXZlbDogdHJ1ZQogICAgICB9CiAgICB9LAogICAgLy8gRmlsbGV0IGRpcmVjdGlvbmFsIHN0cmVuZ3RoIGluY3JlYXNlIChBSVNDIDM2MCBFcS4gSjItNSk6IDEuMCArIDAuNTAgw5cgc2luXjEuNSjOuCkKICAgIERJUkVDVElPTkFMOiB7IGJhc2U6IDEuMCwgY29lZmY6IDAuNTAsIGV4cG9uZW50OiAxLjUgfSwKICAgIC8vIFN0YXR1cyB0aHJlc2hvbGRzIG9uIHV0aWxpemF0aW9uICglKQogICAgU1RBVFVTOiB7IG5lYXI6IDkwLCBsaW1pdDogMTAwIH0sCiAgICAvLyBQcmFjdGljYWwgcmFuZ2VzIChTSSB1bml0czogbW0sIG1twrIsIE1QYSkuIFZhbHVlcyBvdXRzaWRlIHRyaWdnZXIgYSBXQVJOSU5HIG9ubHkg4oCUCiAgICAvLyBpbnB1dHMgYXJlIG5ldmVyIGNsYW1wZWQuCiAgICBSQU5HRVM6IHsKICAgICAgZmlsbGV0TGVnOiAgICB7IG1pbjogMywgICBtYXg6IDI1LCAgICAgbGFiZWw6ICJmaWxsZXQgbGVnIHNpemUiLCB1bml0OiAibW0iIH0sCiAgICAgIGZpbGxldFRocm9hdDogeyBtaW46IDIsICAgbWF4OiAxOCwgICAgIGxhYmVsOiAiZmlsbGV0IGVmZmVjdGl2ZSB0aHJvYXQiLCB1bml0OiAibW0iIH0sCiAgICAgIGJ1dHRUaHJvYXQ6ICAgeyBtaW46IDIsICAgbWF4OiAxMDAsICAgIGxhYmVsOiAiYnV0dCB3ZWxkIGVmZmVjdGl2ZSB0aHJvYXQiLCB1bml0OiAibW0iIH0sCiAgICAgIGxlbmd0aDogICAgICAgeyBtaW46IDEwLCAgbWF4OiAzMDAwLCAgIGxhYmVsOiAid2VsZCBsZW5ndGggcGVyIGxpbmUiLCB1bml0OiAibW0iIH0sCiAgICAgIGFyZWE6ICAgICAgICAgeyBtaW46IDEwLCAgbWF4OiA1MDAwMDAsIGxhYmVsOiAiZWZmZWN0aXZlIHdlbGQgYXJlYSIsIHVuaXQ6ICJtbcKyIiB9LAogICAgICBsaW5lczogICAgICAgIHsgbWluOiAxLCAgIG1heDogMTIsICAgICBsYWJlbDogIm51bWJlciBvZiB3ZWxkIGxpbmVzIiwgdW5pdDogIiIgfSwKICAgICAgc3RyZW5ndGg6ICAgICB7IG1pbjogNDAwLCBtYXg6IDgzMCwgICAgbGFiZWw6ICJ3ZWxkIG1ldGFsIHRlbnNpbGUgc3RyZW5ndGgiLCB1bml0OiAiTVBhIiB9LAogICAgICBjdXN0b21LOiAgICAgIHsgbWluOiAwLjEwLCBtYXg6IDAuNjAsICBsYWJlbDogImN1c3RvbSBzdHJlc3MgY29lZmZpY2llbnQiLCB1bml0OiAiIiB9LAogICAgICBzZjogICAgICAgICAgIHsgbWluOiAxLjAsIG1heDogNS4wLCAgICBsYWJlbDogInNhZmV0eSAvIGRlc2lnbiBmYWN0b3IiLCB1bml0OiAiIiB9CiAgICB9CiAgfTsKICAvKiA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09CiAgICAgVU5JVCBDT05WRVJTSU9OUyDigJQgZXZlcnl0aGluZyBpcyBjYWxjdWxhdGVkIGludGVybmFsbHkgaW4KICAgICBTSTogbGVuZ3RoIG1tLCBhcmVhIG1twrIsIHN0cmVzcyBNUGEgKD0gTi9tbcKyKSwgZm9yY2UgTi4KICAgICA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09ICovCiAgY29uc3QgVE9fTU0gICA9IHsgbW06IDEsIGluOiAyNS40IH07ICAgICAgICAgICAgICAgICAgICAgICAgICAvLyAxIGluID0gMjUuNCBtbSAoZXhhY3QpCiAgY29uc3QgVE9fTU0yICA9IHsgbW0yOiAxLCBpbjI6IDY0NS4xNiB9OyAgICAgICAgICAgICAgICAgICAgICAvLyAxIGluwrIgPSAyNS40wrIgbW3CsgogIGNvbnN0IFRPX01QQSAgPSB7IE1QYTogMSwga3NpOiA2Ljg5NDc1NzI5MzE2OCB9OyAgICAgICAgICAgICAgLy8gMSBrc2kgPSA2Ljg5NDc1NyBNUGEKICBjb25zdCBUT19OICAgID0geyBOOiAxLCBrTjogMTAwMCwgbGJmOiA0LjQ0ODIyMTYxNTI2MDUsIGtpcDogNDQ0OC4yMjE2MTUyNjA1IH07IC8vIDEgbGJmID0gNC40NDgyMjIgTgogIGNvbnN0IFVOSVRfTEFCRUwgPSB7IG1tOiAibW0iLCBpbjogImluIiwgbW0yOiAibW3CsiIsIGluMjogImluwrIiLCBNUGE6ICJNUGEiLCBrc2k6ICJrc2kiLCBOOiAiTiIsIGtOOiAia04iLCBsYmY6ICJsYmYiLCBraXA6ICJraXAiIH07CiAgLyogLS0tLS0tLS0tLSBET00gaGVscGVycyAtLS0tLS0tLS0tICovCiAgY29uc3QgJCA9IChpZCkgPT4gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoIndzYy0iICsgaWQpOyAvLyBhbGwgSURzIGFyZSBwcmVmaXhlZCB0byBhdm9pZCBjbGFzaGVzIHdpdGggdGhlIGhvc3QgcGFnZQogIGNvbnN0IGZvcm0gPSAkKCJ3ZWxkRm9ybSIpOwogIGNvbnN0IHJlc3VsdHNFbCA9ICQoInJlc3VsdHMiKTsKICBjb25zdCByYWRpbyA9IChuYW1lKSA9PiBmb3JtLnF1ZXJ5U2VsZWN0b3IoYGlucHV0W25hbWU9IiR7bmFtZX0iXTpjaGVja2VkYCkudmFsdWU7CiAgY29uc3Qgc2hvdyA9IChlbCwgb24pID0+IHsgZWwuaGlkZGVuID0gIW9uOyBlbC5xdWVyeVNlbGVjdG9yQWxsKCJpbnB1dCxzZWxlY3QiKS5mb3JFYWNoKGkgPT4geyBpZiAoIWkuY2xvc2VzdCgiW2hpZGRlbl0iKSB8fCBpLmNsb3Nlc3QoIltoaWRkZW5dIikgPT09IGVsKSBpLmRpc2FibGVkID0gIW9uOyB9KTsgfTsKICAvKiAtLS0tLS0tLS0tIE51bWJlciBmb3JtYXR0aW5nIC0tLS0tLS0tLS0gKi8KICBjb25zdCBmbXQgPSAodiwgZCA9IDIpID0+IHYudG9Mb2NhbGVTdHJpbmcoImVuLVVTIiwgeyBtaW5pbXVtRnJhY3Rpb25EaWdpdHM6IGQsIG1heGltdW1GcmFjdGlvbkRpZ2l0czogZCB9KTsKICBmdW5jdGlvbiBmbXRGb3JjZSh2KSB7CiAgICBjb25zdCBhID0gTWF0aC5hYnModik7CiAgICBjb25zdCBkID0gYSA+PSAxMDAwID8gMCA6IGEgPj0gMTAwID8gMSA6IGEgPj0gMSA\/IDIgOiAzOwogICAgcmV0dXJuIGZtdCh2LCBkKTsKICB9CiAgY29uc3QgZXNjID0gKHMpID0+IFN0cmluZyhzKS5yZXBsYWNlKC9bJjw+Il0vZywgYyA9PiAoeyAiJiI6ICImYW1wOyIsICI8IjogIiZsdDsiLCAiPiI6ICImZ3Q7IiwgJyInOiAiJnF1b3Q7IiB9W2NdKSk7CiAgLyogPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQogICAgIFZBTElEQVRJT04KICAgICA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09ICovCiAgY29uc3QgTlVNX1JFID0gL15bKy1dPyhcZCsoXC5cZCopP3xcLlxkKykoW2VFXVsrLV0\/XGQrKT8kLzsKICBmdW5jdGlvbiBzZXRNc2coaWQsIHR5cGUsIHRleHQpIHsKICAgIGNvbnN0IGVsID0gJChgJHtpZH0tJHt0eXBlfWApOwogICAgaWYgKCFlbCkgcmV0dXJuOwogICAgZWwudGV4dENvbnRlbnQgPSB0ZXh0IHx8ICIiOwogICAgZWwuY2xhc3NMaXN0LnRvZ2dsZSgid3NjLXNob3ciLCAhIXRleHQpOwogIH0KICBmdW5jdGlvbiBjbGVhckZpZWxkKGlkKSB7CiAgICBjb25zdCBpbnB1dCA9ICQoaWQpOwogICAgaWYgKGlucHV0KSBpbnB1dC5yZW1vdmVBdHRyaWJ1dGUoImFyaWEtaW52YWxpZCIpOwogICAgc2V0TXNnKGlkLCAiZXJyb3IiLCAiIik7CiAgICBzZXRNc2coaWQsICJ3YXJuIiwgIiIpOwogIH0KICAvKiogUmVhZHMgYSBudW1lcmljIGlucHV0OyByZXR1cm5zIHtvaywgdmFsdWV9IGFuZCBzaG93cyBpbmxpbmUgZXJyb3JzLiAqLwogIGZ1bmN0aW9uIHJlYWROdW0oaWQsIG9wdHMgPSB7fSkgewogICAgY29uc3QgeyBvcHRpb25hbCA9IGZhbHNlLCBpbnRlZ2VyID0gZmFsc2UsIGFsbG93WmVybyA9IGZhbHNlLCBtaW4gPSBudWxsLCBtYXggPSBudWxsLCBtaW5Nc2cgPSBudWxsIH0gPSBvcHRzOwogICAgY29uc3QgaW5wdXQgPSAkKGlkKTsKICAgIGNvbnN0IHJhdyA9IGlucHV0LnZhbHVlLnRyaW0oKTsKICAgIGNvbnN0IGZhaWwgPSAobXNnKSA9PiB7IGlucHV0LnNldEF0dHJpYnV0ZSgiYXJpYS1pbnZhbGlkIiwgInRydWUiKTsgc2V0TXNnKGlkLCAiZXJyb3IiLCBtc2cpOyByZXR1cm4geyBvazogZmFsc2UgfTsgfTsKICAgIGlmIChyYXcgPT09ICIiKSByZXR1cm4gb3B0aW9uYWwgPyB7IG9rOiB0cnVlLCB2YWx1ZTogbnVsbCB9IDogZmFpbCgiVGhpcyBmaWVsZCBpcyByZXF1aXJlZC4iKTsKICAgIGlmICghTlVNX1JFLnRlc3QocmF3KSkgcmV0dXJuIGZhaWwoIkVudGVyIGEgbnVtZXJpYyB2YWx1ZSAoZGlnaXRzIGFuZCBhbiBvcHRpb25hbCBkZWNpbWFsIHBvaW50KS4iKTsKICAgIGNvbnN0IHYgPSBwYXJzZUZsb2F0KHJhdyk7CiAgICBpZiAoIU51bWJlci5pc0Zpbml0ZSh2KSkgcmV0dXJuIGZhaWwoIkVudGVyIGEgZmluaXRlIG51bWJlci4iKTsKICAgIGlmIChhbGxvd1plcm8gPyB2IDwgMCA6IHYgPD0gMCkgcmV0dXJuIGZhaWwoYWxsb3daZXJvID8gIlZhbHVlIGNhbm5vdCBiZSBuZWdhdGl2ZS4iIDogKHYgPT09IDAgPyAiVmFsdWUgbXVzdCBiZSBncmVhdGVyIHRoYW4gemVyby4iIDogIk5lZ2F0aXZlIHZhbHVlcyBhcmUgbm90IGFsbG93ZWQuIikpOwogICAgaWYgKGludGVnZXIgJiYgIU51bWJlci5pc0ludGVnZXIodikpIHJldHVybiBmYWlsKCJFbnRlciBhIHdob2xlIG51bWJlci4iKTsKICAgIGlmIChtaW4gIT09IG51bGwgJiYgdiA8IG1pbikgcmV0dXJuIGZhaWwobWluTXNnIHx8IGBNaW5pbXVtIHZhbHVlIGlzICR7bWlufS5gKTsKICAgIGlmIChtYXggIT09IG51bGwgJiYgdiA+IG1heCkgcmV0dXJuIGZhaWwoYE1heGltdW0gdmFsdWUgaXMgJHttYXh9LmApOwogICAgcmV0dXJuIHsgb2s6IHRydWUsIHZhbHVlOiB2IH07CiAgfQogIC8qKiBSYW5nZSB3YXJuaW5nIChkb2VzIG5vdCBjbGFtcCkuIHNpVmFsdWUgaXMgaW4gdGhlIFJBTkdFUyB1bml0LiAqLwogIGZ1bmN0aW9uIHJhbmdlV2FybihpZCwga2V5LCBzaVZhbHVlLCB3YXJuaW5ncywgZGlzcGxheVVuaXRUZXh0KSB7CiAgICBjb25zdCByID0gQ09ORklHLlJBTkdFU1trZXldOwogICAgaWYgKCFyIHx8IHNpVmFsdWUgPT09IG51bGwpIHJldHVybjsKICAgIGlmIChzaVZhbHVlIDwgci5taW4gfHwgc2lWYWx1ZSA+IHIubWF4KSB7CiAgICAgIGNvbnN0IHUgPSByLnVuaXQgPyAiICIgKyByLnVuaXQgOiAiIjsKICAgICAgY29uc3QgbXNnID0gYE91dHNpZGUgdHlwaWNhbCByYW5nZSBmb3IgJHtyLmxhYmVsfSAoJHtyLm1pbn3igJMke3IubWF4fSR7dX0pLiBWYWx1ZSB1c2VkIGFzIGVudGVyZWQg4oCUIHBsZWFzZSBkb3VibGUtY2hlY2suYDsKICAgICAgc2V0TXNnKGlkLCAid2FybiIsIG1zZyk7CiAgICAgIHdhcm5pbmdzLnB1c2goYCR7Y2FwaXRhbGl6ZShyLmxhYmVsKX0gJHtkaXNwbGF5VW5pdFRleHQgPyAiKCIgKyBkaXNwbGF5VW5pdFRleHQgKyAiKSAiIDogIiJ9aXMgb3V0c2lkZSB0aGUgdHlwaWNhbCByYW5nZSBvZiAke3IubWlufeKAkyR7ci5tYXh9JHt1fS5gKTsKICAgIH0KICB9CiAgY29uc3QgY2FwaXRhbGl6ZSA9IChzKSA9PiBzLmNoYXJBdCgwKS50b1VwcGVyQ2FzZSgpICsgcy5zbGljZSgxKTsKICAvKiA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09CiAgICAgVUkgU1RBVEUg4oCUIHNob3cvaGlkZSBmaWVsZHMgYmFzZWQgb24gc2VsZWN0aW9ucwogICAgID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0gKi8KICBmdW5jdGlvbiB1cGRhdGVVSSgpIHsKICAgIGNvbnN0IG1vZGUgPSByYWRpbygibW9kZSIpOwogICAgY29uc3QgdHlwZSA9IHJhZGlvKCJ3ZWxkVHlwZSIpOwogICAgY29uc3QgYnV0dE1ldGhvZCA9ICQoImJ1dHRNZXRob2QiKS52YWx1ZTsKICAgIGNvbnN0IGRpcmVjdEFyZWEgPSB0eXBlID09PSAiYnV0dCIgJiYgYnV0dE1ldGhvZCA9PT0gImFyZWEiOwogICAgJCgibW9kZVRhZyIpLnRleHRDb250ZW50ID0gbW9kZSA9PT0gImNhcGFjaXR5IiA\/ICJDYXBhY2l0eSIgOiAiVXRpbGl6YXRpb24iOwogICAgJCgibG9hZC1yZXEiKS50ZXh0Q29udGVudCA9IG1vZGUgPT09ICJjYXBhY2l0eSIgPyAiKG5vdCBuZWVkZWQgZm9yIGNhcGFjaXR5IG1vZGUpIiA6ICIocmVxdWlyZWQpIjsKICAgICQoImxvYWQiKS5kaXNhYmxlZCA9IG1vZGUgPT09ICJjYXBhY2l0eSI7CiAgICBpZiAobW9kZSA9PT0gImNhcGFjaXR5IikgY2xlYXJGaWVsZCgibG9hZCIpOwogICAgc2hvdygkKCJidXR0TWV0aG9kRmllbGQiKSwgdHlwZSA9PT0gImJ1dHQiKTsKICAgIHNob3coJCgic2l6ZUJhc2lzRmllbGQiKSwgdHlwZSA9PT0gImZpbGxldCIpOwogICAgc2hvdygkKCJhcmVhRmllbGQiKSwgZGlyZWN0QXJlYSk7CiAgICBzaG93KCQoInNpemVGaWVsZCIpLCAhZGlyZWN0QXJlYSk7CiAgICBzaG93KCQoImxlbmd0aEZpZWxkIiksICFkaXJlY3RBcmVhKTsKICAgIHNob3coJCgiY29uZmlnRmllbGQiKSwgIWRpcmVjdEFyZWEpOwogICAgc2hvdygkKCJsaW5lc0ZpZWxkIiksICFkaXJlY3RBcmVhKTsKICAgICQoImNvbmZpZy1oaW50IikuaGlkZGVuID0gZGlyZWN0QXJlYTsKICAgIC8vIFNpemUgZmllbGQgbGFiZWwgJiBoaW50CiAgICBjb25zdCBzaXplTGFiZWwgPSAkKCJzaXplLWxhYmVsIiksIHNpemVIaW50ID0gJCgic2l6ZS1oaW50Iik7CiAgICBpZiAodHlwZSA9PT0gImZpbGxldCIpIHsKICAgICAgaWYgKHJhZGlvKCJzaXplQmFzaXMiKSA9PT0gImxlZyIpIHsgc2l6ZUxhYmVsLnRleHRDb250ZW50ID0gIldlbGQgbGVnIHNpemUgKHcpIjsgc2l6ZUhpbnQudGV4dENvbnRlbnQgPSBgRXF1YWwtbGVnIGZpbGxldC4gRWZmZWN0aXZlIHRocm9hdCA9ICR7Q09ORklHLkZJTExFVF9USFJPQVRfRkFDVE9SfSDDlyBsZWcuYDsgfQogICAgICBlbHNlIHsgc2l6ZUxhYmVsLnRleHRDb250ZW50ID0gIkVmZmVjdGl2ZSB0aHJvYXQgKGEpIjsgc2l6ZUhpbnQudGV4dENvbnRlbnQgPSAiVGhlb3JldGljYWwgdGhyb2F0IOKAlCBzaG9ydGVzdCBkaXN0YW5jZSBmcm9tIHJvb3QgdG8gZmFjZS4gVXNlZCBkaXJlY3RseS4iOyB9CiAgICB9IGVsc2UgaWYgKGJ1dHRNZXRob2QgPT09ICJwanAiKSB7CiAgICAgIHNpemVMYWJlbC50ZXh0Q29udGVudCA9ICJFZmZlY3RpdmUgdGhyb2F0IChFKSI7CiAgICAgIHNpemVIaW50LnRleHRDb250ZW50ID0gIlBlciB5b3VyIGNvZGUgZm9yIHRoZSBncm9vdmUgdHlwZSwgYW5nbGUgYW5kIHByb2Nlc3Mg4oCUIHVzdWFsbHkgbGVzcyB0aGFuIHRoZSBncm9vdmUgZGVwdGggb3IgcGxhdGUgdGhpY2tuZXNzLiI7CiAgICB9IGVsc2UgaWYgKGJ1dHRNZXRob2QgPT09ICJjanAiKSB7CiAgICAgIHNpemVMYWJlbC50ZXh0Q29udGVudCA9ICJUaGlubmVyIGNvbm5lY3RlZCBwYXJ0IHRoaWNrbmVzcyAodCkiOwogICAgICBzaXplSGludC50ZXh0Q29udGVudCA9ICJGb3IgQ0pQIHdlbGRzIHRoZSBlZmZlY3RpdmUgdGhyb2F0IGlzIHRha2VuIGFzIHRoZSB0aGlja25lc3Mgb2YgdGhlIHRoaW5uZXIgcGFydCBqb2luZWQuIjsKICAgIH0KICAgIC8vIENvbmZpZ3VyYXRpb24g4oaSIG51bWJlciBvZiBsaW5lcwogICAgY29uc3QgY2ZnID0gJCgiY29uZmlnIikudmFsdWUsIGxpbmVzID0gJCgibGluZXMiKTsKICAgIGNvbnN0IGhpbnQgPSAkKCJjb25maWctaGludCIpOwogICAgaWYgKGNmZyA9PT0gInNpbmdsZSIpIHsKICAgICAgbGluZXMudmFsdWUgPSAiMSI7IGxpbmVzLnJlYWRPbmx5ID0gdHJ1ZTsgY2xlYXJGaWVsZCgibGluZXMiKTsKICAgICAgaGludC50ZXh0Q29udGVudCA9ICJTaW5nbGUgd2VsZDogb25lIGxpbmUuIFRvdGFsIGVmZmVjdGl2ZSBsZW5ndGggPSBlbnRlcmVkIGxlbmd0aC4iOwogICAgfSBlbHNlIGlmIChjZmcgPT09ICJwYXJhbGxlbCIpIHsKICAgICAgbGluZXMucmVhZE9ubHkgPSBmYWxzZTsKICAgICAgaWYgKCFsaW5lcy52YWx1ZSB8fCBwYXJzZUZsb2F0KGxpbmVzLnZhbHVlKSA8IDIpIGxpbmVzLnZhbHVlID0gIjIiOwogICAgICBoaW50LnRleHRDb250ZW50ID0gIlBhcmFsbGVsIHdlbGRzOiB0d28gb3IgbW9yZSBlcXVhbC1sZW5ndGggbGluZXMuIFRvdGFsIGxlbmd0aCA9IGxpbmVzIMOXIGxlbmd0aC4gTG9hZCBhc3N1bWVkIHRvIGFjdCB0aHJvdWdoIHRoZSBncm91cCBjZW50cm9pZCBhbmQgYmUgc2hhcmVkIGVxdWFsbHkuIjsKICAgIH0gZWxzZSB7CiAgICAgIGxpbmVzLnJlYWRPbmx5ID0gZmFsc2U7CiAgICAgIGhpbnQudGV4dENvbnRlbnQgPSAiVXNlci1kZWZpbmVkIGdyb3VwOiBuIGVxdWFsLWxlbmd0aCBsaW5lcywgdG90YWwgbGVuZ3RoID0gbiDDlyBsZW5ndGguIEZvciB1bmVxdWFsIGxpbmVzLCBlbnRlciB0aGUgc3VtbWVkIGxlbmd0aCB3aXRoIDEgbGluZS4gRWNjZW50cmljIGxvYWRpbmcgaXMgbm90IGNvdmVyZWQuIjsKICAgIH0KICAgIC8vIFN0cmVzcyBiYXNpcwogICAgY29uc3QgYmFzaXMgPSAkKCJzdHJlc3NCYXNpcyIpLnZhbHVlOwogICAgc2hvdygkKCJjdXN0b21LRmllbGQiKSwgYmFzaXMgPT09ICJjdXN0b20iKTsKICAgICQoInN0cmVzc0Jhc2lzLWZvcm11bGEiKS50ZXh0Q29udGVudCA9IENPTkZJRy5TVFJFU1NfQkFTRVNbYmFzaXNdLmZvcm11bGE7CiAgICAvLyBMb2FkIGRpcmVjdGlvbgogICAgc2hvdygkKCJhbmdsZUZpZWxkIiksICQoImRpcmVjdGlvbiIpLnZhbHVlID09PSAiY3VzdG9tIik7CiAgICAvLyBEaXJlY3Rpb25hbCBmYWN0b3Igb25seSBmb3IgZmlsbGV0IHdlbGRzCiAgICBjb25zdCBhcHBseURpciA9ICQoImFwcGx5RGlyIik7CiAgICBhcHBseURpci5kaXNhYmxlZCA9IHR5cGUgIT09ICJmaWxsZXQiOwogICAgaWYgKHR5cGUgIT09ICJmaWxsZXQiKSBhcHBseURpci5jaGVja2VkID0gZmFsc2U7CiAgICAkKCJhcHBseURpci1oaW50IikudGV4dENvbnRlbnQgPSB0eXBlID09PSAiZmlsbGV0IgogICAgICA\/ICJBSVNDIDM2MCBmYWN0b3IgKDEuMCArIDAuNTAgc2luwrnCt+KBtc64KSBmb3IgbGluZWFyIGZpbGxldCB3ZWxkIGdyb3VwcyBsb2FkZWQgaW4tcGxhbmUgdGhyb3VnaCB0aGUgY2VudHJvaWQuIE9mZiBieSBkZWZhdWx0IChjb25zZXJ2YXRpdmUpLiIKICAgICAgOiAiTm90IGFwcGxpY2FibGUgdG8gYnV0dCAoZ3Jvb3ZlKSB3ZWxkcy4iOwogIH0KICAvKiAtLS0tLS0tLS0tIENvbnZlcnQgdmFsdWUgd2hlbiBhIHVuaXQgc2VsZWN0b3IgY2hhbmdlcyAtLS0tLS0tLS0tICovCiAgZnVuY3Rpb24gYmluZFVuaXRDb252ZXJzaW9uKGlucHV0SWQsIHNlbGVjdElkLCB0YWJsZSkgewogICAgY29uc3Qgc2VsID0gJChzZWxlY3RJZCk7CiAgICBzZWwuZGF0YXNldC5wcmV2ID0gc2VsLnZhbHVlOwogICAgc2VsLmFkZEV2ZW50TGlzdGVuZXIoImNoYW5nZSIsICgpID0+IHsKICAgICAgY29uc3QgaW5wdXQgPSAkKGlucHV0SWQpOwogICAgICBjb25zdCByYXcgPSBpbnB1dC52YWx1ZS50cmltKCk7CiAgICAgIGNvbnN0IHByZXYgPSBzZWwuZGF0YXNldC5wcmV2LCBuZXh0ID0gc2VsLnZhbHVlOwogICAgICBpZiAocmF3ICE9PSAiIiAmJiBOVU1fUkUudGVzdChyYXcpKSB7CiAgICAgICAgY29uc3Qgc2kgPSBwYXJzZUZsb2F0KHJhdykgKiB0YWJsZVtwcmV2XTsKICAgICAgICBjb25zdCB2ID0gc2kgLyB0YWJsZVtuZXh0XTsKICAgICAgICBpbnB1dC52YWx1ZSA9IFN0cmluZygrdi50b1ByZWNpc2lvbig2KSk7CiAgICAgIH0KICAgICAgc2VsLmRhdGFzZXQucHJldiA9IG5leHQ7CiAgICB9KTsKICB9CiAgLyogPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQogICAgIENBTENVTEFUSU9OCiAgICAgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PSAqLwogIGZ1bmN0aW9uIGNhbGN1bGF0ZSgpIHsKICAgIGNvbnN0IGZpZWxkcyA9IFsibGluZXMiLCAic2l6ZSIsICJsZW5ndGgiLCAiYXJlYSIsICJzdHJlbmd0aCIsICJjdXN0b21LIiwgInNmIiwgImFuZ2xlIiwgImxvYWQiXTsKICAgIGZpZWxkcy5mb3JFYWNoKGNsZWFyRmllbGQpOwogICAgY29uc3QgbW9kZSA9IHJhZGlvKCJtb2RlIik7CiAgICBjb25zdCB0eXBlID0gcmFkaW8oIndlbGRUeXBlIik7CiAgICBjb25zdCBidXR0TWV0aG9kID0gJCgiYnV0dE1ldGhvZCIpLnZhbHVlOwogICAgY29uc3QgZGlyZWN0QXJlYSA9IHR5cGUgPT09ICJidXR0IiAmJiBidXR0TWV0aG9kID09PSAiYXJlYSI7CiAgICBjb25zdCBjZmcgPSAkKCJjb25maWciKS52YWx1ZTsKICAgIGNvbnN0IGJhc2lzS2V5ID0gJCgic3RyZXNzQmFzaXMiKS52YWx1ZTsKICAgIGNvbnN0IGJhc2lzID0gQ09ORklHLlNUUkVTU19CQVNFU1tiYXNpc0tleV07CiAgICBjb25zdCBzaXplVW5pdCA9ICQoInNpemVVbml0IikudmFsdWUsIGxlbmd0aFVuaXQgPSAkKCJsZW5ndGhVbml0IikudmFsdWUsIGFyZWFVbml0ID0gJCgiYXJlYVVuaXQiKS52YWx1ZTsKICAgIGNvbnN0IHN0cmVuZ3RoVW5pdCA9ICQoInN0cmVuZ3RoVW5pdCIpLnZhbHVlLCBmb3JjZVVuaXQgPSAkKCJmb3JjZVVuaXQiKS52YWx1ZTsKICAgIGNvbnN0IHdhcm5pbmdzID0gW107CiAgICBsZXQgb2sgPSB0cnVlOwogICAgY29uc3QgbmVlZCA9IChyKSA9PiB7IGlmICghci5vaykgb2sgPSBmYWxzZTsgcmV0dXJuIHI7IH07CiAgICAvLyAtLS0tIFJlYWQgaW5wdXRzIC0tLS0KICAgIGxldCBuTGluZXMgPSAxLCBzaXplSW4gPSBudWxsLCBsZW5ndGhJbiA9IG51bGwsIGFyZWFJbiA9IG51bGw7CiAgICBpZiAoIWRpcmVjdEFyZWEpIHsKICAgICAgY29uc3QgbWluTGluZXMgPSBjZmcgPT09ICJwYXJhbGxlbCIgPyAyIDogMTsKICAgICAgbkxpbmVzID0gbmVlZChyZWFkTnVtKCJsaW5lcyIsIHsgaW50ZWdlcjogdHJ1ZSwgbWluOiBtaW5MaW5lcywgbWluTXNnOiBjZmcgPT09ICJwYXJhbGxlbCIgPyAiUGFyYWxsZWwgY29uZmlndXJhdGlvbiBuZWVkcyBhdCBsZWFzdCAyIHdlbGQgbGluZXMuIiA6IG51bGwgfSkpLnZhbHVlOwogICAgICBzaXplSW4gPSBuZWVkKHJlYWROdW0oInNpemUiKSkudmFsdWU7CiAgICAgIGxlbmd0aEluID0gbmVlZChyZWFkTnVtKCJsZW5ndGgiKSkudmFsdWU7CiAgICB9IGVsc2UgewogICAgICBhcmVhSW4gPSBuZWVkKHJlYWROdW0oImFyZWEiKSkudmFsdWU7CiAgICB9CiAgICBjb25zdCBmZXh4SW4gPSBuZWVkKHJlYWROdW0oInN0cmVuZ3RoIikpLnZhbHVlOwogICAgY29uc3QgayA9IGJhc2lzS2V5ID09PSAiY3VzdG9tIiA\/IG5lZWQocmVhZE51bSgiY3VzdG9tSyIsIHsgbWF4OiAxLCB9KSkudmFsdWUgOiBiYXNpcy5mYWN0b3I7CiAgICBjb25zdCBzZlJlYWQgPSBuZWVkKHJlYWROdW0oInNmIiwgeyBvcHRpb25hbDogdHJ1ZSB9KSk7CiAgICBjb25zdCBzZiA9IHNmUmVhZC52YWx1ZSA9PT0gbnVsbCB8fCBzZlJlYWQudmFsdWUgPT09IHVuZGVmaW5lZCA\/IDEgOiBzZlJlYWQudmFsdWU7CiAgICBsZXQgdGhldGEgPSAwOwogICAgY29uc3QgZGlyID0gJCgiZGlyZWN0aW9uIikudmFsdWU7CiAgICBpZiAoZGlyID09PSAidHJhbnN2ZXJzZSIpIHRoZXRhID0gOTA7CiAgICBpZiAoZGlyID09PSAiY3VzdG9tIikgdGhldGEgPSBuZWVkKHJlYWROdW0oImFuZ2xlIiwgeyBhbGxvd1plcm86IHRydWUsIG1heDogOTAgfSkpLnZhbHVlOwogICAgY29uc3QgbG9hZFJlYWQgPSBtb2RlID09PSAidXRpbGl6YXRpb24iID8gbmVlZChyZWFkTnVtKCJsb2FkIikpIDogeyBvazogdHJ1ZSwgdmFsdWU6IG51bGwgfTsKICAgIGNvbnN0IGxvYWRJbiA9IGxvYWRSZWFkLnZhbHVlOwogICAgaWYgKCFvaykgewogICAgICBjb25zdCBmaXJzdEJhZCA9IGZvcm0ucXVlcnlTZWxlY3RvcignW2FyaWEtaW52YWxpZD0idHJ1ZSJdJyk7CiAgICAgIGNvbnN0IGNvdW50ID0gZm9ybS5xdWVyeVNlbGVjdG9yQWxsKCdbYXJpYS1pbnZhbGlkPSJ0cnVlIl0nKS5sZW5ndGg7CiAgICAgICQoInJlc3VsdHNQYW5lbCIpLmhpZGRlbiA9IHRydWU7CiAgICAgIGlmIChmaXJzdEJhZCkgZmlyc3RCYWQuZm9jdXMoKTsKICAgICAgcmV0dXJuOwogICAgfQogICAgLy8gLS0tLSBDb252ZXJ0IHRvIFNJIC0tLS0KICAgIGNvbnN0IHNpemVNbSA9IHNpemVJbiAhPT0gbnVsbCA\/IHNpemVJbiAqIFRPX01NW3NpemVVbml0XSA6IG51bGw7CiAgICBjb25zdCBsZW5ndGhNbSA9IGxlbmd0aEluICE9PSBudWxsID8gbGVuZ3RoSW4gKiBUT19NTVtsZW5ndGhVbml0XSA6IG51bGw7CiAgICBjb25zdCBmZXh4TVBhID0gZmV4eEluICogVE9fTVBBW3N0cmVuZ3RoVW5pdF07CiAgICAvLyAtLS0tIEVmZmVjdGl2ZSB0aHJvYXQgLS0tLQogICAgLy8gRmlsbGV0IChsZWcgZW50ZXJlZCk6IGEgPSAwLjcwNyDDlyB3ICAgKGVxdWFsLWxlZyA5MMKwIGZpbGxldCwgdGhyb2F0IGF0IDQ1wrApCiAgICAvLyBGaWxsZXQgKHRocm9hdCBlbnRlcmVkKSAvIFBKUDogYSA9IGVudGVyZWQgdmFsdWUKICAgIC8vIENKUDogYSA9IHRoaWNrbmVzcyBvZiB0aGlubmVyIHBhcnQgam9pbmVkCiAgICBsZXQgdGhyb2F0TW0gPSBudWxsLCB0aHJvYXROb3RlID0gIiI7CiAgICBpZiAoIWRpcmVjdEFyZWEpIHsKICAgICAgaWYgKHR5cGUgPT09ICJmaWxsZXQiKSB7CiAgICAgICAgaWYgKHJhZGlvKCJzaXplQmFzaXMiKSA9PT0gImxlZyIpIHsKICAgICAgICAgIHRocm9hdE1tID0gQ09ORklHLkZJTExFVF9USFJPQVRfRkFDVE9SICogc2l6ZU1tOwogICAgICAgICAgdGhyb2F0Tm90ZSA9IGAke0NPTkZJRy5GSUxMRVRfVEhST0FUX0ZBQ1RPUn0gw5cgbGVnYDsKICAgICAgICAgIHJhbmdlV2Fybigic2l6ZSIsICJmaWxsZXRMZWciLCBzaXplTW0sIHdhcm5pbmdzKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgdGhyb2F0TW0gPSBzaXplTW07IHRocm9hdE5vdGUgPSAiZW50ZXJlZCBkaXJlY3RseSI7CiAgICAgICAgICByYW5nZVdhcm4oInNpemUiLCAiZmlsbGV0VGhyb2F0Iiwgc2l6ZU1tLCB3YXJuaW5ncyk7CiAgICAgICAgfQogICAgICB9IGVsc2UgewogICAgICAgIHRocm9hdE1tID0gc2l6ZU1tOwogICAgICAgIHRocm9hdE5vdGUgPSBidXR0TWV0aG9kID09PSAiY2pwIiA\/ICJ0aGlubmVyIHBhcnQgdGhpY2tuZXNzIChDSlApIiA6ICJlbnRlcmVkIFBKUCBlZmZlY3RpdmUgdGhyb2F0IjsKICAgICAgICByYW5nZVdhcm4oInNpemUiLCAiYnV0dFRocm9hdCIsIHNpemVNbSwgd2FybmluZ3MpOwogICAgICB9CiAgICAgIHJhbmdlV2FybigibGVuZ3RoIiwgImxlbmd0aCIsIGxlbmd0aE1tLCB3YXJuaW5ncyk7CiAgICAgIHJhbmdlV2FybigibGluZXMiLCAibGluZXMiLCBuTGluZXMsIHdhcm5pbmdzKTsKICAgIH0KICAgIC8vIC0tLS0gVG90YWwgbGVuZ3RoIGFuZCBlZmZlY3RpdmUgYXJlYSAtLS0tCiAgICBjb25zdCB0b3RhbExlbmd0aE1tID0gZGlyZWN0QXJlYSA\/IG51bGwgOiBuTGluZXMgKiBsZW5ndGhNbTsKICAgIGNvbnN0IGFyZWFNbTIgPSBkaXJlY3RBcmVhID8gYXJlYUluICogVE9fTU0yW2FyZWFVbml0XSA6IHRocm9hdE1tICogdG90YWxMZW5ndGhNbTsKICAgIGlmIChkaXJlY3RBcmVhKSByYW5nZVdhcm4oImFyZWEiLCAiYXJlYSIsIGFyZWFNbTIsIHdhcm5pbmdzKTsKICAgIC8vIC0tLS0gU3RyZXNzIGJhc2lzIC0tLS0KICAgIHJhbmdlV2Fybigic3RyZW5ndGgiLCAic3RyZW5ndGgiLCBmZXh4TVBhLCB3YXJuaW5ncyk7CiAgICBpZiAoYmFzaXNLZXkgPT09ICJjdXN0b20iKSByYW5nZVdhcm4oImN1c3RvbUsiLCAiY3VzdG9tSyIsIGssIHdhcm5pbmdzKTsKICAgIGNvbnN0IGRlc2lnblN0cmVzc01QYSA9IGsgKiBmZXh4TVBhOwogICAgaWYgKHNmUmVhZC52YWx1ZSAhPT0gbnVsbCkgcmFuZ2VXYXJuKCJzZiIsICJzZiIsIHNmLCB3YXJuaW5ncyk7CiAgICBpZiAoc2YgPCAxKSB3YXJuaW5ncy5wdXNoKCJTYWZldHkgLyBkZXNpZ24gZmFjdG9yIGlzIGJlbG93IDEuMCDigJQgdGhpcyBpbmNyZWFzZXMgdGhlIGVzdGltYXRlZCBjYXBhY2l0eSBhYm92ZSB0aGUgc2VsZWN0ZWQgc3RyZXNzIGJhc2lzLiIpOwogICAgaWYgKCFiYXNpcy5pc0Rlc2lnbkxldmVsICYmIHNmIDw9IDEpIHdhcm5pbmdzLnB1c2goIk5vbWluYWwgKHVuZmFjdG9yZWQpIHN0cmVuZ3RoIHVzZWQgd2l0aG91dCBhbiBhZGRpdGlvbmFsIHNhZmV0eSBmYWN0b3IuIFRoaXMgaXMgTk9UIGFuIGFsbG93YWJsZSBvciBkZXNpZ24gY2FwYWNpdHkuIik7CiAgICAvLyAtLS0tIERpcmVjdGlvbmFsIGZhY3RvciAoZmlsbGV0IG9ubHksIG9wdGlvbmFsKSAtLS0tCiAgICBsZXQga0RpciA9IDE7CiAgICBjb25zdCBhcHBseURpciA9ICQoImFwcGx5RGlyIikuY2hlY2tlZCAmJiB0eXBlID09PSAiZmlsbGV0IjsKICAgIGlmIChhcHBseURpcikgewogICAgICBjb25zdCBEID0gQ09ORklHLkRJUkVDVElPTkFMOwogICAgICBrRGlyID0gRC5iYXNlICsgRC5jb2VmZiAqIE1hdGgucG93KE1hdGguc2luKHRoZXRhICogTWF0aC5QSSAvIDE4MCksIEQuZXhwb25lbnQpOwogICAgfQogICAgLy8gLS0tLSBDYXBhY2l0eTogUiA9IEEgw5cgRiDDlyBLX2RpciDDtyBTRiAgKG1twrIgw5cgTi9tbcKyID0gTikgLS0tLQogICAgY29uc3QgY2FwYWNpdHlOID0gYXJlYU1tMiAqIGRlc2lnblN0cmVzc01QYSAqIGtEaXIgLyBzZjsKICAgIGNvbnN0IGNhcGFjaXR5T3V0ID0gY2FwYWNpdHlOIC8gVE9fTltmb3JjZVVuaXRdOwogICAgLy8gLS0tLSBVdGlsaXphdGlvbiAtLS0tCiAgICBsZXQgdXRpbCA9IG51bGwsIGxvYWROID0gbnVsbDsKICAgIGlmIChtb2RlID09PSAidXRpbGl6YXRpb24iKSB7CiAgICAgIGxvYWROID0gbG9hZEluICogVE9fTltmb3JjZVVuaXRdOwogICAgICB1dGlsID0gbG9hZE4gLyBjYXBhY2l0eU4gKiAxMDA7CiAgICB9CiAgICAvLyBFeHRyYSBlbmdpbmVlcmluZyB3YXJuaW5ncwogICAgaWYgKHR5cGUgPT09ICJidXR0IiAmJiBidXR0TWV0aG9kID09PSAiY2pwIikgd2FybmluZ3MucHVzaCgiQ0pQIGdyb292ZSB3ZWxkcyB3aXRoIG1hdGNoaW5nIGZpbGxlciBhcmUgbm9ybWFsbHkgZ292ZXJuZWQgYnkgdGhlIGJhc2UgbWV0YWwsIG5vdCB0aGUgd2VsZCBtZXRhbC4gQ2hlY2sgYmFzZSBtZXRhbCBjYXBhY2l0eSBzZXBhcmF0ZWx5LiIpOwogICAgaWYgKHR5cGUgPT09ICJmaWxsZXQiICYmIGRpciAhPT0gInBhcmFsbGVsIiAmJiAhYXBwbHlEaXIpIHdhcm5pbmdzLnB1c2goIlRyYW5zdmVyc2UvYW5nbGVkIGxvYWQgb24gYSBmaWxsZXQgd2VsZDogdGhlIGRpcmVjdGlvbmFsIHN0cmVuZ3RoIGluY3JlYXNlIGlzIG5vdCBhcHBsaWVkIChjb25zZXJ2YXRpdmUpLiIpOwogICAgcmVuZGVyKHsKICAgICAgbW9kZSwgdHlwZSwgYnV0dE1ldGhvZCwgZGlyZWN0QXJlYSwgY2ZnLCBuTGluZXMsIHNpemVJbiwgc2l6ZVVuaXQsIGxlbmd0aEluLCBsZW5ndGhVbml0LCBhcmVhVW5pdCwKICAgICAgdGhyb2F0TW0sIHRocm9hdE5vdGUsIHRvdGFsTGVuZ3RoTW0sIGFyZWFNbTIsIGZleHhJbiwgc3RyZW5ndGhVbml0LCBmZXh4TVBhLCBiYXNpc0tleSwgYmFzaXMsIGssCiAgICAgIGRlc2lnblN0cmVzc01QYSwgc2YsIHNmRW50ZXJlZDogc2ZSZWFkLnZhbHVlICE9PSBudWxsLCB0aGV0YSwgZGlyLCBhcHBseURpciwga0RpciwKICAgICAgY2FwYWNpdHlOLCBjYXBhY2l0eU91dCwgZm9yY2VVbml0LCBsb2FkSW4sIHV0aWwsIHdhcm5pbmdzCiAgICB9KTsKICB9CiAgLyogPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQogICAgIFJFTkRFUiBSRVNVTFRTCiAgICAgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PSAqLwogIGZ1bmN0aW9uIHJlbmRlcihyKSB7CiAgICBjb25zdCBsZW5VID0gci5kaXJlY3RBcmVhID8gKHIuYXJlYVVuaXQgPT09ICJpbjIiID8gImluIiA6ICJtbSIpIDogci5sZW5ndGhVbml0OwogICAgY29uc3QgdGhyVSA9IHIuZGlyZWN0QXJlYSA\/IGxlblUgOiByLnNpemVVbml0OwogICAgY29uc3QgZlUgPSBVTklUX0xBQkVMW3IuZm9yY2VVbml0XTsKICAgIGNvbnN0IHNVID0gVU5JVF9MQUJFTFtyLnN0cmVuZ3RoVW5pdF07CiAgICAvLyBEdWFsLXVuaXQgZGlzcGxheSBoZWxwZXJzIChwcmltYXJ5ID0gdXNlcidzIHVuaXQsIHNlY29uZGFyeSA9IHRoZSBvdGhlciBzeXN0ZW0pCiAgICBjb25zdCBkdWFsTGVuID0gKG1tLCB1bml0KSA9PiB7CiAgICAgIGNvbnN0IHAgPSBtbSAvIFRPX01NW3VuaXRdOwogICAgICBjb25zdCBhbHRVID0gdW5pdCA9PT0gIm1tIiA\/ICJpbiIgOiAibW0iOwogICAgICByZXR1cm4gYCR7Zm10KHApfSAke3VuaXR9PHNwYW4gY2xhc3M9IndzYy1hbHQiPiR7Zm10KG1tIC8gVE9fTU1bYWx0VV0sIGFsdFUgPT09ICJpbiIgPyAzIDogMil9ICR7YWx0VX08L3NwYW4+YDsKICAgIH07CiAgICBjb25zdCBhcmVhUHJpbWFyeVUgPSAoci5kaXJlY3RBcmVhID8gci5hcmVhVW5pdCA6IChyLmxlbmd0aFVuaXQgPT09ICJpbiIgPyAiaW4yIiA6ICJtbTIiKSk7CiAgICBjb25zdCBhcmVhQWx0VSA9IGFyZWFQcmltYXJ5VSA9PT0gIm1tMiIgPyAiaW4yIiA6ICJtbTIiOwogICAgY29uc3QgZHVhbEFyZWEgPSBgJHtmbXQoci5hcmVhTW0yIC8gVE9fTU0yW2FyZWFQcmltYXJ5VV0pfSAke1VOSVRfTEFCRUxbYXJlYVByaW1hcnlVXX08c3BhbiBjbGFzcz0id3NjLWFsdCI+JHtmbXQoci5hcmVhTW0yIC8gVE9fTU0yW2FyZWFBbHRVXSwgYXJlYUFsdFUgPT09ICJpbjIiID8gMyA6IDIpfSAke1VOSVRfTEFCRUxbYXJlYUFsdFVdfTwvc3Bhbj5gOwogICAgY29uc3Qgc3RyZXNzQWx0VSA9IHIuc3RyZW5ndGhVbml0ID09PSAiTVBhIiA\/ICJrc2kiIDogIk1QYSI7CiAgICBjb25zdCBkdWFsU3RyZXNzID0gKG1wYSkgPT4gYCR7Zm10KG1wYSAvIFRPX01QQVtyLnN0cmVuZ3RoVW5pdF0pfSAke3NVfTxzcGFuIGNsYXNzPSJ3c2MtYWx0Ij4ke2ZtdChtcGEgLyBUT19NUEFbc3RyZXNzQWx0VV0pfSAke3N0cmVzc0FsdFV9PC9zcGFuPmA7CiAgICBjb25zdCB0eXBlVGV4dCA9IHIudHlwZSA9PT0gImZpbGxldCIgPyAiRmlsbGV0IHdlbGQiCiAgICAgIDogci5idXR0TWV0aG9kID09PSAiY2pwIiA\/ICJCdXR0IHdlbGQg4oCUIGNvbXBsZXRlIGpvaW50IHBlbmV0cmF0aW9uIChDSlApIgogICAgICA6IHIuYnV0dE1ldGhvZCA9PT0gInBqcCIgPyAiQnV0dCB3ZWxkIOKAlCBwYXJ0aWFsIGpvaW50IHBlbmV0cmF0aW9uIChQSlApIgogICAgICA6ICJCdXR0IHdlbGQg4oCUIGVmZmVjdGl2ZSBhcmVhIGVudGVyZWQiOwogICAgY29uc3QgY2ZnVGV4dCA9IHIuZGlyZWN0QXJlYSA\/ICJuL2EgKGFyZWEgZW50ZXJlZCBkaXJlY3RseSkiCiAgICAgIDogci5jZmcgPT09ICJzaW5nbGUiID8gIlNpbmdsZSB3ZWxkIiA6IHIuY2ZnID09PSAicGFyYWxsZWwiID8gIlBhcmFsbGVsIHdlbGRzIiA6ICJVc2VyLWRlZmluZWQgZ3JvdXAiOwogICAgY29uc3QgZGlyVGV4dCA9IHIuZGlyID09PSAicGFyYWxsZWwiID8gIlBhcmFsbGVsICjOuCA9IDDCsCkiIDogci5kaXIgPT09ICJ0cmFuc3ZlcnNlIiA\/ICJUcmFuc3ZlcnNlICjOuCA9IDkwwrApIiA6IGBDdXN0b20gKM64ID0gJHtmbXQoci50aGV0YSl9wrApYDsKICAgIGxldCBodG1sID0gIiI7CiAgICAvLyAtLS0tIEhlYWRsaW5lIC0tLS0KICAgIGh0bWwgKz0gYDxkaXYgY2xhc3M9IndzYy1oZWFkbGluZSI+CiAgICAgIDxkaXYgY2xhc3M9IndzYy1sYWJlbCI+RXN0aW1hdGVkIHdlbGQgY2FwYWNpdHk8L2Rpdj4KICAgICAgPGRpdiBjbGFzcz0id3NjLXZhbHVlIj4ke2ZtdEZvcmNlKHIuY2FwYWNpdHlPdXQpfTxzcGFuIGNsYXNzPSJ3c2MtdW5pdCI+JHtmVX08L3NwYW4+PC9kaXY+CiAgICAgIDxkaXYgY2xhc3M9IndzYy1zdWIiPiR7ZXNjKHIuYmFzaXMubGFiZWwpfSR7ci5zZiAhPT0gMSA\/IGAgw7cgU0YgJHtmbXQoci5zZil9YCA6ICIifSR7ci5rRGlyICE9PSAxID8gYCDDlyBLPHN1Yj5kaXI8L3N1Yj4gJHtmbXQoci5rRGlyLCAzKX1gIDogIiJ9PC9kaXY+CiAgICA8L2Rpdj5gOwogICAgLy8gLS0tLSBVdGlsaXphdGlvbiAtLS0tCiAgICBpZiAoci5tb2RlID09PSAidXRpbGl6YXRpb24iKSB7CiAgICAgIGNvbnN0IHUgPSByLnV0aWw7CiAgICAgIGNvbnN0IGNscyA9IHUgPiBDT05GSUcuU1RBVFVTLmxpbWl0ID8gIm92ZXIiIDogdSA+PSBDT05GSUcuU1RBVFVTLm5lYXIgPyAibmVhciIgOiAib2siOwogICAgICBjb25zdCBzdGF0dXNUZXh0ID0gY2xzID09PSAib3ZlciIgPyAiRXhjZWVkcyBlc3RpbWF0ZWQgY2FwYWNpdHkiIDogY2xzID09PSAibmVhciIgPyAiQ2xvc2UgdG8gZXN0aW1hdGVkIGNhcGFjaXR5IiA6ICJCZWxvdyBlc3RpbWF0ZWQgY2FwYWNpdHkiOwogICAgICBjb25zdCBpY29uID0gY2xzID09PSAib3ZlciIgPyAi4pyVIiA6IGNscyA9PT0gIm5lYXIiID8gIiEiIDogIuKckyI7CiAgICAgIGh0bWwgKz0gYDxkbCBjbGFzcz0id3NjLXV0aWwtZ3JpZCI+CiAgICAgICAgPGRpdj48ZHQ+QXBwbGllZCBsb2FkPC9kdD48ZGQ+JHtmbXRGb3JjZShyLmxvYWRJbil9ICR7ZlV9PC9kZD48L2Rpdj4KICAgICAgICA8ZGl2PjxkdD5DYXBhY2l0eTwvZHQ+PGRkPiR7Zm10Rm9yY2Uoci5jYXBhY2l0eU91dCl9ICR7ZlV9PC9kZD48L2Rpdj4KICAgICAgICA8ZGl2PjxkdD5VdGlsaXphdGlvbjwvZHQ+PGRkPiR7Zm10KHUsIDEpfSAlPC9kZD48L2Rpdj4KICAgICAgPC9kbD4KICAgICAgPGRpdiBjbGFzcz0id3NjLWJhciB3c2MtJHtjbHN9IiByb2xlPSJpbWciIGFyaWEtbGFiZWw9IlV0aWxpemF0aW9uICR7Zm10KHUsIDEpfSBwZXJjZW50IG9mIGVzdGltYXRlZCBjYXBhY2l0eSI+PHNwYW4gc3R5bGU9IndpZHRoOiR7TWF0aC5taW4odSwgMTAwKX0lIj48L3NwYW4+PC9kaXY+CiAgICAgIDxkaXYgY2xhc3M9IndzYy1iYXItc2NhbGUiIGFyaWEtaGlkZGVuPSJ0cnVlIj48c3Bhbj4wJTwvc3Bhbj48c3Bhbj4ke0NPTkZJRy5TVEFUVVMubmVhcn0lPC9zcGFuPjxzcGFuPjEwMCU8L3NwYW4+PC9kaXY+CiAgICAgIDxkaXYgY2xhc3M9IndzYy1zdGF0dXMgd3NjLSR7Y2xzfSIgcm9sZT0ic3RhdHVzIj48c3BhbiBjbGFzcz0id3NjLWljbyIgYXJpYS1oaWRkZW49InRydWUiPiR7aWNvbn08L3NwYW4+PHNwYW4+JHtzdGF0dXNUZXh0fSR7Y2xzID09PSAib3ZlciIgPyBgIChieSAke2ZtdCh1IC0gMTAwLCAxKX0gJSlgIDogIiJ9PC9zcGFuPjwvZGl2PmA7CiAgICB9IGVsc2UgewogICAgICBodG1sICs9IGA8ZGl2IGNsYXNzPSJ3c2Mtc3RhdHVzIHdzYy1pbmZvIiByb2xlPSJzdGF0dXMiPjxzcGFuIGNsYXNzPSJ3c2MtaWNvIiBhcmlhLWhpZGRlbj0idHJ1ZSI+aTwvc3Bhbj48c3Bhbj5DYXBhY2l0eSBlc3RpbWF0ZSDigJQgc3dpdGNoIHRvIExvYWQgVXRpbGl6YXRpb24gdG8gY2hlY2sgYW4gYXBwbGllZCBsb2FkLjwvc3Bhbj48L2Rpdj5gOwogICAgfQogICAgLy8gLS0tLSBEZXRhaWxzIC0tLS0KICAgIGNvbnN0IHJvd3MgPSBbXTsKICAgIHJvd3MucHVzaChbIldlbGQgdHlwZSIsIGVzYyh0eXBlVGV4dCldKTsKICAgIHJvd3MucHVzaChbIkNvbmZpZ3VyYXRpb24iLCBlc2MoY2ZnVGV4dCldKTsKICAgIGlmICghci5kaXJlY3RBcmVhKSB7CiAgICAgIHJvd3MucHVzaChbIk51bWJlciBvZiB3ZWxkIGxpbmVzIiwgU3RyaW5nKHIubkxpbmVzKV0pOwogICAgICBpZiAoci50eXBlID09PSAiZmlsbGV0IiAmJiByYWRpbygic2l6ZUJhc2lzIikgPT09ICJsZWciKSByb3dzLnB1c2goWyJMZWcgc2l6ZSAodykiLCBkdWFsTGVuKHIuc2l6ZUluICogVE9fTU1bci5zaXplVW5pdF0sIHIuc2l6ZVVuaXQpXSk7CiAgICAgIGlmIChyLnR5cGUgPT09ICJidXR0IiAmJiByLmJ1dHRNZXRob2QgPT09ICJjanAiKSByb3dzLnB1c2goWyJUaGlubmVyIHBhcnQgdGhpY2tuZXNzICh0KSIsIGR1YWxMZW4oci5zaXplSW4gKiBUT19NTVtyLnNpemVVbml0XSwgci5zaXplVW5pdCldKTsKICAgICAgcm93cy5wdXNoKFtgRWZmZWN0aXZlIHRocm9hdCA8c3BhbiBjbGFzcz0id3NjLWFsdCIgc3R5bGU9ImRpc3BsYXk6aW5saW5lIj4oJHtlc2Moci50aHJvYXROb3RlKX0pPC9zcGFuPmAsIGR1YWxMZW4oci50aHJvYXRNbSwgdGhyVSldKTsKICAgICAgcm93cy5wdXNoKFsiTGVuZ3RoIHBlciBsaW5lIiwgZHVhbExlbihyLmxlbmd0aEluICogVE9fTU1bci5sZW5ndGhVbml0XSwgci5sZW5ndGhVbml0KV0pOwogICAgICByb3dzLnB1c2goW2BUb3RhbCBlZmZlY3RpdmUgbGVuZ3RoIDxzcGFuIGNsYXNzPSJ3c2MtYWx0IiBzdHlsZT0iZGlzcGxheTppbmxpbmUiPigke3IubkxpbmVzfSDDlyBsZW5ndGgpPC9zcGFuPmAsIGR1YWxMZW4oci50b3RhbExlbmd0aE1tLCBsZW5VKV0pOwogICAgfSBlbHNlIHsKICAgICAgcm93cy5wdXNoKFsiRWZmZWN0aXZlIHRocm9hdCIsICLigJQgKGFyZWEgZW50ZXJlZCkiXSk7CiAgICAgIHJvd3MucHVzaChbIlRvdGFsIGVmZmVjdGl2ZSBsZW5ndGgiLCAi4oCUIChhcmVhIGVudGVyZWQpIl0pOwogICAgfQogICAgcm93cy5wdXNoKFsiRWZmZWN0aXZlIHdlbGQgYXJlYSIsIGR1YWxBcmVhXSk7CiAgICByb3dzLnB1c2goWyJXZWxkIG1ldGFsIHRlbnNpbGUgc3RyZW5ndGggKEY8c3ViPkVYWDwvc3ViPikiLCBkdWFsU3RyZXNzKHIuZmV4eE1QYSldKTsKICAgIHJvd3MucHVzaChbIlN0cmVzcyBiYXNpcyIsIGAke2VzYyhyLmJhc2lzLmxhYmVsKX08c3BhbiBjbGFzcz0id3NjLWFsdCI+ayA9ICR7Zm10KHIuaywgMyl9IMOXIEY8c3ViPkVYWDwvc3ViPjwvc3Bhbj5gXSk7CiAgICByb3dzLnB1c2goWyJEZXNpZ24gLyBhbGxvd2FibGUgc3RyZXNzIHVzZWQiLCBkdWFsU3RyZXNzKHIuZGVzaWduU3RyZXNzTVBhKV0pOwogICAgcm93cy5wdXNoKFsiTG9hZCBkaXJlY3Rpb24iLCBlc2MoZGlyVGV4dCldKTsKICAgIHJvd3MucHVzaChbIkRpcmVjdGlvbmFsIGZhY3RvciAoSzxzdWI+ZGlyPC9zdWI+KSIsIHIuYXBwbHlEaXIgPyBmbXQoci5rRGlyLCAzKSA6ICIxLjAwMCAobm90IGFwcGxpZWQpIl0pOwogICAgcm93cy5wdXNoKFsiU2FmZXR5IC8gZGVzaWduIGZhY3RvciAoU0YpIiwgZm10KHIuc2YpICsgKHIuc2ZFbnRlcmVkID8gIiIgOiAiIChkZWZhdWx0KSIpXSk7CiAgICByb3dzLnB1c2goWyJFc3RpbWF0ZWQgY2FwYWNpdHkiLCBgJHtmbXRGb3JjZShyLmNhcGFjaXR5T3V0KX0gJHtmVX08c3BhbiBjbGFzcz0id3NjLWFsdCI+JHtmbXRGb3JjZShyLmNhcGFjaXR5TiAvIDEwMDApfSBrTiDCtyAke2ZtdEZvcmNlKHIuY2FwYWNpdHlOIC8gVE9fTi5raXApfSBraXA8L3NwYW4+YF0pOwogICAgaHRtbCArPSBgPGRpdiBjbGFzcz0id3NjLWRldGFpbHMiPjxoMz5DYWxjdWxhdGlvbiBkZXRhaWxzPC9oMz48dGFibGUgY2xhc3M9IndzYy1rdiI+PHRib2R5PiR7cm93cy5tYXAoKFtrLCB2XSkgPT4gYDx0cj48dGggc2NvcGU9InJvdyI+JHtrfTwvdGg+PHRkPiR7dn08L3RkPjwvdHI+YCkuam9pbigiIil9PC90Ym9keT48L3RhYmxlPjwvZGl2PmA7CiAgICAvLyAtLS0tIEFzc3VtcHRpb25zIC0tLS0KICAgIGNvbnN0IGFzc3VtcHRpb25zID0gW107CiAgICBpZiAoci50eXBlID09PSAiZmlsbGV0IiAmJiByYWRpbygic2l6ZUJhc2lzIikgPT09ICJsZWciKSBhc3N1bXB0aW9ucy5wdXNoKGBFcXVhbC1sZWcgZmlsbGV0IGluIGEgOTDCsCBqb2ludDsgZWZmZWN0aXZlIHRocm9hdCA9ICR7Q09ORklHLkZJTExFVF9USFJPQVRfRkFDVE9SfSDDlyBsZWcgKG5vIHBlbmV0cmF0aW9uIGNyZWRpdCkuYCk7CiAgICBpZiAoci50eXBlID09PSAiYnV0dCIgJiYgci5idXR0TWV0aG9kID09PSAicGpwIikgYXNzdW1wdGlvbnMucHVzaCgiUEpQIGVmZmVjdGl2ZSB0aHJvYXQgdGFrZW4gYXMgZW50ZXJlZCDigJQgY29uZmlybSBpdCBhZ2FpbnN0IHlvdXIgY29kZSdzIHRhYmxlIGZvciB0aGUgZ3Jvb3ZlIHR5cGUsIGFuZ2xlIGFuZCB3ZWxkaW5nIHByb2Nlc3MuIik7CiAgICBpZiAoci50eXBlID09PSAiYnV0dCIgJiYgci5idXR0TWV0aG9kID09PSAiY2pwIikgYXNzdW1wdGlvbnMucHVzaCgiQ0pQIHNlbGVjdGVkIGV4cGxpY2l0bHk6IGVmZmVjdGl2ZSB0aHJvYXQgPSB0aGlubmVyIHBhcnQgdGhpY2tuZXNzLiBPbmx5IHZhbGlkIGZvciBhIHF1YWxpZmllZCwgaW5zcGVjdGVkIGNvbXBsZXRlLXBlbmV0cmF0aW9uIGpvaW50LiIpOwogICAgaWYgKHIuZGlyZWN0QXJlYSkgYXNzdW1wdGlvbnMucHVzaCgiRWZmZWN0aXZlIHdlbGQgYXJlYSBlbnRlcmVkIGRpcmVjdGx5OyB0aHJvYXQgYW5kIGxlbmd0aCBhcmUgbm90IGNoZWNrZWQuIik7CiAgICBhc3N1bXB0aW9ucy5wdXNoKGBTdHJlc3MgYmFzaXM6ICR7ci5iYXNpcy5mb3JtdWxhLnJlcGxhY2UoImsgZW50ZXJlZCBiZWxvdyIsICJrID0gIiArIGZtdChyLmssIDMpKX0uYCk7CiAgICBhc3N1bXB0aW9ucy5wdXNoKCJXZWxkIG1ldGFsIHN0cmVuZ3RoIG9ubHkg4oCUIGJhc2UgbWV0YWwgc2hlYXIgeWllbGQvcnVwdHVyZSBpcyBub3QgY2hlY2tlZC4iKTsKICAgIGlmICghci5kaXJlY3RBcmVhICYmIHIubkxpbmVzID4gMSkgYXNzdW1wdGlvbnMucHVzaChgTG9hZCBzaGFyZWQgZXF1YWxseSBieSAke3IubkxpbmVzfSBlcXVhbC1sZW5ndGggbGluZXMgYW5kIGFwcGxpZWQgdGhyb3VnaCB0aGUgd2VsZC1ncm91cCBjZW50cm9pZCAobm8gZWNjZW50cmljaXR5KS5gKTsKICAgIGVsc2UgaWYgKCFyLmRpcmVjdEFyZWEpIGFzc3VtcHRpb25zLnB1c2goIkxvYWQgYXBwbGllZCB0aHJvdWdoIHRoZSB3ZWxkIGNlbnRyb2lkIChubyBlY2NlbnRyaWNpdHkgb3IgYmVuZGluZykuIik7CiAgICBhc3N1bXB0aW9ucy5wdXNoKHIuYXBwbHlEaXIgPyBgRmlsbGV0IGRpcmVjdGlvbmFsIGluY3JlYXNlIGFwcGxpZWQ6IEtfZGlyID0gMS4wICsgMC41MCBzaW7CucK34oG1KCR7Zm10KHIudGhldGEsIDApfcKwKSA9ICR7Zm10KHIua0RpciwgMyl9LmAgOiAiTm8gZGlyZWN0aW9uYWwgc3RyZW5ndGggaW5jcmVhc2UgYXBwbGllZC4iKTsKICAgIGFzc3VtcHRpb25zLnB1c2goIlN0YXRpYyBsb2FkaW5nIG9ubHkg4oCUIGZhdGlndWUgaXMgbm90IGNvbnNpZGVyZWQuIik7CiAgICBodG1sICs9IGA8ZGl2IGNsYXNzPSJ3c2MtcmVzdWx0LWJsb2NrIj48aDM+QXNzdW1wdGlvbnMgdXNlZDwvaDM+PHVsPiR7YXNzdW1wdGlvbnMubWFwKGEgPT4gYDxsaT4ke2VzYyhhKX08L2xpPmApLmpvaW4oIiIpfTwvdWw+PC9kaXY+YDsKICAgIGlmIChyLndhcm5pbmdzLmxlbmd0aCkgewogICAgICBodG1sICs9IGA8ZGl2IGNsYXNzPSJ3c2MtcmVzdWx0LWJsb2NrIHdzYy13YXJuaW5ncyI+PGgzPldhcm5pbmdzPC9oMz48dWw+JHtyLndhcm5pbmdzLm1hcCh3ID0+IGA8bGk+JHtlc2Modyl9PC9saT5gKS5qb2luKCIiKX08L3VsPjwvZGl2PmA7CiAgICB9CiAgICBodG1sICs9IGA8cCBjbGFzcz0id3NjLWZpbmUiPlByZWxpbWluYXJ5IGVzdGltYXRlLiBXZWxkIGNhcGFjaXR5IGFsc28gZGVwZW5kcyBvbiBsb2FkIGRpcmVjdGlvbiwgd2VsZCBxdWFsaXR5LCBiYXNlIG1ldGFsIHN0cmVuZ3RoLCBqb2ludCBnZW9tZXRyeSwgZWNjZW50cmljaXR5LCBmYXRpZ3VlIGFuZCB0aGUgYXBwbGljYWJsZSBkZXNpZ24gc3RhbmRhcmQuIFZlcmlmeSB3aXRoIGNvZGUtY29tcGxpYW50IGRlc2lnbiBhbmQgcmV2aWV3IGJ5IGEgcXVhbGlmaWVkIHN0cnVjdHVyYWwgb3Igd2VsZGluZyBlbmdpbmVlci48L3A+YDsKICAgIHJlc3VsdHNFbC5pbm5lckhUTUwgPSBodG1sOwogICAgY29uc3QgcGFuZWwgPSAkKCJyZXN1bHRzUGFuZWwiKTsKICAgIHBhbmVsLmhpZGRlbiA9IGZhbHNlOwogICAgcGFuZWwuc2Nyb2xsSW50b1ZpZXcoeyBiZWhhdmlvcjogbWF0Y2hNZWRpYSgiKHByZWZlcnMtcmVkdWNlZC1tb3Rpb246IHJlZHVjZSkiKS5tYXRjaGVzID8gImF1dG8iIDogInNtb290aCIsIGJsb2NrOiAic3RhcnQiIH0pOwogIH0KICAvKiA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09CiAgICAgRVZFTlRTCiAgICAgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PSAqLwogIGZvcm0uYWRkRXZlbnRMaXN0ZW5lcigic3VibWl0IiwgKGUpID0+IHsgZS5wcmV2ZW50RGVmYXVsdCgpOyBjYWxjdWxhdGUoKTsgfSk7CiAgZm9ybS5hZGRFdmVudExpc3RlbmVyKCJjaGFuZ2UiLCAoZSkgPT4gewogICAgaWYgKGUudGFyZ2V0Lm5hbWUgPT09ICJtb2RlIikgJCgicmVzdWx0c1BhbmVsIikuaGlkZGVuID0gdHJ1ZTsKICAgIGlmIChbIm1vZGUiLCAid2VsZFR5cGUiLCAic2l6ZUJhc2lzIl0uaW5jbHVkZXMoZS50YXJnZXQubmFtZSkgfHwgWyJjb25maWciLCAiYnV0dE1ldGhvZCIsICJzdHJlc3NCYXNpcyIsICJkaXJlY3Rpb24iXS5pbmNsdWRlcyhlLnRhcmdldC5pZC5yZXBsYWNlKC9ed3NjLS8sICIiKSkpIHVwZGF0ZVVJKCk7CiAgfSk7CiAgLy8gQ2xlYXIgYW4gZXJyb3IgYXMgc29vbiBhcyB0aGUgdXNlciBlZGl0cyB0aGF0IGZpZWxkCiAgZm9ybS5hZGRFdmVudExpc3RlbmVyKCJpbnB1dCIsIChlKSA9PiB7CiAgICBpZiAoZS50YXJnZXQubWF0Y2hlcygiaW5wdXRbdHlwZT10ZXh0XSIpKSBjbGVhckZpZWxkKGUudGFyZ2V0LmlkLnJlcGxhY2UoL153c2MtLywgIiIpKTsKICAgIGlmIChlLnRhcmdldC5pZCA9PT0gIndzYy1zdHJlbmd0aCIpICQoImVsZWN0cm9kZSIpLnZhbHVlID0gIiI7CiAgfSk7CiAgJCgiZWxlY3Ryb2RlIikuYWRkRXZlbnRMaXN0ZW5lcigiY2hhbmdlIiwgKCkgPT4gewogICAgY29uc3QgdiA9ICQoImVsZWN0cm9kZSIpLnZhbHVlOwogICAgaWYgKCF2KSByZXR1cm47CiAgICBjb25zdCBbdW5pdCwgdmFsXSA9IHYuc3BsaXQoIjoiKTsKICAgIGNvbnN0IG1wYSA9IHBhcnNlRmxvYXQodmFsKSAqIFRPX01QQVt1bml0XTsKICAgIGNvbnN0IHRhcmdldCA9ICQoInN0cmVuZ3RoVW5pdCIpLnZhbHVlOwogICAgJCgic3RyZW5ndGgiKS52YWx1ZSA9IFN0cmluZygrKG1wYSAvIFRPX01QQVt0YXJnZXRdKS50b1ByZWNpc2lvbig1KSk7CiAgICBjbGVhckZpZWxkKCJzdHJlbmd0aCIpOwogIH0pOwogIGJpbmRVbml0Q29udmVyc2lvbigic2l6ZSIsICJzaXplVW5pdCIsIFRPX01NKTsKICBiaW5kVW5pdENvbnZlcnNpb24oImxlbmd0aCIsICJsZW5ndGhVbml0IiwgVE9fTU0pOwogIGJpbmRVbml0Q29udmVyc2lvbigiYXJlYSIsICJhcmVhVW5pdCIsIFRPX01NMik7CiAgYmluZFVuaXRDb252ZXJzaW9uKCJzdHJlbmd0aCIsICJzdHJlbmd0aFVuaXQiLCBUT19NUEEpOwogIGJpbmRVbml0Q29udmVyc2lvbigibG9hZCIsICJmb3JjZVVuaXQiLCBUT19OKTsKICB1cGRhdGVVSSgpOwp9KSgpOwo=\";var bin=atob(b);var bytes=new Uint8Array(bin.length);for(var i=0;bin.length-i;i++){bytes[i]=bin.charCodeAt(i);}var el=document.createElement(\"script\");el.text=new TextDecoder(\"utf-8\").decode(bytes);document.body.appendChild(el);})();<\/script>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>The Weld Strength Calculator estimates the load capacity of fillet and butt welds using weld dimensions, effective length, material strength, and applied load. Review estimated&#8230;<\/p>","protected":false},"author":2,"featured_media":25119,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"pmpro_default_level":"","_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_hide_featured_image":false,"_jetpack_featured_image_duplicate_dismissed":0,"_jetpack_feature_clip_id":0,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_post_was_ever_published":false},"categories":[8808],"tags":[8862,8861,8793],"class_list":["post-25118","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-manufacturing-and-processes","tag-fillet-weld","tag-weld-strength","tag-welding-calculator","pmpro-has-access"],"acf":[],"jetpack_sharing_enabled":true,"jetpack_featured_media_url":"https:\/\/www.mechstream.com\/wp-content\/uploads\/2026\/11\/Weld-Strength-Calculator.png","_links":{"self":[{"href":"https:\/\/www.mechstream.com\/fr\/wp-json\/wp\/v2\/posts\/25118","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.mechstream.com\/fr\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.mechstream.com\/fr\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.mechstream.com\/fr\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.mechstream.com\/fr\/wp-json\/wp\/v2\/comments?post=25118"}],"version-history":[{"count":3,"href":"https:\/\/www.mechstream.com\/fr\/wp-json\/wp\/v2\/posts\/25118\/revisions"}],"predecessor-version":[{"id":25122,"href":"https:\/\/www.mechstream.com\/fr\/wp-json\/wp\/v2\/posts\/25118\/revisions\/25122"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.mechstream.com\/fr\/wp-json\/wp\/v2\/media\/25119"}],"wp:attachment":[{"href":"https:\/\/www.mechstream.com\/fr\/wp-json\/wp\/v2\/media?parent=25118"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.mechstream.com\/fr\/wp-json\/wp\/v2\/categories?post=25118"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.mechstream.com\/fr\/wp-json\/wp\/v2\/tags?post=25118"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}