<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no">
<title>[[TITLE]]</title>
<meta name="description" content="[[DESC]]">
<link rel="canonical" href="[[URL]]">
<meta property="og:type" content="book"><meta property="og:title" content="[[TITLE]]">
<meta property="og:description" content="[[DESC]]"><meta property="og:url" content="[[URL]]">
<meta property="og:image" content="[[COVER]]"><meta name="twitter:card" content="summary_large_image">
[[SCHEMA]]
<style>
:root{--bg:#fdfdfb;--fg:#1a1a1a;--muted:#8a8a8a;--accent:#9a7d2e;--chrome:#ffffff;--line:#e7e2d6;}
*{box-sizing:border-box;-webkit-tap-highlight-color:transparent}
html,body{margin:0;height:100%;background:var(--bg);color:var(--fg);font-family:Georgia,'Times New Roman',serif}
body{transition:background .25s,color .25s}
body.theme-sepia{--bg:#f6ecd4;--fg:#5b4636;--chrome:#efe4c8;--line:#e0d3ad}
body.theme-mint{--bg:#dcebd7;--fg:#22331f;--chrome:#d0e2ca;--line:#bcd4b4}
body.theme-dark{--bg:#0e0e0e;--fg:#c9c6bf;--muted:#777;--chrome:#1b1b1b;--line:#2a2a2a}
/* readable fallback (no JS) */
#source{max-width:680px;margin:0 auto;padding:28px 22px;line-height:1.7}
#source h1{text-align:center}#source h2{margin-top:1.6em}
#app{display:none}
body.ready{overflow:hidden}
body.ready #source{display:none}
body.ready #app{display:flex;position:fixed;inset:0;flex-direction:column}
.chrome{background:var(--chrome);border-color:var(--line);flex:0 0 auto;transition:transform .25s,opacity .2s;z-index:5}
#topbar{display:flex;align-items:center;gap:6px;padding:10px 12px;border-bottom:1px solid var(--line)}
#topbar .ttl{flex:1;text-align:center;font-size:14px;font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.iconbtn{border:0;background:transparent;color:var(--fg);font-size:20px;width:40px;height:40px;border-radius:8px;cursor:pointer}
.iconbtn:active{background:rgba(128,128,128,.15)}
#chrometop.hide{transform:translateY(-100%);opacity:0;pointer-events:none}
#chromebot.hide{transform:translateY(100%);opacity:0;pointer-events:none}
#reader{flex:1;position:relative;overflow:hidden}
#viewport{position:absolute;inset:0;padding:14px 22px}
#content{height:100%;column-gap:44px;-webkit-column-gap:44px;transition:transform .28s ease;will-change:transform;max-width:none}
#content p{margin:0 0 .9em;text-align:var(--align,justify);hyphens:auto;-webkit-hyphens:auto}
#content .chtitle{font-size:1.25em;font-weight:700;margin:.2em 0 .8em;text-align:center;line-height:1.3}
body.scrollmode #reader{overflow-y:auto;-webkit-overflow-scrolling:touch}
body.scrollmode #viewport{position:static;padding:18px 22px 60px}
body.scrollmode #content{height:auto;column-width:auto!important;columns:auto!important;transform:none!important}
.tap{position:absolute;top:0;bottom:0;width:33%;z-index:2}
#tapL{left:0}#tapR{right:0}#tapM{left:33%;width:34%}
body.scrollmode .tap{display:none}
#chromebot{padding:8px 14px 12px;border-top:1px solid var(--line)}
#meta{display:flex;justify-content:space-between;font-size:11px;color:var(--muted);margin-bottom:6px}
#seek{width:100%;-webkit-appearance:none;height:4px;border-radius:2px;background:var(--line);outline:none}
#seek::-webkit-slider-thumb{-webkit-appearance:none;width:16px;height:16px;border-radius:50%;background:var(--accent);cursor:pointer}
#seek::-moz-range-thumb{width:16px;height:16px;border:0;border-radius:50%;background:var(--accent);cursor:pointer}
.panel{position:absolute;left:0;right:0;bottom:0;background:var(--chrome);border-top:1px solid var(--line);z-index:20;transform:translateY(100%);transition:transform .28s ease;max-height:80%;overflow:auto;padding:6px 0 16px}
.panel.open{transform:translateY(0)}
#toc{top:0;bottom:auto;transform:translateY(-100%);border-top:0;border-bottom:1px solid var(--line)}
#toc.open{transform:translateY(0)}
.tocitem{padding:12px 18px;border-bottom:1px solid var(--line);cursor:pointer;font-size:14px;display:flex;justify-content:space-between;gap:10px}
.tocitem.cur{color:var(--accent);font-weight:700}.tocitem .pct{color:var(--muted);font-size:11px}
.tabs{display:flex;border-bottom:1px solid var(--line);position:sticky;top:0;background:var(--chrome)}
.tab{flex:1;text-align:center;padding:12px;font-size:13px;cursor:pointer;color:var(--muted);border-bottom:2px solid transparent}
.tab.on{color:var(--accent);border-bottom-color:var(--accent);font-weight:700}
.sect{padding:14px 18px;display:none}.sect.on{display:block}
.row{display:flex;align-items:center;gap:10px;margin:10px 0}
.lab{font-size:13px;min-width:96px}
.fonts{display:flex;gap:8px;overflow:auto;padding-bottom:4px}
.fontchip{border:1px solid var(--line);border-radius:10px;padding:8px 12px;cursor:pointer;white-space:nowrap;background:transparent;color:var(--fg);font-size:16px}
.fontchip.on{border-color:var(--accent);color:var(--accent)}
.swatches{display:flex;gap:12px}
.sw{width:34px;height:34px;border-radius:50%;cursor:pointer;border:2px solid var(--line)}
.sw.on{outline:2px solid var(--accent);outline-offset:2px}
.seg{display:flex;border:1px solid var(--line);border-radius:8px;overflow:hidden}
.seg button{flex:1;border:0;background:transparent;color:var(--fg);padding:8px 10px;cursor:pointer;font-size:13px}
.seg button.on{background:var(--accent);color:#fff}
input[type=range].mini{flex:1}
.toggle{margin-left:auto;width:44px;height:26px;border-radius:14px;background:var(--line);position:relative;cursor:pointer;transition:background .2s}
.toggle.on{background:var(--accent)}
.toggle b{position:absolute;top:3px;left:3px;width:20px;height:20px;border-radius:50%;background:#fff;transition:left .2s}
.toggle.on b{left:21px}
#ruler{position:absolute;left:0;right:0;height:34px;background:rgba(154,125,46,.14);border-top:1px solid rgba(154,125,46,.4);border-bottom:1px solid rgba(154,125,46,.4);pointer-events:none;z-index:3;display:none}
#dim{position:absolute;inset:0;background:#000;opacity:0;pointer-events:none;z-index:4}
.backdrop{position:absolute;inset:0;background:rgba(0,0,0,.25);z-index:15;opacity:0;pointer-events:none;transition:opacity .2s}
.backdrop.on{opacity:1;pointer-events:auto}
</style></head>
<body class="theme-white">
<div id="source">[[BODY]]</div>
<div id="app">
<div id="chrometop" class="chrome"><div id="topbar">
<button class="iconbtn" id="tocBtn" title="Contents">☰</button>
<div class="ttl" id="bookttl">[[TITLE]]</div>
<button class="iconbtn" id="aaBtn" title="Display">Aa</button></div></div>
<div id="reader"><div id="viewport"><div id="content"></div></div>
<div id="ruler"></div><div id="dim"></div>
<div class="tap" id="tapL"></div><div class="tap" id="tapM"></div><div class="tap" id="tapR"></div></div>
<div id="chromebot" class="chrome"><div id="meta"><span id="mLeft">Chapter</span><span id="mRight">0%</span></div>
<input type="range" id="seek" min="0" max="1000" value="0"></div>
<div class="backdrop" id="backdrop"></div>
<div class="panel" id="toc"></div>
<div class="panel" id="aa">
<div class="tabs"><div class="tab on" data-t="font">Font</div><div class="tab" data-t="layout">Layout</div><div class="tab" data-t="more">More</div></div>
<div class="sect on" id="s-font"><div class="fonts" id="fontchips"></div>
<div class="row"><span class="lab">Size</span><span>A</span><input type="range" class="mini" id="fsize" min="15" max="30" step="1"><span style="font-size:22px">A</span></div>
<div class="row"><span class="lab">Spacing</span><input type="range" class="mini" id="fspace" min="130" max="210" step="10"></div></div>
<div class="sect" id="s-layout">
<div class="row"><span class="lab">Page color</span><div class="swatches" id="swatches"></div></div>
<div class="row"><span class="lab">Alignment</span><div class="seg" id="alignseg"><button data-a="left">Left</button><button data-a="justify" class="on">Justified</button></div></div>
<div class="row"><span class="lab">Continuous scroll</span><div class="toggle" id="tScroll"><b></b></div></div></div>
<div class="sect" id="s-more">
<div class="row"><span class="lab">Reading ruler</span><div class="toggle" id="tRuler"><b></b></div></div>
<div class="row"><span class="lab">Brightness</span><input type="range" class="mini" id="bright" min="0" max="70" step="5" value="0"></div>
<div class="row"><span class="lab">Go to chapter</span><div class="seg"><button id="goPrev">Prev</button><button id="goNext">Next</button></div></div></div>
</div>
</div>
<script>
var SLUG="new-reader-template";
function LS(k,v){try{if(v===undefined)return localStorage.getItem(k);localStorage.setItem(k,v);}catch(e){return null;}}
var BOOK=(function(){
var src=document.getElementById('source');var nodes=Array.prototype.slice.call(src.childNodes);
var chapters=[],cur=null,front="";
nodes.forEach(function(n){
var isCh=n.nodeType===1&&/^ch\d+/.test(n.id||"");
if(isCh){var title=(n.tagName==='H2')?n.textContent.trim():"";cur={title:title,html:front};front="";chapters.push(cur);}
else if(cur){cur.html+=(n.nodeType===1?n.outerHTML:"");}
else{if(n.nodeType===1&&n.tagName!=='H1')front+=n.outerHTML;}
});
if(!chapters.length)chapters=[{title:"",html:src.innerHTML}];
return chapters;
})();
var S={ci:0,page:0,pages:1,
fs:parseInt(LS('zybk_fs')||"19"),sp:parseInt(LS('zybk_sp')||"170"),
fam:LS('zybk_fam')||"Georgia, 'Times New Roman', serif",theme:LS('zybk_theme')||"white",
align:LS('zybk_align')||"justify",scroll:LS('zybk_scroll')==="1",ruler:LS('zybk_ruler')==="1"};
var el=function(id){return document.getElementById(id)};
var content=el('content'),viewport=el('viewport'),reader=el('reader');
var FONTS=[["Bookerly","Georgia, 'Times New Roman', serif"],["Palatino","'Palatino Linotype','Book Antiqua',Palatino,serif"],["Charter","Charter,'Iowan Old Style','Times New Roman',serif"],["Times","'Times New Roman',Times,serif"],["Sans","system-ui,-apple-system,'Segoe UI',Roboto,sans-serif"]];
var THEMES=[["white","#fdfdfb"],["sepia","#f6ecd4"],["mint","#dcebd7"],["dark","#0e0e0e"]];
function renderChrome(){
var fc=el('fontchips');fc.innerHTML="";
FONTS.forEach(function(f){var b=document.createElement('button');b.className="fontchip"+(S.fam===f[1]?" on":"");b.style.fontFamily=f[1];b.textContent=f[0];b.onclick=function(){S.fam=f[1];LS('zybk_fam',f[1]);apply();paginate();goPage(0);renderChrome();};fc.appendChild(b);});
var sw=el('swatches');sw.innerHTML="";
THEMES.forEach(function(t){var d=document.createElement('div');d.className="sw"+(S.theme===t[0]?" on":"");d.style.background=t[1];d.onclick=function(){S.theme=t[0];LS('zybk_theme',t[0]);apply();renderChrome();};sw.appendChild(d);});
el('fsize').value=S.fs;el('fspace').value=S.sp;
Array.prototype.forEach.call(el('alignseg').children,function(b){b.classList.toggle('on',b.dataset.a===S.align);});
el('tScroll').classList.toggle('on',S.scroll);el('tRuler').classList.toggle('on',S.ruler);
}
function buildTOC(){var t=el('toc');t.innerHTML="";
BOOK.forEach(function(c,i){var d=document.createElement('div');d.className="tocitem"+(i===S.ci?" cur":"");
var pct=Math.round(i/BOOK.length*100);var nm=c.title||("Chapter "+(i+1));
d.innerHTML='<span>'+nm.replace(/</g,"<")+'</span><span class="pct">'+pct+'%</span>';
d.onclick=function(){gotoChapter(i,0);closeAll();};t.appendChild(d);});}
function apply(){
document.body.className="theme-"+S.theme+" ready"+(S.scroll?" scrollmode":"");
content.style.fontSize=S.fs+"px";content.style.lineHeight=(S.sp/100);content.style.fontFamily=S.fam;
content.style.setProperty("--align",S.align);
el('ruler').style.display=(S.ruler&&!S.scroll)?"block":"none";
if(!S.scroll){var w=viewport.clientWidth;content.style.columnWidth=w+"px";content.style.webkitColumnWidth=w+"px";content.style.height=viewport.clientHeight+"px";}
}
function pageStep(){return viewport.clientWidth+44;}
function paginate(){if(S.scroll){S.pages=1;return;}S.pages=Math.max(1,Math.round(content.scrollWidth/pageStep()));}
function goPage(p){if(S.scroll)return;S.page=Math.max(0,Math.min(p,S.pages-1));content.style.transform="translateX("+(-S.page*pageStep())+"px)";savePos();updateMeta();}
function nextPage(){if(S.scroll)return;if(S.page>=S.pages-1){if(S.ci<BOOK.length-1)gotoChapter(S.ci+1,0);}else goPage(S.page+1);}
function prevPage(){if(S.scroll)return;if(S.page<=0){if(S.ci>0)gotoChapter(S.ci-1,"last");}else goPage(S.page-1);}
function gotoChapter(i,page){
S.ci=Math.max(0,Math.min(i,BOOK.length-1));S.page=0;buildTOC();
var c=BOOK[S.ci]||{title:"",html:""};
content.innerHTML='<h2 class="chtitle">'+((c.title||"").replace(/</g,"<"))+'</h2>'+(c.html||"");
apply();requestAnimationFrame(function(){paginate();if(page==="last")goPage(S.pages-1);else goPage(page||0);savePos();updateMeta();});
if(S.scroll)reader.scrollTop=0;
}
function overall(){var within=S.scroll?(reader.scrollHeight>reader.clientHeight?reader.scrollTop/(reader.scrollHeight-reader.clientHeight):0):(S.pages>1?S.page/(S.pages-1):0);return (S.ci+within)/BOOK.length;}
function updateMeta(){var o=overall();el('seek').value=Math.round(o*1000);el('mRight').textContent=Math.round(o*100)+"%";el('mLeft').textContent=(BOOK[S.ci].title||("Chapter "+(S.ci+1))).slice(0,32);}
function savePos(){LS('zybk_ci_'+SLUG,S.ci);LS('zybk_pg_'+SLUG,S.page);}
el('tapR').onclick=function(){nextPage();};el('tapL').onclick=function(){prevPage();};el('tapM').onclick=function(){toggleChrome();};
document.addEventListener('keydown',function(e){if(e.key==="ArrowRight")nextPage();if(e.key==="ArrowLeft")prevPage();});
el('seek').addEventListener('input',function(){var frac=this.value/1000;var i=Math.min(BOOK.length-1,Math.floor(frac*BOOK.length));el('mRight').textContent=Math.round(frac*100)+"%";el('mLeft').textContent=(BOOK[i].title||("Chapter "+(i+1))).slice(0,32);});
el('seek').addEventListener('change',function(){var frac=this.value/1000;var i=Math.min(BOOK.length-1,Math.floor(frac*BOOK.length));gotoChapter(i,0);});
reader.addEventListener('scroll',function(){if(S.scroll){updateMeta();var sp=reader.scrollHeight>reader.clientHeight?reader.scrollTop/(reader.scrollHeight-reader.clientHeight):0;}});
function toggleChrome(){el('chrometop').classList.toggle('hide');el('chromebot').classList.toggle('hide');}
function openPanel(p){closeAll();el(p).classList.add('open');el('backdrop').classList.add('on');}
function closeAll(){el('toc').classList.remove('open');el('aa').classList.remove('open');el('backdrop').classList.remove('on');}
el('tocBtn').onclick=function(){el('toc').classList.contains('open')?closeAll():openPanel('toc');};
el('aaBtn').onclick=function(){el('aa').classList.contains('open')?closeAll():openPanel('aa');};
el('backdrop').onclick=closeAll;
Array.prototype.forEach.call(document.querySelectorAll('.tab'),function(t){t.onclick=function(){document.querySelectorAll('.tab').forEach(function(x){x.classList.remove('on')});t.classList.add('on');['font','layout','more'].forEach(function(s){el('s-'+s).classList.toggle('on',s===t.dataset.t)});};});
el('fsize').oninput=function(){S.fs=+this.value;LS('zybk_fs',S.fs);apply();paginate();goPage(0);};
el('fspace').oninput=function(){S.sp=+this.value;LS('zybk_sp',S.sp);apply();paginate();goPage(0);};
Array.prototype.forEach.call(el('alignseg').children,function(b){b.onclick=function(){S.align=b.dataset.a;LS('zybk_align',S.align);renderChrome();apply();};});
el('tScroll').onclick=function(){S.scroll=!S.scroll;LS('zybk_scroll',S.scroll?"1":"0");renderChrome();gotoChapter(S.ci,0);};
el('tRuler').onclick=function(){S.ruler=!S.ruler;LS('zybk_ruler',S.ruler?"1":"0");renderChrome();apply();};
el('bright').oninput=function(){el('dim').style.opacity=(this.value/100);};
el('goPrev').onclick=function(){if(S.ci>0)gotoChapter(S.ci-1,0);};
el('goNext').onclick=function(){if(S.ci<BOOK.length-1)gotoChapter(S.ci+1,0);};
reader.addEventListener('mousemove',function(e){if(!S.ruler||S.scroll)return;var r=reader.getBoundingClientRect();el('ruler').style.top=(e.clientY-r.top-17)+"px";});
reader.addEventListener('touchmove',function(e){if(!S.ruler||S.scroll)return;var r=reader.getBoundingClientRect();el('ruler').style.top=(e.touches[0].clientY-r.top-17)+"px";},{passive:true});
window.addEventListener('resize',function(){apply();paginate();goPage(S.page);});
/* boot */
renderChrome();buildTOC();
var startCi=parseInt(LS('zybk_ci_'+SLUG)||"0")||0;var startPg=parseInt(LS('zybk_pg_'+SLUG)||"0")||0;
gotoChapter(startCi,startPg);
</script></body></html>