/* The stage: one artwork, large, with strands of related art beneath it.
   stage.js moves the artwork (a transform on a spring) and fades what surrounds it; this
   file gives everything its place. The art is the only colour: the one gradient here is the
   picture's own mean colour, washed behind it. */

.stage {
  --stage-art-max: 70vh;
  --stage-tile: 150px;

  position: fixed;
  inset: 0;
  z-index: var(--z-stage);
  overflow-x: hidden;
  overflow-y: auto;
  overscroll-behavior: contain;
  scrollbar-width: thin;
  scrollbar-color: var(--line) transparent;
}

@supports (height: 1dvh) {
  .stage {
    --stage-art-max: 70dvh;
  }
}

@media (min-width: 760px) {
  .stage {
    --stage-art-max: 78vh;
    --stage-tile: 200px;
  }

  @supports (height: 1dvh) {
    .stage {
      --stage-art-max: 78dvh;
    }
  }
}

/* On its way out the stage lets go at once: the wall underneath takes the next touch. */
.stage.is-leaving {
  pointer-events: none;
}

/* The ground is its own layer so it can arrive while the artwork is still travelling. */
.stage-ground {
  position: fixed;
  inset: 0;
  background: var(--ground);
  pointer-events: none;
  will-change: opacity;
}

/* ── close ───────────────────────────────────────────────────────────────── */

.stage-close {
  position: fixed;
  top: calc(var(--safe-top) + var(--s3));
  left: var(--s3);
  z-index: calc(var(--z-stage) + 2);
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  background: var(--material);
  border: 1px solid var(--material-edge);
  -webkit-backdrop-filter: blur(22px) saturate(160%);
  backdrop-filter: blur(22px) saturate(160%);
  color: var(--ink);
  transition: transform 90ms ease-out;
}

.stage-close:active {
  transform: scale(0.94);
}

.stage-close svg,
.stage-action svg,
.stage-strip-go svg {
  width: 22px;
  height: 22px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.5;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* the chevron's weight sits right of its box */
.stage-close svg {
  transform: translateX(-1px);
}

/* ── one artwork: a page ─────────────────────────────────────────────────── */

.stage-page {
  position: relative;
}

/* The page that was here, fading where it stood (stage.js sets its top and width). */
.stage-page.is-ghost {
  position: fixed;
  left: 0;
  pointer-events: none;
}

/* the artwork starts clear of the close button: it is never covered at rest */
.stage-hero {
  padding: calc(var(--safe-top) + 44px + 2 * var(--s3)) var(--s4) 0;
}

.stage-slot {
  position: relative;
  width: min(100%, calc(var(--stage-art-max) * var(--stage-ratio, 1)));
  aspect-ratio: var(--stage-ratio, 1);
  margin-inline: auto;
}

/* The picture's mean colour, strongest (28%) behind it and gone before the next thing. */
.stage-wash {
  position: absolute;
  inset: -26% -40%;
  background: radial-gradient(
    closest-side,
    rgb(var(--stage-mean, 0 0 0) / 0.28) 40%,
    rgb(var(--stage-mean, 0 0 0) / 0.25) 52%,
    rgb(var(--stage-mean, 0 0 0) / 0.18) 64%,
    rgb(var(--stage-mean, 0 0 0) / 0.1) 76%,
    rgb(var(--stage-mean, 0 0 0) / 0.03) 88%,
    rgb(var(--stage-mean, 0 0 0) / 0) 100%
  );
  pointer-events: none;
}

/* Above everything on the page while it travels, under the close button. */
.stage-art {
  position: absolute;
  inset: 0;
  z-index: calc(var(--z-stage) + 1);
  overflow: hidden;
  border-radius: var(--radius-art);
  background-color: var(--ground-raised);
  transform-origin: 0 0;
}

/* While a picture is in the air its layers are kept ready; at rest nothing is promoted. */
.stage-page.is-flying .stage-art {
  will-change: transform;
}

.stage-page.is-flying .stage-below,
.stage-page.is-flying .stage-wash {
  will-change: opacity;
}

.stage-art-inner {
  position: absolute;
  inset: 0;
  transform-origin: 50% 50%;
}

.stage-thumb,
.stage-full {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0;
}

.stage-thumb.is-in,
.stage-full.is-in {
  opacity: 1;
}

/* only a picture that was not in the cache fades; a cached one is simply there */
.stage-thumb.is-late {
  transition: opacity 320ms ease-out;
}

.stage-full {
  transition: opacity 420ms ease-out;
}

/* ── under the artwork ───────────────────────────────────────────────────── */

/* positioned, so it paints over the wash */
.stage-below {
  position: relative;
}

.stage-actions {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--s2);
  margin-top: var(--s3);
  padding-inline: var(--s4);
}

.stage-action {
  flex: none;
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  color: var(--ink-soft);
}

.stage-action:active {
  background: var(--line);
}

.stage-keep[aria-pressed="true"] {
  color: var(--love);
}

.stage-keep[aria-pressed="true"] svg {
  fill: currentColor;
}

/* A chip is 36px to see and 44px to hit. */
.stage-chip {
  position: relative;
  flex: none;
}

.stage-chip::after {
  content: "";
  position: absolute;
  inset: -5px -1px;
}

.stage-below .stage-title {
  max-width: 36rem;
  margin: var(--s2) auto 0;
  padding-inline: var(--s5);
  color: var(--ink-soft);
  text-align: center;
  text-wrap: balance;
}

/* ── strands ─────────────────────────────────────────────────────────────── */

.stage-strands {
  margin-top: var(--s6);
  padding-bottom: calc(96px + var(--safe-bottom));
}

/* positioned, so its arrows can sit over the ends of its strip */
.stage-strand {
  position: relative;
}

.stage-strand + .stage-strand {
  margin-top: var(--s5);
}

.stage-strand-head {
  display: flex;
  align-items: center;
  gap: var(--s3);
  height: 20px;
  margin-bottom: var(--s1);
  padding-inline: var(--s4);
}

.stage-strand-label {
  margin: 0;
}

.stage-swatches {
  display: flex;
  gap: var(--s1);
}

.stage-swatch {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  box-shadow: inset 0 0 0 1px var(--line); /* a near-black colour still reads as a dot */
}

/* Native scrolling, nothing else. The block padding is room for the focus ring. */
.stage-strip {
  display: flex;
  gap: var(--wall-gap);
  margin: 0;
  padding: var(--s1) var(--s4);
  list-style: none;
  overflow-x: auto;
  overflow-y: hidden;
  overscroll-behavior-x: contain;
  scroll-snap-type: x proximity;
  scroll-padding-inline: var(--s4);
  scrollbar-width: none;
}

.stage-strip::-webkit-scrollbar {
  display: none;
}

.stage-strip-item {
  flex: none;
  scroll-snap-align: start;
}

.stage-strip .tile {
  width: calc(var(--stage-tile) * var(--stage-r, 1));
  height: var(--stage-tile);
}

/* "the wall": the way out of a strand, centred on its pictures, a little apart from them */
.stage-strip-end {
  flex: none;
  display: flex;
  align-items: center;
  padding-inline-start: var(--s3);
  scroll-snap-align: end;
}

/* The arrows of a strip: a plain mouse has no other way sideways. Centred on the pictures
   (the strip is the last thing in its strand, with --s1 of padding under them). Only where a
   pointer hovers, at the foot of this file; stage.js marks the one whose end is reached. */
.stage-strip-go {
  position: absolute;
  bottom: calc(var(--s1) + (var(--stage-tile) - 44px) / 2);
  display: none;
  place-items: center;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  background: var(--material);
  border: 1px solid var(--material-edge);
  -webkit-backdrop-filter: blur(22px) saturate(160%);
  backdrop-filter: blur(22px) saturate(160%);
  color: var(--ink);
  opacity: 0;
  pointer-events: none;
  transition: opacity 120ms ease-out, transform 90ms ease-out;
}

.stage-strip-go[data-dir="-1"] {
  left: var(--s3);
}

.stage-strip-go[data-dir="1"] {
  right: var(--s3);
}

.stage-strip-go:active {
  transform: scale(0.94);
}

/* one chevron, turned round for the way on; its weight sits toward its point */
.stage-strip-go[data-dir="-1"] svg {
  transform: translateX(-1px);
}

.stage-strip-go[data-dir="1"] svg {
  transform: translateX(1px) scaleX(-1);
}

@media (min-width: 760px) {
  .stage-strand + .stage-strand {
    margin-top: var(--s6);
  }
}

/* ── print: the shared sheet, lifted above the stage ─────────────────────── */

.sheet-scrim.stage-sheet-scrim {
  z-index: calc(var(--z-stage) + 3);
}

.sheet.stage-sheet {
  z-index: calc(var(--z-stage) + 4);
}

.stage-print {
  padding: var(--s2) 0 var(--s3);
}

.stage-print-label {
  margin-bottom: var(--s4);
}

.stage-size.is-soft {
  color: var(--ink-faint);
}

/* ── helpers ─────────────────────────────────────────────────────────────── */

/* A tile whose picture is in the air: the artwork is the tile until it lands. */
.stage-lifted {
  opacity: 0 !important;
}

/* the field a link is copied from where there is no clipboard API; 16px so iOS does not zoom */
.stage-copy {
  position: fixed;
  top: 0;
  left: 0;
  width: 1px;
  height: 1px;
  padding: 0;
  border: 0;
  font-size: 16px;
  opacity: 0;
  pointer-events: none;
}

@media (hover: hover) and (pointer: fine) {
  .stage-action:hover {
    color: var(--ink);
  }

  .stage-keep[aria-pressed="true"]:hover {
    color: var(--love);
  }

  .stage-strip-go {
    display: grid;
  }

  /* `inherit`, not `auto`: a stage on its way out, or a page fading away, stays untouchable */
  .stage-strand:hover .stage-strip-go:not(.is-spent) {
    opacity: 1;
    pointer-events: inherit;
  }
}

@media (prefers-reduced-motion: reduce) {
  .stage-close,
  .stage-strip-go {
    transition: none;
  }
}

@media (prefers-reduced-transparency: reduce) {
  .stage-close,
  .stage-strip-go {
    background: var(--ground-raised);
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
  }
}

/* the dialog itself can hold the focus (a landing on an artwork): it shows no ring */
.stage:focus {
  outline: none;
}

/* the one way on from a picture */
.stage-buy {
  color: var(--ground);
  background: var(--ink);
  border-color: var(--ink);
  padding: 0 var(--s5);
}
