/* ==========================================================================
   Sovereign Terminal v5 — light paper finance newsroom
   --------------------------------------------------------------------------
   A high-contrast LIGHT-ONLY theme: a cool white paper ground, near-black
   indigo ink, and one electric blue-violet accent that carries every CTA and
   feature panel. Condensed heavy uppercase display type and letterspaced
   micro-caps for kickers and bylines.

   The token NAMES are inherited from the previous dark build and are kept
   deliberately — every one of the ~3800 rules below refers to them, so
   renaming would touch the whole file for no visual gain. Their MEANING is
   inverted:

     --navy-*  is no longer a descending navy ramp but an ASCENDING surface
               ramp. --navy-800 is the page (pure white); each step away from
               it is a progressively more tinted panel. So the -900 / -850
               "deep" steps are now the most saturated wells, and code that
               reached for a deeper navy to sink a panel still sinks it.
     --ink-*   runs dark-to-light exactly as before: -100 is the strongest
               headline ink, -500 the quietest meta. Every `color: var(--ink-…)`
               therefore keeps its intended hierarchy with no edits.

   Only the two ends needed real care. --ink-100 was #FFFFFF (a headline on
   navy) and is now near-black; --line-* were white-alpha hairlines and are now
   ink-alpha. Both are commented in place below.

   Sections in order:
     1  Tokens
     2  Reset / base
     3  Typography primitives
     4  Buttons, chips, badges
     5  Header / navigation
     6  Cards (the shared article-card vocabulary)
     7  Front page sections
     8  Newsletter band
     9  Footer
    10  Archive / category
    11  Single post
    12  Static page
    13  404
    14  Utilities, motion, print
   ========================================================================== */

/* ── 1. Tokens ───────────────────────────────────────────────────────────── */
:root {
	/* Ground — an ASCENDING surface ramp (see the header note). -800 is the
	   page itself; the steps either side are tinted panels. The tint is a cool
	   indigo-grey rather than neutral grey, so every surface stays related to
	   the violet accent and the page never looks like unstyled white.

	   -800 → the page. Pure white, so photographs and the violet read at full
	          strength against it.
	   -850 → raised bands (.is-raised), the step that separates a section.
	   -900 → the most tinted well (.is-deep, code blocks, form fields).
	   -750 → inset media placeholders, sitting just off the page.
	   -700 / -600 → progressively firmer fills for chips and avatars. */
	--navy-800: #FFFFFF;
	--navy-850: #F4F5FB;
	--navy-900: #EBEDF7;
	--navy-750: #E4E7F4;
	--navy-700: #D8DCEF;
	--navy-600: #C6CBE6;

	/* The single accent. Everything that must be pressed, or must read as a
	   feature panel, is this violet. Deepened from the dark build's #4A47F5:
	   on white that original hit only ~4.9:1 and looked hazy, where this
	   passes AA for body text and still reads as electric rather than navy.
	   -300 is no longer a light tint for dark grounds but a DEEPER shade, so
	   every `color: var(--violet-300)` hover state stays legible on paper. */
	--violet-500: #3A32E0;
	--violet-400: #4B44F0;
	--violet-600: #2A24B8;
	--violet-300: #2E27C4;

	/* Ink on paper. Same dark-to-light hierarchy the dark build had, so the
	   existing rules keep their meaning — only the absolute values moved.
	   -100 is a near-black indigo rather than pure black: pure #000 on white
	   vibrates at display weight, and the blue cast ties the type to the
	   accent. Every step is AA or better on the -800/-850 grounds. */
	--ink-100: #0A0722;
	--ink-200: #1E1A3C;
	--ink-300: #3D3866;
	--ink-400: #5A5480;
	/* The quietest step, used for timestamps, counts and footer legal links.
	   Darkened from #736D96, which cleared AA on the white page (4.82) but fell
	   to 4.13 on the --navy-900 footer ground where much of this text actually
	   sits. This value clears 4.5 on every surface in the ramp. */
	--ink-500: #6A6490;

	/* Hairlines. Inverted from white-alpha to INK-alpha, keeping the same two
	   weights: a whisper for card divisions, a firmer one for section rules
	   that need to hold a heading. Alphas are higher than the dark build's
	   0.09/0.17 because a dark line on white at 9% is invisible, where a white
	   line on navy at 9% still glows. */
	--line-soft: rgba(10, 7, 34, 0.13);
	--line-firm: rgba(10, 7, 34, 0.26);

	/* Category accents. Re-tuned from the dark build: each swatch is darkened
	   and saturated so it holds its identity as a fill behind WHITE text on a
	   white page. The originals were chosen to glow against navy — amber, sky
	   and rose in particular washed out completely on paper. */
	--amber: #A05F00;
	--red: #C2261A;
	--green: #1F7346;
	--sky: #2E63BE;
	--rose: #C43A61;
	--teal: #0F7F76;

	/* Type. Archivo carries display at 800 with tight tracking; Inter takes
	   body copy where Archivo's apertures would cost readability. */
	--font-display: "Archivo", "Helvetica Neue", Arial, sans-serif;
	--font-body: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;

	/* Fluid display scale. Every headline size is a clamp so the layout never
	   needs a breakpoint purely to resize type. */
	--fs-display: clamp(2.6rem, 6.4vw, 5.4rem);
	--fs-h1: clamp(2rem, 4.4vw, 3.4rem);
	--fs-h2: clamp(1.6rem, 3vw, 2.5rem);
	--fs-h3: clamp(1.15rem, 1.8vw, 1.55rem);
	--fs-lead: clamp(1.02rem, 1.4vw, 1.2rem);
	--fs-body: 1rem;
	--fs-sm: 0.875rem;
	--fs-xs: 0.75rem;
	--fs-micro: 0.6875rem;

	/* Rhythm */
	--gap: clamp(1.1rem, 2.2vw, 1.75rem);
	--gap-lg: clamp(1.75rem, 3.5vw, 3rem);
	--pad-section: clamp(3rem, 6.5vw, 5.5rem);
	--container: 1320px;
	--container-narrow: 760px;
	--radius: 4px;
	--radius-lg: 10px;
	--radius-pill: 999px;

	--logo-h: 40px;

	--ease: cubic-bezier(0.22, 0.61, 0.36, 1);
	--dur: 0.32s;
}

/* ── 2. Reset / base ─────────────────────────────────────────────────────── */
*,
*::before,
*::after {
	box-sizing: border-box;
}

* {
	margin: 0;
}

html {
	-webkit-text-size-adjust: 100%;
	scroll-behavior: smooth;
	/* Light-only, declared in CSS as well as the <meta> in header.php so native
	   UI — scrollbars, form controls, autofill, spellcheck underlines — follows
	   the theme even if the document is served from cache. */
	color-scheme: light;
	/* Fixed header height plus breathing room, so an in-page anchor never
	   lands with its heading tucked under the masthead. */
	scroll-padding-top: 120px;
}

body {
	background: var(--navy-800);
	color: var(--ink-200);
	font-family: var(--font-body);
	font-size: var(--fs-body);
	line-height: 1.65;
	-webkit-font-smoothing: antialiased;
	-moz-osx-font-smoothing: grayscale;
	overflow-x: hidden;
}

img,
picture,
svg,
video {
	display: block;
	max-width: 100%;
}

img {
	height: auto;
}

a {
	color: inherit;
	text-decoration: none;
}

button,
input,
select,
textarea {
	font: inherit;
	color: inherit;
}

button {
	background: none;
	border: 0;
	cursor: pointer;
}

ul,
ol {
	list-style: none;
	padding: 0;
}

:focus-visible {
	/* -500 rather than the dark build's -300: the focus ring must be the
	   loudest thing on a pale surface, and -300 is now a deeper shade used for
	   text rather than the bright tint it was on navy. */
	outline: 2px solid var(--violet-500);
	outline-offset: 3px;
	border-radius: 2px;
}

::selection {
	background: var(--violet-500);
	color: #fff;
}

.container {
	width: 100%;
	max-width: var(--container);
	margin-inline: auto;
	padding-inline: clamp(1rem, 3.5vw, 2.5rem);
}

.container--narrow {
	max-width: var(--container-narrow);
}

.section-pad {
	padding-block: var(--pad-section);
}

.section-pad--tight {
	padding-block: clamp(2rem, 4vw, 3.25rem);
}

/* Raised band: one step lighter than the page, used to separate a section
   without introducing a second hue. */
.is-raised {
	background: var(--navy-850);
}

.is-deep {
	background: var(--navy-900);
}

.skip-link {
	position: absolute;
	left: -9999px;
	top: 0;
	z-index: 999;
	background: var(--violet-500);
	color: #fff;
	padding: 0.75rem 1.25rem;
	font-weight: 600;
}

.skip-link:focus {
	left: 1rem;
	top: 1rem;
}

/* ── 3. Typography primitives ────────────────────────────────────────────── */

/* The reference's signature: heavy condensed uppercase, tracked tight, with
   a line-height under 1 so multi-line headlines lock into a block. */
.display,
.sec-head__title,
.pulse-head__title,
.error-page__title {
	font-family: var(--font-display);
	font-weight: 800;
	text-transform: uppercase;
	letter-spacing: -0.015em;
	line-height: 0.96;
	color: var(--ink-100);
}

/* Kicker: the small letterspaced label above a headline. Reads as the desk
   or story angle — "RACE TO REDUCE", "GAME GUIDE" in the reference. */
.kicker {
	display: inline-block;
	font-family: var(--font-body);
	font-size: var(--fs-micro);
	font-weight: 600;
	text-transform: uppercase;
	letter-spacing: 0.16em;
	color: var(--ink-400);
	margin-bottom: 0.55rem;
}

.kicker--accent {
	color: var(--violet-300);
}

/* Byline: uppercase, tracked, quiet. Never competes with the headline. */
.byline {
	display: inline-flex;
	align-items: center;
	gap: 0.5rem;
	font-size: var(--fs-micro);
	font-weight: 600;
	text-transform: uppercase;
	letter-spacing: 0.14em;
	color: var(--ink-400);
	line-height: 1.4;
}

.byline__avatar {
	width: 26px;
	height: 26px;
	border-radius: 50%;
	object-fit: cover;
	flex-shrink: 0;
	background: var(--navy-700);
}

.byline--lg .byline__avatar {
	width: 44px;
	height: 44px;
}

.byline--plain .byline__avatar {
	display: none;
}

.byline__stack {
	display: flex;
	flex-direction: column;
	gap: 0.1rem;
}

.byline__name {
	color: var(--ink-300);
}

.byline--lg .byline__name {
	font-size: var(--fs-xs);
	color: var(--ink-200);
}

.byline__role,
.byline__sep,
.byline time {
	font-weight: 500;
	letter-spacing: 0.1em;
	color: var(--ink-500);
	text-transform: none;
}

.byline__role {
	text-transform: uppercase;
	letter-spacing: 0.14em;
}

/* Meta row: reading time and date, hairline separated. */
.metarow {
	display: inline-flex;
	align-items: center;
	gap: 0.85rem;
	font-size: var(--fs-micro);
	font-weight: 500;
	letter-spacing: 0.1em;
	text-transform: uppercase;
	color: var(--ink-500);
}

.metarow__item {
	display: inline-flex;
	align-items: center;
	gap: 0.35rem;
}

.metarow svg {
	width: 12px;
	height: 12px;
	flex-shrink: 0;
	opacity: 0.75;
}

/* Section heading: the rule-and-title pattern that opens every band. */
.sec-head {
	display: flex;
	align-items: flex-end;
	justify-content: space-between;
	gap: var(--gap);
	flex-wrap: wrap;
	padding-bottom: 1.1rem;
	margin-bottom: var(--gap-lg);
	border-bottom: 1px solid var(--line-firm);
}

.sec-head__title {
	font-size: var(--fs-h2);
}

.sec-head__kicker {
	font-size: var(--fs-sm);
	color: var(--ink-400);
	max-width: 44ch;
}

/* Centred variant — the reference's "ON THE PULSE" band. */
.sec-head--center {
	flex-direction: column;
	align-items: center;
	text-align: center;
	border-bottom: 0;
	gap: 0.5rem;
	margin-bottom: var(--gap-lg);
}

.sec-head--center .sec-head__title {
	font-size: var(--fs-h1);
}

/* ── 4. Buttons, chips, badges ───────────────────────────────────────────── */
.btn {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 0.5rem;
	padding: 0.7rem 1.4rem;
	border-radius: var(--radius-pill);
	font-size: var(--fs-xs);
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: 0.1em;
	line-height: 1;
	white-space: nowrap;
	border: 1px solid transparent;
	transition: background var(--dur) var(--ease), color var(--dur) var(--ease),
		border-color var(--dur) var(--ease), transform var(--dur) var(--ease);
}

.btn:hover {
	transform: translateY(-1px);
}

.btn:active {
	transform: translateY(0);
}

.btn--primary {
	background: var(--violet-500);
	color: #fff;
}

.btn--primary:hover {
	background: var(--violet-400);
}

.btn--ghost {
	border-color: var(--line-firm);
	color: var(--ink-200);
}

.btn--ghost:hover {
	border-color: var(--violet-500);
	/* Was white-on-violet-tint. On paper the fill stays a pale violet wash and
	   the label goes to the accent, which is the higher-contrast pairing. */
	color: var(--violet-600);
	background: rgba(58, 50, 224, 0.09);
}

/* The inverse button: on the old dark ground this was white-on-navy. It is
   still the "solid, non-accent" CTA, so on paper it inverts to ink-on-white.
   Used inside violet bands where a violet button would disappear. */
.btn--light {
	background: var(--ink-100);
	color: #fff;
}

.btn--light:hover {
	background: var(--ink-200);
	color: #fff;
}

/* Inside a violet band the ghost button's ink border and label would vanish,
   so it reverts to the white-on-dark treatment there. .brief is excluded on
   purpose: its only button sits inside the white card, not on the band. */
.showcase .btn--ghost,
.statband .btn--ghost {
	border-color: rgba(255, 255, 255, 0.45);
	color: #fff;
}

.showcase .btn--ghost:hover,
.statband .btn--ghost:hover {
	border-color: #fff;
	background: rgba(255, 255, 255, 0.14);
	color: #fff;
}

/* A white solid button reads best inside those same bands.
   NOT .brief: its button lives inside the white card on the violet band, not
   on the band itself, so white-on-white would erase it. The card's button
   keeps the default ink/violet .btn--light treatment. */
.showcase .btn--light,
.statband .btn--light {
	background: #fff;
	color: var(--violet-600);
}

.showcase .btn--light:hover,
.statband .btn--light:hover {
	background: var(--ink-200);
	color: #fff;
}

/* The brief panel's submit sits on white inside the form card, so it stays the
   loudest thing there: solid accent, white label. The button carries
   .btn--primary already — this keeps the pairing explicit and survives the
   button class being swapped again. */
.brief__field .newsletter-form__btn {
	background: var(--violet-500);
	color: #fff;
}

.brief__field .newsletter-form__btn:hover {
	background: var(--violet-600);
	color: #fff;
}

.btn--sm {
	padding: 0.55rem 1.05rem;
	font-size: var(--fs-micro);
}

.btn--lg {
	padding: 0.95rem 1.9rem;
	font-size: var(--fs-sm);
}

.btn[disabled] {
	opacity: 0.55;
	cursor: not-allowed;
	transform: none;
}

/* The circular chevron affordance that trails "Read now" / "View all". */
.arrow-badge {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 20px;
	height: 20px;
	border-radius: 50%;
	background: currentColor;
	flex-shrink: 0;
	transition: transform var(--dur) var(--ease);
}

.arrow-badge svg {
	width: 11px;
	height: 11px;
	/* The glyph is knocked out of the filled circle by painting it the colour
	   of the surface behind the badge — now white rather than navy. */
	color: var(--navy-800);
}

.btn--ghost .arrow-badge svg,
a:hover > .arrow-badge svg {
	color: var(--navy-800);
}

/* On a violet or otherwise dark fill the badge itself is white (it uses
   currentColor), so the knocked-out glyph must go dark instead of white-on-
   white. Covers the showcase card, stat band and every filled CTA. */
.showcase__cue .arrow-badge svg,
.statband .arrow-badge svg,
.btn--primary .arrow-badge svg,
.deskcard .arrow-badge svg {
	color: var(--violet-600);
}

a:hover > .arrow-badge,
.btn:hover .arrow-badge {
	transform: translateX(2px);
}

.arrow-badge--violet {
	background: var(--violet-500);
}

.arrow-badge--violet svg {
	color: #fff;
}

.arrow-badge--lg {
	width: 30px;
	height: 30px;
}

.arrow-badge--lg svg {
	width: 15px;
	height: 15px;
}

/* Category chip. Colour arrives on inline custom properties from
   st_term_color(), because the palette is assigned per install. */
.chip {
	display: inline-flex;
	align-items: center;
	padding: 0.3rem 0.65rem;
	border-radius: var(--radius);
	background: var(--chip-bg, var(--violet-500));
	color: var(--chip-fg, #fff);
	font-size: var(--fs-micro);
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: 0.11em;
	line-height: 1.2;
	transition: opacity var(--dur) var(--ease);
}

.chip:hover {
	opacity: 0.85;
}

.card__chips {
	display: flex;
	flex-wrap: wrap;
	gap: 0.4rem;
}

/* Eyebrow with a pulsing dot — used on archive and 404 heroes. */
.eyebrow {
	display: inline-flex;
	align-items: center;
	gap: 0.5rem;
	font-size: var(--fs-micro);
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: 0.18em;
	color: var(--violet-300);
}

.badge-dot {
	width: 6px;
	height: 6px;
	border-radius: 50%;
	background: var(--violet-500);
	box-shadow: 0 0 0 0 rgba(58, 50, 224, 0.6);
	animation: st-pulse 2.4s infinite;
}

/* The ring fades to fully transparent, so the colour it fades FROM only has to
   match whatever set the dot's own shadow — the footer status dot overrides
   both. Left as a transparent-violet ramp for that reason. */
@keyframes st-pulse {
	70% {
		box-shadow: 0 0 0 8px rgba(58, 50, 224, 0);
	}
	100% {
		box-shadow: 0 0 0 0 rgba(58, 50, 224, 0);
	}
}

/* ── 5. Header / navigation ──────────────────────────────────────────────── */
.site-header {
	position: sticky;
	top: 0;
	z-index: 100;
	background: var(--navy-800);
	border-bottom: 1px solid var(--line-soft);
	transition: box-shadow var(--dur) var(--ease), background var(--dur) var(--ease);
}

.site-header--scrolled {
	/* Translucent white rather than translucent navy, and a far lighter
	   shadow: on paper the 0.42 black shadow of the dark build read as a
	   smudge. The hairline border does most of the separating work now. */
	background: rgba(255, 255, 255, 0.88);
	backdrop-filter: blur(14px);
	border-bottom-color: var(--line-firm);
	box-shadow: 0 6px 24px rgba(10, 7, 34, 0.09);
}

.masthead {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: var(--gap);
	min-height: 74px;
}

/* Brand. The customizer logo is inherited untouched — only its height is
   ours, driven by --logo-h from st_customizer_css(). */
.masthead__brand .custom-logo-link,
.masthead__brand .custom-logo {
	display: block;
}

.masthead__brand img {
	max-height: var(--logo-h);
	width: auto;
	object-fit: contain;
}

.site-logo {
	font-family: var(--font-display);
	font-weight: 800;
	font-size: 1.35rem;
	text-transform: uppercase;
	letter-spacing: -0.02em;
	color: var(--ink-100);
}

/* Desktop nav sits inline in the masthead, as in the reference: wordmark
   left, the desk list immediately beside it, utilities right. */
.nav-primary {
	flex: 1;
	min-width: 0;
}

.nav-list {
	display: flex;
	align-items: center;
	gap: clamp(0.9rem, 1.8vw, 1.9rem);
	flex-wrap: wrap;
}

.nav-list a {
	display: inline-block;
	font-size: var(--fs-micro);
	font-weight: 600;
	text-transform: uppercase;
	letter-spacing: 0.13em;
	color: var(--ink-300);
	padding-block: 0.35rem;
	position: relative;
	transition: color var(--dur) var(--ease);
}

.nav-list a::after {
	content: "";
	position: absolute;
	left: 0;
	bottom: 0;
	width: 100%;
	height: 2px;
	background: var(--violet-400);
	transform: scaleX(0);
	transform-origin: left;
	transition: transform var(--dur) var(--ease);
}

.nav-list a:hover,
.nav-list .current-menu-item > a,
.nav-list .current-cat > a {
	color: var(--ink-100);
}

.nav-list a:hover::after,
.nav-list .current-menu-item > a::after,
.nav-list .current-cat > a::after {
	transform: scaleX(1);
}

.masthead__util {
	display: flex;
	align-items: center;
	gap: 0.6rem;
	flex-shrink: 0;
}

/* Mobile menu toggle — hidden until the desk row can no longer fit. */
.menu-pill {
	display: none;
	align-items: center;
	gap: 0.5rem;
	padding: 0.5rem 0.95rem;
	border: 1px solid var(--line-firm);
	border-radius: var(--radius-pill);
	font-size: var(--fs-micro);
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: 0.12em;
	color: var(--ink-200);
}

.menu-pill__bars {
	display: flex;
	flex-direction: column;
	gap: 3px;
	width: 14px;
}

.menu-pill__bars span {
	display: block;
	height: 1.5px;
	background: currentColor;
	/* Quick, so the bars-to-X morph keeps pace with the drawer, which opens
	   instantly. At the full --dur the icon visibly trailed the panel. */
	transition: transform 0.12s var(--ease), opacity 0.12s var(--ease);
}

.menu-pill[aria-expanded="true"] .menu-pill__bars span:nth-child(1) {
	transform: translateY(4.5px) rotate(45deg);
}

.menu-pill[aria-expanded="true"] .menu-pill__bars span:nth-child(2) {
	opacity: 0;
}

.menu-pill[aria-expanded="true"] .menu-pill__bars span:nth-child(3) {
	transform: translateY(-4.5px) rotate(-45deg);
}

/* Drawer-only subscribe link. Hidden by default; the 1080px block below
   turns it on, where the masthead pill is hidden. */
.nav-subscribe {
	display: none;
}

@media (max-width: 1080px) {
	.menu-pill {
		display: inline-flex;
	}

	/* Hidden below the desktop breakpoint, so the masthead carries only the
	   wordmark and the MENU toggle. The newsletter is still reachable — the
	   drawer sits over the page and the footer band is a scroll away — and the
	   pill was competing with the toggle for the same corner. */
	.masthead__util .btn {
		display: none;
	}

	/* Below this width the desk row becomes a drawer. */
	.nav-primary {
		position: absolute;
		left: 0;
		right: 0;
		top: 100%;
		background: var(--navy-850);
		border-bottom: 1px solid var(--line-soft);
		flex: none;
	}

	/* Opens instantly. This was previously a grid-template-rows 0fr→1fr
	   transition, which made the whole list unfurl over ~0.3s and read as lag
	   on a tap. Navigation should respond immediately, so the drawer is simply
	   shown or hidden with no animation. */
	.nav-menu {
		display: none;
	}

	.nav-menu.is-open {
		display: block;
	}

	.nav-list {
		flex-direction: column;
		align-items: stretch;
		gap: 0;
		padding-inline: clamp(1rem, 3.5vw, 2.5rem);
	}

	.nav-list li {
		border-bottom: 1px solid var(--line-soft);
	}

	.nav-list li:last-child {
		border-bottom: 0;
	}

	.nav-list a {
		padding-block: 0.9rem;
		font-size: var(--fs-xs);
	}

	.nav-list a::after {
		display: none;
	}

	.nav-subscribe {
		display: flex;
		align-items: center;
		justify-content: space-between;
		gap: 0.5rem;
		margin: 0 clamp(1rem, 3.5vw, 2.5rem) 1rem;
		padding: 0.8rem 1.1rem;
		background: var(--violet-500);
		border-radius: var(--radius-pill);
		color: #fff;
		font-size: var(--fs-micro);
		font-weight: 700;
		text-transform: uppercase;
		letter-spacing: 0.12em;
	}

	.nav-subscribe .arrow-badge {
		background: #fff;
	}

	.nav-subscribe .arrow-badge svg {
		color: var(--violet-500);
	}
}

@media (max-width: 640px) {
	.masthead {
		min-height: 62px;
	}
}

/* Reading progress bar on single posts */
.read-progress {
	position: fixed;
	top: 0;
	left: 0;
	right: 0;
	height: 3px;
	z-index: 200;
	background: transparent;
	pointer-events: none;
}

.read-progress__fill {
	height: 100%;
	width: 0;
	background: var(--violet-400);
}

/* ── 6. Cards ────────────────────────────────────────────────────────────── */

/* The shared vertical card: media over a body of kicker, headline, byline.
   Every grid on the site composes from this. */
.card {
	display: flex;
	flex-direction: column;
	gap: 0.85rem;
	min-width: 0;
}

.card__media {
	display: block;
	overflow: hidden;
	border-radius: var(--radius);
	background: var(--navy-750);
}

.card__media-clip {
	display: block;
	aspect-ratio: 4 / 3;
	overflow: hidden;
}

.card__img,
.hcard__img,
.spot__img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	transition: transform 0.6s var(--ease);
}

.card:hover .card__img,
.hcard:hover .hcard__img,
.spot:hover .spot__img {
	transform: scale(1.045);
}

/* No-thumbnail fallback: a tinted well with a diagonal hatch, so a missing
   image reads as deliberate rather than as a hole. */
.card__media--empty {
	background:
		repeating-linear-gradient(
			135deg,
			/* Ink-alpha hatch: the dark build's 3.5% white was invisible here. */
			rgba(10, 7, 34, 0.055) 0 10px,
			transparent 10px 20px
		),
		var(--navy-750);
}

.card__body {
	display: flex;
	flex-direction: column;
	gap: 0.55rem;
	min-width: 0;
}

.card__title {
	font-size: var(--fs-h3);
	font-weight: 700;
	line-height: 1.22;
	letter-spacing: -0.01em;
	color: var(--ink-100);
}

.card__title a {
	background-image: linear-gradient(var(--violet-300), var(--violet-300));
	background-size: 0% 1px;
	background-position: 0 100%;
	background-repeat: no-repeat;
	transition: background-size var(--dur) var(--ease), color var(--dur) var(--ease);
}

.card__title a:hover {
	color: var(--violet-300);
	background-size: 100% 1px;
}

.card__excerpt {
	font-size: var(--fs-sm);
	color: var(--ink-400);
	display: -webkit-box;
	-webkit-line-clamp: 3;
	line-clamp: 3;
	-webkit-box-orient: vertical;
	overflow: hidden;
}

.card__foot {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 0.75rem;
	flex-wrap: wrap;
	margin-top: auto;
	padding-top: 0.15rem;
}

/* Compact card: the reference's "ON THE PULSE" row — a short landscape
   image, a kicker, a two-line headline, a byline. Nothing else. */
.card--compact .card__media-clip {
	aspect-ratio: 16 / 10;
}

.card--compact .card__title {
	font-size: 1.05rem;
	line-height: 1.28;
}

/* Horizontal card: thumbnail left, copy right. The reference's right-hand
   headline column and the Latest rail both use it. */
.hcard {
	display: grid;
	grid-template-columns: 1fr 96px;
	gap: 0.9rem;
	align-items: start;
	padding-bottom: 1.05rem;
	border-bottom: 1px solid var(--line-soft);
	min-width: 0;
}

.hcard:last-child {
	border-bottom: 0;
	padding-bottom: 0;
}

.hcard__media {
	display: block;
	overflow: hidden;
	border-radius: var(--radius);
	aspect-ratio: 1 / 1;
	background: var(--navy-750);
	order: 2;
}

.hcard__body {
	display: flex;
	flex-direction: column;
	gap: 0.4rem;
	min-width: 0;
}

.hcard__title {
	font-size: 1rem;
	font-weight: 600;
	line-height: 1.3;
	color: var(--ink-100);
}

.hcard__title a:hover {
	color: var(--violet-300);
}

/* Grids */
.grid-2,
.grid-3,
.grid-4 {
	display: grid;
	gap: var(--gap);
}

.grid-2 {
	grid-template-columns: repeat(2, minmax(0, 1fr));
}

.grid-3 {
	grid-template-columns: repeat(3, minmax(0, 1fr));
}

.grid-4 {
	grid-template-columns: repeat(4, minmax(0, 1fr));
}

@media (max-width: 1080px) {
	.grid-4 {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}
}

@media (max-width: 860px) {
	.grid-3 {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}
}

@media (max-width: 560px) {
	.grid-2,
	.grid-3,
	.grid-4 {
		grid-template-columns: minmax(0, 1fr);
	}
}

/* ── 7. Front page sections ──────────────────────────────────────────────── */

/* 7.1 Hero — a cinematic stage with an overlapping "next up" rail.

   Replaces the newspaper split (big lead beside a stacked headline column).
   The composition is now vertical and layered: one full-bleed photograph with
   the headline set OVER it, and the follow-up stories in a single row of cards
   that overlap the image's bottom edge so the two tiers read as one object.

   The stage is the only full-bleed element on the page and the only place the
   light theme goes dark, which is what gives the top of the site its weight. */
.hero {
	position: relative;
	/* Bottom padding is carried by the rail's negative offset below, not here —
	   see .hero-rail. */
	padding-bottom: clamp(1.5rem, 3vw, 2.5rem);
}

/* ── The stage */
.stage {
	position: relative;
	display: flex;
	align-items: flex-end;
	isolation: isolate;
	/* Full-bleed comes free: .hero is already a full-width section (the
	   container lives INSIDE the stage, around the copy only). No 100vw trick —
	   100vw counts the scrollbar gutter, which shifted the stage ~7px left of
	   the viewport and bled it under the scrollbar. */
	width: 100%;
	/* A tall, wide frame. min() keeps it from eating a short laptop screen, and
	   the vh term stops a very wide monitor from making it letterbox-thin. */
	min-height: min(78vh, 720px);
	/* The bottom value must clear the rail's negative offset PLUS a gap, or the
	   cards land flush against the byline row. Rail pulls up by at most 5rem,
	   so this is that plus ~2.5rem of air. */
	padding-block: clamp(2.5rem, 6vw, 5rem) clamp(5.5rem, 9vw, 7.5rem);
	background: var(--ink-100);
	overflow: hidden;
}

.stage__media {
	position: absolute;
	inset: 0;
	z-index: -1;
}

.stage__img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	/* A slow drift on load, so the stage has life without asking the reader to
	   wait for anything. Held off for reduced-motion users in section 14. */
	animation: st-stage-drift 18s var(--ease) forwards;
}

.stage__img--empty {
	display: block;
	background:
		repeating-linear-gradient(
			135deg,
			rgba(255, 255, 255, 0.05) 0 14px,
			transparent 14px 28px
		),
		var(--ink-200);
	animation: none;
}

@keyframes st-stage-drift {
	from {
		transform: scale(1.06);
	}
	to {
		transform: scale(1);
	}
}

/* Three-layer scrim. A single flat overlay either greys the photograph or
   leaves the type unreadable; these separate the jobs:
     1  a strong foot, where the copy sits
     2  a lateral wash from the left, so the headline's measure is covered
        without dimming the right of the frame
     3  a soft vignette, which keeps the eye in the middle of the image */
.stage__scrim {
	position: absolute;
	inset: 0;
	background:
		linear-gradient(to top, rgba(10, 7, 34, 0.94) 0%, rgba(10, 7, 34, 0.62) 34%, rgba(10, 7, 34, 0.12) 68%),
		linear-gradient(to right, rgba(10, 7, 34, 0.78), rgba(10, 7, 34, 0.1) 62%, transparent),
		radial-gradient(120% 100% at 50% 40%, transparent 42%, rgba(10, 7, 34, 0.45));
}

.stage__inner {
	position: relative;
	width: 100%;
}

.stage__copy {
	max-width: 46rem;
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: 0.9rem;
}

/* Eyebrow: a live dot, the slot label, then the desk. Small, tracked, and the
   first thing that tells you what you are looking at. */
.stage__eyebrow {
	display: inline-flex;
	align-items: center;
	gap: 0.6rem;
	font-size: var(--fs-micro);
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: 0.18em;
	color: #fff;
}

.stage__live {
	width: 7px;
	height: 7px;
	border-radius: 50%;
	background: var(--violet-400);
	box-shadow: 0 0 0 0 rgba(95, 92, 255, 0.75);
	animation: st-pulse 2.4s infinite;
}

.stage__sep {
	width: 14px;
	height: 1px;
	background: rgba(255, 255, 255, 0.45);
}

.stage__desk {
	color: #A5A1FF;
}

.stage__title {
	font-family: var(--font-display);
	font-weight: 800;
	text-transform: uppercase;
	letter-spacing: -0.025em;
	line-height: 0.92;
	font-size: clamp(2.1rem, 5.6vw, 4.4rem);
	color: #fff;
	text-wrap: balance;
	/* Lifts the headline off a busy photograph without a plate behind it. */
	text-shadow: 0 2px 30px rgba(6, 2, 28, 0.6);
}

/* An animated underline that draws in on hover. Keyed to the LINK, not the
   stage: the headline is the hit area, so the affordance has to appear when the
   pointer is actually over something clickable. Underlining on stage-hover
   implied the whole panel was a link, which it deliberately is not. */
.stage__title a {
	background-image: linear-gradient(#fff, #fff);
	background-size: 0% 2px;
	background-position: 0 100%;
	background-repeat: no-repeat;
	transition: background-size 0.45s var(--ease);
}

.stage__title a:hover,
.stage__title a:focus-visible {
	background-size: 100% 2px;
}

.stage__excerpt {
	font-size: var(--fs-lead);
	color: rgba(255, 255, 255, 0.82);
	max-width: 54ch;
	text-shadow: 0 1px 14px rgba(6, 2, 28, 0.55);
}

.stage__foot {
	display: flex;
	align-items: center;
	gap: 1.25rem;
	flex-wrap: wrap;
	margin-top: 0.35rem;
}

/* The byline helper's $on_dark flag does not change its markup, so the dark
   treatment is applied here by descent instead. */
.stage .byline,
.stage .byline__name,
.stage .metarow,
.stage .byline time,
.stage .byline__sep {
	color: rgba(255, 255, 255, 0.82);
}

.stage .byline__avatar {
	box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.28);
}

/* ── The rail */

/* Pulled up onto the stage so the cards break its bottom edge. The stage's own
   bottom padding leaves room for this, so the overlap never covers the copy. */
.hero-rail {
	position: relative;
	z-index: 2;
	display: grid;
	grid-template-columns: repeat(4, minmax(0, 1fr));
	gap: clamp(0.5rem, 1vw, 0.85rem);
	list-style: none;
	margin: clamp(-5rem, -6vw, -3rem) 0 0;
	padding: 0;
}

.railcard {
	min-width: 0;
}

/* Two rows: copy on top, then a foot holding the timestamp and the thumbnail
   side by side.

   The thumbnail was absolutely positioned in the bottom-right corner, which
   forced the body to reserve 3.5rem of right padding for the WHOLE card height
   to stop the clamped headline running under it. That cut the headline measure
   from ~300px to 266px and pushed titles to 3–4 wrapped lines, truncating more
   words. In flow it only takes space on the row it actually occupies. */
.railcard__link {
	position: relative;
	display: flex;
	flex-direction: column;
	gap: 0.5rem;
	height: 100%;
	padding: 1rem 1rem 0.9rem;
	background: #fff;
	border: 1px solid var(--line-soft);
	border-radius: var(--radius);
	overflow: hidden;
	box-shadow: 0 18px 40px rgba(10, 7, 34, 0.16);
	transition: transform var(--dur) var(--ease), box-shadow var(--dur) var(--ease),
		border-color var(--dur) var(--ease);
}

.railcard__link:hover {
	transform: translateY(-4px);
	border-color: var(--cat-bg, var(--violet-500));
	box-shadow: 0 24px 52px rgba(10, 7, 34, 0.22);
}

/* A tick in the desk colour along the card's top edge, drawn in on hover. It
   is what ties each card to its section without a coloured chip. */
.railcard__tick {
	position: absolute;
	top: 0;
	left: 0;
	right: 0;
	height: 3px;
	background: var(--cat-bg, var(--violet-500));
	transform: scaleX(0);
	transform-origin: left;
	transition: transform 0.4s var(--ease);
}

.railcard__link:hover .railcard__tick {
	transform: scaleX(1);
}

/* Outline numeral, top-right, quiet. Reads as a position marker rather than
   as content to be read. */
.railcard__index {
	position: absolute;
	top: 0.75rem;
	right: 0.9rem;
	font-family: var(--font-display);
	font-weight: 800;
	font-size: 1.15rem;
	line-height: 1;
	color: transparent;
	-webkit-text-stroke: 1px var(--line-firm);
	font-variant-numeric: tabular-nums;
	transition: color var(--dur) var(--ease),
		-webkit-text-stroke-color var(--dur) var(--ease);
}

.railcard__link:hover .railcard__index {
	color: var(--cat-bg, var(--violet-500));
	-webkit-text-stroke-color: transparent;
}

.railcard__body {
	display: flex;
	flex-direction: column;
	gap: 0.3rem;
	min-width: 0;
	/* Only the index in the top-right corner needs clearing now — the thumbnail
	   lives in the foot row and no longer overlaps the headline. */
	padding-right: 1.75rem;
}

/* The foot row: timestamp left, thumbnail right, pushed to the card's bottom so
   every card in the row aligns on the same baseline whatever its headline. */
.railcard__foot {
	display: flex;
	align-items: flex-end;
	justify-content: space-between;
	gap: 0.75rem;
	margin-top: auto;
	padding-top: 0.5rem;
}

.railcard__desk {
	font-size: var(--fs-micro);
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: 0.14em;
	color: var(--cat-bg, var(--violet-500));
}

.railcard__title {
	font-size: 0.95rem;
	font-weight: 600;
	line-height: 1.3;
	color: var(--ink-100);
	/* Two lines: an unusually long headline must not stretch one card and knock
	   the row out of alignment. */
	display: -webkit-box;
	-webkit-line-clamp: 2;
	line-clamp: 2;
	-webkit-box-orient: vertical;
	overflow: hidden;
}

.railcard__time {
	font-size: var(--fs-micro);
	font-weight: 500;
	text-transform: uppercase;
	letter-spacing: 0.1em;
	color: var(--ink-500);
	white-space: nowrap;
}

/* The story's art as a real thumbnail, pinned bottom-right.

   This was a 4px-tall full-width strip — the idea was "a hint of the photo
   without a row of thumbnails", but 4px of a photograph carries no image
   information at all: it rendered as a smear that read like a broken progress
   bar. A small square actually identifies the story, which is the only reason
   to show art here. */
.railcard__thumb {
	flex-shrink: 0;
	width: 44px;
	height: 44px;
	border-radius: var(--radius);
	overflow: hidden;
	background: var(--navy-750);
}

.railcard__thumb img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	transition: transform 0.6s var(--ease);
}

.railcard__link:hover .railcard__thumb img {
	transform: scale(1.08);
}

/* ── Responsive */

/* Below the desktop width four cards cannot hold a two-line headline, so the
   rail goes to two columns and stops overlapping as far. */
@media (max-width: 1080px) {
	.hero-rail {
		grid-template-columns: repeat(2, minmax(0, 1fr));
		gap: 0.75rem;
		margin-top: clamp(-3.5rem, -4vw, -2rem);
	}

	/* Two rows of cards overlap further up than one, so the stage needs more
	   bottom clearance here than at full width, not less. */
	.stage {
		padding-block: clamp(2.5rem, 6vw, 5rem) clamp(4.5rem, 8vw, 6rem);
	}
}

@media (max-width: 860px) {
	.stage {
		min-height: min(72vh, 600px);
	}

	.stage__copy {
		max-width: none;
	}
}

@media (max-width: 620px) {
	/* The stage keeps a real minimum height rather than a vh share: on a short
	   phone in landscape a vh-only frame collapses to a letterbox. */
	.stage {
		min-height: 460px;
		/* Bottom clears the rail's smaller 1.5rem lift plus air, matching the
		   desktop rule's logic at this scale. */
		padding-block: 2rem clamp(2.75rem, 9vw, 3.5rem);
		align-items: flex-end;
	}

	/* The lateral wash is dropped — at this width the copy spans the full frame,
	   so a left-weighted gradient just darkens one edge unevenly. */
	.stage__scrim {
		background:
			linear-gradient(to top, rgba(10, 7, 34, 0.95) 0%, rgba(10, 7, 34, 0.7) 42%, rgba(10, 7, 34, 0.2) 78%),
			radial-gradient(120% 100% at 50% 40%, transparent 40%, rgba(10, 7, 34, 0.4));
	}

	.stage__excerpt {
		/* Two lines on a phone: the headline and the byline are what matter at
		   this size, and a four-line summary pushes both off the first screen. */
		display: -webkit-box;
		-webkit-line-clamp: 2;
		line-clamp: 2;
		-webkit-box-orient: vertical;
		overflow: hidden;
	}

	.stage__foot {
		gap: 0.85rem;
	}

	/* The byline (~146px) and the full meta row (~211px) overrun a 343px
	   column by a hair and wrap to two lines, costing 40px of stage height for
	   nothing. Dropping the DATE — the second .metarow__item — keeps reading
	   time, which is the more useful of the two here, and fits one line.
	   The date is still on the article itself. */
	.stage .metarow__item:nth-child(2) {
		display: none;
	}

	/* One column, and the overlap shrinks to a small lift: a full-width card
	   pulled far up would cover the headline it sits under. */
	.hero-rail {
		grid-template-columns: minmax(0, 1fr);
		gap: 0.6rem;
		margin-top: -1.5rem;
	}

	/* Horizontal rows on a phone — a stack of four vertical cards is a lot of
	   scrolling before the rest of the page. */
	.railcard__link {
		flex-direction: row;
		align-items: center;
		gap: 0.85rem;
		padding: 0.85rem 0.9rem;
	}

	.railcard__index {
		position: static;
		flex-shrink: 0;
		font-size: 1rem;
		/* Filled rather than outlined at this size: a 1px stroke on a 16px
		   numeral reads as a smudge on a phone screen. */
		color: var(--cat-bg, var(--violet-500));
		-webkit-text-stroke: 0;
	}

	.railcard__body {
		padding-right: 0;
	}

	.railcard__title {
		-webkit-line-clamp: 2;
		line-clamp: 2;
	}

	/* An explicit 3-column grid rather than a flex row. Flex needed
	   `display:contents` + wrapping + order juggling to put the timestamp under
	   the headline while keeping the thumb on its right, and that combination
	   broke each part onto its own line. The grid just names the geometry:

	     index | copy      | thumb
	     index | timestamp | thumb   */
	.railcard__link {
		display: grid;
		grid-template-columns: auto minmax(0, 1fr) 46px;
		grid-template-rows: auto auto;
		align-items: start;
		column-gap: 0.8rem;
		row-gap: 0.2rem;
	}

	.railcard__index {
		grid-column: 1;
		grid-row: 1 / span 2;
		align-self: center;
	}

	.railcard__body {
		grid-column: 2;
		grid-row: 1;
		padding-right: 0;
	}

	/* Contents are placed directly, so the wrapper must not form a row of its
	   own — its two children take the grid cells instead. */
	.railcard__foot {
		display: contents;
	}

	.railcard__time {
		grid-column: 2;
		grid-row: 2;
	}

	.railcard__thumb {
		grid-column: 3;
		grid-row: 1 / span 2;
		align-self: center;
		width: 46px;
		height: 46px;
	}
}

/* 7.2 Ticker strip — a marquee of desk names under the hero. Editorial
   furniture that advertises breadth at a glance. */
.tickerbar {
	border-block: 1px solid var(--line-soft);
	background: var(--navy-850);
	overflow: hidden;
	padding-block: 0.7rem;
	display: flex;
	align-items: center;
	gap: 1rem;
}

.tickerbar__label {
	flex-shrink: 0;
	margin-left: clamp(1rem, 3.5vw, 2.5rem);
	padding: 0.28rem 0.7rem;
	border-radius: var(--radius);
	background: var(--violet-500);
	color: #fff;
	font-size: var(--fs-micro);
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: 0.14em;
}

.tickerbar__viewport {
	flex: 1;
	overflow: hidden;
	mask-image: linear-gradient(90deg, transparent, #000 3%, #000 92%, transparent);
}

.tickerbar__track {
	display: flex;
	align-items: center;
	gap: 2.5rem;
	width: max-content;
	animation: st-marquee 46s linear infinite;
}

.tickerbar:hover .tickerbar__track,
.tickerbar:focus-within .tickerbar__track {
	animation-play-state: paused;
}

.tickerbar__item {
	display: inline-flex;
	align-items: center;
	gap: 0.6rem;
	font-size: var(--fs-micro);
	font-weight: 600;
	text-transform: uppercase;
	letter-spacing: 0.14em;
	color: var(--ink-400);
	white-space: nowrap;
	transition: color var(--dur) var(--ease);
}

.tickerbar__item:hover {
	color: var(--ink-100);
}

.tickerbar__dot {
	width: 5px;
	height: 5px;
	border-radius: 50%;
	background: var(--cat-bg, var(--violet-400));
	flex-shrink: 0;
}

/* Translating by -25% moves the track by exactly one copy of the list, which
   the template prints four times — so the wrap lands on a point visually
   identical to the start and the loop is seamless.
   The fraction and the copy count in front-page.php must stay in step: at two
   copies and -50% the travel was narrower than the viewport on a 1440 screen
   and a gap opened at the right edge before the wrap. */
@keyframes st-marquee {
	to {
		transform: translateX(-25%);
	}
}

/* 7.25 On the Pulse — a briefing block: one lead story with large art, and a
   numbered rail of follow-ups beside it.

   Replaces the old three-equal-cards grid under a centred heading. Two things
   make it read differently: the heading is left-aligned against a rule with a
   pulsing tick (so the section opens like a wire feed rather than a titled
   card row), and the content is deliberately ASYMMETRIC — a 1.35fr lead beside
   a 1fr rail, where the rail items are numbered rows rather than cards. */
.pulse-head {
	display: flex;
	align-items: baseline;
	justify-content: space-between;
	gap: var(--gap);
	flex-wrap: wrap;
	padding-bottom: 1rem;
	margin-bottom: var(--gap-lg);
	border-bottom: 2px solid var(--ink-100);
}

.pulse-head__id {
	display: inline-flex;
	align-items: center;
	gap: 0.7rem;
	min-width: 0;
}

/* The live tick. Reuses the badge-dot pulse keyframes so the section reads as
   a running feed without a second animation. */
.pulse-head__tick {
	width: 9px;
	height: 9px;
	flex-shrink: 0;
	border-radius: 50%;
	background: var(--violet-500);
	box-shadow: 0 0 0 0 rgba(58, 50, 224, 0.6);
	animation: st-pulse 2.4s infinite;
}

.pulse-head__title {
	font-family: var(--font-display);
	font-weight: 800;
	text-transform: uppercase;
	letter-spacing: -0.02em;
	line-height: 0.95;
	font-size: var(--fs-h2);
	color: var(--ink-100);
}

.pulse-head__kicker {
	font-size: var(--fs-sm);
	color: var(--ink-400);
	max-width: 42ch;
}

.pulse {
	display: grid;
	grid-template-columns: minmax(0, 1.35fr) minmax(0, 1fr);
	gap: clamp(1.5rem, 3.2vw, 2.75rem);
	/* stretch, not start: the rail is a flex column that distributes its rows
	   over the full track height, so it finishes level with the lead instead of
	   stopping short and leaving a hole in the right-hand column. */
	align-items: stretch;
}

/* ── Lead story */
.pulse-lead {
	display: flex;
	flex-direction: column;
	gap: 1rem;
	min-width: 0;
}

.pulse-lead__media {
	position: relative;
	display: block;
	overflow: hidden;
	border-radius: var(--radius);
	background: var(--navy-750);
}

.pulse-lead__clip {
	display: block;
	aspect-ratio: 16 / 10;
	overflow: hidden;
}

.pulse-lead__img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	transition: transform 0.7s var(--ease);
}

.pulse-lead:hover .pulse-lead__img {
	transform: scale(1.035);
}

/* Corner flag rather than an inline kicker, so the lead's desk reads at a
   glance and the copy below opens straight on the headline. */
.pulse-lead__flag {
	position: absolute;
	top: 0;
	left: 0;
	padding: 0.4rem 0.85rem;
	background: var(--violet-500);
	color: #fff;
	font-size: var(--fs-micro);
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: 0.16em;
	border-bottom-right-radius: var(--radius);
}

.pulse-lead__body {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: 0.6rem;
	min-width: 0;
}

.pulse-lead__title {
	font-family: var(--font-display);
	font-weight: 800;
	text-transform: uppercase;
	letter-spacing: -0.015em;
	line-height: 1.02;
	font-size: clamp(1.4rem, 2.5vw, 2.1rem);
	color: var(--ink-100);
	text-wrap: balance;
}

.pulse-lead__title a:hover {
	color: var(--violet-500);
}

.pulse-lead__excerpt {
	font-size: var(--fs-sm);
	color: var(--ink-400);
	max-width: 54ch;
}

/* ── Numbered rail */
.pulse-rail {
	display: flex;
	flex-direction: column;
	/* Rows share out any height left over once their content is laid out, so
	   the rail always reaches the foot of the lead column. With a fixed
	   padding the rail's height depended entirely on how long the headlines
	   happened to be, which is what left the gap. */
	justify-content: space-between;
	list-style: none;
	margin: 0;
	padding: 0;
	min-width: 0;
}

.pulse-item {
	display: grid;
	grid-template-columns: 2.25rem minmax(0, 1fr) 68px;
	gap: 0.9rem;
	align-items: start;
	/* Vertical padding is a floor; justify-content above adds the slack. */
	padding-block: 0.95rem;
	border-bottom: 1px solid var(--line-soft);
}

.pulse-item:first-child {
	padding-top: 0;
}

.pulse-item:last-child {
	border-bottom: 0;
	padding-bottom: 0;
}

/* Outline numerals: the rank labels the row without competing with the
   headline. Fills in on hover, which is the row's only affordance. */
.pulse-item__num {
	font-family: var(--font-display);
	font-weight: 800;
	font-size: 1.3rem;
	line-height: 1.1;
	color: transparent;
	-webkit-text-stroke: 1px var(--ink-400);
	font-variant-numeric: tabular-nums;
	transition: color var(--dur) var(--ease),
		-webkit-text-stroke-color var(--dur) var(--ease);
}

.pulse-item:hover .pulse-item__num {
	color: var(--violet-500);
	-webkit-text-stroke-color: transparent;
}

.pulse-item__body {
	display: flex;
	flex-direction: column;
	gap: 0.3rem;
	min-width: 0;
}

.pulse-item__desk {
	font-size: var(--fs-micro);
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: 0.14em;
	color: var(--violet-500);
}

.pulse-item__title {
	font-size: 1rem;
	font-weight: 600;
	line-height: 1.3;
	color: var(--ink-100);
}

.pulse-item__title a:hover {
	color: var(--violet-500);
}

.pulse-item__time {
	font-size: var(--fs-micro);
	font-weight: 500;
	text-transform: uppercase;
	letter-spacing: 0.1em;
	color: var(--ink-500);
}

.pulse-item__media {
	display: block;
	overflow: hidden;
	border-radius: var(--radius);
	aspect-ratio: 1 / 1;
	background: var(--navy-750);
}

.pulse-item__media img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	transition: transform 0.6s var(--ease);
}

.pulse-item:hover .pulse-item__media img {
	transform: scale(1.07);
}

/* Tablet: the rail drops under the lead and becomes a two-up row, which keeps
   the section from turning into one very tall column. */
@media (max-width: 900px) {
	.pulse {
		grid-template-columns: minmax(0, 1fr);
		gap: var(--gap-lg);
	}

	.pulse-rail {
		display: grid;
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}

	/* As a grid the first-child padding reset no longer applies per column, so
	   every item in the top row needs it. */
	.pulse-item {
		padding-top: 0;
	}

	/* Two columns turns the item rule into a per-cell border, which reads badly
	   at the end of the list: with three items the rule under item 02 points
	   straight at the empty fourth cell.

	   So at this breakpoint the row rule is dropped entirely and the items are
	   separated by grid gap instead. Cheaper than trying to detect the last row
	   in CSS, and honest — a two-up grid does not need horizontal rules to be
	   readable the way a single vertical column does. */
	.pulse-item {
		border-bottom: 0;
		padding-bottom: 0;
	}

	.pulse-rail {
		gap: clamp(1.1rem, 2.4vw, 1.6rem) var(--gap);
	}
}

@media (max-width: 620px) {
	.pulse-rail {
		grid-template-columns: minmax(0, 1fr);
	}

	.pulse-item {
		/* The thumbnail shrinks and the number narrows; at this width three
		   full-size tracks left the headline in a ~120px gutter. */
		grid-template-columns: 1.75rem minmax(0, 1fr) 56px;
		gap: 0.7rem;
		padding-block: 0.95rem;
	}

	.pulse-item:first-child {
		padding-top: 0;
	}

	.pulse-item:last-child {
		border-bottom: 0;
		padding-bottom: 0;
	}

	.pulse-item__num {
		font-size: 1.05rem;
	}
}

/* 7.3 Showcase — a wide photographic plate with a violet copy card lifted
   over its lower-right corner.

   Replaces the old 50/50 split-with-a-diagonal-wedge panel. The overlap is the
   whole idea: the card breaks the plate's edge so the two elements read as
   layered objects rather than as two halves of one box, and the headline gets
   a solid ground instead of competing with the photograph behind it.

   Built as a grid with a deliberately overlapping second track rather than an
   absolutely-positioned card — the card's own height then drives the section's
   height, so a long headline can never spill outside the plate. */
.showcase {
	position: relative;
	display: grid;
	/* Plate and card share ONE grid cell, stacked. That is what lets the card
	   be positioned against the plate's edges with auto margins and keeps the
	   section's height equal to the plate's — no overhang, so no empty band
	   below the image. Both children name the same row/column. */
	grid-template-columns: minmax(0, 1fr);
	grid-template-rows: auto;
}

.showcase__plate,
.showcase__card {
	grid-area: 1 / 1;
}

.showcase__plate {
	position: relative;
	overflow: hidden;
	border-radius: var(--radius-lg);
	background: var(--navy-750);
	/* 16/9 rather than a wider 21/9: the copy card overlaps the plate's lower
	   portion, and on a very letterboxed plate the card hung far below the
	   image and left dead space beside it. A taller plate gives the overlap
	   something to sit against. */
	aspect-ratio: 16 / 9;
}

.showcase__img {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
	transition: transform 0.9s var(--ease);
}

.showcase:hover .showcase__img {
	transform: scale(1.04);
}

/* A scrim rising from the plate's bottom-right, under the copy card. The card
   is opaque violet so it does not need this for its own legibility — the scrim
   stops the card looking pasted onto an unrelated bright photo by darkening
   the corner it sits in, and it gives the FEATURED label something to read
   against on a pale image. */
.showcase__plate::after {
	content: "";
	position: absolute;
	inset: 0;
	pointer-events: none;
	background:
		linear-gradient(to top, rgba(10, 7, 34, 0.5), transparent 55%),
		linear-gradient(to left, rgba(10, 7, 34, 0.34), transparent 62%);
}

/* No artwork: the same hatched well the cards use, so a thumbnail-less
   feature still reads as deliberate. */
.showcase__img--empty {
	background:
		repeating-linear-gradient(
			135deg,
			rgba(10, 7, 34, 0.055) 0 12px,
			transparent 12px 24px
		),
		var(--navy-750);
}

/* Vertical rotated label running up the plate's left edge — the piece of
   editorial furniture that replaces the old wedge as the section's signature. */
.showcase__label {
	position: absolute;
	top: clamp(1rem, 2vw, 1.75rem);
	left: clamp(1rem, 2vw, 1.75rem);
	display: inline-block;
	padding: 0.4rem 0.8rem;
	background: var(--violet-500);
	color: #fff;
	border-radius: var(--radius);
	font-family: var(--font-body);
	font-size: var(--fs-micro);
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: 0.18em;
	line-height: 1;
}

/* The copy card. Sits in the grid's only column, then shifts to overlap the
   plate. `margin-top` is negative so it rises onto the image. */
.showcase__card {
	position: relative;
	z-index: 1;
	display: flex;
	flex-direction: column;
	gap: 0.7rem;
	padding: clamp(1.25rem, 2.6vw, 2.25rem);
	background: var(--violet-500);
	border-radius: var(--radius-lg);
	color: #fff;
	/* Sits fully INSIDE the plate, inset from its bottom-right corner. The card
	   used to hang ~180px below the image, which left an empty white strip
	   across the section's whole left half. Pulling it entirely within the
	   plate means the plate's own bottom edge is the section's bottom edge and
	   there is no leftover band to fill.

	   `margin-bottom` is the inset from the plate's foot; `margin-top: auto`
	   pushes the card down the grid area to get there, so the card's height
	   never has to be known in advance. */
	width: min(520px, 100%);
	margin-top: auto;
	margin-bottom: clamp(1rem, 2.4vw, 2rem);
	margin-left: auto;
	margin-right: clamp(1rem, 3vw, 3rem);
	box-shadow: 0 24px 60px rgba(10, 7, 34, 0.34);
}

.showcase__desk {
	font-size: var(--fs-micro);
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: 0.18em;
	color: rgba(255, 255, 255, 0.78);
}

.showcase__title {
	font-family: var(--font-display);
	font-weight: 800;
	text-transform: uppercase;
	letter-spacing: -0.015em;
	line-height: 1;
	font-size: clamp(1.5rem, 2.8vw, 2.35rem);
	/* Explicit, because the shared .display group is not applied here and the
	   card's own colour must win over any inherited ink. */
	color: #fff;
	text-wrap: balance;
}

.showcase__title a:hover {
	text-decoration: underline;
	text-underline-offset: 5px;
	text-decoration-thickness: 2px;
}

.showcase__excerpt {
	font-size: var(--fs-sm);
	color: rgba(255, 255, 255, 0.86);
}

.showcase__foot {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 1rem;
	flex-wrap: wrap;
	margin-top: 0.25rem;
	padding-top: 0.9rem;
	border-top: 1px solid rgba(255, 255, 255, 0.22);
}

.showcase__cue {
	display: inline-flex;
	align-items: center;
	gap: 0.5rem;
	flex-shrink: 0;
	font-size: var(--fs-micro);
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: 0.14em;
	color: #fff;
}

.showcase:hover .showcase__cue .arrow-badge {
	transform: translateX(3px);
}

.showcase .byline,
.showcase .byline__name,
.showcase .metarow,
.showcase .byline time,
.showcase .byline__sep {
	color: rgba(255, 255, 255, 0.82);
}

/* Tablet: the card widens and centres, still inset inside the plate. */
@media (max-width: 900px) {
	/* The card is nearly as wide as the plate here, so the plate needs a taller
	   photo for the card to sit inside without covering all of it. Expressed as
	   `height` with the ratio OFF — `aspect-ratio` + `min-height` makes the
	   browser satisfy the floor by widening the plate, which overflowed the
	   viewport at 768px. Same trap as the mobile block below. */
	.showcase__plate {
		aspect-ratio: auto;
		height: 62vw;
		min-height: 400px;
		max-height: 520px;
	}

	.showcase__card {
		width: min(620px, calc(100% - 2rem));
		margin-inline: auto;
		margin-bottom: 1rem;
	}
}

@media (max-width: 620px) {
	/* Stacked. The card is nearly full width here and its text wraps to a tall
	   block, so the desktop overlap is abandoned: the card only tucks under the
	   plate's bottom edge by a fixed amount. Keeping a proportional (vw-based)
	   lift instead made the card cover most of a short plate on small phones.

	   Here the two children leave the shared cell and become real rows: at this
	   width a card inset inside the plate would cover the entire photograph.
	   They still touch — the card overlaps the plate's bottom edge slightly —
	   so stacking does not reintroduce a gap.

	   The plate needs a height FLOOR: on a pure ratio it shrank with the
	   viewport while the card GREW (its text wraps to more lines), so on a
	   390px screen the photo became a 229px strip under a 298px card.

	   The floor is set with `height` + `min-height`, NOT `aspect-ratio` plus
	   `min-height`. With a ratio still in force the browser satisfied the floor
	   by resolving the ratio from the height and blowing the plate's WIDTH out
	   to 450px inside a 390px viewport — a real horizontal overflow. Dropping
	   the ratio here keeps width bound to the container and lets height be the
	   free dimension, which is what a floor needs. */
	.showcase {
		grid-template-rows: auto auto;
	}

	.showcase__plate {
		grid-area: 1 / 1;
		aspect-ratio: auto;
		height: 46vw;
		min-height: 260px;
	}

	.showcase__card {
		grid-area: 2 / 1;
		width: calc(100% - 1.5rem);
		margin-inline: auto;
		/* Lifts onto the plate's foot so the two read as joined. */
		margin-top: -1.5rem;
		margin-bottom: 0;
		/* Tighter type so the card stays proportionate to the plate above it
		   instead of dominating the section. */
		gap: 0.55rem;
		padding: 1.15rem 1.1rem;
	}

	.showcase__title {
		font-size: clamp(1.3rem, 6.4vw, 1.65rem);
	}

	.showcase__foot {
		/* The cue would otherwise wrap under a two-line byline and strand
		   itself against the left edge. */
		justify-content: flex-start;
		gap: 0.75rem;
	}
}

/* Very small phones: the excerpt is the first thing to go. Three lines of
   summary plus a headline plus a byline is more card than a 360px screen can
   hold without the photo above it becoming a sliver. */
@media (max-width: 400px) {
	.showcase__excerpt {
		display: -webkit-box;
		-webkit-line-clamp: 2;
		line-clamp: 2;
		-webkit-box-orient: vertical;
		overflow: hidden;
	}
}

/* 7.4 Spotlight — a wide photo with the headline set alongside it rather
   than over it, as in the reference. */
.spot {
	display: grid;
	grid-template-columns: minmax(0, 1.25fr) minmax(0, 1fr);
	gap: clamp(1.25rem, 2.6vw, 2.25rem);
	align-items: center;
}

.spot__media {
	display: block;
	position: relative;
	overflow: hidden;
	border-radius: var(--radius);
	aspect-ratio: 16 / 10;
	background: var(--navy-750);
}

/* A translucent violet corner wash, echoing the colour-blocked photo
   treatment throughout the reference. */
.spot__media::after {
	content: "";
	position: absolute;
	inset: 0;
	/* Lighter than the dark build's 0.55 — the photograph now sits on white
	   with nothing to recover its midtones, so a heavy violet cast just
	   dirtied it. Enough to colour-block the corner, not enough to tint. */
	background: linear-gradient(215deg, rgba(58, 50, 224, 0.34), transparent 46%);
	pointer-events: none;
}

.spot__body {
	display: flex;
	flex-direction: column;
	gap: 0.9rem;
	min-width: 0;
}

.spot__title {
	font-family: var(--font-display);
	font-weight: 800;
	text-transform: uppercase;
	letter-spacing: -0.015em;
	line-height: 0.98;
	font-size: clamp(1.6rem, 2.9vw, 2.6rem);
	color: var(--ink-100);
}

.spot__title a:hover {
	color: var(--violet-300);
}

.spot__excerpt {
	font-size: var(--fs-sm);
	color: var(--ink-400);
	max-width: 46ch;
}

/* Byline and meta on one row. Was .hero-lead__foot, borrowed from the old hero
   split; that hero is gone, so the spotlight owns this rule now. */
.spot__foot {
	display: flex;
	align-items: center;
	gap: 1rem;
	flex-wrap: wrap;
}

@media (max-width: 860px) {
	.spot {
		grid-template-columns: minmax(0, 1fr);
	}
}

/* 7.5 Desk board — a static directory, not a carousel.
   A 3x2 board where the first panel spans both rows and keeps a photograph,
   and the remaining five are flat plates in their own desk colour. Each panel
   carries the desk's newest headline, so the section is navigation into live
   coverage rather than a strip of labels. */
.deskboard {
	display: grid;
	grid-template-columns: repeat(3, minmax(0, 1fr));
	grid-auto-rows: minmax(178px, auto);
	gap: var(--gap);
}

.deskcard {
	position: relative;
	display: flex;
	flex-direction: column;
	justify-content: space-between;
	gap: 1.25rem;
	overflow: hidden;
	border-radius: var(--radius);
	padding: 1.15rem;
	isolation: isolate;
	background: var(--navy-800);
	border: 1px solid var(--line-soft);
	transition: transform var(--dur) var(--ease), border-color var(--dur) var(--ease);
}

/* The desk's own colour arrives as a full-bleed wash that rises on hover,
   so the board reads as a set of coloured plates without nine hard-coded
   background rules. */
.deskcard::before {
	content: "";
	position: absolute;
	inset: 0;
	z-index: -1;
	background: var(--cat-bg, var(--violet-500));
	/* Lower than the dark build's 0.16. A desk colour at 16% over white is
	   already a mid tint that fights the ink type sitting on it; 9% keeps the
	   plate identifiably coloured while leaving the headline crisp. */
	opacity: 0.09;
	transition: opacity var(--dur) var(--ease);
}

.deskcard:hover {
	transform: translateY(-3px);
	border-color: var(--cat-bg, var(--violet-500));
}

.deskcard:hover::before {
	opacity: 1;
}

/* Lead panel: spans two rows in the first column and reveals its cover art.
   Which card holds this class rotates on an interval (see main.js), so every
   desk takes a turn as the photographed panel.

   The grid position is NOT animated — moving a grid item between tracks
   cannot tween, and trying produces a jump. Only the artwork cross-fades; the
   panel geometry changes instantly underneath it, which reads as the photo
   moving rather than the box resizing. */
.deskcard--lead {
	grid-row: span 2;
	justify-content: flex-end;
	min-height: 380px;
	padding: 1.4rem;
	border-color: transparent;
}

/* Every card carries its image; only the lead shows it. Fading opacity rather
   than toggling display keeps the swap smooth and lets the browser decode the
   next photo before it is needed. */
.deskcard__img,
.deskcard__scrim {
	position: absolute;
	inset: 0;
	opacity: 0;
	pointer-events: none;
	transition: opacity 0.55s var(--ease);
}

.deskcard__img {
	z-index: -2;
	width: 100%;
	height: 100%;
	object-fit: cover;
}

/* Stays DARK deliberately: this scrim sits over a photograph and carries white
   type. It is the one place in the light theme that keeps a near-navy fill,
   and it is now slightly heavier than the dark build's — with a white page
   around it there is no ambient darkness helping the type. */
.deskcard__scrim {
	z-index: -1;
	background: linear-gradient(to top, rgba(10, 7, 34, 0.96) 8%, rgba(10, 7, 34, 0.55) 55%, rgba(10, 7, 34, 0.25));
}

.deskcard--lead .deskcard__img,
.deskcard--lead .deskcard__scrim {
	opacity: 1;
}

.deskcard--lead:hover .deskcard__img {
	transform: scale(1.05);
	transition: opacity 0.55s var(--ease), transform 0.7s var(--ease);
}

/* On the photographed panel the colour wash would drown the image, so the
   scrim does the legibility work and the wash is held back. */
.deskcard--lead::before {
	opacity: 0;
}

.deskcard--lead:hover::before {
	opacity: 0.34;
}

.deskcard__top {
	display: flex;
	flex-direction: column;
	gap: 0.3rem;
}

.deskcard--lead .deskcard__top {
	order: -1;
	margin-bottom: auto;
}

/* On paper the plate begins as a PALE wash of the desk colour, so its type
   must be ink — the dark build's white would be white-on-near-white. On hover
   the wash rises to full opacity and every label flips to white together
   (see the .deskcard:hover block below). */
.deskcard__name {
	font-family: var(--font-display);
	font-weight: 800;
	font-size: clamp(1.1rem, 1.9vw, 1.5rem);
	text-transform: uppercase;
	letter-spacing: -0.01em;
	line-height: 1.05;
	color: var(--ink-100);
	transition: color var(--dur) var(--ease);
}

.deskcard--lead .deskcard__name {
	font-size: clamp(1.5rem, 2.6vw, 2.1rem);
}

.deskcard__count {
	font-size: var(--fs-micro);
	font-weight: 600;
	text-transform: uppercase;
	letter-spacing: 0.14em;
	color: var(--ink-400);
	transition: color var(--dur) var(--ease);
}

.deskcard:hover .deskcard__count {
	color: rgba(255, 255, 255, 0.82);
}

.deskcard__foot {
	display: flex;
	align-items: flex-end;
	justify-content: space-between;
	gap: 0.85rem;
}

.deskcard__latest {
	display: flex;
	flex-direction: column;
	gap: 0.25rem;
	min-width: 0;
}

.deskcard__latest-label {
	font-size: var(--fs-micro);
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: 0.16em;
	color: var(--ink-500);
	transition: color var(--dur) var(--ease);
}

.deskcard__latest-title {
	font-size: var(--fs-sm);
	font-weight: 600;
	line-height: 1.3;
	color: var(--ink-200);
	transition: color var(--dur) var(--ease);
	/* Two lines, so an unusually long headline cannot stretch one plate and
	   knock the whole row out of alignment. */
	display: -webkit-box;
	-webkit-line-clamp: 2;
	line-clamp: 2;
	-webkit-box-orient: vertical;
	overflow: hidden;
}

.deskcard--lead .deskcard__latest-title {
	font-size: var(--fs-body);
	-webkit-line-clamp: 3;
	line-clamp: 3;
}

.deskcard__go {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 32px;
	height: 32px;
	flex-shrink: 0;
	border-radius: 50%;
	border: 1px solid var(--line-firm);
	color: var(--ink-200);
	transition: background var(--dur) var(--ease), border-color var(--dur) var(--ease),
		color var(--dur) var(--ease), transform var(--dur) var(--ease);
}

.deskcard__go svg {
	width: 15px;
	height: 15px;
}

.deskcard:hover .deskcard__go {
	background: #fff;
	border-color: #fff;
	/* The desk colour, so the glyph is knocked out of the white disc against
	   whatever plate colour has just risen behind it. */
	color: var(--cat-bg, var(--violet-500));
	transform: translateX(3px);
}

/* Hover state: the plate fills with its solid desk colour, so all of the ink
   type above flips to white in one move. Kept as a single block so the flip is
   obviously coordinated rather than scattered across the section. */
.deskcard:hover .deskcard__name,
.deskcard:hover .deskcard__latest-title {
	color: #fff;
}

.deskcard:hover .deskcard__latest-label {
	color: rgba(255, 255, 255, 0.72);
}

/* The photographed lead panel is the exception: it carries a dark scrim over
   its image from the start, so its type is white at rest, hover or not. */
.deskcard--lead .deskcard__name,
.deskcard--lead .deskcard__latest-title {
	color: #fff;
}

.deskcard--lead .deskcard__count,
.deskcard--lead .deskcard__latest-label {
	color: rgba(255, 255, 255, 0.72);
}

.deskcard--lead .deskcard__go {
	border-color: rgba(255, 255, 255, 0.45);
	color: #fff;
}

@media (max-width: 900px) {
	.deskboard {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}

	/* The lead stops spanning rows here: at two columns a double-height panel
	   leaves a hole beside it on an odd count. */
	.deskcard--lead {
		grid-row: auto;
		grid-column: span 2;
		min-height: 300px;
	}
}

@media (max-width: 560px) {
	.deskboard {
		grid-template-columns: minmax(0, 1fr);
	}

	.deskcard--lead {
		grid-column: auto;
		min-height: 260px;
	}
}

/* 7.65 The Wire — a dated timeline.
   Stories hang off a vertical spine, grouped under the day they were filed.
   The only section on the page with a sense of time passing, which is what
   keeps it distinct from the desk board above and the ranked list below. */
.wire {
	position: relative;
	list-style: none;
	padding: 0;
	margin: 0;
}

/* The spine. Drawn as a pseudo-element on the list rather than a border on
   each row, so it runs continuously through the date marks too. */
.wire::before {
	content: "";
	position: absolute;
	top: 0.6rem;
	bottom: 0.6rem;
	left: 7px;
	width: 1px;
	background: linear-gradient(
		to bottom,
		transparent,
		var(--line-firm) 6%,
		var(--line-firm) 94%,
		transparent
	);
}

/* Date rule — "Today", "Yesterday", then real dates. */
.wire__daymark {
	position: relative;
	padding-left: 2.75rem;
	margin-block: 1.5rem 0.85rem;
}

.wire__daymark:first-child {
	margin-top: 0;
}

.wire__day {
	display: inline-block;
	padding: 0.28rem 0.7rem;
	border-radius: var(--radius);
	background: var(--navy-750);
	border: 1px solid var(--line-soft);
	font-size: var(--fs-micro);
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: 0.16em;
	color: var(--ink-300);
}

.wire__item {
	position: relative;
	padding-left: 2.75rem;
}

/* The node sitting on the spine, in the story's desk colour. A ring rather
   than a filled dot so it reads against the line at any colour. */
.wire__node {
	position: absolute;
	left: 0;
	top: 1.5rem;
	width: 15px;
	height: 15px;
	border-radius: 50%;
	background: var(--navy-800);
	border: 3px solid var(--cat-bg, var(--violet-500));
	transition: transform var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}

.wire__item:hover .wire__node {
	transform: scale(1.25);
	box-shadow: 0 0 0 5px rgba(10, 7, 34, 0.07);
}

.wire__card {
	display: grid;
	grid-template-columns: minmax(0, 1fr) 132px;
	gap: 1.25rem;
	align-items: center;
	padding-block: 1.15rem;
	border-bottom: 1px solid var(--line-soft);
}

.wire__item:last-child .wire__card {
	border-bottom: 0;
}

.wire__body {
	display: flex;
	flex-direction: column;
	gap: 0.4rem;
	min-width: 0;
}

.wire__meta {
	display: flex;
	align-items: center;
	gap: 0.65rem;
	font-size: var(--fs-micro);
	font-weight: 600;
	text-transform: uppercase;
	letter-spacing: 0.14em;
}

/* Monospaced-feel timestamp: tabular figures keep the column aligned down
   the feed even though the times differ. */
.wire__time {
	color: var(--ink-200);
	font-variant-numeric: tabular-nums;
}

.wire__desk {
	position: relative;
	padding-left: 0.75rem;
	color: var(--cat-bg, var(--violet-300));
}

.wire__desk::before {
	content: "";
	position: absolute;
	left: 0;
	top: 50%;
	width: 3px;
	height: 3px;
	margin-top: -1.5px;
	border-radius: 50%;
	background: currentColor;
}

.wire__title {
	font-size: clamp(1.05rem, 1.6vw, 1.3rem);
	font-weight: 700;
	line-height: 1.25;
	letter-spacing: -0.01em;
	color: var(--ink-100);
}

.wire__title a:hover {
	color: var(--violet-300);
}

.wire__excerpt {
	font-size: var(--fs-sm);
	color: var(--ink-400);
	max-width: 62ch;
	display: -webkit-box;
	-webkit-line-clamp: 2;
	line-clamp: 2;
	-webkit-box-orient: vertical;
	overflow: hidden;
}

.wire__media {
	display: block;
	overflow: hidden;
	border-radius: var(--radius);
	aspect-ratio: 4 / 3;
	background: var(--navy-750);
}

.wire__img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	transition: transform 0.6s var(--ease);
}

.wire__item:hover .wire__img {
	transform: scale(1.06);
}

@media (max-width: 700px) {
	.wire__daymark,
	.wire__item {
		padding-left: 1.9rem;
	}

	.wire::before {
		left: 5px;
	}

	.wire__node {
		width: 11px;
		height: 11px;
		border-width: 2px;
		top: 1.35rem;
	}

	/* The thumbnail leads on narrow screens rather than being squeezed into a
	   sliver beside the copy. */
	.wire__card {
		grid-template-columns: minmax(0, 1fr);
		gap: 0.85rem;
	}

	.wire__media {
		order: -1;
		aspect-ratio: 16 / 9;
	}

	.wire__excerpt {
		display: none;
	}
}

/* 7.7 Stat band — a full-width violet strip breaking the grid, giving the
   long homepage a change of pace between card sections. */
.statband {
	background: var(--violet-500);
	color: #fff;
}

.statband__grid {
	display: grid;
	grid-template-columns: repeat(4, minmax(0, 1fr));
	gap: var(--gap);
	padding-block: clamp(1.75rem, 3.5vw, 2.75rem);
}

.statband__item {
	display: flex;
	flex-direction: column;
	gap: 0.25rem;
}

.statband__num {
	font-family: var(--font-display);
	font-weight: 800;
	font-size: clamp(1.75rem, 3.4vw, 2.75rem);
	line-height: 1;
	letter-spacing: -0.02em;
}

.statband__label {
	font-size: var(--fs-micro);
	font-weight: 600;
	text-transform: uppercase;
	letter-spacing: 0.15em;
	color: rgba(255, 255, 255, 0.76);
}

@media (max-width: 720px) {
	.statband__grid {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}
}

/* 7.8 Closing block — latest stories beside a desk index, so the page ends
   on navigation rather than yet another card grid. */
.closing {
	display: grid;
	grid-template-columns: minmax(0, 1.5fr) minmax(0, 1fr);
	gap: clamp(1.5rem, 3.5vw, 3rem);
	align-items: start;
}

@media (max-width: 900px) {
	.closing {
		grid-template-columns: minmax(0, 1fr);
	}
}

.ranklist {
	display: flex;
	flex-direction: column;
}

.rank {
	display: grid;
	grid-template-columns: 3.25rem 1fr;
	gap: 1rem;
	align-items: start;
	padding-block: 1.05rem;
	border-bottom: 1px solid var(--line-soft);
}

.rank:first-child {
	padding-top: 0;
}

.rank:last-child {
	border-bottom: 0;
}

.rank__num {
	font-family: var(--font-display);
	font-weight: 800;
	font-size: 1.6rem;
	line-height: 1;
	color: var(--violet-500);
	letter-spacing: -0.03em;
}

.rank__title {
	font-size: 1.05rem;
	font-weight: 600;
	line-height: 1.3;
	color: var(--ink-100);
	margin-bottom: 0.3rem;
}

.rank__title a:hover {
	color: var(--violet-300);
}

/* Desk index — a compact list of every category with a hover sweep in that
   desk's own colour. Shared by the closing block and the single sidebar. */
.cat-list {
	display: flex;
	flex-direction: column;
}

.cat-list a {
	position: relative;
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 0.75rem;
	padding: 0.8rem 0.9rem;
	border-bottom: 1px solid var(--line-soft);
	overflow: hidden;
	isolation: isolate;
	transition: color var(--dur) var(--ease);
}

.cat-list a:last-child {
	border-bottom: 0;
}

.cat-list__name {
	position: relative;
	z-index: 1;
	font-size: var(--fs-xs);
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: 0.12em;
	color: var(--ink-200);
	transition: color var(--dur) var(--ease);
}

.cat-list__count {
	position: relative;
	z-index: 1;
	font-size: var(--fs-micro);
	font-weight: 600;
	color: var(--ink-500);
	transition: color var(--dur) var(--ease);
}

.cat-list__fill {
	position: absolute;
	inset: 0;
	z-index: 0;
	background: var(--cat-bg, var(--violet-500));
	transform: scaleX(0);
	transform-origin: left;
	transition: transform var(--dur) var(--ease);
}

.cat-list a:hover .cat-list__fill {
	transform: scaleX(1);
}

.cat-list a:hover .cat-list__name,
.cat-list a:hover .cat-list__count {
	color: var(--cat-fg, #fff);
}

/* ── 8. Newsletter ───────────────────────────────────────────────────────── */

/* The target of every SUBSCRIBE button in the theme. Field names, the honeypot
   and the #newsletter id are fixed by inc/newsletter.php and main.js —
   restyle freely, never rename.

   An asymmetric split band on a deep ink ground: the pitch and its proof points
   hold a wide left column, the form sits in a raised card on the right. This
   replaces the previous centred-white-card-on-violet composition — the section
   now reads as a masthead panel rather than a boxed promo, and it is the one
   deliberately dark region on an otherwise light page, which is what makes it
   stop the scroll. */
.brief {
	position: relative;
	background: var(--ink-100);
	padding-block: clamp(2.5rem, 5.5vw, 4.5rem);
	overflow: hidden;
}

/* A violet rule across the very top, so the band announces itself before any
   of its content is read. */
.brief::before {
	content: "";
	position: absolute;
	top: 0;
	left: 0;
	right: 0;
	height: 3px;
	background: linear-gradient(
		90deg,
		var(--violet-500),
		var(--violet-400) 45%,
		var(--sky) 100%
	);
}

/* One broad violet bloom off the right edge, behind the form card. Replaces the
   old colour-block collage — a single soft wash reads as depth on the dark
   ground where nine hard rectangles read as decoration. */
.brief::after {
	content: "";
	position: absolute;
	top: -30%;
	right: -8%;
	width: min(680px, 60vw);
	aspect-ratio: 1;
	border-radius: 50%;
	background: radial-gradient(circle, rgba(74, 68, 240, 0.5), transparent 70%);
	pointer-events: none;
}

.brief__grid {
	position: relative;
	z-index: 1;
	display: grid;
	/* Deliberately uneven: the pitch takes the larger track so the section is
	   editorial-led, with the form as the smaller, denser object beside it. */
	grid-template-columns: minmax(0, 1.25fr) minmax(0, 1fr);
	gap: clamp(1.75rem, 4vw, 4rem);
	align-items: center;
}

/* ── Left column: the pitch */
.brief__pitch {
	min-width: 0;
}

.brief__kicker {
	display: inline-flex;
	align-items: center;
	gap: 0.5rem;
	margin-bottom: 1rem;
	padding: 0.35rem 0.85rem;
	border: 1px solid rgba(255, 255, 255, 0.28);
	border-radius: var(--radius-pill);
	font-size: var(--fs-micro);
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: 0.18em;
	color: #fff;
}

/* The live dot on the kicker, reusing the shared pulse. */
.brief__kicker::before {
	content: "";
	width: 6px;
	height: 6px;
	border-radius: 50%;
	background: var(--violet-400);
	box-shadow: 0 0 0 0 rgba(75, 68, 240, 0.7);
	animation: st-pulse 2.4s infinite;
}

.brief__title {
	font-family: var(--font-display);
	font-weight: 800;
	text-transform: uppercase;
	letter-spacing: -0.02em;
	line-height: 0.98;
	font-size: clamp(1.75rem, 3.8vw, 3rem);
	color: #fff;
	margin-bottom: 0.9rem;
	max-width: 22ch;
	text-wrap: balance;
}

.brief__sub {
	font-size: var(--fs-lead);
	color: rgba(255, 255, 255, 0.74);
	max-width: 52ch;
}

/* Proof points: a row of figure-over-label pairs divided by hairlines. Sits
   under the copy in the left column rather than centred beneath the form. */
.brief__facts {
	display: flex;
	flex-wrap: wrap;
	gap: clamp(1.25rem, 3vw, 2.5rem);
	margin: clamp(1.5rem, 3vw, 2.25rem) 0 0;
	padding-top: clamp(1.25rem, 2.5vw, 1.75rem);
	border-top: 1px solid rgba(255, 255, 255, 0.16);
}

.brief__fact {
	display: flex;
	flex-direction: column;
	gap: 0.2rem;
	min-width: 0;
}

.brief__facts dt {
	font-family: var(--font-display);
	font-weight: 800;
	font-size: clamp(1.35rem, 2.4vw, 1.85rem);
	line-height: 1;
	letter-spacing: -0.02em;
	text-transform: uppercase;
	/* A light violet, stated literally: this is the only dark region in a
	   light-only theme, so --violet-300 (a DEEP shade tuned for white grounds)
	   would be near-invisible here. */
	color: #A5A1FF;
}

.brief__facts dd {
	margin: 0;
	font-size: var(--fs-xs);
	line-height: 1.35;
	color: rgba(255, 255, 255, 0.6);
	max-width: 20ch;
}

/* ── Right column: the form card */
.brief__panel {
	position: relative;
	display: flex;
	flex-direction: column;
	padding: clamp(1.5rem, 2.6vw, 2rem);
	/* Lifted off the band rather than punched into it: a light panel on the
	   dark ground, which puts the form on the same paper as the rest of the
	   site and makes the input obviously a place to type. */
	background: #fff;
	border-radius: var(--radius-lg);
	box-shadow: 0 30px 70px rgba(0, 0, 0, 0.45);
}

.brief__panel-label {
	font-size: var(--fs-micro);
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: 0.18em;
	color: var(--violet-500);
	margin-bottom: 0.6rem;
}

.brief__panel-lede {
	font-family: var(--font-display);
	font-weight: 800;
	text-transform: uppercase;
	letter-spacing: -0.01em;
	line-height: 1.05;
	font-size: clamp(1.1rem, 1.8vw, 1.4rem);
	color: var(--ink-100);
	margin-bottom: 1.1rem;
}

/* Stacked field and button. The column is too narrow for the old single-pill
   row — at this width the placeholder truncated before the button. */
.brief__field {
	display: flex;
	flex-direction: column;
	gap: 0.55rem;
}

.brief__field .newsletter-form__input {
	width: 100%;
	/* An <input> carries an intrinsic min-width from its `size` attribute, which
	   ignores width:100% and pushed the field past the viewport at 320px.
	   min-width:0 lets it shrink with its container. */
	min-width: 0;
	padding: 0.8rem 1.1rem;
	background: var(--navy-900);
	border: 1px solid var(--line-firm);
	border-radius: var(--radius-pill);
	color: var(--ink-100);
	font-size: var(--fs-sm);
	transition: border-color var(--dur) var(--ease), box-shadow var(--dur) var(--ease),
		background var(--dur) var(--ease);
}

.brief__field .newsletter-form__input::placeholder {
	color: var(--ink-500);
}

.brief__field .newsletter-form__input:focus {
	outline: none;
	background: #fff;
	border-color: var(--violet-500);
	box-shadow: 0 0 0 4px rgba(58, 50, 224, 0.16);
}

.brief__field .newsletter-form__btn {
	width: 100%;
	justify-content: center;
}

.brief .newsletter-form__msg {
	margin-top: 0.8rem;
	font-size: var(--fs-sm);
	font-weight: 600;
}

.brief .newsletter-form__msg--success {
	color: #0F7040;
}

.brief .newsletter-form__msg--error {
	color: #C2261A;
}

.brief__note {
	margin-top: 0.85rem;
	font-size: var(--fs-micro);
	line-height: 1.45;
	text-transform: uppercase;
	letter-spacing: 0.1em;
	color: var(--ink-500);
}

/* Closing reassurance on a hairline, so the card has a base rather than ending
   on the fine print. */
.brief__trust {
	display: flex;
	align-items: flex-start;
	gap: 0.5rem;
	margin-top: 1rem;
	padding-top: 0.9rem;
	border-top: 1px solid var(--line-soft);
	font-size: var(--fs-xs);
	line-height: 1.4;
	color: var(--ink-400);
}

.brief__trust-dot {
	width: 6px;
	height: 6px;
	margin-top: 0.42em;
	flex-shrink: 0;
	border-radius: 50%;
	background: #12A66B;
}

/* Tablet: the two tracks stack. The form leads, because at this width a reader
   scrolling past should hit the control before the supporting copy. */
@media (max-width: 900px) {
	.brief__grid {
		grid-template-columns: minmax(0, 1fr);
		gap: clamp(1.5rem, 4vw, 2.25rem);
	}

	.brief__panel {
		order: -1;
	}

	.brief__title {
		max-width: 26ch;
	}

	.brief__sub {
		max-width: none;
	}

	/* Side by side the bloom sat behind the card; stacked it would wash out the
	   headline instead. */
	.brief::after {
		display: none;
	}
}

@media (max-width: 560px) {
	/* The facts row becomes two columns rather than wrapping unevenly: three
	   figure/label pairs in one flex row leave a single orphan on the second
	   line at phone widths. */
	.brief__facts {
		display: grid;
		grid-template-columns: repeat(2, minmax(0, 1fr));
		gap: 1.1rem;
	}

	/* The third fact spans both columns, so the grid ends flush instead of
	   leaving a hole beside a lone item. */
	.brief__fact:last-child:nth-child(odd) {
		grid-column: 1 / -1;
	}

	.brief__facts dd {
		max-width: none;
	}
}

/* ── 9. Footer ───────────────────────────────────────────────────────────── */

/* Asymmetric two-track footer: a tall brand rail on the left, the desk index
   beside it, and a thin base bar. Deliberately not the stacked full-width
   bands used elsewhere. */
.site-footer {
	position: relative;
	background: var(--navy-900);
	padding-bottom: 1.75rem;
}

/* Spectrum rule — one band per desk in its own colour, spanning the full
   width. Doubles as a legend for the colour coding used across the site. */
.footer-spectrum {
	display: flex;
	height: 4px;
	width: 100%;
}

.footer-spectrum span {
	flex: 1;
	background: var(--cat-bg, var(--violet-500));
}

.footer-grid {
	display: grid;
	/* The brand rail is fixed-ish and the index takes the rest, rather than
	   the two sharing equal tracks — the asymmetry is the point. */
	grid-template-columns: minmax(0, 0.85fr) minmax(0, 1.35fr);
	gap: clamp(2rem, 5vw, 5rem);
	padding-block: clamp(2.5rem, 5vw, 4rem);
}

@media (max-width: 900px) {
	.footer-grid {
		grid-template-columns: minmax(0, 1fr);
		gap: 2.5rem;
	}
}

/* ── Brand rail */
.footer-id {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: 1.1rem;
	/* A hairline down the inner edge separates the two tracks without a box. */
	position: relative;
}

@media (min-width: 901px) {
	.footer-id::after {
		content: "";
		position: absolute;
		top: 0;
		bottom: 0;
		right: clamp(-2.5rem, -2.5vw, -1rem);
		width: 1px;
		background: var(--line-soft);
	}
}

.footer-id__logo img {
	max-height: 46px;
	width: auto;
}

.footer-id__name {
	font-family: var(--font-display);
	font-weight: 800;
	font-size: 1.6rem;
	text-transform: uppercase;
	letter-spacing: -0.02em;
	color: var(--ink-100);
}

.footer-id__desc {
	font-size: var(--fs-sm);
	color: var(--ink-400);
	max-width: 38ch;
}

/* Live status stamp — shows when the wire last moved, so the footer reads as
   a running newsroom rather than a static sitemap. */
.footer-status {
	display: inline-flex;
	align-items: center;
	gap: 0.5rem;
	padding: 0.4rem 0.8rem;
	border: 1px solid var(--line-soft);
	border-radius: var(--radius-pill);
	font-size: var(--fs-micro);
	font-weight: 600;
	text-transform: uppercase;
	letter-spacing: 0.14em;
	color: var(--ink-300);
}

.footer-status__dot {
	width: 6px;
	height: 6px;
	border-radius: 50%;
	/* Darkened from #3ED598: a mint dot on white read as a pale smudge, and
	   this is the theme's only "live" signal — it has to look lit. */
	background: #12A66B;
	box-shadow: 0 0 0 0 rgba(18, 166, 107, 0.6);
	animation: st-pulse 2.4s infinite;
}

.footer-contact {
	display: flex;
	flex-direction: column;
	gap: 0.35rem;
	font-size: var(--fs-sm);
	color: var(--ink-300);
}

.footer-contact a {
	transition: color var(--dur) var(--ease);
}

.footer-contact a:hover {
	color: var(--violet-500);
}

/* ── Desk index */
.footer-heading {
	font-size: var(--fs-micro);
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: 0.18em;
	color: var(--ink-500);
	margin-bottom: 1.1rem;
}

/* Tag cloud sized by output: the busiest desks set larger, so the shape of
   the coverage is legible at a glance. --scale is set per link in PHP. */
.deskcloud {
	display: flex;
	flex-wrap: wrap;
	gap: 0.5rem;
}

.deskcloud__link {
	display: inline-flex;
	align-items: center;
	gap: 0.5rem;
	padding: 0.45rem 0.85rem;
	border-radius: var(--radius-pill);
	border: 1px solid var(--line-soft);
	background: var(--navy-850);
	/* Scaled with calc rather than transform: transform would leave the
	   original box in flow and the chips would overlap. */
	font-size: calc(var(--fs-xs) * var(--scale, 1));
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: 0.08em;
	line-height: 1.2;
	color: var(--ink-200);
	transition: background var(--dur) var(--ease), border-color var(--dur) var(--ease),
		color var(--dur) var(--ease), transform var(--dur) var(--ease);
}

.deskcloud__link:hover {
	background: var(--cat-bg, var(--violet-500));
	border-color: var(--cat-bg, var(--violet-500));
	color: var(--cat-fg, #fff);
	transform: translateY(-2px);
}

.deskcloud__count {
	font-size: 0.72em;
	font-weight: 600;
	opacity: 0.6;
	font-variant-numeric: tabular-nums;
}

/* ── Base bar */
.footer-base {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: var(--gap);
	flex-wrap: wrap;
	padding-top: 1.5rem;
	border-top: 1px solid var(--line-soft);
}

.footer-copy {
	font-size: var(--fs-xs);
	color: var(--ink-500);
}

.footer-legal {
	display: flex;
	align-items: center;
	gap: 1.25rem;
	flex-wrap: wrap;
	font-size: var(--fs-xs);
	color: var(--ink-500);
	/* Pushed to sit beside the copyright, leaving the Top link at the far
	   right regardless of how many legal links there are. */
	margin-right: auto;
	margin-left: 1.25rem;
}

.footer-legal a {
	transition: color var(--dur) var(--ease);
}

.footer-legal a:hover {
	color: var(--ink-200);
}

.footer-legal__menu {
	display: flex;
	gap: 1.25rem;
	flex-wrap: wrap;
}

.footer-top {
	display: inline-flex;
	align-items: center;
	gap: 0.5rem;
	padding: 0.5rem 0.9rem;
	border: 1px solid var(--line-soft);
	border-radius: var(--radius-pill);
	font-size: var(--fs-micro);
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: 0.14em;
	color: var(--ink-300);
	transition: background var(--dur) var(--ease), border-color var(--dur) var(--ease),
		color var(--dur) var(--ease);
}

.footer-top svg {
	width: 13px;
	height: 13px;
	transition: transform var(--dur) var(--ease);
}

.footer-top:hover {
	background: var(--violet-500);
	border-color: var(--violet-500);
	color: #fff;
}

.footer-top:hover svg {
	transform: translateY(-2px);
}

@media (max-width: 640px) {
	.footer-base {
		justify-content: flex-start;
	}

	.footer-legal {
		margin-left: 0;
		margin-right: 0;
		width: 100%;
		order: 3;
	}

	.footer-top {
		order: 2;
		margin-left: auto;
	}
}

/* ── 10. Archive / category ──────────────────────────────────────────────── */

/* Hero: the term name on the left, its stats on the right, over a band
   washed in the term's own colour. */
.deskhero {
	position: relative;
	background: var(--navy-850);
	border-bottom: 1px solid var(--line-soft);
	padding-block: clamp(2.25rem, 5vw, 3.75rem);
	overflow: hidden;
}

/* A broad diagonal wash in the desk colour, anchored to the left edge so it
   sits behind the name rather than across the stats. */
.deskhero::before {
	content: "";
	position: absolute;
	inset: 0;
	background: linear-gradient(
		100deg,
		var(--chip-bg, var(--violet-500)) -20%,
		transparent 52%
	);
	/* Lowered from 0.2: the desk colours are darker in this theme and the band
	   beneath is now pale, so 0.2 put a mid-tone behind the display-size title
	   and cost it contrast. */
	opacity: 0.12;
	pointer-events: none;
}

/* A thick bar of the desk colour down the leading edge — the strongest
   colour cue on the page, and the thing that makes each desk feel distinct. */
.deskhero::after {
	content: "";
	position: absolute;
	top: 0;
	bottom: 0;
	left: 0;
	width: 6px;
	background: var(--chip-bg, var(--violet-500));
}

.deskhero__grid {
	position: relative;
	z-index: 1;
	display: grid;
	grid-template-columns: minmax(0, 1fr) auto;
	gap: clamp(1.5rem, 4vw, 3.5rem);
	align-items: end;
}

@media (max-width: 780px) {
	.deskhero__grid {
		grid-template-columns: minmax(0, 1fr);
		align-items: start;
		gap: 1.5rem;
	}
}

.deskhero__lede {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: 0.85rem;
	min-width: 0;
}

.deskhero__title {
	font-family: var(--font-display);
	font-weight: 800;
	text-transform: uppercase;
	letter-spacing: -0.02em;
	line-height: 0.9;
	font-size: var(--fs-display);
	color: var(--ink-100);
	/* Long search queries and tag names must not push the stats off-screen. */
	overflow-wrap: anywhere;
}

.deskhero__desc {
	font-size: var(--fs-lead);
	color: var(--ink-300);
	max-width: 60ch;
}

/* Stat block — count and freshness, rules between them. */
.deskstats {
	display: flex;
	gap: clamp(1.25rem, 3vw, 2.5rem);
	margin: 0;
	flex-shrink: 0;
}

.deskstats__item {
	display: flex;
	flex-direction: column;
	gap: 0.2rem;
	padding-left: clamp(1.25rem, 3vw, 2.5rem);
	border-left: 1px solid var(--line-firm);
}

.deskstats__item:first-child {
	padding-left: 0;
	border-left: 0;
}

.deskstats dt {
	font-size: var(--fs-micro);
	font-weight: 600;
	text-transform: uppercase;
	letter-spacing: 0.16em;
	color: var(--ink-500);
	order: 2;
}

.deskstats dd {
	margin: 0;
	font-family: var(--font-display);
	font-weight: 800;
	font-size: clamp(1.5rem, 2.6vw, 2.1rem);
	line-height: 1;
	letter-spacing: -0.02em;
	color: var(--ink-100);
	white-space: nowrap;
}

/* ── Two-column spread */
.archive-layout {
	display: grid;
	grid-template-columns: minmax(0, 1fr) 320px;
	gap: clamp(1.75rem, 4vw, 3.5rem);
	align-items: start;
}

@media (max-width: 1000px) {
	.archive-layout {
		grid-template-columns: minmax(0, 1fr);
	}
}

.archive-side {
	display: flex;
	flex-direction: column;
	gap: var(--gap);
	position: sticky;
	top: 100px;
}

@media (max-width: 1000px) {
	.archive-side {
		position: static;
	}
}

/* ── Lead story: picture first, copy beneath. */
.deskled {
	display: flex;
	flex-direction: column;
	gap: 1.1rem;
	padding-bottom: var(--gap-lg);
	margin-bottom: 0.5rem;
	border-bottom: 1px solid var(--line-firm);
}

.deskled__media {
	position: relative;
	display: block;
	overflow: hidden;
	border-radius: var(--radius);
	background: var(--navy-750);
}

.deskled__clip {
	display: block;
	aspect-ratio: 16 / 9;
	overflow: hidden;
}

.deskled__img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	transition: transform 0.7s var(--ease);
}

.deskled:hover .deskled__img {
	transform: scale(1.03);
}

/* Corner flag in the desk colour, inherited from the hero's --chip-bg. */
.deskled__tag {
	position: absolute;
	top: 0;
	left: 0;
	padding: 0.4rem 0.85rem;
	background: var(--chip-bg, var(--violet-500));
	/* Paired with the background rather than fixed white: the light swatches
	   (sand, amber, sky, rose) carry dark text, and white would vanish. */
	color: var(--chip-fg, #fff);
	font-size: var(--fs-micro);
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: 0.16em;
	border-bottom-right-radius: var(--radius);
}

.deskled__body {
	display: flex;
	flex-direction: column;
	gap: 0.75rem;
	align-items: flex-start;
}

.deskled__title {
	font-family: var(--font-display);
	font-weight: 800;
	text-transform: uppercase;
	letter-spacing: -0.018em;
	line-height: 0.98;
	font-size: clamp(1.6rem, 3.2vw, 2.6rem);
	color: var(--ink-100);
}

.deskled__title a:hover {
	color: var(--violet-300);
}

.deskled__excerpt {
	font-size: var(--fs-lead);
	color: var(--ink-300);
	max-width: 60ch;
}

/* ── Numbered story rows */
.deskrow {
	display: grid;
	grid-template-columns: 3rem minmax(0, 1fr) 148px;
	gap: 1.25rem;
	align-items: start;
	padding-block: 1.5rem;
	border-bottom: 1px solid var(--line-soft);
}

.deskrow:last-of-type {
	border-bottom: 0;
}

.deskrow__num {
	font-family: var(--font-display);
	font-weight: 800;
	font-size: 1.35rem;
	line-height: 1.2;
	letter-spacing: -0.03em;
	/* Numbers in the desk colour, tying the list to the hero band. */
	color: var(--chip-bg, var(--violet-400));
	font-variant-numeric: tabular-nums;
}

.deskrow__body {
	display: flex;
	flex-direction: column;
	gap: 0.45rem;
	min-width: 0;
}

.deskrow__meta {
	display: flex;
	align-items: center;
	gap: 0.65rem;
	font-size: var(--fs-micro);
	font-weight: 600;
	text-transform: uppercase;
	letter-spacing: 0.14em;
	color: var(--ink-500);
}

.deskrow__desk {
	position: relative;
	padding-left: 0.75rem;
	color: var(--violet-300);
}

.deskrow__desk::before {
	content: "";
	position: absolute;
	left: 0;
	top: 50%;
	width: 3px;
	height: 3px;
	margin-top: -1.5px;
	border-radius: 50%;
	background: currentColor;
}

.deskrow__title {
	font-size: clamp(1.1rem, 1.7vw, 1.35rem);
	font-weight: 700;
	line-height: 1.25;
	letter-spacing: -0.01em;
	color: var(--ink-100);
}

.deskrow__title a:hover {
	color: var(--violet-300);
}

.deskrow__excerpt {
	font-size: var(--fs-sm);
	color: var(--ink-400);
	display: -webkit-box;
	-webkit-line-clamp: 2;
	line-clamp: 2;
	-webkit-box-orient: vertical;
	overflow: hidden;
}

.deskrow__media {
	display: block;
	overflow: hidden;
	border-radius: var(--radius);
	aspect-ratio: 4 / 3;
	background: var(--navy-750);
}

.deskrow__img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	transition: transform 0.6s var(--ease);
}

.deskrow:hover .deskrow__img {
	transform: scale(1.06);
}

@media (max-width: 640px) {
	/* The number moves inline with the meta row and the thumbnail leads, so a
	   narrow screen is not trying to hold three columns. */
	.deskrow {
		grid-template-columns: minmax(0, 1fr);
		gap: 0.85rem;
	}

	.deskrow__num {
		display: none;
	}

	.deskrow__media {
		order: -1;
		aspect-ratio: 16 / 9;
	}
}

/* Pagination */
.pagination {
	margin-top: var(--gap-lg);
	padding-top: var(--gap-lg);
	border-top: 1px solid var(--line-soft);
}

.pagination .nav-links {
	display: flex;
	align-items: center;
	justify-content: center;
	gap: 0.45rem;
	flex-wrap: wrap;
}

.pagination .page-numbers {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	min-width: 40px;
	height: 40px;
	padding-inline: 0.75rem;
	border-radius: var(--radius);
	border: 1px solid var(--line-soft);
	font-size: var(--fs-xs);
	font-weight: 600;
	color: var(--ink-300);
	transition: background var(--dur) var(--ease), border-color var(--dur) var(--ease),
		color var(--dur) var(--ease);
}

.pagination .page-numbers:hover {
	border-color: var(--violet-500);
	color: var(--violet-600);
	background: rgba(58, 50, 224, 0.07);
}

.pagination .page-numbers.current {
	background: var(--violet-500);
	border-color: var(--violet-500);
	color: #fff;
}

.pagination .dots {
	border: 0;
}

.no-results {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: 1.25rem;
	padding-block: clamp(2.5rem, 6vw, 5rem);
	max-width: 50ch;
}

.no-results p {
	font-size: var(--fs-lead);
	color: var(--ink-300);
}

/* ── 11. Single post ─────────────────────────────────────────────────────── */
.single-main {
	padding-bottom: var(--pad-section);
}

/* 11.1 Hero — the article opens on its photograph, headline set over it. */
.phero {
	position: relative;
	display: flex;
	align-items: flex-end;
	isolation: isolate;
	margin-bottom: clamp(1.75rem, 4vw, 3rem);
}

.phero--art {
	min-height: clamp(360px, 56vh, 620px);
	padding-block: clamp(2rem, 5vw, 4rem);
}

/* No artwork: a banded header instead, so the page still opens deliberately
   rather than dropping the reader straight into body copy. */
.phero--plain {
	padding-block: clamp(2.25rem, 5vw, 4rem) clamp(1.5rem, 3vw, 2.25rem);
	background: var(--navy-850);
	border-bottom: 1px solid var(--line-soft);
}

.phero__media {
	position: absolute;
	inset: 0;
	z-index: -1;
	overflow: hidden;
}

.phero__img {
	width: 100%;
	height: 100%;
	object-fit: cover;
}

/* Two-stop scrim: heavy at the foot where the type sits, light at the head so
   the photograph is still legible as an image. */
/* Kept DARK: the headline is set over the photograph in white, so the scrim
   still has to sink the image. It no longer fades into the page ground at the
   foot (that only worked when the page was navy) — instead it holds a strong
   ink wash the whole way down, and the article body below starts on white with
   a clean edge. */
.phero__scrim {
	position: absolute;
	inset: 0;
	background:
		linear-gradient(to top, rgba(10, 7, 34, 0.94) 2%, rgba(10, 7, 34, 0.8) 34%, rgba(10, 7, 34, 0.5) 70%, rgba(10, 7, 34, 0.5)),
		linear-gradient(to right, rgba(10, 7, 34, 0.55), transparent 60%);
}

.phero__inner {
	position: relative;
	max-width: 60rem;
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: 1rem;
}

.phero__title {
	font-family: var(--font-display);
	font-weight: 800;
	text-transform: uppercase;
	letter-spacing: -0.02em;
	line-height: 0.94;
	font-size: clamp(2rem, 5.2vw, 4rem);
	color: var(--ink-100);
	text-wrap: balance;
}

/* The art hero is the theme's one inverted region: white type over a scrimmed
   photograph. --ink-100 is now near-black, so the title, standfirst and every
   meta element inside must be forced back to white here. Scoped to --art only;
   .phero--plain keeps the normal ink treatment on its pale band. */
.phero--art .phero__title {
	color: #fff;
	/* Lifts the headline off a busy photograph without a solid plate behind it. */
	text-shadow: 0 2px 24px rgba(6, 2, 28, 0.55);
}

.phero--art .byline,
.phero--art .byline__name,
.phero--art .metarow,
.phero--art .kicker {
	color: rgba(255, 255, 255, 0.82);
}

.phero__standfirst {
	font-size: var(--fs-lead);
	color: var(--ink-200);
	max-width: 62ch;
}

/* Declared after the base .phero__standfirst so this wins the cascade — the
   base rule sets --ink-200, which would be near-black over the dark scrim. */
.phero--art .phero__standfirst {
	color: rgba(255, 255, 255, 0.92);
	text-shadow: 0 1px 12px rgba(6, 2, 28, 0.6);
}

.phero__caption {
	margin-top: -1rem;
	margin-bottom: clamp(1.5rem, 3vw, 2.5rem);
	padding-left: 0.85rem;
	border-left: 2px solid var(--chip-bg, var(--violet-500));
	font-size: var(--fs-xs);
	color: var(--ink-500);
}

/* 11.2 Body — three tracks: detail rail, article, sidebar. */
.single-layout {
	display: grid;
	grid-template-columns: 190px minmax(0, 1fr) 320px;
	gap: clamp(1.5rem, 3.5vw, 3rem);
	align-items: start;
}

@media (max-width: 1180px) {
	/* Sidebar drops under the article first; the detail rail is narrow enough
	   to keep its column a while longer. */
	.single-layout {
		grid-template-columns: 180px minmax(0, 1fr);
	}

	.single-sidebar {
		grid-column: 1 / -1;
	}
}

@media (max-width: 860px) {
	.single-layout {
		grid-template-columns: minmax(0, 1fr);
	}
}

/* Detail rail */
.postrail {
	display: flex;
	flex-direction: column;
	gap: 1.35rem;
	position: sticky;
	top: 100px;
	padding-right: 1.25rem;
	border-right: 1px solid var(--line-soft);
}

@media (max-width: 860px) {
	/* Folds into a single row above the copy, so it reads as a byline strip
	   rather than a stranded column. */
	.postrail {
		position: static;
		flex-direction: row;
		flex-wrap: wrap;
		gap: 1.5rem;
		padding-right: 0;
		padding-bottom: 1.25rem;
		border-right: 0;
		border-bottom: 1px solid var(--line-soft);
	}
}

.postrail__block {
	display: flex;
	flex-direction: column;
	gap: 0.4rem;
}

.postrail__label {
	font-size: var(--fs-micro);
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: 0.16em;
	color: var(--ink-500);
}

.postrail__value {
	font-size: var(--fs-sm);
	font-weight: 600;
	color: var(--ink-200);
}

.postrail__author {
	display: flex;
	align-items: center;
	gap: 0.6rem;
}

.postrail__avatar {
	width: 40px;
	height: 40px;
	border-radius: 50%;
	object-fit: cover;
	flex-shrink: 0;
}

.postrail__name {
	display: block;
	font-size: var(--fs-sm);
	font-weight: 700;
	color: var(--ink-100);
	line-height: 1.2;
}

.postrail__role {
	display: block;
	font-size: var(--fs-micro);
	text-transform: uppercase;
	letter-spacing: 0.12em;
	color: var(--ink-500);
}

/* Article body. Long-form copy is the one place the page steps back from
   uppercase display and lets Inter run at a comfortable measure. */
.article-content,
.page-content {
	font-size: 1.0625rem;
	line-height: 1.78;
	color: var(--ink-200);
	max-width: 68ch;
}

/* Drop cap in the desk colour, opening the article the way print does. */
.article-content > p:first-of-type::first-letter {
	float: left;
	font-family: var(--font-display);
	font-weight: 800;
	font-size: 3.4em;
	line-height: 0.82;
	margin: 0.06em 0.12em 0 0;
	color: var(--chip-bg, var(--violet-400));
}

.article-content > * + *,
.page-content > * + * {
	margin-top: 1.4em;
}

.article-content h2,
.page-content h2 {
	font-family: var(--font-display);
	font-weight: 800;
	text-transform: uppercase;
	letter-spacing: -0.01em;
	line-height: 1.08;
	font-size: clamp(1.4rem, 2.4vw, 1.95rem);
	color: var(--ink-100);
	margin-top: 2.2em;
}

.article-content h3,
.page-content h3 {
	font-size: clamp(1.15rem, 1.8vw, 1.4rem);
	font-weight: 700;
	line-height: 1.25;
	color: var(--ink-100);
	margin-top: 1.9em;
}

.article-content h4,
.page-content h4 {
	font-size: 1.05rem;
	font-weight: 700;
	color: var(--ink-100);
	margin-top: 1.7em;
}

.article-content a,
.page-content a {
	color: var(--violet-300);
	text-decoration: underline;
	text-underline-offset: 3px;
	text-decoration-thickness: 1px;
	transition: color var(--dur) var(--ease);
}

/* Was #fff — on paper an in-copy link must DARKEN on hover, not disappear. */
.article-content a:hover,
.page-content a:hover {
	color: var(--ink-100);
}

.article-content strong,
.page-content strong {
	color: var(--ink-100);
	font-weight: 700;
}

.article-content ul,
.article-content ol,
.page-content ul,
.page-content ol {
	padding-left: 1.4rem;
	list-style: revert;
}

.article-content li,
.page-content li {
	margin-block: 0.45em;
}

.article-content li::marker,
.page-content li::marker {
	color: var(--chip-bg, var(--violet-400));
}

.article-content blockquote,
.page-content blockquote {
	padding: 1.25rem 1.5rem;
	border-left: 3px solid var(--chip-bg, var(--violet-500));
	background: var(--navy-850);
	border-radius: 0 var(--radius) var(--radius) 0;
	font-size: 1.12rem;
	line-height: 1.55;
	color: var(--ink-100);
}

.article-content blockquote p + p,
.page-content blockquote p + p {
	margin-top: 0.8em;
}

.article-content blockquote cite,
.page-content blockquote cite {
	display: block;
	margin-top: 0.75rem;
	font-size: var(--fs-micro);
	font-style: normal;
	font-weight: 600;
	text-transform: uppercase;
	letter-spacing: 0.14em;
	color: var(--ink-500);
}

.article-content img,
.page-content img {
	border-radius: var(--radius);
}

.article-content figure,
.page-content figure {
	margin-inline: 0;
}

.article-content figcaption,
.page-content figcaption {
	margin-top: 0.55rem;
	font-size: var(--fs-xs);
	color: var(--ink-500);
}

.article-content code,
.page-content code {
	background: var(--navy-900);
	border: 1px solid var(--line-soft);
	border-radius: 3px;
	padding: 0.1em 0.4em;
	font-size: 0.9em;
}

.article-content pre,
.page-content pre {
	background: var(--navy-900);
	border: 1px solid var(--line-soft);
	border-radius: var(--radius);
	padding: 1.15rem;
	overflow-x: auto;
}

.article-content pre code,
.page-content pre code {
	background: none;
	border: 0;
	padding: 0;
}

.article-content table,
.page-content table {
	width: 100%;
	border-collapse: collapse;
	font-size: var(--fs-sm);
	/* Wide tables must scroll inside their own box rather than pushing the
	   page sideways. */
	display: block;
	overflow-x: auto;
}

.article-content th,
.article-content td,
.page-content th,
.page-content td {
	padding: 0.65rem 0.85rem;
	border-bottom: 1px solid var(--line-soft);
	text-align: left;
}

.article-content th,
.page-content th {
	font-size: var(--fs-micro);
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: 0.12em;
	color: var(--ink-300);
}

.article-content hr,
.page-content hr {
	border: 0;
	border-top: 1px solid var(--line-soft);
	margin-block: 2.4em;
}

/* End-of-article mark, in the post's desk colour. */
.article-end {
	margin-top: 2.25rem;
}

.article-end__mark {
	display: block;
	width: 34px;
	height: 5px;
	border-radius: 3px;
	background: var(--chip-bg, var(--violet-500));
}

.article-tags {
	display: flex;
	align-items: center;
	gap: 0.5rem;
	flex-wrap: wrap;
	margin-top: 1.75rem;
	padding-top: 1.5rem;
	border-top: 1px solid var(--line-soft);
}

.article-tags__label {
	font-size: var(--fs-micro);
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: 0.16em;
	color: var(--ink-500);
	margin-right: 0.25rem;
}

.article-tags .chip {
	background: var(--navy-750);
	color: var(--ink-300);
}

.article-tags .chip:hover {
	background: var(--chip-bg, var(--violet-500));
	color: var(--chip-fg, #fff);
	opacity: 1;
}

/* Prev / next */
.article-nav {
	display: grid;
	grid-template-columns: repeat(2, minmax(0, 1fr));
	gap: var(--gap);
	margin-top: 1.75rem;
	padding-top: 1.75rem;
	border-top: 1px solid var(--line-soft);
}

@media (max-width: 560px) {
	.article-nav {
		grid-template-columns: minmax(0, 1fr);
	}
}

.article-nav__item {
	display: flex;
	flex-direction: column;
	gap: 0.4rem;
	padding: 1rem 1.15rem;
	border: 1px solid var(--line-soft);
	border-radius: var(--radius);
	transition: border-color var(--dur) var(--ease), background var(--dur) var(--ease);
}

.article-nav__item:hover {
	border-color: var(--chip-bg, var(--violet-400));
	background: var(--navy-850);
}

.article-nav__item--next {
	text-align: right;
	align-items: flex-end;
}

.article-nav__label {
	display: inline-flex;
	align-items: center;
	gap: 0.35rem;
	font-size: var(--fs-micro);
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: 0.14em;
	color: var(--violet-300);
}

.article-nav__title {
	font-size: var(--fs-sm);
	font-weight: 600;
	line-height: 1.35;
	color: var(--ink-200);
}

.related {
	margin-top: var(--gap-lg);
	padding-top: var(--gap-lg);
	border-top: 1px solid var(--line-firm);
}

/* 11.3 Sidebar */
.single-sidebar {
	display: flex;
	flex-direction: column;
	gap: var(--gap);
	position: sticky;
	top: 100px;
}

@media (max-width: 1180px) {
	.single-sidebar {
		position: static;
		/* Below the article the panels read better side by side than as one
		   tall stack. */
		display: grid;
		grid-template-columns: repeat(2, minmax(0, 1fr));
		align-items: start;
		margin-top: var(--gap-lg);
		padding-top: var(--gap-lg);
		border-top: 1px solid var(--line-firm);
	}
}

@media (max-width: 700px) {
	.single-sidebar {
		grid-template-columns: minmax(0, 1fr);
	}
}

/* Sidebar newsletter — a bordered brief card echoing the footer band, rather
   than the old filled violet block. */
.sidebrief {
	position: relative;
	padding: 1.5rem 1.35rem;
	background: var(--navy-850);
	border: 1px solid var(--line-firm);
	border-radius: var(--radius-lg);
	overflow: hidden;
	text-align: center;
}

/* Accent hairline across the top, in the post's desk colour. */
.sidebrief::before {
	content: "";
	position: absolute;
	top: 0;
	left: 0;
	right: 0;
	height: 3px;
	background: var(--chip-bg, var(--violet-500));
}

/* A soft bloom behind the copy, the same device the footer card uses. */
.sidebrief::after {
	content: "";
	position: absolute;
	top: 0;
	left: 50%;
	transform: translate(-50%, -60%);
	width: 120%;
	aspect-ratio: 2 / 1;
	background: radial-gradient(ellipse, rgba(58, 50, 224, 0.12), transparent 70%);
	pointer-events: none;
}

.sidebrief > * {
	position: relative;
	z-index: 1;
}

.sidebrief__kicker {
	display: inline-block;
	margin-bottom: 0.6rem;
	font-size: var(--fs-micro);
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: 0.18em;
	color: var(--violet-300);
}

.sidebrief__title {
	font-family: var(--font-display);
	font-weight: 800;
	text-transform: uppercase;
	letter-spacing: -0.01em;
	line-height: 1.04;
	font-size: 1.25rem;
	color: var(--ink-100);
	margin-bottom: 0.5rem;
}

.sidebrief__sub {
	font-size: var(--fs-xs);
	color: var(--ink-400);
	margin-bottom: 1.1rem;
}

/* Stacked field and button: the column is too narrow for a row. Overrides the
   shared .newsletter-form__input, which is sized for the footer pill. */
.sidebrief__input {
	width: 100%;
	margin-bottom: 0.55rem;
	padding: 0.7rem 1rem;
	background: var(--navy-900);
	border: 1px solid var(--line-firm);
	border-radius: var(--radius-pill);
	color: var(--ink-100);
	font-size: var(--fs-sm);
	text-align: center;
}

.sidebrief__input::placeholder {
	color: var(--ink-500);
}

.sidebrief__input:focus {
	outline: none;
	background: #fff;
	border-color: var(--violet-500);
	box-shadow: 0 0 0 3px rgba(58, 50, 224, 0.18);
}

.sidebrief__btn {
	width: 100%;
}

.sidebrief .newsletter-form__msg {
	margin-top: 0.75rem;
	font-size: var(--fs-xs);
}

.sidebrief .newsletter-form__msg--success {
	color: #0F7040;
}

.sidebrief .newsletter-form__msg--error {
	color: #C2261A;
}

/* Sidebar panels — flush blocks led by a colour tab rather than bordered
   boxes. Shared by the archive and single-post sidebars. */
.panel {
	position: relative;
	padding: 1.4rem 0 0;
	background: none;
	border: 0;
	border-top: 2px solid var(--line-firm);
}

/* The heading sits ON the top rule as a tab in the desk colour, which is
   what replaces the old boxed-in look. --chip-bg is inherited from <main>
   on archives; elsewhere it falls back to the house violet. */
.panel__heading {
	position: absolute;
	top: 0;
	left: 0;
	transform: translateY(-50%);
	padding: 0.32rem 0.7rem;
	background: var(--chip-bg, var(--violet-500));
	/* See .deskled__tag — the fill and its text colour travel together. */
	color: var(--chip-fg, #fff);
	border-radius: 2px;
	font-size: var(--fs-micro);
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: 0.16em;
	margin: 0;
	border: 0;
}

.panel .cat-list a {
	padding-inline: 0;
}

/* ── Ranked story list */
.side-list {
	display: flex;
	flex-direction: column;
	padding-top: 0.35rem;
}

.side-item {
	display: grid;
	grid-template-columns: 1.6rem minmax(0, 1fr);
	gap: 0.8rem;
	align-items: start;
	padding-block: 0.9rem;
	border-bottom: 1px solid var(--line-soft);
}

.side-item:last-child {
	border-bottom: 0;
	padding-bottom: 0;
}

/* The lead item carries artwork, so it takes a third track. Keyed off
   :first-child rather than :has(), which Safari below 15.4 does not support —
   and only the first item is ever given a thumbnail. */
.side-item:first-child {
	grid-template-columns: 1.6rem minmax(0, 1fr) 64px;
}

/* Outline numerals — the rank reads as a marker rather than as content, and
   stays quiet next to the headline it labels. */
.side-item__rank {
	font-family: var(--font-display);
	font-weight: 800;
	font-size: 1.5rem;
	line-height: 1;
	color: transparent;
	-webkit-text-stroke: 1px var(--ink-500);
	font-variant-numeric: tabular-nums;
	transition: -webkit-text-stroke-color var(--dur) var(--ease), color var(--dur) var(--ease);
}

/* The top rank fills in, in the desk colour. */
.side-item:first-child .side-item__rank {
	color: var(--chip-bg, var(--violet-400));
	-webkit-text-stroke: 0;
}

.side-item:hover .side-item__rank {
	-webkit-text-stroke-color: var(--chip-bg, var(--violet-400));
}

.side-item__body {
	display: flex;
	flex-direction: column;
	gap: 0.25rem;
	min-width: 0;
}

.side-item__title {
	font-size: 0.92rem;
	font-weight: 600;
	line-height: 1.32;
	color: var(--ink-100);
}

.side-item__title a:hover {
	color: var(--violet-300);
}

.side-item__time {
	font-size: var(--fs-micro);
	text-transform: uppercase;
	letter-spacing: 0.1em;
	color: var(--ink-500);
}

.side-item__media {
	display: block;
	overflow: hidden;
	border-radius: var(--radius);
	aspect-ratio: 1 / 1;
	background: var(--navy-750);
}

.side-item__media img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	transition: transform 0.6s var(--ease);
}

.side-item:hover .side-item__media img {
	transform: scale(1.07);
}

/* Widget-area defaults, so an added widget inherits the panel treatment. */
.widget {
	padding: 1.4rem 0 0;
	border-top: 2px solid var(--line-firm);
}

.widget ul li {
	padding-block: 0.45rem;
	border-bottom: 1px solid var(--line-soft);
	font-size: var(--fs-sm);
}

.widget ul li:last-child {
	border-bottom: 0;
}

/* ── 12. Static page ─────────────────────────────────────────────────────── */
.page-main {
	padding-block: clamp(2rem, 5vw, 3.5rem) var(--pad-section);
}

.page-header {
	padding-bottom: 1.5rem;
	margin-bottom: 1.75rem;
	border-bottom: 1px solid var(--line-firm);
}

.page-header__title {
	font-family: var(--font-display);
	font-weight: 800;
	text-transform: uppercase;
	letter-spacing: -0.018em;
	line-height: 0.98;
	font-size: clamp(2rem, 4.4vw, 3.2rem);
	color: var(--ink-100);
}

.page-header__updated {
	display: inline-block;
	margin-top: 0.75rem;
	font-size: var(--fs-micro);
	font-weight: 600;
	text-transform: uppercase;
	letter-spacing: 0.14em;
	color: var(--ink-500);
}

.page-hero {
	margin-bottom: 1.75rem;
}

.page-hero__img {
	width: 100%;
	border-radius: var(--radius);
}

/* ── 13. 404 ─────────────────────────────────────────────────────────────── */
.error-main {
	padding-block: clamp(2.5rem, 6vw, 4.5rem) var(--pad-section);
}

.error-page {
	position: relative;
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: 1.1rem;
	max-width: 62ch;
	padding-bottom: var(--pad-section);
}

/* The oversized ghost numeral behind the copy. Pushed off the right edge and
   clipped, so it reads as a graphic rather than as text to be read. */
.error-page__code {
	position: absolute;
	top: -0.28em;
	right: -0.08em;
	z-index: -1;
	font-family: var(--font-display);
	font-weight: 800;
	font-size: clamp(9rem, 26vw, 20rem);
	line-height: 0.8;
	letter-spacing: -0.05em;
	color: var(--violet-500);
	/* Lowered from 0.16: a dark violet numeral on white at that opacity read as
	   solid grey text competing with the headline, where on navy it was a faint
	   ghost. This keeps it as background texture. */
	opacity: 0.1;
	pointer-events: none;
	user-select: none;
}

.error-page__title {
	font-size: var(--fs-h1);
}

.error-page__desc {
	font-size: var(--fs-lead);
	color: var(--ink-300);
}

.error-page__actions {
	display: flex;
	gap: 0.75rem;
	flex-wrap: wrap;
	margin-top: 0.4rem;
}

.error-recent {
	padding-top: var(--gap-lg);
	border-top: 1px solid var(--line-firm);
}

/* ── 14. Utilities, motion, print ────────────────────────────────────────── */
.u-sr-only {
	position: absolute;
	width: 1px;
	height: 1px;
	padding: 0;
	margin: -1px;
	overflow: hidden;
	clip: rect(0, 0, 0, 0);
	white-space: nowrap;
	border: 0;
}

/* Stretches a link over its whole card. Used where the card cannot be an
   <a> because it already contains links (chips, bylines). */
.stretch-hit::after {
	content: "";
	position: absolute;
	inset: 0;
	z-index: 1;
}

/* Scroll reveal. The hidden initial state is gated on .js so a visitor
   without JavaScript never sees permanently invisible content. */
.js [data-reveal] {
	opacity: 0;
	transform: translateY(18px);
	transition: opacity 0.6s var(--ease), transform 0.6s var(--ease);
}

.js [data-reveal].is-visible {
	opacity: 1;
	transform: none;
}

@media (prefers-reduced-motion: reduce) {
	html {
		scroll-behavior: auto;
	}

	*,
	*::before,
	*::after {
		animation-duration: 0.001ms !important;
		animation-iteration-count: 1 !important;
		transition-duration: 0.001ms !important;
		scroll-behavior: auto !important;
	}

	.js [data-reveal] {
		opacity: 1;
		transform: none;
	}

	.tickerbar__track {
		animation: none;
	}
}

@media print {
	.site-header,
	.site-footer,
	.brief,
	.single-sidebar,
	.postrail,
	.related,
	.article-nav,
	.read-progress,
	.tickerbar {
		display: none !important;
	}

	body {
		background: #fff;
		color: #000;
	}

	.single-layout {
		grid-template-columns: 1fr;
	}

	/* The scrim and its artwork do not print, so the headline needs its ink
	   back. .phero--art .phero__title is more specific than a bare
	   .phero__title, so the light-theme white would otherwise win here and
	   print an invisible headline. */
	.phero__title,
	.phero--art .phero__title,
	.phero--art .phero__standfirst,
	.article-content {
		color: #000;
		text-shadow: none;
	}

	.phero__media,
	.phero__scrim {
		display: none !important;
	}
}
