@charset "UTF-8";
/* ============================================================================
   The motion vocabulary, shared by every page.

   This began as a block at the foot of home.css. It is a separate sheet now
   because the other ten pages want the same words: things arrive, photographs
   move against their frames, and a claim can assemble itself.

   Two kinds of motion live here, and they run on different clocks.

   Arrivals -- the reveal, the wipe, the words, the frames opening -- play once
   on wall time when a thing comes into view, and stay. reveal.js watches for
   the entry and adds `in`; the stylesheet only ever hides something under
   html.io, which the head script sets before first paint and takes back if
   reveal.js never arrives. Under reduced motion none of it runs.

   Travel -- the parallax, the band's pan, the hero copy letting go -- is
   scrubbed by the scroll position on a view timeline, because that is what
   it is. A browser without `animation-timeline` skips it and loses nothing.
   ========================================================================== */

/* ------------------------------------------------------------- the reveal
   The default arrival. Applied by class where a page wants to be explicit,
   and by selector to the handful of blocks every page is built from, so ten
   pages of markup did not have to grow a class attribute each. */

/* ------------------------------------------------- a headline, word by word
   For the one sentence on a page that the rest of the page is evidence for.
   Used sparingly -- if two headlines do this, neither is the claim. */
.rise-words span{display:inline-block}

/* --------------------------------------------------------------- the wipe
   Photographs uncover rather than fade. clip-path clips the element it is on,
   so .wipe goes on the img or the figure itself and needs no help from a
   parent. Do not put it on a card: it would clip the words too. */

/* ------------------------------------------------------------ the parallax
   Photographs move slightly against their frames as the page scrolls, at
   three different rates so a cluster has depth rather than sliding as one
   board. The scale is what buys the travel: without it the translate would
   drag empty frame into view at the edges -- which also means .par only ever
   goes on something inside a .frame, or it grows past its own box and over
   whatever is beside it. */

/* The clipping container .par needs. Nothing else. */
.frame{margin:0;overflow:hidden;background:var(--paper)}
.frame img{display:block;width:100%;height:auto}
@supports (animation-timeline:view()){
  @media (prefers-reduced-motion:no-preference){
    .par{
      animation:par-slow linear both;
      animation-timeline:view();animation-range:cover 0% cover 100%;
    }
    .par-mid{animation-name:par-mid}
    .par-fast{animation-name:par-fast}
    /* A cluster is always three frames in a fixed order, so it does not need
       the classes spelled out in the markup three times. */
    .cluster img{
      animation:par-slow linear both;
      animation-timeline:view();animation-range:cover 0% cover 100%;
    }
    .cl-2 img{animation-name:par-fast}
    .cl-3 img{animation-name:par-mid}
  }
}
@keyframes par-slow{from{transform:scale(1.1) translateY(2.4%)}
                    to{transform:scale(1.1) translateY(-2.4%)}}
@keyframes par-mid {from{transform:scale(1.12) translateY(4%)}
                    to{transform:scale(1.12) translateY(-4%)}}
@keyframes par-fast{from{transform:scale(1.14) translateY(5.5%)}
                    to{transform:scale(1.14) translateY(-5.5%)}}

/* ---------------------------------------------- words beside a cluster
   Words on one side, a staggered mosaic of frames on the other.

   The first version had one frame span both rows and stretch to fill them. At
   this column width that came to 269x809 -- a 1:3 sliver that cropped the
   people out of a photograph of people. Every frame keeps its own 3:4 now and
   the second column is dropped down the page instead, which gives the same
   broken grid without asking any image to be a shape it is not. */
.stakes{display:grid;gap:clamp(1.8rem,4vw,3.5rem);align-items:start}
@media (min-width:900px){
  .stakes{grid-template-columns:minmax(0,1fr) minmax(0,1.15fr)}
  .stakes.flip > *:first-child{order:2}
}
.cluster{
  display:grid;grid-template-columns:1fr 1fr;
  gap:clamp(.7rem,1.8vw,1.2rem);align-items:start;
}
.cluster figure{margin:0;overflow:hidden;background:var(--paper)}
.cluster img{width:100%;height:auto;aspect-ratio:3/4;object-fit:cover}
.cluster.wide img{aspect-ratio:4/3}
.cl-1{grid-column:1;grid-row:1}
.cl-3{grid-column:1;grid-row:2}
/* Spanning both rows, not sitting in the first one: a margin on a single-row
   item grows that row and opens a matching hole in the other column. And it
   needs .cluster in front of it, because .cluster figure{margin:0} outranks a
   bare .cl-2 on specificity and the offset silently does nothing. */
.cluster .cl-2{grid-column:2;grid-row:1/3;align-self:start;
  margin-top:clamp(2rem,9vw,6.5rem)}

/* ---------------------------------------------------------------- the band
   One wide photograph with one line over it, for the point in a page where
   the eye has read four text blocks and needs somewhere to rest.

   The image is deliberately taller than the band and hangs over both edges, so
   it has room to travel without ever showing the ground behind it. */
.band{
  margin:var(--gap) calc(var(--pad) * -1);
  display:block;overflow:hidden;background:var(--cream);
  padding:0;border-bottom:0;
}
.band-img{
  display:block;width:100%;height:auto;max-width:none;
  aspect-ratio:21/9;object-fit:cover;
}
.band p{
  margin:0;color:var(--ink);text-align:center;
  font-family:var(--display);font-weight:400;line-height:1.18;
  font-size:clamp(1.55rem,4.4vw,3rem);
  max-width:26ch;padding:clamp(2.4rem,6vw,4rem) var(--pad);
  margin-inline:auto;text-wrap:balance;
}
.band cite{display:block;font-family:var(--sans);font-style:normal;
  font-size:.68rem;letter-spacing:.22em;text-transform:uppercase;
  color:var(--ink);margin-top:1.4rem}
@media (max-width:620px){.band-img{aspect-ratio:16/10}}

/* --------------------------------------------------------------- the names
   For lists whose charm is that they are names and not numbers. A slow drift
   lets them read as a place rather than as inventory. Hidden from assistive
   tech -- the duplicated track would read twice -- with the real list carried
   in a visually hidden paragraph beside it. */
.names{
  margin:calc(var(--gap) * .7) calc(var(--pad) * -1) 0;
  padding:clamp(1rem,2.5vw,1.6rem) 0;overflow:hidden;
  border-top:1px solid var(--line);border-bottom:1px solid var(--line);
  -webkit-mask-image:linear-gradient(90deg,transparent,#000 7%,#000 93%,transparent);
          mask-image:linear-gradient(90deg,transparent,#000 7%,#000 93%,transparent);
}
.names-track{display:flex;width:max-content}
.names-track span{
  font-family:var(--display);font-size:clamp(1.25rem,3vw,2rem);
  color:var(--ink-faint);white-space:nowrap;display:flex;align-items:center;
  padding:0 clamp(1rem,2.6vw,2.2rem);gap:clamp(1rem,2.6vw,2.2rem);
}
.names-track span::after{
  content:"";width:4px;height:4px;border-radius:50%;background:var(--clay);
  flex:none;opacity:.6;
}
@media (prefers-reduced-motion:no-preference){
  /* The track holds the list twice, so -50% is one seamless lap. */
  .names-track{animation:lap 52s linear infinite}
}
@keyframes lap{to{transform:translateX(-50%)}}

/* ------------------------------------------------------------- the gallery
   A wall of frames, uncovering a row at a time. Deliberately not a lightbox:
   the point of a gallery on this site is to be scrolled past, not opened. */
.gallery{
  display:grid;gap:clamp(.6rem,1.6vw,1.1rem);margin-top:2.4rem;
  grid-template-columns:repeat(auto-fit,minmax(15rem,1fr));
}
/* The aspect lives on the frame, not on the img.

   With it on the img, the wide frame's 16:9 was taller than its 4:3 neighbours
   and grid stretched them to match, leaving a hundred pixels of empty ground
   under each. The frames are all 4:3 now and set the row height between them;
   the wide one takes whatever that comes to and crops a panorama out of it. */
.gallery figure{
  margin:0;overflow:hidden;background:var(--paper);aspect-ratio:4/3;
}
.gallery img{
  width:100%;height:100%;object-fit:cover;display:block;
  transition:transform 1.2s cubic-bezier(.2,.7,.2,1);
}
.gallery figure:hover img{transform:scale(1.05)}
/* One frame in four gets the width of two, so the wall has a rhythm instead of
   reading as a spreadsheet. It keeps a definite aspect rather than taking
   `auto`: a grid item with aspect-ratio:auto sizes from its content, which
   made the wide frame 396 tall against its neighbours' 191 and left a hole
   under each of them. 11/4 is two columns and the gap between them over one
   row of the others -- near enough that the rows read as level. */
.gallery figure:nth-child(4n+1){grid-column:span 2;aspect-ratio:11/4}
@media (max-width:640px){
  .gallery figure:nth-child(4n+1){grid-column:auto;aspect-ratio:4/3}
}

/* ============================================================================
   Arrivals. Each plays once, on entry, at its own pace.

   Nothing here ever makes content invisible. A visitor is assumed to give the
   site seven seconds, and text that is not painted until a scroll event fires
   is seven seconds badly spent -- it also breaks find-in-page and reads as a
   blank column to anyone moving quickly. So the resting state is a small
   offset and nothing more: everything is legible from the first paint and
   simply settles as it is reached. Photographs are never clipped away.

   `.io <thing>:not(.in)` is still the hook, and adding `in` is still the
   whole trigger; it just no longer costs anybody sight of the words.
   ========================================================================== */
:root{--arrive:cubic-bezier(.16,.8,.24,1)}

/* ---- the reveal: up and in */
.io .reveal, .io main .lede, .io main .card, .io main .split, .io main .step,
.io main .note, .io main .named li, .io main .form .field, .io main .statement,
.io main .closing-body, .io main .facts li, .io main .onward, .io .wk{
  transition:opacity 1s var(--arrive),transform 1s var(--arrive);
}
.io .reveal:not(.in), .io main .lede:not(.in), .io main .card:not(.in),
.io main .split:not(.in), .io main .step:not(.in), .io main .note:not(.in),
.io main .named li:not(.in), .io main .form .field:not(.in),
.io main .statement:not(.in), .io main .closing-body:not(.in),
.io main .facts li:not(.in), .io main .onward:not(.in), .io .wk:not(.in){
  transform:translateY(14px);
}
/* Things that sit in a row arrive in the order they are read. */
.io main .card:nth-child(2), .io main .named li:nth-child(2),
.io main .form .field:nth-child(2), .io main .facts li:nth-child(2), .io .wk:nth-child(2){transition-delay:.12s}
.io main .card:nth-child(3), .io main .named li:nth-child(3),
.io main .form .field:nth-child(3), .io main .facts li:nth-child(3), .io .wk:nth-child(3){transition-delay:.24s}
.io main .card:nth-child(4), .io main .named li:nth-child(4),
.io main .facts li:nth-child(4), .io .wk:nth-child(4){transition-delay:.36s}
.io main .facts li:nth-child(5){transition-delay:.48s}
.io main .facts li:nth-child(6){transition-delay:.6s}

/* ---- a headline, word by word */
.io .rise-words span{transition:opacity .8s var(--arrive),transform .8s var(--arrive)}
.io .rise-words:not(.in) span{transform:translateY(.26em)}
.io .rise-words span:nth-child(2){transition-delay:.07s}
.io .rise-words span:nth-child(3){transition-delay:.14s}
.io .rise-words span:nth-child(4){transition-delay:.21s}
.io .rise-words span:nth-child(5){transition-delay:.28s}
.io .rise-words span:nth-child(6){transition-delay:.35s}
.io .rise-words span:nth-child(7){transition-delay:.42s}
.io .rise-words span:nth-child(8){transition-delay:.49s}
.io .rise-words span:nth-child(9){transition-delay:.56s}
.io .rise-words span:nth-child(10){transition-delay:.63s}
.io .rise-words span:nth-child(11){transition-delay:.7s}

/* ---- the denials, one at a time */
.io .nots li{transition:opacity .9s var(--arrive),transform .9s var(--arrive)}
.io .nots:not(.in) li{transform:translateY(12px)}
.io .nots li:nth-child(2){transition-delay:.1s}
.io .nots li:nth-child(3){transition-delay:.2s}
.io .nots li:nth-child(4){transition-delay:.3s}
.io .nots li:nth-child(5){transition-delay:.4s}
.io .nots li:nth-child(6){transition-delay:.5s}

/* ---- photographs settle rather than uncover. They used to be clipped out of
   the page until their turn, which is the one thing she asked not to happen. */
.io .wipe, .io .wk figure, .io .gallery figure{transition:transform 1s var(--arrive)}
.io .wipe:not(.in), .io .wk:not(.in) figure, .io .gallery:not(.in) figure{transform:scale(.985)}
.io .gallery figure:nth-child(2){transition-delay:.09s}
.io .gallery figure:nth-child(3){transition-delay:.18s}
.io .gallery figure:nth-child(4){transition-delay:.27s}
.io .gallery figure:nth-child(5){transition-delay:.09s}
.io .gallery figure:nth-child(6){transition-delay:.18s}
.io .gallery figure:nth-child(7){transition-delay:.27s}
.io .gallery figure:nth-child(8){transition-delay:.36s}

/* ---- the frames open: uncovered upward while settling up to size */
.io .cluster figure{transition:transform 1.1s var(--arrive)}
.io .cluster:not(.in) figure{transform:scale(.965)}
.io .cluster .cl-2{transition-delay:.16s}
.io .cluster .cl-3{transition-delay:.32s}

/* ---- the band's line settles into place */
.io .band p{transition:opacity 1.2s var(--arrive),letter-spacing 1.2s var(--arrive)}
.io .band:not(.in) p{letter-spacing:.045em}
