/* ==========================================================================
   RED — the frog sings.   This page only.

   The Red label is the one engraving in the range that is already doing
   something: the frog sits in profile with its throat up and three musical
   notes drawn above its head.  Nothing here invents a gesture — it plays the
   one the illustrator drew.

   Nothing was traced and no artwork was redrawn.  The label is black ink on a
   near-white ground, so the three notes were lifted straight out of
   plate.webp and normalised until their own ground is pure white; `multiply`
   then puts white to nothing and they composite back onto the label exactly
   as ink prints.  The rectangle they came from is refilled with a quadratic
   surface fitted to the surrounding label (residual 0.51/255 — below the
   quantisation of the file itself), so with the animation at rest the
   photograph is pixel-for-pixel what it always was.

   Everything is scoped to `.song-red`, a class js/red-song.js puts on the
   hero plate.  To remove the whole thing: delete the two tags in
   wines/red/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 every layer be positioned in per cent of the original file's own
   coordinates.  Getting this backwards puts every layer on the wordmark. */
.song-red__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.  It paints the fitted ground ONLY where the ink was, and its
   alpha is the exact union of the three note masks — every pixel it rubs out
   is a pixel a note paints back at the same strength, so the two cancel.  A
   half-erased pixel repainted at half strength would land three quarters of
   the way home and no further, which is a grey ghost of the notes.
   Saved lossless: at this size a quality setting of 95 flattened the fitted
   gradient and the patch showed as a rectangle. */
.song-red__ground {
  position: absolute;
  left: 72.857%;
  top: 75.895%;
  width: 13.214%;
  height: 3.158%;
  background: url('../assets/images/wines/red/song-ground.webp') center / 100% 100% no-repeat;
}

/* The notes, back in their own places.
   Each is a second copy of the WHOLE photograph masked down to one note, at
   exactly the size and position of the plate beneath it — not a cut-out
   pasted back on.  A small cut-out is resampled on its own, so its edge lands
   a fraction of a pixel off the edge underneath and the note gets a faint
   outline; the full plate resamples identically to the plate below it, so on
   the frame the phrase begins the three notes are the same pixels that are
   printed there and the stage can be switched on without a flicker.

   Each turns about its own centre, so `rotate` and `scale` in the phrase mean
   what they meant when these were three little boxes; and each carries its
   own travel in `--nx` / `--ny`, because the three notes are different sizes
   and used to move by a share of their own width. */
.song-red__note {
  position: absolute;
  inset: 0;
  background: url('../assets/images/wines/red/plate.webp') center / 100% 100% no-repeat;
  -webkit-mask-mode: alpha;
          mask-mode: alpha;
  will-change: transform, opacity;
}
.song-red__note--1 {
  -webkit-mask: url('../assets/images/wines/red/song-note-1-mask.webp') 76.7790% 77.3555% / 4.6429% 1.6842% no-repeat;
          mask: url('../assets/images/wines/red/song-note-1-mask.webp') 76.7790% 77.3555% / 4.6429% 1.6842% no-repeat;
  transform-origin: 75.5357% 76.8947%;
  --nx: 1.1536%;  --ny: -2.3%;
}
.song-red__note--2 {
  -webkit-mask: url('../assets/images/wines/red/song-note-2-mask.webp') 81.4394% 77.9388% / 5.7143% 1.9474% no-repeat;
          mask: url('../assets/images/wines/red/song-note-2-mask.webp') 81.4394% 77.9388% / 5.7143% 1.9474% no-repeat;
  transform-origin: 79.6429% 77.3947%;
  --nx: 1.5607%;  --ny: -2.8%;
}
.song-red__note--3 {
  -webkit-mask: url('../assets/images/wines/red/song-note-3-mask.webp') 84.8771% 78.6366% / 5.5357% 1.9474% no-repeat;
          mask: url('../assets/images/wines/red/song-note-3-mask.webp') 84.8771% 78.6366% / 5.5357% 1.9474% no-repeat;
  transform-origin: 82.9464% 78.0789%;
  --nx: 1.4929%;  --ny: -2.8%;
}

/* The throat.
   A second copy of the same photograph, masked to a soft ellipse over the
   sac and scaled about the jaw hinge.  The pixels under the mask's soft edge
   are identical to the ones beneath it, so there is no edge to see: only the
   throat appears to fill.  The engraving is never deformed — it is the
   photograph of it that swells, which is the same thing to the eye. */
.song-red__throat {
  position: absolute;
  inset: 0;
  background: url('../assets/images/wines/red/plate.webp') center / 100% 100% no-repeat;
  -webkit-mask-image: radial-gradient(ellipse 5.18% 1.105% at 72.68% 80.737%, #000 48%, transparent 100%);
          mask-image: radial-gradient(ellipse 5.18% 1.105% at 72.68% 80.737%, #000 48%, transparent 100%);
  /* the sac swells forward and down from where it joins the body, which is
     the left of it — not from the jaw, or it would balloon backwards */
  transform-origin: 68.39% 79.684%;
  scale: 1;
}

/* ==========================================================================
   The phrase
   ==========================================================================
   Three croaks, then a beat of quiet, then again — it runs on its own for as
   long as the bottle is on screen.  The loop is 3s: 2.05s of song and 0.95s
   of rest, so it reads as breathing rather than as a looping GIF.  It used to
   be 5.4s; the song itself was shortened by a third along with the wait,
   because a phrase that keeps its old speed inside a cycle this short leaves
   no rest at all, and the rest is what stops it reading as a looping GIF.

   The notes that are printed on the label drift up and out and three more are
   there when the phrase finishes, so the loop closes on the state the label
   is actually printed in and there is never a frame where the bottle is
   missing something.  The fade at each end is kept at 108ms in real time
   rather than at its old share of the cycle: it is there to smear the one
   sub-pixel tick where the copies land on their own printed edges, and that
   tick does not get smaller because the loop did.  The two later notes carry a small permanent offset,
   which keeps the three of them from moving as one block on every pass. */
@media (prefers-reduced-motion: no-preference) {
  /* The stage is invisible outside the phrase.  Red is the one wine whose
     layers replace something already printed — the three notes are lifted out
     and the rectangle they came from is refilled — so unlike the others its
     rest state would otherwise be a reconstruction rather than the
     photograph, however good the reconstruction is.  Switching the stage off
     between phrases makes it the photograph.  The switch happens on the frame
     where the notes are exactly where they are printed, so it has nothing to
     show. */
  .song-red .song-red__stage {
    animation: red-veil var(--song-loop, 3s) infinite both;
  }

  .song-red .song-red__note {
    animation: song-note var(--song-loop, 3s) cubic-bezier(0.32, 0.06, 0.28, 1) infinite both;
  }
  .song-red .song-red__note--2 { animation-delay: 0.11s; }
  .song-red .song-red__note--3 { animation-delay: 0.21s; }

  .song-red .song-red__throat {
    animation: song-throat var(--song-loop, 3s) ease-in-out infinite both;
  }

  /* Off screen or tab in the background: hold, do not restart.  Pausing
     rather than removing the class means it picks the phrase up where it
     left it instead of snapping back to the beginning in view. */
  .song-red.is-held .song-red__stage,
  .song-red.is-held .song-red__note,
  .song-red.is-held .song-red__throat { animation-play-state: paused; }
}

/* The stage fades rather than snaps.  On the frame the layers appear, the
   compositor is drawing them into their own texture instead of straight into
   the page, and a masked copy of a photograph rasterised twice does not land
   on itself to the last sub-pixel.  Stepped, that lands as one visible tick
   on the darkest ink; ramped over a tenth of a second, while the notes are
   still exactly where they are printed, it is nothing at all. */
@keyframes red-veil {
  0%          { opacity: 0; }
  3.6%, 68.3% { opacity: 1; }
  71.9%       { opacity: 0; }
  100%        { opacity: 0; }
}

/* Percentages below are the 2.05s phrase mapped onto the 3s loop
   (2.05 / 3 = 68.3%); everything after that is the rest beat. */
@keyframes song-note {
  /* held at the printed position for the first 2%, which is the window the
     stage fades up in */
  0%, 3.6%    { translate: 0 0; rotate: 0deg; scale: 1; opacity: 1; }
  27.1%       { translate: var(--nx) var(--ny); rotate: 9deg; scale: 0.86; opacity: 0; }
  /* home again while it cannot be seen, so the return never reads as a
     rewind — by the time it fades back the frog has sung it again */
  39.4%       { translate: 0 0; rotate: 0deg; scale: 1; opacity: 0; }
  68.3%, 100% { translate: 0 0; rotate: 0deg; scale: 1; opacity: 1; }
}

@keyframes song-throat {
  0%, 20.1%   { scale: 1; }
  29.8%       { scale: 1.13; }
  36.5%       { scale: 1.02; }
  43.3%       { scale: 1.11; }
  51.5%, 100% { scale: 1; }
}

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