/* ==========================================================================
   PAGES — rules for one template only, keyed on WordPress's body classes.
   ========================================================================== */

@layer pages {

	/* ======================================================================
	   HOMEPAGE (body.home). Ported from docs/prototype/hero-paper-prototype.html.
	   Order: hero, intro, client logos, "What I do" (sticky shape panel with
	   the four service bands sliding under it), Selected work.
	   The shapes and the text fades are drawn by assets/js/home.js.
	   ====================================================================== */

	/* The header floats over the hero here (the hero's sizes are tuned to it);
	   it looks and behaves the same as on every other page. */
	.home .site-header { position: fixed; inset: 0 0 auto 0; }
	/* Jumps to a part of the page (the scroll arrow) stop below the header */
	html:has(body.home) { scroll-padding-top: calc(env(safe-area-inset-top, 0px) + var(--head-h)); }
	.home { overflow-x: clip; }   /* clip, not hidden: hidden would stop the sticky panel working */

	/* Homepage type: grows with the screen's height on phones */
	.home main h1 {
		margin: 0 0 20px; font-size: clamp(28px, min(11.5vw, calc(4.756 * var(--vh))), 48px);   /* 36px on an iPhone 16 Pro */
		font-size: clamp(28px, min(11.5vw, calc(4.756 * var(--vh)), 11.25cqi), 48px);   /* ...and never wider than its column: "Graphic Designer" is about 0.88 of the size wide (Jarv, 25 Oct 2026). The line above is for browsers without cqi */
		line-height: 1.1; letter-spacing: -0.028em;
	}
	/* not the project cards: they keep their own sizes (components.css) */
	.home main h2, .home main h3:not(:where(.work-card__name)) {
		margin: 0 0 20px; font-size: clamp(26px, min(10.1vw, calc(4.756 * var(--vh))), 46px);
		line-height: 1.1; letter-spacing: -0.024em;
	}
	.home main p:not(:where([class^="work-card"])) {
		max-width: none; font-size: clamp(16px, min(6vw, calc(2.7 * var(--vh))), 25px);
		line-height: 1.42; letter-spacing: -0.005em; color: var(--c-muted);
	}
	.home .nowrap { white-space: nowrap; }   /* keep hyphenated words on one line */

	/* ---- Shape panels ---- */
	.art {
		height: var(--art-h);
		padding: calc(env(safe-area-inset-top, 0px) + var(--head-h) + 2px) var(--gut) 0;
		background: var(--grain) var(--c-paper);
	}
	.art canvas { display: block; width: 100%; height: 100%; }

	/* ---- Hero: fills the first screen, then scrolls away ---- */
	.hero { position: relative; min-height: 100svh; display: flex; flex-direction: column; padding-bottom: 45px; }
	.hero .art {
		height: var(--hero-art-h);
		padding-top: calc(env(safe-area-inset-top, 0px) + var(--head-h) + 2px + var(--hero-drop));
	}
	.hero-copy { padding: calc(5.15 * var(--vh)) var(--gut) 45px; container-type: inline-size; }   /* the heading sizes to this column (cqi, below) */

	/* The scroll arrow, in a ring, centred under the subline */
	.scroll-cue {
		position: relative; align-self: center; margin: auto 0;   /* spare height shared above and below */
		display: flex; align-items: center; justify-content: center;
		width: 52px; height: 52px; border: 2.83px solid var(--c-ink); border-radius: 50%; color: var(--c-ink);
	}
	.scroll-cue svg { width: 34px; height: 34px; }
	/* The printed version (home.js draws it): a textured ring and a slightly
	   hand-drawn arrow replace the CSS ring and the flat arrow */
	.cue-printed .scroll-cue { border-color: transparent; }
	.cue-printed .scroll-cue svg { display: none; }
	.cue-ring { position: absolute; inset: -2.83px; width: 52px; height: 52px; }
	.cue-arrow { width: 34px; height: 34px; }
	.hero .art canvas { cursor: pointer; }   /* tap the hero pieces to replay the intro */

	/* ---- Intro paragraph ---- */
	.intro { padding: 56px var(--gut) 64px; }
	.home .intro p { color: var(--c-ink); }
	.intro p + p { margin-top: 1em; }

	/* ---- Client logos, on ink ---- */
	.logos { padding: 56px var(--gut) 64px; background: var(--grain-ink) var(--c-ink); }
	.home .logos h2 { margin-bottom: 10px; color: var(--c-paper); }
	.home .logos p { margin-bottom: 36px; color: var(--c-mist); }

	/* ---- Services (Jarv, 24 Oct 2026): four bands, each with a paper-pieces
	   icon (inc/home.php) in place of the old sticky shape panel. Stacked with
	   a keyline between them on phones; two by two with a keyline cross from
	   1280px (below). The icons and arrows move in motion.css. ---- */
	.svc-intro { padding: 56px var(--gut) 40px; }
	.svc-band { padding: 40px var(--gut) 48px; border-top: 1px solid var(--rule); background: var(--grain) var(--c-paper); }
	.home .svc-band h3, .home .svc-band p { color: var(--c-ink); }
	/* "What I do" sized for phones by width and screen height */
	.home .svc-intro h2 {
		margin-bottom: 16px; font-size: clamp(27px, min(10.2vw, calc(calc(5.487 * var(--vh)) - 5.54px)), 46px);
	}
	/* The services on phones: fixed sizes (Jarv, 25 Oct 2026) */
	.home .svc-band h3 { margin-bottom: 16px; font-size: 32px; }
	.home .svc-band p, .home .svc-intro p { font-size: 18px; }
	.svc-band p + p, .svc-intro p + p { margin-top: 1.42em; }
	.svc-band .btns { margin-top: 16px; }
	.band__title-link:hover { opacity: 0.7; }   /* a band heading, once its service page is published */

	/* The icon. --size: 104px on phones (Jarv, 25 Oct 2026; was 130), smaller on
	   desktop. Each drawing sits 3 units in from the left of its 40-unit
	   square (Video 4), so it's pulled left by that much to line up with the
	   text. The B2 ink texture (made by home.js as --ink-tex) is cut out of
	   it, so the paper shows through as on the hero pieces; the link arrows too. */
	.svc-icon {
		--size: 104px;
		display: block; width: var(--size); height: var(--size); overflow: visible;
		margin: 0 0 20px calc(var(--size) * var(--in, 3) / -40);
	}
	.svc-band--motion .svc-icon { --in: 4; }
	.svc-icon, .svc-link__arrow {
		-webkit-mask-image: linear-gradient(#000, #000), var(--ink-tex, linear-gradient(transparent, transparent));
		        mask-image: linear-gradient(#000, #000), var(--ink-tex, linear-gradient(transparent, transparent));
		-webkit-mask-size: auto, 358px 358px;   /* the pieces' grain: 512px texture at 0.7 */
		        mask-size: auto, 358px 358px;
		-webkit-mask-composite: xor;
		        mask-composite: exclude;
	}
	/* Each piece is drawn finished; --p (0 at rest, 1 finished, set by
	   motion.css) brings it from its loose position: --q is the piece's own
	   share of --p, --u how far it still has to go */
	.svc-icon .pc {
		--q: clamp(0, (var(--p) - var(--a, 0)) / var(--w, 1), 1);
		--u: calc(1 - var(--q));
		transform-box: fill-box;
		transform-origin: var(--o, center);
		transform: translate(calc(var(--x, 0px) * var(--u)), calc(var(--y, 0px) * var(--u)))
			rotate(calc(var(--r, 0deg) * var(--u)))
			scale(calc(1 + (var(--sx, var(--s, 1)) - 1) * var(--u)), calc(1 + (var(--s, 1) - 1) * var(--u)));
	}

	/* Pieces that change length are trimmed, not stretched, so their rounded
	   corners keep their shape (Jarv, 24 Oct 2026: a stretched bar's corners
	   looked distorted). Each is drawn at its longest; --r0 / --l0 trim the
	   right / left at rest, --r1 the right once finished; --rr is the corner. */
	.svc-icon .clip { clip-path: inset(0 calc(var(--r0, 0px) * var(--u) + var(--r1, 0px) * var(--q)) 0 calc(var(--l0, 0px) * var(--u)) round var(--rr, 1.5px)); }

	/* The link to that service's work: an arrow and the words, no button */
	.svc-link {
		display: inline-flex; align-items: center; gap: 10px; min-height: 44px;
		color: var(--c-ink); font-weight: 600; font-size: 18px; text-decoration: none;
	}
	.svc-link:focus-visible { outline: 3px solid var(--c-ink); outline-offset: 4px; border-radius: 3px; }
	.svc-link__arrow { flex: none; width: 22px; height: 22px; }
	@media (hover: hover) { .svc-link:hover { color: var(--c-ink-hover); } }   /* a step lighter, like the buttons */

	/* ---- Selected work, on a light blue (sky at 24% on paper) ---- */
	.work-pick { padding: 64px var(--gut); background: var(--grain) var(--c-sky-band); }
	.work-row { display: grid; gap: 6px; }
	@media (min-width: 600px) and (max-width: 1023px) { .work-row { grid-template-columns: 1fr 1fr; } }   /* tablets: two by two */

	/* ---- Desktop, 1024px and up ---- */
	@media (min-width: 1024px) {
		.home main h1 { font-size: 72px; font-size: min(72px, 11.25cqi); }   /* 72px where it fits; a touch smaller on narrower laptops so each line stays whole */
		.home main h2, .home main h3:not(:where(.work-card__name)), .home .svc-band h3, .home .svc-intro h2 { font-size: 48px; }
		.home main p:not(:where([class^="work-card"])), .home .svc-band p, .home .svc-intro p { font-size: 22px; }

		/* Hero: two equal halves, text left, shapes right, arrow centred below,
		   24px clear of the header above and of the arrow below */
		.hero {
			display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); align-items: center;
			min-height: 100vh; padding: calc(var(--head-h) + 24px) 0 calc(40px + 52px + 24px);
		}
		.hero .art { grid-column: 2; grid-row: 1; height: auto; padding: 0 48px; background: none; }
		.hero .art canvas { height: min(60vh, 520px); }
		/* The text's left gap matches the space right of the shapes (Jarv, 21 Oct
		   2026), never closer to the edge than the header; it keeps its full
		   640px (so "Senior Freelance" stays on one line), stopping 48px short of the shapes */
		.hero-copy {
			grid-column: 1; grid-row: 1; justify-self: start;
			--hero-left: max(var(--gut), calc(25vw - 190px));
			padding: 0 0 0 var(--hero-left);
			width: calc(var(--hero-left) + min(640px, 75vw - 238px - var(--hero-left)));
		}
		.home .hero-copy p { font-size: 26px; }
		.scroll-cue { position: absolute; bottom: 40px; left: calc(50% - 26px); margin: 0; }

		.intro { padding: 96px var(--gut); }
		.home .intro p { max-width: 720px; margin-inline: auto; font-size: 26px; }   /* block centred, text left-aligned */

		.logos { padding: 96px var(--gut) 112px; }

		/* Services, stacked (until 1280px) */
		.svc-intro { padding: 96px var(--gut) 48px; }
		.svc-band { padding: 64px var(--gut); }
		.svc-intro .copy, .svc-band .copy { max-width: 760px; }
		.svc-icon { --size: 96px; margin-bottom: 24px; }
		.svc-link { font-size: 19px; }
		.svc-link__arrow { width: 24px; height: 24px; }

		.work-pick { padding: 80px var(--gut) 96px; }
		.work-row { grid-template-columns: repeat(4, 1fr); gap: 8px; }
		.work-card__name { font-size: 22px; }
	}

	/* Services from 1280px: two by two with a keyline cross, the icon left
	   of the words, its top level with the top of the heading's capitals,
	   18px paragraphs (Jarv, 24 Oct 2026). Some scrolling is fine. */
	@media (min-width: 1280px) {
		.services { display: grid; grid-template-columns: 1fr 1fr; padding: 0 var(--gut) 64px; }
		.svc-intro { grid-column: 1 / -1; padding: 96px 0 64px 120px; }   /* lines up with the service words (icon 80 + gap 40); 64px down to the keylines */
		.svc-band {
			display: grid; grid-template-columns: 80px minmax(0, 1fr); column-gap: 40px; align-content: start;
			border-top: 0; padding: 64px 56px 64px 0;
		}
		.svc-band--digital, .svc-band--print { padding: 64px 0 64px 56px; border-left: 1px solid var(--rule); }
		.svc-band--brand, .svc-band--digital { border-bottom: 1px solid var(--rule); }
		.svc-icon { grid-column: 1; grid-row: 1 / span 2; --size: 80px; margin-bottom: 0; }
		/* lifted by the space inside each drawing above its shapes */
		.svc-band--brand .svc-icon { margin-top: -6.5px; }
		.svc-band--digital .svc-icon { margin-top: -2.5px; }
		.svc-band--motion .svc-icon { margin-top: 1.5px; }
		.svc-band--print .svc-icon { margin-top: -0.5px; }
		.svc-band .copy, .svc-band .btns { grid-column: 2; }
		.svc-band .copy { max-width: 560px; }
		.home .svc-band h3 { font-size: 40px; margin-bottom: 14px; }
		.home .svc-band p { font-size: 18px; }
		.svc-band p + p { margin-top: 1em; }
		.svc-band .btns { margin-top: 24px; }
		.svc-intro .copy > :last-child { margin-bottom: 0; }
	}

	/* Very big screens (over 1800px): content stays in a centred 1800px frame;
	   only the colours run on to the screen edges */
	@media (min-width: 1801px) {
		.home { --frame: calc((100vw - 1800px) / 2); }
		.hero { padding-inline: var(--frame); }
		.hero-copy { --hero-left: 260px; }   /* matches the shapes' right gap inside the frame */
	}

	/* ======================================================================
	   WORK AND PROJECT PAGES: a touch lighter paper than the homepage
	   (Jarv, 14 Oct 2026), the same grain
	   ====================================================================== */
	body.is-work, body.is-project, body.is-about, body.is-contact, body.error404 { --bg: var(--c-paper-light); }

	/* ======================================================================
	   WORK PAGE (body.is-work, /work/). Ported from docs/prototype/work.html.
	   ====================================================================== */
	.work-intro { padding: 40px var(--gut) 17px; }   /* + the filters' 15px top = 32 */
	.work-intro h1 { margin: 0 0 12px; font-size: 36px; line-height: 1.1; letter-spacing: -0.02em; }
	.work-intro p { max-width: none; font-size: 18px; line-height: 1.45; color: var(--c-muted); }

	/* Service filters: All plus one per service; the chosen one filled ink.
	   The row sticks just under the header on the same frosted paper, tucked
	   4px under it so the two panels overlap with no seam. */
	.work-filters {
		position: sticky; top: calc(env(safe-area-inset-top, 0px) + var(--head-h) - 4px); z-index: 6;
		display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 8px; padding: 15px var(--gut) 16px;
		background: color-mix(in srgb, var(--bg) 90%, transparent);
		-webkit-backdrop-filter: blur(14px); backdrop-filter: blur(14px);
	}
	.work-filters__btn {
		display: inline-flex; align-items: center; padding: 9px 16px; border: 1px solid var(--c-ink); border-radius: 3px;
		color: var(--c-ink); font-size: 15px; font-weight: 500; line-height: 1;
		transition: background-color 0.2s ease;
	}
	.work-filters__btn:hover { background: color-mix(in srgb, var(--c-ink) 8%, transparent); }
	.work-filters__btn[aria-current] { background: var(--c-ink); color: var(--bg); }
	.work-filters__btn[aria-current]:hover { background: var(--c-ink-hover); }
	/* Once stuck under the header, a light keyline above and below (drawn inside, so nothing moves) */
	.work-filters.is-stuck { box-shadow: inset 0 1px 0 color-mix(in srgb, var(--c-ink) 12%, transparent), inset 0 -1px 0 color-mix(in srgb, var(--c-ink) 12%, transparent); }
	@media (prefers-reduced-motion: reduce) { .work-filters__btn { transition: none; } }

	/* Phones: one line you swipe sideways, so the stuck bar stays slim */
	@media (max-width: 599px) {
		.work-filters { flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none; -webkit-overflow-scrolling: touch; overscroll-behavior-x: contain; }
		.work-filters::-webkit-scrollbar { display: none; }
		.work-filters__btn { flex: none; white-space: nowrap; }
		.work-filters::after { content: ""; flex: none; width: 1px; }   /* keeps the right-hand padding when scrolled to the end */
	}

	/* The cards: 1 across on phones, 2 from 600px, 4 from 1024px. Without the
	   script they sit in plain rows; assets/js/work.js stacks them in balanced
	   columns (each card into the shortest column, in order). */
	.work-grid {
		--cols: 1; --gap: 6px;
		display: grid; grid-template-columns: repeat(var(--cols), minmax(0, 1fr)); gap: var(--gap); align-items: start;
		padding: 0 var(--gut) 64px;
	}
	@media (min-width: 600px) { .work-grid { --cols: 2; } }
	.work-grid > li[hidden] { display: none; }
	.work-grid .work-card { background: var(--grain) var(--c-white); }
	/* as the prototype's Work cards: the summary and tags set a touch tighter than the homepage's */
	.work-grid .work-card__line { letter-spacing: normal; }
	.work-grid .work-card__tags { line-height: normal; letter-spacing: normal; }
	.work-grid.is-masonry { display: block; position: relative; }
	.work-grid.is-masonry > li { position: absolute; top: 0; left: 0; }

	@media (min-width: 1024px) {
		.work-intro { padding: 72px var(--gut) 33px; }
		.work-intro h1 { font-size: 50px; }
		.work-intro p { font-size: 20px; }
		.work-grid { --cols: 4; --gap: 8px; padding-bottom: 112px; }
	}

	/* ======================================================================
	   PROJECT PAGES (body.is-project, /work/{path}/). Ported from
	   docs/prototype/portfolio.html (22 Oct 2026): the split layout (story
	   beside the pictures) on paper, the only one kept. The prototype's own
	   colour names are set here to the final colours, so its rules carry
	   over unchanged; its older ink (#08184a) is now the site's ink.
	   ====================================================================== */
	body.is-project {
		--ink: var(--c-ink);
		--muted: var(--c-muted);
		--paper: var(--c-paper-light);
		--rule: #dfe3ee;
		--body: #dbe8ff;            /* text on the larger view's dark ground */
		--gap: 6px;                 /* between picture tiles */
		--radius: 5px;              /* soft corners on tiles and the story panel */
	}
	@media (min-width: 1024px) { body.is-project { --gap: 8px; } }
	/* As the prototype: the header floats over the coloured project header
	   (its top padding allows for it), and text the page doesn't size itself
	   uses the browser's normal line spacing */
	.is-project .site-header { position: fixed; inset: 0 0 auto 0; }
	.is-project .site-main { color: var(--ink); line-height: normal; }
	.is-project .site-main p { max-width: none; }   /* widths come from the layout here, as the prototype (the story column is capped at 62ch itself) */
	/* The arrows (← →) aren't in Archivo: take them from the system font, as the
	   prototype did, so they look (and line up) the same */
	.is-project [aria-hidden="true"]:is(.crumbs *, .p-next *, .crumb-bar *) { font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif; }

	/* ---- Project header: in the project's own colour, white text ---- */
	.p-head {
	  background: var(--project); color: #fff;
	  padding: calc(var(--head-h) + 32px) var(--gut) 32px;
	}
	.crumbs { margin: 0 0 20px; font-size: 15px; color: #fff; }
	.crumbs a { color: #fff; transition: opacity 0.2s ease; }
	.crumbs a:hover { opacity: 0.7; }
	/* Back bar (Jarv, 22 Oct 2026): once "All work" scrolls away, a slim bar in the
	   project's colour appears under the header with the way back and the project's
	   name, so phones (where Work sits in the menu) never need to scroll to the top.
	   Opacity only, never moves. */
	.crumb-bar {
	  position: fixed; left: 0; right: 0; z-index: 39;
	  top: calc(env(safe-area-inset-top, 0px) + var(--head-h));
	  display: flex; align-items: baseline; gap: 14px; height: 40px; line-height: 40px; padding: 0 var(--gut);   /* baseline: both words sit on one line (Jarv, 22 Oct 2026) */
	  background: var(--project); color: #fff; font-size: 15px;
	  opacity: 0; visibility: hidden; transition: opacity 0.2s ease, visibility 0s linear 0.2s;
	}
	.crumb-bar.on { opacity: 1; visibility: visible; transition: opacity 0.2s ease; }
	.crumb-bar a { flex: none; color: #fff; font-weight: 700; transition: opacity 0.2s ease; }
	.crumb-bar a:hover { opacity: 0.7; }
	.crumb-bar a:focus-visible { outline: 2px solid #fff; outline-offset: 3px; }
	.crumb-bar .t { min-width: 0; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; opacity: 0.8; }
	.menu-open .crumb-bar { visibility: hidden; }
	@media (prefers-reduced-motion: reduce) { .crumb-bar, .crumb-bar a { transition: none; } }
	.p-head h1 {
	  margin: 0 0 16px; font-weight: 900; letter-spacing: -0.03em; line-height: 1.02;
	  font-size: clamp(40px, 10.5vw, 50px); text-wrap: balance;   /* 900, 50px on desktop (Jarv, 21 Oct 2026) */
	}
	.lede { margin: 0;   /* full width, so the header stays short */ font-size: clamp(18px, 4.6vw, 20px); line-height: 1.35; color: #fff; text-wrap: pretty; }   /* 20px on desktop (Jarv, 21 Oct 2026) */
	/* The live site, under the summary (web projects): led by the arrow from the
	   homepage service links, which nudges right on hover (Jarv, 25 Oct 2026) */
	.p-head .site { margin: 16px 0 0; font-size: clamp(16px, 4.2vw, 18px); font-weight: 700; }
	.site-link { display: inline-flex; align-items: center; gap: 10px; min-height: 44px; color: #fff; text-decoration: none; transition: opacity 0.2s ease; }
	.site-link:hover { opacity: 0.7; }
	.site-link:focus-visible { outline: 2px solid #fff; outline-offset: 3px; border-radius: 3px; }
	.site-arrow { flex: none; width: 22px; height: 22px; }
	@media (hover: hover) and (prefers-reduced-motion: no-preference) {
	  .site-arrow { transition: transform 0.25s cubic-bezier(0.3, 0, 0.2, 1); }
	  .site-link:hover .site-arrow { transform: translateX(5px); }
	}
	@media (prefers-reduced-motion: reduce) { .site-link { transition: none; } }
	@media (min-width: 1024px) { .p-head { padding: calc(var(--head-h) + 64px) var(--gut) 40px; } }

	/* ---- Lead image: the strongest single picture, full content width ---- */
	.p-lead { margin: 0; padding: var(--gap) var(--gut) 0; }   /* tucked right under the header, same gap as the image grids */
	.p-lead img { width: 100%; height: auto; aspect-ratio: var(--la, auto); object-fit: cover; object-position: var(--pos, 50% 50%); }

	/* ---- Strip: up to three images, one wide and two narrower, kept short
	   so the story starts near the top of the page ---- */
	/* One row, the first image twice the width of the others; short on phones */
	.p-strip { display: grid; grid-template-columns: 2fr 1fr 1fr; gap: var(--gap); padding: var(--gap) var(--gut) 0; height: calc(160px + var(--gap)); }
	.p-strip .tile, .p-strip .tile-todo { aspect-ratio: auto; height: auto; grid-column: auto; }
	.p-strip .tile:first-child:nth-last-child(2) { grid-column: span 2; }   /* only two: the first takes two thirds, the second one third */
	.p-strip .tile:only-child { grid-column: 1 / -1; }                /* only one: full width */
	@media (min-width: 700px) { .p-strip { height: calc(clamp(240px, 28vw, 440px) + var(--gap)); } }

	/* ---- The story: label on the left, text on the right (desktop) ---- */
	.p-story { padding: 56px var(--gut) 24px; display: grid; gap: 32px; }
	.p-story section { display: grid; gap: 8px; }
	.p-story p + p { margin-top: 4px; }   /* paragraphs within a section: 12px apart */
	.p-story h2 { margin: 0; font-size: clamp(17px, 4.4vw, 22px); line-height: 1.5; font-weight: 900; letter-spacing: -0.01em; }   /* 900 (Jarv, 21 Oct 2026) */
	.p-story p { margin: 0; font-size: clamp(17px, 4.4vw, 22px); line-height: 1.5; text-wrap: pretty; }
	@media (min-width: 1024px) {
	  .p-story { padding: 96px var(--gut) 40px; gap: 40px; }
	  /* One grid for all four: the label column is as wide as the longest
	     label, so every text starts just after it */
	  .p-story { grid-template-columns: max-content minmax(0, 62ch); column-gap: 80px; }   /* text capped at about 62 characters a line */
	  .p-story section { display: contents; }
	  .p-story h2 { grid-column: 1; }
	  .p-story p { grid-column: 2; }
	  .p-story p + p { margin-top: -24px; }   /* a following paragraph sits closer than the next section */
	  .p-client { grid-column: 1 / -1; contain: inline-size; }   /* 1024 to 1279: logos on their own row above the story (contain: so they don't widen the label column) */
	}
	@media (min-width: 1280px) {
	  /* Room for a third column: logos fill the space to the right,
	     centred both ways against all four sections */
	  .p-story { grid-template-columns: max-content minmax(0, 62ch) 1fr; }
	  .p-client { grid-column: 3; grid-row: 1 / span var(--rows, 4); align-self: center; justify-self: center; }
	}

	/* ---- Client logos (as on the client's own site) ---- */
	/* The client's own lockup, exactly as supplied (their brand rules set its
	   spacing), so it's an image, never rebuilt in code */
	.p-client img { width: min(100%, var(--maxw, 160px), var(--w, 9999px), calc(72px * var(--ar, 2))); max-width: min(100%, 160px); max-height: 72px; height: auto; }   /* client logos kept small (Jarv, 16 Oct 2026); width from the logo's shape (--ar, project.php) so its space is kept before it loads */
	@media (min-width: 1280px) { .p-client { width: 100%; } .p-client img { margin-inline: auto; } }

	/* Logo still to come: a marked box the same size as a logo */
	.p-client .todo-box { display: grid; place-items: center; width: 240px; max-width: 100%; height: 90px; }

	/* ---- Placeholders: anything still to be written or supplied ---- */
	.todo { outline: 1px dashed currentColor; outline-offset: 3px; opacity: 0.85; }
	.todo::before { content: "Placeholder: "; font-weight: 700; }
	.todo-box { border: 1px dashed var(--muted); color: var(--muted); font-size: 15px; text-align: center; padding: 12px; }
	.p-work > section > .todo-box { display: grid; place-items: center; min-height: 240px; }

	/* ---- Work: chapters, each a short heading and a bento grid ---- */
	.p-work { padding: 32px var(--gut) 72px; display: grid; grid-template-columns: minmax(0, 1fr); gap: 56px; }   /* minmax: nothing inside can widen the column past the screen */
	.chapter-head { display: grid; gap: 6px; margin-bottom: 16px; }   /* heading, then its line underneath */
	.chapter-head h2 { margin: 0; line-height: normal; font-weight: 900; font-size: clamp(26px, 7vw, 28px); letter-spacing: -0.024em; }   /* 900, 28px on desktop (Jarv, 21 Oct 2026) */
	.chapter-head p { margin: 0; color: var(--ink); font-size: 16px; line-height: 1.55; }   /* every chapter's intro line: same as the chapter text (Jarv, 21 Oct 2026) */   /* same size as the story text */
	@media (min-width: 1024px) { .p-work { padding: 48px var(--gut) 120px; gap: 96px; } .chapter-head { margin-bottom: 24px; } }

	/* The bento grid. Mobile: 2 columns, each tile its own shape (--ma).
	   Desktop: 12 columns; rows grow with the width (row = 0.68 of a column)
	   so tiles keep their shape at every screen size. */
	.bento { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--gap); }
	.tile {
	  grid-column: span var(--m, 1); aspect-ratio: var(--ma, 1);
	  position: relative; overflow: hidden; display: block; background: #eef0f5;
	}
	/* A faint keyline drawn inside every tile, so images with a white edge
	   (title cards, UI) don't melt into the page. Inside, so it adds no size. */
	.tile::after { content: ""; position: absolute; inset: 0; pointer-events: none; box-shadow: inset 0 0 0 1px rgb(10 20 60 / 0.07); border-radius: inherit; }
	/* Soft corners: every tile (images, films, animations, placeholders), the
	   lead image and the story panel. overflow: hidden on .tile clips its contents. */
	.tile, .tile-todo, .p-lead img, .p-split > .p-aside, .p-aside > .p-story { border-radius: var(--radius); }
	.tile img { width: 100%; height: 100%; object-fit: cover; object-position: var(--pos, 50% 50%); }
	/* panel: true (Jarv, 19 Oct 2026): a logo or drawing centred on a white panel with
	   room round it, never cropped; panels in a row share one shape (ar) */
	.tile.is-panel { background: #fff; }
	.tile.is-panel img { object-fit: contain; padding: var(--pad, 12%); }   /* no filter or blending: on iPhone HDR screens a brightened white glowed brighter than the panel; the files are pure white instead (Jarv, 20 Oct 2026) */
	/* caption: "..." = a short line under one picture; a string in a row = a line under the row */
	.pic { margin: 0; display: grid; gap: 8px; align-content: start; }
	.pic > .tile { aspect-ratio: var(--a); }
	.pic figcaption, .row-cap { color: var(--muted); font-size: 14px; line-height: 1.4; }   /* 14px (Jarv, 21 Oct 2026) */
	.row-cap { margin: 0 0 16px; }
	.row-cap.is-above { margin: 0; }   /* sits just above its row (the grid gap below it) */
	/* a row with captions under its pictures: clear space before whatever comes next,
	   so each caption belongs to the picture above it (Jarv, 19 Oct 2026) */
	.blocks > .bento-row:has(.pic):not(:last-child) { margin-bottom: 16px; }
	@media (min-width: 1024px) { .blocks > .bento-row:has(.pic):not(:last-child) { margin-bottom: 24px; } }
	/* text: longer chapter copy, the same size and colour as the story */
	.chapter-text { display: grid; gap: 12px; margin: 4px 0 24px; }   /* the full width of the column: a 62ch cap left a wide empty margin and a longer page (Jarv, 19 Oct 2026) */
	.chapter-text p { margin: 0; color: var(--ink); font-size: 16px; line-height: 1.55; text-wrap: pretty; }   /* 16px (Jarv, 21 Oct 2026) */
	@media (min-width: 1024px) {
	  .bento {
	    grid-template-columns: repeat(12, 1fr);
	    grid-auto-rows: calc((100vw - 2 * var(--gut) - 11 * var(--gap)) / 12 * 0.68);
	    grid-auto-flow: dense;   /* lets the small tiles of a group stack beside its big one */
	  }
	  .tile { grid-column: span var(--c); grid-row: span var(--r); aspect-ratio: auto; }
	}

	/* A chapter is a stack of blocks: bento grids, and full-width rows for
	   groups holding artwork that mustn't be cropped. In a row every image
	   keeps its own shape and all are the same height. On phones, landscape
	   artwork goes full width and portrait artwork pairs up. */
	.blocks { display: grid; gap: var(--gap); }
	.bento-row { display: flex; flex-wrap: wrap; align-items: flex-start; gap: var(--gap); }
	.bento-row > * { flex: 1 1 100%; aspect-ratio: var(--a); }
	.bento-row > .pic { aspect-ratio: auto; }   /* a picture with its caption: the picture keeps the shape, not the pair */
	.bento-row > .tall { flex-basis: calc(50% - var(--gap) / 2); }
	@media (min-width: 1024px) {
	  .bento-row { flex-wrap: nowrap; }
	  .bento-row > *, .bento-row > .tall { flex: var(--a) var(--a) 0; min-width: 0; }
	}
	.bento-row .tile, .bento-row .tile-todo { grid-column: auto; grid-row: auto; }
	.bento-row > .tile-todo { aspect-ratio: var(--a); }   /* placeholders keep their given shape on phones too */
	@media (min-width: 1024px) { .bento-row .tile, .bento-row .tile-todo { aspect-ratio: var(--a); } }


	/* A title card with two stills (lead: true). Phones: the card full width,
	   the stills paired below. Desktop: the card on one side, the stills
	   stacked on the other. The narrow column is sized so both sides end level
	   with every image at its own shape (--a, width / height): no cropping. */
	.bento-film { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--gap); }   /* minmax: columns never grow past the screen */
	.bento-film > .tile { grid-column: auto; grid-row: auto; aspect-ratio: var(--a); }
	.bento-film > :first-child { grid-column: 1 / -1; }
	@media (min-width: 1024px) {
	  .bento-film { grid-template-columns: 1fr calc((100% - var(--gap) * (1 + var(--a))) / 3); }
	  .bento-film > .tile { aspect-ratio: var(--a); }
	  .bento-film > :first-child { grid-column: 1; grid-row: span 2; }
	  .bento-film.flip { grid-template-columns: calc((100% - var(--gap) * (1 + var(--a))) / 3) 1fr; }
	  .bento-film.flip > :first-child { grid-column: 2; grid-row: 1 / span 2; }
	  /* below: true on the lead = the film full width, its two stills side by side under it */
	  .bento-film.below { grid-template-columns: repeat(2, minmax(0, 1fr)); }
	  .bento-film.below > :first-child { grid-column: 1 / -1; grid-row: auto; }
	}

	/* A group's caption (its lead's label): plain text under the images, so it
	   never reads as a button */
	.film-group { margin: 0; }
	.film-group:not(:last-child) { margin-bottom: 24px; }   /* clear space after the caption, so it belongs to the images above */
	@media (min-width: 1024px) { .film-group:not(:last-child) { margin-bottom: 40px; } }
	.film-group figcaption { margin-top: 8px; color: var(--muted); font-size: 14px; line-height: 1.4; }   /* same as picture captions */

	/* Image still to find or produce: a marked tile in the grid, same size as an image */
	.tile-todo {
	  grid-column: span var(--m, 1); aspect-ratio: var(--ma, 1);
	  display: grid; place-items: center; padding: 0; text-align: center;   /* padding on the label, so it doesn't add to the tile's width */
	  border: 1px dashed var(--muted); color: var(--muted); font-size: 15px; line-height: 1.35; background: #fafbfd;
	}
	.tile-todo > span { padding: 16px; }
	.tile-todo strong { display: block; margin-bottom: 4px; }
	@media (min-width: 1024px) { .tile-todo { grid-column: span var(--c); grid-row: span var(--r); aspect-ratio: auto; } }

	/* ---- Split layout (?layout=split): story in the left 3 columns, staying
	   in view, images in the right 9. From 1200px; narrower screens stack. ---- */
	@media (min-width: 1024px) {
	  /* the image grid is 9 columns in this layout; rows keep the same shape */
	  .bento { grid-template-columns: repeat(9, 1fr); grid-auto-rows: calc((100vw - 2 * var(--gut) - 8 * var(--gap)) / 9 * 0.68); }
	}
	/* Logos with a white background (e.g. RNIB's PNG) blend into what's behind,
	   so there's no white box: on phones too (Jarv, 25 Oct 2026; was desktop only) */
	.p-story .p-client img { mix-blend-mode: multiply; }

	@media (min-width: 1200px) {
	  .p-split {
	    display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); column-gap: var(--gap);
	    align-items: start; padding: 56px var(--gut) 120px;
	  }
	  /* The tinted panel runs the full height beside the images, with a wider
	     gutter (32px) before them; the text inside it stays in view. */
	  .p-split > .p-aside {
	    grid-column: 1 / span 3; align-self: stretch; margin-right: 24px;   /* + the 8px grid gap = 32px */
	    background: color-mix(in srgb, var(--project) var(--tint, 5%), #fff);
	  }
	  /* On paper the panel tints the paper, with the grain over it */
	  .p-split > .p-aside {
	    background: var(--grain) color-mix(in srgb, var(--project) var(--tint, 5%), var(--paper));
	  }
	  .p-aside > .p-story {
	    position: sticky; top: calc(var(--head-h) + 64px);   /* clear of the sticky header and the back bar */
	    display: flex; flex-direction: column; gap: 20px; padding: 24px;
	    background: inherit;   /* the panel's tint, so the logo below has a colour to blend into */
	  }
	  .p-story section { display: block; }
	  /* a fine line between the sections, in a deeper mix of the project colour */
	  .p-story section + section { padding-top: 20px; border-top: 1px solid color-mix(in srgb, var(--project) 25%, #fff); }
	  .p-story h2 { margin-bottom: 4px; }
	  .p-story p + p { margin-top: 12px; }   /* space between paragraphs within a section */
	  .p-story h2, .p-story p { font-size: 16px; line-height: 1.5; }
	  .p-story .p-client {   /* logo under the story, after the same fine line */
	    order: 9; contain: none; padding-top: 24px;
	    border-top: 1px solid color-mix(in srgb, var(--project) 25%, #fff);
	  }
	  .p-story .p-client img { width: min(100%, var(--maxw, 140px), var(--w, 9999px), calc(64px * var(--ar, 2))); max-width: min(100%, 140px); max-height: 64px; margin: 0 auto; }   /* centred; square logos capped in height; width from the logo's shape */
	  .p-split > .p-work { grid-column: 4 / -1; padding: 0; gap: 72px; }
	  .bento { grid-auto-rows: calc((100vw - 2 * var(--gut) - 11 * var(--gap)) / 12 * 0.68); }   /* same columns as the page grid */
	}

	/* ---- Next project ---- */
	/* ---- More work in [service]: small outlined buttons to the filtered Work page ---- */
	/* Project details: a recap at the foot of the page, after the work, above
	   "More work in" (which carries the services) (Jarv, 26 Oct 2026) */
	/* the work column drops its end space here, so the line sits midway: 40px above and below on phones, 48px on desktop (Jarv, 26 Oct 2026) */
	.p-split:has(+ .p-details), .p-split:has(+ .p-details) > .p-work, .p-work:has(+ .p-details) { padding-bottom: 0; }
	.p-details { margin: 40px var(--gut) 0; padding-top: 40px; border-top: 1px solid var(--rule); }
	.p-details h2 { margin: 0 0 20px; font-size: 22px; font-weight: 900; color: var(--c-ink); }
	.p-details dl { display: grid; gap: 18px; margin: 0; }
	.p-details dt { margin-bottom: 4px; font-size: 18px; font-weight: 700; color: var(--c-ink); }
	.p-details dd { margin: 0; font-size: 16px; line-height: 1.45; color: var(--c-muted); }
	@media (min-width: 700px) { .p-details dl { grid-template-columns: repeat(2, 1fr); gap: 24px 32px; } }
	@media (min-width: 1024px) {
	  .p-details { margin-top: 48px; padding-top: 48px; }
	  .p-details dl { display: flex; gap: 48px; }
	  .p-details dl > div { flex: 1 1 0; min-width: 0; }
	  .p-details dl > .wide { flex-grow: 1.6; }
	}
	.p-details + .p-more { padding-top: 40px; }
	.p-more { padding: 56px var(--gut) 0; }
	.p-more-label { margin: 0 0 12px; font-size: 15px; font-weight: 500; color: var(--c-ink); }
	.p-more-list { display: flex; flex-wrap: wrap; gap: 8px; margin: 0; padding: 0; list-style: none; }
	.p-more-list a {
	  display: inline-flex; align-items: center; min-height: 36px; padding: 0 14px;
	  border: 1px solid var(--c-ink); border-radius: 3px; color: var(--c-ink); font-size: 14px; font-weight: 700; text-decoration: none;
	}
	.p-more-list a:focus-visible { outline: 2px solid var(--c-ink); outline-offset: 3px; }
	@media (min-width: 1024px) { .p-more { padding-top: 80px; } }

	/* ---- More work: one small line on paper, All work left, Next right
	   (replaced the big Next project band, 15 Oct 2026) ---- */
	.p-next { display: flex; justify-content: space-between; align-items: baseline; gap: 24px; padding: 24px var(--gut) 40px; }
	.p-next .all { white-space: nowrap; }
	.p-next .next { text-align: right; }
	.p-next a { color: var(--c-ink); font-weight: 500; font-size: 16px; text-decoration: none; }
	.p-next a { transition: opacity 0.2s ease; }
	.p-next a:hover { opacity: 0.7; }   /* dims like the menu links; no underline */
	@media (min-width: 1024px) { .p-next { padding-top: 40px; } .p-next a { font-size: 18px; } }
	/* a keyline between "More work in" and All work / Next, midway: 40px each side on
	   phones, 48px on desktop (Jarv, 26 Oct 2026) */
	.p-more + .p-next { margin: 40px var(--gut) 0; padding: 39px 0 40px; border-top: 1px solid var(--rule); }
	@media (min-width: 1024px) { .p-more + .p-next { margin-top: 48px; padding-top: 47px; } }
	/* SVG build tiles */
	.tile-build svg, .tile-build img { display: block; width: 100%; height: 100%; }
	.tile-build .b-pop { transform-box: fill-box; transform-origin: center; }
	.tile-build.is-waiting .b-pop, .tile-build.is-waiting .b-draw { opacity: 0; }
	.tile-build.is-building .b-pop { animation: b-pop 0.5s cubic-bezier(0.34, 1.56, 0.64, 1) both; }
	.tile-build.is-building .b-draw { animation: b-draw 0.8s ease-out both; }
	/* Animated SVGs (trace, float, assemble). See animTile in the script. */
	.tile-anim { display: grid; place-items: center; background: #fff; }
	.tile-anim svg { display: block; width: 100%; height: 100%; }
	.tile-anim .fl { transform-box: fill-box; transform-origin: center; }
	@keyframes float {
	  0%, 100% { transform: none; }
	  30% { transform: translate(var(--fx), var(--fy)) rotate(var(--fr)); }
	  65% { transform: translate(calc(var(--fx) * -0.6), calc(var(--fy) * 0.4)) rotate(calc(var(--fr) * -0.7)); }
	}
	@keyframes hop {
	  0%, 26%, 100% { transform: none; }
	  5%  { transform: translateY(-7%) scale(1.07) rotate(-3deg); }
	  10% { transform: translateY(-3%) scale(1.03) rotate(2deg); }
	  15% { transform: translateY(-5%) scale(1.05) rotate(-1deg); }
	  20% { transform: translateY(-1%) scale(1.01) rotate(0.5deg); }
	}
	@keyframes sweep {
	  0%, 24%, 100% { stroke-dashoffset: 0; }
	  3%  { stroke-dashoffset: 30; }
	}

	/* An icon grid section (grid: { cols, phone }): equal cells, every icon whole */
	.icon-grid { display: grid; grid-template-columns: repeat(var(--phone, 2), 1fr); gap: var(--gap); }
	.icon-grid > .tile { aspect-ratio: var(--ga, 4/3); padding: var(--gpad, 14%); }
	@media (min-width: 1024px) { .icon-grid { grid-template-columns: repeat(var(--cols, 3), 1fr); } }

	@keyframes b-pop { from { opacity: 0; transform: scale(0.6); } to { opacity: 1; transform: none; } }
	@keyframes b-draw { from { clip-path: inset(0 100% 0 0); } to { clip-path: inset(0 0 0 0); } }

	/* tilt: [x, y, turn, scale] = a screen shown larger, turned slightly and
	   running off the tile's right and bottom edges, on a light ground (like a
	   presentation slide). x and y inset it from the top left, in % of the tile. */
	.tile.is-tilt { background: #f1f1f2; }
	.tile.is-tilt img {
	  transform-origin: 0 0; border-radius: 10px; box-shadow: 0 12px 40px rgb(10 20 60 / 0.16);
	  transform: translate(var(--tx), var(--ty)) rotate(var(--tr)) scale(var(--ts));
	}
	/* Video and link tiles */
	.tile video { display: block; width: 100%; height: 100%; object-fit: cover; object-position: var(--pos, 50% 50%); }
	.tile-label {
	  position: absolute; left: 16px; bottom: 16px; padding: 10px 16px; border-radius: 3px;
	  background: #fff; color: var(--ink); font-size: 15px; font-weight: 500;
	}
	/* a title card's label sits top left, clear of the lower-third bars in the films */
	.tile:not(.tile-ext) > .tile-label { bottom: auto; top: 16px; }
	.tile-ext:hover .tile-label, .tile-ext:focus-visible .tile-label { background: var(--ink); color: #fff; }
	/* Play button centred on a film's still */
	.tile-play {
	  position: absolute; top: 50%; left: 50%; translate: -50% -50%;
	  width: 84px; height: 84px; border-radius: 50%;
	  background: rgba(255, 255, 255, 0.94); box-shadow: 0 6px 24px rgba(8, 24, 74, 0.25);
	  transition: scale 0.2s ease;
	}
	.tile-play::after {   /* the triangle, nudged right so it looks centred */
	  content: ""; position: absolute; top: 50%; left: 54%; translate: -50% -50%;
	  border-style: solid; border-width: 15px 0 15px 25px; border-color: transparent transparent transparent var(--ink);
	}
	.tile-yt:hover .tile-play, .tile-yt:focus-visible .tile-play { scale: 1.08; }
	.sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
	.tile-player { background: #000; }
	.tile-player iframe { display: block; width: 100%; height: 100%; border: 0; pointer-events: none; transform: scale(1.01); }   /* a hair larger, so no black edge of the player shows */
	/* our still covers YouTube's own pause screen */
	.pl-still { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; opacity: 0; transition: opacity 0.2s; pointer-events: none; }
	.is-paused .pl-still { opacity: 1; }
	/* the clear layer over the player: catches the mouse, toggles play */
	.pl-shield { position: absolute; inset: 0; width: 100%; padding: 0; border: 0; background: transparent; cursor: pointer; }
	.pl-shield .tile-play { opacity: 0; transition: opacity 0.2s; }
	.is-paused .pl-shield .tile-play { opacity: 1; }
	.pl-shield:focus-visible { outline: 2px solid #fff; outline-offset: -4px; }
	/* the control bar: visible when paused, on hover or keyboard focus */
	.pl-bar {
	  position: absolute; left: 12px; right: 12px; bottom: 12px; display: flex; align-items: center; gap: 12px;
	  padding: 6px 12px; border-radius: 99px; background: rgba(8, 24, 74, 0.72); color: #fff;
	  opacity: 0; transition: opacity 0.2s;
	}
	/* shown when paused, while the mouse moves over it, or for keyboard users */
	.tile-player:hover:not(.is-idle) .pl-bar, .tile-player:has(:focus-visible) .pl-bar, .is-paused .pl-bar { opacity: 1; }
	.tile-player.is-idle:not(.is-paused) .pl-shield { cursor: none; }
	/* touch screens use YouTube's own player and controls (see ytPlayer) */
	.tile-player.is-native iframe { pointer-events: auto; transform: none; }
	/* full screen (desktop): the film fills the screen, black around it */
	.tile-player:fullscreen { width: 100vw; height: 100vh; aspect-ratio: auto; border-radius: 0; background: #000; }
	.tile-player:fullscreen .pl-still { object-fit: contain; }
	.pl-fs::before {   /* four corner marks */
	  content: ""; position: absolute; left: 50%; top: 50%; width: 14px; height: 14px; translate: -50% -50%;
	  background:
	    linear-gradient(#fff 0 0) top left / 5px 2px, linear-gradient(#fff 0 0) top left / 2px 5px,
	    linear-gradient(#fff 0 0) top right / 5px 2px, linear-gradient(#fff 0 0) top right / 2px 5px,
	    linear-gradient(#fff 0 0) bottom left / 5px 2px, linear-gradient(#fff 0 0) bottom left / 2px 5px,
	    linear-gradient(#fff 0 0) bottom right / 5px 2px, linear-gradient(#fff 0 0) bottom right / 2px 5px;
	  background-repeat: no-repeat;
	}
	.pl-btn {
	  flex: none; min-width: 32px; height: 32px; padding: 0 6px; border: 0; border-radius: 99px;
	  background: transparent; color: #fff; font: 600 13px/1 var(--font); cursor: pointer; position: relative;
	}
	.pl-btn::after { content: ""; position: absolute; inset: -6px; }   /* 44px tap target */
	.pl-toggle::before {   /* play triangle, or two pause bars when playing */
	  content: ""; position: absolute; top: 50%; left: 54%; translate: -50% -50%;
	  border-style: solid; border-width: 7px 0 7px 12px; border-color: transparent transparent transparent #fff;
	}
	.pl-toggle.is-playing::before { left: 50%; width: 4px; height: 14px; border: 0; border-left: 4px solid #fff; border-right: 4px solid #fff; padding-left: 4px; box-sizing: content-box; }
	.pl-cc { border: 1.5px solid rgba(255, 255, 255, 0.6); height: 24px; border-radius: 4px; }
	.pl-cc[aria-pressed="true"] { background: #fff; color: var(--ink); border-color: #fff; }
	.pl-btn:focus-visible, .pl-track:focus-visible { outline: 2px solid #fff; outline-offset: 2px; }
	.pl-track { flex: 1; height: 6px; border-radius: 3px; background: rgba(255, 255, 255, 0.3); cursor: pointer; position: relative; touch-action: none; }
	.pl-track::after { content: ""; position: absolute; inset: -12px 0; }   /* easier to grab */
	.pl-fill { display: block; height: 100%; width: 0; border-radius: 3px; background: #fff; position: relative; }
	.pl-fill::after { content: ""; position: absolute; right: -6px; top: 50%; translate: 0 -50%; width: 12px; height: 12px; border-radius: 50%; background: #fff; }
	.pl-time { flex: none; font-size: 13px; font-variant-numeric: tabular-nums; }

	/* ---- Larger view: click a tile to see the whole, uncropped picture ---- */
	.viewer { width: 100vw; height: 100dvh; max-width: none; max-height: none; margin: 0; padding: 0; border: 0; background: rgba(4, 12, 40, 0.94);
	  overflow: hidden; overscroll-behavior: contain; touch-action: none; }   /* our own swipe; no page scroll or browser gestures behind it */
	.viewer-open { overflow: hidden; }   /* on <html> while the larger view is open: the page behind stays put */
	.viewer::backdrop { background: transparent; }
	.viewer[open] { display: grid; place-items: center; }
	.viewer img { max-width: calc(100vw - 32px); max-height: calc(100dvh - 176px); width: auto; height: auto; user-select: none; -webkit-user-drag: none; }
	@media (min-width: 700px) { .viewer img { max-width: calc(100vw - 176px); } }
	/* a panel picture: a white box the tile's shape, as wide as fits, the logo
	   inside with the same padding as on the page (padding = a share of the width) */
	.viewer img.is-panel {
	  --w: min(calc(100vw - 32px), calc((100dvh - 176px) * var(--ar)));
	  box-sizing: border-box; width: var(--w); height: auto; aspect-ratio: var(--ar);
	  padding: calc(var(--w) * var(--padn)); background: #fff; object-fit: contain;
	}
	@media (min-width: 700px) { .viewer img.is-panel { --w: min(calc(100vw - 176px), calc((100dvh - 176px) * var(--ar))); } }   /* room for the arrows beside the picture */
	.viewer button {
	  position: absolute; min-width: 44px; height: 44px; padding: 0 14px; border: 0; border-radius: 3px;
	  background: #fff; color: var(--ink); font: 500 15px/1 var(--font); cursor: pointer;
	}
	.viewer .close { top: 16px; right: 16px; }
	/* Arrows at the sides, halfway down (Jarv, 18 Oct 2026): round. On phones they sit
	   over the picture's edges, so (28 Oct 2026) they're solid ink with a thin light
	   ring and a soft shadow, readable on light pictures too, and larger. */
	.viewer .prev, .viewer .next-img {
	  top: 50%; translate: 0 -50%; width: 52px; height: 52px; min-width: 0; padding: 0 0 3px; border-radius: 50%;
	  background: rgba(27, 42, 94, 0.82); color: #fff; font-size: 30px; line-height: 1;
	  box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.35), 0 2px 10px rgba(0, 0, 0, 0.3);
	  transition: background-color 0.2s ease;
	}
	.viewer .prev { left: 12px; }
	.viewer .next-img { right: 12px; }
	.viewer .prev:hover, .viewer .next-img:hover, .viewer .prev:focus-visible, .viewer .next-img:focus-visible { background: #2f4380; }
	@media (min-width: 700px) { .viewer .prev { left: 32px; } .viewer .next-img { right: 32px; } .viewer .prev, .viewer .next-img { width: 48px; height: 48px; font-size: 26px; } }
	/* Phones (Jarv, 28 Oct 2026): the arrows leave the picture and sit either side of
	   the count at the bottom ("‹ 1 of 3 ›"), so the work is uncovered; swiping is the main way through */
	@media (max-width: 699px) {
	  .viewer .prev, .viewer .next-img { top: auto; bottom: 14px; translate: none; width: 44px; height: 44px; font-size: 26px; }
	  .viewer .prev { left: calc(50% - 100px); }
	  .viewer .next-img { right: calc(50% - 100px); }
	  .viewer .ai-note { bottom: 72px; }
	}
	@media (prefers-reduced-motion: reduce) { .viewer .prev, .viewer .next-img { transition: none; } }
	/* AI note (Jarv, 19 Oct 2026): one quiet line above the count, only on pictures that used AI */
	.viewer .ai-note { position: absolute; bottom: 52px; left: 16px; right: 16px; margin: 0; text-align: center; color: var(--body); font-size: 14px; }
	.viewer .ai-note:empty { display: none; }
	.viewer .count { position: absolute; bottom: 28px; left: 50%; translate: -50% 0; color: var(--body); font-size: 14px; }

	/* ---- Button hovers (Jarv, 15 Oct 2026): every button eases (0.2s) one
	   step, like the header Contact button. Dark buttons lighten to #2f4380
	   (white type 9.4:1); light buttons on the ink band turn pale blue (ink
	   type 9.2:1); outlined buttons take a light ink wash. ---- */
	.p-more-list a { transition: background-color 0.2s ease; }
	.p-more-list a:hover { background: rgba(27, 42, 94, 0.08); }
	@media (prefers-reduced-motion: reduce) { .p-more-list a { transition: none; } }

	/* ======================================================================
	   ABOUT (body.is-about, /about/). Ported from docs/prototype/about-paper.html:
	   one central column, like an article
	   ====================================================================== */
	.about { padding: 40px var(--gut) 72px; }
	.about > * { max-width: 840px; margin-inline: auto; }
	.about h1 { margin: 0 0 20px; font-size: 36px; line-height: 1.1; letter-spacing: -0.024em; }
	.about p { max-width: none; margin: 0 0 16px; font-size: 16px; line-height: 1.5; color: var(--c-muted); }
	.about .about-lead { font-size: 18px; line-height: 1.4; color: var(--c-ink); }
	.about .about-cv { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 24px; }
	.about-block { margin-top: 56px; padding-top: 24px; border-top: 1px solid color-mix(in srgb, var(--c-ink) 18%, transparent); }
	.about h2 { margin: 0 0 24px; font-size: 26px; line-height: normal; letter-spacing: -0.02em; }
	.skills { display: grid; gap: 20px; }
	/* each: a small icon left, title and text right */
	.skill { display: grid; grid-template-columns: 40px 1fr; column-gap: 16px; align-items: start; align-content: start; }
	.skill-icon { grid-row: 1 / span 2; display: block; width: 40px; height: 40px; margin-top: 2px; }
	.skills dt { margin-bottom: 4px; font-size: 18px; line-height: normal; font-weight: 700; color: var(--c-ink); }
	.skills dd { margin: 0; font-size: 16px; line-height: 1.5; color: var(--c-muted); }
	/* Editor text in the About layout (privacy-policy.php): the first paragraph
	   as About's larger opening line, headings as About's, lists and links */
	.about-prose > p:first-child { font-size: 18px; line-height: 1.4; color: var(--c-ink); }
	/* a keyline above each section, as About's "What I bring" (Jarv, 25 Oct 2026) */
	/* The line sits midway between the text above and the heading below (measured to
	   the letters: the margin allows for the paragraph's descenders, so 41px each side on phones) */
	.about-prose h2 { margin: 37px 0 12px; padding-top: 40px; border-top: 1px solid color-mix(in srgb, var(--c-ink) 18%, transparent); }
	.about-prose h3 { margin: 28px 0 8px; font-size: 18px; line-height: normal; font-weight: 700; color: var(--c-ink); }
	.about-prose ul, .about-prose ol { margin: 0 0 16px; padding-left: 1.25em; color: var(--c-muted); font-size: 16px; line-height: 1.5; }
	.about-prose li + li { margin-top: 6px; }
	.about-prose a { color: var(--c-ink); text-decoration: underline; text-underline-offset: 2px; }
	.about-prose strong { color: var(--c-ink); font-weight: 700; }
	.about-prose code { font: inherit; }
	.about-prose > :last-child { margin-bottom: 0; }
	@media (min-width: 1024px) {
		.about { padding: 72px var(--gut) 112px; }
		.about h1 { font-size: 50px; }
		.about .about-lead, .about-prose > p:first-child { font-size: 20px; }
		.about-prose h2 { margin-top: 53px; padding-top: 56px; }   /* 57px each side of the line */
		.about-block { margin-top: 80px; }
		.about h2 { font-size: 28px; }
		.skills { grid-template-columns: 1fr 1fr; gap: 28px 48px; }
	}

	/* ======================================================================
	   CONTACT (body.is-contact, /contact/). Ported from docs/prototype/contact-paper.html.
	   A short page: the footer sits at the bottom of the screen.
	   ====================================================================== */
	body.is-contact { display: flex; flex-direction: column; }
	body.is-contact .site-main { flex: 1 0 auto; }
	.contact { display: grid; gap: 40px; padding: 40px var(--gut) 72px; }
	.contact h1 { margin: 0 0 16px; font-size: 36px; line-height: 1.1; letter-spacing: -0.024em; }
	.contact-lede p { max-width: 34ch; margin: 0 0 16px; font-size: 18px; line-height: 1.45; color: var(--c-muted); }
	.contact-lede p:first-of-type { color: var(--c-ink); }
	/* "Message sent." (contact.js): the matchstick plane, a heading and a line,
	   centred where the form was */
	.sent { display: grid; justify-items: center; gap: 12px; padding: 24px 0 8px; text-align: center; }
	.sent[hidden] { display: none; }
	.sent:focus { outline: none; }   /* focus is moved here for screen readers, not shown */
	.sent__pic { width: min(100%, 300px); height: auto; margin-bottom: 16px; }
	.sent h2 { margin: 0; font-size: 28px; line-height: 1.1; letter-spacing: -0.02em; }
	.sent p { max-width: 34ch; margin: 0; font-size: 18px; line-height: 1.45; color: var(--c-muted); text-wrap: pretty; }
	@media (min-width: 1024px) {
		.contact { grid-template-columns: 5fr 7fr; gap: 64px; align-items: start; padding: 72px var(--gut) 112px; }
		.contact h1 { font-size: 50px; }
		.contact-lede p { font-size: 20px; }
		.sent { padding-top: 56px; }
		.sent h2 { font-size: 36px; }
		.sent p { font-size: 20px; }
	}

	/* ======================================================================
	   PAGE NOT FOUND (body.error404, 404.php): the matchstick 404, then a short
	   line and a way back, all centred. A short page, so the footer sits at the
	   bottom of the screen, as on Contact.
	   ====================================================================== */
	body.error404 { display: flex; flex-direction: column; }
	body.error404 .site-main { flex: 1 0 auto; }
	.not-found { display: flex; flex-direction: column; align-items: center; padding: 48px var(--gut) 80px; text-align: center; }
	.not-found__pic { width: min(100%, 464px); height: auto; margin-bottom: 32px; }
	.not-found h1 { margin: 0 0 16px; font-size: 36px; line-height: 1.1; letter-spacing: -0.024em; }
	.not-found p { max-width: 34ch; margin: 0; font-size: 18px; line-height: 1.45; color: var(--c-muted); text-wrap: pretty; }
	.not-found .btns { justify-content: center; }
	@media (min-width: 1024px) {
		.not-found { padding: 72px var(--gut) 112px; }
		.not-found h1 { font-size: 50px; }
		.not-found p { font-size: 20px; }
	}

	/* ======================================================================
	   UNDER CONSTRUCTION (inc/construction.php): the holding page visitors see
	   until launch. The name with its coral dot, one line, centred on paper.
	   ====================================================================== */
	body.under-construction { display: grid; place-items: center; min-height: 100vh; min-height: 100dvh; margin: 0; padding: 40px var(--gut); }
	.soon { text-align: center; }
	.soon__name { margin: 0 0 20px; }   /* the header's name and textured dot (components.css) */
	.soon h1 { margin: 0; font-size: 36px; line-height: 1.1; letter-spacing: -0.024em; }
	@media (min-width: 1024px) {
		.soon h1 { font-size: 50px; }
	}
}
