@charset "UTF-8";
/*
Theme Name: InSightGY
Theme URI: https://insight.gy
Author: Janus Ideas
Author URI: https://insight.gy
Description: A custom newsroom theme for InSightGY, an independent Guyanese news and commentary publication. Built for long-form reading on mobile data: no framework, no jQuery, no icon font, two self-hosted variable typefaces.
Version: 1.6.0
Requires at least: 6.4
Tested up to: 7.0
Requires PHP: 7.4
License: GNU General Public License v2 or later
License URI: http://www.gnu.org/licenses/gpl-2.0.html
Text Domain: insightgy
Tags: news, blog, one-column, custom-logo, custom-menu, featured-images, editor-style, translation-ready, block-styles, wide-blocks, full-width-template, threaded-comments

InSightGY WordPress Theme, (C) 2026 Janus Ideas.
InSightGY is distributed under the terms of the GNU GPL version 2 or later.

This theme bundles the following third-party resources:

Archivo, Copyright (c) Omnibus-Type
License: SIL Open Font License, 1.1, https://scripts.sil.org/OFL
Source: https://fonts.google.com/specimen/Archivo

Newsreader, Copyright (c) Production Type
License: SIL Open Font License, 1.1, https://scripts.sil.org/OFL
Source: https://fonts.google.com/specimen/Newsreader

Tabler Icons, Copyright (c) 2020 Paweł Kuna
License: MIT, https://opensource.org/licenses/MIT
Source: https://tabler.io/icons

The InSightGY logo and all photography remain the property of InSightGY and
are not covered by the GPL grant above.
*/

/* =========================================================================
   CONTENTS
   01  Fonts
   02  Design tokens
   03  Reset and base
   04  Typography
   05  Layout primitives
   06  Components
   07  Masthead and navigation
   08  Front page sections
   09  Article
   10  Archive, search, 404
   11  Footer
   12  Forms
   13  Motion
   14  Print
   ========================================================================= */


/* ── 01  FONTS ─────────────────────────────────────────────────────────────
   Two families, both variable, both self-hosted, latin subset only.
   Archivo carries every headline and every piece of interface text.
   Newsreader carries article body copy: it is drawn for on-screen reading
   at long lengths, which is what this publication actually ships.
   ------------------------------------------------------------------------ */

@font-face {
	font-family: "Archivo";
	src: url("fonts/archivo-var.woff2") format("woff2-variations");
	font-weight: 400 900;
	font-style: normal;
	font-display: swap;
	unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6,
		U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193,
		U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
	font-family: "Newsreader";
	src: url("fonts/newsreader-var.woff2") format("woff2-variations");
	font-weight: 300 800;
	font-style: normal;
	font-display: swap;
	unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6,
		U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193,
		U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
	font-family: "Newsreader";
	src: url("fonts/newsreader-italic-var.woff2") format("woff2-variations");
	font-weight: 300 800;
	font-style: italic;
	font-display: swap;
	unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6,
		U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193,
		U+2212, U+2215, U+FEFF, U+FFFD;
}


/* ── 02  DESIGN TOKENS ─────────────────────────────────────────────────────
   Palette is extracted from the InSightGY logo, not invented:
   navy #002038 and amber #f8a830 are the two colours in the mark.

   Contrast, measured, on paper #fbfcfd:
     ink        #002038  16.18:1
     ink-soft   #3d5a72   7.04:1
     ink-meta   #54697f   5.52:1
     link       #8f5208   6.05:1
   Raw amber on paper is 1.92:1, so amber is NEVER text on a light surface.
   It is a rule, a chip fill and a focus ring. On amber, text is navy (8.42:1).

   Radius: zero, everywhere, with no exceptions. Structure is sharp.
   ------------------------------------------------------------------------ */

:root {
	color-scheme: light;

	/* brand */
	--brand-navy: #002038;
	--brand-amber: #f8a830;

	/* surfaces */
	--paper: #fbfcfd;
	--paper-2: #eef2f6;
	--paper-3: #e3e9ef;
	--surface-invert: #002038;

	/* ink */
	--ink: #002038;
	--ink-soft: #3d5a72;
	--ink-meta: #54697f;
	--ink-invert: #f2f6fa;
	--ink-invert-soft: #a9c0d3;

	/* accents */
	--accent: #f8a830;
	--accent-text: #8f5208;
	--accent-text-hover: #6f3f05;
	--on-accent: #002038;

	/* lines */
	--rule: #d5dee6;
	--rule-strong: #b3c2ce;

	/* the surface behind the framed page */
	--page-behind: #e6ebf0;
	--page-shadow: 0 0 0 1px rgba(0, 32, 56, .07), 0 24px 60px -30px rgba(0, 32, 56, .3);

	/* type */
	--font-ui: "Archivo", ui-sans-serif, system-ui, -apple-system,
		"Segoe UI", Roboto, Arial, sans-serif;
	--font-read: "Newsreader", ui-serif, Georgia, "Times New Roman", serif;

	/* measure */
	--wrap: 1320px;
	--wrap-narrow: 720px;
	--gutter: clamp(1rem, 4vw, 2.5rem);

	/*
	 * The grid.
	 *
	 * Twelve columns, one gutter value, used by every section on the site.
	 * Before this each block invented its own columns, so nothing shared an
	 * edge down the page: the lead was 1.85fr/1fr, the rail was four equal
	 * columns, the bento used named areas. Individually fine, collectively
	 * arbitrary. A single grid is what makes an editorial page feel composed
	 * rather than assembled.
	 */
	--grid-cols: 12;
	--grid-gap: 1.5rem;

	/*
	 * Spacing on an 8px base unit.
	 *
	 * Replaces free-form clamp() values. Fluid sizes still interpolate, but
	 * they start and end on the scale rather than at whatever looked right.
	 */
	--u: 8px;
	--s-1: calc(var(--u) * 1);    /* 8  */
	--s-2: calc(var(--u) * 2);    /* 16 */
	--s-3: calc(var(--u) * 3);    /* 24 */
	--s-4: calc(var(--u) * 4);    /* 32 */
	--s-6: calc(var(--u) * 6);    /* 48 */
	--s-8: calc(var(--u) * 8);    /* 64 */
	--s-12: calc(var(--u) * 12);  /* 96 */
	--s-16: calc(var(--u) * 16);  /* 128 */

	/* rhythm */
	--space-section: clamp(var(--s-6), 2rem + 6vw, var(--s-12));
	--space-block: clamp(var(--s-3), 1rem + 2.5vw, var(--s-6));

	/* elevation: tinted to the navy, never neutral black */
	--shadow-card: 0 1px 2px rgba(0, 32, 56, .06),
		0 12px 28px -12px rgba(0, 32, 56, .16);
	--shadow-bar: 0 1px 0 var(--rule), 0 8px 24px -16px rgba(0, 32, 56, .28);

	/*
	 * Motion tokens.
	 *
	 * Curves are taken from a known set, not hand-rolled: the browser's own
	 * ease-out is too weak to read as deliberate. ease-in is never used on UI,
	 * because it starts slow and delays the exact moment the user is watching.
	 *
	 *   ease-out     entering and exiting
	 *   ease-in-out  moving or morphing on screen
	 *   ease-drawer  the iOS drawer curve, for the mobile panel
	 *   linear       constant motion only (the ticker)
	 */
	--ease-out: cubic-bezier(.23, 1, .32, 1);
	--ease-in-out: cubic-bezier(.77, 0, .175, 1);
	--ease-drawer: cubic-bezier(.32, .72, 0, 1);
	--ease: var(--ease-out);

	/* UI motion stays under 300ms. Reveals are content, so they may run longer. */
	--dur-press: .12s;
	--dur-fast: .16s;
	--dur: .2s;
	--dur-menu: .18s;
	--dur-panel: .28s;
	--dur-slow: .42s;
	--dur-reveal: .5s;

	/* layers */
	--z-base: 1;
	--z-sticky: 100;
	--z-header: 200;
	--z-drawer: 300;
	--z-skip: 400;
}

html[data-theme="dark"] {
	color-scheme: dark;

	--paper: #041220;
	--paper-2: #0a1e30;
	--paper-3: #12293d;
	--surface-invert: #0a1e30;

	--ink: #e8eef4;
	--ink-soft: #a4b8c9;
	--ink-meta: #8ba3b8;
	--ink-invert: #e8eef4;
	--ink-invert-soft: #a4b8c9;

	--accent: #f8a830;
	--accent-text: #f8a830;
	--accent-text-hover: #ffc165;
	--on-accent: #002038;

	--rule: #17334a;
	--rule-strong: #24455f;

	--page-behind: #010a13;
	--page-shadow: 0 0 0 1px rgba(255, 255, 255, .06);

	--shadow-card: 0 1px 2px rgba(0, 0, 0, .4),
		0 12px 28px -12px rgba(0, 0, 0, .6);
	--shadow-bar: 0 1px 0 var(--rule), 0 8px 24px -16px rgba(0, 0, 0, .7);
}

@media (prefers-color-scheme: dark) {
	html:not([data-theme="light"]) {
		color-scheme: dark;

		--paper: #041220;
		--paper-2: #0a1e30;
		--paper-3: #12293d;
		--surface-invert: #0a1e30;

		--ink: #e8eef4;
		--ink-soft: #a4b8c9;
		--ink-meta: #8ba3b8;
		--ink-invert: #e8eef4;
		--ink-invert-soft: #a4b8c9;

		--accent: #f8a830;
		--accent-text: #f8a830;
		--accent-text-hover: #ffc165;
		--on-accent: #002038;

		--rule: #17334a;
		--rule-strong: #24455f;

		--page-behind: #010a13;
		--page-shadow: 0 0 0 1px rgba(255, 255, 255, .06);

		--shadow-card: 0 1px 2px rgba(0, 0, 0, .4),
			0 12px 28px -12px rgba(0, 0, 0, .6);
		--shadow-bar: 0 1px 0 var(--rule), 0 8px 24px -16px rgba(0, 0, 0, .7);
	}
}


/* ── 03  RESET AND BASE ───────────────────────────────────────────────────── */

*,
*::before,
*::after { box-sizing: border-box; }

* { margin: 0; }

html {
	-webkit-text-size-adjust: 100%;
	text-size-adjust: 100%;
	scroll-behavior: smooth;
	scroll-padding-top: 6rem;
}

@media (prefers-reduced-motion: reduce) {
	html { scroll-behavior: auto; }
}

body {
	background: var(--paper);
	color: var(--ink);
	font-family: var(--font-ui);
	font-size: 1rem;
	line-height: 1.5;
	font-synthesis-weight: none;
	-webkit-font-smoothing: antialiased;
	-moz-osx-font-smoothing: grayscale;
	text-rendering: optimizeLegibility;
	overflow-x: hidden;
}

/* ── THE PAGE FRAME ───────────────────────────────────────────────────────
   The whole page is a centred column rather than something that stretches to
   whatever width the browser happens to be. Constraining .wrap alone was not
   enough: the hero, the ticker, the opinion band and the footer all carry
   their own background and so ran edge to edge regardless.

   Framing the body instead contains everything at once, including those
   full-bleed bands, and the surface behind it reads as the page's margin.
   Set the width to "Full width" in the Customizer for the old behaviour.
   ------------------------------------------------------------------------ */

html {
	background: var(--page-behind);
}

body {
	max-width: var(--page-width, none);
	margin-inline: auto;
	box-shadow: var(--page-shadow, none);
}

/* No frame to draw at full width, and none on phones where it would waste
   horizontal space that the content needs. */
body.frame-full { max-width: none; box-shadow: none; }

@media (max-width: 900px) {
	body { max-width: none; box-shadow: none; }
}

img,
picture,
svg,
video {
	display: block;
	max-width: 100%;
	height: auto;
}

button,
input,
select,
textarea {
	font: inherit;
	color: inherit;
}

a { color: inherit; }

ul, ol { padding: 0; list-style: none; }

:where(a, button, input, select, textarea, summary, [tabindex]):focus-visible {
	outline: 2px solid var(--accent);
	outline-offset: 3px;
	border-radius: 0;
}

::selection {
	background: var(--accent);
	color: var(--on-accent);
}

.screen-reader-text {
	position: absolute !important;
	width: 1px;
	height: 1px;
	padding: 0;
	overflow: hidden;
	clip: rect(0 0 0 0);
	clip-path: inset(50%);
	white-space: nowrap;
	border: 0;
}

.skip-link {
	position: absolute;
	top: 0;
	left: var(--gutter);
	z-index: var(--z-skip);
	transform: translateY(-120%);
	padding: .75rem 1.25rem;
	background: var(--accent);
	color: var(--on-accent);
	font-weight: 700;
	font-size: .875rem;
	text-decoration: none;
	transition: transform var(--dur) var(--ease);
}

.skip-link:focus {
	transform: translateY(0);
}


/* ── 04  TYPOGRAPHY ───────────────────────────────────────────────────────── */

h1, h2, h3, h4, h5, h6 {
	font-family: var(--font-ui);
	font-weight: 800;
	line-height: 1.05;
	letter-spacing: -.025em;
	text-wrap: balance;
}

/* Display sizes. Fluid, planned against image sizes, never raw scale alone. */
.t-display {
	font-size: clamp(2.25rem, 1.1rem + 4.6vw, 4.5rem);
	line-height: .98;
	letter-spacing: var(--headline-tracking, -.035em);
	font-weight: var(--headline-weight, 800);
	text-transform: var(--headline-transform, none);
}

.t-xl {
	font-size: clamp(1.75rem, 1.1rem + 2.6vw, 3rem);
	line-height: 1.03;
	letter-spacing: var(--headline-tracking, -.03em);
	font-weight: var(--headline-weight, 800);
	text-transform: var(--headline-transform, none);
}

.t-lg {
	font-size: clamp(1.375rem, 1.1rem + 1.2vw, 1.9375rem);
	line-height: 1.1;
	letter-spacing: var(--headline-tracking, -.022em);
	font-weight: var(--headline-weight, 800);
	text-transform: var(--headline-transform, none);
}

.t-md {
	font-size: clamp(1.125rem, 1rem + .5vw, 1.375rem);
	line-height: 1.18;
	letter-spacing: var(--headline-tracking, -.015em);
	font-weight: var(--headline-weight, 800);
	text-transform: var(--headline-transform, none);
}

.t-sm {
	font-size: 1.0625rem;
	line-height: 1.25;
	letter-spacing: var(--headline-tracking, -.01em);
	font-weight: var(--headline-weight, 700);
	text-transform: var(--headline-transform, none);
}

/* Interface meta: dates, bylines, counts. */
.t-meta {
	font-family: var(--font-ui);
	font-size: .8125rem;
	font-weight: 500;
	line-height: 1.35;
	letter-spacing: .015em;
	color: var(--ink-meta);
	font-variant-numeric: tabular-nums;
}

.t-lede {
	font-family: var(--font-read);
	font-size: clamp(1.125rem, 1rem + .6vw, 1.4375rem);
	line-height: 1.5;
	font-weight: 400;
	color: var(--ink-soft);
	text-wrap: pretty;
}

.t-dek {
	font-family: var(--font-read);
	font-size: 1.0625rem;
	line-height: 1.5;
	color: var(--ink-soft);
	text-wrap: pretty;
}


/* ── 05  LAYOUT PRIMITIVES ────────────────────────────────────────────────── */

.wrap {
	width: 100%;
	max-width: var(--wrap);
	margin-inline: auto;
	padding-inline: var(--gutter);
}

/* ── THE GRID ─────────────────────────────────────────────────────────────
   One 12-column grid, shared by every section, so column edges line up all
   the way down the page. Below 768px everything collapses to a single
   column: twelve columns on a phone is a grid nobody can see.
   ------------------------------------------------------------------------ */

.grid {
	display: grid;
	grid-template-columns: repeat(var(--grid-cols), minmax(0, 1fr));
	gap: var(--grid-gap);
}

/*
 * Span helpers. Only the spans this design actually uses are defined, so an
 * unused class cannot quietly drift into the stylesheet.
 */
@media (min-width: 768px) {
	.col-3 { grid-column: span 3; }
	.col-4 { grid-column: span 4; }
	.col-5 { grid-column: span 5; }
	.col-6 { grid-column: span 6; }
	.col-7 { grid-column: span 7; }
	.col-8 { grid-column: span 8; }
	.col-9 { grid-column: span 9; }
	.col-12 { grid-column: 1 / -1; }
}

/* Single column below the md breakpoint, always. */
@media (max-width: 767px) {
	.grid > * { grid-column: 1 / -1; }
}

.wrap-narrow {
	width: 100%;
	max-width: var(--wrap-narrow);
	margin-inline: auto;
	padding-inline: var(--gutter);
}

.section {
	padding-block: var(--space-section);
}

.section + .section {
	padding-block-start: 0;
}

/*
 * Normalise the gap before the footer to exactly one space-section, whatever
 * the page happens to end with. Without this, a page ending in a .section
 * stacks that section's bottom padding on top of the footer's own offset and
 * opens a double gap, while a page ending in body copy gets almost none.
 */
main { padding-block-end: var(--space-section); }
main > .section:last-child { padding-block-end: 0; }

/* Section header. Deliberately has no uppercase eyebrow label:
   on a newspaper front the beat name IS the headline. */
.section-head {
	display: flex;
	flex-wrap: wrap;
	align-items: baseline;
	justify-content: space-between;
	gap: 1rem 1.5rem;
	margin-block-end: var(--space-block);
	padding-block-start: 1.25rem;
	border-block-start: 3px solid var(--accent);
}

.section-head__title {
	font-size: clamp(1.5rem, 1.1rem + 1.6vw, 2.25rem);
	letter-spacing: -.03em;
}

.section-head__link {
	font-size: .875rem;
	font-weight: 700;
	color: var(--accent-text);
	text-decoration: none;
	letter-spacing: .01em;
	border-block-end: 2px solid transparent;
	transition: border-color var(--dur) var(--ease), color var(--dur) var(--ease);
}

.section-head__link:hover {
	color: var(--accent-text-hover);
	border-block-end-color: currentColor;
}


/* ── 06  COMPONENTS ───────────────────────────────────────────────────────── */

/* Category chip. This is content, not decoration: it names the beat. */
.chip {
	display: inline-block;
	font-family: var(--font-ui);
	font-size: .6875rem;
	font-weight: 800;
	letter-spacing: .09em;
	text-transform: uppercase;
	text-decoration: none;
	padding: .3rem .5rem;
	background: var(--accent);
	color: var(--on-accent);
	transition: background var(--dur) var(--ease);
}

.chip:hover { background: #ffbe57; }

.chip--ghost {
	background: transparent;
	color: var(--accent-text);
	padding-inline: 0;
	border-block-end: 2px solid var(--accent);
}

.chip--ghost:hover {
	background: transparent;
	color: var(--accent-text-hover);
}

.chip--invert {
	background: var(--accent);
	color: #002038;
}

/* Buttons. Sharp, like everything else. */
.btn {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: .5rem;
	padding: .8125rem 1.375rem;
	font-family: var(--font-ui);
	font-size: .9375rem;
	font-weight: 700;
	letter-spacing: .005em;
	text-decoration: none;
	white-space: nowrap;
	border: 2px solid transparent;
	cursor: pointer;
	transition: background var(--dur) var(--ease), color var(--dur) var(--ease),
		border-color var(--dur) var(--ease), transform var(--dur-fast) var(--ease);
}

.btn:active { transform: translateY(1px); }

.btn--primary {
	background: var(--accent);
	color: var(--on-accent);
	border-color: var(--accent);
}

.btn--primary:hover { background: #ffbe57; border-color: #ffbe57; }

.btn--outline {
	background: transparent;
	color: var(--ink);
	border-color: var(--rule-strong);
}

.btn--outline:hover { border-color: var(--ink); }

.btn--on-navy {
	background: var(--accent);
	color: #002038;
	border-color: var(--accent);
}

.btn--on-navy:hover { background: #ffbe57; border-color: #ffbe57; }

/* Byline block */
.byline {
	display: flex;
	align-items: center;
	gap: .5rem;
	flex-wrap: wrap;
}

.byline__name {
	font-size: .8125rem;
	font-weight: 700;
	color: var(--ink-soft);
	text-decoration: none;
}

.byline__name:hover { color: var(--accent-text); }

.byline__sep {
	width: 3px;
	height: 3px;
	background: var(--rule-strong);
	flex: none;
}

/* Story card. The single repeated unit of the whole site. */
.story {
	display: grid;
	gap: .75rem;
	position: relative;
}

.story__media {
	position: relative;
	overflow: hidden;
	background: var(--paper-2);
	aspect-ratio: 16 / 10;
}

.story__media img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	transition: transform var(--dur-slow) var(--ease);
}

/*
 * Hover motion is gated on a real pointer. A tap on a touch screen fires a
 * synthetic hover that then sticks, so an ungated hover leaves a card zoomed
 * in until the reader taps somewhere else.
 */
@media (hover: hover) and (pointer: fine) {
	.story:hover .story__media img { transform: scale(1.04); }
}

.story__chip {
	position: absolute;
	inset-block-start: 0;
	inset-inline-start: 0;
	z-index: var(--z-base);
}

.story__title {
	text-wrap: balance;
}

.story__title a {
	text-decoration: none;
	background-image: linear-gradient(var(--accent), var(--accent));
	background-repeat: no-repeat;
	background-position: 0 100%;
	background-size: 0% 2px;
	transition: background-size var(--dur) var(--ease);
}

.story__title a:focus-visible { background-size: 100% 2px; }

@media (hover: hover) and (pointer: fine) {
	.story:hover .story__title a { background-size: 100% 2px; }
}

.story__foot {
	display: flex;
	align-items: center;
	gap: .5rem;
	flex-wrap: wrap;
}

/* Typographic fallback for posts with no featured image.
   A real design, not a fake photo and not a grey box. */
.story__media--none {
	display: grid;
	place-items: center;
	padding: 1.5rem;
	background:
		repeating-linear-gradient(
			-45deg,
			transparent 0 10px,
			rgba(0, 32, 56, .04) 10px 11px
		),
		var(--paper-2);
}

html[data-theme="dark"] .story__media--none,
html:not([data-theme="light"]) .story__media--none {
	background:
		repeating-linear-gradient(
			-45deg,
			transparent 0 10px,
			rgba(255, 255, 255, .045) 10px 11px
		),
		var(--paper-2);
}

.story__media--none span {
	font-family: var(--font-ui);
	font-size: clamp(.75rem, .6rem + .5vw, 1rem);
	font-weight: 800;
	letter-spacing: .14em;
	text-transform: uppercase;
	text-align: center;
	color: var(--ink-meta);
	border-block: 2px solid var(--accent);
	padding-block: .4rem;
}

/* Divided list of headlines, used in rails and indexes. */
.stack {
	display: grid;
}

.stack > * {
	padding-block: 1.125rem;
	border-block-start: 1px solid var(--rule);
}

.stack > *:first-child {
	padding-block-start: 0;
	border-block-start: 0;
}


/* ── 07  MASTHEAD AND NAVIGATION ──────────────────────────────────────────── */

/* ── Utility bar ───────────────────────────────────────────────────────────
   The thin strip above the masthead: the date on one side, the four service
   links on the other. Deliberately NOT sticky, so it scrolls away and leaves
   the masthead alone at the top of the viewport.

   It is the first thing dropped on a phone. Four service links are not what
   somebody on a bus came for, and every one of them is also in the footer and
   the drawer, so nothing is lost by hiding it.
   ------------------------------------------------------------------------ */

.utility {
	background: var(--paper-2);
	border-block-end: 1px solid var(--rule);
}

.utility__bar {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: var(--s-4);
	min-height: 40px;
}

/*
 * The nav has to be allowed to shrink. A flex item defaults to
 * min-width: auto, which means it refuses to go narrower than its content, so
 * a long list does not overflow its own box — it widens the whole page and
 * takes every other section with it.
 *
 * This location is meant for four service links, but a menu location accepts
 * whatever menu somebody assigns to it, and assigning the main menu here is
 * an obvious thing to try. So the list scrolls inside the bar instead, with
 * the same trailing mask the beat strip uses, and the page width is never at
 * the mercy of the menu.
 */
.utility__nav {
	min-width: 0;
	flex: 0 1 auto;
}

.utility__date {
	flex: 0 0 auto;
	display: inline-flex;
	align-items: center;
	gap: .4rem;
	margin: 0;

	font-family: var(--font-ui);
	font-size: .75rem;
	font-weight: 600;
	letter-spacing: .01em;
	color: var(--ink-meta);
	white-space: nowrap;
}

.utility__date svg {
	width: 15px;
	height: 15px;
	color: var(--accent-text);
}

.utility__list {
	display: flex;
	align-items: center;
	gap: var(--s-4);
	margin: 0;
	padding: 0;
	list-style: none;

	/* Overflow scrolls inside the bar rather than widening the document. */
	overflow-x: auto;
	scrollbar-width: none;
	-ms-overflow-style: none;
	scroll-snap-type: x proximity;
	padding-inline-end: 2rem;
	mask-image: linear-gradient(to right, #000 calc(100% - 2rem), transparent 100%);
	-webkit-mask-image: linear-gradient(to right, #000 calc(100% - 2rem), transparent 100%);
}

.utility__list::-webkit-scrollbar { display: none; }

.utility__list > * {
	flex: none;
	scroll-snap-align: end;
}

.utility__list a {
	display: inline-flex;
	align-items: center;
	gap: .4rem;

	padding-block: .5rem;

	font-family: var(--font-ui);
	font-size: .75rem;
	font-weight: 700;
	letter-spacing: .06em;
	text-transform: uppercase;
	text-decoration: none;
	color: var(--ink-soft);
	white-space: nowrap;

	transition: color var(--dur) var(--ease-out);
}

.utility__list svg {
	width: 16px;
	height: 16px;
	color: var(--accent-text);
	transition: color var(--dur) var(--ease-out);
}

.utility__list a:focus-visible {
	outline: 2px solid var(--accent);
	outline-offset: 2px;
}

@media (hover: hover) and (pointer: fine) {
	.utility__list a:hover { color: var(--ink); }
	.utility__list a:hover svg { color: var(--ink); }
}

/*
 * Below the beat-strip breakpoint the bar goes entirely. Squeezing four
 * uppercase labels and the date into 390px produces either a scroll nobody
 * discovers or type nobody can read.
 */
@media (max-width: 860px) {
	.utility { display: none; }
}

.masthead {
	position: sticky;
	inset-block-start: 0;
	z-index: var(--z-header);
	background: color-mix(in srgb, var(--paper) 88%, transparent);
	backdrop-filter: saturate(180%) blur(14px);
	-webkit-backdrop-filter: saturate(180%) blur(14px);
	border-block-end: 1px solid var(--rule);
	transition: box-shadow var(--dur) var(--ease);
}

@supports not (backdrop-filter: blur(1px)) {
	.masthead { background: var(--paper); }
}

@media (prefers-reduced-transparency: reduce) {
	.masthead {
		background: var(--paper);
		backdrop-filter: none;
		-webkit-backdrop-filter: none;
	}
}

.masthead.is-stuck { box-shadow: var(--shadow-bar); }

/* ── Header layouts ────────────────────────────────────────────────────────
   Four arrangements of the same three parts: brand, navigation, tools.

   The one rule none of them breaks is that .masthead__bar stays 68px.
   main.js measures that row to decide how many nav items fit before the rest
   move into the More menu, so a row whose height varied by layout would turn
   that measurement into a guess and the nav would start wrapping again.
   Layouts that want the brand somewhere else put it on its own row above.
   ------------------------------------------------------------------------ */

.masthead__brandrow {
	display: flex;
	align-items: center;
	justify-content: center;
	padding-block: var(--s-3);
	border-block-end: 1px solid var(--rule);
}

.masthead--stacked .masthead__brandrow {
	justify-content: flex-start;
}

/*
 * Both copies of the brand exist in the markup; only one is ever shown. Above
 * the breakpoint the row above wins, below it the bar does. display:none
 * rather than visibility, so the hidden copy takes no space and contributes
 * no duplicate link to the accessibility tree.
 */
@media (min-width: 861px) {
	.masthead--centred .masthead__bar > .brand,
	.masthead--stacked .masthead__bar > .brand {
		display: none;
	}
}

/* Centred: brand above, navigation centred beneath it. */
.masthead--centred .masthead__bar { justify-content: center; }
.masthead--centred .nav-primary { flex: 0 1 auto; }

.masthead--centred .masthead__tools,
.masthead--stacked .masthead__tools {
	position: absolute;
	inset-inline-end: var(--grid-gap);
	inset-block-start: 0;
	height: 100%;
}

.masthead--centred,
.masthead--stacked { position: relative; }

/*
 * With the tools lifted out of the flow the nav would otherwise run under
 * them, so the row keeps a matching reserve on that side.
 */
.masthead--centred .masthead__bar,
.masthead--stacked .masthead__bar {
	padding-inline-end: 7rem;
}

/* Stacked: brand left on its own line, navigation left beneath it. */
.masthead--stacked .masthead__bar { justify-content: flex-start; }

/* Compact: one shorter row and a smaller lockup. */
.masthead--compact .masthead__bar { height: 56px; }
.masthead--compact .brand img,
.masthead--compact .brand__mark { max-height: 28px; }
.masthead--compact .brand__word { font-size: 1.125rem; }

/*
 * Below the beat-strip breakpoint every layout collapses to the same thing:
 * brand and the menu button on one row. Four header arrangements on a 390px
 * screen is three arrangements nobody asked for.
 */
@media (max-width: 860px) {
	.masthead__brandrow { display: none; }

	.masthead--centred .masthead__bar,
	.masthead--stacked .masthead__bar {
		justify-content: space-between;
		padding-inline-end: 0;
	}

	.masthead--centred .masthead__tools,
	.masthead--stacked .masthead__tools {
		position: static;
		height: auto;
	}
}

.masthead__bar {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 1rem;
	height: 68px;
}

.brand {
	display: flex;
	align-items: center;
	gap: .625rem;
	text-decoration: none;
	flex: none;
}

/*
 * the_custom_logo() emits its own <a class="custom-logo-link"><img
 * class="custom-logo"> and does NOT nest inside .brand, so it has to be
 * sized on its own selector. Scoping it under .brand silently does nothing.
 */
.brand img { height: 34px; width: auto; }
.brand__mark { height: 30px; width: auto; }

.masthead__bar .custom-logo-link,
.footer__brand .custom-logo-link {
	display: block;
	flex: none;
	line-height: 0;
}

/*
 * Hard caps, not a preferred size. The uploaded lockup is 2559x439, which at
 * an unconstrained 40px tall renders about 233px wide and was itself a large
 * part of why the nav ran out of room. Width is capped first.
 */
.masthead__bar .custom-logo {
	height: auto;
	max-height: 36px;
	max-width: min(200px, 38vw);
	width: auto;
	object-fit: contain;
	object-position: left center;
}

/*
 * Dark mode logo.
 *
 * WordPress has one custom_logo setting and no concept of a dark variant, so
 * a navy wordmark uploaded there disappears against the navy dark surface.
 * The theme renders both images and swaps them with CSS. When no dark logo has
 * been uploaded, insightgy_brand() falls back to the mark plus the CSS
 * wordmark instead, which is already theme-aware.
 */
.brand-logo__dark { display: none; }

html[data-theme="dark"] .brand-logo__light { display: none; }
html[data-theme="dark"] .brand-logo__dark { display: block; }

@media (prefers-color-scheme: dark) {
	html:not([data-theme="light"]) .brand-logo__light { display: none; }
	html:not([data-theme="light"]) .brand-logo__dark { display: block; }
	html[data-theme="light"] .brand-logo__light { display: block; }
	html[data-theme="light"] .brand-logo__dark { display: none; }
}

.footer__brand .custom-logo {
	height: 46px;
	width: auto;
	max-width: 280px;
	object-fit: contain;
	object-position: left center;
}

.drawer__top .custom-logo { height: 34px; }

/*
 * The wordmark is a single colour, because the real logo is: in the lockup
 * "InSightGY" is entirely navy and the amber lives only in the ring around
 * the Guyana outline. Splitting the word into two colours would invent a
 * brand detail that does not exist.
 */
.brand__word {
	font-family: var(--font-ui);
	font-size: 1.3125rem;
	font-weight: 800;
	letter-spacing: -.03em;
	color: var(--ink);
}

/* Primary navigation. One line at desktop, always. */
/*
 * Primary navigation.
 *
 * This nav previously assumed six items or fewer and set white-space: nowrap
 * with no overflow handling. The live site put twelve items in it, the list
 * overflowed its flex track, and it painted straight over the logo and the
 * icon buttons. A comment in the README is not a constraint, so the nav is now
 * built to survive any number of items:
 *
 *   base state (and the no-JS state)  scrolls horizontally behind a mask
 *   enhanced state (.is-priority)     overflow collapses into a More menu
 *
 * The base state alone makes overlap structurally impossible, so the worst
 * case if the script never runs is a scrollable row, never a broken header.
 */
.nav-primary {
	display: none;

	/*
	 * flex-basis MUST be 0, not auto.
	 *
	 * With `1 1 auto` the nav's width is derived from its own content, while
	 * the priority+ pass derives the content from the width. That is circular:
	 * moving items out shrinks the nav, which changes what fits, which fires
	 * the ResizeObserver again, and the layout oscillates until it collapses
	 * back to showing everything. `1 1 0` makes the nav simply take whatever
	 * space brand and tools leave behind, so the measurement is stable.
	 */
	flex: 1 1 0;
	min-width: 0;
	overflow: hidden;      /* the hard stop that prevents any overlap */
}

@media (min-width: 1024px) {
	.nav-primary { display: block; }
}

.nav-primary > ul {
	display: flex;
	align-items: center;
	gap: clamp(.5rem, .2rem + 1vw, 1.5rem);
	margin: 0;
	white-space: nowrap;
	overflow-x: auto;
	scrollbar-width: none;
	-ms-overflow-style: none;
	mask-image: linear-gradient(to right, #000 calc(100% - 2rem), transparent 100%);
	-webkit-mask-image: linear-gradient(to right, #000 calc(100% - 2rem), transparent 100%);
}

.nav-primary > ul::-webkit-scrollbar { display: none; }

/*
 * Once JS has measured and moved the overflow, nothing needs to scroll, and
 * the clipping must be released or it cuts off the More panel: an absolutely
 * positioned child is still clipped by an ancestor's overflow:hidden. The
 * priority+ pass guarantees the items fit, so nothing can spill here.
 */
.nav-primary.is-priority { overflow: visible; }

.nav-primary.is-priority > ul {
	overflow: visible;
	justify-content: center;
	mask-image: none;
	-webkit-mask-image: none;
}

.nav-primary a {
	display: block;
	padding: .375rem 0;
	font-size: .875rem;
	font-weight: 600;
	letter-spacing: -.005em;
	text-decoration: none;
	color: var(--ink);
	border-block-end: 2px solid transparent;
	transition: color var(--dur) var(--ease-out),
		border-color var(--dur) var(--ease-out);
}

.nav-primary a:hover,
.nav-primary .current-menu-item > a,
.nav-primary .current-menu-parent > a,
.nav-primary .current-menu-ancestor > a {
	color: var(--accent-text);
	border-block-end-color: var(--accent);
}

/* ── The More menu ──────────────────────────────────────────────────────── */

.nav-more { position: relative; flex: none; }
.nav-more[hidden] { display: none; }

.nav-more__btn {
	display: inline-flex;
	align-items: center;
	gap: .25rem;
	padding: .375rem 0;
	background: none;
	border: 0;
	border-block-end: 2px solid transparent;
	font-family: var(--font-ui);
	font-size: .875rem;
	font-weight: 600;
	letter-spacing: -.005em;
	color: var(--ink);
	cursor: pointer;
	transition: color var(--dur) var(--ease-out),
		border-color var(--dur) var(--ease-out);
}

.nav-more__btn:hover,
.nav-more.is-open .nav-more__btn { color: var(--accent-text); }
.nav-more.is-open .nav-more__btn { border-block-end-color: var(--accent); }

.nav-more__btn svg {
	width: 14px;
	height: 14px;
	transition: transform var(--dur-menu) var(--ease-out);
}

.nav-more.is-open .nav-more__btn svg { transform: rotate(180deg); }

.nav-more__panel {
	position: absolute;
	inset-block-start: calc(100% + .75rem);
	inset-inline-end: 0;
	z-index: var(--z-header);
	min-width: 15rem;
	max-height: min(70vh, 34rem);
	overflow-y: auto;
	padding: .5rem 0;
	background: var(--paper);
	border: 1px solid var(--rule);
	box-shadow: var(--shadow-card);

	/*
	 * Anchored to its trigger, so it grows from the trigger corner rather than
	 * from its own centre. Never scale(0): nothing in the real world appears
	 * out of nothing.
	 */
	transform-origin: top right;
	opacity: 0;
	transform: translateY(-4px) scale(.97);
	visibility: hidden;
	transition: opacity var(--dur-menu) var(--ease-out),
		transform var(--dur-menu) var(--ease-out),
		visibility 0s linear var(--dur-menu);
}

.nav-more.is-open .nav-more__panel {
	opacity: 1;
	transform: none;
	visibility: visible;
	transition: opacity var(--dur-menu) var(--ease-out),
		transform var(--dur-menu) var(--ease-out),
		visibility 0s;
}

.nav-more__panel ul { display: grid; }

.nav-more__panel a {
	display: block;
	padding: .5625rem 1rem;
	font-size: .9375rem;
	font-weight: 600;
	letter-spacing: -.01em;
	white-space: nowrap;
	border-block-end: 0;
	border-inline-start: 3px solid transparent;
	transition: background var(--dur-fast) var(--ease-out),
		color var(--dur-fast) var(--ease-out),
		border-color var(--dur-fast) var(--ease-out);
}

.nav-more__panel a:hover,
.nav-more__panel .current-menu-item > a {
	background: var(--paper-2);
	color: var(--accent-text);
	border-inline-start-color: var(--accent);
}

/* Items settle in sequence rather than all at once. */
@media (prefers-reduced-motion: no-preference) {
	.nav-more__panel li {
		opacity: 0;
		transform: translateX(4px);
	}

	.nav-more.is-open .nav-more__panel li {
		opacity: 1;
		transform: none;
		transition: opacity var(--dur-menu) var(--ease-out),
			transform var(--dur-menu) var(--ease-out);
		transition-delay: calc(var(--i, 0) * 26ms);
	}
}

.masthead__tools {
	display: flex;
	align-items: center;
	gap: .25rem;
	flex: none;
}

.icon-btn {
	display: inline-grid;
	place-items: center;
	width: 40px;
	height: 40px;
	padding: 0;
	background: transparent;
	border: 0;
	color: var(--ink);
	cursor: pointer;
	transition: background var(--dur) var(--ease), color var(--dur) var(--ease);
}

.icon-btn:hover { background: var(--paper-2); color: var(--accent-text); }
.icon-btn:active { transform: translateY(1px); }
.icon-btn svg { width: 20px; height: 20px; }

@media (min-width: 1024px) {
	.icon-btn--menu { display: none; }
}

/* Theme toggle shows the icon for the mode it switches TO. */
.theme-toggle .t-sun { display: none; }
html[data-theme="dark"] .theme-toggle .t-sun { display: block; }
html[data-theme="dark"] .theme-toggle .t-moon { display: none; }

@media (prefers-color-scheme: dark) {
	html:not([data-theme="light"]) .theme-toggle .t-sun { display: block; }
	html:not([data-theme="light"]) .theme-toggle .t-moon { display: none; }
	html[data-theme="light"] .theme-toggle .t-sun { display: none; }
	html[data-theme="light"] .theme-toggle .t-moon { display: block; }
}

/* Beat strip: the 12 sections, scrollable on small screens. */
.beats {
	border-block-end: 1px solid var(--rule);
	background: var(--paper);
}

/*
 * Twelve beats will not fit on one line at any realistic width, so the strip
 * scrolls. The mask fades the trailing edge so it is visible that there is
 * more to the right, rather than the list simply appearing to be cut off.
 */
.beats__scroll {
	display: flex;
	gap: 1.25rem;
	overflow-x: auto;
	scrollbar-width: none;
	-ms-overflow-style: none;
	padding-block: .625rem;
	padding-inline-end: 2.5rem;
	scroll-snap-type: x proximity;
	mask-image: linear-gradient(to right, #000 calc(100% - 2.5rem), transparent 100%);
	-webkit-mask-image: linear-gradient(to right, #000 calc(100% - 2.5rem), transparent 100%);
}

.beats__scroll::-webkit-scrollbar { display: none; }

.beats__scroll a {
	flex: none;
	scroll-snap-align: start;
	font-size: .75rem;
	font-weight: 700;
	letter-spacing: .07em;
	text-transform: uppercase;
	text-decoration: none;
	color: var(--ink-meta);
	white-space: nowrap;
	transition: color var(--dur) var(--ease);
}

.beats__scroll a:hover,
.beats__scroll a[aria-current="page"] { color: var(--accent-text); }

/* Mobile drawer */
.drawer {
	position: fixed;
	inset: 0;
	z-index: var(--z-drawer);
	display: grid;
	grid-template-rows: auto 1fr;
	background: var(--paper);
	transform: translateX(100%);
	visibility: hidden;
	transition: transform var(--dur-slow) var(--ease),
		visibility 0s linear var(--dur-slow);
}

.drawer.is-open {
	transform: translateX(0);
	visibility: visible;
	transition: transform var(--dur-slow) var(--ease), visibility 0s;
}

.drawer__top {
	display: flex;
	align-items: center;
	justify-content: space-between;
	height: 68px;
	border-block-end: 1px solid var(--rule);
}

.drawer__body {
	overflow-y: auto;
	padding-block: 1.5rem 3rem;
}

.drawer__body ul { display: grid; }

.drawer__body a {
	display: block;
	padding-block: .875rem;
	border-block-end: 1px solid var(--rule);
	font-family: var(--font-ui);
	font-size: 1.375rem;
	font-weight: 700;
	letter-spacing: -.02em;
	text-decoration: none;
	color: var(--ink);
}

.drawer__body a:hover { color: var(--accent-text); }

.drawer__search { margin-block-start: 2rem; }

/*
 * The service links inside the drawer. Set apart from the section list above
 * with a rule and smaller type, because they answer a different question:
 * the list above is "what do you cover", this is "how do I reach you".
 */
.drawer__services {
	margin-block-start: 2rem;
	padding-block-start: 1.5rem;
	border-block-start: 1px solid var(--rule);
}

.drawer__services ul {
	display: grid;
	gap: .25rem;
	margin: 0;
	padding: 0;
	list-style: none;
}

.drawer__services a {
	display: flex;
	align-items: center;
	gap: .625rem;

	padding-block: .625rem;

	font-family: var(--font-ui);
	font-size: .8125rem;
	font-weight: 700;
	letter-spacing: .06em;
	text-transform: uppercase;
	text-decoration: none;
	color: var(--ink-soft);
}

.drawer__services svg {
	width: 18px;
	height: 18px;
	color: var(--accent-text);
}

.drawer__services a:focus-visible {
	outline: 2px solid var(--accent);
	outline-offset: 2px;
}

body.is-locked { overflow: hidden; }


/* ── 08  FRONT PAGE SECTIONS ──────────────────────────────────────────────
   Six distinct layout families, no family used twice:
     A  lead      asymmetric split, one dominant story plus a stacked rail
     B  rail      horizontal scroll-snap cards
     C  band      full-bleed navy pull-quote block (the one inverted block)
     D  bento     asymmetric grid, cell count always equals item count
     E  index     three grouped clusters of beats
     F  media     wide art beside an episode list
   ------------------------------------------------------------------------ */

/* TICKER ------------------------------------------------------------------
   The only continuously-moving element on the site. On a news front a moving
   strip communicates recency, which is information rather than decoration.
   Implemented as a CSS animation so it keeps running smoothly while the page
   is still loading, which is precisely when a JS loop would stutter.
   ------------------------------------------------------------------------ */

.ticker {
	border-block-end: 1px solid var(--rule);
	background: var(--paper-2);
	overflow: hidden;
}

.ticker__bar {
	display: flex;
	align-items: center;
	gap: .875rem;
	height: 44px;
}

.ticker__label {
	display: inline-flex;
	align-items: center;
	gap: .375rem;
	flex: none;
	padding: .25rem .5rem;
	background: var(--accent);
	color: var(--on-accent);
	font-size: .6875rem;
	font-weight: 800;
	letter-spacing: .09em;
	text-transform: uppercase;
}

.ticker__label svg { width: 13px; height: 13px; }

.ticker__window {
	position: relative;
	flex: 1 1 0;
	min-width: 0;
	overflow: hidden;
	display: flex;
	mask-image: linear-gradient(to right, transparent 0, #000 1.5rem, #000 calc(100% - 1.5rem), transparent 100%);
	-webkit-mask-image: linear-gradient(to right, transparent 0, #000 1.5rem, #000 calc(100% - 1.5rem), transparent 100%);
}

.ticker__track {
	display: flex;
	align-items: center;
	gap: 2.5rem;
	flex: none;
	padding-inline-end: 2.5rem;
	white-space: nowrap;
	will-change: transform;
}

.ticker__track a {
	display: inline-flex;
	align-items: baseline;
	gap: .5rem;
	font-size: .875rem;
	font-weight: 600;
	letter-spacing: -.005em;
	text-decoration: none;
	color: var(--ink);
	transition: color var(--dur-fast) var(--ease-out);
}

.ticker__track time {
	font-size: .6875rem;
	font-weight: 700;
	letter-spacing: .06em;
	text-transform: uppercase;
	color: var(--accent-text);
	flex: none;
}

.ticker__toggle {
	display: inline-grid;
	place-items: center;
	width: 30px;
	height: 30px;
	flex: none;
	padding: 0;
	background: transparent;
	border: 1px solid var(--rule-strong);
	color: var(--ink-meta);
	cursor: pointer;
	transition: color var(--dur-fast) var(--ease-out),
		border-color var(--dur-fast) var(--ease-out);
}

.ticker__toggle svg { width: 13px; height: 13px; }
.ticker__toggle-play { display: none; }
.ticker[data-paused="true"] .ticker__toggle-play { display: block; }
.ticker[data-paused="true"] .ticker__toggle-pause { display: none; }

@media (hover: hover) and (pointer: fine) {
	.ticker__track a:hover { color: var(--accent-text); }
	.ticker__toggle:hover { color: var(--ink); border-color: var(--ink); }
}

@media (prefers-reduced-motion: no-preference) {
	.ticker__track {
		/*
		 * Exactly -50% of the two-copy row, so the duplicate has landed
		 * precisely where the original started and the loop has no seam.
		 * Duration is set from the measured width by ticker.js, keeping the
		 * reading speed constant no matter how many headlines there are.
		 */
		animation: insightgy-ticker var(--ticker-duration, 40s) linear infinite;
	}

	.ticker[data-paused="true"] .ticker__track,
	.ticker[data-hold] .ticker__track,
	.ticker[data-offscreen] .ticker__track {
		animation-play-state: paused;
	}
}

@keyframes insightgy-ticker {
	from { transform: translate3d(0, 0, 0); }
	to   { transform: translate3d(-100%, 0, 0); }
}

/*
 * Reduced motion: nothing moves. The strip becomes an ordinary scrollable
 * row, and the duplicate copy is removed so it is not read twice.
 */
@media (prefers-reduced-motion: reduce) {
	.ticker__window { overflow-x: auto; scrollbar-width: none; }
	.ticker__window::-webkit-scrollbar { display: none; }
	.ticker__track[aria-hidden="true"] { display: none; }
	.ticker__toggle { display: none; }
}

/* HERO SLIDER -------------------------------------------------------------
   A scroll-snap track, not a carousel library. Touch swipe, momentum and
   snapping are the browser's; the script only drives buttons, dots and
   autoplay. The scrim is structural, not decoration: it is what keeps the
   headline at WCAG AA over an arbitrary press photograph.
   ------------------------------------------------------------------------ */

/*
 * No bottom margin: the lead block directly below already carries its own top
 * padding, and stacking the two opens a dead band of paper under the hero.
 */
.hero {
	position: relative;
	background: var(--surface-invert);
}

.hero__viewport {
	display: grid;
	grid-auto-flow: column;
	grid-auto-columns: 100%;
	overflow-x: auto;
	overscroll-behavior-x: contain;
	scroll-snap-type: x mandatory;
	scrollbar-width: none;
	-ms-overflow-style: none;
}

.hero__viewport::-webkit-scrollbar { display: none; }

.hero__slide {
	position: relative;
	scroll-snap-align: start;
	scroll-snap-stop: always;
	min-width: 0;
	display: grid;
	grid-template-areas: "stack";
	block-size: clamp(24rem, 20rem + 26vw, 40rem);
	isolation: isolate;
}

.hero__media,
.hero__body { grid-area: stack; min-width: 0; }

.hero__media { position: relative; overflow: hidden; }

.hero__img {
	width: 100%;
	height: 100%;
	object-fit: cover;
}

.hero__img--none {
	background:
		repeating-linear-gradient(-45deg, transparent 0 12px, rgba(255, 255, 255, .05) 12px 13px),
		var(--surface-invert);
}

/*
 * Two stops are not enough: a linear ramp leaves the middle of the image too
 * bright behind the dek. This eases the ramp so the text band is reliably
 * dark while the top of the photograph stays legible.
 */
.hero__scrim {
	position: absolute;
	inset: 0;
	background: linear-gradient(
		to top,
		rgba(0, 12, 22, .92) 0%,
		rgba(0, 12, 22, .82) 22%,
		rgba(0, 12, 22, .55) 45%,
		rgba(0, 12, 22, .25) 70%,
		rgba(0, 12, 22, .12) 100%
	);
}

.hero__body {
	position: relative;
	z-index: var(--z-base);
	display: flex;
	align-items: flex-end;
	padding-block-end: clamp(4.5rem, 3rem + 6vw, 7rem);
}

.hero__inner { max-width: 62rem; }

.hero__chip { margin-block-end: 1rem; }

.hero__title {
	font-size: clamp(1.75rem, 1.1rem + 3.2vw, 3.75rem);
	line-height: 1;
	letter-spacing: -.035em;
	color: #fff;
	max-width: 20ch;
}

.hero__title a {
	text-decoration: none;
	background-image: linear-gradient(var(--accent), var(--accent));
	background-repeat: no-repeat;
	background-position: 0 100%;
	background-size: 0% 3px;
	transition: background-size var(--dur-panel) var(--ease-out);
}

.hero__dek {
	margin-block-start: 1rem;
	font-family: var(--font-read);
	font-size: clamp(1rem, .95rem + .4vw, 1.1875rem);
	line-height: 1.5;
	color: rgba(255, 255, 255, .88);
	max-width: 52ch;
}

.hero__meta { margin-block-start: 1.25rem; }
.hero__meta .t-meta,
.hero__meta .byline__name { color: rgba(255, 255, 255, .82); }
.hero__meta .byline__sep { background: rgba(255, 255, 255, .5); }

/* Controls */
.hero__controls {
	position: absolute;
	inset-inline: 0;
	inset-block-end: clamp(1rem, .5rem + 1.5vw, 1.75rem);
	z-index: calc(var(--z-base) + 1);
	display: flex;
	align-items: center;
	gap: .5rem;
}

.hero__arrow,
.hero__play {
	display: inline-grid;
	place-items: center;
	width: 40px;
	height: 40px;
	flex: none;
	padding: 0;
	background: rgba(0, 12, 22, .55);
	color: #fff;
	border: 1px solid rgba(255, 255, 255, .3);
	cursor: pointer;
	transition: background var(--dur) var(--ease-out),
		border-color var(--dur) var(--ease-out),
		transform var(--dur-press) var(--ease-out);
}

.hero__arrow svg,
.hero__play svg { width: 18px; height: 18px; }

.hero__arrow:active,
.hero__play:active { transform: translateY(1px); }

.hero__play { margin-inline-start: auto; }

.hero__dots {
	display: flex;
	align-items: center;
	gap: .375rem;
}

.hero__dot {
	width: 28px;
	height: 4px;
	padding: 0;
	border: 0;
	background: rgba(255, 255, 255, .38);
	cursor: pointer;
	transition: background var(--dur) var(--ease-out),
		width var(--dur-panel) var(--ease-out);
}

.hero__dot[aria-selected="true"] { background: var(--accent); width: 44px; }

.hero__play-play { display: none; }
.hero[data-paused="true"] .hero__play-play { display: block; }
.hero[data-paused="true"] .hero__play-pause { display: none; }

@media (hover: hover) and (pointer: fine) {
	.hero__arrow:hover,
	.hero__play:hover {
		background: var(--accent);
		color: #002038;
		border-color: var(--accent);
	}

	.hero__dot:hover { background: rgba(255, 255, 255, .7); }
	.hero__slide:hover .hero__title a { background-size: 100% 3px; }
}

.hero__title a:focus-visible { background-size: 100% 3px; }

/*
 * Slide content settles in after the slide arrives rather than all at once.
 * Driven by a class the script sets, so it replays on every slide change.
 */
@media (prefers-reduced-motion: no-preference) {
	.hero__slide .hero__chip,
	.hero__slide .hero__title,
	.hero__slide .hero__dek,
	.hero__slide .hero__meta {
		opacity: 0;
		transform: translateY(12px);
	}

	.hero__slide.is-active .hero__chip,
	.hero__slide.is-active .hero__title,
	.hero__slide.is-active .hero__dek,
	.hero__slide.is-active .hero__meta {
		opacity: 1;
		transform: none;
		transition: opacity var(--dur-slow) var(--ease-out),
			transform var(--dur-slow) var(--ease-out);
	}

	.hero__slide.is-active .hero__chip  { transition-delay: 40ms; }
	.hero__slide.is-active .hero__title { transition-delay: 100ms; }
	.hero__slide.is-active .hero__dek   { transition-delay: 160ms; }
	.hero__slide.is-active .hero__meta  { transition-delay: 220ms; }
}

/* Without JS nothing sets .is-active, so content must never stay hidden. */
.no-js .hero__slide .hero__chip,
.no-js .hero__slide .hero__title,
.no-js .hero__slide .hero__dek,
.no-js .hero__slide .hero__meta { opacity: 1; transform: none; }

@media (prefers-reduced-motion: reduce) {
	.hero__viewport { scroll-behavior: auto; }
}

/* A. THE NEWS WELL --------------------------------------------------------
   The front page opens the way a broadsheet does: one story is unambiguously
   the lead, a secondary column carries the rest of the day, and a narrow rail
   ranks what else is being read. All three sit on the same 12-column grid, so
   their edges align with every section below them.

     cols 1-7   lead story, large image, largest headline on the site
     cols 8-10  also today, stacked headlines divided by hairlines
     cols 11-12 most read, ranked

   The hierarchy is doing real work: a reader should be able to tell in one
   glance which story the desk thinks matters most. Three equal columns cannot
   say that.
   ------------------------------------------------------------------------ */

.lead {
	padding-block: var(--s-4) 0;
}

.lead__grid {
	display: grid;
	grid-template-columns: repeat(var(--grid-cols), minmax(0, 1fr));
	gap: var(--s-4) var(--grid-gap);
	align-items: start;
}

.lead__main { grid-column: 1 / -1; }
.lead__side { grid-column: 1 / -1; }
.lead__rail { grid-column: 1 / -1; }

@media (min-width: 900px) {
	.lead__main { grid-column: span 7; }
	.lead__side { grid-column: span 3; }
	.lead__rail { grid-column: span 2; }
}

/* Between md and the full well, drop the ranked rail under the other two. */
@media (min-width: 768px) and (max-width: 899px) {
	.lead__main { grid-column: span 8; }
	.lead__side { grid-column: span 4; }
}

.lead__main .story__media { aspect-ratio: 16 / 9; }

.lead__main .story__title {
	font-size: clamp(2rem, 1.1rem + 3.4vw, 3.625rem);
	line-height: .99;
	letter-spacing: -.035em;
	font-weight: 800;
}

.lead__side,
.lead__rail {
	display: grid;
	align-content: start;
	gap: 0;
	border-block-start: 3px solid var(--accent);
	padding-block-start: var(--s-2);
}

.lead__side-title,
.lead__rail-title {
	font-size: 1.125rem;
	letter-spacing: -.02em;
	margin-block-end: var(--s-1);
}

.lead__side .story {
	gap: var(--s-1);
	padding-block: var(--s-2);
	border-block-start: 1px solid var(--rule);
}

.lead__side .story:first-of-type { border-block-start: 0; }
.lead__side .story:last-child { padding-block-end: 0; }

/* Ranked rail: the number carries the hierarchy, so the type can stay small. */
.lead__rail ol { counter-reset: rank; display: grid; }

.lead__rail li {
	counter-increment: rank;
	display: grid;
	grid-template-columns: var(--s-3) minmax(0, 1fr);
	gap: var(--s-1);
	padding-block: var(--s-2);
	border-block-start: 1px solid var(--rule);
}

.lead__rail li:first-child { border-block-start: 0; }

.lead__rail li::before {
	content: counter(rank);
	font-family: var(--font-ui);
	font-size: 1.125rem;
	font-weight: 800;
	line-height: 1.1;
	color: var(--accent);
	font-variant-numeric: tabular-nums;
}

.lead__rail a {
	font-family: var(--font-ui);
	font-size: .9375rem;
	font-weight: 700;
	line-height: 1.25;
	letter-spacing: -.012em;
	color: var(--ink);
	text-decoration: none;
}

@media (hover: hover) and (pointer: fine) {
	.lead__rail a:hover { color: var(--accent-text); }
}

/* B. RAIL ---------------------------------------------------------------- */
.rail {
	display: grid;
	grid-auto-flow: column;
	grid-auto-columns: minmax(78vw, 1fr);
	gap: 1.5rem;
	overflow-x: auto;
	scroll-snap-type: x mandatory;
	scrollbar-width: thin;
	padding-block-end: 1rem;
	margin-inline: calc(var(--gutter) * -1);
	padding-inline: var(--gutter);
}

.rail > * { scroll-snap-align: start; }

@media (min-width: 640px) {
	.rail { grid-auto-columns: minmax(44%, 1fr); }
}

/*
 * Four cards across, but expressed as 3 of 12 columns each rather than as its
 * own four-column grid, so the card edges line up with the news well above.
 */
@media (min-width: 1024px) {
	.rail {
		grid-auto-flow: row;
		grid-template-columns: repeat(var(--grid-cols), minmax(0, 1fr));
		gap: var(--grid-gap);
		overflow: visible;
		margin-inline: 0;
		padding-inline: 0;
	}

	.rail > * { grid-column: span 3; }
}

/* C. BAND: the single inverted block on the page. Deliberate, once only. */
/*
 * No vertical margin here. The band carries its own padding, and the section
 * above already ends with a full space-section of padding. Adding a margin on
 * top of that stacks two gaps and opens a dead band of paper before the navy.
 */
.band {
	background: var(--surface-invert);
	color: var(--ink-invert);
	padding-block: var(--space-section);
}

html[data-theme="dark"] .band,
html:not([data-theme="light"]) .band {
	border-block: 1px solid var(--rule);
}

.band__grid {
	display: grid;
	grid-template-columns: repeat(var(--grid-cols), minmax(0, 1fr));
	gap: var(--s-4) var(--grid-gap);
	align-items: start;
}

.band__grid > * { grid-column: 1 / -1; }

/*
 * 7 + 5, echoing the news well's 7 + 3 + 2 above it.
 *
 * Addressed by position, not :first-child / :last-child. The opinion list is
 * only rendered when there are further opinion pieces left after the front
 * page has reserved its stories, and when it is absent the single remaining
 * child matched BOTH selectors, so the quote was thrown into columns 9 to 12
 * with an empty half-page beside it.
 */
@media (min-width: 900px) {
	.band__grid > *:nth-child(1) { grid-column: span 7; }
	.band__grid > *:nth-child(2) { grid-column: 9 / -1; }
}

.band__quote {
	font-family: var(--font-read);
	font-size: clamp(1.5rem, 1rem + 2.4vw, 2.625rem);
	line-height: 1.18;
	font-weight: 400;
	letter-spacing: -.015em;
	color: var(--ink-invert);
	text-wrap: pretty;
}

/*
 * A border-bottom on a multi-line link draws a rule under every wrapped line,
 * which turns a pull quote into a block of underlined text. Underline with
 * skip-ink instead, and keep it off until hover so the quote reads as a quote.
 */
.band__quote a {
	text-decoration: underline;
	text-decoration-color: transparent;
	text-decoration-thickness: 2px;
	text-underline-offset: .18em;
	transition: text-decoration-color var(--dur) var(--ease);
}

.band__quote a:hover,
.band__quote a:focus-visible { text-decoration-color: var(--accent); }

.band__attr {
	margin-block-start: 1.5rem;
	display: flex;
	align-items: center;
	gap: .75rem;
	flex-wrap: wrap;
}

.band__attr-name {
	font-family: var(--font-ui);
	font-size: .9375rem;
	font-weight: 700;
	color: var(--ink-invert);
}

.band__attr-role {
	font-family: var(--font-ui);
	font-size: .8125rem;
	color: var(--ink-invert-soft);
}

.band__list {
	border-block-start: 3px solid var(--accent);
	padding-block-start: 1.25rem;
}

.band__list-title {
	font-size: 1.125rem;
	color: var(--ink-invert);
	margin-block-end: .25rem;
}

.band__list .story { gap: .375rem; padding-block: 1.0625rem; }

.band__list .story + .story {
	border-block-start: 1px solid rgba(255, 255, 255, .14);
}

/*
 * Anything rendered on navy has to take the inverted ink tokens explicitly.
 * The story card is shared with the rest of the site, so its byline carries
 * the light-mode --ink-soft, which lands at 2.26:1 against #002038. Setting
 * it on the card's own colour properties is not enough: .byline__name sets
 * its own colour and would win over inheritance.
 */
.band .story__title,
.band .byline__name,
.site-footer .story__title,
.site-footer .byline__name { color: var(--ink-invert); }

.band .t-meta,
.band .story__foot,
.site-footer .t-meta,
.site-footer .story__foot { color: var(--ink-invert-soft); }

.band .byline__name:hover,
.site-footer .byline__name:hover { color: var(--accent); }

.band .byline__sep,
.site-footer .byline__sep { background: var(--ink-invert-soft); }

/* D. BENTO ---------------------------------------------------------------
   Cells always equal items, so a blank tile is structurally impossible.
   Each count gets its own explicit grid-template-areas: with named areas the
   browser cannot auto-place a story into a gap, which is how the earlier
   nth-child version ended up with a hole at four and five items.
   ------------------------------------------------------------------------ */
/*
 * align-items: start stops the shorter cells stretching to match the tall
 * hero. Without it the hero's portrait crop sets the row heights and the
 * stories beside it float in the middle of their own dead space.
 */
.bento {
	display: grid;
	gap: var(--s-4) var(--grid-gap);
	align-items: start;
}

.bento > *:nth-child(1) { grid-area: a; }
.bento > *:nth-child(2) { grid-area: b; }
.bento > *:nth-child(3) { grid-area: c; }
.bento > *:nth-child(4) { grid-area: d; }

@media (min-width: 760px) and (max-width: 1023px) {
	.bento--2,
	.bento--3,
	.bento--4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }

	.bento--3 > *:nth-child(1) { grid-column: 1 / -1; }
	.bento--3 > *:nth-child(1) .story__media { aspect-ratio: 2 / 1; }
}

/*
 * Bento shapes expressed in twelfths, so the cells align with the news well
 * and the rail rather than sitting on a private grid of their own.
 */
@media (min-width: 1024px) {
	.bento { grid-template-columns: repeat(var(--grid-cols), minmax(0, 1fr)); }

	.bento--1 { grid-template-areas: "a a a a a a a a a a a a"; }
	.bento--1 .story__media { aspect-ratio: 21 / 9; }

	.bento--2 { grid-template-areas: "a a a a a a b b b b b b"; }

	/* Tall hero beside two stacked stories: 8 + 4. */
	.bento--3 {
		grid-template-areas:
			"a a a a a a a a b b b b"
			"a a a a a a a a c c c c";
	}

	/* Tall hero, one wide story above two narrow ones: 6 + 6, then 6 + 3 + 3. */
	.bento--4 {
		grid-template-areas:
			"a a a a a a b b b b b b"
			"a a a a a a c c c d d d";
	}

	/*
	 * 3:4 rather than 4:5. Across eight of twelve columns a 4:5 crop is over
	 * 800px tall, which dwarfs the two stories beside it instead of leading
	 * them.
	 */
	.bento--3 > *:nth-child(1) .story__media,
	.bento--4 > *:nth-child(1) .story__media { aspect-ratio: 3 / 4; }

	.bento--3 > *:nth-child(1) .story__title,
	.bento--4 > *:nth-child(1) .story__title {
		font-size: clamp(1.5rem, 1.1rem + 1.6vw, 2.25rem);
	}
}

/* E. INDEX: 12 beats grouped into 3 clusters, not a 12-row hairline list. */
.beatindex {
	display: grid;
	grid-template-columns: repeat(var(--grid-cols), minmax(0, 1fr));
	gap: var(--s-4) var(--grid-gap);
}

.beatindex > * { grid-column: 1 / -1; }

/* Three clusters, 4 columns each. */
@media (min-width: 760px) {
	.beatindex > * { grid-column: span 4; }
}

.beatindex__group-title {
	font-size: .75rem;
	font-weight: 800;
	letter-spacing: .11em;
	text-transform: uppercase;
	color: var(--ink-meta);
	padding-block-end: .875rem;
	border-block-end: 1px solid var(--rule);
	margin-block-end: .5rem;
}

.beatindex__link {
	display: flex;
	align-items: baseline;
	justify-content: space-between;
	gap: 1rem;
	padding-block: .6875rem;
	text-decoration: none;
	color: var(--ink);
	transition: color var(--dur) var(--ease);
}

.beatindex__link:hover { color: var(--accent-text); }

.beatindex__name {
	font-family: var(--font-ui);
	font-size: 1.125rem;
	font-weight: 700;
	letter-spacing: -.02em;
}

.beatindex__count {
	font-family: var(--font-ui);
	font-size: .75rem;
	font-weight: 600;
	color: var(--ink-meta);
	font-variant-numeric: tabular-nums;
	flex: none;
}

/* F. MEDIA: podcast feature. */
.mediafeature {
	display: grid;
	grid-template-columns: repeat(var(--grid-cols), minmax(0, 1fr));
	gap: var(--s-4) var(--grid-gap);
	align-items: center;
}

.mediafeature > * { grid-column: 1 / -1; }

/* Square art on 5, episode list on 7. */
@media (min-width: 860px) {
	.mediafeature > *:first-child { grid-column: span 5; }
	.mediafeature > *:last-child { grid-column: span 7; }
}

.mediafeature__art {
	position: relative;
	aspect-ratio: 1;
	overflow: hidden;
	background: var(--paper-2);
}

.mediafeature__art img {
	width: 100%;
	height: 100%;
	object-fit: cover;
}

.mediafeature__eps .story { gap: .3125rem; padding-block: 1rem; }
.mediafeature__eps .story + .story { border-block-start: 1px solid var(--rule); }

/* Empty state, shown when a beat has nothing published yet. */
.empty {
	display: grid;
	gap: .75rem;
	justify-items: start;
	padding: clamp(1.5rem, 1rem + 2vw, 2.5rem);
	border: 1px dashed var(--rule-strong);
	background: var(--paper-2);
}

.empty__title {
	font-family: var(--font-ui);
	font-size: 1.125rem;
	font-weight: 700;
	letter-spacing: -.02em;
	color: var(--ink);
}

.empty__body {
	font-family: var(--font-read);
	font-size: 1rem;
	color: var(--ink-soft);
	max-width: 46ch;
}


/* ── 09  ARTICLE ──────────────────────────────────────────────────────────── */

.article-head {
	padding-block: clamp(2rem, 1rem + 3vw, 3.5rem) 0;
}

.article-head__inner {
	max-width: 62rem;
	margin-inline: auto;
}

.article-head__chips {
	display: flex;
	gap: .5rem;
	flex-wrap: wrap;
	margin-block-end: 1.25rem;
}

.article-head__title {
	font-size: clamp(2rem, 1.1rem + 3.6vw, 3.75rem);
	line-height: 1;
	letter-spacing: var(--headline-tracking, -.035em);
	font-weight: var(--headline-weight, 800);
	text-transform: var(--headline-transform, none);
	margin-block-end: 1.25rem;
}

.article-head__lede { max-width: 60ch; }

.article-head__meta {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: .5rem .75rem;
	margin-block-start: 1.75rem;
	padding-block-start: 1.25rem;
	border-block-start: 1px solid var(--rule);
}

.article-hero {
	margin-block: clamp(2rem, 1rem + 3vw, 3rem);
}

.article-hero img {
	width: 100%;
	max-height: 74vh;
	object-fit: cover;
}

.article-hero figcaption {
	margin-block-start: .75rem;
	font-family: var(--font-ui);
	font-size: .8125rem;
	color: var(--ink-meta);
	max-width: 70ch;
}

/* ── ARTICLE LAYOUT ───────────────────────────────────────────────────────
   A narrow margin rail beside the reading column, which is how editorial
   pages have set long-form for a century. Everything that is *about* the
   story rather than part of it moves into the rail, so the prose runs
   uninterrupted at its measure instead of being broken up by furniture.

     cols 1-3   rail: contents, share. Sticky, so it follows the reader.
     cols 4-10  the text, still capped at its reading measure
     cols 11-12 left empty on purpose. Editorial pages need somewhere for the
                eye to rest, and a full-bleed text block reads as a wall.
   ------------------------------------------------------------------------ */

.article-layout {
	display: grid;
	grid-template-columns: repeat(var(--grid-cols), minmax(0, 1fr));
	gap: var(--s-4) var(--grid-gap);
	align-items: start;
}

.article-layout > * { grid-column: 1 / -1; }

@media (min-width: 1100px) {
	.article-rail { grid-column: 1 / span 3; }
	.article-layout > .article-body { grid-column: 4 / span 7; }
}

/* Beside a sidebar the well is narrower, so the rail would squeeze the text. */
@media (min-width: 1100px) {
	.has-sidebar .article-rail { grid-column: 1 / -1; }
	.has-sidebar .article-layout > .article-body { grid-column: 1 / -1; }
}

.article-rail__inner {
	position: sticky;
	inset-block-start: 6rem;
	display: grid;
	gap: var(--s-4);
}

/* The rail is a margin, not a panel: it carries no background of its own. */
@media (max-width: 1099px) {
	.article-rail__inner {
		position: static;
		gap: var(--s-3);
	}
}

/*
 * Exactly one share block is ever visible.
 *
 * Scoped through .article-layout rather than written as bare .share--rail:
 * the base `.share { display: grid }` rule lives further down the stylesheet
 * and, at equal specificity, later wins. Two visible share rows was the
 * result. Two class selectors settle it regardless of source order.
 */
.article-layout .share--rail { display: none; }

@media (min-width: 1100px) {
	.article-layout .share--rail { display: grid; }
	.article-layout .share--foot { display: none; }

	/* With a sidebar the rail is suppressed, so the foot takes over again. */
	.has-sidebar .article-layout .share--rail { display: none; }
	.has-sidebar .article-layout .share--foot { display: grid; }
}

/* In the rail the contents list is the margin note, so it loses its panel. */
@media (min-width: 1100px) {
	.article-rail .toc {
		margin: 0;
		padding: var(--s-2) 0 0;
		background: none;
		border-inline-start: 0;
		border-block-start: 3px solid var(--accent);
		max-width: none;
	}

	.article-rail .share__row { gap: var(--s-1); }
	.article-rail .share__btn { width: 38px; height: 38px; }
}

/* Reading column. This is the product: everything else serves it. */
/*
 * The two Customizer controls for reading text write --article-size and
 * --article-leading. Both carry the shipped value as their fallback, so the
 * defaults here are the design's, and a reader who never opens the Customizer
 * sees exactly what was designed.
 *
 * The size is the ceiling of the fluid clamp rather than a fixed value, so
 * raising it still scales down on a narrow screen instead of overflowing it.
 */
.article-body {
	font-family: var(--font-read);
	font-size: clamp(1.0625rem, 1rem + .35vw, var(--article-size, 1.25rem));
	line-height: var(--article-leading, 1.66);
	color: var(--ink);

	/*
	 * 56ch, not the 68ch you might expect from "aim for 65 to 75 characters".
	 *
	 * The ch unit is the advance width of the ZERO glyph, and in Newsreader
	 * the zero is far wider than the average lowercase letter. Measured on
	 * real prose, 68ch sets about 86 characters per line, well past the
	 * comfortable range. 56ch measures at roughly 70. The number looks wrong
	 * and the result is right, which is why this comment exists.
	 */
	max-width: 56ch;
	margin-inline: auto;
	text-wrap: pretty;
}

.article-body > * + * { margin-block-start: 1.4em; }

.article-body p { hyphens: auto; }

.article-body h2 {
	font-family: var(--font-ui);
	font-size: clamp(1.4375rem, 1.1rem + 1.2vw, 1.9375rem);
	line-height: 1.12;
	letter-spacing: -.028em;
	margin-block-start: 2.2em;
}

.article-body h3 {
	font-family: var(--font-ui);
	font-size: clamp(1.1875rem, 1rem + .7vw, 1.4375rem);
	line-height: 1.18;
	letter-spacing: -.022em;
	margin-block-start: 1.9em;
}

.article-body h4 {
	font-family: var(--font-ui);
	font-size: 1.0625rem;
	font-weight: 700;
	letter-spacing: -.01em;
	margin-block-start: 1.8em;
}

.article-body a {
	color: var(--accent-text);
	text-decoration: underline;
	text-decoration-thickness: 1px;
	text-underline-offset: .18em;
	transition: color var(--dur) var(--ease);
}

.article-body a:hover {
	color: var(--accent-text-hover);
	text-decoration-thickness: 2px;
}

.article-body strong { font-weight: 700; }

.article-body ul,
.article-body ol {
	padding-inline-start: 1.4em;
	display: grid;
	gap: .5em;
}

.article-body ul { list-style: disc; }
.article-body ol { list-style: decimal; }
.article-body li::marker { color: var(--accent-text); }

.article-body blockquote {
	margin-inline: 0;
	padding-inline-start: 1.25rem;
	border-inline-start: 3px solid var(--accent);
	font-size: 1.12em;
	line-height: 1.45;
	color: var(--ink-soft);
	font-style: italic;
}

.article-body img,
.article-body figure { margin-block: 2em; }

.article-body figcaption {
	margin-block-start: .625rem;
	font-family: var(--font-ui);
	font-size: .8125rem;
	line-height: 1.45;
	color: var(--ink-meta);
}

.article-body hr {
	border: 0;
	border-block-start: 1px solid var(--rule);
	margin-block: 2.5em;
}

.article-body table {
	width: 100%;
	border-collapse: collapse;
	font-family: var(--font-ui);
	font-size: .9375rem;
}

.article-body th,
.article-body td {
	text-align: start;
	padding: .625rem .75rem;
	border-block-end: 1px solid var(--rule);
}

.article-body th { font-weight: 700; background: var(--paper-2); }

/* Wide and full blocks from the block editor */
.article-body .alignwide {
	width: min(100vw - (var(--gutter) * 2), 68rem);
	margin-inline: calc(50% - min(50vw - var(--gutter), 34rem));
}

.article-body .alignfull {
	width: 100vw;
	margin-inline: calc(50% - 50vw);
	max-width: none;
}

/* Tables and pre must scroll inside themselves, never the page. */
.article-body pre,
/*
 * Data tables. This publication runs budget figures and election results, so
 * a table is content rather than decoration and is styled as such: a tinted
 * header, zebra rows to track across a wide one, and figures set in tabular
 * numerals so columns of numbers line up on the decimal.
 *
 * The wrapper scrolls rather than the page, which is why max-width is capped
 * here: a wide table must not be able to widen the article column.
 */
.article-body .wp-block-table {
	overflow-x: auto;
	max-width: 100%;
}

.article-body table {
	width: 100%;
	border-collapse: collapse;
	font-family: var(--font-ui);
	font-size: .9375rem;
	line-height: 1.45;
}

.article-body thead th {
	background: var(--paper-3);
	font-weight: 800;
	text-align: start;
}

.article-body th,
.article-body td {
	padding: .625rem .75rem;
	border: 1px solid var(--rule);
	font-variant-numeric: tabular-nums;
}

.article-body tbody tr:nth-child(even) {
	background: var(--paper-2);
}

.article-body table caption {
	margin-block-end: .5rem;
	font-family: var(--font-ui);
	font-size: .8125rem;
	color: var(--ink-meta);
	text-align: start;
}

.article-body pre {
	background: var(--paper-2);
	padding: 1rem 1.25rem;
	font-size: .875rem;
	line-height: 1.55;
}

/* ── BLOCK STYLES ─────────────────────────────────────────────────────────
   The three block styles registered in inc/blocks.php, so the patterns a
   writer inserts render the same way in every story.
   ------------------------------------------------------------------------ */

.article-body .is-style-insightgy-pull {
	border-inline-start: 0;
	padding-inline-start: 0;
	margin-block: 2.25em;
	padding-block: 1.5rem;
	border-block: 3px solid var(--accent);
	font-family: var(--font-read);
	font-size: 1.35em;
	line-height: 1.3;
	font-style: normal;
	color: var(--ink);
	text-wrap: pretty;
}

.article-body .is-style-insightgy-pull cite {
	display: block;
	margin-block-start: .875rem;
	font-family: var(--font-ui);
	font-size: .8125rem;
	font-weight: 700;
	font-style: normal;
	letter-spacing: .02em;
	color: var(--ink-meta);
}

.article-body .insightgy-facts,
.article-body .is-style-insightgy-facts {
	margin-block: 2.25em;
	padding: 1.5rem;
	background: var(--paper-2);
	border-inline-start: 3px solid var(--accent);
}

.article-body .insightgy-facts h3,
.article-body .is-style-insightgy-facts h3 {
	margin-block-start: 0;
	font-size: 1.0625rem;
	letter-spacing: .02em;
	text-transform: uppercase;
}

.article-body .insightgy-facts ul,
.article-body .is-style-insightgy-facts ul { font-size: .95em; }

.article-body .insightgy-note {
	padding: 1rem 1.25rem;
	background: var(--paper-2);
	font-size: .95em;
	color: var(--ink-soft);
}

.article-body .is-style-insightgy-full-bleed {
	width: 100vw;
	max-width: none;
	margin-inline: calc(50% - 50vw);
}

.article-body .is-style-insightgy-full-bleed img { width: 100%; }

/* ── WORDPRESS CORE CLASSES ───────────────────────────────────────────────
   Classes the editor emits that no template of mine renders. Without these,
   an editor who sets an image to "align left" or adds a caption gets nothing,
   which is a content bug rather than a styling nicety.
   ------------------------------------------------------------------------ */

.alignleft {
	float: left;
	margin: .35em 1.5rem 1rem 0;
	max-width: 50%;
}

.alignright {
	float: right;
	margin: .35em 0 1rem 1.5rem;
	max-width: 50%;
}

.aligncenter {
	display: block;
	margin-inline: auto;
	margin-block: 2em;
}

@media (max-width: 600px) {
	/* Floats at phone width leave unreadable slivers of text beside them. */
	.alignleft,
	.alignright {
		float: none;
		max-width: 100%;
		margin-inline: 0;
	}
}

.article-body .wp-caption { max-width: 100%; margin-block: 2em; }
.article-body .wp-caption img { width: 100%; }

.article-body .wp-caption-text,
.article-body .gallery-caption {
	margin-block-start: .625rem;
	font-family: var(--font-ui);
	font-size: .8125rem;
	line-height: 1.45;
	color: var(--ink-meta);
	text-align: start;
}

/* Sticky posts get the amber rule the section heads use. */
.story.sticky .story__title {
	border-inline-start: 3px solid var(--accent);
	padding-inline-start: .75rem;
}

/* A comment by the post's author, so a reply from the newsroom reads as one. */
.commentlist li.bypostauthor > .comment-body .fn::after {
	content: attr(data-author-label);
}

.commentlist li.bypostauthor > .comment-body {
	border-inline-start: 3px solid var(--accent);
	padding-inline-start: 1rem;
}

/* Screen-reader helper WordPress emits in its own markup. */
.says,
.screen-reader-response { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); }

/* Gallery block and classic galleries. */
.article-body .gallery {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(min(200px, 100%), 1fr));
	gap: 1rem;
	margin-block: 2em;
}

.article-body .gallery-item { margin: 0; }

/* ── COMPONENTS INSIDE THE READING COLUMN ─────────────────────────────────
   `.article-body a` is specificity (0,1,1) and beats a bare component class
   like `.btn--primary` at (0,1,0). Anything rendered inside the reading
   column, whether by a template or injected by a content filter, therefore
   inherits the body link colour unless it is re-stated here. That is not
   cosmetic: it put #8f5208 text on the amber support button at 3.14:1.
   ------------------------------------------------------------------------ */

.article-body a.btn,
.article-body a.share__btn,
.article-body a.chip,
.article-body .toc__list a,
.article-body .republish__summary {
	text-decoration: none;
}

.article-body a.btn--primary,
.article-body a.btn--primary:hover { color: var(--on-accent); }

.article-body a.btn--outline,
.article-body a.btn--outline:hover { color: var(--ink); }

.article-body a.share__btn { color: var(--ink-soft); }
.article-body a.share__btn:hover { color: var(--on-accent); }
.article-body a.chip { color: var(--on-accent); }
.article-body .toc__list a { color: var(--ink); }

/* Article footer: tags, share, author */
.article-foot {
	margin-block-start: clamp(2.5rem, 1.5rem + 3vw, 4rem);
	padding-block-start: 1.75rem;
	border-block-start: 3px solid var(--accent);
	display: grid;
	gap: 1.75rem;
}

.tag-row {
	display: flex;
	flex-wrap: wrap;
	gap: .5rem;
}

.tag-row a {
	font-family: var(--font-ui);
	font-size: .75rem;
	font-weight: 600;
	letter-spacing: .02em;
	text-decoration: none;
	padding: .3125rem .625rem;
	background: var(--paper-2);
	color: var(--ink-soft);
	transition: background var(--dur) var(--ease), color var(--dur) var(--ease);
}

.tag-row a:hover { background: var(--accent); color: var(--on-accent); }

.authorbox {
	display: grid;
	gap: .5rem;
	padding: 1.5rem;
	background: var(--paper-2);
}

.authorbox__name {
	font-family: var(--font-ui);
	font-size: 1.125rem;
	font-weight: 800;
	letter-spacing: -.02em;
}

.authorbox__bio {
	font-family: var(--font-read);
	font-size: 1rem;
	line-height: 1.55;
	color: var(--ink-soft);
	max-width: 62ch;
}

/* Comments */
.comments {
	margin-block-start: clamp(2.5rem, 1.5rem + 3vw, 4rem);
}

.comments__title {
	font-family: var(--font-ui);
	font-size: clamp(1.375rem, 1.1rem + 1vw, 1.75rem);
	letter-spacing: -.025em;
	margin-block-end: 1.5rem;
	padding-block-start: 1.5rem;
	border-block-start: 3px solid var(--accent);
}

.commentlist,
.commentlist .children { list-style: none; padding: 0; }
.commentlist .children { padding-inline-start: clamp(1rem, .5rem + 2vw, 2.5rem); }

.commentlist li.comment { padding-block: 1.5rem; border-block-start: 1px solid var(--rule); }
.commentlist > li.comment:first-child { border-block-start: 0; }

.comments .comment-meta {
	display: flex;
	align-items: center;
	gap: .625rem;
	flex-wrap: wrap;
	margin-block-end: .75rem;
}

.comments .avatar { flex: none; }

.comments .fn {
	font-family: var(--font-ui);
	font-size: .9375rem;
	font-weight: 700;
	font-style: normal;
	color: var(--ink);
}

.comments .comment-metadata,
.comments .comment-metadata a {
	font-family: var(--font-ui);
	font-size: .75rem;
	color: var(--ink-meta);
	text-decoration: none;
}

.comments .comment-content { font-size: .95em; }

.comments .reply a,
.comments .comment-reply-link {
	display: inline-block;
	margin-block-start: .75rem;
	font-family: var(--font-ui);
	font-size: .8125rem;
	font-weight: 700;
	color: var(--accent-text);
	text-decoration: none;
	border-block-end: 2px solid transparent;
}

.comments .reply a:hover,
.comments .comment-reply-link:hover { border-block-end-color: var(--accent); }

.comment-respond { margin-block-start: 2rem; }

.comment-respond .comment-form-comment,
.comment-respond .comment-form-author,
.comment-respond .comment-form-email,
.comment-respond .comment-form-url { margin-block-end: 1.25rem; }

.comment-respond label {
	display: block;
	margin-block-end: .5rem;
	font-family: var(--font-ui);
	font-size: .8125rem;
	font-weight: 700;
	letter-spacing: .02em;
	color: var(--ink);
}

.comment-respond input[type="text"],
.comment-respond input[type="email"],
.comment-respond input[type="url"],
.comment-respond textarea {
	width: 100%;
	padding: .8125rem 1rem;
	font-family: var(--font-ui);
	font-size: 1rem;
	background: var(--paper);
	color: var(--ink);
	border: 1px solid var(--rule-strong);
	border-radius: 0;
	transition: border-color var(--dur) var(--ease);
}

.comment-respond input:focus,
.comment-respond textarea:focus { border-color: var(--accent); outline-offset: 2px; }

.comment-respond .comment-notes,
.comment-respond .logged-in-as { font-family: var(--font-ui); font-size: .8125rem; color: var(--ink-meta); }

/* Prev / next */
.postnav {
	display: grid;
	gap: 1px;
	background: var(--rule);
	border-block: 1px solid var(--rule);
	margin-block-start: var(--space-block);
}

@media (min-width: 700px) {
	.postnav { grid-template-columns: 1fr 1fr; }
}

.postnav a {
	display: grid;
	gap: .375rem;
	padding: 1.5rem;
	background: var(--paper);
	text-decoration: none;
	transition: background var(--dur) var(--ease);
}

.postnav a:hover { background: var(--paper-2); }
.postnav__dir { font-size: .75rem; font-weight: 700; letter-spacing: .08em;
	text-transform: uppercase; color: var(--accent-text); }
.postnav__title { font-family: var(--font-ui); font-size: 1.0625rem;
	font-weight: 700; letter-spacing: -.018em; line-height: 1.25; }
.postnav a.is-next { text-align: end; }


/* ── 10  ARCHIVE, SEARCH, 404 ─────────────────────────────────────────────── */

.page-head {
	padding-block: clamp(2.5rem, 1.5rem + 4vw, 4.5rem) var(--space-block);
	border-block-end: 1px solid var(--rule);
	margin-block-end: var(--space-block);
}

.page-head__title {
	font-size: clamp(2.25rem, 1.2rem + 4vw, 4rem);
	letter-spacing: -.035em;
	line-height: 1;
}

.page-head__desc {
	margin-block-start: 1rem;
	max-width: 58ch;
}

.grid-posts {
	display: grid;
	grid-template-columns: repeat(var(--grid-cols), minmax(0, 1fr));
	gap: var(--s-4) var(--grid-gap);
}

.grid-posts > * { grid-column: 1 / -1; }

/* 6 + 6, then 4 + 4 + 4. Both divide twelve, so the columns keep aligning. */
@media (min-width: 620px) {
	.grid-posts > * { grid-column: span 6; }
}

@media (min-width: 1000px) {
	.grid-posts > * { grid-column: span 4; }
}

/* ── Listing layouts ───────────────────────────────────────────────────────
   The grid above is the default. These two turn the same cards into rows.

   The card markup is a flat sequence — media, kicker, headline, dek, byline —
   so a row is made by putting the card itself on a grid and pinning the media
   to a column that spans every row. Nothing about the card has to change,
   which is why all three layouts stay in step when a card is edited.
   ------------------------------------------------------------------------ */

@media (min-width: 620px) {
	.posts--list > * { grid-column: 1 / -1; }

	.posts--list .story {
		display: grid;
		grid-template-columns: 13rem 1fr;
		column-gap: var(--s-4);
		align-items: start;
		padding-block-end: var(--s-4);
		border-block-end: 1px solid var(--rule);
	}

	.posts--list .story:last-child {
		padding-block-end: 0;
		border-block-end: 0;
	}

	/* The picture occupies column one whatever the text below it runs to. */
	.posts--list .story__media {
		grid-row: 1 / -1;
		aspect-ratio: 4 / 3;
	}

	/* A card with no picture at all should not leave a hole where one was. */
	.posts--list .story:not(:has(.story__media)) {
		grid-template-columns: 1fr;
	}
}

/* Two rows across, each still a row rather than a tile. */
@media (min-width: 1000px) {
	.posts--list2 > * { grid-column: span 6; }

	.posts--list2 .story {
		grid-template-columns: 10rem 1fr;
	}
}

/* Beside a sidebar there is not room for a picture beside the text as well. */
@media (min-width: 1000px) {
	.has-sidebar .posts--list2 > * { grid-column: 1 / -1; }
}

/* Beside a sidebar the well is narrower, so two up reads better than three. */
@media (min-width: 1000px) {
	.has-sidebar .grid-posts > * { grid-column: span 6; }

	/*
	 * ...but a list is a list. The rule above is more specific than the list
	 * layout's own, so without this a single-column list silently became two
	 * columns as soon as a sidebar was switched on, which is not what the
	 * setting says it does.
	 *
	 * Both list layouts go full width here. Beside a sidebar the well is not
	 * wide enough to carry two rows that each have a picture beside the text,
	 * so the two-column list collapses to one rather than crushing both.
	 */
	.has-sidebar .posts--list > *,
	.has-sidebar .posts--list2 > * { grid-column: 1 / -1; }
}

.pagination {
	margin-block-start: var(--space-block);
	padding-block-start: 1.5rem;
	border-block-start: 1px solid var(--rule);
}

.pagination .nav-links {
	display: flex;
	flex-wrap: wrap;
	gap: .375rem;
	align-items: center;
}

.pagination .page-numbers {
	display: inline-grid;
	place-items: center;
	min-width: 42px;
	height: 42px;
	padding-inline: .5rem;
	font-family: var(--font-ui);
	font-size: .9375rem;
	font-weight: 700;
	text-decoration: none;
	color: var(--ink);
	border: 1px solid var(--rule);
	transition: background var(--dur) var(--ease), color var(--dur) var(--ease),
		border-color var(--dur) var(--ease);
}

.pagination a.page-numbers:hover { border-color: var(--ink); }

.pagination .page-numbers.current {
	background: var(--accent);
	border-color: var(--accent);
	color: var(--on-accent);
}

.pagination .dots { border-color: transparent; }

.notfound {
	padding-block: clamp(3rem, 2rem + 6vw, 7rem);
	display: grid;
	gap: 1.5rem;
	justify-items: start;
	max-width: 44rem;
}


/* ── 10a  LONG-FORM FURNITURE ─────────────────────────────────────────────
   Patterns borrowed from newsrooms that publish at this length: reading
   progress (Guardian, Vox), a contents list (Guardian, Reuters), a visible
   corrections note (ProPublica), a mid-article support ask (Guardian), and a
   running-story rail (The Verge's StoryStream).
   ------------------------------------------------------------------------ */

/*
 * Reading progress, with no JavaScript at all.
 *
 * A scroll-driven animation is composited off the main thread, so the bar
 * stays smooth while the article's images are still decoding. The whole thing
 * is inside @supports: where the browser cannot do this natively the bar never
 * appears, which is correct, because it is orientation rather than content.
 */
.progress { display: none; }

@supports (animation-timeline: scroll()) {
	@media (prefers-reduced-motion: no-preference) {
		.progress {
			display: block;
			position: fixed;
			inset-block-start: 0;
			inset-inline: 0;
			z-index: calc(var(--z-header) + 1);
			height: 3px;
			pointer-events: none;
		}

		.progress__bar {
			display: block;
			height: 100%;
			width: 100%;
			background: var(--accent);
			transform-origin: 0 50%;
			animation: insightgy-progress linear;
			animation-timeline: scroll(root block);
		}
	}
}

@keyframes insightgy-progress {
	from { transform: scaleX(0); }
	to   { transform: scaleX(1); }
}

/* Contents */
.toc {
	margin-block-end: var(--s-4);
	padding: var(--s-2) var(--s-3);
	background: var(--paper-2);
	border-inline-start: 3px solid var(--accent);
	/* Matches the reading column, so the two share an edge. */
	max-width: var(--article-measure, 56ch);
	margin-inline: auto;
}

.has-sidebar .toc { margin-inline: 0; }

.toc__title {
	font-family: var(--font-ui);
	font-size: .75rem;
	font-weight: 800;
	letter-spacing: .11em;
	text-transform: uppercase;
	color: var(--ink-meta);
	margin-block-end: .875rem;
}

.toc__list {
	display: grid;
	gap: .5rem;
	counter-reset: toc;
	list-style: none;
}

.toc__list li { counter-increment: toc; }

.toc__list a {
	display: grid;
	grid-template-columns: 1.75rem 1fr;
	gap: .25rem;
	font-family: var(--font-ui);
	font-size: .9375rem;
	font-weight: 600;
	line-height: 1.35;
	letter-spacing: -.01em;
	color: var(--ink);
	text-decoration: none;
}

.toc__list a::before {
	content: counter(toc);
	font-variant-numeric: tabular-nums;
	color: var(--accent-text);
	font-weight: 800;
}

/* Corrections and updates */
.correction {
	margin-block-start: 1.75rem;
	padding: 1rem 1.25rem;
	background: var(--paper-2);
	border-inline-start: 3px solid var(--ink-meta);
}

.correction--fix { border-inline-start-color: #b3261e; }

html[data-theme="dark"] .correction--fix,
html:not([data-theme="light"]) .correction--fix { border-inline-start-color: #ffb4ab; }

.correction__label {
	display: flex;
	flex-wrap: wrap;
	align-items: baseline;
	gap: .5rem;
	font-family: var(--font-ui);
	font-size: .75rem;
	font-weight: 800;
	letter-spacing: .09em;
	text-transform: uppercase;
	color: var(--ink);
	margin-block-end: .375rem;
}

.correction__label time {
	font-weight: 600;
	letter-spacing: .02em;
	text-transform: none;
	color: var(--ink-meta);
}

.correction__body {
	font-family: var(--font-read);
	font-size: 1rem;
	line-height: 1.5;
	color: var(--ink-soft);
}

.article-updated { margin-block-start: .5rem; }

/* Mid-article support ask */
.support {
	margin-block: 2.5em;
	padding: clamp(1.5rem, 1rem + 2vw, 2.25rem);
	background: var(--surface-invert);
	color: var(--ink-invert);
	display: grid;
	gap: .75rem;
	justify-items: start;
}

.support__title {
	font-family: var(--font-ui);
	font-size: clamp(1.125rem, 1rem + .6vw, 1.4375rem);
	font-weight: 800;
	letter-spacing: -.02em;
	color: var(--ink-invert);
}

.support__body {
	font-family: var(--font-read);
	font-size: 1.0625rem;
	line-height: 1.5;
	color: var(--ink-invert-soft);
	max-width: 52ch;
}

.support__btn { margin-block-start: .5rem; }

/* Republishing */
.republish {
	border: 1px solid var(--rule);
	background: var(--paper-2);
}

.republish__summary {
	display: flex;
	align-items: center;
	gap: .5rem;
	padding: .875rem 1.125rem;
	font-family: var(--font-ui);
	font-size: .875rem;
	font-weight: 700;
	color: var(--ink);
	cursor: pointer;
	list-style: none;
}

.republish__summary::-webkit-details-marker { display: none; }
.republish__summary svg { width: 16px; height: 16px; color: var(--accent-text); }

.republish__body {
	display: grid;
	gap: .875rem;
	justify-items: start;
	padding: 0 1.125rem 1.125rem;
	font-family: var(--font-ui);
	font-size: .9375rem;
	line-height: 1.5;
	color: var(--ink-soft);
}

.republish__credit {
	padding: .75rem 1rem;
	background: var(--paper);
	border: 1px solid var(--rule);
	font-family: var(--font-read);
	color: var(--ink);
}

/* Running story */
.series {
	margin-block-end: var(--s-4);
	border-block-start: 3px solid var(--accent);
	padding-block-start: var(--s-2);
	/* Matches the reading column, so the two share an edge. */
	max-width: var(--article-measure, 56ch);
	margin-inline: auto;
}

.has-sidebar .series { margin-inline: 0; }

.series__eyebrow {
	font-family: var(--font-ui);
	font-size: .6875rem;
	font-weight: 800;
	letter-spacing: .11em;
	text-transform: uppercase;
	color: var(--accent-text);
}

.series__title {
	font-size: clamp(1.25rem, 1.1rem + .8vw, 1.625rem);
	letter-spacing: -.025em;
	margin-block: .25rem;
}

.series__title a { text-decoration: none; }

.series__count {
	font-family: var(--font-ui);
	font-size: .8125rem;
	color: var(--ink-meta);
	margin-block-end: 1rem;
}

.series__list { display: grid; list-style: none; }

.series__item {
	display: grid;
	grid-template-columns: 1.75rem minmax(0, 1fr) auto;
	align-items: baseline;
	gap: .25rem .5rem;
	padding-block: .625rem;
	border-block-start: 1px solid var(--rule);
}

.series__num {
	font-family: var(--font-ui);
	font-size: .8125rem;
	font-weight: 800;
	color: var(--rule-strong);
	font-variant-numeric: tabular-nums;
}

.series__item.is-current .series__num { color: var(--accent); }

.series__link {
	font-family: var(--font-ui);
	font-size: .9375rem;
	font-weight: 600;
	line-height: 1.3;
	letter-spacing: -.012em;
	color: var(--ink);
	text-decoration: none;
}

.series__item.is-current .series__link { font-weight: 800; }

.series__item.is-current {
	background: var(--paper-2);
	margin-inline: -.75rem;
	padding-inline: .75rem;
}

.series__date {
	font-family: var(--font-ui);
	font-size: .75rem;
	color: var(--ink-meta);
	white-space: nowrap;
	grid-column: 2 / -1;
}

@media (min-width: 560px) {
	.series__date { grid-column: 3 / 4; }
}

/* Byline avatar */
.byline__avatar {
	width: 32px;
	height: 32px;
	border-radius: 0;
	flex: none;
	object-fit: cover;
	background: var(--paper-2);
}

/* Author page */
.authorpage {
	display: grid;
	gap: 1.25rem;
	align-items: start;
	padding-block: clamp(2rem, 1.5rem + 3vw, 3.5rem) var(--space-block);
	border-block-end: 1px solid var(--rule);
	margin-block-end: var(--space-block);
}

@media (min-width: 640px) {
	.authorpage { grid-template-columns: auto minmax(0, 1fr); gap: 2rem; }
}

.authorpage__avatar {
	width: 88px;
	height: 88px;
	border-radius: 0;
	object-fit: cover;
	background: var(--paper-2);
}

.authorpage__name {
	font-size: clamp(1.75rem, 1.2rem + 2.4vw, 2.75rem);
	letter-spacing: -.03em;
	line-height: 1;
}

.authorpage__bio {
	margin-block-start: .875rem;
	font-family: var(--font-read);
	font-size: 1.0625rem;
	line-height: 1.55;
	color: var(--ink-soft);
	max-width: 62ch;
}

.authorpage__count { margin-block-start: .875rem; }
.authorpage__links { margin-block-start: .5rem; font-size: .875rem; }
.authorpage__links a { color: var(--accent-text); }

@media (hover: hover) and (pointer: fine) {
	.toc__list a:hover { color: var(--accent-text); }
	.series__link:hover { color: var(--accent-text); }
	.republish__summary:hover { color: var(--accent-text); }
}

/* ── 10b  BREADCRUMBS, SHARE, SIDEBAR, WIDGETS, BACK TO TOP ──────────────── */

.crumbs {
	border-block-end: 1px solid var(--rule);
	background: var(--paper);
}

.crumbs ol {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: .375rem .5rem;
	padding-block: .75rem;
	font-size: .8125rem;
	color: var(--ink-meta);
}

.crumbs li { display: flex; align-items: center; gap: .5rem; }

.crumbs li + li::before {
	content: "/";
	color: var(--rule-strong);
}

.crumbs a { text-decoration: none; color: var(--ink-meta); }
.crumbs [aria-current="page"] { color: var(--ink); font-weight: 600; }

/* Share */
.share { display: grid; gap: .75rem; }

.share__label {
	font-family: var(--font-ui);
	font-size: .75rem;
	font-weight: 800;
	letter-spacing: .09em;
	text-transform: uppercase;
	color: var(--ink-meta);
}

.share__row { display: flex; flex-wrap: wrap; gap: .5rem; }

.share__btn {
	display: inline-grid;
	place-items: center;
	width: 42px;
	height: 42px;
	padding: 0;
	background: transparent;
	color: var(--ink-soft);
	border: 1px solid var(--rule-strong);
	cursor: pointer;
	transition: background var(--dur) var(--ease-out),
		color var(--dur) var(--ease-out),
		border-color var(--dur) var(--ease-out),
		transform var(--dur-press) var(--ease-out);
}

.share__btn svg { width: 18px; height: 18px; }
.share__btn:active { transform: translateY(1px); }
.share__btn.is-copied { background: var(--accent); color: var(--on-accent); border-color: var(--accent); }

/* Sidebar: 8 + 4 on the shared grid, not a bespoke 1fr/20rem split. */
.has-sidebar {
	display: grid;
	grid-template-columns: repeat(var(--grid-cols), minmax(0, 1fr));
	gap: var(--s-6) var(--grid-gap);
	align-items: start;
}

.has-sidebar > * { grid-column: 1 / -1; }

@media (min-width: 1000px) {
	.has-sidebar > .article-main { grid-column: span 8; }
	.has-sidebar > .sidebar { grid-column: span 4; }
}

.article-main { min-width: 0; }

/*
 * The reading column is centred inside its own track, so it keeps its measure
 * whether or not a sidebar is present.
 */
.has-sidebar .article-body { margin-inline: 0; }

.sidebar { min-width: 0; }

.sidebar__inner {
	position: sticky;
	inset-block-start: 6rem;   /* clears the sticky masthead */
	display: grid;
	gap: var(--space-block);
}

/*
 * No bottom border. Each widget already opens with a 3px amber rule above its
 * title, so a closing hairline as well leaves two lines and a gap between
 * every pair of widgets.
 */
.widget { padding-block-end: 0; }

.widget__title {
	font-family: var(--font-ui);
	font-size: 1.0625rem;
	font-weight: 800;
	letter-spacing: -.02em;
	padding-block-start: 1rem;
	border-block-start: 3px solid var(--accent);
	margin-block-end: 1.25rem;
}

.widget__empty { font-size: .9375rem; color: var(--ink-meta); }

.widget ul, .widget ol { display: grid; gap: .75rem; }

.widget a { color: inherit; text-decoration: none; }

.widget-posts { gap: 0; }

.widget-post {
	display: flex;
	align-items: flex-start;
	gap: .875rem;
	padding-block: .875rem;
	border-block-start: 1px solid var(--rule);
}

.widget-posts > .widget-post:first-child { border-block-start: 0; padding-block-start: 0; }

.widget-post__media { flex: none; width: 84px; overflow: hidden; background: var(--paper-2); }
.widget-post__media img { width: 100%; height: 100%; aspect-ratio: 16 / 10; object-fit: cover; }

.widget-post__rank {
	flex: none;
	width: 1.75rem;
	font-family: var(--font-ui);
	font-size: 1.25rem;
	font-weight: 800;
	line-height: 1;
	color: var(--accent);
	font-variant-numeric: tabular-nums;
}

.widget-post__body { min-width: 0; display: grid; gap: .25rem; }

.widget-post__title {
	font-family: var(--font-ui);
	font-size: .9375rem;
	font-weight: 700;
	line-height: 1.25;
	letter-spacing: -.012em;
	color: var(--ink);
}

.widget-social .footer__social,
.widget-social { display: flex; gap: .5rem; flex-wrap: wrap; }

.widget-social a {
	display: grid;
	place-items: center;
	width: 40px;
	height: 40px;
	color: var(--ink-soft);
	border: 1px solid var(--rule-strong);
	transition: background var(--dur) var(--ease-out), color var(--dur) var(--ease-out),
		border-color var(--dur) var(--ease-out);
}

.widget-social svg { width: 18px; height: 18px; }

/* ── The rest of the widgets ───────────────────────────────────────────────
   Everything here shares the sidebar's type scale and hairline rhythm, so a
   sidebar with six different widgets in it still reads as one column rather
   than six boxes.
   ------------------------------------------------------------------------ */

/* A widget area sitting in the flow of a page rather than in the sidebar. */
.widget-area {
	margin-block: var(--s-6);
}

.widget-area--article {
	margin-block: var(--s-5);
	padding-block: var(--s-4);
	border-block: 1px solid var(--rule);
}

.widget--inline .widget__title {
	margin-block-start: 0;
}

/* Link lists: sections, archive months. */
.widget-links {
	margin: 0;
	padding: 0;
	list-style: none;
	display: grid;
}

.widget-links li {
	border-block-end: 1px solid var(--rule);
}

.widget-links li:last-child { border-block-end: 0; }

.widget-links a {
	display: flex;
	align-items: baseline;
	justify-content: space-between;
	gap: .75rem;

	padding-block: .625rem;

	font-family: var(--font-ui);
	font-size: .9375rem;
	font-weight: 600;
	text-decoration: none;
	color: var(--ink);
}

.widget-links__count {
	flex: none;
	font-size: .75rem;
	font-weight: 700;
	color: var(--ink-meta);
	font-variant-numeric: tabular-nums;
}

/* Writers. */
.widget-authors {
	margin: 0;
	padding: 0;
	list-style: none;
	display: grid;
	gap: .25rem;
}

.widget-authors a {
	display: grid;
	grid-template-columns: auto 1fr;
	align-items: center;
	gap: .625rem .75rem;

	padding-block: .5rem;
	text-decoration: none;
}

.widget-authors__face {
	grid-row: 1 / -1;
	width: 40px;
	height: 40px;
	object-fit: cover;
}

.widget-authors__name {
	font-family: var(--font-ui);
	font-size: .9375rem;
	font-weight: 700;
	color: var(--ink);
}

.widget-authors__count {
	font-size: .75rem;
	color: var(--ink-meta);
}

/* Topics: reuses the chip component rather than inventing a tag style. */
.widget-tags {
	display: flex;
	flex-wrap: wrap;
	gap: .375rem;
}

/* Recent comments. */
.widget-comments {
	margin: 0;
	padding: 0;
	list-style: none;
	display: grid;
}

.widget-comments li { border-block-end: 1px solid var(--rule); }
.widget-comments li:last-child { border-block-end: 0; }

.widget-comments__link {
	display: grid;
	gap: .125rem;
	padding-block: .75rem;
	text-decoration: none;
}

.widget-comments__who {
	font-family: var(--font-ui);
	font-size: .75rem;
	font-weight: 800;
	letter-spacing: .04em;
	text-transform: uppercase;
	color: var(--accent-text);
}

.widget-comments__text {
	font-family: var(--font-read);
	font-size: .9375rem;
	line-height: 1.45;
	color: var(--ink);
}

.widget-comments__where {
	font-size: .75rem;
	color: var(--ink-meta);
}

/* About and newsletter notes. */
.widget-about__text {
	margin: 0 0 .75rem;
	font-family: var(--font-read);
	font-size: .9375rem;
	line-height: 1.55;
	color: var(--ink-soft);
}

.widget-about__link {
	font-family: var(--font-ui);
	font-size: .8125rem;
	font-weight: 800;
	letter-spacing: .04em;
	text-transform: uppercase;
	color: var(--accent-text);
}

/* Archive dropdown. */
.widget-archive {
	width: 100%;
	min-height: 2.75rem;
	padding: .5rem .625rem;
	font-family: var(--font-ui);
	font-size: .9375rem;
	color: var(--ink);
	background: var(--paper);
	border: 1px solid var(--rule);
	border-radius: 0;
}

.widget-archive:focus-visible {
	outline: 2px solid var(--accent);
	outline-offset: -1px;
}

/* The featured card sits flush inside its widget. */
.widget-featured .story__title { font-size: 1.125rem; }

/* The newsletter form, narrower than the footer's. */
.signup--widget .signup__row {
	display: grid;
	gap: .5rem;
}

/* In the navy footer these all need the inverted ink, as the others do. */
.site-footer .widget-links a,
.site-footer .widget-authors__name,
.site-footer .widget-comments__text {
	color: var(--ink-invert);
}

.site-footer .widget-links li,
.site-footer .widget-comments li {
	border-block-end-color: rgba(255, 255, 255, .14);
}

.site-footer .widget-about__text,
.site-footer .widget-links__count,
.site-footer .widget-authors__count,
.site-footer .widget-comments__where {
	color: var(--ink-invert-soft);
}

.site-footer .widget-about__link,
.site-footer .widget-comments__who {
	color: var(--accent);
}

/*
 * Back to top.
 *
 * The bottom-right corner is shared real estate: this button lives there, and
 * so does anything a plugin decides to dock there. Rather than each one
 * guessing, the theme publishes what it occupies as tokens on :root, and
 * whatever comes second offsets itself by them. The InSightGY Newsroom
 * plugin's assistant launcher reads these; without the theme it falls back to
 * zero and sits in the corner on its own.
 */
:root {
	--fab-size: 44px;
	--fab-inset: clamp(1rem, .5rem + 1.5vw, 1.75rem);
	--fab-gap: .75rem;
}

.to-top {
	position: fixed;
	inset-block-end: var(--fab-inset);
	inset-inline-end: var(--fab-inset);
	z-index: var(--z-sticky);
	display: grid;
	place-items: center;
	width: var(--fab-size);
	height: var(--fab-size);
	padding: 0;
	background: var(--surface-invert);
	color: var(--ink-invert);
	border: 1px solid rgba(255, 255, 255, .18);
	cursor: pointer;

	/* Never scale(0): nothing in the real world appears out of nothing. */
	opacity: 0;
	transform: translateY(8px) scale(.9);
	visibility: hidden;
	transition: opacity var(--dur) var(--ease-out),
		transform var(--dur) var(--ease-out),
		background var(--dur) var(--ease-out),
		color var(--dur) var(--ease-out),
		visibility 0s linear var(--dur);
}

.to-top.is-in {
	opacity: 1;
	transform: none;
	visibility: visible;
	transition: opacity var(--dur) var(--ease-out),
		transform var(--dur) var(--ease-out),
		background var(--dur) var(--ease-out),
		color var(--dur) var(--ease-out),
		visibility 0s;
}

.to-top svg { width: 20px; height: 20px; }
.to-top:active { transform: translateY(1px); }

@media (hover: hover) and (pointer: fine) {
	.crumbs a:hover { color: var(--accent-text); }
	.share__btn:hover { background: var(--accent); color: var(--on-accent); border-color: var(--accent); }
	.widget-post__title:hover { color: var(--accent-text); }
	.widget-social a:hover { background: var(--accent); color: var(--on-accent); border-color: var(--accent); }
	.to-top:hover { background: var(--accent); color: var(--on-accent); border-color: var(--accent); }
}

/* Footer widget columns */
.footer__widgets {
	display: grid;
	grid-template-columns: repeat(var(--grid-cols), minmax(0, 1fr));
	gap: var(--s-6) var(--grid-gap);
}

.footer__widgets > * { grid-column: 1 / -1; }

/* Columns divide twelve, so 1, 2, 3 and 4 all land on the grid. */
@media (min-width: 760px) {
	.footer__widgets > * { grid-column: span calc(12 / var(--footer-cols, 3)); }
}

.footer__widgets .widget__title {
	border-block-start: 0;
	padding-block-start: 0;
	font-size: .75rem;
	font-weight: 800;
	letter-spacing: .11em;
	text-transform: uppercase;
	color: var(--accent);
}
.footer__widgets a { color: var(--ink-invert-soft); }
.footer__widgets li { font-size: .9375rem; }

@media (hover: hover) and (pointer: fine) {
	.footer__widgets a:hover { color: var(--accent); }
}

/* ── 10c  LAYOUT PRESETS ──────────────────────────────────────────────────
   Five answers to one question: how much of the day should a reader see at
   once. Each preset changes column spans and image weight only. None of them
   changes the 12-column grid or the spacing scale, so whichever is chosen the
   page stays on the grid.

     broadsheet  7 + 3 + 2   most hierarchy, one clear lead        (default)
     classic     8 + 4       one wide column beside one support column
     magazine    full lead   image led, fewer and larger stories
     compact     5 + 4 + 3   dense, small images, more headlines
     reader      8 centred   text first, no slider, no ticker

   Only the differences from broadsheet are written out, so the presets stay
   readable and cannot drift into four near-copies of the same rules.
   ------------------------------------------------------------------------ */

/* ── Classic: one wide news column beside one support column ─────────────── */
@media (min-width: 900px) {
	.preset-classic .lead__main { grid-column: span 8; }
	.preset-classic .lead__side { grid-column: span 4; }
	.preset-classic .lead__rail { grid-column: span 4; }
}

@media (min-width: 1024px) {
	/* Three across rather than four, so each card gets more room. */
	.preset-classic .rail > * { grid-column: span 4; }
	.preset-classic .grid-posts > * { grid-column: span 4; }
}

@media (min-width: 1024px) {
	.preset-classic .bento--3,
	.preset-classic .bento--4 {
		grid-template-areas:
			"a a a a a a b b b b b b"
			"a a a a a a c c c d d d";
	}
	.preset-classic .bento--3 { grid-template-areas: "a a a a a a b b b b b b" "a a a a a a c c c c c c"; }
}

/* ── Magazine: image led, fewer and larger ───────────────────────────────── */
@media (min-width: 900px) {
	.preset-magazine .lead__main { grid-column: 1 / -1; }
	.preset-magazine .lead__side { grid-column: span 6; }
	.preset-magazine .lead__rail { grid-column: span 6; }
	.preset-magazine .lead__main .story__media { aspect-ratio: 21 / 9; }
	.preset-magazine .lead__main .story__title {
		font-size: clamp(2.5rem, 1.5rem + 4vw, 4.5rem);
	}
}

@media (min-width: 1024px) {
	/* Two across, so every picture is worth looking at. */
	.preset-magazine .rail > * { grid-column: span 6; }
	.preset-magazine .grid-posts > * { grid-column: span 6; }
	.preset-magazine .rail .story__media,
	.preset-magazine .grid-posts .story__media { aspect-ratio: 3 / 2; }
	.preset-magazine .rail .story__title,
	.preset-magazine .grid-posts .story__title {
		font-size: clamp(1.375rem, 1.1rem + 1.2vw, 1.9375rem);
	}
	.preset-magazine .bento--3,
	.preset-magazine .bento--4 { grid-template-areas: "a a a a a a b b b b b b" "c c c c c c d d d d d d"; }
	.preset-magazine .bento > * .story__media { aspect-ratio: 3 / 2; }
}

/* ── Compact: dense, wire-service front ──────────────────────────────────── */
@media (min-width: 900px) {
	.preset-compact .lead__main { grid-column: span 5; }
	.preset-compact .lead__side { grid-column: span 4; }
	.preset-compact .lead__rail { grid-column: span 3; }
	.preset-compact .lead__main .story__media { aspect-ratio: 3 / 2; }
	.preset-compact .lead__main .story__title {
		font-size: clamp(1.5rem, 1.1rem + 1.6vw, 2.25rem);
	}
}

@media (min-width: 1024px) {
	/* Six across, small pictures, headline doing the work. */
	.preset-compact .rail > * { grid-column: span 2; }
	.preset-compact .grid-posts > * { grid-column: span 3; }
	.preset-compact .rail .story__media,
	.preset-compact .grid-posts .story__media { aspect-ratio: 4 / 3; }
	.preset-compact .rail .story__title,
	.preset-compact .grid-posts .story__title { font-size: .9375rem; line-height: 1.25; }
	.preset-compact .bento > * { grid-column: span 3 !important; grid-row: auto !important; }
	.preset-compact .bento { grid-template-areas: none; }
	.preset-compact .bento > * .story__media { aspect-ratio: 4 / 3; }
	.preset-compact .bento > *:nth-child(1) .story__title { font-size: 1.0625rem; }
}

.preset-compact { --space-section: clamp(var(--s-4), 1.5rem + 3vw, var(--s-8)); }

/* ── Reader: text first ──────────────────────────────────────────────────── */
.preset-reader .hero,
.preset-reader .ticker { display: none; }

@media (min-width: 900px) {
	.preset-reader .lead__main { grid-column: 2 / span 7; }
	.preset-reader .lead__side { grid-column: 2 / span 7; }
	.preset-reader .lead__rail { grid-column: 10 / -1; }
}

@media (min-width: 1024px) {
	/* Single column of headlines with standfirsts, no card grid. */
	.preset-reader .rail > *,
	.preset-reader .grid-posts > * { grid-column: 2 / span 7; }
	.preset-reader .bento > * { grid-column: 2 / span 7 !important; grid-row: auto !important; }
	.preset-reader .bento { grid-template-areas: none; }
	.preset-reader .beatindex > * { grid-column: span 4; }
}

/*
 * Pictures are demoted rather than removed: a news page with no images at all
 * reads as broken, but in this preset they should never lead.
 *
 * The grid-area assignments MUST be scoped to exactly the same parents that
 * declare the template areas. Scoping the template to .rail and .grid-posts
 * but the areas to every .story put area names on cards whose parent never
 * defined them, and every child of those cards landed in the same implicit
 * cell, stacked on top of each other.
 */
@media (min-width: 1024px) {
	.preset-reader .rail .story,
	.preset-reader .grid-posts .story,
	.preset-reader .bento .story {
		grid-template-columns: minmax(0, 1fr) 12rem;
		grid-template-areas:
			"chip  media"
			"title media"
			"dek   media"
			"foot  media";
		column-gap: var(--s-3);
		align-items: start;
	}

	.preset-reader .rail .story .story__media,
	.preset-reader .grid-posts .story .story__media,
	.preset-reader .bento .story .story__media { grid-area: media; aspect-ratio: 4 / 3; }

	.preset-reader .rail .story .story__kicker,
	.preset-reader .grid-posts .story .story__kicker,
	.preset-reader .bento .story .story__kicker { grid-area: chip; }

	.preset-reader .rail .story .story__title,
	.preset-reader .grid-posts .story .story__title,
	.preset-reader .bento .story .story__title { grid-area: title; }

	.preset-reader .rail .story .t-dek,
	.preset-reader .grid-posts .story .t-dek,
	.preset-reader .bento .story .t-dek { grid-area: dek; }

	.preset-reader .rail .story .story__foot,
	.preset-reader .grid-posts .story .story__foot,
	.preset-reader .bento .story .story__foot { grid-area: foot; }
}

/* ── 11  FOOTER ───────────────────────────────────────────────────────────── */

.site-footer {
	background: var(--surface-invert);
	color: var(--ink-invert);
	padding-block: var(--space-section) 2rem;
}

html[data-theme="dark"] .site-footer,
html:not([data-theme="light"]) .site-footer {
	border-block-start: 1px solid var(--rule);
}

.footer__grid {
	display: grid;
	grid-template-columns: repeat(var(--grid-cols), minmax(0, 1fr));
	gap: var(--s-6) var(--grid-gap);
}

.footer__grid > * { grid-column: 1 / -1; }

/*
 * The footer sits on the same 12 columns as everything above it, but it has
 * either three children or four depending on whether the service links
 * resolved, so it needs two layouts.
 *
 * :nth-child(1):nth-last-child(4) matches the first child only when there are
 * exactly four of them, which is how a stylesheet counts its own children
 * without :has() and without the markup telling it.
 */

/* Three columns: 5 + 3 + 4. */
@media (min-width: 860px) {
	.footer__grid > *:nth-child(1) { grid-column: span 5; }
	.footer__grid > *:nth-child(2) { grid-column: span 3; }
	.footer__grid > *:nth-child(3) { grid-column: span 4; }
}

/*
 * Four columns at a middling width would give the two link columns about
 * 120px each, which breaks "Submit news" over two lines. So they pair up into
 * two rows of two first, and only spread into one row once there is room.
 */
@media (min-width: 860px) and (max-width: 1179px) {
	.footer__grid > *:nth-child(1):nth-last-child(4),
	.footer__grid > *:nth-child(1):nth-last-child(4) ~ * {
		grid-column: span 6;
	}
}

/* Four columns: 4 + 2 + 2 + 4. */
@media (min-width: 1180px) {
	.footer__grid > *:nth-child(1):nth-last-child(4) { grid-column: span 4; }
	.footer__grid > *:nth-child(1):nth-last-child(4) ~ *:nth-child(2) { grid-column: span 2; }
	.footer__grid > *:nth-child(1):nth-last-child(4) ~ *:nth-child(3) { grid-column: span 2; }
	.footer__grid > *:nth-child(1):nth-last-child(4) ~ *:nth-child(4) { grid-column: span 4; }
}

.footer__brand img { height: 38px; width: auto; }

/*
 * The footer sits on navy, so the brand lockup cannot inherit the light-mode
 * ink token or it renders navy on navy and disappears.
 */
.footer__brand .brand__word { color: var(--ink-invert); }
.footer__brand .brand__mark { height: 44px; }

.footer__tagline {
	margin-block-start: 1rem;
	font-family: var(--font-read);
	font-size: 1.0625rem;
	line-height: 1.5;
	color: var(--ink-invert-soft);
	max-width: 34ch;
}

.footer__col-title {
	font-size: .75rem;
	font-weight: 800;
	letter-spacing: .11em;
	text-transform: uppercase;
	color: var(--accent);
	margin-block-end: 1rem;
}

.footer__list { display: grid; gap: .625rem; }

.footer__list a {
	font-size: .9375rem;
	font-weight: 500;
	text-decoration: none;
	color: var(--ink-invert-soft);
	transition: color var(--dur) var(--ease);
}

.footer__list a:hover { color: var(--accent); }

.footer__social {
	display: flex;
	gap: .5rem;
	margin-block-start: 1.5rem;
}

.footer__social a {
	display: grid;
	place-items: center;
	width: 40px;
	height: 40px;
	color: var(--ink-invert);
	border: 1px solid rgba(255, 255, 255, .2);
	transition: background var(--dur) var(--ease), color var(--dur) var(--ease),
		border-color var(--dur) var(--ease);
}

.footer__social a:hover {
	background: var(--accent);
	color: #002038;
	border-color: var(--accent);
}

.footer__social svg { width: 18px; height: 18px; }

.footer__base {
	margin-block-start: var(--space-block);
	padding-block-start: 1.5rem;
	border-block-start: 1px solid rgba(255, 255, 255, .16);
	display: flex;
	flex-wrap: wrap;
	gap: .75rem 1.5rem;
	align-items: center;
	justify-content: space-between;
}

.footer__base p,
.footer__base a {
	font-size: .8125rem;
	color: var(--ink-invert-soft);
	text-decoration: none;
}

.footer__base a:hover { color: var(--accent); }


/* ── 12  FORMS ────────────────────────────────────────────────────────────
   Label above input, helper below, error below that. Never placeholder-as-label.
   Every colour here is contrast-checked against its own section background.
   ------------------------------------------------------------------------ */

.field {
	display: grid;
	gap: .5rem;
}

.field__label {
	font-family: var(--font-ui);
	font-size: .8125rem;
	font-weight: 700;
	letter-spacing: .02em;
	color: var(--ink);
}

.field__input {
	width: 100%;
	padding: .8125rem 1rem;
	background: var(--paper);
	color: var(--ink);
	border: 1px solid var(--rule-strong);
	transition: border-color var(--dur) var(--ease);
}

.field__input::placeholder { color: var(--ink-meta); opacity: 1; }
.field__input:hover { border-color: var(--ink-meta); }
.field__input:focus { border-color: var(--accent); }

.field__help {
	font-size: .75rem;
	color: var(--ink-meta);
}

.field__error {
	font-size: .8125rem;
	font-weight: 600;
	color: #b3261e;
}

html[data-theme="dark"] .field__error,
html:not([data-theme="light"]) .field__error { color: #ffb4ab; }

/* On the navy footer the form needs its own contrast-safe treatment. */
.footer .field__label { color: var(--ink-invert); }
.footer .field__help { color: var(--ink-invert-soft); }

.signup {
	display: grid;
	gap: .75rem;
}

@media (min-width: 480px) {
	.signup__row { display: grid; grid-template-columns: 1fr auto; gap: .5rem; }
}

/*
 * Scoped to the footer, not to .signup.
 *
 * These are inverted colours for the navy footer: near-white text in a
 * near-transparent white well. Unscoped, they applied to the signup form
 * anywhere it appeared — and the moment the newsletter widget put that form
 * in a light sidebar it rendered near-white text on near-white paper, which
 * is invisible and an accessibility failure.
 *
 * A rule that assumes a background belongs to the thing that provides the
 * background, so it lives with the footer now, and .field__input's own light
 * colours apply everywhere else.
 */
.site-footer .signup .field__input,
.footer .signup .field__input {
	background: rgba(255, 255, 255, .07);
	border-color: rgba(255, 255, 255, .28);
	color: var(--ink-invert);
}

.site-footer .signup .field__input::placeholder,
.footer .signup .field__input::placeholder { color: #b8ccdb; }

.site-footer .signup .field__input:hover,
.footer .signup .field__input:hover { border-color: rgba(255, 255, 255, .5); }

.signup .field__input:focus { border-color: var(--accent); }

.searchform {
	display: grid;
	grid-template-columns: 1fr auto;
	gap: .5rem;
	max-width: 32rem;
}


/* ── 13  MOTION ───────────────────────────────────────────────────────────
   MOTION_INTENSITY 4. Two things move, and each earns it:
     1. Sections rise into view once, which paces a long front page.
     2. Cards respond to hover and press, which confirms they are targets.
   No parallax, no scroll hijack, no marquee, no infinite loops.
   Everything below collapses to static under prefers-reduced-motion.
   ------------------------------------------------------------------------ */

@media (prefers-reduced-motion: no-preference) {
	.reveal {
		opacity: 0;
		transform: translateY(18px);
		transition: opacity .6s var(--ease), transform .6s var(--ease);
		transition-delay: calc(var(--i, 0) * 70ms);
		will-change: opacity, transform;
	}

	.reveal.is-in {
		opacity: 1;
		transform: none;
		will-change: auto;
	}
}

/* If JS never runs, content must still be visible. */
.no-js .reveal { opacity: 1; transform: none; }


/* ── 14  PRINT ────────────────────────────────────────────────────────────── */

@media print {
	.masthead,
	.beats,
	.drawer,
	.site-footer,
	.postnav,
	.section--related { display: none !important; }

	body { background: #fff; color: #000; }

	.article-body { max-width: none; font-size: 11pt; line-height: 1.45; }
	.article-body a { text-decoration: underline; }
	.article-body a::after { content: " (" attr(href) ")"; font-size: 9pt; }
}
