/* Activity / status icon contract R1 -- see docs/LUA_ACTIVITY_STATUS_ICON_CONTRACT_R1.md
   Pure transform/opacity/filter keyframes only (GPU-composited, no layout
   thrash), matching the animation style already used in styles.css
   (lessyPulse, lessyFriendlyFloat, runtimePulse). Additive/isolated file --
   not merged into styles.css so adopting this contract never risks the
   existing shared stylesheet. */

.activity-status-icon {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 48px;
  height: 48px;
}

.activity-status-icon[hidden] {
  display: none;
}

.activity-status-icon__image {
  width: 100%;
  height: 100%;
  object-fit: contain;
  display: block;
}

/* Visually hidden but announced -- same clip-based technique used
   throughout the codebase for screen-reader-only live regions. This is a
   SEPARATE element from .activity-status-icon__image (which is purely
   decorative, alt="" + aria-hidden), not a live region nested inside a
   role="img" wrapper -- see activityStatusIcon.js's doc comment for why
   that combination doesn't work. */
.activity-status-icon__status {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

.activity-status-icon--idle .activity-status-icon__image {
  animation: none;
  opacity: 1;
}

.activity-status-icon--greet .activity-status-icon__image {
  animation: activityIconGreet 0.6s ease-out;
}

.activity-status-icon--thinking .activity-status-icon__image {
  animation: activityIconPulse 1.4s ease-in-out infinite;
}

.activity-status-icon--pointing .activity-status-icon__image {
  animation: activityIconNudge 1.2s ease-in-out infinite;
}

.activity-status-icon--success .activity-status-icon__image {
  animation: activityIconSuccess 0.5s ease-out;
}

/* Deliberately calmer/slower than thinking -- a soft caution, not an alarm. */
.activity-status-icon--warning_soft .activity-status-icon__image {
  animation: activityIconSoftGlow 2.2s ease-in-out infinite;
}

.activity-status-icon--sleep .activity-status-icon__image {
  animation: none;
  opacity: 0.45;
}

@keyframes activityIconGreet {
  from { opacity: 0; transform: translateY(6px) scale(0.9); }
  to { opacity: 1; transform: translateY(0) scale(1); }
}

@keyframes activityIconPulse {
  0%, 100% { transform: scale(1); opacity: 1; }
  50% { transform: scale(1.06); opacity: 0.85; }
}

@keyframes activityIconNudge {
  0%, 70%, 100% { transform: translateX(0); }
  80% { transform: translateX(-3px); }
  90% { transform: translateX(3px); }
}

@keyframes activityIconSuccess {
  0% { transform: scale(1); }
  40% { transform: scale(1.18); }
  100% { transform: scale(1); }
}

@keyframes activityIconSoftGlow {
  0%, 100% { filter: drop-shadow(0 0 0 rgba(255, 176, 32, 0)); }
  50% { filter: drop-shadow(0 0 6px rgba(255, 176, 32, 0.55)); }
}

/* Per-surface motion style (Kai, 2026-07-30, avatar/status go-live spec):
   the 8-state contract above stays surface-agnostic on purpose (see
   activityStatusIcon.js's doc comment -- do not add a 9th state), but a
   propeller and a moon read naturally as SPINNING objects, not pulsing
   glows. These overrides are presentation only, scoped by the existing
   [data-surface] attribute that surfaceBranding.js's applyThemeHooks()
   already sets on <html>/<body> -- the same mechanism every other
   surface-specific CSS delta in this codebase uses (see styles.css's
   [data-theme="avigation"] block). No JS change needed: the module still
   only ever toggles .activity-status-icon--thinking, this just changes
   what that class means to look at on these two surfaces.
   Avigation: "roterer bare under faktisk arbeid... ingen kontinuerlig
   idle-rotasjon... stopp ved complete" -- idle/success/sleep are
   untouched above (idle has no animation at all), so the propeller is
   static outside of thinking/pointing and returns to static the moment
   app.js's existing success-then-idle timer fires. */
[data-surface="avigation"] .activity-status-icon--thinking .activity-status-icon__image,
[data-surface="avigation"] .activity-status-icon--pointing .activity-status-icon__image {
  animation: activityIconRotate 1.6s linear infinite;
}

/* LUA Cloud: "thinking/routing/web/model: rolig rotasjon" -- noticeably
   calmer/slower than Avigation's propeller, since a moon turning and an
   engine spinning are different characters. The asymmetric moon icon
   (lua-moon-icon.svg) was redesigned alongside this so the rotation is
   actually visible (its craters sweep past) instead of reading as an
   almost-static disc. */
[data-surface="lua_cloud"] .activity-status-icon--thinking .activity-status-icon__image,
[data-surface="lua_cloud"] .activity-status-icon--pointing .activity-status-icon__image {
  animation: activityIconRotate 5s linear infinite;
}

@keyframes activityIconRotate {
  from { transform: rotate(0deg); }
  to { transform: rotate(360deg); }
}

/* LUA Cloud: "success: kort lys/glod, deretter idle" -- a brief glow
   suits the moon's lit-sphere gradient better than the generic scale-pop
   above; Avigation keeps the generic .activity-status-icon--success as
   specified (Kai's Avigation spec only calls out stop-at-complete, which
   the existing success-then-idle timer in app.js already provides). */
[data-surface="lua_cloud"] .activity-status-icon--success .activity-status-icon__image {
  animation: activityIconMoonGlow 0.9s ease-out;
}

@keyframes activityIconMoonGlow {
  0% { filter: drop-shadow(0 0 0 rgba(201, 195, 230, 0)); transform: scale(1); }
  40% { filter: drop-shadow(0 0 10px rgba(224, 216, 250, 0.85)); transform: scale(1.08); }
  100% { filter: drop-shadow(0 0 0 rgba(201, 195, 230, 0)); transform: scale(1); }
}

@media (prefers-reduced-motion: reduce) {
  .activity-status-icon__image {
    animation: none !important;
  }
}
