/*!
Theme Name: v3dstagram
Theme URI: https://v3d.space
Author: v3d
Author URI: https://v3d.space
Description: An Instagram-shaped feed for v3d.space. Narrow centered column on desktop with the background video playing around it, 4:5 media cards, and a full-width expanded view. Inherits the content model of the V theme (categories 3–6, custom_role/location/url meta) without its markup.
Version: 1.0.0
Requires at least: 6.0
Tested up to: 6.5
Requires PHP: 7.4
License: GNU General Public License v2 or later
License URI: LICENSE
Text Domain: v3dstagram
Tags: custom-logo, custom-menu, featured-images, translation-ready
*/

/* ==========================================================================
   Fonts
   ========================================================================== */

@font-face {
	font-family: "Rubik Mono One";
	src: url("fonts/rubik-mono-one-v14-latin-ext_latin-regular.woff2") format("woff2"),
		url("fonts/rubik-mono-one-v14-latin-ext_latin-regular.woff") format("woff");
	font-weight: 400;
	font-style: normal;
	font-display: swap;
}

@font-face {
	font-family: "Space Mono";
	src: url("fonts/space-mono-v12-latin-ext_latin-regular.woff2") format("woff2"),
		url("fonts/space-mono-v12-latin-ext_latin-regular.woff") format("woff");
	font-weight: 400;
	font-style: normal;
	font-display: swap;
}

@font-face {
	font-family: "Space Mono";
	src: url("fonts/space-mono-v12-latin-ext_latin-700.woff2") format("woff2"),
		url("fonts/space-mono-v12-latin-ext_latin-700.woff") format("woff");
	font-weight: 700;
	font-style: normal;
	font-display: swap;
}

@font-face {
	font-family: "Space Mono";
	src: url("fonts/space-mono-v12-latin-ext_latin-italic.woff2") format("woff2"),
		url("fonts/space-mono-v12-latin-ext_latin-italic.woff") format("woff");
	font-weight: 400;
	font-style: italic;
	font-display: swap;
}

/* ==========================================================================
   Tokens
   ========================================================================== */

:root {
	--v3d-column: 470px;
	--v3d-radius: 4px;
	--v3d-gap: 1.5rem;

	--v3d-ink: #f4f4f2;
	--v3d-ink-dim: #a6a6a2;
	--v3d-ink-faint: #6e6e6a;
	--v3d-surface: rgb(14 14 14 / 82%);
	--v3d-surface-solid: #0e0e0e;
	--v3d-line: rgb(255 255 255 / 14%);
	--v3d-accent: #e8e337;

	--v3d-bg-dim: 0.55;

	--v3d-font: "Space Mono", ui-monospace, SFMono-Regular, Menlo, monospace;
	--v3d-font-display: "Rubik Mono One", "Space Mono", monospace;

	--v3d-ease: cubic-bezier(0.16, 1, 0.3, 1);
}

/* ==========================================================================
   Reset / base
   ========================================================================== */

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

/*
 * The [hidden] attribute is a correctness contract the JS relies on to switch
 * bio languages and show/hide the modal. A plain class selector outranks the
 * UA stylesheet's [hidden] { display: none }, so any component rule that sets
 * display silently defeats it — which is exactly how both bio languages ended
 * up rendering at once. !important is warranted here: it makes the contract
 * hold no matter what is added later.
 */
[hidden] {
	display: none !important;
}

/*
 * WordPress puts a fixed 32px admin bar (46px on small screens) above the page
 * for logged-in users. Everything the theme pins to the top of the viewport has
 * to clear it, or it covers the Edit link. One token, used by the sticky pill
 * bar, the modal and the modal's close button.
 */
.admin-bar {
	--v3d-top-offset: 32px;
}

@media screen and (max-width: 782px) {
	.admin-bar {
		--v3d-top-offset: 46px;
	}
}

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

body {
	margin: 0;
	min-height: 100vh;
	background: var(--v3d-surface-solid);
	color: var(--v3d-ink);
	font-family: var(--v3d-font);
	font-size: 15px;
	line-height: 1.6;
	/* The fixed background video is the page ground; never scroll sideways. */
	overflow-x: hidden;
}

img,
video {
	max-width: 100%;
	height: auto;
	display: block;
}

a {
	color: var(--v3d-ink);
	text-decoration-color: var(--v3d-ink-faint);
	text-underline-offset: 3px;
}

a:hover,
a:focus-visible {
	text-decoration-color: var(--v3d-accent);
}

button {
	font: inherit;
	color: inherit;
	cursor: pointer;
}

:focus-visible {
	outline: 2px solid var(--v3d-accent);
	outline-offset: 2px;
}

.screen-reader-text {
	position: absolute !important;
	width: 1px;
	height: 1px;
	padding: 0;
	margin: -1px;
	overflow: hidden;
	clip: rect(0 0 0 0);
	white-space: nowrap;
	border: 0;
}

.skip-link {
	position: absolute;
	top: -100px;
	left: 8px;
	z-index: 200;
	padding: 0.6rem 1rem;
	background: var(--v3d-surface-solid);
	border: 1px solid var(--v3d-line);
}

.skip-link:focus {
	top: 8px;
	width: auto;
	height: auto;
	clip: auto;
	margin: 0;
	white-space: normal;
}

/* ==========================================================================
   Background video
   ========================================================================== */

.v3d-bg {
	position: fixed;
	inset: 0;
	z-index: -1;
	overflow: hidden;
	background: var(--v3d-surface-solid);
}

.v3d-bg__video {
	width: 100%;
	height: 100%;
	object-fit: cover;
}

.v3d-bg__scrim {
	position: absolute;
	inset: 0;
	background: rgb(8 8 8 / calc(var(--v3d-bg-dim) * 100%));
}

.v3d-bg-toggle {
	position: fixed;
	right: 1rem;
	bottom: 1rem;
	z-index: 60;
	display: grid;
	place-items: center;
	width: 40px;
	height: 40px;
	background: var(--v3d-surface);
	color: var(--v3d-ink);
	border: 1px solid var(--v3d-line);
	border-radius: 50%;
	backdrop-filter: blur(8px);
	transition: opacity 0.2s var(--v3d-ease);
	opacity: 0.55;
}

.v3d-bg-toggle:hover,
.v3d-bg-toggle:focus-visible {
	opacity: 1;
}

/* ==========================================================================
   Layout
   ========================================================================== */

.v3d-site {
	position: relative;
	z-index: 1;
}

.v3d-main {
	padding: 2.5rem 1rem 4rem;
}

.v3d-column {
	width: 100%;
	max-width: var(--v3d-column);
	margin-inline: auto;
}

/* ==========================================================================
   Bio card — the first item in the feed
   ========================================================================== */

.v3d-card--bio {
	position: relative;
	padding: 1.75rem 1.25rem;
	text-align: center;
}

.v3d-profile {
	display: flex;
	flex-direction: column;
	align-items: center;
}

/* A visual continuation cue, not a control; the real cards follow in the DOM. */
.v3d-more-illustration {
	position: absolute;
	left: 50%;
	bottom: 0.65rem;
	display: grid;
	place-items: center;
	width: 2.5rem;
	height: 2.5rem;
	transform: translateX(-50%);
	font-size: 1.15rem;
	color: var(--v3d-accent);
	pointer-events: none;
}

/* One circular portrait: the photo is lifted out of the bio prose so it is
   never shown twice. Falls back to a lettered placeholder. */
.v3d-profile__avatar {
	flex: 0 0 auto;
	width: 160px;
	height: 160px;
	display: grid;
	place-items: center;
	overflow: hidden;
	margin-bottom: 1.1rem;
	border: 1px solid var(--v3d-line);
	border-radius: 50%;
	background: #191919;
}

.v3d-profile__avatar img {
	width: 100%;
	height: 100%;
	object-fit: cover;
}

.v3d-profile__initial {
	font-family: var(--v3d-font-display);
	font-size: 3.4rem;
	color: var(--v3d-accent);
}

.v3d-profile__name {
	margin: 0;
	font-family: var(--v3d-font-display);
	font-size: 1.5rem;
	font-weight: 400;
	line-height: 1.25;
	letter-spacing: -0.01em;
}

.v3d-profile__handle,
.v3d-profile__tagline {
	margin: 0.2rem 0 0;
	font-size: 0.82rem;
	color: var(--v3d-ink-dim);
}

/* Language toggle */

.v3d-lang {
	flex: 0 0 auto;
	display: flex;
	gap: 2px;
	margin-top: 0.9rem;
	border: 1px solid var(--v3d-line);
	border-radius: 999px;
	overflow: hidden;
}

.v3d-lang__btn {
	padding: 0.3rem 0.6rem;
	font-size: 0.7rem;
	letter-spacing: 0.06em;
	background: transparent;
	border: 0;
	color: var(--v3d-ink-dim);
}

.v3d-lang__btn.is-active {
	background: var(--v3d-accent);
	color: #111;
}

/* Bio */

.v3d-profile__bio {
	max-width: 42ch;
	margin-top: 1.1rem;
	font-size: 0.86rem;
	text-align: left;
	color: var(--v3d-ink-dim);
}

.v3d-profile__bio p {
	margin: 0 0 0.6rem;
}

/* Any image still left in the bio prose — the portrait itself is lifted out
   by v3dstagram_get_bio_text() and shown once as the circular avatar. */
.v3d-profile__bio img {
	display: block;
	float: none;
	max-width: 100%;
	margin: 0 auto 1rem;
	border-radius: var(--v3d-radius);
}

.v3d-profile__bio a {
	color: var(--v3d-accent);
}

.v3d-profile__bio a:focus-visible {
	text-decoration: underline;
	text-underline-offset: 3px;
}

/* Icons written into the intro article itself, in front of each link. They are
   decorative — the link text carries the meaning — so they only need to match
   the link colour and hold a little space. */
.v3d-profile__bio i {
	margin-right: 0.1em;
	color: var(--v3d-accent);
	font-style: normal;
}

/*
 * Keeps an icon glued to the link it belongs to.
 *
 * &nbsp; between the two is not enough on its own: Font Awesome sets
 * .fa-solid { display: inline-block }, and a line may break immediately
 * *before* an atomic inline-block — at the ordinary space in front of the
 * icon, which the article cannot control. Wrapping the pair is what actually
 * holds; measured over 231 widths, this drops orphaned icons from 176 to 0.
 *
 * The span still wraps as a unit, so a narrow column pushes icon and link to
 * the next line together rather than overflowing.
 */
.v3d-profile__bio .v3d-nb {
	white-space: nowrap;
}

/*
 * The Pivilion mark, which has no Font Awesome equivalent.
 *
 * wp_kses_post() strips <svg> from post content, so the article can only carry
 * an <i class="fa-pivilion">; the artwork has to arrive from CSS. The original
 * Sketch logo is a wireframe whose open paths cannot produce a solid icon, so
 * these three closed facets preserve its isometric silhouette at Font Awesome
 * scale. The accent colour is baked in as %23e8e337 — a data URI cannot read a
 * custom property, and a literal # would terminate the URL.
 *
 * Scoped to .v3d-profile__bio deliberately: fa-pivilion is not a real Font
 * Awesome class and has no business in the global icon namespace.
 */
.v3d-profile__bio .fa-pivilion {
	display: inline-block;
	/* Matches the original mark's measured 60.48 : 46.31 aspect. */
	width: 1.31em;
	height: 1em;
	vertical-align: -0.125em;
	background: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 60 46' fill='%23e8e337'><polygon points='30,0 60,17 30,34 0,17'/><polygon points='0,20 27,36 15,45 0,36'/><polygon points='60,20 60,36 45,45 33,36'/></svg>")
		no-repeat center / contain;
}

/* ==========================================================================
   Filter pills
   ========================================================================== */

.v3d-pills {
	/* Stays reachable while scrolling a full-height feed. */
	position: sticky;
	top: var(--v3d-top-offset, 0px);
	z-index: 20;
	padding: 0.75rem 1rem;
	margin-bottom: 1.25rem;
	background: rgb(14 14 14 / 72%);
	backdrop-filter: blur(14px);
	/* Pills scroll inside their own rail; the page never scrolls sideways. */
	overflow-x: auto;
	scrollbar-width: none;
	-ms-overflow-style: none;
}

.v3d-pills::-webkit-scrollbar {
	display: none;
}

.v3d-pills__list {
	display: flex;
	gap: 0.5rem;
	padding: 0;
	margin: 0;
	list-style: none;
	width: max-content;
	min-width: 100%;
}

.v3d-pill {
	display: inline-block;
	padding: 0.35rem 0.9rem;
	font-size: 0.76rem;
	letter-spacing: 0.04em;
	text-transform: uppercase;
	text-decoration: none;
	white-space: nowrap;
	color: var(--v3d-ink-dim);
	background: var(--v3d-surface);
	border: 1px solid var(--v3d-line);
	border-radius: 999px;
	backdrop-filter: blur(10px);
	transition: color 0.15s var(--v3d-ease), background-color 0.15s var(--v3d-ease);
}

.v3d-pill:hover {
	color: var(--v3d-ink);
}

.v3d-pill.is-active {
	background: var(--v3d-accent);
	border-color: var(--v3d-accent);
	color: #111;
}

.v3d-pill i {
	margin-right: 0.35rem;
}

.v3d-pill__count {
	margin-left: 0.4rem;
	opacity: 0.6;
	font-size: 0.9em;
}

/* A destination, not a filter — outlined in the accent so it reads apart. */
.v3d-pill--cv {
	border-color: var(--v3d-accent);
	color: var(--v3d-accent);
}

.v3d-pill--cv:hover,
.v3d-pill--cv:focus-visible {
	background: var(--v3d-accent);
	color: #111;
}

/* ==========================================================================
   Feed cards
   ========================================================================== */

.v3d-feed {
	display: flex;
	flex-direction: column;
	gap: var(--v3d-gap);
}

.v3d-feed__items {
	display: flex;
	flex-direction: column;
	gap: var(--v3d-gap);
}

/*
 * Reels-style scrolling: one card, one screen, and the scroll stops on each.
 *
 * scroll-snap-stop: always is the part that produces "stops on every card" —
 * without it a firm flick sails past several, which matters most on a
 * touchscreen. mandatory + a full-height card means nothing else is on screen
 * to compete with the current item.
 *
 * Measured before committing to this. Desktop: a 4:5 image at 470px column
 * width needs 587px of height, and a full-height card leaves 772px at
 * 1440x900, 592px at 1280x720. Mobile full-bleed at 390px wide needs 487px,
 * and the budget is 696px at full dvh, 582px with Safari chrome showing, 519px
 * on an iPhone SE. It fits everywhere; the max-height guard only engages on
 * unusually short windows.
 *
 * dvh (with a vh fallback declared first) is what keeps this stable on phones:
 * it tracks the *dynamic* viewport, so a card does not resize mid-gesture as
 * the address bar hides and reveals.
 *
 * NOT gated on prefers-reduced-motion. It was, and that turned out to disable
 * the entire feature on Android phones with "Remove animations" enabled —
 * which MIUI/HyperOS switches on with battery saver, so the layout silently
 * collapsed to a plain scrolling feed on a very common configuration.
 *
 * The layout is the design; only the *animation* is motion. Reduced-motion
 * visitors get the same full-screen cards, landing instantly rather than
 * gliding, via the scroll-behavior: auto in the reduce block further down.
 *
 * Excluded on the CV, which is a document rather than a feed.
 */
html:not(.v3d-no-snap) {
	scroll-snap-type: y mandatory;
	/*
	 * Keeps a snapped card clear of the sticky pill bar. feed.js measures the
	 * bar and publishes --v3d-pills-h; the fallback covers no-JS and the
	 * templates that have no pill bar at all.
	 */
	scroll-padding-top: var(--v3d-pills-h, 57px);
}

body:not(.v3d-cv) .v3d-feed,
body:not(.v3d-cv) .v3d-feed__items {
	gap: 0;
}

body:not(.v3d-cv) .v3d-card {
	/*
	 * Height is one viewport MINUS the sticky pill bar. A full 100dvh card
	 * would always have its last rows hidden behind that bar, so it could
	 * never sit flush on screen.
	 *
	 * align:start, not center: with center the browser splits any
	 * scroll-margin across both ends, which parked every card exactly half a
	 * margin (24px) low with its bottom edge off screen.
	 */
	/* Room for the title/meta row beneath the media. */
	--v3d-card-reserve: 4rem;
	min-height: calc(100vh - var(--v3d-pills-h, 57px));
	min-height: calc(100dvh - var(--v3d-pills-h, 57px));
	display: flex;
	flex-direction: column;
	justify-content: center;
	scroll-snap-align: start;
	scroll-snap-stop: always;
}

body:not(.v3d-cv) .v3d-card__media {
	max-height: calc(100vh - var(--v3d-pills-h, 57px) - var(--v3d-card-reserve));
	max-height: calc(100dvh - var(--v3d-pills-h, 57px) - var(--v3d-card-reserve));
}

/* Desktop-only decoration: full-height cards butt against one another, so the
   card frame would double up against the media's own. */
@media (min-width: 768px) {
	body:not(.v3d-cv) .v3d-card {
		/* Taller title/meta row at this width. The pill bar is handled by
		   scroll-padding-top, not a per-card scroll margin. */
		--v3d-card-reserve: 6rem;
		border: 0;
		border-radius: 0;
		background: none;
		backdrop-filter: none;
	}

	.v3d-card__media {
		border: 1px solid var(--v3d-line);
		/* Square at the bottom: the body below carries the closing corners, so
		   the pair reads as one rounded rectangle instead of two stacked boxes. */
		border-radius: var(--v3d-radius) var(--v3d-radius) 0 0;
	}

	/* The card itself stays unframed (see above), so the body carries the
	   surface that keeps the title and meta legible over the background video
	   — the same material the bio card uses. border-top is dropped so the
	   media's own bottom edge is not drawn twice. */
	body:not(.v3d-cv) .v3d-card__body {
		background: var(--v3d-surface);
		border-right: 1px solid var(--v3d-line);
		border-bottom: 1px solid var(--v3d-line);
		border-left: 1px solid var(--v3d-line);
		border-radius: 0 0 var(--v3d-radius) var(--v3d-radius);
		backdrop-filter: blur(14px);
	}

	/* The bio has no media box to carry the frame, so it keeps its own. */
	.v3d-card--bio {
		justify-content: center;
		/* The frame is on .v3d-profile at this width, so the card's own
		   horizontal padding would inset it and leave the bio narrower than
		   every other card. The profile supplies its own inner padding. */
		padding-inline: 0;
	}

	.v3d-card--bio .v3d-profile {
		padding: 2rem 1.5rem;
		border: 1px solid var(--v3d-line);
		border-radius: var(--v3d-radius);
		background: var(--v3d-surface);
		backdrop-filter: blur(14px);
	}
}

.v3d-card {
	background: var(--v3d-surface);
	border: 1px solid var(--v3d-line);
	border-radius: var(--v3d-radius);
	overflow: hidden;
	backdrop-filter: blur(14px);
}

.v3d-card a {
	cursor: url("res/cursor.png"), pointer;
}

.v3d-card__media {
	position: relative;
	display: block;
	/* The 4:5 box is reserved before media loads, so the feed never jumps. */
	aspect-ratio: 4 / 5;
	background: #151515;
	overflow: hidden;
}

.v3d-media {
	width: 100%;
	height: 100%;
	object-fit: cover;
}

/* Generated card for posts with neither an image nor a video. */
.v3d-media--text {
	display: flex;
	flex-direction: column;
	justify-content: flex-end;
	gap: 0.5rem;
	padding: 1.5rem;
	background:
		linear-gradient(
			145deg,
			hsl(var(--v3d-card-hue, 0) 40% 16%),
			hsl(calc(var(--v3d-card-hue, 0) + 40) 30% 8%)
		);
}

.v3d-media__text {
	font-family: var(--v3d-font-display);
	font-size: clamp(1.1rem, 4.5vw, 1.6rem);
	line-height: 1.25;
	color: var(--v3d-ink);
	/* Long titles must not spill out of the fixed-ratio box. */
	overflow-wrap: anywhere;
}

.v3d-media__role {
	font-size: 0.72rem;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	color: var(--v3d-accent);
}

.v3d-card__badge {
	position: absolute;
	top: 0.75rem;
	right: 0.75rem;
	display: grid;
	place-items: center;
	width: 28px;
	height: 28px;
	font-size: 0.7rem;
	color: #fff;
	background: rgb(0 0 0 / 55%);
	border-radius: 50%;
	backdrop-filter: blur(4px);
}

.v3d-card__body {
	padding: 0.9rem 1rem 1.1rem;
}

.v3d-card__title {
	margin: 0;
	font-family: var(--v3d-font-display);
	font-size: 0.95rem;
	font-weight: 400;
	line-height: 1.35;
	letter-spacing: -0.01em;
}

.v3d-card__title a {
	text-decoration: none;
}

.v3d-card__meta {
	margin: 0.35rem 0 0;
	font-size: 0.76rem;
	color: var(--v3d-ink-dim);
}

.v3d-card__role i {
	margin-right: 0.3rem;
	color: var(--v3d-accent);
}

.v3d-sep {
	color: var(--v3d-ink-faint);
}

.v3d-card__link {
	margin-left: 0.35rem;
	color: var(--v3d-ink-dim);
	text-decoration: none;
}

.v3d-card__link:hover {
	color: var(--v3d-accent);
}

.v3d-empty {
	padding: 3rem 1rem;
	text-align: center;
	color: var(--v3d-ink-dim);
}

/* Only ever rendered for users who can edit the post. */
.v3d-card__edit,
.v3d-item__edit {
	margin: 0.5rem 0 0;
	font-size: 0.72rem;
	letter-spacing: 0.05em;
	text-transform: uppercase;
}

.v3d-card__edit a,
.v3d-item__edit a {
	display: inline-flex;
	align-items: center;
	gap: 0.35rem;
	text-decoration: none;
	color: var(--v3d-accent);
}

.v3d-item__edit a:hover {
	text-decoration: underline;
}

/* ==========================================================================
   Feed status / pagination / sentinel
   ========================================================================== */

.v3d-feed__status {
	padding: 1.25rem 0;
	font-size: 0.78rem;
	text-align: center;
	color: var(--v3d-ink-faint);
}

.v3d-pagination {
	padding: 1rem 0;
	text-align: center;
	font-size: 0.8rem;
}

.v3d-pagination .page-numbers {
	display: inline-block;
	padding: 0.3rem 0.6rem;
	text-decoration: none;
	color: var(--v3d-ink-dim);
}

.v3d-pagination .page-numbers.current {
	color: var(--v3d-accent);
}

.v3d-sentinel {
	height: 1px;
}

/* ==========================================================================
   Expanded item (modal body and single.php share this)
   ========================================================================== */

.v3d-item {
	display: grid;
	grid-template-columns: 1fr;
	background: var(--v3d-surface);
	border: 1px solid var(--v3d-line);
	border-radius: var(--v3d-radius);
	overflow: hidden;
}

.v3d-item__media {
	background: #101010;
	display: grid;
	place-items: center;
	/* Uncropped in the expanded view: never cut the work off. */
	max-height: 80vh;
}

.v3d-item__media .v3d-media {
	width: auto;
	max-width: 100%;
	max-height: 80vh;
	object-fit: contain;
}

.v3d-item__media .v3d-media--text {
	width: 100%;
	aspect-ratio: 4 / 5;
	max-height: 60vh;
}

.v3d-item__panel {
	padding: 1.5rem;
}

.v3d-item__title {
	margin: 0;
	font-family: var(--v3d-font-display);
	font-size: clamp(1.2rem, 2.6vw, 1.9rem);
	font-weight: 400;
	line-height: 1.2;
	letter-spacing: -0.02em;
}

.v3d-item__meta {
	display: flex;
	flex-wrap: wrap;
	gap: 0.75rem;
	margin: 0.6rem 0 1.25rem;
	font-size: 0.78rem;
	letter-spacing: 0.04em;
	text-transform: uppercase;
	color: var(--v3d-ink-dim);
}

.v3d-item__role i {
	margin-right: 0.3rem;
	color: var(--v3d-accent);
}

.v3d-item__content {
	font-size: 0.92rem;
	color: var(--v3d-ink-dim);
}

.v3d-item__content a {
	color: var(--v3d-ink);
}

.v3d-item__content img {
	border-radius: var(--v3d-radius);
	margin: 1rem 0;
}

.v3d-item__details {
	display: grid;
	gap: 0.4rem;
	padding-top: 1rem;
	margin: 1.5rem 0 0;
	border-top: 1px solid var(--v3d-line);
	font-size: 0.8rem;
}

.v3d-item__row {
	display: grid;
	grid-template-columns: 8rem 1fr;
	gap: 0.5rem;
}

.v3d-item__row dt {
	color: var(--v3d-ink-faint);
	text-transform: uppercase;
	letter-spacing: 0.05em;
	font-size: 0.72rem;
}

.v3d-item__row dd {
	margin: 0;
	overflow-wrap: anywhere;
}

.v3d-item__footer {
	margin-top: 1.25rem;
	font-size: 0.75rem;
	color: var(--v3d-ink-faint);
}

.v3d-item__footer a {
	color: var(--v3d-ink-dim);
}

/* single.php chrome */

.v3d-main--full {
	padding-inline: 0;
}

.v3d-item-wrap {
	width: 100%;
	max-width: 1400px;
	margin-inline: auto;
	padding-inline: 1rem;
}

.v3d-back {
	display: inline-flex;
	align-items: center;
	gap: 0.5rem;
	margin-bottom: 1.25rem;
	font-size: 0.8rem;
	letter-spacing: 0.05em;
	text-transform: uppercase;
	text-decoration: none;
	color: var(--v3d-ink-dim);
}

.v3d-back:hover {
	color: var(--v3d-accent);
}

.v3d-adjacent {
	display: flex;
	justify-content: space-between;
	gap: 1rem;
	padding: 1.5rem 0;
	font-size: 0.8rem;
}

.v3d-adjacent a {
	color: var(--v3d-ink-dim);
	text-decoration: none;
}

.v3d-adjacent a:hover {
	color: var(--v3d-accent);
}

/* ==========================================================================
   Modal
   ========================================================================== */

.v3d-modal {
	position: fixed;
	/* Starts below the admin bar so Edit stays reachable while it is open. */
	inset: var(--v3d-top-offset, 0px) 0 0 0;
	z-index: 100;
	display: grid;
	place-items: center;
	padding: 2rem 1rem;
	background: rgb(6 6 6 / 88%);
	backdrop-filter: blur(10px);
	overflow-y: auto;
	overscroll-behavior: contain;
	animation: v3d-fade 0.2s var(--v3d-ease);
}

.v3d-modal[hidden] {
	display: none;
}

@keyframes v3d-fade {
	from {
		opacity: 0;
	}
}

.v3d-modal__inner {
	width: 100%;
	/* This is the "full desktop width" the feed column deliberately is not. */
	max-width: 1500px;
	margin: auto;
}

.v3d-modal__inner:focus {
	outline: none;
}

.v3d-modal__close {
	position: fixed;
	top: calc(var(--v3d-top-offset, 0px) + 1rem);
	right: 1rem;
	z-index: 110;
	display: grid;
	place-items: center;
	width: 42px;
	height: 42px;
	font-size: 1.1rem;
	background: var(--v3d-surface);
	color: var(--v3d-ink);
	border: 1px solid var(--v3d-line);
	border-radius: 50%;
}

.v3d-modal__close:hover {
	border-color: var(--v3d-accent);
	color: var(--v3d-accent);
}

.v3d-modal__loading,
.v3d-modal__error {
	padding: 4rem 1rem;
	text-align: center;
	color: var(--v3d-ink-dim);
}

/* Prevent the page behind the modal from scrolling. */
body.v3d-modal-open {
	overflow: hidden;
}

/* Wide screens: media beside the text, both inside a full-width modal. */
@media (min-width: 900px) {
	.v3d-modal .v3d-item {
		grid-template-columns: minmax(0, 1.6fr) minmax(340px, 0.9fr);
	}

	.v3d-modal .v3d-item__media {
		max-height: 88vh;
	}

	.v3d-modal .v3d-item__media .v3d-media {
		max-height: 88vh;
	}

	.v3d-modal .v3d-item__panel {
		max-height: 88vh;
		overflow-y: auto;
		padding: 2rem;
	}

	.is-item-full .v3d-item {
		grid-template-columns: minmax(0, 1.6fr) minmax(340px, 0.9fr);
	}
}

/* ==========================================================================
   Pages, archives, 404, comments
   ========================================================================== */

.v3d-archive-header {
	margin-bottom: 1.25rem;
}

.v3d-archive-title {
	margin: 0;
	font-family: var(--v3d-font-display);
	font-size: 1.2rem;
	font-weight: 400;
}

.v3d-archive-desc {
	margin-top: 0.4rem;
	font-size: 0.85rem;
	color: var(--v3d-ink-dim);
}

.v3d-page {
	padding: 1.5rem;
	background: var(--v3d-surface);
	border: 1px solid var(--v3d-line);
	border-radius: var(--v3d-radius);
	backdrop-filter: blur(14px);
}

.v3d-page__title {
	margin: 0 0 1rem;
	font-family: var(--v3d-font-display);
	font-size: 1.4rem;
	font-weight: 400;
	line-height: 1.25;
}

.v3d-page__content {
	font-size: 0.92rem;
	color: var(--v3d-ink-dim);
}

.v3d-page__thumb {
	margin-bottom: 1.25rem;
}

.v3d-404 {
	padding: 4rem 1rem;
	text-align: center;
}

.v3d-404__code {
	margin: 0;
	font-family: var(--v3d-font-display);
	font-size: clamp(3rem, 14vw, 6rem);
	font-weight: 400;
	color: var(--v3d-accent);
}

.v3d-404__text {
	margin: 0.5rem 0 1.5rem;
	color: var(--v3d-ink-dim);
}

.v3d-comments {
	padding: 1.5rem 0;
	font-size: 0.88rem;
}

.v3d-comments__title {
	font-family: var(--v3d-font-display);
	font-size: 1rem;
	font-weight: 400;
}

.v3d-comments__list {
	padding-left: 1rem;
	list-style: none;
}

.v3d-comments input,
.v3d-comments textarea {
	width: 100%;
	max-width: 100%;
	padding: 0.5rem;
	font: inherit;
	color: var(--v3d-ink);
	background: #161616;
	border: 1px solid var(--v3d-line);
	border-radius: var(--v3d-radius);
}

/* ==========================================================================
   CV — a document, not a feed
   ========================================================================== */

.v3d-main--cv {
	padding: 2rem 1rem 4rem;
}

.v3d-cv-doc {
	width: 100%;
	max-width: 820px;
	margin-inline: auto;
	padding: 2rem;
	background: var(--v3d-surface);
	border: 1px solid var(--v3d-line);
	border-radius: var(--v3d-radius);
	backdrop-filter: blur(14px);
}

.v3d-cv__header {
	padding-bottom: 1.25rem;
	margin-bottom: 1.75rem;
	border-bottom: 1px solid var(--v3d-line);
}

.v3d-cv__name {
	margin: 0;
	font-family: var(--v3d-font-display);
	font-size: clamp(1.4rem, 4vw, 2.1rem);
	font-weight: 400;
	line-height: 1.15;
	letter-spacing: -0.02em;
}

.v3d-cv__tagline {
	margin: 0.4rem 0 0;
	font-size: 0.9rem;
	color: var(--v3d-ink-dim);
}

.v3d-cv__lang {
	width: fit-content;
}

.v3d-cv__actions {
	display: flex;
	flex-wrap: wrap;
	gap: 1rem;
	margin-top: 1.25rem;
	font-size: 0.78rem;
	letter-spacing: 0.05em;
	text-transform: uppercase;
}

.v3d-cv__back,
.v3d-cv__print {
	display: inline-flex;
	align-items: center;
	gap: 0.45rem;
	padding: 0;
	font: inherit;
	letter-spacing: inherit;
	text-transform: inherit;
	text-decoration: none;
	background: none;
	border: 0;
	color: var(--v3d-ink-dim);
}

.v3d-cv__back:hover,
.v3d-cv__print:hover {
	color: var(--v3d-accent);
}

.v3d-cv__section {
	margin-bottom: 2rem;
}

.v3d-cv__heading {
	display: flex;
	align-items: baseline;
	gap: 0.5rem;
	margin: 0 0 0.9rem;
	font-family: var(--v3d-font-display);
	font-size: 0.95rem;
	font-weight: 400;
	letter-spacing: 0.02em;
	text-transform: uppercase;
}

.v3d-cv__heading i {
	color: var(--v3d-accent);
	font-size: 0.85em;
}

.v3d-cv__count {
	font-family: var(--v3d-font);
	font-size: 0.75rem;
	color: var(--v3d-ink-faint);
}

.v3d-cv__prose {
	font-size: 0.9rem;
	color: var(--v3d-ink-dim);
}

.v3d-cv__prose img {
	max-width: 200px;
	border-radius: var(--v3d-radius);
}

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

.v3d-cv__entry {
	display: grid;
	grid-template-columns: 1fr auto;
	gap: 0 1rem;
	padding: 0.55rem 0;
	border-bottom: 1px solid rgb(255 255 255 / 6%);
	font-size: 0.86rem;
}

.v3d-cv__title a {
	text-decoration: none;
	color: var(--v3d-ink);
}

.v3d-cv__title a:hover {
	text-decoration: underline;
	text-decoration-color: var(--v3d-accent);
}

.v3d-cv__year {
	grid-column: 2;
	grid-row: 1;
	color: var(--v3d-ink-faint);
	font-variant-numeric: tabular-nums;
}

.v3d-cv__detail {
	grid-column: 1;
	font-size: 0.78rem;
	color: var(--v3d-ink-dim);
}

.v3d-cv__link {
	grid-column: 1 / -1;
	font-size: 0.74rem;
	color: var(--v3d-ink-faint);
	overflow-wrap: anywhere;
}

.v3d-footer {
	padding: 2rem 1rem 3rem;
	text-align: center;
	font-size: 0.72rem;
	color: var(--v3d-ink-faint);
}

.v3d-footer__text {
	margin: 0;
}

/* ==========================================================================
   Responsive
   ========================================================================== */

@media (max-width: 767px) {
	.v3d-main {
		padding: 1rem 0 3rem;
	}

	/* Full-bleed feed on phones, the way Instagram does it. */
	.v3d-column {
		max-width: none;
	}

	.v3d-card--bio,
	.v3d-card {
		border-radius: 0;
		border-inline: 0;
	}

	.v3d-item-wrap {
		padding-inline: 0;
	}

	.v3d-back {
		margin: 0 1rem 1rem;
	}

	.v3d-modal {
		padding: 0;
	}

	.v3d-modal__inner {
		padding-top: 3.5rem;
	}

	.v3d-item {
		border-radius: 0;
		border-inline: 0;
	}

	.v3d-item__row {
		grid-template-columns: 1fr;
		gap: 0;
	}

	/* The background video is not loaded at this width; hide the control. */
	.v3d-bg-toggle {
		display: none;
	}
}

@media (prefers-reduced-motion: reduce) {
	*,
	*::before,
	*::after {
		animation-duration: 0.001ms !important;
		animation-iteration-count: 1 !important;
		transition-duration: 0.001ms !important;
		scroll-behavior: auto !important;
	}

	.v3d-bg-toggle {
		display: none;
	}
}

@media print {
	.v3d-bg,
	.v3d-bg-toggle,
	.v3d-more-illustration,
	.v3d-pills,
	.v3d-modal,
	.v3d-pagination,
	.v3d-footer {
		display: none !important;
	}

	body {
		background: #fff;
		color: #000;
	}

	.v3d-card,
	.v3d-item,
	.v3d-profile {
		border: 1px solid #ccc;
		background: none;
		backdrop-filter: none;
	}

	/* The CV is the page people actually print — save-as-PDF is a first-class
	   action on it, so it gets a proper document treatment. */
	.v3d-cv__actions,
	.v3d-cv__lang,
	.v3d-cv__back,
	.v3d-cv__print,
	.v3d-card__edit,
	.v3d-item__edit {
		display: none !important;
	}

	@page {
		margin: 14mm;
	}

	.v3d-main--cv {
		padding: 0;
	}

	.v3d-cv-doc {
		max-width: none;
		padding: 0;
		border: 0;
		background: none;
		backdrop-filter: none;
	}

	.v3d-cv__name,
	.v3d-cv__heading,
	.v3d-cv__title a {
		color: #000;
	}

	.v3d-cv__tagline,
	.v3d-cv__detail,
	.v3d-cv__year,
	.v3d-cv__count,
	.v3d-cv__prose {
		color: #333;
	}

	.v3d-cv__link {
		color: #555;
	}

	.v3d-cv__heading i {
		color: #000;
	}

	/* Never split an entry, or a heading from the list it introduces. */
	.v3d-cv__entry {
		break-inside: avoid;
		border-bottom: 1px solid #ddd;
	}

	.v3d-cv__heading {
		break-after: avoid;
	}

	.v3d-cv__section {
		break-inside: auto;
	}

	.v3d-cv__prose img {
		max-width: 140px;
	}
}
