1.Analyse and review all and whole codes and Improve them even more thoroughly and significantly as possible without breaking and compromising anything.

2.Increase its robustness as much as possible. 

3.Make it a state-of-art web app version. 

4.Fix all potential and posible issues, errors, edge cases, bottlenecks, loop, etc in any circumstances possible. 

5.Always consider all the consequences of your changes and handle all of them effectively and carefully without any side-effects. 

6.Send the fully working full codes.
--- 
Codes: [
<!DOCTYPE html>
<html lang="en">
<head>
    <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">
    
    <!-- Stylesheets -->
    <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">
    
    <!-- Scripts -->
    <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" defer></script>

<script src="https://unpkg.com/ionicons@7.1.0/dist/ionicons/ionicons.js" nomodule defer></script>

</head>
<body>
    <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">
            <!-- Book items will be populated here -->
        </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>
                <li><a href="#" id="settings-link">Settings</a></li>
            </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">
            <!-- Library content will be populated here -->
        </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>
</body>
</html>
---
"use strict";

// Configuration Object
const config = {
    proxyUrl: "https://sh.dafeyan784.workers.dev/?target=",
    targetUrl: "https://jnovels.com/top-light-novels-to-read/",
    batchSize: 40,
    maxRetries: 3,
    retryDelay: 1000, // in milliseconds
    searchDebounceTime: 300, // in milliseconds
    intersectionObserverThreshold: 0.2,
    intersectionObserverRootMargin: "250px",
    errorMessageDisplayTime: 5000, // in milliseconds
    fetchTimeout: 10000, // in milliseconds
    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'
};

/**
 * Main Class for the Novel Website
 */
class NovelWebsite {
    constructor() {
        this.db = new Database();
        this.elements = this.getElements();
        this.state = {
            currentBatch: 0,
            images: [],
            loadedImages: new Set(),
            isLoading: false,
            isPanelOpen: false,
            pdfUrlToTextMap: new Map()
        };
        this.setupEventListeners();
    }

    /**
     * Cache DOM elements for later use
     */
    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")
        };
    }

    /**
     * Setup all necessary event listeners
     */
    setupEventListeners() {
        if (this.elements.searchInput) {
            this.elements.searchInput.addEventListener("keydown", this.handleSearchKeydown.bind(this));
        }

        if (this.elements.searchButton) {
            this.elements.searchButton.addEventListener("click", this.performSearch.bind(this));
        }

        if (this.elements.menuBtn) {
            this.elements.menuBtn.addEventListener("click", () => this.togglePanel(this.elements.menuPanel));
        }

        if (this.elements.libraryLink) {
            this.elements.libraryLink.addEventListener("click", this.handleLibraryLink.bind(this));
        }

        if (this.elements.settingsLink) {
            this.elements.settingsLink.addEventListener("click", this.handleSettingsLink.bind(this));
        }

        document.addEventListener("click", this.handleDocumentClick.bind(this));

        if (this.elements.themeToggle) {
            this.elements.themeToggle.addEventListener("change", this.handleThemeToggle.bind(this));
        }

        window.addEventListener("beforeunload", this.handleBeforeUnload.bind(this));
    }

    /**
     * Initialize the website functionality
     */
    async init() {
        this.loadSavedTheme();
        if (typeof AOS !== "undefined") {
            AOS.init();
        }
        await this.fetchAndLoadImages();
    }

    /**
     * Load the saved theme from localStorage
     */
    loadSavedTheme() {
        if (localStorage.getItem("darkTheme") === "true") {
            document.body.classList.add("dark-theme");
            if (this.elements.themeToggle) {
                this.elements.themeToggle.checked = true;
            }
        }
    }

    /**
     * Fetch and load images
     */
    async fetchAndLoadImages() {
        if (!this.state.isLoading && !this.state.isPanelOpen) {
            this.state.isLoading = true;
            this.toggleLoadingSpinner(true);
            try {
                let htmlContent = await this.db.getHtmlContent(1);
                let content = htmlContent ? htmlContent.content : await this.fetchWithTimeout(`${config.proxyUrl}${encodeURIComponent(config.targetUrl)}`);

                if (content) {
                    if (!htmlContent) {
                        await this.db.putHtmlContent(1, content);
                    }
                    this.extractImagesAndPdfLinks(content);

                    if (this.state.images.length > 0) {
                        await this.loadImages();
                        this.setupIntersectionObserver();
                    } else {
                        this.showErrorMessage("No images found. Please check the source.");
                    }
                } else {
                    this.showErrorMessage("No content fetched. Please try again later.");
                }
            } catch (error) {
                console.error("Error during fetching or parsing:", error);
                this.showErrorMessage("Failed to fetch books. Please try again later.");
            } finally {
                this.state.isLoading = false;
                this.toggleLoadingSpinner(false);
            }
        }
    }

    /**
     * Fetch with a timeout
     * @param {string} url - URL to fetch
     * @param {object} options - Fetch options
     * @param {number} timeout - Timeout in milliseconds
     * @returns {Promise<string>} - Response text
     */
    async fetchWithTimeout(url, options = {}, timeout = config.fetchTimeout) {
        const controller = new AbortController();
        const timer = setTimeout(() => controller.abort(), timeout);

        try {
            const response = await fetch(url, { ...options, signal: controller.signal });
            clearTimeout(timer);
            if (response.ok) {
                return await response.text();
            }
            throw new Error(`HTTP error! Status: ${response.status}`);
        } catch (error) {
            clearTimeout(timer);
            console.error("Fetch error:", error);
            this.showErrorMessage("Network error. Please check your connection and try again.");
            throw new Error(`Fetch failed: ${error.message}`);
        }
    }

    /**
     * Extract images and PDF links from HTML content
     * @param {string} html - HTML content
     */
    extractImagesAndPdfLinks(html) {
        if (html) {
            const parser = new DOMParser();
            const doc = parser.parseFromString(html, "text/html");

            // Extract images
            const imgElements = Array.from(doc.querySelectorAll('img[loading="lazy"][decoding="async"].alignnone'));
            this.state.images = imgElements.filter(img => img.src && !this.state.loadedImages.has(img.src)).map(img => img);
            imgElements.forEach(img => this.state.loadedImages.add(img.src));

            // Extract PDF links
            const anchorElements = Array.from(doc.querySelectorAll("a[href]"));
            anchorElements.forEach(anchor => {
                if (anchor.href && typeof anchor.href === "string") {
                    const href = anchor.href.trim();
                    const textContent = (anchor.querySelector('span[style="color: #ff6600;"]') || anchor).textContent?.trim();
                    if (href && textContent) {
                        const existingTexts = this.state.pdfUrlToTextMap.get(href) || [];
                        this.state.pdfUrlToTextMap.set(href, [...existingTexts, textContent]);
                    }
                }
            });

            if (this.state.images.length === 0) {
                this.showErrorMessage("No images found. Please check the source.");
            }
        } else {
            this.showErrorMessage("Failed to parse HTML content.");
        }
    }

    /**
     * Load a batch of images
     */
    async loadImages() {
        const startIndex = this.state.currentBatch * config.batchSize;
        const endIndex = Math.min(startIndex + config.batchSize, this.state.images.length);
        const imageBatch = this.state.images.slice(startIndex, endIndex);
        const fragment = document.createDocumentFragment();

        if (imageBatch.length === 0) {
            this.showErrorMessage("No more images to load.");
            return;
        }

        try {
            const gridItems = await Promise.all(imageBatch.map(img => this.createGridItem(img)));
            gridItems.forEach(item => {
                if (item) {
                    fragment.appendChild(item);
                }
            });
            if (this.elements.bookGrid) {
                this.elements.bookGrid.appendChild(fragment);
            }
            this.state.currentBatch++;
        } catch (error) {
            console.error("Error loading images:", error);
            this.showErrorMessage("An error occurred while loading images.");
        }
    }

    /**
     * Create a grid item for each image
     * @param {HTMLElement} imageElement - Image element from the parsed HTML
     * @param {number} retryCount - Current retry attempt
     * @returns {Promise<HTMLElement|null>} - Grid item element or null if failed
     */
    async createGridItem(imageElement, retryCount = 0) {
        if (!imageElement || !imageElement.src) {
            console.error("Invalid image element:", imageElement);
            return null;
        }

        const gridItem = this.createElement("div", { class: "grid-item", "data-aos": "fade-up" });
        const img = new Image();
        img.src = imageElement.src;
        img.className = "lazyload";
        img.alt = "Book Cover";

        return new Promise(resolve => {
            img.onload = () => {
                img.style.display = "block";
                resolve(gridItem);
            };

            img.onerror = async () => {
                if (retryCount < config.maxRetries) {
                    setTimeout(() => {
                        this.createGridItem(imageElement, retryCount + 1).then(resolve);
                    }, config.retryDelay);
                } else {
                    console.error(`Failed to load image after ${config.maxRetries} retries:`, imageElement.src);
                    img.src = config.fallbackImage;
                    img.onload = () => resolve(gridItem);
                    img.onerror = () => {
                        this.showErrorMessage(`Failed to load image: ${imageElement.src}`);
                        resolve(null);
                    };
                }
            };

            gridItem.appendChild(img);

            const anchor = imageElement.closest("a");
            if (anchor && anchor.href) {
                img.addEventListener("click", event => {
                    event.preventDefault();
                    if (this.isValidUrl(anchor.href)) {
                        window.open(anchor.href, "_blank", "noopener,noreferrer");
                    } else {
                        this.showErrorMessage("Invalid link detected.");
                    }
                });

                const pdfTexts = this.state.pdfUrlToTextMap.get(anchor.href);
                if (pdfTexts && pdfTexts.length > 0) {
                    const textElement = this.createElement("p", { class: "textElement" }, pdfTexts.join(", "));
                    gridItem.appendChild(textElement);
                }
            }
        });
    }

    /**
     * Validate URL
     * @param {string} url - URL to validate
     * @returns {boolean} - True if valid, else false
     */
    isValidUrl(url) {
        if (typeof url !== "string") return false;
        try {
            new URL(url);
            return true;
        } catch {
            return false;
        }
    }

    /**
     * Setup Intersection Observer for lazy loading
     */
    setupIntersectionObserver() {
        if (this.elements.bookGrid) {
            const observer = new IntersectionObserver(entries => {
                if (entries.some(entry => entry.isIntersecting)) {
                    if (
                        this.state.currentBatch * config.batchSize < this.state.images.length &&
                        !this.state.isLoading
                    ) {
                        this.loadImages();
                    }
                }
            }, {
                rootMargin: config.intersectionObserverRootMargin,
                threshold: config.intersectionObserverThreshold
            });

            const lastGridItem = this.elements.bookGrid.lastElementChild;
            if (lastGridItem) {
                observer.observe(lastGridItem);
            } else {
                observer.disconnect();
            }
        }
    }

    /**
     * Utility method to create DOM elements
     * @param {string} tag - Tag name
     * @param {object} attributes - Attributes to set
     * @param  {...any} children - Child nodes or text
     * @returns {HTMLElement} - Created element
     */
    createElement(tag, attributes = {}, ...children) {
        const element = document.createElement(tag);
        Object.entries(attributes).forEach(([key, value]) => element.setAttribute(key, value));
        children.forEach(child => {
            if (typeof child === "string") {
                element.textContent = child;
            } else if (child instanceof Node) {
                element.appendChild(child);
            }
        });
        return element;
    }

    /**
     * Toggle the loading spinner
     * @param {boolean} show - Whether to show or hide the spinner
     */
    toggleLoadingSpinner(show) {
        if (this.elements.loadingSpinner) {
            this.elements.loadingSpinner.classList.toggle("active", show);
            this.elements.loadingSpinner.setAttribute("aria-hidden", !show);
        }
    }

    /**
     * Display an error message
     * @param {string} message - Error message to display
     */
    showErrorMessage(message) {
        if (this.elements.errorMessage) {
            this.elements.errorMessage.textContent = message;
            this.elements.errorMessage.classList.add("active");
            setTimeout(() => {
                this.elements.errorMessage.classList.remove("active");
            }, config.errorMessageDisplayTime);
        }
    }

    /**
     * Redirect to search results page
     * @param {string} query - Search query
     */
    redirectSearchResults(query) {
        const sanitizedQuery = this.sanitizeInput(query);
        if (sanitizedQuery) {
            const searchUrl = `search-results.html?query=${encodeURIComponent(sanitizedQuery)}`;
            window.open(searchUrl, "_blank", "noopener,noreferrer");
        } else {
            this.showErrorMessage("Invalid search query.");
        }
    }

    /**
     * Sanitize user input to prevent XSS
     * @param {string} input - User input
     * @returns {string} - Sanitized input
     */
    sanitizeInput(input) {
        if (typeof input !== "string") return "";
        const div = document.createElement("div");
        div.textContent = input;
        return div.innerHTML;
    }

    /**
     * Debounce function to limit the rate at which a function can fire
     * @param {function} func - Function to debounce
     * @param {number} delay - Delay in milliseconds
     * @returns {function} - Debounced function
     */
    debounce(func, delay) {
        let timeoutId;
        return (...args) => {
            clearTimeout(timeoutId);
            timeoutId = setTimeout(() => func.apply(this, args), delay);
        };
    }

    /**
     * Perform search with debouncing
     */
    performSearch = this.debounce(event => {
        event.preventDefault();
        const query = this.elements.searchInput?.value.trim();

        if (!query || query.length < 3) {
            this.showErrorMessage("Search term must be at least 3 characters long.");
        } else if (query.length > 100) {
            this.showErrorMessage("Search term must be less than 100 characters.");
        } else {
            this.redirectSearchResults(query);
        }
    }, config.searchDebounceTime);

    /**
     * Toggle visibility of a panel
     * @param {HTMLElement} panel - Panel element to toggle
     */
    togglePanel(panel) {
        if (panel) {
            panel.classList.toggle("active");
            this.state.isPanelOpen = panel.classList.contains("active");
        }
    }

    /**
     * Handle clicks outside of panels to close them
     * @param {Event} event - Click event
     */
    handleDocumentClick(event) {
        const isClickInsidePanel = event.target.closest(".panel");
        const isClickMenuBtn = event.target.closest(".menu-btn");

        if (!isClickInsidePanel && !isClickMenuBtn) {
            const panels = [this.elements.menuPanel, this.elements.libraryPanel, this.elements.settingsPanel];
            panels.forEach(panel => panel?.classList.remove("active"));
            this.state.isPanelOpen = false;
        }
    }

    /**
     * Handle theme toggle switch
     */
    handleThemeToggle() {
        document.body.classList.toggle("dark-theme");
        const isDarkTheme = document.body.classList.contains("dark-theme");
        localStorage.setItem("darkTheme", isDarkTheme);
    }

    /**
     * Handle keydown events on the search input
     * @param {KeyboardEvent} event - Keyboard event
     */
    handleSearchKeydown(event) {
        if (event.key === "Enter") {
            this.performSearch(event);
        }
    }

    /**
     * Handle clicking on the Library link
     */
    handleLibraryLink() {
        if (this.elements.menuPanel) {
            this.elements.menuPanel.classList.remove("active");
        }
        this.togglePanel(this.elements.libraryPanel);
    }

    /**
     * Handle clicking on the Settings link
     */
    handleSettingsLink() {
        if (this.elements.menuPanel) {
            this.elements.menuPanel.classList.remove("active");
        }
        this.togglePanel(this.elements.settingsPanel);
    }

    /**
     * Handle actions before the window unloads
     */
    async handleBeforeUnload() {
        try {
            await this.db.clearHtmlContent();
        } catch (error) {
            console.error("Error clearing database on unload:", error);
        }
    }
}

/**
 * Database Class using Dexie.js for IndexedDB operations
 */
class Database {
    constructor() {
        this.db = new Dexie("NovelDatabase");
        this.db.version(1).stores({
            htmlContent: "++id, content"
        });
    }

    /**
     * Get HTML content by ID
     * @param {number} id - ID of the content
     * @returns {Promise<object|null>} - HTML content or null
     */
    async getHtmlContent(id) {
        try {
            return await this.db.htmlContent.get(id) || null;
        } catch (error) {
            console.error("Database read error:", error);
            return null;
        }
    }

    /**
     * Put (insert/update) HTML content
     * @param {number} id - ID of the content
     * @param {string} content - HTML content
     */
    async putHtmlContent(id, content) {
        try {
            await this.db.htmlContent.put({ id, content });
        } catch (error) {
            console.error("Database write error:", error);
        }
    }

    /**
     * Clear all HTML content
     */
    async clearHtmlContent() {
        try {
            await this.db.htmlContent.clear();
        } catch (error) {
            console.error("Database clear error:", error);
        }
    }
}

// Initialize the Website once the DOM is fully loaded
document.addEventListener("DOMContentLoaded", () => {
    const novelWebsite = new NovelWebsite();
    novelWebsite.init();
});
---
/* Keyframe Animations */
@keyframes fadeIn {
    0% { opacity: 0; }
    to { opacity: 1; }
}

@keyframes scaleIn {
    0% { transform: scale(0.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); 
    }
}

/* CSS Variables */
:root {
    /* Colors */
    --color-primary: #333;
    --color-secondary: #f5f5f5;
    --color-text: #333;
    --color-background: #f5f5f5;
    --color-shadow: rgba(0, 0, 0, 0.1);
    --color-hover: #666;

    /* Fonts */
    --font-primary: 'Montserrat', sans-serif;
    --font-secondary: 'Playfair Display', serif;

    /* Font Sizes */
    --font-size-base: 16px;
    --font-size-h1: 2.5rem;
    --font-size-h2: 2rem;
    --font-size-h3: 1.75rem;

    /* Spacing */
    --spacing-xs: 0.25rem;
    --spacing-sm: 0.5rem;
    --spacing-md: 1rem;
    --spacing-lg: 1.5rem;
    --spacing-xl: 2rem;

    /* Transitions */
    --transition-speed: 0.3s;
    --transition-timing: ease-in-out;

    /* Layout */
    --header-height: 60px;
    --container-max-width: 1200px;
    --border-radius: 10px;
}

/* Dark Theme Overrides */
.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;
}

/* Global Styles */
*, ::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;
}

/* Header and Buttons */
.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 */
.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 Content */
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);
}

/* Text Element Overlay */
.textElement {
    position: absolute;
    bottom: 0;
    left: 0;
    width: 100%;
    padding: var(--spacing-sm);
    background-color: rgba(0, 0, 0, 0.7);
    color: #fff;
    font-family: var(--font-secondary);
    font-size: 0.9rem;
    text-align: center;
    opacity: 0.8;
    transition: opacity var(--transition-speed) var(--transition-timing);
}

.grid-item:focus .textElement,
.grid-item:hover .textElement {
    opacity: 1;
}

/* Panels */
.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;
}

/* Loading Spinner and Error Message */
.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 Panel */
.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 0.4s;
    border-radius: 34px;
}

.slider:before {
    position: absolute;
    content: "";
    height: 26px;
    width: 26px;
    left: 4px;
    bottom: 4px;
    background-color: #fff;
    transition: transform 0.4s;
    border-radius: 50%;
}

input:checked + .slider {
    background-color: #2196f3;
}

input:checked + .slider:before {
    transform: translateX(26px);
}

/* Title Animation */
.title {
    animation: slideUp var(--transition-speed) var(--transition-timing);
}

/* Menu Button and Search Bar Animations */
.menu-btn,
.search-bar {
    animation: scaleIn var(--transition-speed) var(--transition-timing);
}

/* Responsive Design */

/* Tablet Devices */
@media (max-width: 768px) {
    .book-grid {
        grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
    }

    .panel {
        width: 75%;
    }
}

/* Mobile Devices */
@media (max-width: 480px) {
    .book-grid {
        grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
    }

    .panel {
        width: 100%;
    }

    .search-bar {
        max-width: 200px;
    }
}
--- ]