/* Stage mechanics shared by every variant. Anything with a colour or a
   typeface in it belongs to the variant, not here. */

*,
*::before,
*::after {
  box-sizing: border-box;
}

html,
body {
  height: 100%;
  margin: 0;
  overflow: hidden;
}

body {
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

.deck {
  position: fixed;
  inset: 0;
  overflow: hidden;
  cursor: default;
}

.deck.is-idle {
  cursor: none;
}

/* The content plane. Fixed 1920x1080 so every measurement in a variant is an
   absolute design pixel; scaled to fit by deck.js. Overflow stays visible so
   `.bleed` fills can reach the edges of the screen. */
.stage {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 1920px;
  height: 1080px;
  transform-origin: 50% 50%;
  --bleed-x: 0px;
  --bleed-y: 0px;
}

.slide {
  position: absolute;
  inset: 0;
  display: none;
}

.slide.is-active {
  display: block;
}

/* Fills that must cover the whole screen rather than just the content plane.
   The selector is deliberately two levels deep so it outranks a variant's own
   `inset: 0` without needing !important. */
.slide .bleed {
  top: calc(-1 * var(--bleed-y));
  right: calc(-1 * var(--bleed-x));
  bottom: calc(-1 * var(--bleed-y));
  left: calc(-1 * var(--bleed-x));
}

.slide .bleed-y {
  top: calc(-1 * var(--bleed-y));
  bottom: calc(-1 * var(--bleed-y));
}

.slide .bleed-l { left: calc(-1 * var(--bleed-x)); }
.slide .bleed-r { right: calc(-1 * var(--bleed-x)); }

/* Photographs are placed with an object-fit cover layer so a variant only has
   to position the frame, never the image inside it. */
.photo {
  position: absolute;
  inset: 0;
  overflow: hidden;
}

.photo img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* The graded copy sits on top of the colour one; fading it out is how a
   photograph "arrives in colour" without animating a filter. */
.photo__grade {
  will-change: opacity;
}

/* Layers that animate are promoted once, up front, rather than being promoted
   and demoted on every transition. */
.slide .bleed,
.photo,
.deck-progress {
  backface-visibility: hidden;
}

.deck-chrome {
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 50;
}

.deck-progress {
  position: absolute;
  left: calc(-1 * var(--bleed-x));
  right: calc(-1 * var(--bleed-x));
  bottom: calc(-1 * var(--bleed-y));
  height: 3px;
  transform: scaleX(0);
  transform-origin: 0 50%;
}

/* Nothing is counted on the title: the number and the progress bar are for a
   deck already running, and on the opening sheet they read as stray marks. */
.deck[data-slide='title'] .deck-counter,
.deck[data-slide='title'] .deck-progress {
  display: none;
}

/* Covers the stage for the first moment so the deck fades up out of its own
   ground colour rather than snapping into the opening animation. */
.deck-opening {
  position: fixed;
  inset: 0;
  z-index: 90;
  pointer-events: none;
}

/* A picture opened full size, with its caption kept. Colours come from the
   variant through --zoom-veil; everything else is the stage's own type. */
.deck-zoom {
  position: absolute;
  inset: 0;
  z-index: 80;
  display: none;
}

.deck-zoom.is-open {
  display: block;
}

.deck-zoom__backdrop {
  position: absolute;
  top: calc(-1 * var(--bleed-y));
  right: calc(-1 * var(--bleed-x));
  bottom: calc(-1 * var(--bleed-y));
  left: calc(-1 * var(--bleed-x));
  background: var(--zoom-veil, #fafafa);
  cursor: pointer;
}

/* The pictures live in one strip inside a fixed window, so stepping to the
   next one is a single slide rather than a fade between two loose images. */
.deck-zoom__window {
  position: absolute;
  left: 370px;
  top: 176px;
  width: 1180px;
  height: 620px;
  overflow: hidden;
}

.deck-zoom__track {
  display: flex;
  gap: 80px;
  height: 100%;
}

.deck-zoom__cell {
  flex: none;
  width: 1180px;
  height: 620px;
}

.deck-zoom__cell img {
  width: 100%;
  height: 100%;
  object-fit: contain;
  display: block;
}

/* The single image that travels between the slide and the window. Its resting
   frame has the picture's own proportions, so the hand-over to the strip is
   seamless. */
.deck-zoom__flyer {
  position: absolute;
  display: none;
  object-fit: cover;
  will-change: left, top, width, height, border-radius;
}

.deck-zoom__caption {
  position: absolute;
  left: 50%;
  top: 838px;
  transform: translateX(-50%);
  width: 1180px;
  text-align: center;
}

.deck-zoom__years {
  display: block;
  font-size: 38px;
  line-height: 1.1;
}

.deck-zoom__name {
  display: block;
  margin: 12px auto 0;
  max-width: 900px;
  font-size: 21px;
  font-weight: 300;
  line-height: 1.5;
  opacity: 0.66;
}

[data-zoom] {
  cursor: zoom-in;
}

/* B / W blank the screen without leaving the slide. */
.deck-curtain {
  position: fixed;
  inset: 0;
  z-index: 100;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.28s ease;
}

.deck[data-curtain='black'] .deck-curtain {
  background: #000;
  opacity: 1;
}

.deck[data-curtain='white'] .deck-curtain {
  background: #fff;
  opacity: 1;
}
