/* ==========================================================================
   VIOGNIER — the frog strikes.   This page only.

   The Viognier engraving is drawn at the end of a movement: the tongue is
   already out, arced across the empty ochre with the pad on the tip.  The
   illustrator drew the last frame, so the animation is simply the half second
   before it — the tongue snaps back into the mouth and fires again, and the
   loop rests in the state the label is actually printed in.

   Nothing was traced and no artwork was redrawn.  The stroke IS the
   photograph: it is cut out of plate.webp along its own outline and carries
   its own pixels, grain and all.  The rectangle it came from is refilled with
   a quadratic surface fitted to the ochre around it, and the cut is hard
   across the stroke and only feathers out beyond it, where the photograph is
   already pure ground and a soft edge therefore costs nothing.  At rest the
   two layers put the label back to within 0.16/255 on average — 16 pixels of
   3630 differ by more than 2, all of them where the tongue meets the jaw.

   Everything is scoped to `.tongue-vio`, a class js/viognier-tongue.js puts on
   the hero plate.  To remove the whole thing: delete the two tags in
   wines/viognier/index.html.
   ========================================================================== */

/* The stage is laid over the drawn photograph, not over the figure's box.
   `.product--bottle` letterboxes its plates (`object-fit: contain`, set in
   product.css:387) because these bottles are cut-outs rather than crops.  So
   the shot is fitted to the box's HEIGHT and centred horizontally, not the
   other way round — the box below reproduces exactly that, which is what lets
   both layers be positioned in per cent of the original file's own
   coordinates.  Getting this backwards puts them on the wordmark. */
.tongue-vio__stage {
  position: absolute;
  left: 50%;
  top: 0;
  height: 100%;
  /* Hidden until js/label-motion.js adds the block's class, which it does
     only once the bottle has finished arriving; after that the veil below
     owns this property and this value never applies again.  The other wines
     hide their own layers instead and do not need it here. */
  opacity: 0;
  aspect-ratio: 560 / 1900;
  transform: translateX(-50%);
  pointer-events: none;
}

/* The eraser.  110 x 33 px of the original 560 x 1900 file — x 272-382,
   y 1437-1470 — expressed in that file's own per cent, so the numbers below
   must stay in step with the crop the images were cut from.  It carries the
   fitted ochre and paints it only where the stroke was. */
.tongue-vio__ground {
  position: absolute;
  left: 48.5714%;
  top: 75.6316%;
  width: 19.6429%;
  height: 1.7368%;
  background: url('../assets/images/wines/viognier/tongue-ground.webp') center / 100% 100% no-repeat;
}

/* The tongue.
   Not a cut-out pasted back on: a second copy of the WHOLE photograph, at
   exactly the size and position of the one beneath it, masked down to the
   stroke.  That distinction is the difference between clean and nearly clean.
   A small cut-out is resampled on its own, so its edge lands a fraction of a
   pixel off the edge underneath and the stroke gets a faint outline at every
   screen size; the full plate resamples identically to the plate below it, so
   at rest the two are the same pixels and there is nothing to see.  Only the
   mask is small, and a soft mask has no edge to misplace.

   Hinged at the mouth (67.5%, 76.5% of the file) so that scaling it draws the
   tongue INTO the head rather than shrinking it where it lies. */
.tongue-vio__ink {
  position: absolute;
  inset: 0;
  background: url('../assets/images/wines/viognier/plate.webp') center / 100% 100% no-repeat;
  -webkit-mask: url('../assets/images/wines/viognier/tongue-mask.webp') 60.4444% 76.9684% / 19.6429% 1.7368% no-repeat;
          mask: url('../assets/images/wines/viognier/tongue-mask.webp') 60.4444% 76.9684% / 19.6429% 1.7368% no-repeat;
  -webkit-mask-mode: alpha;
          mask-mode: alpha;
  transform-origin: 67.5% 76.5%;
  will-change: transform;
}

/* ==========================================================================
   The strike
   ==========================================================================
   One catch every 3s: a beat, the tongue whips back into the mouth, a
   moment closed, then it fires — a little past its printed length — and
   settles onto it.  The rest of the loop is the label exactly as printed, so
   most of the time the bottle is simply the bottle.

   The loop used to be 5.2s.  Only the waiting was shortened: the strike is
   still the same 0.78s it always was, now 26% of the cycle instead of 15%,
   because a catch that takes half as long stops being a catch.

   Each keyframe carries the easing for the segment that FOLLOWS it, which is
   what separates the slow drag back from the snap out; a single easing across
   the whole phrase would make both halves the same speed and it would read as
   a slider rather than a strike. */
@media (prefers-reduced-motion: no-preference) {
  /* The stage is invisible except during the strike.  Outside those 800ms the
     compositor is not asked to put anything over the label at all, so the
     rest state is not a good reconstruction of the photograph — it IS the
     photograph, untouched, and there is no sub-pixel edge to find.  Both
     switches happen on a frame where the tongue is at its printed length, so
     the swap has nothing to show. */
  .tongue-vio .tongue-vio__stage {
    animation: vio-veil var(--tongue-loop, 3s) infinite both;
  }
  .tongue-vio .tongue-vio__ink {
    animation: vio-strike var(--tongue-loop, 3s) infinite both;
  }

  /* Off screen or tab in the background: hold, do not restart. */
  .tongue-vio.is-held .tongue-vio__stage,
  .tongue-vio.is-held .tongue-vio__ink { animation-play-state: paused; }
}

@keyframes vio-veil {
  0%, 4.9%    { opacity: 0; }
  5%, 31%     { opacity: 1; }
  31.1%, 100% { opacity: 0; }
}

@keyframes vio-strike {
  /* printed, waiting */
  0%     { transform: scaleX(1);
           animation-timing-function: cubic-bezier(0.55, 0, 0.85, 0.4); }
  5%     { transform: scaleX(1);
           animation-timing-function: cubic-bezier(0.55, 0, 0.85, 0.4); }
  /* drawn back in — the pad on the tip travels furthest, so it reads as a
     whip rather than a fade */
  12.6%  { transform: scaleX(0.04);
           animation-timing-function: linear; }
  22.3%  { transform: scaleX(0.04);
           animation-timing-function: cubic-bezier(0.08, 0.82, 0.24, 1); }
  /* fired, and past where it is printed */
  26.8%  { transform: scaleX(1.04);
           animation-timing-function: cubic-bezier(0.33, 0, 0.2, 1); }
  /* settled onto the printed length, and there for the rest of the loop */
  31%    { transform: scaleX(1); }
  100%   { transform: scaleX(1); }
}

/* Reduced motion: no class is ever added, so the label simply is what it is
   printed as.  Nothing to switch off. */
