<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>lijnlasten &#8211; BuildSoft Support</title>
	<atom:link href="https://support.buildsoft.eu/fr/article-tags/lijnlasten/feed/" rel="self" type="application/rss+xml" />
	<link>https://support.buildsoft.eu/fr/</link>
	<description>BuildSoft Support</description>
	<lastBuildDate>Tue, 23 Jun 2026 07:26:46 +0000</lastBuildDate>
	<language>fr-FR</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.2.14</generator>
	<item>
		<title>Online line load calculator</title>
		<link>https://support.buildsoft.eu/fr/knowledge-base/line-load-calculator/</link>
		
		<dc:creator><![CDATA[Dorien Elleboog]]></dc:creator>
		<pubDate>Mon, 15 Jun 2026 10:33:06 +0000</pubDate>
				<guid isPermaLink="false">https://support.buildsoft.eu/?post_type=ht_kb&#038;p=29831</guid>

					<description><![CDATA[Line Load Calculator Material Library Click a row to select a material, then press Add Material kN/m³ kN/m² Concrete (reinforced) 25 — Steel 77 — Live load (1 kN/m²) — 1 Snow (0.5 kN/m²) — 0.5 Hollow core slab (WX 150) — 2.296 Hollow core slab (WX 200) — 2.923...]]></description>
										<content:encoded><![CDATA[
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Line Load Calculator</title>
<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">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
<style>
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

:root {
  --red:          #e74c3c;
  --red-dark:     #c0392b;
  --text:         #2c2c2c;
  --muted:        #888;
  --light:        #f6f6f6;
  --border:       #ddd;
  --white:        #fff;
  --shadow:       0 1px 4px rgba(0,0,0,0.09);
  --input-border: #ccc;
  --sel-bg:       #fff8f7;
  --sel-border:   #e74c3c;
  --result-bg:    #f0f0f0;
}

body {
  background: #f9f9f9;
  color: var(--text);
  font-family: 'Lato', Arial, sans-serif;
  font-size: 14px;
  line-height: 1.55;
}

/* ── PAGE ── */
.page-content {
  max-width: 980px;
  margin: 0 auto;
  padding: 36px 24px 60px;
}

h1 {
  font-family: 'Bitter', Georgia, serif;
  font-size: 30px;
  font-weight: 700;
  color: var(--text);
  margin-bottom: 28px;
  letter-spacing: -0.01em;
}

/* ── CARD ── */
.calc-card {
  background: var(--white);
  border: 1px solid var(--border);
  border-radius: 8px;
  box-shadow: var(--shadow);
  margin-bottom: 24px;
  overflow: hidden;
}

.calc-card-header {
  padding: 20px 26px 14px;
  border-bottom: 1px solid var(--border);
}

.calc-card-header h2 {
  font-family: 'Bitter', Georgia, serif;
  font-size: 17px;
  font-weight: 600;
  color: var(--text);
  margin-bottom: 3px;
}

.calc-card-header .ref {
  font-size: 12px;
  color: var(--muted);
  font-style: italic;
}

.calc-card-body { padding: 20px 26px; }

/* ── TABLES ── */
table {
  width: 100%;
  border-collapse: collapse;
  font-size: 13px;
}

thead tr {
  background: var(--light);
  border-bottom: 2px solid var(--border);
}

thead th {
  padding: 9px 13px;
  text-align: left;
  font-size: 11px;
  font-weight: 700;
  color: var(--muted);
  letter-spacing: 0.05em;
  white-space: nowrap;
  font-family: 'Lato', Arial, sans-serif;
}

thead th.right { text-align: right; }

tbody tr {
  border-bottom: 1px solid var(--border);
  cursor: pointer;
  transition: background 0.1s;
}

tbody tr:last-child { border-bottom: none; }
tbody tr:hover { background: #fafafa; }

tbody tr.selected {
  background: var(--sel-bg);
  border-left: 3px solid var(--sel-border);
}

tbody tr.selected td:first-child { padding-left: 11px; }

td {
  padding: 9px 13px;
  color: var(--text);
  vertical-align: middle;
}

td.val { text-align: right; }
td.val.empty { color: #bbb; }

/* ── HINT BAR ── */
.hint-bar {
  background: var(--light);
  border-top: 1px solid var(--border);
  padding: 7px 13px;
  font-size: 11px;
  color: var(--muted);
  font-style: italic;
}

/* ── BUTTON ROWS ── */
.btn-row {
  display: flex;
  gap: 8px;
  margin-bottom: 14px;
  flex-wrap: wrap;
  align-items: center;
}

.btn {
  font-family: 'Lato', Arial, sans-serif;
  font-size: 12px;
  font-weight: 700;
  padding: 7px 16px;
  border-radius: 4px;
  cursor: pointer;
  border: none;
  transition: background 0.15s, transform 0.1s;
  letter-spacing: 0.03em;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  white-space: nowrap;
}

.btn:active { transform: scale(0.98); }

.btn-primary { background: var(--red); color: #fff; }
.btn-primary:hover { background: var(--red-dark); }

.btn-outline {
  background: #fff;
  color: var(--red);
  border: 1px solid var(--red);
}
.btn-outline:hover { background: #fff5f4; }

.btn-ghost {
  background: #fff;
  color: var(--muted);
  border: 1px solid var(--border);
}
.btn-ghost:hover { background: var(--light); color: var(--text); }

.btn-print {
  background: #fff;
  color: #555;
  border: 1px solid var(--border);
}
.btn-print:hover { background: var(--light); }

/* ── NUMBER INPUTS ── */
input[type="number"] {
  font-family: 'Lato', Arial, sans-serif;
  font-size: 13px;
  color: var(--text);
  background: #fff;
  border: 1px solid var(--input-border);
  border-radius: 4px;
  padding: 5px 8px;
  width: 80px;
  text-align: right;
  transition: border-color 0.15s, box-shadow 0.15s;
  -moz-appearance: textfield;
}

input[type="number"]::-webkit-outer-spin-button,
input[type="number"]::-webkit-inner-spin-button { -webkit-appearance: none; }

input[type="number"]:focus {
  outline: none;
  border-color: var(--red);
  box-shadow: 0 0 0 2px rgba(231,76,60,0.13);
}

input[type="number"]:disabled {
  background: var(--light);
  color: #bbb;
  cursor: not-allowed;
}

td.input-cell { padding: 6px 9px; text-align: right; }

/* ── WEIGHT CELL ── */
td.weight-cell {
  text-align: right;
  font-weight: 700;
  color: var(--text);
  white-space: nowrap;
}

td.weight-cell.zero { color: #bbb; font-weight: 400; }

/* ── TOTALS ROW ── */
.totals-row {
  background: var(--light) !important;
  border-top: 2px solid var(--border) !important;
  cursor: default !important;
}

.totals-row:hover { background: var(--light) !important; }

.totals-row td {
  font-size: 11px;
  font-weight: 700;
  color: var(--muted);
  letter-spacing: 0.05em;
  padding: 10px 13px;
}

.totals-row .total-val {
  text-align: right;
  font-size: 15px;
  color: var(--red);
  font-weight: 700;
}

/* ── EMPTY STATE ── */
.empty-state {
  padding: 28px;
  text-align: center;
  color: #bbb;
  font-size: 13px;
  font-style: italic;
  display: none;
}

.empty-state.visible { display: block; }

/* ── LINE LOAD INPUTS ── */
.ll-inputs {
  display: flex;
  gap: 24px;
  flex-wrap: wrap;
  margin-top: 18px;
  padding-top: 18px;
  border-top: 1px solid var(--border);
}

.field-group { display: flex; flex-direction: column; gap: 5px; }

.field-group label {
  font-size: 12px;
  font-weight: 700;
  color: var(--text);
  display: flex;
  align-items: baseline;
  gap: 5px;
}

.field-group label .unit { font-size: 11px; color: var(--muted); font-weight: 400; }

.field-group input[type="number"] {
  width: 130px;
  text-align: left;
  padding: 7px 10px;
  font-size: 14px;
}

/* ── RESULT BOX ── */
.result-box {
  background: var(--result-bg);
  border: 1px solid #ddd;
  border-radius: 6px;
  padding: 20px 24px;
  color: var(--muted);
  font-style: italic;
  font-size: 14px;
  min-height: 72px;
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 36px;
}

.result-box.has-results {
  font-style: normal;
  background: #fff;
  border-color: var(--border);
}

.result-item { display: flex; flex-direction: column; gap: 2px; }

.result-item label {
  font-size: 11px;
  color: var(--muted);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  font-style: normal;
}

.result-item .rval {
  font-family: 'Bitter', Georgia, serif;
  font-size: 24px;
  font-weight: 700;
  color: var(--red);
  font-style: normal;
  line-height: 1.1;
}

.result-item .runit { font-size: 11px; color: var(--muted); font-style: normal; }

/* ── REF FOOTER ── */
.ref-footer {
  text-align: center;
  font-size: 11px;
  color: var(--muted);
  padding: 12px 0 0;
}

/* ── SEL DOT ── */
.sel-dot {
  display: inline-block;
  width: 7px; height: 7px;
  border-radius: 50%;
  background: var(--red);
  opacity: 0;
  transition: opacity 0.15s;
  margin-right: 5px;
  vertical-align: middle;
}

tr.selected .sel-dot { opacity: 1; }

/* ── FLASH ── */
@keyframes rowFlash {
  0%   { background: #fff0ef; }
  100% { background: transparent; }
}
.flash { animation: rowFlash 0.55s ease-out; }

/* ── TOAST ── */
.toast {
  position: fixed;
  bottom: 24px; right: 24px;
  background: var(--text);
  color: #fff;
  font-size: 12px;
  font-family: 'Lato', Arial, sans-serif;
  padding: 10px 18px;
  border-radius: 4px;
  opacity: 0;
  transform: translateY(8px);
  transition: all 0.22s;
  pointer-events: none;
  z-index: 999;
  box-shadow: 0 2px 8px rgba(0,0,0,0.18);
}

.toast.show { opacity: 1; transform: translateY(0); }
.toast.error { background: var(--red); }

/* ── PRINT STYLES ── */
@media print {
  body { background: #fff; font-size: 12px; }
  .no-print { display: none !important; }
  .print-only { display: block !important; }
  .calc-card { box-shadow: none; break-inside: avoid; }
  .page-content { padding: 0; max-width: 100%; }
  input[type="number"] { border: none; background: transparent; }
  .btn-row, .ll-inputs .field-group input { display: none; }
  .ll-inputs { border-top: 1px solid #ddd; }
  .print-val { display: inline !important; }
}

.print-only { display: none; }

@media (max-width: 680px) {
  .page-content { padding: 16px 12px 40px; }
  .calc-card-body { padding: 14px; }
  .calc-card-header { padding: 14px 14px 10px; }
  table { font-size: 12px; }
}
</style>
</head>
<body>

<div class="page-content">


  <!-- ══ CARD 1: MATERIAL LIBRARY ══ -->
  <div class="calc-card no-print">
    <div class="calc-card-header">
      <h2>Material Library</h2>
      <div class="ref">Click a row to select a material, then press <strong>Add</strong></div>
    </div>
    <div class="calc-card-body" style="padding:0;">
      <table id="material-table" style="table-layout:fixed; width:100%;">
        <colgroup>
          <col style="width:20px;">
          <col>
          <col style="width:90px;">
          <col style="width:90px;">
        </colgroup>
        <thead>
          <tr>
            <th style="width:20px;"></th>
            <th>Material</th>
            <th class="right">kN/m³</th>
            <th class="right">kN/m²</th>
          </tr>
        </thead>
      </table>
      <div id="material-tbody-wrapper" style="max-height:330px; overflow-y:auto;">
        <table style="table-layout:fixed; width:100%;">
          <colgroup>
            <col style="width:20px;">
            <col>
            <col style="width:90px;">
            <col style="width:90px;">
          </colgroup>
          <tbody id="material-tbody">
          <tr data-name="Concrete (reinforced)" data-knm3="25" data-knm2="">
            <td><span class="sel-dot"></span></td>
            <td>Concrete (reinforced)</td>
            <td class="val">25</td>
            <td class="val empty">—</td>
          </tr>
          <tr data-name="Steel" data-knm3="77" data-knm2="">
            <td><span class="sel-dot"></span></td>
            <td>Steel</td>
            <td class="val">77</td>
            <td class="val empty">—</td>
          </tr>
          <tr data-name="Live load (1 kN/m²)" data-knm3="" data-knm2="1">
            <td><span class="sel-dot"></span></td>
            <td>Live load (1 kN/m²)</td>
            <td class="val empty">—</td>
            <td class="val">1</td>
          </tr>
          <tr data-name="Snow (0.5 kN/m²)" data-knm3="" data-knm2="0.5">
            <td><span class="sel-dot"></span></td>
            <td>Snow (0.5 kN/m²)</td>
            <td class="val empty">—</td>
            <td class="val">0.5</td>
          </tr>
          <tr data-name="Hollow core slab (WX 150)" data-knm3="" data-knm2="2.296">
            <td><span class="sel-dot"></span></td>
            <td>Hollow core slab (WX 150)</td>
            <td class="val empty">—</td>
            <td class="val">2.296</td>
          </tr>
          <tr data-name="Hollow core slab (WX 200)" data-knm3="" data-knm2="2.923">
            <td><span class="sel-dot"></span></td>
            <td>Hollow core slab (WX 200)</td>
            <td class="val empty">—</td>
            <td class="val">2.923</td>
          </tr>
          <tr data-name="Hollow core slab (WX 265)" data-knm3="" data-knm2="3.581">
            <td><span class="sel-dot"></span></td>
            <td>Hollow core slab (WX 265)</td>
            <td class="val empty">—</td>
            <td class="val">3.581</td>
          </tr>
          <tr data-name="Hollow core slab (WX 320)" data-knm3="" data-knm2="3.973">
            <td><span class="sel-dot"></span></td>
            <td>Hollow core slab (WX 320)</td>
            <td class="val empty">—</td>
            <td class="val">3.973</td>
          </tr>
          <tr data-name="Timber C18" data-knm3="3.728" data-knm2="">
            <td><span class="sel-dot"></span></td>
            <td>Timber C18</td>
            <td class="val">3.728</td>
            <td class="val empty">—</td>
          </tr>
          <tr data-name="Masonry" data-knm3="15.7" data-knm2="">
            <td><span class="sel-dot"></span></td>
            <td>Masonry</td>
            <td class="val">15.7</td>
            <td class="val empty">—</td>
          </tr>
          <tr data-name="Insulation (PUR)" data-knm3="0.294" data-knm2="">
            <td><span class="sel-dot"></span></td>
            <td>Insulation (PUR)</td>
            <td class="val">0.294</td>
            <td class="val empty">—</td>
          </tr>
        </tbody>
        </table>
      </div>
    </div>
    <!-- Export / Import / Clear all buttons -->
    <div style="padding: 12px 14px; border-top: 1px solid var(--border); background: var(--light); display:flex; gap:8px; flex-wrap:wrap;">
      <button class="btn btn-ghost" id="btn-export">
        <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>
        Export txt
      </button>
      <button class="btn btn-ghost" id="btn-import">
        <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>
        Import txt
      </button>
      <input type="file" id="import-file" accept=".txt" style="display:none;">
      <button class="btn btn-ghost" id="btn-clear-all">
        <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>
        Clear all
      </button>
    </div>
  </div>

  <!-- ══ CARD 2: LOAD COMPOSITION ══ -->
  <div class="calc-card" id="card-composition">
    <div class="calc-card-header">
      <h2>Load Composition</h2>
      <div class="ref">Enter dimensions per material — weight is calculated automatically</div>
    </div>
    <div class="calc-card-body" style="padding: 16px 26px 20px;">

      <div class="btn-row no-print">
        <button class="btn btn-primary" id="btn-add">
          <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>
          Add
        </button>
        <button class="btn btn-outline" id="btn-remove">
          <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>
          Remove
        </button>
        <button class="btn btn-ghost" id="btn-clear">
          <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>
          Clear All
        </button>
      </div>

      <div class="calc-card" style="margin-bottom:0; box-shadow:none;">
        <table id="load-table">
          <thead>
            <tr>
              <th style="width:16px;" class="no-print"></th>
              <th>Material</th>
              <th class="right">kN/m³</th>
              <th class="right">kN/m²</th>
              <th class="right">L [m]</th>
              <th class="right">W [m]</th>
              <th class="right">H [m]</th>
              <th class="right">Weight [kN]</th>
            </tr>
          </thead>
          <tbody id="load-body"></tbody>
          <tfoot>
            <tr class="totals-row" id="totals-row" style="display:none;">
              <td colspan="7" style="text-align:right;">TOTAL LOAD</td>
              <td class="total-val" id="total-weight">0.000 kN</td>
            </tr>
          </tfoot>
        </table>
        <div class="empty-state visible" id="empty-state">No materials added yet — select from the library above and click <em>Add</em></div>
        <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>
      </div>

      <!-- LINE LOAD INPUTS -->
      <div class="ll-inputs">
        <div class="field-group">
          <label>Beam span <span class="unit">[m]</span></label>
          <input type="number" id="span-input" placeholder="e.g. 5.0" min="0" step="0.1">
          <span class="print-only print-val" id="span-print"></span>
        </div>
        <div class="field-group">
          <label>Tributary width <span class="unit">[m]</span></label>
          <input type="number" id="trib-input" placeholder="e.g. 3.0" min="0" step="0.1">
          <span class="print-only print-val" id="trib-print"></span>
        </div>
      </div>
    </div>
  </div>

  <!-- ══ CARD 3: RESULTS ══ -->
  <div class="calc-card" id="card-results">
    <div class="calc-card-header">
      <h2>Results</h2>
    </div>
    <div class="calc-card-body">
      <div class="result-box" id="result-box">
        <span id="result-placeholder">Fill in materials and dimensions to see results</span>
        <div class="result-item" id="res-total-block" style="display:none;">
          <label>Total Load</label>
          <div class="rval" id="res-total">—</div>
          <div class="runit">kN</div>
        </div>
        <div class="result-item" id="res-line-block" style="display:none;">
          <label>Line Load</label>
          <div class="rval" id="res-line">—</div>
          <div class="runit">kN/m</div>
        </div>
        <div class="result-item" id="res-m2-block" style="display:none;">
          <label>Load per m²</label>
          <div class="rval" id="res-m2">—</div>
          <div class="runit">kN/m²</div>
        </div>
      </div>
      <div class="ref-footer">Load descent — line load calculation per beam or wall element</div>
    </div>
  </div>

  <!-- ══ BOTTOM BUTTONS ══ -->
  <div style="display:flex; justify-content:flex-end; gap:8px; margin-top:4px;" class="no-print">
    <button class="btn btn-print" id="btn-print">
      <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>
      PDF
    </button>
    <button class="btn btn-ghost" id="btn-help">
      <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>
      Help
    </button>
  </div>

</div><!-- /page-content -->

<!-- ══ HELP MODAL ══ -->
<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;">
  <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;">
    <!-- Modal header -->
    <div style="background:#f6f6f6; border-bottom:1px solid #ddd; padding:18px 24px; display:flex; align-items:center; justify-content:space-between;">
      <h2 style="font-family:'Bitter',Georgia,serif; font-size:17px; font-weight:600; color:#2c2c2c; margin:0;">How to use this calculator</h2>
      <button id="help-close" style="background:none; border:none; cursor:pointer; color:#888; font-size:20px; line-height:1; padding:0 2px;">&times;</button>
    </div>
    <!-- Modal body -->
    <div style="padding:24px; font-size:13px; color:#2c2c2c; line-height:1.65; max-height:70vh; overflow-y:auto;">

      <div style="margin-bottom:18px;">
        <div style="font-family:'Bitter',Georgia,serif; font-weight:600; font-size:14px; color:#e74c3c; margin-bottom:6px;">1 — Material Library</div>
        <p>The top table lists available materials with their unit weights (kN/m³) or area loads (kN/m²). <strong>Click a row</strong> to select it — a red dot appears to confirm your selection.</p>
        <ul style="margin:8px 0 0 18px; display:flex; flex-direction:column; gap:4px;">
          <li><strong>Export txt</strong> — saves the current library to a tab-delimited <em>.txt</em> file.</li>
          <li><strong>Import txt</strong> — loads materials from a tab-delimited <em>.txt</em> file and appends them to the existing list. Expected columns: <em>Material · kN/m³ · kN/m²</em> (header row is optional).</li>
          <li><strong>Clear all</strong> — removes all materials from both the library and the load composition table.</li>
        </ul>
      </div>

      <div style="margin-bottom:18px;">
        <div style="font-family:'Bitter',Georgia,serif; font-weight:600; font-size:14px; color:#e74c3c; margin-bottom:6px;">2 — Load Composition</div>
        <p>Build up the load by adding materials from the library:</p>
        <ul style="margin:8px 0 0 18px; display:flex; flex-direction:column; gap:4px;">
          <li><strong>Add</strong> — adds the selected material as a new row.</li>
          <li>Enter <strong>L</strong> (length), <strong>W</strong> (width) and <strong>H</strong> (height) in metres. For area loads (kN/m²) the height field is disabled.</li>
          <li>The <strong>Weight [kN]</strong> is calculated automatically:<br>
            — volumetric: <em>kN/m³ × L × W × H</em><br>
            — area load: <em>kN/m² × L × W</em>
          </li>
          <li><strong>Remove Selected</strong> — click a row to select it, then press this button to delete it.</li>
          <li><strong>Clear All</strong> — empties the load composition table.</li>
        </ul>
      </div>

      <div style="margin-bottom:18px;">
        <div style="font-family:'Bitter',Georgia,serif; font-weight:600; font-size:14px; color:#e74c3c; margin-bottom:6px;">3 — Results</div>
        <p>The results update automatically as you enter data:</p>
        <ul style="margin:8px 0 0 18px; display:flex; flex-direction:column; gap:4px;">
          <li><strong>Total Load [kN]</strong> — sum of all weights in the load composition.</li>
          <li><strong>Line Load [kN/m]</strong> — total load divided by the beam span. Enter the span in metres to activate.</li>
          <li><strong>Load per m² [kN/m²]</strong> — total load divided by the tributary width. Enter the width in metres to activate.</li>
        </ul>
      </div>

      <div>
        <div style="font-family:'Bitter',Georgia,serif; font-weight:600; font-size:14px; color:#e74c3c; margin-bottom:6px;">4 — PDF export</div>
        <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 — the Material Library and buttons are hidden.</p>
      </div>

    </div>
    <!-- Modal footer -->
    <div style="border-top:1px solid #ddd; padding:12px 24px; text-align:right; background:#f6f6f6;">
      <button id="help-close-btn" class="btn btn-primary" style="font-size:12px;">Close</button>
    </div>
  </div>
</div>

<div class="toast" id="toast"></div>

<script>
$(function () {

  let rowCounter = 0;
  let selectedMaterial = null;
  let selectedLoadId   = null;

  /* ── Toast ── */
  function showToast(msg, isError) {
    const $t = $('#toast');
    $t.text(msg).removeClass('error show');
    if (isError) $t.addClass('error');
    requestAnimationFrame(() => {
      $t.addClass('show');
      setTimeout(() => $t.removeClass('show'), 2400);
    });
  }

  /* ── Weight calculation ── */
  function calcWeight(knm3, knm2, l, w, h) {
    const L = parseFloat(l) || 0;
    const W = parseFloat(w) || 0;
    const H = parseFloat(h) || 0;
    if (knm3 !== '') return parseFloat(knm3) * L * W * H;
    if (knm2 !== '') return parseFloat(knm2) * L * W;
    return 0;
  }

  function updateRow($row) {
    const knm3 = $row.data('knm3').toString();
    const knm2 = $row.data('knm2').toString();
    const wt = calcWeight(knm3, knm2,
      $row.find('.inp-l').val(),
      $row.find('.inp-w').val(),
      $row.find('.inp-h').val());
    const $wt = $row.find('.weight-cell');
    $wt.text(wt.toFixed(3) + ' kN');
    $wt.toggleClass('zero', wt === 0);
    updateTotals();
  }

  function updateTotals() {
    let total = 0;
    $('#load-body tr').each(function () {
      const v = parseFloat($(this).find('.weight-cell').text());
      if (!isNaN(v)) total += v;
    });

    const hasRows = $('#load-body tr').length > 0;
    $('#total-weight').text(total.toFixed(3) + ' kN');

    const span = parseFloat($('#span-input').val()) || 0;
    const trib = parseFloat($('#trib-input').val()) || 0;

    if (hasRows) {
      $('#result-placeholder').hide();
      $('#result-box').addClass('has-results');
      $('#res-total-block').show();
      $('#res-total').text(total.toFixed(3));

      if (span > 0) { $('#res-line-block').show(); $('#res-line').text((total / span).toFixed(3)); }
      else           { $('#res-line-block').hide(); }

      if (trib > 0) { $('#res-m2-block').show(); $('#res-m2').text((total / trib).toFixed(3)); }
      else           { $('#res-m2-block').hide(); }
    } else {
      $('#result-placeholder').show();
      $('#result-box').removeClass('has-results');
      $('#res-total-block, #res-line-block, #res-m2-block').hide();
    }
  }

  function syncEmpty() {
    const hasRows = $('#load-body tr').length > 0;
    $('#empty-state').toggleClass('visible', !hasRows);
    $('#load-hint').toggle(hasRows);
    $('#totals-row').toggle(hasRows);
    updateTotals();
  }

  /* ── Select material ── */
  $('#material-tbody').on('click', 'tr', function () {
    $('#material-tbody tr').removeClass('selected');
    $(this).addClass('selected');
    selectedMaterial = {
      name: $(this).data('name'),
      knm3: $(this).data('knm3').toString(),
      knm2: $(this).data('knm2').toString()
    };
  });

  /* ── Add ── */
  $('#btn-add').on('click', function () {
    if (!selectedMaterial) { showToast('Select a material from the library first', true); return; }
    const id = 'row-' + (++rowCounter);
    const { name, knm3, knm2 } = selectedMaterial;
    const hAttr = knm3 === '' ? 'disabled' : '';

    const $row = $(`
      <tr data-id="${id}" data-knm3="${knm3}" data-knm2="${knm2}">
        <td class="no-print"><span class="sel-dot"></span></td>
        <td>${name}</td>
        <td class="val">${knm3 !== '' ? knm3 : '—'}</td>
        <td class="val">${knm2 !== '' ? knm2 : '—'}</td>
        <td class="input-cell"><input type="number" class="inp-l" placeholder="0.00" min="0" step="0.01"></td>
        <td class="input-cell"><input type="number" class="inp-w" placeholder="0.00" min="0" step="0.01"></td>
        <td class="input-cell"><input type="number" class="inp-h" placeholder="0.00" min="0" step="0.01" ${hAttr}></td>
        <td class="weight-cell zero">0.000 kN</td>
      </tr>`);

    $('#load-body').append($row);
    $row.addClass('flash');
    setTimeout(() => $row.removeClass('flash'), 550);
    syncEmpty();
    showToast(name + ' added');
  });

  /* ── Select load row ── */
  $('#load-body').on('click', 'tr', function (e) {
    if ($(e.target).is('input')) return;
    $('#load-body tr').removeClass('selected');
    $(this).addClass('selected');
    selectedLoadId = $(this).data('id');
  });

  /* ── Remove ── */
  $('#btn-remove').on('click', function () {
    if (!selectedLoadId) { showToast('Select a row in the load table first', true); return; }
    const $row = $(`#load-body tr[data-id="${selectedLoadId}"]`);
    const name = $row.find('td:nth-child(2)').text();
    $row.remove();
    selectedLoadId = null;
    syncEmpty();
    showToast(name + ' removed');
  });

  /* ── Clear All (load table only) ── */
  $('#btn-clear').on('click', function () {
    if (!$('#load-body tr').length) return;
    $('#load-body').empty();
    selectedLoadId = null;
    syncEmpty();
    showToast('Load table cleared');
  });

  /* ── Clear all (library + load table) ── */
  $('#btn-clear-all').on('click', function () {
    // Default library rows to restore
    const defaultRows = [
      { name: 'Concrete (reinforced)',      knm3: '25',    knm2: '' },
      { name: 'Steel',                      knm3: '77',    knm2: '' },
      { name: 'Live load (1 kN/m²)',        knm3: '',      knm2: '1' },
      { name: 'Snow (0.5 kN/m²)',           knm3: '',      knm2: '0.5' },
      { name: 'Hollow core slab (WX 150)',  knm3: '',      knm2: '2.296' },
      { name: 'Hollow core slab (WX 200)',  knm3: '',      knm2: '2.923' },
      { name: 'Hollow core slab (WX 265)',  knm3: '',      knm2: '3.581' },
      { name: 'Hollow core slab (WX 320)',  knm3: '',      knm2: '3.973' },
      { name: 'Timber C18',                 knm3: '3.728', knm2: '' },
      { name: 'Masonry',                    knm3: '15.7',  knm2: '' },
      { name: 'Insulation (PUR)',           knm3: '0.294', knm2: '' }
    ];
    const $tbody = $('#material-tbody');
    $tbody.empty();
    defaultRows.forEach(r => {
      $tbody.append(`
        <tr data-name="${r.name}" data-knm3="${r.knm3}" data-knm2="${r.knm2}">
          <td><span class="sel-dot"></span></td>
          <td>${r.name}</td>
          <td class="${r.knm3 ? 'val' : 'val empty'}">${r.knm3 || '—'}</td>
          <td class="${r.knm2 ? 'val' : 'val empty'}">${r.knm2 || '—'}</td>
        </tr>`);
    });
    selectedMaterial = null;
    $('#load-body').empty();
    selectedLoadId = null;
    syncEmpty();
    showToast('Material library and load table reset');
  });

  /* ── Live recalc ── */
  $('#load-body').on('input', 'input', function () { updateRow($(this).closest('tr')); });
  $('#span-input, #trib-input').on('input', updateTotals);

  /* ── Print / PDF ── */
  $('#btn-print').on('click', function () {
    // Write span/trib values as visible text for print
    const spanVal = $('#span-input').val();
    const tribVal = $('#trib-input').val();
    $('#span-print').text(spanVal ? spanVal + ' m' : '—');
    $('#trib-print').text(tribVal ? tribVal + ' m' : '—');
    window.print();
  });

  /* ── Export materials as tab-delimited .txt ── */
  $('#btn-export').on('click', function () {
    const lines = ['Material\tkN/m³\tkN/m²'];
    $('#material-tbody tr').each(function () {
      const name = $(this).data('name');
      const knm3 = $(this).data('knm3').toString();
      const knm2 = $(this).data('knm2').toString();
      lines.push([name, knm3, knm2].join('\t'));
    });
    const blob = new Blob([lines.join('\r\n')], { type: 'text/plain;charset=utf-8' });
    const url  = URL.createObjectURL(blob);
    const a    = document.createElement('a');
    a.href     = url;
    a.download = 'materials.txt';
    a.click();
    URL.revokeObjectURL(url);
    showToast('Materials exported to materials.txt');
  });

  /* ── Import materials from tab-delimited .txt ── */
  $('#btn-import').on('click', function () { $('#import-file').val('').click(); });

  $('#import-file').on('change', function () {
    const file = this.files[0];
    if (!file) return;
    const reader = new FileReader();
    reader.onload = function (e) {
      const lines = e.target.result.split(/\r?\n/).filter(l => l.trim());
      // Skip header row if it starts with "Material"
      const dataLines = lines[0].toLowerCase().startsWith('material') ? lines.slice(1) : lines;

      if (!dataLines.length) { showToast('No data found in file', true); return; }

      const $tbody = $('#material-tbody');
      let count = 0;

      dataLines.forEach(line => {
        const parts = line.split('\t');
        if (parts.length < 2) return;
        const name = parts[0].trim();
        const knm3 = (parts[1] || '').trim();
        const knm2 = (parts[2] || '').trim();
        if (!name) return;

        const knm3Disp  = knm3 !== '' ? knm3 : '—';
        const knm2Disp  = knm2 !== '' ? knm2 : '—';
        const knm3Class = knm3 !== '' ? 'val' : 'val empty';
        const knm2Class = knm2 !== '' ? 'val' : 'val empty';

        const $newRow = $(`
          <tr data-name="${name}" data-knm3="${knm3}" data-knm2="${knm2}">
            <td><span class="sel-dot"></span></td>
            <td>${name}</td>
            <td class="${knm3Class}">${knm3Disp}</td>
            <td class="${knm2Class}">${knm2Disp}</td>
          </tr>`);

        $tbody.append($newRow);
        $newRow.addClass('flash');
        setTimeout(() => $newRow.removeClass('flash'), 550);
        count++;
      });

      showToast(count + ' material' + (count !== 1 ? 's' : '') + ' added to library');
    };
    reader.readAsText(file);
  });

  /* ── Help modal ── */
  function openHelp() {
    $('#help-overlay').css('display', 'flex');
    $('body').css('overflow', 'hidden');
  }

  function closeHelp() {
    $('#help-overlay').hide();
    $('body').css('overflow', '');
  }

  $('#btn-help').on('click', openHelp);
  $('#help-close, #help-close-btn').on('click', closeHelp);

  // Close on backdrop click
  $('#help-overlay').on('click', function (e) {
    if ($(e.target).is('#help-overlay')) closeHelp();
  });

  // Close on Escape key
  $(document).on('keydown', function (e) {
    if (e.key === 'Escape') closeHelp();
  });

});
</script>
</body>
</html>
]]></content:encoded>
					
		
		
			</item>
	</channel>
</rss>
