/*
 * ==========================================================================
 * THREE LAYOUTS, ON THE THREE PAGE TYPES THAT CHOSE THEM.
 * ==========================================================================
 *
 * Onkar, 2026-10-07, after looking at five home-page previews: *"i liked v1
 * and v2 and v4 can be for catagory but non of them can be home page but other
 * places can use them"*. The three he kept were given the pages they suit:
 *
 *   `.bs`  BROADSHEET  ->  /latest/          the full index, which IS a front
 *   `.tl`  TILES       ->  /sections/        fifteen sections, fifteen photos
 *   `.dk`  DESK        ->  every category     a rail that stays beside the list
 *
 * **AND THEN THE FRONT PAGE CHANGED TOO, later the same day** — *"now covert
 * [h]4 to main hompage"* — so the sentence that used to stand here, "the front
 * page is left exactly as it was", is no longer true and has been removed
 * rather than left to mislead. `.cv`, `.dr`, `.sx` and `.cvr` at the foot of
 * this file ARE the front page now; see the banner above them.
 *
 * They were drawn as home pages first (`/ui/v1/`, `/ui/v2/`, `/ui/v4/`, still
 * served locally by `inc/ui-variants.php`), which is why the class prefixes are
 * terse and why `ui-variants.css` next door is now only the two he did not
 * pick plus the preview chrome. That file DEPENDS on this one — the geometry
 * below is declared here once rather than in both.
 *
 * -------------------------------------------------------------------------
 * STILL NO COLOUR IN THIS FILE
 * -------------------------------------------------------------------------
 *
 * Not one hex, `rgb()` or named colour. Every surface, ink, rule and scrim is
 * `var(--token)` out of layer 01, so these three pages follow a repaint from
 * wp-admin like everything else. `tests/ui-variants.test.mjs` fails the build
 * on a literal and has been made to fail on purpose three ways.
 *
 * -------------------------------------------------------------------------
 * WHY THIS IS NOT IN `preview/src/*.css`
 * -------------------------------------------------------------------------
 *
 * Those ten layers build `assets/css/site.css`, which EVERY page loads. These
 * three layouts are about 30KB and reach three page types; putting them in the
 * bundle would put a broadsheet, a tile grid and a sticky rail onto every blog
 * post in order to style pages that post will never be. That is the measured
 * thing this project refuses to do, and it is the same rule the toolkit lives
 * by: engines load per tool, never on an article.
 *
 * So `adb_layout_enqueue()` in `inc/layouts.php` puts this on an archive, on
 * /latest/ and on /sections/, and on nothing else. It is the ONE place to edit
 * these three layouts; there is no generated twin, which is why this file is
 * hand-written where `site.css` must never be.
 */

/* --- Geometry. None of this redefines a palette token. ------------------- */

:root {
	--ui-mast:      6.5rem;              /* matches 02-base.css scroll-padding */
	--ui-rule:      1px solid var(--rule);
	--ui-rule-soft: 1px solid var(--rule-soft);
	--ui-tile:      17rem;               /* the smallest a tile may get */
	--ui-tight:     1.08;                /* display leading, broadsheet */
	--ui-snug:      1.18;                /* heading leading everywhere else */
}


/* ==========================================================================
 * v1 - BROADSHEET
 *
 * Rules, never cards. The whole visual argument of this variant is that
 * NOTHING here has a border-radius, a shadow or a background panel: the page
 * is ink on paper divided by hairlines, which is how a newspaper front carries
 * this much on one screen without looking busy.
 *
 * Serif display at tight leading, and the type scale is pushed one step up
 * from the rest of the site for the lead headline only — a broadsheet's front
 * has exactly one loudest thing on it.
 * ======================================================================== */

.bs { padding-block: var(--sp-40) var(--sp-60); }

/* The nameplate. Three cells so the name sits optically centred whatever the
   two side strings measure — a flex row with `space-between` would have put
   it wherever the longest side pushed it. */
.bs__plate {
	display: grid;
	grid-template-columns: 1fr auto 1fr;
	gap: var(--sp-20);
	align-items: baseline;
	padding-bottom: var(--sp-20);
	border-bottom: 3px double var(--rule);
}

.bs__plate-name {
	font-family: var(--serif);
	font-size: var(--fs-xx-large);
	font-weight: 700;
	letter-spacing: -0.02em;
	line-height: 1;
	color: var(--ink);
}

.bs__plate-side {
	color: var(--ink-dim);
	font-family: var(--sans);
	font-size: var(--fs-small);
	letter-spacing: 0.04em;
	text-transform: uppercase;
}

.bs__plate-side--end { text-align: right; }

.bs__strap {
	margin: var(--sp-10) 0 var(--sp-30);
	padding-bottom: var(--sp-20);
	border-bottom: var(--ui-rule);
	color: var(--ink-faded);
	font-family: var(--serif);
	font-size: var(--fs-large);
	font-style: italic;
	text-align: center;
}

/* Eight columns of lead, four of rail, with a rule BETWEEN them rather than a
   gap — the rule is what makes it read as a newspaper column rather than two
   stacked blocks that happen to be adjacent. */
.bs__top {
	display: grid;
	grid-template-columns: minmax(0, 8fr) minmax(0, 4fr);
	gap: var(--sp-40);
}

.bs__rail {
	padding-left: var(--sp-40);
	border-left: var(--ui-rule);
}

.bs__kicker {
	display: flex;
	flex-wrap: wrap;
	align-items: baseline;
	gap: var(--sp-10);
	margin: 0 0 var(--sp-10);
}

.bs__cat {
	color: var(--accent-ink);
	font-family: var(--sans);
	font-size: var(--fs-small);
	font-weight: 500;
	letter-spacing: 0.08em;
	text-decoration: none;
	text-transform: uppercase;
}

.bs__cat:hover { text-decoration: underline; }

.bs__cat--sm { letter-spacing: 0.06em; }

.bs__time,
.bs__mins,
.bs__briefm {
	color: var(--ink-dim);
	font-family: var(--sans);
	font-size: var(--fs-small);
}

/*
 * One step DOWN from `--fs-huge`, which is the site's largest.
 *
 * `--fs-huge` tops out at 51px and this headline sits in a 675px column, not
 * across the page: the lead ran to five lines and pushed the picture and the
 * lede below the fold on a laptop. A broadsheet lead wants to be the loudest
 * thing on the page, which it still is — `--fs-xx-large` is 43px against the
 * 24px of the briefs beside it — but loudest is a ratio, not a maximum.
 */
.bs__h1 {
	margin: 0 0 var(--sp-30);
	font-family: var(--serif);
	font-size: var(--fs-xx-large);
	font-weight: 700;
	letter-spacing: -0.02em;
	line-height: var(--ui-tight);
}

.bs__h1-a,
.bs__briefh a,
.bs__cellh a {
	color: var(--ink);
	text-decoration: none;
}

.bs__h1-a:hover,
.bs__briefh a:hover,
.bs__cellh a:hover {
	text-decoration: underline;
	text-decoration-thickness: 2px;
	text-underline-offset: 3px;
}

/*
 * The lead's picture FLOATS and the lede wraps round it, which is the one
 * genuinely newspaper-shaped thing on the page. Floated rather than gridded
 * because text wrapping an image is exactly what float is for, and a grid
 * would put the picture in a cell with the words beside it instead of around
 * it.
 */
.bs__fig {
	float: right;
	width: 46%;
	margin: 0.35rem 0 var(--sp-20) var(--sp-30);
}

.bs__img,
.bs__cellimg {
	display: block;
	width: 100%;
	height: auto;
	aspect-ratio: 16 / 9;
	object-fit: cover;
}

.bs__lede {
	margin: 0;
	color: var(--ink);
	font-family: var(--serif);
	font-size: var(--fs-read-lead);
	line-height: 1.6;
}

/* The drop cap. `::first-letter` on the lede is why the lede is its own
   paragraph in the markup — on a longer paragraph the cap would land on a
   sentence that is not the opening. */
.bs__lede::first-letter {
	float: left;
	margin: 0.08em 0.08em 0 0;
	color: var(--ink);
	font-family: var(--serif);
	font-size: 3.4em;
	font-weight: 700;
	line-height: 0.82;
}

.bs__more {
	clear: both;
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: var(--sp-10);
	margin: var(--sp-30) 0 0;
	padding-top: var(--sp-20);
	border-top: var(--ui-rule-soft);
}

.bs__link {
	display: inline-flex;
	align-items: center;
	min-height: 2.75rem;
	color: var(--accent-ink);
	font-family: var(--sans);
	font-size: var(--fs-medium);
	font-weight: 500;
	text-decoration: none;
	text-underline-offset: 3px;
}

.bs__link:hover { text-decoration: underline; }

.bs__dot { color: var(--ink-dim); }

.bs__railhead,
.bs__bandhead {
	margin: 0 0 var(--sp-20);
	padding-bottom: var(--sp-10);
	border-bottom: 2px solid var(--ink);
	color: var(--ink);
	font-family: var(--sans);
	font-size: var(--fs-small);
	font-weight: 500;
	letter-spacing: 0.12em;
	text-transform: uppercase;
}

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

.bs__brief + .bs__brief {
	margin-top: var(--sp-20);
	padding-top: var(--sp-20);
	border-top: var(--ui-rule-soft);
}

.bs__briefh {
	margin: 0.3rem 0 0.35rem;
	font-family: var(--serif);
	font-size: var(--fs-large);
	font-weight: 600;
	line-height: var(--ui-snug);
}

/* `.bs__briefp` was deleted with the markup that used it — see the note in
   `ui-layouts.php` about what a brief is. */

.bs__briefm {
	display: flex;
	align-items: center;
	gap: 0.4rem;
	margin: 0;
}

/* The briefs sit on the lead's baseline, not stretched to its height. The lead
   column is the tall one now and the rail should stop where its last brief
   does rather than growing a tail of empty rule. */
.bs__top { align-items: start; }

.bs__bandhead { margin-top: var(--sp-50); }

.bs__band {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr));
	gap: var(--sp-30);
}

/* The rule lives on the CELL, not between cells, so a row that wraps to two
   does not leave a hairline hanging in the gap. */
.bs__cell {
	padding-top: var(--sp-20);
	border-top: var(--ui-rule);
}

.bs__cellfig { margin: 0 0 var(--sp-20); }

.bs__cellh {
	margin: 0.3rem 0 0.35rem;
	font-family: var(--serif);
	font-size: var(--fs-medium);
	font-weight: 600;
	line-height: var(--ui-snug);
}

.bs__cellp {
	margin: 0;
	color: var(--ink-faded);
	font-family: var(--sans);
	font-size: var(--fs-small);
	line-height: 1.55;
}

.bs__foot {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: space-between;
	gap: var(--sp-20);
	margin-top: var(--sp-50);
	padding-top: var(--sp-20);
	border-top: 3px double var(--rule);
}

.bs__footp {
	margin: 0;
	max-width: var(--measure);
	color: var(--ink-faded);
	font-family: var(--sans);
	font-size: var(--fs-medium);
}

/* Below 60rem a floated 46% picture leaves a column too narrow for a drop cap
   to sit in, so the picture goes full width and the cap goes away. Keeping it
   produced a four-line cap beside two words. */
@media (max-width: 59.99rem) {
	.bs__top {
		grid-template-columns: minmax(0, 1fr);
	}

	.bs__rail {
		padding-left: 0;
		padding-top: var(--sp-30);
		border-left: 0;
		border-top: 3px double var(--rule);
	}

	.bs__fig {
		float: none;
		width: 100%;
		margin: 0 0 var(--sp-20);
	}

	.bs__lede::first-letter {
		float: none;
		margin: 0;
		font-size: inherit;
		line-height: inherit;
	}

	.bs__plate {
		grid-template-columns: minmax(0, 1fr);
		text-align: center;
	}

	.bs__plate-side--end { text-align: center; }
}

/* ==========================================================================
 * v2 - TILES
 *
 * after HTML5 UP "Phantom" (CC BY 3.0). The photograph is the object and the
 * whole tile is the hit area. Phantom varies its tiles by COLOUR; this one
 * varies them by SIZE, because varying by colour is the recolour that was
 * ruled out — and size turns out to be the stronger signal anyway, since it
 * survives being printed, being on a bad screen, and being colour-blind.
 * ======================================================================== */

.tl { padding-block: var(--sp-40) var(--sp-60); }

.tl__head {
	max-width: var(--measure);
	margin-bottom: var(--sp-40);
}

.tl__h1 {
	margin: 0 0 var(--sp-20);
	color: var(--ink);
	font-family: var(--display);
	font-size: var(--fs-xx-large);
	font-weight: var(--display-weight);
	letter-spacing: var(--display-tracking);
	line-height: var(--display-leading);
}

.tl__sub {
	margin: 0;
	color: var(--ink-faded);
	font-family: var(--sans);
	font-size: var(--fs-large);
	line-height: 1.55;
}

/*
 * `auto-fit` with a floor, and the spans are applied only where there is room
 * for them (see the query below). A two-column span inside a two-column grid
 * is a full-width tile, which is fine; inside a ONE-column grid it is a
 * horizontal overflow, which is the fault `clip.test.mjs` exists to catch.
 */
.tl__grid {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(var(--ui-tile), 1fr));
	gap: var(--sp-20);
}

.tl__tile {
	position: relative;
	display: flex;
	align-items: flex-end;
	min-height: 15rem;
	overflow: hidden;
	border-radius: var(--radius-lg);
	background: var(--invert-bg);
	color: var(--invert-text);
	text-decoration: none;
	isolation: isolate;
}

.tl__media {
	position: absolute;
	inset: 0;
	z-index: 0;
}

.tl__img {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
	transition: transform var(--dur-slow) var(--ease-out);
}

/*
 * THE SCRIM IS A TOKEN, MIXED. `--scrim` is the palette's own near-black; the
 * percentages say how much of it to use and nothing about what colour it is.
 * It is opaque at the bottom where the words are and clear at the top where
 * the picture is, because a flat 50% wash over the whole tile dulls the
 * photograph everywhere to fix contrast in one place.
 */
.tl__tile::after {
	content: "";
	position: absolute;
	inset: 0;
	z-index: 1;
	background: linear-gradient(
		to top,
		color-mix(in srgb, var(--scrim) 92%, transparent) 0%,
		color-mix(in srgb, var(--scrim) 70%, transparent) 38%,
		color-mix(in srgb, var(--scrim) 18%, transparent) 78%,
		transparent 100%
	);
	transition: opacity var(--dur) var(--ease);
}

.tl__body {
	position: relative;
	z-index: 2;
	display: flex;
	flex-direction: column;
	gap: 0.35rem;
	padding: var(--sp-30);
	width: 100%;
}

.tl__cat {
	align-self: flex-start;
	padding: 0.2rem 0.55rem;
	border-radius: var(--btn-radius);
	background: color-mix(in srgb, var(--invert-text) 18%, transparent);
	color: var(--invert-text);
	font-family: var(--sans);
	font-size: var(--fs-small);
	font-weight: 500;
	letter-spacing: 0.06em;
	text-transform: uppercase;
}

/* A `<span>` styled as a heading. See the markup note: the whole tile is one
   anchor, so a real nested heading-with-link would be invalid. */
.tl__h {
	font-family: var(--display);
	font-size: var(--fs-large);
	font-weight: var(--display-weight);
	letter-spacing: var(--display-tracking);
	line-height: var(--ui-snug);
}

.tl__p {
	color: var(--invert-dim);
	font-family: var(--sans);
	font-size: var(--fs-medium);
	line-height: 1.5;
}

.tl__meta {
	display: flex;
	align-items: center;
	gap: 0.4rem;
	color: var(--invert-dim);
	font-family: var(--sans);
	font-size: var(--fs-small);
}

.tl__tile:hover .tl__img { transform: scale(1.04); }
.tl__tile:hover::after   { opacity: 0.88; }

/* Offset outward: the focus ring has to be visible against a photograph, and
   an inset ring on a dark tile disappears into the scrim. */
.tl__tile:focus-visible {
	outline: var(--focus);
	outline-offset: 3px;
}

.tl__after { margin-top: var(--sp-50); }

/* The spans only exist where there are at least two columns to span. */
@media (min-width: 40rem) {
	.tl__tile--big {
		grid-column: span 2;
		grid-row: span 2;
		min-height: 32rem;
	}

	.tl__tile--big .tl__h { font-size: var(--fs-x-large); }

	.tl__tile--wide {
		grid-column: span 2;
		min-height: 17rem;
	}
}

/* ==========================================================================
 * v4 - DESK
 *
 * after HTML5 UP "Editorial" (CC BY 3.0) + Magz (MIT). A rail that does not
 * leave, beside a column that scrolls.
 *
 * The rail is SECOND in the DOM and first on the screen, via `order`. Reading
 * order matters more than paint order: a screen reader and a keyboard both get
 * the lead story immediately instead of wading through fifteen section links
 * and a subscribe form to reach it.
 * ======================================================================== */

.dk { padding-block: var(--sp-40) var(--sp-60); }

.dk__grid {
	display: grid;
	grid-template-columns: minmax(0, 1fr) 20rem;
	gap: var(--sp-50);
	align-items: start;
}

.dk__rail { position: sticky; top: var(--ui-mast); }

.dk__kicker {
	display: flex;
	flex-wrap: wrap;
	align-items: baseline;
	gap: var(--sp-10);
	margin: 0 0 var(--sp-10);
	color: var(--ink-dim);
	font-family: var(--sans);
	font-size: var(--fs-small);
}

.dk__cat {
	color: var(--accent-ink);
	font-weight: 500;
	letter-spacing: 0.08em;
	text-decoration: none;
	text-transform: uppercase;
}

.dk__cat:hover { text-decoration: underline; }

.dk__h1 {
	margin: 0 0 var(--sp-30);
	font-family: var(--display);
	font-size: var(--fs-xx-large);
	font-weight: var(--display-weight);
	letter-spacing: var(--display-tracking);
	line-height: var(--display-leading);
}

.dk__h1-a,
.dk__rowh a,
.dk__seca,
.dk__toola {
	color: var(--ink);
	text-decoration: none;
}

.dk__h1-a:hover,
.dk__rowh a:hover {
	text-decoration: underline;
	text-decoration-thickness: 2px;
	text-underline-offset: 3px;
}

.dk__fig {
	margin: 0 0 var(--sp-30);
	overflow: hidden;
	border-radius: var(--radius-lg);
}

.dk__img {
	display: block;
	width: 100%;
	height: auto;
	aspect-ratio: 2 / 1;
	object-fit: cover;
}

.dk__lede {
	margin: 0;
	max-width: var(--measure);
	color: var(--ink-faded);
	font-family: var(--sans);
	font-size: var(--fs-read-lead);
	line-height: 1.6;
}

.dk__more {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: var(--sp-10);
	margin: var(--sp-20) 0 0;
	color: var(--ink-dim);
	font-family: var(--sans);
	font-size: var(--fs-small);
}

.dk__link {
	display: inline-flex;
	align-items: center;
	min-height: 2.75rem;
	color: var(--accent-ink);
	font-family: var(--sans);
	font-size: var(--fs-medium);
	font-weight: 500;
	text-decoration: none;
	text-underline-offset: 3px;
}

.dk__link:hover { text-decoration: underline; }

.dk__bt,
.dk__blockh {
	margin: 0 0 var(--sp-20);
	padding-bottom: var(--sp-10);
	border-bottom: 2px solid var(--ink);
	color: var(--ink);
	font-family: var(--sans);
	font-size: var(--fs-small);
	font-weight: 500;
	letter-spacing: 0.12em;
	text-transform: uppercase;
}

.dk__bt {
	margin-top: var(--sp-50);
}

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

.dk__row {
	display: grid;
	grid-template-columns: 2.5rem 5.5rem minmax(0, 1fr);
	gap: var(--sp-20);
	align-items: start;
	padding-block: var(--sp-20);
}

.dk__row + .dk__row { border-top: var(--ui-rule-soft); }

.dk__n {
	color: var(--ink-dim);
	font-family: var(--mono);
	font-size: var(--fs-small);
	font-variant-numeric: tabular-nums;
	padding-top: 0.15rem;
}

.dk__rowfig {
	display: block;
	overflow: hidden;
	border-radius: var(--radius-sm);
	background: var(--paper-deep);
}

.dk__rowimg {
	display: block;
	width: 100%;
	height: auto;
	aspect-ratio: 1 / 1;
	object-fit: cover;
}

.dk__cat--sm { font-size: var(--fs-small); }

.dk__rowh {
	margin: 0.2rem 0 0.3rem;
	font-family: var(--sans);
	font-size: var(--fs-large);
	font-weight: 500;
	line-height: var(--ui-snug);
}

.dk__rowp {
	margin: 0 0 0.3rem;
	color: var(--ink-faded);
	font-family: var(--sans);
	font-size: var(--fs-medium);
	line-height: 1.55;
}

.dk__rowm {
	display: flex;
	align-items: center;
	gap: 0.4rem;
	margin: 0;
	color: var(--ink-dim);
	font-family: var(--sans);
	font-size: var(--fs-small);
}

.dk__dot { color: var(--ink-dim); }

/* A Magz block: a titled panel with a list in it. */
.dk__block {
	padding: var(--sp-30);
	border: var(--ui-rule);
	border-radius: var(--radius-lg);
	background: var(--surface);
}

.dk__block + .dk__block { margin-top: var(--sp-30); }

.dk__secs,
.dk__tools {
	margin: 0;
	padding: 0;
	list-style: none;
}

/*
 * 44px rows. Fifteen sections in a tight 28px list looks tidier and cannot be
 * hit with a thumb — priority 2 in the UX rule set, and the reason this list
 * is as long as it is.
 */
.dk__seca,
.dk__toola {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: var(--sp-20);
	min-height: 2.75rem;
	padding-inline: 0.25rem;
	border-radius: var(--radius-sm);
	font-family: var(--sans);
	font-size: var(--fs-medium);
	transition: background var(--dur) var(--ease);
}

.dk__seca:hover,
.dk__toola:hover { background: var(--paper-deep); }

.dk__seca:focus-visible,
.dk__toola:focus-visible,
.dk__link:focus-visible {
	outline: var(--focus);
	outline-offset: 2px;
}

.dk__secc {
	flex: 0 0 auto;
	min-width: 1.75rem;
	padding: 0.1rem 0.4rem;
	border-radius: var(--btn-radius);
	background: var(--paper-deep);
	color: var(--ink-dim);
	font-size: var(--fs-small);
	font-variant-numeric: tabular-nums;
	text-align: center;
}

.dk__toola { justify-content: flex-start; }

.dk__toolicon {
	display: inline-flex;
	flex: 0 0 auto;
	align-items: center;
	justify-content: center;
	width: 2rem;
	height: 2rem;
	border-radius: var(--radius-sm);
	background: var(--vermillion-wash);
	color: var(--accent-ink);
}

.dk__blockf {
	margin: var(--sp-20) 0 0;
	color: var(--ink-dim);
	font-family: var(--sans);
	font-size: var(--fs-small);
	line-height: 1.5;
}

.dk__block--sub { background: var(--paper-deep); }

/*
 * One column below 64rem, and the rail STOPS being sticky. A sticky rail on a
 * phone is a rail standing on the article — and it moves below the column, so
 * the lead story is the first thing on the screen rather than fifteen links.
 */
@media (max-width: 63.99rem) {
	.dk__grid { grid-template-columns: minmax(0, 1fr); }

	.dk__rail {
		position: static;
		top: auto;
	}

	.dk__row {
		grid-template-columns: 4.5rem minmax(0, 1fr);
		gap: var(--sp-20);
	}

	/* The running number goes: at two columns it was costing 40px of a 375px
	   screen to repeat information the order already gives. */
	.dk__n { display: none; }
}

/* ==========================================================================
 * DESK ON A CATEGORY ARCHIVE
 *
 * The archive keeps its OWN components — `.lead`, the query head, the index
 * rows, the pagination — and Desk supplies only the grid and the rail. See
 * `inc/layouts-render.php` for why redrawing those rows would have broken the
 * one thing all ninety-three archives share with the front page.
 *
 * But a component drawn for the full width does not automatically work in a
 * column two thirds of it, and this is the part that had to be said out loud.
 * ======================================================================== */

/*
 * THE MEDIA QUERY ASKS THE WRONG QUESTION, AND THIS IS THE CLASSIC VERSION OF
 * THAT BUG.
 *
 * `04-components.css` collapses `.lead` to one column at
 * `@media (max-width: 900px)` — the right call when the lead was always as wide
 * as the page, because then the VIEWPORT width and the COMPONENT width were
 * the same number.
 *
 * Inside the Desk column they are not. At a 1440 viewport the column is about
 * 700px, the media query never fires, and the lead stays a two-column grid of
 * `1.15fr 1fr` inside 700px — so the headline got roughly 370px and
 * "GST council clears the two-slab structure: what changes for a household"
 * came out SIX lines tall beside a thumbnail.
 *
 * The honest fix is a container query on `.lead` itself, and that is a change
 * to a component four page types share — a remodel, on a day the instruction
 * was to adopt a layout. So this is additive and scoped: inside the Desk
 * column, the lead takes the stacked form the component already defines for
 * itself, including its own `order: -1`. One place to change when `.lead`
 * eventually does get a container query, and nothing else moves meanwhile.
 */
.dk__col .lead {
	grid-template-columns: minmax(0, 1fr);
	gap: var(--sp-30);
}

.dk__col .lead__figure { order: -1; }

/*
 * The section you are standing in, marked.
 *
 * `aria-current="page"` is on the anchor in the markup and is what actually
 * tells a screen reader; this is the visible half of the same fact. Weight and
 * a filled count, not colour alone — the UX rules put "never convey meaning by
 * colour alone" at priority 10 and it costs nothing to obey here.
 */
.dk__seca.is-here {
	background: var(--paper-deep);
	font-weight: 500;
}

.dk__seca.is-here .dk__secc {
	background: var(--accent-ink);
	color: var(--on-accent);
}

/*
 * An archive's own head and chips stay full width ABOVE the grid, so the two
 * columns begin at the lead. The rail is `order: -1` on the source but drawn
 * second — see the template note.
 */
.dk__grid > .dk__col { min-width: 0; }

/* ==========================================================================
 * THE ANCHOR COLOUR TRAP, AND WHY EVERY LINK HERE IS WRITTEN TWICE
 * ==========================================================================
 *
 * `site.css` carries this, deliberately, site-wide:
 *
 *     :root a { color: inherit; }
 *
 * That is a GOOD rule — it lets a dark band colour its own links by setting
 * `color` once on the band instead of restating it on every anchor inside. But
 * its specificity is **(0,1,1)**: one pseudo-class plus one element. A single
 * class is **(0,1,0)**. So `:root a` beats `.st__h1-a { color: ... }`, and
 * every link colour in the first draft of this work was silently discarded.
 *
 * MEASURED, NOT GUESSED. Asking the browser which rules matched returned, in
 * order:
 *
 *     INLINE          a:where(:not(.wp-element-button))  -> contrast
 *     site.css        :root a                            -> inherit     <-- wins
 *     ui-variants.css .st__h1-a                          -> --invert-text
 *
 * and the computed value came back `rgb(16, 18, 51)` — `--ink`, inherited from
 * the body. Note WordPress's own inline rule is `:where()`d down to (0,1,0)
 * and loses to both; blaming core for this, as CLAUDE.md once did, sends the
 * next person to the wrong file.
 *
 * WHAT IT LOOKED LIKE. Never a missing style. Tile headlines rendered in
 * near-black ON the photograph's dark scrim, and a primary button came out
 * near-white on a near-white pill — present, correct in the DOM, perfectly
 * clickable, and invisible.
 *
 * THE CURE is `:root` in front, which makes each selector (0,2,0) and settles
 * it outright rather than by source order. `:root` rather than a body class
 * because these three layouts now run on live pages that carry no class of
 * mine — and because echoing the shape of the rule it beats is what makes the
 * arithmetic legible at the call site.
 *
 * A new link in any of these three belongs in this list, and the way to find
 * out is to look at it on a dark surface.
 * ======================================================================== */


/* v1 - on paper */
:root .bs__h1-a,
:root .bs__briefh a,
:root .bs__cellh a { color: var(--ink); }

:root .bs__cat,
:root .bs__link { color: var(--accent-ink); }

/* v2 - on the photograph */
:root .tl__tile { color: var(--invert-text); }
:root .tl__h    { color: var(--invert-text); }
:root .tl__p,
:root .tl__meta { color: var(--invert-dim); }

/* v4 - all on paper */
:root .dk__h1-a,
:root .dk__rowh a,
:root .dk__seca,
:root .dk__toola { color: var(--ink); }

:root .dk__cat,
:root .dk__link { color: var(--accent-ink); }


/* ==========================================================================
 * REDUCED MOTION
 *
 * Every piece of movement in this file is decoration — a tile zoom, a cell
 * lift, a scrim fade. None of it carries meaning, so under
 * `prefers-reduced-motion` all of it goes rather than being slowed down. The
 * hover STATES stay (the background change, the underline, the border),
 * because those are feedback and removing them would take the signal away with
 * the animation.
 *
 * Scoped to the three layout roots rather than written as a global `*` rule:
 * this sheet now loads on live pages, and a blanket
 * `transition-duration: 0.01ms !important` would reach the masthead, the
 * footer and anything else the page happens to be carrying.
 * ======================================================================== */

@media (prefers-reduced-motion: reduce) {
	.bs *, .bs *::before, .bs *::after,
	.tl *, .tl *::before, .tl *::after,
	.dk *, .dk *::before, .dk *::after {
		animation-duration: 0.01ms !important;
		animation-iteration-count: 1 !important;
		transition-duration: 0.01ms !important;
	}

	.tl__tile:hover .tl__img { transform: none; }
}


/* ==========================================================================
 * THE FRONT PAGE: COVER & DOORS
 * ==========================================================================
 *
 * Onkar, 2026-10-07: *"now covert [h]4 to main hompage"*. So `.cv` (the
 * cover), `.dr` (the two doors), `.sx` (the sections strip) and `.cvr` (the
 * ruled index) stopped being preview CSS and moved here, into the sheet that
 * is actually served.
 *
 * They are in `layouts.css` rather than in a sheet of their own because the
 * three preview routes still use them too, and `adb_layout_enqueue()` already
 * prints this file on any `/ui/` route. One definition, loaded wherever it is
 * needed. The alternative — a `home.css` beside `ui-home.css` — would have
 * been the same cover written twice, and this project has already paid for a
 * pair of files that must be kept in agreement by hand (`menu.js` and
 * `sections.js`, which are the same forty lines twice and say so).
 *
 * **WHAT THAT COSTS, MEASURED:** /latest/, /sections/ and the 93 archives now
 * carry the cover-and-doors rules without using them. The number is in
 * HANDOVER.md next to the decision rather than guessed at here. It is paid on
 * three page types that already load this file, and never on a blog post —
 * which is the line this project actually draws.
 * ======================================================================== */

/*
 * THE TWO DOORS ARE THE SAME SIZE, and that is the argument. `1fr 1fr`, not
 * `1.3fr 1fr`: making the reading door bigger would be the live page's
 * decision in a nicer frame, and making the toolkit bigger would be untrue to
 * a site whose masthead is fifteen editorial sections.
 *
 * They overlap the hero by a negative margin so the first screen contains the
 * headline AND the choice. A door you have to scroll to find is not a door, it
 * is a section.
 */
.dr {
	margin-top: calc(var(--sp-50) * -1);
	padding-bottom: var(--sp-50);
}

.dr__grid {
	position: relative;
	z-index: 3;
	display: grid;
	grid-template-columns: repeat(2, minmax(0, 1fr));
	gap: var(--sp-30);
}

.dr__door {
	/* The stretched link below is absolute; this is what it is absolute TO. */
	position: relative;
	display: flex;
	flex-direction: column;
	gap: var(--sp-20);
	padding: var(--sp-40);
	border: var(--ui-rule);
	border-radius: var(--radius-lg);
	background: var(--surface);
	box-shadow: var(--shadow-lift);
	color: var(--ink);
	text-decoration: none;
	transition: transform var(--dur) var(--ease), border-color var(--dur) var(--ease);
}

.dr__door:hover {
	transform: translateY(-3px);
	border-color: var(--accent-ink);
}

/* The door is a <div> since 2026-10-19 — see `ui-home-cover.php`. It has no
   focus of its own any more, so the lift follows whichever link inside it the
   keyboard has landed on, and the ring goes on that link. */
.dr__door:focus-within {
	transform: translateY(-3px);
	border-color: var(--accent-ink);
}

.dr__door a:focus-visible {
	outline: var(--focus);
	outline-offset: 3px;
}

/* The DO door is the inverted one — the single dark surface on this page. */
.dr__door--do {
	background: var(--invert-bg);
	border-color: var(--invert-bg-2);
	color: var(--invert-text);
}

.dr__eyebrow {
	font-family: var(--sans);
	font-size: var(--fs-small);
	font-weight: 500;
	letter-spacing: 0.16em;
	text-transform: uppercase;
}

.dr__h2 {
	font-family: var(--display);
	font-size: var(--fs-x-large);
	font-weight: var(--display-weight);
	letter-spacing: var(--display-tracking);
	line-height: var(--ui-snug);
}

.dr__promise {
	font-family: var(--sans);
	font-size: var(--fs-medium);
	line-height: 1.55;
}

.dr__list {
	display: flex;
	flex-direction: column;
	gap: 0.6rem;
	margin-top: auto;
	padding-top: var(--sp-20);
	border-top: var(--ui-rule-soft);
}

/*
 * EVERY NAME IS ITS OWN LINK, AND IT SITS ON TOP OF THE CARD'S.
 *
 * `.dr__go--all` reaches over the whole door, so a click anywhere still opens
 * the hub. These lift above that overlay — and WITHOUT `position` the
 * `z-index` does nothing at all, so the overlay would swallow every one of
 * them and the page would look exactly like the fault this replaced.
 *
 * 44px is the brief's floor and not decoration here: these six are the things
 * on the front page most likely to be reached for with a thumb.
 */
.dr__li,
.dr__tool {
	position: relative;
	z-index: 1;
	color: inherit;
	text-decoration: none;
}

.dr__li {
	display: flex;
	flex-direction: column;
	justify-content: center;
	gap: 0.1rem;
	min-height: 2.75rem;
}

.dr__li:hover .dr__lih,
.dr__li:focus-visible .dr__lih,
.dr__tool:hover .dr__tooln,
.dr__tool:focus-visible .dr__tooln {
	text-decoration: underline;
	text-underline-offset: 3px;
}

.dr__licat {
	font-family: var(--sans);
	font-size: var(--fs-small);
	font-weight: 500;
	letter-spacing: 0.06em;
	text-transform: uppercase;
}

.dr__lih {
	font-family: var(--sans);
	font-size: var(--fs-medium);
	font-weight: 500;
	line-height: var(--ui-snug);
}

.dr__tools {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(10rem, 1fr));
	gap: 0.35rem;
	margin-top: auto;
	padding-top: var(--sp-20);
	border-top: 1px solid var(--invert-bg-2);
}

.dr__tool {
	display: flex;
	align-items: center;
	gap: 0.55rem;
	/* 2.75rem, not 2.5: it is a LINK now, and 44px is the brief's floor for
	   anything a thumb has to find. Measured at 40px before this. */
	min-height: 2.75rem;
	font-family: var(--sans);
	font-size: var(--fs-medium);
}

.dr__toolicon {
	display: inline-flex;
	flex: 0 0 auto;
	align-items: center;
	justify-content: center;
	width: 2rem;
	height: 2rem;
	border-radius: var(--radius-sm);
	background: var(--invert-bg-2);
}

.dr__tooln {
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

/* The "go" line CARRIES the door's destination now and reaches over the whole
   card to do it, because the door itself can no longer be a link: the names
   inside it had to become links, and an <a> may not hold an <a>.
   ::BEFORE, not ::after — ::after is already the arrow, and one box cannot be
   both the overlay and the glyph. */
.dr__go--all::before {
	content: "";
	position: absolute;
	inset: 0;
	z-index: 0;
	border-radius: inherit;
}

/*
 * NO `position` ON THE GO LINE ITSELF, and that is the whole trick.
 *
 * `inset: 0` resolves against the nearest POSITIONED ancestor. Giving this
 * element `position: relative` — the obvious thing, to make the arrow stack —
 * makes the overlay absolute to the GO LINE, so it stretched over a 180x44
 * strip of text and the rest of the card went back to doing nothing. The
 * arrow carries its own `position` instead; a relative box with no offsets
 * does not move, it only joins the stacking order.
 */
.dr__go {
	color: inherit;
	text-decoration: none;
	display: inline-flex;
	align-items: center;
	gap: 0.4rem;
	min-height: 2.75rem;
	font-family: var(--sans);
	font-size: var(--fs-medium);
	font-weight: 500;
}

.dr__go::after {
	content: "\2192";
	/* Above the overlay its own sibling paints, or the arrow disappears. */
	position: relative;
	z-index: 1;
	transition: transform var(--dur) var(--ease);
}

.dr__door:hover .dr__go::after { transform: translateX(3px); }

/* ==========================================================================
 * THE SECTIONS STRIP — shared by all three
 *
 * The live front page shows the fifteen sections NOWHERE. All three candidates
 * fix that, so the strip is written once.
 *
 * It scrolls sideways below the width where the chips fit, the same mechanism
 * the masthead rail uses — and because `clip.test.mjs` excludes a horizontal
 * scroller by MECHANISM rather than by class name, this needs no special case
 * over there. That is exactly why that exclusion was written the way it was.
 * ======================================================================== */
.sx { padding-block: var(--sp-50); }

.sx__head {
	display: flex;
	flex-wrap: wrap;
	align-items: baseline;
	justify-content: space-between;
	gap: var(--sp-20);
}

.sx__h2 { flex: 1 1 auto; }

.sx__rail {
	overflow-x: auto;
	overscroll-behavior-x: contain;
	scrollbar-width: thin;
	-webkit-overflow-scrolling: touch;
}

.sx__track {
	display: flex;
	gap: var(--sp-20);
	width: max-content;
	padding-inline: var(--gutter);
	padding-bottom: var(--sp-10);
}

.sx__chip {
	position: relative;
	display: flex;
	flex: 0 0 auto;
	flex-direction: column;
	justify-content: flex-end;
	width: 13rem;
	height: 9rem;
	overflow: hidden;
	padding: var(--sp-20);
	border-radius: var(--radius-lg);
	background: var(--invert-bg);
	color: var(--invert-text);
	text-decoration: none;
	isolation: isolate;
}

.sx__media {
	position: absolute;
	inset: 0;
	z-index: 0;
}

.sx__img {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
	transition: transform var(--dur-slow) var(--ease-out);
}

.sx__chip::after {
	content: "";
	position: absolute;
	inset: 0;
	z-index: 1;
	background: linear-gradient(
		to top,
		color-mix(in srgb, var(--scrim) 90%, transparent) 0%,
		color-mix(in srgb, var(--scrim) 55%, transparent) 55%,
		color-mix(in srgb, var(--scrim) 20%, transparent) 100%
	);
}

.sx__name,
.sx__count {
	position: relative;
	z-index: 2;
	font-family: var(--sans);
}

.sx__name {
	font-size: var(--fs-large);
	font-weight: 500;
	line-height: var(--ui-snug);
}

.sx__count { font-size: var(--fs-small); }

.sx__chip:hover .sx__img { transform: scale(1.05); }

.sx__chip:focus-visible {
	outline: var(--focus);
	outline-offset: 3px;
}

/* ==========================================================================
 * h2 - THE COVER
 * ======================================================================== */
.cv {
	position: relative;
	display: flex;
	align-items: flex-end;
	min-height: min(88vh, 44rem);
	overflow: hidden;
	background: var(--invert-bg);
	isolation: isolate;
}

.cv__img {
	position: absolute;
	inset: 0;
	z-index: 0;
	width: 100%;
	height: 100%;
	object-fit: cover;
}

.cv__scrim {
	position: absolute;
	inset: 0;
	z-index: 1;
	background: linear-gradient(
		to top,
		color-mix(in srgb, var(--scrim) 94%, transparent) 0%,
		color-mix(in srgb, var(--scrim) 68%, transparent) 50%,
		color-mix(in srgb, var(--scrim) 28%, transparent) 100%
	);
}

.cv__in {
	position: relative;
	z-index: 2;
	padding-block: var(--sp-60) var(--sp-50);
	color: var(--invert-text);
}

.cv__kicker {
	display: flex;
	flex-wrap: wrap;
	align-items: baseline;
	gap: 0.4rem;
	margin: 0 0 var(--sp-20);
	color: var(--invert-dim);
	font-family: var(--sans);
	font-size: var(--fs-small);
}

.cv__cat {
	font-weight: 500;
	letter-spacing: 0.1em;
	text-decoration: none;
	text-transform: uppercase;
}

.cv__cat:hover { text-decoration: underline; }

.cv__h1 {
	margin: 0 0 var(--sp-20);
	max-width: 20ch;
	font-family: var(--serif);
	font-size: var(--fs-huge);
	font-weight: 700;
	letter-spacing: -0.022em;
	line-height: var(--ui-tight);
}

.cv__h1-a { text-decoration: none; }

.cv__h1-a:hover {
	text-decoration: underline;
	text-underline-offset: 5px;
}

.cv__lede {
	margin: 0 0 var(--sp-30);
	max-width: var(--measure);
	color: var(--invert-dim);
	font-family: var(--sans);
	font-size: var(--fs-read-lead);
	line-height: 1.6;
}

.cv__btns {
	display: flex;
	flex-wrap: wrap;
	gap: var(--sp-10);
	margin: 0;
}

.cv__btn {
	display: inline-flex;
	align-items: center;
	min-height: 2.75rem;
	padding-inline: var(--sp-30);
	border: 1px solid transparent;
	border-radius: var(--btn-radius);
	background: var(--invert-text);
	font-family: var(--sans);
	font-size: var(--fs-medium);
	font-weight: 500;
	text-decoration: none;
	transition: background var(--dur) var(--ease);
}

.cv__btn--ghost {
	border-color: var(--invert-dim);
	background: transparent;
}

.cv__btn:focus-visible,
.cv__h1-a:focus-visible {
	outline: 2px solid var(--invert-text);
	outline-offset: 3px;
}

/*
 * THE COVER IS SHORTER HERE THAN IN h2, AND THAT IS THE COMPROMISE THE
 * COMBINATION COSTS.
 *
 * h2's cover is `min(88vh, 44rem)` because its whole thesis is that the first
 * screen holds one story and nothing else. h4 has to hold that story AND the
 * choice under it, or the doors are a thing you discover by scrolling — which
 * is what they already were on the live page, at position four.
 *
 * 74vh leaves roughly the top third of the doors showing on a laptop: enough
 * to read "Read" and "Do" and to know there is a decision, without the cover
 * stopping being a cover. Measured, not guessed — at `min(88vh, 44rem)` the
 * doors began below the fold at 1440x900, which is the one outcome this page
 * cannot have.
 */
.cv--doors { min-height: min(74vh, 36rem); }

/* Room under the cover's own button for the doors to lift into, so the overlap
   never lands on top of "Read this". */
.cv--doors .cv__in { padding-bottom: var(--sp-60); }

/* The doors sit ON the cover rather than after it. `.dr` already carries the
   negative margin for h1; this only has to make sure the doors win the paint
   order against a full-bleed photograph. */
.dr--under .dr__grid { z-index: 4; }

/*
 * The gap under the doors was paid TWICE: `.dr` ends on `padding-bottom:
 * var(--sp-50)` and `.cv__tier` opens on `padding-block: var(--sp-50)`, so
 * about 96px of nothing sat between the choice and the reading that follows
 * it. Neither value is wrong on its own — this is the seam between two
 * layouts that were never meant to meet, and it is the sort of thing only a
 * screenshot finds.
 */
.dr--under { padding-bottom: var(--sp-20); }

/*
 * THE SPINE. Cover (dark) -> doors (paper) -> tier (paper) -> sections
 * (deep) -> index (paper).
 *
 * Without this h4 runs doors, tier, sections and index as four consecutive
 * paper bands — the exact fault this file's header accuses the live front page
 * of, reintroduced by joining two pages that each had their own rhythm.
 * Alternating ONE band in the middle is enough: the eye needs a change, not a
 * stripe.
 *
 * Scoped to h4's body class so h1's and h2's rhythms, which are already
 * right, do not move.
 */
.adb-ui--coverdoors .sx,
.adb-lay--cover .sx { background: var(--paper-deep); }

.adb-ui--coverdoors .cvr,
.adb-lay--cover .cvr { background: var(--paper); }

/*
 * TWO BODY CLASSES FOR ONE PAGE, and that is not belt-and-braces.
 *
 * The preview at `/ui/h4/` renders through `adb_ui_render()` and gets
 * `adb-ui--coverdoors`; the real front page renders through WordPress and
 * gets `adb-lay--cover` from `adb_layout_body_class()`. They are the same
 * design reached by two different doors, so a rule scoped to one of them
 * applies to half the places it is meant to.
 *
 * That is exactly what happened when h4 went live on 2026-10-07: the spine
 * — the one band of `--paper-deep` that stops four paper sections running
 * together — was written against the preview class while h4 WAS a preview,
 * and the live page silently came out flat. Nothing failed, nothing
 * looked broken, and the preview the decision was made from no longer
 * matched the page that shipped.
 *
 * **Anything scoped to `.adb-ui--coverdoors` now owes a twin here.** The
 * rest of this layout needs no such pairing because it is scoped to the
 * component classes, which is the better habit and the reason there are
 * only two lines of it.
 */

.cv__tier { padding-block: var(--sp-50); }

.cv__tiergrid {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
	gap: var(--sp-40);
}

.cv__cardfig {
	display: block;
	overflow: hidden;
	margin-bottom: var(--sp-20);
	border-radius: var(--radius-lg);
	background: var(--surface-3);
}

.cv__cardimg {
	display: block;
	width: 100%;
	height: auto;
	aspect-ratio: 3 / 2;
	object-fit: cover;
	transition: transform var(--dur-slow) var(--ease-out);
}

.cv__card:hover .cv__cardimg { transform: scale(1.03); }

.cv__cardcat {
	font-family: var(--sans);
	font-size: var(--fs-small);
	font-weight: 500;
	letter-spacing: 0.08em;
	text-decoration: none;
	text-transform: uppercase;
}

.cv__cardh {
	margin: 0.4rem 0 0.5rem;
	font-family: var(--serif);
	font-size: var(--fs-x-large);
	font-weight: 700;
	line-height: var(--ui-snug);
}

.cv__cardh a { text-decoration: none; }

.cv__cardh a:hover {
	text-decoration: underline;
	text-decoration-thickness: 2px;
	text-underline-offset: 3px;
}

.cv__cardp {
	margin: 0;
	font-family: var(--sans);
	font-size: var(--fs-medium);
	line-height: 1.55;
}

.cvr {
	padding-block: var(--sp-50);
	background: var(--paper-deep);
}

.cvr__head {
	margin: 0 0 var(--sp-30);
	padding-bottom: var(--sp-10);
	border-bottom: 2px solid var(--ink);
	font-family: var(--sans);
	font-size: var(--fs-small);
	font-weight: 500;
	letter-spacing: 0.12em;
	text-transform: uppercase;
}

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

.cvr__row {
	display: flex;
	flex-wrap: wrap;
	align-items: baseline;
	justify-content: space-between;
	gap: var(--sp-20);
	padding-block: var(--sp-20);
	border-bottom: var(--ui-rule-soft);
}

.cvr__rowh {
	flex: 1 1 20rem;
	font-family: var(--serif);
	font-size: var(--fs-large);
	font-weight: 600;
	line-height: var(--ui-snug);
	text-decoration: none;
}

.cvr__rowh:hover {
	text-decoration: underline;
	text-underline-offset: 3px;
}

.cvr__rowm {
	display: flex;
	align-items: center;
	gap: 0.4rem;
	font-family: var(--sans);
	font-size: var(--fs-small);
}

.cvr__cat {
	font-weight: 500;
	letter-spacing: 0.06em;
	text-decoration: none;
	text-transform: uppercase;
}

.cv__h1 { color: var(--invert-text); }

/* On the dark surfaces */
:root .dr__door { color: var(--ink); }

:root .dr__door--do { color: var(--invert-text); }

:root .dr__door--do .dr__promise { color: var(--invert-dim); }

:root .dr__door--read .dr__eyebrow,
:root .dr__door--read .dr__licat,
:root .dr__door--read .dr__go { color: var(--accent-ink); }

:root .dr__door--read .dr__lih { color: var(--ink); }

:root .cv__h1-a,
:root .cv__cat { color: var(--invert-text); }

:root .cv__btn { color: var(--invert-bg); }

:root .cv__btn--ghost { color: var(--invert-text); }

:root .sx__chip,
:root .sx__name { color: var(--invert-text); }

:root .sx__count { color: var(--invert-dim); }

/* ==========================================================================
 * RESPONSIVE
 * ======================================================================== */
@media (max-width: 63.99rem) {
	/* The doors stack. They stay the same size as each other, which is the
	   claim — one above the other is still equal billing. */
	.dr__grid { grid-template-columns: minmax(0, 1fr); }
	.dr { margin-top: calc(var(--sp-30) * -1); }
}

@media (max-width: 47.99rem) {
	.sx__chip { width: 11rem; height: 8rem; }
}

/* ==========================================================================
 * REDUCED MOTION, FOR THE FRONT PAGE'S FAMILIES
 *
 * Every movement in the cover, the doors, the sections strip and the index is
 * decoration — a tile zoom, a card lift, an arrow nudge. None of it carries
 * meaning, so under `prefers-reduced-motion` all of it goes rather than being
 * slowed down. The hover STATES stay (the background, the underline, the
 * border), because those are feedback and taking them away would remove the
 * signal along with the animation.
 *
 * **THIS BLOCK HAD TO BE WRITTEN BY HAND AFTER THE SPLIT, AND THAT IS WORTH
 * SAYING.** When the cover and doors moved out of `ui-home.css`, the script
 * that split the file sorted each rule by the families in its selector — and
 * the old reduced-motion rule named `.wr__`, `.cv__`, `.wfr__` and `.sx__` in
 * ONE grouped selector. Spanning both halves, it went to the preview sheet
 * with the rest of its group, which meant the LIVE front page animated under
 * reduced motion while the local preview of the same design behaved
 * perfectly. Nothing visible, nothing failing, and only a reader who had
 * asked for less movement would ever have met it.
 *
 * The general shape of that mistake: **a grouped selector is not one rule,
 * and anything that sorts rules by selector will put it in exactly one of the
 * places it belongs.** After any such split, grep the destination for the
 * accessibility blocks by name — they are the ones with nothing to show for
 * themselves when they go missing.
 * ======================================================================== */
@media (prefers-reduced-motion: reduce) {
	.cv *, .cv *::before, .cv *::after,
	.dr *, .dr *::before, .dr *::after,
	.sx *, .sx *::before, .sx *::after,
	.cvr *, .cvr *::before, .cvr *::after {
		animation-duration: 0.01ms !important;
		animation-iteration-count: 1 !important;
		transition-duration: 0.01ms !important;
	}

	.cv__card:hover .cv__cardimg,
	.sx__chip:hover .sx__img,
	.dr__door:hover,
	.dr__door:hover .dr__go::after { transform: none; }
}

/*
 * ==========================================================================
 * THREE FRONT-PAGE CANDIDATES.
 * ==========================================================================
 *
 * Onkar, 2026-10-07: *"now make something thats worthy for home page make 3
 * candidates"*. Served at `/ui/h1/`, `/ui/h2/`, `/ui/h3/` on a local host
 * only. See `inc/ui-home.php` for the thesis behind each and for what the
 * live front page was measured to be getting wrong.
 *
 * STILL NO COLOUR LITERAL. Not one hex, `rgb()` or named colour; every
 * surface, ink, rule and scrim is `var(--token)` out of layer 01.
 * `tests/ui-variants.test.mjs` gates this file with the other two and has been
 * made to fail on purpose. The scrims are `color-mix(in srgb, var(--scrim) N%,
 * transparent)` — a statement about how much of a token to use, not about what
 * colour it is.
 *
 * Geometry comes from `layouts.css`, which these routes are enqueued after.
 *
 * -------------------------------------------------------------------------
 * THE ONE THING ALL THREE DO THAT THE LIVE PAGE DOES NOT
 * -------------------------------------------------------------------------
 *
 * **They give the page a SPINE.** The live front page is one flat paper tone
 * from the bottom of the hero to the newsletter band — eight screens of it —
 * so nothing announces that a new kind of thing has started. Each candidate
 * alternates `--paper` and `--paper-deep`, with exactly one `--invert-bg` band
 * reserved for the toolkit. One inverted band is a statement; two is a stripe
 * pattern, and the thing you most wanted to say stops being the loudest.
 */


/* ==========================================================================
 * h1 - TWO DOORS
 * ======================================================================== */


.wr__head,
.sx__h2 {
	margin: 0 0 var(--sp-30);
	padding-bottom: var(--sp-10);
	border-bottom: 2px solid var(--ink);
	color: var(--ink);
	font-family: var(--sans);
	font-size: var(--fs-small);
	font-weight: 500;
	letter-spacing: 0.12em;
	text-transform: uppercase;
}

.wr__more,
.cvr__more { margin: var(--sp-30) 0 0; }

.wr__morea,
.cvr__morea,
.sx__all,
.wfr__all {
	display: inline-flex;
	align-items: center;
	min-height: 2.75rem;
	font-family: var(--sans);
	font-size: var(--fs-medium);
	font-weight: 500;
	text-decoration: none;
}

.wr__morea:hover,
.cvr__morea:hover,
.sx__all:hover,
.wfr__all:hover { text-decoration: underline; }

/* ==========================================================================
 * h4 — COVER & DOORS. Onkar's combination.
 *
 * Almost all of this page is already written: `.cv` is h2's cover, `.dr` is
 * h1's doors, `.sx` is the sections strip, `.cvr` is h2's ruled index. What
 * h4 needs is the JOIN between the first two, and that is the whole of this
 * block. A fourth set of classes for a page made of two existing ones would
 * be a third copy of the same cover to keep in agreement with the other two.
 * ======================================================================== */


/* And the headings on paper, stated for the same reason rather than left to
   agree with the element rule by luck. */
.wr__head,
.sx__h2,
.cvr__head,
.wf__h1,
.wft__h2,
.wft__grouph,
.wfr__h2 { color: var(--ink); }

/* ==========================================================================
 * THE ANCHOR COLOUR TRAP — see layouts.css for the full reasoning.
 *
 * `site.css` carries `:root a { color: inherit }` at (0,1,1), which beats any
 * single-class colour rule on an anchor. `:root` in front makes these (0,2,0)
 * and settles it. Every link on a dark surface below would otherwise render in
 * near-black ON the photograph it sits on.
 * ======================================================================== */


/* On paper */
:root .wr__cat,
:root .wr__morea,
:root .cvr__morea,
:root .cvr__cat,
:root .cv__cardcat,
:root .sx__all,
:root .wfr__all,
:root .wfr__cat { color: var(--accent-ink); }

:root .wr__rowh,
:root .wr__leadh a,
:root .wr__cardh a,
:root .cv__cardh a,
:root .cvr__rowh,
:root .wft__tool,
:root .wfr__leadh a,
:root .wfr__cardh a,
:root .wfr__rowh { color: var(--ink); }

:root .wr__meta,
:root .wr__rowm,
:root .cvr__rowm,
:root .cv__cardp,
:root .wft__p,
:root .wfr__meta,
:root .wfr__rowm,
:root .wfr__leadp,
:root .wr__leadp { color: var(--ink-faded); }

:root .wr__n,
:root .wfr__n,
:root .wr__dot,
:root .cv__dot,
:root .wfr__dot { color: var(--ink-dim); }
