{"id":29831,"date":"2026-06-15T10:33:06","date_gmt":"2026-06-15T10:33:06","guid":{"rendered":"https:\/\/support.buildsoft.eu\/?post_type=ht_kb&#038;p=29831"},"modified":"2026-06-23T07:26:46","modified_gmt":"2026-06-23T07:26:46","slug":"line-load-calculator","status":"publish","type":"ht_kb","link":"https:\/\/support.buildsoft.eu\/es\/knowledge-base\/line-load-calculator\/","title":{"rendered":"Online line load calculator"},"content":{"rendered":"\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<title>Line Load Calculator<\/title>\n<link href=\"https:\/\/fonts.googleapis.com\/css2?family=Bitter:wght@400;600;700&#038;family=Lato:ital,wght@0,300;0,400;0,700;1,400&#038;display=swap\" rel=\"stylesheet\">\n<script src=\"https:\/\/cdnjs.cloudflare.com\/ajax\/libs\/jquery\/3.7.1\/jquery.min.js\"><\/script>\n<style>\n*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }\n\n:root {\n  --red:          #e74c3c;\n  --red-dark:     #c0392b;\n  --text:         #2c2c2c;\n  --muted:        #888;\n  --light:        #f6f6f6;\n  --border:       #ddd;\n  --white:        #fff;\n  --shadow:       0 1px 4px rgba(0,0,0,0.09);\n  --input-border: #ccc;\n  --sel-bg:       #fff8f7;\n  --sel-border:   #e74c3c;\n  --result-bg:    #f0f0f0;\n}\n\nbody {\n  background: #f9f9f9;\n  color: var(--text);\n  font-family: 'Lato', Arial, sans-serif;\n  font-size: 14px;\n  line-height: 1.55;\n}\n\n\/* \u2500\u2500 PAGE \u2500\u2500 *\/\n.page-content {\n  max-width: 980px;\n  margin: 0 auto;\n  padding: 36px 24px 60px;\n}\n\nh1 {\n  font-family: 'Bitter', Georgia, serif;\n  font-size: 30px;\n  font-weight: 700;\n  color: var(--text);\n  margin-bottom: 28px;\n  letter-spacing: -0.01em;\n}\n\n\/* \u2500\u2500 CARD \u2500\u2500 *\/\n.calc-card {\n  background: var(--white);\n  border: 1px solid var(--border);\n  border-radius: 8px;\n  box-shadow: var(--shadow);\n  margin-bottom: 24px;\n  overflow: hidden;\n}\n\n.calc-card-header {\n  padding: 20px 26px 14px;\n  border-bottom: 1px solid var(--border);\n}\n\n.calc-card-header h2 {\n  font-family: 'Bitter', Georgia, serif;\n  font-size: 17px;\n  font-weight: 600;\n  color: var(--text);\n  margin-bottom: 3px;\n}\n\n.calc-card-header .ref {\n  font-size: 12px;\n  color: var(--muted);\n  font-style: italic;\n}\n\n.calc-card-body { padding: 20px 26px; }\n\n\/* \u2500\u2500 TABLES \u2500\u2500 *\/\ntable {\n  width: 100%;\n  border-collapse: collapse;\n  font-size: 13px;\n}\n\nthead tr {\n  background: var(--light);\n  border-bottom: 2px solid var(--border);\n}\n\nthead th {\n  padding: 9px 13px;\n  text-align: left;\n  font-size: 11px;\n  font-weight: 700;\n  color: var(--muted);\n  letter-spacing: 0.05em;\n  white-space: nowrap;\n  font-family: 'Lato', Arial, sans-serif;\n}\n\nthead th.right { text-align: right; }\n\ntbody tr {\n  border-bottom: 1px solid var(--border);\n  cursor: pointer;\n  transition: background 0.1s;\n}\n\ntbody tr:last-child { border-bottom: none; }\ntbody tr:hover { background: #fafafa; }\n\ntbody tr.selected {\n  background: var(--sel-bg);\n  border-left: 3px solid var(--sel-border);\n}\n\ntbody tr.selected td:first-child { padding-left: 11px; }\n\ntd {\n  padding: 9px 13px;\n  color: var(--text);\n  vertical-align: middle;\n}\n\ntd.val { text-align: right; }\ntd.val.empty { color: #bbb; }\n\n\/* \u2500\u2500 HINT BAR \u2500\u2500 *\/\n.hint-bar {\n  background: var(--light);\n  border-top: 1px solid var(--border);\n  padding: 7px 13px;\n  font-size: 11px;\n  color: var(--muted);\n  font-style: italic;\n}\n\n\/* \u2500\u2500 BUTTON ROWS \u2500\u2500 *\/\n.btn-row {\n  display: flex;\n  gap: 8px;\n  margin-bottom: 14px;\n  flex-wrap: wrap;\n  align-items: center;\n}\n\n.btn {\n  font-family: 'Lato', Arial, sans-serif;\n  font-size: 12px;\n  font-weight: 700;\n  padding: 7px 16px;\n  border-radius: 4px;\n  cursor: pointer;\n  border: none;\n  transition: background 0.15s, transform 0.1s;\n  letter-spacing: 0.03em;\n  display: inline-flex;\n  align-items: center;\n  gap: 6px;\n  white-space: nowrap;\n}\n\n.btn:active { transform: scale(0.98); }\n\n.btn-primary { background: var(--red); color: #fff; }\n.btn-primary:hover { background: var(--red-dark); }\n\n.btn-outline {\n  background: #fff;\n  color: var(--red);\n  border: 1px solid var(--red);\n}\n.btn-outline:hover { background: #fff5f4; }\n\n.btn-ghost {\n  background: #fff;\n  color: var(--muted);\n  border: 1px solid var(--border);\n}\n.btn-ghost:hover { background: var(--light); color: var(--text); }\n\n.btn-print {\n  background: #fff;\n  color: #555;\n  border: 1px solid var(--border);\n}\n.btn-print:hover { background: var(--light); }\n\n\/* \u2500\u2500 NUMBER INPUTS \u2500\u2500 *\/\ninput[type=\"number\"] {\n  font-family: 'Lato', Arial, sans-serif;\n  font-size: 13px;\n  color: var(--text);\n  background: #fff;\n  border: 1px solid var(--input-border);\n  border-radius: 4px;\n  padding: 5px 8px;\n  width: 80px;\n  text-align: right;\n  transition: border-color 0.15s, box-shadow 0.15s;\n  -moz-appearance: textfield;\n}\n\ninput[type=\"number\"]::-webkit-outer-spin-button,\ninput[type=\"number\"]::-webkit-inner-spin-button { -webkit-appearance: none; }\n\ninput[type=\"number\"]:focus {\n  outline: none;\n  border-color: var(--red);\n  box-shadow: 0 0 0 2px rgba(231,76,60,0.13);\n}\n\ninput[type=\"number\"]:disabled {\n  background: var(--light);\n  color: #bbb;\n  cursor: not-allowed;\n}\n\ntd.input-cell { padding: 6px 9px; text-align: right; }\n\n\/* \u2500\u2500 WEIGHT CELL \u2500\u2500 *\/\ntd.weight-cell {\n  text-align: right;\n  font-weight: 700;\n  color: var(--text);\n  white-space: nowrap;\n}\n\ntd.weight-cell.zero { color: #bbb; font-weight: 400; }\n\n\/* \u2500\u2500 TOTALS ROW \u2500\u2500 *\/\n.totals-row {\n  background: var(--light) !important;\n  border-top: 2px solid var(--border) !important;\n  cursor: default !important;\n}\n\n.totals-row:hover { background: var(--light) !important; }\n\n.totals-row td {\n  font-size: 11px;\n  font-weight: 700;\n  color: var(--muted);\n  letter-spacing: 0.05em;\n  padding: 10px 13px;\n}\n\n.totals-row .total-val {\n  text-align: right;\n  font-size: 15px;\n  color: var(--red);\n  font-weight: 700;\n}\n\n\/* \u2500\u2500 EMPTY STATE \u2500\u2500 *\/\n.empty-state {\n  padding: 28px;\n  text-align: center;\n  color: #bbb;\n  font-size: 13px;\n  font-style: italic;\n  display: none;\n}\n\n.empty-state.visible { display: block; }\n\n\/* \u2500\u2500 LINE LOAD INPUTS \u2500\u2500 *\/\n.ll-inputs {\n  display: flex;\n  gap: 24px;\n  flex-wrap: wrap;\n  margin-top: 18px;\n  padding-top: 18px;\n  border-top: 1px solid var(--border);\n}\n\n.field-group { display: flex; flex-direction: column; gap: 5px; }\n\n.field-group label {\n  font-size: 12px;\n  font-weight: 700;\n  color: var(--text);\n  display: flex;\n  align-items: baseline;\n  gap: 5px;\n}\n\n.field-group label .unit { font-size: 11px; color: var(--muted); font-weight: 400; }\n\n.field-group input[type=\"number\"] {\n  width: 130px;\n  text-align: left;\n  padding: 7px 10px;\n  font-size: 14px;\n}\n\n\/* \u2500\u2500 RESULT BOX \u2500\u2500 *\/\n.result-box {\n  background: var(--result-bg);\n  border: 1px solid #ddd;\n  border-radius: 6px;\n  padding: 20px 24px;\n  color: var(--muted);\n  font-style: italic;\n  font-size: 14px;\n  min-height: 72px;\n  display: flex;\n  align-items: center;\n  flex-wrap: wrap;\n  gap: 36px;\n}\n\n.result-box.has-results {\n  font-style: normal;\n  background: #fff;\n  border-color: var(--border);\n}\n\n.result-item { display: flex; flex-direction: column; gap: 2px; }\n\n.result-item label {\n  font-size: 11px;\n  color: var(--muted);\n  font-weight: 700;\n  text-transform: uppercase;\n  letter-spacing: 0.06em;\n  font-style: normal;\n}\n\n.result-item .rval {\n  font-family: 'Bitter', Georgia, serif;\n  font-size: 24px;\n  font-weight: 700;\n  color: var(--red);\n  font-style: normal;\n  line-height: 1.1;\n}\n\n.result-item .runit { font-size: 11px; color: var(--muted); font-style: normal; }\n\n\/* \u2500\u2500 REF FOOTER \u2500\u2500 *\/\n.ref-footer {\n  text-align: center;\n  font-size: 11px;\n  color: var(--muted);\n  padding: 12px 0 0;\n}\n\n\/* \u2500\u2500 SEL DOT \u2500\u2500 *\/\n.sel-dot {\n  display: inline-block;\n  width: 7px; height: 7px;\n  border-radius: 50%;\n  background: var(--red);\n  opacity: 0;\n  transition: opacity 0.15s;\n  margin-right: 5px;\n  vertical-align: middle;\n}\n\ntr.selected .sel-dot { opacity: 1; }\n\n\/* \u2500\u2500 FLASH \u2500\u2500 *\/\n@keyframes rowFlash {\n  0%   { background: #fff0ef; }\n  100% { background: transparent; }\n}\n.flash { animation: rowFlash 0.55s ease-out; }\n\n\/* \u2500\u2500 TOAST \u2500\u2500 *\/\n.toast {\n  position: fixed;\n  bottom: 24px; right: 24px;\n  background: var(--text);\n  color: #fff;\n  font-size: 12px;\n  font-family: 'Lato', Arial, sans-serif;\n  padding: 10px 18px;\n  border-radius: 4px;\n  opacity: 0;\n  transform: translateY(8px);\n  transition: all 0.22s;\n  pointer-events: none;\n  z-index: 999;\n  box-shadow: 0 2px 8px rgba(0,0,0,0.18);\n}\n\n.toast.show { opacity: 1; transform: translateY(0); }\n.toast.error { background: var(--red); }\n\n\/* \u2500\u2500 PRINT STYLES \u2500\u2500 *\/\n@media print {\n  body { background: #fff; font-size: 12px; }\n  .no-print { display: none !important; }\n  .print-only { display: block !important; }\n  .calc-card { box-shadow: none; break-inside: avoid; }\n  .page-content { padding: 0; max-width: 100%; }\n  input[type=\"number\"] { border: none; background: transparent; }\n  .btn-row, .ll-inputs .field-group input { display: none; }\n  .ll-inputs { border-top: 1px solid #ddd; }\n  .print-val { display: inline !important; }\n}\n\n.print-only { display: none; }\n\n@media (max-width: 680px) {\n  .page-content { padding: 16px 12px 40px; }\n  .calc-card-body { padding: 14px; }\n  .calc-card-header { padding: 14px 14px 10px; }\n  table { font-size: 12px; }\n}\n<\/style>\n<\/head>\n<body>\n\n<div class=\"page-content\">\n\n\n  <!-- \u2550\u2550 CARD 1: MATERIAL LIBRARY \u2550\u2550 -->\n  <div class=\"calc-card no-print\">\n    <div class=\"calc-card-header\">\n      <h2>Material Library<\/h2>\n      <div class=\"ref\">Click a row to select a material, then press <strong>Add<\/strong><\/div>\n    <\/div>\n    <div class=\"calc-card-body\" style=\"padding:0;\">\n      <table id=\"material-table\" style=\"table-layout:fixed; width:100%;\">\n        <colgroup>\n          <col style=\"width:20px;\">\n          <col>\n          <col style=\"width:90px;\">\n          <col style=\"width:90px;\">\n        <\/colgroup>\n        <thead>\n          <tr>\n            <th style=\"width:20px;\"><\/th>\n            <th>Material<\/th>\n            <th class=\"right\">kN\/m\u00b3<\/th>\n            <th class=\"right\">kN\/m\u00b2<\/th>\n          <\/tr>\n        <\/thead>\n      <\/table>\n      <div id=\"material-tbody-wrapper\" style=\"max-height:330px; overflow-y:auto;\">\n        <table style=\"table-layout:fixed; width:100%;\">\n          <colgroup>\n            <col style=\"width:20px;\">\n            <col>\n            <col style=\"width:90px;\">\n            <col style=\"width:90px;\">\n          <\/colgroup>\n          <tbody id=\"material-tbody\">\n          <tr data-name=\"Concrete (reinforced)\" data-knm3=\"25\" data-knm2=\"\">\n            <td><span class=\"sel-dot\"><\/span><\/td>\n            <td>Concrete (reinforced)<\/td>\n            <td class=\"val\">25<\/td>\n            <td class=\"val empty\">\u2014<\/td>\n          <\/tr>\n          <tr data-name=\"Steel\" data-knm3=\"77\" data-knm2=\"\">\n            <td><span class=\"sel-dot\"><\/span><\/td>\n            <td>Steel<\/td>\n            <td class=\"val\">77<\/td>\n            <td class=\"val empty\">\u2014<\/td>\n          <\/tr>\n          <tr data-name=\"Live load (1 kN\/m\u00b2)\" data-knm3=\"\" data-knm2=\"1\">\n            <td><span class=\"sel-dot\"><\/span><\/td>\n            <td>Live load (1 kN\/m\u00b2)<\/td>\n            <td class=\"val empty\">\u2014<\/td>\n            <td class=\"val\">1<\/td>\n          <\/tr>\n          <tr data-name=\"Snow (0.5 kN\/m\u00b2)\" data-knm3=\"\" data-knm2=\"0.5\">\n            <td><span class=\"sel-dot\"><\/span><\/td>\n            <td>Snow (0.5 kN\/m\u00b2)<\/td>\n            <td class=\"val empty\">\u2014<\/td>\n            <td class=\"val\">0.5<\/td>\n          <\/tr>\n          <tr data-name=\"Hollow core slab (WX 150)\" data-knm3=\"\" data-knm2=\"2.296\">\n            <td><span class=\"sel-dot\"><\/span><\/td>\n            <td>Hollow core slab (WX 150)<\/td>\n            <td class=\"val empty\">\u2014<\/td>\n            <td class=\"val\">2.296<\/td>\n          <\/tr>\n          <tr data-name=\"Hollow core slab (WX 200)\" data-knm3=\"\" data-knm2=\"2.923\">\n            <td><span class=\"sel-dot\"><\/span><\/td>\n            <td>Hollow core slab (WX 200)<\/td>\n            <td class=\"val empty\">\u2014<\/td>\n            <td class=\"val\">2.923<\/td>\n          <\/tr>\n          <tr data-name=\"Hollow core slab (WX 265)\" data-knm3=\"\" data-knm2=\"3.581\">\n            <td><span class=\"sel-dot\"><\/span><\/td>\n            <td>Hollow core slab (WX 265)<\/td>\n            <td class=\"val empty\">\u2014<\/td>\n            <td class=\"val\">3.581<\/td>\n          <\/tr>\n          <tr data-name=\"Hollow core slab (WX 320)\" data-knm3=\"\" data-knm2=\"3.973\">\n            <td><span class=\"sel-dot\"><\/span><\/td>\n            <td>Hollow core slab (WX 320)<\/td>\n            <td class=\"val empty\">\u2014<\/td>\n            <td class=\"val\">3.973<\/td>\n          <\/tr>\n          <tr data-name=\"Timber C18\" data-knm3=\"3.728\" data-knm2=\"\">\n            <td><span class=\"sel-dot\"><\/span><\/td>\n            <td>Timber C18<\/td>\n            <td class=\"val\">3.728<\/td>\n            <td class=\"val empty\">\u2014<\/td>\n          <\/tr>\n          <tr data-name=\"Masonry\" data-knm3=\"15.7\" data-knm2=\"\">\n            <td><span class=\"sel-dot\"><\/span><\/td>\n            <td>Masonry<\/td>\n            <td class=\"val\">15.7<\/td>\n            <td class=\"val empty\">\u2014<\/td>\n          <\/tr>\n          <tr data-name=\"Insulation (PUR)\" data-knm3=\"0.294\" data-knm2=\"\">\n            <td><span class=\"sel-dot\"><\/span><\/td>\n            <td>Insulation (PUR)<\/td>\n            <td class=\"val\">0.294<\/td>\n            <td class=\"val empty\">\u2014<\/td>\n          <\/tr>\n        <\/tbody>\n        <\/table>\n      <\/div>\n    <\/div>\n    <!-- Export \/ Import \/ Clear all buttons -->\n    <div style=\"padding: 12px 14px; border-top: 1px solid var(--border); background: var(--light); display:flex; gap:8px; flex-wrap:wrap;\">\n      <button class=\"btn btn-ghost\" id=\"btn-export\">\n        <svg width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\"><path d=\"M6 1v7M3 5l3 3 3-3M1 10h10\" stroke=\"currentColor\" stroke-width=\"1.8\" stroke-linecap=\"round\" stroke-linejoin=\"round\"\/><\/svg>\n        Export txt\n      <\/button>\n      <button class=\"btn btn-ghost\" id=\"btn-import\">\n        <svg width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\"><path d=\"M6 8V1M3 4l3-3 3 3M1 10h10\" stroke=\"currentColor\" stroke-width=\"1.8\" stroke-linecap=\"round\" stroke-linejoin=\"round\"\/><\/svg>\n        Import txt\n      <\/button>\n      <input type=\"file\" id=\"import-file\" accept=\".txt\" style=\"display:none;\">\n      <button class=\"btn btn-ghost\" id=\"btn-clear-all\">\n        <svg width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\"><path d=\"M2 2l8 8M10 2l-8 8\" stroke=\"currentColor\" stroke-width=\"1.8\" stroke-linecap=\"round\"\/><\/svg>\n        Clear all\n      <\/button>\n    <\/div>\n  <\/div>\n\n  <!-- \u2550\u2550 CARD 2: LOAD COMPOSITION \u2550\u2550 -->\n  <div class=\"calc-card\" id=\"card-composition\">\n    <div class=\"calc-card-header\">\n      <h2>Load Composition<\/h2>\n      <div class=\"ref\">Enter dimensions per material \u2014 weight is calculated automatically<\/div>\n    <\/div>\n    <div class=\"calc-card-body\" style=\"padding: 16px 26px 20px;\">\n\n      <div class=\"btn-row no-print\">\n        <button class=\"btn btn-primary\" id=\"btn-add\">\n          <svg width=\"11\" height=\"11\" viewBox=\"0 0 12 12\" fill=\"none\"><path d=\"M6 1v10M1 6h10\" stroke=\"currentColor\" stroke-width=\"2.2\" stroke-linecap=\"round\"\/><\/svg>\n          Add\n        <\/button>\n        <button class=\"btn btn-outline\" id=\"btn-remove\">\n          <svg width=\"11\" height=\"11\" viewBox=\"0 0 12 12\" fill=\"none\"><path d=\"M1 6h10\" stroke=\"currentColor\" stroke-width=\"2.2\" stroke-linecap=\"round\"\/><\/svg>\n          Remove\n        <\/button>\n        <button class=\"btn btn-ghost\" id=\"btn-clear\">\n          <svg width=\"11\" height=\"11\" viewBox=\"0 0 12 12\" fill=\"none\"><path d=\"M2 2l8 8M10 2l-8 8\" stroke=\"currentColor\" stroke-width=\"1.8\" stroke-linecap=\"round\"\/><\/svg>\n          Clear All\n        <\/button>\n      <\/div>\n\n      <div class=\"calc-card\" style=\"margin-bottom:0; box-shadow:none;\">\n        <table id=\"load-table\">\n          <thead>\n            <tr>\n              <th style=\"width:16px;\" class=\"no-print\"><\/th>\n              <th>Material<\/th>\n              <th class=\"right\">kN\/m\u00b3<\/th>\n              <th class=\"right\">kN\/m\u00b2<\/th>\n              <th class=\"right\">L [m]<\/th>\n              <th class=\"right\">W [m]<\/th>\n              <th class=\"right\">H [m]<\/th>\n              <th class=\"right\">Weight [kN]<\/th>\n            <\/tr>\n          <\/thead>\n          <tbody id=\"load-body\"><\/tbody>\n          <tfoot>\n            <tr class=\"totals-row\" id=\"totals-row\" style=\"display:none;\">\n              <td colspan=\"7\" style=\"text-align:right;\">TOTAL LOAD<\/td>\n              <td class=\"total-val\" id=\"total-weight\">0.000 kN<\/td>\n            <\/tr>\n          <\/tfoot>\n        <\/table>\n        <div class=\"empty-state visible\" id=\"empty-state\">No materials added yet \u2014 select from the library above and click <em>Add<\/em><\/div>\n        <div class=\"hint-bar no-print\" id=\"load-hint\" style=\"display:none;\">Click a row to select it, then press <strong>Remove Selected<\/strong> to delete it<\/div>\n      <\/div>\n\n      <!-- LINE LOAD INPUTS -->\n      <div class=\"ll-inputs\">\n        <div class=\"field-group\">\n          <label>Beam span <span class=\"unit\">[m]<\/span><\/label>\n          <input type=\"number\" id=\"span-input\" placeholder=\"e.g. 5.0\" min=\"0\" step=\"0.1\">\n          <span class=\"print-only print-val\" id=\"span-print\"><\/span>\n        <\/div>\n        <div class=\"field-group\">\n          <label>Tributary width <span class=\"unit\">[m]<\/span><\/label>\n          <input type=\"number\" id=\"trib-input\" placeholder=\"e.g. 3.0\" min=\"0\" step=\"0.1\">\n          <span class=\"print-only print-val\" id=\"trib-print\"><\/span>\n        <\/div>\n      <\/div>\n    <\/div>\n  <\/div>\n\n  <!-- \u2550\u2550 CARD 3: RESULTS \u2550\u2550 -->\n  <div class=\"calc-card\" id=\"card-results\">\n    <div class=\"calc-card-header\">\n      <h2>Results<\/h2>\n    <\/div>\n    <div class=\"calc-card-body\">\n      <div class=\"result-box\" id=\"result-box\">\n        <span id=\"result-placeholder\">Fill in materials and dimensions to see results<\/span>\n        <div class=\"result-item\" id=\"res-total-block\" style=\"display:none;\">\n          <label>Total Load<\/label>\n          <div class=\"rval\" id=\"res-total\">\u2014<\/div>\n          <div class=\"runit\">kN<\/div>\n        <\/div>\n        <div class=\"result-item\" id=\"res-line-block\" style=\"display:none;\">\n          <label>Line Load<\/label>\n          <div class=\"rval\" id=\"res-line\">\u2014<\/div>\n          <div class=\"runit\">kN\/m<\/div>\n        <\/div>\n        <div class=\"result-item\" id=\"res-m2-block\" style=\"display:none;\">\n          <label>Load per m\u00b2<\/label>\n          <div class=\"rval\" id=\"res-m2\">\u2014<\/div>\n          <div class=\"runit\">kN\/m\u00b2<\/div>\n        <\/div>\n      <\/div>\n      <div class=\"ref-footer\">Load descent \u2014 line load calculation per beam or wall element<\/div>\n    <\/div>\n  <\/div>\n\n  <!-- \u2550\u2550 BOTTOM BUTTONS \u2550\u2550 -->\n  <div style=\"display:flex; justify-content:flex-end; gap:8px; margin-top:4px;\" class=\"no-print\">\n    <button class=\"btn btn-print\" id=\"btn-print\">\n      <svg width=\"13\" height=\"13\" viewBox=\"0 0 14 14\" fill=\"none\"><rect x=\"2\" y=\"5\" width=\"10\" height=\"7\" rx=\"1\" stroke=\"currentColor\" stroke-width=\"1.6\"\/><path d=\"M4 5V2.5a.5.5 0 0 1 .5-.5h5a.5.5 0 0 1 .5.5V5\" stroke=\"currentColor\" stroke-width=\"1.6\"\/><rect x=\"4\" y=\"8\" width=\"6\" height=\"1\" rx=\".5\" fill=\"currentColor\"\/><rect x=\"4\" y=\"10\" width=\"4\" height=\"1\" rx=\".5\" fill=\"currentColor\"\/><\/svg>\n      PDF\n    <\/button>\n    <button class=\"btn btn-ghost\" id=\"btn-help\">\n      <svg width=\"13\" height=\"13\" viewBox=\"0 0 14 14\" fill=\"none\"><circle cx=\"7\" cy=\"7\" r=\"5.5\" stroke=\"currentColor\" stroke-width=\"1.6\"\/><path d=\"M5.5 5.5a1.5 1.5 0 0 1 3 0c0 1-1.5 1.5-1.5 2.5\" stroke=\"currentColor\" stroke-width=\"1.6\" stroke-linecap=\"round\"\/><circle cx=\"7\" cy=\"10.5\" r=\".75\" fill=\"currentColor\"\/><\/svg>\n      Help\n    <\/button>\n  <\/div>\n\n<\/div><!-- \/page-content -->\n\n<!-- \u2550\u2550 HELP MODAL \u2550\u2550 -->\n<div id=\"help-overlay\" style=\"display:none; position:fixed; inset:0; background:rgba(0,0,0,0.45); z-index:1000; align-items:center; justify-content:center; padding:20px;\">\n  <div id=\"help-modal\" style=\"background:#fff; border-radius:8px; box-shadow:0 8px 32px rgba(0,0,0,0.18); max-width:580px; width:100%; font-family:'Lato',Arial,sans-serif; overflow:hidden;\">\n    <!-- Modal header -->\n    <div style=\"background:#f6f6f6; border-bottom:1px solid #ddd; padding:18px 24px; display:flex; align-items:center; justify-content:space-between;\">\n      <h2 style=\"font-family:'Bitter',Georgia,serif; font-size:17px; font-weight:600; color:#2c2c2c; margin:0;\">How to use this calculator<\/h2>\n      <button id=\"help-close\" style=\"background:none; border:none; cursor:pointer; color:#888; font-size:20px; line-height:1; padding:0 2px;\">&times;<\/button>\n    <\/div>\n    <!-- Modal body -->\n    <div style=\"padding:24px; font-size:13px; color:#2c2c2c; line-height:1.65; max-height:70vh; overflow-y:auto;\">\n\n      <div style=\"margin-bottom:18px;\">\n        <div style=\"font-family:'Bitter',Georgia,serif; font-weight:600; font-size:14px; color:#e74c3c; margin-bottom:6px;\">1 \u2014 Material Library<\/div>\n        <p>The top table lists available materials with their unit weights (kN\/m\u00b3) or area loads (kN\/m\u00b2). <strong>Click a row<\/strong> to select it \u2014 a red dot appears to confirm your selection.<\/p>\n        <ul style=\"margin:8px 0 0 18px; display:flex; flex-direction:column; gap:4px;\">\n          <li><strong>Export txt<\/strong> \u2014 saves the current library to a tab-delimited <em>.txt<\/em> file.<\/li>\n          <li><strong>Import txt<\/strong> \u2014 loads materials from a tab-delimited <em>.txt<\/em> file and appends them to the existing list. Expected columns: <em>Material \u00b7 kN\/m\u00b3 \u00b7 kN\/m\u00b2<\/em> (header row is optional).<\/li>\n          <li><strong>Clear all<\/strong> \u2014 removes all materials from both the library and the load composition table.<\/li>\n        <\/ul>\n      <\/div>\n\n      <div style=\"margin-bottom:18px;\">\n        <div style=\"font-family:'Bitter',Georgia,serif; font-weight:600; font-size:14px; color:#e74c3c; margin-bottom:6px;\">2 \u2014 Load Composition<\/div>\n        <p>Build up the load by adding materials from the library:<\/p>\n        <ul style=\"margin:8px 0 0 18px; display:flex; flex-direction:column; gap:4px;\">\n          <li><strong>Add<\/strong> \u2014 adds the selected material as a new row.<\/li>\n          <li>Enter <strong>L<\/strong> (length), <strong>W<\/strong> (width) and <strong>H<\/strong> (height) in metres. For area loads (kN\/m\u00b2) the height field is disabled.<\/li>\n          <li>The <strong>Weight [kN]<\/strong> is calculated automatically:<br>\n            \u2014 volumetric: <em>kN\/m\u00b3 \u00d7 L \u00d7 W \u00d7 H<\/em><br>\n            \u2014 area load: <em>kN\/m\u00b2 \u00d7 L \u00d7 W<\/em>\n          <\/li>\n          <li><strong>Remove Selected<\/strong> \u2014 click a row to select it, then press this button to delete it.<\/li>\n          <li><strong>Clear All<\/strong> \u2014 empties the load composition table.<\/li>\n        <\/ul>\n      <\/div>\n\n      <div style=\"margin-bottom:18px;\">\n        <div style=\"font-family:'Bitter',Georgia,serif; font-weight:600; font-size:14px; color:#e74c3c; margin-bottom:6px;\">3 \u2014 Results<\/div>\n        <p>The results update automatically as you enter data:<\/p>\n        <ul style=\"margin:8px 0 0 18px; display:flex; flex-direction:column; gap:4px;\">\n          <li><strong>Total Load [kN]<\/strong> \u2014 sum of all weights in the load composition.<\/li>\n          <li><strong>Line Load [kN\/m]<\/strong> \u2014 total load divided by the beam span. Enter the span in metres to activate.<\/li>\n          <li><strong>Load per m\u00b2 [kN\/m\u00b2]<\/strong> \u2014 total load divided by the tributary width. Enter the width in metres to activate.<\/li>\n        <\/ul>\n      <\/div>\n\n      <div>\n        <div style=\"font-family:'Bitter',Georgia,serif; font-weight:600; font-size:14px; color:#e74c3c; margin-bottom:6px;\">4 \u2014 PDF export<\/div>\n        <p>Press <strong>PDF<\/strong> to open the browser print dialog. Choose <em>Save as PDF<\/em> as the destination. Only the Load Composition and Results sections are included \u2014 the Material Library and buttons are hidden.<\/p>\n      <\/div>\n\n    <\/div>\n    <!-- Modal footer -->\n    <div style=\"border-top:1px solid #ddd; padding:12px 24px; text-align:right; background:#f6f6f6;\">\n      <button id=\"help-close-btn\" class=\"btn btn-primary\" style=\"font-size:12px;\">Close<\/button>\n    <\/div>\n  <\/div>\n<\/div>\n\n<div class=\"toast\" id=\"toast\"><\/div>\n\n<script>\n$(function () {\n\n  let rowCounter = 0;\n  let selectedMaterial = null;\n  let selectedLoadId   = null;\n\n  \/* \u2500\u2500 Toast \u2500\u2500 *\/\n  function showToast(msg, isError) {\n    const $t = $('#toast');\n    $t.text(msg).removeClass('error show');\n    if (isError) $t.addClass('error');\n    requestAnimationFrame(() => {\n      $t.addClass('show');\n      setTimeout(() => $t.removeClass('show'), 2400);\n    });\n  }\n\n  \/* \u2500\u2500 Weight calculation \u2500\u2500 *\/\n  function calcWeight(knm3, knm2, l, w, h) {\n    const L = parseFloat(l) || 0;\n    const W = parseFloat(w) || 0;\n    const H = parseFloat(h) || 0;\n    if (knm3 !== '') return parseFloat(knm3) * L * W * H;\n    if (knm2 !== '') return parseFloat(knm2) * L * W;\n    return 0;\n  }\n\n  function updateRow($row) {\n    const knm3 = $row.data('knm3').toString();\n    const knm2 = $row.data('knm2').toString();\n    const wt = calcWeight(knm3, knm2,\n      $row.find('.inp-l').val(),\n      $row.find('.inp-w').val(),\n      $row.find('.inp-h').val());\n    const $wt = $row.find('.weight-cell');\n    $wt.text(wt.toFixed(3) + ' kN');\n    $wt.toggleClass('zero', wt === 0);\n    updateTotals();\n  }\n\n  function updateTotals() {\n    let total = 0;\n    $('#load-body tr').each(function () {\n      const v = parseFloat($(this).find('.weight-cell').text());\n      if (!isNaN(v)) total += v;\n    });\n\n    const hasRows = $('#load-body tr').length > 0;\n    $('#total-weight').text(total.toFixed(3) + ' kN');\n\n    const span = parseFloat($('#span-input').val()) || 0;\n    const trib = parseFloat($('#trib-input').val()) || 0;\n\n    if (hasRows) {\n      $('#result-placeholder').hide();\n      $('#result-box').addClass('has-results');\n      $('#res-total-block').show();\n      $('#res-total').text(total.toFixed(3));\n\n      if (span > 0) { $('#res-line-block').show(); $('#res-line').text((total \/ span).toFixed(3)); }\n      else           { $('#res-line-block').hide(); }\n\n      if (trib > 0) { $('#res-m2-block').show(); $('#res-m2').text((total \/ trib).toFixed(3)); }\n      else           { $('#res-m2-block').hide(); }\n    } else {\n      $('#result-placeholder').show();\n      $('#result-box').removeClass('has-results');\n      $('#res-total-block, #res-line-block, #res-m2-block').hide();\n    }\n  }\n\n  function syncEmpty() {\n    const hasRows = $('#load-body tr').length > 0;\n    $('#empty-state').toggleClass('visible', !hasRows);\n    $('#load-hint').toggle(hasRows);\n    $('#totals-row').toggle(hasRows);\n    updateTotals();\n  }\n\n  \/* \u2500\u2500 Select material \u2500\u2500 *\/\n  $('#material-tbody').on('click', 'tr', function () {\n    $('#material-tbody tr').removeClass('selected');\n    $(this).addClass('selected');\n    selectedMaterial = {\n      name: $(this).data('name'),\n      knm3: $(this).data('knm3').toString(),\n      knm2: $(this).data('knm2').toString()\n    };\n  });\n\n  \/* \u2500\u2500 Add \u2500\u2500 *\/\n  $('#btn-add').on('click', function () {\n    if (!selectedMaterial) { showToast('Select a material from the library first', true); return; }\n    const id = 'row-' + (++rowCounter);\n    const { name, knm3, knm2 } = selectedMaterial;\n    const hAttr = knm3 === '' ? 'disabled' : '';\n\n    const $row = $(`\n      <tr data-id=\"${id}\" data-knm3=\"${knm3}\" data-knm2=\"${knm2}\">\n        <td class=\"no-print\"><span class=\"sel-dot\"><\/span><\/td>\n        <td>${name}<\/td>\n        <td class=\"val\">${knm3 !== '' ? knm3 : '\u2014'}<\/td>\n        <td class=\"val\">${knm2 !== '' ? knm2 : '\u2014'}<\/td>\n        <td class=\"input-cell\"><input type=\"number\" class=\"inp-l\" placeholder=\"0.00\" min=\"0\" step=\"0.01\"><\/td>\n        <td class=\"input-cell\"><input type=\"number\" class=\"inp-w\" placeholder=\"0.00\" min=\"0\" step=\"0.01\"><\/td>\n        <td class=\"input-cell\"><input type=\"number\" class=\"inp-h\" placeholder=\"0.00\" min=\"0\" step=\"0.01\" ${hAttr}><\/td>\n        <td class=\"weight-cell zero\">0.000 kN<\/td>\n      <\/tr>`);\n\n    $('#load-body').append($row);\n    $row.addClass('flash');\n    setTimeout(() => $row.removeClass('flash'), 550);\n    syncEmpty();\n    showToast(name + ' added');\n  });\n\n  \/* \u2500\u2500 Select load row \u2500\u2500 *\/\n  $('#load-body').on('click', 'tr', function (e) {\n    if ($(e.target).is('input')) return;\n    $('#load-body tr').removeClass('selected');\n    $(this).addClass('selected');\n    selectedLoadId = $(this).data('id');\n  });\n\n  \/* \u2500\u2500 Remove \u2500\u2500 *\/\n  $('#btn-remove').on('click', function () {\n    if (!selectedLoadId) { showToast('Select a row in the load table first', true); return; }\n    const $row = $(`#load-body tr[data-id=\"${selectedLoadId}\"]`);\n    const name = $row.find('td:nth-child(2)').text();\n    $row.remove();\n    selectedLoadId = null;\n    syncEmpty();\n    showToast(name + ' removed');\n  });\n\n  \/* \u2500\u2500 Clear All (load table only) \u2500\u2500 *\/\n  $('#btn-clear').on('click', function () {\n    if (!$('#load-body tr').length) return;\n    $('#load-body').empty();\n    selectedLoadId = null;\n    syncEmpty();\n    showToast('Load table cleared');\n  });\n\n  \/* \u2500\u2500 Clear all (library + load table) \u2500\u2500 *\/\n  $('#btn-clear-all').on('click', function () {\n    \/\/ Default library rows to restore\n    const defaultRows = [\n      { name: 'Concrete (reinforced)',      knm3: '25',    knm2: '' },\n      { name: 'Steel',                      knm3: '77',    knm2: '' },\n      { name: 'Live load (1 kN\/m\u00b2)',        knm3: '',      knm2: '1' },\n      { name: 'Snow (0.5 kN\/m\u00b2)',           knm3: '',      knm2: '0.5' },\n      { name: 'Hollow core slab (WX 150)',  knm3: '',      knm2: '2.296' },\n      { name: 'Hollow core slab (WX 200)',  knm3: '',      knm2: '2.923' },\n      { name: 'Hollow core slab (WX 265)',  knm3: '',      knm2: '3.581' },\n      { name: 'Hollow core slab (WX 320)',  knm3: '',      knm2: '3.973' },\n      { name: 'Timber C18',                 knm3: '3.728', knm2: '' },\n      { name: 'Masonry',                    knm3: '15.7',  knm2: '' },\n      { name: 'Insulation (PUR)',           knm3: '0.294', knm2: '' }\n    ];\n    const $tbody = $('#material-tbody');\n    $tbody.empty();\n    defaultRows.forEach(r => {\n      $tbody.append(`\n        <tr data-name=\"${r.name}\" data-knm3=\"${r.knm3}\" data-knm2=\"${r.knm2}\">\n          <td><span class=\"sel-dot\"><\/span><\/td>\n          <td>${r.name}<\/td>\n          <td class=\"${r.knm3 ? 'val' : 'val empty'}\">${r.knm3 || '\u2014'}<\/td>\n          <td class=\"${r.knm2 ? 'val' : 'val empty'}\">${r.knm2 || '\u2014'}<\/td>\n        <\/tr>`);\n    });\n    selectedMaterial = null;\n    $('#load-body').empty();\n    selectedLoadId = null;\n    syncEmpty();\n    showToast('Material library and load table reset');\n  });\n\n  \/* \u2500\u2500 Live recalc \u2500\u2500 *\/\n  $('#load-body').on('input', 'input', function () { updateRow($(this).closest('tr')); });\n  $('#span-input, #trib-input').on('input', updateTotals);\n\n  \/* \u2500\u2500 Print \/ PDF \u2500\u2500 *\/\n  $('#btn-print').on('click', function () {\n    \/\/ Write span\/trib values as visible text for print\n    const spanVal = $('#span-input').val();\n    const tribVal = $('#trib-input').val();\n    $('#span-print').text(spanVal ? spanVal + ' m' : '\u2014');\n    $('#trib-print').text(tribVal ? tribVal + ' m' : '\u2014');\n    window.print();\n  });\n\n  \/* \u2500\u2500 Export materials as tab-delimited .txt \u2500\u2500 *\/\n  $('#btn-export').on('click', function () {\n    const lines = ['Material\\tkN\/m\u00b3\\tkN\/m\u00b2'];\n    $('#material-tbody tr').each(function () {\n      const name = $(this).data('name');\n      const knm3 = $(this).data('knm3').toString();\n      const knm2 = $(this).data('knm2').toString();\n      lines.push([name, knm3, knm2].join('\\t'));\n    });\n    const blob = new Blob([lines.join('\\r\\n')], { type: 'text\/plain;charset=utf-8' });\n    const url  = URL.createObjectURL(blob);\n    const a    = document.createElement('a');\n    a.href     = url;\n    a.download = 'materials.txt';\n    a.click();\n    URL.revokeObjectURL(url);\n    showToast('Materials exported to materials.txt');\n  });\n\n  \/* \u2500\u2500 Import materials from tab-delimited .txt \u2500\u2500 *\/\n  $('#btn-import').on('click', function () { $('#import-file').val('').click(); });\n\n  $('#import-file').on('change', function () {\n    const file = this.files[0];\n    if (!file) return;\n    const reader = new FileReader();\n    reader.onload = function (e) {\n      const lines = e.target.result.split(\/\\r?\\n\/).filter(l => l.trim());\n      \/\/ Skip header row if it starts with \"Material\"\n      const dataLines = lines[0].toLowerCase().startsWith('material') ? lines.slice(1) : lines;\n\n      if (!dataLines.length) { showToast('No data found in file', true); return; }\n\n      const $tbody = $('#material-tbody');\n      let count = 0;\n\n      dataLines.forEach(line => {\n        const parts = line.split('\\t');\n        if (parts.length < 2) return;\n        const name = parts[0].trim();\n        const knm3 = (parts[1] || '').trim();\n        const knm2 = (parts[2] || '').trim();\n        if (!name) return;\n\n        const knm3Disp  = knm3 !== '' ? knm3 : '\u2014';\n        const knm2Disp  = knm2 !== '' ? knm2 : '\u2014';\n        const knm3Class = knm3 !== '' ? 'val' : 'val empty';\n        const knm2Class = knm2 !== '' ? 'val' : 'val empty';\n\n        const $newRow = $(`\n          <tr data-name=\"${name}\" data-knm3=\"${knm3}\" data-knm2=\"${knm2}\">\n            <td><span class=\"sel-dot\"><\/span><\/td>\n            <td>${name}<\/td>\n            <td class=\"${knm3Class}\">${knm3Disp}<\/td>\n            <td class=\"${knm2Class}\">${knm2Disp}<\/td>\n          <\/tr>`);\n\n        $tbody.append($newRow);\n        $newRow.addClass('flash');\n        setTimeout(() => $newRow.removeClass('flash'), 550);\n        count++;\n      });\n\n      showToast(count + ' material' + (count !== 1 ? 's' : '') + ' added to library');\n    };\n    reader.readAsText(file);\n  });\n\n  \/* \u2500\u2500 Help modal \u2500\u2500 *\/\n  function openHelp() {\n    $('#help-overlay').css('display', 'flex');\n    $('body').css('overflow', 'hidden');\n  }\n\n  function closeHelp() {\n    $('#help-overlay').hide();\n    $('body').css('overflow', '');\n  }\n\n  $('#btn-help').on('click', openHelp);\n  $('#help-close, #help-close-btn').on('click', closeHelp);\n\n  \/\/ Close on backdrop click\n  $('#help-overlay').on('click', function (e) {\n    if ($(e.target).is('#help-overlay')) closeHelp();\n  });\n\n  \/\/ Close on Escape key\n  $(document).on('keydown', function (e) {\n    if (e.key === 'Escape') closeHelp();\n  });\n\n});\n<\/script>\n<\/body>\n<\/html>\n","protected":false},"excerpt":{"rendered":"<p>Line Load Calculator Material Library Click a row to select a material, then press Add Material kN\/m\u00b3 kN\/m\u00b2 Concrete (reinforced) 25 \u2014 Steel 77 \u2014 Live load (1 kN\/m\u00b2) \u2014 1 Snow (0.5 kN\/m\u00b2) \u2014 0.5 Hollow core slab (WX 150) \u2014 2.296 Hollow core slab (WX 200) \u2014 2.923&#8230;<\/p>\n","protected":false},"author":3,"comment_status":"closed","ping_status":"closed","template":"","format":"standard","meta":[],"ht-kb-category":[1269],"ht-kb-tag":[1368,1365,1363,1364,1366,1367],"_links":{"self":[{"href":"https:\/\/support.buildsoft.eu\/es\/wp-json\/wp\/v2\/ht-kb\/29831"}],"collection":[{"href":"https:\/\/support.buildsoft.eu\/es\/wp-json\/wp\/v2\/ht-kb"}],"about":[{"href":"https:\/\/support.buildsoft.eu\/es\/wp-json\/wp\/v2\/types\/ht_kb"}],"author":[{"embeddable":true,"href":"https:\/\/support.buildsoft.eu\/es\/wp-json\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"https:\/\/support.buildsoft.eu\/es\/wp-json\/wp\/v2\/comments?post=29831"}],"version-history":[{"count":2,"href":"https:\/\/support.buildsoft.eu\/es\/wp-json\/wp\/v2\/ht-kb\/29831\/revisions"}],"predecessor-version":[{"id":29854,"href":"https:\/\/support.buildsoft.eu\/es\/wp-json\/wp\/v2\/ht-kb\/29831\/revisions\/29854"}],"wp:attachment":[{"href":"https:\/\/support.buildsoft.eu\/es\/wp-json\/wp\/v2\/media?parent=29831"}],"wp:term":[{"taxonomy":"ht_kb_category","embeddable":true,"href":"https:\/\/support.buildsoft.eu\/es\/wp-json\/wp\/v2\/ht-kb-category?post=29831"},{"taxonomy":"ht_kb_tag","embeddable":true,"href":"https:\/\/support.buildsoft.eu\/es\/wp-json\/wp\/v2\/ht-kb-tag?post=29831"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}