@layer components {
	/*
	 * The bio is a screen, not a page.
	 *
	 * Its pieces are laid into a grid that spans the whole hero, so every edge
	 * is held by something and there is no side for content to collect against.
	 * The cells that would otherwise run long — the story, the photographs —
	 * turn over in place rather than growing, which is what keeps it to one
	 * screen without anything being cut.
	 */
	.hero.has-bio {
		display: grid;
		height: 100svh;
	}

	.hero.has-bio .hero-media,
	.hero.has-bio .hero-scrim {
		grid-area: 1 / 1;
	}

	.hero.has-bio .hero-media img {
		filter: saturate(0.75);
	}

	.hero.has-bio .hero-scrim {
		background:
			linear-gradient(to bottom, hsl(var(--over-scrim) / 0.72) 0%, hsl(var(--over-scrim) / 0.62) 100%);
		backdrop-filter: blur(2px);
	}

	/* ------------------------------------------------------------- the grid */

	.bento {
		grid-area: 1 / 1;
		z-index: 2;
		display: grid;
		gap: clamp(0.5rem, 0.9vw, 1rem);
		min-height: 0;
		padding: calc(var(--header-h) + var(--space-2xs)) var(--gutter) var(--space-m);
		color: var(--over-ink);

		grid-template-columns: repeat(4, minmax(0, 1fr));
		/*
		 * The middle band is guaranteed a height rather than taking what the
		 * rows above and below leave over — starved of room, the story cell
		 * clipped its own text.
		 */
		grid-template-rows: auto minmax(clamp(10rem, 30vh, 20rem), 1fr) auto;
		grid-template-areas:
			"portrait identity identity stats"
			"portrait story    story    frame"
			"portrait quote    kit      links";
	}

	.cell-portrait { grid-area: portrait; }
	.cell-identity { grid-area: identity; }
	.cell-stats    { grid-area: stats; }
	.cell-story    { grid-area: story; }
	.cell-frame    { grid-area: frame; }
	.cell-quote    { grid-area: quote; }
	.cell-kit      { grid-area: kit; }
	.cell-links    { grid-area: links; }

	/* ------------------------------------------------------------ the cells */

	.cell {
		position: relative;
		display: flex;
		flex-direction: column;
		gap: var(--space-2xs);
		min-width: 0;
		min-height: 0;
		padding: clamp(0.7rem, min(1.3vw, 1.9vh), 1.4rem);
		border-radius: var(--radius-lg);
		border: 1px solid color-mix(in oklab, var(--over-ink) 14%, transparent);
		background: hsl(var(--over-scrim) / 0.26);
		backdrop-filter: blur(14px) saturate(1.2);
		overflow: hidden;
	}

	/* Arriving in order, the way the rest of the site does. */
	.has-js .bento .cell {
		opacity: 0;
		translate: 0 1.25rem;
		filter: blur(6px);
		transition:
			opacity 800ms var(--ease-out),
			translate 800ms var(--ease-out),
			filter 800ms var(--ease-out);
		transition-delay: calc((var(--i, 1) - 1) * 90ms);
	}

	.has-js .bento.is-ready .cell {
		opacity: 1;
		translate: 0 0;
		filter: blur(0);
	}

	.cell-kicker {
		margin: 0;
		font-size: var(--step--2);
		letter-spacing: 0.2em;
		text-transform: uppercase;
		color: color-mix(in oklab, var(--over-ink) 52%, transparent);
	}

	/* ---------------------------------------------------------- the portrait */

	.cell-portrait {
		padding: 0;
		justify-content: flex-end;
	}

	.cell-portrait img {
		position: absolute;
		inset: 0;
		width: 100%;
		height: 100%;
		object-fit: cover;
		object-position: center 30%;
	}

	.cell-plate {
		position: relative;
		padding: var(--space-m) clamp(0.9rem, 1.4vw, 1.5rem) clamp(0.9rem, 1.4vw, 1.5rem);
		background: linear-gradient(to top, hsl(var(--over-scrim) / 0.85), transparent);
	}

	.cell-name {
		margin: 0;
		font-family: var(--font-display);
		font-size: clamp(1.35rem, min(2.4vw, 4vh), 2.5rem);
		line-height: 1;
		letter-spacing: -0.02em;
	}

	.cell-where {
		margin: 0.4em 0 0;
		font-size: var(--step--2);
		letter-spacing: 0.2em;
		text-transform: uppercase;
		color: color-mix(in oklab, var(--over-ink) 66%, transparent);
	}

	/* ---------------------------------------------------------- the identity */

	.cell-identity {
		justify-content: center;
	}

	.identity {
		margin: 0;
		font-family: var(--font-display);
		font-size: clamp(1.05rem, min(2.1vw, 3.4vh), 2.15rem);
		line-height: 1.14;
		letter-spacing: -0.02em;
		text-wrap: balance;
	}

	/* ------------------------------------------------------------- the counts */

	.cell-stats {
		justify-content: center;
	}

	.stats {
		display: grid;
		gap: clamp(0.35rem, 0.9vh, 0.9rem);
		margin: 0;
	}

	.stat {
		display: flex;
		align-items: baseline;
		gap: 0.6em;
	}

	.stat-figure {
		font-family: var(--font-display);
		font-size: clamp(1.2rem, min(2.2vw, 3.4vh), 2.25rem);
		line-height: 1;
		letter-spacing: -0.02em;
		font-variant-numeric: tabular-nums;
	}

	.stat-label {
		margin: 0;
		font-size: var(--step--2);
		letter-spacing: 0.14em;
		text-transform: uppercase;
		color: color-mix(in oklab, var(--over-ink) 60%, transparent);
	}

	/* -------------------------------------------------------------- the story */

	/*
	 * The story is longer than the cell, so it is read a passage at a time.
	 * Passages are stacked in one cell and cross-faded; the cell keeps the
	 * height of the longest, so nothing shifts as they turn over.
	 */
	.story {
		display: grid;
		flex: 1;
		min-height: 0;
	}

	.story-leaf {
		grid-area: 1 / 1;
		margin: 0;
		align-self: center;
		font-size: clamp(0.72rem, 1.55vh, 1rem);
		line-height: 1.6;
		color: color-mix(in oklab, var(--over-ink) 88%, transparent);
		opacity: 0;
		visibility: hidden;
		pointer-events: none;
		translate: 0 0.75rem;
		transition:
			opacity 500ms var(--ease-out),
			translate 500ms var(--ease-out);
	}

	.story-leaf.is-current {
		opacity: 1;
		visibility: visible;
		pointer-events: auto;
		translate: 0 0;
	}

	.story-leaf a {
		color: var(--over-ink);
		text-decoration-color: color-mix(in oklab, var(--over-ink) 50%, transparent);
	}

	.story-bar {
		display: flex;
		align-items: center;
		justify-content: space-between;
		gap: var(--space-s);
		margin-top: auto;
		padding-top: var(--space-2xs);
	}

	.story-dots {
		display: flex;
		gap: 0.4rem;
	}

	/*
	 * The mark is a hairline; the target is not. A 2px-tall button is under
	 * every guideline there is, so the bar is drawn on the background with a
	 * content box and the padding around it carries the press.
	 */
	.story-dot {
		width: 1.5rem;
		height: 2px;
		padding: 12px 0;
		background: color-mix(in oklab, var(--over-ink) 26%, transparent) content-box;
		transition: background var(--dur) var(--ease-out);
	}

	.story-dot.is-current {
		background: var(--over-ink) content-box;
	}

	.story-next,
	.frames-link {
		display: inline-flex;
		align-items: center;
		gap: 0.5em;
		font-size: var(--step--2);
		letter-spacing: 0.16em;
		text-transform: uppercase;
		color: color-mix(in oklab, var(--over-ink) 70%, transparent);
		transition: color var(--dur-fast) var(--ease-out), gap var(--dur-fast) var(--ease-out);
	}

	.story-next:hover,
	.frames-link:hover {
		color: var(--over-ink);
		gap: 0.85em;
	}

	/* -------------------------------------------------------------- the quote */

	.cell-quote {
		justify-content: center;
	}

	.quote {
		margin: 0;
	}

	.quote p {
		margin: 0;
		font-family: var(--font-display);
		font-size: clamp(0.98rem, min(1.7vw, 2.5vh), 1.7rem);
		line-height: 1.2;
		letter-spacing: -0.015em;
		text-wrap: balance;
	}

	.quote p::before {
		content: "\201C";
	}

	.quote p::after {
		content: "\201D";
	}

	.quote cite {
		display: block;
		margin-top: 0.7em;
		font-style: normal;
		font-size: var(--step--2);
		letter-spacing: 0.18em;
		text-transform: uppercase;
		color: color-mix(in oklab, var(--over-ink) 58%, transparent);
	}

	.quote cite::before {
		content: "";
		display: inline-block;
		width: 1.5rem;
		height: 1px;
		margin-right: 0.7em;
		vertical-align: middle;
		background: currentcolor;
	}

	/* ---------------------------------------------------------------- the kit */

	.kit {
		display: flex;
		flex-wrap: wrap;
		gap: 0.35rem;
		margin: 0;
		padding: 0;
		list-style: none;
	}

	.kit li {
		padding: 0.28em 0.65em;
		border-radius: 999px;
		border: 1px solid color-mix(in oklab, var(--over-ink) 20%, transparent);
		font-size: clamp(0.62rem, 1.3vh, 0.75rem);
		white-space: nowrap;
	}

	/* The bodies are read from the frames themselves, so they lead. */
	.kit-bodies li {
		background: color-mix(in oklab, var(--over-ink) 12%, transparent);
		border-color: color-mix(in oklab, var(--over-ink) 30%, transparent);
	}

	/*
	 * The glass reads as a run rather than as chips. Four more pills below the
	 * bodies overran the cell on a short screen, and the lenses are a list of
	 * focal lengths — a sentence suits them better than eight boxes.
	 */
	.kit-glass {
		display: block;
		margin-top: 0.15rem;
		font-size: var(--step--2);
		line-height: 1.7;
		color: color-mix(in oklab, var(--over-ink) 66%, transparent);
	}

	.kit-glass li {
		display: inline;
		padding: 0;
		border: 0;
		white-space: normal;
	}

	.kit-glass li + li::before {
		content: " · ";
		color: color-mix(in oklab, var(--over-ink) 40%, transparent);
	}

	/* ------------------------------------------------------------- the frames */

	.cell-frame {
		padding: 0;
		justify-content: flex-end;
	}

	.frames {
		position: absolute;
		inset: 0;
		display: grid;
	}

	.frame {
		grid-area: 1 / 1;
		margin: 0;
		opacity: 0;
		transition: opacity 1200ms var(--ease-out), scale 6000ms linear;
		scale: 1.06;
	}

	.frame.is-current {
		opacity: 1;
		scale: 1;
	}

	.frame img {
		width: 100%;
		height: 100%;
		object-fit: cover;
		display: block;
	}

	.frames-link {
		position: relative;
		align-self: flex-start;
		margin: 0;
		padding: var(--space-m) clamp(0.9rem, 1.4vw, 1.5rem) clamp(0.9rem, 1.4vw, 1.5rem);
		width: 100%;
		background: linear-gradient(to top, hsl(var(--over-scrim) / 0.85), transparent);
		color: var(--over-ink);
	}

	/* -------------------------------------------------------------- the links */

	.cell-links {
		justify-content: center;
		gap: 0.4rem;
	}

	.link-card {
		display: flex;
		flex-direction: column;
		gap: 0.1em;
		padding: 0.45em 0;
		color: var(--over-ink);
		text-decoration: none;
		border-bottom: 1px solid color-mix(in oklab, var(--over-ink) 14%, transparent);
		transition: border-color var(--dur-fast) var(--ease-out);
	}

	.link-card:hover {
		border-color: color-mix(in oklab, var(--over-ink) 45%, transparent);
	}

	.link-label {
		font-size: var(--step--1);
		line-height: 1.2;
	}

	.link-note {
		font-size: var(--step--2);
		color: color-mix(in oklab, var(--over-ink) 55%, transparent);
	}

	/* Sitting on the portrait, under his name. */
	.link-social {
		margin-top: var(--space-2xs);
	}

	.link-social ul {
		display: flex;
		flex-wrap: wrap;
		gap: 0.35rem;
		margin: 0;
		padding: 0;
		list-style: none;
	}

	/*
	 * On the portrait the four spread the full width of the plate. Huddled at
	 * one end under his name they left the rest of the line empty, and four
	 * evenly spaced marks read as a considered row rather than a leftover.
	 */
	.cell-portrait .link-social ul {
		justify-content: space-between;
		gap: var(--space-2xs);
	}

	/* ------------------------------------------------------------- the screen */

	html:has(body.dz-bio),
	body.dz-bio {
		height: 100svh;
		overflow: hidden;
	}

	body.dz-bio .site-main {
		min-height: 0;
	}

	body.dz-bio .site-main > *:not(.hero):not(dialog),
	body.dz-bio .site-footer {
		display: none;
	}

	/*
	 * The bio's page marker.
	 *
	 * Named for itself rather than "deck-bar", which is what the gallery calls
	 * its own controls — and bio.css loads after gallery.css, so this rule's
	 * `grid-area` was reaching the front page's deck bar and folding it into
	 * the rail's 20px gutter column, arrows and all.
	 */
	.bio-pager {
		display: none;
		grid-area: 1 / 1;
		z-index: 3;
		align-self: end;
		justify-content: center;
		gap: 0.4rem;
		padding-bottom: var(--space-s);
	}

	.bio-pager-dot {
		width: 1.4rem;
		height: 2px;
		padding: 12px 0;
		background: color-mix(in oklab, var(--over-ink) 26%, transparent) content-box;
		transition: background var(--dur) var(--ease-out);
	}

	.bio-pager-dot.is-current {
		background: var(--over-ink) content-box;
	}

	/* ------------------------------------------------------------ the phone */

	/*
	 * One screen, not a deck.
	 *
	 * Four swipes was three too many: two of every pair carried a line or two
	 * of text, and nobody swipes four times to read a bio. So on a phone the
	 * cards stop being cards — they lose their chrome and become bands of one
	 * composition — and what would not fit is either folded into a line or
	 * given a turn in a slot it shares.
	 *
	 * The archive turns over behind everything, his portrait is a mark beside
	 * his name, and the claim and the quote take the same line in turn. The
	 * story keeps its own passages. Nothing is lost; it is said in less room.
	 */
	@media (max-width: 60rem) {
		/*
		 * A column, not a grid — because one band has to be the one that gives.
		 * Sharing the height evenly squeezed the story worst of all: its
		 * longest passage wanted 282px and was handed 252, so it was the one
		 * band that got cut. Here every other band keeps the height it asks
		 * for and the story takes whatever is left.
		 */
		.bento {
			display: flex;
			flex-direction: column;
			gap: clamp(var(--space-2xs), 1.6vh, var(--space-m));
			overflow: visible;
			padding: calc(var(--header-h) + var(--space-s)) var(--gutter) var(--space-m);
			scroll-snap-type: none;
		}

		/* The chrome goes with the cards. */
		.bento .cell {
			grid-area: auto;
			order: 0;
			padding: 0;
			border: 0;
			border-radius: 0;
			background: none;
			backdrop-filter: none;
			overflow: visible;
			scroll-snap-align: none;
			min-height: 0;
		}

		/* --------------------------------------------- the frame behind it all */

		.bento .cell-frame {
			position: absolute;
			inset: 0;
			z-index: -1;
			order: -1;
		}

		.bento .cell-frame .frames-link {
			display: none;
		}

		/* ------------------------------------------------------------ his name */

		/*
		 * The mark, his name and where he is on one line; the four accounts on
		 * their own beneath. Beside the name they had 262px to fit four 56px
		 * circles into, so the fourth wrapped and sat alone under the other
		 * three — and the band grew by a whole row to hold it.
		 */
		.bento .cell-portrait {
			display: grid;
			grid-template-columns: auto minmax(0, 1fr);
			grid-template-rows: auto auto auto;
			align-items: center;
			gap: 0 var(--space-s);
			order: 1;
		}

		/* The plate steps aside so its parts can be placed individually. */
		.bento .cell-portrait .cell-plate {
			display: contents;
		}

		/* The mark spans the two lines it stands beside. */
		.bento .cell-portrait img {
			grid-row: 1 / 3;
			grid-column: 1;
		}

		.bento .cell-name {
			grid-row: 1;
			grid-column: 2;
			align-self: end;
			line-height: 1.05;
		}

		.bento .cell-where {
			grid-row: 2;
			grid-column: 2;
			align-self: start;
			margin-top: 0.2em;
		}

		.bento .cell-portrait .link-social {
			grid-row: 3;
			grid-column: 1 / -1;
			margin-top: var(--space-s);
		}

		/* The theme draws this block now, so no inline padding to fight. */
		.bento .cell-portrait .link-social a {
			width: clamp(2.5rem, 11vw, 3rem);
			height: clamp(2.5rem, 11vw, 3rem);
			padding: 0;
		}

		.bento .cell-portrait .link-social .wp-block-coblocks-social__icon {
			flex: none;
			width: 1.15rem;
			height: 1.15rem;
		}

		/* The portrait is a mark beside the name rather than a card of its own. */
		.bento .cell-portrait img {
			position: static;
			width: clamp(3rem, 15vw, 4.25rem);
			height: clamp(3rem, 15vw, 4.25rem);
			border-radius: 50%;
			object-position: center 25%;
			border: 1px solid color-mix(in oklab, var(--over-ink) 25%, transparent);
		}

		.bento .cell-plate {
			padding: 0;
			background: none;
		}

		.cell-name {
			font-size: clamp(1.4rem, 7vw, 2rem);
		}

		/* --------------------------------------------- the claim and the quote */

		/*
		 * Two short display lines that say the same kind of thing, so they
		 * share one slot and take turns. Stacked in a single grid cell the
		 * band keeps the height of the taller, and nothing below it moves.
		 */
		.bento .cell-identity,
		.bento .cell-quote {
			order: 2;
			justify-content: center;
			transition: opacity 700ms var(--ease-out), translate 700ms var(--ease-out);
		}

		.bento .cell-identity .cell-kicker {
			display: none;
		}

		.bento .cell-say {
			position: relative;
			order: 2;
			min-height: 0;
		}

		/*
		 * Hiding the one that is not speaking has to out-rank the arrival rule
		 * that lights every cell once the screen is ready — `.bento.is-ready
		 * .cell` is (0,4,0), and a plain `.bento .cell-quote` is (0,3,0), so
		 * both lines were showing at full strength, one across the other.
		 */
		.has-js .bento.is-ready .cell-identity:not(.is-saying),
		.has-js .bento.is-ready .cell-quote:not(.is-saying) {
			opacity: 0;
			translate: 0 0.5rem;
			pointer-events: none;
		}

		/* The one waiting its turn is lifted out of flow, so the band keeps
		   the height of a single line and nothing under it moves. */
		.has-js .bento .cell-quote {
			position: absolute;
			inset: 0;
		}

		.identity,
		.quote p {
			font-size: clamp(1.15rem, 5.4vw, 1.6rem);
			line-height: 1.15;
		}

		/* ---------------------------------------------------------- the story */

		.bento .cell-story {
			order: 3;
			flex: 1;
			min-height: 0;
			padding-top: var(--space-2xs);
			border-top: 1px solid color-mix(in oklab, var(--over-ink) 16%, transparent);
		}

		.bento .story {
			min-height: 0;
		}

		.bento .cell-story .cell-kicker {
			display: none;
		}

		.story-leaf {
			font-size: clamp(0.72rem, 1.75vh, 0.95rem);
			line-height: 1.55;
		}

		/* ---------------------------------------------------------- the counts */

		/* Three figures on one line, which is all they ever needed. */
		.bento .cell-stats {
			order: 4;
		}

		.bento .stats {
			grid-auto-flow: column;
			grid-auto-columns: minmax(0, 1fr);
			gap: var(--space-2xs);
		}

		/*
		 * Centred in its own third. Left-aligned, each figure sat against the
		 * left edge of a 106px column with 80-odd pixels of nothing after it —
		 * three short numbers each shoved to one side of its own space.
		 */
		.bento .stat {
			flex-direction: column;
			align-items: center;
			justify-content: start;
			text-align: center;
			gap: 0.1em;
		}

		/* "years behind the lens" breaks evenly rather than dropping one word. */
		.bento .stat-label {
			text-wrap: balance;
		}

		.stat-figure {
			font-size: clamp(1.15rem, 5.5vw, 1.6rem);
		}

		.stat-label {
			font-size: 0.6rem;
			letter-spacing: 0.1em;
		}

		/* ------------------------------------------------------------- the kit */

		/* The bodies, as a line. The lens list is a page's worth of detail. */
		.bento .cell-kit {
			order: 5;
		}

		.bento .cell-kit .cell-kicker,
		.bento .kit-glass {
			display: none;
		}

		.bento .kit-bodies {
			gap: 0.3rem;
		}

		.bento .kit-bodies li {
			font-size: 0.62rem;
			padding: 0.25em 0.6em;
		}

		/* ----------------------------------------------------------- the links */

		.bento .cell-links {
			order: 6;
			gap: var(--space-2xs);
			padding-top: var(--space-2xs);
			border-top: 1px solid color-mix(in oklab, var(--over-ink) 16%, transparent);
		}

		.bento .cell-links .cell-kicker {
			display: none;
		}

		.bento .link-card {
			flex-direction: row;
			align-items: baseline;
			gap: 0.5em;
			padding: 0.3em 0;
			border-bottom: 0;
		}

		.bento .link-note {
			display: none;
		}

		.bento .link-label {
			font-size: var(--step--2);
			letter-spacing: 0.14em;
			text-transform: uppercase;
		}

		/* The pager has nothing to page through now. */
		.bio-pager {
			display: none;
		}
	}

	/*
	 * Shorter screens, in the order things can be spared.
	 *
	 * The story is the bio — his own account of the work — so it is the last
	 * thing to give. What goes first is the kit, which is a detail the archive
	 * pages carry anyway, and then the notes under the two links, whose labels
	 * already say where they lead.
	 */
	@media (max-width: 60rem) and (max-height: 47rem) {
		.bento .cell-kit {
			display: none;
		}

		.bento .cell-links {
			flex-direction: row;
			flex-wrap: wrap;
			gap: var(--space-s);
		}

		.bento .cell-portrait .link-social a {
			width: 2.25rem;
			height: 2.25rem;
		}

		.bento .cell-portrait .link-social .wp-block-coblocks-social__icon {
			width: 1rem;
			height: 1rem;
		}

		.bento .cell-portrait .link-social {
			margin-top: var(--space-2xs);
		}

		.stat-figure {
			font-size: clamp(1rem, 4.6vw, 1.3rem);
		}
	}

	@media (max-width: 60rem) and (max-height: 38rem) {
		.bento .cell-links {
			display: none;
		}

		.bento .cell-portrait img {
			width: 2.5rem;
			height: 2.5rem;
		}

		.identity,
		.quote p {
			font-size: clamp(1rem, 4.6vw, 1.2rem);
		}
	}

	/*
	 * A short phone halves the halved cell again, and the longest passage went
	 * 23px over. The label above it goes rather than the type shrinking below
	 * reading size — a paragraph of prose does not need to be told it is one.
	 */
	@media (max-width: 60rem) and (max-height: 46rem) {
		.cell-story .cell-kicker {
			display: none;
		}

		.story-leaf {
			font-size: clamp(0.68rem, 1.6vh, 0.9rem);
			line-height: 1.5;
		}
	}
}

/*
 * Deliberately outside the layers.
 *
 * CoBlocks ships its own stylesheet for the social block, and a plugin sheet is
 * unlayered — unlayered rules beat every @layer regardless of specificity. These
 * overrides have to sit at the same level to reach the buttons at all.
 */
.dz-bio .wp-block-coblocks-social__button {
	background-color: transparent;
	border: 1px solid color-mix(in oklab, var(--over-ink) 28%, transparent);
	color: var(--over-ink);
	transition:
		border-color var(--dur-fast) var(--ease-out),
		background-color var(--dur-fast) var(--ease-out);
}

.dz-bio .wp-block-coblocks-social__button:hover,
.dz-bio .wp-block-coblocks-social__button:focus-visible {
	background-color: color-mix(in oklab, var(--over-ink) 14%, transparent);
	border-color: var(--over-ink);
	color: var(--over-ink);
}

/* The icon says it; the word beside it is for screen readers. */
.dz-bio .wp-block-coblocks-social__text {
	position: absolute;
	width: 1px;
	height: 1px;
	margin: -1px;
	padding: 0;
	overflow: hidden;
	clip-path: inset(50%);
	white-space: nowrap;
	border: 0;
}
