/* ===================================================================
   Horizon Symmetry — case study

   Built to the nonstop reference. Two fixed things and one moving one:
   a slim bar across the top, a rail down the right that never scrolls,
   and the gallery, which is the entire scroll of the page.

   The rail carries everything verbal — project row, the four folds,
   and the next project pinned to its floor. The gallery carries only
   work, edge to edge, with a hairline of black between frames.

   Tokens and fonts come from styles.css.
   =================================================================== */

.case {
  /* the bar is sized around the landing page's logo, so the mark is the
     same object on both — see .brand__mark in styles.css */
  --bar:       clamp(4.6rem, 6.2vw, 6rem);
  --bar-clear: clamp(2rem, 4.8vh, 4.25rem);    /* air under the bar */
  --bar-text:  clamp(0.98rem, 1.1vw, 1.08rem); /* matches body copy */
  --rail: clamp(21rem, 34vw, 44rem);  /* right rail */
  --gap:  10px;                       /* between frames, and to the edges */
  background: var(--void);
}

/* ---------- top bar -------------------------------------------------- */

.bar {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: 30;
  height: var(--bar);
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  /* left lines up with the gallery's edge, right with the rail's copy */
  padding-left: var(--gap);
  padding-right: clamp(0.85rem, 1.1vw, 1.15rem);
  background: var(--void);
}

.bar__brand {
  display: inline-flex;
  justify-self: start;
  border-radius: 0.35rem;
  text-decoration: none;
}
/* Set to the height of the button opposite it, rather than to its own
   scale: the two are the only objects in the bar, they sit at the same
   eye level, and any difference between them reads as the mark being
   oversized. 2.9em is .bar__end's height, and --bar-text is its font
   size, so the mark tracks the button wherever the button goes. */
.bar__brand img {
  display: block;
  width: auto;
  height: calc(var(--bar-text) * 2.9);
  transition: transform 0.5s var(--ease-out), filter 0.5s var(--ease);
}
.bar__brand:hover img {
  transform: scale(1.04);
  filter: drop-shadow(0 0 30px rgba(230, 196, 250, 0.55));
}

.bar__nav {
  display: flex;
  gap: clamp(1.4rem, 2.6vw, 2.6rem);
  justify-self: center;
}

.bar__nav a {
  color: var(--ink-dim);
  font-size: var(--bar-text);
  text-decoration: none;
  transition: color 0.3s var(--ease);
}
.bar__nav a:hover { color: var(--ink); }
.bar__nav a[aria-current="page"] { color: var(--ink); }

/* Carries the landing page's call to action: a pill that fills from the
   left on hover. Kept in step with .cta in styles.css. */
.bar__end {
  position: relative;
  z-index: 1;                  /* contains the fill, which sits at -1 */
  overflow: hidden;            /* the fill is a rectangle; this rounds it */
  justify-self: end;
  display: inline-flex;
  align-items: center;
  gap: 0.55rem;
  height: 2.9em;
  padding: 0 1.6em;
  border: 1px solid rgba(230, 196, 250, 0.42);
  border-radius: 30em;
  color: var(--violet-hot);
  font-size: var(--bar-text);
  font-weight: 500;
  letter-spacing: 0.012em;
  text-decoration: none;
  white-space: nowrap;
  box-shadow:
    6px 6px 16px rgba(0, 0, 0, 0.8),
    -6px -6px 16px rgba(155, 59, 224, 0.14);
  transition:
    color 0.5s ease,
    border-color 0.5s ease,
    box-shadow 0.5s ease;
}

.bar__end::before {
  content: "";
  position: absolute;
  z-index: -1;
  inset: 0 auto 0 0;
  width: 0;
  background-image: linear-gradient(to right, var(--violet) 0%, var(--violet-hot) 100%);
  transition: width 0.55s var(--ease-out);
}
.bar__end:hover::before,
.bar__end:focus-visible::before { width: 100%; }

.bar__end:hover,
.bar__end:focus-visible {
  color: var(--void);
  border-color: transparent;
  box-shadow:
    8px 8px 22px rgba(0, 0, 0, 0.85),
    -8px -8px 22px rgba(155, 59, 224, 0.22);
}
.bar__end:focus-visible { outline: 2px solid var(--violet-hot); outline-offset: 3px; }

.bar__end svg {
  width: 0.9em;
  height: 0.9em;
  transition: transform 0.45s var(--ease-out);
}
.bar__end:hover svg { transform: translate(2px, -2px); }

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

/* The frames are placeholders: swap each .ph for an <img> and the
   layout does not change — .shot img is already sized to cover. */

.gallery {
  margin-right: var(--rail);
  padding: calc(var(--bar) + var(--bar-clear)) var(--gap) var(--gap);
  display: flex;
  flex-direction: column;
  gap: var(--gap);
}

/* .pair is two frames side by side; .row is the same thing for three.
   Both share one height, and with .shot--fit each one's flex-grow is its
   own ratio, so any mix of shapes lands on a single common baseline. */
.pair,
.row {
  display: flex;
  gap: var(--gap);
}
.pair .shot,
.row .shot { flex: 1; min-width: 0; }

.shot {
  margin: 0;
  overflow: hidden;
  background: #0C0C0F;
  height: 72svh;
}

.shot--wide { height: 46svh; }
.shot--half { height: 58svh; }

/* A frame that takes its shape from the picture instead of the viewport.
   --r is the image's own width/height, so nothing is ever cropped. In a
   pair, flex-grow is that same number: two frames of any two shapes then
   land on exactly one shared height. */
.shot.shot--fit {
  height: auto;
  aspect-ratio: var(--r);
}
.pair .shot.shot--fit,
.row .shot.shot--fit { flex: var(--r) 1 0; }

/* Every frame is already cut to the shape of what it holds, so the media
   fills it edge to edge. Stated on the element as well as the class,
   because a <video> carries width/height attributes that would otherwise
   lay it out at its own pixel size and spill it out of the frame. */
.shot img,
.shot video,
.shot__cover,
.shot__clip {
  width: 100%;
  height: 100%;
  max-width: 100%;
  object-fit: cover;
  display: block;
}

/* the stand-in: a flat block that says which frame it is */
.ph {
  height: 100%;
  display: grid;
  place-items: center;
  background: var(--accent, #23303A);
  color: rgba(255, 255, 255, 0.82);
  font-family: var(--display);
  font-size: clamp(1rem, 1.5vw, 1.35rem);
  letter-spacing: 0.16em;
  text-transform: uppercase;
}

/* ---------- the colour board, in motion ------------------------------- */

/* The palette board as it is drawn in the brand book: four straight
   columns, the hex over the name at the foot of each. Geometry is taken
   off crude-04.jpg so the moving board sits where the still one did —
   labels 2.1% in from the left edge and 4.7% up from the floor.

   The motion is the one Ar/Cut's board uses, measured off arcut-04:
   each colour takes a turn swelling while the rest give way, holds,
   then hands over to the next. Widths are flex-grow, so the board's
   total width never changes and every band pays for the swell in
   proportion. */

.palette {
  position: relative;
  container-type: size;
  background: #1C1814;
}

.palette__board {
  position: absolute;
  inset: 0;
  display: flex;
}

.palette__band {
  flex: 1 1 0;
  min-width: 0;
  display: flex;
  align-items: flex-end;
  padding: 0 0 4.7cqh 2.1cqh;
  background: var(--c);
  color: var(--t);
  overflow: hidden;
  animation: palette-swell 6.4s cubic-bezier(0.4, 0, 0.2, 1) infinite;
  /* -4 drops every band straight into the steady loop, so the first
     cycle is not played as a stagger */
  animation-delay: calc((var(--i) - 4) * 1.6s);
}

.palette__label {
  display: flex;
  flex-direction: column;
  gap: 0.7cqh;
}

.palette__hex {
  font-family: var(--body);
  font-size: 2.4cqh;
  letter-spacing: 0.03em;
  opacity: 0.66;
  white-space: nowrap;
}

.palette__name {
  font-family: "Iowan Old Style", Palatino, "Palatino Linotype", Georgia, serif;
  font-size: 4.6cqh;
  line-height: 1;
  white-space: nowrap;
}

/* 0 -> 13.75% is the 0.88s swell, held to 25%, given back by 38.75%.
   The windows overlap on purpose: one band is still returning while the
   next is already taking, which is the hand-off Ar/Cut has. */
@keyframes palette-swell {
  0%      { flex-grow: 1; }
  13.75%  { flex-grow: 2.9; }
  25%     { flex-grow: 2.9; }
  38.75%  { flex-grow: 1; }
  100%    { flex-grow: 1; }
}

@media (prefers-reduced-motion: reduce) {
  .palette__band { animation: none; }
}

/* ---------- the Market Pulse issue, setting itself --------------------- */

/* The artwork is never retyped: each line is a window onto crude-06.jpg
   itself, so the bespoke logotype and the original typesetting survive
   exactly. A line's box is only as tall as that line, with the jpg sized
   to the frame behind it and slid up by --p, which keeps eleven cheap
   layers instead of eleven full-size ones.

   Band edges sit at the midpoint of each gap between lines, measured off
   the file, so no window can ever clip its neighbour's ascenders.

   The reveal is a soft-edged mask swept across each line: a gradient
   four times the line's width, transparent at both ends and opaque in
   the middle. Sweeping it right to left writes the line on, holds it,
   then carries it off the same way it arrived. No hard edge anywhere.

   The stagger lives in each line's own keyframes rather than in an
   animation-delay, which is what lets the entrance be unhurried while
   the whole card still clears in one synchronised pass. On a shared
   delay the exit is forced to repeat the entrance stagger, and the
   logotype then sits dark for as long as the stagger is wide. */

.pulse {
  position: relative;
  background: #1C1914;
}

.pulse__line {
  position: absolute;
  left: 0;
  right: 0;
  top: var(--t);
  height: var(--h);
  background-image: url("../assets/crude/crude-06.jpg");
  background-size: 100% auto;
  background-position: 0 var(--p);
  background-repeat: no-repeat;
  -webkit-mask-image: linear-gradient(90deg, transparent 0 28%, #000 33% 67%, transparent 72% 100%);
          mask-image: linear-gradient(90deg, transparent 0 28%, #000 33% 67%, transparent 72% 100%);
  -webkit-mask-size: 400% 100%;
          mask-size: 400% 100%;
  -webkit-mask-repeat: no-repeat;
          mask-repeat: no-repeat;
  /* the resting state is hidden, so nothing can flash in before its turn */
  -webkit-mask-position: 100% 0;
          mask-position: 100% 0;
  animation-duration: 8.5s;
  animation-timing-function: cubic-bezier(0.45, 0.05, 0.55, 0.95);
  animation-iteration-count: infinite;
}

/* 1.05s to write a line on, 0.15s between them, so the last lands at
   3.9s. Held to 7.15s, then every line clears together, the wipe closing
   exactly on the loop boundary so the card is never sitting dark for
   longer than the beat it takes the logotype to start again. 0% and
   100% are different mask positions but both read as hidden, so the
   wrap is invisible. */
.pulse__line:nth-child(1) { animation-name: pulse-w0; }
.pulse__line:nth-child(2) { animation-name: pulse-w1; }
.pulse__line:nth-child(3) { animation-name: pulse-w2; }
.pulse__line:nth-child(4) { animation-name: pulse-w3; }
.pulse__line:nth-child(5) { animation-name: pulse-w4; }
.pulse__line:nth-child(6) { animation-name: pulse-w5; }
.pulse__line:nth-child(7) { animation-name: pulse-w6; }
.pulse__line:nth-child(8) { animation-name: pulse-w7; }
.pulse__line:nth-child(9) { animation-name: pulse-w8; }
.pulse__line:nth-child(10) { animation-name: pulse-w9; }
.pulse__line:nth-child(11) { animation-name: pulse-w10; }

@keyframes pulse-w0 {
  0%     { -webkit-mask-position: 100% 0; mask-position: 100% 0; }
  12.353% { -webkit-mask-position: 50% 0; mask-position: 50% 0; }
  84.118% { -webkit-mask-position: 50% 0; mask-position: 50% 0; }
  100%    { -webkit-mask-position: 0% 0; mask-position: 0% 0; }
}
@keyframes pulse-w1 {
  0%     { -webkit-mask-position: 100% 0; mask-position: 100% 0; }
  9.412%  { -webkit-mask-position: 100% 0; mask-position: 100% 0; }
  21.765% { -webkit-mask-position: 50% 0; mask-position: 50% 0; }
  84.118% { -webkit-mask-position: 50% 0; mask-position: 50% 0; }
  100%    { -webkit-mask-position: 0% 0; mask-position: 0% 0; }
}
@keyframes pulse-w2 {
  0%     { -webkit-mask-position: 100% 0; mask-position: 100% 0; }
  15.294% { -webkit-mask-position: 100% 0; mask-position: 100% 0; }
  27.647% { -webkit-mask-position: 50% 0; mask-position: 50% 0; }
  84.118% { -webkit-mask-position: 50% 0; mask-position: 50% 0; }
  100%    { -webkit-mask-position: 0% 0; mask-position: 0% 0; }
}
@keyframes pulse-w3 {
  0%     { -webkit-mask-position: 100% 0; mask-position: 100% 0; }
  21.176% { -webkit-mask-position: 100% 0; mask-position: 100% 0; }
  33.529% { -webkit-mask-position: 50% 0; mask-position: 50% 0; }
  84.118% { -webkit-mask-position: 50% 0; mask-position: 50% 0; }
  100%    { -webkit-mask-position: 0% 0; mask-position: 0% 0; }
}
@keyframes pulse-w4 {
  0%     { -webkit-mask-position: 100% 0; mask-position: 100% 0; }
  22.941% { -webkit-mask-position: 100% 0; mask-position: 100% 0; }
  35.294% { -webkit-mask-position: 50% 0; mask-position: 50% 0; }
  84.118% { -webkit-mask-position: 50% 0; mask-position: 50% 0; }
  100%    { -webkit-mask-position: 0% 0; mask-position: 0% 0; }
}
@keyframes pulse-w5 {
  0%     { -webkit-mask-position: 100% 0; mask-position: 100% 0; }
  24.706% { -webkit-mask-position: 100% 0; mask-position: 100% 0; }
  37.059% { -webkit-mask-position: 50% 0; mask-position: 50% 0; }
  84.118% { -webkit-mask-position: 50% 0; mask-position: 50% 0; }
  100%    { -webkit-mask-position: 0% 0; mask-position: 0% 0; }
}
@keyframes pulse-w6 {
  0%     { -webkit-mask-position: 100% 0; mask-position: 100% 0; }
  26.471% { -webkit-mask-position: 100% 0; mask-position: 100% 0; }
  38.824% { -webkit-mask-position: 50% 0; mask-position: 50% 0; }
  84.118% { -webkit-mask-position: 50% 0; mask-position: 50% 0; }
  100%    { -webkit-mask-position: 0% 0; mask-position: 0% 0; }
}
@keyframes pulse-w7 {
  0%     { -webkit-mask-position: 100% 0; mask-position: 100% 0; }
  28.235% { -webkit-mask-position: 100% 0; mask-position: 100% 0; }
  40.588% { -webkit-mask-position: 50% 0; mask-position: 50% 0; }
  84.118% { -webkit-mask-position: 50% 0; mask-position: 50% 0; }
  100%    { -webkit-mask-position: 0% 0; mask-position: 0% 0; }
}
@keyframes pulse-w8 {
  0%     { -webkit-mask-position: 100% 0; mask-position: 100% 0; }
  30.0%   { -webkit-mask-position: 100% 0; mask-position: 100% 0; }
  42.353% { -webkit-mask-position: 50% 0; mask-position: 50% 0; }
  84.118% { -webkit-mask-position: 50% 0; mask-position: 50% 0; }
  100%    { -webkit-mask-position: 0% 0; mask-position: 0% 0; }
}
@keyframes pulse-w9 {
  0%     { -webkit-mask-position: 100% 0; mask-position: 100% 0; }
  31.765% { -webkit-mask-position: 100% 0; mask-position: 100% 0; }
  44.118% { -webkit-mask-position: 50% 0; mask-position: 50% 0; }
  84.118% { -webkit-mask-position: 50% 0; mask-position: 50% 0; }
  100%    { -webkit-mask-position: 0% 0; mask-position: 0% 0; }
}
@keyframes pulse-w10 {
  0%     { -webkit-mask-position: 100% 0; mask-position: 100% 0; }
  33.529% { -webkit-mask-position: 100% 0; mask-position: 100% 0; }
  45.882% { -webkit-mask-position: 50% 0; mask-position: 50% 0; }
  84.118% { -webkit-mask-position: 50% 0; mask-position: 50% 0; }
  100%    { -webkit-mask-position: 0% 0; mask-position: 0% 0; }
}

@media (prefers-reduced-motion: reduce) {
  .pulse__line {
    animation: none;
    -webkit-mask-image: none;
            mask-image: none;
  }
}

/* ---------- rail ----------------------------------------------------- */

.rail {
  position: fixed;
  top: var(--bar);
  right: 0;
  bottom: 0;
  width: var(--rail);
  z-index: 20;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  padding:
    var(--bar-clear)
    clamp(0.85rem, 1.1vw, 1.15rem)
    clamp(0.85rem, 1.1vw, 1.15rem);
  border-left: 1px solid var(--rule);
  background: var(--void);
}

/* ---------- project row ---------------------------------------------- */

.rail__head {
  display: grid;
  grid-template-columns: auto auto minmax(0, 1fr) auto;
  align-items: center;
  gap: 0.6rem;
  padding: clamp(0.55rem, 1.1vh, 0.75rem) 0;
}

.rail__mark {
  width: 1.15rem;
  height: 1.15rem;
  border-radius: 0.3rem;
  background: var(--accent, var(--violet));
  flex: 0 0 auto;
}

.rail__name {
  margin: 0;
  font-family: var(--pixel);
  font-weight: 400;
  font-size: clamp(1.15rem, 1.28vw, 1.32rem);
  letter-spacing: 0;
  white-space: nowrap;
}

/* the tagline sits in its own column so it lines up with the one in the
   next-project row at the bottom of the rail */
.rail__tag {
  margin: 0;
  padding-left: clamp(0.5rem, 2.5vw, 2.6rem);
  color: var(--ink-dim);
  font-size: clamp(0.95rem, 1.05vw, 1.06rem);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.rail__year {
  color: var(--ink-dim);
  font-size: clamp(0.95rem, 1.05vw, 1.06rem);
  font-variant-numeric: tabular-nums;
}

/* ---------- folds ---------------------------------------------------- */

.folds { border-top: 1px solid var(--rule); }

.fold { border-bottom: 1px solid var(--rule); }

/* the heading is here for structure only — the button carries the type,
   and it inherits, so h2's own margin and weight have to go */
.fold h2 {
  margin: 0;
  font-size: inherit;
  font-weight: 400;
}

.fold__head {
  width: 100%;
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: center;
  gap: 1rem;
  padding: clamp(0.45rem, 0.9vh, 0.62rem) 0;
  background: none;
  border: 0;
  color: var(--ink-dim);
  font: inherit;
  text-align: left;
  cursor: pointer;
  transition: color 0.3s var(--ease);
}
.fold__head:hover { color: var(--ink); }
.fold.is-open .fold__head { color: var(--ink); }

.fold__name {
  font-size: clamp(1.02rem, 1.12vw, 1.14rem);
  letter-spacing: -0.005em;
}

/* a plus that loses its upright to become a minus */
.fold__sign {
  position: relative;
  width: 0.72rem;
  height: 0.72rem;
}
.fold__sign::before,
.fold__sign::after {
  content: "";
  position: absolute;
  inset: 50% 0 auto 0;
  height: 1px;
  background: currentColor;
  transition: transform 0.4s var(--ease-out), opacity 0.25s var(--ease);
}
.fold__sign::after { transform: rotate(90deg); }
.fold.is-open .fold__sign::after { transform: rotate(90deg) scaleX(0); opacity: 0; }

/* 0fr → 1fr animates the real height without measuring it */
.fold__wrap {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows 0.55s var(--ease-out);
}
.fold.is-open .fold__wrap { grid-template-rows: 1fr; }

.fold__inner {
  overflow: hidden;
  opacity: 0;
  transition: opacity 0.4s var(--ease);
}
.fold.is-open .fold__inner {
  opacity: 1;
  transition-delay: 0.1s;
}

.fold__body { padding-bottom: clamp(0.8rem, 1.7vh, 1.1rem); }

.fold__body p {
  margin: 0;
  color: var(--ink-dim);
  font-size: clamp(0.98rem, 1.08vw, 1.08rem);
  line-height: 1.6;
  text-wrap: pretty;
}
.fold__body p + p { margin-top: 0.75rem; }

/* ---------- next project --------------------------------------------- */

/* pinned to the rail's floor, always in view */
.upnext {
  display: block;
  margin-top: auto;
  text-decoration: none;
  color: var(--ink);
}

.upnext__label {
  display: block;
  padding-bottom: clamp(0.6rem, 1.4vh, 0.9rem);
  font-size: clamp(1.05rem, 1.15vw, 1.18rem);
  color: var(--ink);
}

.upnext__row {
  display: grid;
  grid-template-columns: auto auto minmax(0, 1fr) auto auto;
  align-items: center;
  gap: 0.6rem;
  padding-top: clamp(0.65rem, 1.4vh, 0.95rem);
  border-top: 1px solid var(--rule);
}

.upnext__name {
  font-family: var(--pixel);
  font-weight: 400;
  font-size: clamp(1.15rem, 1.28vw, 1.32rem);
}

.upnext__tag {
  padding-left: clamp(0.5rem, 2.5vw, 2.6rem);
  color: var(--ink-dim);
  font-size: clamp(0.95rem, 1.05vw, 1.06rem);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.upnext__year {
  color: var(--ink-dim);
  font-size: clamp(0.95rem, 1.05vw, 1.06rem);
  font-variant-numeric: tabular-nums;
}

.upnext__go {
  width: 0.85rem;
  height: 0.85rem;
  color: var(--ink-dim);
  transition: transform 0.4s var(--ease-out), color 0.3s var(--ease);
}
.upnext:hover .upnext__go {
  color: var(--ink);
  transform: translate(2px, -2px);
}

/* ---------- the closing ask ------------------------------------------ */

/* Last child of the gallery, so it sits in the scrolling column and keeps
   the rail beside it. The frames run edge to edge on a 10px gap, which is
   far too tight for type — this is the one block in the column that pads
   itself back in, and a hairline above it separates the ask from the work. */
/* Centred, and with no rule above it. The line was doing the job the
   space already does, and it cut the ask off from the work instead of
   letting it follow from it. */
.case-cta {
  margin-top: clamp(1.25rem, 4vh, 2.5rem);
  padding: clamp(2rem, 6vh, 3.75rem) clamp(1.5rem, 4vw, 3.5rem) clamp(1rem, 3vh, 2rem);
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: clamp(1.5rem, 4vw, 2.25rem);
}

.case-cta h2 {
  margin: 0;
  max-width: 22ch;
  font-family: var(--pixel);
  font-weight: 400;
  font-size: clamp(1.5rem, 2.6vw, 2.35rem);
  line-height: 1.18;
  letter-spacing: 0;
  text-wrap: balance;
}

/* .cta arrives hidden and waits on the hero's .is-ready, which a case page
   never sets — hand it its resting state outright, as about.html does */
.case-cta .cta { opacity: 1; transform: none; transition-delay: 0s; }

/* ---------- narrow screens ------------------------------------------- */

@media (max-width: 900px) {
  .case { --rail: 0px; }

  /* The four links are centred between the mark and the button, and at a
     fixed 1rem they ran into the button below about 375px — an SE or a
     mini put Contact under the pill. The gap gives way with the screen
     instead, which is the only one of the three that can. */
  .bar__nav { gap: clamp(0.5rem, 3.2vw, 1rem); }
  /* and below that the words themselves give a little, which is what
     finally clears an SE — the mark and the button are both fixed to the
     bar's height and cannot help */
  .bar__nav a { font-size: clamp(0.8rem, 3.4vw, var(--bar-text)); }
  .bar__end span { display: none; }

  /* The rail stops being a rail. Dissolving it lets its two halves take
     their own places in the page: the argument above the work, the next
     project at the very bottom where it belongs on a phone. */
  .case main { display: flex; flex-direction: column; }
  .rail { display: contents; }

  .rail__top {
    order: 1;
    padding: calc(var(--bar) + var(--bar-clear)) var(--gutter) 0;
  }

  .gallery {
    order: 2;
    margin-right: 0;
    padding-top: clamp(1.5rem, 4vh, 2.5rem);
  }

  .upnext {
    order: 3;
    padding: clamp(1.6rem, 5vh, 2.6rem) var(--gutter) clamp(2rem, 6vh, 3rem);
  }

  .case-cta {
    padding-left: var(--gutter);
    padding-right: var(--gutter);
  }

  .shot,
  .shot--half { height: 54svh; }
  .shot--wide { height: 38svh; }

  /* The composition is the layout, at every width. A pair stays a pair on
     a phone: .shot--fit already carries the picture's own ratio, and in a
     pair its flex-grow is that same number, so two frames of any two
     shapes land on one shared height and fill the line exactly. Smaller,
     but a composition, and nothing is ever cropped to make it fit.

     Stacking them full width was the mistake. It turned every frame into
     a full-bleed hero, which forced a crop to keep the page in any kind
     of rhythm, and a crop takes the sides off a poster and the ends off
     the palette. Read as a column of unrelated pictures rather than a
     piece of work laid out. */


}

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



/* the two elements the landing page hands over to */
/* the two elements the landing page hands over to; handoff.js measures
   them on a hidden copy of this page before it animates anything */
.shot__cover {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

