/* ==========================================================================
   shop-motion.css : the motion layer of the shop table (concept-table-v2 §5-§6).
   Loads after shop-table.css on shop listings (inc/enqueue.php). Tokens (--dur-*, --ease-*) live in base.css.
   Nothing here moves on load. Rules of the file:
   - transform, translate and opacity only; no will-change except while a book is turning;
   - the hidden start state of the shelf entrance exists only on tables the script has marked (data-enter="pending"), so with no
     script, with reduced motion, or after the script gives up, everything is visible and in place;
   - shop-motion.js adds html.pil-motion when it runs. Without it the keyframes below (the CSS-only turn) apply.
   ========================================================================== */

/* ---------- 1. The turn ----------
   The book rotates in shop-table.css (transition, 520 / 380ms, --ease-turn, 120ms hover intent). Here:
   the faces darken as they go edge-on (the .face::after overlay, rgba(40,32,20,.28) at full opacity) and the contact
   shadow narrows to scaleX(.16) at the midpoint. With the script, both follow the book's real rotation through
   --pil-shade (0..1) and --pil-sq (.16..1) on the stage. */
html.pil-motion .stage .face::after { opacity: var(--pil-shade, 0); }
/* The hint that the covers turn: once per session the first book half-turns to 32 degrees and back (shop-motion.js sets
   .is-nudge for the way out and removes it for the way back). 260ms out on --ease-standard; the way back is the book's own
   380ms on --ease-turn. The shade and the contact shadow follow the real angle, as in a turn. */
@media (prefers-reduced-motion: no-preference) {
  .stage.is-nudge .book { transform: rotateY(32deg); transition-duration: 260ms; transition-timing-function: var(--ease-standard); }
}
html.pil-motion .stage .contact {
  animation: none !important;                      /* the keyframes below are the fallback for a page without the script */
  transform: translateX(-50%) scaleX(var(--pil-sq, 1));
}
.stage.is-moving .face::after { will-change: opacity; }
.stage.is-moving .contact { will-change: transform; }

/* The fallback: the same two names the first build used, now with the shade, and the midpoint where the book is
   really edge-on (ease-turn puts 90 degrees at 37% of the time). */
@media (prefers-reduced-motion: no-preference) {
  @keyframes pil-turn-a {
    0%, 100% { transform: translateX(-50%) scaleX(1); animation-timing-function: cubic-bezier(.3, 0, .7, 1); }
    37% { transform: translateX(-50%) scaleX(.16); animation-timing-function: cubic-bezier(.3, 0, .7, 1); }
  }
  @keyframes pil-turn-b {
    0%, 100% { transform: translateX(-50%) scaleX(1); animation-timing-function: cubic-bezier(.3, 0, .7, 1); }
    37% { transform: translateX(-50%) scaleX(.16); animation-timing-function: cubic-bezier(.3, 0, .7, 1); }
  }
  @keyframes pil-shade-a { 0%, 100% { opacity: 0; } 37% { opacity: 1; } }
  @keyframes pil-shade-b { 0%, 100% { opacity: 0; } 37% { opacity: 1; } }
  html:not(.pil-motion) .stage.is-turned .face::after { animation: pil-shade-a var(--dur-turn) linear; }
  html:not(.pil-motion) .stage.has-turned:not(.is-turned):not(:hover) .face::after { animation: pil-shade-b var(--dur-return) linear; }
}
@media (prefers-reduced-motion: no-preference) and (hover: hover) and (pointer: fine) {
  html:not(.pil-motion) .stage.has-turned:hover:not(.is-turned) .face::after { animation: pil-shade-a var(--dur-turn) linear var(--dur-intent) both; }
}
/* reduced motion: no shade, no shadow movement (the cross-fade of shop-table.css stays) */
@media (prefers-reduced-motion: reduce) {
  .stage .face::after { animation: none !important; opacity: 0 !important; }
  .stage .contact { animation: none !important; transform: translateX(-50%) !important; }
}

/* The faces, with the script: stage[data-face] (set by shop-motion.js from the book's real angle, past 90 degrees = back)
   decides which face is visible, with no delay, so a hover that leaves before the intent delay, a reversal halfway and a
   keyboard turn can never leave the wrong face drawn. One face visible at any time. The delay-only transitions of
   shop-table.css are the base that works without this file. backface-visibility stays the primary mechanism where it exists. */
@media (prefers-reduced-motion: no-preference) {
  html.pil-motion .stage[data-face] .face { transition: none; }
  html.pil-motion .stage[data-face="front"] .front, html.pil-motion .stage[data-face="back"] .back { visibility: visible; }
  html.pil-motion .stage[data-face="front"] .back, html.pil-motion .stage[data-face="back"] .front { visibility: hidden; }
}

/* ---------- 2. The regroup ----------
   The View Transition (script-started, class html.pil-vt while it runs). One name per cell is set by the script; the
   finder keeps its own name, so it is not part of the cross-fade of the page. */
html.pil-vt::view-transition-group(*) {
  animation-duration: var(--dur-layout);
  animation-timing-function: var(--ease-standard);
}
html.pil-vt::view-transition-old(*):only-child { animation: none; opacity: 0; }
html.pil-vt::view-transition-new(*):only-child {  /* a column that arrives */
  animation: pil-arrive var(--dur-state) var(--ease-decelerate) calc(var(--dur-layout) * .4) both;
}
html.pil-vt::view-transition-group(pil-finder) { animation-duration: 0.001ms; }
@keyframes pil-arrive { from { opacity: 0; } to { opacity: 1; } }

/* ---------- 3. The shelf entrance (tables 2..n) ----------
   Only the books (.book, the unpainted .blank) and their contact shadows: opacity 0 -> 1 and translateY(-16px -> 0),
   --dur-enter, --ease-arrive, 60ms apart in reading order (--si is the column's place in its table, set by the script).
   `translate` is the individual property, so the turn's `transform` is untouched. Opacity goes on the faces, not on
   .book, because opacity on a preserve-3d element would flatten the book while it plays. */
@keyframes pil-settle-y { from { translate: 0 -16px; animation-timing-function: var(--ease-arrive); } to { translate: 0 0; } }
@keyframes pil-settle-o { from { opacity: 0; animation-timing-function: var(--ease-arrive); } to { opacity: 1; } }

@media (prefers-reduced-motion: no-preference) {
  /* played once, by the script, when the row of covers is a third in view (never scrubbed by scroll: a parent who scrolls back up to compare finds the covers there) */
  .shelf-table[data-enter="pending"] :is(.book, .blank) { translate: 0 -16px; }
  .shelf-table[data-enter="pending"] :is(.book > *, .blank, .contact) { opacity: 0; }
  .shelf-table[data-enter="pending"] .stage-blank::before { opacity: 0; }   /* (a pseudo-element cannot sit inside :is()) */
  .shelf-table[data-enter="in"] :is(.book, .blank) {
    animation: pil-settle-y var(--dur-enter) var(--ease-arrive) calc(var(--si, 0) * 60ms) both;
  }
  .shelf-table[data-enter="in"] .book > *, .shelf-table[data-enter="in"] .stage-blank::before {
    animation: pil-settle-o var(--dur-enter) var(--ease-arrive) calc(var(--si, 0) * 60ms) both;
  }
  .shelf-table[data-enter="in"] .blank {
    animation: pil-settle-y var(--dur-enter) var(--ease-arrive) calc(var(--si, 0) * 60ms) both, pil-settle-o var(--dur-enter) var(--ease-arrive) calc(var(--si, 0) * 60ms) both;
  }
  /* the contact shadow: !important only to outrank the fallback switch-off above (animation: none !important) */
  .shelf-table[data-enter="in"] .stage .contact {
    animation: pil-settle-o var(--dur-enter) var(--ease-arrive) calc(var(--si, 0) * 60ms) both !important;
  }
}

@media print {
  .shelf-table[data-enter] :is(.book, .blank, .book > *, .contact) { animation: none !important; opacity: 1 !important; translate: none !important; }
  .shelf-table[data-enter] .stage-blank::before { animation: none !important; opacity: 1 !important; }
}
