/*
Theme Name: Rudi Portfolio
Description: Image-first visual portfolio. Standalone, no plugins required.
Version: 0.2.0
Text Domain: rudi-portfolio
*/

@font-face {
	font-family: 'General Sans';
	src: url('assets/fonts/GeneralSans-Variable.woff2') format('woff2');
	font-weight: 200 700;
	font-display: swap;
}
@font-face {
	font-family: 'Rudi Music';
	src: url('assets/fonts/RudiMusic-Bold.woff2') format('woff2');
	font-weight: 700; font-style: normal; font-display: swap;
}

:root {
	--bg: #0c0b0e;
	--text: #f1eee8;
	--muted: #9a968f;
	--line: #2a2830;
	--accent: #f2b84b;
	--pill-bg: #3a3a3a; --pill-fg: #ececec; --pill-hover-bg: #f2b84b; --pill-hover-fg: #0c0b0e; /* pills: greyscale reverse on dark; light bands switch to #333333 on very light beige */
	--head: 'Rudi Music', 'General Sans', system-ui, sans-serif; /* letters only: numbers and symbols fall back to General Sans */
	--body: 'General Sans', system-ui, sans-serif;
	--gap: clamp(12px, 2vw, 28px);
	--pad: clamp(16px, 3vw, 40px);
	--ease: cubic-bezier(.16, 1, .3, 1); /* expo ease-out, for all the quiet motion at the end of this file */
}

* { box-sizing: border-box; margin: 0; }
html { scroll-behavior: smooth; background: var(--bg); }
.lenis.lenis-smooth { scroll-behavior: auto !important; } /* Lenis does the easing itself */
body {
	background: var(--bg);
	color: var(--text);
	font: 400 1rem/1.5 'General Sans', system-ui, sans-serif;
	-webkit-font-smoothing: antialiased;
	min-height: 100svh; display: flex; flex-direction: column;
}
main { flex: 1; overflow-x: clip; }
a { color: inherit; text-decoration: none; }
a:hover { color: var(--accent); }
img { display: block; max-width: 100%; }
body:has(dialog[open]) { overflow: hidden; }
section[id] { scroll-margin-top: 3.5rem; }

.skip { position: absolute; left: -999px; }
.skip:focus { left: var(--pad); top: var(--pad); z-index: 20; background: var(--bg); padding: .5rem 1rem; }

/* Top bar: translucent so it reads over any photo. */
.bar {
	position: fixed; inset: 0 0 auto; z-index: 10;
	display: flex; justify-content: center; align-items: baseline; gap: 1rem;
	padding: calc(var(--pad) * .6) var(--pad);
	color: #fff; background: rgb(12 11 14 / .5); backdrop-filter: blur(14px);
	font-weight: 500;
}
.admin-bar .bar { top: 32px; }
@media (max-width: 782px) { .admin-bar .bar { top: 46px; } }
.bar a:hover { color: var(--accent); }
.bar nav { display: flex; gap: clamp(14px, 3vw, 40px); font: 700 clamp(.8125rem, 1.1vw, .9375rem)/1.2 var(--head); text-transform: uppercase; letter-spacing: .1em; } /* RudiMusic-Bold is Larken Bold with a dotted i (the demo file's i has no dot) */

/* Hero: one full-bleed photograph, name stacked bottom-left. */
.hero {
	position: relative; height: calc(100svh - var(--wp-admin--admin-bar--height, 0px)); min-height: 480px;
	display: flex; align-items: flex-end; padding: var(--pad);
}
.hero > img, .hero > video { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; object-position: 62% 40%; }
.snd {
	position: absolute; z-index: 1; right: var(--pad); bottom: calc(var(--pad) * .6 + 1.75rem);
	padding: .35rem .9rem; border: 0; border-radius: 999px; background: #f3efe7;
	color: #333333; font: 500 .75rem 'General Sans', sans-serif; letter-spacing: .08em; text-transform: uppercase; cursor: pointer;
}
.snd:hover, .play:hover, .play:focus-visible, figure.film .embed[data-src]:hover .play { background: #f2b84b; color: #0c0b0e; } /* a film's whole poster is the target, so hovering it lights the button too */
@media (max-width: 640px) {
	.hero { padding-bottom: calc(var(--pad) + 1.25rem); }
	.snd { bottom: auto; top: calc(var(--wp-admin--admin-bar--height, 0px) + 4.25rem); }
}
.hero::after { content: ''; position: absolute; inset: 0; background: linear-gradient(to top, rgb(0 0 0 / .7), transparent 55%); }
.hero > div { position: relative; z-index: 1; }
.hero small { position: absolute; z-index: 1; right: var(--pad); bottom: calc(var(--pad) * .6); font-size: .6875rem; letter-spacing: .06em; color: rgb(255 255 255 / .6); }
h1 {
	font: 700 clamp(4rem, 11vw, 10rem)/.9 var(--head);
	max-width: 6ch;
}
.sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; } /* in the page for screen readers, not on screen */
.hero p { font: 400 clamp(1.25rem, 2.6vw, 2.25rem)/1.2 var(--body); max-width: 30ch; }

/* Section label (above everything it introduces) */
.k { font: 700 clamp(1.25rem, 2.2vw, 1.75rem)/1.2 var(--head); color: var(--text); } /* section headings and labels: the Rudi Music font at a readable size (digits fall back to General Sans, the font has letters only) */
.facts dt.k { font: 700 .75rem/1.4 var(--head); text-transform: uppercase; letter-spacing: .12em; color: var(--muted); } /* the About facts are small labels, not headings */
.k.sub { margin-top: 2rem; }

/* Bands alternate white-on-black and black-on-white; the colours below are scoped to each band. */
.tone { background: var(--bg); color: var(--text); padding-bottom: clamp(24px, 4vw, 56px); }
.tone.light { --pill-bg: #f3efe7; --pill-fg: #333333; --pill-hover-bg: #a65f00; --pill-hover-fg: #fff; --bg: #fff; --text: #0c0b0e; --muted: #6b6862; --line: #d4d1ca; --accent: #a65f00; --logo: brightness(0); }
.tone.dark { --pill-bg: #3a3a3a; --pill-fg: #ececec; --pill-hover-bg: #f2b84b; --pill-hover-fg: #0c0b0e; --bg: #0c0b0e; --text: #f1eee8; --muted: #9a968f; --line: #2a2830; --accent: #f2b84b; --logo: brightness(0) invert(1); }

/* Groups: a hairline, a label, one serif statement. */
.grp { padding: clamp(56px, 9vw, 130px) var(--pad) 0; display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); column-gap: var(--gap); }
.grp > * { grid-column: 1 / -1; }
.grp > .txt { grid-column: span 1; margin-bottom: clamp(32px, 5vw, 64px); } /* text-only blocks sit three to a row */
.grp > .txt.two { grid-column: span 2; }
@media (max-width: 800px) { .grp > .txt, .grp > .txt.two { grid-column: 1 / -1; } }
.grp > header { margin-bottom: clamp(32px, 6vw, 80px); }
.grp > header:not(:has(.lead)) { margin-bottom: 1.5rem; }
.lead { margin-top: 1rem; font: 700 clamp(1.875rem, 4vw, 3.5rem)/1.1 var(--head); max-width: 26ch; }
.about h1.lead { margin: 0 0 1.5rem; } /* the page's H1 */
.tl-bar + .lead { margin: 0 0 2rem; } /* a band's statement under its first year */
.tl-bar + .lead:has( + .lead-sub ) { margin-bottom: 1rem; }
.lead-sub { margin: 0 0 2rem; max-width: 46ch; color: var(--muted); }
.lead a { border-bottom: 1px solid var(--line); }
.lead a:hover { border-color: var(--accent); }

/* A project: label above, then copy beside an uneven image grid. Every second one mirrors. */
.proj { margin-bottom: clamp(56px, 9vw, 120px); }
.proj > h3 { margin-bottom: 1rem; }
.in { display: grid; grid-template-columns: minmax(0, 4fr) minmax(0, 8fr); gap: var(--gap); align-items: start; }
.in:not(:has(.pics)) { grid-template-columns: minmax(0, 1fr); }
.flip { direction: rtl; }
.flip > * { direction: ltr; }
.flip .pics { direction: rtl; }
.flip .pics > * { direction: ltr; }
.copy { font: 400 clamp(1.0625rem, 1.4vw, 1.3125rem)/1.45 var(--body); max-width: 34ch; }
.copy b { font-weight: 600; }
.copy a { text-decoration: underline; text-decoration-color: var(--line); text-underline-offset: .2em; text-decoration-thickness: 1px; }
.copy a:hover { text-decoration-color: var(--accent); }
.side .copy + .stat, .stat + .stat { margin-top: 1.5rem; }
@media (max-width: 800px) {
	.in { grid-template-columns: minmax(0, 1fr); }
}

/* Outlined links under a block of copy (Instagram etc.). */
.links { display: flex; flex-wrap: wrap; gap: .25rem 1.25rem; margin-top: 1.25rem; }
.links a { display: inline-flex; align-items: center; gap: .35rem; font-size: .75rem; }
.links b { font-weight: 700; }
.links svg { flex: none; width: .875rem; height: .875rem; }
.links img { flex: none; width: .875rem; height: .875rem; filter: var(--logo); }
.strip-copy + .links, .lbl ~ .copy + .links { margin-top: 0; margin-bottom: 1rem; }

/* Numbers set large, as type. */
.stat { display: flex; flex-direction: column; gap: .25rem; }
.stat strong { font: 600 clamp(2.5rem, 5.5vw, 5rem)/.95 'General Sans', sans-serif; letter-spacing: -.04em; color: var(--accent); overflow-wrap: anywhere; }
.stat span { font: 400 1.0625rem/1.35 var(--body); color: var(--muted); max-width: 30ch; }
.stat > a { display: flex; flex-direction: column; gap: .25rem; color: inherit; } /* a stat that links to its source */
.stat > a:hover strong { text-decoration: underline; text-decoration-thickness: 2px; text-underline-offset: .12em; }

/* Sponsor logos: whatever colour the file has, show it white. */
.logos { list-style: none; padding: 0; display: flex; flex-wrap: wrap; align-items: center; gap: 1.5rem 2.5rem; margin-top: 1rem; }
.logos img { height: 3.25rem; width: auto; filter: var(--logo); opacity: .85; }

/* Image grids by count (12 columns). Photos keep their own proportions, so rows come out ragged on purpose. */
.pics { display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); gap: var(--gap); align-items: start; }
.pics figure { min-width: 0; }
.pics .film { width: auto; }
.n1 figure:nth-child(1) { grid-column: 1 / -1; }
.n2 figure:nth-child(1) { grid-column: 1 / span 8; }
.n2 figure:nth-child(2) { grid-column: 10 / span 3; align-self: end; }
.n3 figure:nth-child(1) { grid-column: 1 / span 7; }
.n3 figure:nth-child(2) { grid-column: 9 / span 4; align-self: end; }
.n3 figure:nth-child(3) { grid-column: 4 / span 6; }
.n4 figure:nth-child(1) { grid-column: 1 / span 5; }
.n4 figure:nth-child(2) { grid-column: 7 / span 6; }
.n4 figure:nth-child(3) { grid-column: 2 / span 6; }
.n4 figure:nth-child(4) { grid-column: 9 / span 4; align-self: end; }
.n5 figure:nth-child(1) { grid-column: 1 / span 8; }
.n5 figure:nth-child(2) { grid-column: 9 / span 4; align-self: end; }
.n5 figure:nth-child(n+3) { grid-column: span 4; }
@media (min-width: 801px) { .n6 > figure { grid-column: span 4; grid-row: 2; } } /* a row of three, below the gallery (which holds row 1) */
@media (max-width: 800px) {
	.pics figure:nth-child(n) { grid-column: span 6; align-self: start; }
	.pics figure:nth-child(1) { grid-column: 1 / -1; }
	.pics.n2 figure:nth-child(2) { grid-column: 1 / -1; }
}

/* Figures: tile, hover overlay, credit */
figure { margin: 0; }
figure a { position: relative; display: block; overflow: hidden; background: #1a191d; }
figure img { width: 100%; height: auto; transition: transform .6s, opacity .9s, filter .9s; }
figure a:hover img { transform: scale(1.025); }
/* Heading laid over a photo, always on (the hover caption comes on top of it). */
.badge { position: absolute; top: 0; left: 0; padding: 1rem 1.25rem; font: 700 clamp(1.75rem, 3.4vw, 3rem)/1 var(--head); color: #fff; text-shadow: 0 2px 20px rgb(0 0 0 / .6); }
.vid video { display: block; width: 100%; height: auto; background: #000; }
figcaption .who { display: block; color: var(--text); font-size: .8125rem; letter-spacing: 0; margin-bottom: .1rem; }
figcaption { margin-top: .4rem; font-size: .6875rem; letter-spacing: .06em; color: var(--muted); }
/* Credits stay out of the way: they fade in section by section, once the visitor has stopped on a section for 3 seconds, then stay (site.js puts .credits-on on the section). Without scripts they just show. */
.js .credit { opacity: 0; transition: opacity .6s ease; }
.credits-on .credit { opacity: 1; }
@media (prefers-reduced-motion: reduce) { .js .credit { transition: none; } }
.ov {
	position: absolute; inset: auto 0 0; padding: 3rem 1rem .85rem;
	background: linear-gradient(to top, rgb(0 0 0 / .78), transparent);
	font: 400 .875rem/1.3 'General Sans', sans-serif; color: #fff;
}
.ov b { font-weight: 400; display: block; font-size: 1rem; }
.ov.major b { font-weight: 700; font-size: 1.25rem; letter-spacing: -.01em; }
.albums .ov { inset: 0; display: grid; place-content: center; justify-items: center; gap: .25rem; padding: 1rem; text-align: center; background: rgb(0 0 0 / .6); } /* covers: album and artist, centred on the whole tile */
.albums .ov b { font-weight: 700; font-size: 1.25rem; letter-spacing: -.01em; }
@media (hover: hover) {
	.ov { opacity: 0; transition: opacity .25s; }
	figure a:hover .ov, figure a:focus-visible .ov { opacity: 1; }
}
@media (hover: none) { .albums .ov { display: none; } } /* no hover on a phone: a full-tile shade would hide the cover for good */

/* Images fade up from grey as they arrive (only when JS is there to flip them back). */
.js figure img:not(.in) { opacity: .15; filter: grayscale(1); }

/* Scrolling strips */
.lbl { display: flex; justify-content: space-between; align-items: center; margin-bottom: 1rem; }
.btn:hover, .form button:hover { background: var(--pill-hover-bg); color: var(--pill-hover-fg); }

/* Pull quote, centred, where a strip's label would be */
.pull { margin: 0 auto 2rem; max-width: 44ch; text-align: center; }
.pull p { font: 700 clamp(1.5rem, 3.2vw, 2.5rem)/1.2 var(--head); }
.pull cite { display: block; margin-top: 1rem; font: 400 .875rem/1.4 var(--body); font-style: normal; color: var(--muted); }
.pull cite span { display: block; }
.strip {
	--sh: clamp(240px, 34vw, 460px);
	display: flex; gap: var(--gap); overflow-x: auto; scroll-snap-type: x mandatory;
	margin-top: 1.5rem; padding-bottom: 1rem; scrollbar-color: var(--line) transparent;
}
.lbl + .strip { margin-top: 0; }
.strip figure { flex: none; scroll-snap-align: start; }
.strip img { height: var(--sh); width: auto; max-width: none; }
.band { padding: clamp(56px, 9vw, 120px) var(--pad) 0; }
.band .strip { --sh: clamp(200px, 28vw, 380px); }
/* Glide gallery under a project's photo grid. A mouse drives it from site.js (snap would fight that); touch swipes and settles on a tile. */
.pics .glide { grid-column: 1 / -1; grid-row: 1; } /* in the photo grid, in its own row on top; the photos sit below it */
.glide { container-type: inline-size; }
/* Spotlight while it is scrolled (site.js puts .on on the gallery and .gallery-on on body): it grows, lifts toward the middle of the screen (--lift) and the page dims behind it. Transform and opacity only. */
.glide { position: relative; z-index: 0; transition: transform .7s cubic-bezier(.16, 1, .3, 1), z-index 0s .7s; } /* z-index drops last, so it never dips under the dimming on its way back. position: z-index only counts on a grid item (the photo grid) or a positioned box (the covers sit in a plain block) */
.glide.on { z-index: 31; transform: translate(var(--lift-x, 0px), var(--lift, 0px)) scale(1.1); transition-delay: 0s; }
.glide.covers.on { transform: translate(var(--lift-x, 0px), var(--lift, 0px)) scale(1.04); } /* the covers run the full width of the page: at 1.1 the heading and the end covers would slide off the screen */
.glide .lbl h3 { transition: color .6s cubic-bezier(.16, 1, .3, 1); }
.glide.on .lbl h3 { color: #f1eee8; } /* it lifts above the dimming, so the heading goes light even in a white band */
body::before { content: ''; position: fixed; inset: 0; z-index: 30; background: #000; opacity: 0; pointer-events: none; transition: opacity .6s cubic-bezier(.16, 1, .3, 1); }
body.gallery-on::before { opacity: .78; }
.glide .strip { --sh: clamp(240px, 30vw, 400px); padding-bottom: 0; scrollbar-width: none; } /* no bar, so no room kept for it */
@supports (width: 1cqw) { .glide .strip { --sh: calc(100cqw * 2 / 3); } } /* tile height: a wide photo is exactly as wide as the gallery, so the page opens on one whole photo and none of the next shows */
@supports ( width: 1cqw ) { .glide.covers .strip { --sh: calc( ( 100cqw - 2 * var( --gap ) ) / 2.5 ); } }
@media ( max-width: 430px ) { @supports ( width: 1cqw ) { .glide.covers .strip { --sh: calc( ( 100cqw - var( --gap ) ) / 1.5 ); } } } /* phones: a cover and a half, so the covers stay big enough to read */ /* album covers (square): 2 whole covers, 2 gaps and half of the third fill the row, so the page opens showing 2.5 */
.glide .strip::-webkit-scrollbar { display: none; }
@media (hover: hover) and (pointer: fine) { .glide .strip { scroll-snap-type: none; } }
@media (hover: none) {
	.glide .strip { scroll-snap-type: x proximity; }
	.glide .strip figure { scroll-snap-align: center; }
	.glide.covers .strip figure { scroll-snap-align: start; } /* centring a cover would shift the row off its 2.5 */
}
.proj .copy { margin-bottom: 1.5rem; }

/* Contact */
.in.cta { grid-template-columns: minmax(0, 4fr) minmax(0, 8fr); row-gap: 2.5rem; padding-bottom: clamp(56px, 9vw, 120px); }
.cv { display: flex; flex-direction: column; gap: .5rem; font: 400 1.25rem/1.3 var(--body); }
.cv a { border-bottom: 1px solid var(--line); align-self: start; }
.cv .soon { color: var(--muted); }
.form { display: grid; gap: 1.25rem; max-width: 36rem; }
.form label { display: grid; gap: .35rem; font-size: .75rem; text-transform: uppercase; letter-spacing: .12em; color: var(--muted); }
.form input, .form textarea {
	font: 400 1.125rem/1.4 var(--body); color: var(--text); background: none; border: 0; border-bottom: 1px solid var(--line);
	padding: .5rem 0; border-radius: 0; resize: vertical;
}
.form input:focus, .form textarea:focus { outline: 0; border-color: var(--accent); }
.form button {
	justify-self: start; padding: .7rem 1.6rem; border: 0; border-radius: 999px;
	background: var(--pill-bg); color: var(--pill-fg); font: 500 .875rem 'General Sans', sans-serif; letter-spacing: .08em; text-transform: uppercase; cursor: pointer;
}
.form .hp { position: absolute; left: -9999px; }
.form button:disabled { opacity: .45; cursor: not-allowed; }
.form .pow-status:empty { display: none; }
.form .note { font: 400 1.125rem/1.3 var(--body); color: var(--accent); }
@media (max-width: 800px) { .in.cta { grid-template-columns: minmax(0, 1fr); } }

.foot { display: flex; justify-content: space-between; flex-wrap: wrap; gap: 1rem; padding: var(--pad); border-top: 1px solid var(--line); color: var(--muted); font-size: .875rem; }
.foot nav { display: flex; gap: 1.5rem; }
.foot nav button { padding: 0; border: 0; background: none; color: inherit; font: inherit; cursor: pointer; } /* "Cookie settings" reads as a link, like its neighbours */
.foot nav button:hover { color: var(--accent); }

/* Plain pages (Impressum etc.) — not .page, WP puts that on <body> */
.doc { padding: 8rem var(--pad) 4rem; max-width: 52rem; }
.doc h1 { font-size: clamp(2.5rem, 7vw, 5rem); max-width: none; margin-bottom: 2rem; }
.doc p + p { margin-top: 1em; }

/* Lightbox */
dialog { width: 100%; height: 100%; max-width: none; max-height: none; border: 0; padding: 0; background: #08070a; color: var(--text); }
dialog[open] { display: flex; flex-direction: column; justify-content: center; align-items: center; gap: 1rem; padding: var(--pad); }
dialog img { max-width: 100%; max-height: calc(100svh - 8rem); width: auto; height: auto; }
dialog footer { display: flex; gap: 1.5rem; width: 100%; align-items: baseline; font-size: .875rem; }
dialog .cap { flex: 1; color: var(--muted); }
dialog button { background: none; border: 0; padding: .5rem 0; font: inherit; color: inherit; cursor: pointer; }
dialog button:hover { color: var(--accent); }

@media (prefers-reduced-motion: reduce) {
	html { scroll-behavior: auto; }
	figure img { transition: none; }
	.js figure img:not(.in) { opacity: 1; filter: none; }
}

/* ---- Multi-page additions ---- */
.fine { font-size: .75rem; color: var(--muted); }
.more { display: inline-block; margin-top: .75rem; font-size: .75rem; font-weight: 500; letter-spacing: .1em; text-transform: uppercase; border-bottom: 1px solid var(--line); }
.more:hover { border-color: var(--accent); }
.more-row { margin-top: 1.5rem; }
.role { margin-top: .75rem; font-size: .75rem; font-weight: 500; letter-spacing: .12em; text-transform: uppercase; color: var(--muted); }
.pg > .tone:first-child .grp { padding-top: clamp(96px, 14vw, 180px); }

/* Header: wordmark left (wide screens), menu centred */
.bar { display: grid; grid-template-columns: 1fr auto 1fr; }
.bar .mark { justify-self: start; font: 700 1.25rem/1 var(--head); letter-spacing: 0; text-transform: none; }
.bar nav a { border-bottom: 1px solid transparent; }
.bar nav a[aria-current] { border-bottom-color: currentColor; }
.home-m { display: none; }
.burger, .menu, .menu-ring { display: none; } /* phones and narrow windows only, with scripts: see the menu below */
@media (max-width: 900px) {
	.bar { display: flex; justify-content: center; }
	.bar .mark, .bar .mark-pad { display: none; }
	.home-m { display: inline; }
	.bar nav { gap: 12px; font-size: .75rem; letter-spacing: .06em; flex-wrap: wrap; justify-content: center; }
}

/* The header slides up out of view once the page is scrolled down (site.js adds .away) and comes back when it is wanted. Never away with the mobile menu open, or while a link in it has keyboard focus
   (:focus-visible, not :focus-within, so a tap on the burger does not pin it). Reduced motion: no slide, it just goes. The translate also clears the admin bar's strip, which scrolls away on phones. */
@media (prefers-reduced-motion: no-preference) {
	.bar { transition: transform .45s var(--ease); }
	.bar.away { transform: translateY( calc( -100% - var(--wp-admin--admin-bar--height, 0px) ) ); }
}
@media (prefers-reduced-motion: reduce) { .bar.away { opacity: 0; pointer-events: none; } }
html.menu-open .bar.away { transform: none; opacity: 1; pointer-events: auto; }
.bar.away:has( :focus-visible ) { transform: none; opacity: 1; pointer-events: auto; } /* its own rule: a browser without :has drops just this one */

/* Mobile menu (hamburger). Markup in header.php, behaviour in site.js ("Mobile menu"). Only with scripts: without them the link row above stays.
   The menu is a full-screen layer outside the header, because the header's backdrop-filter and view-transition-name would trap a fixed layer.
   This part is the plain version (a fade); the sweep, the rise and the springy burger are added below, and only for people who allow motion. */
@media (max-width: 900px) {
	.js .bar { justify-content: space-between; align-items: center; }
	.js .bar .mark { display: block; }
	.js .bar nav { display: none; }
	html.menu-open { overflow: hidden; scrollbar-gutter: stable; }
	html.menu-open body .bar { background: transparent; backdrop-filter: none; } /* merges with the dark layer; "body" outranks body:not(.home) .bar */

	.js .burger { display: flex; align-items: center; gap: .7rem; min-height: 44px; padding: 0; border: 0; background: none; color: inherit; font: 700 .75rem/1 var(--head); letter-spacing: .14em; text-transform: uppercase; cursor: pointer; -webkit-tap-highlight-color: transparent; }
	.burger:focus-visible { outline: 2px solid var(--accent); outline-offset: 4px; }
	.burger-ico { position: relative; flex: none; width: 26px; height: 14px; }
	.burger-ico i { position: absolute; right: 0; height: 2px; border-radius: 1px; }
	.burger-ico i:first-child { top: 0; width: 100%; background: #fff; }
	.burger-ico i:last-child { bottom: 0; width: 60%; background: var(--accent); } /* the short gold bar */
	.burger[aria-expanded="true"] i:first-child { transform: translateY(6px) rotate(45deg); }
	.burger[aria-expanded="true"] i:last-child { width: 100%; transform: translateY(-6px) rotate(-45deg); }

	.js .menu {
		position: fixed; inset: 0; z-index: 9; display: flex; flex-direction: column; overflow-y: auto; overscroll-behavior: contain;
		padding: calc( var(--wp-admin--admin-bar--height, 0px) + 5.5rem ) 0 calc( var(--consent-h, 0px) + var(--pad) ); /* clear of the header above and the cookie bar below */
		background: var(--bg); --logo: brightness(0) invert(1); /* --logo: the LinkedIn icon, white on dark */
		visibility: hidden; opacity: 0; pointer-events: none; transition: opacity .2s, visibility 0s .2s;
	}
	html.menu-open .menu { visibility: visible; opacity: 1; pointer-events: auto; transition: opacity .2s; }
	.menu > * { flex: none; } /* never squeezed: a short screen scrolls instead */
	.menu > a { display: flex; align-items: baseline; gap: .75rem; padding: 0 var(--pad); overflow: hidden; font: 700 clamp( 2.5rem, 13vw, 4.25rem )/1.02 var(--head); color: var(--text); } /* overflow hidden: the title rises out of this edge */
	.menu > a + a { border-top: 1px solid var(--line); }
	.menu .mi { min-width: 1.75rem; font: 500 .75rem/1 var(--body); letter-spacing: .08em; color: var(--accent); }
	.menu .mt { display: block; padding: .35em 0; } /* the padding is inside the title so it rises clear of the row's edge */
	.menu > a[aria-current] .mt, .menu > a:is( :active, :focus-visible ) .mt { color: var(--accent); }
	.menu > a[aria-current] .mt::after { content: ''; display: inline-block; width: .16em; height: .16em; margin-left: .12em; border-radius: 50%; background: currentColor; } /* a full stop after the page you are on */
	.menu > a:is( :active, :focus-visible ) :is( .mi, .mt ) { translate: .6rem 0; }
	.menu > a:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
	.menu-foot { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: .75rem 1.5rem; margin-top: auto; padding: 2rem var(--pad) 0; font-size: .875rem; color: var(--muted); }
	.menu-foot a { color: var(--text); }
	.menu-foot .links { margin-top: 0; }
	@media (hover: hover) {
		.menu > a:hover .mt, .menu-foot a:hover { color: var(--accent); }
	}
}
@media (max-width: 900px) and (prefers-reduced-motion: no-preference) {
	.js .bar { transition: transform .45s var(--ease), background-color .5s var(--ease), backdrop-filter .5s var(--ease); }
	.burger { transition: transform .18s var(--ease); }
	.burger:active { transform: scale(.92); } /* a quick press squish */
	.burger-ico i { transition: transform .5s cubic-bezier(.34, 1.56, .64, 1), width .5s cubic-bezier(.34, 1.56, .64, 1); } /* the springy overshoot */

	/* Two layers open as circles from the burger: a gold one a little faster and ahead, the dark menu .08s behind it, so a thin gold edge sweeps across. Closing is the reverse: the gold one trails. */
	.js .menu, .js .menu-ring {
		--bx: calc( 100% - var(--pad) - 13px ); --by: calc( var(--wp-admin--admin-bar--height, 0px) + var(--pad) * .6 + 22px ); /* the burger icon's centre */
		clip-path: circle( 0 at var(--bx) var(--by) );
	}
	.js .menu-ring { position: fixed; inset: 0; z-index: 8; display: block; background: var(--accent); visibility: hidden; pointer-events: none; transition: clip-path .7s var(--ease) .08s, visibility 0s .78s; }
	.js .menu { opacity: 1; transition: clip-path .6s var(--ease), visibility 0s .6s; } /* visibility waits for the close, so a closed menu cannot be tabbed into */
	html.menu-open .menu, html.menu-open .menu-ring { clip-path: circle( 150vmax at var(--bx) var(--by) ); }
	html.menu-open .menu-ring { visibility: visible; transition: clip-path .7s var(--ease), visibility 0s; }
	html.menu-open .menu { transition: clip-path .85s var(--ease) .08s, visibility 0s; }

	/* Each title rises out of its row, one after the next. Closing: they just fade, then wait below for next time. */
	.menu .mt { transform: translateY( 110% ); opacity: 0; transition: opacity .2s, transform 0s .2s; }
	.menu .mi, .menu-foot { opacity: 0; transition: opacity .2s; }
	html.menu-open .menu .mt { transform: none; opacity: 1; transition: transform .8s var(--ease) calc( var(--i) * 60ms + 200ms ), translate .4s var(--ease), color .3s; }
	html.menu-open .menu .mi { opacity: 1; transition: opacity .6s calc( var(--i) * 60ms + 200ms ), translate .4s var(--ease); }
	html.menu-open .menu-foot { opacity: 1; transition: opacity .6s .6s; }
}

/* Films: 16:9 slots that load nothing until clicked */
.film { flex: none; scroll-snap-align: start; width: clamp(280px, 38vw, 560px); }
.strip.films:has( > .film:only-child ) { justify-content: center; } /* a lone film (Evans Robson Quartet): centred, 30% bigger, no heading or arrows */
.strip.films > .film:only-child { width: min(100%, clamp(364px, 49.4vw, 728px)); }
.proj:has( > .strip.films > .film:only-child ) .lbl, .proj:has( .strip.films > .film:only-child ) > .lbl { display: none; }
.embed { position: relative; aspect-ratio: 16 / 9; background: #111; overflow: hidden; }
.embed img, .strip .embed img { width: 100%; height: 100%; max-width: none; object-fit: cover; opacity: .75; }
.embed iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }
figure.film .embed[data-src] { cursor: pointer; } /* the whole poster opens the video (site.js); the coming-soon tile has no data-src and stays plain */
.play { position: absolute; inset: 0; margin: auto; width: 4rem; height: 4rem; border: 0; border-radius: 50%; background: #f3efe7; color: #333333; display: grid; place-items: center; cursor: pointer; }
.soon { position: absolute; left: 1rem; bottom: 1rem; padding: .35rem .8rem; border-radius: 999px; background: #f3efe7; color: #333333; font-size: .75rem; letter-spacing: .1em; text-transform: uppercase; }
.privacy { display: block; margin-top: .1rem; }
figcaption .privacy a { text-decoration: underline; }

/* Dated rows (contracted promotion, tour dates) */
.rows { list-style: none; padding: 0; margin-top: 1.25rem; }
.rows li { display: grid; grid-template-columns: 8.5rem 1fr; column-gap: 1rem; border-top: 1px solid var(--line); padding: .6rem 0; }
.rows time { font-size: .8125rem; color: var(--muted); }
.rows b { font-weight: 600; }
.rows span { grid-column: 2; font-size: .875rem; color: var(--muted); }
.rows em, .cards em { margin-left: .4rem; padding: .1rem .5rem; border: 0; background: var(--pill-bg); color: var(--pill-fg); border-radius: 999px; font-style: normal; font-size: .6875rem; letter-spacing: .08em; text-transform: uppercase; }

/* Event cards (Contracted promotion): one even grid, each picture beside its own event. 15rem is the narrowest a card gets, so 4 across on a wide screen, 2 on a tablet, 1 or 2 on a phone. */
.cards { list-style: none; padding: 0; display: grid; grid-template-columns: repeat( 4, minmax( 0, 1fr ) ); gap: calc( var(--gap) * 1.5 ) var(--gap); } /* four across, then two, then one: never three and a lonely fourth */
@media ( max-width: 860px ) { .cards { grid-template-columns: repeat( 2, minmax( 0, 1fr ) ); } }
@media ( max-width: 460px ) { .cards { grid-template-columns: minmax( 0, 1fr ); } }
.cards .card img { width: 100%; height: auto; aspect-ratio: 4 / 5; object-fit: cover; object-position: 50% 30%; margin: 0; } /* same shape for every picture; 30% keeps heads in frame; margin: Home's .card img adds a bottom margin */
.cards .card > div { margin-top: .75rem; }
.cards time { display: block; font-size: .8125rem; color: var(--muted); }
.cards h4 { margin-top: .35rem; font: 700 clamp( 1.25rem, 2vw, 1.5rem )/1.15 var(--head); }
.cards p { margin-top: .25rem; font-size: .9375rem; color: var(--muted); }
.cards .fine { font-size: .75rem; }
@media ( hover: hover ) {
	.cards .card a:hover img { transform: none; } /* the picture lifts instead of zooming */
	.cards .card:hover h4 { color: var(--accent); }
}
@media ( hover: hover ) and ( prefers-reduced-motion: no-preference ) {
	.cards .card a { transition: transform .4s var(--ease); }
	.cards h4 { transition: color .4s var(--ease); }
	.cards .card:hover a { transform: translateY( -4px ); }
}

/* Home */
.do, .nums { display: grid; gap: var(--gap); grid-template-columns: repeat(4, minmax(0, 1fr)); }
.nums { grid-template-columns: repeat(3, minmax(0, 1fr)); } /* three stats; the narrow-screen rules below still win */
.do article { border-top: 1px solid var(--line); padding-top: 1rem; }
/* H3: card titles on Home, project and strip titles on Work and About */
.do h3, .proj > h3, .lbl h3 { font: 700 clamp(1.25rem, 2vw, 1.5rem)/1.15 var(--head); }
.do .copy { margin-top: .75rem; }
.nums .stat strong { font-size: clamp(1.75rem, 3.4vw, 3.25rem); }
.card { display: block; }
.card img { width: 100%; height: auto; margin-bottom: .75rem; }
.card b { display: block; font: 700 1.375rem/1.1 var(--head); }
.card span { display: block; margin-top: .25rem; font-size: .9375rem; color: var(--muted); }
@media (max-width: 900px) { .do, .nums { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 520px) { .do, .nums { grid-template-columns: minmax(0, 1fr); } }

/* News */
.filters { display: flex; flex-wrap: wrap; gap: .5rem; margin-bottom: 1.5rem; }
.filters button { padding: .25rem .8rem; border: 0; border-radius: 999px; background: var(--pill-bg); color: var(--pill-fg); font: inherit; font-size: .8125rem; cursor: pointer; }
.filters button[aria-pressed="true"] { background: var(--pill-fg); color: var(--pill-bg); }
.news { list-style: none; padding: 0; }
.news li { display: grid; grid-template-columns: 10rem minmax(0, 1fr) 7rem; gap: var(--gap); align-items: start; border-top: 1px solid var(--line); padding: 1.25rem 0; }
.news .when { display: flex; flex-direction: column; align-items: flex-start; gap: .5rem; }
.news time { font-size: .8125rem; letter-spacing: .08em; text-transform: uppercase; color: var(--text); }
.news time.tbc { color: var(--muted); }
.news h3 { margin: .35rem 0 .25rem; font: 700 clamp(1.25rem, 2.2vw, 1.75rem)/1.15 var(--head); }
.news p { color: var(--muted); max-width: 52ch; }
.news img { width: 100%; height: 7rem; object-fit: cover; }
.news li[hidden] { display: none; }
.tag { display: inline-block; padding: .15rem .6rem; border: 0; border-radius: 999px; background: var(--pill-bg); color: var(--pill-fg); font-size: .6875rem; letter-spacing: .1em; text-transform: uppercase; }
@media (max-width: 700px) { .news li { grid-template-columns: minmax(0, 1fr) 5rem; } .news .when { grid-column: 1 / -1; flex-direction: row; align-items: center; gap: .75rem; } .news img { height: 5rem; } }

/* Tours: poster wall and the details pop-up */
.yr { margin-top: clamp(32px, 5vw, 64px); }
.yr h2 { margin-bottom: 1rem; }
.wall { list-style: none; padding: 0; display: grid; gap: var(--gap); grid-template-columns: repeat(auto-fill, minmax(min(100%, 230px), 1fr)); }
.tour { position: relative; display: block; width: 100%; padding: 0; border: 0; background: #1a191d; cursor: pointer; overflow: hidden; }
.tour img { width: 100%; height: auto; aspect-ratio: 4 / 5; object-fit: cover; transition: transform .6s; }
.tour:hover img { transform: scale(1.025); }
.tour .ov { opacity: 0; transition: opacity .25s; }
.tour:hover .ov, .tour:focus-visible .ov { opacity: 1; }
@media (hover: none) { .tour .ov { opacity: 1; } }
.tl { margin-top: .6rem; }
.tl b { font-weight: 700; }
.tourbox { width: min(1100px, 94vw); height: fit-content; max-height: 92svh; margin: auto; padding: 0; overflow: auto; background: #0c0b0e; color: #f1eee8; }
.tourbox[open] { display: block; padding: 0; }
.tourbox::backdrop { background: rgb(0 0 0 / .72); }
/* Film pop-up: one box for every film tile, centred, half the screen wide (never under 320px), faded in and out by site.js (.show). The width also gives way on a short screen, so the 16:9 player never gets cut off. No Close button: Esc or a click on the backdrop closes it, so the box is just the frame. */
.vidbox { width: min(clamp(320px, 50vw, 92vw), calc(92svh * 16 / 9)); height: fit-content; max-height: 92svh; margin: auto; overflow: hidden; background: #0c0b0e; color: #f1eee8; opacity: 0; transition: opacity .35s ease; }
.vidbox[open] { display: block; padding: 0; }
.vidbox.show { opacity: 1; }
.vidbox::backdrop { background: rgb(0 0 0 / 0); transition: background-color .35s ease; }
.vidbox.show::backdrop { background: rgb(0 0 0 / .82); }
@media (prefers-reduced-motion: reduce) {
	.vidbox { opacity: 1; transition: none; }
	.vidbox::backdrop { background: rgb(0 0 0 / .82); transition: none; }
}
.tb { position: relative; display: grid; grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); gap: clamp(16px, 3vw, 40px); padding: clamp(16px, 3vw, 40px); }
.tb-poster { width: 100%; height: auto; max-height: 82svh; object-fit: contain; align-self: start; }
.tb-body h3 { margin: .5rem 0 1rem; font: 700 clamp(1.5rem, 3vw, 2.25rem)/1.1 var(--head); }
.tb-body .fine { margin-top: 1rem; }
.tourbox, .vidbox { --logo: brightness(0) invert(1); --bg: #0c0b0e; --text: #f1eee8; --muted: #9a968f; --line: #2a2830; --accent: #f2b84b; --pill-bg: #3a3a3a; --pill-fg: #ececec; --pill-hover-bg: #f2b84b; --pill-hover-fg: #0c0b0e; } /* the pop-up is always dark, even when it sits inside a light band */
.tb-body .logos { gap: 1rem 2rem; margin-top: 1.25rem; }
.tb-body .logos img { height: 2.25rem; }
.tb-body .logos img.tall { height: 3.5rem; }
.logos img.asis { filter: none; } /* made for dark backgrounds already: the white filter would hide its dark lettering */
.tb-head { display: flex; flex-wrap: wrap; justify-content: space-between; align-items: flex-start; gap: 0 1.5rem; }
.tb-head > div { flex: 1 1 14rem; min-width: 0; }
.tb-head .links { flex: none; flex-direction: column; align-items: flex-end; gap: .5rem; margin-top: 1.6rem; } /* top right, below the X */
.tb:not(.rel) .tb-head h3 { margin-top: 0; } /* a tour's title is the first line: level with the top of the poster */
@media (min-width: 801px) { /* the head sits at the top, beside the X: links start 3.5rem down (the pop-up's padding is var(--pad)) and the title keeps clear of it */
	.tb-head .links { margin-top: calc( 3.5rem - var(--pad) ); }
	.tb-head > div { padding-right: calc( 3.75rem - var(--pad) ); }
}
.tb-film { grid-column: 1 / -1; } /* video spans the whole pop-up, under poster and details */
.tb-film .fine { margin-top: .75rem; }
.tb-film .embed img { object-position: 50% 32%; } /* tall posters crop to 16:9: keep faces in */
.tb .x { position: absolute; top: .5rem; right: .5rem; z-index: 1; display: grid; place-items: center; width: 44px; height: 44px; padding: 0; border: 0; outline: 0; background: none; color: var(--text); cursor: pointer; filter: drop-shadow( 0 1px 3px rgb(0 0 0 / .6) ); -webkit-tap-highlight-color: transparent; transition: color .2s, transform .2s var(--ease); } /* just an X; the shadow keeps it readable over a poster on phones */
.tb .x:hover, .tb .x:focus-visible { color: var(--accent); }
.tb .x:focus-visible { transform: scale(1.15); } /* keyboard focus: gold and a little bigger, instead of an outline ring */
@media (max-width: 800px) { .tb { grid-template-columns: minmax(0, 1fr); } .tb-poster { max-height: 60svh; } }
/* Release pop-up: cover with the media highlights under it, details and the player on the right. One column on a phone: cover, details, player, highlights. */
.rel .tb-poster { grid-column: 1; grid-row: 1; }
.rel .tb-body { grid-column: 2; grid-row: 1 / span 2; }
.rel .tb-media { grid-column: 1; grid-row: 2; }
.embed.bc { aspect-ratio: auto; height: var(--bc-h); margin-top: 1.5rem; background: #17151a; }
.bc-note { position: absolute; left: 0; right: 0; bottom: 1.25rem; text-align: center; font-size: .75rem; letter-spacing: .12em; text-transform: uppercase; color: var(--muted); }
.embed.bc .play { top: -2rem; } /* the label sits under the button, so lift the pair together */
.rel-quote { margin: 1.25rem 0 0; }
.rel-quote p { font-size: 1rem; line-height: 1.55; }
.rel-quote cite { display: block; margin-top: .6rem; font-style: normal; font-size: .8125rem; color: var(--muted); }
.rel-quote cite a { border-bottom: 1px solid var(--line); }
.rel-quote cite a:hover { border-color: var(--accent); }
.tb-media .k { margin-bottom: .5rem; }
.media { list-style: none; padding: 0; margin: 0; }
.media li { padding: .7rem 0; border-top: 1px solid var(--line); }
.media li:last-child { border-bottom: 1px solid var(--line); }
.media a { font-weight: 500; border-bottom: 1px solid var(--line); }
.media a:hover { border-color: var(--accent); }
.media span { display: block; margin-top: .2rem; font-size: .8125rem; color: var(--muted); }
@media (max-width: 800px) { .rel .tb-poster, .rel .tb-body, .rel .tb-media { grid-column: 1; grid-row: auto; } .rel .tb-head .links { flex-direction: row; align-items: center; gap: .5rem 1.25rem; margin-top: 0; } }

/* Concerts: the dark band under the tours (rp_concerts in render.php, "Concerts" in site.js). The filters need scripts, so without them the controls and the count stay hidden and the whole list shows. */
.cc { --cc-h: 2.25rem; margin-top: clamp(24px, 4vw, 48px); color-scheme: dark; } /* --cc-h: the height the chips and the project menu share; dark: the menu's list draws dark */
@media (pointer: coarse) { .cc { --cc-h: 2.75rem; } } /* a thumb needs 44px */
.cc [hidden] { display: none; } /* a rule that sets display (the rows, the buttons) would otherwise beat the hidden attribute */
.cc-bar, .cc-meta { display: none; }
.js .cc-bar { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 1.25rem 2rem; }
.cc-grp { display: grid; gap: .4rem; min-width: 0; }
.cc-lbl { font-size: .75rem; font-weight: 500; letter-spacing: .12em; text-transform: uppercase; color: var(--muted); }
.cc-chips { display: flex; flex-wrap: wrap; gap: .5rem; }
.cc-chip, .cc-select { height: var(--cc-h); border: 1px solid var(--line); border-radius: 999px; background: var(--bg); color: var(--text); font: 400 .875rem/1 var(--body); }
.cc-chip { padding: 0 1rem; cursor: pointer; }
.cc-chip:hover, .cc-select:hover { border-color: var(--muted); }
.cc-chip[aria-pressed="true"] { border-color: var(--text); background: var(--text); color: var(--bg); } /* the one chosen: inverted */
.cc-pick { position: relative; display: block; }
.cc-pick::after { content: ''; position: absolute; right: 1.1rem; top: 50%; width: .4rem; height: .4rem; border: solid var(--muted); border-width: 0 1.5px 1.5px 0; translate: 0 -70%; rotate: 45deg; pointer-events: none; } /* the arrow, drawn here because the browser's own is switched off */
.cc-select { appearance: none; width: clamp(12rem, 22vw, 16rem); max-width: 100%; padding: 0 2.5rem 0 1rem; cursor: pointer; text-overflow: ellipsis; }
.cc-select option, .cc-select optgroup { background: var(--bg); color: var(--text); }
.cc-chip:focus-visible, .cc-select:focus-visible, .cc-reset:focus-visible, .cc-empty button:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.cc-meta { flex-wrap: wrap; align-items: center; gap: .25rem 1.25rem; min-height: var(--cc-h); margin-top: 1rem; } /* its height stays put when the reset button comes and goes */
.js .cc-meta { display: flex; }
.cc-count { font-size: .8125rem; color: var(--muted); }
.cc-reset, .cc-empty button { padding: 0; border: 0; border-bottom: 1px solid var(--line); background: none; color: var(--text); font: inherit; cursor: pointer; }
.cc-reset { font-size: .8125rem; }
.cc-reset:hover, .cc-empty button:hover { border-color: var(--accent); color: var(--accent); }
.cc-empty { padding: 1.25rem 0; border-top: 1px solid var(--line); color: var(--muted); }
.cc .yr .k { margin-bottom: .75rem; }
.cc-list { list-style: none; padding: 0; }
.cc-row { display: grid; gap: .15rem 0; padding: .9rem 0; border-top: 1px solid var(--line); } /* the line is on top of each row, so it stays whichever rows are hidden */
.cc-date { font-size: .9375rem; font-weight: 500; }
.cc-t { display: block; font-size: clamp(1.0625rem, 1.4vw, 1.25rem); line-height: 1.25; }
.cc-with, .cc-tour, .cc-city { display: block; color: var(--muted); }
.cc-with { margin-top: .15rem; font-size: .9375rem; }
.cc-tour { font-size: .8125rem; }
.cc-tags { display: flex; flex-wrap: wrap; gap: .4rem; }
.cc-tag { padding: .1rem .6rem; border: 1px solid var(--muted); border-radius: 999px; color: var(--muted); font-size: .75rem; line-height: 1.5; letter-spacing: .08em; text-transform: uppercase; white-space: nowrap; }
.cc-tag.up { border-color: var(--accent); color: var(--accent); }
@media (min-width: 701px) {
	.cc-row { grid-template-columns: clamp(8rem, 14vw, 11rem) minmax(0, 5fr) minmax(0, 3fr) clamp(7rem, 12vw, 10rem); column-gap: var(--gap); align-items: baseline; } /* date | title | venue and city | tags; the same widths on every row, so the columns line up */
	.cc-where { grid-column: 3; }
	.cc-tags { grid-column: 4; justify-content: flex-end; }
}
@media (max-width: 700px) { /* compact: date first, then title, venue and city on one line, tags last */
	.cc-date { font-size: .8125rem; color: var(--muted); }
	.cc-venue, .cc-city { display: inline; }
	.cc-venue + .cc-city::before { content: ', '; } /* only when both are there */
	.cc-tags { margin-top: .4rem; }
	.cc-select { width: 100%; }
	.cc-grp:has( > .cc-pick ) { flex: 1 1 100%; }
}
@media (prefers-reduced-motion: no-preference) { .cc-chip, .cc-select { transition: color .2s, background-color .2s, border-color .2s; } }

/* About */
.about { display: grid; grid-template-columns: minmax(0, 4fr) minmax(0, 8fr); gap: calc(var(--gap) * 2); align-items: start; }
.portrait img { width: 100%; height: auto; }
.about .copy { margin-top: 1.25rem; max-width: 52ch; }
.facts { margin-top: 2rem; }
.facts div { display: grid; grid-template-columns: 8rem 1fr; border-top: 1px solid var(--line); padding: .6rem 0; }
.facts dd { margin: 0; }
.cvs { display: flex; flex-wrap: wrap; gap: .75rem; margin-top: 1.5rem; }
.btn { padding: .55rem 1.2rem; border: 0; border-radius: 999px; background: var(--pill-bg); color: var(--pill-fg); font-size: .8125rem; letter-spacing: .08em; text-transform: uppercase; }
.cvs .soon { position: static; padding: .55rem 0; background: none; color: var(--muted); letter-spacing: .04em; text-transform: none; font-size: .9375rem; }
.funding { width: 100%; margin-top: 1.5rem; border-collapse: collapse; }
.funding th, .funding td { padding: .7rem 1rem .7rem 0; border-top: 1px solid var(--line); text-align: left; vertical-align: top; }
.funding th:last-child, .funding td:last-child { padding-right: 0; }

/* "See more" accordion around the funding list: a plain <details>, so it works without scripts and from the keyboard */
.fund { margin-top: 1.5rem; border-top: 1px solid var(--line); }
.fund summary { display: flex; justify-content: space-between; align-items: center; padding: .9rem 0; list-style: none; cursor: pointer; font-size: .75rem; font-weight: 500; letter-spacing: .12em; text-transform: uppercase; color: var(--muted); }
.fund summary::-webkit-details-marker { display: none; }
.fund summary::after { content: '+'; font-size: 1.375rem; line-height: 1; letter-spacing: 0; }
.fund[open] summary::after { content: '\2212'; }
.fund summary:hover { color: var(--text); }
.fund summary:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.fund .o, .fund[open] .c { display: none; }
.fund[open] .o { display: inline; }
.fund .funding { margin-top: 0; }
@media (max-width: 520px) { .funding { font-size: .875rem; } .funding th, .funding td { padding-right: .6rem; } .funding th { font-size: .6875rem; letter-spacing: .06em; } }
.funding th { font-size: .75rem; font-weight: 500; letter-spacing: .12em; text-transform: uppercase; color: var(--muted); }
.quotes { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: calc(var(--gap) * 1.5); }
.quotes blockquote { margin: 0; font-size: 1.0625rem; line-height: 1.5; }
.quotes figcaption { margin-top: 1rem; font-size: .875rem; letter-spacing: 0; color: var(--muted); }
.quotes figcaption b { display: block; color: var(--text); }
@media (max-width: 900px) { .about, .quotes { grid-template-columns: minmax(0, 1fr); } .portrait { max-width: 22rem; } }

/* Legal pages */
.doc h2 { margin: 2rem 0 .5rem; font: 700 1.25rem/1.2 var(--head); }
.doc a { text-decoration: underline; }
.form .fine { margin-top: -.5rem; }

.nums .stat, .nums .stat + .stat { margin-top: 0; }

body:not(.home) .bar { background: rgb(12 11 14 / .94); }

@media (max-width: 600px) { .wall { grid-template-columns: repeat(2, minmax(0, 1fr)); } .tl { font-size: .875rem; } }

.funding tfoot th, .funding tfoot td { border-top: 2px solid var(--text); font-weight: 600; }
.funding tfoot th { color: var(--text); letter-spacing: .12em; }

figcaption a { display: inline; position: static; overflow: visible; background: none; }

.rows li.off b, .rows li.off time { text-decoration: line-through; text-decoration-thickness: 1px; opacity: .6; }

/* Selected work: uneven sizes and offsets, every picture at its own proportions */
.feat { display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); column-gap: var(--gap); row-gap: clamp(32px, 6vw, 88px); align-items: start; }
.feat .card:nth-child(1) { grid-column: 1 / span 7; }
.feat .card:nth-child(2) { grid-column: 9 / span 4; align-self: end; }
.feat .card:nth-child(3) { grid-column: 2 / span 4; }
.feat .card:nth-child(4) { grid-column: 7 / span 6; margin-top: clamp(24px, 6vw, 96px); }
@media (max-width: 700px) {
	.feat { grid-template-columns: repeat(2, minmax(0, 1fr)); }
	.feat .card:nth-child(n) { grid-column: auto; margin-top: 0; align-self: start; }
	.feat .card:nth-child(1), .feat .card:nth-child(4) { grid-column: 1 / -1; }
}

/* Dated blocks (Archive): each year is a container (.tl-year) holding a bar with the year, then its blocks, each month a label above its blocks.
   The bar is sticky: it scrolls with the page, sticks to the top of the screen (the site header slides in over it), and the next year's bar pushes it away when its year ends.
   site.js adds .stuck to a caught bar and puts the month in .tl-fm. Nothing between a bar and <main> may set overflow, or sticky stops working. */
.tline { --ty: clamp(2rem, 4vw, 3rem); --h: calc(var(--ty) + 1.25rem); --pin: 0px; } /* --ty is the year size; --h the bar height; --pin where the bars stick: the top of the screen, under the admin bar when logged in (site.js sets it) */
.tl-bar { position: sticky; top: var(--pin); z-index: 4; display: flex; align-items: center; gap: 1rem; height: var(--h); margin: 1.375rem calc(var(--pad) * -1) .375rem; padding: 0 var(--pad); background: var(--bg); } /* as wide as the screen; the margins are the year's old 2rem above and 1rem below, less the .625rem the bar leaves around the text */
.tl-bar::after { content: ''; position: absolute; inset: auto 0 0; height: 1px; background: var(--line); opacity: 0; } /* the line under a caught bar */
.tl-bar.stuck::after { opacity: 1; }
@media (prefers-reduced-motion: no-preference) { .tl-bar::after { transition: opacity .2s; } }
.tl-ym { display: flex; align-items: center; gap: 1rem; }
.tl-y { font: 700 var(--ty)/1 var(--head); }
.tl-fm { font-size: clamp(1.125rem, 2vw, 1.5rem); font-weight: 700; letter-spacing: .08em; text-transform: uppercase; color: var(--muted); }
.tl-logo { margin-left: auto; height: 1.75rem; width: auto; filter: var(--logo); opacity: .9; } /* right of the bar */
.tl-logo.tall { height: 2.75rem; } /* squarer logos need more height to read */
.tl-entry { padding-top: 1rem; border-top: 1px solid var(--line); }
.tl-date { margin-bottom: .75rem; font-size: .8125rem; letter-spacing: .08em; text-transform: uppercase; color: var(--muted); }
.tline .proj { margin-bottom: 2.5rem; }
@media (min-width: 801px) { /* an entry with three blocks (Jun 2023 at SIMA) puts them side by side, the month label across the top */
	.tl-entry:has( > .proj ~ .proj ~ .proj ) { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 0 var(--gap); align-items: start; }
	.tl-entry:has( > .proj ~ .proj ~ .proj ) > .tl-date { grid-column: 1 / -1; }
}
.tline .flip, .tline .flip .pics, .tline .flip > *, .tline .flip .pics > * { direction: ltr; }
.tl-cta { margin: 0 0 0 auto; font: 700 clamp(1.125rem, 2vw, 1.5rem)/1.2 var(--head); }
.tl-cta a { border-bottom: 1px solid var(--line); }
.tl-cta a:hover { border-color: var(--accent); }

/* ---- Quiet motion: expo ease-out, 200 to 900 ms, transform and opacity only, nothing moves the layout. All of it is off under reduced motion. ---- */
@media (prefers-reduced-motion: no-preference) {
	/* Home: the hero line rises on load; the picture drifts and grows a little as the page scrolls, where scroll-driven animation exists */
	@keyframes rise { from { opacity: 0; transform: translateY(16px); } }
	.hero p { animation: rise .9s var(--ease) .2s backwards; }
	@supports (animation-timeline: view()) {
		@keyframes drift { to { transform: translateY(3%) scale(1.06); } }
		.hero { overflow: clip; } /* the picture must not spill onto the next band */
		.hero > video, .hero > img { animation: drift linear both; animation-timeline: view(); animation-range: exit 0% exit 100%; }
	}

	/* Archive: each entry draws in once, when site.js first sees it (.shown): the line, the month, then the content. Without scripts they just show. */
	.tl-entry { position: relative; border-top-color: transparent; } /* the border keeps its 1px of room; the line below is drawn in its place */
	.tl-entry::before { content: ''; position: absolute; top: -1px; left: 0; right: 0; height: 1px; background: var(--line); transform-origin: left; transition: transform .7s var(--ease); }
	.tl-date, .tl-entry > .proj { transition: opacity .8s var(--ease), transform .8s var(--ease); }
	.js .tl-entry:not(.shown)::before { transform: scaleX(0); }
	.js .tl-entry:not(.shown) .tl-date { opacity: 0; transform: translateY(12px); }
	.js .tl-entry:not(.shown) > .proj { opacity: 0; transform: translateY(24px); }

	/* Page changes: the header holds still, the page fades out when a link is clicked (site.js adds .leaving) and the next one fades in. Done with plain
	   CSS and JS, because the native cross-document view transition never ran in the preview browser. backwards: no animation state is kept afterwards, so main stays free of a stacking context. */
	main, .foot { animation: page-in .45s var(--ease) backwards; }
	@keyframes page-in { from { opacity: 0; } }
	html.leaving main, html.leaving .foot { opacity: 0; transition: opacity .22s ease; }
}

/* ---- Cookie bar (rp_consent_bar in render.php, "Cookie bar" in site.js) ----
   Fixed to the bottom and always dark, whatever band is under it (the root colours are the dark ones). It sits above the header (10) and below the gallery dimming (30), so a gallery in the spotlight dims it too; dialogs are in the top layer and cover it. site.js sets --consent-h to its height, and the page gets that much room underneath, so the bar never hides the footer links. */
body { padding-bottom: var( --consent-h, 0px ); }
.consent[hidden] { display: none; }
.consent {
	position: fixed; inset: auto 0 0; z-index: 20;
	display: flex; flex-wrap: wrap; justify-content: space-between; align-items: center; gap: .75rem 1.5rem;
	padding: 1rem var(--pad);
	background: var(--bg); color: var(--text); border-top: 1px solid var(--line);
	font-size: .8125rem;
}
.consent p { flex: 1 1 24rem; max-width: 80ch; }
.consent-btns { display: flex; flex-wrap: wrap; align-items: center; gap: .5rem 1rem; }
.consent button { padding: .55rem 1.2rem; border: 0; border-radius: 999px; background: var(--pill-bg); color: var(--pill-fg); font: 500 .8125rem 'General Sans', sans-serif; letter-spacing: .08em; text-transform: uppercase; cursor: pointer; } /* Accept and Decline share this, so neither stands out */
.consent button:hover { background: var(--pill-hover-bg); color: var(--pill-hover-fg); }
.consent a { text-decoration: underline; text-underline-offset: .2em; }
.consent :focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.consent:focus-visible { outline: 2px solid var(--accent); outline-offset: -4px; } /* the bar itself, after "Cookie settings" opens it: inside the edge, which is the screen's edge */
@media (prefers-reduced-motion: no-preference) {
	@keyframes consent-in { from { opacity: 0; } }
	.consent { animation: consent-in .35s ease backwards; } /* plays each time the bar is shown */
}
