/* ---------- VIEWS ----------
   The stage holds four ways of seeing the same ten experiences. One is
   shown at a time; the toggle, bottom right, switches. Each view owns its
   own section and its own stylesheet under css/views/. */
.stage {
  position: relative;
  margin-inline: calc(-1 * var(--gutter));
  min-height: 100vh;
  min-height: 100dvh;
}

/* A slot is where a card should be: an empty 4:3 box in the flow of a page.
   The engine flies the card into it and keeps it there while you scroll. */
.slot {
  width: 100%;
  aspect-ratio: 4 / 3;
}

/* ---------- CANVAS ---------- */
.canvas__wall {
  max-width: var(--frame-max);
  margin-inline: auto;
  padding: calc(env(safe-area-inset-top, 0px) + 110px) calc(var(--gutter) + 54px) calc(env(safe-area-inset-bottom, 0px) + 200px) var(--gutter);
  display: flex;
  align-items: flex-start;
  gap: 34px;
}
.canvas__col { flex: 1 1 0; display: grid; gap: 34px; will-change: transform; }
/* The columns start at different heights, so the wall never lines up in rows. */
.canvas__col:nth-child(2) { margin-top: 74px; }
.canvas__col:nth-child(3) { margin-top: 28px; }

/* The years, down the side: where you are, and a way to anywhere. */
.canvas__years {
  position: fixed;
  right: max(10px, calc(var(--gutter) - 14px));
  top: 50%;
  transform: translateY(-50%);
  z-index: 1550;
  display: grid;
  gap: 2px;
  justify-items: end;
}
.canvas__year {
  appearance: none;
  border: 0;
  background: none;
  font: inherit;
  font-size: 12px;
  letter-spacing: 0.02em;
  line-height: 20px;
  padding: 0 4px;
  color: var(--text-faint, #9b99a8);
  cursor: pointer;
  opacity: 0.55;
  transition: opacity 160ms ease, color 160ms ease, transform 160ms ease;
}
.canvas__year:hover { opacity: 1; color: var(--text-strong); }
.canvas__year[aria-current="true"] {
  opacity: 1;
  color: var(--text-strong);
  transform: translateX(-3px);
  font-weight: 500;
}
@media (max-width: 900px) {
  .canvas__wall { gap: 18px; padding-inline: var(--gutter) calc(var(--gutter) + 40px); }
  .canvas__col { gap: 18px; }
  .canvas__col:nth-child(2) { margin-top: 42px; }
  .canvas__col:nth-child(3) { display: none; }
}
@media (max-width: 560px) {
  .canvas__wall { padding-top: 96px; gap: 14px; }
  .canvas__col { gap: 14px; }
  .canvas__col:nth-child(2) { margin-top: 26px; }
  .canvas__year { font-size: 11px; line-height: 18px; }
}
@media (prefers-reduced-motion: reduce) {
  .canvas__col { transform: none !important; }
}

/* ---------- PROJECT ---------- */
.project {
  max-width: var(--frame-max);
  margin-inline: auto;
  padding: calc(env(safe-area-inset-top, 0px) + 110px) var(--gutter) calc(env(safe-area-inset-bottom, 0px) + 160px);
  display: grid;
  gap: 26px;
}
/* One measure for everything on a project page: pictures, title and text
   share a 640px column, so on a wide screen the pictures read as part of
   the page rather than a hero. */
.project__head,
.project__prose { max-width: 640px; margin-inline: auto; width: 100%; }
.project .slot {
  --ar: 1.3333;
  width: min(100%, 640px, calc(68vh * var(--ar)));
  aspect-ratio: var(--ar);
  margin-inline: auto;
}
.project .slot--gallery { max-width: none; width: 100%; }
.project__head { padding-bottom: clamp(34px, 7vh, 64px); }
.project__head .t-title {
  font-size: 30px;
  line-height: 36px;
  letter-spacing: -0.4px;
  font-weight: 500;
}
.project__head { display: grid; gap: 6px; }

/* The reading column: one measure, centred, paragraphs a breath apart. */
.project__prose {
  /* Close under the picture it belongs to, open before the next one — and the
     gap below clears the next picture's halo. */
  padding-block: 4px 64px;
  display: grid;
  gap: 20px;
}
.project__prose { will-change: transform, opacity; }

/* The strip: the pictures that did not fit the story, side by side,
   snapping as you scroll sideways. The cards float over it. */
/* Everything the story did not carry, as a mosaic: the whole set is there to
   scroll past, and every so often one picture takes a wider cell so the grid
   keeps a rhythm instead of reading as a contact sheet. */
.project__gallery {
  width: 100%;
  max-width: 1120px;
  margin: 22px auto 0;
  padding-inline: var(--gutter);
  display: flex;
  align-items: flex-start;
  gap: 20px;
}
.project__gallery-col { flex: 1 1 0; display: grid; gap: 20px; }
.project .slot--gallery { margin: 0; }
@media (max-width: 900px) { .project__gallery, .project__gallery-col { gap: 14px; } }
body.in-project .cards .card { touch-action: pan-x pan-y; }
.project__text {
  margin: 0;
  font-size: 18px;
  line-height: 1.65;
  letter-spacing: 0.005em;
  color: var(--text-body);
  text-wrap: pretty;
}
@media (max-width: 720px) {
  /* The same pairing on a phone, at a phone's scale. */
  .project { gap: 18px; padding-top: 96px; }
  .project__prose { padding-block: 2px 44px; gap: 16px; }
  .project__text { font-size: 17px; }
  .project__head .t-title { font-size: 24px; line-height: 30px; }
  .project .slot { width: min(100%, 640px, calc(62vh * var(--ar))); }
}
.view {
  position: relative;
  width: 100%;
  min-height: 100vh;
  min-height: 100dvh;
  /* Only the chrome of a view fades across a switch — the wheel, the words, the
     grid. The pictures live in their own layer and keep flying underneath. */
  animation: view-in 420ms var(--ease-out) both;
}
.view[hidden] { display: none; }
.view.is-leaving { animation: view-out 200ms var(--ease-out) both; pointer-events: none; }
@keyframes view-in { from { opacity: 0; } to { opacity: 1; } }
@keyframes view-out { from { opacity: 1; } to { opacity: 0; } }

/* The page arrives: its title and its words rise into place while the pictures
   are still on their way. */
.project__head { animation: page-rise 620ms var(--ease-out) both; }
@keyframes page-rise {
  from { opacity: 0; transform: translate3d(0, 12px, 0); }
  to { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce) {
  .view, .view.is-leaving, .project__head { animation: none; }
}

/* The toggle: a glass pill like the header. At rest it shows only the
   current mode; on hover (or keyboard focus) the other three unfold to its
   left. Right-anchored, so it grows leftward. */
.view-toggle {
  position: fixed;
  right: var(--gutter);
  bottom: calc(env(safe-area-inset-bottom, 0px) + 28px);
  z-index: 2000;
  display: flex;
  align-items: center;
  padding: 7px 16px;
  border-radius: 999px;
  background: var(--glass-chrome);
  box-shadow:
    inset 0 1px 0 var(--glass-top),
    inset 0 0 0 1px var(--glass-line),
    0 1px 2px rgba(23, 21, 43, 0.05),
    0 18px 40px -20px var(--glass-shadow);
}
body.in-project .view-toggle { display: none; }
.view-toggle button {
  font: inherit;
  font-size: 14px;
  line-height: 20px;
  letter-spacing: 0.01em;
  color: var(--text-body);
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
  white-space: nowrap;
  overflow: hidden;
  max-width: 0;
  margin: 0;
  opacity: 0;
  transition:
    max-width 0.5s var(--ease-out),
    margin 0.5s var(--ease-out),
    opacity 0.3s var(--ease-out),
    color var(--dur-fast, 120ms) var(--ease-out);
}
.view-toggle button[aria-pressed="true"] {
  color: var(--text-strong);
  font-weight: 500;
  max-width: 120px;
  opacity: 1;
}
.view-toggle:hover button,
.view-toggle:focus-within button {
  max-width: 120px;
  opacity: 1;
  margin-left: 18px;
}
.view-toggle:hover button:first-child,
.view-toggle:focus-within button:first-child { margin-left: 0; }
.view-toggle button:hover,
.view-toggle button:focus-visible { color: var(--text-strong); }
.view-toggle button:focus-visible { outline: none; box-shadow: 0 0 0 3px var(--focus-ring); border-radius: 6px; }

@media (max-width: 720px) {
  .view-toggle { padding: 7px 14px; }
  .view-toggle:hover button, .view-toggle:focus-within button { margin-left: 14px; }
}

/* ---------- PLAYER ----------
   A film card flies into this frame (the engine targets .player__slot) and
   the video fades in on top of it. The frame is 16:9, as wide as fits. */
.player {
  position: fixed;
  inset: 0;
  z-index: 1400;                       /* under the cards (1500): the card IS the frame */
  display: grid;
  place-items: center;
  padding: calc(env(safe-area-inset-top, 0px) + 72px) var(--gutter) calc(env(safe-area-inset-bottom, 0px) + 72px);
  background: var(--scrim);
  opacity: 0;
  transition: opacity 0.4s var(--ease-out);
}
.player[hidden] { display: none; }
body.is-playing .player { opacity: 1; }
.player__frame {
  width: min(100%, 1040px, calc((100dvh - 144px) * 16 / 9));
  aspect-ratio: 16 / 9;
}
/* A still is looked at in the same frame, in its own shape. */
.player.is-photo { padding-block: calc(env(safe-area-inset-top, 0px) + 68px) calc(env(safe-area-inset-bottom, 0px) + 96px); }
.player.is-photo .player__frame {
  width: min(100%, 1180px, calc((100dvh - 164px) * 4 / 3));
  aspect-ratio: 4 / 3;
}
.player__nav {
  position: fixed;
  top: 50%;
  translate: 0 -50%;
  z-index: 2100;
  width: 44px; height: 44px;
  display: grid; place-items: center;
  border: 0; border-radius: 999px;
  color: var(--text-strong);
  background: var(--glass-chrome);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.95), inset 0 0 0 1px rgba(255, 255, 255, 0.6), 0 1px 2px rgba(23, 21, 43, 0.05), 0 18px 40px -20px rgba(23, 21, 43, 0.22);
  cursor: pointer;
  pointer-events: auto;
  opacity: 0.9;
  transition: opacity 160ms ease;
}
.player__nav:hover { opacity: 1; }
.player__nav[hidden] { display: none; }
.player__nav--prev { left: var(--gutter); }
.player__nav--next { right: var(--gutter); }
.player__nav:focus-visible { outline: none; box-shadow: 0 0 0 3px var(--focus-ring); }
.player__label {
  position: fixed;
  left: 50%;
  translate: -50% 0;
  bottom: calc(env(safe-area-inset-bottom, 0px) + 26px);
  z-index: 2100;
  margin: 0;
  max-width: min(680px, calc(100vw - 2 * var(--gutter)));
  text-align: center;
  font-size: 13px;
  line-height: 20px;
  color: var(--text-body);
  opacity: 0;
  transition: opacity 0.35s var(--ease-out);
}
.player__label[hidden] { display: none; }
body.is-playing .player__label { opacity: 1; }
.player__label b { font-weight: 500; color: var(--text-strong); }
.player__label span { color: var(--text-faint, #9b99a8); }
@media (max-width: 620px) {
  .player__nav { width: 38px; height: 38px; }
  .player__nav--prev { left: 8px; }
  .player__nav--next { right: 8px; }
}
.player__slot { width: 100%; height: 100%; position: relative; }
/* The video itself, in its own layer above the cards, matched to the slot. */
.player__video {
  position: fixed;
  z-index: 1700;
  padding: 6px;                        /* inside the card's glass rim */
  opacity: 0;
  transition: opacity 0.5s var(--ease-out);
  pointer-events: none;
}
.player__video[hidden] { display: none; }
.player__video.is-on { opacity: 1; pointer-events: auto; }
.player__video iframe {
  display: block;
  width: 100%;
  height: 100%;
  border: 0;
  border-radius: 15px;
  background: #000;
}
.player__ui { position: fixed; inset: 0; z-index: 2100; pointer-events: none; }
.player__ui[hidden] { display: none; }
.player__ui .player__close { pointer-events: auto; }
.player__close {
  position: fixed;
  top: calc(env(safe-area-inset-top, 0px) + 14px);
  right: var(--gutter);
  z-index: 2100;
  width: 40px; height: 40px;
  display: grid; place-items: center;
  border: 0; border-radius: 999px;
  color: var(--text-strong);
  background: var(--glass-chrome);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.95), inset 0 0 0 1px rgba(255, 255, 255, 0.6), 0 1px 2px rgba(23, 21, 43, 0.05), 0 18px 40px -20px rgba(23, 21, 43, 0.22);
  cursor: pointer;
}
.player__close:focus-visible { outline: none; box-shadow: 0 0 0 3px var(--focus-ring); }
body.is-playing .site-header, body.is-playing .close, body.is-playing .view-toggle, body.is-playing .cloud__caption, body.is-playing .canvas__years { opacity: 0; pointer-events: none; transition: opacity 0.3s var(--ease-out); }
