/* =========================================================
   17 BLEND — Nocturne's architecture, motion and palette;
   Festival's programme; Rosso's series page; Cathedral's
   header behaviour; the photographer's own type.
   ========================================================= */
:root {
  --bg: #ffffff;
  --raised: #f2f2f0;
  --text: #121417;
  --muted: #5f6670; /* 5.9:1 on white */
  --dim: #6b727b; /* 4.9:1 on white */
  --body: #3d434a;
  --line: rgba(18, 20, 23, 0.1);
  --line-2: rgba(18, 20, 23, 0.28);
  --heart: #e0367a; /* the logo's pink */
  --void: #ffffff;
  /* exactly two families: the portfolio pair */
  --display: "Literata", Georgia, "Times New Roman", serif;
  --text-font: "Inter", "Helvetica Neue", Arial, sans-serif;
  --dvs: normal;
  --serif: var(--display);
  --sans: var(--text-font);
  /* display weights: light for the very large type, regular elsewhere */
  --w-big: 300;
  --w-disp: 400;
  /* ONE type scale — every font-size in this file uses one of these six */
  --fs-display: clamp(36px, 4.4vw, 60px); /* page titles */
  --fs-title: clamp(
    26px,
    2.6vw,
    36px
  ); /* series names, home photo titles, stat numerals */
  --fs-sub: 20px; /* caption titles, lead paragraphs, viewer title, brand */
  --fs-body: 16px; /* body text, place lines, intros */
  --fs-small: 13px; /* EXIF, secondary meta, footer */
  --fs-label: 11px; /* uppercase letterspaced labels, nav, counters, buttons */
  /* one line-height per role */
  --lh-display: 1.06;
  --lh-title: 1.15;
  --lh-sub: 1.35;
  --lh-body: 1.6;
  --lh-small: 1.5;
  --lh-label: 1.4;
  /* one tracking for every uppercase label */
  --ls-label: 0.16em;
  --ls-display: -0.02em;
  --ls-title: -0.01em;
  --logo: 32px;
  /* Rosso's 8px ladder (used by the series page) */
  --xxxs: 4px;
  --xxs: 8px;
  --xs: 16px;
  --sm: 24px;
  --md: 32px;
  --lg: 48px;
  --xl: 64px;
  --band: clamp(64px, 10vh, 96px);
  --maxw: 1280px;
  --widew: 1440px;
  --mx: clamp(16px, 2vw, 32px);
  --navh: 76px;
  --caph: 104px;
  --ease: cubic-bezier(0.22, 0.61, 0.18, 1);
  --out: cubic-bezier(0.16, 1, 0.3, 1);
  color-scheme: light;
}
@media (max-width: 560px) {
  :root {
    --mx: 14px; /* phones: page and menu share one edge */
  }
}
@media (max-width: 759px) {
  :root {
    --navh: 58px;
    --caph: 100px;
    --logo: 28px;
  }
}

*,
*::before,
*::after {
  box-sizing: border-box;
}
html {
  background: var(--bg);
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
}
body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font: 400 var(--fs-body) / var(--lh-body) var(--sans);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  font-optical-sizing: auto;
  font-variation-settings: var(--dvs);
  min-height: 100vh;
  overflow-x: clip;
}
a {
  color: inherit;
  text-decoration: none;
}
button {
  font: inherit;
  color: inherit;
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
a {
  -webkit-tap-highlight-color: transparent;
}
h1,
h2,
h3,
p,
ol,
ul,
dl,
dd,
figure {
  margin: 0;
  padding: 0;
}
ol,
ul {
  list-style: none;
}
em {
  font-style: italic;
}
::selection {
  background: var(--text);
  color: var(--bg);
}
:focus {
  outline: none;
}
:focus-visible {
  outline: 1px solid var(--text);
  outline-offset: 4px;
}
.vh {
  position: absolute !important;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
}
.tnum {
  font-variant-numeric: tabular-nums lining-nums;
}
.lbl {
  font: 500 var(--fs-label) / var(--lh-label) var(--sans);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--muted);
  font-variant-numeric: tabular-nums lining-nums;
}
.of {
  color: var(--dim);
}

/* skip */
.skip {
  position: fixed;
  left: 16px;
  top: -60px;
  z-index: 80;
  background: var(--text);
  color: var(--bg);
  padding: 10px 14px;
  font: 600 var(--fs-label) / var(--lh-label) var(--sans);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  transition: top 0.2s;
}
.skip:focus-visible {
  top: 12px;
  outline-offset: 2px;
}

/* ambient glow */
.ambient {
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  overflow: hidden;
  opacity: calc(var(--go, 0.36) * 0.6);
  transition: opacity 1.4s var(--ease);
}
.ambient i {
  position: absolute;
  left: 50%;
  top: 47%;
  width: min(130vw, 1700px);
  height: min(115vh, 1150px);
  transform: translate(calc(-50% + var(--gx, 0px)), -50%);
  background-color: var(--glow, hsl(212 20% 90%));
  -webkit-mask-image: radial-gradient(
    closest-side,
    #000 0%,
    rgba(0, 0, 0, 0.62) 34%,
    rgba(0, 0, 0, 0.22) 64%,
    transparent 100%
  );
  mask-image: radial-gradient(
    closest-side,
    #000 0%,
    rgba(0, 0, 0, 0.62) 34%,
    rgba(0, 0, 0, 0.22) 64%,
    transparent 100%
  );
  transition:
    background-color 1.8s var(--ease),
    transform 1.8s var(--out);
}
html[data-view="work"] .ambient {
  --go: 0;
}

/* nav — Cathedral behaviour: transparent over the top of the page,
   solid once the page (or the home sequence) has scrolled; a 1px
   progress line underneath fills left to right. Never hides. */
.nav {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 20;
  height: var(--navh);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 0 var(--mx);
  transition:
    background-color 0.25s,
    border-color 0.25s;
  border-bottom: 1px solid transparent;
}
.nav.is-solid {
  background: rgba(255, 255, 255, 0.94);
  border-bottom-color: var(--line);
}
.nav-progress {
  position: absolute;
  left: 0;
  right: 0;
  bottom: -1px;
  height: 1px;
  background: var(--text);
  transform-origin: 0 50%;
  transform: scaleX(0);
  pointer-events: none;
}
.brand {
  position: relative;
  display: flex;
  align-items: center;
  gap: 12px;
  min-width: 0;
  white-space: nowrap;
  color: var(--text);
}
.brand-name {
  display: block;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  font: var(--w-disp) var(--fs-sub) / var(--lh-sub) var(--serif);
  letter-spacing: 0;
}
/* the portfolio logo (Logo.astro): bar + stem in the text colour, I + dot in the gradient */
.logo {
  flex: none;
  display: block;
  width: var(--logo);
  height: var(--logo);
  overflow: visible;
  color: var(--text);
}
.logo .wipe-r,
.logo .wipe-d {
  animation: var(--wipe) var(--t) cubic-bezier(0.45, 0, 0.2, 1) both;
  animation-delay: calc(var(--d, 0s) + var(--d0, 0s));
}
.logo .wipe-r {
  --wipe: wipeR;
  clip-path: inset(0 100% 0 0);
}
.logo .wipe-d {
  --wipe: wipeD;
  clip-path: inset(0 0 100% 0);
}
.logo .dot {
  opacity: 0;
  transform: translateY(8px);
  transform-box: fill-box;
  animation: dotRise 0.45s cubic-bezier(0.2, 0.7, 0.2, 1)
    calc(0.8s + var(--d0, 0s)) forwards;
}
@keyframes wipeR {
  to {
    clip-path: inset(0 0 0 0);
  }
}
@keyframes wipeD {
  to {
    clip-path: inset(0 0 0 0);
  }
}
@keyframes dotRise {
  to {
    opacity: 1;
    transform: none;
  }
}
/* hover hint (TopBar.astro): the pieces drift apart along the cut lines */
.brand [data-part] {
  transition: translate 0.35s cubic-bezier(0.34, 1.5, 0.64, 1);
}
.brand:hover [data-part="bar"] {
  translate: -1.5px -1.2px;
}
.brand:hover [data-part="stem"] {
  translate: -1.6px 1.4px;
}
.brand:hover [data-part="i"] {
  translate: 1.6px 1.6px;
}
.brand:hover [data-part="dot"] {
  translate: 1.8px -2.2px;
}
/* gradient ring that spreads from the logo on click */
.ripple {
  position: absolute;
  left: 0;
  top: 50%;
  width: var(--logo);
  height: var(--logo);
  margin-top: calc(var(--logo) / -2);
  border-radius: 50%;
  border: 2px solid transparent;
  background: linear-gradient(100deg, #2f6bff, #e0367a 55%, #ff7a59)
    border-box;
  -webkit-mask:
    linear-gradient(#000 0 0) padding-box,
    linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
  mask-composite: exclude;
  opacity: 0;
  pointer-events: none;
}
@media (prefers-reduced-motion: reduce) {
  .logo .wipe-r,
  .logo .wipe-d {
    clip-path: none;
  }
  .logo .dot {
    opacity: 1;
    transform: none;
  }
  .brand [data-part] {
    translate: none !important;
  }
}
.nav-links {
  display: flex;
  flex: none;
  gap: clamp(18px, 3vw, 44px);
}
.nav-links a,
.nav-links button {
  position: relative;
  display: block;
  padding: 10px 0;
  font: 500 var(--fs-label) / var(--lh-label) var(--sans);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--muted);
  transition: color 0.3s;
}
.nav-links a::after,
.nav-links button::after {
  content: "";
  position: absolute;
  left: 0;
  right: var(--ls-label);
  bottom: 3px;
  height: 1px;
  background: currentColor;
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 0.5s var(--out);
}
.nav-links a:hover,
.nav-links button:hover,
.nav-links button[aria-expanded="true"],
.nav-links [aria-current="page"] {
  color: var(--text);
}
.nav-links [aria-current="page"]::after,
.nav-links button[aria-expanded="true"]::after,
.nav-links button:hover::after,
.nav-links a:hover::after {
  transform: scaleX(1);
}
@media (max-width: 759px) {
  /* phones: same tokens, tighter gaps so logo + name + three links fit at 375px */
  .nav {
    gap: 10px;
    padding: 0 var(--mx);
  }
  .brand {
    gap: 8px;
  }
  .brand-name {
    font-size: var(--fs-body);
  }
  .nav-links {
    gap: 12px;
  }
  .nav-links a,
  .nav-links button {
    letter-spacing: 0.08em;
  }
  .nav-links a::after,
  .nav-links button::after {
    right: 0.08em;
  }
}
@media (max-width: 400px) {
  /* small phones: give the full name room next to the three links */
  .nav {
    gap: 6px;
  }
  .nav-links {
    gap: 7px;
  }
  .nav-links a,
  .nav-links button {
    letter-spacing: 0.02em;
  }
  .nav-links a::after,
  .nav-links button::after {
    right: 0.02em;
  }
}

/* series picker: opens from "Series" in the nav */
.nav-links button {
  cursor: pointer;
}
.smenu {
  position: fixed;
  top: var(--navh);
  right: var(--mx);
  z-index: 19;
  width: min(440px, calc(100vw - 2 * var(--mx)));
  padding: 8px 0;
  background: rgba(255, 255, 255, 0.98);
  box-shadow: 0 18px 50px rgba(18, 20, 23, 0.1);
  border: 1px solid var(--line);
  opacity: 0;
  visibility: hidden;
  transform: translateY(-8px);
  transition:
    opacity 0.45s var(--out),
    transform 0.6s var(--out),
    visibility 0s 0.45s;
}
.smenu.is-open {
  opacity: 1;
  visibility: visible;
  transform: none;
  transition:
    opacity 0.45s var(--out),
    transform 0.6s var(--out);
}
.smenu-h {
  padding: 12px 20px 10px;
}
.smenu a {
  display: grid;
  grid-template-columns: 28px minmax(0, 1fr) 72px;
  align-items: center;
  gap: 16px;
  padding: 14px 20px;
  border-top: 1px solid var(--line);
  transition:
    background-color 0.3s var(--ease),
    opacity 0.3s var(--ease);
}
.smenu-list:hover a {
  opacity: 0.45;
}
.smenu-list a:hover,
.smenu-list a:focus-visible {
  opacity: 1;
  background: var(--raised);
}
.smenu-n {
  font: 500 var(--fs-label) / var(--lh-label) var(--sans);
  letter-spacing: var(--ls-label);
  color: var(--muted);
}
.smenu-name {
  display: block;
  white-space: nowrap;
  padding-bottom: 0.08em; /* room for the tails of y, g, p */
  font: var(--w-disp) var(--fs-title) / 1.3 var(--serif);
  letter-spacing: var(--ls-title);
  color: var(--text);
}
.smenu-meta {
  display: block;
  margin-top: 6px;
  white-space: nowrap;
  font: 500 var(--fs-label) / var(--lh-label) var(--sans);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--muted);
}
/* every thumbnail sits in the same 72×52 box, shown whole (contain, never cropped) */
.smenu-thumb {
  display: block;
  overflow: hidden;
  width: 72px;
  height: 52px;
  aspect-ratio: auto !important;
}
.smenu-thumb img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain; /* whole photo, never cropped */
}
@media (max-width: 759px) {
  .smenu {
    left: 0;
    right: 0;
    width: auto;
    border-left: 0;
    border-right: 0;
  }
}
/* hearts that burst on the page (grids, series, home) — outside the viewer */
.page-burst {
  position: fixed;
  inset: 0;
  z-index: 70;
  pointer-events: none;
  overflow: hidden;
}
main a[href^="#/photo/"] {
  touch-action: manipulation;
}

main {
  position: relative;
  z-index: 1;
  outline: none;
}
main.is-entering {
  animation: enter 0.7s var(--ease) both;
}
@keyframes enter {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}

/* image boxes: flat neutral box, then a quick fade */
.ph {
  position: relative;
  display: block;
  background: var(--raised);
  overflow: hidden;
}
.ph img {
  display: block;
  width: 100%;
  height: auto;
}
.ph img.is-loaded {
  opacity: 1;
}
.ph.is-error::after {
  content: "Image unavailable";
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  font: 500 var(--fs-label) / var(--lh-label) var(--sans);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--muted);
}

/* like button */
.like {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 10px;
  margin: -10px;
  color: var(--muted);
  font: 500 var(--fs-small) / var(--lh-label) var(--sans);
  letter-spacing: 0.04em;
  font-variant-numeric: tabular-nums lining-nums;
  transition: color 0.3s var(--ease);
}
.like svg {
  width: 18px;
  height: 18px;
  overflow: visible;
  fill: transparent;
  stroke: currentColor;
  stroke-width: 1.5;
  stroke-linejoin: round;
  transition:
    fill 0.35s var(--ease),
    stroke 0.35s var(--ease);
}
.like:hover {
  color: var(--text);
}
.like[aria-pressed="true"] {
  color: var(--text);
}
.like[aria-pressed="true"] svg {
  fill: var(--heart);
  stroke: var(--heart);
}
.like.pop svg {
  animation: pop 0.55s var(--out);
}
@keyframes pop {
  0% {
    transform: scale(1);
  }
  28% {
    transform: scale(1.34);
  }
  55% {
    transform: scale(0.9);
  }
  100% {
    transform: scale(1);
  }
}
.like-sm {
  gap: 6px;
  font-size: var(--fs-label);
}
.like-sm svg {
  width: 13px;
  height: 13px;
}

/* ---------- HOME ---------- */
/* The window scrolls (normal scrollbar). A short intro, then the work at once. */
.hero {
  position: relative;
  z-index: 1;
  padding: calc(var(--navh) + clamp(20px, 4vh, 40px)) var(--mx)
    clamp(28px, 5vh, 48px);
}
.hero-in {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, auto);
  align-items: end;
  gap: 24px clamp(32px, 5vw, 80px);
  max-width: var(--widew);
  margin: 0 auto;
}
.hero-kick {
  grid-column: 1 / -1;
  padding-bottom: 14px;
  border-bottom: 1px solid var(--line);
  animation: fadeup 1.4s var(--out) both;
}
.hero-title {
  max-width: 22ch;
  overflow: hidden;
  padding: 0.14em 0 0.08em;
  margin: -0.14em 0 -0.08em;
  font: var(--w-big) var(--fs-display) / var(--lh-display) var(--serif);
  letter-spacing: var(--ls-display);
}
.hero-title > span {
  display: block;
  animation: rise 1.5s var(--out) both 0.1s;
}
.hero-side {
  max-width: none;
  animation: fadeup 1.4s var(--out) both 0.4s;
}
.hero-text {
  font: 400 var(--fs-body) / var(--lh-body) var(--sans);
  color: var(--body);
}
.hero-side .btn-row {
  margin-top: 0;
  flex-wrap: nowrap;
}
@media (max-width: 559px) {
  .btn-row {
    flex-wrap: nowrap;
    width: 100%;
  }
  html .btn {
    flex: none;
    min-width: 0;
    width: calc((100vw - 2 * var(--mx) - 12px) / 2);
    padding: 0 12px;
  }
}
@media (max-width: 899px) {
  .hero-in {
    grid-template-columns: minmax(0, 1fr);
  }
}

/* featured sequence: Nocturne's contained plates + ambient glow + slow caption reveal,
   now a continuous column (photo + caption per item, 48px apart) */
.feat {
  --fh: 78vh;
  --fgap: 48px;
  position: relative;
  z-index: 1;
  display: grid;
  gap: var(--fgap);
  padding: 0 var(--mx);
}
@supports (height: 1svh) {
  .feat {
    --fh: 78svh;
  }
}
@media (max-width: 759px) {
  .feat {
    --fgap: 32px;
  }
}
.fitem {
  position: relative;
  width: min(100%, calc(var(--fh) * var(--ar)));
  min-width: 0;
  margin: 0 auto;
}
.plate-link {
  display: block;
}
.plate-link:focus-visible {
  outline-offset: 6px;
}
.fitem .ph {
  transition: filter 0.4s var(--ease);
}
@media (hover: hover) {
  .plate-link:hover .ph {
    filter: brightness(1.06);
  }
}
.lower {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  grid-template-areas: "num act" "text act";
  align-items: start;
  gap: 6px 24px;
  padding-top: 16px;
}
.lower-num {
  grid-area: num;
  display: flex;
  flex-wrap: wrap;
  gap: 4px 14px;
  min-width: 0;
}
.lower-num a {
  color: var(--muted);
  transition: color 0.3s;
}
.lower-num a:hover {
  color: var(--text);
}
.lower-text {
  grid-area: text;
  min-width: 0;
}
.lower-title {
  font: var(--w-disp) var(--fs-title) / var(--lh-title) var(--serif);
  letter-spacing: var(--ls-title);
  overflow-wrap: anywhere;
}
.lower-place {
  margin-top: 4px;
  font: 400 var(--fs-body) / var(--lh-body) var(--sans);
  color: var(--muted);
}
.lower-place em {
  font-style: normal;
}
.yr {
  font: 500 var(--fs-label) / var(--lh-label) var(--sans);
  font-style: normal;
  letter-spacing: var(--ls-label);
  margin-left: 12px;
  color: var(--dim);
}
.lower-act {
  grid-area: act;
  padding-top: 2px;
}

/* right-edge counter for the featured sequence (only while it is on screen) */
.progress {
  position: fixed;
  right: calc(var(--mx) / 2);
  top: 50%;
  z-index: 5;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
  transform: translate(50%, -50%);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.8s var(--ease);
}
.progress.is-on {
  opacity: 1;
}
/* full-width photos leave no margin for the counter */
.progress {
  display: none;
}
.pg-line {
  position: relative;
  width: 1px;
  height: 76px;
  background: var(--line);
  overflow: hidden;
}
.pg-line i {
  position: absolute;
  inset: 0;
  background: var(--text);
  transform-origin: top;
  transform: scaleY(var(--p, 0.125));
  transition: transform 1s var(--out);
}
.pg-cur {
  color: var(--text);
}
@media (max-width: 899px) {
  .progress {
    display: none;
  }
}
/* ---------- THE PROGRAMME (Festival layout, type scale and hovers — on Nocturne's dark) ---------- */
.home-prog .prog {
  padding-top: clamp(80px, 14vh, 144px);
}
.prog {
  position: relative;
  z-index: 1;
  padding: calc(var(--navh) + clamp(32px, 8vh, 96px)) var(--mx)
    clamp(64px, 11vh, 128px);
}
.kick {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 8px 24px;
  padding-bottom: 16px;
  border-bottom: 1px solid var(--line);
}
.prog-head {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: end;
  gap: 20px 48px;
  padding: clamp(28px, 6vh, 64px) 0 clamp(32px, 6vh, 64px);
}
.prog-title {
  font: var(--w-big) var(--fs-title) / var(--lh-title) var(--serif);
  letter-spacing: var(--ls-display);
}
.prog-note {
  max-width: 38ch;
  font: 400 var(--fs-body) / var(--lh-body) var(--sans);
  color: var(--muted);
  text-align: right;
}
@media (max-width: 759px) {
  .prog-head {
    grid-template-columns: minmax(0, 1fr);
  }
  .prog-note {
    text-align: left;
  }
}
.plist {
  border-top: 1px solid var(--line);
}
.prow {
  display: grid;
  grid-template-columns: 64px minmax(0, 1fr) minmax(150px, 200px) auto;
  align-items: center;
  gap: 0 clamp(20px, 3vw, 48px);
  padding: clamp(20px, 3.4vh, 36px) 0;
  border-bottom: 1px solid var(--line);
  transition: opacity 0.4s var(--ease);
}
.prow-num {
  align-self: start;
  padding-top: 10px;
  color: var(--text);
}
.prow-main {
  display: block;
  min-width: 0;
}
.prow-title {
  display: block;
  font: var(--w-disp) var(--fs-title) / var(--lh-title) var(--serif);
  letter-spacing: var(--ls-title);
  overflow-wrap: anywhere;
}
.prow-arr {
  font-weight: 300;
  opacity: 0;
  transition: opacity 0.4s var(--ease);
}
.prow-blurb {
  display: block;
  margin-top: 8px;
  max-width: 56ch;
  font: 400 var(--fs-body) / var(--lh-body) var(--sans);
  color: var(--muted);
}
.prow-facts {
  display: grid;
  gap: 7px;
}
.prow-facts b {
  font-weight: 500;
  color: var(--text);
}
.prow-thumb {
  display: block;
  --th: clamp(64px, 6.4vw, 96px);
}
.prow-thumb .ph {
  height: var(--th);
  width: auto;
  transition: filter 0.4s var(--ease);
}
.prow:hover .prow-arr,
.prow:focus-visible .prow-arr {
  opacity: 1;
}
.prow:focus-visible {
  outline-offset: -1px;
}

@media (max-width: 899px) {
  .prow {
    grid-template-columns: 44px minmax(0, 1fr) auto;
  }
  .prow-facts {
    grid-column: 2;
    grid-row: 2;
    display: flex;
    flex-wrap: wrap;
    gap: 6px 18px;
    margin-top: 16px;
  }
  .prow-thumb {
    grid-column: 3;
    grid-row: 1 / span 2;
    --th: 84px;
  }
}
@media (max-width: 559px) {
  .prow {
    grid-template-columns: 30px minmax(0, 1fr);
    gap: 0 12px;
  }
  .prow-thumb {
    display: none;
  }
}
.prog-foot {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 16px 32px;
  margin-top: clamp(32px, 6vh, 56px);
}

/* ---------- buttons: sharp hairline rectangles ---------- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 14px;
  box-sizing: border-box;
  height: 48px;
  min-width: 220px;
  padding: 0 24px;
  border: 1px solid var(--line-2);
  color: var(--text);
  font: 500 var(--fs-label) / var(--lh-label) var(--sans);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  white-space: nowrap;
  transition:
    background-color 0.5s var(--ease),
    border-color 0.5s var(--ease),
    color 0.5s var(--ease);
}
.btn:hover {
  border-color: var(--text);
  background: rgba(18, 20, 23, 0.04);
}
.btn-solid {
  background: var(--text);
  border-color: var(--text);
  color: var(--bg);
}
.btn-solid:hover {
  background: #000;
  border-color: #000;
}
.btn .arr {
  font: 400 var(--fs-small) / 1 var(--sans);
  letter-spacing: 0;
  transition: transform 0.5s var(--out);
}
.btn:hover .arr {
  transform: translateX(4px);
}
.btn:hover .arr.down {
  transform: translateY(3px);
}
.btn-row {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
}
@media (max-width: 400px) {
  .btn {
    padding: 0 18px;
    letter-spacing: 0.12em;
  }
}

/* footer */
.foot {
  position: relative;
  z-index: 1;
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 12px 32px;
  padding: 30px var(--mx) calc(30px + env(safe-area-inset-bottom));
  border-top: 1px solid var(--line);
  font: 400 var(--fs-small) / var(--lh-small) var(--sans);
  letter-spacing: 0.01em;
  color: var(--muted);
}
.foot-links {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 28px;
}
.foot a {
  transition: color 0.3s;
}
.foot a:hover {
  color: var(--text);
}

/* ---------- PAGE HEAD (work / index / about) ---------- */
.page {
  padding: calc(var(--navh) + clamp(20px, 4vh, 40px)) var(--mx) 0;
}
.page-head {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: end;
  gap: 28px 40px;
  padding-bottom: clamp(20px, 3vh, 32px);
}
.page-head .lbl {
  grid-column: 1/-1;
}
.page-title {
  font: var(--w-big) var(--fs-display) / var(--lh-display) var(--serif);
  letter-spacing: var(--ls-display);
  min-width: 0;
  overflow-wrap: anywhere;
}
.page-title em {
  color: var(--muted);
}
.page-meta {
  max-width: 40ch;
  font: 400 var(--fs-body) / var(--lh-body) var(--sans);
  color: var(--muted);
  text-align: right;
}
@media (max-width: 759px) {
  .page-head {
    grid-template-columns: 1fr;
  }
  .page-meta {
    text-align: left;
  }
}

.filter {
  display: flex;
  flex-wrap: wrap;
  gap: 6px clamp(20px, 3.2vw, 48px);
  padding: 22px 0;
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
  margin-bottom: clamp(36px, 6vh, 64px);
}
.filter a {
  position: relative;
  padding: 6px 0;
  font: 500 var(--fs-label) / var(--lh-label) var(--sans);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--muted);
  transition: color 0.3s;
}
.filter a sup {
  margin-left: 6px;
  font-size: var(--fs-label);
  letter-spacing: 0.04em;
  vertical-align: baseline;
  line-height: 0;
  font-variant-numeric: tabular-nums;
  color: var(--dim);
}
.filter a::after {
  content: "";
  position: absolute;
  left: 0;
  right: var(--ls-label);
  bottom: -23px;
  height: 1px;
  background: var(--text);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 0.6s var(--out);
}
.filter a:hover {
  color: var(--text);
}
.filter a[aria-current="true"] {
  color: var(--text);
}
.filter a[aria-current="true"]::after {
  transform: scaleX(1);
}
@media (max-width: 560px) {
  /* links wrap onto two lines here, so keep the underline under its own word */
  .filter a::after {
    bottom: 0;
  }
}

/* justified grid */
.jgrid {
  position: relative;
  transition: opacity 0.35s var(--ease);
  margin-bottom: clamp(80px, 14vh, 160px);
}
.jgrid.is-fading {
  opacity: 0;
}
.tile {
  position: absolute;
  top: 0;
  left: 0;
}
.tile-link {
  display: block;
}
.tile .ph {
  transition: filter 0.6s var(--ease);
}
/* captions are always visible (hover, no hover, touch): number + title,
   then place · year and the heart. Each row reserves --capband for them. */
.cap {
  display: flex;
  flex-wrap: nowrap;
  align-items: first baseline;
  justify-content: space-between;
  gap: 16px;
  padding-top: 12px;
}
.cap-l {
  grid-area: t;
  display: flex;
  align-items: baseline;
  gap: 10px;
  min-width: 0;
}
.cap-n {
  flex: none;
  color: var(--muted);
}
.cap-t {
  display: block;
  min-width: 0;
  overflow-wrap: break-word;
  font: var(--w-disp) var(--fs-body) / 1.35 var(--serif);
  color: var(--text);
}
.cap .like {
  flex: none;
  margin-left: auto;
}
@media (max-width: 559px) {
  .cap-t {
    font-size: var(--fs-small);
  }
}
.cap-p {
  grid-area: p;
  display: block;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font: 400 var(--fs-small) / var(--lh-small) var(--sans);
  color: var(--muted);
}
.cap .like {
  grid-area: a;
}
@media (hover: hover) {
}

/* ---------- SERIES PAGE (Rosso's editorial layout, Nocturne's palette + motion) ---------- */
.eb {
  font: 500 var(--fs-label) / var(--lh-label) var(--sans);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--muted);
  font-variant-numeric: tabular-nums lining-nums;
}
.s-head {
  position: relative;
  z-index: 1;
  padding: calc(var(--navh) + clamp(20px, 4vh, 40px)) var(--mx)
    var(--md, 32px);
}
.s-head > *,
.s-specs {
  max-width: var(--maxw);
  margin-left: auto;
  margin-right: auto;
}
.s-top {
  display: flex;
  justify-content: space-between;
  gap: var(--sm);
  padding-bottom: var(--xs);
  border-bottom: 1px solid var(--line);
  margin-bottom: var(--lg);
  animation: fadeup 1.4s var(--out) both;
}
.s-top .eb:first-child {
  color: var(--text);
}
.s-name {
  overflow: hidden;
  padding: 0.14em 0 0.12em;
  margin: -0.14em 0 -0.12em;
  font: var(--w-big) var(--fs-display) / var(--lh-display) var(--serif);
  letter-spacing: var(--ls-display);
  overflow-wrap: anywhere;
}
.s-name > span {
  display: block;
  animation: rise 1.5s var(--out) both 0.1s;
}
@keyframes rise {
  from {
    transform: translateY(104%);
  }
  to {
    transform: none;
  }
}
@keyframes fadeup {
  from {
    opacity: 0;
    transform: translateY(14px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}
.s-foot {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: end;
  gap: var(--md) var(--lg);
  margin-top: var(--md);
  animation: fadeup 1.4s var(--out) both 0.45s;
}
.s-blurb {
  max-width: 40ch;
  font: 400 var(--fs-sub) / var(--lh-sub) var(--sans);
  color: var(--body);
}
@media (max-width: 759px) {
  .s-foot {
    grid-template-columns: minmax(0, 1fr);
  }
}
.s-specs-wrap {
  position: relative;
  z-index: 1;
  padding: 0 var(--mx);
  animation: fadeup 1.4s var(--out) both 0.7s;
}
.specs {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
}
.spec {
  display: flex;
  flex-direction: column;
  gap: var(--xxs);
  min-width: 0;
}
.specs .spec {
  padding: var(--md) var(--sm) var(--sm);
  border-left: 1px solid var(--line);
}
.specs .spec:first-child {
  border-left: 0;
  padding-left: 0;
}
.spec-v {
  font: var(--w-big) var(--fs-title) / var(--lh-title) var(--serif);
  letter-spacing: var(--ls-title);
  font-variant-numeric: tabular-nums lining-nums;
  white-space: nowrap;
}
.spec-sub {
  color: var(--dim);
}
@media (max-width: 759px) {
  .specs {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
  .specs .spec:nth-child(3) {
    border-left: 0;
    padding-left: 0;
  }
  .specs .spec:nth-child(n + 3) {
    border-top: 1px solid var(--line);
  }
  .specs .spec {
    padding: var(--sm) var(--xs) var(--xs);
  }
}
.s-specs-wrap {
  overflow-x: clip;
}

/* editorial body: a full-width (contained) plate alternates with a two-up row */
.ed-list {
  --fullh: 82vh;
  --pairh: 70vh;
  --pgap: var(--md);
  position: relative;
  z-index: 1;
  padding: var(--sm, 24px) var(--mx) 0;
  max-width: calc(var(--widew) + var(--mx) * 2);
  margin: 0 auto;
}
@supports (height: 1svh) {
  .ed-list {
    --fullh: 82svh;
    --pairh: 70svh;
  }
}
.ed + .ed {
  margin-top: var(--band);
}
.fig-link {
  display: block;
}
.fig-link:focus-visible {
  outline-offset: 6px;
}
.fig-link .ph {
  transition: filter 0.6s var(--ease);
}
@media (hover: hover) {
  .fig-link:hover .ph {
    filter: brightness(1.06);
  }
}
.ed-full .fig {
  width: min(100%, calc(var(--fullh) * var(--ar)));
  margin: 0 auto;
}
.ed-pair {
  display: flex;
  align-items: flex-start;
  gap: var(--pgap);
  width: min(100%, calc(var(--pairh) * var(--sum) + var(--pgap)));
  margin: 0 auto;
}
.ed-pair .fig {
  flex-basis: 0;
  flex-shrink: 1;
  min-width: 0;
}
/* caption band */
.fc {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: start;
  gap: 0 var(--sm);
  margin-top: var(--xxs);
  padding-top: var(--xs);
  border-top: 1px solid var(--line);
}
.fc-n {
  padding-top: 5px;
  min-width: var(--xl);
}
.fc-n .cur {
  color: var(--text);
}
.fc-text {
  display: block;
  min-width: 0;
}
.fc-t {
  display: block;
  overflow-wrap: anywhere;
  font: var(--w-disp) var(--fs-sub) / var(--lh-sub) var(--serif);
  letter-spacing: 0;
}
.fc-p {
  display: block;
  margin-top: 2px;
  font: 400 var(--fs-body) / var(--lh-body) var(--sans);
  color: var(--muted);
}
.fc-p em {
  font-style: normal;
}
.fc-x {
  display: block;
  margin-top: var(--xxxs);
  font: 400 var(--fs-small) / var(--lh-small) var(--sans);
  letter-spacing: 0.02em;
  text-transform: none;
  color: var(--dim);
}
.fc-act {
  padding-top: 4px;
}
@media (max-width: 1099px) {
  .ed-pair .fc {
    grid-template-columns: minmax(0, 1fr) auto;
  }
  .ed-pair .fc-n {
    grid-column: 1 / -1;
    padding: 0 0 var(--xxxs);
  }
}
/* a portrait in a full slot: the caption moves beside it */
@media (min-width: 960px) {
  .ed-full.is-tall .fig {
    display: flex;
    align-items: flex-end;
    justify-content: center;
    gap: var(--lg);
    width: 100%;
  }
  .ed-full.is-tall .fig-link {
    flex: none;
    width: min(
      calc(100% - 280px - var(--lg)),
      calc(var(--fullh) * var(--ar))
    );
  }
  .ed-full.is-tall .fc {
    flex: none;
    width: 280px;
    grid-template-columns: minmax(0, 1fr);
    gap: var(--xs);
    margin-top: 0;
    padding-top: var(--sm);
  }
  .ed-full.is-tall .fc-n {
    padding-top: 0;
  }
  .ed-full.is-tall .fc-t {
    white-space: normal;
  }
}
@media (max-width: 639px) {
  .ed-pair {
    flex-direction: column;
    gap: var(--lg);
    width: 100%;
  }
  .ed-pair .fig {
    flex: none !important;
    width: 100%;
  }
  .ed-list {
    --fullh: 76svh;
  }
  .fc {
    grid-template-columns: minmax(0, 1fr) auto;
  }
  .fc-n {
    grid-column: 1 / -1;
    padding: 0 0 var(--xxxs);
  }
}

.s-next {
  position: relative;
  z-index: 1;
  margin-top: var(--band);
  padding: var(--band) var(--mx);
  border-top: 1px solid var(--line);
}
.s-next-in {
  max-width: var(--maxw);
  margin: 0 auto;
  display: grid;
  gap: var(--sm);
}
.s-next-link {
  justify-self: start;
  display: inline-flex;
  align-items: baseline;
  gap: 0.3em;
  max-width: 100%;
  font: var(--w-disp) var(--fs-title) / var(--lh-title) var(--serif);
  letter-spacing: var(--ls-title);
  overflow-wrap: anywhere;
  transition: color 0.4s;
}
.s-next-link .arr {
  font-size: var(--fs-sub);
  color: var(--muted);
  transition:
    transform 0.7s var(--out),
    color 0.4s;
}
.s-next-link:hover {
  font-style: italic;
}
.s-next-link:hover .arr {
  transform: translateX(0.3em);
  color: var(--text);
}
.s-next .btn-row {
  margin-top: var(--xs);
}
/* ---------- ABOUT ---------- */
.about-lede {
  grid-column: 1/-1;
  max-width: 22ch;
  font: var(--w-big) var(--fs-display) / var(--lh-display) var(--serif);
  letter-spacing: var(--ls-display);
}
.about-lede em {
  color: var(--muted);
}
.about-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 64px;
  padding: clamp(40px, 7vh, 80px) 0 clamp(80px, 14vh, 160px);
  border-top: 1px solid var(--line);
}
@media (min-width: 960px) {
  .about-grid {
    grid-template-columns: minmax(0, 5fr) minmax(0, 6fr);
    gap: 6vw;
  }
}
.about-bio p + p {
  margin-top: 1.2em;
}
.about-bio .lbl {
  margin-bottom: 22px;
}
.bio-lg {
  font: 400 var(--fs-sub) / var(--lh-sub) var(--sans);
  color: var(--text);
}
.about-bio p:not(.lbl):not(.bio-lg) {
  color: var(--body);
  max-width: 52ch;
}
.kit {
  display: grid;
}
.kit-row {
  display: grid;
  grid-template-columns: 120px 1fr;
  gap: 20px;
  padding: 22px 0;
  border-bottom: 1px solid var(--line);
}
.kit-row:first-child {
  border-top: 1px solid var(--line);
}
.kit-row dt {
  padding-top: 5px;
}
.kit-name {
  display: block;
  font: 500 var(--fs-body) / var(--lh-body) var(--sans);
}
.kit-note {
  display: block;
  margin-top: 3px;
  font: 500 var(--fs-label) / var(--lh-label) var(--sans);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--muted);
}
.lens-list li + li {
  margin-top: 14px;
}
.kit a {
  background-image: linear-gradient(currentColor, currentColor);
  background-size: 0 1px;
  background-repeat: no-repeat;
  background-position: 0 100%;
  transition: background-size 0.6s var(--out);
}
.kit a:hover {
  background-size: 100% 1px;
}
@media (max-width: 759px) {
  .kit-row {
    grid-template-columns: 1fr;
    gap: 8px;
  }
}

/* ---------- VIEWER ---------- */
.viewer {
  position: fixed;
  inset: 0;
  z-index: 50;
  container-type: size;
  color: var(--text);
  background: rgb(255 255 255 / var(--fade, 1));
  --pt: 72px;
  --pb: 104px;
  --px: 104px;
  --pr: 0px;
  opacity: 0;
  visibility: hidden;
  transition:
    opacity 0.5s var(--ease),
    visibility 0s linear 0.5s;
  overscroll-behavior: contain;
}
.viewer.is-open {
  opacity: 1;
  visibility: visible;
  transition: opacity 0.5s var(--ease);
}
@media (min-width: 1100px) {
  .viewer.info-open {
    --pr: 384px;
  }
}
@media (max-width: 759px) {
  .viewer {
    --pt: 56px;
    --pb: 118px;
    --px: 0px;
  }
}
.v-ambient {
  position: absolute;
  inset: 0;
  pointer-events: none;
  overflow: hidden;
  opacity: calc(0.4 * var(--fade, 1));
}
.v-ambient i {
  position: absolute;
  left: 50%;
  top: 48%;
  width: 150cqw;
  height: 135cqh;
  transform: translate(calc(-50% - var(--pr) / 2), -50%);
  background-color: var(--glow, hsl(212 20% 90%));
  -webkit-mask-image: radial-gradient(
    closest-side,
    #000 0%,
    rgba(0, 0, 0, 0.6) 30%,
    rgba(0, 0, 0, 0.18) 62%,
    transparent 100%
  );
  mask-image: radial-gradient(
    closest-side,
    #000 0%,
    rgba(0, 0, 0, 0.6) 30%,
    rgba(0, 0, 0, 0.18) 62%,
    transparent 100%
  );
  transition:
    background-color 1.6s var(--ease),
    transform 0.7s var(--out);
}
.v-stage {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--pt) calc(var(--px) + var(--pr)) var(--pb) var(--px);
  touch-action: none;
  user-select: none;
  -webkit-user-select: none;
  transition: padding 0.7s var(--out);
}
.v-frame {
  position: relative;
  width: min(
    100%,
    calc((100cqh - var(--pt) - var(--pb)) * var(--ar, 1.5))
  );
  aspect-ratio: var(--ar, 1.5);
  background: var(--raised);
  transition:
    opacity 0.28s var(--ease),
    transform 0.6s var(--out);
}
.v-frame img {
  display: block;
  width: 100%;
  height: auto;
  opacity: 0;
  transition: opacity 0.45s var(--ease);
}
.v-frame img.is-loaded {
  opacity: 1;
}
.v-frame.leave-l {
  opacity: 0;
  transform: translateX(-28px);
}
.v-frame.leave-r {
  opacity: 0;
  transform: translateX(28px);
}

.v-bar {
  position: absolute;
  left: 0;
  right: 0;
  z-index: 3;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  padding: 0 clamp(18px, 2.4vw, 36px);
  transition:
    opacity 0.6s var(--ease),
    transform 0.6s var(--out),
    right 0.7s var(--out);
}
.v-top {
  top: 0;
  height: var(--pt);
  padding-top: env(safe-area-inset-top);
}
.v-bottom {
  bottom: 0;
  height: var(--pb);
  right: var(--pr);
  padding-bottom: env(safe-area-inset-bottom);
}
.v-bar,
.v-edge {
  opacity: calc(var(--fade, 1));
}
.viewer.ui-hidden {
  cursor: none;
}
.viewer.ui-hidden .v-bar,
.viewer.ui-hidden .v-edge {
  opacity: 0;
  pointer-events: none;
}
.viewer.ui-hidden .v-top {
  transform: translateY(-10px);
}
.viewer.ui-hidden .v-bottom {
  transform: translateY(10px);
}
.v-count {
  display: flex;
  align-items: center;
  gap: 6px;
}
.v-num {
  min-width: 76px;
  text-align: center;
  font: 500 var(--fs-label) / var(--lh-label) var(--sans);
  letter-spacing: var(--ls-label);
  font-variant-numeric: tabular-nums;
}
.v-num b {
  font-weight: 500;
  color: var(--text);
}
.v-ctx {
  margin-left: 18px;
  padding-left: 20px;
  border-left: 1px solid var(--line);
}
.ibtn {
  display: inline-grid;
  place-items: center;
  width: 40px;
  height: 40px;
  color: var(--muted);
  transition: color 0.3s;
}
.ibtn:hover {
  color: var(--text);
}
.ibtn svg {
  width: 18px;
  height: 18px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.2;
}
.v-close {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  height: 40px;
  padding: 0 4px;
  color: var(--muted);
  transition: color 0.3s;
}
.v-close:hover {
  color: var(--text);
}
.v-close svg {
  width: 16px;
  height: 16px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.2;
}
.v-meta {
  min-width: 0;
}
.v-title {
  overflow-wrap: anywhere;
  font: var(--w-disp) var(--fs-sub) / var(--lh-sub) var(--serif);
  letter-spacing: 0;
}
.v-place {
  margin-top: 2px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font: 400 var(--fs-body) / var(--lh-body) var(--sans);
  color: var(--muted);
}
.v-place em {
  font-style: normal;
}
.v-actions {
  display: flex;
  align-items: center;
  gap: clamp(20px, 2.4vw, 36px);
  flex: none;
}
.v-actions .like {
  font-size: var(--fs-small);
}
.v-actions .like svg {
  width: 20px;
  height: 20px;
}
.tbtn {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding: 10px 0;
  font: 500 var(--fs-label) / var(--lh-label) var(--sans);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--muted);
  transition: color 0.3s;
}
.tbtn:hover,
.tbtn[aria-expanded="true"] {
  color: var(--text);
}
.tbtn svg {
  width: 17px;
  height: 17px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.2;
}
.v-edge {
  position: absolute;
  top: 50%;
  z-index: 2;
  width: var(--px);
  height: min(46cqh, 420px);
  transform: translateY(-50%);
  display: grid;
  place-items: center;
  color: var(--muted);
  transition:
    color 0.3s,
    opacity 0.6s var(--ease),
    right 0.7s var(--out);
}
.v-edge:hover {
  color: var(--text);
}
.v-edge svg {
  width: 26px;
  height: 26px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1;
  transition: transform 0.5s var(--out);
}
.v-prev {
  left: 0;
}
.v-next {
  right: var(--pr);
}
.v-prev:hover svg {
  transform: translateX(-4px);
}
.v-next:hover svg {
  transform: translateX(4px);
}
@media (max-width: 759px) {
  .v-edge {
    display: none;
  }
  .v-ctx {
    display: none;
  }
  .v-close span {
    display: none;
  }
  .v-bottom {
    align-items: flex-start;
    padding-top: 18px;
  }
  .v-actions {
    gap: 22px;
    padding-top: 4px;
  }
  .tbtn span {
    display: none;
  }
}
.v-info {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  z-index: 4;
  width: min(384px, 100%);
  overflow-y: auto;
  overscroll-behavior: contain;
  background: #fafaf9;
  border-left: 1px solid var(--line);
  padding: 28px 34px 40px;
  transform: translateX(101%);
  transition:
    transform 0.7s var(--out),
    visibility 0s linear 0.7s;
  visibility: hidden;
}
.viewer.info-open .v-info {
  transform: none;
  visibility: visible;
  transition: transform 0.7s var(--out);
}
.v-info-head {
  display: flex;
  justify-content: space-between;
  align-items: center;
  height: 44px;
  margin-bottom: 36px;
}
.v-info-head .ibtn {
  margin-right: -10px;
}
.vi-title {
  font: var(--w-disp) var(--fs-title) / var(--lh-title) var(--serif);
  letter-spacing: var(--ls-title);
}
.vi-place {
  margin-top: 8px;
  font: 400 var(--fs-body) / var(--lh-body) var(--sans);
  color: var(--muted);
}
.vi-place em {
  font-style: normal;
}
.exif {
  margin-top: 34px;
  width: 100%;
  border-collapse: collapse;
}
.exif th,
.exif td {
  padding: 13px 0;
  border-bottom: 1px solid var(--line);
  text-align: left;
  vertical-align: baseline;
}
.exif tr:first-child th,
.exif tr:first-child td {
  border-top: 1px solid var(--line);
}
.exif th {
  width: 42%;
  font: 500 var(--fs-label) / var(--lh-label) var(--sans);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--muted);
}
.exif td {
  font: 400 var(--fs-small) / var(--lh-small) var(--sans);
  font-variant-numeric: tabular-nums lining-nums;
  color: var(--text);
}
.vi-note {
  margin-top: 28px;
  font: 400 var(--fs-small) / var(--lh-small) var(--sans);
  color: var(--muted);
}
.vi-keys {
  margin-top: 32px;
  display: flex;
  flex-wrap: wrap;
  gap: 10px 18px;
}
.vi-keys kbd {
  display: inline-block;
  min-width: 20px;
  margin-right: 6px;
  padding: 3px 5px;
  border: 1px solid var(--line);
  font: 500 var(--fs-label) / 1 var(--sans);
  text-align: center;
  color: var(--text);
}
@media (hover: none) {
  .vi-keys {
    display: none;
  }
}

.v-burst {
  position: absolute;
  inset: 0;
  z-index: 6;
  pointer-events: none;
  overflow: hidden;
}
.burst {
  position: absolute;
  width: 0;
  height: 0;
}
.burst svg {
  position: absolute;
  left: -70px;
  top: -70px;
  width: 140px;
  height: 140px;
  fill: var(--heart);
  filter: drop-shadow(0 8px 24px rgba(224, 54, 122, 0.35));
  animation: burst 1.05s var(--out) forwards;
}
.burst-ring {
  position: absolute;
  left: -64px;
  top: -64px;
  width: 128px;
  height: 128px;
  border: 1.5px solid rgba(224, 54, 122, 0.7);
  border-radius: 50%;
  animation: ring 0.9s var(--out) forwards;
}
@keyframes burst {
  0% {
    opacity: 0;
    transform: scale(0.2);
  }
  16% {
    opacity: 1;
    transform: scale(1.14);
  }
  30% {
    transform: scale(0.95);
  }
  44% {
    transform: scale(1);
  }
  72% {
    opacity: 1;
    transform: scale(1) translateY(0);
  }
  100% {
    opacity: 0;
    transform: scale(1.04) translateY(-26px);
  }
}
@keyframes ring {
  0% {
    opacity: 0.9;
    transform: scale(0.35);
  }
  100% {
    opacity: 0;
    transform: scale(2.3);
  }
}

/* toast */
.toast {
  position: fixed;
  left: 50%;
  bottom: calc(32px + env(safe-area-inset-bottom));
  z-index: 90;
  transform: translate(-50%, 12px);
  padding: 13px 20px;
  background: var(--text);
  border: 1px solid var(--text);
  font: 500 var(--fs-label) / var(--lh-label) var(--sans);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--bg);
  opacity: 0;
  pointer-events: none;
  transition:
    opacity 0.4s var(--ease),
    transform 0.5s var(--out);
}
.toast.show {
  opacity: 1;
  transform: translate(-50%, 0);
}

/* ================= HOVER: the photo lifts a little ================= */
.tile-link,
.plate-link,
.fig-link,
.prow-thumb .ph,
.smenu-thumb {
  transition:
    transform 0.55s var(--out),
    box-shadow 0.55s var(--out);
}
.tile-link .ph,
.plate-link .ph,
.fig-link .ph {
  transition: box-shadow 0.55s var(--out);
}
@media (hover: hover) {
  .tile-link:hover,
  .fig-link:hover {
    transform: translateY(-6px) scale(1.015);
  }
  .plate-link:hover {
    transform: translateY(-6px) scale(1.008);
  }
  .tile-link:hover .ph,
  .plate-link:hover .ph,
  .fig-link:hover .ph {
    box-shadow: 0 22px 44px -18px rgba(18, 20, 23, 0.35);
  }
  .prow:hover .prow-thumb .ph,
  .smenu a:hover .smenu-thumb {
    transform: translateY(-4px) scale(1.04);
    box-shadow: 0 14px 30px -12px rgba(18, 20, 23, 0.35);
  }
  .plate-link:hover .ph,
  .fig-link:hover .ph,
  .tile:hover .ph {
    filter: none;
  }
}
/* ================= MOTION ON SCROLL =================
   Photos rise into place as they arrive, captions follow a beat later.
   The revealed state waits for the intro to end (html:not(.has-intro)). */
.fitem .ph {
  opacity: 0;
  transform: translateY(48px) scale(0.97);
  transition:
    opacity 1.1s var(--ease),
    transform 1.6s var(--out),
    filter 0.6s var(--ease);
}
html:not(.has-intro) .fitem.is-in .ph {
  opacity: 1;
  transform: none;
}
.lower > * {
  opacity: 0;
  transform: translateY(16px);
  transition:
    opacity 1s var(--ease),
    transform 1.4s var(--out);
}
html:not(.has-intro) .fitem.is-in .lower > * {
  opacity: 1;
  transform: none;
  transition-delay: 0.35s;
}
html:not(.has-intro) .fitem.is-in .lower > :nth-child(2) {
  transition-delay: 0.5s;
}
html:not(.has-intro) .fitem.is-in .lower > :nth-child(3) {
  transition-delay: 0.65s;
}
.fig {
  opacity: 0;
  transform: translateY(40px);
  transition:
    opacity 1.1s var(--ease),
    transform 1.5s var(--out);
}
html:not(.has-intro) .fig.is-in {
  opacity: 1;
  transform: none;
}
.ed-pair .fig:nth-child(2) {
  transition-delay: 0.16s;
}
.fc > * {
  opacity: 0;
  transform: translateY(10px);
  transition:
    opacity 0.9s var(--ease) 0.35s,
    transform 1.2s var(--out) 0.35s;
}
html:not(.has-intro) .fig.is-in .fc > * {
  opacity: 1;
  transform: none;
}
/* work tiles, programme rows, page heads, series numbers: a short stagger */
.rv {
  opacity: 0;
  translate: 0 26px;
  transition:
    opacity 0.9s var(--ease) var(--rd, 0s),
    translate 1.2s var(--out) var(--rd, 0s);
}
html:not(.has-intro) .rv.is-in {
  opacity: 1;
  translate: none;
}
.plist > li.rv {
  translate: -28px 0;
}

/* ================= INTRO =================
   Every load: a white stage, the logo builds large, the letters of the
   name rise in the logo's colours and settle to ink, the series line
   opens out, a gradient line fills as the photos load. Then the logo
   and name fly into the nav while the white lifts off the page. */
.intro {
  display: none;
}
html.has-intro .intro,
.intro.is-leaving {
  display: block;
  position: fixed;
  inset: 0;
  z-index: 300;
}
.intro.is-leaving {
  pointer-events: none;
}
.intro-curtain {
  position: absolute;
  inset: 0;
  overflow: hidden;
  background: var(--bg);
  clip-path: inset(0 0 0 0);
  transition: clip-path 1.05s cubic-bezier(0.76, 0, 0.24, 1) 0.3s;
}
.intro.is-leaving .intro-curtain {
  clip-path: inset(0 0 100% 0);
}
.intro-orb {
  position: absolute;
  left: 50%;
  top: 50%;
  width: min(110vw, 1100px);
  aspect-ratio: 1;
  translate: -50% -50%;
  border-radius: 50%;
  background: conic-gradient(
    from 0deg,
    rgba(47, 107, 255, 0.14),
    rgba(224, 54, 122, 0.12),
    rgba(255, 122, 89, 0.12),
    rgba(47, 107, 255, 0.14)
  );
  -webkit-mask-image: radial-gradient(closest-side, #000, transparent);
  mask-image: radial-gradient(closest-side, #000, transparent);
  animation:
    orbIn 2.4s var(--out) both,
    orbSpin 14s linear infinite;
}
@keyframes orbIn {
  from {
    opacity: 0;
    scale: 0.35;
  }
}
@keyframes orbSpin {
  to {
    rotate: 360deg;
  }
}
.intro-stage {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 28px;
  font-size: var(--ifs, 64px);
  color: var(--text);
}
.intro-mark {
  display: flex;
  align-items: center;
  gap: 0.42em;
}
.intro.stacked .intro-tag {
  --ls0: 0.45em;
  --ls1: 0.2em;
  font-size: 11px;
}
.intro.stacked .intro-mark {
  flex-direction: column;
  gap: 0.5em;
}
.intro-mark .logo {
  width: var(--il, 1.6em);
  height: var(--il, 1.6em);
  transform-origin: 0 0;
  --d0: 0.15s;
}
.intro-name {
  display: inline-flex;
  overflow: hidden;
  padding: 0.06em 0.04em 0.2em;
  margin: -0.06em -0.04em -0.2em;
  font: 400 1em / 1.15 var(--serif);
  letter-spacing: -0.012em;
  white-space: nowrap;
  transform-origin: 0 0;
}
.intro-name .ch {
  display: inline-block;
  color: var(--c, var(--text));
  opacity: 0;
  transform: translateY(110%) rotate(9deg);
  transform-origin: 0 100%;
  animation:
    chIn 1s var(--out) forwards,
    chInk 1.1s var(--ease) forwards;
  animation-delay:
    calc(0.95s + var(--i) * 42ms), calc(1.75s + var(--i) * 42ms);
}
.intro-name .sp {
  width: 0.26em;
}
@keyframes chIn {
  to {
    opacity: 1;
    transform: none;
  }
}
@keyframes chInk {
  to {
    color: var(--text);
  }
}
.intro-tag {
  --ls0: 1.1em;
  --ls1: 0.42em;
  white-space: nowrap;
  padding-left: var(--ls1);
  font: 500 var(--fs-small) / 1 var(--sans);
  letter-spacing: var(--ls1);
  text-transform: uppercase;
  color: var(--muted);
  opacity: 0;
  animation: tagIn 1.6s var(--out) 2.05s forwards;
}
@keyframes tagIn {
  from {
    opacity: 0;
    letter-spacing: var(--ls0);
  }
  to {
    opacity: 1;
    letter-spacing: var(--ls1);
  }
}
.intro-bar {
  width: min(220px, 50vw);
  height: 2px;
  overflow: hidden;
  background: var(--line);
  opacity: 0;
  animation: barIn 0.6s var(--ease) 2.2s forwards;
}
.intro-bar i {
  display: block;
  height: 100%;
  background: linear-gradient(100deg, #2f6bff, #e0367a 55%, #ff7a59);
  transform: scaleX(var(--p, 0));
  transform-origin: left;
  transition: transform 0.7s var(--out);
}
@keyframes barIn {
  to {
    opacity: 1;
  }
}
.intro.is-leaving .intro-tag,
.intro.is-leaving .intro-bar {
  animation: none;
  opacity: 0;
}
/* the page waits under the white: its own entrance plays when the intro ends */
html.has-intro,
html.has-intro body {
  overflow: hidden;
}
html.has-intro main,
html.has-intro main * {
  animation-play-state: paused !important;
}
html.has-intro .nav .brand {
  visibility: hidden;
}
html.has-intro .nav-links {
  opacity: 0;
  translate: 0 -8px;
}
.nav-links {
  transition:
    opacity 0.8s var(--ease) 0.9s,
    translate 0.9s var(--out) 0.9s;
}
@media (prefers-reduced-motion: reduce) {
  .fitem .ph,
  .lower > *,
  .fig,
  .fc > *,
  .rv {
    opacity: 1 !important;
    transform: none !important;
    translate: none !important;
  }
}
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-delay: 0s !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    transition-delay: 0s !important;
    scroll-behavior: auto !important;
  }
  .lower > *,
  .fig,
  .fc > * {
    opacity: 1;
    transform: none;
  }
  .fitem .ph {
    transform: none;
  }
  .burst svg {
    animation: none;
    opacity: 0;
  }
}
/* series page: the series line runs up the right edge, fixed while you scroll */
.s-head > *,
.s-specs {
  max-width: none;
}
.s-top {
  position: fixed;
  top: 50%;
  right: calc(var(--mx) / 2);
  z-index: 15;
  flex-direction: row;
  justify-content: flex-start;
  align-items: center;
  gap: 28px;
  margin: 0;
  padding: 0;
  border: 0;
  writing-mode: vertical-rl;
  transform: translate(50%, -50%) rotate(180deg);
  animation: sideIn 1.2s var(--ease) both 0.3s;
}
.s-top .eb {
  white-space: nowrap;
}
@keyframes sideIn {
  from {
    opacity: 0;
  }
}
html.has-intro .s-top {
  opacity: 0;
}
@media (max-width: 699px) {
  .s-top {
    display: none;
  }
}
@media (min-width: 700px) {
  html[data-view="story"] .s-head,
  html[data-view="series"] .s-head,
  html[data-view="series"] .ed-list,
  html[data-view="series"] .s-next,
  html[data-view="series"] .foot {
    padding-right: 64px;
  }
  .s-top {
    right: 32px;
  }
}

/* ================= JOURNAL =================
   Only the photographs with a story. The index leads with one story
   large, the rest follow in staggered columns; a story reads as a
   sequence of wide frames, photos with their backstory beside them,
   staggered pairs, paragraphs and a line set large. */
.j-head {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: flex-end;
  gap: 12px 32px;
  padding: calc(var(--navh) + clamp(20px, 4vh, 40px)) var(--mx)
    clamp(28px, 5vh, 48px);
}
.j-title {
  overflow: hidden;
  padding: 0.14em 0 0.1em;
  margin: -0.14em 0 -0.1em;
  font: var(--w-big) var(--fs-display) / var(--lh-display) var(--serif);
  letter-spacing: var(--ls-display);
}
.j-title > span,
.st-title > span {
  display: block;
  animation: rise 1.5s var(--out) both 0.1s;
}
.j-sub {
  color: var(--muted);
}
.jcard {
  display: block;
  color: var(--text);
}
.jc-cover {
  display: block;
  width: min(100%, calc(var(--ch, 72vh) * var(--ar)));
  transition:
    transform 0.6s var(--out),
    box-shadow 0.6s var(--out);
}
.jc-text {
  display: block;
}
.jc-tags {
  display: block;
  margin: 18px 0 10px;
}
.jc-title {
  display: block;
  font: var(--w-disp) var(--fs-title) / var(--lh-title) var(--serif);
  letter-spacing: var(--ls-title);
}
.jc-ex {
  display: block;
  max-width: 42ch;
  margin-top: 10px;
  color: var(--body);
}
.jc-more {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  margin-top: 18px;
  color: var(--text);
}
.jc-more .arr {
  transition: transform 0.5s var(--out);
}
@media (hover: hover) {
  .jcard:hover .jc-cover {
    transform: translateY(-6px) scale(1.01);
    box-shadow: 0 24px 48px -20px rgba(18, 20, 23, 0.38);
  }
  .jcard:hover .jc-more .arr,
  a.jc-more:hover .arr {
    transform: translateX(6px);
  }
}
/* the lead story: cover large, words beside it */
.jcard-big {
  display: grid;
  grid-template-columns: minmax(0, 1.5fr) minmax(0, 1fr);
  align-items: end;
  gap: clamp(24px, 4vw, 72px);
  padding: 0 var(--mx);
  --ch: 76vh;
}
.jcard-big .jc-title {
  font: var(--w-big) var(--fs-display) / var(--lh-display) var(--serif);
  letter-spacing: var(--ls-display);
}
.jcard-big .jc-ex {
  font: 300 var(--fs-sub) / 1.55 var(--serif);
}
.jcard-big .jc-text {
  padding-bottom: 8px;
}
.j-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  align-items: start;
  gap: clamp(48px, 8vh, 96px) clamp(20px, 3vw, 48px);
  padding: clamp(72px, 12vh, 140px) var(--mx) 0;
  --ch: 64vh;
}
.j-grid .jcard:nth-child(3n + 2) {
  margin-top: clamp(48px, 10vh, 120px);
}
.j-grid .jcard:nth-child(3n + 3) {
  margin-top: clamp(20px, 4vh, 48px);
}
.home-journal {
  position: relative;
  z-index: 1;
  padding: 0 var(--mx) clamp(48px, 8vh, 96px);
}
/* a hairline divides the work from the journal */
.home-journal::before {
  content: "";
  display: block;
  height: 1px;
  margin-bottom: clamp(28px, 5vh, 48px);
  background: var(--line-2);
}
html[data-view="home"] .jgrid {
  margin-bottom: clamp(40px, 6vh, 64px);
}
.hj-head {
  display: flex;
  justify-content: space-between;
  align-items: flex-end;
  gap: 24px;
}
.home-journal .j-grid {
  padding: clamp(32px, 6vh, 56px) 0 0;
}
@media (max-width: 999px) {
  .j-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
  .j-grid .jcard:nth-child(n) {
    margin-top: 0;
  }
  .j-grid .jcard:nth-child(2n) {
    margin-top: clamp(40px, 8vh, 96px);
  }
}
@media (max-width: 699px) {
  .jcard-big {
    grid-template-columns: minmax(0, 1fr);
  }
  .j-grid {
    grid-template-columns: minmax(0, 1fr);
  }
  .j-grid .jcard:nth-child(n) {
    margin-top: 0;
  }
}

/* ---------- a story ---------- */
.st-head {
  max-width: 1100px;
  margin: 0 auto;
  padding: calc(var(--navh) + clamp(28px, 6vh, 64px)) var(--mx) 0;
  text-align: center;
}
.st-tags {
  display: block;
}
.st-title {
  overflow: hidden;
  margin: 14px 0 0;
  padding: 0.14em 0 0.12em;
  font: var(--w-big) calc(var(--fs-display) * 1.35) / 1.02 var(--serif);
  letter-spacing: var(--ls-display);
}
.st-meta {
  margin-top: 14px;
  color: var(--muted);
}
.st-intro {
  max-width: 32em;
  margin: 32px auto 0;
  font: 300 var(--fs-sub) / 1.65 var(--serif);
  color: var(--body);
}
.st-body {
  display: grid;
  gap: clamp(72px, 12vh, 150px);
  padding: clamp(56px, 9vh, 104px) var(--mx) 0;
}
.sfig {
  margin: 0;
}
.jb-wide .sfig {
  width: min(100%, calc(84vh * var(--ar)));
  margin: 0 auto;
}
.jb-note {
  display: grid;
  grid-template-columns: minmax(0, 7fr) minmax(0, 4fr);
  align-items: end;
  gap: clamp(24px, 5vw, 96px);
  width: 100%;
  max-width: 1500px;
  margin: 0 auto;
}
.jb-note.is-right {
  grid-template-columns: minmax(0, 4fr) minmax(0, 7fr);
}
.jb-note.is-right .sfig {
  order: 2;
  justify-self: end;
}
.jb-note .sfig {
  width: min(100%, calc(80vh * var(--ar)));
}
.note {
  max-width: 24em;
  padding-bottom: clamp(40px, 8vh, 96px);
}
.jb-note.is-right .note {
  justify-self: end;
}
.note p {
  font: 300 var(--fs-sub) / 1.65 var(--serif);
  color: var(--body);
}
.note-line {
  display: block;
  width: 56px;
  height: 2px;
  margin-bottom: 22px;
  background: linear-gradient(100deg, #2f6bff, #e0367a 55%, #ff7a59);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 1.2s var(--out) 0.5s;
}
html:not(.has-intro) .jb.is-in .note-line {
  transform: none;
}
.jb-pair {
  display: flex;
  align-items: flex-start;
  gap: clamp(20px, 5vw, 96px);
  width: min(100%, calc(66vh * var(--sum) + 96px));
  margin: 0 auto;
}
.jb-pair .sfig {
  flex: var(--ar) 1 0;
  min-width: 0;
}
.jb-pair .sfig:nth-child(2) {
  margin-top: clamp(56px, 14vh, 180px);
}
.jb-text {
  max-width: 32em;
  margin: 0 auto;
}
.jb-text p {
  font: 300 var(--fs-sub) / 1.75 var(--serif);
  color: var(--body);
}
.jb-quote {
  max-width: min(100%, 980px);
  margin: 0 auto;
  text-align: center;
}
.jb-quote p {
  font: italic var(--w-big) var(--fs-display) / 1.15 var(--serif);
  letter-spacing: var(--ls-display);
}
.st-next {
  padding: clamp(96px, 16vh, 200px) var(--mx) 0;
  text-align: center;
}
.st-next-link {
  display: inline-block;
  margin: 16px 0 32px;
  font: var(--w-big) var(--fs-display) / var(--lh-display) var(--serif);
  letter-spacing: var(--ls-display);
}
.st-next-link .arr {
  display: inline-block;
  transition: transform 0.5s var(--out);
}
.st-next-link:hover .arr {
  transform: translateX(10px);
}
.st-next .btn-row {
  justify-content: center;
}
@media (min-width: 700px) {
  html[data-view="story"] .st-head,
  html[data-view="story"] .st-body,
  html[data-view="story"] .st-next,
  html[data-view="story"] .foot {
    padding-right: 64px;
  }
}
@media (max-width: 699px) {
  .jb-note,
  .jb-note.is-right {
    grid-template-columns: minmax(0, 1fr);
  }
  .jb-note.is-right .sfig {
    order: 0;
  }
  .note {
    padding-bottom: 0;
  }
  .jb-pair {
    flex-direction: column;
    width: 100%;
  }
  .jb-pair .sfig {
    flex: none;
    width: 100%;
  }
  .jb-pair .sfig:nth-child(2) {
    margin-top: 0;
    width: 78%;
    align-self: flex-end;
  }
}

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}
/* ================= HOME: full-screen hero, then the work, then the journal ================= */
.fhero {
  position: relative;
  z-index: 2;
  height: 100vh;
  height: 100svh;
  min-height: 480px;
  overflow: hidden;
  background: #0c0d0f;
  color: #fff;
}
.fh-slide {
  position: absolute;
  inset: 0;
  display: block;
  opacity: 0;
  visibility: hidden;
  transition:
    opacity 1.3s var(--ease),
    visibility 0s 1.3s;
}
.fh-slide.is-on {
  z-index: 1;
  opacity: 1;
  visibility: visible;
  transition: opacity 1.3s var(--ease);
}
.fh-slide img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: var(--pos, 50% 50%);
  transform: scale(1.09);
  transition: transform 8s cubic-bezier(0.2, 0.6, 0.3, 1);
}
.fh-slide.is-on img {
  transform: scale(1);
}
html.has-intro .fh-slide.is-on img {
  transform: scale(1.09);
}
/* tall screens (phones, narrow windows): still full-screen, cropped to
   the middle of the photograph like justinbettman.com; a slide can name
   its own focus for tall screens with posTall in hero.js */
@media (max-aspect-ratio: 1/1) {
  .fh-slide img {
    object-position: var(--pos-tall, var(--pos, 50% 50%));
  }
}
.fh-scrim {
  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: none;
  background:
    linear-gradient(rgba(0, 0, 0, 0.38), transparent 22%),
    linear-gradient(transparent 55%, rgba(0, 0, 0, 0.6));
}
.fh-bar {
  position: absolute;
  left: var(--mx);
  right: var(--mx);
  bottom: clamp(20px, 5vh, 48px);
  z-index: 3;
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 24px;
}
.fh-cap {
  min-width: 0;
}
.fh-title {
  display: block;
  overflow: hidden;
  padding: 0.12em 0 0.1em;
  margin: -0.12em 0 -0.1em;
  font: var(--w-big) var(--fs-display) / var(--lh-display) var(--serif);
  letter-spacing: var(--ls-display);
}
.fh-title span,
.fh-place {
  display: block;
}
.fh-place {
  margin-top: 10px;
  color: rgba(255, 255, 255, 0.82);
}
.fh-cap.swap .fh-title span {
  animation: rise 1.1s var(--out) both;
}
.fh-cap.swap .fh-place {
  animation: fadeup 1.1s var(--out) both 0.15s;
}
.fh-index {
  display: flex;
  gap: 6px;
  margin-top: clamp(18px, 3vh, 28px);
}
.fh-index button {
  position: relative;
  padding: 10px 12px 12px 0;
  min-width: 44px;
  text-align: left;
  color: rgba(255, 255, 255, 0.6);
  font: 500 var(--fs-label) / 1 var(--sans);
  letter-spacing: var(--ls-label);
  transition: color 0.3s;
}
.fh-index button::after {
  content: "";
  position: absolute;
  left: 0;
  right: 12px;
  bottom: 2px;
  height: 1px;
  background: rgba(255, 255, 255, 0.3);
}
.fh-index button i {
  position: absolute;
  left: 0;
  right: 12px;
  bottom: 2px;
  z-index: 1;
  height: 1px;
  background: #fff;
  transform: scaleX(0);
  transform-origin: left;
}
.fh-index button[aria-current="true"] {
  color: #fff;
}
.fh-index button[aria-current="true"] i {
  animation: fhRun var(--dur, 6.5s) linear forwards;
}
.fhero.is-paused .fh-index button[aria-current="true"] i,
html.has-intro .fh-index button[aria-current="true"] i {
  animation-play-state: paused;
}
@keyframes fhRun {
  to {
    transform: scaleX(1);
  }
}
.fh-right {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 18px;
}
.fh-arrows {
  display: flex;
  gap: 10px;
}
.fh-arrows button {
  display: grid;
  place-items: center;
  width: 52px;
  height: 52px;
  border: 1px solid rgba(255, 255, 255, 0.45);
  border-radius: 50%;
  color: #fff;
  transition:
    background-color 0.35s var(--ease),
    border-color 0.35s var(--ease),
    transform 0.35s var(--out);
}
.fh-arrows button:hover {
  background: rgba(255, 255, 255, 0.14);
  border-color: #fff;
}
.fh-arrows button:active {
  transform: scale(0.94);
}
.fh-arrows svg {
  width: 18px;
  height: 18px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.5;
}
.fh-scroll {
  display: flex;
  align-items: center;
  gap: 12px;
  color: rgba(255, 255, 255, 0.85);
}
.fh-scroll i {
  position: relative;
  display: block;
  width: 1px;
  height: 36px;
  overflow: hidden;
  background: rgba(255, 255, 255, 0.3);
}
.fh-scroll i::after {
  content: "";
  position: absolute;
  inset: 0;
  background: #fff;
  animation: fhDrop 2.2s var(--ease) infinite;
}
@keyframes fhDrop {
  from {
    transform: translateY(-100%);
  }
  to {
    transform: translateY(100%);
  }
}
@media (max-width: 699px) {
  .fh-bar {
    flex-direction: column;
    align-items: stretch;
  }
  .fh-right {
    flex-direction: row;
    justify-content: space-between;
    align-items: center;
  }
  .fh-arrows button {
    width: 44px;
    height: 44px;
  }
}
/* the nav sits light over the photographs until the page scrolls past them */
html[data-view="home"] .nav:not(.is-solid) .brand,
html[data-view="home"] .nav:not(.is-solid) .logo,
html[data-view="home"] .nav:not(.is-solid) .nav-links a,
html[data-view="home"] .nav:not(.is-solid) .nav-links button {
  color: #fff;
}
html[data-view="home"] .page.work {
  padding-top: clamp(64px, 10vh, 112px);
}
#work {
  scroll-margin-top: calc(var(--navh) - 1px);
}
@media (prefers-reduced-motion: reduce) {
  .fh-slide img,
  .fh-slide.is-on img {
    transform: none;
  }
}

/* ================= VIEWER: one edge for everything =================
   Arrows, counter, title, Close, Share and the side arrows all sit on
   the same left and right lines (icons are optically inset in their
   boxes, so the boxes are pulled out by that inset). */
.viewer {
  --vpad: clamp(18px, 2.4vw, 36px);
}
.v-bar {
  padding-left: var(--vpad);
  padding-right: var(--vpad);
}
.v-count > .ibtn:first-child {
  margin-left: -16px;
}
.v-close {
  padding: 0;
  margin-right: -2px;
}
.v-prev {
  place-items: center start;
  padding-left: calc(var(--vpad) - 7px);
}
.v-next {
  place-items: center end;
  padding-right: calc(var(--vpad) - 7px);
}

/* ================= PHOTOS RISE INTO PLACE =================
   As a photo reaches the screen it travels up from well below and fades
   in, its caption moving with it as one piece. */
.rvg > * {
  opacity: 0;
  translate: 0 var(--rise, 240px);
  transition:
    opacity 1s var(--ease) var(--rd, 0s),
    translate 1.4s cubic-bezier(0.19, 1, 0.22, 1) var(--rd, 0s);
}
html:not(.has-intro) .rvg.is-in > * {
  opacity: 1;
  translate: none;
}
html:not(.has-intro) .rvg.is-in > :nth-child(2) {
  transition-delay: calc(var(--rd, 0s) + 0.12s);
}
.jb-text.rvg > *,
.jb-quote.rvg > * {
  --rise: 60px;
}

/* ================= TITLES RISE FROM BELOW =================
   Same travel and easing as the photographs. */
.rvt {
  overflow: hidden;
  padding: 0.14em 0 0.12em;
  margin-top: -0.14em;
  margin-bottom: -0.12em;
}
.rvt > .tl {
  display: block;
  translate: 0 110%;
  transition: translate 1.4s cubic-bezier(0.19, 1, 0.22, 1) 0.05s;
}
.rvt > .tl,
.j-title.rvt > span,
.st-title.rvt > span {
  animation: none;
}
.j-title.rvt > span,
.st-title.rvt > span {
  display: block;
  translate: 0 110%;
  transition: translate 1.4s cubic-bezier(0.19, 1, 0.22, 1) 0.05s;
}
html:not(.has-intro) .rvt.is-in > .tl,
html:not(.has-intro) .rvt.is-in > span {
  translate: none;
}

/* ================= LABELS ROLL =================
   Buttons and text links: the label rolls up and an identical copy rolls
   in from below on hover; a press gives a small push. */
.roll {
  position: relative;
  display: inline-grid;
  overflow: hidden;
  vertical-align: top;
  padding-bottom: 0.08em;
  margin-bottom: -0.08em;
}
.roll > span {
  grid-area: 1 / 1;
  transition: transform 0.6s cubic-bezier(0.65, 0, 0.15, 1);
}
.roll > span + span {
  transform: translateY(110%);
}
@media (hover: hover) {
  :is(a, button):hover > .roll > span:first-child {
    transform: translateY(-110%);
  }
  :is(a, button):hover > .roll > span + span {
    transform: none;
  }
}
.btn,
.nav-links a,
.filter a,
.jc-more {
  transition:
    background-color 0.5s var(--ease),
    border-color 0.5s var(--ease),
    color 0.5s var(--ease),
    scale 0.25s var(--out);
}
.btn:active,
.nav-links a:active,
.filter a:active,
.jc-more:active {
  scale: 0.96;
}

@media (prefers-reduced-motion: reduce) {
  .rvg > *,
  .rvt > .tl,
  .rvt > span {
    opacity: 1 !important;
    translate: none !important;
  }
}

/* ================= PHOTO + CAPTION: ONE PIECE =================
   Appearing: the earlier soft rise (26px, fade), photo and caption at
   the same moment. Hover: photo and caption lift together, eased, the
   photo gets a soft shadow; nothing scales, so nothing overlaps.
   transform is listed in the transition with its own zero delay, so the
   reveal stagger never delays or cancels the hover. */
.rvg > * {
  --rise: 26px;
  transition:
    opacity 0.9s var(--ease) var(--rd, 0s),
    translate 1.2s var(--out) var(--rd, 0s),
    transform 0.7s cubic-bezier(0.22, 0.61, 0.36, 1) 0s !important;
}
html:not(.has-intro) .rvg.is-in > :nth-child(2) {
  transition-delay: var(--rd, 0s), var(--rd, 0s), 0s !important;
}
.jb-pair.rvg > .sfig:nth-child(2) {
  transition-delay:
    calc(var(--rd, 0s) + 0.12s), calc(var(--rd, 0s) + 0.12s), 0s !important;
}
.tile .ph,
.sfig .ph,
.jc-cover {
  transition: box-shadow 0.7s cubic-bezier(0.22, 0.61, 0.36, 1) !important;
}
@media (hover: hover) {
  .tile-link:hover,
  .fig-link:hover {
    transform: none;
  }
  .jcard:hover .jc-cover {
    transform: translateY(-6px);
  }
  .tile:hover > *,
  .sfig:hover > *,
  .jcard:hover > * {
    transform: translateY(-6px);
  }
  .tile:hover .ph,
  .sfig:hover .ph,
  .jcard:hover .jc-cover {
    box-shadow: 0 22px 44px -20px rgba(18, 20, 23, 0.38);
  }
}

/* ================= TEXT MASKS: ONE RULE, NO CUT LETTERS =================
   Every element that hides its text until it slides in (titles that rise,
   labels that roll) uses this one box. Literata's descenders (g, y, p)
   reach about 0.25em below the baseline and accents/ascenders about
   0.2em above the line box, so the mask gets 0.32em below and 0.22em
   above, with equal negative margins so the layout does not move.
   The hidden position is pushed far enough (150%) that nothing peeks
   out of the taller box. New masked text should use .rvt or .roll. */
.rvt,
.hero-title,
.s-name,
.j-title,
.st-title,
.fh-title,
.intro-name {
  overflow: hidden;
  padding-top: 0.22em !important;
  padding-bottom: 0.32em !important;
  margin-top: -0.22em !important;
  margin-bottom: -0.32em !important;
}
.st-title {
  margin-top: calc(14px - 0.22em) !important;
}
html body .rvt.rvt > .tl,
html body .rvt.rvt > span {
  translate: 0 150%;
}
@keyframes rise {
  from {
    transform: translateY(150%);
  }
  to {
    transform: none;
  }
}
.roll {
  padding-top: 0.12em;
  padding-bottom: 0.24em;
  margin-top: -0.12em;
  margin-bottom: -0.24em;
}
.roll > span + span {
  transform: translateY(140%);
}
@media (hover: hover) {
  :is(a, button):hover > .roll > span:first-child {
    transform: translateY(-140%);
  }
}

/* plain white background everywhere: no colour glow behind pages or the viewer */
.ambient,
.v-ambient {
  display: none !important;
}

/* no stories yet: hide the Journal link (content/stories.json is empty) */
html.no-stories [data-nav="journal"] {
  display: none;
}
html.no-stories .nav-links li:has(> [data-nav="journal"]) {
  display: none;
}
