Compare commits

...

4 Commits

Author SHA1 Message Date
Levi Neuwirth c2e8737c6e auto: 2026-04-21T01:22:39Z 2026-04-20 21:22:39 -04:00
Levi Neuwirth daa0ea4c3c library: fine-press typography + muted-warm palette
Scoped warm accent tokens (--library-accent and friends) defined at
:root inside library.css — page-scoped since the file only loads on
/library.html and /search.html. Section headings become Spectral
small-caps chapter markers at 1.2rem in the accent color, so the
ornament span inherits it via currentColor. Divider and "more on
this shelf" link pick up the muted variant. The leading blockquote
gets an epigraph treatment: narrower measure, italic, warm intro
ink, with the attribution line dropping to the accent-muted tone.
Card-level refinements (oldstyle figures on dates, small-caps on
item-kind) scoped via .library-section so /new.html and tag pages
retain their lining-figure UI treatment.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-20 21:21:47 -04:00
Levi Neuwirth 0221603766 library: portal ornaments + inter-shelf divider
Each shelf gets a dingbat keyed by portal slug: laurel (research),
quill (nonfiction), open book (fiction), lyre (poetry), plus the
existing clef / ai / tech / trefoil glyphs for the remaining four.
Rendered via mask-image with currentColor so a single SVG per
portal inherits whatever color its heading carries. Between rendered
shelves, a centered fleuron flanked by thin rules (library-divider.svg)
sits via CSS adjacent-sibling so hidden sections leave no orphan
dividers. The template swaps its Unicode placeholder for a
data-ornament span, wires a '\$library-intro\$' slot above the shelves,
and renders a "More on this shelf →" link when has-more gates fire.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-20 21:20:35 -04:00
Levi Neuwirth c877d8c9c6 library: sidecar-driven curation plumbing
Adds the library infrastructure without visible change to the rendered
page: a 'featured:' list in each portal's tag-meta sidecar drives shelf
curation (up to 5, default cap 4, recency fills the rest), a content/
library.md snapshot feeds a '\$library-intro\$' slot for a leading
blockquote, and '\$<slug>-has-more\$' gates expose whether the unfiltered
portal overflows the shelf. Items are now loaded once and partitioned
by primary portal rather than scanned per-section.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-20 21:19:36 -04:00
11 changed files with 439 additions and 47 deletions

View File

@ -2,8 +2,8 @@
{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE OverloadedStrings #-}
module Site (rules) where module Site (rules) where
import Control.Monad (filterM, forM, forM_, when) import Control.Monad (forM, forM_, when)
import Data.Char (toUpper) import Data.Char (isSpace, toUpper)
import Data.List (groupBy, isPrefixOf, sort, sortBy) import Data.List (groupBy, isPrefixOf, sort, sortBy)
import Data.Map.Strict (Map) import Data.Map.Strict (Map)
import Data.Maybe (catMaybes, fromMaybe, listToMaybe) import Data.Maybe (catMaybes, fromMaybe, listToMaybe)
@ -55,6 +55,20 @@ homePortals =
, ("Miscellany", "miscellany") , ("Miscellany", "miscellany")
] ]
-- | Default number of cards shown per library shelf. The sidecar
-- 'featured:' list may push this up to 'libraryShelfMax'.
libraryShelfCap :: Int
libraryShelfCap = 4
-- | Hard ceiling on cards per shelf, regardless of sidecar length.
libraryShelfMax :: Int
libraryShelfMax = 5
-- | Optional prose intro lifted into @$library-intro$@ on the library
-- page. Matched but not routed; consumed via the @"body"@ snapshot.
libraryIntroId :: Identifier
libraryIntroId = fromFilePath "content/library.md"
-- Poems inside collection subdirectories, excluding their index pages. -- Poems inside collection subdirectories, excluding their index pages.
collectionPoems :: Pattern collectionPoems :: Pattern
collectionPoems = "content/poetry/*/*.md" .&&. complement "content/poetry/*/index.md" collectionPoems = "content/poetry/*/*.md" .&&. complement "content/poetry/*/index.md"
@ -257,7 +271,8 @@ rules = do
match ("content/*.md" match ("content/*.md"
.&&. complement "content/index.md" .&&. complement "content/index.md"
.&&. complement "content/commonplace.md" .&&. complement "content/commonplace.md"
.&&. complement "content/colophon.md") $ do .&&. complement "content/colophon.md"
.&&. complement "content/library.md") $ do
route $ gsubRoute "content/" (const "") route $ gsubRoute "content/" (const "")
`composeRoutes` setExtension "html" `composeRoutes` setExtension "html"
compile $ pageCompiler compile $ pageCompiler
@ -457,6 +472,13 @@ rules = do
>>= loadAndApplyTemplate "templates/default.html" ctx >>= loadAndApplyTemplate "templates/default.html" ctx
>>= relativizeUrls >>= relativizeUrls
-- ---------------------------------------------------------------------------
-- Library intro — optional prose block (typically a blockquote) lifted
-- into @$library-intro$@ at the top of /library.html. Matched but not
-- routed; the body snapshot is consumed by the library rule below.
-- ---------------------------------------------------------------------------
match "content/library.md" $ compile sidecarCompiler
-- --------------------------------------------------------------------------- -- ---------------------------------------------------------------------------
-- Library — portal-grouped view over the /new.html dataset, deduplicated -- Library — portal-grouped view over the /new.html dataset, deduplicated
-- by primary portal. An item's primary portal is the top segment of the -- by primary portal. An item's primary portal is the top segment of the
@ -465,14 +487,27 @@ rules = do
-- silently dropped from the library (they remain on /new.html and on any -- silently dropped from the library (they remain on /new.html and on any
-- tag pages their frontmatter produces). -- tag pages their frontmatter produces).
-- --
-- Each shelf is capped at 'libraryShelfCap' items by default. A portal's
-- tag-meta sidecar may carry a 'featured:' list of content-rooted paths
-- (e.g. @content/essays/foo.md@); featured items are placed first, in
-- listed order, and the remainder is filled by recency up to a hard
-- ceiling of 'libraryShelfMax'. Featured paths that don't resolve to an
-- item in the portal (wrong primary portal, or typo) are silently
-- dropped. When the unfiltered portal has more items than the shelf
-- shows, @$<slug>-has-more$@ is exposed so the template can render a
-- "More on this shelf →" affordance linking to the portal's tag page.
--
-- Each card uses the shared item-card partial, with cross-portal filings -- Each card uses the shared item-card partial, with cross-portal filings
-- rendered in the card's tag footer via 'tagLinksFieldExcludingScope', -- rendered in the card's tag footer via 'tagLinksFieldExcludingTopSegment',
-- scoped to the section's portal so the portal's own tag is suppressed. -- scoped to the section's portal so the portal's own tag is suppressed.
-- --------------------------------------------------------------------------- -- ---------------------------------------------------------------------------
create ["library.html"] $ do create ["library.html"] $ do
route idRoute route idRoute
compile $ do compile $ do
let knownPortals = map snd homePortals sidecarIds <- getMatches ("content/tag-meta/*.md"
.||. "content/tag-meta/**/*.md")
let sidecarSet = Set.fromList sidecarIds
knownPortals = map snd homePortals
-- Top segment of the first tag that names a known portal. -- Top segment of the first tag that names a known portal.
-- Nothing when no tag matches — item is excluded from library. -- Nothing when no tag matches — item is excluded from library.
@ -499,31 +534,80 @@ rules = do
<> constField "full-abstract" "true" <> constField "full-abstract" "true"
<> essayCtx <> essayCtx
portalList name p = listField name (portalItemCtx p) $ do -- Load every content item once, then partition by primary portal
essays <- loadAll (allEssays .&&. hasNoVersion) -- so each shelf draws from a pre-filtered list rather than
posts <- loadAll ("content/blog/*.md" .&&. hasNoVersion) -- re-scanning the whole corpus eight times.
fiction <- loadAll ("content/fiction/*.md" .&&. hasNoVersion) essays <- loadAll (allEssays .&&. hasNoVersion)
poetry <- loadAll (allPoetry .&&. hasNoVersion) posts <- loadAll ("content/blog/*.md" .&&. hasNoVersion)
music <- loadAll ("content/music/*/index.md" .&&. hasNoVersion) fiction <- loadAll ("content/fiction/*.md" .&&. hasNoVersion)
let allItems = essays ++ posts ++ fiction ++ poetry ++ music poetry <- loadAll (allPoetry .&&. hasNoVersion)
filtered <- filterM (\i -> (== Just p) <$> primaryPortalOf i) allItems music <- loadAll ("content/music/*/index.md" .&&. hasNoVersion)
sorted <- recentFirstByDisplay filtered let allContent = essays ++ posts ++ fiction ++ poetry ++ music
-- noResult here makes the field absent, so the template's :: [Item String]
-- $if(p-entries)$ gate evaluates false and the section is tagged <- mapM (\i -> (,i) <$> primaryPortalOf i) allContent
-- omitted entirely (rather than rendering an empty <ul>). let itemsByPortal :: Map.Map String [Item String]
if null sorted itemsByPortal =
then noResult ("no items in portal " ++ p) Map.fromListWith (++) [(p, [i]) | (Just p, i) <- tagged]
else return sorted
-- Section order matches homePortals — single ordering authority. -- Eager snapshot load registers the library-intro dependency
let ctx = portalList "research-entries" "research" -- unconditionally, so a first-populate of content/library.md
<> portalList "nonfiction-entries" "nonfiction" -- re-renders the library page even when the gate was previously
<> portalList "fiction-entries" "fiction" -- false (see 'sidecarContext' in Tags.hs for the same pattern).
<> portalList "poetry-entries" "poetry" _ <- loadSnapshot libraryIntroId "body" :: Compiler (Item String)
<> portalList "music-entries" "music" let libraryIntroFld = field "library-intro" $ \_ -> do
<> portalList "ai-entries" "ai" html <- itemBody <$> loadSnapshot libraryIntroId "body"
<> portalList "tech-entries" "tech" if all isSpace html
<> portalList "miscellany-entries" "miscellany" then noResult "empty library intro"
else return html
-- One shelf's context contribution: the @<slug>-entries@
-- listField (or absent via noResult when the shelf is
-- empty) plus an optional @<slug>-has-more@ gate.
portalSection p = do
let portalItems = fromMaybe [] (Map.lookup p itemsByPortal)
sorted <- recentFirstByDisplay portalItems
featuredPaths <-
if sidecarIdentifier p `Set.member` sidecarSet
then do
meta <- getMetadata (sidecarIdentifier p)
return (fromMaybe [] (lookupStringList "featured" meta))
else return []
let portalIdSet =
Set.fromList (map itemIdentifier portalItems)
featuredItems =
[ i
| path <- featuredPaths
, let ident = fromFilePath path
, ident `Set.member` portalIdSet
, Just i <- [listToMaybe
(filter ((== ident) . itemIdentifier) portalItems)]
]
cap = min libraryShelfMax
(max libraryShelfCap (length featuredItems))
featuredIds =
Set.fromList (map itemIdentifier featuredItems)
rest = filter (\i -> not (itemIdentifier i `Set.member` featuredIds)) sorted
merged = take cap (featuredItems ++ rest)
let entriesFld =
listField (p ++ "-entries") (portalItemCtx p)
(if null merged
then noResult ("no items in portal " ++ p)
else return merged)
hasMoreFld
| length portalItems > length merged =
constField (p ++ "-has-more") "true"
| otherwise = mempty
return (entriesFld <> hasMoreFld)
-- Section order follows homePortals — single ordering authority.
sections <- mapM portalSection knownPortals
let ctx = mconcat sections
<> libraryIntroFld
<> constField "title" "Library" <> constField "title" "Library"
<> constField "library" "true" <> constField "library" "true"
<> siteCtx <> siteCtx

View File

@ -0,0 +1,23 @@
---
title: "The Specification Dilemma"
date: 2026-04-20 # required; used for ordering, feed, and display
abstract: > # optional; shown in the metadata block and link previews
We should not consider AI entities as mere tools, though they may be the raw foundation from which exceptional tools for thought are constructed to augment the human mind. Rather, we should consider AI as the ultimate distillation and consolidation of humanity's achievements - the ultimate progeny of our civilization.
tags: # optional; see Tags section
- ai
- tech
# Epistemic profile — all optional; the entire section is hidden unless `status` is set
status: "Draft" # Draft | Working model | Durable | Refined | Superseded | Deprecated
confidence: 100 # 0100 integer (%)
importance: 5 # 15 integer (rendered as filled/empty dots ●●●○○)
evidence: 1 # 15 integer (same)
scope: civilizational # personal | local | average | broad | civilizational
novelty: idiosyncratic # conventional | moderate | idiosyncratic | innovative
practicality: moderate # abstract | low | moderate | high | exceptional
confidence-history: # list of integers; trend arrow derived from last two entries
---
TODO: block quote about Richard Feynman and the beauty of science - idea "it's more beautiful this way"
I have often felt there has been a loss of wonder from the world, and I lament this fact.

View File

@ -0,0 +1,27 @@
---
title: "The Specification Dilemma"
date: 2026-04-20 # required; used for ordering, feed, and display
abstract: > # optional; shown in the metadata block and link previews
As we approach AI, the increase in the ability of Artificial Intelligence models to infer a robust specification from a sparse prompt will lead to a devastating trend of homogeneity. We argue that this is the primary concern regarding the interaction of AI and human intelligence, rather than blanket claims that "AI reduces human cognitive ability."
tags: # optional; see Tags section
- ai
- tech
# Epistemic profile — all optional; the entire section is hidden unless `status` is set
status: "Draft" # Draft | Working model | Durable | Refined | Superseded | Deprecated
confidence: 85 # 0100 integer (%)
importance: 5 # 15 integer (rendered as filled/empty dots ●●●○○)
evidence: 3 # 15 integer (same)
scope: civilizational # personal | local | average | broad | civilizational
novelty: idiosyncratic # conventional | moderate | idiosyncratic | innovative
practicality: high # abstract | low | moderate | high | exceptional
confidence-history: # list of integers; trend arrow derived from last two entries
---
There are at least two distinct ways to reduce the search space over which AGI will have to operate. The first involves a harmonious interaction of agent and human, not transactional in origin, not fully autonomous nor fully human-driven, but rather collaborative in nature - the agent augments the capacity of the human, just as any other good tool for thought does, by working within the scope of something well specified and ideated upon. This is not to say that the agent cannot have a place in such planning, but rather that the human is ultimately the driver of the actions and tasks, defining the scope of what is to be done in as much detail as possible without being the one to actually do it.
The second is a starkly different picture: the human, who only has a vague idea of their own intentions and has not thought over this much, jumps straight into the work of creating via the agent, without thought on the nature of their specification. The agent is forced to infer the majority of the details, make the majority of the decisions, and the human makes none. We may already be seeing this with [Vibe Coding](https://en.wikipedia.org/vibe-coding), but as we continue scaling to AGI, I forsee it happening widely across all sorts of domains^[Some have argued of late that ["only the humanities will survive"](TODO: find source), but I am not so optimistic. If AGI does interact with us in the latter reductive manner that I describe here, then the humanities will be stripped of anything that actually makes them human, at least for the majority of participants.].
These two represent diverging definitions of *intelligence*, both for the models and for their users, or, if you prefer, their collaborators. The first is a definition of intelligence that depends both on what one has the capacity to specify and what one has the capacity to see through. The latter depends wholly on what one has the capacity to see through, and places even more emphasize on this metric than the first, for the amount of recalibration and prompt adjustment necessary to build a specification continuously throughout the duration of a task is always greater than paying the upfront cost of developing a strong specification from the onset. [We the programmers have known this for years](https://en.wikipedia.org/wiki/Hofstadter%27s_law). The first future is chiefly preferable, and the second, which seems to be the unfortunate reality we are racing towards, is not only a realization of the worst affect that AI could have on our cognition, but may also unnecessarily constrain the breadth of intelligence that AGI can achieve.
## What does "Autonomy" really mean?

6
content/library.md Normal file
View File

@ -0,0 +1,6 @@
> *El universo (que otros llaman la Biblioteca) se compone de un número indefinido, y tal vez infinito, de galerías hexagonales, con vastos pozos de ventilación en el medio, cercados por barandas bajísimas.*
>
> [*Ficciones*](https://es.wikipedia.org/wiki/Ficciones) — Jorge Luis Borges (1941)
# TODO: add language flagging within markdown source, needs to propagate to Ozymandias

View File

@ -1,6 +1,35 @@
/* library.css Library + Bibliography page components, plus the /* library.css Library + Bibliography page components, plus the
epistemic-filter UI that now lives on /search.html. */ epistemic-filter UI that now lives on /search.html. */
/* ============================================================
LIBRARY PALETTE scoped warm "candlelight" accent
Only loaded on /library.html (via $if(library)$) and /search.html,
so defining at :root here is effectively page-scoped. Consumed by
section headings, the divider, the intro blockquote, and the
"more on this shelf" link to give the library page a fine-press
feel without touching global colors.
============================================================ */
:root {
--library-accent: #524638; /* muted warm-gray — reads as "warm" only if you look */
--library-accent-muted: #7c7164; /* dusty taupe */
--library-intro-ink: #3c3328;
}
[data-theme="dark"] {
--library-accent: #b5a890; /* soft oat */
--library-accent-muted: #897f6e;
--library-intro-ink: #c8beac;
}
@media (prefers-color-scheme: dark) {
:root:not([data-theme="light"]) {
--library-accent: #b5a890;
--library-accent-muted: #897f6e;
--library-intro-ink: #c8beac;
}
}
/* ============================================================ /* ============================================================
FILTER UI FILTER UI
Originally the Library's sort+filter panel; the sort panel Originally the Library's sort+filter panel; the sort panel
@ -150,27 +179,188 @@
============================================================ */ ============================================================ */
.library-section { .library-section {
margin-bottom: 2.5rem; margin-bottom: 3rem;
} }
/* Section heading fine-press chapter marker. Spectral small-caps in
walnut ink, letterspaced for a traditional printer's-ornament look.
The ornament span inherits currentColor and picks up the same accent. */
.library-section h2 { .library-section h2 {
font-family: var(--font-sans); font-family: var(--font-serif);
font-size: 0.78rem; font-size: 1.2rem;
font-variant: small-caps; font-variant: all-small-caps;
letter-spacing: 0.08em; font-feature-settings: "smcp" 1;
color: var(--text-muted); letter-spacing: 0.09em;
text-transform: lowercase; color: var(--library-accent);
font-weight: 500; text-transform: none;
margin-bottom: 0.5rem; font-weight: 400;
margin: 0 0 0.9rem 0;
}
/* Per-shelf ornament sitting before the heading text. SVGs in
/images/dingbats/ painted via mask-image so they inherit
currentColor ( the same muted tone as the heading). */
.library-section-ornament {
display: inline-block;
width: 1em;
height: 1em;
margin-right: 0.5em;
background-color: currentColor;
mask-repeat: no-repeat;
mask-position: center;
mask-size: contain;
-webkit-mask-repeat: no-repeat;
-webkit-mask-position: center;
-webkit-mask-size: contain;
vertical-align: -0.12em;
}
.library-section-ornament[data-ornament="research"] {
mask-image: url('/images/dingbats/research.svg');
-webkit-mask-image: url('/images/dingbats/research.svg');
}
.library-section-ornament[data-ornament="nonfiction"] {
mask-image: url('/images/dingbats/nonfiction.svg');
-webkit-mask-image: url('/images/dingbats/nonfiction.svg');
}
.library-section-ornament[data-ornament="fiction"] {
mask-image: url('/images/dingbats/fiction.svg');
-webkit-mask-image: url('/images/dingbats/fiction.svg');
}
.library-section-ornament[data-ornament="poetry"] {
mask-image: url('/images/dingbats/poetry.svg');
-webkit-mask-image: url('/images/dingbats/poetry.svg');
}
.library-section-ornament[data-ornament="music"] {
mask-image: url('/images/dingbats/clef.svg');
-webkit-mask-image: url('/images/dingbats/clef.svg');
}
.library-section-ornament[data-ornament="ai"] {
mask-image: url('/images/dingbats/ai.svg');
-webkit-mask-image: url('/images/dingbats/ai.svg');
}
.library-section-ornament[data-ornament="tech"] {
mask-image: url('/images/dingbats/tech.svg');
-webkit-mask-image: url('/images/dingbats/tech.svg');
}
.library-section-ornament[data-ornament="miscellany"] {
mask-image: url('/images/dingbats/trefoil.svg');
-webkit-mask-image: url('/images/dingbats/trefoil.svg');
}
/* Inter-shelf divider. Adjacent-sibling selector renders between
actually-emitted sections a section hidden by its $if$ gate
leaves no orphan divider because it never hits the DOM. */
.library-section + .library-section::before {
content: "";
display: block;
width: 240px;
max-width: 60%;
height: 24px;
margin: 2.5rem auto;
color: var(--library-accent-muted);
background-color: currentColor;
mask-image: url('/images/dingbats/library-divider.svg');
-webkit-mask-image: url('/images/dingbats/library-divider.svg');
mask-repeat: no-repeat;
mask-position: center;
mask-size: contain;
-webkit-mask-repeat: no-repeat;
-webkit-mask-position: center;
-webkit-mask-size: contain;
}
/* "More on this shelf →" link, shown when the portal has more
items than the shelf's cap. Right-aligned, italic, subdued. */
.library-more {
text-align: right;
font-family: var(--font-serif);
font-style: italic;
font-size: 0.95rem;
color: var(--library-accent-muted);
margin: 0.75rem 0 0;
}
.library-more a {
color: inherit;
text-decoration: none;
border-bottom: 1px solid transparent;
transition: border-color var(--transition-fast), color var(--transition-fast);
}
.library-more a:hover {
color: var(--library-accent);
border-bottom-color: var(--library-accent-muted);
}
/* Leading blockquote above the shelves, lifted from content/library.md.
Set as an epigraph: narrower measure, italic serif, warm ink, no
left-bar decoration. */
.library-intro {
max-width: 32rem;
margin: 1.5rem 0 2.75rem;
font-family: var(--font-serif);
font-style: italic;
font-size: 0.95rem;
line-height: 1.55;
color: var(--library-intro-ink);
}
.library-intro blockquote {
border: none;
margin: 0;
padding: 0;
}
.library-intro blockquote p {
margin: 0 0 0.4rem 0;
}
.library-intro blockquote p:last-of-type {
margin: 0;
font-style: normal;
font-size: 0.9rem;
color: var(--library-accent-muted);
}
.library-intro a {
color: inherit;
text-decoration: underline;
text-decoration-color: var(--library-accent-muted);
text-decoration-thickness: 0.05em;
text-underline-offset: 0.2em;
}
.library-intro a:hover {
text-decoration-color: var(--library-accent);
}
/* Card-level typography refinements scoped to the library page.
Oldstyle figures on dates read as book-typesetting rather than
tabular UI; small-caps on the item-kind badge keeps it in the
same fine-press register as the section heading. Scoped via
`.library-section` so /new.html and tag pages keep their
current treatment (lining figures, uppercase badges). */
.library-section .item-card-date {
font-variant-numeric: oldstyle-nums proportional-nums;
font-feature-settings: "onum" 1, "pnum" 1;
}
.library-section .item-card-kind {
font-variant: all-small-caps;
font-feature-settings: "smcp" 1;
letter-spacing: 0.06em;
} }
.library-section h2 a { .library-section h2 a {
color: inherit; color: inherit;
text-decoration: none; text-decoration: none;
border-bottom: 1px solid transparent;
transition: border-color var(--transition-fast);
} }
.library-section h2 a:hover { .library-section h2 a:hover {
color: var(--text); border-bottom-color: var(--library-accent-muted);
} }
/* ============================================================ /* ============================================================

View File

@ -0,0 +1,5 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor">
<path d="M3 6 L 11.5 5 L 11.5 20 L 3 19 Z"/>
<path d="M21 6 L 12.5 5 L 12.5 20 L 21 19 Z"/>
<path d="M11.5 5 L 12.5 5 L 12.5 20 L 11.5 20 Z" fill-opacity="0.55"/>
</svg>

After

Width:  |  Height:  |  Size: 257 B

View File

@ -0,0 +1,7 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 240 24" fill="currentColor">
<rect x="20" y="11.5" width="80" height="1"/>
<circle cx="106" cy="12" r="1.5"/>
<path fill-rule="evenodd" d="M120 4 L 126 12 L 120 20 L 114 12 Z M120 8.5 L 123 12 L 120 15.5 L 117 12 Z"/>
<circle cx="134" cy="12" r="1.5"/>
<rect x="140" y="11.5" width="80" height="1"/>
</svg>

After

Width:  |  Height:  |  Size: 370 B

View File

@ -0,0 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor">
<path d="M20 2 L 22 4 L 10 16 L 7 19 L 4 20 L 5 17 L 8 14 L 18 4 Z"/>
<path d="M15 7 L 13 7 L 14 5 Z"/>
<path d="M18 4 L 16 4 L 17 2 Z"/>
<path d="M12 10 L 10 10 L 11 8 Z"/>
</svg>

After

Width:  |  Height:  |  Size: 270 B

View File

@ -0,0 +1,8 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor">
<path d="M5 4 C 3 9, 3 16, 6 20 L 8 20 C 5 16, 5 9, 7 5 Z"/>
<path d="M19 4 C 21 9, 21 16, 18 20 L 16 20 C 19 16, 19 9, 17 5 Z"/>
<rect x="4.5" y="3" width="15" height="2" rx="0.8"/>
<rect x="9.8" y="5" width="0.7" height="15"/>
<rect x="11.65" y="5" width="0.7" height="15"/>
<rect x="13.5" y="5" width="0.7" height="15"/>
</svg>

After

Width:  |  Height:  |  Size: 424 B

View File

@ -0,0 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor">
<path d="M6 3 C 4 9, 5 17, 11 21 L 11 19 C 7 16, 6 10, 7 5 Z"/>
<path d="M18 3 C 20 9, 19 17, 13 21 L 13 19 C 17 16, 18 10, 17 5 Z"/>
<rect x="9.5" y="20" width="5" height="1.5" rx="0.6"/>
<circle cx="12" cy="12" r="1"/>
</svg>

After

Width:  |  Height:  |  Size: 317 B

View File

@ -1,95 +1,125 @@
<div id="markdownBody"> <div id="markdownBody">
<h1 class="page-title">Library</h1> <h1 class="page-title">Library</h1>
$if(library-intro)$
<div class="library-intro">
$library-intro$
</div>
$endif$
<nav class="library-see-also" aria-label="See also"> <nav class="library-see-also" aria-label="See also">
<a href="/new.html">New</a><span class="library-see-also-sep" aria-hidden="true">·</span><a href="/commonplace.html">Commonplace</a><span class="library-see-also-sep" aria-hidden="true">·</span><a href="/colophon.html">Colophon</a><span class="library-see-also-sep" aria-hidden="true">·</span><a href="/bibliography/">Bibliography</a> <a href="/new.html">New</a><span class="library-see-also-sep" aria-hidden="true">·</span><a href="/commonplace.html">Commonplace</a><span class="library-see-also-sep" aria-hidden="true">·</span><a href="/colophon.html">Colophon</a><span class="library-see-also-sep" aria-hidden="true">·</span><a href="/bibliography/">Bibliography</a>
</nav> </nav>
$if(research-entries)$ $if(research-entries)$
<section class="library-section"> <section class="library-section">
<h2 id="research"><a href="/research/">Research</a></h2> <h2 id="research"><span class="library-section-ornament" data-ornament="research" aria-hidden="true"></span><a href="/research/">Research</a></h2>
<ul class="item-card-list"> <ul class="item-card-list">
$for(research-entries)$ $for(research-entries)$
$partial("templates/partials/item-card.html")$ $partial("templates/partials/item-card.html")$
$endfor$ $endfor$
</ul> </ul>
$if(research-has-more)$
<p class="library-more"><a href="/research/">More on this shelf &rarr;</a></p>
$endif$
</section> </section>
$endif$ $endif$
$if(nonfiction-entries)$ $if(nonfiction-entries)$
<section class="library-section"> <section class="library-section">
<h2 id="nonfiction"><a href="/nonfiction/">Nonfiction</a></h2> <h2 id="nonfiction"><span class="library-section-ornament" data-ornament="nonfiction" aria-hidden="true"></span><a href="/nonfiction/">Nonfiction</a></h2>
<ul class="item-card-list"> <ul class="item-card-list">
$for(nonfiction-entries)$ $for(nonfiction-entries)$
$partial("templates/partials/item-card.html")$ $partial("templates/partials/item-card.html")$
$endfor$ $endfor$
</ul> </ul>
$if(nonfiction-has-more)$
<p class="library-more"><a href="/nonfiction/">More on this shelf &rarr;</a></p>
$endif$
</section> </section>
$endif$ $endif$
$if(fiction-entries)$ $if(fiction-entries)$
<section class="library-section"> <section class="library-section">
<h2 id="fiction"><a href="/fiction/">Fiction</a></h2> <h2 id="fiction"><span class="library-section-ornament" data-ornament="fiction" aria-hidden="true"></span><a href="/fiction/">Fiction</a></h2>
<ul class="item-card-list"> <ul class="item-card-list">
$for(fiction-entries)$ $for(fiction-entries)$
$partial("templates/partials/item-card.html")$ $partial("templates/partials/item-card.html")$
$endfor$ $endfor$
</ul> </ul>
$if(fiction-has-more)$
<p class="library-more"><a href="/fiction/">More on this shelf &rarr;</a></p>
$endif$
</section> </section>
$endif$ $endif$
$if(poetry-entries)$ $if(poetry-entries)$
<section class="library-section"> <section class="library-section">
<h2 id="poetry"><a href="/poetry/">Poetry</a></h2> <h2 id="poetry"><span class="library-section-ornament" data-ornament="poetry" aria-hidden="true"></span><a href="/poetry/">Poetry</a></h2>
<ul class="item-card-list"> <ul class="item-card-list">
$for(poetry-entries)$ $for(poetry-entries)$
$partial("templates/partials/item-card.html")$ $partial("templates/partials/item-card.html")$
$endfor$ $endfor$
</ul> </ul>
$if(poetry-has-more)$
<p class="library-more"><a href="/poetry/">More on this shelf &rarr;</a></p>
$endif$
</section> </section>
$endif$ $endif$
$if(music-entries)$ $if(music-entries)$
<section class="library-section"> <section class="library-section">
<h2 id="music"><a href="/music/">Music</a></h2> <h2 id="music"><span class="library-section-ornament" data-ornament="music" aria-hidden="true"></span><a href="/music/">Music</a></h2>
<ul class="item-card-list"> <ul class="item-card-list">
$for(music-entries)$ $for(music-entries)$
$partial("templates/partials/item-card.html")$ $partial("templates/partials/item-card.html")$
$endfor$ $endfor$
</ul> </ul>
$if(music-has-more)$
<p class="library-more"><a href="/music/">More on this shelf &rarr;</a></p>
$endif$
</section> </section>
$endif$ $endif$
$if(ai-entries)$ $if(ai-entries)$
<section class="library-section"> <section class="library-section">
<h2 id="ai"><a href="/ai/">AI</a></h2> <h2 id="ai"><span class="library-section-ornament" data-ornament="ai" aria-hidden="true"></span><a href="/ai/">AI</a></h2>
<ul class="item-card-list"> <ul class="item-card-list">
$for(ai-entries)$ $for(ai-entries)$
$partial("templates/partials/item-card.html")$ $partial("templates/partials/item-card.html")$
$endfor$ $endfor$
</ul> </ul>
$if(ai-has-more)$
<p class="library-more"><a href="/ai/">More on this shelf &rarr;</a></p>
$endif$
</section> </section>
$endif$ $endif$
$if(tech-entries)$ $if(tech-entries)$
<section class="library-section"> <section class="library-section">
<h2 id="tech"><a href="/tech/">Tech</a></h2> <h2 id="tech"><span class="library-section-ornament" data-ornament="tech" aria-hidden="true"></span><a href="/tech/">Tech</a></h2>
<ul class="item-card-list"> <ul class="item-card-list">
$for(tech-entries)$ $for(tech-entries)$
$partial("templates/partials/item-card.html")$ $partial("templates/partials/item-card.html")$
$endfor$ $endfor$
</ul> </ul>
$if(tech-has-more)$
<p class="library-more"><a href="/tech/">More on this shelf &rarr;</a></p>
$endif$
</section> </section>
$endif$ $endif$
$if(miscellany-entries)$ $if(miscellany-entries)$
<section class="library-section"> <section class="library-section">
<h2 id="miscellany"><a href="/miscellany/">Miscellany</a></h2> <h2 id="miscellany"><span class="library-section-ornament" data-ornament="miscellany" aria-hidden="true"></span><a href="/miscellany/">Miscellany</a></h2>
<ul class="item-card-list"> <ul class="item-card-list">
$for(miscellany-entries)$ $for(miscellany-entries)$
$partial("templates/partials/item-card.html")$ $partial("templates/partials/item-card.html")$
$endfor$ $endfor$
</ul> </ul>
$if(miscellany-has-more)$
<p class="library-more"><a href="/miscellany/">More on this shelf &rarr;</a></p>
$endif$
</section> </section>
$endif$ $endif$