/* dianamaye.love
 *
 * The page is a gallery wall label over the work — the artist's own framing
 * ("this is my gallery", not a service). So: the photograph is the page, and
 * everything written sits on it the way a printed plate sits beside a piece —
 * quiet, precise, and not competing with what it describes.
 *
 * The palette is sampled from the photograph itself rather than chosen against
 * it, which is why it sits on the image instead of on top of it: measured mean
 * #746841, warm gold and shadowed green.
 *
 * On the scrim shape. The photograph is bright through the middle (sun flaring
 * through the canopy, sunlit grass) and dark down the right third (the trunk
 * and its shadow). The dark third is tempting to write on and wrong to rely
 * on: the background is `cover`, so a phone at 390px crops a 3:4 portrait to
 * roughly its middle THIRD horizontally and that band never appears. So the
 * text is kept full-width and centred, and the scrim is weighted to the top
 * and bottom edges where the writing actually sits — leaving the middle of the
 * frame nearly clear, which is where the photograph is worth looking at.
 */

/* Both files are variable fonts, declared with a weight RANGE and
 * `format('woff2')` — not `format('woff2-variations')`, which was an interim
 * spelling that CSS Fonts Level 4 removed. A UA that does not recognise a
 * format string must skip that `src` entirely, so the obsolete one risks the
 * page falling back to a system serif on exactly the client that matters most
 * here: the in-app browser on a phone, which is what an Instagram bio link
 * opens. Plain `woff2` has been correct for variable fonts since Safari 14. */
@font-face {
	font-family: 'Cormorant Garamond';
	src: url('cormorant-garamond-latin.woff2') format('woff2');
	font-weight: 300 400;
	font-style: normal;
	font-display: swap;
}

@font-face {
	font-family: 'Jost';
	src: url('jost-latin.woff2') format('woff2');
	font-weight: 400 500;
	font-style: normal;
	font-display: swap;
}

:root {
	--ink: #0d0a05;
	--bone: #f4ece0;
	--gold: #d9bf85;
	/* Secondary text. Brighter than it would need to be on a flat dark ground:
	 * it is read over a photograph, through a scrim, at small sizes. */
	--moss: #c5b89d;

	/* Belt and braces for the text over the photograph. The scrim does the
	 * real work; this catches the cases the scrim cannot know about — an
	 * unusual viewport cropping a bright patch up under a line of type. */
	--lift: 0 1px 10px rgba(13, 10, 5, 0.6), 0 1px 2px rgba(13, 10, 5, 0.45);

	--rule: rgba(244, 236, 224, 0.16);
	--rule-lit: rgba(212, 184, 120, 0.55);

	--serif: 'Cormorant Garamond', 'Iowan Old Style', Palatino, Georgia, serif;
	--sans: 'Jost', 'Avenir Next', 'Segoe UI', system-ui, sans-serif;

	--gutter: clamp(1.5rem, 6vw, 4rem);
}

*,
*::before,
*::after {
	box-sizing: border-box;
}

html {
	-webkit-text-size-adjust: 100%;
}

body {
	margin: 0;
	min-height: 100svh;
	display: flex;
	background-color: var(--ink);
	color: var(--bone);
	font-family: var(--sans);
	font-weight: 400;
	/* The photograph is a warm image; let the browser render it warmly. */
	-webkit-font-smoothing: antialiased;
}

/* The photograph, and the scrim, as two fixed layers behind everything.
 * Fixed rather than `background-attachment: fixed`, which iOS Safari has never
 * honoured — it silently falls back to scroll and the image jumps. */
body::before,
body::after {
	content: '';
	position: fixed;
	inset: 0;
	z-index: -1;
	pointer-events: none;
}

body::before {
	/* 900x1200. Phones are most of the traffic here — the page is what an
	 * Instagram bio link opens — so the small rendition is the default and the
	 * large one is the override, not the other way round. */
	background-image: url('bg-sm.webp');
	background-size: cover;
	/* 44% horizontally: a narrow viewport crops to the middle of the frame, and
	 * the subject stands just left of the trunk. This keeps them in shot. */
	background-position: 44% 50%;
	background-repeat: no-repeat;
}

@media (min-width: 46rem) {
	body::before {
		/* 1440x1920, for viewports wide enough that the small one would soften. */
		background-image: url('bg-lg.webp');
		background-position: 50% 42%;
	}
}

/* Bottom-weighted, and the weights are not taste — they are measured. The
 * brightest part of the frame runs about lum 200; white-ish text needs the
 * ground under it below about lum 105 to clear 4.5:1, which takes roughly 55%
 * alpha there. So: the top third is left almost clear (canopy and sun flare,
 * the best of the photograph, and nothing is written on it), and the veil
 * ramps hard through the band where the writing starts. */
body::after {
	background:
		linear-gradient(
			180deg,
			/* Never fully clear, even at the top: on a short viewport the whole
			 * plate rides up and the name can land this high. */
			rgba(13, 10, 5, 0.14) 0%,
			rgba(13, 10, 5, 0.26) 20%,
			rgba(13, 10, 5, 0.36) 30%,
			rgba(13, 10, 5, 0.52) 38%,
			rgba(13, 10, 5, 0.66) 52%,
			rgba(13, 10, 5, 0.82) 72%,
			rgba(13, 10, 5, 0.94) 100%
		);
}

.plate {
	width: 100%;
	max-width: 38rem;
	margin-inline: auto;
	padding-inline: var(--gutter);
	padding-block: clamp(2.5rem, 9vh, 5.5rem) clamp(2rem, 6vh, 3.25rem);
	display: flex;
	flex-direction: column;
	/* Everything sits low: the photograph is the work, the writing is the
	 * plate under it. This is also what makes the scrim honest — the top of
	 * the frame can stay clear because nothing is written there. */
	justify-content: flex-end;
	gap: clamp(2.25rem, 7vh, 3.5rem);
}

.foot {
	display: flex;
	flex-direction: column;
	gap: clamp(1.75rem, 5vh, 2.75rem);
}

/* ── Titling ─────────────────────────────────────────────────────────────── */

.titling {
	text-align: center;
}

.name {
	margin: 0;
	font-family: var(--serif);
	font-weight: 300;
	/* The diacritics are the point. Platforms strip them from handles, so this
	 * page is the only place the name is set the way it is spelled — which is
	 * reason enough to set it large and give it room. */
	font-size: clamp(2.9rem, 12vw, 5.75rem);
	line-height: 1.02;
	letter-spacing: 0.012em;
	color: var(--bone);
	text-shadow: var(--lift);
	text-wrap: balance;
}

/* The one line that routinely lands on the sun flare — on a phone it sits high
 * in the frame, where the scrim is deliberately weak. It gets brighter ink and
 * a heavier shadow of its own rather than dragging the whole scrim down. */
.say {
	margin: 1em 0 0;
	font-size: 0.78rem;
	letter-spacing: 0.16em;
	color: #eadfcc;
	text-shadow:
		0 1px 3px rgba(13, 10, 5, 0.92),
		0 2px 18px rgba(13, 10, 5, 0.85);
}

.say i {
	font-style: italic;
	color: var(--gold);
}

.what {
	margin: 1.5em auto 0;
	max-width: 30rem;
	font-family: var(--serif);
	font-weight: 400;
	font-size: clamp(1.05rem, 3.4vw, 1.3rem);
	line-height: 1.62;
	color: var(--bone);
	text-shadow: var(--lift);
	text-wrap: pretty;
}

/* ── Catalogue ───────────────────────────────────────────────────────────── */

.catalogue ul {
	margin: 0;
	padding: 0;
	list-style: none;
	border-top: 1px solid var(--rule);
}

.catalogue li {
	border-bottom: 1px solid var(--rule);
}

.catalogue a {
	display: flex;
	flex-direction: column;
	gap: 0.3rem;
	padding-block: 1.15rem;
	text-decoration: none;
	color: inherit;
	transition: background-color 180ms ease, border-color 180ms ease;
}

.where {
	font-family: var(--serif);
	font-weight: 400;
	font-size: clamp(1.4rem, 5vw, 1.75rem);
	line-height: 1.1;
	color: var(--bone);
	text-shadow: var(--lift);
	transition: color 180ms ease;
}

.what-there {
	font-size: 0.82rem;
	letter-spacing: 0.035em;
	line-height: 1.5;
	color: var(--moss);
	text-shadow: var(--lift);
}

/* Wide enough for the plate to read as two columns: destination on the left,
 * what is there on the right, sharing a baseline — a catalogue listing. */
@media (min-width: 34rem) {
	.catalogue a {
		flex-direction: row;
		align-items: baseline;
		justify-content: space-between;
		gap: 2rem;
	}

	.what-there {
		text-align: right;
		max-width: 19rem;
	}
}

@media (hover: hover) {
	.catalogue a:hover {
		background-color: rgba(212, 184, 120, 0.07);
	}

	.catalogue a:hover .where {
		color: var(--gold);
	}

	.catalogue li:has(a:hover) {
		border-bottom-color: var(--rule-lit);
	}
}

.catalogue a:focus-visible {
	outline: 2px solid var(--gold);
	outline-offset: 3px;
}

.catalogue a:focus-visible .where {
	color: var(--gold);
}

/* ── Terms ───────────────────────────────────────────────────────────────── */

.terms {
	text-align: center;
}

.pace {
	margin: 0 auto;
	max-width: 27rem;
	font-size: 0.83rem;
	line-height: 1.7;
	letter-spacing: 0.02em;
	color: var(--moss);
	text-shadow: var(--lift);
}

.age {
	margin: 1.5em 0 0;
	font-size: 0.72rem;
	letter-spacing: 0.14em;
	color: var(--moss);
	opacity: 0.85;
	text-shadow: var(--lift);
}

/* ── The one moment ──────────────────────────────────────────────────────── */

/* A single page-load sequence — the plate settling onto the photograph — and
 * nothing else moves on this page ever again. */
@media (prefers-reduced-motion: no-preference) {
	.titling,
	.catalogue,
	.terms {
		animation: settle 1000ms cubic-bezier(0.22, 0.61, 0.36, 1) backwards;
	}

	.titling {
		animation-delay: 120ms;
	}

	.catalogue {
		animation-delay: 400ms;
	}

	.terms {
		animation-delay: 600ms;
	}

	@keyframes settle {
		from {
			opacity: 0;
			transform: translateY(14px);
		}

		to {
			opacity: 1;
			transform: none;
		}
	}
}
