fighting pagination bugs
authorThomas Walker Lynch <eknp9n@reasoningtechnology.com>
Wed, 5 Aug 2026 15:27:47 +0000 (15:27 +0000)
committerThomas Walker Lynch <eknp9n@reasoningtechnology.com>
Wed, 5 Aug 2026 15:27:47 +0000 (15:27 +0000)
developer/authored/Manuscript.copy/Element/TOC.js
developer/authored/Manuscript.copy/Element/section.js
developer/authored/Manuscript.copy/Layout/paginate.js

index b1c6df1..80c1105 100644 (file)
@@ -1,15 +1,15 @@
 /*
   Element/TOC.js
   Processes <RT·TOC> tags.
-  Iterates nested <RT·section> boundaries, evaluates tree depth, 
+  Iterates nested RT_section boundaries, evaluates tree depth, 
   and duplicates the title payload for automated navigation.
 */
 
-(function() {
+(function(){
 
-  if (!window.RT) return;
+  if(!window.RT) return;
 
-  const apply_style = function(a ,config) {
+  const apply_style = function(a ,config){
     a.style.textDecoration = 'none';
     a.style.color = 'inherit';
     a.style.display = 'block';
     a.onmouseout  = () => a.style.color = 'inherit';
   };
 
-  RT.Element.add( function() {
+  RT.Element.add(function(){
     const debug = window.RT.Debug || { log: function(){} };
-    if (debug.log) debug.log('TOC' ,'Generating Table of Contents from nested sections');
+    if(debug.log) debug.log('TOC' ,'Generating Table of Contents from expanded section steps');
     
     const config = window.RT.layout_config || {};
-    const TOC_seq = document.querySelectorAll('rt·toc, RT·TOC');
+    const TOC_seq = document.querySelectorAll('RT·TOC, rt·toc');
 
-    TOC_seq.forEach( (container ,TOC_index) => {
+    TOC_seq.forEach((container ,TOC_index) => {
       container.style.display = 'block';
 
       const attr_val = container.getAttribute('level');
       let start_level = 1;
       let end_level = 6; 
       
-      if (attr_val) {
-        const rangeMatch = attr_val.match(/^(\d)-(\d)$/);
-        if (rangeMatch) {
-          start_level = parseInt(rangeMatch[1]);
-          end_level   = parseInt(rangeMatch[2]);
-        } else {
+      if(attr_val){
+        const range_match = attr_val.match(/^(\d)-(\d)$/);
+        if(range_match){
+          start_level = parseInt(range_match[1]);
+          end_level   = parseInt(range_match[2]);
+        }else{
           const single = parseInt(attr_val);
-          if (!isNaN(single)) {
+          if(!isNaN(single)){
             start_level = single;
             end_level   = single;
           } 
       }
 
       const sections = [];
-      const all_sections = document.querySelectorAll('rt·section, RT·section');
+      const all_sections = document.querySelectorAll('RT·counter·step[counter="RT_section"], rt·counter·step[counter="RT_section"]');
       
       all_sections.forEach(section => {
         let depth = 0;
         let curr = section.parentElement;
         
-        while (curr) {
-          if (curr.tagName && curr.tagName.toLowerCase() === 'rt·section') {
+        while(curr){
+          const tag = (curr.tagName || '').toLowerCase();
+          if(tag === 'rt·counter·step' && curr.getAttribute('counter') === 'RT_section'){
             depth++;
           }
           curr = curr.parentElement;
         }
         
         const level = depth + 1;
-        if (level >= start_level && level <= end_level) {
-          
-          // Use querySelector to safely find the title regardless of nested wrapper logic
+        if(level >= start_level && level <= end_level){
           const title_node = section.querySelector('.RT·section-title');
           
-          if (title_node) {
+          if(title_node){
             sections.push({ 
                id: section.id
                ,level: level
       title.style.color = config.brand_primary || '#000';
       container.appendChild(title);
 
-      if (sections.length === 0) return; 
+      if(sections.length === 0) return; 
 
-      const topList = document.createElement('ul');
-      topList.style.listStyle = 'none';
-      topList.style.paddingLeft = '0';
-      topList.style.marginBottom = '0';
-      container.appendChild(topList);
+      const top_list = document.createElement('ul');
+      top_list.style.listStyle = 'none';
+      top_list.style.paddingLeft = '0';
+      top_list.style.marginBottom = '0';
+      container.appendChild(top_list);
 
-      const listStack = [topList];
+      const list_stack = [top_list];
 
-      for (const item of sections) {
+      for(const item of sections){
         const depth = item.level - start_level;   
 
-        while (listStack.length - 1 > depth) {
-          listStack.pop();
+        while(list_stack.length - 1 > depth){
+          list_stack.pop();
         }
 
-        while (listStack.length - 1 < depth) {
-          const parentList = listStack[listStack.length - 1];
-          const lastLi = parentList.lastElementChild;
-
-          if (lastLi) {
-            const subList = document.createElement('ul');
-            subList.style.listStyle = 'none';
-            subList.style.paddingLeft = '1.5rem';
-            subList.style.marginBottom = '0';
-            lastLi.appendChild(subList);
-            listStack.push(subList);
-          } else {
+        while(list_stack.length - 1 < depth){
+          const parent_list = list_stack[list_stack.length - 1];
+          const last_li = parent_list.lastElementChild;
+
+          if(last_li){
+            const sub_list = document.createElement('ul');
+            sub_list.style.listStyle = 'none';
+            sub_list.style.paddingLeft = '1.5rem';
+            sub_list.style.marginBottom = '0';
+            last_li.appendChild(sub_list);
+            list_stack.push(sub_list);
+          }else{
             break;
           }
         }
         apply_style(a ,config);
 
         li.appendChild(a);
-        listStack[listStack.length - 1].appendChild(li);
+        list_stack[list_stack.length - 1].appendChild(li);
       }
     });
   });
index 7fd9361..b03500a 100644 (file)
@@ -1,26 +1,23 @@
 /*
   Element/section.js
-  Processes <RT·section> tags.
-  Applies counting hierarchical numbering, conditional alignment/indents, 
-  subdued dark red borders for top-level elements, and universal page breaks for chapters.
+  Expands <RT·section> macros into <RT·counter·step> primitives.
 */
 
-(function() {
+(function(){
 
-  if (!window.RT) return;
+  if(!window.RT) return;
 
-  const apply_style = function(title_node ,depth ,config) {
+  const apply_style = function(title_node ,depth ,config){
     const base_size = 2.25;
     const size = Math.max(1.1 ,base_size - (depth * 0.35));
     const fade_opacity = Math.max(0.5 ,1 - (depth * 0.2));
 
-    if (depth === 0) {
+    if(depth === 0){
       title_node.style.textAlign = 'center';
       title_node.style.paddingLeft = '0';
-      // Firebrick provides sufficient chroma contrast against dark backgrounds
       title_node.style.borderBottom = '2px solid #B22222'; 
       title_node.style.paddingBottom = '0.5rem';
-    } else {
+    }else{
       title_node.style.textAlign = 'left';
       title_node.style.paddingLeft = (depth * 1.5) + 'rem';
     }
     title_node.style.lineHeight = '1.2';
   };
 
-  RT.Element.add(function() {
+  RT.Element.add(function(){
     const debug = window.RT.Debug || { log: function(){} };
-    if (debug.log) debug.log('section' ,'Processing scoped sections with counting numbering');
+    if(debug.log) debug.log('section' ,'Expanding section macros');
 
     const config = window.RT.layout_config || {};
     const section_seq = document.querySelectorAll('RT·section, rt·section');
 
-    if (section_seq.length === 0) return;
+    if(section_seq.length === 0) return;
 
     const article = document.querySelector('RT·article, rt·article, RT·memo, rt·memo');
-    if (article && !document.querySelector('rt·counter·make[counter="RT_section"]')) {
-      const make = document.createElement('rt·counter·make');
+    if(article && !document.querySelector('RT·counter·make[counter="RT_section"], rt·counter·make[counter="RT_section"]')){
+      const make = document.createElement('RT·counter·make');
       make.setAttribute('counter' ,'RT_section');
-      // Utilizing CountingNumber to output 1.1.1 rather than 0.0.0
       make.setAttribute('style' ,'CountingNumber');
       make.setAttribute('mode' ,'scoped');
       make.setAttribute('on-first-step' ,'0');
     let section_idx = 0;
 
     section_seq.forEach(section => {
-      section.style.display = 'block';
-
       let depth = 0;
       let curr = section.parentElement;
-      while (curr) {
-        if (curr.tagName && curr.tagName.toLowerCase() === 'rt·section') {
+      while(curr){
+        const tag = (curr.tagName || '').toLowerCase();
+        if(tag === 'rt·section' || (tag === 'rt·counter·step' && curr.getAttribute('counter') === 'RT_section')){
           depth++;
         }
         curr = curr.parentElement;
       }
 
-      // Force ALL top-level sections to start on a new page
-      if (depth === 0) {
-        if (!section.previousElementSibling?.tagName?.toLowerCase().includes('page-break')) {
-          const pb = document.createElement('rt·page-break');
-          section.parentNode.insertBefore(pb, section);
+      if(depth === 0){
+        if(!section.previousElementSibling?.tagName?.toLowerCase().includes('page-break')){
+          const pb = document.createElement('RT·page-break');
+          section.parentNode.insertBefore(pb ,section);
         }
       }
 
-      const names = [];
-      const children = Array.from(section.children);
-      children.forEach(child => {
-        if (child.tagName && child.tagName.toLowerCase() === 'rt·name') {
-          names.push(child.innerHTML.trim());
-          child.remove();
-        }
-      });
-
-      const title_text = names.length > 0 ? names.join('<br>') : '•';
-
-      const step = document.createElement('rt·counter·step');
+      const snap_id = section.id || ('section_snap_' + section_idx++);
+      
+      const step = document.createElement('RT·counter·step');
       step.setAttribute('counter' ,'RT_section');
+      step.setAttribute('splitable' ,'true');
+      step.id = snap_id; 
 
-      while (section.firstChild) {
-        step.appendChild(section.firstChild);
-      }
-
-      const snap_id = 'section_snap_' + section_idx++;
-      const snap = document.createElement('rt·counter·snapshot');
+      const snap = document.createElement('RT·counter·snapshot');
       snap.setAttribute('counter' ,'RT_section');
       snap.setAttribute('snapshot' ,snap_id);
+      step.appendChild(snap);
 
       const title_node = document.createElement('div');
       title_node.className = 'RT·section-title';
-      if (!section.id) section.id = snap_id; 
 
-      const read = document.createElement('rt·counter·read');
-      read.setAttribute('snapshot' ,snap_id);
-      
+      const read_count = document.createElement('RT·counter·read');
+      read_count.setAttribute('snapshot' ,snap_id);
+
       const title_content = document.createElement('span');
       title_content.style.marginLeft = '0.75rem';
-      title_content.innerHTML = title_text;
+      
+      const read_name = document.createElement('RT·counter·read');
+      read_name.setAttribute('snapshot' ,snap_id);
+      read_name.setAttribute('key' ,'name');
+      title_content.appendChild(read_name);
 
-      title_node.appendChild(read);
+      title_node.appendChild(read_count);
       title_node.appendChild(title_content);
 
       apply_style(title_node ,depth ,config);
+      step.appendChild(title_node);
 
-      step.insertBefore(title_node ,step.firstChild);
-      step.insertBefore(snap ,step.firstChild);
+      while(section.firstChild){
+        const child = section.firstChild;
+        if((child.tagName || '').toLowerCase() === 'rt·name'){
+          child.style.display = 'none';
+        }
+        step.appendChild(child);
+      }
 
-      section.appendChild(step);
+      section.parentNode.replaceChild(step ,section);
     });
   });
 
index 8f105cf..03cdc31 100644 (file)
@@ -7,7 +7,7 @@
 (function(){
 
   if(!window.RT){
-    console.error("RT not defined - was RT-Style_make run?");
+    console.error("RT not defined. Was RT-Manuscript_make run?");
     return;
   }
 
   const page_conf = (RT.config && RT.config.page) ? RT.config.page : {};
   const page_height_limit = page_conf.height_limit || 1000;
 
-  let measureContainer = null;
+  let measure_container = null;
 
-  // =========================================================
   // 1. DOM Measurement Utilities
-  // =========================================================
-  function getElHeight(el){
-    const wasInDOM = el.parentNode !== null;
-    if(!wasInDOM) document.body.appendChild(el);
+  function get_el_height(el){
+    const was_in_DOM = el.parentNode !== null;
+    if(!was_in_DOM) document.body.appendChild(el);
     const rect = el.getBoundingClientRect();
     const style = window.getComputedStyle(el);
     const margin = parseFloat(style.marginTop) + parseFloat(style.marginBottom);
-    if(!wasInDOM) el.remove();
+    if(!was_in_DOM) el.remove();
     return (rect.height || 0) + (margin || 0);
   }
 
-  function getMeasureContainer(){
-    if(measureContainer && measureContainer.parentNode) return measureContainer;
-    const article = document.querySelector('RT·article');
+  function get_measure_container(){
+    if(measure_container && measure_container.parentNode) return measure_container;
+    const article = document.querySelector('RT·article, rt·article');
     if(!article){
       const temp = document.createElement('div');
       temp.style.visibility = 'hidden';
       temp.style.position = 'absolute';
       temp.style.width = '100%'; 
       document.body.appendChild(temp);
-      measureContainer = temp;
+      measure_container = temp;
       return temp;
     }
     const container = document.createElement('div');
-    const articleStyle = window.getComputedStyle(article);
+    const article_style = window.getComputedStyle(article);
     container.style.visibility = 'hidden';
     container.style.position = 'absolute';
-    container.style.width = articleStyle.width;
-    container.style.fontFamily = articleStyle.fontFamily;
-    container.style.fontSize = articleStyle.fontSize;
-    container.style.lineHeight = articleStyle.lineHeight;
-    container.style.fontWeight = articleStyle.fontWeight;
+    container.style.width = article_style.width;
+    container.style.fontFamily = article_style.fontFamily;
+    container.style.fontSize = article_style.fontSize;
+    container.style.lineHeight = article_style.lineHeight;
+    container.style.fontWeight = article_style.fontWeight;
     document.body.appendChild(container);
-    measureContainer = container;
+    measure_container = container;
     return container;
   }
 
-  function measureFragment(frag){
-    const container = getMeasureContainer();
+  function measure_fragment(frag){
+    const container = get_measure_container();
     container.appendChild(frag);
-    const h = getElHeight(frag);
+    const h = get_el_height(frag);
     container.removeChild(frag);
     return h;
   }
 
-  // =========================================================
   // Splitting Logic
-  // =========================================================
-  function isSplittable(el){
+  function is_splittable(el){
+    if(!el || el.nodeType !== Node.ELEMENT_NODE) return null;
 
-    // Component Dictionary Execution
-    const componentId = el.getAttribute('data-rt-component');
-    if (componentId && window.RT.Component && window.RT.Component[componentId] && window.RT.Component[componentId].split) {
-      return (remaining) => window.RT.Component[componentId].split(el, remaining, measureFragment);
+    const component_id = el.getAttribute('data-rt-component');
+    if(component_id && window.RT.Component && window.RT.Component[component_id] && window.RT.Component[component_id].split){
+      return (remaining) => window.RT.Component[component_id].split(el ,remaining ,measure_fragment);
     }
 
-    // Custom RT splitable attribute delegation
-    if (el.hasAttribute('splitable') && window.RT.Splitter && window.RT.Splitter[el.tagName.toLowerCase()]) {
-      return (remaining) => window.RT.Splitter[el.tagName.toLowerCase()](el, remaining, measureFragment, isSplittable);
+    if(el.hasAttribute('splitable') && window.RT.Splitter && window.RT.Splitter[(el.tagName || '').toLowerCase()]){
+      return (remaining) => window.RT.Splitter[(el.tagName || '').toLowerCase()](el ,remaining ,measure_fragment ,is_splittable);
     }
 
-    // Native HTML Fallbacks
-
-    const tag = el.tagName;
+    const tag = (el.tagName || '').toUpperCase();
     if(tag === 'UL' || tag === 'OL'){
-      const items = Array.from(el.children).filter(c => c.tagName === 'LI');
+      const items = Array.from(el.children).filter(c => (c.tagName || '').toUpperCase() === 'LI');
       if(items.length === 0) return null;
 
-      const itemHeights = items.map(li => getElHeight(li));
-      const emptyClone = el.cloneNode(false);
-      const overhead = getElHeight(emptyClone);
+      const item_heights = items.map(li => get_el_height(li));
+      const empty_clone = el.cloneNode(false);
+      const overhead = get_el_height(empty_clone);
 
-      el._splitInfo = { type: 'list' ,itemHeights ,overhead ,offset: 0 };
-      return makeListSplitter(el ,el._splitInfo);
+      el._splitInfo = { type: 'list' ,itemHeights: item_heights ,overhead: overhead ,offset: 0 };
+      return make_list_splitter(el ,el._splitInfo);
     }
 
     if(tag === 'TABLE'){
       const rows = tbody ? Array.from(tbody.rows) : Array.from(el.rows);
       if(rows.length === 0) return null;
 
-      const theadHeight = thead ? getElHeight(thead) : 0;
-      const rowHeights = rows.map(row => getElHeight(row));
+      const thead_height = thead ? get_el_height(thead) : 0;
+      const row_heights = rows.map(row => get_el_height(row));
 
-      const emptyClone = el.cloneNode(false);
-      if(thead) emptyClone.appendChild(thead.cloneNode(true));
-      emptyClone.appendChild(document.createElement('tbody'));
-      const overhead = getElHeight(emptyClone) - theadHeight;
+      const empty_clone = el.cloneNode(false);
+      if(thead) empty_clone.appendChild(thead.cloneNode(true));
+      empty_clone.appendChild(document.createElement('tbody'));
+      const overhead = get_el_height(empty_clone) - thead_height;
 
-      el._splitInfo = { type: 'table' ,rowHeights ,overhead ,theadHeight ,offset: 0 };
-      return makeTableSplitter(el ,el._splitInfo);
+      el._splitInfo = { type: 'table' ,rowHeights: row_heights ,overhead: overhead ,theadHeight: thead_height ,offset: 0 };
+      return make_table_splitter(el ,el._splitInfo);
     }
     return null; 
   }
 
-  function makeListSplitter(el ,info){
+  function make_list_splitter(el ,info){
     return (remaining) => {
-      const children = Array.from(el.children).filter(c => c.tagName === 'LI');
+      const children = Array.from(el.children).filter(c => (c.tagName || '').toUpperCase() === 'LI');
       const start = info.offset;
 
-      let bestCount = 0;
-      let bestHeight = 0;
-      const tempList = el.cloneNode(false);
+      let best_count = 0;
+      let best_height = 0;
+      const temp_list = el.cloneNode(false);
       
       for(let i = 0; i < children.length; i++){
-        const itemClone = children[i].cloneNode(true);
-        tempList.appendChild(itemClone);
-        const fragHeight = measureFragment(tempList);
-        if(fragHeight <= remaining){
-          bestCount = i + 1;
-          bestHeight = fragHeight;
-        } else {
-          tempList.removeChild(itemClone);
+        const item_clone = children[i].cloneNode(true);
+        temp_list.appendChild(item_clone);
+        const frag_height = measure_fragment(temp_list);
+        if(frag_height <= remaining){
+          best_count = i + 1;
+          best_height = frag_height;
+        }else{
+          temp_list.removeChild(item_clone);
           break;
         }
       }
 
-      if(bestCount === 0) return { first: null ,rest: el ,firstHeight: 0 };
+      if(best_count === 0) return { first: null ,rest: el ,firstHeight: 0 };
 
       const first = el.cloneNode(false);
-      for(let i = 0; i < bestCount; i++){
+      for(let i = 0; i < best_count; i++){
         first.appendChild(children[i].cloneNode(true));
       }
 
       let rest = null;
-      if(bestCount < children.length){
+      if(best_count < children.length){
         rest = el.cloneNode(false);
-        for(let i = bestCount; i < children.length; i++){
+        for(let i = best_count; i < children.length; i++){
           rest.appendChild(children[i].cloneNode(true));
         }
 
-        if(el.tagName === 'OL'){
-          const currentStart = parseInt(el.getAttribute('start') ,10) || 1;
-          rest.setAttribute('start' ,currentStart + bestCount);
+        if((el.tagName || '').toUpperCase() === 'OL'){
+          const current_start = parseInt(el.getAttribute('start') ,10) || 1;
+          rest.setAttribute('start' ,current_start + best_count);
         }
 
         rest._splitInfo = {
           type: 'list'
           ,itemHeights: info.itemHeights
           ,overhead: info.overhead
-          ,offset: start + bestCount
+          ,offset: start + best_count
         };
       }
 
-      return { first ,rest ,firstHeight: bestHeight };
+      return { first: first ,rest: rest ,firstHeight: best_height };
     };
   }
 
-  function makeTableSplitter(el ,info){
+  function make_table_splitter(el ,info){
     const thead = el.querySelector('thead');
-    const createShell = () => {
+    const create_shell = () => {
       const shell = el.cloneNode(false);
       if(thead) shell.appendChild(thead.cloneNode(true));
-      const newTbody = document.createElement('tbody');
-      shell.appendChild(newTbody);
+      const new_tbody = document.createElement('tbody');
+      shell.appendChild(new_tbody);
       return shell;
     };
 
       const rows = tbody ? Array.from(tbody.rows) : Array.from(el.rows);
       const start = info.offset;
 
-      let bestCount = 0;
-      let bestHeight = 0;
-      const tempTable = createShell();
-      const tempBody = tempTable.querySelector('tbody');
+      let best_count = 0;
+      let best_height = 0;
+      const temp_table = create_shell();
+      const temp_body = temp_table.querySelector('tbody');
       
       for(let i = 0; i < rows.length; i++){
-        tempBody.appendChild(rows[i].cloneNode(true));
-        const h = measureFragment(tempTable);
+        temp_body.appendChild(rows[i].cloneNode(true));
+        const h = measure_fragment(temp_table);
         if(h <= remaining){
-          bestCount = i + 1;
-          bestHeight = h;
-        } else {
-          tempBody.removeChild(tempBody.lastChild);
+          best_count = i + 1;
+          best_height = h;
+        }else{
+          temp_body.removeChild(temp_body.lastChild);
           break;
         }
       }
 
-      if(bestCount === 0) return { first: null ,rest: el ,firstHeight: 0 };
+      if(best_count === 0) return { first: null ,rest: el ,firstHeight: 0 };
 
-      const first = createShell();
-      const firstBody = first.querySelector('tbody');
-      for(let i = 0; i < bestCount; i++){
-        firstBody.appendChild(rows[i].cloneNode(true));
+      const first = create_shell();
+      const first_body = first.querySelector('tbody');
+      for(let i = 0; i < best_count; i++){
+        first_body.appendChild(rows[i].cloneNode(true));
       }
 
       let rest = null;
-      if(bestCount < rows.length){
-        rest = createShell();
-        const restBody = rest.querySelector('tbody');
-        for(let i = bestCount; i < rows.length; i++){
-          restBody.appendChild(rows[i].cloneNode(true));
+      if(best_count < rows.length){
+        rest = create_shell();
+        const rest_body = rest.querySelector('tbody');
+        for(let i = best_count; i < rows.length; i++){
+          rest_body.appendChild(rows[i].cloneNode(true));
         }
 
         rest._splitInfo = {
           ,rowHeights: info.rowHeights
           ,overhead: info.overhead
           ,theadHeight: info.theadHeight
-          ,offset: start + bestCount
+          ,offset: start + best_count
         };
       }
 
-      return { first ,rest ,firstHeight: bestHeight };
+      return { first: first ,rest: rest ,firstHeight: best_height };
     };
   }
 
-
-  // =========================================================
   // RT ELEMENT SPLITTERS
-  // =========================================================
   window.RT.Splitter = window.RT.Splitter || {};
 
-  window.RT.Splitter['rt·counter·step'] = function(el, remaining, measureFn, isSplittableFn) {
-    const children = Array.from(el.children);
-    let bestCount = 0;
-    let bestHeight = 0;
-    const tempContainer = el.cloneNode(false);
-    let splitChildResult = null;
-    let forcedBreak = false;
+  window.RT.Splitter['rt·counter·step'] = function(el ,remaining ,measure_fn ,is_splittable_fn){
+    const children = Array.from(el.childNodes);
+    let best_count = 0;
+    let best_height = 0;
+    const temp_container = el.cloneNode(false);
+    let split_child_result = null;
+    let forced_break = false;
 
-    for (let i = 0; i < children.length; i++) {
+    for(let i = 0; i < children.length; i++){
       const child = children[i];
 
-      // Break on explicit splitting break
-      if (child.tagName && child.tagName.toLowerCase() === 'rt·page-break') {
-        forcedBreak = true;
-        bestCount = i;
+      const tag = child.nodeType === Node.ELEMENT_NODE ? (child.tagName || '').toLowerCase() : '';
+      if(tag === 'rt·page-break' || tag === 'rt·page-break-primitive'){
+        forced_break = true;
+        best_count = i;
         break;
       }
 
-      tempContainer.appendChild(child.cloneNode(true));
-      const fragHeight = measureFn(tempContainer);
-
-      if (fragHeight <= remaining) {
-        bestCount = i + 1;
-        bestHeight = fragHeight;
-      } else {
-        tempContainer.removeChild(tempContainer.lastChild);
-        const childSplitter = isSplittableFn(child);
-        if (childSplitter) {
-          const childSplit = childSplitter(remaining - bestHeight);
-          if (childSplit && childSplit.first) {
-            splitChildResult = childSplit;
-            bestHeight += childSplit.firstHeight;
-            bestCount = i;
+      temp_container.appendChild(child.cloneNode(true));
+      const frag_height = measure_fn(temp_container);
+
+      if(frag_height <= remaining){
+        best_count = i + 1;
+        best_height = frag_height;
+      }else{
+        temp_container.removeChild(temp_container.lastChild);
+        const child_splitter = child.nodeType === Node.ELEMENT_NODE ? is_splittable_fn(child) : null;
+        if(child_splitter){
+          const child_split = child_splitter(remaining - best_height);
+          if(child_split && child_split.first){
+            split_child_result = child_split;
+            best_height += child_split.firstHeight;
+            best_count = i;
           }
         }
         break;
       }
     }
 
-    if (bestCount === 0 && !splitChildResult && !forcedBreak) {
-      return { first: null, rest: el, firstHeight: 0 };
+    if(best_count === 0 && !split_child_result && !forced_break){
+      return { first: null ,rest: el ,firstHeight: 0 };
     }
 
     const first = el.cloneNode(false);
-    first.setAttribute('continued''true');
-    const splitId = 'split_' + Math.random().toString(36).substr(2, 9);
-    first.setAttribute('split-id', splitId);
+    first.setAttribute('continued' ,'true');
+    const split_id = 'split_' + Math.random().toString(36).substr(2 ,9);
+    first.setAttribute('split-id' ,split_id);
     
-    for (let i = 0; i < bestCount; i++) {
+    for(let i = 0; i < best_count; i++){
       first.appendChild(children[i].cloneNode(true));
     }
-    if (splitChildResult) first.appendChild(splitChildResult.first);
+    if(split_child_result) first.appendChild(split_child_result.first);
 
     let rest = null;
-    if (bestCount < children.length || splitChildResult || forcedBreak) {
+    if(best_count < children.length || split_child_result || forced_break){
       rest = el.cloneNode(false);
-      rest.setAttribute('continuation', 'true');
-      if (splitChildResult && splitChildResult.rest) rest.appendChild(splitChildResult.rest);
+      rest.setAttribute('continuation' ,'true');
+      
+      if(split_child_result && split_child_result.rest){
+        if(Array.isArray(split_child_result.rest)){
+          split_child_result.rest.forEach(r_node => rest.appendChild(r_node));
+        }else{
+          rest.appendChild(split_child_result.rest);
+        }
+      }
 
-      const startIndex = forcedBreak ? bestCount + 1 : (splitChildResult ? bestCount + 1 : bestCount);
-      for (let i = startIndex; i < children.length; i++) {
+      const start_index = forced_break ? best_count + 1 : (split_child_result ? best_count + 1 : best_count);
+      for(let i = start_index; i < children.length; i++){
         rest.appendChild(children[i].cloneNode(true));
       }
 
-      const makeTag = document.createElement('rt·counter·make');
-      makeTag.setAttribute('counter', el.getAttribute('counter'));
-      makeTag.setAttribute('continues', splitId); 
+      const make_tag = document.createElement('RT·counter·make');
+      make_tag.setAttribute('counter' ,el.getAttribute('counter'));
+      make_tag.setAttribute('continues' ,split_id); 
 
-      rest = [makeTag, rest];
+      rest = [make_tag ,rest];
     }
 
-    return { first, rest, firstHeight: bestHeight };
+    return { first: first ,rest: rest ,firstHeight: best_height };
   };
 
-  // =========================================================
   // PAGINATE 0: CHUNKING & INJECTING STRUCTURE
-  // =========================================================
   function paginate_0(){
     if(debug.log) debug.log('paginate_0' ,'Running initial document chunking');
 
-    const article_seq = document.querySelectorAll('RT·article');
+    const article_seq = document.querySelectorAll('RT·article, rt·article, RT·memo, rt·memo');
     if(article_seq.length === 0){
       debug.error('pagination' ,'No <RT·article> elements found. Pagination aborted.');
       return;
     const footnote_registry = {};
     let footnote_counter = 1;
 
-    // Strip and tag footnotes
     Array.from(article_seq).forEach(article => {
       const all_nodes = Array.from(article.querySelectorAll('*'));
-      const raw_footnotes = all_nodes.filter(node => node.tagName.toLowerCase() === 'rt·footnote');
+      const raw_footnotes = all_nodes.filter(node => (node.tagName || '').toLowerCase() === 'rt·footnote');
       
       raw_footnotes.forEach(fn => {
         const id = footnote_counter++;
       });
     });
 
-    function paginateArticle(article){
+    function paginate_article(article){
       const raw_element_seq = Array.from(article.children).filter(el =>
-        !['SCRIPT' ,'STYLE' ,'RT·PAGE'].includes((el.tagName || '').toUpperCase())
+        !['SCRIPT' ,'STYLE' ,'RT·PAGE' ,'RT·COUNTER·MAKE'].includes((el.tagName || '').toUpperCase()) 
       );
 
+      const global_makes = Array.from(article.children).filter(el => (el.tagName || '').toUpperCase() === 'RT·COUNTER·MAKE');
+
       if(raw_element_seq.length === 0) return;
 
       const page_seq = [];
 
       while(i < raw_element_seq.length){
         const el = raw_element_seq[i];
-        const splitter = isSplittable(el);
+        const splitter = is_splittable(el);
 
         if(splitter){
           const remaining = page_height_limit - current_h;
             current_h += firstHeight;
 
             if(rest){
-              if (Array.isArray(rest)) {
-                raw_element_seq.splice(i, 1, ...rest);
-              } else {
-                raw_element_seq.splice(i, 1, rest);
+              if(Array.isArray(rest)){
+                raw_element_seq.splice(i ,1 ,...rest);
+              }else{
+                raw_element_seq.splice(i ,1 ,rest);
+              }
+              
+              if(current_h > 0){
+                page_seq.push(current_batch_seq);
+                current_batch_seq = [];
+                current_h = 0;
               }
-              // Force page boundary push because element spanned boundary
-              page_seq.push(current_batch_seq);
-              current_batch_seq = [];
-              current_h = 0;
-              continue; 
-            } else {
-              raw_element_seq.splice(i, 1);
               continue; 
+            }else{
+              raw_element_seq.splice(i ,1);
+              continue;
             }
-          } else {
-            if(current_batch_seq.length === 0){
+          }else{
+            if(current_h === 0){
               const frame = document.createElement('RT·scroll-frame');
               frame.style.display = 'block';
               frame.style.overflowY = 'auto';
               frame.appendChild(el);
               current_batch_seq.push(frame);
               i++; 
-            } else {
-              // Element is split but first chunk fails to fit. Evict any stranded headings.
+            }else{
               let backtrack_seq = [];
               let backtrack_h = 0;
               
               while(current_batch_seq.length > 0){
                 const last = current_batch_seq[current_batch_seq.length - 1];
-                if(!/^H[1-6]$/i.test(last.tagName)) break;
+                if(!last.tagName || !/^H[1-6]$/i.test(last.tagName)) break;
                 const popped = current_batch_seq.pop();
                 backtrack_seq.unshift(popped);
-                backtrack_h += getElHeight(popped);
+                backtrack_h += get_el_height(popped);
               }
 
-              if(current_batch_seq.length > 0){
+              if(current_h - backtrack_h > 0){
                 page_seq.push(current_batch_seq);
                 current_batch_seq = backtrack_seq;
                 current_h = backtrack_h;
-                // Leave 'i' alone to re-evaluate 'el' against the fresh page sequence
-              } else {
-                // If only headings existed, accept the massive frame inline to avoid loops
+              }else{
+                current_batch_seq.push(...backtrack_seq);
+                current_h += backtrack_h;
+                
                 const frame = document.createElement('RT·scroll-frame');
                 frame.style.display = 'block';
                 frame.style.overflowY = 'auto';
                 frame.style.maxHeight = page_height_limit + 'px';
                 frame.appendChild(el);
-                
-                current_batch_seq = backtrack_seq;
-                current_h = backtrack_h;
-                
                 current_batch_seq.push(frame);
                 i++;
               }
           continue;
         }
 
-        const h = getElHeight(el);
-        const is_RT_page_break = el.tagName && el.tagName.toLowerCase() === 'rt·page-break';
-        const is_RT_page_break_primitive = el.tagName && el.tagName.toLowerCase() === 'rt·page-break-primitive';
+        const h = get_el_height(el);
+        const tag = (el.tagName || '').toLowerCase();
+        const is_RT_page_break = tag === 'rt·page-break' || tag === 'rt·page-break-primitive';
 
-        // Explicit Page Break Logic - Execute immediately without backward traversal
-        if(is_RT_page_break || is_RT_page_break_primitive){
-          if(current_batch_seq.length > 0){
+        if(is_RT_page_break){
+          if(current_h > 0){
             page_seq.push(current_batch_seq);
             current_batch_seq = [];
             current_h = 0;
           continue; 
         }
 
-        // Standard Dimension Overflow Logic - Check for orphaned headers
-        if( current_h + h > page_height_limit && current_batch_seq.length > 0 ){
+        if(current_h + h > page_height_limit && current_h > 0){
           let backtrack_seq = [];
           let backtrack_h = 0;
           
           while(current_batch_seq.length > 0){
             const last = current_batch_seq[current_batch_seq.length - 1];
-            if(!/^H[1-6]$/i.test(last.tagName)) break;
+            if(!last.tagName || !/^H[1-6]$/i.test(last.tagName)) break;
             const popped = current_batch_seq.pop();
             backtrack_seq.unshift(popped);
-            backtrack_h += getElHeight(popped);
+            backtrack_h += get_el_height(popped);
           }
 
-          if(current_batch_seq.length > 0){
+          if(current_h - backtrack_h > 0){
             page_seq.push(current_batch_seq);
             current_batch_seq = backtrack_seq;
             current_h = backtrack_h;
-          } else {
-            // Document structure resolved entirely to sequential headings that breached bounds.
-            current_batch_seq = backtrack_seq;
-            current_h = backtrack_h;
+          }else{
+            current_batch_seq.push(...backtrack_seq);
+            current_h += backtrack_h;
           }
         }
 
 
       article.innerHTML = '';
       
-      // Inject global page counter initialization
-      const page_counter_make = document.createElement('rt·counter·make');
+      global_makes.forEach(make => article.appendChild(make));
+
+      const page_counter_make = document.createElement('RT·counter·make');
       page_counter_make.setAttribute('counter' ,'RT_page_number');
       page_counter_make.setAttribute('style' ,'NaturalNumber');
       page_counter_make.setAttribute('on-first-step' ,'1');
         const batch = page_seq[p];
         const page_el = document.createElement('RT·page');
         
+        page_el.style.minHeight = page_height_limit + 'px';
+        page_el.style.position = 'relative';
+        page_el.style.paddingBottom = '5rem';
+        page_el.style.boxSizing = 'border-box';
+        
         batch.forEach(item => page_el.appendChild(item));
 
-        // Inject step and snapshot tags into the page
-        const page_step = document.createElement('rt·counter·step');
+        const page_step = document.createElement('RT·counter·step');
         page_step.setAttribute('counter' ,'RT_page_number');
         page_el.appendChild(page_step);
 
         const snapshot_name = `page_snap_${p + 1}`;
-        const page_snap = document.createElement('rt·counter·snapshot');
+        const page_snap = document.createElement('RT·counter·snapshot');
         page_snap.setAttribute('counter' ,'RT_page_number');
         page_snap.setAttribute('snapshot' ,snapshot_name);
         page_el.appendChild(page_snap);
 
-        // Optional footer text injection reading the counter snapshot
         const page_footer = document.createElement('div');
         page_footer.className = 'RT·page-footer';
-        const page_read = document.createElement('rt·counter·read');
+        page_footer.style.position = 'absolute';
+        page_footer.style.bottom = '1.5rem';
+        page_footer.style.left = '0';
+        page_footer.style.width = '100%';
+        page_footer.style.textAlign = 'center';
+
+        const page_read = document.createElement('RT·counter·read');
         page_read.setAttribute('snapshot' ,snapshot_name);
         page_footer.appendChild(page_read);
         page_el.appendChild(page_footer);
       }
     }
 
-    Array.from(article_seq).forEach(article => paginateArticle(article));
+    Array.from(article_seq).forEach(article => paginate_article(article));
 
-    // Resolve footnotes inside the generated pages
     Array.from(article_seq).forEach(article => {
-      const rendered_pages = article.querySelectorAll('RT·page');
+      const rendered_pages = article.querySelectorAll('RT·page, rt·page');
       
       Array.from(rendered_pages).forEach(page => {
         const all_page_nodes = Array.from(page.querySelectorAll('*'));
-        const markers = all_page_nodes.filter(node => node.tagName.toLowerCase() === 'rt·fn-marker');
+        const markers = all_page_nodes.filter(node => (node.tagName || '').toLowerCase() === 'rt·fn-marker');
         
         if(markers.length === 0) return;
 
       });
     });
 
-    if(measureContainer && measureContainer.parentNode){
-      measureContainer.remove();
-      measureContainer = null;
+    if(measure_container && measure_container.parentNode){
+      measure_container.remove();
+      measure_container = null;
     }
   }
 
-  // =========================================================
-  // PAGINATE 1: ABSORB DIMENSIONAL DELTA
-  // =========================================================
   function paginate_1(){
     if(debug.log) debug.log('paginate_1' ,'Adjusting final page heights after component injections');
 
-    const rendered_pages = document.querySelectorAll('RT·page');
+    const rendered_pages = document.querySelectorAll('RT·page, rt·page');
     Array.from(rendered_pages).forEach(page => {
       const actual_height = page.scrollHeight;
       if(actual_height > page_height_limit){
     });
   }
 
-  //----------------------------------------
-  // Registration upon load
-  //
-
   window.RT.paginate_0 = paginate_0;
   window.RT.paginate_1 = paginate_1;
 
-
 })();