/* DharmaChart Wheel — motion + reveal animations.

   Required by wheel-real.jsx. Imported once on /welcome.

   Motion is split into six dialable streams, each tied to a tweak:
     • Pearl breath   — per-planet (NOT the whole wheel)
     • Orbital dust    — slow ambient drift outside the rim
     • Aspect shimmer  — aspect lines breathe their opacity
     • Star twinkle    — band stars + constellation stars flicker
     • Center pulse    — slow heartbeat ring from center
     • Sign band flow  — slow rotating highlight around the rim

   Intensity is controlled via CSS custom properties set by the wheel host;
   speed by another property. Setting intensity to 0 lets the element render
   without the class entirely (cheaper).
*/

.dc-wheel-host {
  position: relative;
  display: inline-block;
  line-height: 0;
}

.dc-wheel {
  user-select: none;
  -webkit-user-select: none;
}

/* ────────────  Per-planet shift (demo chapter)  ──────────── */
/* Each planet is wrapped in a rotation group so the demo's year scrubber
   can spin each body at its own orbital rate. Smooth transition so the
   movement reads as orbital drift, not a snap. */
.dc-planet-shift {
  transform-box: view-box;
  transform-origin: 200px 200px;
  transition: transform 520ms var(--ease-meditative, cubic-bezier(0.25, 0.1, 0.25, 1));
  will-change: transform;
}

/* ────────────  Transit ring rotation  ──────────── */
/* The outer (today's-sky) planet ring rotates as the day-ruler is scrubbed
   in the transits chapter. Smooth transition so the scrub feels mechanical
   rather than jerky. */
.dc-transit-rot {
  transform-box: view-box;
  transform-origin: 200px 200px;
  transition: transform 320ms var(--ease-meditative, cubic-bezier(0.25, 0.1, 0.25, 1));
  will-change: transform;
}

/* ────────────  Ayanamsa rotation  ──────────── */
/* The sign band + ticks + houses rotate together when the ayanamsa changes
   (Tropical ↔ Sidereal lens flip). Planets and ASC/MC tick don't rotate —
   what changes is which sign sits behind them. Smooth transition reads as a
   real lens swap rather than a hard cut. */
.dc-band-rot {
  transform-box: view-box;
  transform-origin: 200px 200px;
  transition: transform 700ms var(--ease-meditative, cubic-bezier(0.25, 0.1, 0.25, 1));
  will-change: transform;
}

/* ────────────  Pearl breath (PER PLANET)  ──────────── */
.dc-planet-breathe {
  transform-box: fill-box;
  transform-origin: center;
  animation: dc-pearl-breathe var(--dc-breathe-duration, 5s) ease-in-out infinite;
}
@keyframes dc-pearl-breathe {
  0%, 100% { transform: scale(1.000); }
  50%      { transform: scale(1.045); }
}

/* ────────────  Orbital dust  ────────────
   All three velocity layers rotate the same direction (clockwise). */
.dc-dust {
  transform-origin: 200px 200px;
  animation: dc-dust-rotate var(--dc-dust-duration, 60s) linear infinite;
}
@keyframes dc-dust-rotate {
  from { transform: rotate(0deg); }
  to   { transform: rotate(360deg); }
}
.dc-dust-counter {
  transform-origin: 200px 200px;
  animation: dc-dust-rotate var(--dc-dust-duration-slow, 95s) linear infinite;
}
.dc-dust-slow {
  transform-origin: 200px 200px;
  animation: dc-dust-rotate var(--dc-dust-duration-slowest, 180s) linear infinite;
}
.dc-dust > circle,
.dc-dust-counter > circle,
.dc-dust-slow > circle {
  transform-box: fill-box;
  transform-origin: center;
  animation: dc-dust-bop 3.6s ease-in-out infinite;
}
@keyframes dc-dust-bop {
  0%, 100% { transform: scale(0.55); }
  50%      { transform: scale(1.35); }
}

/* ────────────  Aspect shimmer  ──────────── */
.dc-wheel-host[data-shimmer="on"] .dc-aspect-line {
  animation: dc-aspect-shimmer-anim var(--dc-shimmer-duration, 4s) ease-in-out infinite;
}
@keyframes dc-aspect-shimmer-anim {
  0%, 100% { stroke-opacity: var(--dc-shimmer-low, 0.55); }
  50%      { stroke-opacity: 1; }
}
.dc-wheel-host[data-shimmer="on"] .dc-aspect-line:nth-child(2n)   { animation-delay: -0.8s; }
.dc-wheel-host[data-shimmer="on"] .dc-aspect-line:nth-child(3n)   { animation-delay: -1.5s; }
.dc-wheel-host[data-shimmer="on"] .dc-aspect-line:nth-child(5n)   { animation-delay: -2.3s; }
.dc-wheel-host[data-shimmer="on"] .dc-aspect-line:nth-child(7n)   { animation-delay: -3.1s; }

/* ────────────  Star twinkle  ──────────── */
.dc-wheel-host[data-twinkle="on"] circle[data-star] {
  animation: dc-twinkle-anim var(--dc-twinkle-duration, 3.4s) ease-in-out infinite;
}
@keyframes dc-twinkle-anim {
  0%, 100% { opacity: var(--dc-twinkle-low, 0.5); }
  50%      { opacity: 1; }
}
.dc-wheel-host[data-twinkle="on"] circle[data-star]:nth-of-type(2n)  { animation-delay: -0.9s; }
.dc-wheel-host[data-twinkle="on"] circle[data-star]:nth-of-type(3n)  { animation-delay: -1.7s; }
.dc-wheel-host[data-twinkle="on"] circle[data-star]:nth-of-type(5n)  { animation-delay: -2.6s; }
.dc-wheel-host[data-twinkle="on"] circle[data-star]:nth-of-type(7n)  { animation-delay: -3.4s; }
.dc-wheel-host[data-twinkle="on"] circle[data-star]:nth-of-type(11n) { animation-delay: -4.1s; }

/* ────────────  Center pulse  ──────────── */
.dc-center-pulse {
  transform-box: fill-box;
  transform-origin: center;
  animation: dc-center-pulse-anim var(--dc-pulse-duration, 6s) ease-out infinite;
  pointer-events: none;
}
@keyframes dc-center-pulse-anim {
  0%   { transform: scale(0.6); opacity: 0.6; }
  100% { transform: scale(2.4); opacity: 0; }
}

/* ────────────  Sign band flow  ──────────── */
.dc-band-flow {
  transform-origin: 200px 200px;
  animation: dc-band-flow-anim var(--dc-flow-duration, 22s) linear infinite;
  pointer-events: none;
}
@keyframes dc-band-flow-anim {
  from { transform: rotate(0deg); }
  to   { transform: rotate(360deg); }
}

/* ────────────  Aspect line ambient entry + highlighted pulse  ──────────── */
.dc-aspect-line {
  animation: dc-aspect-in 1.2s var(--ease-meditative, cubic-bezier(0.25, 0.1, 0.25, 1)) both;
}
@keyframes dc-aspect-in {
  from { opacity: 0; }
  to   { opacity: 1; }
}
.dc-aspect-pulse {
  animation: dc-aspect-pulse 2.4s ease-in-out infinite;
}
@keyframes dc-aspect-pulse {
  0%, 100% { stroke-opacity: 0.7; }
  50%      { stroke-opacity: 1; }
}

/* ────────────  Reveal — chart materializing organically  ────────────
   When a layer mounts (state goes loading → rest), it appears via a slow
   opacity + blur softening. No spring, no pop — the chart is DRAWN in. */
@keyframes dc-reveal-soft {
  0%   { opacity: 0; filter: blur(3px); }
  100% { opacity: 1; filter: blur(0); }
}
@keyframes dc-reveal-resolve {
  0%   { opacity: 0; filter: blur(8px); }
  50%  { opacity: 0.7; filter: blur(3px); }
  100% { opacity: 1; filter: blur(0); }
}
@keyframes dc-reveal-draw {
  0%   { stroke-dashoffset: 600; opacity: 0; }
  20%  { opacity: 0.6; }
  100% { stroke-dashoffset: 0; opacity: 1; }
}

.dc-reveal-rim    { animation: dc-reveal-soft 1.1s ease-out 0s    both; }
.dc-reveal-band   { animation: dc-reveal-soft 1.4s ease-out 0.2s  both; }
.dc-reveal-ticks  { animation: dc-reveal-soft 0.9s ease-out 0.65s both; }
.dc-reveal-houses { animation: dc-reveal-soft 1.0s ease-out 0.9s  both; }
.dc-reveal-asc    { animation: dc-reveal-soft 0.7s ease-out 1.25s both; }
.dc-reveal-center { animation: dc-reveal-soft 0.9s ease-out 1.4s  both; }
.dc-reveal-shadow { animation: dc-reveal-soft 1.4s ease-out 0.4s  both; }
.dc-reveal-dust   { animation: dc-reveal-soft 2.0s ease-out 0.8s  both; }

.dc-reveal-planet {
  animation: dc-reveal-resolve 1.2s ease-out both;
}
.dc-reveal-aspect {
  stroke-dasharray: 600;
  animation: dc-reveal-draw 1.6s cubic-bezier(0.4, 0, 0.2, 1) both;
}

/* ────────────  Loading skeleton — the chart drawing itself  ──────────── */
.dc-skel-pulse {
  transform-box: fill-box;
  transform-origin: center;
  animation: dc-skel-pulse-anim 2.6s ease-in-out infinite;
}
@keyframes dc-skel-pulse-anim {
  0%, 100% { transform: scale(0.85); opacity: 0.5; }
  50%      { transform: scale(1.15); opacity: 1; }
}

.dc-skel-trace-rim {
  animation: dc-skel-trace-anim 2.2s cubic-bezier(0.4, 0, 0.2, 1) 0.2s forwards;
}
.dc-skel-trace-rim-inner {
  animation: dc-skel-trace-anim 2.0s cubic-bezier(0.4, 0, 0.2, 1) 0.7s forwards;
}
@keyframes dc-skel-trace-anim {
  to { stroke-dashoffset: 0; }
}

.dc-skel-dot {
  transform-box: fill-box;
  transform-origin: center;
  opacity: 0;
  animation: dc-skel-dot-anim 0.7s cubic-bezier(0.3, 1.4, 0.4, 1) forwards;
}
@keyframes dc-skel-dot-anim {
  0%   { opacity: 0; transform: scale(0); }
  60%  { opacity: 1; transform: scale(1.3); }
  100% { opacity: 1; transform: scale(1); }
}

.dc-skel-tick {
  opacity: 0;
  animation: dc-skel-tick-anim 0.5s ease-out forwards;
}
@keyframes dc-skel-tick-anim {
  from { opacity: 0; stroke-width: 1.4; }
  to   { opacity: var(--tick-op, 0.55); }
}

.dc-skel-spoke {
  stroke-dasharray: 200;
  stroke-dashoffset: 200;
  animation: dc-skel-spoke-anim 0.9s ease-out forwards;
}
@keyframes dc-skel-spoke-anim {
  to { stroke-dashoffset: 0; }
}

.dc-skel-scan {
  transform-origin: 200px 200px;
  opacity: 0;
  animation: dc-skel-scan-anim 3.6s cubic-bezier(0.55, 0, 0.45, 1) infinite,
             dc-skel-fade-in 0.8s ease-out 3.2s forwards;
}
@keyframes dc-skel-scan-anim {
  from { transform: rotate(0deg); }
  to   { transform: rotate(360deg); }
}
@keyframes dc-skel-fade-in {
  to { opacity: 1; }
}

.dc-skel-text {
  opacity: 0;
  animation: dc-skel-text-anim 2.4s ease-in-out 3.5s infinite;
}
@keyframes dc-skel-text-anim {
  0%, 100% { opacity: 0.35; }
  50%      { opacity: 0.75; }
}

.dc-skeleton {
  animation: dc-skeleton-spin 14s linear infinite;
  transform-origin: 200px 200px;
}
@keyframes dc-skeleton-spin {
  from { transform: rotate(0); }
  to   { transform: rotate(360deg); }
}

.dc-aspect-line[style*="pointer"]:hover {
  stroke-opacity: 1 !important;
  stroke-width: 1.6;
}

@media (prefers-reduced-motion: reduce) {
  .dc-planet-breathe, .dc-dust, .dc-dust-counter, .dc-dust-slow,
  .dc-center-pulse, .dc-band-flow,
  .dc-aspect-pulse, .dc-skeleton, .dc-aspect-line,
  .dc-reveal-rim, .dc-reveal-band, .dc-reveal-ticks, .dc-reveal-houses,
  .dc-reveal-asc, .dc-reveal-center, .dc-reveal-shadow, .dc-reveal-dust,
  .dc-reveal-planet, .dc-reveal-aspect,
  .dc-skel-pulse, .dc-skel-trace-rim, .dc-skel-trace-rim-inner,
  .dc-skel-dot, .dc-skel-tick, .dc-skel-spoke, .dc-skel-scan, .dc-skel-text,
  .dc-wheel-host[data-shimmer="on"] .dc-aspect-line,
  .dc-wheel-host[data-twinkle="on"] circle[data-star] {
    animation: none !important;
  }
}

/* dc-instant — BakedWheel swaps the live wheel in OVER the baked image when the
   page comes to rest. Kill only the one-shot DRAW-IN (reveal + skeleton) so the
   wheel appears instantly full (seamless over the identical image, no faint
   mid-reveal flash). Continuous motion (breathe / dust / twinkle / pulse) is
   intentionally left running, so the chart is still alive once you settle. */
.dc-instant .dc-reveal-rim, .dc-instant .dc-reveal-band, .dc-instant .dc-reveal-ticks,
.dc-instant .dc-reveal-houses, .dc-instant .dc-reveal-asc, .dc-instant .dc-reveal-center,
.dc-instant .dc-reveal-shadow, .dc-instant .dc-reveal-dust, .dc-instant .dc-reveal-planet,
.dc-instant .dc-reveal-aspect, .dc-instant .dc-skeleton,
.dc-instant .dc-skel-pulse, .dc-instant .dc-skel-trace-rim, .dc-instant .dc-skel-trace-rim-inner,
.dc-instant .dc-skel-dot, .dc-instant .dc-skel-tick, .dc-instant .dc-skel-spoke,
.dc-instant .dc-skel-scan, .dc-instant .dc-skel-text {
  animation: none !important;
}
