/* ===== Hardline — full stylesheet (loaded async) ===== */

:root {
	--bg: #ffffff;
	--fg: #111111;
	--muted: #555555;
	--meta: #666666;
	--line: #e5e5e5;
	--bubble: #f2f3f5;
	--sans: -apple-system, BlinkMacSystemFont, "SF Pro Text", "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
	/* One knob for the page width. Article pages want a 720px reading measure;
	   the homepage is scanned rather than read and overrides this below. */
	--container: 720px;
	/* The site header's own measure, deliberately not --container. A logo and a
	   menu are not read line by line, so the frame around them has no reason to
	   narrow with the text inside it — and it did, which meant the header
	   measured 680px on an article and 1080px on the front page, so the same
	   header looked like two different headers depending on the template. It
	   takes the widest measure the site uses and stays there. Only the header:
	   the reading column is unaffected. */
	--container-nav: 1120px;
	/* That same reading column with .container's 20px of side padding taken off,
	   for the one place that sits inside a wider frame and still has to match an
	   article's text width — the tools hub. */
	--measure: 680px;
	/* The scrim over a tool card's photograph. Deliberately not an even fade:
	   the picture is left alone until the last 240px and the whole ramp is spent
	   on the caption, so the top of the card is a photograph and only the part
	   the words sit on is darkened. It stops at 70% rather than solid black —
	   past that the picture stops being a picture, which is the only reason it
	   is there. The caption is bottom-anchored, so the stops are measured from
	   the bottom and do not drift when a description runs to a different number
	   of lines. */
	--tool-scrim: linear-gradient(
		to bottom,
		rgba( 0, 0, 0, 0 ) 0,
		rgba( 0, 0, 0, 0 ) calc( 100% - 240px ),
		rgba( 0, 0, 0, .44 ) calc( 100% - 180px ),
		rgba( 0, 0, 0, .62 ) calc( 100% - 110px ),
		rgba( 0, 0, 0, .70 ) 100%
	);
	/* The mark's blue (assets/images/brand/logo-lockup.svg). It is used as type
	   in one place — the rail's tools row on the homepage — and nowhere else,
	   because the rest of the site is monochrome on purpose and an accent only
	   reads as an accent while it is the only one. (The tools hub used it too
	   until the cards became photographs, which are dark in both themes and
	   need white captions.)
	   11.5:1 on the page background, so it holds up as text and not just as a
	   block of colour. */
	--brand: #1e3a5f;
	/* A failed comment submission has to look different from a successful one,
	   and muted grey cannot carry that. This is the only colour in the theme
	   whose job is purely functional. Both values clear 7:1 on their own
	   background, so it reads as text in either theme. */
	--danger: #b3261e;
}
.dark {
	--bg: #0f0f0f;
	--fg: #ededed;
	--muted: #9a9a9a;
	--meta: #8a8a8a;
	--line: #2a2a2a;
	--bubble: #1e1e1e;
	/* Same hue, lifted. #1e3a5f is 1.7:1 against #0f0f0f, which is unreadable
	   as type; this is the lightest value that still reads as the same blue. */
	--brand: #7ca7de;
	--danger: #ff6b5e;
}

* { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body {
	margin: 0;
	background: var(--bg);
	color: var(--fg);
	font-family: var(--sans);
	font-size: 17px;
	line-height: 1.7;
	transition: background-color .2s ease, color .2s ease;
}
img { max-width: 100%; height: auto; display: block; }
a { color: var(--fg); text-decoration: underline; text-underline-offset: 3px; }
a:hover { text-decoration-thickness: 2px; }
h1, h2, h3, h4 { font-family: var(--sans); font-weight: 600; line-height: 1.25; margin: 1.4em 0 .5em; }
h1 { font-size: 2em; }
h2 { font-size: 1.6em; }
h3 { font-size: 1.25em; }
p { margin: 0 0 1.2em; }
.container { max-width: var(--container); margin: 0 auto; padding: 0 20px; }
.skip-link { position: absolute; left: -9999px; top: 0; background: var(--fg); color: var(--bg); padding: 8px 12px; z-index: 999; }
.skip-link:focus { left: 0; }
.screen-reader-text { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }

/* Header */
.site-header { border-bottom: 1px solid var(--line); }
/* Declared after .container so it wins on equal specificity: same box, wider
   measure. Everything else that uses .container keeps the reading column. */
.header-inner { display: flex; align-items: center; gap: 16px; padding-top: 14px; padding-bottom: 14px; max-width: var( --container-nav ); }
.site-logo { display: inline-flex; align-items: center; text-decoration: none; }
.site-logo-img { display: block; height: 40px; width: auto; }
.site-logo .logo-dark { display: none; }
.dark .site-logo .logo-light { display: none; }
.dark .site-logo .logo-dark { display: block; }
.custom-logo { max-height: 40px; width: auto; }
.site-nav { margin-left: auto; }
.nav-menu { display: flex; gap: 20px; list-style: none; margin: 0; padding: 0; }
.nav-menu a { text-decoration: none; font-size: .95em; }
.nav-menu .current-menu-item > a { text-decoration: underline; text-underline-offset: 4px; }
.theme-toggle { border: 1px solid var(--line); background: none; color: var(--fg); width: 34px; height: 34px; border-radius: 50%; cursor: pointer; font-size: 16px; line-height: 1; }
.nav-toggle { display: none; border: 0; background: none; cursor: pointer; padding: 8px; }
.nav-toggle span { display: block; width: 20px; height: 2px; background: var(--fg); margin: 4px 0; }

/* Ads */
.ad-slot { margin: 24px auto; text-align: center; overflow: hidden; }
.ad-slot--header { margin: 16px auto; }
.ad-slot--content { margin: 28px auto; }

/* Index pages
   Article pages keep the 720px reading measure. The front page takes the full
   width on desktop, because it is scanned, not read line by line, and because in
   a 720px column the old layout left two thirds of a large screen empty.
   Every difference between phone and desktop below is CSS grid or a media
   query. The markup is the same on both, and there is no JavaScript. */
body.home:not(.paged) { --container: 1120px; }

/* The tools hub is both an index and an article, and giving each of those its
   own width is what made the page read as two pages: cards spanning 1080px over
   prose spanning 680px, with the heading somewhere in between. So it keeps the
   wide frame and puts everything inside it in the reading measure — the same
   680px an article column gets — which leaves the space on either side as real
   layout, not spill: that is where side ad units go.
   The frame is kept rather than dropped because dropping it would mean the ad
   gutters had to be re-cut later; as it stands, adding a unit there is additive. */
body.tools-hub { --container: 1120px; }
body.tools-hub .page-single { max-width: var( --measure ); margin-inline: auto; }

/* The masthead shared by index pages: the site name or the page title, then a
   standfirst. It is named for the role rather than for the homepage because the
   tools hub uses the same one — see page-tools.php. */
.index-header { margin: 2.4em 0 1.4em; }
.index-title { font-size: 2.4em; line-height: 1.04; letter-spacing: -.02em; margin: 0; }
.index-tagline { color: var(--muted); margin: .6em 0 0; font-size: 1em; max-width: 44em; }

/* The hero: the section index and the lead story in one grid.
   On a phone the index is a single scrolling row above the story. A rail would
   leave about 250px for the article the page exists to show, so the vertical
   column waits for the width to justify it (see the 1000px block). */
.home-hero { display: grid; gap: 26px; margin: 0 0 2.8em; }

.home-sections { min-width: 0; }
.home-sections-label {
	margin: 0 0 8px;
	font-size: .72em;
	font-weight: 700;
	letter-spacing: .12em;
	text-transform: uppercase;
	color: var(--muted);
}

/* Departments: every category reachable without scrolling.
   It scrolls sideways rather than wrapping, so the band stays one line on a
   phone instead of turning into a paragraph of chips. */
.home-departments {
	display: flex;
	border-top: 2px solid var(--fg);
	border-bottom: 1px solid var(--line);
	overflow-x: auto;
	-webkit-overflow-scrolling: touch;
	scrollbar-width: none;
}
.home-departments::-webkit-scrollbar { display: none; }
.home-departments a {
	display: flex;
	align-items: baseline;
	gap: 7px;
	flex: 1 0 auto;
	padding: 12px 18px;
	border-left: 1px solid var(--line);
	font-size: .86em;
	font-weight: 600;
	text-decoration: none;
	white-space: nowrap;
}
.home-departments a:first-child { border-left: 0; padding-left: 0; }
.home-departments a:hover { text-decoration: underline; text-underline-offset: 4px; }
.home-departments-count { color: var(--muted); font-size: .8em; font-weight: 400; }

/* The tools hub, leading the rail. It is the only row here that is not a
   category, and the only colour on the page. Everything about it is the
   standard row — same box, same padding, same hairline — except the type, which
   is the brand blue rather than black. The colour is the whole of the signal, so
   anything else added on top of it would be a second one competing with it.
   Its trailing element is an arrow rather than a count, because this row leaves
   the archive instead of filtering it. */
.home-departments a.home-departments-tools {
	justify-content: space-between;
	gap: 14px;
	color: var(--brand);
}
.home-departments-arrow { font-weight: 400; }
/* The collapse row. Muted, because it is an exit from the index rather than
   another section in it. */
.home-departments-more { color: var(--muted); }

/* Lead story */
.home-lead { min-width: 0; }
.lead-story { display: grid; gap: 20px; }
.lead-body { min-width: 0; }
.lead-figure { margin: 0; }
.lead-figure img { width: 100%; aspect-ratio: 3 / 2; object-fit: cover; }
.lead-kicker {
	margin: 0 0 .8em;
	font-size: .74em;
	font-weight: 700;
	letter-spacing: .11em;
	text-transform: uppercase;
	color: var(--muted);
}
.lead-title { font-size: 1.75em; line-height: 1.14; letter-spacing: -.015em; margin: 0 0 .55em; }
.lead-title a { text-decoration: none; }
.lead-title a:hover { text-decoration: underline; text-underline-offset: 4px; }
.lead-standfirst { color: var(--muted); margin: 0 0 .8em; font-size: 1.02em; }
.lead-meta { margin: 0; font-size: .85em; color: var(--meta); }

/* The next three, in a tinted band so the top of the page has a floor.
   The negative side margin runs it to the screen edges on a phone and stops it
   at the container on desktop — no full-bleed 100vw trick, which would drag a
   horizontal scrollbar into the page. */
.home-band {
	background: var(--bubble);
	border-top: 1px solid var(--line);
	border-bottom: 1px solid var(--line);
	margin: 0 -20px 3em;
	padding: 26px 20px 30px;
}
.home-band .section-head { margin-top: 0; }

/* Section heads: the rule belongs to the head, so the "All 12 →" link sits on
   the same line as the title instead of below a border that stops halfway. */
.section-head {
	display: flex;
	align-items: baseline;
	justify-content: space-between;
	gap: 16px;
	border-bottom: 2px solid var(--fg);
	margin: 2.8em 0 1.2em;
}
.section-head .section-title { border-bottom: 0; margin: 0; padding-bottom: 8px; }
/* .section-more is a link, .section-count is the same thing where there is
   nowhere to go — the tools hub counts its tools and has no "all" page. */
.section-more,
.section-count { flex: 0 0 auto; padding-bottom: 8px; font-size: .8em; color: var(--muted); text-decoration: none; white-space: nowrap; }
.section-more:hover { color: var(--fg); text-decoration: underline; text-underline-offset: 4px; }

/* One column, then two, then three. */
.grid { display: grid; gap: 30px 24px; grid-template-columns: 1fr; }

/* Grid cards, homepage and tools hub. Their own class names — see
   template-parts/home-card.php for why they do not reuse .post-card: that
   component is a two-column text-beside-thumbnail card driven by
   grid-template-areas, and it collapses in a three-across grid. The chrome here
   mirrors the archive cards so the two read as one family. The hairline is an
   addition, because the archive card leans on its shadow alone and a shadow is
   invisible against the dark theme. */
.home-card,
.tool-card {
	display: flex;
	flex-direction: column;
	background: var(--bg);
	border: 1px solid var(--line);
	border-radius: 14px;
	overflow: hidden;
	box-shadow: 0 1px 3px rgba( 0, 0, 0, .07 );
}
.home-card-thumb { margin: 0; }
.home-card-thumb img { width: 100%; aspect-ratio: 3 / 2; object-fit: cover; transition: transform .35s ease; }
.home-card-body { padding: 14px 16px 16px; }
.home-card-title { font-size: 1.06em; line-height: 1.32; margin: 0 0 6px; }
.home-card-title a { color: inherit; text-decoration: none; }
.home-card-title a:hover { text-decoration: underline; text-underline-offset: 4px; }
.home-card-meta { margin: 0; font-size: .85em; color: var(--meta); }

/* Tool cards, on the tools hub. Each one is a photograph with its caption on
   the lower part of it, so every colour in here is white: the card is dark in
   both themes, because a photograph is, and a caption that flipped to black in
   light mode would be unreadable over one.
   The whole card is clickable while the link text stays just the title, so a
   screen reader announces a name rather than a paragraph. */
.tool-card {
	position: relative;
	/* Keeps the negative z-index below from escaping to an ancestor stacking
	   context. Without it the image would paint behind the card's own
	   background instead of in front of it. */
	isolation: isolate;
	justify-content: flex-end;
	padding: 0;
	color: #fff;
	/* Without a photograph the card keeps its shape as a block of the mark's
	   blue, rather than collapsing, so a tool published without a picture does
	   not break the row it sits in. */
	background: var(--brand);
	transition: box-shadow .2s ease;
}
/* Dark mode needs the page's own raised surface instead: --brand is lifted to
   #7ca7de there, and white type on it is 2.5:1. */
.dark .tool-card { background: var(--bubble); }
.tool-card--image { aspect-ratio: 3 / 4; }

.tool-card-media { position: absolute; inset: 0; z-index: -1; }
.tool-card-media img { display: block; width: 100%; height: 100%; object-fit: cover; }
/* Positioned, and after the image in tree order, so it paints over it. */
.tool-card-media::after { content: ""; position: absolute; inset: 0; background: var(--tool-scrim); }

/* Deliberately not positioned: the stretched link below resolves `inset: 0`
   against the nearest positioned ancestor, and if this wrapper were one the
   link would cover the caption instead of the card. It does not need to be —
   the media sits at z-index -1, so the caption is above it in the normal flow. */
.tool-card-body { padding: 18px 18px 16px; }

.tool-card-title { font-size: 1.24em; line-height: 1.26; letter-spacing: -.01em; margin: 0 0 8px; }
.tool-card-title a { color: inherit; text-decoration: none; }
.tool-card-title a::after { content: ""; position: absolute; inset: 0; }
.tool-card-desc { margin: 0; font-size: .95em; color: rgba( 255, 255, 255, .86 ); }
.tool-card:hover { box-shadow: 0 3px 14px rgba( 0, 0, 0, .18 ); }
.tool-card:hover .tool-card-title a { text-decoration: underline; text-underline-offset: 4px; }
/* The stretched link's own focus ring is a few characters wide, which does not
   say which card you are on. */
.tool-card:focus-within { outline: 2px solid var(--fg); outline-offset: 2px; }

/* The hub's standfirst: the page's own preamble, before its first heading. */
.tools-intro > *:first-child { margin-top: 0; }
.tools-intro > *:last-child { margin-bottom: 0; }
.tools-intro p { margin: 0 0 .7em; }
/* Photograph credits, gathered from the images' captions. Quiet, but not hidden:
   it is an attribution, so it has to be readable rather than decorative. */
.tools-credits { margin: 2.4em 0 0; font-size: .8em; line-height: 1.5; color: var(--meta); }

/* A hover effect only a pointer can produce. */
@media (hover: hover) {
	.home-card-thumb a:hover img { transform: scale(1.04); }
}

@media (min-width: 640px) {
	.grid--3 { grid-template-columns: repeat(2, 1fr); }
	.index-title { font-size: 2.9em; }
	.lead-title { font-size: 2.15em; }
}

@media (min-width: 1000px) {
	.grid--3 { grid-template-columns: repeat(3, 1fr); }
	/* Two across on the hub, never three. Three columns fit the homepage's
	   1080px; inside the hub's 680px reading column the same rule would make
	   every card 210px wide, which is narrower than the thumbnail-less card was
	   designed for. */
	body.tools-hub .grid--3 { grid-template-columns: repeat(2, 1fr); }
	.index-header { margin: 2em 0 1.2em; }
	.index-title { font-size: 3.2em; }
	/* The rail. 244px holds the longest section name and its count and still
	   leaves the story over 650px wide at the narrowest desktop size. */
	.home-hero {
		grid-template-columns: 244px minmax(0, 1fr);
		gap: 48px;
		align-items: start;
		margin-bottom: 3.4em;
	}
	.home-sections-label { margin-bottom: 10px; }
	/* The index turns upright here. It was a scrolling row because the page had
	   no width to spare; the rail exists because now it does. */
	.home-departments {
		flex-direction: column;
		overflow-x: visible;
	}
	.home-departments a {
		border-left: 0;
		border-bottom: 1px solid var(--line);
		padding: 13px 0;
		flex: 0 0 auto;
		justify-content: space-between;
	}
	.home-departments a:last-child { border-bottom: 0; }
	/* A banner, not a poster. The headline below it has to clear the fold, and
	   the maths is width-dependent: at 1000px viewport the column is 675px wide,
	   at 1120px and up it stops at 788px, which made a purely proportional box
	   50px taller exactly where screens are widest. The cap pins it instead, so
	   the fold position is the same at every desktop width.
	   The source photographs are portrait, so a shallow box keeps only a central
	   band — that is the real cost of this, and it is why the cap is 300px and
	   not less. */
	.lead-figure img {
		aspect-ratio: 21 / 9;
		max-height: 300px;
	}
	.lead-title { font-size: 2.4em; }
}
.section-title { font-size: 1.4em; border-bottom: 2px solid var(--fg); padding-bottom: 6px; margin: 1.6em 0 .6em; }
.section-title a { text-decoration: none; }
.post-card { padding: 18px 0; border-bottom: 1px solid var(--line); }
.post-card:last-child { border-bottom: 0; }
.post-card-title { font-size: 1.15em; margin: 0 0 4px; }
.post-card-title a { text-decoration: none; }
.post-card-title a:hover { text-decoration: underline; }
.post-card-meta { font-size: .85em; color: var(--muted); margin: 0 0 6px; }
.post-card-excerpt { margin: 0; font-size: .95em; color: var(--muted); }
.post-card-thumb { margin: 0 0 10px; }

/* Single */
.post-header { margin: 2em 0 1em; }
.post-title { font-size: 2.1em; margin: 0 0 .3em; line-height: 1.2; }
.post-meta { font-size: .9em; color: var(--muted); margin: 0 0 1em; }
.post-meta a { color: var(--muted); }
.post-thumb { margin: 0 0 1.5em; }
.post-content { font-size: 1.05em; }
.post-content h2 { padding-top: .5em; }
.post-content ul, .post-content ol { margin: 0 0 1.2em 1.4em; padding: 0; }
.post-content blockquote { margin: 1.5em 0; padding: .2em 0 .2em 1.2em; border-left: 3px solid var(--fg); font-style: italic; color: var(--muted); }
.post-content figure { margin: 1.5em 0; }
.post-content figcaption { font-size: .85em; color: var(--muted); text-align: center; margin-top: .4em; }
.post-content code { background: var(--line); padding: .1em .35em; font-size: .9em; }
.post-content pre { background: var(--line); padding: 1em; overflow-x: auto; font-size: .9em; }
.post-content table { width: 100%; border-collapse: collapse; margin: 0 0 1.2em; }
.post-content th, .post-content td { border: 1px solid var(--line); padding: .5em .75em; text-align: left; }
.wp-caption { max-width: 100%; }
.page-links { margin: 1.5em 0; }

/* TOC */
.toc { border: 1px solid var(--line); padding: 16px 20px; margin: 0 0 1.8em; font-size: .92em; }
.toc-title { margin: 0 0 8px; font-family: var(--sans); font-weight: 700; }
.toc ol { margin: 0; padding-left: 1.2em; }
.toc li { margin: 4px 0; }
.toc a { text-decoration: none; }
.toc a:hover { text-decoration: underline; }

/* Breadcrumbs */
.breadcrumbs { font-size: .85em; color: var(--muted); margin: 1.2em 0 0; }
.breadcrumbs a { color: var(--muted); text-decoration: none; }
.breadcrumbs a:hover { text-decoration: underline; }
.breadcrumbs .sep { margin: 0 6px; }

/* Author box */
.author-box { display: flex; gap: 16px; border-top: 1px solid var(--line); border-bottom: 1px solid var(--line); padding: 20px 0; margin: 2em 0; }
.author-box img { border-radius: 50%; width: 64px; height: 64px; }
.author-box-name { margin: 0 0 4px; font-family: var(--sans); font-size: 1.1em; }
.author-box-bio { margin: 0; font-size: .92em; color: var(--muted); }

/* Related */
.related-posts { margin: 2em 0; }
.related-list { list-style: none; margin: 0; padding: 0; }
.related-list li { border-top: 1px solid var(--line); }
.related-list a { display: block; padding: 12px 0; text-decoration: none; }
.related-list a:hover { text-decoration: underline; }

/* Archive / lists */
.archive-header { margin: 2em 0 1em; }
.archive-title { font-size: 1.9em; margin: 0; }
.archive-desc { color: var(--muted); margin: .4em 0 0; }
.no-results { margin: 2em 0; }

/* Pagination */
.pagination { display: flex; flex-wrap: wrap; gap: 10px; margin: 2em 0; list-style: none; padding: 0; }
.pagination a, .pagination span { display: inline-block; padding: 6px 12px; border: 1px solid var(--line); text-decoration: none; }
.pagination .current { background: var(--fg); color: var(--bg); border-color: var(--fg); }

/* Search form */
.search-form { display: flex; gap: 8px; margin: 1.5em 0; }
.search-form input[type="search"] { flex: 1; padding: 10px 12px; border: 1px solid var(--line); background: var(--bg); color: var(--fg); font-size: 1em; }
.search-form button { padding: 10px 18px; border: 1px solid var(--fg); background: var(--fg); color: var(--bg); cursor: pointer; font-size: 1em; }

/* 404 */
.error-404 { text-align: center; padding: 3em 0; }
.notfound-categories { list-style: none; display: flex; flex-wrap: wrap; gap: 10px; justify-content: center; padding: 0; margin: 1.5em 0; }
.notfound-categories li { display: flex; align-items: baseline; gap: 6px; }
.notfound-categories a { display: inline-block; border: 1px solid var(--line); border-radius: 999px; padding: 6px 14px; text-decoration: none; }
.notfound-categories a:hover { border-color: var(--fg); }
.notfound-count { color: var(--muted); font-size: .85em; }
.notfound-home { margin: 1.5em 0 0; }

/* Footer */
.site-footer { border-top: 1px solid var(--line); margin-top: 3em; }
.footer-inner { display: flex; flex-wrap: wrap; align-items: center; gap: 12px; justify-content: space-between; padding-top: 20px; padding-bottom: 24px; font-size: .9em; color: var(--muted); }
.footer-copy { margin: 0; }
.footer-menu { display: flex; gap: 16px; list-style: none; margin: 0; padding: 0; }
.footer-menu a { color: var(--muted); text-decoration: none; }
.footer-socials { display: flex; gap: 12px; }
.footer-socials a { color: var(--muted); }

/* Cookie banner */
.cookie-banner { position: fixed; left: 0; right: 0; bottom: 0; background: var(--fg); color: var(--bg); padding: 14px 20px; z-index: 1000; }
.cookie-inner { display: flex; flex-wrap: wrap; align-items: center; gap: 12px; justify-content: space-between; }
.cookie-text { margin: 0; font-size: .9em; }
.cookie-text a { color: var(--bg); }
.cookie-accept { border: 1px solid var(--bg); background: none; color: var(--bg); padding: 8px 16px; cursor: pointer; font-size: .9em; }

/* Comments — social style (X/Facebook inspired) */
.comments-area { margin: 3em 0; }
.comments-area .section-title { font-size: 1.15em; border-bottom: 0; padding-bottom: 0; }
.comment-list, .comment-list .children { list-style: none; margin: 0; padding: 0; }
.comment-list { margin-top: 4px; }
.comment-list > .comment + .comment { margin-top: 20px; }
.comment-list .children { margin: 14px 0 0; padding-left: 14px; border-left: 2px solid var(--line); }
.comment-body { display: flex; gap: 12px; }
.comment-avatar .avatar { width: 40px; height: 40px; border-radius: 50%; display: block; }
.comment-main { flex: 1; min-width: 0; }
.comment-bubble { background: var(--bubble); border-radius: 18px; padding: 8px 16px 10px; }
.comment-header { display: flex; align-items: baseline; flex-wrap: wrap; gap: 8px; }
.comment-author, .comment-time { font-size: .85em; font-weight: 400; color: var(--muted); }
.comment-author a, .comment-time a { color: var(--muted); text-decoration: none; }
.comment-author a:hover, .comment-time a:hover { color: var(--fg); text-decoration: underline; }
.comment-content { margin-top: 4px; font-size: 1.05em; font-weight: 400; color: var(--fg); overflow-wrap: break-word; }
.comment-content p { margin: 0 0 .5em; }
.comment-content p:last-child { margin-bottom: 0; }
.comment-actions { display: flex; gap: 16px; padding: 6px 2px 0; font-size: .82em; font-weight: 600; }
.comment-actions a { color: var(--muted); text-decoration: none; }
.comment-actions a:hover { text-decoration: underline; }
.comment-navigation { margin: 1.2em 0; font-size: .9em; }
.no-comments { font-style: italic; }

/* Comment composer — button + panel */
.comment-composer { margin: 0 0 2.5em; }
.comment-open-btn { border: 1px solid var(--line); background: none; color: var(--fg); padding: 10px 24px; border-radius: 999px; cursor: pointer; font-size: .95em; font-weight: 600; }
.comment-open-btn:hover { border-color: var(--fg); }
.comment-panel { margin-top: 14px; }
.comment-panel[hidden] { display: none; }
.comment-login-prompt { padding: 18px 20px; border: 1px solid var(--line); border-radius: 14px; text-align: center; }
.comment-login-hint { margin: 0 0 12px; color: var(--muted); }
.comment-login-btn { display: inline-block; border: 0; background: var(--fg); color: var(--bg); padding: 9px 22px; border-radius: 999px; text-decoration: none; font-weight: 600; font-size: .92em; }
.comment-login-btn:hover { opacity: .85; }

/* Comment form — composer style */
.comment-respond { margin: 10px 0 0; }
.comment-reply-title { display: none; }
.comment-user { display: inline-flex; align-items: center; gap: 8px; }
.comment-user .avatar { width: 28px; height: 28px; border-radius: 50%; }
.comment-user-name { font-weight: 700; }
.comment-logout { color: var(--muted); font-size: .85em; margin-left: 8px; text-decoration: none; }
.comment-logout:hover { text-decoration: underline; }
.comment-form-comment { margin-top: 10px; }
.comment-form label { display: block; font-size: .85em; color: var(--muted); margin: 14px 0 6px; }
.comment-form input[type="text"], .comment-form input[type="email"], .comment-form input[type="url"], .comment-form textarea {
	width: 100%;
	padding: 12px 14px;
	border: 1px solid var(--line);
	border-radius: 12px;
	background: var(--bg);
	color: var(--fg);
	font-family: var(--sans);
	font-size: 1em;
}
.comment-form textarea { min-height: 52px; resize: vertical; }
.comment-form input:focus, .comment-form textarea:focus { outline: none; border-color: var(--fg); }
.comment-form-cookies-consent { display: flex; gap: 8px; align-items: center; font-size: .85em; color: var(--muted); margin-top: 12px; }
.comment-form .form-submit { margin-top: 14px; text-align: right; }
.comment-form .submit {
	border: 0;
	background: var(--fg);
	color: var(--bg);
	padding: 10px 24px;
	border-radius: 999px;
	cursor: pointer;
	font-size: .95em;
	font-weight: 600;
}
.comment-form .submit:hover { opacity: .85; }

/* Reader comment form (template-parts/comment-form.php).

   Carries its own mcr-* class names rather than reusing .comment-form, because
   the form has to stay clear of that string — the static exporter rewrites any
   <form> whose tag contains `comment-form` into "Comments are disabled on this
   static version of the site." The .comment-form-* rules above are now dead:
   they styled WordPress's own comment_form(), which this theme no longer
   renders. Left in place rather than deleted in the same change that removes
   the markup, so there is one thing to blame if something looks wrong. */
.mcr-form { margin: 0; }
.mcr-note { font-size: .88em; color: var(--muted); margin: 0 0 1.3em; }
.mcr-field { margin: 0 0 1em; }
.mcr-field label { display: block; font-size: .85em; color: var(--muted); margin: 0 0 6px; }
.mcr-req { color: var(--meta); }
.mcr-form input[type="text"],
.mcr-form textarea {
	width: 100%;
	padding: 12px 14px;
	border: 1px solid var(--line);
	border-radius: 12px;
	background: var(--bg);
	color: var(--fg);
	font-family: var(--sans);
	font-size: 1em;
}
.mcr-form textarea { min-height: 124px; resize: vertical; }
.mcr-form input[type="text"]:focus,
.mcr-form textarea:focus { outline: none; border-color: var(--fg); }

.mcr-replying { margin: 0 0 1em; font-size: .88em; color: var(--muted); }
.mcr-replying[hidden] { display: none; }
.mcr-replying-name { color: var(--fg); font-weight: 600; }
.mcr-replying-cancel { margin-left: 10px; color: var(--muted); }

.mcr-actions { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; margin-top: 1.3em; }
.mcr-submit {
	border: 0;
	background: var(--fg);
	color: var(--bg);
	padding: 10px 24px;
	border-radius: 999px;
	cursor: pointer;
	font-family: var(--sans);
	font-size: .95em;
	font-weight: 600;
}
.mcr-submit:hover { opacity: .85; }
.mcr-submit[disabled] { opacity: .5; cursor: default; }
.mcr-status { margin: 0; font-size: .88em; color: var(--muted); }
.mcr-status[data-tone="bad"] { color: var(--danger); }
.mcr-status[data-tone="ok"] { color: var(--fg); font-weight: 600; }

.mcr-thanks {
	margin: 0;
	padding: 18px 20px;
	border: 1px solid var(--line);
	border-radius: 14px;
}
.mcr-thanks[hidden] { display: none; }

/* Off-screen rather than display:none: some bots skip fields they can tell are
   hidden, and a person must never be able to reach it. */
.mcr-honeypot { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

/* Responsive */
@media (max-width: 640px) {
	body { font-size: 16px; }
	.post-title { font-size: 1.7em; }
	.header-inner { flex-wrap: wrap; }
	.nav-toggle { display: block; order: 2; margin-left: auto; }
	.theme-toggle { order: 3; }
	.site-nav { display: none; width: 100%; order: 4; }
	.site-nav.open { display: block; }
	.nav-menu { flex-direction: column; gap: 0; padding: 8px 0; }
	.nav-menu li { border-top: 1px solid var(--line); }
	.nav-menu a { display: block; padding: 12px 0; }
	.author-box { flex-direction: column; }
	.footer-inner { flex-direction: column; align-items: flex-start; }
}

@media (prefers-reduced-motion: reduce) {
	* { transition: none !important; }
}

/* Post tags */
.post-tags { margin: 8px 0 24px; padding-top: 16px; border-top: 1px solid var(--line); display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.post-tags a { display: inline-block; font-size: .82em; color: var(--fg); text-decoration: none; border: 1px solid var(--line); border-radius: 999px; padding: 2px 12px; }
.post-tags a:hover { border-color: var(--fg); }
.post-tags-label { font-size: .82em; color: var(--muted); }

/* Card tags */
.post-card-tags { margin-top: 10px; display: flex; flex-wrap: wrap; gap: 6px; }
.post-card-tags a { font-size: .75em; color: var(--muted); text-decoration: none; border: 1px solid var(--line); border-radius: 999px; padding: 1px 10px; }
.post-card-tags a:hover { color: var(--fg); border-color: var(--fg); }

/* Back to top */
/* 44px so it is a valid touch target, and painted in the page's own two
   colours so it inverts with the theme and needs no separate contrast check.
   Its z-index sits below the skip link (999) and the cookie banner (1000) on
   purpose, both being transient, but that alone would leave it underneath the
   banner for as long as a reader ignores the notice, which is where a first
   visit would start and possibly stay. So the banner's measured height is
   handed in as --to-top-lift by main.js and the control steps over it. The
   fallback keeps the button on screen where the variable is unset, which also
   covers the reader with no JavaScript: they keep the always-on button but do
   overlap an unanswered notice, and with scripting off that notice cannot be
   dismissed either, so the notice is the thing that has to win. */
.to-top {
	position: fixed;
	right: 20px;
	bottom: calc( 20px + var( --to-top-lift, 0px ) );
	z-index: 950;
	display: flex;
	align-items: center;
	justify-content: center;
	width: 44px;
	height: 44px;
	border-radius: 50%;
	background: var(--fg);
	color: var(--bg);
	transition: opacity .2s ease, transform .2s ease, visibility 0s linear .2s;
}
.to-top:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }
.to-top-icon { display: block; }
/* Only once JavaScript is running. The flag is set in the head by
   hardline_head_extra(), before the first paint, so the button never appears
   and then vanishes on load. With no JavaScript the flag is never set and the
   control stays on screen, which is the behaviour the anchor gives on its own.
   The scroll listener in main.js adds .is-visible. */
html.js .to-top { opacity: 0; visibility: hidden; transform: translateY(8px); }
html.js .to-top.is-visible { opacity: 1; visibility: visible; transform: none; transition-delay: 0s; }
