Copy Build a personal reading-queue page with Tailwind CSS. Include currently reading with progress, saved articles grouped into Next and Later, estimated reading time, topic tags, and a compact completion archive. Add JavaScript that moves articles between priority groups, updates reading progress, marks an article complete, and persists queue state in localStorage with guarded storage access. <main class="min-h-screen bg-neutral-50 px-6 py-12"><div class="mx-auto max-w-4xl"><header class="flex items-end justify-between"><div><p class="text-xs font-semibold uppercase tracking-wider text-neutral-400">Your library</p><h1 class="mt-2 text-3xl font-semibold tracking-tight text-neutral-900">Reading queue</h1></div><span id="queueTotal" class="text-sm text-neutral-400"></span></header><section class="mt-8 rounded-2xl bg-neutral-900 p-5 text-white"><p class="text-xs uppercase tracking-wider text-white/40">Continue reading</p><div class="mt-4 flex flex-col gap-4 sm:flex-row sm:items-end"><div class="flex-1"><h2 class="text-xl font-medium">Designing for reversible decisions</h2><p class="mt-1 text-sm text-white/45">Strategy · 14 min read</p><div class="mt-4 h-1.5 overflow-hidden rounded-full bg-white/10"><div id="readingProgress" class="h-full w-[38%] bg-amber-300"></div></div></div><button id="advanceReading" class="rounded-xl bg-white px-4 py-2.5 text-sm font-medium text-neutral-900">Read 10% more</button></div></section><div class="mt-8 grid gap-6 md:grid-cols-2"><section><div class="flex justify-between"><h2 class="font-semibold text-neutral-900">Next</h2><span class="text-xs text-neutral-400">Priority</span></div><div id="queueNext" data-list="next" class="mt-3 space-y-3"><article data-article="systems" class="rounded-2xl border border-neutral-200 bg-white p-4"><span class="text-[10px] uppercase tracking-wider text-violet-600">Systems</span><h3 class="mt-2 font-medium">Interfaces for long-running work</h3><p class="mt-1 text-xs text-neutral-400">9 min · saved yesterday</p><div class="mt-4 flex gap-3 text-xs"><button data-move="later" class="text-neutral-500">Move later</button><button data-complete class="ml-auto font-medium text-green-700">Mark read</button></div></article><article data-article="research" class="rounded-2xl border border-neutral-200 bg-white p-4"><span class="text-[10px] uppercase tracking-wider text-blue-600">Research</span><h3 class="mt-2 font-medium">What evidence survives a roadmap?</h3><p class="mt-1 text-xs text-neutral-400">7 min · saved Monday</p><div class="mt-4 flex gap-3 text-xs"><button data-move="later" class="text-neutral-500">Move later</button><button data-complete class="ml-auto font-medium text-green-700">Mark read</button></div></article></div></section><section><div class="flex justify-between"><h2 class="font-semibold text-neutral-900">Later</h2><span class="text-xs text-neutral-400">No pressure</span></div><div id="queueLater" data-list="later" class="mt-3 space-y-3"><article data-article="culture" class="rounded-2xl border border-neutral-200 bg-white p-4"><span class="text-[10px] uppercase tracking-wider text-amber-600">Culture</span><h3 class="mt-2 font-medium">A practical history of office rituals</h3><p class="mt-1 text-xs text-neutral-400">18 min · saved Aug 24</p><div class="mt-4 flex gap-3 text-xs"><button data-move="next" class="text-neutral-500">Move to next</button><button data-complete class="ml-auto font-medium text-green-700">Mark read</button></div></article></div></section></div><p id="queueArchive" aria-live="polite" class="mt-8 rounded-xl border border-dashed border-neutral-200 p-4 text-sm text-neutral-400">No articles completed in this session.</p></div></main> var progress = 38; function storeQueue() { try { localStorage.setItem("reading-progress", String(progress)); } catch (error) {} } try { progress = Number(localStorage.getItem("reading-progress")) || progress; } catch (error) {} function syncQueue() { document.getElementById("readingProgress").style.width = progress + "%"; document.getElementById("queueTotal").textContent = document.querySelectorAll("[data-article]").length + " saved articles"; } document.getElementById("advanceReading").addEventListener("click", function () { progress = Math.min(100, progress + 10); syncQueue(); storeQueue(); if (progress === 100) this.textContent = "Article complete ✓"; }); document.addEventListener("click", function (event) { var move = event.target.closest("[data-move]"); var complete = event.target.closest("[data-complete]"); if (move) { var target = move.getAttribute("data-move") === "next" ? document.getElementById("queueNext") : document.getElementById("queueLater"); target.appendChild(move.closest("[data-article]")); move.setAttribute("data-move", move.getAttribute("data-move") === "next" ? "later" : "next"); move.textContent = move.getAttribute("data-move") === "next" ? "Move to next" : "Move later"; } if (complete) { var article = complete.closest("[data-article]"); document.getElementById("queueArchive").textContent = "Completed: " + article.querySelector("h3").textContent; article.remove(); } syncQueue(); }); syncQueue();