/*
Theme Name: Revenant Blog
Theme URI: https://surviveth3dead.com
Description: Child theme of Twenty Twenty-Five carrying the revenant palette — Arma 2's menu colours, olive drab, bone and rust — so the blog and the phpBB board read as one site. Tokens are copied verbatim from styles/revenant/theme/revenant.css; if that file changes, change this one.
Author: surviveth3dead.com
Template: twentytwentyfive
Version: 1.9.3
License: GPL-2.0-or-later
Text Domain: revenant-blog
*/

/*  Everything structural lives in theme.json. This file carries only what
    theme.json cannot express: the condensed-uppercase register, and the
    reading adjustments that a board's density does not transfer to essays.

    NO WEBFONTS. The board deliberately ships none — matching that keeps the
    two halves consistent and costs nothing on shared hosting.  */

:root {
	/* verbatim from revenant.css — do not drift these */
	--rv-void:      #0d0e0a;
	--rv-bg:        #131410;
	--rv-panel:     #191b15;
	--rv-line:      #2b2e22;
	--rv-ink:       #d6d0bb;
	--rv-ink-2:     #c6c1ac;
	--rv-muted:     #8b8874;
	--rv-dim:       #6d6b5a;
	--rv-rust:      #b0552c;
	--rv-rust-hi:   #cf6f3d;
	--rv-olive:     #4a5133;
	--rv-olive-hi:  #8f9271;

	--rv-cond: "Arial Narrow", "Helvetica Neue Condensed", "Liberation Sans Narrow", Arial, sans-serif;
}

/*  THE SIGNATURE — condensed, uppercase, widely tracked.
    This is the one thing that makes the site read as Arma 2's menu rather
    than as a generic dark theme. It is spent only where strings are SHORT:
    the masthead, the post date, and eyebrow labels. Headlines deliberately
    do not get it — see the note below. Everywhere else stays quiet.  */
.wp-block-site-title,
.revenant-eyebrow {
	font-family: var(--rv-cond);
	font-stretch: condensed;
	text-transform: uppercase;
	letter-spacing: .2em;
	font-weight: 700;
}

/*  Post titles get the condensed face but NOT the uppercase tracking.
    Wide-tracked capitals work on a masthead and on four-word labels; a
    58-character headline set that way is a wall the reader has to decode
    one letter at a time. The register survives in the typeface; the
    shouting does not.  */
.wp-block-post-title,
.wp-block-query-title {
	font-family: var(--rv-cond);
	font-stretch: condensed;
	letter-spacing: .01em;
	font-weight: 700;
	text-transform: none;
}

.revenant-eyebrow {
	font-size: .72rem;
	color: var(--rv-olive-hi);
}

/*  Subheads inside an article stay sentence case. Uppercase tracking is a
    header register; applied to every h2 across a 1,200-word piece it stops
    being a signal and becomes noise.  */
.entry-content h2,
.entry-content h3 {
	font-family: var(--rv-cond);
	font-stretch: condensed;
	letter-spacing: .04em;
	color: var(--rv-ink);
}

/*  Paragraphs below zero their own top margin, so a heading with no bottom
    margin lands flush on the text it introduces. A subhead needs far more
    space above it than below — the gap is what tells the reader a section
    ended, and the tightness underneath is what binds the heading to the
    prose it belongs to.  */
.entry-content :is(h2, h3, h4) {
	margin-block: 2.4em .55em;
}

.entry-content > :first-child {
	margin-block-start: 0;
}

/*  LONG-FORM READING
    The board is scanned; an article is read. Bone on near-black is ~11:1 —
    high enough to buzz over a full page — so body text drops to --rv-ink-2
    and gains line-height. Both values already exist in revenant.css; nothing
    new is invented here.  */
.entry-content {
	color: var(--rv-ink-2);
	line-height: 1.7;
}

.entry-content p {
	margin-block: 0 1.35em;
}

/*  Paragraphs zero their own top margin (above), which is right everywhere
    except after a block that has no bottom margin of its own — a table then
    has the next sentence sitting on its bottom border.  */
.entry-content :is(.wp-block-table, figure, pre) {
	margin-block: 0 1.6em;
}

/*  Rust is the only warm colour and it marks exactly one thing: a link.
    The moment it appears in three places it reads as decoration.  */
a:where(:not(.wp-element-button)) {
	color: var(--rv-rust-hi);
	text-decoration-thickness: 1px;
	text-underline-offset: .2em;
}

a:where(:not(.wp-element-button)):hover {
	color: var(--rv-ink);
}

/*  A post title in a list IS a link, so the rule above would paint every
    headline rust and spend the accent before the reader hits any prose.
    Titles are bone; rust arrives only on hover, where it means "this is
    clickable" rather than "this is decorated".  */
.wp-block-post-title a,
.wp-block-site-title a {
	color: var(--rv-ink);
	text-decoration: none;
}

.wp-block-post-title a:hover,
.wp-block-site-title a:hover {
	color: var(--rv-rust-hi);
}

/*  Quality floor — not announced, just present.  */
:where(a, button, input, textarea, select, [tabindex]):focus-visible {
	outline: 2px solid var(--rv-rust-hi);
	outline-offset: 2px;
}

hr.wp-block-separator {
	border-color: var(--rv-line);
	opacity: 1;
}

blockquote {
	border-left: 2px solid var(--rv-olive);
	padding-left: 1.2em;
	color: var(--rv-muted);
	font-style: normal;
}

/*  Code blocks read as terminal output, which is what most of them will be.  */
code, pre {
	background: var(--rv-void);
	border: 1px solid var(--rv-line);
	color: var(--rv-olive-hi);
}

pre {
	padding: 1em 1.2em;
	overflow-x: auto;
}

/*  WordPress nests <pre class="wp-block-code"><code>, so the rule above
    paints BOTH and you get a box inside a box. The inner element carries
    the text; the outer carries the frame.  */
pre code {
	background: none;
	border: 0;
	padding: 0;
	color: inherit;
}

/*  Inline code sits in running prose, so it needs to breathe without
    breaking the line rhythm — no border, just a tinted ground.  */
:not(pre) > code {
	border: 0;
	padding: .1em .35em;
	border-radius: 2px;
	font-size: .9em;
}

@media (prefers-reduced-motion: reduce) {
	*, *::before, *::after {
		animation-duration: .01ms !important;
		transition-duration: .01ms !important;
	}
}

/* ==========================================================================
   MAGAZINE LAYOUT
   Homepage/archive/single furniture: carousel, pills, bands, cards, rows,
   filmstrip, sidebar. Nothing above this line changed — the reading column
   and its typography are untouched, because an article is still an article.
   ========================================================================== */

/*  MASTHEAD
    The sitename used to be a small line of type sharing a row with the nav,
    which on a magazine reads as a utility bar rather than a masthead. It now
    gets a band of its own with the ridgeline behind it.

    The image is the FORUM's banner, generated by the same scripts/mkbanner.py
    at the same fixed seed — a Chernarus dusk ridgeline, all silhouette. Not a
    copy of a copy: the script takes an output directory, so the blog runs it
    into its own assets/ and neither side owns the other's file. That is also
    the point of using it at all, since the two halves of the site are
    supposed to look like one place.

        python scripts/mkbanner.py themes/revenant-blog/assets

    The source is 2400x420 and this band is far shorter. `bottom` anchoring is
    deliberate: the ridgeline and the one warm sky band sit in the lower half,
    so cropping from the top loses empty sky and keeps the whole subject.  */
.revenant-masthead {
	position: relative;
	background:
		linear-gradient(to right, rgba(13, 14, 10, .96) 0%, rgba(13, 14, 10, .72) 45%, rgba(13, 14, 10, .45) 100%),
		url(assets/banner.jpg) center bottom / cover no-repeat;
	border-bottom: 1px solid var(--rv-line);
}

.revenant-masthead-inner {
	padding-block: 3.4rem 3rem;
}

/*  The banner carries its own baked-in scrim on the left third so the
    sitename has ground under it however the image crops; the gradient above
    is belt and braces for the very wide viewports where that third is a
    smaller share of the frame.  */
.revenant-masthead .wp-block-site-title {
	margin: 0;
	font-size: clamp(2rem, 6vw, 3.4rem);
	line-height: 1;
	letter-spacing: .18em;
}

.revenant-masthead .wp-block-site-title a {
	color: var(--rv-ink);
	text-shadow: 0 2px 12px rgba(13, 14, 10, .9);
}

/*  No max-width. A measure cap is right for prose and wrong for a tagline —
    it wrapped sixty characters onto two lines directly under the sitename,
    which reads as a paragraph rather than as a strapline. It still wraps on
    a narrow screen, where two lines is the only option.  */
.revenant-masthead .wp-block-site-tagline {
	margin: .9rem 0 0;
	color: var(--rv-ink-2);
	text-shadow: 0 1px 8px rgba(13, 14, 10, .9);
}

/*  NAVBAR
    Its own rail under the masthead, so the nav is navigation and the
    masthead is identity — the two jobs the old single row was doing at once.  */
.revenant-navbar {
	background: var(--rv-void);
	border-bottom: 1px solid var(--rv-line);
	position: sticky;
	top: 0;
	z-index: 20;
}

.revenant-navbar > .wp-block-group {
	align-items: center;
	padding-block: .55rem;
}

.revenant-navbar .wp-block-navigation {
	font-family: var(--rv-cond);
	font-stretch: condensed;
	text-transform: uppercase;
	letter-spacing: .14em;
	font-size: .82rem;
	font-weight: 700;
	gap: 1.6rem;
}

.revenant-navbar .wp-block-navigation a {
	color: var(--rv-ink-2);
	text-decoration: none;
}

.revenant-navbar .wp-block-navigation a:hover {
	color: var(--rv-rust-hi);
}

.revenant-navbar-note {
	margin: 0;
	color: var(--rv-muted);
	font-family: var(--rv-cond);
	font-stretch: condensed;
	text-transform: uppercase;
	letter-spacing: .2em;
	font-size: .7rem;
}

@media (max-width: 640px) {
	.revenant-masthead-inner {
		padding-block: 2.2rem 1.9rem;
	}

	.revenant-navbar {
		position: static;
	}

	.revenant-navbar-note {
		display: none;
	}
}

/*  PILLS
    Colour comes from the post's genre, never from the game. Five hues, all
    solved to the same luminance (bone text 4.5:1, chip against the ground
    2.6:1) so five different colours still read as one family. Colour the
    game instead and the palette is unbounded — at a dozen games a dark
    restrained page turns into confetti.

    The class is `category-<slug>`, which WordPress already puts on
    .wp-block-post inside a Query Loop. functions.php adds it to <body> for
    single posts, which is the only reason that filter exists.  */
.category-open-world-survival { --pill-bg: #505e37; }
.category-survival-horror     { --pill-bg: #8e442a; }
.category-sci-fi-survival     { --pill-bg: #365e6f; }
.category-crafting-and-colony { --pill-bg: #635931; }
.category-extraction-and-pvp  { --pill-bg: #884265; }

/*  The two first-party categories are OUTLINE pills, not filled ones. That
    is a second free signal stacked on top of the card shape: filled means
    the news stream wrote it, outline means a human here did.  */
.category-the-lab {
	--pill-bg: transparent;
	--pill-fg: var(--rv-ink);
	--pill-line: var(--rv-ink);
}

.category-revival-lane {
	--pill-bg: transparent;
	--pill-fg: var(--rv-rust-hi);
	--pill-line: var(--rv-rust-hi);
}

.revenant-pills {
	gap: .4rem;
	margin-block: 0 .6rem;
}

.revenant-pills .wp-block-post-terms {
	margin: 0;
}

.revenant-pills a {
	display: inline-block;
	font-family: var(--rv-cond);
	font-stretch: condensed;
	text-transform: uppercase;
	letter-spacing: .13em;
	font-weight: 700;
	font-size: .68rem;
	line-height: 1;
	padding: .42em .7em .38em;
	background: var(--pill-bg, transparent);
	color: var(--pill-fg, var(--rv-ink));
	border: 1px solid var(--pill-line, transparent);
	text-decoration: none;
}

.revenant-pills a:hover {
	color: var(--rv-void);
	background: var(--rv-ink);
	border-color: var(--rv-ink);
}

/*  Do NOT set --pill-fg or --pill-line as defaults on .revenant-pills. It sits
    closer to the <a> than the .category-<slug> ancestor does, so a default
    here wins the custom-property cascade and silently flattens every outline
    pill back to borderless text. The var() fallbacks above are the defaults.  */

/*  Uncategorised, or a category nobody has assigned a colour yet: a muted
    outline rather than an unstyled rust link.  */
.wp-block-post:not([class*="category-"]) .revenant-pills a,
body:not([class*="category-"]) .revenant-article-head .revenant-pills a {
	border-color: var(--rv-line);
	color: var(--rv-muted);
}

/*  When n8n starts tagging posts with game names, the tag pill replaces the
    genre pill and INHERITS ITS COLOUR — the colour lives on the post's
    category class, not on the pill's own content. core/post-terms renders
    nothing at all when a post has no terms, so today only the category pill
    exists and this rule is inert. No template edit, no deploy.  */
.revenant-pills:has(.taxonomy-post_tag) .taxonomy-category {
	display: none;
}

/*  IMAGE HOVER
    Soledad dims with an overlay element whose opacity runs 0 -> .7, plus a
    scale(1.05) on some styles. Same effect, no extra element: the image
    itself dims, and only `cover` crops zoom. The card images are `contain`
    on a void ground (see below) and a zoom there would just float the
    picture around inside its box.  */
.revenant-cards .wp-block-post-featured-image a,
.revenant-rows .wp-block-post-featured-image a,
.revenant-filmstrip .wp-block-post-featured-image a,
.revenant-carousel .wp-block-post-featured-image a {
	display: block;
	position: relative;
	overflow: hidden;
}

/*  THE HOVER FRAME
    Lifted from Soledad's featured boxes, which draw it with two pseudo-
    elements rather than one border — that is what makes it animate as four
    lines converging instead of a box fading in.

    ::before carries only the top and bottom rules and is squashed flat on X;
    ::after carries only the left and right rules and is squashed flat on Y.
    Releasing both to scale(1) grows the horizontals out from the centre and
    the verticals up and down from it, and they meet as a closed rectangle.
    A single element with `border` cannot do this: scaling it would scale the
    border's own thickness with it.

    Bone, not Soledad's white — white is not in this palette.

    Deliberately NOT on the carousel: those slides already carry a scrim and
    a text ground over the lower half, and a frame under both reads as an
    artefact.  */
.revenant-cards .wp-block-post-featured-image a::before,
.revenant-cards .wp-block-post-featured-image a::after,
.revenant-rows .wp-block-post-featured-image a::before,
.revenant-rows .wp-block-post-featured-image a::after,
.revenant-filmstrip .wp-block-post-featured-image a::before,
.revenant-filmstrip .wp-block-post-featured-image a::after {
	content: "";
	position: absolute;
	inset: var(--frame-inset, 8px);
	z-index: 2;
	opacity: 0;
	pointer-events: none;
	transition: opacity .3s ease, transform .4s ease;
}

.revenant-cards .wp-block-post-featured-image a::before,
.revenant-rows .wp-block-post-featured-image a::before,
.revenant-filmstrip .wp-block-post-featured-image a::before {
	border-top: 1px solid var(--rv-ink);
	border-bottom: 1px solid var(--rv-ink);
	transform: scale(0, 1);
}

.revenant-cards .wp-block-post-featured-image a::after,
.revenant-rows .wp-block-post-featured-image a::after,
.revenant-filmstrip .wp-block-post-featured-image a::after {
	border-left: 1px solid var(--rv-ink);
	border-right: 1px solid var(--rv-ink);
	transform: scale(1, 0);
}

/*  Triggered from the whole card, not the image alone, so the frame and the
    dim arrive together rather than the frame waiting for the cursor to
    cross onto the picture.  */
.revenant-cards .wp-block-post:hover .wp-block-post-featured-image a::before,
.revenant-cards .wp-block-post:hover .wp-block-post-featured-image a::after,
.revenant-rows .wp-block-post:hover .wp-block-post-featured-image a::before,
.revenant-rows .wp-block-post:hover .wp-block-post-featured-image a::after,
.revenant-filmstrip .wp-block-post:hover .wp-block-post-featured-image a::before,
.revenant-filmstrip .wp-block-post:hover .wp-block-post-featured-image a::after {
	opacity: 1;
	transform: scale(1);
}

/*  A 116px square thumbnail cannot carry an 8px inset without the frame
    crowding the picture down to nothing.  */
.revenant-rows .wp-block-post-featured-image a {
	--frame-inset: 6px;
}

.revenant-cards .wp-block-post-featured-image img,
.revenant-rows .wp-block-post-featured-image img,
.revenant-filmstrip .wp-block-post-featured-image img,
.revenant-carousel .wp-block-post-featured-image img {
	transition: opacity .3s ease, transform .5s ease;
}

.revenant-cards .wp-block-post:hover .wp-block-post-featured-image img,
.revenant-rows .wp-block-post:hover .wp-block-post-featured-image img {
	opacity: .5;
}

.revenant-rows .wp-block-post:hover .wp-block-post-featured-image img,
.revenant-filmstrip .wp-block-post:hover .wp-block-post-featured-image img,
.revenant-carousel .wp-block-post:hover .wp-block-post-featured-image img {
	transform: scale(1.06);
}

.revenant-filmstrip .wp-block-post:hover .wp-block-post-featured-image img {
	opacity: .55;
}

/*  CAROUSEL
    Soledad runs Swiper for this — a library plus its stylesheet. The whole
    behaviour is "scroll the track by one slide", and scroll-snap is that,
    natively, with touch and swipe already handled. assets/carousel.js only
    adds autoplay and the two arrows, so with the script absent this stays a
    working swipeable strip rather than a broken slideshow.  */
.revenant-carousel-wrap {
	margin-block: 0 3.5rem;
	background: var(--rv-void);
	border-bottom: 1px solid var(--rv-line);
}

.revenant-carousel {
	position: relative;
}

.revenant-carousel .wp-block-post-template {
	display: flex;
	gap: 3px;
	overflow-x: auto;
	scroll-snap-type: x mandatory;
	scrollbar-width: none;
	margin: 0;
	padding: 0;
	list-style: none;
}

.revenant-carousel .wp-block-post-template::-webkit-scrollbar {
	display: none;
}

/*  Three across. The track scrolls by one slide whatever this is, because
    carousel.js measures the step from the first two slides' offsets rather
    than assuming a count — so the breakpoints below change how many are
    visible without the script needing to know.  */
.revenant-carousel .wp-block-post {
	position: relative;
	flex: 0 0 33.3333%;
	scroll-snap-align: start;
	margin: 0;
	min-width: 0;
}

/*  980, not 1200. A 1080-ish laptop is the commonest desktop width there is,
    and at a 1200 threshold every one of them saw two slides.  */
@media (max-width: 980px) {
	.revenant-carousel .wp-block-post {
		flex-basis: 50%;
	}
}

@media (max-width: 700px) {
	.revenant-carousel .wp-block-post {
		flex-basis: 100%;
	}
}

/*  A 16:9 slide at half the viewport is 420px tall on a desktop, which puts
    the first band of actual content below the fold on a laptop. Capping the
    height rather than changing the ratio keeps the crop under control at
    every width — same trick as the filmstrip: the ratio lives on the WRAPPER
    and `height:100%` inline on the <img>, so the wrapper is what to tell.  */
.revenant-carousel .wp-block-post-featured-image {
	margin: 0;
	height: clamp(190px, 17vw, 270px) !important;
	aspect-ratio: auto !important;
}

.revenant-carousel .wp-block-post-featured-image img {
	height: 100%;
}

/*  The scrim. Text over a photograph needs a ground or it is unreadable on
    whichever frame happens to be bright. pointer-events:none so it never
    swallows the click that should reach the image's own link.  */
.revenant-carousel .wp-block-post::after {
	content: "";
	position: absolute;
	inset: 0;
	pointer-events: none;
	background: linear-gradient(
		to top,
		rgba(13, 14, 10, .97) 0%,
		rgba(13, 14, 10, .95) 26%,
		rgba(13, 14, 10, .55) 52%,
		rgba(13, 14, 10, 0) 85%
	);
}

/*  Most featured images here are termshots, so a slide is usually TEXT under
    text. A gentle scrim that works over a photograph leaves the headline
    sitting on top of legible terminal output, and both become unreadable —
    hence the near-opaque bottom half above, and the left-anchored crop
    below so the part of the capture that survives is the part that starts
    each line.  */
.revenant-carousel .wp-block-post-featured-image img {
	object-position: left center;
}

/*  A gradient alone still lets terminal output show through behind the
    headline, because the capture's own text is bright where the scrim is
    thinnest. The body carries its own near-solid ground so the type always
    sits on something, whatever the image underneath happens to be.  */
/*  Kept under half the slide height on purpose — the picture is the reason a
    carousel exists, and a caption panel taller than the image it captions is
    a list with a photograph behind it. The date was dropped for the same
    reason: it is a whole line's worth of height for information the card
    lists below already carry.  */
.revenant-slide-body {
	position: absolute;
	inset: auto 0 0 0;
	z-index: 2;
	max-height: 48%;
	overflow: hidden;
	padding: .8rem 1.4rem 1rem;
	background: linear-gradient(
		to top,
		rgba(13, 14, 10, .99) 0%,
		rgba(13, 14, 10, .96) 55%,
		rgba(13, 14, 10, .78) 100%
	);
}

/*  Clamped to two lines. On a 245px slide a three-line headline leaves almost
    no picture showing, which defeats the point of a picture-led carousel.  */
.revenant-slide-body .wp-block-post-title {
	margin-block: 0;
	font-size: clamp(1.1rem, 1.55vw, 1.45rem);
	line-height: 1.16;
	display: -webkit-box;
	-webkit-line-clamp: 2;
	line-clamp: 2;
	-webkit-box-orient: vertical;
	overflow: hidden;
}

.revenant-slide-body .wp-block-post-title a {
	color: var(--rv-ink);
}

/*  Pinned to the top, not centred, and not at a percentage either — both of
    those were tried and both collide. The slide body grows UPWARD from the
    bottom as the headline wraps, so on a short slide with a long title there
    is no percentage that clears it. The top edge is the only position that
    is safe at every combination of slide height and headline length.  */
.revenant-carousel-arrow {
	position: absolute;
	top: .8rem;
	z-index: 3;
	width: 2.6rem;
	height: 2.6rem;
	display: grid;
	place-items: center;
	font-size: 1.7rem;
	line-height: 1;
	padding: 0 0 .18em;
	cursor: pointer;
	color: var(--rv-ink);
	background: rgba(13, 14, 10, .72);
	border: 1px solid var(--rv-line);
	transition: background .2s ease, border-color .2s ease;
}

.revenant-carousel-arrow:hover {
	background: var(--rv-rust);
	border-color: var(--rv-rust);
}

.revenant-carousel-arrow.is-prev { left: .8rem; }
.revenant-carousel-arrow.is-next { right: .8rem; }

/*  BANDS
    The old separator was a 1px #2b2e22 hairline on a #131410 ground — about
    1.3:1, which is to say invisible. Soledad separates with a filled bar and
    a notch under it; same idea here, in the palette: a panel bar with an
    olive spine and a hard notch. The alternate band also takes a panel
    ground so the two streams are separated by more than a heading.  */
.revenant-band {
	margin-block: 0 4rem;
}

.revenant-band:last-child {
	margin-block-end: 0;
}

.revenant-band-alt {
	background: var(--rv-panel);
	border: 1px solid var(--rv-line);
	padding: 1.6rem 1.6rem .4rem;
}

.revenant-band-head {
	position: relative;
	align-items: center;
	background: var(--rv-panel);
	border-left: 4px solid var(--rv-olive-hi);
	padding: .72rem 1rem;
	margin-block: 0 1.5rem;
}

.revenant-band-alt .revenant-band-head {
	background: var(--rv-void);
	border-left-color: var(--rv-rust);
}

/*  The notch. A 14px square rotated 45deg and pushed half out of the bar —
    the same device Soledad puts under its widget titles, and the reason its
    section heads read as headers rather than as bold paragraphs.  */
.revenant-band-head::after {
	content: "";
	position: absolute;
	left: 1.7rem;
	bottom: -7px;
	width: 14px;
	height: 14px;
	background: inherit;
	transform: rotate(45deg);
}

.revenant-band-title {
	font-family: var(--rv-cond);
	font-stretch: condensed;
	text-transform: uppercase;
	letter-spacing: .2em;
	font-weight: 700;
	font-size: 1rem;
	margin: 0;
	color: var(--rv-ink);
}

.revenant-band-more {
	margin: 0;
}

.revenant-band-sub {
	color: var(--rv-muted);
	margin-block: 0 1.6rem;
}

.revenant-empty {
	color: var(--rv-muted);
	padding: 2rem 0;
}

/*  SHELL — main column plus sidebar  */
.revenant-shell {
	gap: 3rem;
	margin-bottom: 4rem;
}

/*  CARDS — The Lab. A contained panel with hard corners; the news stream
    is deliberately NOT contained, which is what makes the two streams
    separable at a glance without reading either heading.  */
.revenant-cards .wp-block-post-template {
	gap: 1.6rem;
}

.revenant-cards .wp-block-post {
	background: var(--rv-panel);
	border: 1px solid var(--rv-line);
	padding: 0 0 1.1rem;
	display: flex;
	flex-direction: column;
	transition: border-color .25s ease;
}

.revenant-cards .wp-block-post:hover {
	border-color: var(--rv-olive-hi);
}

.revenant-band-alt .revenant-cards .wp-block-post {
	background: var(--rv-void);
}

.revenant-cards .wp-block-post-featured-image {
	margin: 0 0 .9rem;
}

.revenant-cards .revenant-pills,
.revenant-cards .wp-block-post-title,
.revenant-cards .wp-block-post-excerpt,
.revenant-cards .wp-block-post-date {
	padding-inline: 1.05rem;
}

.revenant-cards .wp-block-post-title {
	margin-block: 0 .5rem;
	line-height: 1.22;
	font-size: 1.18rem;
}

.revenant-cards .wp-block-post-excerpt {
	color: var(--rv-muted);
	font-size: .9rem;
	margin-block: 0 .6rem;
}

.revenant-cards .wp-block-post-excerpt__more-text {
	display: none;
}

.revenant-cards .wp-block-post-date {
	margin-block: auto 0;
	padding-top: .3rem;
}

/*  Same empty-track problem as the filmstrip: `columnCount: 3` lays out
    three tracks, and the current post is filtered out of this query, so on a
    small site it is routinely showing two. auto-fit collapses the spare.  */
.revenant-cards-3 .wp-block-post-template {
	gap: 1.2rem;
	grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)) !important;
}

/*  Most Lab illustrations are termshots — wide captures of terminal output.
    A 16:9 `cover` crop centres them and eats the LEFT edge, which is where
    every line of that output begins, so the thumbnail shows the middle of
    sentences. `contain` on a void ground keeps the tile a uniform 16:9 for
    the grid while leaving the capture whole and legible.

    The aspect-ratio attribute writes `object-fit:cover` inline on the <img>,
    which is the only reason this needs !important.

    Row, filmstrip and carousel images stay on `cover`: they are art, not
    screenshots of text, and a letterboxed slide would look broken.  */
.revenant-cards .wp-block-post-featured-image img {
	object-fit: contain !important;
	background: var(--rv-void);
}

/*  ROWS — The Signal. Square thumbnail left, text right, hairline between.  */
.revenant-rows .wp-block-post {
	display: grid;
	grid-template-columns: 116px 1fr;
	gap: 1.2rem;
	padding-block: 1.5rem;
	border-bottom: 1px solid var(--rv-line);
}

.revenant-rows .wp-block-post:first-child {
	padding-top: 0;
}

.revenant-rows .wp-block-post:last-child {
	border-bottom: 0;
}

.revenant-rows .wp-block-post-featured-image {
	margin: 0;
}

.revenant-rows .wp-block-post-title {
	margin-block: 0 .4rem;
	line-height: 1.24;
	font-size: 1.15rem;
}

.revenant-rows .wp-block-post-excerpt {
	color: var(--rv-muted);
	font-size: .92rem;
	margin-block: 0 .5rem;
}

.revenant-rows .wp-block-post-excerpt__more-text {
	display: none;
}

.revenant-pagination {
	margin-top: 2rem;
}

/*  THE FORUM BAND
    All four forum blocks used to sit stacked in the sidebar, where together
    they were longer than the sidebar's actual job. Given a full-width band
    they fit in three columns and take a fraction of the vertical space, and
    the sidebar goes back to being blog navigation.

    Homepage only. Archives and articles get the lean sidebar and nothing
    else — a reader mid-article is not the person to interrupt with a forum
    roll call.  */
.revenant-forumband {
	margin-block: 0 3rem;
	padding: 1.6rem 1.6rem .4rem;
	background: var(--rv-panel);
	border: 1px solid var(--rv-line);
}

.revenant-forumband .revenant-band-head {
	background: var(--rv-void);
	border-left-color: var(--rv-rust);
}

.revenant-forumband-cols {
	gap: 2.5rem;
}

.revenant-forumband-title {
	font-family: var(--rv-cond);
	font-stretch: condensed;
	text-transform: uppercase;
	letter-spacing: .18em;
	font-weight: 700;
	font-size: .78rem;
	color: var(--rv-olive-hi);
	margin-block: 0 1rem;
}

/*  Inside the band the rows have room, so the meta line sits beside the title
    rather than under it the way the narrow sidebar forced. Two lines per row
    was the sidebar's constraint, kept here by accident: it made every row 90px
    tall and left the three columns ending at three different heights. One
    baseline per row halves the band and squares the bottoms off.

    Above 782px only — that is where WordPress stops stacking columns, and on a
    phone the row is back to being narrow, where the meta belongs underneath.  */
@media (min-width: 782px) {
	.revenant-forumband .revenant-forumfeed__item,
	.revenant-forumband .revenant-otd__item {
		display: flex;
		align-items: baseline;
		gap: .75rem;
	}

	.revenant-forumband .revenant-forumfeed__title,
	.revenant-forumband .revenant-otd__title {
		flex: 1;
		min-width: 0;
	}

	.revenant-forumband .revenant-forumfeed__meta,
	.revenant-forumband .revenant-otd__who {
		flex: none;
		margin-top: 0;
		font-size: .72rem;
	}

	.revenant-forumband .revenant-otd__year {
		flex: none;
		margin-bottom: 0;
	}
}

.revenant-forumband .revenant-forumfeed__item + .revenant-forumfeed__item,
.revenant-forumband .revenant-otd__item + .revenant-otd__item {
	margin-top: .55rem;
	padding-top: .55rem;
}

.revenant-forumband .revenant-stats__row {
	padding: .3rem 0;
}

.revenant-forumband .revenant-around {
	margin-bottom: 1.4rem;
}

/*  FILMSTRIP
    Soledad ends its pages with a full-bleed six-image band (an Instagram
    feed in its case). Same device, fed from the site's own recent posts:
    edge to edge, no gaps, title over a scrim.  */
.revenant-filmstrip {
	margin-top: 1rem;
	border-top: 1px solid var(--rv-line);
}

/*  The template block writes `columnCount: 6`, which lays out six tracks
    whether or not six posts exist — with three published the strip filled
    half the page and stopped. auto-fit collapses the empty tracks, so the
    strip is always full width at whatever count the site currently has.
    The fixed height is what keeps it a strip: 1:1 tiles across a wide
    viewport would otherwise be 500px tall each.  */
.revenant-filmstrip .wp-block-post-template {
	gap: 0;
	grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)) !important;
}

/*  The aspect-ratio attribute writes its ratio on the WRAPPER and
    `height:100%` inline on the <img>, so capping the image's height does
    nothing — the wrapper is what has to be told. Without this a 1:1 tile on
    a wide viewport is ~500px tall and the "strip" is a wall.  */
.revenant-filmstrip .wp-block-post-featured-image {
	height: 200px !important;
	aspect-ratio: auto !important;
}

.revenant-filmstrip .wp-block-post-featured-image img {
	height: 100%;
	object-fit: cover !important;
	object-position: left center;
}

.revenant-filmstrip .wp-block-post {
	position: relative;
	margin: 0;
	overflow: hidden;
}

.revenant-filmstrip .wp-block-post-featured-image {
	margin: 0;
}

.revenant-filmstrip .wp-block-post-title {
	position: absolute;
	inset: auto 0 0 0;
	margin: 0;
	padding: 2.2rem .8rem .7rem;
	font-size: .82rem;
	line-height: 1.25;
	background: linear-gradient(to top, rgba(13, 14, 10, .93), rgba(13, 14, 10, 0));
}

/*  ARCHIVE TITLE BAND — a slim band, not a hero. A hero on every archive
    stops being a hero and just pushes the listing below the fold.  */
.revenant-titleband {
	margin-block: 2.2rem 2.6rem;
	padding-bottom: 1.4rem;
	border-bottom: 1px solid var(--rv-line);
}

.revenant-titleband .wp-block-query-title {
	margin-block: .3rem 0;
}

.revenant-titleband .wp-block-term-description {
	color: var(--rv-muted);
	margin-block: .7rem 0;
	max-width: 52ch;
}

/*  SIDEBAR
    The main column runs far longer than the sidebar does, so without sticky
    the right third of the page is empty for the whole length of the page.
    Costs one rule and no script — Soledad ships a jQuery plugin for it.  */
.revenant-aside-inner {
	position: sticky;
	top: 1.5rem;
}

.revenant-aside-block {
	padding-bottom: 1.5rem;
	margin-bottom: 1.5rem;
	border-bottom: 1px solid var(--rv-line);
}

.revenant-aside-block:last-child {
	border-bottom: 0;
}

/*  Sidebar headings get the bar-and-notch too, at a smaller size, so the
    page has one section-header device rather than two.  */
.revenant-aside-title {
	position: relative;
	font-family: var(--rv-cond);
	font-stretch: condensed;
	text-transform: uppercase;
	letter-spacing: .18em;
	font-weight: 700;
	font-size: .78rem;
	color: var(--rv-ink);
	background: var(--rv-panel);
	border-left: 3px solid var(--rv-olive-hi);
	padding: .55rem .8rem;
	margin-block: 0 1.2rem;
}

.revenant-aside-title::after {
	content: "";
	position: absolute;
	left: 1.3rem;
	bottom: -6px;
	width: 12px;
	height: 12px;
	background: inherit;
	transform: rotate(45deg);
}

.revenant-aside-list .wp-block-post + .wp-block-post {
	margin-top: .9rem;
	padding-top: .9rem;
	border-top: 1px solid var(--rv-line);
}

.revenant-aside-list .wp-block-post-title {
	margin-block: 0 .25rem;
	line-height: 1.3;
	font-size: .95rem;
}

/*  FROM THE BOARD
    phpBB's Atom feed rendered by the core RSS block. Titles arrive as
    "Forum name • Topic title" and are left that way — the forum name is
    useful context, and rewriting it would mean filtering the block's output
    for cosmetics.

    The `topics` feed is new THREADS, not new posts. `overall` is fresher but
    its titles come out as "General Discussion • " with nothing after, because
    the bot-posted replies carry no post subject; fixing that means changing
    the board, which is frozen. Hence the honest label.  */
.revenant-forumfeed {
	list-style: none;
	padding: 0;
	margin: 0 0 .9rem;
}

.revenant-forumfeed__item + .revenant-forumfeed__item,
.revenant-otd__item + .revenant-otd__item {
	margin-top: .8rem;
	padding-top: .8rem;
	border-top: 1px solid var(--rv-line);
}

.revenant-forumfeed__title,
.revenant-otd__title {
	display: block;
	color: var(--rv-ink);
	text-decoration: none;
	font-family: var(--rv-cond);
	font-stretch: condensed;
	font-weight: 700;
	font-size: .95rem;
	line-height: 1.3;
}

.revenant-forumfeed__title:hover,
.revenant-otd__title:hover {
	color: var(--rv-rust-hi);
}

.revenant-forumfeed__meta,
.revenant-otd__who {
	display: block;
	margin-top: .25rem;
	color: var(--rv-muted);
	font-family: var(--rv-cond);
	font-stretch: condensed;
	text-transform: uppercase;
	letter-spacing: .14em;
	font-size: .78rem;
}

/*  ON THIS DAY
    The year is the point of the block — it is what turns a list of threads
    into "this happened here, on this date, years ago", so it leads and it is
    the one thing allowed to carry the accent.  */
.revenant-otd {
	list-style: none;
	padding: 0;
	margin: 0;
}

.revenant-otd__year {
	display: block;
	color: var(--rv-rust-hi);
	font-family: var(--rv-cond);
	font-stretch: condensed;
	font-weight: 700;
	letter-spacing: .18em;
	font-size: .78rem;
	margin-bottom: .15rem;
}

/*  AROUND
    Names, not avatars. The board's avatars are 100px gallery images and six of
    them would outweigh everything else in the sidebar; the block only has to
    answer "are there people here", and names do that at a tenth of the weight.  */
.revenant-around {
	display: flex;
	flex-wrap: wrap;
	gap: .4rem;
	margin: 0;
}

/*  FORUM STATS
    Label left, value right, on one baseline — a definition list in behaviour
    if not in markup, which is the only layout that lets six unrelated numbers
    be scanned rather than read.  */
.revenant-stats {
	list-style: none;
	padding: 0;
	margin: 0;
}

.revenant-stats__row {
	display: flex;
	align-items: baseline;
	justify-content: space-between;
	gap: 1rem;
	padding: .42rem 0;
	border-bottom: 1px solid var(--rv-line);
	font-size: .85rem;
}

.revenant-stats__row:last-child {
	border-bottom: 0;
}

.revenant-stats__row > span {
	color: var(--rv-muted);
}

.revenant-stats__row > b {
	color: var(--rv-ink);
	font-family: var(--rv-cond);
	font-stretch: condensed;
	text-align: right;
}

.revenant-stat__when {
	margin-left: .5em;
	color: var(--rv-muted);
	font-weight: 400;
	font-size: .76rem;
	letter-spacing: .08em;
	text-transform: uppercase;
}

/*  The trust line is a sentence, not a stat block — it sits above the
    colophon and is the last thing read on any page.  */
.revenant-trustline {
	margin: 0 0 .35rem;
	color: var(--rv-ink-2);
	font-family: var(--rv-cond);
	font-stretch: condensed;
	text-transform: uppercase;
	letter-spacing: .16em;
	font-size: .8rem;
}

.revenant-around__name {
	display: inline-block;
	text-decoration: none;
	font-family: var(--rv-cond);
	font-stretch: condensed;
	text-transform: uppercase;
	letter-spacing: .1em;
	font-size: .72rem;
	line-height: 1;
	padding: .42em .6em .38em;
	border: 1px solid var(--rv-line);
	color: var(--rv-ink-2);
}

.revenant-around__name:hover {
	border-color: var(--rv-rust);
	color: var(--rv-rust-hi);
}

.revenant-aside-more {
	margin: 0;
}

.revenant-genre-list {
	list-style: none;
	padding: 0;
	margin: 0;
}

.revenant-genre-list li + li {
	margin-top: .5rem;
}

/*  The genre links carry the same category-<slug> class the pills use, so a
    swatch can be painted from the identical variable. One palette, two
    places, no second list of colours to keep in sync.  */
.revenant-genre {
	display: flex;
	align-items: center;
	gap: .6rem;
	font-family: var(--rv-cond);
	font-stretch: condensed;
	text-transform: uppercase;
	letter-spacing: .1em;
	font-size: .78rem;
	color: var(--rv-ink-2);
	text-decoration: none;
}

.revenant-genre::before {
	content: "";
	inline-size: .7rem;
	block-size: .7rem;
	flex: 0 0 auto;
	background: var(--pill-bg, var(--rv-line));
}

.revenant-genre:hover {
	color: var(--rv-rust-hi);
}

/*  BROWSE BY GAME
    core/tag-cloud rather than a hand-written list, because the game vocabulary
    is meant to grow as coverage grows and a hardcoded list would need a theme
    deploy per game. Equal smallest/largest font sizes switch off the block's
    size-by-popularity scaling, which reads as a 2006 tag cloud and makes the
    rarest game the hardest to click. Neutral chips, not the genre palette: a
    game has no one genre colour, and DayZ appearing in two sections would have
    to pick one.  */
.revenant-gamecloud {
	display: flex;
	flex-wrap: wrap;
	gap: .4rem;
}

.revenant-gamecloud a {
	display: inline-flex;
	align-items: baseline;
	gap: .35rem;
	padding: .25rem .55rem;
	border: 1px solid var(--rv-line);
	font-family: var(--rv-cond);
	font-stretch: condensed;
	text-transform: uppercase;
	letter-spacing: .08em;
	font-size: .78rem !important;
	line-height: 1.2;
	color: var(--rv-ink-2);
	text-decoration: none;
}

.revenant-gamecloud a:hover {
	border-color: var(--rv-rust-hi);
	color: var(--rv-rust-hi);
}

.revenant-gamecloud .tag-link-count {
	color: var(--rv-muted);
	font-size: .7rem;
}

.revenant-aside-cta p:last-child {
	line-height: 2;
}

/*  Reserved ad slot. Empty until an AdSense snippet goes in, and invisible
    while empty so the page never shows a hole.  */
.revenant-ad:empty {
	display: none;
}

.revenant-ad-inline {
	margin-block: 2.5rem;
}

/*  SINGLE
    Wider than the old 680 column and now carrying the sidebar. The two
    custom properties are what WordPress's constrained layout reads, so
    setting them here narrows this page's `alignwide` and widens its reading
    measure without touching theme.json, which every other view uses.  */
.revenant-single-shell {
	--wp--style--global--wide-size: 1180px;
	--wp--style--global--content-size: 780px;
	margin-block-start: 2.4rem;
}

.revenant-article-head {
	margin-block: 0 1.8rem;
	padding-bottom: 1.4rem;
	border-bottom: 1px solid var(--rv-line);
}

/*  Pages — About, Contact, Privacy, Terms, The Servers.
    No sidebar: these are read once, on purpose, and a legal page with a
    "browse by genre" widget beside it is a page nobody finishes. They keep
    the article measure so the reading typography above applies unchanged,
    and the shell is narrowed to it since there is no second column to fill.  */
.revenant-page {
	--wp--style--global--wide-size: 820px;
}

.revenant-page .revenant-article-head {
	margin-block: 0 2rem;
}

.revenant-article-head .wp-block-post-title {
	margin-block: 0 .6rem;
	line-height: 1.1;
}

/*  Tags do not exist yet, and core/post-terms renders nothing without them,
    so the row would otherwise be a stray rule across the page.  */
.revenant-tagrow {
	margin-block: 2.4rem 0;
	padding-top: 1.3rem;
	border-top: 1px solid var(--rv-line);
	gap: .45rem;
	align-items: center;
}

.revenant-tagrow:not(:has(a)) {
	display: none;
}

.revenant-tagrow .wp-block-post-terms {
	margin: 0;
	color: var(--rv-muted);
	font-size: .85rem;
}

.revenant-tagrow a {
	display: inline-block;
	margin-inline: .2rem;
	padding: .3em .6em;
	border: 1px solid var(--rv-line);
	color: var(--rv-ink-2);
	text-decoration: none;
	font-size: .78rem;
}

.revenant-tagrow a:hover {
	border-color: var(--rv-rust-hi);
	color: var(--rv-rust-hi);
}

/*  READ NEXT
    prev/next rather than a "related" grid, because a Query Loop has no
    exclude-current-post control of its own. The related band below it uses
    the `query_loop_block_query_vars` filter in functions.php for that.  */
.revenant-readnext {
	margin-block: 2.6rem 3.2rem;
	padding-top: 1.6rem;
	border-top: 1px solid var(--rv-line);
}

.revenant-readnext-pair {
	gap: 1.5rem;
}

.revenant-readnext-pair .post-navigation-link-next {
	text-align: right;
	margin-left: auto;
}

/*  RESPONSIVE
    One breakpoint for the shell. WordPress stacks its own columns at 781px,
    which is far too late for a 28% sidebar — it is squeezed to unreadable
    long before that. The inline flex-basis the column block writes is why
    these need !important.  */
@media (max-width: 1000px) {
	.revenant-shell {
		flex-wrap: wrap;
	}

	.revenant-shell > .wp-block-column {
		flex-basis: 100% !important;
	}

	.revenant-aside {
		margin-top: 1rem;
		padding-top: 2rem;
		border-top: 1px solid var(--rv-line);
	}

	.revenant-aside-inner {
		position: static;
	}

	.revenant-filmstrip .wp-block-post-template.is-layout-grid {
		grid-template-columns: repeat(3, 1fr);
	}
}

@media (max-width: 640px) {
	.revenant-cards .wp-block-post-template.is-layout-grid,
	.revenant-cards-3 .wp-block-post-template.is-layout-grid {
		grid-template-columns: 1fr;
	}

	.revenant-rows .wp-block-post {
		grid-template-columns: 84px 1fr;
		gap: .9rem;
	}

	.revenant-rows .wp-block-post-excerpt {
		display: none;
	}

	.revenant-band-alt {
		padding-inline: 1rem;
	}

	.revenant-slide-body {
		padding: 1rem 1.1rem .9rem;
	}

	.revenant-carousel-arrow {
		width: 2.1rem;
		height: 2.1rem;
		font-size: 1.3rem;
	}
}
