/* ═══════════════════════════════════════════════════════════════════
   Projects — a gallery that travels sideways.

   The stage is one viewport tall and pins; the track inside it is a
   single flex row wider than the screen, pulled right to left by the
   scroll. Everything on the track travels together — pictures, title
   and the handwritten note — so the section reads as one long sheet
   passing the window rather than as slides advancing.

   Sizing is done in viewport heights, not pixels: every item declares
   its own --ar (the source aspect ratio) and --y (how far off centre it
   rides), and its width falls out of its height. Nothing here is drawn
   — no frame, no rule, no caption plate. Same discipline as the two
   collage sections above.

   Inherits every token from style.css.
   ═══════════════════════════════════════════════════════════════════ */

.prj{
  --gut-w: clamp(1.25rem, 7.5vw, 7rem);
  position:relative; z-index:1;
  background:var(--black);
}

/* The pinned frame. overflow:hidden is what makes the track's travel
   read as a window rather than as a page that has grown sideways —
   without it the row would widen the document and the whole site would
   scroll horizontally. */
.prj__stage{
  height:100dvh;
  display:flex; align-items:center;
  overflow:hidden;

  /* Carries its own background rather than inheriting the section's.
     Pinning lifts this element out of flow and leaves the section's box
     behind as a spacer, so a transparent stage would sit over the
     previous section and let it read straight through the gallery. */
  background:var(--black);
}

.prj__track{
  display:flex; align-items:center;
  flex:0 0 auto;
  gap:clamp(1.25rem,3.2vw,3.25rem);
  /* Nothing on the left. The row is a sheet passing a window, and a sheet
     that begins one gutter in begins with a margin — which reads as the
     page's margin rather than as the edge of something wider than the
     screen. The right gutter stays: that end is where the travel stops,
     and the last picture wants somewhere to stop against. */
  padding-inline:0 var(--gut-w);
  will-change:transform;
}

/* ── the exhibits ─────────────────────────────────────────────────── */
/* Height first, width derived. A row of mixed portrait and landscape
   sources then lands on a common baseline of scale instead of a common
   width, which is what keeps it reading as a hang rather than a strip.

   The heights are set so three frames sit on screen at once on a
   laptop: a landscape at 34vh is roughly a quarter of the viewport
   wide, and three of those plus their gaps fill it with room to spare.
   Raise these and the count drops — they are the one knob for it. */
.prj__item{
  flex:0 0 auto;
  margin:0;
  height:34vh;
  aspect-ratio:var(--ar,3/4);
  overflow:hidden;
  background:var(--ink);
  /* rides off centre by its own --y, so the row never lines up */
  transform:translateY(var(--y,0));
}
/* <picture> is an inline box with no size of its own, so an <img> inside
   one would resolve its height:100% against nothing and collapse. This
   makes the wrapper transparent to the layout, which lets any figure in
   the row carry a webp source without being sized differently from the
   ones that do not. */
.prj__item picture{
  display:block;
  width:100%; height:100%;
}
.prj__item img{
  width:100%; height:100%;
  object-fit:cover;
  display:block;
}

/* ── a picture with its line under it ─────────────────────────────── */
/* One track item, two stacked things. The handwriting used to be a track
   item of its own standing between two photographs; as a column of text
   in a gap it broke the row into a before and an after. Under the picture
   it describes, the pictures close up and the words are attached to
   something.

   The cell carries the row's two positioning devices — the vertical
   scatter and, on this one, the overlap — because it is the flex child
   the track is laying out. The figure inside must not take them a second
   time: --y inherits, so an un-neutralised .prj__item would translate by
   it again on top of its parent. */
.prj__cell{
  flex:0 0 auto;
  display:flex; flex-direction:column;
  align-items:flex-start;
  gap:clamp(.7rem,1.5vh,1.1rem);
  transform:translateY(var(--y,0));
}
.prj__cell .prj__item{ transform:none }
.prj__cell .prj__note{ transform:none }

/* Pulled toward the title, but no longer onto it. The negative margin is
   still deliberate and still only on this one — it closes the gap so the
   row reads as continuous rather than as a title parked beside a strip —
   but it now stops short of the word instead of running under it.

   It used to be clamp(-11rem,-8vw,-4rem), which resolved to -117.6px
   against a 47px gap and 29.4px of padding inside .prj__head: the
   picture's edge landed 41px to the left of the S's ink, so the last
   letter of PROJECTS sat under a render. Read as depth in the abstract;
   read as a collision on the screen, which is the only place it counts.

   The three numbers that decide the clearance are this margin, the
   track's gap and .prj__head's inline padding — air between the S and
   the picture is (padding + gap + margin), so all three have to be read
   together before any one of them moves. At -2.6vw that comes to about
   38px on a laptop and never closes below 21 down to the tablet, where
   js/projects.js takes the title out of the row anyway. */
.prj__cell--over{
  position:relative; z-index:1;
  margin-left:clamp(-4rem,-2.6vw,-1rem);
}

.prj__item--tall{ height:40vh }
.prj__item--port{ height:46vh }

/* ── the title, travelling with the work ──────────────────────────── */
.prj__head{
  flex:0 0 auto;
  /* Above the picture beside it. This z-index is now belt and braces
     rather than load-bearing: the two no longer overlap at all (see
     .prj__cell--over). It stays because the stacking order is the thing
     that decides which wins if either measurement is ever changed, and
     the word should win. */
  position:relative; z-index:3;
  padding-inline:clamp(.5rem,2vw,2rem);
}
.prj__title{
  font-family:var(--display-hi); font-weight:400;
  /* Sized to sit with the frames rather than tower over them — it is one
     exhibit among several, and at the old scale it took the whole screen
     to itself and broke the count of three. */
  font-size:var(--fs-mega);
  line-height:.9;
  letter-spacing:-.02em;
  text-transform:uppercase;
  white-space:nowrap;
  color:var(--bone);
  margin:0;
}

/* The way out of the row and into the page. Set exactly like
   .abt__scope-cta in css/about.css — a rule under a line of small caps
   with an arrow that moves on hover — because it is doing the same job
   one section further up: leaving a taster for the whole of it. */
.prj__cta{
  /* Its own line under the cue. Both are inline-level by nature, so
     without this the link simply follows the hint along the same
     baseline and the two read as one run of small caps. */
  display:flex; align-items:center; gap:.6rem;
  width:max-content;
  margin-top:clamp(1rem,3vh,1.6rem);
  padding-bottom:.35rem;
  font-family:var(--sans);
  font-size:var(--fs-fine); letter-spacing:.14em; text-transform:uppercase;
  color:var(--bronze-lt);
  border-bottom:1px solid var(--hair);
  white-space:nowrap;
  transition:color .25s var(--ease-out), border-color .25s var(--ease-out);
}
.prj__cta svg{
  width:15px; height:15px;
  transition:transform .35s var(--ease-out);
}
.prj__cta:focus-visible{ outline:2px solid var(--bronze-hi); outline-offset:5px }
@media (hover:hover) and (pointer:fine){
  .prj__cta:hover{ color:var(--bronze-hi); border-bottom-color:var(--bronze) }
  .prj__cta:hover svg{ transform:translateX(4px) }
}
@media (prefers-reduced-motion:reduce){
  .prj__cta svg{ transition:none }
  .prj__cta:hover svg{ transform:none }
}

/* ── the handwritten note ─────────────────────────────────────────── */
/* Travels between two pictures, arrow first so the line has already
   left the text by the time the picture it points at arrives. */
.prj__note{
  flex:0 0 auto;
  display:flex; flex-direction:column;
  align-items:flex-start;
  gap:.3rem;
  max-width:17rem;
  transform:translateY(7vh);
}
.prj__note-a{
  width:clamp(88px,8.5vw,120px);
  height:auto;
  margin-left:auto;
  color:var(--bone);
  overflow:visible;
}
.prj__note-a path{
  fill:none; stroke:currentColor;
  /* heavier than the collage arrow: this one is drawn at about two
     thirds the size, and 1.6 came out as a hairline at that scale */
  stroke-width:2.1; stroke-linecap:round; stroke-linejoin:round;
}
.prj__note-t{
  font-family:var(--script);
  /* Sized up about a quarter from the Nothing You Could Do setting.
     Alex Brush draws small on its em — a low x-height under tall
     ascenders — so the same font-size reads noticeably lighter than
     the hand it replaced. This holds the optical size the layout was
     built around. */
  font-size:var(--fs-sub);
  line-height:1.35;
  /* the logo's green, as everywhere this hand is used */
  color:var(--olive);
  margin:0;
  white-space:nowrap;
}

/* ── the dot rail ─────────────────────────────────────────────────── */
/* Phone only, and built by script — see the note in the markup. One
   hairline runs behind the whole row and each dot sits on it, so the set
   reads as positions along a single strip rather than as five loose
   circles. */
.prj__dots{
  display:none;
  position:relative;
  align-items:center; justify-content:center;
  gap:clamp(1.25rem,6vw,2.5rem);
  margin-top:clamp(1rem,3.5vh,1.75rem);
}
.prj__dots[hidden]{ display:none }

.prj__dots::before{
  content:""; position:absolute; z-index:0;
  left:8%; right:8%; top:50%;
  height:1px; background:var(--hair);
}

.prj__dot{
  position:relative;
  /* the mark is small; the target is not */
  width:44px; height:44px;
  display:grid; place-items:center;
  cursor:pointer;
}
/* the mark itself */
.prj__dot::before{
  content:""; position:relative; z-index:2;
  width:9px; height:9px; border-radius:50%;
  background:var(--bone-faint);
  transition:width .22s var(--ease-out), height .22s var(--ease-out),
             background .22s var(--ease-out);
}
.prj__dot.is-on::before{
  width:13px; height:13px;
  background:var(--bone);
}
/* the ring around the current one. Painted on the page background so the
   hairline appears to stop at it rather than run through the middle. */
.prj__dot::after{
  content:""; position:absolute; z-index:1;
  width:30px; height:30px; border-radius:50%;
  border:1.5px solid transparent;
  transition:border-color .22s var(--ease-out);
}
.prj__dot.is-on::after{
  border-color:var(--bone);
  background:var(--black);
}

@media (hover:hover) and (pointer:fine){
  .prj__dot:hover::before{ background:var(--bone) }
}
.prj__dot:active::before{ transform:scale(.9) }

/* ═══ fallbacks — the same track, swipeable ═══════════════════════ */
/* Whenever the pin is not running, the row has to stay reachable under
   its own power. Three cases share one treatment: no script at all, a
   viewport narrow enough that pinning fights the touch gesture, and a
   reader who has asked for reduced motion. js/projects.js sets
   data-native on the stage in the last two cases; .no-js covers the
   first. */
.no-js .prj__stage,
.prj__stage[data-native]{
  overflow-x:auto;
  overscroll-behavior-x:contain;
  /* mandatory, not proximity: the dots below name an exact picture, so
     the row has to come to rest on one */
  scroll-snap-type:x mandatory;
  -webkit-overflow-scrolling:touch;
  /* the pin is gone, so the stage no longer needs a full viewport */
  height:auto;
  padding-block:0;
  /* the row is the scrollbar's own; hiding it keeps the dots as the only
     position indicator, which is the whole point of them */
  scrollbar-width:none;
}
.no-js .prj__stage::-webkit-scrollbar,
.prj__stage[data-native]::-webkit-scrollbar{ display:none }
.no-js .prj__track,
.prj__stage[data-native] .prj__track{
  transform:none !important;
}
.no-js .prj__item,
.prj__stage[data-native] .prj__item{ scroll-snap-align:center }

/* ═══ responsive ══════════════════════════════════════════════════ */

@media (max-width:1100px){
  .prj__item     { height:31vh }
  .prj__item--tall{ height:36vh }
  .prj__item--port{ height:42vh }
}

/* ═══ phone — one picture at a time ═══════════════════════════════ */
/* A different composition, not a squeezed one. The sideways travel is a
   wide-screen idea: it needs room either side of the frame for the next
   picture to be arriving from. On a phone there is no such room, so the
   section stacks — title, then a single picture, then the dots that move
   between them — and the row underneath becomes a snapping carousel that
   the dots drive. js/projects.js moves the title and the note out of the
   track here; everything below assumes that has happened. */
@media (max-width:820px){
  .prj{
    padding:clamp(3rem,10vh,5rem) 0 clamp(2.5rem,8vh,4rem);
  }

  .prj__lead{
    text-align:center;
    padding-inline:var(--gut);
    margin-bottom:clamp(1.5rem,5vh,2.5rem);
  }
  .prj__head{ padding-inline:0 }
  .prj__title{ font-size:var(--fs-major) }
  .prj__cta{ justify-content:center; align-self:center }

  .prj__dots{ display:flex }

  /* One frame, centred, with the next one's edge just showing. Every
     slide takes the same box whatever its source ratio — a carousel
     whose frame changes shape under the thumb reads as a glitch, and
     the dots below would move with it. */
  .prj__track{
    /* Wide enough that the next picture is fully off screen. On the wide
       layout a peeking neighbour is the point; here it would only crowd
       the frame, and the dots already say there is more. */
    gap:16vw;
    /* half the leftover width, so the first and last slides can both
       come to rest dead centre */
    padding-inline:8vw;
  }
  .prj__item,
  .prj__item--tall,
  .prj__item--port{
    height:auto;
    width:84vw;
    aspect-ratio:4/5;
    transform:none;      /* the vertical scatter needs a tall frame */
  }
  /* The cell is the flex child down here too, so the scatter and the
     overlap come off it, not off the figure inside. The note has been
     moved out to the foot of the section by then, which leaves the cell
     holding a single picture the same width as every other slide. */
  .prj__cell{ transform:none; width:84vw }
  .prj__cell--over{ margin-left:0 }

  /* the note is a caption for the whole set down here */
  .prj__note{
    transform:none;
    max-width:none;
    align-items:center;
    padding-inline:var(--gut);
    margin-top:clamp(1.5rem,5vh,2.5rem);
  }
  .prj__note-a{ display:none }   /* nothing left for it to point at */
  .prj__note-t{ white-space:normal; text-align:center }
}

/* ═══ reduced motion ══════════════════════════════════════════════ */
@media (prefers-reduced-motion:reduce){
  .prj__item{ transform:none }
  .prj__note{ transform:none }
}

