/* ryong — public site. One typeface (Geist), true black, hairlines. */

:root {
	--ink: #FCFDFF;
	--body: rgba(252, 253, 255, 0.86);
	--soft: rgba(252, 253, 255, 0.7);
	--mute: #A1A4A5;
	--line: rgba(255, 255, 255, 0.08);
	--line-strong: rgba(255, 255, 255, 0.14);
	--pad: 40px;
	--safe-l: env(safe-area-inset-left, 0px);
	--safe-r: env(safe-area-inset-right, 0px);
	--safe-b: env(safe-area-inset-bottom, 0px);
}

*, *::before, *::after { box-sizing: border-box; }
html { background: #000; scroll-behavior: smooth; -webkit-text-size-adjust: 100%; scrollbar-gutter: stable; }
/* The site is dark, so are its scrollbars: a slim grey bar on black instead of the browser's light default. */
:root { color-scheme: dark; }
html { scrollbar-color: #3a3a3a #000; }
/* Landing on a place in a page (…/#works) goes straight there; smooth scrolling is for links within a page. */
html.no-smooth { scroll-behavior: auto; }
/* Work pages: a sideways trackpad swipe moves between works (site.js), not Back in the browser. */
html:has(.detail) { overscroll-behavior-x: none; }
body {
	margin: 0;
	background: #000;
	color: var(--ink);
	font-family: 'Geist', 'Pretendard Variable', Pretendard, -apple-system, BlinkMacSystemFont, sans-serif;
	font-size: 14px;
	font-weight: 400;
	line-height: 1.5;
	-webkit-font-smoothing: antialiased;
}
img { max-width: 100%; height: auto; display: block; }
a { color: var(--ink); text-decoration: none; }
a:hover { color: #fff; }
h1, h2, p { margin: 0; }
button { font-family: inherit; -webkit-appearance: none; appearance: none; border-radius: 0; background: none; border: 0; color: inherit; padding: 0; }
:focus-visible { outline: 2px solid var(--ink); outline-offset: 3px; }
/* Focus moved by the full-screen viewer only shows a ring when the keyboard is in use (see site.js). */
html:not(.kbd) .lightbox :focus-visible, html:not(.kbd) .zoom:focus-visible { outline: none; }
.wrap { max-width: 1680px; margin: 0 auto; padding-left: calc(var(--pad) + var(--safe-l)); padding-right: calc(var(--pad) + var(--safe-r)); }

/* Header */
.site-header { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 16px; padding: 28px calc(var(--pad) + var(--safe-r)) 28px calc(var(--pad) + var(--safe-l)); max-width: 1680px; margin: 0 auto; }
.site-header--hero { position: absolute; top: 0; left: 0; right: 0; z-index: 3; max-width: none; }
/* Menu that slides back in when you scroll up through the works, and hides again when you scroll down. */
.site-header--float { position: fixed; top: 0; left: 0; right: 0; z-index: 50; max-width: none; padding-top: calc(14px + env(safe-area-inset-top, 0px)); padding-bottom: 14px;
	background: rgba(0, 0, 0, 0.82); -webkit-backdrop-filter: blur(14px); backdrop-filter: blur(14px); border-bottom: 1px solid var(--line);
	transform: translateY(-101%); transition: transform 0.32s cubic-bezier(0.2, 0.7, 0.2, 1); }
.site-header--float.is-shown { transform: none; }
@media (prefers-reduced-motion: reduce) { .site-header--float { transition: none; } }
.site-logo { display: inline-flex; padding: 4px 0; color: var(--ink); }
.site-nav { display: flex; gap: 28px; font-size: 14px; }
.site-nav a { padding: 12px 0; color: var(--soft); }
.site-nav a[aria-current="page"], .site-nav a:hover { color: var(--ink); }

/* Intro (first visit per session only — see the inline script in functions.php) */
.intro { display: none; }
.show-intro .intro {
	position: fixed; inset: 0; z-index: 50; background: #000;
	display: flex; align-items: center; justify-content: center; pointer-events: none;
	animation: introOut 0.8s cubic-bezier(0.7, 0, 0.3, 1) 2.1s forwards;
}
@keyframes introOut { to { opacity: 0; visibility: hidden; } }
/* Skipped with a tap, key or scroll: fade out at once, and bring the rest in without waiting. */
.show-intro.intro-skip .intro { animation: introOut 0.35s ease forwards; }
.show-intro.intro-skip .hero-media { animation-delay: 0s; }
.show-intro.intro-skip .fade { animation-delay: 0.15s; }
.intro .mk { opacity: 0; transform-box: fill-box; transform-origin: center; animation: pop 0.7s cubic-bezier(0.2, 0.8, 0.2, 1) forwards; }
.intro .mk1 { animation-delay: 0.15s; }
.intro .mk2 { animation-delay: 0.4s; }
.intro .mk3 { animation-delay: 0.65s; }
.intro .mk4 { opacity: 0; animation: slash 0.6s cubic-bezier(0.2, 0.8, 0.2, 1) 0.95s forwards; }
@keyframes pop { from { opacity: 0; transform: scale(0.3); } to { opacity: 1; transform: scale(1); } }
@keyframes slash { from { opacity: 0; transform: translate(-10px, -10px); } to { opacity: 1; transform: none; } }

/* Hero */
.hero { position: relative; height: 100vh; height: 100svh; min-height: 560px; max-height: 1100px; overflow: hidden; background: #000; }
.hero-media { position: absolute; inset: 0; transform: scale(1.06); animation: settle 3.2s cubic-bezier(0.2, 0.7, 0.2, 1) 0.2s forwards; }
.show-intro .hero-media { animation-delay: 2.1s; }
@keyframes settle { to { transform: scale(1); } }
.hero .slide { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; object-position: 50% 35%; opacity: 0; transition: opacity 1.6s ease; }
.hero .slide.is-active { opacity: 1; }
/* Video slides: the cover shows first; the muted player fades in once it is actually playing. */
.slide-video { overflow: hidden; }
.slide-video .cover { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; object-position: 50% 40%; }
.slide-video .yt-holder { position: absolute; inset: 0; container-type: size; opacity: 0; transition: opacity 1.2s ease; pointer-events: none; }
.slide-video.is-playing .yt-holder { opacity: 1; }
.slide-video iframe { position: absolute; top: 50%; left: 50%; width: max(100cqw, 177.78cqh); height: max(100cqh, 56.25cqw); transform: translate(-50%, -50%); border: 0; }
.hero-shade { position: absolute; inset: 0; pointer-events: none; background: linear-gradient(to bottom, rgba(0, 0, 0, 0.4) 0%, rgba(0, 0, 0, 0) 20%), linear-gradient(to top, rgba(0, 0, 0, 0.6) 0%, rgba(0, 0, 0, 0) 30%); }
.fade { opacity: 0; animation: fadeIn 1s ease 0.6s forwards; }
.show-intro .fade { animation-delay: 2.6s; }
@keyframes fadeIn { to { opacity: 1; } }

.hero-info { position: absolute; left: 0; bottom: 0; z-index: 2; width: 240px; padding: 0 0 22px calc(var(--pad) + var(--safe-l)); display: flex; flex-direction: column; }
/* The caption may be wider than the progress bars (which keep their fixed width), but stays clear of
   the "Scroll" cue on the right. Title first, then categories · year in grey. */
.hero-cap { display: flex; flex-direction: column; gap: 2px; width: max-content; max-width: min(520px, calc(100vw - 2 * var(--pad) - 120px)); min-height: 20px; margin-bottom: 6px; }
.hero-cap span { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.hero-cap .hc-t { font-size: 14px; color: var(--ink); }
.hero-cap .hc-t { white-space: normal; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; line-clamp: 2; line-height: 1.4; } /* a long title gets a second line before it is cut */
.hero-cap .hc-m { font-size: 12px; color: var(--soft); }
.hero-bars { display: flex; gap: 6px; }
.hero-bars.is-many { gap: 3px; } /* same total width, more works: just tighter gaps */
.seg { position: relative; flex: 1; min-height: 32px; padding: 0; border: 0; background: none; cursor: pointer; display: flex; align-items: center; }
/* Bigger touch area than the thin line it looks like: 44px tall, reaching into the gaps on both sides. */
.seg::before { content: ""; position: absolute; left: -3px; right: -3px; top: 50%; height: 44px; margin-top: -22px; }
.hero-bars.is-many .seg::before { left: -1.5px; right: -1.5px; }
.seg .track { display: block; width: 100%; height: 1px; background: rgba(255, 255, 255, 0.25); overflow: hidden; }
@media (hover: hover) { .seg:hover .track { background: rgba(255, 255, 255, 0.5); } }
.seg .bar { display: block; height: 1px; background: var(--ink); transform: scaleX(0); transform-origin: left; }
.seg .bar.done { transform: scaleX(1); }
.seg .bar.on { animation: fill 6s linear forwards; }
@keyframes fill { to { transform: scaleX(1); } }

.scroll-cue { position: absolute; right: calc(32px + var(--safe-r)); bottom: 32px; z-index: 2; display: flex; flex-direction: column; align-items: center; gap: 10px; padding: 8px; color: var(--soft); font-size: 12px; }
.scroll-cue .line { display: block; width: 1px; height: 48px; background: rgba(255, 255, 255, 0.2); overflow: hidden; }
.scroll-cue .cue { display: block; width: 1px; height: 48px; background: var(--ink); animation: cue 2.2s ease-in-out infinite; }
@keyframes cue {
	0% { transform: scaleY(0); transform-origin: top; }
	45% { transform: scaleY(1); transform-origin: top; }
	55% { transform: scaleY(1); transform-origin: bottom; }
	100% { transform: scaleY(0); transform-origin: bottom; }
}

/* Works */
.works-head { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 20px; padding-top: 96px; padding-bottom: 28px; scroll-margin-top: 0; }
.works-head h2 { font-size: 20px; font-weight: 500; }
.filters { display: flex; flex-wrap: wrap; gap: 8px; }
.pill { display: inline-flex; align-items: center; gap: 8px; min-height: 44px; padding: 0 16px; border-radius: 9999px; border: 1px solid var(--line-strong); background: transparent; color: var(--body); font-size: 13px; cursor: pointer; transition: background 0.2s, color 0.2s, border-color 0.2s; }
.pill span { font-size: 12px; color: var(--mute); }
@media (hover: hover) { .pill:hover { border-color: rgba(255, 255, 255, 0.4); } }
.pill[aria-pressed="true"] { background: var(--ink); border-color: var(--ink); color: #000; }
.pill[aria-pressed="true"] span { color: #555; }

.works { padding-bottom: 140px; }
.grid { column-count: 3; column-gap: 28px; padding-top: 28px; border-top: 1px solid var(--line); }
/* With JS: same masonry look, but works fill left → right, row by row (newest at the top).
   Each work goes into the currently shortest column. Without JS the CSS columns above still work. */
/* Placed by site.js: each work at its own spot (see "Works grid"). */
.grid.is-placed { column-count: auto; position: relative; }
.grid.is-placed .tile { position: absolute; left: 0; top: 0; margin: 0; }
.tile { display: block; break-inside: avoid; margin-bottom: 44px; color: var(--ink); }
.tile[hidden] { display: none; }
.tile .frame { display: block; overflow: hidden; border-radius: 2px; background: #141414; }
.tile .ph { width: 100%; height: auto; transition: transform 0.8s cubic-bezier(0.2, 0.7, 0.2, 1), opacity 0.45s ease; }
/* A picture still on its way after a moment fades in when it arrives (site.js); ones already there (coming
   back to the list) show at once. */
.tile .ph.is-waiting { opacity: 0; }
@media (hover: hover) { .tile:hover .ph { transform: scale(1.03); } }
.tile .frame { position: relative; }
.yt-thumb { aspect-ratio: 16 / 9; object-fit: cover; }
.yt-thumb.is-vertical { aspect-ratio: 9 / 16; }
.tile .play { position: absolute; left: 50%; top: 50%; width: 48px; height: 48px; margin: -24px 0 0 -24px; border-radius: 9999px; background: rgba(0, 0, 0, 0.55); display: flex; align-items: center; justify-content: center; pointer-events: none; transition: background 0.3s; }
.tile .play svg { margin-left: 2px; }
@media (hover: hover) { .tile:hover .play { background: rgba(0, 0, 0, 0.75); } }
.tile .cap { display: flex; justify-content: space-between; align-items: baseline; gap: 16px; padding-top: 12px; font-size: 13px; }
.tile .t { color: var(--body); transition: color 0.3s; }
@media (hover: hover) { .tile:hover .t { color: var(--ink); } }
.tile .m { color: var(--mute); text-align: right; }
.empty { padding: 120px 0; text-align: center; font-size: 15px; color: var(--mute); }
.notice-plugin { padding-top: 40px; padding-bottom: 40px; color: var(--mute); }

.site-footer { display: flex; flex-wrap: wrap; justify-content: space-between; align-items: center; gap: 16px; padding-top: 32px; padding-bottom: calc(40px + var(--safe-b)); border-top: 1px solid var(--line); font-size: 13px; color: var(--mute); }
.site-footer a { color: var(--body); padding: 12px 0; }

/* Hover effects only where there is a real mouse: on touch screens a tap would leave them stuck on. */
/* Work detail */
/* (The scrollbar's room is always kept — see html above — so a page that scrolls and one that doesn't share
   the same width: the menu doesn't shift between pages, nor the pictures between works.) */
.detail { min-height: 100vh; display: flex; flex-direction: column; }
/* Signed in, WordPress adds its admin bar above the page (32px; 46px on small screens): take it off the full-height areas so there's no extra scroll. */
body.admin-bar .detail { min-height: calc(100vh - 32px); }
body.admin-bar .hero { height: calc(100vh - 32px); height: calc(100svh - 32px); }
@media (max-width: 782px) {
	body.admin-bar .detail { min-height: calc(100vh - 46px); }
	body.admin-bar .hero { height: calc(100vh - 46px); height: calc(100svh - 46px); }
}
/* The top bar (All works, number, close) stays put on every screen; a long work scrolls under it. */
.detail-bar { position: sticky; top: 0; z-index: 5; width: 100%; display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 16px; padding-top: 20px; padding-bottom: 20px; border-bottom: 1px solid var(--line); background: #000; }
body.admin-bar .detail-bar { top: 32px; }
@media (max-width: 782px) { body.admin-bar .detail-bar { top: 0; } } /* on small screens WordPress's bar scrolls away with the page */
.back { display: inline-flex; align-items: center; gap: 14px; min-height: 44px; color: var(--body); }
.back .logo-mark { width: 28px; height: 28px; }
.counter { font-size: 13px; color: var(--mute); }
.round { display: inline-flex; align-items: center; justify-content: center; width: 44px; height: 44px; border-radius: 9999px; border: 1px solid var(--line-strong); color: var(--body); flex: none; transition: color 0.2s, border-color 0.2s; }
@media (hover: hover) { .round:hover { color: var(--ink); border-color: rgba(255, 255, 255, 0.4); } }
.round.side { width: 52px; height: 52px; color: var(--mute); }
.detail-main { width: 100%; flex-grow: 1; display: flex; flex-wrap: wrap; align-items: center; align-content: center; gap: 40px; padding-top: 40px; padding-bottom: 40px; }
.detail-art { margin: 0; flex: 999 1 560px; min-width: 0; display: flex; flex-direction: column; align-items: center; gap: 28px; }
.detail-art figure { margin: 0; width: 100%; display: flex; justify-content: center; }
.zoom { display: block; max-width: 100%; padding: 0; border: 0; background: none; cursor: zoom-in; }
.zoom .art { display: block; }
.art-extra { --art-max: 90vh; }
/* Each picture's box is sized from its shape (--r, set on the page) and the height it may take (--art-max),
   so it has its final size before the file has loaded. */
/* The picture may be as tall as the space below the top bar (85px) and the work area's padding (40px each way). */
.detail-art { --art-max: calc(100vh - 165px); }
body.admin-bar .detail-art { --art-max: calc(100vh - 197px); }
.detail-art .zoom[style*="--r"] { width: min(100%, calc(var(--art-max) * var(--r))); }
.detail-art .zoom[style*="--r"] .art { width: 100%; height: auto; aspect-ratio: var(--r); max-height: none; }
/* With extra images the page scrolls; keep the work info in view on wide screens. */
.has-extra { align-items: flex-start; }
/* Same height on screen as the arrows of a single-image work (centred below the top bar), so they don't shift when moving between the two. */
.has-extra .round.side { position: sticky; top: calc(50vh + 16px); }
body.admin-bar .has-extra .round.side { top: calc(50vh + 32px); }
/* Wide screens: the work's details are centred in the full height below the top bar, like the arrows,
   whatever the size of the picture. With several images (the page scrolls) they stay there while scrolling. */
:root { --bar-h: 85px; }
@media (min-width: 1084px) { /* from where the details always sit beside the picture */
	.detail-info { --info-h: calc(100vh - var(--bar-h)); align-self: flex-start; height: var(--info-h); margin: -40px 0; justify-content: center; }
	body.admin-bar .detail-info { --info-h: calc(100vh - var(--bar-h) - 32px); }
	.has-extra .detail-info { position: sticky; top: var(--bar-h); }
	body.admin-bar .has-extra .detail-info { top: calc(var(--bar-h) + 32px); }
	.is-track .detail-info { --info-h: calc(100dvh - var(--bar-h)); }
	body.admin-bar .is-track .detail-info { --info-h: calc(100dvh - var(--bar-h) - 32px); }
	.is-track .has-extra .detail-info { top: 0; }
}
.tile .more { position: absolute; right: 8px; bottom: 8px; display: inline-flex; align-items: center; gap: 4px; padding: 2px 8px; border-radius: 9999px; background: rgba(0, 0, 0, 0.55); font-size: 11px; color: var(--ink); pointer-events: none; }
.detail-art .art { width: auto; max-width: 100%; max-height: var(--art-max); object-fit: contain; border-radius: 2px; opacity: 0; transform: scale(0.98); animation: artIn 0.9s cubic-bezier(0.2, 0.7, 0.2, 1) 0.1s forwards; }
@keyframes artIn { to { opacity: 1; transform: none; } }
html.from-work .detail-art .art { animation: none; opacity: 1; transform: none; }
.video-wrap { width: 100%; max-width: calc(var(--art-max) * 16 / 9); aspect-ratio: 16 / 9; background: #0D0D0D; border-radius: 2px; overflow: hidden; }
.video-wrap.is-vertical { max-width: calc(var(--art-max) * 9 / 16); aspect-ratio: 9 / 16; }
.video-wrap iframe { display: block; width: 100%; height: 100%; border: 0; }
.detail-info { flex: 1 1 240px; max-width: 340px; display: flex; flex-direction: column; gap: 20px; }
.detail-info .label { font-size: 13px; color: var(--mute); }
.detail-info h1 { font-size: 24px; font-weight: 500; line-height: 1.3; margin-top: -8px; }
.detail-info dl { margin: 0; display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 2fr); border-top: 1px solid var(--line); font-size: 14px; }
.detail-info dt, .detail-info dd { margin: 0; padding: 12px 0; border-bottom: 1px solid var(--line); }
.detail-info dt { color: var(--mute); }
.detail-info .desc { font-size: 15px; line-height: 1.8; color: var(--soft); }
.detail-info .desc p + p { margin-top: 1em; }
.detail-mobile-nav { display: none; }
/* Medium widths (a narrow window on a computer, a small laptop): the picture, the details and the arrows
   don't all fit on one line, and the arrows used to drop above and below. Here the arrows stay at the left
   and right edges, halfway down the screen, and the work takes the space between them. */
@media (min-width: 721px) and (max-width: 1140px) {
	.detail:not(.is-track) .detail-main { padding-left: calc(var(--pad) + 92px); padding-right: calc(var(--pad) + 92px); }
	.detail:not(.is-track) .detail-art { flex-basis: 520px; }
	.detail:not(.is-track) .round.side { position: fixed; top: calc(50vh + 16px); z-index: 5; }
	body.admin-bar .detail:not(.is-track) .round.side { top: calc(50vh + 32px); }
	.detail:not(.is-track) .round.side[rel="prev"] { left: var(--pad); }
	.detail:not(.is-track) .round.side[rel="next"] { right: var(--pad); }
}

/* Full-screen image viewer */
.lightbox { position: fixed; inset: 0; z-index: 100; background: #000; display: flex; align-items: center; justify-content: center; touch-action: none; overflow: hidden; } /* gestures are handled in site.js */
.lightbox[hidden] { display: none; }
/* The neighbouring image that slides in beside the current one while swiping (site.js). */
.lb-side { position: absolute; left: 50%; top: 50%; margin: 0; transform: translate(-50%, -50%); pointer-events: none; }
.lb-side[hidden] { display: none; }
.lb-btn:disabled { opacity: 0.25; cursor: default; }
/* Touch screens: a quick pressed look on tap (there is no hover there), instead of the browser's grey box. */
html { -webkit-tap-highlight-color: transparent; }
@media (hover: none) {
	.round:active, .pill:active, .lb-btn:active { background-color: rgba(255, 255, 255, 0.12); }
	.back:active, .site-nav a:active, .site-footer a:active, .about-links a:active { opacity: 0.6; }
}
/* Touch screens move between a work's images by swiping only; the count at the top says where you are. */
@media (max-width: 720px), (pointer: coarse) { .lightbox .lb-prev, .lightbox .lb-next { display: none; } }
@media (min-width: 721px) and (pointer: coarse) {
	.lb-img { max-width: calc(100vw - 48px); }
	.lb-img.has-r { width: min(calc(100vw - 48px), calc((100dvh - 120px) * var(--r))); }
}
/* Sized from the picture's shape (set by site.js), so a smaller copy shown first fills the same box as the full file. */
.lb-img.has-r { aspect-ratio: var(--r); width: min(calc(100vw - 160px), calc((100dvh - 120px) * var(--r))); height: auto; }
.lb-img { max-width: calc(100vw - 160px); max-height: calc(100vh - 120px); max-height: calc(100dvh - 120px); width: auto; height: auto; object-fit: contain; user-select: none; -webkit-user-drag: none; transform-origin: 0 0; will-change: transform; }
.lb-btn { position: absolute; width: 48px; height: 48px; border-radius: 9999px; border: 1px solid var(--line-strong); background: rgba(0, 0, 0, 0.5); color: var(--ink); display: flex; align-items: center; justify-content: center; cursor: pointer; }
@media (hover: hover) { .lb-btn:hover { border-color: rgba(255, 255, 255, 0.5); } }
.lb-btn[hidden] { display: none; }
/* Keyboard focus on round buttons: the thin outline just turns bright, instead of a heavy ring around it. */
.round:focus-visible, .lb-btn:focus-visible { outline: none; color: var(--ink); border-color: rgba(255, 255, 255, 0.85); box-shadow: 0 0 0 3px rgba(255, 255, 255, 0.12); }
.lb-close { top: calc(20px + env(safe-area-inset-top, 0px)); right: calc(20px + var(--safe-r)); }
.lb-prev { left: calc(24px + var(--safe-l)); top: 50%; margin-top: -24px; }
.lb-next { right: calc(24px + var(--safe-r)); top: 50%; margin-top: -24px; }
.lb-count { position: absolute; left: 50%; bottom: calc(24px + var(--safe-b)); transform: translateX(-50%); font-size: 13px; color: var(--mute); }
html.lb-open, html.lb-open body { overflow: hidden; }

/* About */
.about { display: flex; flex-wrap: wrap; gap: 72px; padding-top: 96px; padding-bottom: 120px; }
.about-photo { flex: 1 1 300px; max-width: 420px; }
.about-photo img { width: 100%; aspect-ratio: 4 / 5; object-fit: cover; border-radius: 2px; }
.about-text { flex: 999 1 420px; min-width: 0; max-width: 560px; display: flex; flex-direction: column; gap: 44px; }
.about-text section { display: flex; flex-direction: column; gap: 12px; }
/* Two styles only: label (small, grey) and value (one size, one weight). */
.about-label { margin: 0; font-size: 13px; font-weight: 400; line-height: 1.4; color: var(--mute); letter-spacing: 0.01em; }
.about-value { margin: 0; font-size: 16px; font-weight: 400; line-height: 1.75; color: var(--body); }
.about-links { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 4px; }
.about-links a { display: inline-block; padding: 2px 0; text-decoration: underline; text-decoration-color: rgba(255, 255, 255, 0.25); text-underline-offset: 5px; text-decoration-thickness: 1px; transition: color 0.2s, text-decoration-color 0.2s; }
.about-links a:hover, .about-links a:focus-visible { color: var(--ink); text-decoration-color: var(--ink); }

.plain { padding-top: 120px; padding-bottom: 160px; display: flex; flex-direction: column; gap: 16px; }
.plain h1 { font-size: 20px; font-weight: 500; }
.plain a { color: var(--soft); }

/* Responsive */
@media (max-width: 1100px) {
	.grid { column-count: 2; }
}
@media (max-width: 720px) {
	:root { --pad: 20px; }
	.grid { column-count: 1; }
	.works-head { padding-top: 72px; }
	/* Keep hero controls clear of rounded screen corners and the home indicator. */
	.hero-info { width: 168px; padding: 0 0 calc(var(--safe-b) + 20px) calc(var(--safe-l) + 28px); }
	.scroll-cue { right: calc(var(--safe-r) + 22px); bottom: calc(var(--safe-b) + 28px); }
	.scroll-cue .line, .scroll-cue .cue { height: 36px; }
	.round.side { display: none; }
	/* Stack image → info without the stretched gaps, and keep the bottom nav full width. */
	.detail-main { flex-grow: 0; align-content: flex-start; gap: 24px; padding-top: 24px; padding-bottom: 32px; }
	.detail-info { max-width: none; }
	.detail-art .art, .art-extra .art { max-height: none; }
	.detail-art, .art-extra { --art-max: 100000px; }
	.has-extra .detail-info { position: static; }
	/* Phone browsers float their toolbars over the bottom of the page: keep viewer controls at mid-height and top. */
	.lb-img { max-width: 100vw; max-height: calc(100dvh - 180px); }
	.lb-img.has-r { width: min(100vw, calc((100dvh - 180px) * var(--r))); }
	.lb-btn { width: 44px; height: 44px; }
	.lb-prev, .lb-next { margin-top: -22px; }
	.lb-prev { left: calc(8px + var(--safe-l)); }
	.lb-next { right: calc(8px + var(--safe-r)); }
	.lb-count { bottom: auto; top: calc(32px + env(safe-area-inset-top, 0px)); left: calc(20px + var(--safe-l)); transform: none; }
	/* Phones move between works by swiping; the buttons stay for screen readers and keyboards only. */
	.detail-mobile-nav { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
	.detail-mobile-nav:focus-within { position: static; width: 100%; height: auto; margin: 0; clip: auto; overflow: visible; display: flex; justify-content: space-between; gap: 12px; padding: 16px 0 calc(var(--safe-b) + 32px); border-top: 1px solid var(--line); }
	.detail-main { padding-bottom: calc(var(--safe-b) + 32px); }
	/* The work page fills the screen exactly: it only scrolls when the work itself is taller. The top bar
	   (All works, number, close) stays put while the work scrolls under it. */
	.detail { min-height: 100svh; }
	body.admin-bar .detail { min-height: calc(100svh - 46px); }
	.detail-mobile-nav a { display: inline-flex; align-items: center; gap: 8px; min-height: 44px; padding: 0 18px; border-radius: 9999px; border: 1px solid var(--line-strong); color: var(--body); font-size: 13px; }
	.detail-mobile-nav a:active { border-color: rgba(255, 255, 255, 0.4); }
	.about { gap: 40px; padding-top: 48px; }
}

@media (prefers-reduced-motion: reduce) {
	html { scroll-behavior: auto; }
	.show-intro .intro { display: none; }
	.fade, .intro .mk, .intro .mk4 { opacity: 1; animation: none; }
	.hero-media, .scroll-cue .cue, .detail-art .art { animation: none; transform: none; opacity: 1; }
	.hero .slide { transition: none; }
	.seg .bar.on { animation: none; transform: scaleX(1); }
}

/* ---------- List and work in one page (site.js, "One page") ----------
   A work opened from the list sits in a layer in front of it, and scrolls inside that layer; the list
   behind is left exactly as it was. */
.spa-layer { position: fixed; inset: 0; z-index: 60; overflow-x: hidden; overflow-y: auto; overscroll-behavior: contain; background: #000; outline: none; }
.spa-layer.is-leaving { pointer-events: none; }
/* While a work is open the list doesn't scroll, and its scrollbar makes way for the work's own, in the same
   place: the list keeps that width as padding, so nothing in it moves. */
html.spa-open { overflow: hidden; scrollbar-gutter: auto; }
html.spa-open body { padding-right: var(--sbw, 0px); }
.spa-layer { scrollbar-gutter: stable; }
.spa-clone { position: fixed; z-index: 70; margin: 0; pointer-events: none; transform-origin: 0 0; border-radius: 2px; object-fit: cover; will-change: transform; }

/* ---------- Moving between works (see site.js) ----------
   Computers: the next work waits, hidden, in the same place as this one. Phones and tablets: a strip. */
.detail { position: relative; overflow: clip; } /* the neighbour waiting beside this work must not add scrolling */
.detail-main.is-peer { position: absolute; left: 0; right: 0; pointer-events: none; }
.detail-main.is-peer .art { animation: none; opacity: 1; transform: none; }
.detail-main.no-intro .art { animation: none; opacity: 1; transform: none; }

/* Touch screens (phones and tablets, any orientation): works side by side in a strip the browser scrolls
   sideways itself, one work per stop; each work scrolls up and down inside its own panel under the fixed
   top bar. Set up by site.js; without it the page simply scrolls as usual. */
.detail.is-track { height: 100vh; height: 100dvh; min-height: 0; overflow: hidden; }
body.admin-bar .detail.is-track { height: calc(100dvh - 32px); }
@media (max-width: 782px) { body.admin-bar .detail.is-track { height: calc(100dvh - 46px); } }
.detail-track { flex: 1 1 auto; min-height: 0; display: flex; overflow-x: auto; overflow-y: hidden; scroll-snap-type: x mandatory;
	overscroll-behavior: contain; overflow-anchor: none; scrollbar-width: none; -webkit-overflow-scrolling: touch; }
.detail-track::-webkit-scrollbar { display: none; }
.detail-slide { flex: 0 0 100%; width: 100%; min-width: 0; display: flex; flex-direction: column; overflow-x: hidden; overflow-y: auto;
	scroll-snap-align: start; scroll-snap-stop: always; overscroll-behavior-y: contain; overflow-anchor: none;
	scrollbar-width: thin; scrollbar-color: rgba(255, 255, 255, .2) transparent; scrollbar-gutter: stable; }
.is-track .detail-main { touch-action: auto; }
.page-zoomed .detail-track { overflow-x: hidden; }
/* Swiping replaces the side arrows; the work fits the panel below the top bar. */
.is-track .round.side { display: none; }
@media (min-width: 721px) {
	.is-track .detail-main { flex: 1 0 auto; }
	.is-track .detail-art .art { max-height: calc(100dvh - 210px); }
	.is-track .detail-art, .is-track .art-extra { --art-max: calc(100dvh - 210px); }
	.is-track .video-wrap { max-width: calc((100dvh - 210px) * 16 / 9); }
	.is-track .video-wrap.is-vertical { max-width: calc((100dvh - 210px) * 9 / 16); }
}
/* Tablets held upright: one centred column — the work, then its details at a comfortable reading width. */
@media (min-width: 721px) and (max-width: 1099px) and (min-aspect-ratio: 1/2) and (max-aspect-ratio: 1/1) {
	.is-track .detail-main { flex-direction: column; flex-wrap: nowrap; align-items: center; justify-content: center; align-content: normal; gap: 36px; padding-top: 48px; padding-bottom: calc(48px + var(--safe-b)); }
	.is-track .detail-art { flex: none; width: 100%; }
	.is-track .detail-art .art { max-height: 66dvh; }
	.is-track .detail-art, .is-track .art-extra { --art-max: 66dvh; }
	.is-track .detail-info { flex: none; width: 100%; max-width: 560px; }
	.is-track .has-extra .detail-info { position: static; }
}
/* Phones turned sideways: picture and details side by side, the picture as tall as the screen allows. */
@media (orientation: landscape) and (max-height: 540px) {
	.is-track .detail-main { flex-wrap: nowrap; align-items: center; gap: 28px; padding-top: 16px; padding-bottom: calc(16px + var(--safe-b)); padding-left: max(var(--pad), env(safe-area-inset-left, 0px)); padding-right: max(var(--pad), env(safe-area-inset-right, 0px)); }
	.is-track .detail-art { flex: 1 1 auto; }
	.is-track .detail-art .art { max-height: calc(100dvh - 120px); }
	.is-track .detail-art, .is-track .art-extra { --art-max: calc(100dvh - 120px); }
	.is-track .video-wrap { max-width: calc((100dvh - 120px) * 16 / 9); }
	.is-track .detail-info { flex: 0 0 240px; max-width: 240px; gap: 14px; }
	.is-track .detail-info h1 { font-size: 20px; }
	.is-track .detail-bar { padding-top: 10px; padding-bottom: 10px; }
}
@media (max-width: 720px) {
	.detail-main { touch-action: pan-y pinch-zoom; }
}
@media (max-width: 720px), (pointer: coarse) {
	/* "Swipe" hint shown over the artwork the first time a work is opened from the list in a visit. */
	.swipe-tip { position: fixed; left: 50%; top: 50%; z-index: 20; transform: translate(-50%, -50%); display: inline-flex; align-items: center; gap: 10px; padding: 10px 16px; border-radius: 9999px;
		background: rgba(0, 0, 0, 0.62); -webkit-backdrop-filter: blur(10px); backdrop-filter: blur(10px); color: var(--ink); font-size: 13px; letter-spacing: 0.01em; pointer-events: none;
		opacity: 0; transition: opacity 0.35s ease; white-space: nowrap; }
	.swipe-tip.is-on { opacity: 1; }
	.swipe-tip svg { flex: none; display: block; }
	.swipe-tip span { display: block; line-height: 16px; }
}

/* Viewer zoomed in: the image can be dragged; controls step back. */
.lightbox.is-zoomed .lb-img { cursor: grab; }
.lightbox.is-zoomed .lb-prev, .lightbox.is-zoomed .lb-next, .lightbox.is-zoomed .lb-count { opacity: 0; pointer-events: none; }
.lb-prev, .lb-next, .lb-count { transition: opacity 0.2s; }
.page-zoomed .detail-main { touch-action: auto; }

