/*
 * The blog, ported from the cornytis theme.
 *
 * The geometry is theirs, rule for rule: the card, the leading post, the head
 * with its search, the filter pills, the three-column grid, the pagination,
 * the article's head band and its sticky rail. What changed is every colour,
 * size, weight and radius, which come from this site's tokens rather than
 * cornytis's, so the layout is theirs and the look is ours.
 *
 * Loaded only on the pages that hold a post: the blog, a category, a search
 * and a single article.
 */

/* ------------------------------------------------------------- A post card */

.mn-post-card {
	display: flex;
	flex-direction: column;
	gap: var(--mn-gap-lg);
	/* Named, so its parts can size themselves by how wide the card is rather
	   than by how wide the screen is. See the query under the body below. */
	container: card / inline-size;
}

.mn-post-card-media {
	position: relative;
	display: block;
	aspect-ratio: 4 / 3;
	overflow: hidden;
	border-radius: var(--mn-radius-lg);
	background: var(--mn-gray-100);
	text-decoration: none;
}

.mn-post-card-media img {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
}

/*
 * A card with no picture keeps its place in the row. Left to collapse, the
 * grid runs ragged the first time somebody publishes without an image.
 */
.mn-post-card-placeholder {
	display: block;
	width: 100%;
	height: 100%;
	background: linear-gradient(135deg, var(--mn-gray-100), var(--mn-gray-200));
}

.mn-post-card-body {
	display: flex;
	flex-direction: column;
	gap: var(--mn-card-gap);
	/*
	 * Takes the height the card was given, so the "Read more" pushed to its
	 * bottom has somewhere to be pushed to. Without this the body is only as
	 * tall as its words and every card ends at its own height.
	 */
	flex: 1 1 auto;
}

/*
 * A card narrow enough to need smaller type gets it, wherever it is: in a
 * carousel showing two on a phone, in a sidebar, in a page's own columns. The
 * sizes are set on the body rather than on the card, because a container
 * cannot answer a query about itself.
 */
@container card (max-width: 320px) {

	.mn-post-card-body {
		--mn-card-title: var(--mn-size-lg);
		--mn-card-text: var(--mn-size-small);
	}
}

.mn-post-card-cat {
	display: inline-flex;
	align-self: flex-start;
	align-items: center;
	gap: var(--mn-gap-sm);
	padding: 6px 10px;
	border-radius: var(--mn-radius-pill);
	background: var(--mn-gold-soft);
	color: var(--mn-gold-hover);
	font-family: var(--mn-font-mono);
	font-size: var(--mn-size-micro);
	letter-spacing: var(--mn-tracking-mono);
	line-height: var(--mn-leading-ui);
	text-transform: uppercase;
	text-decoration: none;
	transition: background-color 200ms ease;
}

/*
 * Both chips go to the subject, so both say so under the pointer. Stated once
 * for the two, because a card and the leading post are the same chip at two
 * sizes and not two chips.
 */
.mn-post-card-cat:hover,
.mn-blog-featured__cat:hover {
	background: var(--mn-gold-soft-hover);
}

.mn-post-card-badge {
	padding: 3px 7px;
	border-radius: var(--mn-radius-pill);
	background: var(--mn-gold);
	color: var(--mn-surface);
	font-size: var(--mn-size-micro);
	font-weight: var(--mn-weight-bold);
	letter-spacing: var(--mn-tracking-mono);
	line-height: var(--mn-leading-none);
	text-transform: uppercase;
}

.mn-post-card-title {
	margin: 0;
	color: var(--mn-ink);
	font-size: var(--mn-card-title);
	font-weight: var(--mn-weight-medium);
	line-height: var(--mn-leading-snug);
	letter-spacing: var(--mn-tracking-tight);
	/* A long unbroken word in a title is a card three columns wide. */
	overflow-wrap: anywhere;
	hyphens: auto;
	/* Cut to the number of lines set under Blog, so the row stays level. */
	display: -webkit-box;
	-webkit-line-clamp: var(--mn-card-title-lines, 2);
	line-clamp: var(--mn-card-title-lines, 2);
	-webkit-box-orient: vertical;
	overflow: hidden;
}

/*
 * The title lifts a shade on hover and does nothing else. Ink to gold is a
 * whole heading becoming a different thing, and a rule appearing under it is a
 * second mark on a card that already has one under "Read more".
 */
.mn-post-card-title a,
.mn-blog-featured__title a {
	color: inherit;
	text-decoration: none;
	transition: color 200ms ease;
}

.mn-post-card-title a:hover,
.mn-blog-featured__title a:hover {
	color: var(--mn-gray-700);
}

.mn-post-card-excerpt {
	margin: 0;
	color: var(--mn-gray-600);
	font-size: var(--mn-card-text);
	line-height: var(--mn-leading-body);
	/* Cut to the number of lines set under Blog, so a row keeps its shape. */
	display: -webkit-box;
	-webkit-line-clamp: var(--mn-card-words-lines, 3);
	line-clamp: var(--mn-card-words-lines, 3);
	-webkit-box-orient: vertical;
	overflow: hidden;
}

.mn-post-card-date {
	margin: 0;
	color: var(--mn-gray-500);
	font-size: var(--mn-size-small);
}

/*
 * The label rolls and nothing else moves. The colour holds: a label that lifts
 * and changes colour at the same time is two answers to one gesture.
 *
 * inline-flex, because the roll wraps the words in a span of their own and the
 * arrow beside it dropped to the next line the moment it did.
 */
.mn-post-card-readmore {
	display: inline-flex;
	align-items: center;
	align-self: flex-start;
	/*
	 * Bottom of the card, so a row of cards with titles of different lengths
	 * still has one line of "Read more" across it rather than three heights.
	 * The clearance above it is padding rather than margin: `auto` is what
	 * pushes it down, and it cannot also hold a minimum.
	 */
	margin-top: auto;
	padding-top: var(--mn-gap);
	gap: var(--mn-gap-xs);
	color: var(--mn-ink);
	font-size: var(--mn-size-ui);
	font-weight: var(--mn-weight-medium);
	text-decoration: none;
	white-space: nowrap;
}

/*
 * The colour holds. A label that lifts and changes colour at once is two
 * answers to one gesture, and the lift is the answer.
 */
.mn-post-card-readmore:hover {
	color: inherit;
}

/*
 * The arrow keeps its own colour and its own line. Left to shrink it wrapped
 * under the label the moment the roll put the words in a span of their own.
 */
.mn-post-card-readmore svg {
	flex: none;
	stroke: var(--mn-gold);
}

/* --------------------------------------------------------- The blog itself */

/*
 * Top only. The callout is the last thing inside this element, so any padding
 * on the bottom of it lands underneath the callout rather than above it: a
 * band of page colour between the callout and the footer, which is what a
 * page looks like when it has stopped rather than ended.
 *
 * The space above the callout belongs to the content, which is why it is on
 * the column below and not here.
 */
.mn-blog-archive,
.mn-blog-category,
.mn-blog-search-results {
	padding: var(--mn-gap-lg) 0 0;
}

/*
 * The column of content, and not the trail above it. The trail sits in a
 * container of its own, so an unqualified rule handed it the whole page's
 * bottom spacing and left seventy pixels under a line of small grey text.
 *
 * Asked as "the container that does not hold a trail". It was written as "the
 * container that is not a trail", which is not the same thing and never
 * matched: the class is on the div inside, so both containers passed the test
 * and both took the padding.
 */
.mn-blog-archive>.mn-container:not(:has(> .mn-page-trail)),
.mn-blog-category>.mn-container:not(:has(> .mn-page-trail)),
.mn-blog-search-results>.mn-container:not(:has(> .mn-page-trail)) {
	padding-bottom: var(--mn-space-lg);
}

/*
 * And the last thing in that column adds nothing to it. The grid's own bottom
 * margin is what separates it from the pagination; where there is no
 * pagination it would be a second helping of the same space.
 */
.mn-blog-archive>.mn-container:not(:has(> .mn-page-trail))> :last-child,
.mn-blog-category>.mn-container:not(:has(> .mn-page-trail))> :last-child,
.mn-blog-search-results>.mn-container:not(:has(> .mn-page-trail))> :last-child,
.mn-blog-results> :last-child {
	margin-bottom: 0;
}

/*
 * A card, not a band of page. The picture and the words sit on one surface
 * with one radius and one shadow, which is what every other block of content
 * on this site does and what the leading post was conspicuously not doing.
 */
/*
 * A card, not a band of page: one surface, one radius, one shadow, which is
 * what every other block of content on this site is.
 *
 * Nothing is padded except the words. The picture runs to the card's own edge
 * and is cropped by it, so the card has one outline rather than a picture
 * floating inside a frame with a margin of white around it.
 */
.mn-blog-featured {
	position: relative;
	margin-bottom: var(--mn-space-lg);
	/*
	 * A flow root, so the track's negative margin stays inside it. The track
	 * is padded and pulled back by the same amount to give the card's shadow
	 * somewhere to fall; through a parent with no border or padding of its own
	 * that pull escaped upward, and the page's own thirty pixels above the
	 * band were arriving as sixteen.
	 */
	display: flow-root;
}

.mn-blog-featured__track {
	display: flex;
}

.mn-blog-featured__card {
	display: grid;
	grid-template-columns: 1fr 1.1fr;
	/* Stretched, so the picture is as tall as the words beside it. */
	align-items: stretch;
	width: 100%;
	overflow: hidden;
	border: 1px solid var(--mn-gray-200);
	border-radius: var(--mn-radius-3xl);
	background: var(--mn-surface);
	box-shadow: var(--mn-shadow-sm);
}

/*
 * The picture fills its half however tall the half turns out to be, which is
 * why the image is taken out of the flow rather than given an aspect ratio:
 * a ratio would set the height, and then the words beside it would decide a
 * different one and leave a band of card showing under the picture.
 *
 * The minimum is for the short post, where the words alone would make a card
 * too shallow to show a picture in.
 */
.mn-blog-featured__media {
	position: relative;
	min-height: var(--mn-featured-media);
	overflow: hidden;
	background: var(--mn-gray-100);
}

.mn-blog-featured__media img,
.mn-blog-featured__media .mn-post-card-placeholder {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	object-fit: cover;
}

.mn-blog-featured__body {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: var(--mn-gap-md);
	/* The only padding on the card, and it belongs to the words. */
	padding: var(--mn-space) var(--mn-space);
}

/*
 * The words at the top and the way in at the foot. Centred as a block, the
 * button sat wherever the words happened to end, which is a different place
 * on every card and reads as three cards misaligned rather than three cards.
 */
/*
 * Pushed to the foot of the card. `auto` takes whatever room is spare, which
 * on a short post is none, so the clearance is stated on the line above it
 * instead: the button is never nearer the words than the gap plus this.
 */
.mn-blog-featured__button {
	margin-top: auto;
}

.mn-blog-featured__cat {
	display: inline-flex;
	align-items: center;
	gap: var(--mn-gap-sm);
	margin: 0;
	padding: 6px 10px;
	border-radius: var(--mn-radius-pill);
	background: var(--mn-gold-soft);
	color: var(--mn-gold-hover);
	font-family: var(--mn-font-mono);
	font-size: var(--mn-size-micro);
	letter-spacing: var(--mn-tracking-mono);
	line-height: var(--mn-leading-ui);
	text-transform: uppercase;
	text-decoration: none;
	transition: background-color 200ms ease;
}

.mn-blog-featured__title {
	margin: 0;
	/*
	 * The colour belongs to the element the clamp is on. `-webkit-line-clamp`
	 * has the browser draw the ellipsis, and it draws it in the colour of the
	 * box that owns the clamp, not of the link inside it: colour only the `a`
	 * and the words go white on a dark band while the three dots stay black.
	 * `.mn-post-card-title` above already does it this way.
	 */
	color: var(--mn-ink);
	font-size: clamp(var(--mn-size-title), 3.5vw, var(--mn-size-display));
	font-weight: var(--mn-weight-medium);
	line-height: var(--mn-leading-tight);
	letter-spacing: var(--mn-tracking-display);
	display: -webkit-box;
	-webkit-line-clamp: var(--mn-lead-title-lines, 1);
	line-clamp: var(--mn-lead-title-lines, 1);
	-webkit-box-orient: vertical;
	overflow: hidden;
}


.mn-blog-featured__excerpt {
	margin: 0;
	color: var(--mn-gray-600);
	line-height: var(--mn-leading-body);
	display: -webkit-box;
	-webkit-line-clamp: var(--mn-lead-words-lines, 3);
	line-clamp: var(--mn-lead-words-lines, 3);
	-webkit-box-orient: vertical;
	overflow: hidden;
}

.mn-blog-featured__date {
	margin: 0 0 var(--mn-gap-lg);
	color: var(--mn-gray-500);
	font-size: var(--mn-size-small);
}

/* ------------------------------------------- More than one, so a carousel */

/*
 * One card in view at a time, snapping. The track is the scroller, so a swipe
 * on a phone and a trackpad's own horizontal scroll both work with no script
 * at all; the arrows, the dots and the mouse drag are what the script adds.
 */
/*
 * Room for the card's shadow. A scroller clips both axes whatever the second
 * one is set to, so the shadow was being cut off flat along the top and bottom
 * of the track. The padding gives it somewhere to fall and the negative margin
 * takes the space back out of the layout.
 */
.mn-blog-featured--many .mn-blog-featured__track {
	gap: var(--mn-gap-xl);
	padding-block: 14px;
	margin-block: -14px;
	overflow-x: auto;
	scroll-snap-type: x mandatory;
	scrollbar-width: none;
	-webkit-overflow-scrolling: touch;
}

/*
 * Fading, which is the default: every card in the same cell of a one-cell
 * grid, and only the one in view carrying any opacity. Nothing scrolls, so the
 * cards cannot be reached by dragging the track; the arrows, the dots and a
 * swipe move between them instead.
 */
.mn-blog-featured--fade .mn-blog-featured__track {
	display: grid;
	padding-block: 14px;
	margin-block: -14px;
	overflow: visible;
}

.mn-blog-featured--fade .mn-blog-featured__card {
	grid-area: 1 / 1;
	opacity: 0;
	visibility: hidden;
	transition:
		opacity 320ms ease,
		visibility 0s linear 320ms;
}

.mn-blog-featured--fade .mn-blog-featured__card.is-on {
	opacity: 1;
	visibility: visible;
	transition:
		opacity 320ms ease,
		visibility 0s;
}

/*
 * With no script nothing can set `is-on`, so the first card is shown and the
 * rest are simply not there. One featured post visible beats an empty box.
 */
html:not(.mn-js) .mn-blog-featured--fade .mn-blog-featured__card:first-child {
	opacity: 1;
	visibility: visible;
}

.mn-blog-featured--many .mn-blog-featured__track::-webkit-scrollbar {
	display: none;
}

.mn-blog-featured--slide .mn-blog-featured__card {
	flex: 0 0 100%;
	min-width: 0;
	scroll-snap-align: start;
}

/* A drag is a swipe, so nothing inside it should be selectable mid-gesture. */
.mn-blog-featured__track.is-dragging {
	cursor: grabbing;
}

.mn-blog-featured__track.is-dragging * {
	user-select: none;
	pointer-events: none;
}

/* ------------------------------------------------------ Reaching the edges */

/*
 * The picture runs from the edge of the screen to the middle of it; the words
 * stay inside the page, so they line up with the grid below rather than
 * floating somewhere the rest of the page never goes.
 *
 * The pull is `50% - 50vw` on each side, which takes the section out to the
 * viewport whatever the container has been set to. The words are put back with
 * a padding that is half of whatever the viewport has spare over the container,
 * and never less than the gutter, so on a narrow screen they still clear the
 * edge.
 */
.mn-blog-featured--full {
	position: relative;
	margin-inline: calc(50% - 50vw);
	/*
	 * Flush to the top, and clear of the grid below. A band running to both
	 * edges of the screen is a hero: it begins where the header ends, and a
	 * margin above it only ever reads as the band having missed.
	 */
	margin-top: 0;
	margin-bottom: var(--mn-space-lg);
}

/* And the page holds none above it either. */
.mn-blog-archive--hero {
	padding-top: 0;
}

.mn-blog-featured--full .mn-blog-featured__card {
	grid-template-columns: 50% minmax(0, 1fr);
	/* Fills the band, so the picture inside it does too. */
	height: 100%;
	border: 0;
	border-radius: 0;
	background: none;
	box-shadow: none;
}

.mn-blog-featured--full .mn-blog-featured__media {
	border-radius: 0;
}

.mn-blog-featured--full .mn-blog-featured__body {
	padding-left: var(--mn-space);
	padding-right: max(var(--mn-gutter), calc((100vw - var(--mn-container)) / 2));
	/*
	 * Room for the controls, which are out of the flow and take none of their
	 * own: the gap above them, their height, and the space they sit off the
	 * foot by.
	 */
	padding-bottom: calc(var(--mn-space) * 2 + var(--mn-control-h));
	/*
	 * And as much above the words as the controls take below them. The words
	 * were already an even 48 from the top edge and 48 from the controls; what
	 * made the card read as bottom-heavy is that the bottom carries a strip of
	 * furniture and the top carries nothing, so the whole block sat high in a
	 * column whose height comes from the photograph beside it.
	 */
	padding-top: calc(var(--mn-space) + var(--mn-control-h));
}

/*
 * The controls sit under the words rather than under the whole band, so the
 * carousel reads as belonging to the half it changes.
 *
 * Taken out of the flow to get there. In the flow they were a row beneath the
 * card, and the picture stopped at the card's foot while the band carried on
 * behind them: a strip of ground under a photograph that was meant to run the
 * height of the thing. The room they need is reserved by the words' own
 * padding instead.
 */
.mn-blog-featured--full .mn-blog-featured__controls {
	position: absolute;
	right: 0;
	bottom: var(--mn-space);
	left: 50%;
	margin: 0;
	padding-left: var(--mn-space);
	padding-right: max(var(--mn-gutter), calc((100vw - var(--mn-container)) / 2));
}

/*
 * On the dark band the controls are among light words, so they take the light.
 * The dots follow `currentColor` on their own; the arrows are drawn things and
 * are stated.
 */
.mn-blog-featured--full.mn-blog-featured--dark .mn-blog-featured__controls {
	color: var(--mn-surface);
}

.mn-blog-featured--full.mn-blog-featured--dark .mn-carousel-arrow {
	border-color: rgba(255, 255, 255, 0.25);
	background: transparent;
	color: var(--mn-surface);
}

/* The same gesture on a dark band: a shade of light rather than a colour. */
.mn-blog-featured--full.mn-blog-featured--dark .mn-carousel-arrow:hover {
	border-color: rgba(255, 255, 255, 0.45);
	background: rgba(255, 255, 255, 0.1);
	color: var(--mn-surface);
}

/* Nothing to clip a shadow that is no longer drawn. */
.mn-blog-featured--full .mn-blog-featured__track,
.mn-blog-featured--full.mn-blog-featured--fade .mn-blog-featured__track {
	padding-block: 0;
	margin-block: 0;
}

.mn-blog-featured--full.mn-blog-featured--dark {
	background: var(--mn-ink-deep);
}

/* --------------------------------------------------------- On a dark ground */

/*
 * The same card with the ground and the ink swapped. Only the surface colours
 * change: the shape, the spacing and the type are the light one's, because a
 * theme is what a thing is made of and not what it is.
 */
.mn-blog-featured--dark .mn-blog-featured__card {
	border-color: transparent;
	background: var(--mn-ink-deep);
}

.mn-blog-featured--dark .mn-blog-featured__title {
	color: var(--mn-surface);
}

/* On dark the shade goes the other way, since a darker ink would vanish. */
.mn-blog-featured--dark .mn-blog-featured__title a:hover {
	color: var(--mn-gray-300);
}

.mn-blog-featured--dark .mn-blog-featured__excerpt {
	color: var(--mn-gray-300);
}

.mn-blog-featured--dark .mn-blog-featured__date {
	color: var(--mn-gray-400);
}

.mn-blog-featured--dark .mn-blog-featured__media {
	background: var(--mn-gray-800);
}

.mn-blog-featured--dark .mn-post-card-readmore {
	color: var(--mn-surface);
}

/* ------------------------------------------------ Where you are, and where next */

.mn-blog-featured__controls {
	display: flex;
	justify-content: space-between;
	align-items: end;
	gap: var(--mn-gap-lg);
	margin-top: var(--mn-gap-lg);
}

.mn-blog-featured__dots {
	display: flex;
	align-items: center;
	gap: var(--mn-gap-xs);
	margin: 0;
	padding: 0;
	list-style: none;
}

/*
 * The dots take the colour of the words they sit among rather than a colour of
 * their own, so a row of them on a dark band is light without anything being
 * told which band it is on. Only the opacity separates the one you are on from
 * the rest.
 */
.mn-blog-featured__dot {
	display: block;
	width: 8px;
	height: 8px;
	padding: 0;
	border: 0;
	border-radius: var(--mn-radius-pill);
	background: currentColor;
	opacity: 0.25;
	cursor: pointer;
	transition:
		width 220ms ease,
		opacity 220ms ease;
}

.mn-blog-featured__dot:hover {
	opacity: 0.5;
}

/* The one you are on stretches, so the row reads as a position and not a count. */
.mn-blog-featured__dot.is-on,
.mn-blog-featured__dot.is-on:hover {
	width: 26px;
	opacity: 1;
}

.mn-blog-featured__dot:focus-visible {
	outline: 2px solid var(--mn-focus-outline);
	outline-offset: 3px;
}

.mn-blog-featured__arrows {
	display: flex;
	align-items: center;
	gap: var(--mn-gap);
	transition: opacity 180ms ease;
}

/*
 * Out of the way until wanted, where the setting asks for it. Shown is the
 * default: a control that is there is a control somebody can see before they
 * go looking for it.
 */
.mn-blog-featured--shy .mn-blog-featured__arrows {
	opacity: 0;
}

/* On hover, and on focus, so tabbing to an arrow still finds it. */
.mn-blog-featured--shy:hover .mn-blog-featured__arrows,
.mn-blog-featured--shy .mn-blog-featured__arrows:focus-within {
	opacity: 1;
}

/*
 * A touch screen has no hover, so a shy arrow would never appear. Shown
 * outright there, beside the swipe that already works.
 */
@media (hover: none) {

	.mn-blog-featured--shy .mn-blog-featured__arrows {
		opacity: 1;
	}
}

/*
 * Absent for a browser with no script, because they would do nothing: the
 * track still scrolls and snaps by hand, which is the part that matters.
 */
html:not(.mn-js) .mn-blog-featured__controls {
	display: none;
}

@media (prefers-reduced-motion: reduce) {

	.mn-blog-featured__dot,
	.mn-blog-featured__arrows {
		transition: none;
	}
}

/* --------------------------------------- Recent posts, and its search field */

.mn-blog-archive-head {
	display: flex;
	justify-content: space-between;
	align-items: flex-end;
	gap: var(--mn-gap-lg);
	margin-bottom: var(--mn-gap-xl);
}

/*
 * The name of a page, wherever a page has one: the blog, a subject, a search,
 * an article. One size and one weight, and they are `.mn-pagehead__title`'s,
 * which every page outside the blog already uses.
 *
 * There had been four. The blog was 40 at 500 and the FAQ agreed with it; a
 * category was 56 at 600, a search 48 at 500 and an article 52 at 500, each
 * with a `clamp` of its own and none of the four sizes on the type scale.
 */
.mn-blog-archive-title,
.mn-blog-category-title,
.mn-blog-search-title,
.mn-post-single-title {
	font-size: var(--mn-size-page-title);
	font-weight: var(--mn-weight-medium);
	line-height: var(--mn-leading-tight);
	letter-spacing: var(--mn-tracking-display);
	/* Long words in a heading this size overflow rather than wrap. */
	overflow-wrap: anywhere;
}

.mn-blog-archive-title {
	margin: 0 0 var(--mn-gap);
}

.mn-blog-archive-lead {
	max-width: 480px;
	margin: 0;
	color: var(--mn-gray-600);
	line-height: var(--mn-leading-body);
}

/*
 * The form around the site's own search field. Everything about how the field
 * looks, hovers and focuses is `.mn-search` in theme.css: it is the same box
 * here as on the listing, the favourites and the FAQ, which is the point of
 * there being one component.
 */
.mn-blog-search {
	display: flex;
	align-items: center;
	gap: var(--mn-gap-sm);
}

.mn-blog-search .mn-search {
	min-width: 260px;
}

.mn-blog-search--large {
	width: 100%;
	max-width: 560px;
}

.mn-blog-search--large .mn-search {
	flex: 1 1 auto;
	min-width: 0;
}

.mn-blog-search-submit {
	flex: none;
	gap: var(--mn-gap-xs);
}

/* ------------------------------------------------------------ The subjects */

.mn-blog-filter {
	display: flex;
	flex-wrap: wrap;
	gap: var(--mn-gap-sm);
	margin-bottom: 40px;
}

/*
 * What the arrows are positioned against, and where the row's space below it
 * lives once there is a wrapper to carry it.
 */
.mn-blog-filter-rail {
	position: relative;
	display: flex;
	align-items: center;
	margin-bottom: 40px;
}

.mn-blog-filter-rail .mn-blog-filter {
	margin-bottom: 0;
}

/*
 * The same row, scrolling instead of wrapping, chosen under Blog. The mask
 * and the fade classes are the site's rail, in theme.css beside the FAQ's
 * categories; what belongs to this row is that the pills keep their width
 * rather than being squeezed to fit.
 *
 * It scrolls at every width, and on a screen wide enough for all of them
 * that is indistinguishable from wrapping: a row only scrolls when it has to.
 */
.mn-blog-filter--slide {
	flex-wrap: nowrap;
	width: 100%;
}

.mn-blog-filter--slide .mn-blog-filter-pill {
	flex: 0 0 auto;
}

.mn-blog-filter-pill {
	display: inline-flex;
	align-items: center;
	gap: var(--mn-gap-sm);
	padding: 8px 16px;
	border-radius: var(--mn-radius);
	background: var(--mn-gray-100);
	color: var(--mn-gray-600);
	font-size: var(--mn-size-ui);
	text-decoration: none;
	transition:
		background-color 200ms ease,
		color 200ms ease,
		transform 150ms ease;
}

.mn-blog-filter-pill:hover {
	color: var(--mn-ink);
}

.mn-blog-filter-pill:active {
	transform: scale(0.97);
}

.mn-blog-filter-pill.is-on {
	background: var(--mn-gold-soft);
	color: var(--mn-gold-hover);
	font-weight: var(--mn-weight-medium);
}

/* --------------------------------------------------------------- The grid */

/*
 * Rows further apart than columns, and by more than the columns are apart.
 * A card is a tall thing, so two rows of them read as one continuous column of
 * text unless the space between the rows is clearly larger than the space
 * inside a card.
 */
.mn-blog-grid {
	display: grid;
	grid-template-columns: repeat(3, minmax(0, 1fr));
	gap: var(--mn-space-lg) var(--mn-gap-2xl);
	margin-bottom: var(--mn-space-lg);
}

/*
 * The grid is replaced in place when a subject is chosen rather than the page
 * being loaded again, so it fades out and back rather than blinking.
 */
.mn-blog-results {
	transition:
		opacity 220ms ease,
		transform 220ms ease;
	will-change: opacity, transform;
}

.mn-blog-results.is-swapping {
	opacity: 0;
	transform: translateY(6px);
	pointer-events: none;
}

.mn-blog-filter[aria-busy="true"] {
	pointer-events: none;
}

/* ------------------------------------------------------- A category's page */

.mn-blog-category-head {
	margin-bottom: 56px;
	padding-bottom: var(--mn-gap-2xl);
	border-bottom: 1px solid var(--mn-line);
}

.mn-blog-category-title {
	margin: var(--mn-gap-lg) 0;
	color: var(--mn-ink);
}

.mn-blog-category-desc {
	max-width: 640px;
	margin: 0 0 14px;
	color: var(--mn-gray-600);
	font-size: var(--mn-size-lg);
	line-height: var(--mn-leading-body);
}

.mn-blog-category-count,
.mn-blog-search-count {
	margin: 0;
	color: var(--mn-gray-500);
	font-family: var(--mn-font-mono);
	font-size: var(--mn-size-xs);
	letter-spacing: var(--mn-tracking-mono);
	text-transform: uppercase;
}

.mn-blog-category-back {
	margin-top: var(--mn-gap-lg);
}

/* ---------------------------------------------------------- Search results */

.mn-blog-search-head {
	margin-bottom: 56px;
	padding-bottom: var(--mn-gap-2xl);
	border-bottom: 1px solid var(--mn-line);
}

.mn-blog-search-title {
	margin: var(--mn-gap-lg) 0 var(--mn-gap-md);
	color: var(--mn-ink);
}

.mn-blog-search-count {
	margin-bottom: 28px;
}

/* -------------------------------------------------------- An article's top */

/*
 * A wash rather than a colour, so the hero is a shade darker than whatever the
 * page is standing on. Set to the canvas it was one shade off the page's own
 * off-white and the two ran together; a fixed grey would only move the problem
 * to whichever ground it was not picked for.
 */
.mn-post-single-head {
	background: var(--mn-wash);
}

/*
 * The picture to the edge of the screen, the words on the other half. The
 * words carry the page's own inset on their outer side so the title lines up
 * with the article beneath it, which is the same arrangement the blog's
 * leading post takes at full width.
 */
.mn-post-single-hero {
	display: grid;
	grid-template-columns: repeat(2, minmax(0, 1fr));
	align-items: center;
}

.mn-post-single-intro {
	padding-block: var(--mn-space-lg);
	padding-left: var(--mn-space);
	padding-right: max(var(--mn-gutter), calc((100vw - var(--mn-container)) / 2));
}

/*
 * On a dark ground, chosen under Blog. The band takes a colour rather than the
 * wash: a wash is a way of darkening whatever is underneath, and here the
 * point is to be a band of its own before the reading starts.
 */
.mn-post-single-head--dark {
	background: var(--mn-ink-deep);
}

.mn-post-single-head--dark .mn-post-single-title {
	color: var(--mn-surface);
}

.mn-post-single-head--dark .mn-post-single-standfirst {
	color: var(--mn-gray-300);
}

.mn-post-single-head--dark .mn-post-single-date {
	color: var(--mn-gray-400);
}

/* The trail and its marks, which follow the words they sit among. */
.mn-post-single-head--dark .mn-crumbs__list {
	color: var(--mn-gray-400);
}

.mn-post-single-head--dark .mn-crumbs__link:hover,
.mn-post-single-head--dark .mn-crumbs__current {
	color: var(--mn-surface);
}

/* Behind the picture while it loads, so the gap is not a light rectangle. */
.mn-post-single-head--dark .mn-post-single-thumb {
	background: var(--mn-gray-800);
}

/*
 * The trail is the first line of this column, not a band across the page, so
 * it wears none of the strip's furniture: no rule under it, no margins of its
 * own, just the gap to the chip beneath it.
 */
.mn-post-single-intro .mn-crumbs {
	margin-bottom: var(--mn-gap-2xl);
}

/*
 * The sentence the article opens with, repeated here because the hero is
 * where somebody decides whether to read on. Held to the reading measure: a
 * line that runs the full half of a wide screen is one nobody finishes.
 */
.mn-post-single-standfirst {
	max-width: 46ch;
	margin: 0 0 var(--mn-gap-2xl);
	color: var(--mn-gray-600);
	font-size: var(--mn-size-base);
	line-height: var(--mn-leading-body);
}

/*
 * The theme's own breadcrumb, wearing cornytis's clothes. One component, two
 * appearances, rather than a second breadcrumb that has to be kept in step.
 */
/*
 * The trail, wherever a page has one: its own strip with a rule under it, so
 * it reads as where-you-are rather than as the first line of what follows.
 *
 * Named for the job and not for the article, because the article was the only
 * page that had it and that was the difference somebody noticed.
 *
 * Inside the container rather than being one. A border on the container is
 * drawn on its border box, which is outside its gutter, so the rule ran the
 * width of the screen's column while everything under it started seventy
 * pixels in.
 */
.mn-page-trail {
	padding-bottom: var(--mn-gap-lg);
	margin-bottom: var(--mn-gap-xl);
	border-bottom: 1px solid var(--mn-gray-200);
}


.mn-post-single-cat {
	display: inline-flex;
	align-items: center;
	gap: var(--mn-gap-sm);
	margin: 0 0 18px;
	padding: 6px 10px;
	border-radius: var(--mn-radius-pill);
	background: var(--mn-gold-soft);
	color: var(--mn-gold-hover);
	font-family: var(--mn-font-mono);
	font-size: var(--mn-size-micro);
	letter-spacing: var(--mn-tracking-mono);
	line-height: var(--mn-leading-ui);
	text-transform: uppercase;
}

.mn-post-single-title {
	margin: 0 0 var(--mn-gap-md);
}

.mn-post-single-date {
	margin: 0;
	color: var(--mn-gray-600);
	font-size: var(--mn-size-ui);
}

/*
 * No corners and no ratio of its own: it is a half of the band, and its height
 * comes from the words beside it, exactly as the leading post's picture does.
 *
 * The picture is taken out of the flow to make that true. Left in it, the file
 * s own proportions set the height of the whole band, so a tall photograph
 * made a tall hero whatever the words needed. The floor is there for the
 * opposite case, an article with a short title and no standfirst.
 */
.mn-post-single-thumb {
	position: relative;
	/* The words are centred in the band; the picture fills it. */
	align-self: stretch;
	min-height: var(--mn-featured-media);
	overflow: hidden;
	background: linear-gradient(135deg, var(--mn-gray-100), var(--mn-sand));
}

.mn-post-single-thumb img {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	object-fit: cover;
}

/* ------------------------------------------------------- An article's body */

.mn-post-single-grid {
	display: grid;
	grid-template-columns: minmax(0, 1fr) var(--mn-rail);
	gap: var(--mn-space-lg);
	align-items: flex-start;
	/* Inside the column, so it is space under the article and not under the
	   callout that follows it. */
	padding: var(--mn-space-lg) 0 88px;
	/*
	 * How wide an article reads, chosen under Blog. The cap is on the grid,
	 * not on the words alone: capping the article and leaving the rail where
	 * it was would pull the contents list away from the text it belongs to
	 * and leave a gap between them that nothing fills. The two come in
	 * together, still a pair.
	 *
	 * The measure is said in characters because it is a count of letters and
	 * stays right when the type size changes; the rail and the gap are added
	 * in their own units, so the article column is the measure and no less.
	 */
	max-width: calc( var( --mn-post-measure ) + var( --mn-space-lg ) + var( --mn-rail ) );
	margin-inline: auto;
	/*
	 * The article is .mn-prose, which caps itself at --mn-measure. Wide would
	 * have widened the grid and left the words at seventy characters with the
	 * rail pushed away from them. The token is redefined here rather than the
	 * property overridden below, so prose keeps one answer to its own width.
	 */
	--mn-measure: var( --mn-post-measure );
}

.mn-post-single-grid--narrow {
	--mn-post-measure: 58ch;
}

.mn-post-single-grid--medium {
	--mn-post-measure: 72ch;
}

.mn-post-single-grid--wide {
	--mn-post-measure: 88ch;
}

.mn-post-single-rail {
	position: sticky;
	top: var(--mn-rail-top);
	display: flex;
	flex-direction: column;
	gap: var(--mn-gap-xl);
}

.mn-post-single-rail-title {
	margin: 0 0 var(--mn-gap-lg);
	color: var(--mn-ink);
	font-size: var(--mn-size-base);
	font-weight: var(--mn-weight-bold);
	line-height: var(--mn-leading-ui);
}

/* Anchors, so a jump from the contents lands clear of the sticky header. */
.mn-post-single-body :is(h2, h3)[id] {
	scroll-margin-top: var(--mn-rail-top);
}

.mn-post-toc-list {
	display: flex;
	flex-direction: column;
	gap: var(--mn-gap-2xs);
	margin: 0;
	padding: 0;
	border-left: 1px solid var(--mn-line);
	list-style: none;
}

.mn-post-toc-list li {
	position: relative;
	padding-left: var(--mn-gap-lg);
}

/*
 * The mark sits on the rule rather than beside it, so the line runs unbroken
 * down the list and only the section being read is picked out of it.
 */
.mn-post-toc-list li::before {
	content: "";
	position: absolute;
	left: -1px;
	top: 8px;
	bottom: 8px;
	width: 2px;
	border-radius: var(--mn-radius-xs);
	background: transparent;
	transition: background-color 150ms ease;
}

.mn-post-toc-list li:has(a.is-on)::before {
	background: var(--mn-gold);
}

.mn-post-toc-list a {
	display: block;
	padding: 6px 0;
	color: var(--mn-gray-600);
	font-size: var(--mn-size-ui);
	line-height: var(--mn-leading-ui);
	text-decoration: none;
}

.mn-post-toc-list a:hover,
.mn-post-toc-list a.is-on {
	color: var(--mn-gold-hover);
}

.mn-post-toc-h3 a {
	padding-left: 12px;
	font-size: var(--mn-size-small);
}

.mn-post-related-list {
	display: flex;
	flex-direction: column;
	gap: var(--mn-gap-lg);
	margin: 0;
	padding: 0;
	list-style: none;
}

.mn-post-related-item {
	padding-top: 22px;
	border-top: 1px solid var(--mn-line);
}

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

.mn-post-related-cat {
	display: inline-flex;
	align-items: center;
	gap: var(--mn-gap-xs);
	margin: 0 0 6px;
	color: var(--mn-gold-hover);
	font-family: var(--mn-font-mono);
	font-size: var(--mn-size-micro);
	letter-spacing: var(--mn-tracking-mono);
	text-transform: uppercase;
}

.mn-post-related-title {
	display: block;
	margin-bottom: 6px;
	color: var(--mn-ink);
	font-size: var(--mn-size-base);
	font-weight: var(--mn-weight-bold);
	line-height: var(--mn-leading-snug);
	text-decoration: none;
}

.mn-post-related-title:hover {
	color: var(--mn-gold-hover);
}

.mn-post-related-date {
	margin: 0;
	color: var(--mn-gray-500);
	font-size: var(--mn-size-xs);
}

/* ------------------------------------------------------------ On a tablet */

@media (max-width: 960px) {
	.mn-blog-featured__card {
		grid-template-columns: minmax(0, 1fr);
	}

	/*
	 * Stacked, the picture has no words beside it to take its height from, so
	 * it goes back to a ratio.
	 */
	.mn-blog-featured__media {
		min-height: 0;
		aspect-ratio: 16 / 9;
	}

	.mn-blog-featured__body {
		padding: var(--mn-gap-xl) var(--mn-gap-lg);
	}

	/*
	 * Stacked, half the width is not a column any more. The picture keeps the
	 * whole width and the words come back inside the page.
	 */
	.mn-blog-featured--full .mn-blog-featured__card {
		grid-template-columns: minmax(0, 1fr);
	}

	.mn-blog-featured--full .mn-blog-featured__body,
	.mn-blog-featured--full .mn-blog-featured__controls {
		padding-left: var(--mn-gutter);
		padding-right: var(--mn-gutter);
	}

	/*
	 * Back into the flow. Stacked there is no second column to hold them
	 * against, and absolute controls would sit over the words.
	 */
	.mn-blog-featured--full .mn-blog-featured__controls {
		position: static;
	}

	/*
	 * Stacked, both ends are stated here. The wide layout insets the top by
	 * the depth of its control strip, and that rule carries two classes to
	 * this one's one, so it wins across the media query and left a phone with
	 * ninety-odd pixels above the words. Saying the whole block here settles
	 * it rather than answering it with a third rule.
	 */
	.mn-blog-featured--full .mn-blog-featured__body {
		padding-block: var(--mn-gap-xl);
	}

	.mn-blog-featured--full {
		margin-bottom: var(--mn-gap-xl);
		padding-bottom: var(--mn-gap-xl);
	}

	.mn-blog-archive-head {
		flex-direction: column;
		align-items: stretch;
	}

	.mn-blog-search,
	.mn-blog-search .mn-search {
		min-width: 0;
		width: 100%;
	}

	.mn-blog-grid {
		grid-template-columns: repeat(2, minmax(0, 1fr));
		gap: var(--mn-space) var(--mn-gap-lg);
	}

	/*
	 * Stacked, and the words first. The trail is in this column now, so
	 * leading with the picture put the way back below a screenful of
	 * photograph; the source order is the wide layout's, where the picture is
	 * the left half, so the order is stated here rather than in the markup.
	 */
	.mn-post-single-hero {
		grid-template-columns: minmax(0, 1fr);
	}

	.mn-post-single-intro {
		order: -1;
		padding: var(--mn-space) var(--mn-gutter);
	}

	/*
	 * Stacked, the picture has no words beside it to take its height from, so
	 * it goes back to a ratio, the way the leading post's does.
	 */
	.mn-post-single-thumb {
		min-height: 0;
		aspect-ratio: 16 / 9;
	}

	.mn-post-single-grid {
		grid-template-columns: minmax(0, 1fr);
		gap: var(--mn-gap-2xl);
		padding: 40px 0 56px;
		/* The rail is under the article now, not beside it, so the cap is the
		   measure on its own. */
		max-width: var(--mn-post-measure);
	}

	/*
	 * The rail stops following and goes under the article. A block pinned to
	 * the top of a phone covers the thing it is meant to help you read.
	 */
	.mn-post-single-rail {
		position: static;
		gap: var(--mn-gap-xl);
	}

	/* The contents list is for a screen tall enough to keep it beside you. */
	.mn-post-single-toc {
		display: none;
	}


/* ------------------------------------------------------------- On a phone */

@media (max-width: 560px) {
	.mn-blog-grid {
		grid-template-columns: minmax(0, 1fr);
		gap: var(--mn-space);
	}

	.mn-blog-featured {
		margin-bottom: var(--mn-gap-xl);
	}

	.mn-blog-featured__card {
		border-radius: var(--mn-radius-xl);
	}

	/*
	 * The one big thing on the screen. The card is the whole width of a phone
	 * and the page's own name is above it, so the title can take the step the
	 * scale keeps for a lead.
	 */
	.mn-blog-featured__title {
		font-size: var(--mn-size-lead);
	}

	/* And the words under it step back, so the two are not one grey block. */
	.mn-blog-featured__excerpt {
		font-size: var(--mn-size-ui);
	}

	.mn-blog-search-head,
	.mn-blog-category-head {
		margin-bottom: var(--mn-gap-2xl);
		padding-bottom: var(--mn-gap-xl);
	}

	/* The button goes; returning from the keyboard submits the form. */
	.mn-blog-search--large .mn-blog-search-submit {
		display: none;
	}

	/* The band carries no padding of its own; the words inside it do. */
	.mn-post-single-intro {
		padding: var(--mn-gap-xl) var(--mn-gutter);
	}

	.mn-post-single-grid {
		gap: var(--mn-gap-xl);
		padding: var(--mn-gap-xl) 0 40px;
	}

	.mn-post-related-list {
		gap: var(--mn-gap-lg);
	}
}

@media (prefers-reduced-motion: reduce) {

	.mn-blog-results,
	.mn-blog-filter-pill {
		transition: none;
	}

	.mn-blog-results.is-swapping {
		transform: none;
	}
}