/* ───────────────────────────────────────────────
   RAVEN CURSOR
   Replaces the old .cursor / .cursor-dot rules.
   JS (raven-cursor.js) creates the #raven element
   and toggles .flying / .landed / .pecking on it,
   plus spawns .gold-mote sparkle particles — denser
   and trailing behind while moving, sparse and fully
   random while still, and in a large burst confined
   to whatever link/button was just clicked. This
   file owns all the actual motion/appearance.
─────────────────────────────────────────────── */

/* Every element, not just body/a/button — inheritance alone isn't enough
   because some elements (inputs, textareas, selects, etc.) get their own
   cursor value straight from the browser's UA stylesheet (e.g. cursor:
   text on a text input), which overrides whatever body would otherwise
   hand down. Setting cursor:none directly on * closes that gap. */
html,
body,
* {
  cursor: none !important;
}

#page-content.page-fade-out {
  animation: page-fade-out 150ms ease forwards;
}

#page-content.page-fade-in {
  animation: page-fade-in 200ms ease;
}

@keyframes page-fade-out {
  to {
    opacity: 0;
    transform: translateY(6px);
  }
}

@keyframes page-fade-in {
  from {
    opacity: 0;
    transform: translateY(-6px);
  }

  to {
    opacity: 1;
    transform: translateY(0);
  }
}

/* ── crossfade on real page navigation ──
   Standards-based, no JS router needed: the browser itself snapshots the
   outgoing and incoming page and dissolves between them on a normal
   same-origin <a href> navigation. Needs this same rule present in the
   CSS of every page (it is, since this is the shared stylesheet).
   Supported in Chromium 126+ and Safari 18.2+; Firefox still has it
   behind a flag, so it silently falls back to an ordinary instant
   navigation there — no fallback code needed, the explosion in
   raven-cursor.js is what covers that cut, not a fake crossfade. */
@view-transition {
  navigation: auto;
}

::view-transition-old(root) {
  animation: crossfade-out 0.75s ease-in-out;
}

::view-transition-new(root) {
  animation: crossfade-in 0.75s ease-in-out;
}

@keyframes crossfade-out {
  from {
    opacity: 1;
  }

  to {
    opacity: 0;
  }
}

@keyframes crossfade-in {
  from {
    opacity: 0;
  }

  to {
    opacity: 1;
  }
}

#raven {
  position: fixed;
  top: 0;
  left: 0;
  width: 46px;
  height: 46px;
  pointer-events: none;
  z-index: 9999;
  transform: translate3d(-1000px, -1000px, 0);
  will-change: transform;
}

#raven svg {
  width: 100%;
  height: 100%;
  display: block;
  overflow: visible;
  transform-origin: 50% 50%;
  filter:
    drop-shadow(0 0 3px rgba(255, 224, 150, 0.85)) drop-shadow(0 0 8px rgba(232, 201, 110, 0.55)) drop-shadow(0 2px 4px rgba(0, 0, 0, 0.6));
}

/* ── clicked-element explosion ──
   A quick punch/flash on whatever link or button was just clicked,
   timed alongside the particle burst JS fires from that same element's
   bounding box. */
.raven-exploding {
  animation: element-explode 0.4s ease-out;
}

@keyframes element-explode {
  0% {
    transform: scale(1);
    filter: brightness(1);
  }

  30% {
    transform: scale(0.94);
    filter: brightness(1.5) saturate(1.3);
  }

  100% {
    transform: scale(1);
    filter: brightness(1);
  }
}

/* ── gold sparkle particles ──
   Tiny individual particles that drift or explode outward and fade, in a
   fully random direction each time with a bent (non-linear) path so a
   burst of them never lines up into a visible trail. Used while the
   raven moves (spawned often, over a wider area), while it's still
   (spawned rarely), for its own peck flourish, and — biggest of all —
   for the burst exploding off a just-clicked element. Same visual
   throughout, just different density/area/size, driven from JS. */
.gold-mote {
  position: fixed;
  top: 0;
  left: 0;
  width: var(--size, 3px);
  height: var(--size, 3px);
  margin: calc(var(--size, 3px) / -2) 0 0 calc(var(--size, 3px) / -2);
  border-radius: 50%;
  pointer-events: none;
  z-index: 9998;
  background: radial-gradient(circle, #fff3d0 0%, #ffd876 40%, rgba(184, 134, 11, 0) 75%);
  filter: drop-shadow(0 0 2px rgba(200, 150, 40, 0.8));
  animation: mote-float var(--dur, 700ms) ease-out forwards;
}

@keyframes mote-float {
  0% {
    opacity: 0;
    transform: translate(-50%, -50%) scale(0.3);
  }

  25% {
    opacity: 1;
    transform: translate(-50%, -50%) scale(1);
  }

  55% {
    opacity: 0.85;
    transform: translate(calc(-50% + var(--mdx)), calc(-50% + var(--mdy))) scale(0.7);
  }

  100% {
    opacity: 0;
    transform: translate(calc(-50% + var(--dx)), calc(-50% + var(--dy))) scale(0.15);
  }
}

/* smooths only the delayed flip-to-left after landing, not live flight rotation */
#raven.landed svg {
  transition: transform 0.4s ease;
}

/* ── wings ── */
.wing {
  transform-box: fill-box;
}

.wing-left,
.wing-right {
  transform-origin: left center;
  /* both pivot from the shoulder attachment */
}

#raven.flying .wing-left {
  animation: flapL 0.34s steps(2) infinite;
}

#raven.flying .wing-right {
  animation: flapR 0.34s steps(2) infinite;
}

@keyframes flapL {
  0% {
    transform: rotate(0deg) scaleY(1);
  }

  50% {
    transform: rotate(35deg) scaleY(0.55);
  }

  100% {
    transform: rotate(0deg) scaleY(1);
  }
}

@keyframes flapR {
  0% {
    transform: rotate(0deg) scaleY(1);
  }

  50% {
    transform: rotate(-35deg) scaleY(0.55);
  }

  100% {
    transform: rotate(0deg) scaleY(1);
  }
}

#raven.landed .wing-left {
  transform: rotate(8deg) scaleY(0.85);
  transition: transform 0.25s ease;
}

#raven.landed .wing-right {
  transform: rotate(-8deg) scaleY(0.85);
  transition: transform 0.25s ease;
}

/* ── body / idle bob while perched ── */
#raven.landed .body {
  animation: bob 1.8s ease-in-out infinite;
}

@keyframes bob {

  0%,
  100% {
    transform: translateY(0);
  }

  50% {
    transform: translateY(1.5px);
  }
}

/* ── tail wag while perched ── */
#raven.landed .tail {
  animation: wag 0.6s ease-in-out infinite;
  transform-box: fill-box;
  transform-origin: 0% 0%;
}

@keyframes wag {

  0%,
  100% {
    transform: rotate(-11deg);
  }

  50% {
    transform: rotate(11deg);
  }
}

/* ── peck (fires on click) ── */
#raven.pecking .body {
  animation: peck 0.32s ease-out;
}

@keyframes peck {
  0% {
    transform: translate(0, 0) rotate(0deg);
  }

  40% {
    transform: translate(-14px, 17px) rotate(-34deg);
  }

  60% {
    transform: translate(-14px, 17px) rotate(-34deg);
  }

  100% {
    transform: translate(0, 0) rotate(0deg);
  }
}

/* ── wing wave (fires alongside the peck) ──
   Overrides whatever the wings were doing (mid-flap or folded-landed) for
   the duration of the peck with a quick cheerful flap-up-and-settle. */
#raven.pecking .wing-left {
  animation: wingWaveL 0.32s ease-out;
}

#raven.pecking .wing-right {
  animation: wingWaveR 0.32s ease-out;
}

@keyframes wingWaveL {
  0% {
    transform: rotate(8deg) scaleY(0.85);
  }

  30% {
    transform: rotate(55deg) scaleY(0.55);
  }

  60% {
    transform: rotate(-12deg) scaleY(0.7);
  }

  100% {
    transform: rotate(8deg) scaleY(0.85);
  }
}

@keyframes wingWaveR {
  0% {
    transform: rotate(-8deg) scaleY(0.85);
  }

  30% {
    transform: rotate(-55deg) scaleY(0.55);
  }

  60% {
    transform: rotate(12deg) scaleY(0.7);
  }

  100% {
    transform: rotate(-8deg) scaleY(0.85);
  }
}

/* ── legs: tucked in flight, extended when perched ── */
.legs {
  transform-box: fill-box;
  transform-origin: 50% 0%;
  transition: transform 0.25s ease;
}

#raven.flying .legs {
  transform: scaleY(0.25) translateY(-2px);
  opacity: 0.6;
}

#raven.landed .legs {
  transform: scaleY(1) translateY(0);
  opacity: 1;
}

/* ── accessibility / fallbacks ── */
@media (prefers-reduced-motion: reduce) {

  #raven.flying .wing-left,
  #raven.flying .wing-right,
  #raven.landed .body,
  #raven.landed .tail,
  #raven.pecking .body,
  .raven-exploding {
    animation: none !important;
  }

  .gold-mote {
    display: none;
  }
}

/* touch devices have no real cursor — fall back to the native one entirely */
@media (hover: none),
(pointer: coarse) {

  html,
  body,
  * {
    cursor: auto !important;
  }

  #raven,
  .gold-mote {
    display: none;
  }
}
