@font-face {
  font-family: 'Newsreader';
  font-style: normal;
  font-weight: 200 800;
  font-display: swap;
  src: url('/assets/fonts/newsreader-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191,
    U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'Newsreader';
  font-style: italic;
  font-weight: 200 800;
  font-display: swap;
  src: url('/assets/fonts/newsreader-latin-italic.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191,
    U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

:root {
  /*
    Warm putty, drawn from his materials rather than from a gallery wall:
    birch, raw canvas, oxidised metal. Deep enough that a pale work reads as
    light against it instead of dissolving into it.
  */
  --paper: #e3d8c7;
  --paper-sunk: #d7cab5;
  /* The mat a piece is mounted on. Always lighter than the page. */
  --plate: #efe8dc;
  --ink: #1b1710;
  --ink-soft: #453c2e;
  /* 4.78:1 on the page ground and 5.53:1 on a plate. The obvious #6b5f4c
     measured 4.43:1, just under AA, and it is the colour every caption and
     label uses, so it failed on every page. */
  --ink-muted: #665a48;
  --rule: #c4b69c;
  --rule-strong: #a8967a;
  /* Oxidised rust off the red oil panels, with umber as the quiet second. */
  --clay: #8c4a2f;
  --umber: #6b5433;
  --dark: #17130d;
  --dark-ink: #ded2bf;
  --dark-muted: #b3a68f;

  --serif: 'Newsreader', ui-serif, Georgia, 'Times New Roman', serif;
  --sans: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial,
    sans-serif;

  --measure: 62ch;
  --gutter: clamp(1rem, 0.6rem + 1.6vw, 2rem);
  --page-x: clamp(1.25rem, 0.6rem + 3vw, 4.5rem);
  --section-y: clamp(3.5rem, 2rem + 6vw, 8rem);

  /*
    Target height for a justified gallery row. Each tile asks for a width of
    --ar x --row-h, so this is what decides how many pieces land on a line.
    Raising it means fewer, larger pieces per row.
  */
  --row-h: 12rem;
}

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

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

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

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--serif);
  font-size: clamp(1rem, 0.97rem + 0.15vw, 1.0625rem);
  line-height: 1.65;
  font-synthesis-weight: none;
  text-rendering: optimizeLegibility;
  -webkit-font-smoothing: antialiased;
}

img {
  max-width: 100%;
  height: auto;
}

/*
  Canvas tooth over the whole page. One fixed, pointer-events-none layer so it
  never repaints while the page scrolls, and an inline SVG so it costs no
  request. Everything else sits above it on z-index 2.
*/
body::before {
  content: '';
  position: fixed;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  opacity: 0.5;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='200' height='200'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.62' numOctaves='4'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='200' height='200' filter='url(%23n)' opacity='0.6'/%3E%3C/svg%3E");
  mix-blend-mode: multiply;
}

.masthead,
main,
.foot {
  position: relative;
  z-index: 2;
}

a {
  color: inherit;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.22em;
}

:where(a, button, [tabindex], input, textarea, summary):focus-visible {
  outline: 2px solid var(--clay);
  outline-offset: 3px;
  border-radius: 2px;
}

h1,
h2,
h3 {
  font-weight: 400;
  line-height: 1.12;
  letter-spacing: -0.015em;
  margin: 0;
  text-wrap: balance;
}

p {
  margin: 0 0 1.1em;
  text-wrap: pretty;
}

.shell {
  width: 100%;
  max-width: 96rem;
  margin-inline: auto;
  padding-inline: var(--page-x);
}

.skip {
  position: absolute;
  left: -9999px;
  top: 0;
  background: var(--ink);
  color: var(--paper);
  padding: 0.75rem 1.25rem;
  z-index: 100;
  font-family: var(--sans);
  font-size: 0.875rem;
}
.skip:focus {
  left: 0;
}

/* ---------------------------------------------------------------- masthead */

.masthead {
  position: sticky;
  top: 0;
  z-index: 20;
  background: color-mix(in srgb, var(--paper) 92%, transparent);
  backdrop-filter: saturate(1.4) blur(10px);
  border-bottom: 2px solid var(--ink);
}

.masthead__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.5rem;
  padding-block: clamp(1rem, 0.7rem + 0.9vw, 1.6rem);
}

/* Incised rather than printed: a light edge above and a dark one below, the
   way a carved letter catches the light. */
.wordmark {
  font-size: clamp(1.15rem, 0.95rem + 0.9vw, 1.7rem);
  font-weight: 500;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  text-decoration: none;
  white-space: nowrap;
  text-shadow: 0 1px 0 rgba(255, 252, 245, 0.55), 0 -1px 0 rgba(27, 23, 16, 0.18);
}
.wordmark span {
  display: block;
  font-family: var(--sans);
  font-size: 0.5625rem;
  letter-spacing: 0.3em;
  color: var(--clay);
  margin-top: 0.4em;
  text-shadow: none;
}

.nav {
  display: flex;
  gap: clamp(1rem, 0.4rem + 1.8vw, 2.25rem);
  font-family: var(--sans);
  font-size: 0.8125rem;
  letter-spacing: 0.11em;
  text-transform: uppercase;
}
.nav a {
  text-decoration: none;
  color: var(--ink-soft);
  padding-block: 0.35rem;
  position: relative;
  transition: color 0.2s ease;
}
.nav a::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 1px;
  background: currentColor;
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 0.28s cubic-bezier(0.16, 1, 0.3, 1);
}
.nav a:hover {
  color: var(--ink);
}
.nav a:hover::after,
.nav a[aria-current='page']::after {
  transform: scaleX(1);
}
.nav a[aria-current='page'] {
  color: var(--ink);
}

/* Four nav items and a long hyphenated name do not share a 375px line. */
@media (max-width: 47.99em) {
  .masthead__inner {
    flex-direction: column;
    align-items: flex-start;
    gap: 0.9rem;
  }
  .nav {
    gap: 1.15rem;
    font-size: 0.6875rem;
    letter-spacing: 0.07em;
  }
  .wordmark {
    font-size: 1rem;
    letter-spacing: 0.06em;
  }
}

/* ----------------------------------------------------------- hero slider */

.hero-slider {
  padding-top: clamp(1.5rem, 1rem + 2vw, 3rem);
}

/*
  A fixed stage with object-fit: contain. Nothing gets cropped, which is the
  whole point of the rebuild, and the band never changes height between slides
  so the page below it does not jump.
*/
.hero-slider__stage {
  position: relative;
  display: grid;
  height: clamp(19rem, 56vh, 34rem);
  /* A recessed plate: lighter mat, inner shadow along the top edge, so the
     work sits in the surface rather than floating on it. */
  background: var(--plate);
  border: 1px solid var(--rule-strong);
  box-shadow: inset 0 2px 6px rgba(27, 23, 16, 0.14),
    0 24px 50px -32px rgba(27, 23, 16, 0.7);
}
.hero-slider {
  max-width: 96rem;
  margin-inline: auto;
  padding-inline: var(--page-x);
}
@media (min-width: 64em) {
  .hero-slider__stage {
    height: clamp(24rem, 64vh, 44rem);
  }
}

.hero-slide {
  grid-area: 1 / 1;
  position: relative;
  margin: 0;
  min-width: 0;
  display: none;
  opacity: 0;
  transition: opacity 0.9s cubic-bezier(0.16, 1, 0.3, 1);
}
.hero-slide.is-active {
  display: block;
  opacity: 1;
}
/* Set by the script one frame before .is-active, so the fade has a start. */
.hero-slide.is-entering {
  display: block;
  opacity: 0;
}

/*
  The image is positioned rather than sized in flow. A percentage height on an
  <img> inside a <picture> inside a stretched grid item has no definite
  ancestor to resolve against, so it silently falls back to the intrinsic
  height and a tall piece runs straight out of the stage.
*/
/* The inset is the mat around the work. Keeping it here rather than as
   padding on the stage means the slide still spans the full plate, so the
   caption below it clears the plate edge cleanly. */
.hero-slide__link {
  position: absolute;
  inset: clamp(0.7rem, 0.4rem + 1.2vw, 1.5rem);
  display: block;
  text-decoration: none;
}
.hero-slide__link img {
  position: absolute;
  inset: 0;
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;
}

.hero-slide__caption {
  position: absolute;
  left: 0;
  right: 0;
  bottom: auto;
  top: 100%;
  padding: 0.9rem 0 0;
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
}
.hero-slide__caption a {
  text-decoration: none;
  display: block;
}
.hero-slide__title {
  display: block;
  font-size: 1rem;
  letter-spacing: 0;
}
.hero-slide__meta {
  display: block;
  font-family: var(--sans);
  font-size: 0.75rem;
  letter-spacing: 0.05em;
  color: var(--ink-muted);
  margin-top: 0.15rem;
}

/* The caption hangs below the plate, so the controls row has to clear it. */
.hero-slider__controls {
  display: flex;
  align-items: center;
  gap: 0.35rem;
  padding: 3.6rem 0 0;
}
.hero-slider__btn {
  width: 2.25rem;
  height: 2.25rem;
  display: grid;
  place-items: center;
  border: 1px solid var(--rule);
  background: transparent;
  color: var(--ink-soft);
  cursor: pointer;
  transition: border-color 0.2s ease, color 0.2s ease;
}
.hero-slider__btn:hover {
  border-color: var(--ink-muted);
  color: var(--ink);
}
.hero-slider__btn svg {
  width: 15px;
  height: 15px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.5;
}
/* The UA stylesheet's [hidden] rule does not reach inline SVG, so the play and
   pause icons would both show at once without this. */
.hero-slider__btn svg[hidden] {
  display: none;
}

.hero-slider__dots {
  display: flex;
  gap: 0.4rem;
  list-style: none;
  margin: 0 0 0 auto;
  padding: 0;
}
.hero-slider__dots button {
  width: 1.75rem;
  height: 2px;
  padding: 0;
  border: 0;
  background: var(--rule-strong);
  cursor: pointer;
  transition: background 0.25s ease;
}
.hero-slider__dots button:hover {
  background: var(--ink-muted);
}
.hero-slider__dots button[aria-current='true'] {
  background: var(--ink);
}
/* The 2px bar is the visual, but the tap target needs to be finger sized. */
.hero-slider__dots li {
  display: grid;
  place-items: center;
  height: 2.25rem;
}

@media (prefers-reduced-motion: reduce) {
  .hero-slide {
    transition: none;
  }
}

/* Without JavaScript only the first slide is ever shown, so the controls
   would do nothing. */
.no-js .hero-slider__controls {
  display: none;
}

/* -------------------------------------------------- reveal the full set */

.reveal__cta {
  display: flex;
  justify-content: center;
  padding-block: clamp(1.5rem, 1rem + 2vw, 2.75rem);
  margin: 0;
}
/* The panel ships in the page but hidden, so its images cost nothing until
   someone asks for them. [hidden] does the hiding; this only spaces it. */
.reveal__panel {
  padding-bottom: clamp(1rem, 0.5rem + 1.5vw, 2rem);
}

/* ---------------------------------------------------------- filmstrip */

.strip {
  margin-block: clamp(2.5rem, 1.5rem + 4vw, 5rem);
}
.strip__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
  border-bottom: 2px solid var(--ink);
  padding-bottom: 0.7rem;
  margin-bottom: clamp(1.25rem, 0.8rem + 1.5vw, 2rem);
}
.strip__head h2 {
  font-size: clamp(1.35rem, 1.1rem + 1.1vw, 2.1rem);
}
.strip__head p {
  display: flex;
  gap: 1.5rem;
  align-items: baseline;
  margin: 0;
  font-family: var(--sans);
  font-size: 0.6875rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink-muted);
}
.strip__head a {
  color: var(--ink);
}

/*
  A scroll-snap rail rather than a scripted carousel. It drags on touch,
  scrolls with a trackpad, takes arrow keys once focused, and needs no
  JavaScript. Images stay lazy, so the ones off to the right cost nothing
  until they are scrolled to.
*/
.strip__rail {
  display: flex;
  gap: var(--gutter);
  list-style: none;
  margin: 0;
  padding: 0 0 0.75rem;
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scroll-snap-type: x mandatory;
  /* Padding on a horizontal flex scroller is unreliable: the leading edge can
     be ignored and the trailing edge is routinely dropped. Insetting the first
     and last items instead works everywhere and keeps space after the last
     photograph. scroll-padding keeps snapping aligned to the same line. */
  scroll-padding-inline-start: var(--page-x);
  scrollbar-width: thin;
  scrollbar-color: var(--rule-strong) transparent;
}
.strip__rail > li:first-child {
  margin-inline-start: var(--page-x);
}
.strip__rail > li:last-child {
  margin-inline-end: var(--page-x);
}
.strip__rail > li {
  flex: 0 0 auto;
  scroll-snap-align: start;
  /* Height-led, so every photograph in the row lines up regardless of shape. */
  width: calc(var(--ar, 1.4) * clamp(11rem, 8rem + 12vw, 17rem));
  max-width: 78vw;
}
.strip__rail button {
  display: block;
  width: 100%;
  padding: 0;
  border: 0;
  background: none;
  text-align: left;
  cursor: zoom-in;
}
.strip__rail:focus-visible {
  outline: 2px solid var(--clay);
  outline-offset: 4px;
}

/* ----------------------------------------------------------- gateways */

/* The two doors off the home page. Plates like everything else, so they read
   as part of the same material system rather than as buttons. */
.gateways {
  display: grid;
  gap: var(--gutter);
  grid-template-columns: 1fr;
  padding-block: clamp(2rem, 1.2rem + 3vw, 3.75rem);
}
@media (min-width: 48rem) {
  .gateways {
    grid-template-columns: 1fr 1fr;
  }
}
.gateway {
  display: block;
  text-decoration: none;
  background: var(--plate);
  border: 1px solid var(--rule-strong);
  padding: clamp(1.5rem, 1rem + 2vw, 2.75rem);
  box-shadow: inset 0 2px 5px rgba(27, 23, 16, 0.12),
    0 16px 34px -26px rgba(27, 23, 16, 0.65);
  transition: transform 0.35s cubic-bezier(0.16, 1, 0.3, 1),
    box-shadow 0.35s cubic-bezier(0.16, 1, 0.3, 1);
}
.gateway:hover {
  transform: translateY(-3px);
  box-shadow: inset 0 2px 5px rgba(27, 23, 16, 0.12),
    0 24px 40px -24px rgba(27, 23, 16, 0.7);
}
.gateway__kicker {
  display: block;
  font-family: var(--sans);
  font-size: 0.625rem;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--clay);
  margin-bottom: 0.9rem;
}
.gateway__title {
  display: block;
  font-size: clamp(1.35rem, 1.1rem + 1.1vw, 2rem);
  line-height: 1.1;
  letter-spacing: -0.015em;
  margin-bottom: 0.6rem;
}
.gateway__count {
  display: block;
  font-family: var(--sans);
  font-size: 0.75rem;
  letter-spacing: 0.06em;
  color: var(--ink-muted);
}

/* ------------------------------------------------------- statement band */

/*
  A near-black band that breaks the page and gives the eye somewhere to rest
  between the lead work and the grid. Full bleed on purpose.
*/
.band {
  background: var(--dark);
  color: var(--dark-ink);
  margin-block: clamp(3rem, 2rem + 4vw, 6rem) 0;
  padding-block: clamp(3.5rem, 2rem + 6vw, 7rem);
}
.band__inner {
  display: grid;
  gap: clamp(2rem, 1.2rem + 4vw, 4.5rem);
  grid-template-columns: 1fr;
  align-items: center;
}
@media (min-width: 62rem) {
  .band__inner {
    grid-template-columns: minmax(0, 1fr) minmax(0, 0.85fr);
  }
}
/* A plate on the dark ground, edged in light rather than shadow. */
.band__figure {
  margin: 0;
  padding: clamp(0.6rem, 0.35rem + 1vw, 1.1rem);
  background: #241e16;
  border: 1px solid #3a3125;
}
.band__figure img {
  display: block;
  width: 100%;
  height: auto;
}

.band__kicker {
  font-family: var(--sans);
  font-size: 0.625rem;
  letter-spacing: 0.28em;
  text-transform: uppercase;
  color: #b98a5f;
  margin: 0 0 1.25rem;
}
.band__quote {
  font-size: clamp(1.6rem, 1.1rem + 2.2vw, 3rem);
  line-height: 1.15;
  letter-spacing: -0.02em;
  max-width: 24ch;
  margin: 0 0 1.5rem;
  color: #f0e7d8;
}
.band__sub {
  font-style: italic;
  font-size: clamp(1rem, 0.95rem + 0.4vw, 1.2rem);
  max-width: 44ch;
  color: var(--dark-muted);
  margin: 0;
}
.band a {
  color: #f0e7d8;
}

/* The kicker doubles as a small label on the light ground. */
.kicker {
  font-family: var(--sans);
  font-size: 0.625rem;
  letter-spacing: 0.28em;
  text-transform: uppercase;
  color: var(--clay);
  margin: 0 0 1rem;
}

/* -------------------------------------------------------------------- home */

.hero {
  padding-block: clamp(3rem, 1.5rem + 7vw, 8rem) clamp(2rem, 1rem + 4vw, 4rem);
  display: grid;
  grid-template-columns: 1fr;
  gap: clamp(2rem, 1rem + 4vw, 4rem);
}
@media (min-width: 60rem) {
  .hero {
    grid-template-columns: minmax(0, 7fr) minmax(0, 4fr);
    align-items: end;
  }
}

.hero__line {
  font-size: clamp(1.6rem, 1.05rem + 2.3vw, 3.1rem);
  line-height: 1.16;
  letter-spacing: -0.02em;
  max-width: 18ch;
  margin: 0;
}
.hero__line em {
  font-style: italic;
}

.hero__meta {
  font-family: var(--sans);
  font-size: 0.8125rem;
  letter-spacing: 0.08em;
  color: var(--ink-muted);
  line-height: 1.7;
}
.hero__meta p {
  margin: 0;
  max-width: 34ch;
}

/* ----------------------------------------------------------------- gallery */

.section-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
  padding-bottom: 0.8rem;
  border-bottom: 2px solid var(--ink);
  margin-bottom: clamp(1.75rem, 1rem + 2.5vw, 3rem);
}
.section-head h1,
.section-head h2 {
  font-size: clamp(1.5rem, 1.2rem + 1.3vw, 2.25rem);
}
.section-head__count {
  font-family: var(--sans);
  font-size: 0.75rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-muted);
}

/*
  Justified rows, done with flex arithmetic instead of JavaScript.
  Each tile asks for a basis proportional to its aspect ratio and grows by the
  same factor, so everything sharing a row lands on one height and the row
  fills the line exactly. The ::after soaks up slack on the final row so a
  lonely last piece does not blow up to full width.
*/
.gallery {
  display: flex;
  flex-wrap: wrap;
  gap: var(--gutter);
  list-style: none;
  margin: 0;
  padding: 0;
}
.gallery::after {
  content: '';
  flex-grow: 1000000;
  flex-basis: 0;
}
.gallery > li {
  flex-grow: var(--ar, 1);
  flex-basis: calc(var(--ar, 1) * var(--row-h));
  min-width: 0;
  /*
    A piece left alone on a row would otherwise absorb the whole line: a
    square panel stranded at the end came out 1334px wide and 794px tall,
    dwarfing everything above it. Capping growth at 1.85x the target keeps a
    lone piece in proportion. The row ends short instead, which reads as
    deliberate spacing rather than a mistake.
  */
  max-width: calc(var(--ar, 1) * var(--row-h) * 1.85);
}

@media (max-width: 47.99em) {
  /* One piece per row on a phone. Nothing gets shrunk to a stamp. */
  .gallery > li {
    flex-basis: 100%;
    flex-grow: 1;
    max-width: 100%;
  }
  .gallery::after {
    display: none;
  }

  /*
    Photographs are the exception. Browsing 25 of them one per row means each
    tile needs a ~1200px image, which on this content runs 200-400 KB apiece.
    Two up halves the width needed, so the browser drops to the 640px rung and
    roughly a third of the bytes, and more of the set fits on a screen.
    Paintings stay full width, where scale is the point.
  */
  .gallery--photos > li {
    flex-basis: calc(50% - (var(--gutter) / 2));
    max-width: calc(50% - (var(--gutter) / 2));
  }
}
@media (min-width: 64em) {
  :root {
    --row-h: 15rem;
  }
}
@media (min-width: 90em) {
  :root {
    --row-h: 16rem;
  }
}

/*
  A 94in wide strip next to a square panel would otherwise force a row two
  pixels tall or a tile taller than the viewport. Clamping the frame keeps
  extreme proportions inside a sane band without cropping anything.
*/
.piece__frame img {
  max-height: 78vh;
  object-fit: contain;
}

.piece {
  display: block;
  text-decoration: none;
  height: 100%;
}
.piece__frame {
  display: block;
  background: var(--plate);
  border: 1px solid var(--rule-strong);
  padding: clamp(0.5rem, 0.28rem + 0.85vw, 0.95rem);
  overflow: hidden;
  box-shadow: inset 0 2px 5px rgba(27, 23, 16, 0.12),
    0 16px 34px -26px rgba(27, 23, 16, 0.65);
  transition: transform 0.35s cubic-bezier(0.16, 1, 0.3, 1),
    box-shadow 0.35s cubic-bezier(0.16, 1, 0.3, 1);
}
.piece:hover .piece__frame,
.piece:focus-visible .piece__frame {
  transform: translateY(-3px);
  box-shadow: inset 0 2px 5px rgba(27, 23, 16, 0.12),
    0 24px 40px -24px rgba(27, 23, 16, 0.7);
}
.piece__frame img {
  display: block;
  width: 100%;
  height: auto;
  transition: opacity 0.4s ease;
}
.piece:hover .piece__frame img,
.piece:focus-visible .piece__frame img {
  opacity: 1;
}

.piece__caption {
  display: block;
  padding-top: 0.8rem;
  font-family: var(--sans);
  font-size: 0.75rem;
  letter-spacing: 0.02em;
  color: var(--ink-muted);
  line-height: 1.5;
}
.piece__name {
  display: block;
  color: var(--ink);
  font-family: var(--serif);
  font-weight: 400;
  font-size: 1.05rem;
  letter-spacing: 0;
  margin-bottom: 0.1rem;
}

/* --------------------------------------------------------- single artwork */

.work {
  display: grid;
  gap: clamp(2rem, 1rem + 4vw, 4rem);
  padding-block: clamp(2rem, 1rem + 3vw, 3.5rem) var(--section-y);
  grid-template-columns: 1fr;
}
@media (min-width: 60rem) {
  .work {
    grid-template-columns: minmax(0, 1fr) 20rem;
    align-items: start;
  }
}

.work__view {
  margin: 0;
  position: relative;
}
/* The single work gets the same recessed plate as the gallery tiles. */
.work__view button {
  display: block;
  width: 100%;
  padding: clamp(0.7rem, 0.4rem + 1.2vw, 1.5rem);
  border: 1px solid var(--rule-strong);
  background: var(--plate);
  cursor: zoom-in;
  line-height: 0;
  box-shadow: inset 0 2px 6px rgba(27, 23, 16, 0.14),
    0 24px 50px -32px rgba(27, 23, 16, 0.7);
}
.work__view img {
  width: 100%;
  height: auto;
}

.work__zoomhint {
  position: absolute;
  right: 0.85rem;
  bottom: 0.85rem;
  font-family: var(--sans);
  font-size: 0.6875rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  background: color-mix(in srgb, var(--dark) 72%, transparent);
  color: #fff;
  padding: 0.4rem 0.7rem;
  opacity: 0;
  transition: opacity 0.25s ease;
  pointer-events: none;
}
.work__view:hover .work__zoomhint,
.work__view button:focus-visible + .work__zoomhint {
  opacity: 1;
}

@media (min-width: 60rem) {
  .work__panel {
    position: sticky;
    top: 6.5rem;
  }
}

.work__title {
  font-size: clamp(1.5rem, 1.25rem + 1.1vw, 2.1rem);
  margin-bottom: 0.35rem;
}
.work__year {
  font-style: italic;
  color: var(--ink-muted);
}

.spec {
  margin: 1.75rem 0 0;
  font-family: var(--sans);
  font-size: 0.8125rem;
  line-height: 1.6;
  border-top: 1px solid var(--rule);
}
.spec div {
  display: flex;
  gap: 1rem;
  justify-content: space-between;
  padding: 0.7rem 0;
  border-bottom: 1px solid var(--rule);
}
.spec dt {
  color: var(--ink-muted);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  font-size: 0.6875rem;
  padding-top: 0.15em;
}
.spec dd {
  margin: 0;
  text-align: right;
}

.status {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
}
.status::before {
  content: '';
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--clay);
}
.status[data-state='sold']::before {
  background: var(--rule-strong);
}
.status[data-state='sold'] {
  color: var(--ink-muted);
}

.work__note {
  margin-top: 1.5rem;
  font-size: 0.9375rem;
  color: var(--ink-soft);
}

/* -------------------------------------------------------------- prev/next */

.pager {
  display: flex;
  justify-content: space-between;
  gap: 1rem;
  border-top: 1px solid var(--rule);
  padding-top: 1.5rem;
  margin-top: var(--section-y);
  font-family: var(--sans);
  font-size: 0.8125rem;
  letter-spacing: 0.06em;
}
.pager a {
  text-decoration: none;
  color: var(--ink-muted);
  transition: color 0.2s ease;
  max-width: 45%;
  overflow-wrap: anywhere;
}
.pager a:hover {
  color: var(--ink);
}
.pager span {
  display: block;
  font-size: 0.6875rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  /* --rule-strong is a border colour and only reaches 1.65:1 against the
     paper, well under AA. Text uses the muted ink, which measures 5.03:1. */
  color: var(--ink-muted);
  margin-bottom: 0.3rem;
}
.pager .is-next {
  text-align: right;
  margin-left: auto;
}

/* ------------------------------------------------------------------ prose */

.prose {
  max-width: var(--measure);
  font-size: clamp(1.0625rem, 1rem + 0.3vw, 1.1875rem);
  line-height: 1.72;
  color: var(--ink-soft);
}
.prose p:last-child {
  margin-bottom: 0;
}

.about {
  display: grid;
  gap: clamp(2.5rem, 1.5rem + 5vw, 5rem);
  padding-block: clamp(2.5rem, 1.5rem + 4vw, 5rem) var(--section-y);
  grid-template-columns: 1fr;
}
@media (min-width: 62rem) {
  .about {
    grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
  }
  .about__aside {
    position: sticky;
    top: 6.5rem;
    align-self: start;
  }
}

.label {
  font-family: var(--sans);
  font-size: 0.6875rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink-muted);
  margin: 0 0 1rem;
}

.about__name {
  font-size: clamp(1.9rem, 1.4rem + 2vw, 3rem);
  margin-bottom: 2.25rem;
}

.about > div > h2 {
  font-size: clamp(1.25rem, 1.1rem + 0.7vw, 1.6rem);
  margin: clamp(2.5rem, 1.6rem + 2.6vw, 4rem) 0 1rem;
  padding-top: clamp(1.5rem, 1rem + 1.5vw, 2.25rem);
  border-top: 1px solid var(--rule);
}
.about > div > h2:first-of-type {
  margin-top: 0;
}

/* ---------------------------------------------------------------- contact */

.contact {
  display: grid;
  gap: clamp(2.5rem, 1.5rem + 4vw, 4.5rem);
  padding-block: clamp(2.5rem, 1.5rem + 4vw, 5rem) var(--section-y);
  grid-template-columns: 1fr;
}
@media (min-width: 62rem) {
  .contact {
    grid-template-columns: minmax(0, 4fr) minmax(0, 6fr);
  }
}

.details {
  font-family: var(--sans);
  font-size: 0.9375rem;
  line-height: 1.75;
}
.details h2 {
  font-family: var(--serif);
  font-size: 1.05rem;
  letter-spacing: 0.04em;
  margin: 2rem 0 0.35rem;
}
.details h2:first-child {
  margin-top: 0;
}
.details a {
  color: var(--ink);
}
.details ul {
  list-style: none;
  margin: 0;
  padding: 0;
}
.details li {
  padding: 0.55rem 0;
  border-bottom: 1px solid var(--rule);
}
.details li span {
  display: block;
  color: var(--ink-muted);
  font-size: 0.8125rem;
}

/* ------------------------------------------------------------------- form */

.form {
  display: grid;
  gap: 1.35rem;
  max-width: 34rem;
}
.field {
  display: grid;
  gap: 0.45rem;
}
.field label {
  font-family: var(--sans);
  font-size: 0.75rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-soft);
}
.field .hint {
  font-family: var(--sans);
  font-size: 0.8125rem;
  color: var(--ink-muted);
  letter-spacing: 0;
  text-transform: none;
}
.field input,
.field textarea {
  font: inherit;
  font-size: 1rem;
  color: var(--ink);
  background: transparent;
  border: 1px solid var(--rule-strong);
  padding: 0.7rem 0.85rem;
  width: 100%;
  transition: border-color 0.2s ease, background 0.2s ease;
}
.field input:hover,
.field textarea:hover {
  border-color: var(--ink-muted);
}
.field input:focus,
.field textarea:focus {
  border-color: var(--ink);
  background: #fff;
  outline: none;
}
.field textarea {
  min-height: 9rem;
  resize: vertical;
}
.field .error {
  font-family: var(--sans);
  font-size: 0.8125rem;
  color: #9a3412;
}

/* Honeypot. Off screen rather than display:none, which some bots skip. */
.trap {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

.button {
  font-family: var(--sans);
  font-size: 0.75rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  background: var(--ink);
  color: var(--plate);
  border: 1px solid var(--ink);
  padding: 0.9rem 1.9rem;
  cursor: pointer;
  justify-self: start;
  transition: transform 0.15s ease, background 0.2s ease, color 0.2s ease;
}
.button:hover {
  background: transparent;
  color: var(--ink);
}
.button:active {
  transform: translateY(1px);
}
.button[disabled] {
  opacity: 0.5;
  cursor: progress;
}
.button--ghost {
  background: transparent;
  color: var(--ink);
}
.button--ghost:hover {
  background: var(--ink);
  color: var(--paper);
}

.notice {
  font-family: var(--sans);
  font-size: 0.875rem;
  padding: 0.9rem 1.1rem;
  border-left: 2px solid var(--clay);
  background: var(--paper-sunk);
}
.notice[data-tone='bad'] {
  border-left-color: #9a3412;
}

/* --------------------------------------------------------------- lightbox */

.lightbox {
  border: 0;
  padding: 0;
  margin: 0;
  width: 100%;
  max-width: 100%;
  height: 100%;
  max-height: 100%;
  background: var(--dark);
  color: #f2f0ea;
  overflow: hidden;
}
.lightbox::backdrop {
  background: var(--dark);
}
.lightbox__stage {
  display: grid;
  grid-template-rows: 1fr auto;
  height: 100%;
  padding: clamp(0.75rem, 0.4rem + 1.4vw, 2rem);
  gap: 0.75rem;
}
/*
  The image is positioned rather than laid out. A percentage max-height on a
  grid item resolves against an auto-sized area, which is circular, so the
  browser drops the constraint and a tall piece runs off the bottom under the
  caption. Filling an absolutely positioned box with object-fit: contain gives
  the same letterboxing with no circular sizing.
*/
.lightbox__img {
  position: relative;
  min-height: 0;
  overflow: hidden;
}
.lightbox__img img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: contain;
}
.lightbox__bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  font-family: var(--sans);
  font-size: 0.8125rem;
  color: #a8a49a;
}
.lightbox__bar strong {
  font-family: var(--serif);
  font-weight: 400;
  font-size: 1rem;
  color: #f2f0ea;
  display: block;
}
.lightbox__controls {
  display: flex;
  gap: 0.35rem;
  flex-shrink: 0;
}
.lightbox button {
  background: transparent;
  border: 1px solid #34322d;
  color: #f2f0ea;
  width: 2.75rem;
  height: 2.75rem;
  display: grid;
  place-items: center;
  cursor: pointer;
  transition: background 0.18s ease, border-color 0.18s ease;
}
.lightbox button:hover:not([disabled]) {
  background: #1e1c19;
  border-color: #55524a;
}
.lightbox button[disabled] {
  opacity: 0.3;
  cursor: default;
}
.lightbox svg {
  width: 18px;
  height: 18px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.5;
}

/* ----------------------------------------------------------------- footer */

.foot {
  border-top: 2px solid var(--ink);
  padding-block: clamp(2.5rem, 1.5rem + 4vw, 4.5rem) clamp(1.5rem, 1rem + 2vw, 2.5rem);
  font-family: var(--sans);
  font-size: 0.875rem;
  line-height: 1.7;
  color: var(--ink-soft);
}
.foot__grid {
  display: grid;
  gap: 2rem;
  grid-template-columns: 1fr;
}
@media (min-width: 48rem) {
  .foot__grid {
    grid-template-columns: repeat(3, 1fr);
  }
}
.foot__grid p {
  margin: 0;
}
/* Stacked links in the footer need a real tap target, not just a line of
   text. 44px is the comfortable minimum. */
.foot__grid a {
  display: inline-block;
  min-height: 44px;
  line-height: 44px;
  text-decoration-thickness: 1px;
}
@media (min-width: 48rem) {
  .foot__grid a {
    min-height: 0;
    line-height: inherit;
  }
}
.foot__base {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem 2rem;
  justify-content: space-between;
  margin-top: clamp(2rem, 1.2rem + 3vw, 3.5rem);
  padding-top: 1.25rem;
  border-top: 1px solid var(--rule);
  font-size: 0.75rem;
  color: var(--ink-muted);
}
.foot__base p {
  margin: 0;
}
.foot__base a {
  color: var(--ink-muted);
}
.foot__base a:hover {
  color: var(--ink);
}
.foot a {
  color: var(--ink-soft);
  text-decoration: none;
}
.foot a:hover {
  color: var(--ink);
  text-decoration: underline;
}

/* ------------------------------------------------------------------ misc */

.empty {
  border: 1px dashed var(--rule-strong);
  padding: clamp(2rem, 1.5rem + 3vw, 4rem);
  text-align: center;
  color: var(--ink-muted);
  font-family: var(--sans);
  font-size: 0.9375rem;
}

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