/* The wall: the ranking as a masonry.
   wall.js seats every picture (an explicit size and a transform); this file gives the wall
   its ground, the travel between two rankings, and the heart a mouse finds on a tile. */

.wall {
  /* 52px above for the mark, 120px below for the dock */
  padding: calc(var(--safe-top) + 52px) var(--wall-pad) calc(var(--safe-bottom) + 120px);
}

/* .wall-top belongs to the pair row. It gets nothing here: empty, it takes no room. */

.wall-grid {
  position: relative;
  column-gap: var(--wall-gap); /* nothing is laid out by it: wall.js reads the gap from here */
  contain: layout; /* a picture fading out past the end never stretches the page */
}

.wall-item {
  position: absolute;
  top: 0;
  left: 0;
  overflow-anchor: none; /* a picture changing seats must never drag the scroll with it */
  transition: opacity 180ms ease-out;
}

.wall-item > .tile {
  width: 100%;
  height: 100%;
}

/* Between two rankings the pictures that stay travel to their new seats. Nobody is holding
   a tile while that happens, so a transition is the right tool. */
.wall-grid.is-flowing > .wall-item {
  transition: transform 460ms cubic-bezier(0.22, 1, 0.36, 1), opacity 180ms ease-out;
}

.wall-item.is-leaving {
  opacity: 0;
  pointer-events: none;
}

.wall-item.is-entering {
  animation: wall-in 240ms ease-out backwards;
}

@keyframes wall-in {
  from {
    opacity: 0;
  }
}

/* comes near the viewport: time for more */
.wall-end {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 1px;
  overflow-anchor: none;
  pointer-events: none;
}

.wall-grid.is-empty {
  display: grid;
  place-items: center;
  min-height: 50dvh;
}

.wall-empty {
  margin: 0;
  color: var(--ink-soft);
  text-align: center;
  animation: wall-in 240ms ease-out;
}

/* ── the heart: only where a pointer can hover; touch keeps pictures on the stage ── */

.wall-keep {
  display: none;
}

@media (hover: hover) and (pointer: fine) {
  /* 44px to hit, 36px to see, the same 8px from the corner as the kept dot */
  .wall-keep {
    position: absolute;
    top: var(--s1);
    right: var(--s1);
    display: grid;
    place-items: center;
    width: 44px;
    height: 44px;
    border-radius: 50%;
    color: var(--ink);
    visibility: hidden;
    transition: visibility 0s linear 140ms;
  }

  .wall-keep::before {
    content: "";
    position: absolute;
    inset: 4px;
    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%);
  }

  .wall-keep svg {
    position: relative;
    width: 18px;
    height: 18px;
    fill: none;
    stroke: currentColor;
    stroke-width: 1.6;
    stroke-linecap: round;
    stroke-linejoin: round;
  }

  /* The fade sits on the two parts, not on the button: a faded parent would cut the
     material off from the picture it blurs. */
  .wall-keep::before,
  .wall-keep svg {
    opacity: 0;
    transition: opacity 140ms ease-out, transform 90ms ease-out;
  }

  /* Hover, or the keyboard inside the tile. Not plain :focus-within - a mouse click would
     leave the heart standing on a tile the pointer has left. */
  .wall-item:is(:hover, :has(:focus-visible)) > .wall-keep {
    visibility: visible;
    transition-delay: 0s;
  }

  .wall-item:is(:hover, :has(:focus-visible)) > .wall-keep::before,
  .wall-item:is(:hover, :has(:focus-visible)) > .wall-keep svg {
    opacity: 1;
  }

  .wall-keep:active svg {
    transform: scale(0.86);
  }

  .wall-keep[aria-pressed="true"] svg {
    fill: var(--love);
    stroke: var(--love);
  }

  /* the ring follows what is seen, not the hit area */
  .wall-keep:focus-visible {
    outline: none;
  }

  .wall-keep:focus-visible::before {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
  }
}

@media (prefers-reduced-motion: reduce) {
  /* no travel: what moved fades in at its new seat (wall.js) */
  .wall-grid.is-flowing > .wall-item {
    transition: opacity 180ms ease-out;
  }
}

@media (prefers-reduced-transparency: reduce) {
  .wall-keep::before {
    background: var(--ground-raised);
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
  }
}

/* on a phone the mark has the top line to itself; the call's bar sticks beneath it */
@media (max-width: 759px) {
  .wall > .call-bar {
    top: calc(var(--safe-top) + 46px);
  }
}
