
/* ============================================================
   NEP SIDHU — base system shared by all four variations

   The master layout is the studio's drawing: navigation on all four sides,
   the logo between Work and Exhibitions at the top, and the content sealed
   inside. The frame is fixed and never moves; only `.main` scrolls, and it
   scrolls one way — down. Nothing on this site travels sideways.
   ============================================================ */

/* ---------- type -------------------------------------------
   UppercaseOnly is a supplied file, not a webfont service, and it is a
   display face rather than a text one: 55 glyphs — capitals, digits and
   basic punctuation. It carries NO lowercase and no bold. Two rules follow
   from that and are enforced through the variables below:

     · anything set in it is transformed to uppercase, because an untouched
       "Work" would render W in the face and "ork" out of Helvetica behind it;
     · anything set in it asks for weight 400, because a browser told to
       bolden a 400-only face smears the outline instead.

   Everything it does not carry — the ampersand, the en and em dashes, curly
   quotes, the middot — falls through to Helvetica in the stack, which is
   what the stack is for. */
@font-face {
  font-family: "UppercaseOnly";
  src: url("fonts/UppercaseOnly.ttf") format("truetype");
  font-weight: 400;
  font-style: normal;
  /* block, not swap. swap paints the titles in Helvetica and then re-paints
     them in the face, which on a slow first visit is a visible change of
     typeface a second into the page — the flash the studio reported. block
     holds the text unpainted instead, for up to three seconds, and then
     paints it once in the right face; the head of every page preloads the
     file so that wait is a fraction of the first plate's. Helvetica is still
     the fallback if the file never arrives at all. */
  font-display: block;
}

:root {
  --helv: "Helvetica Neue", Helvetica, Arial, sans-serif;
  --uc: "UppercaseOnly", "Helvetica Neue", Helvetica, Arial, sans-serif;
  --font-body: var(--helv);
  --font-head: var(--helv);
  --font-nav: var(--helv);
  /* the wordmark is its own thing: it sits inside a supplied mark that was
     drawn around Helvetica, so it stays in Helvetica in every variation
     rather than following the heading face */
  --font-logo: var(--helv);
  /* set to uppercase / 400 by whichever variation puts the display face on
     the element; see the note above @font-face */
  --head-case: none;
  --head-weight: 700;

  /* The studio's Dover White, SW 6385. It goes on every title in the three
     variations that stand on the dark ground; 02 keeps its own near-black,
     because an off-white title on an off-white ground is not a title. */
  --title-ink: var(--ink);
  /* The writing under a title — the section chip, the medium, the credit.
     It was set in the muted grey the rest of the small type takes; under a
     title it is the subtext of the work itself and is asked to read, so the
     variations that can afford it hand it a solid ink and a step of size. */
  --sub-ink: var(--muted);
  /* What a hover does to a word or a picture. A hover should lift the thing
     off the ground, never sink it into it — and which of those a fade is
     depends entirely on the ground. On the light ground fading the ink
     toward the paper IS the lift, which is what the sheet has always done;
     on the dark ground the same fade pulls the word down into the black, so
     the three dark variations replace it with a brightening. One filter, so
     it reads the same way on a word, on a reversed chip and on a
     photograph. */
  --hover-lift: opacity(.62);
  /* a picture takes the same idea more gently: a photograph carries its own
     tone and does not need the word's full step to register the hover */
  --hover-art: opacity(.85);

  /* every title size in this sheet is multiplied by this. It is 1 wherever
     the titles are Helvetica, and is turned up by the two variations that
     set them in the display face, which is narrower and lighter and needs
     the size to hold the same presence. */
  --uc-up: 1;

  /* the frame words are multiplied by this one. It applies in every
     variation, Helvetica included — the menu was set small for a frame that
     has since grown, and 1.3 is the studio's step. The two variations on the
     display face take it further; see --uc-nav-up. */
  --nav-up: 1.3;

  /* the frame: how far the words sit from the glass, and how far the
     content box is held off them */
  --fr-pad: 26px;
  /* the mark was drawn to sit between the two top corners; at 250 it crowded
     them, and the studio asked for it back a step */
  --logo-w: 206px;
  /* the supplied mark is 747 x 339, so its height is .4538 of its width; the
     content box clears it rather than being told a number to keep in step */
  --logo-h: calc(var(--logo-w) * .4538);
  --fr-top: calc(var(--fr-pad) + var(--logo-h) + 22px);
  --fr-bot: 74px;
  --fr-side: 84px;

  /* what .main is inset by — overridden to zero by the overlay variation */
  --main-top: var(--fr-top);
  --main-bot: var(--fr-bot);
  --main-side: var(--fr-side);

  /* inner measure of a page that is copy rather than pictures */
  --in-x: 6%;

  /* How far the writing under a picture in the gallery grid stands off the
     edge of its own column. On the desktop grid the column is half the
     content box, so 2px is right — the caption wants to read as belonging to
     the picture above it, not as an indented block. Below 860 the grid
     collapses to one column, that column becomes the whole screen, and the
     same 2px puts the words hard against the glass; there it takes the same
     margin every other line of text on the page already keeps. The picture
     is never given it: full bleed is the point of the mobile grid. */
  --cap-x: 2px;
  /* the corner on the Biennial film. One number, both places it runs. */
  --feat-radius: clamp(16px, 2.2vw, 34px);

  /* how wide a dropdown may run: to the logo, and no further. The two panels
     open from the outside corners inwards, so the mark between them is the
     only thing either of them could ever collide with. */
  --drop-max: min(660px, max(430px, calc(50vw - var(--logo-w) / 2 - 28px)));
}

*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
html, body { height: 100%; }
body {
  margin: 0;
  font-family: var(--font-body);
  font-size: 14px;
  line-height: 1.55;
  letter-spacing: .2px;
  background: var(--bg);
  color: var(--ink);
  -webkit-font-smoothing: antialiased;
  /* the frame stays put: the page itself never scrolls, in either axis */
  overflow: hidden;
}
a { color: inherit; text-decoration: none; }
img { max-width: 100%; display: block; }
h1, h2, h3, p, ul { margin: 0; }
ul { list-style: none; padding: 0; }

/* ---------- the content box --------------------------------
   Fixed, inset by the frame, and the only thing on the page that scrolls.
   overflow-x is hidden outright, so nothing a template does can put a
   sideways bar back. */
.main {
  position: fixed;
  top: var(--main-top);
  right: var(--main-side);
  bottom: var(--main-bot);
  left: var(--main-side);
  overflow-y: auto;
  overflow-x: hidden;
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
  background: var(--content-bg);
}

/* ---------- the bar ----------------------------------------
   The box scrolls inside a frame that does not, so the platform's own
   scrollbar lands in the middle of the design rather than at the edge of the
   window — and on Windows it lands there three times the width. It is given
   a bar of its own instead: a hairline in the ground's own colour, inset
   from the corner of the box, dark on the dark ground and grey on the light
   one. The same bar serves the dropdown panels and the mobile drawer. */
.main::-webkit-scrollbar,
.drop-in::-webkit-scrollbar,
.drawer::-webkit-scrollbar,
body::-webkit-scrollbar { width: 10px; height: 10px; }
.main::-webkit-scrollbar-track,
.drop-in::-webkit-scrollbar-track,
.drawer::-webkit-scrollbar-track,
body::-webkit-scrollbar-track { background: transparent; }
.main::-webkit-scrollbar-thumb,
.drop-in::-webkit-scrollbar-thumb,
.drawer::-webkit-scrollbar-thumb,
body::-webkit-scrollbar-thumb {
  background-color: var(--scroll-thumb);
  border: 3px solid transparent;
  background-clip: content-box;
  border-radius: 5px;
}
.main::-webkit-scrollbar-thumb:hover,
.drop-in::-webkit-scrollbar-thumb:hover,
.drawer::-webkit-scrollbar-thumb:hover,
body::-webkit-scrollbar-thumb:hover { background-color: var(--scroll-thumb-lit); }
.main::-webkit-scrollbar-corner,
body::-webkit-scrollbar-corner { background: transparent; }
/* Firefox has no ::-webkit-scrollbar and takes the two standard properties
   instead — but naming either of them is also what tells Chrome to throw the
   block above away, so they are kept behind a gate only Firefox opens. */
@supports (-moz-appearance: none) {
  .main, .drop-in, .drawer, body {
    scrollbar-width: thin;
    scrollbar-color: var(--scroll-thumb) transparent;
  }
}

/* ---------- real images ------------------------------------ */
.art { display: block; max-width: 100%; height: auto; background: var(--ph-bg); }
.bleed { width: 100%; height: 100%; object-fit: cover; }
.fig { margin: 0; }
.cap {
  display: block; margin-top: 9px; max-width: 620px;
  font-size: 13px; line-height: 1.5; color: var(--sub-ink); letter-spacing: .2px;
}
.cap-title { display: block; }
.cap-detail, .cap-credit { display: block; }
/* italic is what sets the credit apart from the line above it; it was
   also carrying an 80 per cent, and the studio has asked the subtext to
   be solid */
.cap-credit { font-style: italic; }
.no-img {
  font-size: 12.5px; line-height: 1.6; color: var(--flag);
  border-left: 2px solid var(--flag); padding-left: 12px; max-width: 520px;
}

/* remainder of the record, listed */
.bare { padding: 70px var(--in-x) 0; }
.bare-h {
  font-size: 11px; font-weight: 700; letter-spacing: 2.4px;
  color: var(--muted); margin-bottom: 14px;
}
.bare-row {
  display: grid; grid-template-columns: 84px minmax(0,1.4fr) minmax(0,1fr);
  gap: 16px; padding: 13px 0; border-top: 1px solid var(--hairline);
  font-size: 13.5px; align-items: baseline;
}
.bare-row:last-child { border-bottom: 1px solid var(--hairline); }
.bare-row span:first-child { font-size: 11px; letter-spacing: 1px; color: var(--muted); }
.bare-row span:nth-child(3) { color: var(--muted); font-size: 12.5px; }
.bare-row:hover span:nth-child(2) { box-shadow: 0 1px 0 0 currentColor; filter: var(--hover-lift); }

/* ============================================================
   THE FRAME
   ============================================================ */
.frame {
  position: fixed; inset: 0; z-index: 60;
  pointer-events: none;               /* only the words themselves catch a click */
}
/* the navigation sits above the logo, so an open dropdown is never sliced by
   the mark it runs beside */
.frame > * { pointer-events: auto; position: absolute; }
.logo { z-index: 1; }
.fr { z-index: 2; }
/* the two corners that open a list stand above the side rails, so a panel is
   never printed through by the word standing beside it */
.fr-tl, .fr-tr { z-index: 3; }

.fr { display: flex; gap: 22px; align-items: baseline; }
.fr:empty { display: none; }
.fr-tl { top: var(--fr-pad); left: var(--fr-pad); }
.fr-tr { top: var(--fr-pad); right: var(--fr-pad); }
/* The foot stands in the band between the bottom of the content box and the
   glass. It used to be hung from --fr-pad, the same measure the two top
   corners are hung from — which left the words high in the band with all the
   air collected underneath them. They are centred on the band instead:
   --fr-bot is what holds .main off the bottom, so half of it is the band's
   own middle, and the row is pulled back by half its own height to sit on
   that line. --foot-drop is the optical correction on top of that, and it
   depends on how much leading the row is carrying: Helvetica keeps the body's
   1.55, which already sits the letters near enough the middle of the box, so
   it wants nothing. The display face is set solid, and a line box with no
   leading still reserves room under the baseline for descenders that a face
   of capitals never uses — so there the letters read high and want a nudge
   down. The value is em on the row, which is 14px in every variation, so it
   is a fixed 2.24px rather than something that drifts with the menu size.
   Measured against the true middle of the band: within a third of a pixel
   on the three variations that carry the face, and under a pixel on 03. */
:root { --foot-drop: 0em; }
.fr-bl, .fr-br, .fr-bc {
  bottom: calc(var(--fr-bot) / 2);
  transform: translateY(calc(50% + var(--foot-drop)));
}
.fr-bl { left: var(--fr-pad); }
.fr-br { right: var(--fr-pad); }
.fr-bc { left: 50%; transform: translate(-50%, calc(50% + var(--foot-drop))); }
/* the two sides read up the left and down the right, centred on the box */
.fr-l { left: var(--fr-pad); top: 50%; transform: translateY(-50%); }
.fr-r { right: var(--fr-pad); top: 50%; transform: translateY(-50%); }
/* A vertical line box is as wide as the line-height, and the letters sit
   centred in it — so TALKS AND PRESENTATIONS was standing a half-leading in
   from the glass while WORK and BIO started hard on --fr-pad, and the frame
   read as though its sides had been indented. The box is pulled in to the
   type, and what half-leading is left is taken off the outside, so the T of
   TALKS lands on the same line as the W of WORK and the B of BIO, and the
   S of PUBLICATIONS on the same line as EXHIBITIONS and CV. In em, so it
   holds wherever --nav-up and --uc-nav-up put the size. */
:root { --rail-trim: .15em; }
.fr-l .nav-link, .fr-r .nav-link { writing-mode: vertical-rl; line-height: 1; }
/* The padding turns with the words. On a horizontal word the 4px is above and
   below and the 7px either side; standing on end the roles swap, so the rule
   that lands under the letters lands 4px off them there too. The two margins
   below cancel whichever of the two is now on the outside. */
.fr-l .nav-link, .fr-r .nav-link { padding: 7px 4px; margin: -7px -4px; }
.fr-l .nav-link {
  transform: rotate(180deg);
  margin-left: calc(-4px - var(--rail-trim));
}
.fr-r .nav-link { margin-right: calc(-4px - var(--rail-trim)); }

/* ---------- the rule under a hovered word, on the two rails ----
   The base rule is `inset 0 -1px`, a line along the foot of the box. That is
   right for a word lying down and wrong for one standing up: on the rails it
   came out as a short horizontal tick under the LAST letter instead of a rule
   running the length of the word.

   In vertical-rl the glyphs turn a quarter clockwise, so their feet face the
   box's left edge — `inset 1px 0` is the underline, and it runs the full
   height of the word. It is stated in the element's own coordinates, so the
   180-degree turn on the left rail carries it round with the letters: on the
   left rail the rule appears to the right of the word, on the right rail to
   the left, and on both of them it sits under the feet of the capitals and
   between the word and the work. */
.fr-l .nav-link:hover, .fr-r .nav-link:hover {
  box-shadow: inset 1px 0 0 0 currentColor;
}
.fr-l .nav-item.is-active > .nav-link,
.fr-r .nav-item.is-active > .nav-link,
.fr-l .nav-item.is-active > .nav-link:hover,
.fr-r .nav-item.is-active > .nav-link:hover { box-shadow: none; }

/* ---------- logo -------------------------------------------
   The supplied mark, with the wordmark set over its bar. The wordmark takes
   whichever face the variation is set in, so it changes with the type. */
.logo {
  /* --mark-w is the width the mark is actually drawn at, which is not always
     --logo-w: the mark is also held to a share of the window so it cannot
     crowd the burger on a narrow phone. The wordmark is sized off the drawn
     width rather than off --logo-w, so the word keeps the same share of the
     bar whatever the mark is scaled to. */
  --mark-w: min(var(--logo-w), 40vw);
  top: var(--fr-pad); left: 50%; transform: translateX(-50%);
  width: var(--mark-w); line-height: 0; display: block;
}
.logo-bg { width: 100%; height: auto; display: block; }
.logo-word {
  /* NEP SIDHU is laid into the mark's white bar and centred inside it, rather
     than nudged at by eye. The bar was measured off the supplied file, which
     is 747 x 339: it runs x 4-652 and y 132-254, so as a share of the mark it
     is inset .54% from the left and 12.72% from the right, and stands 38.94%
     down at 35.99% of the height. Shares rather than pixels, because the mark
     is scaled - 206px in the frame, 130px in the mobile bar - and the bar
     scales with it. */
  position: absolute;
  left: .54%; right: 12.72%; top: 38.94%; height: 35.99%;
  display: flex; align-items: center; justify-content: center;
  /* letter-spacing lays a step after the last letter as well as between them,
     so the run of ink sits half a step left of the box it is centred in. A
     step of padding on the left takes the content box in by the same amount,
     which moves its centre right by half a step and puts the ink back on the
     middle of the bar. */
  padding-left: .13em;
  font-family: var(--font-logo); font-weight: 700;
  font-size: calc(var(--mark-w) * .078);
  letter-spacing: .13em; line-height: 1; white-space: nowrap;
  color: var(--logo-ink);
}
.logo:hover .logo-word { opacity: .72; }

/* ---------- nav items --------------------------------------- */
.nav-item { position: relative; display: inline-block; }
.nav-link {
  font-family: var(--font-nav);
  font-size: calc(15px * var(--nav-up)); font-weight: 700; letter-spacing: .4px;
  color: var(--nav-ink); white-space: nowrap; display: inline-block;
  padding: 4px 7px; margin: -4px -7px;
  transition: background .15s ease, color .15s ease, filter .15s ease;
}
.nav-link:hover { box-shadow: inset 0 -1px 0 0 currentColor; filter: var(--hover-lift); }

/* where you are: the current page is boxed, as the studio's example does it */
.nav-item.is-active > .nav-link {
  background: var(--nav-active-bg); color: var(--nav-active-ink);
  box-shadow: none;
}
.nav-item.is-active > .nav-link:hover { box-shadow: none; filter: var(--hover-lift); }

/* ---------- dropdowns --------------------------------------- */
.drop {
  position: absolute; top: 100%; left: 0; padding-top: 14px;
  opacity: 0; visibility: hidden; transform: translateY(-4px);
  transition: opacity .18s ease, transform .18s ease, visibility .18s;
  z-index: 70;
}
.fr-tr .drop { left: auto; right: 0; }
.nav-item.has-drop:hover .drop,
.nav-item.has-drop.is-open .drop { opacity: 1; visibility: visible; transform: none; }
/* The panel takes the width of its own longest title rather than a number
   picked in advance — at 300px with a 54px date column the longer works were
   wrapping to three lines each and the list read as a squeezed column. It is
   still capped, so it can never cross the page, and it is held to the height
   of the content box so it never clips a row half way. */
.drop-in {
  display: block; background: var(--drop-bg); border: 1px solid var(--drop-border);
  padding: 14px 0; text-align: left;
  width: max-content; min-width: 380px; max-width: var(--drop-max);
  max-height: calc(100svh - var(--fr-top) - var(--fr-bot) - 24px);
  overflow-y: auto; overscroll-behavior: contain;
}
.drop-link {
  display: flex; gap: 20px; padding: 8px 24px;
  font-size: 13px; line-height: 1.45;
  letter-spacing: .3px; color: var(--drop-ink); align-items: baseline;
}
.drop-link:hover { background: var(--drop-hover); }
.drop-year {
  flex: 0 0 66px; font-size: 11.5px; letter-spacing: .8px;
  color: var(--muted); white-space: nowrap;
}
.drop-title { flex: 1; min-width: 0; }

/* ---------- contact links, bottom centre ---------------------
   Each word carries its own mark to the left of it. The mark is sized in em,
   so it follows the word rather than being pinned to a pixel the frame has
   since grown past, and it is drawn on the same hairline the rest of the
   frame is: it is read WITH the word, not instead of it.

   The gap between the two words is the one number the studio moved: the
   frame was drawn at 26px and it is opened by 70 per cent from there. */
:root { --cx-gap: 44px; }        /* 26px, opened by 70% */
.cx { display: inline-flex; gap: var(--cx-gap); align-items: baseline; }
.cx-link {
  font-family: var(--font-nav);
  font-size: calc(15px * var(--nav-up)); font-weight: 700; letter-spacing: .4px; color: var(--nav-ink);
  white-space: nowrap;
  /* the mark and the word share one baseline; the gap between them is the
     word's own, so it never drifts when the frame is scaled */
  display: inline-flex; align-items: baseline; gap: .42em;
}
.cx-ico {
  width: .82em; height: .82em; flex: 0 0 auto;
  fill: none; stroke: currentColor; stroke-width: 1.5;
  stroke-linecap: round; stroke-linejoin: round;
  /* a viewBox has no baseline of its own, so it is dropped onto the word's */
  align-self: baseline; transform: translateY(.055em);
}
/* the rule belongs under the word, not under the word and its mark */
.cx-link:hover .cx-word { box-shadow: inset 0 -1px 0 0 currentColor; }
.cx-link:hover { filter: var(--hover-lift); }
.cx-link { transition: filter .15s ease; }

/* socials keep their glyphs, for the drawer */
.socials { display: inline-flex; gap: 14px; align-items: center; }
.soc svg {
  width: 17px; height: 17px; fill: none; stroke: var(--nav-ink);
  stroke-width: 1.3; display: block;
}
.soc:hover svg { opacity: .55; }

/* ---------- burger + drawer ---------------------------------- */
.burger {
  display: none; background: none; border: 0; padding: 6px; cursor: pointer;
  width: 34px; height: 30px; flex-direction: column; justify-content: center; gap: 6px;
  position: absolute; right: 14px; top: 16px; z-index: 3;
}
.burger span { display: block; height: 1.5px; width: 22px; background: var(--nav-ink); }
.drawer {
  position: fixed; inset: 0 0 0 auto; width: min(88vw, 420px); z-index: 90;
  background: var(--drawer-bg); overflow-y: auto;
  padding: 78px 26px 40px; transform: translateX(100%);
  visibility: hidden;
  transition: transform .28s ease, visibility .28s;
}
.drawer.is-open { transform: none; visibility: visible; }
.drawer-close {
  position: absolute; top: 16px; right: 20px; z-index: 2;
  background: none; border: 0; cursor: pointer; padding: 4px 8px;
  font-size: 30px; line-height: 1; color: var(--ink);
  font-family: inherit;
}
.dgroup { margin-bottom: 26px; }
.dhead {
  display: block; font-size: 16px; font-weight: 700; letter-spacing: 1.2px;
  margin-bottom: 8px; color: var(--ink);
}
.ditem {
  display: block; font-size: 14px; padding: 5px 0; color: var(--muted);
  border-bottom: 1px solid var(--hairline);
}
.dgroup-text .dhead { font-weight: 400; font-size: 15px; margin-bottom: 12px; }
.dsoc { margin-top: 18px; }

/* ============================================================
   HOME — vertical feed (variations 03 and 04)
   ============================================================ */
.feed { display: block; }
.feed-item { margin-bottom: 58px; }
.feed-art { display: block; width: 100%; height: auto; }
.feed-cap {
  margin-top: 11px; padding: 0 var(--in-x);
  font-size: 14px; line-height: 1.55; color: var(--sub-ink);
  display: flex; flex-wrap: wrap; gap: 10px; align-items: baseline;
}
.feed-link {
  box-shadow: 0 1px 0 0 currentColor;
  /* 14px is .feed-cap's size, restated so --uc-up can lift it */
  font-size: calc(14px * var(--uc-up));
}
.feed-link:hover { filter: var(--hover-lift); }
.feed-meta {
  font-size: 12px; letter-spacing: 1.6px; text-transform: uppercase;
  color: var(--sub-ink);
}
.feed-credit { flex-basis: 100%; font-style: italic; }

/* ============================================================
   GALLERY GRID — home and section indexes (variations 01 and 02)
   ============================================================ */
.page-grid .main { padding: 0; }
.gcells {
  display: grid; grid-template-columns: 1fr 1fr; gap: var(--gutter);
  align-items: start; width: 100%;
}
.gcol { display: flex; flex-direction: column; gap: var(--gutter); min-width: 0; }
.gcell-link { display: block; }
.gcell-art { display: block; width: 100%; height: auto; }
.gcell-link:hover .gcell-art { filter: var(--hover-art); }
.gcell-link:focus-visible { outline: 2px solid var(--ink); outline-offset: 3px; }
.gcell-cap {
  display: block; margin-top: 10px; padding: 0 var(--cap-x);
  font-size: 13.5px; line-height: 1.5; color: var(--sub-ink);
}
.gcell-title {
  display: block; font-weight: 700;
  /* 13.5px is .gcell-cap's size, restated so --uc-up can lift it. It rises
     with the caption: the title of a work must never be set smaller than
     the line of subtext under it. */
  font-size: calc(13.5px * var(--uc-up));
}
.gcell-link:hover .gcell-title { filter: var(--hover-lift); }
.gcell-meta {
  display: block; margin-bottom: 2px;
  font-size: 11.5px; letter-spacing: 2.2px; text-transform: uppercase;
}
.gcell-sub { display: block; margin-top: 2px; }
.gcell-credit { display: block; font-style: italic; }

/* the opening plate: one work at the full measure of the box, then the
   columns underneath it — on all three gallery variations */
.ghero { margin-bottom: var(--gutter); }
.ghero-link { display: block; position: relative; }
.ghero-art {
  display: block; width: 100%;
  height: calc(100vh - var(--main-top) - var(--main-bot));
  height: calc(100svh - var(--main-top) - var(--main-bot));
  object-fit: cover;
}
.ghero-cap {
  display: block; padding: 12px var(--fr-side) 0;
  font-size: 13.5px; line-height: 1.5; color: var(--sub-ink);
}

/* a section index adds a heading above the grid */
.gindex-head { padding: 4vh var(--in-x) 40px; }
.page-gindex .h1 {
  font-size: calc(clamp(30px, 4.4vw, 54px) * var(--uc-up));
  letter-spacing: -.6px; line-height: 1;
  margin-bottom: 0;
}
.gindex-head .plates-count { margin-top: 14px; }
.gindex-head .note-section { margin-top: 20px; }

/* where the grid lands */
.gend { width: 100%; padding: 60px var(--in-x) 0; }
.hend-h { font-size: 10px; letter-spacing: 2.6px; color: var(--muted); }
.hend-nav { margin: 14px 0 0; max-width: 340px; }
.hend-nav li { padding: 5px 0; border-bottom: 1px solid var(--hairline); }
.hend-nav a { font-size: 15px; letter-spacing: .3px; }
.hend-nav a:hover { box-shadow: 0 1px 0 0 currentColor; filter: var(--hover-lift); }

/* ============================================================
   PROJECT PAGE — wall label, then the plates, straight down
   (variations 01 and 02; replaces the sideways filmstrip)
   ============================================================ */
.page-pg .main { padding: 0; }
.pg-head {
  padding: 6vh var(--in-x) 44px; max-width: 780px;
}
.pg-plates { display: flex; flex-direction: column; gap: var(--gutter); }
.pg-fig { width: 100%; }
.pg-fig .art { width: 100%; height: auto; }
.pg-fig .cap { padding: 0 var(--in-x); max-width: none; }
.pg-fig-vid { padding: 0 var(--in-x); }
.pg-fig-vid .vid { max-width: 1000px; }
.pg-back {
  display: inline-block; margin: 64px var(--in-x) 0;
  font-size: 10px; letter-spacing: 2.2px; text-transform: uppercase;
  background: var(--nav-active-bg); color: var(--nav-active-ink);
  padding: 10px 15px;
}
.pg-back:hover { filter: var(--hover-lift); }

/* ---------- reveals ----------
   Each plate surfaces as it comes into view: opacity, a hair of scale, one
   long ease, with the caption half a second behind so the picture lands
   first. */
.reveal {
  opacity: 0; transform: scale(.985) translateY(16px);
  transition: opacity 1.5s ease, transform 2s cubic-bezier(.16,.84,.44,1);
}
.reveal.is-lit { opacity: 1; transform: none; }
.reveal-cap { opacity: 0; transition: opacity 1.6s ease .45s; }
.reveal.is-lit .reveal-cap { opacity: 1; }

@media (prefers-reduced-motion: reduce) {
  .reveal, .reveal-cap {
    opacity: 1 !important; transform: none !important; transition: none;
  }
}

/* ---------- shared project typography ---------------------- */
.proj-title { font-size: calc(15px * var(--uc-up)); font-weight: 700; letter-spacing: 1.6px; text-transform: uppercase; }
.proj-year { font-size: 14.5px; color: var(--sub-ink); margin-top: 6px; }
.proj-sub  { font-size: 14.5px; color: var(--sub-ink); margin-top: 2px; }
.proj-body-src { color: var(--muted); }
.proj-src {
  margin-top: 14px; font-size: 10px; letter-spacing: 2.2px;
  text-transform: uppercase; color: var(--muted);
}
.proj-note {
  font-size: 12px; line-height: 1.5; color: var(--flag);
  border-left: 2px solid var(--flag); padding-left: 10px; margin: 18px 0;
}
.proj-body { margin-top: 14px; }
.proj-count {
  font-size: 11px; letter-spacing: 1.6px; color: var(--muted);
  margin-top: 24px; text-transform: uppercase;
}
.creds-h { font-size: 11px; font-weight: 700; letter-spacing: 2.4px; margin-top: 26px; }
.creds { margin-top: 8px; }
.creds li { font-size: 12.5px; color: var(--muted); padding: 2px 0; }

/* ---------- moving image -----------------------------------
   Every film on this site belongs to the institution or collaborator that
   made it, so nothing is requested from a third-party player until the
   reader presses play. The facade below is a real button; the iframe only
   exists after it is pressed. */
.vid { max-width: 900px; }
.vid-frame {
  position: relative; width: 100%; aspect-ratio: 16 / 9;
  background: var(--ph-bg); border: 1px solid var(--ph-border);
}
.vid-frame iframe {
  position: absolute; inset: 0; width: 100%; height: 100%; border: 0; display: block;
}
.vid-art, .vidcard-art {
  position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: cover; display: block;
}
.vid-frame.has-poster .vid-face,
.vidcard.has-poster .vidcard-face {
  color: #FFF;
  background: linear-gradient(to top, rgba(0,0,0,.72), rgba(0,0,0,.18) 52%, rgba(0,0,0,.3));
}
.vid-frame.has-poster .vid-face-s { color: rgba(255,255,255,.74); }
.vidcard.has-poster .vidcard-meta { color: rgba(255,255,255,.82); }
.vid-frame.has-poster .vid-face,
.vidcard.has-poster .vidcard-face { justify-content: center; }
.vid-frame.has-poster .vid-face-t,
.vid-frame.has-poster .vid-face-s,
.vidcard.has-poster .vidcard-meta {
  position: absolute; left: 16px; right: 16px; text-align: left;
}
.vidcard.has-poster .vidcard-meta { bottom: 13px; }
.vid-frame.has-poster .vid-face-t { bottom: 34px; }
.vid-frame.has-poster .vid-face-s { bottom: 15px; }
.vid-face {
  position: absolute; inset: 0; width: 100%;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 12px; background: none; border: 0; cursor: pointer;
  font-family: inherit; color: var(--ph-ink); text-align: center; padding: 20px;
}
.vid-play {
  width: 58px; height: 58px; flex: 0 0 auto;
  border: 1.5px solid currentColor; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
}
.vid-play::after {
  content: ""; display: block; margin-left: 5px;
  border-style: solid; border-width: 9px 0 9px 15px;
  border-color: transparent transparent transparent currentColor;
}
.vid-face-t { font-size: 11px; letter-spacing: 2.4px; text-transform: uppercase; }
.vid-face-s { font-size: 11px; color: var(--ph-meta); letter-spacing: .2px; }
.vid-face:hover .vid-play { opacity: .6; }
.vid-face:focus-visible { outline: 1px solid currentColor; outline-offset: -6px; }
.vid-credit {
  margin-top: 11px; display: flex; flex-wrap: wrap; gap: 5px 16px;
  font-size: 11.5px; line-height: 1.5; color: var(--muted);
}
.vid-owner { color: var(--ink); }
.vid-creds { flex-basis: 100%; font-style: italic; }
.vid-out { box-shadow: 0 1px 0 0 currentColor; white-space: nowrap; }

/* index stand-in: same weight as a photograph, still no player */
.vidcard { display: block; width: 100%; }
.vidcard-in {
  position: relative; display: block; aspect-ratio: 16 / 9; width: 100%;
  overflow: hidden;
  background: var(--ph-bg); border: 1px solid var(--ph-border); color: var(--ph-ink);
}
.vidcard-face {
  position: absolute; inset: 0;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 12px; text-align: center; padding: 16px;
}
.vidcard.has-poster .vidcard-in { border-color: transparent; }
.vidcard .vid-play { width: 44px; height: 44px; }
.vidcard-meta {
  font-size: 10.5px; letter-spacing: 2px; text-transform: uppercase; color: var(--ph-meta);
}
.note-section { max-width: 620px; }

/* ---------- text pages ------------------------------------- */
.page-text .main { padding: 8vh var(--in-x) 10vh; }
.txt { max-width: 720px; margin: 0 auto; }
.h1 {
  font-size: calc(30.8px * var(--uc-up)); font-weight: 700; line-height: 1;
  letter-spacing: normal; margin-bottom: 30px;
}
.txt p {
  font-size: 14px; line-height: 18.2px; letter-spacing: .5px;
  margin-bottom: 18.2px; text-align: justify; text-justify: inter-word;
}
.txt p:last-child { margin-bottom: 0; }
.note {
  font-size: 12px; color: var(--flag); border-left: 2px solid var(--flag);
  padding-left: 10px; margin-bottom: 26px !important;
}
.credit { font-size: 11px; color: var(--muted); margin-top: 8px; }
.txt-bio { max-width: 960px; }
.bio-grid { display: grid; grid-template-columns: 260px 1fr; gap: 52px; align-items: start; }
.pill {
  display: inline-block; background: var(--pill-bg); color: var(--pill-ink);
  font-size: 11px; font-weight: 700; letter-spacing: 2px; padding: 12px 26px;
  border-radius: 999px; margin-bottom: 34px;
}
.pill:hover { filter: var(--hover-lift); }
.cv-group { margin-bottom: 44px; }
.cv-h {
  font-size: calc(21px * var(--uc-up)); font-weight: 700; letter-spacing: .2px; line-height: 1;
  margin-bottom: 16px;
}
.cv-list li {
  display: grid; grid-template-columns: 106px minmax(0, 1fr); gap: 4px;
  font-size: 14px; line-height: 18.2px; letter-spacing: .5px;
  padding: 2px 0; border: 0; color: var(--ink);
}
.cv-year { white-space: nowrap; }
.pub-list li {
  font-size: 15px; line-height: 18.2px; letter-spacing: .5px;
  padding: 0; border: 0;
}
.pub-pub { color: var(--muted); }
.pub-head { font-weight: 700; }
.pub-year, .pub-extra { color: var(--muted); font-size: 12px; }

/* ---------- plates index (variations 03, 04, and Talks in 01/02) ------- */
.page-plates .main { padding: 5vh var(--in-x) 0; }
.plates-head { margin-bottom: 54px; }
.page-plates .h1 {
  font-size: calc(clamp(34px, 5vw, 62px) * var(--uc-up));
  letter-spacing: -1px; line-height: 1;
  margin-bottom: 0;
}
.plates-count {
  font-size: 11px; letter-spacing: 3px; color: var(--muted);
  text-transform: uppercase; margin-top: 16px;
}
.plates-head .note-section { margin-top: 22px; }
.plates { display: grid; grid-template-columns: repeat(2, 1fr); gap: 60px 40px; }
.plate { position: relative; display: block; }
.plate-wide { grid-column: 1 / -1; }
.plate-num {
  position: absolute; top: -14px; left: -4px; z-index: 2;
  font-size: 11px; letter-spacing: 2.4px; color: var(--muted);
}
.plate-meta { display: block; margin-top: 15px; }
.plate-year { display: block; font-size: 12.5px; letter-spacing: 2.4px; color: var(--sub-ink); }
.plate-title {
  display: inline-block; margin-top: 7px;
  font-size: calc(clamp(19px, 2.1vw, 27px) * var(--uc-up));
  font-weight: 700; letter-spacing: -.3px; line-height: 1;
}
.plate-sub { display: block; margin-top: 8px; font-size: 14px; color: var(--sub-ink); }
.plate:hover .art { filter: var(--hover-art); }
.plate:hover .plate-title { box-shadow: 0 1px 0 0 currentColor; filter: var(--hover-lift); }
.plate .vidcard-in { max-height: 56vh; }
.plate .art { width: 100%; }

/* ---------- a single plated item (Talks, and all of 03/04) ------------ */
.page-proj3 .main { padding: 0; }
.proj3-head { padding: 7vh var(--in-x) 6vh; max-width: 1200px; }
.proj3-title {
  font-size: calc(clamp(30px, 5vw, 62px) * var(--uc-up)); font-weight: 700;
  letter-spacing: -1.2px; line-height: 1;
}
.proj3-year { font-size: 13.5px; letter-spacing: 3px; color: var(--sub-ink); margin-top: 22px; }
.proj3-sub { font-size: 15.5px; color: var(--sub-ink); margin-top: 6px; max-width: 640px; }
.stack-fig { margin-bottom: 7vh; }
.stack-fig.is-bleed { padding: 0; }
.stack-fig.is-inset {
  padding: 0 var(--in-x); max-width: 1080px; margin-left: auto; margin-right: auto;
}
.stack-text {
  max-width: 640px; margin: 0 auto 8vh; padding: 0 var(--in-x);
  font-size: 15px; line-height: 1.7;
}
.stack-creds { max-width: 640px; margin: 0 auto; padding: 0 var(--in-x) 4vh; }

/* ---------- footer ----------------------------------------- */
.ftr { margin-top: 90px; padding: 0 var(--in-x) 46px; }
.ftr-rule { height: 1px; background: var(--hairline); margin-bottom: 24px; }
.ftr-in { display: flex; gap: 26px; align-items: center; flex-wrap: wrap; }
.ftr-line { font-size: 12px; color: var(--muted); max-width: 560px; }
.ftr-line a { box-shadow: 0 1px 0 0 currentColor; }

/* ---------- which elements are "headings" -------------------
   Last in the sheet on purpose: .proj-title and friends set their own weight
   and case further up, and this has to win over them. Small labels — the
   captions, the section rules, the drawer — are deliberately not in this
   list; they stay in Helvetica whatever the variation. */
h1, h2, h3, .h1, .cv-h, .proj-title, .proj3-title, .plate-title,
.gcell-title {
  font-family: var(--font-head);
  text-transform: var(--head-case);
  font-weight: var(--head-weight);
  /* The studio sets its titles solid. Every title size in the sheet states
     it too, so the value is greppable where it is used; this is here so a
     title added later cannot arrive with the body's 1.55 leading by
     default. */
  line-height: 1;
  /* one ink for every title on the site, so the studio's Dover White is set
     in one place per variation rather than chased through the sheet. It is
     last in the file for the same reason the family is: .gcell-title and
     .feed-link name var(--ink) further up, and this has to win. */
  color: var(--title-ink);
}
/* the title inside a figure caption takes the ink and nothing else: it is a
   line of caption, and the caption stays in Helvetica in every variation */
.cap-title { color: var(--title-ink); }
/* the feed title takes the face and the case but not the weight: it sits
   in a caption row and has always been set at the body weight, which is
   also the only weight the display face carries. */
.feed-link {
  font-family: var(--font-head);
  text-transform: var(--head-case);
  color: var(--title-ink);
  line-height: 1;
}

/* ============================================================
   RESPONSIVE
   A frame on four sides needs a window wide enough to spare the room. Below
   that the frame collapses to a bar with the logo and the drawer, the page
   goes back to scrolling itself, and no rule anywhere reintroduces a
   sideways bar.
   ============================================================ */
@media (max-width: 1100px) {
  :root { --fr-side: 62px; --fr-pad: 18px; --logo-w: 168px; }
  .nav-link, .cx-link { font-size: 13px; }
  .cx { --cx-gap: 31px; }   /* 18px, opened by 70% */
}

@media (max-width: 860px) {
  html, body { height: auto; }
  body { overflow: auto; overflow-x: hidden; }
  .frame {
    position: fixed; inset: 0 0 auto 0; height: 74px;
    background: var(--bg); border-bottom: 1px solid var(--hairline);
    pointer-events: auto;
  }
  .fr { display: none; }
  .burger { display: flex; top: 22px; }
  /* the mark is .4538 as tall as it is wide, so 130px clears the 74px bar */
  .logo {
    --mark-w: min(130px, 46vw);
    top: 10px; left: 16px; transform: none; width: var(--mark-w);
  }
  .main {
    position: static; inset: auto; overflow: visible;
    padding: 94px 20px 60px; background: none;
  }
  .page-grid .main, .page-pg .main, .page-proj3 .main { padding: 94px 0 60px; }
  /* one column now, so the caption comes in to the page margin while the
     picture keeps the full width of the screen */
  :root { --in-x: 20px; --gutter: 26px; --cap-x: var(--in-x); }
  .gcells { grid-template-columns: 1fr; gap: 0; }
  .gcol { gap: var(--gutter); }
  .gcol + .gcol { margin-top: var(--gutter); }
  .ghero-art { height: 62vh; }
  .ghero-cap { padding: 12px var(--in-x) 0; }
  .plates { grid-template-columns: 1fr; gap: 46px; }
  .plate-wide { grid-column: auto; }
  .bio-grid { grid-template-columns: 1fr; gap: 26px; }
  .txt p { text-align: left; }
  .stack-fig.is-inset { padding: 0 var(--in-x); }
}


/* ============================================================
   THE BIENNIAL BLOCK — the locked film and the calendar
   ============================================================
   The film is the one thing on the site that moves by itself, so it is
   given the full measure of the content column and nothing beside it. The
   caption under it is centred: it is an announcement rather than a wall
   label, and it is the only centred type on the site for that reason.
   ------------------------------------------------------------ */
.feat { margin: 0 0 var(--gutter); }
/* the box carries the cropped aspect inline, from FEATURE's own numbers, so
   the calendar under it never jumps while the first frames are on the wire */
.feat-media {
  position: relative; width: 100%; overflow: hidden;
  background: var(--hairline);
  border-radius: var(--feat-radius);
  /* Safari has never reliably clipped a positioned child to its parent's
     radius on its own; the mask forces it to, and costs nothing elsewhere */
  -webkit-mask-image: -webkit-radial-gradient(#fff, #000);
  isolation: isolate;
}
.feat-vid {
  display: block; position: absolute; left: 0; bottom: 0;
  width: 100%; height: auto;
  /* the radius again on the film itself, so a browser that declines to clip
     still shows a rounded corner rather than a square one */
  border-radius: var(--feat-radius);
}
.feat-cap { text-align: center; padding: 20px var(--cap-x) 0; }
.feat-title {
  font-family: var(--font-head); font-weight: var(--head-weight);
  text-transform: var(--head-case);
  /* the studio asked for this one 2.5x: 17px was the wall-label measure and
     42.5px is that measure times 2.5. The clamp is the same number held off
     a phone, where 42px of title would take four lines. */
  font-size: calc(clamp(24px, 3.6vw, 42.5px) * var(--uc-up));
  line-height: 1.2;
  letter-spacing: .4px; color: var(--title-ink); margin: 0;
}
.feat-line {
  display: block; margin-top: 6px; font-size: 13px; letter-spacing: .4px;
  color: var(--sub-ink);
}
.feat-line:last-child {
  margin-top: 10px; font-size: 11px; letter-spacing: 2.6px;
  text-transform: uppercase; color: var(--muted);
}

/* the calendar — a date column and a detail column, stacking on a phone */
.sched { margin: calc(var(--gutter) * 1.4) 0 var(--gutter); }
.sched-h {
  font-family: var(--font-head); font-weight: var(--head-weight);
  text-transform: var(--head-case);
  font-size: calc(clamp(22px, 2.6vw, 30px) * var(--uc-up));
  letter-spacing: .3px; line-height: 1.15;
  color: var(--title-ink); margin: 0 0 14px; padding: 0 var(--cap-x);
}
.sched-list { list-style: none; margin: 0; padding: 0; }
.ev {
  display: grid; grid-template-columns: 210px 1fr; gap: 6px 28px;
  padding: 20px var(--cap-x); border-top: 1px solid var(--hairline);
}
.ev:last-child { border-bottom: 1px solid var(--hairline); }
.ev-date {
  display: block; font-size: 11px; letter-spacing: 2.4px;
  text-transform: uppercase; font-weight: 700; color: var(--ink);
}
.ev-meta {
  display: block; margin-top: 5px; font-size: 12px; line-height: 1.5;
  color: var(--muted);
}
.ev-title {
  font-size: clamp(20px, 2.2vw, 27px); font-weight: 700; letter-spacing: .2px;
  color: var(--title-ink); margin: 0 0 8px; line-height: 1.2;
}
.ev-venue { font-size: 12.5px; color: var(--sub-ink); margin: 0 0 8px; }
.ev-body {
  font-size: 13px; line-height: 1.55; color: var(--muted); margin: 0 0 8px;
}
.ev-body:last-child { margin-bottom: 0; }
/* the running order of the day trip: numbered, because with the clock
   times held back the sequence is the only thing carrying the order */
.ev-run { margin: 4px 0 0; padding-left: 18px; }
.ev-run li {
  font-size: 13px; line-height: 1.55; color: var(--muted); padding: 3px 0;
}
.ev-tbc {
  margin: 12px 0 0; font-size: 11px; letter-spacing: 2.4px;
  text-transform: uppercase; color: var(--muted);
}
@media (max-width: 700px) {
  .ev { grid-template-columns: 1fr; gap: 10px; }
}

/* ============================================================
   COMING SOON
   ============================================================
   The studio asked for the word in the title's own face, large, and in the
   centre of the page. It is given the height of the content box rather than
   a margin, so it sits in the middle of what the reader is looking at
   whatever the window is.
   ------------------------------------------------------------ */
.soon {
  display: flex; align-items: center; justify-content: center;
  min-height: 52vh; padding: 40px 0;
}
.soon-word {
  font-family: var(--font-head); font-weight: var(--head-weight);
  font-size: clamp(38px, 9vw, 132px); line-height: 1;
  letter-spacing: .04em; text-transform: uppercase;
  color: var(--title-ink); margin: 0; text-align: center;
}

/* ============================================================
   THE STANDING NOTICE — 02, 03, 04
   ============================================================
   It stands inside the content box rather than against the glass: the frame
   owns all four edges, and the foot of it carries Bio, the contact links and
   CV. --main-bot is where the content box stops, so the notice sits just
   above that line and never lands on top of the navigation.
   ------------------------------------------------------------ */
.notice {
  position: fixed; z-index: 80;
  right: var(--main-side); bottom: calc(var(--main-bot) + 18px);
  max-width: min(340px, calc(100vw - var(--main-side) * 2));
  display: flex; align-items: flex-start; gap: 8px;
  padding: 15px 13px 15px 17px;
  background: var(--bg); border: 1px solid var(--hairline);
  border-radius: 14px; box-shadow: 0 12px 34px rgba(0, 0, 0, .3);
  animation: notice-in .5s .55s both;
}
/* display:flex would otherwise beat the attribute, and the script leans on it */
.notice[hidden] { display: none; }
@keyframes notice-in {
  from { opacity: 0; transform: translateY(10px); }
  to   { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce) { .notice { animation: none; } }
.notice-link { display: block; text-decoration: none; color: inherit; }
.notice-kicker {
  display: block; font-size: 10px; letter-spacing: 2.4px;
  text-transform: uppercase; color: var(--muted); line-height: 1.5;
}
.notice-title {
  display: block; margin-top: 7px; font-size: 14px; line-height: 1.35;
  font-weight: 700; color: var(--title-ink);
}
.notice-go {
  display: block; margin-top: 9px; font-size: 10.5px; letter-spacing: 1.8px;
  text-transform: uppercase; color: var(--sub-ink);
}
.notice-link:hover .notice-go, .notice-link:hover .notice-title {
  filter: var(--hover-lift);
}
.notice-link:focus-visible { outline: 2px solid var(--ink); outline-offset: 3px; }
.notice-x {
  margin-left: auto; flex: none; background: none; border: 0; cursor: pointer;
  color: var(--muted); font-size: 17px; line-height: 1; padding: 0 2px;
}
.notice-x:hover { filter: var(--hover-lift); }
@media (max-width: 700px) {
  .notice {
    left: var(--in-x); right: var(--in-x); max-width: none;
    bottom: calc(var(--main-bot) + 10px);
  }
}

/* a publication whose title is a link out to where it can be bought */
.pub-a { color: inherit; text-decoration: underline; text-underline-offset: 3px; }
.pub-a:hover { filter: var(--hover-lift); }


/* ===================== V1 · GALLERY ========================
   The master layout — the frame holds the content off the glass on all four
   sides and nothing overlaps the work — carried onto 04's dark ground and
   set in 04's face. The grid, the measures and every word on the page are
   01's own; only the ground and the type have moved. */
:root {
  --bg: #0E0E0E;
  --content-bg: #0E0E0E;
  --ink: #EDEBE6;
  --muted: #8B887F;
  --hairline: #262624;
  --nav-ink: #EDEBE6;
  --nav-active-bg: #EDEBE6;
  --nav-active-ink: #0E0E0E;
  --logo-ink: #0E0E0E;
  --flag: #C9A24B;
  /* 01's own frame measures, not 03's — this is still the gallery */
  --pad-x: 34px;
  --gutter: 40px;
  --ph-bg: #171716;
  --ph-border: #2A2A28;
  --ph-ink: #A9A69D;
  --ph-meta: #6E6B64;
  --drop-bg: #131312;
  --drop-border: #2A2A28;
  --drop-ink: #EDEBE6;
  --drop-hover: #1E1E1C;
  --drawer-bg: #0E0E0E;
  --pill-bg: #EDEBE6;
  --pill-ink: #0E0E0E;
  --scroll-thumb: #34342F;
  --scroll-thumb-lit: #56564D;

  /* 04's type: the display face on the titles, 40 per cent up, with the
     navigation, the captions and the body copy left in Helvetica. */
  --font-head: var(--uc);
  --head-case: uppercase;
  --head-weight: 400;
  /* 1.4 is the face's own step, the one 02 and 04 take. 01 takes a further
     40 per cent on top of it — 1.4 x 1.4 — so its titles carry the grid the
     way the plates carry 03 and 04. Every title size in the sheet is written
     as calc(<size> * var(--uc-up)), so this one number moves all of them. */
  --uc-up: 1.96;

  /* ---- 04's home measure, carried onto 01's cards ----------
     04's home page sets a work at clamp(19px, 2.2vw, 30px) lifted by its own
     --uc-up (1.4) and the home step (1.3). That is the size the studio picked
     for a work announced on a home page, and it is stated here as the
     arithmetic rather than as var(--uc-up) — 01's --uc-up is 1.96, so reading
     it would give a different size, and "exactly like 04" is the point. */
  --card-title: calc(clamp(19px, 2.2vw, 30px) * 1.4 * 1.3);
  /* 04 sets its caption rows 4px apart. The gallery cards were 2px, which at
     the old caption size read as one block of small type; at the new one it
     would read as a collision. */
  --card-row: 4px;
}

/* ---------- the cards: home, Work and Exhibitions -----------
   The three pages built from .gcell — the home grid and the two section
   indexes. Talks and Presentations is plated and is deliberately not here.
   Title size and the space under it are 04's home page exactly; the order of
   the lines is 01's own and is untouched. */
.page-grid .gcell-title {
  font-size: var(--card-title);
  line-height: 1;
}
.page-grid .gcell-cap {
  display: flex; flex-direction: column; align-items: flex-start;
  row-gap: var(--card-row);
  margin-top: 11px;
  font-size: 14px; line-height: 1.55;
}
/* the three small lines lose their own margins — the row-gap is what spaces
   them now, so one number moves all of them together */
.page-grid .gcell-meta {
  margin-bottom: 0;
  font-size: 12px; letter-spacing: 1.6px;
}
.page-grid .gcell-sub, .page-grid .gcell-credit { margin-top: 0; }

/* the dark ground's own device: a halo of the artwork's warmth behind each
   plate, never on the chrome */
.has-halo { position: relative; }
.has-halo::before {
  content: ""; position: absolute; inset: -20% 0; z-index: 0;
  background: radial-gradient(ellipse at center,
    rgba(201,162,75,.10) 0%, rgba(201,162,75,.035) 38%, transparent 68%);
  opacity: 0; transition: opacity 2.2s ease; pointer-events: none;
}
.has-halo.is-lit::before { opacity: 1; }
.has-halo > * { position: relative; z-index: 1; }

@media (prefers-reduced-motion: reduce) {
  .has-halo::before { display: none; }
}

/* ---------- an exhibition read as a gallery ----------------
   An exhibition page is its wall label and then its photographs, and stacked
   one above the other at the full measure of the content box that is one
   plate per screen — a show like Shadows in the Major Seventh carries
   twenty-three of them, which is twenty-three screens of scrolling and no way
   to see the show at all. In two columns the same photographs are read at a
   glance and any one of them is still a click away at full size.

   The columns are filled at build time rather than by CSS multi-column, for
   the reason the home grid is: the browser's own balancing needs the whole
   page laid out before it can split it, which fights lazy loading. See
   project_gallery_2col(). */
.exg-cols {
  display: grid; grid-template-columns: 1fr 1fr; gap: var(--gutter);
  align-items: start; width: 100%;
}
.exg-col { display: flex; flex-direction: column; gap: var(--gutter); min-width: 0; }
.exg-fig { width: 100%; margin: 0; }
.exg-fig .art { display: block; width: 100%; height: auto; }
/* the caption comes in to the same margin the gallery captions keep, so the
   writing lines up down the page and the pictures never do */
.exg-fig .cap { padding: 12px var(--cap-x) 0; max-width: none; }
.exg-vid { grid-column: 1 / -1; margin-bottom: var(--gutter); padding: 0 var(--in-x); }
.exg-vid .vid { max-width: 1000px; }
/* one column below the fold-out, where a half-width plate would be a stamp */
@media (max-width: 860px) {
  .exg-cols { grid-template-columns: 1fr; }
}

/* ---------- Dover White, SW 6385 ----------------------------
   The studio's colour, on every title on the page and on the mark between
   the two top corners. It is set once, on --title-ink, and the base sheet
   hands it to the headings, the grid titles, the plate titles and the feed
   titles from there. */
:root {
  --title-ink: #F0EADC;
  --sub-ink: #FFF;
  /* the fade the light ground uses as a lift would sink a word into this
     one, so a hover brightens here instead: Dover White goes to white, a
     reversed chip goes to white behind its black word, and a photograph
     comes up out of the dark */
  --hover-lift: brightness(1.22);
  --hover-art: brightness(1.18);
}

/* The supplied mark is pure white with an alpha channel, so the file is its
   own mask: the raster is dropped and the shape repainted in Dover White.
   NEP SIDHU is knocked out of the bar rather than printed on it, so it stays
   the near-black --logo-ink already gives it.

   Behind @supports because the fallback matters: without mask the ::before
   would print a solid Dover White rectangle over a hidden mark. A browser
   that cannot do this keeps the white mark it was always given. */
@supports ((-webkit-mask-image: url("")) or (mask-image: url(""))) {
  .logo-bg { opacity: 0; }
  .logo::before {
    content: ""; position: absolute; inset: 0;
    background-color: var(--title-ink);
    -webkit-mask: url("brand/logo-light.png") 0 0 / 100% 100% no-repeat;
            mask: url("brand/logo-light.png") 0 0 / 100% 100% no-repeat;
  }
}

/* ---------- the face's horizontal rhythm --------------------
   UppercaseOnly is very nearly monospaced and very nearly a third the width
   of Helvetica at the same size. Measured at 100px: cap height 70 against
   Helvetica's 71, but an H only 31 wide against Helvetica's 72 — the same
   height in a third of the width, which is what reads as squashed. The word
   space is the worse half of it: 30 units against the H's 31, so a space is
   the width of a letter and the words in a title run together into one
   string.

   Neither is fixable by size alone — --uc-up scales height and width
   together, so a larger setting is a larger squash. What the face needs is
   tracking; the word space the studio has asked to be left at the face's
   own, so word-spacing is zero everywhere the face is set and the tracking
   carries the separation on its own. Both belong here rather than in the
   base sheet: the letter-spacing values there (1.6px on .proj-title, -1px on
   the display sizes) were drawn for Helvetica, where tight is right, and
   they are what these rules replace. Everything is in em so it follows
   whatever size --uc-up lands on.

   The two groups part company because tracking does not scale with size the
   way the glyphs do: a caption-scale title needs the space opened up to be
   read at all, while a 42px one is already legible and the same em values
   would blow the words apart. */
.gcell-title, .feed-link, .proj-title {
  letter-spacing: .06em;
  word-spacing: 0;
  /* set solid, like every other title. The face has no descenders at all —
     it is capitals, digits and punctuation — so a title that wraps to two
     lines still has the best part of a third of an em between the foot of
     one line of capitals and the head of the next. */
  line-height: 1;
}
h1, .h1, h2, h3, .cv-h, .plate-title, .proj3-title {
  letter-spacing: .02em;
  word-spacing: 0;
}

/* The studio's further 30 per cent on the titles that head the home page.
   It is deliberately NOT --uc-up: that one is the face's own 40 per cent and
   applies to every title in the sheet, inner pages included. This is the
   home page's step alone, so the works are announced larger where the site
   opens than where they are listed. */
:root { --home-up: 1.3; }

/* ---------- the frame words ---------------------------------
   The menu goes into the face too. --font-nav already carries the family to
   .nav-link and .cx-link, so what is left is the case and the weight the
   face insists on, the same 40 per cent --uc-up gives the titles, and the
   tracking it needs for the same reason the titles need it — "TALKS AND
   PRESENTATIONS" is three words that would otherwise arrive as one.

   The wordmark is deliberately not here: it sits inside a supplied mark
   drawn around Helvetica and stays in Helvetica in every variation. The
   dropdown and drawer LISTS are not here either — those are listings of
   works, not menu words, and they stay in Helvetica with the captions. */
:root { --font-nav: var(--uc); }
.nav-link, .cx-link, .dhead {
  font-family: var(--uc);
  text-transform: uppercase;
  font-weight: 400;
  letter-spacing: .06em;
  word-spacing: 0;
  /* the frame words are set in the face too, so they are set solid with it.
     Every one of them is a single line, so this only shrinks the box around
     the word — which is what the foot and the two side rails are measured
     against; see --foot-drop and --rail-trim. */
  line-height: 1;
}
/* and with the leading gone the foot needs its nudge; see --foot-drop */
:root { --foot-drop: .16em; }
/* The menu gets its own step rather than the titles' 40 per cent. A title is
   a long string, so --uc-up's extra height is enough to give it presence; a
   menu word is four or five letters, and at 1.4 the face's narrowness left
   the frame reading lighter and smaller than the Helvetica it replaced even
   though the px had gone up. 1.75 is where the frame holds its own against
   the plates again. Checked for clipping from 2036px down to 900px, where
   the frame collapses to the bar and the drawer. */
/* 1.75 was where the frame held its own against the plates; the studio's
   further 30 per cent lands it at 2.275. */
:root { --uc-nav-up: calc(1.75 * 1.3); }
.nav-link, .cx-link { font-size: calc(15px * var(--uc-nav-up)); }
.dhead { font-size: calc(16px * var(--uc-nav-up)); }
.dgroup-text .dhead { font-weight: 400; font-size: calc(15px * var(--uc-nav-up)); }

/* ---------- Dover White under the title ---------------------
   DARK_INK hands the three dark variations a solid white for the writing
   under a title. The studio has asked the gallery variations off it: the
   title above is Dover White, and a white line beneath a Dover White line
   reads as two whites arguing rather than one voice. One variable, and the
   section chip, the year, the medium, the credit and the whole wall label
   move with it. Stated after DARK_INK because it is overruling it. */
:root { --sub-ink: #F0EADC; }

/* ---------- a project page's title --------------------------
   04's detail pages set a title at clamp(34px, 6.6vw, 88px) lifted by its own
   1.4 — up to 123px on a wide screen. The studio has asked for half of that,
   and it is written as that same clamp times 1.4 over 2 so the two stay
   locked together if 04's measure ever moves.

   Two things follow from the size. The tracking the face is given at caption
   scale (.06em, further down in UC_TYPE_CSS) is far too open at 60px, so the
   title joins the display group on .02em; and the wall label needs room to
   breathe under a title four times the size it was, which is what the margin
   is. Stated after UC_TYPE_CSS for the same reason as above. */
.proj-title {
  font-size: calc(clamp(34px, 6.6vw, 88px) * 1.4 / 2);
  letter-spacing: .02em; line-height: 1;
}
.pg-head { max-width: 1100px; }
.proj-year { margin-top: 24px; }

/* ===================== V1 · what makes it 01 ================
   The master sheet, and then two things the studio has asked for here and
   only here.

   The titles of the works go to the face's own width. UC_TYPE_CSS opens
   them out by .06em — on the home page, in the two indexes and at the head
   of a project — and GALLERY_TAIL pulls the project page's own back to
   .02em; both are overruled below. The tracking stays where it is still
   doing its job: the frame words, which would otherwise arrive as one
   string, and the small capitals. */
.gcell-title, .feed-link, .proj-title { letter-spacing: 0; }

/* And the two marks come off the contact links in the foot of the frame.
   The frame is typographic on all four sides in every variation; on 01 it is
   typographic without exception, so Instagram and Email are words and
   nothing else. The links themselves are untouched — only the drawing in
   front of them goes.

   Not the drawer's: below 900px the frame collapses and the drawer's two
   social links are marks alone, with no word beside them to carry the
   meaning if the mark were taken away. */
.cx-ico { display: none; }

/* the opening plate sits inside the content box, so its caption lines up
   with the captions in the columns underneath rather than with the frame,
   and comes in with them below 860 — 02's rule, for 02's reason */
.ghero-cap { padding: 12px var(--cap-x) 0; }
