/* lockin.css - the offer to bank without prestiging.
 *
 * Its own file rather than a block in hud.css, which was at 400 of 400 lines. The
 * split is also the honest one: this is a single feature with its own script
 * (public/js/lockin.js) and its own lifecycle, not part of the permanent match
 * chrome. Loaded after hud.css so it can lean on the same --hud-gut rail.
 */

/* ---- The lock-in offer ----------------------------------------------------
   Anchored under the score readout, which is Kenny's pick and the only placement
   that satisfies both halves of the constraint: it has to be noticeable, and it
   must never sit where you are fighting. The centre of the screen is the fight;
   the score is where your eye already goes to watch the number that triggered
   this, so the prompt grows out of that number.

   Never interactive. There is no click target here on purpose — reaching for a
   cursor mid-fight means letting go of the thing keeping you alive, so the whole
   interaction is two keys. It is pointer-events:none so it can never eat a click
   meant for the arena underneath it. */
/* NO CSS ENTRY ANIMATION, AND THAT IS THE BUG FIX. This carried
   `animation: liIn .22s ease-out both`, and `fill: both` pins an element at the
   animation's `from` state whenever the animation is not running — which is always,
   because the element starts `hidden` and a display:none element never starts its
   animation. So the keyframe's `opacity: 0` won permanently and beat the inline
   opacity the fade sets every frame. The prompt was in the DOM, un-hidden, correctly
   positioned, with its text updating, and invisible. It looked like the feature had
   been lost, and Kenny reported exactly that.

   The fade is a JS-driven inline opacity by design (it tracks SCORE, not time), so
   the entrance is a transition instead: transitions compose with inline styles
   rather than overriding them, which is the whole difference. */
#lockInPrompt {
  position: fixed; z-index: 6; pointer-events: none;
  left: var(--hud-gut); top: 156px;
  background: rgba(10, 13, 28, .92);
  border: 1px solid rgba(127, 227, 255, .5);
  border-radius: 11px; padding: 10px 15px;
  box-shadow: 0 0 0 1px rgba(0,0,0,.45), 0 8px 24px rgba(0,0,0,.5);
  /* NOTHING IN CSS OWNS THIS ELEMENT'S OPACITY. Not an animation, not a transition.
     The fade is written inline every frame by lockin.js, which is already 60 updates
     a second and needs no smoothing — and the one bug this element has ever had was
     a CSS animation with fill:both silently outranking that inline value and pinning
     it at zero. Anything declared here can do the same thing again. */
}
.li-head {
  font-size: 14px; letter-spacing: .09em; color: #7fe3ff; font-weight: 800;
}
.li-head b { color: #fff; letter-spacing: 0; font-variant-numeric: tabular-nums; font-size: 17px; }
.li-keys { font-size: 12px; color: #c9d4e8; opacity: .8; margin-top: 5px; white-space: nowrap; }
.li-keys span { opacity: .4; margin: 0 3px; }
.li-keys kbd {
  background: #7fe3ff; color: #0a0c1a; border-radius: 4px;
  padding: 1px 6px; font: inherit; font-weight: 800;
}
/* The window is measured in POINTS, not seconds, so this fills as you climb through
   it rather than counting down a clock. Eat fast and you close your own window. */
.li-bar { height: 3px; background: rgba(255,255,255,.14); border-radius: 2px; margin-top: 6px; overflow: hidden; }
.li-bar i { display: block; height: 100%; background: #7fe3ff; transition: width .12s linear; }

/* Confirmation. A line that fades, not a takeover: the entire reason to choose the
   quiet path is to not be noticed, and a celebration would undo that. */
.li-toast {
  position: fixed; z-index: 6; pointer-events: none;
  left: var(--hud-gut); top: 156px;
  font-size: 13px; font-weight: 700; color: #7fe3ff;
  text-shadow: 0 2px 10px rgba(0,0,0,.9);
  animation: liToast 2.6s ease-out both;
}
@keyframes liToast {
  0% { opacity: 0; transform: translateY(4px); }
  14% { opacity: 1; transform: translateY(0); }
  70% { opacity: 1; }
  100% { opacity: 0; transform: translateY(-8px); }
}
@media (prefers-reduced-motion: reduce) {
  .li-bar i { transition: none; }
  .li-toast { animation-duration: 2.6s; animation-name: liToastCalm; }
  @keyframes liToastCalm { 0%,90% { opacity: 1; } 100% { opacity: 0; } }
}

/* ---- Taking the offer with a thumb -----------------------------------------
   The keys line becomes two real buttons on touch (public/js/lockin.js). Both at
   the 44px target, because this is the control that decides whether a run's score
   is banked or gambled, and it appears mid-fight. Bank reads as the affirmative
   and is weighted accordingly; keeping the climb is the quiet one, since it is
   also what happens if you ignore the offer entirely. */
.li-acts { display: flex; gap: 8px; justify-content: center; margin: 7px 0 2px; }
/* The prompt itself stays pointer-events:none, because it floats over the arena
   and must never swallow an aim gesture. The two buttons opt back in, and only
   the buttons: that is the whole reason the exception is here and not up there. */
.li-act {
  pointer-events: auto;
  min-height: 44px; padding: 0 15px; border-radius: 10px; cursor: pointer;
  font: inherit; font-size: 13px; font-weight: 800; letter-spacing: .01em;
  transition: filter var(--t-quick) var(--e-standard),
              transform var(--t-instant) var(--e-standard);
}
.li-act:active { transform: scale(0.96); }
.li-bank { color: #06210f; border: none; background: linear-gradient(180deg, #7dffa6, #34d97a); }
.li-bank:hover { filter: brightness(1.08); }
.li-keep { color: #cfd6e6; background: rgba(255,255,255,.06); border: 1px solid rgba(255,255,255,.16); }
.li-keep:hover { color: #fff; border-color: rgba(255,255,255,.3); }
