ha:template {
	trim_indent=1
	ha:template {
		li:header {
			# HTML header
			verbatim {
				<!DOCTYPE html>
				<html lang="en">
				<head>
				    <meta charset="UTF-8">
				    <title>}
			insert {html_title}
			verbatim {
				</title>
				    <style>
				        body { display: flex; flex-direction: column; height:100%; margin: 0; padding: 0; overflow: hidden; \}
				
				        .toolbar { padding: 15px;  border-right: 3px solid #ddd\}
				        .drawing { \}
				        .page_layout { border:0; \}
				        .page_title { padding: 2px;  border-bottom: 3px solid #ddd\}
				
				
				        /* Layer button (inactive) */
				        button.layer-toggle { 
				            padding: 8px 12px;
				            cursor: pointer;
				            margin-right: 5px;
				            margin-top: 2px;
				            margin-bottom: 2px;
				            border: 1px solid #ccc;
				            background-color: #fff;
				            width: 100%;
				        \}
				
				        /* Active/Visible state for the layer button */
				        button.layer-toggle.active {
				            background-color: #007bff;
				            color: white;
				            border-color: #0056b3;
				            box-shadow: inset 0 2px 4px rgba(0,0,0,0.2);
				        \}
				
				        /* misc tool buttons */
				        button.tool-button {
				            padding: 2px 2px;
				            margin-top: 2px;
				            margin-bottom: 2px;
				            border: 1px solid #ccc;
				            border-radius: 6px;
				            background-color: #fff;
				            color: #333;
				            transition: all 0.2s ease;
				        \}
				
				        #svg-container { 
				            flex-grow: 1;
				            overflow: hidden;
				            cursor: grab;
				            touch-action: none;
				
				        \}
				        #svg-container:active { cursor: grabbing; \}
				
				
				        /*** page navigation ***/
				        .page { display: none; border: 1px solid black; margin-bottom: 20px; box-shadow: 0 4px 8px rgba(0,0,0,0.1); \}
				        .page.active { display: block; \}
				        .navigation { display: flex; justify-content: space-between; border: 10px solid rgba(0,0,0,0);\}
				        .nav-button { padding: 10px 20px; cursor: pointer; \}
				
				        /*** search ***/
				
				        /* Styling for the pre-rendered highlights */
				        .highlight-rect {
				            fill: red;
				            fill-opacity: 0.5;
				            pointer-events: none;
				
				            stroke-width: 1;
				            stroke: url(#hazardStripes);
				            stroke-opacity: 0.8;
				
				            /* Initially hidden by default CSS */
				            visibility: hidden; 
				        \}
				
				        /* Class added by JS to show the highlight */
				        .highlight-rect.visible {
				            visibility: visible;
				        \}
				
				    </style>
				</head>
			}

			# HTML body: layout table
			verbatim {
				<body>
				
				  <svg style="position: absolute; width: 0; height: 0; overflow: hidden;">
				        <defs>
				            <!-- Define the 45-degree striped pattern -->
				            <pattern id="hazardStripes" 
				                     patternUnits="userSpaceOnUse" 
				                     width="20" height="20" 
				                     patternTransform="rotate(45)">
				                <!-- Yellow background for the pattern tile -->
				                <rect width="20" height="20" fill="yellow" />
				                <!-- Black stripe covering half the tile -->
				                <rect width="10" height="20" fill="black" />
				            </pattern>
				        </defs>
				  </svg>
				
				
				  <!-- main page layout: top is a page, bottom is navigation -->
				  <table class="layout" cellspacing=0 cellpadding=0 width=100% border=10>
				
				  <tr><td>
				    <!-- top: page navigation -->
				    <div class="navigation">
				        <button id="page-btn-prev" class="nav-button" onclick="changePage(-1)">Previous page</button>
				        <span id="page-counter">Page 1 of 4</span>
				        <button class="nav-button" onclick="saveCurrentSvg()">Export page to svg</button>
				        <div>
				          <input type="text" id="search-input" placeholder="Enter a refdes (e.g., U1)">
				          <button onclick="handleSearch()">Search</button>
				        </div>
				
				        <button id="page-btn-next" class="nav-button" onclick="changePage(1)">Next page</button>
				    </div>
				
				  <tr><td align=vtop height=200px>
			}
		}

		li:page_pre {
			verbatim {
				
				    <!-- Page -->
				    <div id="page-}
			insert {page_index}
			verbatim {
				
" class="page">
				      <!-- main layout: title bar on top, tools on the left, drawing on the right -->
				      <table class="page_layout" cellspacing=0 cellpadding=0 width=100%>
				        <tr><th colspan=2 class="page_title">}
			insert {page_title}
			verbatim {
				
				        <tr>
				        <td class="toolbar" valign=top>
			}
			insert {layer_buttons}
			verbatim {
				              <button class="tool-button" onclick="resetView()">Reset View</button>
				              <br><br><small> Zoom: scrollwheel<br>Pan: drag </small>
				        <td width=100% valign=top>
				          <div id="svg-container-}
			insert {page_index}
			verbatim {">
			}
		}

		li:page_post {
			verbatim {
				          </div>
				      </table>
				    </div>
			}
		}

		li:mouse_bindings {
			verbatim {
				      //
				      {
				      let container1 = document.getElementById('svg-container-}
			insert {page_index}
			verbatim {
				      ');
				      container1.addEventListener('wheel', (e) => { wheel_ev(e); \}, { passive: false \});
				      container1.addEventListener('mousedown', (e) => { mouse_down_ev(e); \});
				      \}
				      //
			}
		}

		li:footer {
			verbatim {
				  </table>
				
				  <script>
				      //////// svg zoom+pan+layer_visibility ////////
				      //
			}
			insert {page_view_boxes}
			verbatim {
				      //
				      let svg = document.getElementById('mainSvg-1');
				      let container = document.getElementById('svg-container-1');
				      const initialVb = { ...vb1 \};
				      let vb = { ...vb1 \};
				      //
				      // 1. UPDATED LAYER TOGGLE LOGIC
				      function toggleLayer(layerId, btnElement) {
				          const layer = svg.querySelector('#' + layerId);
				          //
				          if (layer) {
				              const isHidden = window.getComputedStyle(layer).display === 'none';
				              //
				              if (isHidden) {
				                  layer.style.display = 'inline';
				                  btnElement.classList.add('active'); // Reflect visible state
				              \} else {
				                  layer.style.display = 'none';
				                  btnElement.classList.remove('active'); // Reflect hidden state
				              \}
				          \}
				      \}
				      //
				      // 2. VIEWPORT CONTROLS (RESET, ZOOM, PAN)
				      function resetView() {
				          vb = { ...initialVb \};
				          updateViewBox();
				      \}
				      //
				      function updateViewBox() {
				          svg.setAttribute('viewBox', `${vb.x\} ${vb.y\} ${vb.w\} ${vb.h\}`);
				      \}
				      //
				      //
				      let isPanning = false;
				      let startPoint = { x: 0, y: 0 \};
				      //
				      function wheel_ev(e) {
				        e.preventDefault();
				        const zoomScale = 1.1;
				        const delta = e.deltaY > 0 ? zoomScale : 1 / zoomScale;
				        const p = getSVGPoint(e.clientX, e.clientY);
				        vb.x = p.x - (p.x - vb.x) * delta;
				        vb.y = p.y - (p.y - vb.y) * delta;
				        vb.w *= delta;
				        vb.h *= delta;
				        updateViewBox();
				      \}
				      //
				      function mouse_down_ev(e) {
				        isPanning = true;
				        startPoint = { x: e.clientX, y: e.clientY \};
				      \}
				      //
			}
			insert {mouse_bindings}
			verbatim {
				
				      window.addEventListener('mousemove', (e) => {
				          if (!isPanning) return;
				          const dx = (e.clientX - startPoint.x) * (vb.w / container.clientWidth);
				          const dy = (e.clientY - startPoint.y) * (vb.h / container.clientHeight);
				          vb.x -= dx;
				          vb.y -= dy;
				          startPoint = { x: e.clientX, y: e.clientY \};
				          updateViewBox();
				      \});
				      //
				      window.addEventListener('mouseup', () => isPanning = false);
				      //
				      function getSVGPoint(clientX, clientY) {
				          const pts = svg.createSVGPoint();
				          pts.x = clientX;
				          pts.y = clientY;
				          return pts.matrixTransform(svg.getScreenCTM().inverse());
				      \}
				      //
				      //////// paging ////////
				      //
				      const pages = document.querySelectorAll('.page');
				      let currentPageIndex = 0;
				      const totalPages = pages.length;
				      const counterSpan = document.getElementById('page-counter');
				      //
				      if (totalPages < 2) {
				          const btn1 = document.getElementById('page-btn-prev');
				          btn1.disabled = "true";
				          btn1.style.pointerEvents = "none";
				          const btn2 = document.getElementById('page-btn-next');
				          btn2.disabled = "true";
				          btn2.style.pointerEvents = "none";
				      \}
				      //
				      function save_page_state() {
				        page_vb[currentPageIndex].x = vb.x;
				        page_vb[currentPageIndex].y = vb.y;
				        page_vb[currentPageIndex].w = vb.w;
				        page_vb[currentPageIndex].h = vb.h;
				      \}
				      //
				      function restore_page_state() {
				        vb.x = page_vb[currentPageIndex].x;
				        vb.y = page_vb[currentPageIndex].y;
				        vb.w = page_vb[currentPageIndex].w;
				        vb.h = page_vb[currentPageIndex].h;
				      \}
				      //
				      function showPage(index) {
				          // Hide all pages
				          pages.forEach(page => {
				              page.classList.remove('active');
				          \});
				      //
				          // Show the selected page
				          if (pages[index]) {
				              pages[index].classList.add('active');
				          \}
				      //
				          // Update the counter text
				          counterSpan.textContent = `Page ${index + 1\} of ${totalPages\}`;
				      //
				          // Update pan+zoom target
				          svg = document.getElementById('mainSvg-' + (index + 1));
				          container = document.getElementById('svg-container-' + (index + 1));
				      \}
				      //
				      //
				      function changePage(delta) {
				          save_page_state();
				          const newIndex = currentPageIndex + delta;
				      //
				          // Check if the new index is within bounds
				          if (newIndex >= 0 && newIndex < totalPages) {
				              currentPageIndex = newIndex;
				              showPage(currentPageIndex);
				              restore_page_state();
				          \}
				      \}
				      //
				      function changePageTo(target) {
				          save_page_state();
				          const newIndex = target;
				          //
				          // Check if the new index is within bounds
				          if (newIndex >= 0 && newIndex < totalPages) {
				              currentPageIndex = newIndex;
				              showPage(currentPageIndex);
				              restore_page_state();
				          \}
				      \}
				      //
				      function saveCurrentSvg() {
				          // 1. Find the currently active SVG element
				          const currentPage = document.querySelector('.page.active');
				          if (!currentPage) return; // Exit if no page is active
				          //
				          // The SVG is the first child of the page div
				          const svgElement = currentPage.querySelector('svg');
				          if (!svgElement) return;
				          //
				          // 2. Serialize the SVG element to an XML string
				          const serializer = new XMLSerializer();
				          const svgString = serializer.serializeToString(svgElement);
				          //
				          // 3. Create a Blob (Binary Large Object) from the string with the correct MIME type
				          const blob = new Blob([svgString], { type: 'image/svg+xml;charset=utf-8' \});
				          //
				          // 4. Create a temporary URL for the blob
				          const url = URL.createObjectURL(blob);
				          //
				          // 5. Create a temporary anchor (link) element to trigger the download
				          const downloadLink = document.createElement('a');
				          downloadLink.href = url;
				          downloadLink.download = `page-${currentPageIndex + 1\}.svg`; // Suggested file name
				          //
				          // 6. Append link to body, click it programmatically, and remove it
				          document.body.appendChild(downloadLink);
				          downloadLink.click();
				          document.body.removeChild(downloadLink);
				          //
				          // 7. Clean up the blob URL after use
				          URL.revokeObjectURL(url);
				      \}
				      //
				      // Initialize the app on load
				      document.addEventListener('DOMContentLoaded', () => {
				          showPage(currentPageIndex);
				      \});
				      //
				      //////// search ////////
				      //
				      //
				      // map search terms to the HTML element IDs we pre-rendered; keys are lowercase
				      const searchMap = {
			}
			insert {search_name_map}
			verbatim {
				      \};
				      //
				      // map search terms to page indices (starting from 0)
				      const searchMapPage = {
			}
			insert {search_page_map}
			verbatim {
				      \};
				      //
				       const searchInput = document.getElementById('search-input');
				       //
				       function clearHighlights() {
				           // Remove the 'visible' class from all highlight elements
				           document.querySelectorAll('.highlight-rect.visible').forEach(rect => {
				               rect.classList.remove('visible');
				           \});
				       \}
				      //
				       function highlightElements(elementIds) {
				           clearHighlights();
				           elementIds.forEach(id => {
				               const element = document.getElementById(id);
				               if (element) {
				                   // Add the 'visible' class to make it appear via CSS
				                   element.classList.add('visible');
				               \}
				           \});
				       \}
				       //
				       function handleSearch() {
				           const query = searchInput.value.trim();
				           clearHighlights();
				           //
				           if (query && searchMap[query]) {
				               const elementIds = searchMap[query];
				               const targetPageIndex = searchMapPage[query];
				               // Determine which page the first highlight is on (requires parsing ID, or better data structure)
				               // In this simplified example, we know "blue" is on page 2 (index 1) etc.
				               // A better map structure might look like: {"blue": {pageIndex: 1, elementIds: [...]\}\}
				               //
				               changePageTo(targetPageIndex);
				               highlightElements(elementIds);
				               //
				           \} else if (query) {
				               alert(`"${query\}" not found in the index.`);
				           \}
				       \}
				       // make sure the first pan/zoom won't jump
				       resetView();
				  </script>
				</body>
				</html>
			}
		}
	}
}
