/*
 * nolanrumble.com: blog pages (/blog/...). Colours, type and .icon-btn come from
 * theme.css. Mobile first; no fixed widths wider than the screen, and anything wide
 * (code, tables) scrolls inside its own box, never the page.
 *
 * Each page is a floating window over the landscape (D16): a framed, translucent
 * box with a small gap to the screen edges. The page itself doesn't scroll; the
 * window's content does (#window-scroll).
 */

/* Page */

	:root {
		--win-gap: 12px;
		--win-radius: 1.25em;
		--window-bg: var(--sky-top);
	}

	@supports (color: color-mix(in srgb, red 50%, blue)) {
		:root {
			--window-bg: color-mix(in srgb, var(--sky-top) 86%, transparent);
		}
	}

	@media screen and (min-width: 769px) {
		:root {
			--win-gap: 16px;
		}
	}

	html:has(body.blog) {
		background-color: var(--sky-bot);
		height: 100%;
		overflow: hidden;
	}

	body.blog {
		height: 100%;
		margin: 0;
		overflow: hidden;
		overflow-wrap: break-word;
	}

	/* The plain sky, under the landscape (#bg) and in place of it until it loads. */
	body.blog:before {
		background-image: linear-gradient(to bottom, var(--sky-top), var(--sky-bot));
		content: "";
		inset: 0;
		position: fixed;
		z-index: -1;
	}

	/* Zero-specificity reset, so any later rule can set spacing. */
	:where(.blog) :where(h1, h2, h3, p, ul, ol, figure) {
		margin: 0;
		padding: 0;
	}

	/* Content images only: the landscape panels in #bg size themselves. */
	.blog-window img {
		display: block;
		height: auto;
		max-width: 100%;
	}

	:where(.blog) :focus {
		outline: none;
	}

	:where(.blog) :focus-visible {
		border-radius: 0.2em;
		box-shadow: 0 0 0 var(--ring-width) var(--ring);
	}

	.visually-hidden {
		clip-path: inset(50%);
		height: 1px;
		overflow: hidden;
		position: absolute;
		white-space: nowrap;
		width: 1px;
	}

	.skip-link {
		background: var(--btn-bg-hover);
		border-radius: var(--radius);
		box-shadow: var(--shadow-lift) var(--shadow);
		left: calc(var(--win-gap) + var(--gutter));
		padding: 0.5em 1em;
		position: fixed;
		top: -10em;
		z-index: 30;
	}

		.skip-link:focus {
			top: calc(var(--win-gap) + var(--gutter));
		}

/* The window: fixed, framed like the icon buttons (border, shadow, blur), with the
   safe areas outside it. Its content scrolls inside; the close button stays put. */

	.blog-window {
		backdrop-filter: blur(14px);
		-webkit-backdrop-filter: blur(14px);
		background: var(--window-bg);
		border: solid 1px var(--btn-border);
		border-radius: var(--win-radius);
		bottom: calc(var(--win-gap) + env(safe-area-inset-bottom, 0px));
		box-shadow: var(--shadow-lift) var(--shadow);
		left: calc(var(--win-gap) + env(safe-area-inset-left, 0px));
		overflow: hidden;
		position: fixed;
		right: calc(var(--win-gap) + env(safe-area-inset-right, 0px));
		top: calc(var(--win-gap) + env(safe-area-inset-top, 0px));
		z-index: 1;
	}

	.window-scroll {
		inset: 0;
		overflow-x: hidden;
		overflow-y: auto;
		overscroll-behavior: contain;
		position: absolute;
		scroll-padding-top: 1.5em;
	}

		/* Focused only so keyboard scrolling reaches it (nav.js): no ring. */
		.window-scroll:focus-visible {
			box-shadow: none;
		}

	.window-close {
		position: absolute;
		right: 0.75em;
		top: 0.75em;
		z-index: 2;
	}

	/* Arriving from the home page (router.js sets data-enter), the window rises in
	   over the landscape. */
	[data-enter] .blog-window {
		animation: window-in 0.45s cubic-bezier(0.2, 0.8, 0.2, 1);
	}

	@keyframes window-in {
		from {
			opacity: 0;
			transform: translateY(1.5em) scale(0.985);
		}
	}

/* Column inside the window: a gutter, then centred. */

	.site-header, .blog main, .site-footer {
		margin: 0 auto;
		max-width: 60em;
		padding-left: var(--gutter);
		padding-right: var(--gutter);
	}

	/* Room to scroll the last lines clear of the floating button. */
	.blog main {
		padding-bottom: 5em;
	}

/* Header */

	.site-header {
		align-items: baseline;
		display: flex;
		flex-wrap: wrap;
		gap: 0 1em;
		padding-bottom: 1.5em;
		/* Clear of the close button in the corner. */
		padding-right: calc(var(--gutter) + 48px);
		padding-top: 1.25em;
	}

		.site-name {
			font-weight: 800;
			letter-spacing: var(--tracking-tight);
		}

	.crumbs ol {
		color: var(--text-soft);
		display: flex;
		flex-wrap: wrap;
		font-size: var(--fs-small);
		list-style: none;
	}

		.crumbs li + li:before {
			content: "/";
			opacity: 0.6;
			padding: 0 0.5em;
		}

		.crumbs a:hover {
			color: var(--accent);
		}

/* Page heads */

	.page-head, .post-head {
		margin-bottom: 1.75em;
	}

	.blog h1 {
		font-size: var(--fs-h1-sm);
		font-weight: 800;
		letter-spacing: var(--tracking-tight);
		line-height: 1.1;
		text-shadow: 0 1px 14px var(--glow);
	}

		.h1-sub {
			color: var(--text-soft);
			font-weight: 700;
		}

	.lead {
		color: var(--text-soft);
		font-size: var(--fs-lead);
		margin-top: 0.5em;
	}

		/* The hub intro from content/hub.md can run to several paragraphs. */
		.hub-intro p + p {
			margin-top: 0.75em;
		}

		.lead a, .empty a {
			text-decoration: underline;
			text-underline-offset: 0.2em;
		}

	.post-meta, .post-item-meta {
		color: var(--text-soft);
		font-size: var(--fs-small);
	}

	.post-head .post-meta {
		margin-bottom: 0.6em;
	}

	.section-link {
		font-weight: 700;
	}

	.tag:hover, .section-link:hover, .post-item-title a:hover {
		color: var(--accent);
	}

	.empty {
		color: var(--text-soft);
	}

/* Hub */

	/* The "Blog" heading with the section icons beside it, centred in the window. */
	.hub-title-row {
		align-items: center;
		display: grid;
		gap: 0.75em 1.5em;
		grid-template-columns: 1fr auto 1fr;
	}

		.hub-title-row h1 {
			grid-column: 1;
		}

		.hub-title-row .hub-nav {
			grid-column: 2;
		}

	/* Narrow: no room to centre, so smaller icons sit at the right of the heading
	   (and wrap under it on the narrowest screens). */
	@media screen and (max-width: 640px) {
		.hub-title-row {
			display: flex;
			flex-wrap: wrap;
			justify-content: space-between;
		}

			/* Whole pixels, so the icons never land between pixels. */
			.hub-title-row .hub-nav ul {
				gap: 4px;
			}

			.hub-title-row .hub-link {
				width: 58px;
			}

			/* 24px icons draw on their own pixel grid (viewBox 0 0 24 24), so edges stay crisp. */
			.hub-title-row .hub-link .icon-btn {
				height: 48px;
				width: 48px;
			}

				.hub-title-row .hub-link .icon-btn svg {
					height: 24px;
					width: 24px;
				}
	}

	.hub-head {
		margin-bottom: 2.5em;
	}

	.hub-nav ul {
		display: flex;
		gap: 0.5em 1em;
		list-style: none;
		margin: 0;
	}

	.hub-link {
		align-items: center;
		display: flex;
		flex-direction: column;
		gap: 0.4em;
		width: var(--btn-cell);
	}

		.hub-label {
			font-size: var(--fs-small);
			font-weight: 700;
		}

		/* The whole link is the target; its round button shows the state. It grows by
		   scaling, not font-size, so its size in the layout never changes and nothing
		   around it moves. */
		.hub-link .icon-btn,
		.hub-link .icon-btn:hover,
		.hub-link .icon-btn:focus-visible,
		.hub-link .icon-btn:active {
			font-size: 1em;
		}

		.hub-link:hover .icon-btn,
		.hub-link:focus-visible .icon-btn {
			background-color: var(--btn-bg-hover);
			box-shadow: var(--shadow-lift) var(--shadow);
			color: var(--accent);
			transform: translateY(-2px) scale(1.1);
		}

		.hub-link:active .icon-btn {
			transform: scale(0.95);
		}

		/* The section you're in: filled, like the current tag chip. */
		.hub-link[aria-current] .icon-btn {
			background-color: var(--text);
			border-color: var(--text);
			color: var(--sky-top);
		}

	/* A tag page's tag goes on its own, smaller line under the section name, so the
	   heading stays compact beside the icons. The ": " between them is still read aloud. */
	.hub-title-row .h1-sub {
		display: block;
		font-size: 0.6em;
		line-height: 1.2;
		margin-top: 0.15em;
	}

		.hub-title-row .h1-sep {
			clip: rect(0 0 0 0);
			clip-path: inset(50%);
			height: 1px;
			overflow: hidden;
			position: absolute;
			white-space: nowrap;
			width: 1px;
		}

	/* Pages that belong to a section, under its intro. */
	.lead-links {
		color: var(--text-soft);
		margin-top: 0.5em;
	}

		.lead-links a {
			color: var(--accent);
			font-weight: 600;
			text-decoration: underline;
			text-underline-offset: 0.2em;
		}

		.hub-link:focus-visible {
			box-shadow: none;
		}

		.hub-link:focus-visible .icon-btn {
			box-shadow: var(--shadow-lift) var(--shadow), 0 0 0 var(--ring-width) var(--ring);
		}

	.post-item-kicker {
		color: var(--text-soft);
		font-size: var(--fs-small);
		margin-bottom: 0.15em;
	}

	.series-latest {
		color: var(--accent);
	}

	.hub-latest h2 {
		font-size: 1.25em;
		margin-bottom: 0.5em;
	}

/* Tag chips */

	.chips ul {
		display: flex;
		flex-wrap: wrap;
		gap: 0.5em;
		list-style: none;
		margin-bottom: 1.5em;
	}

	.chip {
		align-items: baseline;
		backdrop-filter: blur(var(--blur));
		-webkit-backdrop-filter: blur(var(--blur));
		background: var(--surface);
		border: solid 1px var(--rule);
		border-radius: 2em;
		box-shadow: var(--shadow-rest) var(--shadow);
		display: inline-flex;
		font-size: var(--fs-small);
		gap: 0.4em;
		padding: 0.3em 0.9em;
		transition: background-color var(--ease), color var(--ease), box-shadow var(--ease);
	}

		.chip:hover {
			background: var(--surface-hover);
			color: var(--accent);
		}

		.chip[aria-current] {
			background: var(--text);
			border-color: var(--text);
			color: var(--sky-top);
			font-weight: 700;
		}

		.chip-count {
			opacity: 0.7;
		}

/* Post lists */

	.post-list {
		list-style: none;
	}

	.post-item {
		border-top: solid 1px var(--rule);
		padding: 1em 0;
	}

		.post-item:first-child {
			border-top: none;
			padding-top: 0;
		}

		.post-item-title {
			font-size: 1.2em;
			line-height: 1.35;
			margin-bottom: 0.2em;
		}

		.post-item-summary {
			margin-top: 0.3em;
		}

/* Post */

	.post-cover {
		margin-bottom: 1.75em;
	}

		.post-cover img {
			border-radius: var(--radius);
			box-shadow: var(--shadow-rest) var(--shadow);
			width: 100%;
		}

	.toc {
		border-left: solid 2px var(--rule);
		font-size: var(--fs-small);
		margin-bottom: 2em;
		padding-left: 1em;
	}

		.toc-title {
			font-size: 1em;
			text-transform: uppercase;
			letter-spacing: 0.06em;
			color: var(--text-soft);
		}

		.toc ol {
			list-style: none;
		}

		.toc-3 {
			padding-left: 1em;
		}

		.toc a {
			display: block;
			line-height: 1.4;
			padding: 0.25em 0;
		}

			.toc a:hover {
				color: var(--accent);
			}

	/* Wide screens: the contents sit in a sticky column beside the text. */
	@media screen and (min-width: 1100px) {
		.has-toc .post-body {
			display: grid;
			gap: 3em;
			grid-template-columns: minmax(0, 1fr) 14em;
		}

			.has-toc .toc {
				align-self: start;
				grid-column: 2;
				grid-row: 1;
				max-height: calc(100vh - 2 * var(--win-gap) - 3em);
				overflow-y: auto;
				position: sticky;
				top: 1.5em;
			}

			.has-toc .prose {
				grid-column: 1;
				grid-row: 1;
			}
	}

/* Prose */

	.prose {
		max-width: var(--measure);
	}

		.prose > * + * {
			margin-top: 1.1em;
		}

		.prose h2 {
			font-size: 1.45em;
			letter-spacing: var(--tracking-tight);
			line-height: 1.25;
			margin-top: 1.8em;
		}

		.prose h3 {
			font-size: 1.15em;
			line-height: 1.3;
			margin-top: 1.5em;
		}

		.prose a {
			color: var(--accent);
			text-decoration: underline;
			text-decoration-thickness: 1px;
			text-underline-offset: 0.2em;
		}

			.prose a:hover {
				text-decoration-thickness: 2px;
			}

		.ext-icon {
			display: inline-block;
			fill: currentColor;
			height: 0.65em;
			margin-left: 0.2em;
			vertical-align: baseline;
			width: 0.65em;
		}

		.prose ul, .prose ol {
			padding-left: 1.4em;
		}

			.prose li + li {
				margin-top: 0.3em;
			}

		.prose blockquote {
			border-left: solid 3px var(--rule);
			color: var(--text-soft);
			margin-left: 0;
			margin-right: 0;
			padding-left: 1em;
		}

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

		.prose picture img {
			border-radius: var(--radius);
		}

		/* ![alt](src "small"): half the column on phones and tablets, a third on desktop. */
		.prose picture.img-small {
			display: block;
			margin: 0 auto;
			width: 50%;
		}

			.prose picture.img-small img {
				height: auto;
				width: 100%;
			}

		@media screen and (min-width: 1100px) {
			.prose picture.img-small {
				width: 33.333%;
			}
		}

		.prose :not(pre) > code {
			background: var(--code-bg);
			border-radius: 0.3em;
			font-family: var(--font-mono);
			font-size: 0.88em;
			padding: 0.1em 0.35em;
		}

/* Code blocks: scroll sideways inside their box. copy.js adds the button. */

	.code-block {
		position: relative;
	}

	.code {
		background: var(--code-bg);
		border: solid 1px var(--rule);
		border-radius: var(--radius);
		font-family: var(--font-mono);
		font-size: 0.82em;
		letter-spacing: 0;
		line-height: 1.6;
		margin: 0;
		overflow-x: auto;
		padding: 1em 1.1em;
		tab-size: 4;
	}

		.code code {
			font-family: inherit;
			white-space: pre;
		}

		.code[data-lang]:before {
			color: var(--text-soft);
			content: attr(data-lang);
			display: block;
			font-family: var(--font-ui);
			font-size: 0.8em;
			line-height: 1;
			margin-bottom: 0.8em;
			text-transform: uppercase;
			letter-spacing: 0.06em;
		}

	.copy-btn {
		background: var(--surface);
		border: solid 1px var(--rule);
		border-radius: 1em;
		color: var(--text-soft);
		cursor: pointer;
		font: inherit;
		font-size: 0.72em;
		line-height: 1;
		padding: 0.45em 0.8em;
		position: absolute;
		right: 0.6em;
		top: 0.6em;
	}

		.copy-btn:hover {
			background: var(--surface-hover);
			color: var(--accent);
		}

/* Tables: scroll sideways inside their box. */

	.table-scroll {
		border: solid 1px var(--rule);
		border-radius: var(--radius);
		overflow-x: auto;
	}

		/* Columns keep a readable width and the box scrolls, rather than squeezing a
		   wide table into tall, narrow rows. */
		.table-scroll table {
			border-collapse: collapse;
			font-size: 0.9em;
			min-width: 100%;
			width: max-content;
		}

		.table-scroll th, .table-scroll td {
			border-bottom: solid 1px var(--rule);
			max-width: 18em;
			padding: 0.5em 0.8em;
			text-align: left;
			vertical-align: top;
		}

		.table-scroll thead th {
			background: var(--code-bg);
			white-space: nowrap;
		}

		.table-scroll tr:last-child td {
			border-bottom: none;
		}

/* Older / newer */

	.pager {
		display: grid;
		gap: 1em;
		grid-template-columns: 1fr 1fr;
		margin-top: 3em;
		max-width: var(--measure);
	}

		.pager a {
			background: var(--surface);
			border: solid 1px var(--rule);
			border-radius: var(--radius);
			box-shadow: var(--shadow-rest) var(--shadow);
			display: flex;
			flex-direction: column;
			gap: 0.25em;
			padding: 0.8em 1em;
			transition: background-color var(--ease), box-shadow var(--ease), transform var(--ease);
		}

			.pager a:hover {
				background: var(--surface-hover);
				box-shadow: var(--shadow-lift) var(--shadow);
				transform: translateY(-2px);
			}

		.pager-newer {
			grid-column: 2;
			text-align: right;
		}

		.pager-dir {
			align-items: center;
			color: var(--text-soft);
			display: inline-flex;
			font-size: var(--fs-small);
			gap: 0.3em;
		}

			.pager-newer .pager-dir {
				justify-content: flex-end;
			}

			.pager-dir svg {
				fill: currentColor;
				height: 0.8em;
				width: 0.8em;
			}

		.pager-title {
			font-weight: 700;
			line-height: 1.35;
		}

	@media screen and (max-width: 480px) {
		.pager {
			grid-template-columns: 1fr;
		}

			.pager-newer {
				grid-column: 1;
				grid-row: 1;
			}
	}

/* Photos index */

	.album-cards {
		display: grid;
		gap: 1.25em;
		grid-template-columns: repeat(auto-fill, minmax(min(100%, 16em), 1fr));
		list-style: none;
	}

	.album-card a {
		background: var(--surface);
		border: solid 1px var(--rule);
		border-radius: var(--radius);
		box-shadow: var(--shadow-rest) var(--shadow);
		display: flex;
		flex-direction: column;
		height: 100%;
		overflow: hidden;
		transition: box-shadow var(--ease), transform var(--ease);
	}

		.album-card a:hover {
			box-shadow: var(--shadow-lift) var(--shadow);
			transform: translateY(-2px);
		}

		.album-card img {
			aspect-ratio: 3 / 2;
			object-fit: cover;
			width: 100%;
		}

		.album-card-title {
			font-weight: 700;
			padding: 0.6em 0.9em 0;
		}

		.album-card-meta {
			color: var(--text-soft);
			font-size: var(--fs-small);
			padding: 0 0.9em 0.7em;
		}

/* Album: a masonry-style grid from CSS columns. */

	.album-grid {
		column-gap: 1em;
		columns: 1;
		list-style: none;
	}

		.album-grid li {
			break-inside: avoid;
			margin-bottom: 1em;
		}

		.album-grid img {
			border-radius: var(--radius);
			box-shadow: var(--shadow-rest) var(--shadow);
			width: 100%;
		}

		.album-grid figcaption {
			color: var(--text-soft);
			font-size: var(--fs-small);
			line-height: 1.4;
			padding-top: 0.4em;
		}

	@media screen and (min-width: 600px) {
		.album-grid { columns: 2; }
	}

	@media screen and (min-width: 1100px) {
		.album-grid { columns: 3; }
	}

/* Footer: the site nav for everyone, including without JavaScript. */

	.site-footer {
		padding-bottom: 5em;
		text-align: center;
	}

		.site-footer ul {
			border-top: solid 1px var(--rule);
			display: flex;
			flex-wrap: wrap;
			gap: 0.25em 1.25em;
			justify-content: center;
			list-style: none;
			padding-top: 1.25em;
		}

		.site-footer a {
			align-items: center;
			display: inline-flex;
			gap: 0.4em;
			padding: 0.3em 0;
		}

			.site-footer a:hover {
				color: var(--accent);
			}

			.site-footer a[aria-current] {
				color: var(--accent);
				font-weight: 700;
			}

			.site-footer svg {
				fill: currentColor;
				height: 1em;
				width: 1.15em;
			}

		.site-footer .copyright {
			color: var(--text-soft);
			font-size: var(--fs-small);
			margin-top: 0.75em;
		}

/* Options button (nav.js): bottom-right, out of the way while reading down. */

	/* Inside the window's bottom-right corner. */
	.options-btn {
		bottom: calc(var(--win-gap) + 12px + env(safe-area-inset-bottom, 0px));
		position: fixed;
		right: calc(var(--win-gap) + 12px + env(safe-area-inset-right, 0px));
		transition: background-color var(--ease), box-shadow var(--ease), color var(--ease), transform 0.3s ease-in-out, opacity 0.3s ease-in-out;
		z-index: 10;
	}

		.options-btn.is-away {
			opacity: 0;
			pointer-events: none;
			transform: translateY(calc(100% + var(--gutter)));
		}

	.no-js .options-btn {
		display: none;
	}

/* Options panel: a sheet rising from the bottom on phones and small tablets, a
   panel above the button on wider screens. Its box fills the <dialog>, so a tap on
   the dialog itself is a tap outside (nav.js). */

	.options {
		background: transparent;
		border: none;
		color: var(--text);
		inset: auto 0 0 0;
		margin: 0;
		max-height: none;
		max-width: none;
		padding: 0;
		position: fixed;
		width: 100%;
	}

		.options::backdrop {
			background: rgba(8, 13, 24, 0.35);
		}

	.options-box {
		backdrop-filter: blur(var(--blur));
		-webkit-backdrop-filter: blur(var(--blur));
		background: var(--btn-bg-hover);
		border: solid 1px var(--btn-border);
		border-radius: 1em 1em 0 0;
		box-shadow: var(--shadow-lift) var(--shadow);
		display: flex;
		flex-direction: column;
		gap: 1em;
		max-height: min(85vh, 85dvh);
		overflow-y: auto;
		overscroll-behavior: contain;
		padding: 1em calc(var(--gutter) + env(safe-area-inset-right, 0px)) calc(1em + env(safe-area-inset-bottom, 0px)) calc(var(--gutter) + env(safe-area-inset-left, 0px));
	}

		.options[open] .options-box {
			animation: options-rise 0.22s ease-out;
		}

	@keyframes options-rise {
		from {
			opacity: 0;
			transform: translateY(1.5em);
		}
	}

	.options-head {
		align-items: center;
		display: flex;
		justify-content: space-between;
	}

		.options-title {
			color: var(--text-soft);
			font-size: var(--fs-small);
			letter-spacing: 0.06em;
			text-transform: uppercase;
		}

	.options-context ol, .options-context ul {
		list-style: none;
	}

		.options-toc a, .options-albums a {
			border-radius: var(--radius);
			display: block;
			line-height: 1.4;
			padding: 0.45em 0.5em;
		}

			.options-toc a:hover, .options-albums a:hover {
				background: var(--code-bg);
				color: var(--accent);
			}

		.options-toc .toc-3 a {
			padding-left: 1.5em;
		}

		.options-album-meta {
			color: var(--text-soft);
			font-size: var(--fs-small);
		}

		.options-context .chips ul {
			margin-bottom: 0;
		}

	.options-foot {
		border-top: solid 1px var(--rule);
		display: flex;
		flex-direction: column;
		gap: 0.75em;
		padding-top: 1em;
	}

		.options-nav ul {
			display: grid;
			gap: 0.25em;
			grid-template-columns: repeat(5, minmax(0, 1fr));
			list-style: none;
		}

		.options-nav a {
			align-items: center;
			border-radius: var(--radius);
			display: flex;
			flex-direction: column;
			font-size: var(--fs-small);
			gap: 0.3em;
			padding: 0.5em 0.1em;
			text-align: center;
		}

			.options-nav a:hover {
				background: var(--code-bg);
				color: var(--accent);
			}

			.options-nav a[aria-current] {
				background: var(--code-bg);
				color: var(--accent);
				font-weight: 700;
			}

			.options-nav svg {
				fill: currentColor;
				height: 1.35em;
				width: 1.6em;
			}

		.options-theme {
			align-items: center;
			background: var(--surface);
			border: solid 1px var(--rule);
			border-radius: 2em;
			color: inherit;
			cursor: pointer;
			display: flex;
			font: inherit;
			font-size: var(--fs-small);
			gap: 0.6em;
			justify-content: center;
			padding: 0.55em 1em;
		}

			.options-theme:hover {
				color: var(--accent);
			}

			.options-theme svg {
				height: 18px;
				width: 18px;
			}

	@media screen and (min-width: 769px) {
		.options {
			inset: auto calc(var(--win-gap) + 12px + env(safe-area-inset-right, 0px)) calc(var(--win-gap) + 12px + var(--btn-size-sm) + 12px + env(safe-area-inset-bottom, 0px)) auto;
			width: 24em;
		}

			.options::backdrop {
				background: transparent;
			}

		.options-box {
			border-radius: 1em;
			max-height: calc(100vh - 8em);
			padding: 1em 1.1em;
		}
	}

	/* With JavaScript, narrow screens keep the contents in the options panel instead
	   of above the text; wide screens keep the sticky sidebar. Keyed on .no-js (gone
	   before first paint, theme.js), not on nav.js running, so the text never jumps. */
	@media screen and (max-width: 1099px) {
		:root:not(.no-js) .post .toc {
			display: none;
		}
	}

/* Tech: dense rows, with a small thumbnail when the post has a cover. */

	.post-item article {
		align-items: flex-start;
		display: flex;
		gap: 1em;
	}

	.post-item-text {
		flex: 1;
		min-width: 0;
	}

	.post-item-media img {
		border-radius: var(--radius);
		height: 4.5em;
		object-fit: cover;
		width: 4.5em;
	}

	.post-item[hidden] {
		display: none;
	}

	.list-tech .post-item {
		padding: 0.75em 0;
	}

/* Series pages: each part is a card with its cover on top. */

		.series-list-posts .post-item.has-media article {
			flex-direction: column;
		}

			.series-list-posts .post-item-media {
				width: 100%;
			}

			.series-list-posts .post-item-media img {
				aspect-ratio: 16 / 9;
				height: auto;
				width: 100%;
			}

	.post-item-series, .post-series {
		color: var(--text-soft);
		font-size: var(--fs-small);
		margin: 0.2em 0 0;
	}

		.post-series a {
			color: var(--accent);
		}

/* Series: cards on the section page, the series page, and the parts strip on posts. */

	.series-nav-kicker, .series-part-num {
		color: var(--text-soft);
		font-size: var(--fs-small);
	}

	.series-intro p + p {
		margin-top: 0.75em;
	}

	.series-list-posts {
		display: grid;
		gap: 1em;
		grid-template-columns: repeat(auto-fill, minmax(min(100%, 18em), 1fr));
	}

		.series-list-posts .post-item, .series-list-posts .post-item:first-child {
			background: var(--surface);
			border: solid 1px var(--rule);
			border-radius: var(--radius);
			box-shadow: var(--shadow-rest) var(--shadow);
			padding: 1em 1.2em;
		}

	.series-nav {
		background: var(--surface);
		border: solid 1px var(--rule);
		border-radius: var(--radius);
		box-shadow: var(--shadow-rest) var(--shadow);
		margin-top: 3em;
		max-width: var(--measure);
		padding: 1em 1.2em 1.2em;
	}

		.series-nav-kicker {
			margin: 0;
		}

		.series-nav-title {
			font-size: 1.3em;
			margin: 0.15em 0 0.8em;
		}

			.series-nav-title a {
				color: inherit;
			}

				.series-nav-title a:hover {
					color: var(--accent);
				}

		.series-parts {
			display: grid;
			gap: 0.75em;
			grid-template-columns: repeat(auto-fill, minmax(min(100%, 11em), 1fr));
			list-style: none;
			margin: 0;
			padding: 0;
		}

			.series-part-link {
				border: solid 2px transparent;
				border-radius: var(--radius);
				display: flex;
				flex-direction: column;
				gap: 0.25em;
				height: 100%;
				padding: 0.3em;
				transition: background-color var(--ease);
			}

				a.series-part-link:hover {
					background: var(--surface-hover);
				}

				.is-current .series-part-link {
					border-color: var(--accent);
				}

			.series-part-media img, .series-part-blank {
				aspect-ratio: 16 / 9;
				border-radius: calc(var(--radius) * 0.75);
				display: block;
				height: auto;
				object-fit: cover;
				width: 100%;
			}

			.series-part-blank {
				align-items: center;
				background: var(--code-bg);
				color: var(--text-soft);
				display: flex;
				font-size: 1.5em;
				font-weight: 700;
				justify-content: center;
			}

			.is-current .series-part-num {
				color: var(--accent);
				font-weight: 700;
			}

			.series-part-title {
				font-size: var(--fs-small);
				font-weight: 600;
				line-height: 1.3;
			}

		.series-nav-step {
			display: flex;
			justify-content: space-between;
			margin: 1em 0 0;
		}

			.series-nav-step a {
				align-items: center;
				color: var(--accent);
				display: inline-flex;
				gap: 0.3em;
			}

				.series-nav-step svg {
					fill: currentColor;
					height: 0.8em;
					width: 0.8em;
				}

/* Lightbox (lightbox.js): full screen over a dark backdrop in any theme. */

	.lightbox {
		background: rgba(8, 12, 20, 0.96);
		border: none;
		color: #f1f5f9;
		height: 100vh;
		height: 100dvh;
		margin: 0;
		max-height: none;
		max-width: none;
		overflow: hidden;
		padding: 0;
		width: 100vw;
	}

		.lightbox::backdrop {
			background: rgba(0, 0, 0, 0.6);
		}

	.lightbox-stage {
		align-items: center;
		display: flex;
		inset: calc(3.5em + env(safe-area-inset-top, 0px)) 0 calc(4em + env(safe-area-inset-bottom, 0px));
		justify-content: center;
		overflow: hidden;
		position: absolute;
		touch-action: none;
	}

	.blog .lightbox-img {
		cursor: zoom-in;
		height: auto;
		max-height: 100%;
		max-width: 100%;
		object-fit: contain;
		transition: opacity 0.2s ease-in-out;
		user-select: none;
		width: auto;
	}

		.lightbox.is-zoomed .lightbox-img {
			cursor: grab;
		}

		.lightbox-stage.is-loading .lightbox-img {
			opacity: 0.35;
		}

	.lightbox-caption, .lightbox-counter {
		bottom: calc(1.1em + env(safe-area-inset-bottom, 0px));
		font-size: var(--fs-small);
		line-height: 1.4;
		margin: 0;
		position: absolute;
	}

		.lightbox-caption {
			left: calc(var(--gutter) + env(safe-area-inset-left, 0px));
			right: 6em;
		}

		.lightbox-counter {
			opacity: 0.75;
			right: calc(var(--gutter) + env(safe-area-inset-right, 0px));
		}

	.lightbox-prev, .lightbox-next, .lightbox-close {
		align-items: center;
		background: rgba(255, 255, 255, 0.12);
		border: solid 1px rgba(255, 255, 255, 0.18);
		border-radius: 100%;
		color: inherit;
		cursor: pointer;
		display: flex;
		height: 44px;
		justify-content: center;
		padding: 0;
		position: absolute;
		width: 44px;
		z-index: 1;
	}

		.lightbox-prev:hover, .lightbox-next:hover, .lightbox-close:hover {
			background: rgba(255, 255, 255, 0.24);
		}

		.lightbox-prev:disabled, .lightbox-next:disabled {
			cursor: default;
			opacity: 0.3;
		}

		.lightbox-prev svg, .lightbox-next svg, .lightbox-close svg {
			fill: currentColor;
			height: 18px;
			width: 18px;
		}

	.lightbox-prev, .lightbox-next {
		top: 50%;
		transform: translateY(-50%);
	}

		.lightbox-prev {
			left: calc(0.75em + env(safe-area-inset-left, 0px));
		}

		.lightbox-next {
			right: calc(0.75em + env(safe-area-inset-right, 0px));
		}

	.lightbox-close {
		right: calc(0.75em + env(safe-area-inset-right, 0px));
		top: calc(0.75em + env(safe-area-inset-top, 0px));
	}

	.lightbox :focus-visible {
		box-shadow: 0 0 0 3px rgba(159, 179, 200, 0.8);
	}

/* Larger screens */

	@media screen and (min-width: 737px) {
		.blog h1 {
			font-size: 3em;
		}

		.post-head h1 {
			font-size: 2.6em;
		}
	}

/* Reduced motion */

	@media (prefers-reduced-motion: reduce) {
		.chip, .pager a, .album-card a, .options-btn, .lightbox-img {
			transition: none;
		}

		[data-enter] .blog-window {
			animation: none;
		}

		.options[open] .options-box {
			animation: none;
		}
	}
