/*
Theme Name:   Allyssa Lanctot
Description:  GeneratePress child theme for Allyssa Lanctot's portfolio site,
              in the "Ledger" design. Clips, case studies, sectors and roles
              live in the nlv-core plugin's portfolio module, so the content
              survives a theme switch. Registers no post types.
Author:       NovelLogic
Author URI:   https://novellogic.ca
Template:     generatepress
Version:      0.6.2
Requires at least: 6.5
Tested up to: 7.1
Requires PHP: 8.1
License:      GPL-2.0-or-later
License URI:  https://www.gnu.org/licenses/gpl-2.0.html
Text Domain:  nlv-lanctot
*/

/* ---------------------------------------------------------------------------
 * NO Theme URI HEADER, DELIBERATELY - it would publish the repository host and
 * owner account from a file that ships in the webroot. Do not add one.
 *
 * ---------------------------------------------------------------------------
 * EVERY COLOUR IS A CUSTOM PROPERTY, AND EVERY CUSTOM PROPERTY IS theme.json.
 *
 * There is no hex literal anywhere in this file - the harness fails on one.
 * The six tokens below are the Ledger palette; their values are theme.json
 * presets, light and dark both, so a colour is changed in exactly one place.
 *
 * DARK MODE is data-theme="dark" on <html>, set client-side before first paint
 * (inc/head.php) and by the toggle (assets/js/theme.js). The media-query block
 * is the no-script path: with no data-theme at all, the system setting still
 * decides. Nothing about the scheme is decided server-side, so every visitor
 * gets the same cacheable page.
 *
 * CONTRAST, measured (WCAG 2.x relative luminance), on the paper ground and
 * on the band tint:
 *   light       ink 16.4:1, soft 8.4:1, mute 5.4:1, accent  7.3:1 on #FAF8F4
 *   light tint  ink 15.0:1, soft 7.7:1, mute 4.9:1, accent  6.7:1 on #F2EEE7
 *   dark        ink 15.7:1, soft 9.7:1, mute 5.6:1, accent  7.2:1 on #121110
 *   dark tint   ink 14.7:1, soft 9.2:1, mute 5.3:1, accent  6.8:1 on #1A1816
 * Every text colour clears 4.5:1 on both grounds in both modes, so the
 * accent is allowed at any size. (Mute went #6E6E6E -> #686664 in round 1.1:
 * the old grey was 4.4:1 on the tint.) render-live measures the rendered
 * pages and records it again.
 *
 * NO COLOUR TRANSITIONS. The scheme switch flips every token in one style
 * recalc; a transition on body left the text grey for half a second on each
 * switch (round 1). Nothing here animates a colour.
 *
 * TWO FAMILIES: Libre Caslon Condensed for everything read, Hanken Grotesk
 * for everything that labels (nav, section labels, meta, dates, counts,
 * chips, fact keys, the foot) - sentence case, 13-15px, a little tracking,
 * the mute colour. Nothing on the site reads as terminal type.
 * ------------------------------------------------------------------------ */

:root {
	--lt-bg: var(--wp--preset--color--bg);
	--lt-tint: var(--wp--preset--color--tint);
	--lt-ink: var(--wp--preset--color--ink);
	--lt-soft: var(--wp--preset--color--soft);
	--lt-mute: var(--wp--preset--color--mute);
	--lt-rule: var(--wp--preset--color--rule);
	--lt-accent: var(--wp--preset--color--accent);
	--lt-meta: var(--lt-mute);
	--lt-pad: clamp(20px, 5vw, 72px);
	--lt-top-h: 72px;
	--lt-serif: var(--wp--preset--font-family--serif);
	--lt-sans: var(--wp--preset--font-family--sans);
	color-scheme: light;
}

:root[data-theme="dark"] {
	--lt-bg: var(--wp--preset--color--dark-bg);
	--lt-tint: var(--wp--preset--color--dark-tint);
	--lt-ink: var(--wp--preset--color--dark-ink);
	--lt-soft: var(--wp--preset--color--dark-soft);
	--lt-mute: var(--wp--preset--color--dark-mute);
	--lt-rule: var(--wp--preset--color--dark-rule);
	--lt-accent: var(--wp--preset--color--dark-accent);
	--lt-meta: var(--lt-soft);
	color-scheme: dark;
}

@media (prefers-color-scheme: dark) {
	:root:not([data-theme]) {
		--lt-bg: var(--wp--preset--color--dark-bg);
		--lt-tint: var(--wp--preset--color--dark-tint);
		--lt-ink: var(--wp--preset--color--dark-ink);
		--lt-soft: var(--wp--preset--color--dark-soft);
		--lt-mute: var(--wp--preset--color--dark-mute);
		--lt-rule: var(--wp--preset--color--dark-rule);
		--lt-accent: var(--wp--preset--color--dark-accent);
		--lt-meta: var(--lt-soft);
		color-scheme: dark;
	}
}

/* ---------------------------------------------------------------------------
 * The parent's frame, out of the way. GeneratePress wraps everything in a
 * 1200px container with padded, white "separate containers"; the ledger is
 * full-bleed with its own gutter (--lt-pad).
 * ------------------------------------------------------------------------ */

/*
 * An anchor (About, Contact) lands with its section's top rule EXACTLY on the
 * header's bottom rule: one hairline, no strip. Round 1 padded every page for
 * the coverage filter bar, which left a 16px (desktop) / 76px (phone) band
 * with two hairlines above the section. Only a page that HAS the sticky bar
 * pads for it (see the 860px block).
 */
html {
	background: var(--lt-bg);
	-webkit-text-size-adjust: 100%;
	scroll-padding-top: calc(var(--lt-top-h) - 1px);
}

body.lt {
	margin: 0;
	background: var(--lt-bg);
	color: var(--lt-ink);
	font-family: var(--lt-serif);
	font-size: 20px;
	line-height: 1.45;
}

body.lt .site.grid-container,
body.lt .grid-container {
	max-width: none;
	padding: 0;
}

body.lt .site-content {
	display: block;
	padding: 0;
}

body.lt .content-area,
body.lt .site-main,
body.lt .inside-article,
body.lt .entry-content,
body.lt article.page,
body.lt .separate-containers .inside-article {
	margin: 0;
	padding: 0;
	background: transparent;
	width: auto;
	float: none;
}

body.lt .entry-content > *,
body.lt .entry-header {
	margin-top: 0;
}

body.lt .entry-header {
	display: none;
}

body.lt a {
	color: inherit;
	text-decoration-thickness: 1px;
	text-underline-offset: 4px;
}

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

/*
 * GeneratePress puts a .1s colour transition on every link, button and
 * input. Off: the scheme switch must land in one frame (round 1).
 */
body.lt a,
body.lt button,
body.lt input,
body.lt summary {
	transition: none;
}

body.lt :focus-visible {
	outline: 2px solid var(--lt-accent);
	outline-offset: 3px;
}

body.lt [hidden] {
	display: none !important;
}

.lt-ico {
	width: .7em;
	height: .7em;
	vertical-align: baseline;
}

/*
 * The label face. Everything that labels rather than reads.
 */
.lt-label,
.lt-count,
.lt-more,
.lt-back,
.lt-foot,
.lt-nav,
.lt-top__home,
.lt-row__a small,
.lt-row__b small,
.lt-row__c,
.lt-intro__meta,
.lt-fact__k,
.lt-chip,
.lt-toggle,
.lt-details summary,
.lt-outlets,
.lt-reels,
.lt-totop {
	font-family: var(--lt-sans);
	font-size: 14px;
	letter-spacing: .02em;
	font-weight: 400;
	line-height: 1.45;
}

.lt-label,
.lt-back,
.lt-foot {
	color: var(--lt-mute);
}

/*
 * Small meta under and beside the rows (sector, client · date, counts, fact
 * keys) is --lt-meta: the mute grey in light, the soft tone in DARK, where
 * grey-on-near-black at 14px read faint (round 1.1). Soft in dark is 9.7:1
 * on paper and 9.2:1 on the band.
 */
.lt-count,
.lt-row__a small,
.lt-row__b small,
.lt-row__c,
.lt-fact__k,
.lt-details summary {
	color: var(--lt-meta);
}

/* ---------------------------------------------------------------------------
 * Header. One row at every width, --lt-top-h tall: 72px, and 64px on a phone.
 * ------------------------------------------------------------------------ */

.lt-top {
	position: sticky;
	top: 0;
	z-index: 10;
	box-sizing: border-box;
	height: var(--lt-top-h);
	background: var(--lt-bg);
	display: flex;
	flex-wrap: nowrap;
	justify-content: space-between;
	align-items: center;
	gap: 24px;
	padding: 0 var(--lt-pad);
	border-bottom: 1px solid var(--lt-rule);
}

.admin-bar .lt-top {
	top: 32px;
}

@media (max-width: 782px) {
	.admin-bar .lt-top {
		top: 46px;
	}
}

.lt-top__home {
	display: inline-flex;
	align-items: center;
	min-height: 44px;
	text-decoration: none;
	font-size: 15px;
	font-weight: 500;
	white-space: nowrap;
	color: var(--lt-ink);
}

.lt-top__mono {
	display: none;
}

.lt-nav {
	display: flex;
	align-items: center;
	gap: 22px;
	min-width: 0;
	font-size: 15px;
}

.lt-nav a,
.lt-toggle {
	display: inline-flex;
	align-items: center;
	min-height: 44px;
	text-decoration: none;
	white-space: nowrap;
	color: var(--lt-soft);
}

.lt-nav a.is-current {
	color: var(--lt-accent);
}

/*
 * The toggle is a nav link that happens to be a button: no box, no fill, in
 * either scheme. 44px square at least, for the tap.
 */
.lt-toggle {
	gap: 6px;
	min-width: 44px;
	justify-content: center;
	padding: 0;
	margin: 0;
	background: none;
	border: 0;
	border-radius: 0;
	font-size: 15px;
	cursor: pointer;
}

body.lt .lt-toggle:hover,
body.lt .lt-toggle:focus {
	background: none;
	color: var(--lt-accent);
}

.lt-toggle .lt-ico {
	width: 14px;
	height: 14px;
}

/* ---------------------------------------------------------------------------
 * Hero
 * ------------------------------------------------------------------------ */

.lt-hero {
	padding: clamp(56px, 9vw, 140px) var(--lt-pad) clamp(40px, 6vw, 88px);
}

.lt-name {
	margin: 0;
	font-family: var(--lt-serif);
	font-weight: 400;
	font-size: clamp(64px, 15.4vw, 232px);
	line-height: .86;
	letter-spacing: -.02em;
	overflow: hidden;
	color: var(--lt-ink);
}

.lt-name span {
	display: inline-block;
}

@media (prefers-reduced-motion: no-preference) {
	.lt-name span {
		animation: lt-rise .9s cubic-bezier(.2, .8, .2, 1) both;
	}

	.lt-name span:nth-child(2) {
		animation-delay: .08s;
	}

	@keyframes lt-rise {
		from {
			transform: translateY(100%);
		}

		to {
			transform: none;
		}
	}
}

.lt-intro {
	margin-top: clamp(32px, 4vw, 56px);
	display: grid;
	grid-template-columns: 1fr 3fr;
	gap: 24px 48px;
}

.lt-intro__meta {
	display: flex;
	flex-direction: column;
	gap: 4px;
	font-size: 15px;
}

/* The role line reads first: ink, 500. The company line under it: soft. */
.lt-intro__meta > :first-child {
	color: var(--lt-ink);
	font-weight: 500;
}

.lt-intro__meta > :not(:first-child) {
	color: var(--lt-soft);
}

.lt-intro p {
	margin: 0;
	font-size: clamp(24px, 2.3vw, 32px);
	line-height: 1.3;
	max-width: 30ch;
}

.lt-intro em {
	color: var(--lt-accent);
}

/* ---------------------------------------------------------------------------
 * The ledger: a 1/4 label column beside 3/4 rows, on every section.
 * ------------------------------------------------------------------------ */

.lt-sec {
	display: grid;
	grid-template-columns: 1fr 3fr;
	gap: 24px 48px;
	padding: clamp(48px, 6vw, 88px) var(--lt-pad);
	border-top: 1px solid var(--lt-rule);
}

/*
 * Section labels: numbered per page, in order, in the accent, under a short
 * accent rule ("01 — Recognition"). The number is a CSS counter, so every
 * template numbers itself and a hidden section is not counted. The rule is a
 * background, so it takes no box of its own; margin and padding net to the
 * old 6px, so the label's text still sits where it did beside the first row.
 * 15px / 500 (round 1.1), one step up from the other labels: the accent at
 * 14px / 400 read thin on the dark ground. Accent is 7.2:1 (dark paper) and
 * 6.8:1 (dark band); 7.3:1 and 6.7:1 in light.
 */
body.lt {
	counter-reset: lt-sec;
}

.lt-sec > .lt-label {
	margin: -8px 0 0;
	padding-top: 14px;
	font-size: 15px;
	font-weight: 500;
	color: var(--lt-accent);
	counter-increment: lt-sec;
	background: linear-gradient(var(--lt-accent), var(--lt-accent)) no-repeat 0 0 / 24px 1px;
}

.lt-sec > .lt-label::before {
	content: counter(lt-sec, decimal-leading-zero) " — ";
}

/*
 * Bands: every other ledger section on a page is set on the tint, full
 * bleed, hairlines kept. On home that is Recognition, Selected coverage,
 * Education and Contact. nth-of-type counts the page's sibling <section>s,
 * the hero or page head included, so each template alternates from its top.
 */
.lt-sec:nth-of-type(even) {
	background: var(--lt-tint);
}

.lt-sec__body {
	min-width: 0;
}

.lt-rows {
	display: flex;
	flex-direction: column;
}

/*
 * The first column has a FIXED floor, 160px, so "Communications" (144px at
 * 22px) never breaks mid-word; "Senior Director, Communicati/ons" did at
 * 861-1050px (round 1). A fixed floor, not min-content: min-content would
 * size each row's grid to its own words and the b column would step.
 *
 * The third column is fixed too, for the same reason: every row is its own
 * grid, so an auto column sizes to that row's content and the columns before
 * it shift by a few pixels per row. 112px holds "Press release" and
 * "22 stations". render-live asserts the b column's left edge is identical
 * on every row.
 */
.lt-row {
	display: grid;
	grid-template-columns: minmax(160px, 1.2fr) minmax(0, 2.4fr) 112px;
	gap: 8px 32px;
	align-items: baseline;
	padding: 18px 0;
	text-decoration: none;
	color: inherit;
}

/*
 * ONE rule between rows, and none after the last: the section below draws
 * its own top rule, and two lines 18px apart read as a double divider
 * (round 1). The rule is a border-top on every VISIBLE row that follows a
 * visible row, so a filtered list is ruled correctly too.
 */
.lt-rows > .lt-row:not([hidden]) ~ .lt-row:not([hidden]),
.lt-sec__body > .lt-award ~ .lt-award {
	border-top: 1px solid var(--lt-rule);
}

.lt-rows > .lt-row:first-child {
	padding-top: 0;
}

.lt-row__a {
	font-size: 22px;
	line-height: 1.25;
	overflow-wrap: normal;
	word-break: normal;
	hyphens: manual;
}

.lt-row__a small,
.lt-row__b small {
	display: block;
	margin-top: 4px;
}

.lt-row__b {
	color: var(--lt-soft);
	min-width: 0;
}

.lt-row__c {
	white-space: nowrap;
	text-align: right;
}

a.lt-row:hover .lt-row__a,
.lt-row__link:hover {
	color: var(--lt-accent);
}

body.lt a.lt-row:hover {
	color: inherit;
}

.lt-row__link {
	text-decoration: none;
}

.lt-more-n {
	color: var(--lt-mute);
	white-space: nowrap;
}

.lt-more {
	margin-top: 24px;
	display: inline-flex;
	align-items: center;
	min-height: 44px;
	color: var(--lt-ink);
}

button.lt-more {
	padding: 0;
	background: none;
	border: 0;
	text-decoration: underline;
	text-decoration-thickness: 1px;
	text-underline-offset: 4px;
	cursor: pointer;
}

body.lt button.lt-more:hover,
body.lt button.lt-more:focus {
	background: none;
	color: var(--lt-accent);
}

.lt-empty {
	margin: 0 0 12px;
	color: var(--lt-soft);
}

/* A story's full outlet list, behind <details> so it opens without scripts. */

.lt-details {
	margin-top: 6px;
}

.lt-details summary {
	display: inline-flex;
	align-items: center;
	min-height: 44px;
	cursor: pointer;
	list-style: none;
	text-decoration: underline;
	text-decoration-thickness: 1px;
	text-underline-offset: 4px;
}

.lt-details summary::-webkit-details-marker {
	display: none;
}

.lt-details summary:hover {
	color: var(--lt-accent);
}

.lt-outlets {
	margin: 4px 0 0;
	padding: 0;
	list-style: none;
	color: var(--lt-soft);
	font-size: 15px;
}

.lt-outlets li {
	padding: 6px 0;
}

.lt-outlet {
	color: var(--lt-ink);
	font-weight: 500;
}

.lt-outlets small {
	display: inline;
	margin: 0;
	color: var(--lt-mute);
	font-size: 14px;
}

.lt-reels {
	margin: 8px 0 0;
	display: flex;
	flex-direction: column;
	gap: 4px;
	font-size: 15px;
}

/* Recognition */

.lt-award {
	display: flex;
	flex-direction: column;
	gap: 6px;
	padding: 20px 0;
}

.lt-award:first-child {
	padding-top: 0;
}

.lt-award strong {
	font-weight: 400;
	font-size: clamp(28px, 3vw, 40px);
	line-height: 1.1;
}

.lt-award.is-lead strong {
	font-size: clamp(36px, 4.2vw, 56px);
}

.lt-award span {
	color: var(--lt-soft);
}

/* About, with the portrait: a third of the content column, the text beside it. */

.lt-about__grid {
	display: grid;
	grid-template-columns: minmax(0, 1fr) minmax(0, 2fr);
	gap: 24px 48px;
	align-items: start;
}

.lt-about__grid:not(:has(.lt-portrait)) {
	grid-template-columns: 1fr;
}

.lt-portrait {
	margin: 0;
	max-width: 85%;
}

/*
 * 4:5, cropped from the top so her face stays centred. The width and height
 * attributes (800x800) reserve the space before the file arrives; this
 * aspect-ratio then overrides their square, still before any byte loads, so
 * nothing shifts. 85% of its third of the column (round 1.1), a 3px radius,
 * full colour, no filter.
 */
.lt-portrait img {
	display: block;
	width: 100%;
	height: auto;
	aspect-ratio: 4 / 5;
	object-fit: cover;
	object-position: 50% 0;
	border-radius: 3px;
}

.lt-about p {
	margin: 0 0 20px;
	font-size: 24px;
	line-height: 1.4;
	max-width: 34ch;
}

/* Contact */

.lt-contact {
	display: grid;
	grid-template-columns: repeat(2, minmax(0, 1fr));
	gap: 24px 48px;
}

.lt-contact__links {
	display: flex;
	flex-direction: column;
	gap: 12px;
	font-size: 22px;
}

.lt-contact__links a {
	overflow-wrap: anywhere;
}

.lt-contact__where {
	display: flex;
	flex-direction: column;
	gap: 6px;
	color: var(--lt-soft);
}

.lt-foot {
	padding: 28px var(--lt-pad) 40px;
	display: flex;
	justify-content: space-between;
	gap: 12px;
	flex-wrap: wrap;
	border-top: 1px solid var(--lt-rule);
	font-size: 13px;
}

/* ---------------------------------------------------------------------------
 * Page heads: /coverage/, /work/, a case study, 404. The same shape on all of
 * them: the title FIRST, in DOM and on screen, in the content column (the
 * 3/4 that the rows below use), then its intro and meta, then any filters.
 * ------------------------------------------------------------------------ */

.lt-pagehead,
.lt-cshead {
	padding: clamp(48px, 7vw, 104px) var(--lt-pad) 40px;
	display: grid;
	grid-template-columns: 1fr 3fr;
	gap: 24px 48px;
}

.lt-pagehead__main,
.lt-cshead__main {
	grid-column: 2;
	min-width: 0;
}

.lt-cshead__aside {
	grid-column: 1;
	grid-row: 1;
	padding-top: 6px;
}

/*
 * padding-bottom makes room for descenders. At line-height .88 the "g" of
 * "Coverage" hangs well below the line box. Padding, in em, scales with the
 * clamp.
 */
.lt-pagehead h1,
.lt-cshead h1 {
	margin: 0;
	padding-bottom: .16em;
	font-family: var(--lt-serif);
	font-weight: 400;
	font-size: clamp(64px, 10vw, 160px);
	line-height: .88;
	letter-spacing: -.02em;
	color: var(--lt-ink);
}

.lt-cshead h1 {
	font-size: clamp(52px, 8vw, 128px);
	line-height: .9;
	max-width: 14ch;
}

.lt-pagehead p {
	margin: 14px 0 0;
	color: var(--lt-soft);
	max-width: 44ch;
}

.lt-pagehead p.lt-count {
	max-width: none;
}

.lt-back {
	display: inline-flex;
	align-items: center;
	gap: 6px;
	min-height: 44px;
	text-decoration: none;
}

.lt-filterbar {
	display: grid;
	grid-template-columns: 1fr 3fr;
	gap: 12px 48px;
	padding: 0 var(--lt-pad) 32px;
	background: var(--lt-bg);
}

.lt-filterbar > .lt-chips {
	grid-column: 2;
}

/* Tighter than round 1, so the sector chips sit on ONE row at 1440 (round 2). */
.lt-chips {
	display: flex;
	flex-wrap: wrap;
	gap: 6px;
}

.lt-chip {
	background: none;
	color: var(--lt-soft);
	border: 1px solid var(--lt-rule);
	border-radius: 0;
	padding: 0 10px;
	min-height: 44px;
	white-space: nowrap;
	cursor: pointer;
}

body.lt .lt-chip:hover,
body.lt .lt-chip:focus {
	background: none;
	color: var(--lt-ink);
	border-color: var(--lt-ink);
}

body.lt .lt-chip.is-on,
body.lt .lt-chip.is-on:hover {
	background: var(--lt-ink);
	color: var(--lt-bg);
	border-color: var(--lt-ink);
}

.lt-chip [data-n]:empty {
	display: none;
}


.lt-totop {
	position: fixed;
	right: var(--lt-pad);
	bottom: 20px;
	z-index: 9;
	display: inline-flex;
	align-items: center;
	gap: 6px;
	min-height: 44px;
	padding: 0 14px;
	background: var(--lt-bg);
	border: 1px solid var(--lt-rule);
	color: var(--lt-ink);
	text-decoration: none;
}

/* ---------------------------------------------------------------------------
 * Case study
 * ------------------------------------------------------------------------ */

.lt-facts {
	display: flex;
	flex-wrap: wrap;
	gap: 20px 64px;
	margin-top: 40px;
	padding-top: 20px;
	border-top: 1px solid var(--lt-rule);
}

.lt-fact {
	display: flex;
	flex-direction: column;
	gap: 6px;
}

/*
 * The facts are core/group blocks, and WordPress's flow layout gives every
 * child but the first a margin-block-start (the block gap). The flex gap owns
 * the spacing here; the layout's margins are zeroed at both levels.
 */
body.lt .lt-facts > *,
body.lt .lt-fact > *,
body.lt .lt-fact p {
	margin: 0;
	margin-block-start: 0;
}

/*
 * 20px Caslon Condensed at 48ch is about 63 characters a line, inside the
 * 60-70 a body column wants (round 1: it was 23px at 36ch, ~47).
 */
.lt-body p {
	margin: 0 0 20px;
	font-size: 20px;
	line-height: 1.5;
	max-width: 48ch;
}

/* ---------------------------------------------------------------------------
 * Round 2: outlet logos, sector drawings, the case-study band and pull-stat,
 * and the folds.
 * ------------------------------------------------------------------------ */

/*
 * A logo is a mask painted with currentColor (inc/logos.php): soft at rest,
 * the accent on hover, ink in a story row. The mark's size is set inline,
 * from the manifest; the file is an alpha shape, so no mask-mode is needed.
 */
.lt-logo {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	color: var(--lt-soft);
	text-decoration: none;
}

body.lt a.lt-logo:hover {
	color: var(--lt-accent);
}

.lt-logo__mark {
	display: block;
	max-width: 100%;
	background: currentColor;
	-webkit-mask: var(--logo) no-repeat center / contain;
	mask: var(--logo) no-repeat center / contain;
}

/* Home, "Where it ran": a hairline grid, four across (three on a phone). */
.lt-logos {
	display: grid;
	grid-template-columns: repeat(4, minmax(0, 1fr));
	border-top: 1px solid var(--lt-rule);
	border-left: 1px solid var(--lt-rule);
}

.lt-logos .lt-logo {
	display: flex;
	min-height: 104px;
	padding: 16px 20px;
	border-right: 1px solid var(--lt-rule);
	border-bottom: 1px solid var(--lt-rule);
}

/* A story row's outlet line: up to three logos, then "+N more". */
.lt-rowlogos {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 10px 24px;
	min-height: 28px;
}

.lt-logo--row {
	color: var(--lt-ink);
}

.lt-rowlogos .lt-more-n {
	font-family: var(--lt-sans);
	font-size: 14px;
	letter-spacing: .02em;
	color: var(--lt-meta);
}

/* Case-study rows (home, /work/): the sector drawing leads, in a fourth cell. */
.lt-row--art {
	grid-template-columns: 88px minmax(160px, 1.2fr) minmax(0, 2.4fr) 112px;
	align-items: center;
}

.lt-row__art {
	display: block;
	width: 88px;
	height: 88px;
	box-sizing: border-box;
	background: var(--lt-tint);
	color: var(--lt-mute);
	border: 1px solid var(--lt-rule);
}

.lt-sec:nth-of-type(even) .lt-row__art {
	background: var(--lt-bg);
}

.lt-art {
	display: block;
	width: 100%;
	height: 100%;
}

.lt-art * {
	vector-effect: non-scaling-stroke;
}

.lt-art .a {
	stroke: var(--lt-accent);
	opacity: 1;
}

.lt-rows--tight > .lt-row {
	padding: 12px 0;
}

.lt-rows--tight > .lt-row:first-child {
	padding-top: 0;
}

/* A list behind one line: a case study's later stories, the press releases. */
.lt-fold {
	margin-top: 12px;
}

.lt-fold > .lt-rows {
	margin-top: 12px;
}

/* A case study's head, under the facts: the pull-stat, or where it ran. */
.lt-pull {
	margin: 32px 0 0;
	display: flex;
	align-items: baseline;
	flex-wrap: wrap;
	gap: 4px 16px;
}

.lt-pull__n {
	font-size: clamp(56px, 6vw, 88px);
	line-height: 1;
	letter-spacing: -.01em;
	color: var(--lt-accent);
}

.lt-pull__l,
.lt-ran__k {
	font-family: var(--lt-sans);
	font-size: 15px;
	letter-spacing: .02em;
	color: var(--lt-meta);
}

.lt-ran {
	margin-top: 32px;
}

.lt-ran__k {
	margin: 0 0 12px;
	font-size: 14px;
}

.lt-ran__logos {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 16px 36px;
}

/*
 * The band under a case study's head: full bleed, about 180px on a desktop.
 * The sector's light and dark images share one grid cell; the other
 * scheme's is visibility:hidden, not display:none, so it is laid out and
 * fetched too and a toggle swaps in the same frame (no flash, no fetch). The
 * crop is object-fit: cover, positioned per image from inc/case-study.php.
 * No image: the sector drawing.
 */
.lt-band {
	display: grid;
	height: clamp(112px, 12.5vw, 180px);
	overflow: hidden;
	border-top: 1px solid var(--lt-rule);
	background: var(--lt-tint);
}

.lt-band__img {
	grid-area: 1 / 1;
	display: block;
	width: 100%;
	height: 100%;
	min-height: 0;
	object-fit: cover;
}

.lt-band__img--dark,
:root[data-theme="dark"] .lt-band__img--light {
	visibility: hidden;
}

:root[data-theme="dark"] .lt-band__img--dark {
	visibility: visible;
}

@media (prefers-color-scheme: dark) {
	:root:not([data-theme]) .lt-band__img--light {
		visibility: hidden;
	}

	:root:not([data-theme]) .lt-band__img--dark {
		visibility: visible;
	}
}

.lt-band--art {
	color: var(--lt-mute);
}

/* ---------------------------------------------------------------------------
 * Round 3: the About page and client logos (inc/clients.php).
 * ------------------------------------------------------------------------ */

/*
 * A client logo is the same mask as an outlet logo, painted soft and the
 * accent on hover. In a row it fills the art cell the drawing would; beside a
 * case study's title it sits at the title's foot, and wraps under it on a
 * narrow screen.
 */
.lt-client-art {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 100%;
	height: 100%;
	padding: 8px;
	box-sizing: border-box;
	color: var(--lt-soft);
}

a.lt-row:hover .lt-client-art {
	color: var(--lt-accent);
}

/* One line with the title on a desktop: the title gives way, the mark does not. */
.lt-cshead__title {
	display: flex;
	align-items: flex-end;
	justify-content: space-between;
	gap: 20px 48px;
}

.lt-cshead__title h1 {
	min-width: 0;
}

.lt-cshead__client {
	display: flex;
	flex: none;
	padding-bottom: 14px;
	color: var(--lt-soft);
}

/* The Clients wall: a hairline grid, three across at every width. */
.lt-clients {
	display: grid;
	grid-template-columns: repeat(3, minmax(0, 1fr));
	border-top: 1px solid var(--lt-rule);
	border-left: 1px solid var(--lt-rule);
}

.lt-client {
	display: flex;
	align-items: center;
	justify-content: center;
	min-height: 128px;
	padding: 20px;
	border-right: 1px solid var(--lt-rule);
	border-bottom: 1px solid var(--lt-rule);
	text-align: center;
	text-decoration: none;
	color: var(--lt-ink);
}

.lt-client--logo {
	color: var(--lt-soft);
}

body.lt a.lt-client:hover {
	color: var(--lt-accent);
}

.lt-client__name {
	font-size: 22px;
	line-height: 1.2;
}

/* About copy: the placeholder tag, and the teaser's line and link. */
.lt-ph {
	margin-right: .3em;
	font-family: var(--lt-sans);
	font-size: 15px;
	font-weight: 500;
	letter-spacing: .02em;
	color: var(--lt-accent);
}

/*
 * /about/'s copy (round 4.2): 34ch at 24px was ~35 characters a line, so How
 * I work ran 42 lines. 22px at 66ch is ~60-68 characters, the reading measure;
 * beside the portrait the Introduction takes the whole of its column.
 */
.lt-about:not(.lt-about--teaser) .lt-about__copy p {
	font-size: 22px;
	line-height: 1.5;
	max-width: 66ch;
}

.lt-about__more {
	margin-top: 4px;
}

.lt-about__more > p:first-of-type {
	margin-top: 16px;
}

.lt-about--teaser p {
	max-width: 40ch;
}

.lt-about__copy .lt-more {
	margin-top: 0;
}

/* ---------------------------------------------------------------------------
 * Round 4: /coverage/ by client (inc/coverage.php, lanctot_client_block()).
 * Each client is a ledger section labelled with its name: its logo (if we
 * have one) and its descriptor, a meta line, then its stories as rows.
 * ------------------------------------------------------------------------ */

.lt-covclient {
	margin-bottom: 28px;
}

/* The client first (round 4): its name in the serif, large, with its logo beside it. */
.lt-covclient__name {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 8px 20px;
	margin: 0 0 10px;
	font-family: var(--lt-serif);
	font-size: clamp(32px, 3.4vw, 48px);
	line-height: 1.05;
	color: var(--lt-ink);
}

.lt-covclient__logo {
	display: flex;
	color: var(--lt-soft);
}

.lt-covclient__desc {
	margin: 0 0 6px;
	font-size: 19px;
	line-height: 1.4;
	max-width: 56ch;
	color: var(--lt-soft);
}

p.lt-covclient__meta {
	margin: 0;
}

/*
 * A story's outlet line without logos (round 4): up to two names, in the
 * label face at the logo row's size. A one-outlet story's own headline sits
 * under its outlet, linked.
 */
.lt-rownames {
	font-family: var(--lt-sans);
	font-size: 14px;
	letter-spacing: .02em;
	color: var(--lt-ink);
}

/* Two names read "A, B"; the comma is CSS, so a name that has a comma of its own stays one name. */
.lt-rowname + .lt-rowname::before {
	content: ", ";
}

.lt-row__headline {
	display: block;
	margin-top: 6px;
}

/* The "opens elsewhere" arrow, one mask for every link on /coverage/ (inc/coverage.php, lanctot_ne()). */
.lt-ne {
	display: inline-block;
	width: .75em;
	height: .75em;
	margin-left: .2em;
	vertical-align: -.02em;
	background: currentColor;
	-webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M5 11 11 5M6 5h5v5' fill='none' stroke='black' stroke-width='1.6' stroke-linecap='square'/%3E%3C/svg%3E") no-repeat center / contain;
	mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M5 11 11 5M6 5h5v5' fill='none' stroke='black' stroke-width='1.6' stroke-linecap='square'/%3E%3C/svg%3E") no-repeat center / contain;
}

.lt-sec--client .lt-fold {
	margin-top: 4px;
}

/* 404 */

.lt-404 .lt-more {
	margin-top: 0;
	margin-right: 28px;
}

/* ---------------------------------------------------------------------------
 * Narrow screens: the label column stacks over its rows.
 * ------------------------------------------------------------------------ */

@media (max-width: 860px) {
	.lt-intro,
	.lt-sec,
	.lt-pagehead,
	.lt-cshead,
	.lt-filterbar,
	.lt-contact {
		grid-template-columns: 1fr;
	}

	.lt-pagehead__main,
	.lt-cshead__main,
	.lt-cshead__aside,
	.lt-filterbar > .lt-chips {
		grid-column: 1;
	}

	.lt-cshead__aside {
		grid-row: auto;
	}

	.lt-sec {
		gap: 20px;
	}

	.lt-row {
		grid-template-columns: minmax(0, 1fr) auto;
		gap: 4px 16px;
	}

	.lt-row__b {
		grid-column: 1 / -1;
		grid-row: 2;
	}

	.lt-row__c {
		grid-column: 2;
		grid-row: 1;
	}

	/*
	 * The filters stay in reach on a long list: sticky under the header, both
	 * chip groups on ONE scrolling row, so the bar is one chip tall.
	 */
	.lt-filterbar {
		position: sticky;
		top: var(--lt-top-h);
		z-index: 8;
		display: flex;
		gap: 8px;
		padding: 8px var(--lt-pad);
		overflow-x: auto;
		border-bottom: 1px solid var(--lt-rule);
		scrollbar-width: none;
	}

	.admin-bar .lt-filterbar {
		top: calc(var(--lt-top-h) + 46px);
	}

	.lt-filterbar > .lt-chips {
		flex-wrap: nowrap;
		flex: none;
	}

	.lt-filterbar > .lt-chips + .lt-chips {
		padding-left: 8px;
		border-left: 1px solid var(--lt-rule);
	}

	html:has(.lt-filterbar:not([hidden])) {
		scroll-padding-top: calc(var(--lt-top-h) + 60px);
	}
}

@media (max-width: 560px) {
	:root {
		--lt-top-h: 64px;
	}

	body.lt {
		font-size: 18px;
	}

	.lt-top {
		gap: 12px;
	}

	.lt-top__name {
		display: none;
	}

	.lt-top__mono {
		display: inline;
		font-family: var(--lt-serif);
		font-size: 22px;
		letter-spacing: 0;
	}

	.lt-nav {
		gap: 14px;
		font-size: 14px;
	}

	.lt-nav .lt-opt {
		display: none;
	}

	.lt-toggle__label {
		position: absolute;
		width: 1px;
		height: 1px;
		overflow: hidden;
		clip-path: inset(50%);
		white-space: nowrap;
	}

	.lt-about__grid {
		grid-template-columns: 1fr;
	}

	.lt-portrait {
		max-width: 272px;
	}

	.lt-about p {
		font-size: 21px;
	}

	/* /about/'s copy on a phone (round 4.2): 19px keeps ~38 characters a line in 350px. */
	.lt-about:not(.lt-about--teaser) .lt-about__copy p {
		font-size: 19px;
		line-height: 1.45;
	}

	.lt-body p {
		font-size: 19px;
	}
}

/* Round 2, narrow: three logos across; the drawing beside the title, the description under both. */
@media (max-width: 860px) {
	.lt-logos {
		grid-template-columns: repeat(3, minmax(0, 1fr));
	}

	.lt-logos .lt-logo {
		min-height: 72px;
		padding: 12px;
	}

	.lt-row--art {
		grid-template-columns: 64px minmax(0, 1fr) auto;
		gap: 4px 16px;
		align-items: start;
	}

	.lt-row--art .lt-row__art {
		width: 64px;
		height: 64px;
		grid-row: 1 / span 2;
	}

	.lt-row--art .lt-row__a {
		grid-column: 2;
		grid-row: 1;
	}

	.lt-row--art .lt-row__b {
		grid-column: 2 / -1;
		grid-row: 2;
	}

	.lt-row--art .lt-row__c {
		grid-column: 3;
		grid-row: 1;
	}

	.lt-client-art {
		padding: 6px;
	}

	.lt-cshead__title {
		flex-wrap: wrap;
	}
}

/* Round 3, phone: the wall's tiles and names shrink; still three across. */
@media (max-width: 560px) {
	.lt-client {
		min-height: 88px;
		padding: 12px 8px;
	}

	.lt-client__name {
		font-size: 16px;
	}

	.lt-cshead__client {
		padding-bottom: 0;
	}

	.lt-covclient__desc {
		font-size: 17px;
	}
}
