diff --git a/dsiUnits-js/src/dsiUnit.js b/dsiUnits-js/src/dsiUnit.js
index 1a475a66de4d5746d40c42fad9b7838cd8369f55..93de7ae411f4114a9182adf3703ecad617b35212 100644
--- a/dsiUnits-js/src/dsiUnit.js
+++ b/dsiUnits-js/src/dsiUnit.js
@@ -6,24 +6,23 @@ export class DSIUnit {
     const parser = DSIParser.getInstance();
     const result = parser.parse(dsiString);
     this.dsiString = result.original;
-    this.tree = result.tree; // tree: array of fractions (each fraction is an array of nodes)
+    this.tree = result.tree;
     this.warnings = result.warnings;
     this.nonDsiUnit = result.nonDsiUnit;
-    this.valid = (this.warnings.length === 0);
-    this.scaleFactor = 1.0; // Stub for now.
+    // For non-DSI units (or empty string), treat them as "valid" for rendering purposes.
+    this.valid = this.nonDsiUnit ? true : (this.warnings.length === 0);
+    this.scaleFactor = 1.0;
   }
 
   toHTML({ wrapper = '', prefix = '', suffix = '' } = {}) {
+    let htmlOutput = '';
     if (this.nonDsiUnit) {
+      // For non-DSI units, ignore warnings and do not apply error wrapping.
       const content = `<span class="dsi-nonunit">${this.dsiString.startsWith('|') ? this.dsiString.slice(1) : this.dsiString}</span>`;
-      return `${wrapper}${prefix}${content}${suffix}${wrapper}`;
-    }
-
-    let htmlOutput = '';
-    if (this.tree.length === 1) {
+      htmlOutput = content;
+    } else if (this.tree.length === 1) {
       htmlOutput = this.tree[0].map(node => node.toHTML()).join('<span class="dsi-mul">&nbsp;</span>');
     } else if (this.tree.length === 2) {
-      // Render as a fraction in one line (no extra whitespace)
       const numerator = this.tree[0].map(node => node.toHTML()).join('<span class="dsi-mul">&nbsp;</span>');
       const denominator = this.tree[1].map(node => node.toHTML()).join('<span class="dsi-mul">&nbsp;</span>');
       htmlOutput = `<span class="dsi-fraction"><span class="dsi-numerator">${numerator}</span><span class="dsi-denom">${denominator}</span></span>`;
@@ -34,10 +33,18 @@ export class DSIUnit {
     if (this.scaleFactor !== 1.0) {
       htmlOutput = `<span class="dsi-scale">${this.scaleFactor}&middot;</span>` + htmlOutput;
     }
-    if (!this.valid) {
+    // Only wrap in error styling if it's a DSI unit (not nonDSI) and not valid.
+    if (!this.nonDsiUnit && !this.valid) {
       htmlOutput = `<span class="dsi-error">${htmlOutput}</span>`;
     }
-    return `${wrapper}${prefix}${htmlOutput}${suffix}${wrapper}`;
+    // Add a tooltip if there are warnings (only for DSI units).
+    let tooltip = "";
+    if (!this.nonDsiUnit && this.warnings && this.warnings.length > 0) {
+      // Replace double backslashes with a single one for display in the tooltip.
+      const tooltipText = this.warnings.map(w => w.replace(/\\\\/g, '\\')).join("; ");
+      tooltip = ` title="${tooltipText}"`;
+    }
+    return `<span class="dsi-unit-wrapper"${tooltip}>${wrapper}${prefix}${htmlOutput}${suffix}${wrapper}</span>`;
   }
 
   toString() {
diff --git a/dsiUnits-js/src/dsiUnitNode.js b/dsiUnits-js/src/dsiUnitNode.js
index 59d99c40c9d1a6168101569487f9e6a28559cbba..1b99a8342dee72a0ac1ce6e0cec4089abb115295 100644
--- a/dsiUnits-js/src/dsiUnitNode.js
+++ b/dsiUnits-js/src/dsiUnitNode.js
@@ -6,7 +6,6 @@ export class DSIUnitNode {
     this.prefix = prefix;
     this.unit = unit;
     this.valid = valid;
-    // Normalize exponent: if empty or "1", treat as 1.
     if (exponent === '' || exponent === '1') {
       this.exponent = 1;
     } else {
@@ -17,7 +16,7 @@ export class DSIUnitNode {
   }
 
   toHTML() {
-    // Build prefix HTML (if exists)
+    // Build prefix HTML
     let prefixHTML = '';
     if (this.prefix) {
       if (this.prefix in dsiPrefixesHTML) {
@@ -35,27 +34,24 @@ export class DSIUnitNode {
         unitHTML = `<span class="dsi-unit"><span class="dsi-invalid">${this.unit}</span></span>`;
       }
     }
-    // Combine the parts
     let baseHTML = prefixHTML + unitHTML;
 
-    // Handle exponent output for non-1 exponents.
+    // Handle exponent output: if exponent is not 1, check for common fractional exponents.
     if (this.exponent !== 1) {
-      // If exponent is numeric, check for common fractional values.
       if (typeof this.exponent === 'number') {
         if (Math.abs(this.exponent - 0.5) < 0.0001) {
           // Square root
-          return `<span class="dsi-sqrt">√(${baseHTML})</span>`;
+          return `<span class="dsi-root"><span class="dsi-root-symbol">√</span><span class="dsi-root-content">${baseHTML}</span></span>`;
         } else if (Math.abs(this.exponent - 0.333333) < 0.0001) {
           // Cube root
-          return `<span class="dsi-sqrt">∛(${baseHTML})</span>`;
+          return `<span class="dsi-root"><span class="dsi-root-symbol">∛</span><span class="dsi-root-content">${baseHTML}</span></span>`;
         } else if (Math.abs(this.exponent - 0.25) < 0.0001) {
           // Fourth root
-          return `<span class="dsi-sqrt">∜(${baseHTML})</span>`;
+          return `<span class="dsi-root"><span class="dsi-root-symbol">∜</span><span class="dsi-root-content">${baseHTML}</span></span>`;
         } else {
           return `${baseHTML}<sup class="dsi-exponent">${this.exponent}</sup>`;
         }
       } else {
-        // If exponent is non-numeric, simply render as red text
         return `${baseHTML}<sup class="dsi-exponent"><span class="dsi-invalid">${this.exponent}</span></sup>`;
       }
     }
diff --git a/dsiUnits-js/tests/dsiUnits.test.js b/dsiUnits-js/tests/dsiUnits.test.js
index a20b918a682f10d71c961867ab3b23d8a11db74f..e5069d3e2d65023f4e8f8bbd5beac4d847c481cb 100644
--- a/dsiUnits-js/tests/dsiUnits.test.js
+++ b/dsiUnits-js/tests/dsiUnits.test.js
@@ -1,37 +1,35 @@
 // tests/dsiUnits.test.js
 import { DSIUnit } from '../src/dsiUnit.js';
-import { DSIUnitNode } from '../src/dsiUnitNode.js';
 
 describe('DSIUnit HTML Output Tests', () => {
   test('Base case: one unit without prefix or exponent', () => {
     const unit = new DSIUnit('\\metre');
     expect(unit.tree.length).toBe(1);
     expect(unit.tree[0].length).toBe(1);
-    const node = unit.tree[0][0];
-    expect(node.unit).toBe('metre');
-    expect(node.exponent).toBe(1);
-    expect(unit.toHTML()).toBe('<span class="dsi-unit">m</span>');
+    expect(unit.tree[0][0].unit).toBe('metre');
+    expect(unit.tree[0][0].exponent).toBe(1);
+    expect(unit.toHTML()).toBe('<span class="dsi-unit-wrapper"><span class="dsi-unit">m</span></span>');
     expect(unit.valid).toBe(true);
     expect(unit.warnings).toEqual([]);
   });
 
   test('Exponent handling: metre^2 and square-root', () => {
     const unit2 = new DSIUnit('\\metre\\tothe{2}');
-    expect(unit2.toHTML()).toBe('<span class="dsi-unit">m</span><sup class="dsi-exponent">2</sup>');
+    expect(unit2.toHTML()).toBe('<span class="dsi-unit-wrapper"><span class="dsi-unit">m</span><sup class="dsi-exponent">2</sup></span>');
 
     const unitSqrt = new DSIUnit('\\metre\\tothe{0.5}');
-    expect(unitSqrt.toHTML()).toBe('<span class="dsi-sqrt">√(<span class="dsi-unit">m</span>)</span>');
+    expect(unitSqrt.toHTML()).toBe('<span class="dsi-unit-wrapper"><span class="dsi-root"><span class="dsi-root-symbol">√</span><span class="dsi-root-content"><span class="dsi-unit">m</span></span></span></span>');
   });
 
   test('Fraction: e.g. mega metre per second^2', () => {
     const unitFrac = new DSIUnit('\\mega\\metre\\per\\second\\tothe{2}');
-    const expectedHTML = '<span class="dsi-fraction"><span class="dsi-numerator"><span class="dsi-unit">M</span><span class="dsi-unit">m</span></span><span class="dsi-denom"><span class="dsi-unit">s</span><sup class="dsi-exponent">2</sup></span></span>';
+    const expectedHTML = '<span class="dsi-unit-wrapper"><span class="dsi-fraction"><span class="dsi-numerator"><span class="dsi-unit">M</span><span class="dsi-unit">m</span></span><span class="dsi-denom"><span class="dsi-unit">s</span><sup class="dsi-exponent">2</sup></span></span></span>';
     expect(unitFrac.toHTML()).toBe(expectedHTML);
   });
 
   test('Robustness: unknown unit', () => {
     const unitUnknown = new DSIUnit('\\foo');
-    const expectedHTML = '<span class="dsi-error"><span class="dsi-unit"><span class="dsi-invalid">foo</span></span></span>';
+    const expectedHTML = '<span class="dsi-unit-wrapper" title="The identifier «foo» does not match any D-SI units!"><span class="dsi-error"><span class="dsi-unit"><span class="dsi-invalid">foo</span></span></span></span>';
     expect(unitUnknown.toHTML()).toBe(expectedHTML);
     expect(unitUnknown.valid).toBe(false);
     expect(unitUnknown.warnings).toContain('The identifier «foo» does not match any D-SI units!');
@@ -39,21 +37,27 @@ describe('DSIUnit HTML Output Tests', () => {
 
   test('Non D-SI unit marker', () => {
     const nonDsi = new DSIUnit('|NonDsiUnit');
-    const expectedHTML = '<span class="dsi-nonunit">NonDsiUnit</span>';
+    const expectedHTML = '<span class="dsi-unit-wrapper"><span class="dsi-nonunit">NonDsiUnit</span></span>';
     expect(nonDsi.toHTML()).toBe(expectedHTML);
   });
 
   test('Empty string', () => {
     const emptyUnit = new DSIUnit('');
-    const expectedHTML = '<span class="dsi-nonunit">NULL</span>';
+    const expectedHTML = '<span class="dsi-unit-wrapper"><span class="dsi-nonunit">NULL</span></span>';
     expect(emptyUnit.toHTML()).toBe(expectedHTML);
     expect(emptyUnit.warnings).toContain('Given D-SI string is empty!');
   });
 
   test('Double backslash handling', () => {
     const unitDouble = new DSIUnit('\\\\metre\\per\\second');
-    const expectedHTML = '<span class="dsi-error"><span class="dsi-fraction"><span class="dsi-numerator"><span class="dsi-unit">m</span></span><span class="dsi-denom"><span class="dsi-unit">s</span></span></span></span>';
+    const expectedHTML = '<span class="dsi-unit-wrapper" title="Double backslash found in string, treating as one backslash: «\\metre\\per\\second»"><span class="dsi-error"><span class="dsi-fraction"><span class="dsi-numerator"><span class="dsi-unit">m</span></span><span class="dsi-denom"><span class="dsi-unit">s</span></span></span></span></span>';
     expect(unitDouble.toHTML()).toBe(expectedHTML);
     expect(unitDouble.warnings.some(w => w.includes('Double backslash'))).toBe(true);
   });
+
+  test('Fourth root: micro metre tothe{0.25}', () => {
+    const unitFourth = new DSIUnit('\\micro\\metre\\tothe{0.25}');
+    const expectedHTML = '<span class="dsi-unit-wrapper"><span class="dsi-root"><span class="dsi-root-symbol">∜</span><span class="dsi-root-content"><span class="dsi-unit">µ</span><span class="dsi-unit">m</span></span></span></span>';
+    expect(unitFourth.toHTML()).toBe(expectedHTML);
+  });
 });
diff --git a/dsiUnits-js/tests/visual_test.html b/dsiUnits-js/tests/visual_test.html
index 09b3a0698293af35089c3b96718576e4ea05f989..25f35f8351e211d1568487a9d24edddcd7d68eb8 100644
--- a/dsiUnits-js/tests/visual_test.html
+++ b/dsiUnits-js/tests/visual_test.html
@@ -2,11 +2,15 @@
 <html lang="en">
 <head>
   <meta charset="UTF-8">
-  <title>D-SI Units Visual Test</title>
+  <title>D-SI Units Visual Test & Documentation</title>
   <style>
     body {
       font-family: sans-serif;
       margin: 20px;
+      line-height: 1.6;
+    }
+    h1, h2, h3 {
+      color: #333;
     }
     table {
       border-collapse: collapse;
@@ -19,27 +23,29 @@
       text-align: left;
       vertical-align: top;
     }
+    th {
+      background-color: #eee;
+    }
     pre {
       margin: 0;
       font-family: monospace;
       background: #f8f8f8;
       padding: 4px;
     }
-    /* Invalid parts appear in red */
+    /* Invalid tokens in red */
     .dsi-invalid {
       color: red;
       font-weight: bold;
     }
-    /* Overall error: wrap entire output in orange */
+    /* Error wrapper (for overall errors) in orange */
     .dsi-error {
       color: orange;
     }
-    /* Fraction styling: display as block elements to mimic LaTeX fraction */
+    /* Fraction styling */
     .dsi-fraction {
       display: inline-block;
       text-align: center;
       vertical-align: middle;
-      margin: 0 2px;
     }
     .dsi-numerator {
       display: block;
@@ -52,21 +58,120 @@
       padding: 0 2px;
       line-height: 1.2;
     }
-    /* Sqrt styling */
-    .dsi-sqrt {
+    /* Radical styling */
+    .dsi-root {
+      display: inline-flex;
+      align-items: flex-start;
+    }
+    .dsi-root-symbol {
+      font-size: 1.2em;
+      padding-right: 2px;
+    }
+    .dsi-root-content {
+      border-top: 1px solid #000;
       display: inline-block;
-      font-family: 'Times New Roman', serif;
+      padding-top: 2px;
     }
-    /* Multiply symbol between units */
     .dsi-mul {
       padding: 0 2px;
     }
+    .dsi-unit-wrapper {
+      /* Wrapper for the final output; tooltip is handled via the title attribute */
+    }
+    /* Documentation explanation styling */
+    #documentation {
+      margin-bottom: 40px;
+      padding: 10px;
+      border: 1px solid #ccc;
+      background-color: #fafafa;
+    }
+    /* Styling for the allowed prefixes and units tables */
+    .doc-table {
+      margin-bottom: 20px;
+    }
+    .doc-table th {
+      background-color: #ddd;
+    }
+    /* Styling for the interactive section */
+    #interactiveSection {
+      border: 1px solid #ccc;
+      padding: 10px;
+      margin-top: 40px;
+    }
+    #dsiInput {
+      width: 400px;
+      font-family: monospace;
+    }
+    #interactiveResult {
+      margin-top: 10px;
+      padding: 10px;
+      border: 1px solid #ccc;
+      min-height: 40px;
+    }
+    #warningText {
+      color: red;
+      margin-top: 5px;
+    }
+    #liveUpdateContainer {
+      margin-top: 10px;
+    }
   </style>
 </head>
 <body>
-<h1>D-SI Units Visual Test</h1>
+<h1>D-SI Units Visual Test & Documentation</h1>
+
+<div id="documentation">
+  <h2>How D-SI Units Are Composed</h2>
+  <p>
+    A D-SI unit string is composed of one or more components, each preceded by a backslash (<code>\</code>).
+    The components include:
+  </p>
+  <ul>
+    <li>An <strong>optional prefix</strong> (e.g. <code>\kilo</code> for 10³, <code>\milli</code> for 10⁻³),</li>
+    <li>A <strong>base unit</strong> (e.g. <code>\metre</code>, <code>\second</code>),</li>
+    <li>An optional exponent specified with <code>\tothe{...}</code> (e.g. <code>\metre\tothe{2}</code> for square metres). Common fractional exponents such as 0.5, 0.333333, and 0.25 are rendered as square, cube, and fourth roots respectively.</li>
+    <li>An optional <strong>fraction operator</strong> <code>\per</code> to separate numerator and denominator (e.g. <code>\metre\per\second</code> for metres per second).</li>
+  </ul>
+  <p>
+    The rendered output mimics LaTeX-like formatting with radicals (a horizontal line over the radicand) and fractions.
+  </p>
+</div>
+<!-- Interactive Section -->
+<h2>Interactive D-SI Unit Renderer</h2>
+<div id="interactiveSection">
+  <label for="dsiInput">Enter D-SI string:</label>
+  <input type="text" id="dsiInput" placeholder="e.g. \metre\tothe{0.333333}">
+  <button id="renderBtn">Render</button>
+  <div id="liveUpdateContainer">
+    <label for="liveUpdate">Live Update: </label>
+    <input type="checkbox" id="liveUpdate" checked>
+  </div>
+  <div id="interactiveResult"></div>
+</div>
+<h2>Allowed Prefixes</h2>
+<table id="prefixes-table" class="doc-table">
+  <thead>
+  <tr>
+    <th>Prefix Name</th>
+    <th>Symbol</th>
+  </tr>
+  </thead>
+  <tbody></tbody>
+</table>
+
+<h2>Allowed Units</h2>
+<table id="units-table" class="doc-table">
+  <thead>
+  <tr>
+    <th>Unit Name</th>
+    <th>Symbol</th>
+  </tr>
+  </thead>
+  <tbody></tbody>
+</table>
 
-<h2>Valid D-SI Strings</h2>
+<h2>Example D-SI Strings</h2>
+<h3>Valid D-SI Strings</h3>
 <table id="valid-table">
   <thead>
   <tr>
@@ -77,7 +182,7 @@
   <tbody></tbody>
 </table>
 
-<h2>Invalid D-SI Strings</h2>
+<h3>Invalid D-SI Strings</h3>
 <table id="invalid-table">
   <thead>
   <tr>
@@ -90,9 +195,37 @@
 </table>
 
 <script type="module">
+  // Import the DSIUnit class and unit mappings.
   import { DSIUnit } from "../src/dsiUnit.js";
+  import { dsiPrefixesHTML, dsiUnitsHTML } from "../src/unitStrings.js";
 
-  // Define arrays of sample D-SI strings.
+  // Populate Allowed Prefixes table.
+  const prefixesTbody = document.getElementById('prefixes-table').querySelector('tbody');
+  Object.keys(dsiPrefixesHTML).sort().forEach(prefix => {
+    const tr = document.createElement('tr');
+    const tdName = document.createElement('td');
+    tdName.textContent = prefix;
+    const tdSymbol = document.createElement('td');
+    tdSymbol.textContent = dsiPrefixesHTML[prefix];
+    tr.appendChild(tdName);
+    tr.appendChild(tdSymbol);
+    prefixesTbody.appendChild(tr);
+  });
+
+  // Populate Allowed Units table.
+  const unitsTbody = document.getElementById('units-table').querySelector('tbody');
+  Object.keys(dsiUnitsHTML).sort().forEach(unit => {
+    const tr = document.createElement('tr');
+    const tdName = document.createElement('td');
+    tdName.textContent = unit;
+    const tdSymbol = document.createElement('td');
+    tdSymbol.textContent = dsiUnitsHTML[unit];
+    tr.appendChild(tdName);
+    tr.appendChild(tdSymbol);
+    unitsTbody.appendChild(tr);
+  });
+
+  // Sample D-SI strings for the examples.
   const validDSI = [
     '\\metre',
     '\\metre\\tothe{2}',
@@ -100,15 +233,15 @@
     '\\mega\\metre\\per\\second\\tothe{2}',
     '\\kilo\\metre\\per\\hour',
     '\\metre\\per\\second',
-    '\\metre\\tothe{0.333333}', // should render as cube root
-    '\\metre\\tothe{0.25}'      // should render as fourth root
+    '\\metre\\tothe{0.333333}', // Cube root
+    '\\metre\\tothe{0.25}'      // Fourth root
   ];
 
   const invalidDSI = [
-    '\\foo',
-    '\\milli\\tothe{2}',
-    '\\metre\\per',
-    '\\\\metre\\per\\second'
+    '\\foo',                      // Unknown unit.
+    '\\milli\\tothe{2}',          // Missing base unit after prefix.
+    '\\metre\\per',               // Fraction missing numerator or denominator.
+    '\\\\metre\\per\\second'      // Double backslashes.
   ];
 
   function renderDSI(rawStr) {
@@ -131,27 +264,53 @@
     dsiStrings.forEach(rawStr => {
       const result = renderDSI(rawStr);
       const tr = document.createElement('tr');
-
       const tdRaw = document.createElement('td');
       tdRaw.innerHTML = `<pre>${rawStr}</pre>`;
       tr.appendChild(tdRaw);
-
       const tdRendered = document.createElement('td');
       tdRendered.innerHTML = result.html;
       tr.appendChild(tdRendered);
-
       if (tableId === 'invalid-table') {
         const tdWarnings = document.createElement('td');
         tdWarnings.innerHTML = result.warnings.join('<br>');
         tr.appendChild(tdWarnings);
       }
-
       tbody.appendChild(tr);
     });
   }
 
+  // Populate the example tables.
   populateTable('valid-table', validDSI);
   populateTable('invalid-table', invalidDSI);
+
+  // Interactive section: re-render on button click or live update if enabled.
+  const renderBtn = document.getElementById('renderBtn');
+  const dsiInput = document.getElementById('dsiInput');
+  const liveUpdateCheckbox = document.getElementById('liveUpdate');
+  const interactiveResult = document.getElementById('interactiveResult');
+
+  function updateInteractiveResult() {
+    const inputStr = dsiInput.value;
+    try {
+      const unit = new DSIUnit(inputStr);
+      const renderedHTML = unit.toHTML();
+      let warningsHTML = "";
+      if (unit.warnings.length > 0) {
+        warningsHTML = `<div id="warningText">Warnings: ${unit.warnings.join("; ")}</div>`;
+      }
+      interactiveResult.innerHTML = renderedHTML + warningsHTML;
+    } catch (err) {
+      interactiveResult.innerHTML = `<span style="color:red;">Error: ${err.message}</span>`;
+    }
+  }
+
+  renderBtn.addEventListener('click', updateInteractiveResult);
+
+  dsiInput.addEventListener('input', () => {
+    if (liveUpdateCheckbox.checked) {
+      updateInteractiveResult();
+    }
+  });
 </script>
 </body>
 </html>