/* The server-rendered pages — the parts that are not the SPA's.
 *
 * The blog, and the front page's list of the latest few updates: app/public_render.go
 * renders both, and the front page reuses .post-list rather than growing a
 * second one, which is also what lets public.js's member enhancement find it with
 * no special case.
 *
 * The page furniture these pages sit in — .header, .eyebrow, .section, .inner,
 * .card, .btn, links — is in styles/page.css, loaded by both this page and the
 * SPA. It used to be duplicated here, because those rules lived in Lit `css`
 * templates inside shadow roots and a server-rendered document cannot reach
 * into one. Moving the page-level components to light DOM removed that wall,
 * and with it ~100 lines of copy that nothing would have caught drifting.
 *
 * What is left here is the post list, which both of them render, and then what
 * only these pages have: the prose styling for rendered markdown, the members
 * gate, and the contact form's own note. Every colour is a token from main.css.
 *
 * The footer is not here. It was, while the SPA had none; it is site-wide
 * chrome now and lives in styles/page.css with the rest of it.
 */

/* pg-router's equivalent for a page that has no router: the column the SPA's
   route component would otherwise occupy. */
#page-main {
	display: flex;
	flex-direction: column;
	align-items: center;
	flex: 1;
	width: 100vw;
	box-sizing: border-box;
	overflow-x: hidden;
}

/* --- Index --------------------------------------------------------------- */

.blog-intro {
	margin: 12px 0 0;
	font-size: 1rem;
	line-height: 1.65;
	color: var(--light-color-3);
	max-width: 62ch;
}

.post-list {
	list-style: none;
	margin: 0;
	padding: 0;
	display: flex;
	flex-direction: column;
	width: 100%;
}

.post-list-item { border-top: 1px solid var(--hairline); }
.post-list-item:last-child { border-bottom: 1px solid var(--hairline); }

/* Overrides the .section link treatment in page.css: the whole card is the
   link, so it must not read as body text with an underline through it. */
.post-list-item a {
	display: block;
	padding: 28px 0;
	color: inherit;
	text-decoration: none;
}

.post-list-item a:hover { color: inherit; }
.post-list-item a:hover h2 { color: var(--signal-color); }

.post-list-meta {
	display: flex;
	align-items: center;
	gap: 10px;
	font-size: 0.75rem;
	font-weight: 600;
	letter-spacing: 0.12em;
	text-transform: uppercase;
	color: var(--light-color-4);
	margin-bottom: 10px;
}

/* h2 on the blog index, where the post title is the heading under the page's
   h1; h3 on the front page, where the band already carries an h2. One rule
   because it is one thing — the same list, in two documents.

   text-transform is the reason the h3 cannot simply inherit: page.css
   uppercases every `.section h3`, which is right for the short labels that
   selector was written for and wrong for a sentence. A post title is a
   sentence, and set in capitals it stops being readable at exactly the size
   this list shows it. */
.post-list-item h2,
.post-list-item h3 {
	text-transform: none;
	margin: 0 0 8px;
	font-size: 1.4rem;
	font-weight: 700;
	letter-spacing: -0.02em;
	line-height: 1.25;
	color: var(--light-color-1);
	transition: color 150ms;
}

.post-list-item p {
	margin: 0;
	max-width: 62ch;
}

.post-list-empty {
	border-top: 1px solid var(--hairline);
	padding: 28px 0;
	color: var(--light-color-4);
}

/* Members-only marker. Outlined in the accent rather than filled with it — the
   accent is a foreground colour on near-black, and a filled chip with
   near-white text lands around 3:1. */
.lock-chip {
	border: 1px solid var(--redline-dim);
	border-radius: 100px;
	padding: 2px 9px;
	font-size: 0.66rem;
	font-weight: 600;
	letter-spacing: 0.1em;
	color: var(--redline);
}

/* --- Post ---------------------------------------------------------------- */

/* Date and byline under the title, in the page header — the same place the
   account page hangs its read-only facts, rather than in a card. */
.post-meta {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 10px;
	margin: 4px 0 0;
	font-size: 0.75rem;
	font-weight: 600;
	letter-spacing: 0.12em;
	text-transform: uppercase;
	color: var(--light-color-4);
}

.post-summary {
	margin: 8px 0 0;
	font-size: 1.05rem;
	line-height: 1.6;
	color: var(--light-color-3);
	max-width: 62ch;
}

/* Rendered markdown. The only long-form prose on the site, so it is the one
   place that needs a full type scale rather than page.css's UI text. */
.post-body {
	font-size: 1rem;
	line-height: 1.65;
	color: var(--light-color-4);
	max-width: 68ch;
	overflow-wrap: break-word;
}

.post-body > *:first-child { margin-top: 0; }

/* A rule above the heading rather than a size jump, matching how .section h3
   separates blocks in page.css. */
.post-body h2 {
	margin: 40px 0 16px;
	padding-top: 12px;
	border-top: 1px solid var(--hairline);
	font-size: clamp(1.3rem, 3vw, 1.6rem);
	font-weight: 700;
	letter-spacing: -0.02em;
	line-height: 1.25;
	color: var(--light-color-1);
}

.post-body h3 {
	margin: 32px 0 12px;
	font-size: 1rem;
	font-weight: 600;
	letter-spacing: 0.05em;
	text-transform: uppercase;
	color: var(--light-color-4);
}

.post-body p { margin: 0 0 20px; }

.post-body ul, .post-body ol {
	margin: 0 0 20px;
	padding-left: 20px;
	gap: 8px;
}

.post-body a { display: inline; }

.post-body strong { color: var(--light-color-1); }

.post-body blockquote {
	margin: 24px 0;
	padding: 4px 0 4px 20px;
	border-left: 2px solid var(--redline-dim);
	color: var(--light-color-4);
}

.post-body img {
	max-width: 100%;
	height: auto;
	border-radius: 12px;
	display: block;
	margin: 24px 0;
}

.post-body code {
	background: var(--lighten-color-1);
	border-radius: 4px;
	padding: 2px 6px;
	font-size: 0.9em;
}

.post-body pre {
	background: var(--darken-color-1);
	border: 1px solid var(--hairline);
	border-radius: 12px;
	padding: 16px;
	overflow-x: auto;
	margin: 0 0 20px;
}

.post-body pre code { background: none; padding: 0; }

/* --- What svc/markdown emits that goldmark did not ------------------------
 *
 * The blog moved onto this repository's own renderer on 2026-08-06 (see the
 * decision log). Rendered output is nearly identical; these are the three
 * shapes that are new, and each needs a rule or it lands unstyled on the one
 * page served to strangers.
 *
 * Kept deliberately in step with the equivalents in styles/docs.css: same
 * renderer, so a change to its output has to be answered in both files. */

/* Headings now carry an id and a trailing permalink. Quiet until the heading is
   hovered — a post with a hash after every heading reads as a rendering bug —
   but a real link, so it can be copied from the context menu. Shareable section
   links on a public post are worth having: content is the sales channel. */
.post-body .anchor {
	margin-left: 8px;
	color: var(--light-color-4);
	text-decoration: none;
	opacity: 0;
	font-weight: 400;
}

.post-body h2:hover .anchor,
.post-body h3:hover .anchor,
.post-body h4:hover .anchor,
.post-body .anchor:focus-visible { opacity: 1; }

/* Task boxes, left as real disabled checkboxes by the renderer. */
.post-body li.task { list-style: none; }
.post-body li.task > input[type=checkbox] {
	margin-right: 8px;
	accent-color: var(--signal-color);
	width: 0.9em;
	height: 0.9em;
	vertical-align: -0.05em;
}

/* Fenced code is wrapped in .highlight whether or not anything was highlighted.
   `.post-body pre` above still matches the <pre> inside it, so only the syntax
   classes are needed here. These five are the whole set svc/markdown/highlight.go
   emits; a diff fence reuses .c, .t and .k rather than having its own. The
   values are in main.css, because styles/docs.css styles the same output. */
.post-body .highlight .c { color: var(--code-comment); font-style: italic; }
.post-body .highlight .s { color: var(--code-string); }
.post-body .highlight .m { color: var(--code-number); }
.post-body .highlight .k { color: var(--code-keyword); }
.post-body .highlight .t { color: var(--code-type); font-style: italic; }

/* Table styling follows the admin tables in styles/admin.css. The wrapper
   scrolls rather than the page: a wide revision comparison must never make the
   whole document scroll sideways on a phone.

   The wrapper is now a real element — svc/markdown emits .table-scroll around
   every table — so the scrolling moved onto it. It used to be `display: block`
   on the <table> itself, which is the version of this you reach for when there
   is no wrapper to hang it on: it works, but it takes the element out of table
   layout, so the columns stop sizing to their content. */
.post-body .table-scroll {
	overflow-x: auto;
	margin: 0 0 24px;
}

.post-body table {
	width: 100%;
	border-collapse: collapse;
	font-size: 0.9rem;
}

.post-body th, .post-body td {
	border-bottom: 1px solid var(--hairline);
	padding: 10px 12px;
	text-align: left;
	vertical-align: top;
}

.post-body th {
	color: var(--light-color-4);
	font-size: 0.75rem;
	font-weight: 600;
	letter-spacing: 0.08em;
	text-transform: uppercase;
}

.post-body td { color: var(--light-color-3); }

.post-body hr {
	border: 0;
	border-top: 1px solid var(--hairline);
	margin: 36px 0;
}

/* Same treatment as .back-link in styles/admin.css.
   Qualified with `a` to clear page.css's `.section a`, which is (0,1,1) and
   would otherwise win on colour and underline. */
.section a.post-back {
	display: inline-flex;
	align-items: center;
	gap: 6px;
	font-size: 0.82rem;
	font-weight: 600;
	color: var(--light-color-4);
	text-decoration: none;
	letter-spacing: 0.01em;
	transition: color 80ms;
	align-self: flex-start;
}

.section a.post-back::before { content: "←"; }
.section a.post-back:hover { color: var(--light-color-1); text-decoration: underline; }

/* --- The gate ------------------------------------------------------------ */

/* Deliberately not a paywall overlay fading out truncated text. There is no
   truncated text to fade — the body was never sent. A greyed-out ghost of
   content that does not exist would be a lie, and the one thing this blog
   cannot afford to read as is marketing.
   The panel itself is .card from page.css; only the button needs adding. */
.gate h2 {
	margin: 0;
	font-size: clamp(1.3rem, 3vw, 1.8rem);
	font-weight: 700;
	letter-spacing: -0.02em;
	color: var(--light-color-1);
}

/* Mirrors .btn in styles/page.css. An <a> rather than a <button> because it
   navigates, so the box properties are restated rather than inherited — and
   qualified with `a` to outrank page.css's `.section a`. */
.section a.join-btn {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	align-self: flex-start;
	border: 0;
	border-radius: 5px;
	background-color: var(--chalk);
	color: var(--void);
	padding: 10px 16px;
	min-width: 60px;
	font-size: 1em;
	font-weight: 600;
	text-decoration: none;
	transition-duration: 300ms;
	transition-property: background-color;
}

.section a.join-btn:hover {
	background-color: var(--chalk-dim);
	color: var(--void);
}

.section a.join-btn:focus-visible {
	outline: 2px solid var(--light-color-1);
	outline-offset: 2px;
}

.gate .gate-sub {
	font-size: 0.88rem;
}

/* --- Contact ------------------------------------------------------------- */

/* The line under the contact form. Quieter than the form and not a .card of its
   own: it qualifies what the field above it does with an address, so it belongs
   against the form rather than beside it. */
.form-note {
	margin: 0;
	font-size: 0.82rem;
	line-height: 1.6;
	color: var(--light-color-4);
}

/* The footer moved to styles/page.css. It is on every page of the site now,
   not only the server-rendered ones, and shared page furniture lives in the
   sheet both entry points link. */
