/* ============================================================
   README — the Oxedyne dev-shop blog
   ============================================================
   Loaded by the pages Steel renders itself: the reader at /readme
   and the authoring console at /manage. This file only themes them;
   the markup and the routing are Steel's. Tokens come from
   variables.css, so the blog wears the same dark palette as the
   front page. Oxedyne is dark only.

   Steel emits structural HTML and names no styling of its own -- an
   <h2>, not an <h2 class="...">. So the prose is styled on bare
   elements, and the surfaces around it on the classes Steel does
   name (the "aside-" family, an Elearnity heritage the prefix keeps
   whatever the site is called):

     standalone page  .aside-body (background), .aside-page (column),
                      .aside-nav (the top line), .aside-home + .aside-logo
                      (the Oxedyne mark, to the front page), .aside-back
                      (a post's way back to the index)
     the prose        .aside (the article wrapper), .aside-date,
                      .aside-read (the reading time beside the date),
                      and the bare elements inside it
     the index        .aside-index (the list), .aside-index-head,
                      .aside-index-item (each card), .aside-excerpt,
                      .aside-index-tag (the "Tagged x" line under a
                      ?tag= filter), .aside-empty
     syndication      .aside-also / .aside-also-lbl / .aside-also-link
     tags             .post-tags (the list), .tag (a pill, and the
                      span in the filtered heading)

   The console editor's own furniture (the .mc-* forms and the
   .tag-chip / .tag-palette chips) is styled by an inline stylesheet
   Steel always ships, which wins over this file, so those rules do
   not live here. This file's job is the reader, plus the palette
   tokens both surfaces read from variables.css.
   ============================================================ */

body {
	font-family: var(--font);
	background: var(--bg-primary);
	color: var(--text-primary);
	-webkit-font-smoothing: antialiased;
	line-height: 1.65;
	margin: 0;
}

/* ── Prose ─────────────────────────────────────────────────────────
   Bare elements, so the Markdown Steel renders is styled wherever it
   lands: the standalone page, and the editor's live preview. */

h1, h2, h3, h4, h5, h6 {
	color: var(--text-primary);
	line-height: 1.2;
	font-weight: 600;
	margin: 1.6em 0 0.5em;
}
h1 { font-size: clamp(28px, 3.4vw, 40px); margin-top: 0; }
h2 { font-size: clamp(22px, 2.4vw, 28px); }
h3 { font-size: clamp(19px, 1.8vw, 22px); }

p, li {
	color: var(--text-secondary);
	font-size: clamp(17px, 1.2vw, 19px);
	margin: 0 0 0.9em;
}

a {
	color: var(--accent);
	text-decoration: none;
}
a:hover { color: var(--accent-hover); text-decoration: underline; }

ul, ol { margin: 0 0 1em 1.3em; }
li { margin-bottom: 0.35em; }

blockquote {
	margin: 1.2em 0;
	padding: 0.2em 1.1em;
	border-left: 3px solid var(--accent);
	color: var(--text-muted);
}

hr {
	border: none;
	border-top: 1px solid var(--border);
	margin: 2em 0;
}

img { max-width: 100%; height: auto; border-radius: var(--radius); }

/* Code, inline and in a block. */
code, pre {
	font-family: var(--font-mono);
	font-size: 0.92em;
}
code {
	background: var(--bg-tertiary);
	border: 1px solid var(--border);
	border-radius: var(--radius-sm);
	padding: 0.12em 0.4em;
}
pre {
	background: var(--bg-secondary);
	border: 1px solid var(--border);
	border-radius: var(--radius);
	padding: 14px 16px;
	overflow-x: auto;   /* A long line scrolls itself rather than the page. */
	line-height: 1.5;
	margin: 1.2em 0;
}
pre code {
	background: none;
	border: none;
	padding: 0;
}

/* ── The standalone page ───────────────────────────────────────────
   Steel wraps the reader in <body class="aside-body"><main
   class="aside-page">, with a <nav class="aside-nav"> back to the
   index at the top. The column sits flush on the page's own dark
   ground: no tinted panel, in keeping with the front page. */
.aside-body {
	background: var(--bg-primary);
	margin: 0;
}
.aside-page {
	max-width: 44rem;
	margin: 0 auto;
	padding: clamp(28px, 5vw, 72px) clamp(20px, 5vw, 40px);
}
/* The index is two columns -- the posts and the filter beside them -- so it wants more room than a
   single post, which keeps the 44rem reading measure that keeps its lines short enough to scan. */
.aside-page:has(.aside-layout) { max-width: 60rem; }
/* The line at the top: the Oxedyne mark leading back to the front page,
   and -- on a post, not on the index -- the way back to the list beside
   it. The mark is set to the same treatment as the front page's own
   logo links, a lift and a fade, so the two pages feel like one site. */
.aside-nav {
	font-family: var(--font);
	font-size: 14px;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	margin-bottom: 2rem;
	display: flex;
	align-items: center;
	gap: clamp(16px, 3vw, 28px);
}
.aside-nav a { color: var(--text-muted); text-decoration: none; }
.aside-nav a:hover { color: var(--accent); text-decoration: underline; }
.aside-home {
	display: block;
	flex: none;
	transition: opacity 120ms ease, transform 120ms ease;
}
/* The mark is a picture, so it takes the lift the front page gives its
   marks rather than the underline a word would take. */
.aside-home:hover { opacity: 0.82; transform: translateY(-2px); text-decoration: none; }
.aside-home:focus-visible {
	outline: 2px solid var(--accent);
	outline-offset: 6px;
	border-radius: var(--radius-sm);
}
/* Sized to the nav line, not to the page: the mark is furniture here,
   where on the front page it is the subject. It stacks the flame over
   the word (aspect 1.46), so it needs more height than a wordmark
   would to leave the word legible -- below about 3rem it becomes a
   smudge under the flame. */
.aside-logo {
	display: block;
	height: clamp(2.75rem, 6vw, 3.5rem);
	width: auto;
}

/* ── The prose article ─────────────────────────────────────────────
   <article class="aside"> wraps a post; the bare-element rules above
   carry its innards. Two posts on one page are ruled apart. */
.aside {
	color: var(--text-secondary);
	padding-bottom: 2rem;
}
.aside + .aside {
	border-top: 1px solid var(--border);
	padding-top: 2rem;
}
.aside-date {
	font-family: var(--font-mono);
	font-size: 14px;
	color: var(--text-muted);
	letter-spacing: 0.06em;
	margin-bottom: 0.4em;
}
/* The reading time sits beside the date and inherits its whole look, so it needs
   only the separator that keeps the two apart. Two shapes wear it: on the index
   the two are siblings in the card's meta line, and on a post page the reading
   time sits inside the date block beside the <time>. Both are written through
   the element that must be there for a separator to be wanted at all, so a post
   with no date shows the reading time with nothing leading it. */
.aside-date + .aside-read::before,
.aside-date time + .aside-read::before {
	content: "·";
	margin: 0 0.5em;
	opacity: 0.6;
}

.aside-index-head h1 { margin-bottom: 0.6rem; }
/* The "Tagged <span class="tag">x</span>" line shown when the index
   is narrowed by ?tag=; the pill itself is the .tag rule below. */
.aside-index-tag {
	color: var(--text-muted);
	font-size: 14px;
	margin: 0 0 1.5rem;
}
.aside-empty { color: var(--text-muted); }

/* ── Two-column reader ─────────────────────────────────────────────
   On a wide screen the page is the posts on the left and the filter on
   the right, the filter a third of the width and the posts the other
   two. On a narrow screen it folds to a single column of posts, the
   filter behind a toggle above them (see the mobile block at the foot). */
.aside-layout {
	display: grid;
	grid-template-columns: 1fr;
	gap: 1.6rem;
}
@media (min-width: 768px) {
	.aside-layout {
		grid-template-columns: 2fr 1fr;
		align-items: start;
	}
	/* The posts hold the left column and the filter the right, whatever the source order --
	   the toggle comes first in the markup so a phone meets it before the stream, and explicit
	   placement keeps that from putting the filter on the left of a wide screen. */
	.aside-main { grid-column: 1; grid-row: 1; }
	.aside-side { grid-column: 2; grid-row: 1; }
}
.aside-main { min-width: 0; }
.aside-side { min-width: 0; }

/* ── Post cards (left column) ──────────────────────────────────────
   Each post is a card: a head with the facts a reader weighs and the
   title that opens it, over a fixed-height window onto the formatted
   prose that fades out at its foot, with a "Read more" beneath. A
   filled card on the page's own dark ground, so the list reads as
   raised boxes rather than rules on a flat field. */
.aside-cards {
	display: flex;
	flex-direction: column;
	gap: 1.1rem;
}
.aside-card {
	background: var(--bg-secondary);
	border: 1px solid var(--border);
	border-radius: var(--radius-lg);
	overflow: hidden;
}
.aside-card-head { padding: 0.9rem 1.1rem 0.2rem; }
.aside-card .aside-item-meta {
	display: flex;
	align-items: baseline;
	flex-wrap: wrap;
	margin: 0 0 0.3em;
}
.aside-card-title {
	font-size: clamp(20px, 2.2vw, 25px);
	line-height: 1.2;
	margin: 0.15rem 0 0;
}
.aside-card-title a { color: var(--text-primary); text-decoration: none; }
.aside-card-title a:hover { color: var(--accent); text-decoration: underline; }
/* The fixed-height window onto the prose. It clips and fades, so the column stays a set of
   choices rather than the whole blog inlined. */
.aside-card-preview {
	position: relative;
	max-height: 11rem;
	overflow: hidden;
	padding: 0 1.1rem;
	margin-top: 0.4rem;
}
/* The fade dies into the card's own ground. It is a literal rather than a token, since a
   colour with an alpha of zero must be the exact card colour or the fade greys off first --
   this is `--bg-secondary` (dark theme), which is the only theme oxedyne wears. */
.aside-card-preview::after {
	content: "";
	position: absolute;
	left: 0;
	right: 0;
	bottom: 0;
	height: 3.5rem;
	background: linear-gradient(to bottom, rgba(30, 26, 22, 0), var(--bg-secondary));
	pointer-events: none;
}
/* A preview that is not cut promises no more, so it wears no fade. */
.aside-card-preview.aside-card-fit::after { display: none; }
.aside-card-prose {
	font-size: 0.95rem;
	line-height: 1.55;
	color: var(--text-secondary);
}
.aside-card-prose > :first-child { margin-top: 0; }
.aside-card-foot {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 0.5rem 0.9rem;
	padding: 0.6rem 1.1rem 0.9rem;
}
.aside-card-foot .post-tags { margin: 0; }
/* The way in to the whole piece: a plain link drawn as the site's primary action, an ember
   button with the page's own dark ink on it. */
.aside-readmore {
	display: inline-block;
	font-size: 0.8rem;
	font-weight: 700;
	letter-spacing: 0.02em;
	color: var(--bg-primary);
	background: var(--accent);
	border: none;
	border-radius: var(--radius);
	padding: 0.4rem 0.9rem;
	text-decoration: none;
	transition: background 120ms ease;
}
.aside-readmore:hover { background: var(--accent-hover); text-decoration: none; }

/* ── "Also on …" ───────────────────────────────────────────────────
   Where a post has been syndicated, linked from the foot of the
   piece. Muted: a footer note, not the headline. */
.aside-also {
	margin-top: 2em;
	padding-top: 1em;
	border-top: 1px solid var(--border);
	font-size: 0.9em;
	color: var(--text-muted);
}
.aside-also-lbl {
	font-weight: 600;
	margin-right: 0.2em;
}
.aside-also-link {
	color: var(--accent);
	text-decoration: underline;
	margin: 0 0.15em;
}
.aside-also-link:hover { color: var(--accent-hover); }

/* ── Djot callout boxes ────────────────────────────────────────────
   A Djot `::: warning` becomes <div class="warning">; these give the
   common names a look. Scoped under .aside so they dress prose and
   nothing else, on the page and in the editor's preview alike. */
.aside .note,
.aside .info,
.aside .tip,
.aside .warning,
.aside .sidebar {
	margin: 1.1em 0;
	padding: 0.7em 1.1em;
	border-radius: var(--radius-sm);
	background: var(--bg-secondary);
}
.aside .note > :first-child,
.aside .info > :first-child,
.aside .tip > :first-child,
.aside .warning > :first-child,
.aside .sidebar > :first-child { margin-top: 0; }
.aside .note > :last-child,
.aside .info > :last-child,
.aside .tip > :last-child,
.aside .warning > :last-child,
.aside .sidebar > :last-child { margin-bottom: 0; }

/* A left accent names the kind at a glance. */
.aside .note,
.aside .info    { border-left: 4px solid var(--accent); }
.aside .tip     { border-left: 4px solid var(--ok); }
.aside .warning { border-left: 4px solid var(--warn); }
.aside .sidebar { border: 1px solid var(--border); }

/* ── Tags on a read surface ────────────────────────────────────────
   A post's tags, set as small rounded pills below the prose and on
   each index card. Each links to the index narrowed to that tag. */
.post-tags {
	list-style: none;
	display: flex;
	flex-wrap: wrap;
	gap: 8px;
	margin: 1.6em 0 0;
	padding: 0;
}
.post-tags li { margin: 0; }

.tag {
	display: inline-block;
	font-size: 13px;
	line-height: 1;
	color: var(--accent-text);
	background: var(--accent-soft);
	border: 1px solid var(--border-2);
	border-radius: 999px;
	padding: 6px 12px;
	text-decoration: none;
	transition: background 120ms ease, color 120ms ease;
}
.tag:hover {
	background: var(--bg-hover);
	color: var(--text-primary);
	text-decoration: none;
}

/* A category chip, ahead of the tags on the same row.
   The site's own fixed vocabulary rather than a word the author reached for, so it reads as the
   solid one. Same shape and metrics as a tag, so the row scans as one row -- the weight says
   which is which, not a second geometry. */
.post-cat {
	display: inline-block;
	font-size: 13px;
	font-weight: 600;
	line-height: 1;
	color: var(--bg-1, #111);
	background: var(--accent);
	border: 1px solid var(--accent);
	border-radius: 999px;
	padding: 6px 12px;
	text-decoration: none;
	transition: background 120ms ease, color 120ms ease;
}
.post-cat:hover {
	background: var(--accent-text, var(--accent));
	border-color: var(--accent-text, var(--accent));
	text-decoration: none;
}

/* ── Newsletter sign-up ───────────────────────────────────────────
   The inline form under the index, the standalone /readme/subscribe page, and
   the confirmation result pages. Themed in oxedyne's own tokens: a dark field
   and an ember button, matching the site rather than the console default. */
.aside-subscribe-inline {
	margin: 2.5rem 0 0;
	padding: 1.4rem 1.6rem;
	border: 1px solid var(--border);
	border-radius: var(--radius-lg);
	background: var(--bg-secondary);
}
.aside-subscribe-inline h2 { margin: 0 0 0.3rem; font-size: 1.2rem; color: var(--text-primary); }
.aside-subscribe-inline p { margin: 0 0 0.9rem; color: var(--text-secondary); }
.aside-subscribe-page { max-width: 34em; }
.aside-subscribe label {
	display: block;
	font-size: 0.8rem;
	text-transform: uppercase;
	letter-spacing: 0.05em;
	color: var(--text-muted);
	margin: 0 0 0.35rem;
}
.aside-subscribe {
	display: flex;
	flex-wrap: wrap;
	gap: 0.6rem;
	align-items: flex-end;
}
.aside-subscribe input[type="email"] {
	flex: 1 1 16rem;
	box-sizing: border-box;
	font: inherit;
	color: var(--text-primary);
	background: var(--bg-tertiary);
	border: 1px solid var(--border-2);
	border-radius: var(--radius-sm);
	padding: 0.6rem 0.75rem;
}
.aside-subscribe input[type="email"]:focus {
	outline: none;
	border-color: var(--accent);
}
.aside-subscribe-btn {
	font: inherit;
	cursor: pointer;
	white-space: nowrap;
	color: var(--bg-primary);
	background: var(--accent);
	border: 1px solid var(--accent);
	border-radius: var(--radius-sm);
	padding: 0.6rem 1.1rem;
	transition: background 120ms ease;
}
.aside-subscribe-btn:hover { background: var(--accent-hover); border-color: var(--accent-hover); }
.aside-subscribe-result { max-width: 34em; }
.aside-subscribe-result h1 { color: var(--text-primary); }
.aside-subscribe-result p { color: var(--text-secondary); }

/* ── The filter panel ──────────────────────────────────────────────────────
   The reader's instrument for narrowing the post list, wired by filter.js. A
   filled card on the page's own dark ground, its wells and chips carrying fills
   rather than thin outlines, so it reads as its own raised surface. Structural
   here -- the prose's own look is set above. */

.aside-filter {
	display: flex;
	flex-direction: column;
	gap: 1rem;
	margin: 0;
	padding: 1rem 1.1rem;
	border: 1px solid var(--border);
	border-radius: var(--radius-lg);
	background: var(--bg-secondary);
}

/* The search box, in the site's own search look: a pill the input rides transparent within,
   with an inline magnifier that takes the box's own muted ink. */
.aside-search-box {
	display: flex;
	align-items: center;
	gap: 0.5rem;
	height: 2.4rem;
	padding: 0 0.75rem;
	background: var(--bg-tertiary);
	border: 1px solid transparent;
	border-radius: var(--radius);
	color: var(--text-muted);
	transition: border-color 120ms ease;
}
.aside-search-box:focus-within { border-color: var(--accent); }
.aside-search-ico {
	width: 1.05rem;
	height: 1.05rem;
	flex: 0 0 auto;
}
.aside-filter-search {
	flex: 1 1 auto;
	min-width: 0;
	border: none;
	background: transparent;
	outline: none;
	font: inherit;
	font-size: 0.9rem;
	color: var(--text-primary);
}
.aside-filter-search::placeholder { color: var(--text-muted); }

/* The author faces. A pressed face is the one the list is narrowed to -- filled the site's
   ember, its ink the page's own dark. */
.aside-filter-authors {
	display: flex;
	flex-wrap: wrap;
	gap: 0.5rem;
}
.aside-author {
	display: inline-flex;
	align-items: center;
	gap: 0.45rem;
	font: inherit;
	font-size: 0.85rem;
	padding: 0.25rem 0.7rem 0.25rem 0.3rem;
	border: 1px solid var(--border);
	border-radius: 999px;
	background: var(--bg-tertiary);
	color: var(--text-secondary);
	cursor: pointer;
	transition: border-color 120ms ease, background 120ms ease, color 120ms ease;
}
.aside-author:hover { border-color: var(--accent); }
.aside-author[aria-pressed="true"] {
	border-color: var(--accent);
	background: var(--accent);
	color: var(--bg-primary);
}
/* A single author cannot be deselected, so their face is an indicator, not a control. */
.aside-authors-lone .aside-author { cursor: default; }
.aside-author-pic,
.aside-author-initial {
	width: 1.7rem;
	height: 1.7rem;
	border-radius: 50%;
	flex: 0 0 auto;
	object-fit: cover;
}
.aside-author-initial {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	font-size: 0.8rem;
	font-weight: 600;
	color: var(--bg-primary);
	background: var(--accent);
}
.aside-author[aria-pressed="true"] .aside-author-initial {
	background: rgba(21, 18, 15, 0.28);
	color: var(--bg-primary);
}

/* One mode label, shared by the search and both facet families. */
.aside-mode {
	display: inline-flex;
	align-items: center;
	gap: 0.3rem;
	cursor: pointer;
}

/* The search and the two vocabularies are the same block three times: a heading, a mode row,
   then what the block narrows on. They share every rule here. */
.aside-facet { margin: 0; }
.aside-facet-head {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 0.35rem 1rem;
	margin: 0 0 0.5rem;
}
.aside-facet-lbl {
	font-size: 0.72rem;
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: 0.07em;
	color: var(--text-secondary);
}
.aside-facet-mode {
	display: flex;
	flex-wrap: wrap;
	gap: 0.15rem 0.85rem;
	font-size: 0.78rem;
	color: var(--text-secondary);
}
.aside-facet-mode .aside-mode { gap: 0.25rem; }
.aside-facet-mode input[type="radio"] {
	accent-color: var(--accent);
	width: 0.85rem;
	height: 0.85rem;
	margin: 0;
}
.aside-facet-boxes {
	display: grid;
	grid-template-columns: 1fr 1fr;
	gap: 0.7rem;
}
.aside-facetbox { min-width: 0; }
.aside-facetbox-lbl {
	display: block;
	font-size: 0.66rem;
	text-transform: uppercase;
	letter-spacing: 0.06em;
	margin: 0 0 0.35rem;
	color: var(--text-muted);
}
/* A well: a filled inset the chips sit in, darker than the filter card, so a box a reader
   drops into reads as a recessed field rather than a dashed ghost. */
.aside-chips {
	display: flex;
	flex-wrap: wrap;
	gap: 0.4rem;
	align-content: flex-start;
	min-height: 2.9rem;
	padding: 0.45rem;
	border: 1px solid var(--border);
	border-radius: var(--radius);
	background: var(--bg-primary);
}
.aside-chips.aside-drop {
	border-color: var(--accent);
	background: var(--accent-soft);
}

/* A chip -- one geometry for the filter's chips and a post's own (`.tag` / `.post-cat`), so the
   two read as the same thing wherever they appear: the same font, the same pill, a height set to
   match the post chip. */
.aside-chip {
	--chip-h: 1.55rem;
	position: relative;
	box-sizing: border-box;
	display: inline-flex;
	align-items: center;
	height: var(--chip-h);
	padding: 0 12px;
	border: 1px solid transparent;
	border-radius: 999px;
	font: inherit;
	font-size: 13px;
	line-height: 1;
	cursor: pointer;
	user-select: none;
	transition: background 120ms ease, color 120ms ease, border-color 120ms ease;
}
.aside-chip-lbl { white-space: nowrap; }
/* A closer sits in the right cap, so the label gives it room. */
.aside-chips-selected .aside-chip { padding-right: var(--chip-h); }

/* The closer: a square filling the chip's height, pinned to the right cap so the cross sits on
   its centre. `height:100%` is the padding box, so the 1px border cancels and half of that in from
   the padding edge lands on the cap centre on both axes. The × glyph is hidden and two bars drawn,
   so the stroke weight is ours and not the font's. */
.aside-chip-x {
	position: absolute;
	right: 0;
	top: 0;
	height: 100%;
	aspect-ratio: 1;
	font-size: 0;
	opacity: 0.72;
}
.aside-chip-x::before,
.aside-chip-x::after {
	content: "";
	position: absolute;
	left: 50%;
	top: 50%;
	/* Off `--chip-h`, not `em`: the closer carries `font-size:0` to kill the × glyph, which
	   would also zero any `em` here. */
	width: calc(var(--chip-h) * 0.36);
	height: 1.5px;
	border-radius: 2px;
	background: currentColor;
}
.aside-chip-x::before { transform: translate(-50%, -50%) rotate(45deg); }
.aside-chip-x::after  { transform: translate(-50%, -50%) rotate(-45deg); }
.aside-chips-source .aside-chip-x { display: none; }
.aside-chip:hover .aside-chip-x { opacity: 1; }

/* Selected chips wear the colours a post's own chips wear, so what the filter is holding and
   what a post is labelled with read as the same vocabulary: a category solid, a tag soft. */
.aside-chips-selected .aside-chip-cat {
	background: var(--accent);
	border-color: var(--accent);
	color: var(--bg-primary);
	font-weight: 600;
}
.aside-chips-selected .aside-chip-tag {
	background: var(--accent-soft);
	border-color: var(--border-2);
	color: var(--accent-text);
}
/* An available chip is the same shape, filled the card colour on the darker well so it reads as a
   raised thing to pick up, its family named by the border colour rather than by a wash. */
.aside-chips-source .aside-chip {
	background: var(--bg-secondary);
	color: var(--text-secondary);
}
.aside-chips-source .aside-chip-cat { border-color: var(--accent); }
.aside-chips-source .aside-chip-tag { border-color: var(--accent-text); }
.aside-chips-source .aside-chip-cat:hover {
	background: var(--accent);
	color: var(--bg-primary);
}
.aside-chips-source .aside-chip-tag:hover {
	background: var(--accent-soft);
	color: var(--accent-text);
}

/* ── Reading-time slider ───────────────────────────────────────────────────
   Two thumbs on one rail, the span between them filled ember so the chosen band
   reads at a glance. The label above, the read-out beside, on their own lines so
   the track has the width. */
.aside-filter-time {
	display: grid;
	grid-template-columns: 1fr auto;
	align-items: center;
	gap: 0.35rem 0.75rem;
	font-size: 0.78rem;
	color: var(--text-secondary);
}
.aside-time-lbl {
	grid-column: 1 / -1;
	text-transform: uppercase;
	letter-spacing: 0.07em;
	font-weight: 700;
}
.aside-time-track {
	position: relative;
	height: 1.4rem;
	min-width: 8rem;
}
/* The rail and the filled span sit at the track's midline, under the thumbs. */
.aside-time-rail,
.aside-time-fill {
	position: absolute;
	top: 50%;
	transform: translateY(-50%);
	height: 5px;
	border-radius: 5px;
	pointer-events: none;
}
.aside-time-rail {
	left: 0;
	right: 0;
	background: var(--bg-hover);
}
.aside-time-fill {
	/* left and right are set by the script from the thumb positions. */
	left: 0;
	right: 0;
	background: var(--accent);
}
/* The input, its track and the thumb are all one height, and the input is centred on the rail's
   midline. Blink centres a thumb within a taller track but WebKit/iOS top-aligns it; making the
   three heights equal removes the choice -- the thumb fills the track and lands on the midline on
   both engines. */
.aside-time-track input[type="range"] {
	position: absolute;
	top: calc(50% - 0.525rem);
	left: 0;
	width: 100%;
	height: 1.05rem;
	margin: 0;
	pointer-events: none;
	-webkit-appearance: none;
	appearance: none;
	background: transparent;
}
.aside-time-track input[type="range"]::-webkit-slider-runnable-track {
	height: 1.05rem;
	background: transparent;
}
.aside-time-track input[type="range"]::-moz-range-track {
	height: 1.05rem;
	background: transparent;
}
.aside-time-track input[type="range"]::-webkit-slider-thumb {
	-webkit-appearance: none;
	appearance: none;
	pointer-events: auto;
	margin-top: 0;
	width: 1.05rem;
	height: 1.05rem;
	border-radius: 50%;
	border: 2px solid var(--bg-secondary);
	background: var(--accent);
	box-shadow: 0 1px 3px rgba(0, 0, 0, 0.4);
	cursor: pointer;
}
.aside-time-track input[type="range"]::-moz-range-thumb {
	pointer-events: auto;
	width: 1.05rem;
	height: 1.05rem;
	border-radius: 50%;
	border: 2px solid var(--bg-secondary);
	background: var(--accent);
	box-shadow: 0 1px 3px rgba(0, 0, 0, 0.4);
	cursor: pointer;
}
.aside-time-out {
	font-variant-numeric: tabular-nums;
	text-align: right;
	color: var(--accent-text);
	font-weight: 600;
}

/* ============================================================
   Who writes here.

   The description an author keeps in their profile, met above the posts, and
   the byline and note that carry the same words onto a post's own page. On a
   blog one person writes, this block is what the blog is about; where several
   write, each says their own piece and is named.
   ============================================================ */

.aside-about {
	display: flex;
	flex-direction: column;
	gap: 0.9rem;
	margin: 0 0 1.4rem;
	padding: 1rem 1.1rem;
	border-left: 3px solid var(--accent);
	background: var(--bg-secondary);
	border-radius: 0 var(--radius-lg) var(--radius-lg) 0;
}
.aside-about-who {
	display: flex;
	align-items: flex-start;
	gap: 0.8rem;
}
.aside-about-who .aside-author-pic,
.aside-about-who .aside-author-initial {
	width: 2.6rem;
	height: 2.6rem;
	font-size: 1.05rem;
}
.aside-about-body { min-width: 0; }
.aside-about-name {
	display: block;
	font-size: 0.85rem;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	color: var(--text-secondary);
	margin: 0 0 0.15rem;
}
.aside-about-bio {
	font-size: 1.02rem;
	line-height: 1.5;
	color: var(--text-secondary);
	margin: 0;
}

/* The byline: who wrote the piece, above the piece and on each card where several write. */
.aside-byline {
	display: flex;
	align-items: center;
	gap: 0.55rem;
	margin: 0 0 0.6rem;
}
.aside-byline .aside-author-pic,
.aside-byline .aside-author-initial {
	width: 1.5rem;
	height: 1.5rem;
	font-size: 0.72rem;
}
.aside-byline-name {
	font-size: 0.85rem;
	letter-spacing: 0.06em;
	color: var(--text-secondary);
}

/* The note beneath a post: the same description, where the reader has just
   finished and is deciding whether to read another. */
.aside-author-note {
	display: flex;
	align-items: flex-start;
	gap: 0.8rem;
	margin: 1.2rem 0 0;
	padding: 0.9rem 1rem;
	border-top: 1px solid var(--border);
	background: var(--bg-secondary);
	border-radius: 0 0 var(--radius-lg) var(--radius-lg);
}
.aside-author-note .aside-author-pic,
.aside-author-note .aside-author-initial {
	width: 2.4rem;
	height: 2.4rem;
	font-size: 1rem;
}
.aside-author-note-name {
	display: block;
	font-size: 0.8rem;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	color: var(--text-secondary);
	margin: 0 0 0.2rem;
}
.aside-author-note-body p {
	font-size: 0.98rem;
	line-height: 1.5;
	margin: 0;
}

/* ── Mobile: the filter folds behind a toggle ──────────────────────────────
   The two-column layout has no room on a narrow screen, so the filter folds
   away behind a button above the posts and unfolds in place -- an ordinary
   in-flow panel, not an overlay: this is a standalone page with no app shell to
   cover. The same element is only shown and hidden, never redrawn, so every
   selection the reader made is still there when it reopens. */
.aside-filter-toggle { display: none; }
@media (max-width: 767px) {
	.aside-filter-toggle {
		display: inline-flex;
		justify-self: start;
		align-items: center;
		gap: 0.5rem;
		margin: 0 0 1rem;
		padding: 0.5rem 0.9rem;
		font: inherit;
		font-weight: 700;
		color: var(--bg-primary);
		background: var(--accent);
		border: none;
		border-radius: var(--radius);
		cursor: pointer;
	}
	.aside-filter-toggle[aria-expanded="true"] { background: var(--accent-hover); }
	/* Folded away until the toggle opens it, then an ordinary in-flow panel above the posts. */
	.aside-side { display: none; }
	.aside-side.open { display: block; margin: 0 0 1.4rem; }
	/* Two half-width chip columns leave a chip nowhere to go on a phone, so they stack --
	   Selected first in the markup, so it lands above Available. */
	.aside-facet-boxes { grid-template-columns: 1fr; }
}
