/* ==========================================================================
   ANIMATIONS — cute, quick, and switched off for reduced motion
   ========================================================================== */

@keyframes blink { 50% { opacity: 0; } }
@keyframes bootOut { to { opacity: 0; visibility: hidden; } }
@keyframes twinkle { 0%, 100% { transform: scale(.6) rotate(0); opacity: .6; } 50% { transform: scale(1.1) rotate(45deg); opacity: 1; } }
@keyframes bop { from { transform: translateY(0); } to { transform: translateY(-2px); } }
@keyframes floatUp {
  0% { transform: translate(0, 0) scale(.6); opacity: 0; }
  15% { opacity: 1; }
  100% { transform: translate(var(--dx, 0px), -90px) scale(1.1) rotate(var(--rot, 10deg)); opacity: 0; }
}
@keyframes blockIn { from { transform: scaleY(0); } to { transform: scaleY(1); } }
@keyframes floaty { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-6px); } }
@keyframes install { from { width: 18%; } to { width: 92%; } }
@keyframes typingDot { 0%, 100% { transform: translateY(0); opacity: .5; } 50% { transform: translateY(-4px); opacity: 1; } }
@keyframes marquee { from { transform: translateX(0); } to { transform: translateX(-100%); } }

/* Windows */
@keyframes winOpen {
  from { transform: scale(.94) translateY(6px); opacity: 0; }
  to { transform: none; opacity: 1; }
}
@keyframes winClose { to { transform: scale(.96); opacity: 0; } }
@keyframes nudge {
  0%, 100% { translate: 0 0; }
  10% { translate: -9px 3px; } 20% { translate: 8px -4px; } 30% { translate: -7px -2px; }
  40% { translate: 9px 4px; } 50% { translate: -6px 2px; } 60% { translate: 6px -3px; }
  70% { translate: -4px 3px; } 80% { translate: 3px -2px; } 90% { translate: -2px 1px; }
}
.window.is-opening { animation: winOpen .18s cubic-bezier(.2, .9, .3, 1.2) both; }
.window.is-closing { animation: winClose .12s ease-in forwards; pointer-events: none; }
.window.is-nudged { animation: nudge .5s linear; }

@keyframes iconFlash { 50% { opacity: .15; } }
.desktop-icons.is-refreshing { animation: iconFlash .18s steps(1) 2; }

@keyframes bubbleIn { from { transform: scale(.5) translateY(10px); opacity: 0; } to { transform: none; opacity: 1; } }
.buddy__bubble { animation: bubbleIn .25s cubic-bezier(.3, 1.6, .5, 1) both; }

@keyframes balloonIn { from { transform: translateY(16px) scale(.96); opacity: 0; } to { transform: none; opacity: 1; } }
.balloon, .toast { animation: balloonIn .3s cubic-bezier(.3, 1.4, .5, 1) both; }
.balloon.is-leaving, .toast.is-leaving { animation: winClose .25s ease-in forwards; }

/* Avatar ------------------------------------------------------------------ */
@keyframes avBlink { 0%, 92%, 100% { transform: scaleY(1); } 95% { transform: scaleY(.08); } }
@keyframes avWave { 0%, 100% { transform: rotate(0); } 25% { transform: rotate(-22deg); } 75% { transform: rotate(10deg); } }
@keyframes avBounce { 0%, 100% { transform: translateY(0); } 30% { transform: translateY(-14px) scale(1.02, .98); } 55% { transform: translateY(0) scale(1.03, .97); } 75% { transform: translateY(-5px); } }
@keyframes avBreathe { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(1.5px); } }
@keyframes avType { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-1.5px); } }
@keyframes avNote { 0% { transform: translate(0, 0) rotate(0); opacity: 0; } 20% { opacity: 1; } 100% { transform: translate(var(--nx, 10px), -46px) rotate(20deg); opacity: 0; } }
@keyframes avScreen { 0%, 100% { opacity: .75; } 50% { opacity: 1; } }

.av .av-eyes { transform-box: fill-box; transform-origin: center; animation: avBlink 4.2s infinite; }
.av .av-body { transform-box: fill-box; transform-origin: 50% 100%; animation: avBreathe 3.2s ease-in-out infinite; }
.av .av-arm { transform-box: fill-box; transform-origin: 12% 88%; opacity: 0; transition: opacity .15s ease; }
.av.is-waving .av-arm { opacity: 1; animation: avWave .7s ease-in-out 3; }
.av.is-bouncing .av-all { animation: avBounce .7s ease-out; transform-box: fill-box; transform-origin: 50% 100%; }
.av .av-phones { opacity: 0; transition: opacity .3s ease; }
.av.is-listening .av-phones { opacity: 1; }
.av .av-notes text { opacity: 0; }
.av.is-listening .av-notes text { animation: avNote 2.4s ease-out infinite; }
.av.is-listening .av-notes text:nth-child(2) { animation-delay: .8s; --nx: -12px; }
.av.is-listening .av-notes text:nth-child(3) { animation-delay: 1.6s; --nx: 18px; }
.av .av-laptop-screen { animation: avScreen 2s ease-in-out infinite; }
.av.is-typing .av-hands { animation: avType .18s linear infinite; }

/* Flower easter egg */
.flower .fl-petal { transform-box: fill-box; transform-origin: 50% 100%; transform: scale(0); transition: transform .5s cubic-bezier(.3, 1.6, .5, 1); }
.flower .fl-bud { transition: opacity .3s ease; }
.flower.is-bloomed .fl-petal { transform: scale(1); }
.flower.is-bloomed .fl-bud { opacity: 0; }
.flower .fl-center { opacity: 0; transition: opacity .3s ease .25s; }
.flower.is-bloomed .fl-center { opacity: 1; }
.flower:focus-visible { outline: 2px dotted var(--desk-label); outline-offset: 2px; }
.flower.is-spinning .fl-head { transform-box: fill-box; transform-origin: center; animation: flSpin .8s cubic-bezier(.3, 1.3, .5, 1); }
@keyframes flSpin { to { transform: rotate(360deg); } }
.flower .fl-sway { transform-box: fill-box; transform-origin: 50% 100%; animation: flSway 4s ease-in-out infinite; }
@keyframes flSway { 0%, 100% { transform: rotate(-2deg); } 50% { transform: rotate(2.5deg); } }

/* Glitter theme gets a living title bar */
@keyframes holo { from { background-position: 0 0; } to { background-position: 300% 0; } }
:root[data-theme="glitter"] .window:not(.is-inactive) .titlebar {
  background: linear-gradient(90deg, #ff2d8f, #b388ff, #7ad7ff, #ff9fd0, #ff2d8f);
  background-size: 300% 100%;
  animation: holo 6s linear infinite;
}
:root[data-theme="glitter"] .desktop::after {
  content: "";
  position: absolute; inset: 0;
  pointer-events: none;
  background:
    radial-gradient(circle at 20% 30%, #fff 0 1px, transparent 2px) 0 0 / 61px 61px,
    radial-gradient(circle at 70% 60%, #fff 0 1px, transparent 2px) 0 0 / 47px 47px;
  animation: glitter 3s steps(3) infinite;
  opacity: .8;
}
@keyframes glitter { 33% { opacity: .3; background-position: 3px 2px, -2px 3px; } 66% { opacity: 1; background-position: -2px 1px, 2px -3px; } }

/* ==========================================================================
   REDUCED MOTION — honour the OS setting and the in-app toggle
   ========================================================================== */

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
    scroll-behavior: auto !important;
  }
  .marquee span { padding-left: 0; }
}

:root[data-motion="reduced"] *,
:root[data-motion="reduced"] *::before,
:root[data-motion="reduced"] *::after {
  animation-duration: .001ms !important;
  animation-iteration-count: 1 !important;
  transition-duration: .001ms !important;
}
:root[data-motion="reduced"] .marquee span { padding-left: 0; }
