/*
  Shared mechanics for both versions: the poster board, the turning
  pieces, the card file and the card index frame. Each world sets the
  custom properties below and dresses everything else.
*/

:root {
  --ease-out: cubic-bezier(.16, 1, .3, 1);
  --flip-time: .6s;
  --focus: #1d63a8;
  --piece-shadow: 0 10px 18px -4px rgb(10 12 20 / .5);
  --card-edge: #fff;
}

*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; text-size-adjust: 100%; scroll-behavior: smooth; }
body { margin: 0; }
img { display: block; max-width: 100%; }
button { font: inherit; color: inherit; }
h1, h2, h3, p, figure, dl, dd, blockquote { margin: 0; }
[hidden] { display: none !important; }

.vh {
  position: absolute !important;
  width: 1px; height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

.skip {
  position: absolute; left: 16px; top: -100px; z-index: 100;
  padding: 12px 18px;
  background: #fff; color: #000;
}
.skip:focus { top: 16px; }

/* ---------- Poster board ---------- */

.board {
  position: relative;
  display: grid;
  grid-template-columns: repeat(6, 1fr);
  grid-template-rows: repeat(11, 1fr);
  aspect-ratio: 8.4 / 11;      /* 6 cards of 1.4:1 across, 11 down */
  width: 100%;
  isolation: isolate;
  /* The whole poster sits behind the pieces, so sub-pixel seams between them never show the frame. */
  background: url(../img/poster.jpg) 0 0 / 100% 100% no-repeat;
}

.piece {
  position: relative;
  z-index: 1;
  display: block;
  outline: none;
  -webkit-tap-highlight-color: transparent;
  /* Stay on top while settling back, then drop into place. */
  transition: z-index 0s .25s;
}

.piece-lift,
.piece-flip,
.face { position: absolute; inset: 0; }

/* Hover only raises a piece a little, so the cursor can travel across the
   poster without one card covering its neighbours. The shadow sits on its
   own layer and fades, which is far cheaper than animating a filter. */
.piece-lift { transition: transform .28s var(--ease-out); }
.piece-lift::after {
  content: "";
  position: absolute;
  inset: 0;
  box-shadow: var(--piece-shadow);
  opacity: 0;
  pointer-events: none;
  transition: opacity .28s var(--ease-out);
}

.piece-flip {
  transform: perspective(900px) scale(1) rotateZ(0deg) rotateY(0deg);
  transform-style: preserve-3d;
  transition: transform var(--flip-time) var(--ease-out);
}

.face {
  overflow: hidden;
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
}

.face-jigsaw {
  background-image: url(../img/poster.jpg);
  background-size: 600% 1100%;
  background-repeat: no-repeat;
}

.face-picture {
  transform: rotateY(180deg);
  background: var(--card-edge);
}
.face-picture img {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
}
/* An upright picture lies sideways on its landscape card. */
.piece.is-portrait .face-picture img {
  inset: auto; left: 50%; top: 50%;
  width: 71.4286%; height: 140%;
  transform: translate(-50%, -50%) rotate(90deg);
}

.piece-num {
  position: absolute; left: 6%; top: 6%;
  z-index: 2;
  pointer-events: none;
  opacity: 0;
  transition: opacity .3s var(--ease-out);
}
.board.show-numbers .piece-num { opacity: 1; }

/* Every card turned picture side up, in a wave from 1 to 66. */
.board.is-turned .piece-flip {
  transform: perspective(900px) scale(1) rotateZ(0deg) rotateY(180deg);
}
.board.is-turning .piece-flip {
  transition-delay: calc(var(--i) * 16ms);
}

/* Raised: a small lift and a soft shadow. */
@media (hover: hover) and (pointer: fine) {
  .board .piece:hover { z-index: 30; transition-delay: 0s; }
  .board .piece:hover .piece-lift { transform: translateY(-3px) scale(1.08); }
  .board .piece:hover .piece-lift::after { opacity: 1; }
}
.board .piece:focus-visible { z-index: 30; transition-delay: 0s; }
.board .piece:focus-visible .piece-lift { transform: translateY(-3px) scale(1.08); }
.board .piece:focus-visible .piece-lift::after { opacity: 1; outline: 3px solid var(--focus); outline-offset: 2px; }
/* The piece being opened stays raised until the card has flown out of it. */
.board .piece.is-source { visibility: hidden; }

/* The card that flies from the poster into its page. */
.file-card.flyer {
  position: fixed;
  z-index: 10;
  margin: 0;
  pointer-events: none;
  filter: drop-shadow(0 24px 30px rgb(10 12 20 / .35));
}

/* ---------- Card index frame ---------- */

.index {
  list-style: none;
  margin: 0; padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 210px), 1fr));
}
.index-card {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  column-gap: 10px;
  align-items: baseline;
  text-decoration: none;
  color: inherit;
}
.index-frame {
  grid-column: 1 / -1;
  display: grid;
  place-items: center;
  aspect-ratio: 1 / 1;
}
.index-frame img {
  width: 100%; height: auto;
  transition: transform .45s var(--ease-out), box-shadow .45s var(--ease-out);
}
.index-card.is-portrait .index-frame img { width: auto; height: 100%; }

/* ---------- Card file (one card, both sides) ---------- */

.file {
  --L: min(500px, 64vh, calc(100vw - 48px));
  padding: 0; border: 0;
  max-width: none; max-height: none;
  overscroll-behavior: contain;
}
.file::backdrop { background: rgb(8 10 16 / .72); }
.file[open]::backdrop { animation: file-fade .32s var(--ease-out); }
.file[open] .file-sheet { animation: file-fade .32s var(--ease-out); }
@keyframes file-fade { from { opacity: 0; } }
.file-sheet { min-height: 100%; }

.file-stage {
  display: grid;
  place-items: center;
  width: var(--L);
  height: var(--L);
}

.file-card {
  position: relative;
  width: var(--L);
  aspect-ratio: 1.4 / 1;
  padding: 0; border: 0;
  background: none;
  cursor: pointer;
  filter: drop-shadow(0 18px 24px rgb(10 12 20 / .3));
  transition: width .5s var(--ease-out);
}
.file-card.is-portrait {
  width: calc(var(--L) / 1.4);
  aspect-ratio: 1 / 1.4;
}

.file-card-flip {
  position: absolute; inset: 0;
  transform-style: preserve-3d;
  transform: perspective(1600px) rotateZ(0deg) rotateY(0deg);
  transition: transform .8s var(--ease-out);
}
.file-card.is-turned .file-card-flip {
  transform: perspective(1600px) rotateZ(0deg) rotateY(180deg);
}
/* An upright card turns over and swings sideways so the jigsaw piece reads the right way up. */
.file-card.is-portrait.is-turned .file-card-flip {
  transform: perspective(1600px) rotateZ(90deg) rotateY(180deg);
}

.file-card .face-picture { transform: none; }
.file-card .face-picture img {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: contain;
  transform: none;
}
.file-card .face-back { transform: rotateY(180deg); background: var(--card-edge); }
.file-card .face-jigsaw {
  position: absolute;
  inset: 0;
}
.file-card.is-portrait .face-jigsaw {
  inset: auto; left: 50%; top: 50%;
  width: 140%; height: 71.4286%;
  transform: translate(-50%, -50%) rotate(-90deg);
}

.file.is-dutch .file-actions [data-action="turn"] { display: none; }
.file-card:disabled { cursor: default; }

.locator { position: relative; aspect-ratio: 8.4 / 11; }
.locator img { width: 100%; height: 100%; }
.locator-mark {
  position: absolute;
  width: calc(100% / 6);
  height: calc(100% / 11);
  transition: left .45s var(--ease-out), top .45s var(--ease-out);
}

/* ---------- The wrapper turns round ---------- */

.wrapper-figure img { transition: transform .9s var(--ease-out); }
.wrapper-figure.is-turned img { transform: rotate(180deg); }

/* ---------- Reduced motion: same states, no travel ---------- */

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .piece-lift, .piece-flip, .file-card-flip, .file-card,
  .wrapper-figure img, .index-frame img, .locator-mark {
    transition-duration: .01s !important;
    transition-delay: 0s !important;
  }
}
