/* The keyboard. Geometry (left/width, in percent) comes from JS off measured piano
   proportions: white 23.5 x 150 mm, black 15 x 95 mm. */
.keyboard { position: relative; filter: drop-shadow(0 20px 24px rgba(0,0,0,.35)); }
.key {
  position: absolute; top: 0; border: 0; cursor: pointer;
  transform-origin: top center;
  /* Press snaps down; release rebounds past rest, the way a weighted key does.
     background and box-shadow both 200ms so release is one event. */
  transition: transform 250ms cubic-bezier(.22,1.5,.5,1), background 200ms ease, box-shadow 200ms ease;
  -webkit-tap-highlight-color: transparent;
}
.white {
  height: 100%; z-index: 1; color: #9a6b81;
  /* Less pink in the lower third — the old #efd3df read as a stain rather than shading. */
  background: linear-gradient(180deg, #fff 0%, var(--white-key) 80%, #f2e4ea 100%);
  border-left: 1px solid #cdb0bd; border-radius: 0 0 6px 6px;
  box-shadow: inset 0 -11px 15px -9px rgba(90,45,66,.2);
}
.white span { position: absolute; left: 0; right: 0; bottom: 13px; font-size: 9.5px; font-weight: 800; letter-spacing: .06em; }
.black {
  height: 62%; z-index: 3;
  background:
    linear-gradient(180deg, rgba(255,255,255,.13), transparent 20%),
    linear-gradient(90deg, #0d070b, #2a1925 48%, #0a0509);
  border: 1px solid #070305; border-radius: 0 0 5px 5px;
  box-shadow: inset 0 -9px 11px -5px rgba(0,0,0,.65), 0 6px 12px -2px rgba(0,0,0,.5);
}
.key.active { transition-duration: 55ms, 55ms, 55ms; }

/* There is no .key::before any more. It used to paint a three-layer burst standing ABOVE the
   key — a white-cored dome, a vertical shaft and a wide streak, blended plus-lighter — and
   whatever the hue it mixed toward, the core read as a plain white mound sitting on top of the
   key at every press. That mound is what this removes. What is left says the same thing three
   quieter ways: the key body lights in the hand's colour, the plume draws a bar of that colour
   along the strike line, and the tile has already landed there.
   Gone with it: the key-flash and key-sustain keyframes (they only ever ran on ::before), the
   sub-frame-keyframe rule they existed to satisfy, and the constraint that .keyboard keep its
   drop-shadow filter to contain an additive blend. .key::after is untouched — that is the
   anticipation pulse, which is a different cue with a different job. */

/* The hand's colour lights the key body. --glow defaults to the hand but a hot streak
   overrides it, which is what keeps the streak readable without a fourth colour in the
   hand-colour language.
   This IS the strike now. The white dome above the key, the pink rule along the strike line
   and the plume's bar of light have all gone; what is left is the key going down in the hand's
   colour, under the tile that just landed on it.
   ponytail: still an animated box-shadow, which is paint-bound rather than composited.
   .key::after is the anticipation cue and ::before is free again — if a dense chord measurably
   drops frames, move this onto ::before as a scaled gradient. */
.key.left-hand  { --glow: var(--left-hand); }
.key.right-hand { --glow: var(--right-hand); }
.keyboard[data-heat="2"] .key.active { --glow: #ffd36e; }
.keyboard[data-heat="3"] .key.active { --glow: #ffb02e; }

.white.active {
  background: linear-gradient(180deg, oklch(from var(--hand) calc(l + (1 - l) * .82) calc(c * .35) h), var(--hand));
  transform: scaleY(.975);
  box-shadow: inset 0 -3px oklch(from var(--hand) calc(l * .35) c h / .16),
              0 0 28px color-mix(in srgb, var(--glow) 55%, transparent);
}
.black.active {
  background: linear-gradient(180deg, oklch(from var(--hand) calc(l * .90) c h), oklch(from var(--hand) calc(l * .76) c h));
  transform: scaleY(.965);
  box-shadow: 0 0 24px color-mix(in srgb, var(--glow) 65%, transparent);
}

/* Anticipation: the key you are about to need lights from below, a fraction of a beat
   before its note lands. This is the one cue that pulls a learner's eye off the falling
   bars and down onto the keyboard, which is where it has to end up. */
.key::after {
  content: ""; position: absolute; inset: 0; border-radius: inherit;
  pointer-events: none; opacity: 0;
}
.key[data-next]::after { animation: next-pulse var(--lead, .5s) ease-out both; }
.key[data-next="left"]::after  { background: linear-gradient(180deg, transparent 45%, color-mix(in srgb, var(--left-hand) 60%, transparent)); }
.key[data-next="right"]::after { background: linear-gradient(180deg, transparent 45%, color-mix(in srgb, var(--right-hand) 60%, transparent)); }
@keyframes next-pulse { 0% { opacity: 0; } 45% { opacity: .9; } 100% { opacity: 0; } }
