5.5 KiB
5.5 KiB
Spine — Pico CSS styling
Styles the index page using Pico CSS v2 via CDN,
restructuring HTML to use Pico-native semantic elements and adding a small
custom <style> block for the few things Pico doesn't cover.
CSS strategy
- Pico CSS v2 loaded from CDN:
https://cdn.jsdelivr.net/npm/@picocss/pico@2/css/pico.min.css - No build step. No local CSS file. No Sass/PostCSS.
- Light/dark theme auto-switches via
prefers-color-scheme(Pico default). - Custom styles in a single inline
<style>block inside<head>. - No Tabler Icons. Format glyphs use emoji instead.
HTML restructure
Pico styles semantic elements. The current <div>-heavy output is rewritten
to use Pico-native elements. Only spine- prefixed classes remain for
layout pieces Pico doesn't provide.
| Current element | New element | Purpose |
|---|---|---|
<div class="frame"> |
<article> |
Card container (Pico styles borders/padding) |
<div class="titlebar"> |
<header> inside <article> |
Title bar with book count |
<div class="group">WANT (3)</div> |
<hgroup><h2>WANT</h2><small>3</small></hgroup> |
Group header with count |
<div class="row"> |
<div class="spine-row"> |
Book row (flex, Pico has no horizontal list) |
<div class="detail"> |
<blockquote class="spine-detail"> |
Expanded notes section |
<span class="pill want"> |
<mark class="want">want</mark> |
Status badge (colored per status) |
<span class="glyph"> |
<span class="spine-glyph"> |
Format emoji |
<span class="title"> |
<span class="spine-title"> |
Book title + author |
<span class="muted"> |
<small> |
Author name (Pico styles <small> as muted) |
<span class="tags"> |
<small> with tag text |
Category tags |
<span class="trail"> |
<span class="spine-trail"> |
Recommendation trail |
Custom CSS
In an inline <style> block in <head>:
.spine-row {
display: flex; align-items: center; gap: 0.75rem;
padding: 0.4rem 0;
border-bottom: 1px solid var(--pico-muted-border-color);
}
.spine-row:last-child { border-bottom: none; }
.spine-selected { background: var(--pico-secondary-background); }
.spine-glyph { width: 1.5rem; text-align: center; flex-shrink: 0; }
.spine-title { flex: 1; min-width: 0; }
.spine-trail { font-size: 0.85em; color: var(--pico-muted-color); }
.spine-detail {
margin: 0 0 0 2rem;
border-left: 2px solid var(--pico-primary);
}
.spine-detail p { margin-bottom: 0.3rem; }
.spine-detail footer { margin-top: 0.5rem; }
/* Status pill colors */
mark.want { background: var(--pico-mark-background); color: var(--pico-mark-color); }
mark.reading { background: #faeeda; color: #854f0b; }
mark.read { background: #e1f5ee; color: #085041; }
mark.abandoned { background: var(--pico-muted-color); color: var(--pico-background-color); }
/* Pico-specific overrides */
article { margin-bottom: 0; }
article header { padding-bottom: 0.5rem; margin-bottom: 0.5rem; }
Format glyphs
Emoji per format, empty string if unset:
| Format | Glyph |
|---|---|
hardcover |
📖 |
ebook |
📱 |
audiobook |
🎧 |
nil / unset |
(empty) |
Full page shell
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Spine</title>
<link rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/@picocss/pico@2/css/pico.min.css">
<style>…custom styles…</style>
</head>
<body>
<main class="container">
<article>
<header>
<strong>spine</strong>
<small>N books · M reading</small>
</header>
…groups and rows…
</article>
</main>
</body>
</html>
Example output (Use of Weapons, expanded)
<hgroup><h2>READING</h2><small>1</small></hgroup>
<div class="spine-row spine-selected">
<span class="spine-glyph">🎧</span>
<span class="spine-title">Use of Weapons <small>Iain M. Banks</small></span>
<small>:scifi: :literary:</small>
<span class="spine-trail">Priya: If you liked Player of Games, this one will wreck you</span>
<mark class="reading">reading</mark>
<blockquote class="spine-detail">
<p><small>[2026-03-02]</small> The two-track structure is doing something I can't name yet.</p>
<p><small>[2026-03-07]</small> Zakalwe's competence reads as a wound.</p>
<p><small>[2026-03-09]</small> The chapter numbering. Oh.</p>
<footer>Format: audiobook · ISBN: 978-0316029193 · Added: [2026-02-20]</footer>
</blockquote>
</div>
Empty state
<article>
<header><strong>spine</strong></header>
<p>No books yet.</p>
</article>
Files changed
spine.el—spine-render-indexandspine-render-empty-staterewritten to emit Pico-structured HTML with inline CSS
No new files. No new dependencies beyond the CDN <link>.
Out of scope
- JavaScript interactivity
- Cover image display
- Write endpoints
- Per-note format
?id=selection without page reload (full page reload only)
Acceptance
- Page renders with Pico CSS applied (fonts, spacing, colors match Pico defaults)
- Light/dark mode switches with OS preference
- Groups appear in order: WANT, READING, READ — zero-book groups omitted
?id=...expands the matching book's detail with reading notes- Status pills have distinct colors per state
- Format shown as emoji glyph
- Recommendation trail shown when
REC_BYpresent - Empty state shows "No books yet."
- No console 404s (Pico CDN resolves)
- No Tabler Icons reference in output