/* ============================================================
   Nika Simone Chilewich

   Scale and discipline referenced from Glitch&Grit; measured, not guessed:
     display   158px / 900 / lh .80 / tracking -.05em
     body      15px  / 600 / tracking -.035em
     tags      12px  / 900
     padding   15px at the page edge
   Pared back from the reference: fewer panels per slide, one accent per
   project, no filter bar, and real black only where it earns it.

   Every project sets --accent. On a project page the body copy takes it too,
   so the page is black plus one hue and the photographs do the rest.
   ============================================================ */

:root{
--black:#0B0B0C;   /* not absolute zero. A photograph's darkest pixel is
                        rarely 0 — this film's is 9 — so on a true black
                        page every image reads as a lighter band exactly
                        the width of the column. Meeting the pictures at
                        their own floor is what lets them emerge from the
                        ground instead of sitting on it. */
  --paper:#FFFBF6;          /* the intro ground, and warm white on black */
  --ink-2:rgba(255,251,246,.56);
  --ink-3:rgba(255,251,246,.34);
  --rule:rgba(255,251,246,.16);

  --accent:#E9EDEA;         /* overridden per project */
  --accent-dim:color-mix(in srgb, var(--accent) 62%, #000);
  --accent-line:color-mix(in srgb, var(--accent) 26%, #000);

  --sans:"DM Sans",-apple-system,BlinkMacSystemFont,"Helvetica Neue",Arial,sans-serif;

  --pad:15px;               /* their edge padding, measured */
  --gut:clamp(16px,2vw,28px);

  --ease:cubic-bezier(.22,.61,.36,1);
  --swipe:cubic-bezier(.76,0,.24,1);

  /* measured type ramp */
  --t-display:clamp(46px,10.9vw,158px);
  --t-mid:clamp(26px,4.4vw,64px);
  --t-body:15px;
  --t-tag:12px;
  --t-micro:10px;
}

/* Lenis drives the scroll; these are its required hooks */
html.lenis,html.lenis body{height:auto}
.lenis.lenis-smooth{scroll-behavior:auto!important}
.lenis.lenis-stopped{overflow:hidden}

*,*::before,*::after{box-sizing:border-box}
html{-webkit-text-size-adjust:100%}
body{
  margin:0;background:var(--black);color:var(--paper);
  font-family:var(--sans);font-size:var(--t-body);font-weight:600;
  letter-spacing:-.035em;line-height:1.11;
  -webkit-font-smoothing:antialiased;
  /* clip, not hidden: overflow-x:hidden turns the body into a scroll
     container and silently disables position:sticky for every descendant,
     which is what stopped the credits column holding as you scroll. */
  overflow-x:clip;
}
img,video{display:block;max-width:100%}
a{color:inherit;text-decoration:none}
h1,h2,h3,p,dl,dd,figure,ul{margin:0;padding:0}
ul{list-style:none}
::selection{background:var(--accent);color:var(--black)}
:focus-visible{outline:2px solid var(--accent);outline-offset:3px}

.vh{position:absolute;width:1px;height:1px;margin:-1px;overflow:hidden;
  clip-path:inset(50%);white-space:nowrap}
.skip{position:absolute;left:-9999px;z-index:300;background:var(--paper);
  color:var(--black);padding:10px 16px}
.skip:focus{left:var(--pad);top:10px}

/* ------------------------------------------------- intro & the name bar
   One element does both jobs. On the homepage the name starts spanning the
   screen on paper, then travels down and shrinks into the bar at the foot of
   the site. On every other page it is already settled. Clicking it comes home. */

.introbg{
  position:fixed;inset:0;z-index:190;background:var(--paper);
  transition:opacity .9s var(--ease) .25s;
}
.introbg.is-done{opacity:0;pointer-events:none}

.introsub{
  position:fixed;left:var(--pad);right:var(--pad);z-index:200;
  bottom:calc(var(--pad) + var(--t-mid) + 18px);
  display:flex;flex-wrap:wrap;justify-content:center;gap:4px 26px;
  font-size:var(--t-tag);font-weight:900;text-transform:uppercase;
  color:var(--black);
  opacity:0;animation:introIn .8s var(--ease) .55s forwards;
  transition:opacity .5s var(--ease);
}
.introsub.is-done{opacity:0 !important;animation:none}
@keyframes introIn{from{opacity:0;transform:translateY(10px)}to{opacity:1;transform:none}}

.namebar{
  position:fixed;left:var(--pad);right:var(--pad);bottom:var(--pad);z-index:200;
  display:flex;justify-content:space-between;align-items:baseline;
  font-size:clamp(18px,1.7vw,26px);font-weight:700;letter-spacing:-.03em;
  line-height:1;text-transform:uppercase;pointer-events:none;
  /* The same treatment as the bar at the top, and as the name on the
     homepage: blended by difference, so a picture passing behind inverts
     the letters instead of swallowing them. */
  color:var(--paper);mix-blend-mode:difference;
  transition:font-size 1.2s var(--swipe),font-weight 1.2s var(--swipe),
             letter-spacing 1.2s var(--swipe);
}
/* the name sits at the foot of the screen from the first frame; only its
   scale and its colour change as the page settles */
.namebar a{
  pointer-events:auto;color:var(--paper);
  transition:color 1.2s var(--swipe),opacity .25s var(--ease);
}
.namebar a:hover{color:var(--hov,var(--paper))}
/* "Simone" sits right of centre while "About" sits left of it, so the two
   middle words lean opposite ways. The offset here is half the nav's, which
   keeps the tilt without the name bar drifting as far as the nav does. */
.namebar__mid{position:absolute;left:61%;transform:translateX(-50%)}

/* The dark wash that used to sit under the name is gone. It was there to
   hold an unblended name over a photograph; the blend does that job now, and
   leaving the wash in would darken the very ground the blend reads against. */

/* The opening. Each word is carried from the middle of the screen down to
   the place it keeps, so the name arrives rather than appears. The journey is
   measured in the browser — the words end where the bar already puts them. */
.namebar.is-intro a{
  color:var(--lit);
  /* Held back until the journey has been measured, so the small name at the
     foot is never seen before it is placed in the middle. */
  opacity:0;
  transform:translate3d(var(--ix,0px),var(--iy,0px),0) scale(var(--is,1));
  /* Only the fading in is timed here. The transform must land without a
     transition or the name is seen flying up from the foot to reach the
     centre — it is meant to be there from the first moment, and to make the
     journey once, downwards. */
  transition:opacity .55s var(--ease);
}
.namebar.is-intro.is-cast a{opacity:1}
.namebar.is-intro.is-settling a{
  color:var(--paper);transform:none;
  transition:transform 1.25s var(--swipe),color 1.25s var(--swipe);
}

/* ------------------------------------------------------ the home mark

   The name is not a caption on the work and it does not travel anywhere. It
   is held in the middle of the screen and the reel runs underneath it, and
   because it is blended by difference rather than drawn on top, the letters
   take their colour from whatever is passing behind — white against the
   black, inverted against a picture. The same treatment as the nav above it,
   at the scale of a title. */
.mark{
  position:fixed;inset:0;z-index:110;
  display:grid;place-items:center;
  pointer-events:none;
  mix-blend-mode:difference;
  color:var(--paper);
}
.mark a{
  pointer-events:auto;color:inherit;text-decoration:none;
  display:block;text-align:center;
  font-weight:1000;text-transform:uppercase;
  letter-spacing:-.045em;line-height:.86;
  /* Sized off the longest word, so the name fills the measure at any width.
     Deliberately wider than the column of pictures: at 77% it landed within a
     few pixels of the image edges and the two read as one block with a shared
     margin. The name should overhang the work, not line up with it.

     Three limits: the width of the window, a ceiling so it does not become
     absurd on a very large monitor, and the height of the window, since three
     lines at this weight will otherwise run off a short screen. */
  font-size:min(13.4vw,268px,27svh);
}
.mark span{display:block}
@media (max-width:860px){
  .mark a{font-size:min(13.4vw,107px,27svh);letter-spacing:-.04em}
}

/* ---------------------------------------------------------- nav */

.nav{
  position:fixed;top:0;left:0;right:0;z-index:120;
  display:flex;justify-content:space-between;align-items:center;
  padding:var(--pad);
  font-size:clamp(18px,1.7vw,26px);font-weight:700;letter-spacing:-.03em;
  text-transform:uppercase;color:var(--paper);
  mix-blend-mode:difference;pointer-events:none;
}
.nav a{pointer-events:auto;
  transition:opacity .25s var(--ease),color .28s var(--ease)}
.nav a:hover{color:var(--hov,var(--paper))}
/* No marking of the page you are on, for now. The attribute stays — a screen
   reader still announces which link is the current page — but nothing is
   dimmed, so all six words in the two bars read at one weight. */
/* "About" leans left of centre and "Simone" leans right by the same amount,
   so the top and bottom bars tilt in opposite directions — off-axis, but by
   a matched distance rather than a large one. */
.nav__mid{position:absolute;left:39%;transform:translateX(-50%)}

/* ------------------------------------------------- the nav, at the sides

   On the homepage the three words leave the top edge and stand in two
   columns at the left and right margins, level with the middle of the page.
   They keep the difference blend, so a picture passing behind them inverts
   them exactly as it does the name.

   They do not move. Tried against the reel's speed, the lean read as a
   wobble rather than as weight — the words are small and at the margin, and
   motion there competes with the one thing on the page that should be
   moving. They are set smaller than the bar they replaced, and a little
   open, which is what carries at this size. */
.nav--side{
  top:0;bottom:0;right:0;
  align-items:center;
  font-size:clamp(12px,1vw,15px);font-weight:600;letter-spacing:.055em;
}
.nav--side .nav__col{
  display:flex;flex-direction:column;gap:.85em;
  pointer-events:none;
}
.nav--side .nav__col--r{text-align:right}
.nav--side a{pointer-events:auto;display:block}
@media (max-width:620px){
  /* too narrow to keep the words out of the pictures' way */
  .nav--side{top:0;bottom:auto;align-items:flex-start}
  .nav--side .nav__col{flex-direction:row;gap:1.1em}
}

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

.slide{
  position:relative;min-height:100svh;
  display:grid;place-items:center;
  padding:calc(var(--pad) + 42px) var(--pad);
  overflow:hidden;isolation:isolate;
}
.slide__media{position:absolute;inset:0;z-index:0;pointer-events:none}
.slide__panel{
  position:absolute;overflow:hidden;background:#0A0A0A;
  opacity:0;
  /* --drift is set on scroll; composing it here keeps the entry
     transition and the parallax from overwriting each other */
  transform:translate3d(0,calc(var(--from,40px) + var(--drift,0px)),0) scale(.985);
  transition:opacity .9s var(--ease) var(--d,0ms),
             transform 1.25s var(--ease) var(--d,0ms);
  will-change:transform,opacity;
}
.slide.is-in .slide__panel{opacity:1;
  transform:translate3d(0,var(--drift,0px),0) scale(1)}
.slide__panel img,.slide__panel video,
.slide__panel iframe,.slide__panel .yt{
  pointer-events:none;
  width:100%;height:100%;object-fit:cover;border:0;display:block;
}
.slide__panel--film{background:#000}

/* A film is layered over its own poster frame and revealed only while it is
   actually playing, so YouTube's play button never shows through. */
.yt-film{
  position:absolute;inset:0;display:block;overflow:hidden;
  opacity:0;transition:opacity .55s var(--ease);pointer-events:none;
}
.yt-film.is-playing{opacity:1}
/* The player is sized well beyond its frame and centred, so YouTube's own
   title bar and end-card chrome — which live at the top and bottom edges of
   the player — are cropped away entirely. Nothing of theirs is ever visible. */
.yt-film iframe{
  position:absolute;top:50%;left:50%;
  width:142%;height:142%;
  transform:translate(-50%,-50%);
  border:0;display:block;
}

/* a scrim only under the title, so panels stay bright at the edges */
.slide::after{
  content:"";position:absolute;inset:0;z-index:1;pointer-events:none;
  background:radial-gradient(52% 40% at 50% 50%,
    rgba(0,0,0,.86) 0%,rgba(0,0,0,.62) 48%,rgba(0,0,0,0) 100%);
}
.slide--full::after{background:rgba(0,0,0,.52)}

.slide__inner{
  position:relative;z-index:2;text-align:center;
  display:flex;flex-direction:column;align-items:center;gap:0;
}
.slide__tags{
  font-size:var(--t-tag);font-weight:900;text-transform:uppercase;
  color:var(--accent);line-height:1.18;
  opacity:0;transform:translateY(8px);
  transition:opacity .7s var(--ease) .1s,transform .7s var(--ease) .1s;
}
.slide__tags span{display:block}
.slide__title{
  font-size:var(--t-display);font-weight:900;line-height:.80;
  letter-spacing:-.05em;text-transform:uppercase;color:var(--accent);
  max-width:14ch;text-wrap:balance;
  opacity:0;transform:translateY(16px);
  transition:opacity .8s var(--ease) .16s,transform .9s var(--ease) .16s;
}
.slide__cta{
  /* sits close under the title — the pairing reads as one block */
  margin-top:9px;font-size:var(--t-micro);font-weight:900;
  letter-spacing:.06em;text-transform:uppercase;
  color:var(--accent);
  opacity:0;transform:translateY(8px);
  transition:opacity .7s var(--ease) .28s,transform .7s var(--ease) .28s;
}
.slide__cta::after{content:" ↗"}
.slide.is-in .slide__tags,
.slide.is-in .slide__title,
.slide.is-in .slide__cta{opacity:1;transform:none}
.slide:hover .slide__title{opacity:.86}

/* compositions ------------------------------------------------ */

/* split — media one side, stills the other */
.slide--split .p1{left:0;top:12%;width:38%;height:62%}
.slide--split .p2{right:0;top:8%;width:26%;height:38%}
.slide--split .p3{right:6%;bottom:9%;width:30%;height:36%}
.slide--split .p4{left:14%;bottom:6%;width:19%;height:26%}

/* panels — scattered stills, no dominant element */
.slide--panels .p1{left:2%;top:14%;width:20%;height:34%}
.slide--panels .p2{left:9%;bottom:11%;width:17%;height:30%}
.slide--panels .p3{right:3%;top:10%;width:22%;height:32%}
.slide--panels .p4{right:9%;bottom:13%;width:19%;height:29%}
.slide--panels .p5{left:27%;top:4%;width:15%;height:22%}
.slide--panels .p6{right:26%;bottom:4%;width:15%;height:22%}

/* solo — one large still, offset */
.slide--solo .p1{right:0;top:0;width:46%;height:100%}
.slide--solo .p2{left:3%;bottom:12%;width:20%;height:30%}

/* duo — two films side by side, title across them */
.slide--duo .p1{left:0;top:14%;width:47%;height:58%}
.slide--duo .p2{right:0;top:26%;width:47%;height:58%}

/* pair — the screen split evenly: one still, one looping clip, each taking
   exactly half. An even split reads as a decision; the earlier narrow column
   over a full-bleed photograph read as clutter. The scrim is flat rather than
   radial so the halves stay legible and the title has one calm field to sit on. */

.slide--pair .slide__panel{
  top:0;height:100%;width:50%;opacity:1;transform:none;
}
.slide--pair .slide__panel--still{left:0;right:auto}
.slide--pair .slide__panel--clip{left:50%;right:auto}
.slide--pair .slide__panel--still img{width:100%;height:100%;object-fit:cover}

/* an iframe cannot object-fit, so the film is sized to cover the half and
   centred on it — 177.78vh is 16:9 against the full height */
.slide--pair .slide__panel--clip .yt,
.slide--pair .slide__panel--clip iframe,
.slide--pair .slide__panel--clip img{
  position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);
  width:100%;height:100%;min-width:177.78vh;min-height:56.25vw;
  object-fit:cover;border:0;
}
.slide--pair::after{
  background:linear-gradient(0deg,rgba(0,0,0,.62),rgba(0,0,0,.42));
}
/* a hairline where the two halves meet */
.slide--pair .slide__panel--clip{box-shadow:-1px 0 0 rgba(0,0,0,.9)}

@media (max-width:860px){
  .slide--pair .slide__panel{width:100%;height:50%}
  .slide--pair .slide__panel--still{top:0}
  .slide--pair .slide__panel--clip{top:50%;left:0;box-shadow:0 -1px 0 rgba(0,0,0,.9)}
}

/* full — one film or one still filling the frame */
.slide--full .slide__panel{inset:0;width:100%;height:100%;opacity:1;transform:none}
.slide--full .slide__panel--still img{
  width:100%;height:100%;object-fit:cover;   /* object-position set per project */
}

@media (max-width:860px){
  .slide--split .p1{width:56%;height:40%;top:8%}
  .slide--split .p2,.slide--split .p3{width:40%;height:26%}
  .slide--split .p4,.slide--panels .p5,.slide--panels .p6{display:none}
  .slide--panels .p1,.slide--panels .p2,
  .slide--panels .p3,.slide--panels .p4{width:34%;height:24%}
  .slide--solo .p1{width:70%;height:46%;top:6%}
  .slide--duo .p1{width:82%;height:30%;top:8%;left:9%}
  .slide--duo .p2{width:82%;height:30%;bottom:8%;top:auto;right:9%}
}

/* ---------------------------------------------------------- projects index */

.page{padding:calc(var(--pad) + 52px) 0 96px}
.page__head{
  display:flex;justify-content:space-between;align-items:baseline;
  gap:var(--gut);padding:0 var(--pad) 26px;
  font-size:var(--t-tag);font-weight:900;text-transform:uppercase;
}
.page__title{
  font-size:var(--t-mid);font-weight:900;letter-spacing:-.05em;
  text-transform:uppercase;line-height:.9;
}

.tiles{display:grid;grid-template-columns:repeat(3,1fr);gap:0}
.tile{display:block;position:relative;background:#0A0A0A}
.tile__frame{position:relative;aspect-ratio:16/10;overflow:hidden;display:block}
.tile__frame img{width:100%;height:100%;object-fit:cover;
  transition:transform 1.1s var(--ease),opacity .6s var(--ease)}
.tile:hover .tile__frame img{transform:scale(1.04)}
.tile__bar{
  display:grid;grid-template-columns:auto 1fr auto;align-items:baseline;
  gap:14px;padding:12px var(--pad) 20px;
  font-size:var(--t-body);font-weight:600;
}
.tile__n{color:var(--ink-3);font-variant-numeric:tabular-nums}
.tile__go{color:var(--ink-3);text-transform:uppercase;font-size:var(--t-tag);
  font-weight:900;opacity:0;transition:opacity .3s var(--ease)}
.tile__go::after{content:" ↗"}
.tile:hover .tile__go{opacity:1}
.tile:hover .tile__name{color:var(--accent)}
.tile__name{transition:color .3s var(--ease)}

@media (max-width:1000px){.tiles{grid-template-columns:repeat(2,1fr)}}
@media (max-width:640px){.tiles{grid-template-columns:1fr}}

/* ---------------------------------------------------------- project page */

.work{padding:calc(var(--pad) + 52px) var(--pad) 0;overflow-x:clip}
.work__title{
  font-size:var(--t-display);font-weight:900;line-height:.80;
  letter-spacing:-.05em;text-transform:uppercase;color:var(--accent);
  text-wrap:balance;margin-bottom:38px;
  /* the title lags behind the scroll and fades, so the opening image rises
     over it and takes its place */
  position:relative;z-index:0;
  will-change:transform,opacity;
  transform:translate3d(0,var(--drift,0px),0);
  opacity:var(--fade,1);
}
/* the media sits above the title and carries its own ground, so the title
   passes behind it rather than through it */
.work__media{position:relative;z-index:1;background:var(--black)}
.work__tags{
  font-size:var(--t-tag);font-weight:900;text-transform:uppercase;
  color:var(--accent);line-height:1.2;margin-bottom:14px;
  /* the tags lag the scroll a little less than the title, so the gap between
     them opens as the pair travels and the image climbs over both */
  position:relative;z-index:0;
  will-change:transform,opacity;
  transform:translate3d(0,var(--drift,0px),0);
  opacity:var(--fade,1);
}
.work__tags span{display:block}

/* Images on the left, credits held beside them on the right. Contained rather
   than full-bleed: at full width a gallery of installation shots is hard to
   read as individual works. The credits stay put for the length of the scroll. */
/* The credits float beneath the opening image rather than sitting in a fixed
   table beside it. Three groups, each ruled off, with its heading set larger
   and drifting on its own plane — so the words Credits, Date and Location sit
   slightly apart from the rows they belong to. The colour stays the project's
   accent; the rows stay small. */

.work__media--lead{margin-bottom:0}

.float{
  position:relative;
  display:grid;grid-template-columns:auto minmax(0,1fr) auto;
  align-items:start;gap:clamp(18px,3.5vw,60px);
  padding:clamp(150px,26vh,330px) var(--pad);
  color:var(--accent);
}
.float__edge{
  /* smaller than the rows they sit beside — a shade above the 10px Cipher
     sets its margin labels at. The left one carries the whole project title,
     held to two lines. */
  font-size:11px;font-weight:600;letter-spacing:.06em;
  text-transform:uppercase;color:var(--accent-dim);
  line-height:1.35;max-width:15ch;
  will-change:transform;transform:translate3d(0,var(--drift,0px),0);
}
.float__r{max-width:none;white-space:nowrap}
.float__r{text-align:right}

.float__mid{justify-self:center;width:100%;max-width:660px}
/* the closing rule hangs off the last group, not the container, so it drifts
   with the line above it instead of sitting still under moving text */
.float__mid .grp:last-child{border-bottom:1px solid var(--accent-line)}

.grp{
  position:relative;
  display:grid;grid-template-columns:minmax(96px,34%) 1fr;
  gap:clamp(14px,2vw,28px);
  /* first baselines align, so the heading sits on the same line as the first
     row rather than floating above it */
  align-items:baseline;
  border-top:1px solid var(--accent-line);
  /* the space below a block is the room its neighbour's rule travels through
     on the way past; at 20px the rule reached the text above it */
  padding:18px 0 40px;
  will-change:transform;transform:translate3d(0,var(--drift,0px),0);
}
/* the heading rides its own plane — larger, quieter, and drifting at a rate
   of its own, so it floats free of the rows beneath it */
.grp__head{
  font-size:clamp(15px,1.2vw,18px);font-weight:600;letter-spacing:-.02em;
  line-height:1.125;color:var(--accent-dim);
}
.grp__rows p{
  /* measured on glitchandgrit.com/work/flowers-full-service:
     12.5px / 600 / 14.06px leading / -.035em */
  font-size:12.5px;font-weight:600;letter-spacing:-.035em;
  /* Opened from the 1.125 measured on glitchandgrit to 2.4. A line can only
     drift as far as the space beneath it, and the stagger has to beat the
     line spacing to read as separate lines rather than a sliding block: at
     1.125 the lines were flush and could not move at all, and at 1.7 they
     sheared 9px against 21px of spacing, which still read as a slab. At 2.4
     there are 18px of clear space between one line's letters and the next,
     and the drift spends 14px of it. */
  line-height:2.4;
  color:var(--accent);
  /* Custom properties inherit, and this sits inside .grp, which is itself
     translated by --drift. Without a local value a row would inherit its
     block's drift and apply it a second time, travelling twice as far as the
     heading it belongs to — which is exactly what tore the date and location
     away from their labels. A row that should move gets its own value set
     inline by the script, and inline wins over this. */
  --drift:0px;
  will-change:transform;transform:translate3d(0,var(--drift,0px),0);
}
.grp__rows .role{color:var(--accent-dim);font-weight:500}
.grp__rows b{font-weight:700}

@media (max-width:720px){
  .float{grid-template-columns:1fr;gap:20px;padding:70px var(--pad)}
  .float__r{text-align:left}
  .float__mid{max-width:none}
  .grp{grid-template-columns:1fr;gap:8px}
}

.more{
  display:flex;justify-content:space-between;align-items:baseline;gap:14px;
  padding:5px 0;color:var(--accent);font-weight:400;
  transition:padding-left .35s var(--ease);
}
.more:hover{padding-left:9px;font-weight:700}
.more em{font-style:normal;font-size:var(--t-tag);font-weight:700;opacity:.55}

.work__media{
  /* 947 wide and centred — the column sits on the page rather than bleeding
     off it, with the black margins doing the framing */
  display:flex;flex-direction:column;gap:var(--gut);
  max-width:947px;margin-inline:auto;
}
.work__media figure{margin:0;background:#0A0A0A}
/* Two abreast at half the column, the second width this page uses. A square
   clip is 1080 wide at source, which is short of the column on a fine screen
   and comfortably past it at half. */
/* A rendering you can take hold of. The perspective sits on the frame and the
   turn on the art inside it, so the drag reads as pulling an edge toward you
   rather than sliding a flat picture about. */
.work__media figure.live.tilt{aspect-ratio:var(--ratio, 2639 / 1159);
  background:transparent;position:relative;perspective:1400px;
  cursor:grab;touch-action:pan-y}
.work__media figure.live.tilt:active{cursor:grabbing}
.tilt__stage{position:absolute;inset:0;transform-style:preserve-3d}
.tilt__art{width:100%;height:100%;display:block;font-family:var(--sans);
  letter-spacing:.01em;
  /* a pool of shadow under it so it sits above the page rather than on it —
     the ground is near-black rather than black, so a shadow still reads */
  filter:drop-shadow(0 26px 34px rgba(0,0,0,.72))
         drop-shadow(0 4px 8px rgba(0,0,0,.45));
  transform-style:preserve-3d;will-change:transform;
  transform:perspective(1400px)
            rotateX(var(--rx,0deg)) rotateY(var(--ry,0deg))
            scale(var(--sc,1));
  -webkit-user-drag:none;user-select:none}

/* Six plates and a map. The plates and the map lag the scroll together; the
   title runs against them and is set to the right, over the map. */
/* height comes from its contents, not from the generic live ratio */
/* the grid of plates is centred against the circle, so the two read at the
   same height rather than both hanging from the top */
.work__media figure.live.cs{aspect-ratio:auto;background:transparent;position:relative;
  display:grid;grid-template-columns:minmax(0,30%) minmax(0,70%);
  gap:clamp(12px,2.4%,34px);align-items:center}
.cs__plates{display:grid;grid-template-columns:1fr 1fr;
  gap:clamp(6px,1.4vw,16px);align-content:center}
.cs__plate{margin:0;will-change:transform;
  transform:translate3d(0,var(--drift,0px),0)}
/* all six the same square, cropped rather than letterboxed, so the grid
   is even and no plate carries a border of its own */
.cs__plate img{width:100%;aspect-ratio:1;object-fit:cover;display:block;
  background:#0A0A0A}
/* set above the black labels printed on the map, which land around 6px on
   screen — these need to read as the louder of the two */
.cs__plate figcaption{margin-top:8px;font-size:clamp(10px,1.05vw,13px);font-weight:700;
  letter-spacing:.05em;line-height:1.25;color:var(--accent);text-transform:uppercase}
/* the column is the yardstick for the title, so its size is a share of the
   map's own width rather than of the window */
.cs__right{position:relative;container-type:inline-size}
.cs__map{width:100%;height:auto;display:block;will-change:transform;
  transform:translate3d(0,var(--drift,0px),0)}
/* Set across the circle: it starts at the circle's left edge and carries on
   past the right, held on one line so the run is unbroken. It is laid over the
   map and moves with it, so the two read as one object rather than as a
   caption sliding over a picture. */
.cs__title{position:absolute;left:var(--left,34%);top:var(--top,5%);z-index:2;margin:0;
  text-align:left;white-space:nowrap;
  font-size:var(--size,10.2cqw);font-weight:900;line-height:var(--lead,1);
  letter-spacing:-.035em;text-transform:uppercase;color:var(--accent);
  will-change:transform;transform:translate3d(0,var(--drift,0px),0);
  pointer-events:none}
/* hugs its own text, so the line's true width is what gets measured and
   positioned rather than the width of the block it sits in */
.cs__title span{display:block;width:max-content}
@media (max-width:720px){
  .work__media figure.live.cs{grid-template-columns:1fr}
  .cs__title{position:static;text-align:right;margin-bottom:10px}
}

/* A line of shade structures, each a stencil so the colour is set here. The
   drift lives on .stx__item and the pop-in on .stx__pop inside it: both move
   the thing, and a single element cannot carry two transforms. */
/* both classes, so this wins over the generic .live ratio below it */
/* The line runs the width of the page, not the width of the text column.
   Ten equal columns cap how wide the widest structure may be, which caps the
   height they all share — so inside the 947 column they came out at 48px,
   small enough to be illegible. Out here they are half again as big.
   The depth is whatever the row needs: the height comes from the column
   width, so any fixed band would only add black above the row. */
.work__media figure.live.stx{
  width:calc(100vw - 2 * var(--pad));
  margin-inline:calc(50% - 50vw + var(--pad));
  aspect-ratio:auto;background:transparent;position:relative}
/* The same air above the line as below it. The column it sits in already
   puts a gutter between its children, and the credits below are outside
   that column and get none — so the gap above was one gutter and the gap
   below was nothing. The gutter is subtracted from the top margin so the
   two measure the same from the edge of the picture to the edge of the
   credits. */
.work__media--lead figure.live.stx{
  --stxair:clamp(44px,4.4vw,88px);
  margin-block:calc(var(--stxair) - var(--gut)) var(--stxair)}
/* Equal columns rather than equal gaps. Sized to their own art, a billboard
   took twice the width of a bench and the centres fell where they fell — the
   row read as clumped even though the gap between every pair was identical.
   One tenth of the row each, art centred in it, so the spacing between
   structures is the same the whole way across and the row fills the page. */
.stx__row{display:flex;flex-wrap:nowrap;align-items:flex-end;gap:0}
.stx__item{flex:1 1 0;min-width:0;
  will-change:transform;transform:translate3d(0,var(--drift,0px),0)}
/* Two fixed bands: the structures stand on the line between them, their names
   begin on it. Stacking them instead let a name that wraps to two lines shove
   its structure up a line, which is what made the row look uneven — the drift
   was identical across all ten the whole time. */
/* The art sets the height and the caption follows it. Every structure is
   the same height now, so they begin and end on the same two lines and the
   captions start together; the minimum holds a two-line name without
   pushing its neighbours' first line down. */
.stx__pop{display:flex;flex-direction:column;align-items:center;width:100%}
.stx__art{position:relative;display:block;width:100%;max-width:100%}
.stx__lyr{position:absolute;inset:0;background:var(--ink,#3DFF9B);
  -webkit-mask-image:var(--src);mask-image:var(--src);
  -webkit-mask-size:contain;mask-size:contain;
  -webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;
  -webkit-mask-position:bottom center;mask-position:bottom center;
  opacity:0;transform:translateY(12%) scale(.96);transform-origin:bottom center}
/* The caption sets the narrowest a column may be — several structures are
   slimmer than their own name — so it is held tight enough that ten of them
   still stand in one line across the column. */
.stx__cap{align-self:stretch;margin-top:10px;min-height:var(--capH,2.6em);
  font-size:clamp(8px,0.72vw,11px);font-weight:800;
  letter-spacing:.05em;text-align:center;line-height:1.25;color:var(--ink,#3DFF9B);
  overflow-wrap:break-word;
  opacity:0;transform:translateY(5px);text-transform:uppercase;
  width:100%;padding-inline:4px;transition:opacity .3s ease,transform .3s ease}
/* Ten across stops working long before a phone. At 375px each structure
   gets 34px of width, which puts the art at 17px and clips eight of the ten
   names. Five and five keeps them readable; the single line is the right
   shape for the screens that can hold it, not for every screen. */
@media (max-width:720px){
  .stx__row{flex-wrap:wrap;row-gap:18px}
  .stx__item{flex:0 0 20%}
}

.stx__item.is-in .stx__st{opacity:1;transform:none;
  transition:opacity .34s ease,transform .52s cubic-bezier(.2,1.5,.35,1)}
.stx__item.is-in .stx__cap{opacity:1;transform:none}
.stx__item.is-crowd .stx__pp{opacity:1;transform:none;
  transition:opacity .28s ease,transform .46s cubic-bezier(.2,1.7,.35,1)}
@media (prefers-reduced-motion: reduce){
  .stx__lyr,.stx__cap{opacity:1;transform:none}
}

/* A diagram that is drawn rather than photographed. The backdrop carries the
   district marks, which stay put; the network on top is live. */
.work__media figure.live{position:relative;aspect-ratio:var(--ratio, 2000 / 1224);
  background:transparent}
/* Scoped to the diagram. Left open to every live figure it also caught the
   case study's map and plates and pinned them to a box with no height. */
/* it drifts with the page like any other picture, rather than animating */
/* ------------------------------------------------------------ the reel
   One column of work up the middle, turned by the mouse. No perspective and
   no dimming: measured on the reference, every frame there sits at full
   colour with no transform at all. What reads as depth is pictures of
   different sizes passing on one axis under a slow, weighted scroll — so that
   is what this is. Pushing frames toward the reader instead made them behave
   like cut-outs. */
/* Black first, then the work. The reel is held back while the name stands in
   the middle of the screen, and comes up as the name travels down to the foot,
   so the picture arrives behind a name that has already been read. */
.is-opening .reel__track{opacity:0}
.reel__track{transition:opacity 1.5s var(--ease)}
@media (prefers-reduced-motion:reduce){
  .is-opening .reel__track{opacity:1}
}
/* No background of its own. The page is already black, and this sits on a
   composited 3-D layer — two surfaces both painting #000, one of them through
   the GPU, is how you end up with a black that does not quite match the black
   around it. One surface, one black. */
.reel{position:fixed;inset:0;overflow:hidden;z-index:0}
/* Air between every frame, as the reference has — about a fifth of the
   screen's height, so one picture has cleared before the next arrives. The
   gap sits between items, so the doubled list still closes on itself. */
.reel__track{position:absolute;left:50%;top:0;width:100vw;
  display:flex;flex-direction:column;align-items:center;
  /* Nothing between the tiles. The column runs continuously, as the
     reference does — each picture meets the next. */
  gap:0;
  transform:translate3d(-50%,var(--run,0px),0)}
.reel__f{display:flex;justify-content:center;align-items:center;
  /* A little taller than the screen, so a lying picture does not end the
     instant it has been seen — it holds for a moment longer as the reel
     carries on, and the next one arrives a beat after rather than on cue. */
  width:100%;height:116svh;margin:0;line-height:0;border:0;outline:0;
  flex:0 0 auto;overflow:hidden;
  /* No mute. The reference lights every tile the same, and the continuity
     comes from the tiles themselves rather than from one being picked out. */
  opacity:1}
/* Held to the screen's height as well as the column's width, so a standing
   picture is taken in whole and a lying one does not dwarf it.

   Sized from the proportion the frame declares rather than from the bitmap,
   because the bitmap is not there yet: these load lazily and the films do not
   preload at all. Asked for its natural size, an unloaded picture stands at
   nothing, and the column re-lays itself out every time one arrives. Written
   this way the room is correct from the first layout and nothing moves when
   the file lands. */
.reel__f img,.reel__f video{display:block;
  /* Filling a cell of fixed height, so every tile is the same size and the
     column runs without a seam. Cropped to fit, as the reference crops. */
  height:100%;object-fit:cover;max-width:none;flex:0 0 auto;
}
/* Two kinds of picture, two sizes. A lying picture takes the whole page, as
   the film does; a standing one takes half of it. Each still is still held to
   its own pixel width, so nothing is blown up past what it actually has. */
.reel__f--wide img,.reel__f--wide video{width:100vw}
/* A standing picture is not cut to the screen's height. It keeps its own
   length — one width for all of them, so the column has an edge — and the
   next picture follows the moment it ends. Only the lying ones are cropped,
   because only they get the full-bleed moment that depends on filling the
   screen exactly. */
.reel__f--tall{height:auto}
.reel__f--tall img,.reel__f--tall video{
  width:56vw;height:auto;aspect-ratio:var(--ar,1);object-fit:fill;
}
@media (max-width:860px){
  .reel__track{width:74vw}
}
/* The film is given more of the screen than the stills around it — it is the
   one moving thing in the reel and it carries the opening. It is allowed past
   the column's own width, and its natural width is not the limit here, so
   what it loses in sharpness it gains in presence. */
.reel__f--film video{width:100vw;flex:0 0 auto}

.work__media figure.live.eco{will-change:transform;
  transform:translate3d(0,var(--drift,0px),0)}
.work__media figure.live.eco img{position:absolute;inset:0;width:100%;height:100%;
  object-fit:contain}
.work__media figure.live.eco svg{position:absolute;inset:0;width:100%;height:100%;
  font-family:var(--sans);letter-spacing:.01em}
.work__pair{display:grid;grid-template-columns:1fr 1fr;gap:var(--gut);align-items:start}
.work__media video{width:100%;height:auto;display:block}
.mv{position:relative}
@media (max-width:720px){.work__pair{grid-template-columns:1fr}}
.work__media img{width:100%;height:auto}
.frame16{position:relative;aspect-ratio:16/9;background:#000;overflow:hidden}
.frame16 iframe,.frame16 img,.frame16 .film{position:absolute;inset:0;
  width:100%;height:100%;border:0;object-fit:cover}

/* the film rests as its own still — no YouTube title bar, logo or branding
   until it is played */
.film{position:relative;display:block;background:#000}
.film img{width:100%;height:100%;object-fit:cover}
.film iframe{position:absolute;inset:0;width:100%;height:100%;border:0}
.film__play{
  position:absolute;inset:0;width:100%;height:100%;
  display:grid;place-items:center;
  background:rgba(0,0,0,.16);border:0;cursor:pointer;
  transition:background .35s var(--ease);
}
.film__play:hover{background:rgba(0,0,0,.04)}
.film__play span{
  width:72px;height:72px;border-radius:50%;
  border:1px solid var(--accent);
  background:rgba(0,0,0,.28);
  display:grid;place-items:center;
  transition:transform .4s var(--ease),background .35s var(--ease);
}
.film__play:hover span{transform:scale(1.06);background:rgba(0,0,0,.5)}
.film__play span::after{
  content:"";width:0;height:0;margin-left:4px;
  border-left:15px solid var(--accent);
  border-top:9px solid transparent;border-bottom:9px solid transparent;
}
.film.is-live .film__play{display:none}
.filmlink{
  display:flex;justify-content:space-between;align-items:baseline;gap:14px;
  padding:11px 0;border-bottom:1px solid var(--rule);color:var(--accent);
  transition:padding-left .35s var(--ease);
}
.filmlink:hover{padding-left:10px}
.filmlink em{font-style:normal;font-size:var(--t-tag);font-weight:900;
  text-transform:uppercase;opacity:.6}
/* a caption sits directly under its own image, inside the page margin */
.work__media figcaption.cap{
  padding:10px 0 0;max-width:70ch;
  font-size:var(--t-tag);font-weight:500;line-height:1.5;
  color:var(--accent-dim);white-space:normal;
}
.cap{font-size:var(--t-tag);font-weight:600;line-height:1.42;color:var(--ink-3);
  white-space:pre-line}

.work__next{
  margin-top:96px;padding:26px var(--pad) 78px;border-top:1px solid var(--rule);
}
.work__next a{display:block;font-size:var(--t-mid);font-weight:900;
  letter-spacing:-.05em;text-transform:uppercase;line-height:.9;
  transition:color .3s var(--ease)}
.work__next a:hover{color:var(--accent)}
.work__next em{display:block;font-style:normal;font-size:var(--t-tag);
  color:var(--ink-3);margin-bottom:8px}

/* ---------------------------------------------------------- text pages */

.prose{max-width:62ch;display:flex;flex-direction:column;gap:12px;
  padding:0 var(--pad)}
.prose p{font-size:var(--t-body);line-height:1.5;font-weight:600}
.cites{padding:0 var(--pad)}
.cites li{border-bottom:1px solid var(--rule)}
.cites a,.cites>li>span{display:flex;justify-content:space-between;
  align-items:baseline;gap:20px;padding:15px 0;
  transition:padding-left .35s var(--ease)}
.cites a:hover{padding-left:11px;color:var(--accent)}
.cites em{font-style:normal;font-size:var(--t-tag);font-weight:900;
  text-transform:uppercase;color:var(--ink-3);flex:none}
.lists{display:grid;grid-template-columns:repeat(auto-fit,minmax(300px,1fr));
  gap:44px var(--gut);padding:0 var(--pad)}
.lists h2{font-size:var(--t-tag);font-weight:900;text-transform:uppercase;
  color:var(--ink-3);padding-bottom:10px;border-bottom:1px solid var(--rule);
  margin-bottom:6px}
.lists .cites{padding:0}

/* The press list keeps to the left half of the page — one column of
   citations read straight down, with the right half left as air. It drifts
   against the scroll the way a project's text does, so the page moves with
   the rest of the site rather than sitting still. */
.lists--left > *[data-drift]{
  will-change:transform;transform:translate3d(0,var(--drift,0px),0);
}
.lists--left{grid-template-columns:1fr 1fr}
.lists--left > *{grid-column:1}
@media (max-width:860px){
  .lists--left{grid-template-columns:1fr}
}
/* The list stops clear of the name at the foot, by the same distance it
   starts below the bar at the head, so the column sits evenly between the
   two. The name's own line is part of that distance, which is why it is
   written out rather than guessed at. */
/* The press page does not scroll — the list inside it does. Padding alone
   could never fix the collision: the bars are fixed, so page-scrolled text
   passes behind them whatever the padding is. Held in its own column between
   the two bars, the citations begin below the nav and end above the name and
   never meet either. */
.page--press{
  --barline:clamp(18px,1.7vw,26px);
  --gap:60px;
  --top:calc(var(--pad) * 2 + var(--barline) + var(--gap));
  --bottom:calc(var(--pad) + var(--barline) + var(--gap));
  position:fixed;inset:0;padding:0;
  display:block;overflow:hidden;
}
.press__scroll{
  position:absolute;left:0;right:0;
  top:var(--top);bottom:var(--bottom);
  overflow-y:auto;overscroll-behavior:contain;
  scrollbar-width:none;
}
.press__scroll::-webkit-scrollbar{display:none}
/* Out to the right edge of SIMONE in the bar below, which the name bar puts
   at 61% of the measure. */
.press__col{
  width:calc(61% + 3.2em);
  padding:0 var(--pad);
}
@media (max-width:860px){
  .press__col{width:100%}
}
/* Both edges flush, so the column reads as a block of text rather than a
   ragged list; a citation too long for one line simply takes two. The last
   line of each is left alone — forcing it to the margin too pulls the word
   spaces of a short citation into gaps. */
.page--press .cites--bare a,
.page--press .cites--bare > li > span{
  text-align:justify;text-justify:inter-word;
  font-size:clamp(15px,1.12vw,19px);line-height:1.45;
}
/* Nothing stands to the right of a citation: the line is the link, so the
   whole of it is the target and there is no word to read instead of it. */
.cites--bare a,.cites--bare > li > span{display:block}
.cites--bare a{color:var(--paper);transition:padding-left .35s var(--ease),
  color .3s var(--ease)}
.cites--bare a:hover{color:var(--hov,var(--accent))}

/* ------------------------------------------------------- saved article */

/* The one citation whose article exists only as a capture. It opens over the
   list, on the same near-black ground as everything else, with the sheet
   itself the only white on screen — so the page it came from is still there
   at the edges and closing it costs nothing. */
html.is-held,html.is-held body{overflow:hidden}
.cutting{position:fixed;inset:0;z-index:210;display:none;
  background:var(--black);opacity:0;
  transition:opacity .34s var(--ease)}
.cutting.is-open{display:block}
.cutting.is-lit{opacity:1}
/* An iframe is a replaced element: given both `top` and `bottom` it keeps its
   own 150px and ignores the second. The sheet is a plain box that stretches,
   and the frame fills it. */
.cutting__sheet{position:absolute;left:50%;transform:translateX(-50%);
  top:clamp(54px,8vh,92px);bottom:clamp(28px,5vh,60px);
  width:min(92vw,880px);background:#fff}
.cutting__sheet iframe{display:block;width:100%;height:100%;border:0}
.cutting__bar{position:absolute;left:50%;transform:translateX(-50%);
  top:0;height:clamp(54px,8vh,92px);width:min(92vw,880px);
  display:flex;align-items:center;justify-content:flex-end;gap:1.6em}
.cutting__out,.cutting__close{
  background:none;border:0;padding:4px 0;margin:0;cursor:pointer;
  font-family:inherit;font-size:clamp(12px,1vw,15px);font-weight:600;
  letter-spacing:.055em;text-transform:uppercase;color:var(--paper);
  text-decoration:none;transition:color .3s var(--ease)}
.cutting__out:hover{color:#99F8FF}
.cutting__close:hover{color:#FFBA6A}

/* ---------------------------------------------------------- motion off */

@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{
    animation-duration:.001ms !important;animation-iteration-count:1 !important;
    transition-duration:.001ms !important;
  }
  .introbg,.introsub{display:none}
  .namebar.is-intro{font-size:var(--t-body);font-weight:600}
  .namebar.is-intro a{color:var(--lit)}
  .slide__panel,.slide__tags,.slide__title,.slide__cta{
    opacity:1 !important;transform:none !important}
}
