/* Press animations. Colour comes from each button's --c (theme + button colour). */

.fx-host { overflow: hidden; }
.fx-layer { position: absolute; inset: 0; pointer-events: none; z-index: 1; overflow: hidden; border-radius: inherit; }
/* Button contents sit above the effect layer. */
.fx-host > .hud-lbl, .fx-host > .hud-ico, .fx-host > .caret,
.fx-host > .glyph, .fx-host > .label, .fx-host > .foot { position: relative; z-index: 2; }
.fx-host > .dial { z-index: 2; }
/* Themes can override the label shadows; light themes need a lighter one to stay crisp. */
.fx-host .hud-lbl, .fx-host .label { text-shadow: var(--label-shadow, 0 1px 6px rgba(0,0,0,.8)); }

.fx-state {
  position: absolute; z-index: 2; left: 0; right: 0; bottom: 4px; text-align: center;
  font: 600 9px/1 var(--font-body); letter-spacing: .16em; text-transform: uppercase; color: var(--dim);
  text-shadow: var(--state-shadow, 0 1px 4px #000); pointer-events: none;
}
.key > .fx-state { left: auto; right: 14px; bottom: auto; top: 14px; font-size: 10px; }
.fx-on > .fx-state, .fx-charging > .fx-state, .fx-arming > .fx-state, .fx-locked > .fx-state { color: var(--c); }
.fx-on { border-color: var(--c) !important; box-shadow: inset 0 0 0 1px var(--c), 0 0 22px -8px var(--c) !important; }

/* shared flash + kick */
.fx-flash {
  position: absolute; inset: 0;
  background: radial-gradient(circle, #fff 0%, var(--c) 35%, transparent 70%);
  animation: fx-flash .5s ease-out forwards;
}
@keyframes fx-flash { from { opacity: .9; transform: scale(.3); } to { opacity: 0; transform: scale(1.6); } }
.fx-kick { animation: fx-kick .25s ease-out; }
@keyframes fx-kick { 40% { scale: 1.04; } }

/* ripple */
.fx-ripple {
  position: absolute; width: 20px; height: 20px; margin: -10px 0 0 -10px; border-radius: 50%;
  border: 2px solid var(--c); animation: fx-ripple .7s ease-out forwards;
}
@keyframes fx-ripple { from { opacity: 1; } to { transform: scale(18); opacity: 0; } }

/* landing gear struts */
.fx-strut {
  position: absolute; top: 56%; width: 4px; height: 30%; margin-left: -2px;
  background: linear-gradient(var(--c), color-mix(in srgb, var(--c) 20%, transparent));
  transform: scaleY(0); transform-origin: top;
  transition: transform .45s cubic-bezier(.3, 1.6, .5, 1) calc(var(--i) * 90ms);
}
.fx-strut::after { content: ""; position: absolute; bottom: -3px; left: -7px; width: 18px; height: 4px; border-radius: 2px; background: var(--c); }
.fx-on .fx-strut { transform: scaleY(1); }

/* quantum charge ring */
.fx-ring { position: absolute; left: 50%; top: 50%; height: 88%; aspect-ratio: 1; transform: translate(-50%, -50%); }
.fx-ring circle { fill: none; stroke-width: 4; }
.fx-ring .track { stroke: color-mix(in srgb, var(--c) 14%, transparent); }
.fx-ring .prog {
  stroke: var(--c); stroke-linecap: round; stroke-dasharray: 251.33; stroke-dashoffset: 251.33;
  filter: drop-shadow(0 0 6px var(--c));
}
.fx-ring .prog.drain { transition: stroke-dashoffset .35s ease; }
.fx-on .fx-ring .track { stroke: color-mix(in srgb, var(--c) 50%, transparent); }
.fx-charging { animation: fx-jitter .07s infinite; }
@keyframes fx-jitter { 50% { translate: .6px -.6px; scale: .985; } }

/* decoy sparks */
.fx-spark {
  position: absolute; left: 50%; top: 50%; width: 5px; height: 5px; border-radius: 50%;
  background: var(--c); box-shadow: 0 0 8px var(--c), 0 0 2px #fff;
  animation: fx-spark .7s ease-out forwards;
}
@keyframes fx-spark {
  from { transform: translate(-50%, -50%); }
  to { transform: translate(calc(-50% + var(--dx)), calc(-50% + var(--dy))) scale(.2); opacity: 0; }
}

/* light beam */
.fx-beam {
  position: absolute; inset: 0; opacity: 0; transition: opacity .3s;
  background: radial-gradient(ellipse 80% 90% at 50% 0%, rgba(255, 214, 140, .55), transparent 70%);
}
.fx-on .fx-beam { opacity: 1; }
.fx-flicker .fx-beam { animation: fx-flicker .6s steps(1); }
@keyframes fx-flicker { 0% { opacity: 0; } 10% { opacity: 1; } 18% { opacity: .15; } 28% { opacity: 1; } 36% { opacity: .4; } 46% { opacity: 1; } }

/* recoil + muzzle flash */
.fx-shot { animation: fx-recoil .1s ease-out; }
@keyframes fx-recoil { 35% { translate: 1px 3px; scale: .95; } }
.fx-muzzle {
  position: absolute; bottom: 4%; left: 50%; width: 70px; height: 70px; margin-left: -35px; border-radius: 50%;
  background: radial-gradient(circle, #fff 0%, var(--c) 28%, transparent 65%);
  animation: fx-muzzle .12s ease-out forwards;
}
@keyframes fx-muzzle { from { transform: scale(.4); opacity: 1; } to { transform: scale(1.3); opacity: 0; } }

/* speed streaks */
.fx-streak {
  position: absolute; left: 100%; height: 2px; border-radius: 2px;
  background: linear-gradient(90deg, transparent, var(--c)); animation: fx-streak linear forwards;
}
@keyframes fx-streak { to { left: -70%; } }
.fx-boost { animation: fx-rumble .1s infinite; }
@keyframes fx-rumble { 50% { translate: -1px 0; } }

/* doors */
.fx-door {
  position: absolute; top: 0; bottom: 0; width: 50%; opacity: .9;
  background: repeating-linear-gradient(135deg, color-mix(in srgb, var(--panel-hi) 90%, #000) 0 8px, color-mix(in srgb, var(--panel) 90%, #000) 8px 16px);
  transition: transform .6s cubic-bezier(.7, 0, .3, 1) .12s;
}
.fx-door.l { left: 0; border-right: 1px solid var(--c); box-shadow: inset -3px 0 8px -4px var(--c); }
.fx-door.r { right: 0; border-left: 1px solid var(--c); box-shadow: inset 3px 0 8px -4px var(--c); }
.fx-on .fx-door.l { transform: translateX(-94%); }
.fx-on .fx-door.r { transform: translateX(94%); }
.fx-notrans .fx-door { transition: none; }

/* lock-on brackets */
.fx-br {
  position: absolute; width: 20px; height: 20px;
  left: calc(50% - 10px + var(--sx) * 24px); top: calc(50% - 10px + var(--sy) * 24px);
  border: 2px solid var(--dim); opacity: .3; transition: border-color .2s, opacity .2s;
}
.fx-locking .fx-br { animation: fx-converge .65s cubic-bezier(.2, .8, .3, 1); }
@keyframes fx-converge {
  from { transform: translate(calc(var(--sx) * 40px), calc(var(--sy) * 40px)) rotate(45deg); opacity: 0; }
  70% { opacity: 1; }
  to { transform: none; opacity: 1; }
}
.fx-locked .fx-br { border-color: var(--c); opacity: 1; animation: fx-blink .2s 3; }
@keyframes fx-blink { 50% { opacity: .2; } }
.fx-dot { position: absolute; left: 50%; top: 50%; width: 6px; height: 6px; margin: -3px; border-radius: 50%; background: var(--c); opacity: 0; transition: opacity .2s; }
.fx-locked .fx-dot { opacity: 1; }

/* hazard arming bar */
.fx-hazard {
  position: absolute; inset: 0; transform: scaleX(0); transform-origin: left;
  background: repeating-linear-gradient(-45deg, color-mix(in srgb, var(--red) 40%, transparent) 0 10px, color-mix(in srgb, var(--amber) 15%, transparent) 10px 20px);
}
.fx-hazard.drain { transition: transform .3s ease; }
.fx-arming { animation: fx-jitter .06s infinite; }
.fx-ejected { animation: fx-eject .6s ease-out; }
@keyframes fx-eject { 30% { translate: 0 -10px; } 60% { translate: 0 3px; } }

/* timed hold progress */
.fx-timer {
  position: absolute; left: 0; right: 0; bottom: 0; height: 3px;
  background: var(--c); box-shadow: 0 0 8px var(--c);
  transform: scaleX(0); transform-origin: left;
}
.fx-timer.drain { transition: transform .3s ease; }

@media (prefers-reduced-motion: reduce) {
  .fx-host, .fx-host * { animation-duration: .01ms !important; animation-iteration-count: 1 !important; transition-duration: .01ms !important; }
}
