{"id":24889,"date":"2026-09-15T01:10:32","date_gmt":"2026-09-15T01:10:32","guid":{"rendered":"https:\/\/www.mechstream.com\/?p=24889"},"modified":"2026-09-15T01:43:10","modified_gmt":"2026-09-15T01:43:10","slug":"thermal-stress-calculator","status":"publish","type":"post","link":"https:\/\/www.mechstream.com\/fr\/thermal-stress-calculator\/","title":{"rendered":"Thermal Stress Calculator"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">The <strong>Thermal Stress Calculator<\/strong> is a practical engineering tool designed to quickly estimate thermal stress caused by temperature changes in restrained materials. By entering Young\u2019s modulus, coefficient of thermal expansion, initial and final temperatures, and restraint conditions, users can calculate thermal strain and thermal stress efficiently. This calculator is useful for engineers, designers, students, and manufacturers working with metals and structural materials where thermal expansion and contraction can affect component performance, dimensional stability, and structural reliability.<\/p>\n\n\n\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n  <meta charset=\"UTF-8\">\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n  <meta name=\"description\" content=\"Use this Thermal Stress Calculator to estimate restrained thermal stress, thermal strain, temperature change, and tension or compression in common engineering units.\">\n  <title>Thermal Stress Calculator | Free Engineering Tool<\/title>\n  <style>\n    #thermal-stress-calculator-widget {\n      --ink: #16263d;\n      --ink-soft: #5c6b80;\n      --muted: #68768d;\n      --surface: #ffffff;\n      --surface-soft: #f5f8fb;\n      --page: #ffffff;\n      --line: #d9e2eb;\n      --line-strong: #c4d0dc;\n      --teal: #1769aa;\n      --teal-dark: #0d4f84;\n      --orange: #e77c2d;\n      --orange-soft: #fff2e7;\n      --red: #b74d4d;\n      --red-soft: #fff1f1;\n      --green: #19775e;\n      --green-soft: #eaf7f1;\n      --shadow: 0 18px 45px rgba(22, 38, 61, 0.10);\n      --radius: 10px;\n      color: var(--ink);\n      background: var(--page);\n      font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, \"Segoe UI\", sans-serif;\n      line-height: 1.55;\n      display: block;\n    }\n\n    #thermal-stress-calculator-widget, #thermal-stress-calculator-widget * {\n      box-sizing: border-box;\n    }\n\n    #thermal-stress-calculator-widget button, #thermal-stress-calculator-widget input, #thermal-stress-calculator-widget select {\n      font: inherit;\n    }\n\n    #thermal-stress-calculator-widget button {\n      cursor: pointer;\n    }\n\n    #thermal-stress-calculator-widget a {\n      color: inherit;\n    }\n\n    #thermal-stress-calculator-widget .site-header {\n      background: var(--ink);\n      color: #ffffff;\n      border-bottom: 4px solid var(--orange);\n    }\n\n    #thermal-stress-calculator-widget .header-inner, #thermal-stress-calculator-widget .main-inner, #thermal-stress-calculator-widget .footer-inner {\n      width: min(1160px, calc(100% - 40px));\n      margin: 0 auto;\n    }\n\n    #thermal-stress-calculator-widget .main-inner {\n      padding: 38px 0;\n    }\n\n    #thermal-stress-calculator-widget .header-inner {\n      min-height: 72px;\n      display: flex;\n      align-items: center;\n      justify-content: space-between;\n      gap: 24px;\n    }\n\n    #thermal-stress-calculator-widget .brand {\n      display: inline-flex;\n      align-items: center;\n      gap: 12px;\n      text-decoration: none;\n      font-weight: 800;\n      letter-spacing: 0;\n    }\n\n    #thermal-stress-calculator-widget .brand-mark {\n      width: 34px;\n      height: 34px;\n      display: grid;\n      place-items: center;\n      color: var(--ink);\n      background: var(--orange);\n      border-radius: 8px;\n      font-size: 18px;\n      font-weight: 900;\n    }\n\n    #thermal-stress-calculator-widget .header-nav {\n      display: flex;\n      align-items: center;\n      gap: 22px;\n      color: #c7d5e4;\n      font-size: 0.88rem;\n    }\n\n    #thermal-stress-calculator-widget .header-nav a {\n      text-decoration: none;\n    }\n\n    #thermal-stress-calculator-widget .header-nav a:hover, #thermal-stress-calculator-widget .header-nav a:focus-visible {\n      color: #ffffff;\n    }\n\n    #thermal-stress-calculator-widget .intro {\n      padding: 56px 0 34px;\n    }\n\n    #thermal-stress-calculator-widget .eyebrow {\n      margin: 0 0 10px;\n      color: var(--teal);\n      font-size: 0.76rem;\n      font-weight: 800;\n      letter-spacing: 0.12em;\n      text-transform: uppercase;\n    }\n\n    #thermal-stress-calculator-widget h1, #thermal-stress-calculator-widget h2, #thermal-stress-calculator-widget h3, #thermal-stress-calculator-widget p {\n      margin: 0;\n    }\n\n    #thermal-stress-calculator-widget main,\n    #thermal-stress-calculator-widget section,\n    #thermal-stress-calculator-widget aside,\n    #thermal-stress-calculator-widget form {\n      display: block;\n      margin: 0;\n    }\n\n    #thermal-stress-calculator-widget ul,\n    #thermal-stress-calculator-widget ol,\n    #thermal-stress-calculator-widget dl {\n      margin: 0;\n    }\n\n    #thermal-stress-calculator-widget h1 {\n      max-width: 760px;\n      margin-bottom: 14px;\n      font-size: clamp(2.25rem, 5vw, 4rem);\n      line-height: 1.03;\n      letter-spacing: 0;\n    }\n\n    #thermal-stress-calculator-widget .intro-copy {\n      max-width: 760px;\n      margin-bottom: 0;\n      color: var(--ink-soft);\n      font-size: 1.08rem;\n    }\n\n    #thermal-stress-calculator-widget .calculator-shell {\n      display: block;\n      width: 100%;\n      max-width: none;\n      margin: 0;\n      overflow: hidden;\n      background: var(--surface);\n      border: 1px solid var(--line);\n      border-radius: var(--radius);\n      box-shadow: var(--shadow);\n    }\n\n    #thermal-stress-calculator-widget .form-panel, #thermal-stress-calculator-widget .result-panel {\n      padding: 34px;\n    }\n\n    #thermal-stress-calculator-widget .form-panel {\n      min-width: 0;\n    }\n\n    #thermal-stress-calculator-widget .result-panel {\n      display: block;\n      color: var(--ink);\n      background: var(--surface);\n      border-top: 1px solid var(--line);\n      border-left: 0;\n    }\n\n    #thermal-stress-calculator-widget .result-panel[hidden] {\n      display: none;\n    }\n\n    #thermal-stress-calculator-widget .result-panel .section-heading {\n      display: flex;\n      flex-direction: column;\n    }\n\n    #thermal-stress-calculator-widget .section-heading {\n      margin-bottom: 26px;\n    }\n\n    #thermal-stress-calculator-widget .section-heading h2 {\n      margin-bottom: 6px;\n      font-size: 1.55rem;\n      line-height: 1.2;\n    }\n\n    #thermal-stress-calculator-widget .section-heading p {\n      margin-bottom: 0;\n      color: var(--ink-soft);\n      font-size: 0.94rem;\n    }\n\n    #thermal-stress-calculator-widget .result-panel .section-heading {\n      margin-bottom: 30px;\n    }\n\n    #thermal-stress-calculator-widget .result-panel .section-heading h2 {\n      color: var(--ink);\n    }\n\n    #thermal-stress-calculator-widget .result-panel .section-heading p {\n      color: var(--ink-soft);\n    }\n\n    #thermal-stress-calculator-widget .output-unit-control {\n      position: relative;\n      display: inline-flex;\n      align-items: center;\n      gap: 10px;\n      margin-top: 18px;\n      color: var(--ink-soft);\n      font-size: 0.82rem;\n      font-weight: 700;\n    }\n\n    #thermal-stress-calculator-widget .stress-unit-picker {\n      position: relative;\n      display: inline-block;\n    }\n\n    #thermal-stress-calculator-widget .stress-unit-trigger {\n      appearance: none;\n      display: inline-flex;\n      align-items: center;\n      justify-content: space-between;\n      gap: 18px;\n      width: 112px;\n      min-height: 42px;\n      padding: 8px 12px;\n      color: var(--ink);\n      background: #ffffff;\n      border: 1px solid var(--line-strong);\n      border-radius: 7px;\n      font: inherit;\n      font-size: 0.84rem;\n      font-weight: 800;\n      text-align: left;\n      box-shadow: none;\n    }\n\n    #thermal-stress-calculator-widget .stress-unit-trigger:hover,\n    #thermal-stress-calculator-widget .stress-unit-trigger[aria-expanded=\"true\"] {\n      border-color: var(--teal);\n      background: #ffffff;\n    }\n\n    #thermal-stress-calculator-widget .stress-unit-trigger:focus-visible {\n      outline: 3px solid rgba(23, 105, 170, 0.18);\n      outline-offset: 2px;\n    }\n\n    #thermal-stress-calculator-widget .stress-unit-chevron {\n      width: 8px;\n      height: 8px;\n      flex: 0 0 auto;\n      border-right: 2px solid var(--ink-soft);\n      border-bottom: 2px solid var(--ink-soft);\n      transform: rotate(45deg) translateY(-2px);\n      transition: transform 140ms ease;\n    }\n\n    #thermal-stress-calculator-widget .stress-unit-trigger[aria-expanded=\"true\"] .stress-unit-chevron {\n      transform: rotate(225deg) translate(-1px, -1px);\n    }\n\n    #thermal-stress-calculator-widget .stress-unit-menu {\n      position: absolute;\n      top: calc(100% + 6px);\n      left: 0;\n      z-index: 20;\n      display: grid;\n      min-width: 112px;\n      padding: 5px;\n      background: #ffffff;\n      border: 1px solid var(--line-strong);\n      border-radius: 7px;\n      box-shadow: 0 12px 24px rgba(22, 38, 61, 0.16);\n    }\n\n    #thermal-stress-calculator-widget .stress-unit-menu[hidden] {\n      display: none;\n    }\n\n    #thermal-stress-calculator-widget .stress-unit-option {\n      width: 100%;\n      min-height: 34px;\n      padding: 7px 9px;\n      color: var(--ink);\n      background: #ffffff;\n      border: 0;\n      border-radius: 4px;\n      font: inherit;\n      font-size: 0.82rem;\n      text-align: left;\n    }\n\n    #thermal-stress-calculator-widget .stress-unit-option:hover,\n    #thermal-stress-calculator-widget .stress-unit-option:focus-visible,\n    #thermal-stress-calculator-widget .stress-unit-option[aria-selected=\"true\"] {\n      color: var(--teal-dark);\n      background: #eef5fb;\n    }\n\n    #thermal-stress-calculator-widget .example-strip {\n      display: flex;\n      align-items: center;\n      justify-content: space-between;\n      gap: 16px;\n      padding: 13px 15px;\n      margin-bottom: 26px;\n      background: var(--orange-soft);\n      border: 1px solid #f6d5ba;\n      border-radius: 8px;\n    }\n\n    #thermal-stress-calculator-widget .example-strip p {\n      margin: 0;\n      color: #794622;\n      font-size: 0.86rem;\n    }\n\n    #thermal-stress-calculator-widget .text-button {\n      flex: 0 0 auto;\n      padding: 0;\n      border: 0;\n      color: var(--teal-dark);\n      background: transparent;\n      font-weight: 800;\n      font-size: 0.86rem;\n      text-decoration: underline;\n      text-underline-offset: 3px;\n    }\n\n    #thermal-stress-calculator-widget .text-button:hover, #thermal-stress-calculator-widget .text-button:focus-visible {\n      color: var(--ink);\n    }\n\n    #thermal-stress-calculator-widget .field-grid {\n      display: grid;\n      grid-template-columns: repeat(2, minmax(0, 1fr));\n      gap: 22px 18px;\n    }\n\n    #thermal-stress-calculator-widget .field-group {\n      min-width: 0;\n    }\n\n    #thermal-stress-calculator-widget .field-group.full-width {\n      grid-column: 1 \/ -1;\n    }\n\n    #thermal-stress-calculator-widget .field-label {\n      display: flex;\n      align-items: baseline;\n      justify-content: space-between;\n      gap: 12px;\n      margin-bottom: 8px;\n      color: var(--ink);\n      font-size: 0.92rem;\n      font-weight: 800;\n    }\n\n    #thermal-stress-calculator-widget .field-label small {\n      color: var(--muted);\n      font-size: 0.75rem;\n      font-weight: 600;\n    }\n\n    #thermal-stress-calculator-widget .control-row {\n      display: grid;\n      grid-template-columns: minmax(0, 1fr) 110px;\n      min-height: 46px;\n    }\n\n    #thermal-stress-calculator-widget .control-row input, #thermal-stress-calculator-widget .control-row select, #thermal-stress-calculator-widget .standalone-select {\n      min-width: 0;\n      width: 100%;\n      color: var(--ink);\n      background: #ffffff;\n      border: 1px solid var(--line-strong);\n      outline: none;\n      transition: border-color 140ms ease, box-shadow 140ms ease;\n    }\n\n    #thermal-stress-calculator-widget .control-row input {\n      padding: 11px 13px;\n      border-radius: 7px 0 0 7px;\n      border-right: 0;\n    }\n\n    #thermal-stress-calculator-widget .control-row select {\n      padding: 0 9px;\n      border-radius: 0 7px 7px 0;\n      background-color: var(--surface-soft);\n      font-size: 0.84rem;\n    }\n\n    #thermal-stress-calculator-widget .standalone-select {\n      padding: 11px 13px;\n      border-radius: 7px;\n      background-color: var(--surface-soft);\n    }\n\n    #thermal-stress-calculator-widget .control-row input:focus, #thermal-stress-calculator-widget .control-row select:focus, #thermal-stress-calculator-widget .standalone-select:focus {\n      position: relative;\n      z-index: 1;\n      border-color: var(--teal);\n      box-shadow: 0 0 0 3px rgba(23, 105, 170, 0.13);\n    }\n\n    #thermal-stress-calculator-widget .helper {\n      min-height: 40px;\n      margin: 7px 0 0;\n      color: var(--muted);\n      font-size: 0.78rem;\n      line-height: 1.45;\n    }\n\n    #thermal-stress-calculator-widget .field-error {\n      display: none;\n      margin: 5px 0 0;\n      color: var(--red);\n      font-size: 0.78rem;\n      font-weight: 700;\n    }\n\n    #thermal-stress-calculator-widget .field-group.has-error .field-error {\n      display: block;\n    }\n\n    #thermal-stress-calculator-widget .field-group.has-error input, #thermal-stress-calculator-widget .field-group.has-error select {\n      border-color: var(--red);\n      background: var(--red-soft);\n    }\n\n    #thermal-stress-calculator-widget .temperature-row {\n      display: grid;\n      grid-template-columns: repeat(2, minmax(0, 1fr)) 150px;\n      gap: 10px;\n    }\n\n    #thermal-stress-calculator-widget .temperature-row .control-row {\n      display: block;\n    }\n\n    #thermal-stress-calculator-widget .temperature-row .control-row input {\n      width: 100%;\n      border-right: 1px solid var(--line-strong);\n      border-radius: 7px;\n    }\n\n    #thermal-stress-calculator-widget .temperature-unit-label {\n      display: block;\n      margin-bottom: 7px;\n      color: var(--muted);\n      font-size: 0.74rem;\n      font-weight: 700;\n    }\n\n    #thermal-stress-calculator-widget .restraint-wrap {\n      display: grid;\n      grid-template-columns: minmax(0, 1fr) 110px;\n      align-items: center;\n      gap: 14px;\n    }\n\n    #thermal-stress-calculator-widget input[type=\"range\"] {\n      width: 100%;\n      accent-color: var(--teal);\n    }\n\n    #thermal-stress-calculator-widget .restraint-wrap .control-row {\n      display: block;\n    }\n\n    #thermal-stress-calculator-widget .restraint-wrap .control-row input {\n      width: 100%;\n      border-right: 1px solid var(--line-strong);\n      border-radius: 7px;\n    }\n\n    #thermal-stress-calculator-widget .actions {\n      display: flex;\n      align-items: center;\n      justify-content: center;\n      flex-direction: column;\n      gap: 12px;\n      position: relative;\n      margin-top: 28px;\n      padding-top: 24px;\n      border-top: 1px solid var(--line);\n    }\n\n    #thermal-stress-calculator-widget .primary-button {\n      width: min(280px, 100%);\n      min-height: 52px;\n      padding: 0 28px;\n      border-radius: 7px;\n      font-weight: 800;\n      border: 1px solid transparent;\n    }\n\n    #thermal-stress-calculator-widget .primary-button {\n      color: #ffffff;\n      background: var(--teal);\n      border-color: var(--teal);\n    }\n\n    #thermal-stress-calculator-widget .primary-button:hover, #thermal-stress-calculator-widget .primary-button:focus-visible {\n      background: var(--teal-dark);\n      border-color: var(--teal-dark);\n    }\n\n    #thermal-stress-calculator-widget .primary-button:focus-visible, #thermal-stress-calculator-widget .text-button:focus-visible, #thermal-stress-calculator-widget .header-nav a:focus-visible {\n      outline: 3px solid rgba(231, 124, 45, 0.35);\n      outline-offset: 3px;\n    }\n\n    #thermal-stress-calculator-widget .validation-summary {\n      display: none;\n      margin: 4px 0 0;\n      color: var(--red);\n      font-size: 0.82rem;\n      font-weight: 700;\n      text-align: center;\n    }\n\n    #thermal-stress-calculator-widget .validation-summary.visible {\n      display: block;\n    }\n\n    #thermal-stress-calculator-widget .result-kicker {\n      margin: 0 0 10px;\n      color: var(--teal);\n      font-size: 0.75rem;\n      font-weight: 800;\n      letter-spacing: 0.12em;\n      text-transform: uppercase;\n    }\n\n    #thermal-stress-calculator-widget .result-value {\n      margin: 0;\n      color: var(--ink);\n      font-size: clamp(2.8rem, 5vw, 4.35rem);\n      font-variant-numeric: tabular-nums;\n      line-height: 1;\n      overflow-wrap: anywhere;\n    }\n\n    #thermal-stress-calculator-widget .result-unit {\n      display: block;\n      margin-top: 13px;\n      color: var(--ink-soft);\n      font-size: 0.95rem;\n      font-weight: 700;\n    }\n\n    #thermal-stress-calculator-widget .stress-state {\n      display: inline-flex;\n      align-items: center;\n      gap: 8px;\n      width: fit-content;\n      margin-top: 24px;\n      padding: 8px 12px;\n      color: var(--ink);\n      background: #eef5fb;\n      border: 1px solid #c8dced;\n      border-radius: 999px;\n      font-size: 0.84rem;\n      font-weight: 800;\n    }\n\n    #thermal-stress-calculator-widget .state-dot {\n      width: 8px;\n      height: 8px;\n      border-radius: 50%;\n      background: var(--orange);\n    }\n\n    #thermal-stress-calculator-widget .stress-state.tension .state-dot {\n      background: #72d9b8;\n    }\n\n    #thermal-stress-calculator-widget .stress-state.compression .state-dot {\n      background: #ffad79;\n    }\n\n    #thermal-stress-calculator-widget .stress-state.neutral .state-dot {\n      background: #b7c8da;\n    }\n\n    #thermal-stress-calculator-widget .result-details {\n      display: grid;\n      gap: 0;\n      margin-top: 34px;\n      border-top: 1px solid var(--line);\n      border-bottom: 1px solid var(--line);\n    }\n\n    #thermal-stress-calculator-widget .result-detail {\n      display: flex;\n      align-items: baseline;\n      justify-content: space-between;\n      gap: 16px;\n      padding: 16px 0;\n      border-bottom: 1px solid var(--line);\n    }\n\n    #thermal-stress-calculator-widget .result-detail:last-child {\n      border-bottom: 0;\n    }\n\n    #thermal-stress-calculator-widget .result-detail span {\n      color: var(--ink-soft);\n      font-size: 0.85rem;\n    }\n\n    #thermal-stress-calculator-widget .result-detail strong {\n      color: var(--ink);\n      font-variant-numeric: tabular-nums;\n      text-align: right;\n    }\n\n    #thermal-stress-calculator-widget .sign-note {\n      margin-top: 34px;\n      padding: 16px;\n      color: var(--ink-soft);\n      background: #eef5fb;\n      border-left: 3px solid var(--teal);\n      font-size: 0.82rem;\n    }\n\n    #thermal-stress-calculator-widget .sign-note strong {\n      color: var(--ink);\n    }\n\n    #thermal-stress-calculator-widget .content-section {\n      padding: 74px 0 0;\n    }\n\n    #thermal-stress-calculator-widget .content-section h2 {\n      margin-bottom: 12px;\n      font-size: 2rem;\n      line-height: 1.15;\n    }\n\n    #thermal-stress-calculator-widget .content-lead {\n      max-width: 780px;\n      color: var(--ink-soft);\n    }\n\n    #thermal-stress-calculator-widget .formula-layout {\n      display: grid;\n      grid-template-columns: minmax(0, 1.1fr) minmax(280px, 0.9fr);\n      gap: 22px;\n      margin-top: 26px;\n    }\n\n    #thermal-stress-calculator-widget .formula-box, #thermal-stress-calculator-widget .assumption-box, #thermal-stress-calculator-widget .note-list {\n      background: var(--surface);\n      border: 1px solid var(--line);\n      border-radius: var(--radius);\n    }\n\n    #thermal-stress-calculator-widget .formula-box {\n      padding: 30px;\n    }\n\n    #thermal-stress-calculator-widget .equation {\n      margin: 0 0 18px;\n      color: var(--teal-dark);\n      font-family: Georgia, \"Times New Roman\", serif;\n      font-size: clamp(1.8rem, 4vw, 3rem);\n      line-height: 1.2;\n    }\n\n    #thermal-stress-calculator-widget .equation.secondary {\n      margin-bottom: 0;\n      font-size: clamp(1.35rem, 3vw, 2rem);\n    }\n\n    #thermal-stress-calculator-widget .formula-box p:last-child {\n      margin-bottom: 0;\n    }\n\n    #thermal-stress-calculator-widget .variable-list {\n      display: grid;\n      grid-template-columns: auto 1fr;\n      gap: 12px 16px;\n      margin: 22px 0 0;\n    }\n\n    #thermal-stress-calculator-widget .variable-list dt {\n      color: var(--orange);\n      font-family: Georgia, \"Times New Roman\", serif;\n      font-size: 1.15rem;\n      font-weight: 800;\n    }\n\n    #thermal-stress-calculator-widget .variable-list dd {\n      margin: 0;\n      color: var(--ink-soft);\n      font-size: 0.91rem;\n    }\n\n    #thermal-stress-calculator-widget .assumption-box {\n      padding: 26px;\n      background: var(--ink);\n      color: #ffffff;\n    }\n\n    #thermal-stress-calculator-widget .assumption-box h3 {\n      margin-bottom: 12px;\n      color: #ffffff;\n      font-size: 1.1rem;\n    }\n\n    #thermal-stress-calculator-widget .assumption-box p {\n      margin-bottom: 0;\n      color: #c8d6e4;\n      font-size: 0.91rem;\n    }\n\n    #thermal-stress-calculator-widget .steps {\n      display: grid;\n      grid-template-columns: repeat(4, minmax(0, 1fr));\n      gap: 16px;\n      margin: 26px 0 0;\n      padding: 0;\n      list-style: none;\n      counter-reset: steps;\n    }\n\n    #thermal-stress-calculator-widget .steps li {\n      position: relative;\n      min-height: 130px;\n      padding: 22px 18px 18px;\n      background: var(--surface);\n      border: 1px solid var(--line);\n      border-radius: var(--radius);\n      counter-increment: steps;\n    }\n\n    #thermal-stress-calculator-widget .steps li::before {\n      content: counter(steps, decimal-leading-zero);\n      display: block;\n      margin-bottom: 14px;\n      color: var(--orange);\n      font-size: 0.78rem;\n      font-weight: 900;\n      letter-spacing: 0.08em;\n    }\n\n    #thermal-stress-calculator-widget .steps li strong {\n      display: block;\n      margin-bottom: 5px;\n      font-size: 0.93rem;\n    }\n\n    #thermal-stress-calculator-widget .steps li span {\n      color: var(--ink-soft);\n      font-size: 0.82rem;\n    }\n\n    #thermal-stress-calculator-widget .notes-layout {\n      display: grid;\n      grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);\n      gap: 22px;\n      margin-top: 26px;\n    }\n\n    #thermal-stress-calculator-widget .note-list {\n      margin: 0;\n      padding: 23px 26px 23px 46px;\n    }\n\n    #thermal-stress-calculator-widget .note-list li {\n      padding: 5px 0;\n      color: var(--ink-soft);\n    }\n\n    #thermal-stress-calculator-widget .note-list li::marker {\n      color: var(--orange);\n    }\n\n    #thermal-stress-calculator-widget .safety-note {\n      padding: 25px 26px;\n      color: #653d22;\n      background: var(--orange-soft);\n      border: 1px solid #f6d5ba;\n      border-radius: var(--radius);\n    }\n\n    #thermal-stress-calculator-widget .safety-note h3 {\n      margin-bottom: 8px;\n      color: #794622;\n      font-size: 1.05rem;\n    }\n\n    #thermal-stress-calculator-widget .safety-note p {\n      margin-bottom: 0;\n      font-size: 0.91rem;\n    }\n\n    #thermal-stress-calculator-widget .site-footer {\n      margin-top: 78px;\n      padding: 26px 0;\n      color: #b7c8da;\n      background: var(--ink);\n      font-size: 0.82rem;\n    }\n\n    #thermal-stress-calculator-widget .footer-inner {\n      display: flex;\n      align-items: center;\n      justify-content: space-between;\n      gap: 18px;\n    }\n\n    #thermal-stress-calculator-widget .footer-inner p {\n      margin: 0;\n    }\n\n    @media (max-width: 900px) {\n      #thermal-stress-calculator-widget .calculator-shell,\n      #thermal-stress-calculator-widget .formula-layout,\n      #thermal-stress-calculator-widget .notes-layout {\n        grid-template-columns: 1fr;\n      }\n\n      #thermal-stress-calculator-widget .sign-note {\n        margin-top: 34px;\n      }\n\n      #thermal-stress-calculator-widget .steps {\n        grid-template-columns: repeat(2, minmax(0, 1fr));\n      }\n    }\n\n    @media (max-width: 620px) {\n      #thermal-stress-calculator-widget .header-inner,\n      #thermal-stress-calculator-widget .main-inner,\n      #thermal-stress-calculator-widget .footer-inner {\n        width: min(100% - 28px, 1160px);\n      }\n\n      #thermal-stress-calculator-widget .header-inner {\n        min-height: 64px;\n      }\n\n      #thermal-stress-calculator-widget .header-nav {\n        display: none;\n      }\n\n      #thermal-stress-calculator-widget .intro {\n        padding: 40px 0 26px;\n      }\n\n      #thermal-stress-calculator-widget h1 {\n        font-size: 2.45rem;\n      }\n\n      #thermal-stress-calculator-widget .form-panel, #thermal-stress-calculator-widget .result-panel {\n        padding: 24px 20px;\n      }\n\n      #thermal-stress-calculator-widget .field-grid, #thermal-stress-calculator-widget .temperature-row, #thermal-stress-calculator-widget .steps {\n        grid-template-columns: 1fr;\n      }\n\n      #thermal-stress-calculator-widget .field-group.full-width {\n        grid-column: auto;\n      }\n\n      #thermal-stress-calculator-widget .temperature-row {\n        gap: 12px;\n      }\n\n      #thermal-stress-calculator-widget .temperature-row .control-row input {\n        min-height: 46px;\n      }\n\n      #thermal-stress-calculator-widget .example-strip {\n        align-items: flex-start;\n        flex-direction: column;\n        gap: 9px;\n      }\n\n      #thermal-stress-calculator-widget .restraint-wrap {\n        grid-template-columns: 1fr 96px;\n        gap: 10px;\n      }\n\n      #thermal-stress-calculator-widget .content-section {\n        padding-top: 54px;\n      }\n\n      #thermal-stress-calculator-widget .formula-box, #thermal-stress-calculator-widget .assumption-box, #thermal-stress-calculator-widget .note-list, #thermal-stress-calculator-widget .safety-note {\n        padding: 22px 20px;\n      }\n\n      #thermal-stress-calculator-widget .footer-inner {\n        align-items: flex-start;\n        flex-direction: column;\n      }\n    }\n\n    @media (prefers-reduced-motion: reduce) {\n      #thermal-stress-calculator-widget {\n        scroll-behavior: auto;\n      }\n\n      #thermal-stress-calculator-widget, #thermal-stress-calculator-widget * {\n        transition-duration: 0.01ms !important;\n      }\n    }\n  <\/style>\n<\/head>\n<body>\n  <div id=\"thermal-stress-calculator-widget\">\n    <main class=\"main-inner\">\n    <section id=\"calculator\" class=\"calculator-shell\" aria-label=\"Thermal stress calculator\">\n      <div class=\"form-panel\">\n        <div class=\"example-strip\">\n          <p><strong>Quick start:<\/strong> structural steel example is ready to load.<\/p>\n          <button class=\"text-button\" id=\"loadExample\" type=\"button\">Load steel example<\/button>\n        <\/div>\n\n        <form id=\"calculatorForm\" novalidate>\n          <div class=\"field-grid\">\n            <div class=\"field-group\" data-field=\"modulus\">\n              <label class=\"field-label\" for=\"modulus\">Young&#8217;s Modulus <small>E<\/small><\/label>\n              <div class=\"control-row\">\n                <input id=\"modulus\" name=\"modulus\" type=\"number\" inputmode=\"decimal\" step=\"any\" autocomplete=\"off\" aria-describedby=\"modulusHelp modulusError\">\n                <select id=\"modulusUnit\" name=\"modulusUnit\" aria-label=\"Young's Modulus unit\">\n                  <option value=\"Pa\">Pa<\/option>\n                  <option value=\"MPa\">MPa<\/option>\n                  <option value=\"GPa\" selected>GPa<\/option>\n                  <option value=\"psi\">psi<\/option>\n                  <option value=\"ksi\">ksi<\/option>\n                <\/select>\n              <\/div>\n              <p class=\"helper\" id=\"modulusHelp\">Material stiffness. Common structural steel value: 200 GPa.<\/p>\n              <p class=\"field-error\" id=\"modulusError\" role=\"alert\"><\/p>\n            <\/div>\n\n            <div class=\"field-group\" data-field=\"cte\">\n              <label class=\"field-label\" for=\"cte\">Thermal Expansion Coefficient <small>&alpha;<\/small><\/label>\n              <div class=\"control-row\">\n                <input id=\"cte\" name=\"cte\" type=\"number\" inputmode=\"decimal\" step=\"any\" autocomplete=\"off\" aria-describedby=\"cteHelp cteError\">\n                <select id=\"cteUnit\" name=\"cteUnit\" aria-label=\"Thermal expansion coefficient unit\">\n                  <option value=\"perC\">1\/&deg;C<\/option>\n                  <option value=\"umPerMPerC\" selected>&micro;m\/m&middot;&deg;C<\/option>\n                  <option value=\"perF\">1\/&deg;F<\/option>\n                  <option value=\"uinPerInPerF\">&micro;in\/in&middot;&deg;F<\/option>\n                <\/select>\n              <\/div>\n              <p class=\"helper\" id=\"cteHelp\">For steel, use 12 &micro;m\/m&middot;&deg;C. Negative values are valid for negative-expansion materials.<\/p>\n              <p class=\"field-error\" id=\"cteError\" role=\"alert\"><\/p>\n            <\/div>\n\n            <div class=\"field-group full-width\" data-field=\"temperature\">\n              <span class=\"field-label\">Temperature inputs <small>T<sub>initial<\/sub> and T<sub>final<\/sub><\/small><\/span>\n              <div class=\"temperature-row\">\n                <div>\n                  <label class=\"temperature-unit-label\" for=\"initialTemperature\">Initial temperature<\/label>\n                  <div class=\"control-row\">\n                    <input id=\"initialTemperature\" name=\"initialTemperature\" type=\"number\" inputmode=\"decimal\" step=\"any\" autocomplete=\"off\" aria-describedby=\"temperatureHelp temperatureError\">\n                  <\/div>\n                <\/div>\n                <div>\n                  <label class=\"temperature-unit-label\" for=\"finalTemperature\">Final temperature<\/label>\n                  <div class=\"control-row\">\n                    <input id=\"finalTemperature\" name=\"finalTemperature\" type=\"number\" inputmode=\"decimal\" step=\"any\" autocomplete=\"off\" aria-describedby=\"temperatureHelp temperatureError\">\n                  <\/div>\n                <\/div>\n                <div>\n                  <label class=\"temperature-unit-label\" for=\"temperatureUnit\">Unit for both values<\/label>\n                  <select class=\"standalone-select\" id=\"temperatureUnit\" name=\"temperatureUnit\">\n                    <option value=\"C\" selected>&deg;C<\/option>\n                    <option value=\"F\">&deg;F<\/option>\n                    <option value=\"K\">K<\/option>\n                  <\/select>\n                <\/div>\n              <\/div>\n              <p class=\"helper\" id=\"temperatureHelp\">The change is calculated as final minus initial. An 80 &deg;C change is also 80 K or 144 &deg;F.<\/p>\n              <p class=\"field-error\" id=\"temperatureError\" role=\"alert\"><\/p>\n            <\/div>\n\n            <div class=\"field-group full-width\" data-field=\"restraint\">\n              <label class=\"field-label\" for=\"restraint\">Restraint Factor <small>R<\/small><\/label>\n              <div class=\"restraint-wrap\">\n                <input id=\"restraintSlider\" type=\"range\" min=\"0\" max=\"1\" step=\"0.01\" value=\"1\" aria-label=\"Restraint factor slider\">\n                <div class=\"control-row\">\n                  <input id=\"restraint\" name=\"restraint\" type=\"number\" inputmode=\"decimal\" min=\"0\" max=\"1\" step=\"0.01\" value=\"1\" aria-describedby=\"restraintHelp restraintError\">\n                <\/div>\n              <\/div>\n              <p class=\"helper\" id=\"restraintHelp\">0 means free expansion; 1 means fully restrained expansion or contraction.<\/p>\n              <p class=\"field-error\" id=\"restraintError\" role=\"alert\"><\/p>\n            <\/div>\n          <\/div>\n\n          <div class=\"actions\">\n            <button class=\"primary-button\" type=\"submit\">Calculate<\/button>\n            <p class=\"validation-summary\" id=\"validationSummary\" role=\"alert\"><\/p>\n          <\/div>\n        <\/form>\n      <\/div>\n\n      <aside class=\"result-panel\" id=\"resultPanel\" aria-live=\"polite\" aria-atomic=\"true\" hidden>\n        <div class=\"section-heading\">\n          <p class=\"result-kicker\">Calculated result<\/p>\n          <h2>Thermal stress<\/h2>\n          <p>Signed result using the stated restraint convention.<\/p>\n        <\/div>\n\n        <p class=\"result-value\" id=\"stressValue\">&mdash;<\/p>\n        <span class=\"result-unit\" id=\"stressUnit\">MPa<\/span>\n        <div class=\"stress-state neutral\" id=\"stressState\">\n          <span class=\"state-dot\" aria-hidden=\"true\"><\/span>\n          <span id=\"stressStateText\">Awaiting calculation<\/span>\n        <\/div>\n\n        <div class=\"result-details\">\n          <div class=\"result-detail\">\n            <span>Temperature change<\/span>\n            <strong id=\"deltaTemperature\">&mdash;<\/strong>\n          <\/div>\n          <div class=\"result-detail\">\n            <span>Thermal strain<\/span>\n            <strong id=\"thermalStrain\">&mdash;<\/strong>\n          <\/div>\n          <div class=\"result-detail\">\n            <span>Stress magnitude<\/span>\n            <strong id=\"stressMagnitude\">&mdash;<\/strong>\n          <\/div>\n        <\/div>\n\n        <p class=\"sign-note\"><strong>Sign convention:<\/strong> restrained heating produces negative compressive stress; restrained cooling produces positive tensile stress. A zero result is neutral or fully free expansion.<\/p>\n      <\/aside>\n    <\/section>\n\n    <\/main>\n  <\/div>\n\n  <script>\n    (function () {\n      \"use strict\";\n\n      const widget = document.getElementById(\"thermal-stress-calculator-widget\");\n      const get = (selector) => widget.querySelector(selector);\n      const form = get(\"#calculatorForm\");\n      const loadExampleButton = get(\"#loadExample\");\n      const restraintSlider = get(\"#restraintSlider\");\n      const validationSummary = get(\"#validationSummary\");\n      const resultPanel = get(\"#resultPanel\");\n\n      const fields = {\n        modulus: get(\"#modulus\"),\n        modulusUnit: get(\"#modulusUnit\"),\n        cte: get(\"#cte\"),\n        cteUnit: get(\"#cteUnit\"),\n        initialTemperature: get(\"#initialTemperature\"),\n        finalTemperature: get(\"#finalTemperature\"),\n        temperatureUnit: get(\"#temperatureUnit\"),\n        restraint: get(\"#restraint\")\n      };\n\n      const outputs = {\n        stressValue: get(\"#stressValue\"),\n        stressUnit: get(\"#stressUnit\"),\n        stressState: get(\"#stressState\"),\n        stressStateText: get(\"#stressStateText\"),\n        deltaTemperature: get(\"#deltaTemperature\"),\n        thermalStrain: get(\"#thermalStrain\"),\n        stressMagnitude: get(\"#stressMagnitude\")\n      };\n\n      const modulusToPa = {\n        Pa: 1,\n        MPa: 1e6,\n        GPa: 1e9,\n        psi: 6894.757293168,\n        ksi: 6894757.293168\n      };\n\n      const stressUnits = {\n        Pa: 1,\n        kPa: 1e3,\n        MPa: 1e6,\n        GPa: 1e9,\n        psi: 6894.757293168,\n        ksi: 6894757.293168\n      };\n\n      const exampleValues = {\n        modulus: \"200\",\n        modulusUnit: \"GPa\",\n        cte: \"12\",\n        cteUnit: \"umPerMPerC\",\n        initialTemperature: \"20\",\n        finalTemperature: \"100\",\n        temperatureUnit: \"C\",\n        restraint: \"1\"\n      };\n\n      function isFiniteNumber(value) {\n        return Number.isFinite(value);\n      }\n\n      function readNumber(input) {\n        const raw = input.value.trim();\n        return raw === \"\" ? null : Number(raw);\n      }\n\n      function setFieldError(fieldName, message) {\n        const group = get('[data-field=\"' + fieldName + '\"]');\n        const error = get(\"#\" + fieldName + \"Error\");\n        if (!group || !error) {\n          return;\n        }\n        group.classList.toggle(\"has-error\", Boolean(message));\n        error.textContent = message || \"\";\n\n        const controls = group.querySelectorAll(\"input, select\");\n        controls.forEach(function (control) {\n          control.setAttribute(\"aria-invalid\", message ? \"true\" : \"false\");\n        });\n      }\n\n      function clearErrors() {\n        [\"modulus\", \"cte\", \"temperature\", \"restraint\"].forEach(function (fieldName) {\n          setFieldError(fieldName, \"\");\n        });\n        validationSummary.textContent = \"\";\n        validationSummary.classList.remove(\"visible\");\n      }\n\n      function validate() {\n        clearErrors();\n        let valid = true;\n        const modulus = readNumber(fields.modulus);\n        const cte = readNumber(fields.cte);\n        const initialTemperature = readNumber(fields.initialTemperature);\n        const finalTemperature = readNumber(fields.finalTemperature);\n        const restraint = readNumber(fields.restraint);\n\n        if (modulus === null) {\n          setFieldError(\"modulus\", \"Enter Young's modulus.\");\n          valid = false;\n        } else if (!isFiniteNumber(modulus) || modulus <= 0) {\n          setFieldError(\"modulus\", \"Young's modulus must be a finite value greater than 0.\");\n          valid = false;\n        }\n\n        if (cte === null) {\n          setFieldError(\"cte\", \"Enter a coefficient of thermal expansion.\");\n          valid = false;\n        } else if (!isFiniteNumber(cte)) {\n          setFieldError(\"cte\", \"Enter a finite numerical coefficient.\");\n          valid = false;\n        }\n\n        if (initialTemperature === null || finalTemperature === null) {\n          setFieldError(\"temperature\", \"Enter both initial and final temperatures.\");\n          valid = false;\n        } else if (!isFiniteNumber(initialTemperature) || !isFiniteNumber(finalTemperature)) {\n          setFieldError(\"temperature\", \"Both temperatures must be finite numerical values.\");\n          valid = false;\n        }\n\n        if (restraint === null) {\n          setFieldError(\"restraint\", \"Enter a restraint factor from 0 to 1.\");\n          valid = false;\n        } else if (!isFiniteNumber(restraint) || restraint < 0 || restraint > 1) {\n          setFieldError(\"restraint\", \"Restraint factor must be between 0 and 1.\");\n          valid = false;\n        }\n\n        if (!valid) {\n          validationSummary.textContent = \"Please correct the highlighted fields before calculating.\";\n          validationSummary.classList.add(\"visible\");\n          return null;\n        }\n\n        return {\n          modulus: modulus,\n          cte: cte,\n          initialTemperature: initialTemperature,\n          finalTemperature: finalTemperature,\n          restraint: restraint\n        };\n      }\n\n      function temperatureToCelsius(value, unit) {\n        if (unit === \"F\") {\n          return (value - 32) * 5 \/ 9;\n        }\n        if (unit === \"K\") {\n          return value - 273.15;\n        }\n        return value;\n      }\n\n      function cteToPerC(value, unit) {\n        if (unit === \"umPerMPerC\") {\n          return value * 1e-6;\n        }\n        if (unit === \"perF\") {\n          return value * 9 \/ 5;\n        }\n        if (unit === \"uinPerInPerF\") {\n          return value * 1e-6 * 9 \/ 5;\n        }\n        return value;\n      }\n\n      function deltaInDisplayUnit(deltaC, unit) {\n        return unit === \"F\" ? deltaC * 9 \/ 5 : deltaC;\n      }\n\n      function formatNumber(value, options) {\n        const config = options || {};\n        if (!isFiniteNumber(value)) {\n          return \"Invalid\";\n        }\n        if (Object.is(value, -0) || value === 0) {\n          return \"0\";\n        }\n        const absolute = Math.abs(value);\n        if (absolute >= 1e7 || absolute < 1e-4) {\n          return value.toExponential(config.decimals === undefined ? 4 : config.decimals).replace(\"+\", \"\");\n        }\n        return value.toLocaleString(\"en-US\", {\n          maximumFractionDigits: config.decimals === undefined ? 5 : config.decimals,\n          useGrouping: true\n        });\n      }\n\n      function formatSignedNumber(value, options) {\n        if (value > 0) {\n          return \"+\" + formatNumber(value, options);\n        }\n        return formatNumber(value, options);\n      }\n\n      let lastCalculation = null;\n\n      function renderResult(result) {\n        const outputUnit = selectedStressUnit();\n        const stressInOutputUnit = result.signedStressPa \/ stressUnits[outputUnit];\n        const magnitudeInOutputUnit = Math.abs(result.signedStressPa) \/ stressUnits[outputUnit];\n        const displayDelta = deltaInDisplayUnit(result.deltaC, fields.temperatureUnit.value);\n        const tempSymbol = fields.temperatureUnit.value === \"C\" ? \"&deg;C\" : fields.temperatureUnit.value === \"F\" ? \"&deg;F\" : \"K\";\n\n        outputs.stressValue.textContent = formatSignedNumber(stressInOutputUnit, { decimals: 4 });\n        outputs.stressUnit.textContent = outputUnit;\n        outputs.deltaTemperature.innerHTML = formatNumber(displayDelta, { decimals: 4 }) + \" \" + tempSymbol;\n        outputs.thermalStrain.textContent = formatNumber(result.thermalStrain, { decimals: 6 });\n        outputs.stressMagnitude.textContent = formatNumber(magnitudeInOutputUnit, { decimals: 4 }) + \" \" + outputUnit;\n\n        outputs.stressState.classList.remove(\"tension\", \"compression\", \"neutral\");\n        if (result.signedStressPa < -1e-12) {\n          outputs.stressState.classList.add(\"compression\");\n          outputs.stressStateText.textContent = \"Compression\";\n        } else if (result.signedStressPa > 1e-12) {\n          outputs.stressState.classList.add(\"tension\");\n          outputs.stressStateText.textContent = \"Tension\";\n        } else {\n          outputs.stressState.classList.add(\"neutral\");\n          outputs.stressStateText.textContent = \"Neutral \/ no stress\";\n        }\n      }\n\n      function calculate() {\n        const values = validate();\n        if (!values) {\n          return false;\n        }\n\n        const modulusPa = values.modulus * modulusToPa[fields.modulusUnit.value];\n        const ctePerC = cteToPerC(values.cte, fields.cteUnit.value);\n        const initialC = temperatureToCelsius(values.initialTemperature, fields.temperatureUnit.value);\n        const finalC = temperatureToCelsius(values.finalTemperature, fields.temperatureUnit.value);\n        const deltaC = finalC - initialC;\n        const thermalStrain = ctePerC * deltaC;\n\n        \/\/ Negative stress represents compression during restrained heating.\n        const signedStressPa = -modulusPa * thermalStrain * values.restraint;\n        if (![modulusPa, ctePerC, deltaC, thermalStrain, signedStressPa].every(isFiniteNumber)) {\n          validationSummary.textContent = \"The calculation produced an invalid result. Check the entered values.\";\n          validationSummary.classList.add(\"visible\");\n          return false;\n        }\n\n        lastCalculation = {\n          deltaC: deltaC,\n          thermalStrain: thermalStrain,\n          signedStressPa: signedStressPa\n        };\n        renderResult(lastCalculation);\n        resultPanel.hidden = false;\n        return true;\n      }\n\n      function applyExample() {\n        Object.keys(exampleValues).forEach(function (key) {\n          fields[key].value = exampleValues[key];\n        });\n        restraintSlider.value = exampleValues.restraint;\n        clearErrors();\n      }\n\n      \/\/ Add the output unit selector to the result header without external UI dependencies.\n      const resultHeading = get(\".result-panel .section-heading\");\n      const outputControl = document.createElement(\"label\");\n      outputControl.className = \"output-unit-control\";\n      outputControl.setAttribute(\"for\", \"stressUnitTrigger\");\n      outputControl.innerHTML = '<span>Display stress in<\/span><span class=\"stress-unit-picker\"><button class=\"stress-unit-trigger\" id=\"stressUnitTrigger\" type=\"button\" aria-haspopup=\"listbox\" aria-expanded=\"false\"><span id=\"stressUnitSelected\">MPa<\/span><span class=\"stress-unit-chevron\" aria-hidden=\"true\"><\/span><\/button><span class=\"stress-unit-menu\" id=\"stressUnitMenu\" role=\"listbox\" aria-label=\"Thermal stress output unit\" hidden><button class=\"stress-unit-option\" type=\"button\" role=\"option\" data-unit=\"Pa\" aria-selected=\"false\">Pa<\/button><button class=\"stress-unit-option\" type=\"button\" role=\"option\" data-unit=\"kPa\" aria-selected=\"false\">kPa<\/button><button class=\"stress-unit-option\" type=\"button\" role=\"option\" data-unit=\"MPa\" aria-selected=\"true\">MPa<\/button><button class=\"stress-unit-option\" type=\"button\" role=\"option\" data-unit=\"GPa\" aria-selected=\"false\">GPa<\/button><button class=\"stress-unit-option\" type=\"button\" role=\"option\" data-unit=\"psi\" aria-selected=\"false\">psi<\/button><button class=\"stress-unit-option\" type=\"button\" role=\"option\" data-unit=\"ksi\" aria-selected=\"false\">ksi<\/button><\/span><\/span>';\n      resultHeading.appendChild(outputControl);\n\n      let selectedStressUnitValue = \"MPa\";\n      const stressUnitTrigger = get(\"#stressUnitTrigger\");\n      const stressUnitSelected = get(\"#stressUnitSelected\");\n      const stressUnitMenu = get(\"#stressUnitMenu\");\n      const stressUnitOptions = widget.querySelectorAll(\".stress-unit-option\");\n\n      function closeStressUnitMenu() {\n        stressUnitMenu.hidden = true;\n        stressUnitTrigger.setAttribute(\"aria-expanded\", \"false\");\n      }\n\n      function openStressUnitMenu() {\n        stressUnitMenu.hidden = false;\n        stressUnitTrigger.setAttribute(\"aria-expanded\", \"true\");\n      }\n\n      function selectedStressUnit() {\n        return selectedStressUnitValue;\n      }\n\n      stressUnitTrigger.addEventListener(\"click\", function (event) {\n        event.preventDefault();\n        if (stressUnitMenu.hidden) {\n          openStressUnitMenu();\n        } else {\n          closeStressUnitMenu();\n        }\n      });\n\n      stressUnitOptions.forEach(function (option) {\n        option.addEventListener(\"click\", function () {\n          selectedStressUnitValue = option.dataset.unit;\n          stressUnitSelected.textContent = selectedStressUnitValue;\n          stressUnitOptions.forEach(function (item) {\n            item.setAttribute(\"aria-selected\", item === option ? \"true\" : \"false\");\n          });\n          closeStressUnitMenu();\n          if (lastCalculation) {\n            renderResult(lastCalculation);\n          }\n        });\n      });\n\n      document.addEventListener(\"click\", function (event) {\n        if (!outputControl.contains(event.target)) {\n          closeStressUnitMenu();\n        }\n      });\n\n      stressUnitTrigger.addEventListener(\"keydown\", function (event) {\n        if (event.key === \"ArrowDown\" || event.key === \"Enter\" || event.key === \" \") {\n          event.preventDefault();\n          openStressUnitMenu();\n          stressUnitOptions[0].focus();\n        }\n      });\n\n      form.addEventListener(\"submit\", function (event) {\n        event.preventDefault();\n        calculate();\n      });\n\n      loadExampleButton.addEventListener(\"click\", applyExample);\n\n      restraintSlider.addEventListener(\"input\", function () {\n        fields.restraint.value = restraintSlider.value;\n        setFieldError(\"restraint\", \"\");\n      });\n\n      fields.restraint.addEventListener(\"input\", function () {\n        const numericValue = Number(fields.restraint.value);\n        if (isFiniteNumber(numericValue) && numericValue >= 0 && numericValue <= 1) {\n          restraintSlider.value = numericValue;\n        }\n      });\n\n      Object.keys(fields).forEach(function (key) {\n        fields[key].addEventListener(\"input\", function () {\n          if (key === \"modulus\" || key === \"modulusUnit\") {\n            setFieldError(\"modulus\", \"\");\n          } else if (key === \"cte\" || key === \"cteUnit\") {\n            setFieldError(\"cte\", \"\");\n          } else if (key === \"initialTemperature\" || key === \"finalTemperature\" || key === \"temperatureUnit\") {\n            setFieldError(\"temperature\", \"\");\n          }\n          validationSummary.classList.remove(\"visible\");\n        });\n      });\n\n      populateStressUnits();\n      applyExample();\n    }());\n  <\/script>\n<\/body>\n<\/html>\n","protected":false},"excerpt":{"rendered":"<p>The Thermal Stress Calculator is a practical engineering tool designed to quickly estimate thermal stress caused by temperature changes in restrained materials. By entering Young\u2019s&#8230;<\/p>","protected":false},"author":2,"featured_media":24875,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"pmpro_default_level":"","_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_feature_clip_id":0,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_post_was_ever_published":false},"categories":[8647],"tags":[3515,8718,8583,8717],"class_list":["post-24889","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-materials-science-and-properties","tag-engineering-calculator","tag-stress-calculator","tag-thermal-expansion","tag-thermal-stress","pmpro-has-access"],"acf":[],"jetpack_sharing_enabled":true,"jetpack_featured_media_url":"https:\/\/www.mechstream.com\/wp-content\/uploads\/2026\/09\/Thermal-Stress-Calculator.png","_links":{"self":[{"href":"https:\/\/www.mechstream.com\/fr\/wp-json\/wp\/v2\/posts\/24889","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=24889"}],"version-history":[{"count":0,"href":"https:\/\/www.mechstream.com\/fr\/wp-json\/wp\/v2\/posts\/24889\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.mechstream.com\/fr\/wp-json\/wp\/v2\/media\/24875"}],"wp:attachment":[{"href":"https:\/\/www.mechstream.com\/fr\/wp-json\/wp\/v2\/media?parent=24889"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.mechstream.com\/fr\/wp-json\/wp\/v2\/categories?post=24889"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.mechstream.com\/fr\/wp-json\/wp\/v2\/tags?post=24889"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}