Improve thoroughly significantly without breaking anything. Increase its robustness as much as possible. Send the fully working full codes. -- <!doctypehtml><html lang=en><meta charset=UTF-8><meta content="width=device-width,initial-scale=1"name=viewport><title>Top Light Novels</title><meta content="Discover and explore the top light novels to read."name=description><meta content="light novels, top novels, reading, books, literature"name=keywords><link href=styles.css rel=stylesheet><link href=https://fonts.googleapis.com rel=preconnect><link href=https://fonts.gstatic.com rel=preconnect crossorigin><link href=https://www.cloudflare.com rel=preconnect><link href=https://cdn.jsdelivr.net rel=preconnect><link href=https://unpkg.com rel=preconnect><link href="https://fonts.googleapis.com/css2?family=Montserrat:wght@400;700&family=Playfair+Display:wght@400;700&display=swap"rel=stylesheet><script src=https://cdn.jsdelivr.net/npm/dexie@latest/dist/dexie.min.js defer></script><script src=script.js defer type=module></script><script src=https://unpkg.com/ionicons@7.1.0/dist/ionicons/ionicons.esm.js type=module></script><script src=https://unpkg.com/ionicons@7.1.0/dist/ionicons/ionicons.js nomodule></script><header><button aria-label="Open Menu"class=menu-btn aria-controls=menu-panel aria-expanded=false><ion-icon name=menu-outline class=menu-icon></ion-icon></button><div class=search-bar role=search><input aria-label="Search Novels"id=search-input autocomplete=off class=search-input placeholder=Search...> <button aria-label="Search Novels"class=search-btn id=search-button><ion-icon name=search-outline></ion-icon></button></div></header><main><section aria-label="Top Light Novels Grid"class=book-grid id=book-grid role=grid></section></main><aside aria-hidden=true aria-labelledby=menu-heading class=panel id=menu-panel><h3 id=menu-heading>Menu</h3><nav><ul><li><a href=# id=library-link>Library</a><li><a href=# id=settings-link>Settings</a></ul></nav></aside><aside aria-hidden=true aria-labelledby=library-heading class=panel id=library-panel><h3 id=library-heading>Library</h3><div id=library-content></div></aside><aside aria-hidden=true aria-labelledby=settings-heading class=panel id=settings-panel><h3 id=settings-heading>Settings</h3><div class=settings-option><label for=theme-toggle>Dark Theme</label><div class=toggle-switch><input aria-label="Toggle Dark Theme"id=theme-toggle type=checkbox> <span class=slider></span></div></div></aside><div class=loading-spinner role=status id=loading-spinner aria-hidden=true aria-label=Loading></div><div class=error-message role=alert id=error-message aria-live=assertive></div> -- "use strict";const config={proxyUrl:"https://sh.dafeyan784.workers.dev/?target=",targetUrl:"https://jnovels.com/top-light-novels-to-read/",batchSize:40,maxRetries:3,retryDelay:1e3,searchDebounceTime:300,intersectionObserverThreshold:.2,intersectionObserverRootMargin:"250px",errorMessageDisplayTime:5e3,fetchTimeout:1e4,fallbackImage:'data:image/svg+xml,%3Csvg xmlns="http://www.w3.org/2000/svg" width="200" height="300" viewBox="0 0 200 300"%3E%3Crect width="100%" height="100%" fill="%23f0f0f0"/%3E%3Ctext x="50%" y="50%" dominant-baseline="middle" text-anchor="middle" font-family="Arial, sans-serif" font-size="16" fill="%23999"%3EImage not available%3C/text%3E%3C/svg%3E'};class NovelWebsite{constructor(){this.db=new Database,this.elements=this.getElements(),this.state={currentBatch:0,images:[],loadedImages:new Set,isLoading:!1,isPanelOpen:!1,pdfUrlToTextMap:new Map},this.setupEventListeners()}getElements(){return{bookGrid:document.querySelector("#book-grid"),searchInput:document.querySelector("#search-input"),searchButton:document.querySelector("#search-button"),loadingSpinner:document.querySelector(".loading-spinner"),menuBtn:document.querySelector(".menu-btn"),menuPanel:document.querySelector("#menu-panel"),libraryPanel:document.querySelector("#library-panel"),settingsPanel:document.querySelector("#settings-panel"),themeToggle:document.querySelector("#theme-toggle"),errorMessage:document.querySelector("#error-message"),libraryLink:document.querySelector("#library-link"),settingsLink:document.querySelector("#settings-link")}}setupEventListeners(){this.elements.searchInput?.addEventListener("keydown",this.handleSearchKeydown.bind(this)),this.elements.searchButton?.addEventListener("click",this.performSearch.bind(this)),this.elements.menuBtn?.addEventListener("click",()=>this.togglePanel(this.elements.menuPanel)),this.elements.libraryLink?.addEventListener("click",this.handleLibraryLink.bind(this)),this.elements.settingsLink?.addEventListener("click",this.handleSettingsLink.bind(this)),document.addEventListener("click",this.handleDocumentClick.bind(this)),this.elements.themeToggle?.addEventListener("change",this.handleThemeToggle.bind(this)),window.addEventListener("beforeunload",this.handleBeforeUnload.bind(this))}async init(){this.loadSavedTheme(),"undefined"!=typeof AOS&&AOS.init(),await this.fetchAndLoadImages()}loadSavedTheme(){"true"===localStorage.getItem("darkTheme")&&(document.body.classList.add("dark-theme"),this.elements.themeToggle&&(this.elements.themeToggle.checked=!0))}async fetchAndLoadImages(){if(!this.state.isLoading&&!this.state.isPanelOpen){this.state.isLoading=!0,this.toggleLoadingSpinner(!0);try{var e=await this.db.getHtmlContent(1),t=e?e.content:await this.fetchWithTimeout(""+config.proxyUrl+encodeURIComponent(config.targetUrl));t?(e||await this.db.putHtmlContent(1,t),this.extractImagesAndPdfLinks(t),0<this.state.images.length?(await this.loadImages(),this.setupIntersectionObserver()):this.showErrorMessage("No images found. Please check the source.")):this.showErrorMessage("No content fetched. Please try again later.")}catch(e){console.error("Error during fetching or parsing:",e),this.showErrorMessage("Failed to fetch books. Please try again later.")}finally{this.state.isLoading=!1,this.toggleLoadingSpinner(!1)}}}async fetchWithTimeout(e,t={},s=config.fetchTimeout){const r=new AbortController;s=setTimeout(()=>r.abort(),s);try{var n=await fetch(e,{...t,signal:r.signal});if(clearTimeout(s),n.ok)return await n.text();throw new Error("HTTP error! Status: "+n.status)}catch(e){throw clearTimeout(s),console.error("Fetch error:",e),this.showErrorMessage("Network error. Please check your connection and try again."),new Error("Fetch failed: "+e.message)}}extractImagesAndPdfLinks(e){var t;e?(e=(new DOMParser).parseFromString(e,"text/html"),t=Array.from(e.querySelectorAll('img[loading="lazy"][decoding="async"].alignnone')),e.querySelectorAll("a[href]").forEach(e=>{var t;e.href&&"string"==typeof e.href&&(t=e.href.trim(),e=(e.querySelector('span[style="color: #ff6600;"]')||e).textContent?.trim(),t&&e&&this.state.pdfUrlToTextMap.set(t,(this.state.pdfUrlToTextMap.get(t)||[]).concat(e)))}),this.state.images=t.filter(e=>e.src&&!this.state.loadedImages.has(e.src)),t.forEach(e=>this.state.loadedImages.add(e.src))):this.showErrorMessage("Failed to parse HTML content.")}async loadImages(){var e=this.state.currentBatch*config.batchSize,t=Math.min(e+config.batchSize,this.state.images.length),e=this.state.images.slice(e,t);const s=document.createDocumentFragment();0===e.length?this.showErrorMessage("No more images to load."):(await Promise.all(e.map(e=>this.createGridItem(e).then(e=>{e&&s.appendChild(e)}))),this.elements.bookGrid?.appendChild(s),this.state.currentBatch++)}async createGridItem(r,n=0){if(!r||!r.src)return console.error("Invalid image element:",r),null;const a=this.createElement("div",{class:"grid-item","data-aos":"fade-up"}),i=new Image;return i.src=r.src,i.className="lazyload",i.alt="Book Cover",new Promise(e=>{i.onload=()=>{i.style.display="block",e(a)},i.onerror=async()=>{n<config.maxRetries?setTimeout(()=>this.createGridItem(r,n+1).then(e),config.retryDelay):(console.error(`Failed to load image after ${config.maxRetries} retries:`,r.src),i.src=config.fallbackImage,i.onload=()=>e(a),i.onerror=()=>{this.showErrorMessage("Failed to load image: "+r.src),e(null)})},a.appendChild(i);const t=r.closest("a");var s;t?.href&&(i.addEventListener("click",e=>{e.preventDefault(),this.isValidUrl(t.href)?window.open(t.href,"_blank","noopener,noreferrer"):this.showErrorMessage("Invalid link detected.")}),(s=this.state.pdfUrlToTextMap.get(t.href))?.length&&(s=this.createElement("p",{class:"textElement"},s.join(", ")),a.appendChild(s)))})}isValidUrl(e){if("string"!=typeof e)return!1;try{return new URL(e),!0}catch{return!1}}setupIntersectionObserver(){if(this.elements.bookGrid){const t=new IntersectionObserver(e=>{e.some(e=>e.isIntersecting)&&this.state.currentBatch*config.batchSize<this.state.images.length&&!this.state.isLoading&&this.loadImages()},{rootMargin:config.intersectionObserverRootMargin,threshold:config.intersectionObserverThreshold});var e;(e=this.elements.bookGrid.lastElementChild)?t.observe(e):t.disconnect()}}createElement(e,t={},...s){const r=document.createElement(e);return Object.entries(t).forEach(([e,t])=>r.setAttribute(e,t)),s.forEach(e=>{"string"==typeof e?r.textContent=e:e instanceof Node&&r.appendChild(e)}),r}toggleLoadingSpinner(e){this.elements.loadingSpinner&&this.elements.loadingSpinner.classList.toggle("active",e)}showErrorMessage(e){this.elements.errorMessage&&(this.elements.errorMessage.textContent=e,this.elements.errorMessage.classList.add("active"),setTimeout(()=>this.elements.errorMessage.classList.remove("active"),config.errorMessageDisplayTime))}redirectSearchResults(e){var e=this.sanitizeInput(e);e?(e="search-results.html?query="+encodeURIComponent(e),window.open(e,"_blank","noopener,noreferrer")):this.showErrorMessage("Invalid search query.")}sanitizeInput(e){var t;return"string"!=typeof e?"":((t=document.createElement("div")).textContent=e,t.innerHTML)}debounce(t,s){let r;return(...e)=>{clearTimeout(r),r=setTimeout(()=>t.apply(this,e),s)}}performSearch=this.debounce(e=>{e.preventDefault();e=this.elements.searchInput?.value.trim();!e||e.length<3?this.showErrorMessage("Search term must be at least 3 characters long."):100<e.length?this.showErrorMessage("Search term must be less than 100 characters."):this.redirectSearchResults(e)},config.searchDebounceTime);togglePanel(e){e&&(e.classList.toggle("active"),this.state.isPanelOpen=e.classList.contains("active"))}handleDocumentClick(e){e.target.closest(".panel")||e.target.closest(".menu-btn")||([this.elements.menuPanel,this.elements.libraryPanel,this.elements.settingsPanel].forEach(e=>e?.classList.remove("active")),this.state.isPanelOpen=!1)}handleThemeToggle(){document.body.classList.toggle("dark-theme"),localStorage.setItem("darkTheme",document.body.classList.contains("dark-theme"))}handleSearchKeydown(e){"Enter"===e.key&&this.performSearch(e)}handleLibraryLink(){this.elements.menuPanel?.classList.remove("active"),this.togglePanel(this.elements.libraryPanel)}handleSettingsLink(){this.elements.menuPanel?.classList.remove("active"),this.togglePanel(this.elements.settingsPanel)}async handleBeforeUnload(){try{await this.db.clearHtmlContent()}catch(e){console.error("Error clearing database on unload:",e)}}}class Database{constructor(){this.db=new Dexie("NovelDatabase"),this.db.version(1).stores({htmlContent:"++id, content"})}async getHtmlContent(e){try{return await this.db.htmlContent.get(e)||null}catch(e){return console.error("Database read error:",e),null}}async putHtmlContent(e,t){try{await this.db.htmlContent.put({id:e,content:t})}catch(e){console.error("Database write error:",e)}}async clearHtmlContent(){try{await this.db.htmlContent.clear()}catch(e){console.error("Database clear error:",e)}}}document.addEventListener("DOMContentLoaded",()=>{(new NovelWebsite).init()}); -- @keyframes fadeIn{0%{opacity:0}to{opacity:1}}@keyframes scaleIn{0%{transform:scale(.8)}to{transform:scale(1)}}@keyframes slideUp{0%{transform:translateY(20px);opacity:0}to{transform:translateY(0);opacity:1}}@keyframes spin{0%{transform:translate(-50%,-50%) rotate(0deg)}to{transform:translate(-50%,-50%) rotate(360deg)}}:root{--color-primary:#333;--color-secondary:#f5f5f5;--color-text:#333;--color-background:#f5f5f5;--color-shadow:rgba(0, 0, 0, 0.1);--color-hover:#666;--font-primary:'Montserrat', sans-serif;--font-secondary:'Playfair Display', serif;--font-size-base:16px;--font-size-h1:2.5rem;--font-size-h2:2rem;--font-size-h3:1.75rem;--spacing-xs:0.25rem;--spacing-sm:0.5rem;--spacing-md:1rem;--spacing-lg:1.5rem;--spacing-xl:2rem;--transition-speed:0.3s;--transition-timing:ease-in-out;--header-height:60px;--container-max-width:1200px;--border-radius:10px}.dark-theme{--color-primary:#f5f5f5;--color-secondary:#333;--color-text:#f5f5f5;--color-background:#222;--color-shadow:rgba(255, 255, 255, 0.1);--color-hover:#ddd}*,::after,::before{box-sizing:border-box}html{font-size:var(--font-size-base);scroll-behavior:smooth}body{font-family:var(--font-primary);margin:0;padding:0;background-color:var(--color-background);color:var(--color-text);transition:background-color var(--transition-speed) var(--transition-timing),color var(--transition-speed) var(--transition-timing);line-height:1.6}.back-btn,.menu-btn,header{display:flex;align-items:center}header{position:fixed;top:0;left:0;width:100%;height:var(--header-height);background-color:var(--color-primary);color:var(--color-secondary);padding:var(--spacing-sm) var(--spacing-md);justify-content:space-between;z-index:100;box-shadow:0 2px 5px var(--color-shadow)}.back-btn,.menu-btn{background-color:transparent;border:0;cursor:pointer;width:40px;height:40px;justify-content:center;border-radius:50%;transition:transform var(--transition-speed) var(--transition-timing)}.back-btn:focus,.back-btn:hover,.menu-btn:focus,.menu-btn:hover{transform:scale(1.1);outline:0}.back-btn ion-icon,.menu-icon{font-size:24px;color:var(--color-secondary)}.search-bar{display:flex;align-items:center;background-color:var(--color-secondary);border-radius:20px;padding:var(--spacing-sm) var(--spacing-md);box-shadow:0 2px 5px var(--color-shadow);transition:box-shadow var(--transition-speed) var(--transition-timing);margin-right:60px;max-width:300px;width:100%}.search-bar.active{box-shadow:0 4px 10px var(--color-shadow)}.search-input{flex:1;border:0;background-color:transparent;font-size:1rem;outline:0;padding:0;color:var(--color-text)}.search-input::placeholder{color:#999}.search-btn{background-color:transparent;border:0;cursor:pointer;display:flex;align-items:center;justify-content:center;transition:transform var(--transition-speed) var(--transition-timing)}.search-btn:focus,.search-btn:hover{transform:scale(1.1);outline:0}.search-btn ion-icon{font-size:20px;color:var(--color-text)}main{display:flex;flex-direction:column;align-items:center;min-height:calc(100vh - var(--header-height));padding:var(--spacing-xl);margin-top:var(--header-height)}.book-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(200px,1fr));gap:var(--spacing-lg);width:100%;max-width:var(--container-max-width)}.grid-item,.grid-item img{border-radius:var(--border-radius)}.grid-item{position:relative;background-color:var(--color-secondary);box-shadow:0 2px 5px var(--color-shadow);cursor:pointer;transition:transform var(--transition-speed) var(--transition-timing),box-shadow var(--transition-speed) var(--transition-timing);overflow:hidden;aspect-ratio:2/3}.grid-item img{width:100%;height:100%;object-fit:cover;transition:transform var(--transition-speed) var(--transition-timing)}.grid-item:focus,.grid-item:hover{transform:translateY(-5px);box-shadow:0 4px 10px var(--color-shadow)}.grid-item:focus img,.grid-item:hover img{transform:scale(1.05)}.textElement{position:absolute;bottom:0;left:0;width:100%;padding:var(--spacing-sm);background-color:rgba(0,0,0,.7);color:#fff;font-family:var(--font-secondary);font-size:.9rem;text-align:center;opacity:.8;transition:opacity var(--transition-speed) var(--transition-timing)}.grid-item:focus .textElement,.grid-item:hover .textElement{opacity:1}.panel{position:fixed;top:0;right:-100%;background-color:var(--color-background);height:100vh;width:50%;max-width:250px;padding:var(--spacing-xl);transition:right var(--transition-speed) var(--transition-timing);box-shadow:-2px 0 5px var(--color-shadow);z-index:101;display:flex;flex-direction:column;align-items:flex-start;overflow-y:auto}.panel a,.panel h3{color:var(--color-text)}.panel h3{margin:0 0 var(--spacing-lg);font-size:var(--font-size-h3);font-weight:700}.panel ul{list-style-type:none;padding:0;width:100%}.panel li{margin-bottom:var(--spacing-md)}.panel a{text-decoration:none;font-size:1.125rem;transition:color var(--transition-speed) var(--transition-timing),background-color var(--transition-speed) var(--transition-timing);display:block;padding:var(--spacing-sm);border-radius:var(--border-radius);background-color:var(--color-secondary);box-shadow:0 2px 5px var(--color-shadow)}.panel a:focus,.panel a:hover{color:var(--color-hover);background-color:var(--color-primary);outline:0}.panel.active{right:0}.error-message,.loading-spinner{position:fixed;left:50%;display:none}.loading-spinner{top:50%;transform:translate(-50%,-50%);width:50px;height:50px;border:5px solid var(--color-secondary);border-top:5px solid var(--color-primary);border-radius:50%;animation:spin 1s linear infinite;z-index:103}.error-message.active,.loading-spinner.active{display:block}.error-message{bottom:var(--spacing-md);transform:translateX(-50%);background-color:#ff4d4d;color:#fff;padding:var(--spacing-sm) var(--spacing-md);border-radius:var(--border-radius);box-shadow:0 2px 5px var(--color-shadow);z-index:200}.settings-option{margin-bottom:var(--spacing-lg);width:100%}.settings-option label{display:block;margin-bottom:var(--spacing-sm);font-weight:700;font-size:1rem}.toggle-switch{position:relative;display:inline-block;width:60px;height:34px}.toggle-switch input{opacity:0;width:0;height:0}.slider{position:absolute;cursor:pointer;top:0;left:0;right:0;bottom:0;background-color:#ccc;transition:background-color .4s;border-radius:34px}.slider:before{position:absolute;content:"";height:26px;width:26px;left:4px;bottom:4px;background-color:#fff;transition:transform .4s;border-radius:50%}input:checked+.slider{background-color:#2196f3}input:checked+.slider:before{transform:translateX(26px)}.title{animation:slideUp var(--transition-speed) var(--transition-timing)}.menu-btn,.search-bar{animation:scaleIn var(--transition-speed) var(--transition-timing)}@media (max-width:768px){.book-grid{grid-template-columns:repeat(auto-fill,minmax(150px,1fr))}.panel{width:75%}}@media (max-width:480px){.book-grid{grid-template-columns:repeat(auto-fill,minmax(120px,1fr))}.panel{width:100%}.search-bar{max-width:200px}}