/* ===========================================================================
   preview.css — the specification index's cursor-following product preview

   ONE reused <img class="preview">, created by js/preview.js and appended to
   <body>. It is not a cursor: no ring, no dot, no blend-difference disc. It is
   the product photograph for the row the pointer is resting on, and it exists
   only while a fine pointer is over a row of `table.index`.

   Division of labour, so the two halves never fight:
     JS  owns  `translate` and `scale`  — written per frame from two Dampers,
               on the shared clock, never a private requestAnimationFrame.
     CSS owns  `opacity`                — the enter / leave fade, on tokens.

   Nothing here hardcodes a colour or a duration; every value is a token from
   tokens.css.                                                              */

.preview{
  position: fixed;
  left: 0;
  top: 0;

  /* Not cqw: the floater lives on <body>, outside the card's container. */
  width: clamp(148px, 15vw, 248px);
  aspect-ratio: 1;                 /* JS overrides per asset (w / h) */
  height: auto;
  object-fit: cover;

  /* The card's own photo-panel treatment: 2px, not 0 and not 20px, plus the
     1px inner hairline every photo panel on this site carries. */
  border-radius: 2px;
  background-color: var(--plate-seal);
  box-shadow:
    inset 0 0 0 1px var(--panel-edge),
    0 2px 6px rgba(27, 29, 33, 0.10),
    0 18px 46px rgba(27, 29, 33, 0.22);

  /* Starting state. `translate` and `scale` are the individual properties, so
     JS can write each one without ever composing a transform string. */
  translate: 0 0;
  scale: 0.9;
  opacity: 0;

  /* It must never intercept the row's own link, hover or drag. */
  pointer-events: none;
  user-select: none;
  -webkit-user-drag: none;

  /* Above the card (2), below the sacrificial sheet (4), the menu overlay (5)
     and the skip link (10). */
  z-index: 3;

  transition: opacity var(--d-pill-out) var(--e-fall);
}

.preview.is-on{
  opacity: 1;
  /* Promoted only while it is actually travelling. */
  will-change: translate, scale;
  transition: opacity var(--d-row) var(--e-lay);
}

/* ===== reduced motion ======================================================
   §8: no travel and no scale — a plain opacity fade, in place. preview.js
   stops writing `translate` (it parks the image once, where the pointer was)
   and clears its inline `scale`; the !important below is the belt to that
   brace, so a mid-session change of the media query cannot leave a stale
   inline scale on the element.                                             */

@media (prefers-reduced-motion: reduce){
  .preview{
    scale: 1 !important;
    transition: opacity var(--d-row) linear;
  }
  .preview.is-on{
    will-change: auto;
    transition: opacity var(--d-row) linear;
  }
}

/* A coarse pointer never gets one — preview.js does not even create the
   element there. This is only a second lock on the same door. */
@media (hover: none), (pointer: coarse){
  .preview{ display: none }
}
