/**
 * Single blog post — the "left rail" layout (handoff 1B).
 *
 * Loaded on is_singular('post') only (see loglineit_blog_assets), so nothing in
 * here is scoped defensively against the rest of the site beyond the .single-post
 * body class the frame overrides need.
 *
 * Every colour is one of the theme's --brand-* tokens, which already carry their
 * own light and dark values, so there is no second palette to keep in step here.
 * The one exception is the rank pill, whose colours come from the plugin's
 * admin-tunable level ladder as inline custom properties — computed, with their
 * text colour contrast-checked, in loglineit_rank_pill_style().
 */

/* -- The page frame -------------------------------------------------------- */

/* This template runs wider than the rest of the site: 280 + 56 + 720 does not
   fit inside the standard 64rem frame, and the article's measure is fixed at
   720px rather than elastic. The whole page widens — header, nav and footer
   included — so the chrome stays lined up with the content below it. */
.single-post .site-container {
	max-width: 1280px;
	padding-inline: 56px;
}

.single-post .site-layout {
	/* No right-hand sidebar on a post: sidebar.php returns early, because this
	   layout carries its own rail. */
	grid-template-columns: 1fr;
	padding: 44px 0 64px;
}

/* -- The two-column grid --------------------------------------------------- */

.blog--left-rail {
	display: grid;
	grid-template-columns: 280px minmax(0, 1fr);
	gap: 56px;
	align-items: start;
}

/* One sticky group, not three sticky cards, so the rail moves as a unit. It can
   never overlap the footer: a sticky box is bounded by its grid area, and the
   article is always the taller of the two columns. */
.blog__rail {
	position: sticky;
	top: calc(var(--header-h, 64px) + 16px);
	align-self: start;
	display: flex;
	flex-direction: column;
	gap: 24px;
	min-width: 0;
}

/* Set by blog.js when the rail is taller than the viewport — sticky would then
   pin its top off-screen and the bottom of the card could never be read. */
.blog__rail.is-unstuck {
	position: static;
}

/* -- Back to the index -----------------------------------------------------
   The link itself is styled in style.css, which also carries it on the archive
   pages; in the rail it only needs its own margin cleared, since the rail's
   flex gap already spaces it. */

.blog--left-rail .blog-feed-link {
	margin: 0;
}

/* -- Author card ----------------------------------------------------------- */

.author-card {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: 10px;
	padding-bottom: 24px;
	border-bottom: 1px solid var(--brand-border);
}

.author-card__link {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: 10px;
	color: inherit;
	text-decoration: none;
}

.author-card__photo .avatar {
	display: block;
	width: 96px;
	height: 96px;
	border-radius: 50%;
	object-fit: cover;
	background: var(--brand-surface);
}

.author-card__name {
	font-size: 1rem;
	font-weight: 800;
	line-height: 1.25;
}

.author-card__link:hover .author-card__name,
.author-card__link:focus-visible .author-card__name {
	color: var(--brand-accent);
	text-decoration: underline;
}

.author-card__bio {
	margin: 2px 0 0;
	color: var(--brand-muted);
	font-size: 0.875rem;
	line-height: 1.6;
}

/* -- Rank pill -------------------------------------------------------------
   --rank-bg / --rank-fg (and their dark pair) arrive inline from PHP. The
   fallbacks are the theme's own accent, so a level whose stored colour is
   unparseable still renders as a pill rather than as unstyled text. */
.rank-pill {
	display: inline-block;
	padding: 2px 9px;
	border-radius: 999px;
	background: var(--rank-bg, var(--brand-accent));
	color: var(--rank-fg, var(--brand-accent-contrast));
	font-size: 0.75rem;
	font-weight: 800;
	line-height: 1.5;
	letter-spacing: 0.01em;
}

@media (prefers-color-scheme: dark) {
	:root:not([data-theme="light"]) .rank-pill {
		background: var(--rank-bg-dark, var(--brand-accent));
		color: var(--rank-fg-dark, var(--brand-accent-contrast));
	}
}

:root[data-theme="dark"] .rank-pill {
	background: var(--rank-bg-dark, var(--brand-accent));
	color: var(--rank-fg-dark, var(--brand-accent-contrast));
}

/* -- "On this page" --------------------------------------------------------
   Hidden until blog.js has found two or more h2s to list. The [hidden] rule is
   explicit because the display below would otherwise win over it. */
.toc {
	display: block;
}

.toc[hidden] {
	display: none;
}

.toc__box {
	border: 0;
}

/* In the rail the summary is simply the label: no marker, no pointer, and
   blog.js holds the disclosure open and takes the summary out of the tab order,
   so it cannot be collapsed away. */
.toc__label {
	list-style: none;
	cursor: default;
	margin: 0 0 10px;
	color: var(--brand-muted);
	font-size: 0.75rem;
	font-weight: 800;
	text-transform: uppercase;
	letter-spacing: 0.12em;
}

.toc__label::-webkit-details-marker {
	display: none;
}

.toc__list {
	list-style: none;
	margin: 0;
	padding: 0;
	display: flex;
	flex-direction: column;
	gap: 8px;
}

.toc__list a {
	display: block;
	padding-left: 12px;
	border-left: 2px solid var(--brand-border);
	color: var(--brand-muted);
	font-size: 0.9375rem;
	line-height: 1.4;
	text-decoration: none;
}

.toc__list a:hover {
	color: var(--brand-text);
}

.toc__list .is-current a {
	border-left-color: var(--brand-accent);
	color: var(--brand-accent);
	font-weight: 700;
}

/* -- CTA card --------------------------------------------------------------
   On the site's grey canvas a --brand-surface card is all but invisible, so it
   takes the card token (the same white the handoff calls --bg) like every other
   card on this site. */
.cta-card {
	padding: 18px;
	border: 1px solid var(--brand-border);
	border-radius: 12px;
	background: var(--brand-card);
}

.cta-card__head {
	margin: 0 0 6px;
	font-size: 0.9375rem;
	font-weight: 800;
	line-height: 1.3;
}

.cta-card__body {
	margin: 0 0 14px;
	color: var(--brand-muted);
	font-size: 0.875rem;
	line-height: 1.55;
}

.cta-card__btn {
	display: block;
	width: 100%;
	padding: 10px 14px;
	border: 0;
	border-radius: 8px;
	background: var(--brand-accent);
	color: var(--brand-accent-contrast);
	font: inherit;
	font-size: 0.9375rem;
	font-weight: 800;
	line-height: 1.3;
	text-align: center;
	text-decoration: none;
	cursor: pointer;
}

.cta-card__btn:hover,
.cta-card__btn:focus-visible {
	background: var(--brand-accent-hover);
	color: var(--brand-accent-contrast);
}

/* -- The article ----------------------------------------------------------- */

/* The measure is fixed, not elastic: the column does not stretch with the
   window. Vertical rhythm is the flex gap — no per-element margins. */
.blog--left-rail .post {
	max-width: 720px;
	min-width: 0;
	display: flex;
	flex-direction: column;
	gap: 22px;
	margin: 0;
}

.post__meta {
	display: flex;
	align-items: center;
	flex-wrap: wrap;
	gap: 10px;
	color: var(--brand-muted);
	font-size: 0.875rem;
}

.pill--category {
	display: inline-block;
	padding: 2px 10px;
	border-radius: 999px;
	background: var(--brand-accent-2);
	color: #fff;
	font-size: 0.75rem;
	font-weight: 800;
	line-height: 1.5;
	text-transform: uppercase;
	letter-spacing: 0.04em;
	text-decoration: none;
}

.pill--category:hover,
.pill--category:focus-visible {
	background: var(--brand-accent-2-hover);
	color: #fff;
}

.post__readtime {
	white-space: nowrap;
}

.post__title {
	margin: 0;
	font-size: 2.75rem;
	line-height: 1.12;
	font-weight: 800;
	letter-spacing: -0.02em;
	text-wrap: balance;
}

.post__lede {
	margin: 0;
	color: var(--brand-muted);
	font-size: 1.25rem;
	font-weight: 500;
	line-height: 1.55;
	text-wrap: pretty;
}

/* -- Featured image --------------------------------------------------------
   aspect-ratio rather than a fixed height, so the space is reserved before the
   image arrives (no layout shift) — and at 720px wide 1440/760 *is* the 380px
   the layout asks for. */
.post__feature {
	margin: 0;
}

.post__feature-img {
	display: block;
	width: 100%;
	height: auto;
	aspect-ratio: 1440 / 760;
	object-fit: cover;
	border-radius: 12px;
	background: var(--brand-surface);
}

.post__caption {
	margin: 8px 0 0;
	color: var(--brand-muted);
	font-size: 0.8125rem;
	line-height: 1.5;
}

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

.blog--left-rail .entry-content {
	font-size: 1.0625rem;
	line-height: 1.7;
	text-wrap: pretty;
}

/* Beats the site-wide `.entry-content > * + *` rule (one class) with two. */
.blog--left-rail .entry-content > * + * {
	margin-top: 22px;
}

.blog--left-rail .entry-content > :first-child {
	margin-top: 0;
}

.blog--left-rail .entry-content h2 {
	margin-top: 40px;
	font-size: 1.625rem;
	line-height: 1.2;
	font-weight: 800;
	letter-spacing: -0.01em;
	/* Clears the sticky header when a contents link (or a #hash) jumps here. */
	scroll-margin-top: calc(var(--header-h, 64px) + 24px);
}

.blog--left-rail .entry-content h3 {
	margin-top: 30px;
	font-size: 1.25rem;
	line-height: 1.3;
	font-weight: 800;
}

/* A heading focused by a contents click is a scroll target, not a control —
   the ring would read as though something had been activated. */
.blog--left-rail .entry-content h2:focus {
	outline: none;
}

.blog--left-rail .entry-content img {
	max-width: 100%;
	height: auto;
	border-radius: 12px;
}

.blog--left-rail .entry-content figcaption {
	margin-top: 8px;
	color: var(--brand-muted);
	font-size: 0.8125rem;
	line-height: 1.5;
}

/* Pull quote. There is no custom block for the eyebrow the mock shows, so an
   ordinary editor blockquote takes the card treatment and its <cite> the
   credit line. */
.blog--left-rail .entry-content blockquote {
	margin: 0;
	padding: 20px 22px;
	border: 1px solid var(--brand-border);
	border-radius: 12px;
	background: var(--brand-surface);
	font-size: 1.0625rem;
	font-weight: 600;
	line-height: 1.6;
}

.blog--left-rail .entry-content blockquote > * + * {
	margin-top: 10px;
}

.blog--left-rail .entry-content blockquote cite {
	display: block;
	color: var(--brand-muted);
	font-size: 0.875rem;
	font-style: normal;
	font-weight: 400;
}

/* Wide content scrolls inside itself rather than pushing the page sideways. */
.blog--left-rail .entry-content pre,
.blog--left-rail .entry-content table {
	display: block;
	max-width: 100%;
	overflow-x: auto;
}

/* -- Focus ----------------------------------------------------------------- */

.blog--left-rail a:focus-visible,
.blog--left-rail button:focus-visible,
.blog--left-rail summary:focus-visible {
	outline: 2px solid var(--brand-accent);
	outline-offset: 3px;
	border-radius: 4px;
}

/* -- Below 1080px: the rail unwraps around the article ---------------------
   `display: contents` on the rail lets its three cards be placed individually
   in the page's flow — author strip and contents above the article, the call to
   action after it — without a second copy of the markup for narrow screens. */
@media (max-width: 1080px) {
	.single-post .site-container {
		padding-inline: 32px;
	}

	.blog--left-rail {
		display: flex;
		flex-direction: column;
		gap: 28px;
		/* The grid above wants `start`; a column flex container reads that on the
		   cross axis, which would shrink every card to fit its own contents
		   instead of the column width. */
		align-items: stretch;
	}

	.blog__rail {
		display: contents;
	}

	.blog-feed-link {
		order: 0;
		align-self: flex-start;
	}

	.author-card {
		order: 1;
		flex-direction: row;
		align-items: center;
		gap: 16px;
		flex-wrap: wrap;
	}

	.author-card__link {
		flex-direction: row;
		align-items: center;
		gap: 12px;
	}

	.author-card__photo .avatar {
		width: 64px;
		height: 64px;
	}

	.author-card__bio {
		flex: 1 1 100%;
		margin: 0;
	}

	.toc {
		order: 2;
	}

	.toc__box {
		padding: 12px 16px;
		border: 1px solid var(--brand-border);
		border-radius: 12px;
		background: var(--brand-card);
	}

	/* Back to a real disclosure: marker on, and blog.js closes it here. */
	.toc__label {
		margin: 0;
		cursor: pointer;
		list-style: revert;
	}

	.toc__label::-webkit-details-marker {
		display: revert;
	}

	.toc__box[open] .toc__label {
		margin-bottom: 12px;
	}

	/* 100%, not none: an image whose file has gone missing has no intrinsic
	   size, and a broken <img> carrying an aspect-ratio is sized by Chrome from
	   a very large intrinsic width — which, with `none`, drags the whole article
	   out to ~3000px and puts the page into horizontal scroll. Capping at the
	   container means the worst a missing file can do is look wrong in its own
	   box. */
	.blog--left-rail .post {
		order: 3;
		max-width: 100%;
	}

	.cta-card {
		order: 4;
	}
}

/* -- Phones ---------------------------------------------------------------- */

@media (max-width: 640px) {
	.single-post .site-container {
		padding-inline: 20px;
	}

	.single-post .site-layout {
		padding: 24px 0 48px;
	}

	.post__title {
		font-size: 1.875rem;
	}

	.post__lede {
		font-size: 1.125rem;
	}

	/* A 1.9:1 strip is a letterbox across a phone — the same 3/2 crop the rest
	   of the theme switches to, which lands at roughly the 220px tall the layout
	   asks for on a 375px screen. */
	.post__feature-img {
		aspect-ratio: 3 / 2;
	}

	.blog--left-rail .entry-content h2 {
		font-size: 1.375rem;
	}
}
