/* ============================================================
   ASHBOURNE — Motion system
   Every loop reads as a machine DOING something: scanning,
   calibrating, acquiring, transmitting. Irregular timing over
   obvious constant loops. All silenced under reduced-motion.
   ============================================================ */

/* sweep a line/band down or across a field */
@keyframes ash-scan-y { 0% { transform: translateY(-110%) } 55% { transform: translateY(110%) } 100% { transform: translateY(110%) } }
@keyframes ash-scan-x { 0% { transform: translateX(-110%) } 55% { transform: translateX(110%) } 100% { transform: translateX(110%) } }

/* counter-rotating ring segments */
@keyframes ash-orbit { to { transform: rotate(360deg) } }
@keyframes ash-orbit-rev { to { transform: rotate(-360deg) } }

/* irregular status blink — pauses, not a metronome */
@keyframes ash-lamp {
  0%, 46% { opacity: 1 }
  50%, 54% { opacity: 0.15 }
  58%, 72% { opacity: 1 }
  76% { opacity: 0.15 }
  80%, 100% { opacity: 1 }
}

/* pixel cell arriving */
@keyframes ash-pixel-pop { 0% { opacity: 0; transform: scale(0.3) } 60% { opacity: 1; transform: scale(1) } 100% { opacity: 1; transform: scale(1) } }

/* hazard stripes travelling */
@keyframes ash-stripe-drift { to { background-position: 56px 0 } }

/* SVG line drawing itself */
@keyframes ash-draw { to { stroke-dashoffset: 0 } }

/* reticle locking onto a target */
@keyframes ash-acquire {
  0%, 8% { transform: scale(1.35); opacity: 0.35 }
  30%, 78% { transform: scale(1); opacity: 1 }
  92%, 100% { transform: scale(1.35); opacity: 0.35 }
}

/* raster flicker for grids */
@keyframes ash-flicker { 0%, 100% { opacity: 0.5 } 42% { opacity: 0.5 } 46% { opacity: 0.95 } 50% { opacity: 0.6 } 72% { opacity: 0.85 } 76% { opacity: 0.5 } }

/* calibration tick travelling along a rule */
@keyframes ash-tick-run { 0% { left: 0 } 100% { left: 100% } }

.ash-scan-y { animation: ash-scan-y 4.2s cubic-bezier(.4,0,.2,1) infinite }
.ash-scan-x { animation: ash-scan-x 5.4s cubic-bezier(.4,0,.2,1) infinite }
.ash-orbit { animation: ash-orbit 9s linear infinite; transform-origin: 50% 50% }
.ash-orbit-rev { animation: ash-orbit-rev 14s linear infinite; transform-origin: 50% 50% }
.ash-lamp { animation: ash-lamp 3.4s steps(1, end) infinite }
.ash-stripe { animation: ash-stripe-drift 3.2s linear infinite }
.ash-acquire { animation: ash-acquire 5.6s cubic-bezier(.4,0,.2,1) infinite; transform-origin: 50% 50% }
.ash-flicker { animation: ash-flicker 6s steps(1, end) infinite }
.ash-draw { stroke-dasharray: var(--ash-len, 240); stroke-dashoffset: var(--ash-len, 240); animation: ash-draw 2.4s var(--ease-out) forwards }

/* ---------- Declarative layer (motion/ash-motion.js) ----------
   The classes ash-motion.js adds. They are CSS keyframes and transitions on
   purpose: CSS keeps running in a hidden document where requestAnimationFrame
   is suspended, so an entrance can never leave content parked out of sight.
   Every resting state here is the visible state. */
@keyframes ash-boot-open { from { transform: scaleY(0.02) } to { transform: none } }
@keyframes ash-lift-in { from { opacity: 0; transform: translateY(var(--ash-shift, 16px)) } to { opacity: 1; transform: none } }

.ash-anim-boot { animation: ash-boot-open 380ms var(--ease-out) both }
.ash-anim-in { animation: ash-lift-in 460ms var(--ease-out) both; animation-delay: calc(var(--i, 0) * var(--ash-each, 50ms)) }
/* Inside a booting panel the contents wait for the housing to finish opening. */
.ash-anim-boot > .ash-anim-in { animation-delay: calc(240ms + var(--i, 0) * var(--ash-each, 50ms)) }

/* Pointer-driven states: transitions, so they need no animation clock. */
.ash-anim-magnet { transition: transform var(--dur-mid) var(--ease-snap), box-shadow var(--dur-mid) var(--ease-snap) }
.ash-anim-tilt { transition: transform 280ms var(--ease-out) }
.ash-anim-drift { will-change: transform }

/* ---------- Responsive ornament control ---------- */
/* Decorative graphics step down on small screens so hierarchy survives. */
@media (max-width: 640px) {
  .ash-hide-sm { display: none !important }
  .ash-quiet-sm { opacity: 0.5 }
}
@media (max-width: 1024px) {
  .ash-hide-md { display: none !important }
}

@media (prefers-reduced-motion: reduce) {
  .ash-scan-y, .ash-scan-x, .ash-orbit, .ash-orbit-rev,
  .ash-lamp, .ash-acquire, .ash-flicker, .ash-draw, .ash-stripe,
  .ash-anim-boot, .ash-anim-in {
    animation: none !important;
  }
  .ash-anim-magnet, .ash-anim-tilt { transition: none !important }
  .ash-draw { stroke-dashoffset: 0 }
}
