/* ── Live thumbnail ────────────────────────────────────────────────────────
   A card thumbnail that is the real page running in an iframe, not a picture
   of it. Screenshots drift the moment the page is edited; an instance cannot.

   Markup:
     <span class="lt-frame" data-src="/sneak/mike/?slide=variety&thumb=1"></span>

   assets/live-thumb.js creates the iframe only when the card nears the
   viewport, then scales it. Nothing loads if the visitor never scrolls there.

   The iframe renders at a fixed LT_W x LT_H logical size and is scaled down,
   so the embedded page keeps its desktop layout. Let it render at card width
   instead and the slide trips its own breakpoint: the Mike's page swaps its
   CTA to "open on a desktop" below ~900px.
*/
.lt-frame {
  display: block;
  position: relative;
  aspect-ratio: 16 / 10;
  overflow: hidden;
  background: #000;
}
.lt-poster {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
/* The poster STAYS, and can, now that the iframe is fully opaque: an opaque
   iframe covers it completely, so there is nothing to ghost against. Hiding it
   on the load event was wrong twice over. Load fires before the embedded page
   has booted Swiper and painted, so every card flashed black on the way in, and
   a reclaimed iframe left nothing behind it. Leaving it there means the card
   always has something to show. */
/* The iframe sits over the poster and hides it once it has actually painted.
   Until then, and again if it is torn down, the poster is what shows. */
.lt-frame iframe {
  position: absolute;
  z-index: 1;
  top: 0;
  left: 0;
  width: 1300px;
  height: 812px;
  border: 0;
  display: block;
  transform-origin: 0 0;
  /* Do NOT promote this to its own layer. Both will-change: transform and
     backface-visibility: hidden were tried: the first spread the shimmer, the
     second softened it, because a promoted layer is rasterised at the full
     1300px and then bilinear-scaled down to card size. Left alone, the browser
     rasterises at the size it actually paints and stays sharp. The flicker was
     the translucency, not the scale. */
  /* the card is the link; the iframe must never swallow the click */
  pointer-events: none;
  background: #000;
}
/* The dimming used to be opacity on the iframe itself, which means the browser
   alpha-composites a whole moving page every frame. A static veil over the top
   costs one flat layer instead and looks identical. */
.lt-frame::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: none;
  background: rgba(0, 0, 0, .22);
  transition: opacity .35s ease;
}
a:hover .lt-frame::before,
.lt-frame:hover::before { opacity: 0; }
/* Until the iframe exists the box is flat black, which reads as a broken card.
   A faint pulse says "loading" without shipping a spinner. */
/* Only when there is nothing else to look at. With a poster behind it the
   pulse just dirties a picture that is already there. */
.lt-frame:not(.is-live):not(.has-poster)::after {
  content: "";
  position: absolute;
  inset: 0;
  background: radial-gradient(120% 90% at 50% 45%, rgba(240, 234, 220, 0.06), transparent 70%);
  animation: ltPulse 1.6s ease-in-out infinite;
}
@keyframes ltPulse { 0%, 100% { opacity: 0.45 } 50% { opacity: 1 } }
@media (prefers-reduced-motion: reduce) {
  .lt-frame:not(.is-live):not(.has-poster)::after { animation: none; }
}
