/* ----------------------------------------------------------------------
   Cancer constellation
   Stars ease into position trailing light, a shockwave ring marks each
   arrival, the figure lines draw between them and then carry a travelling
   pulse, and finally the crab outline draws in behind. Star positions are
   real: RA/Dec for the seven principal stars of Cancer, projected in
   scripts/build-cancer-constellation.mjs.
   Motion is transform and opacity where it can be, so it stays smooth.
   ---------------------------------------------------------------------- */

.has-cancer{position:relative;overflow:hidden}
.has-cancer > .container{position:relative;z-index:1}

.cancer-sky{
  position:absolute;inset:0;z-index:0;
  pointer-events:none;
  overflow:hidden;
  opacity:0.5;
}
.cancer-sky svg{
  position:absolute;
  left:50%;
  top:50%;
  transform:translate(-50%,-50%);
  height:min(94%, 620px);
  width:auto;
  overflow:visible;
}
.c89-star,.c89-halo,.c89-ring,.c89-star__spikes,.c89-spike{transform-box:fill-box;transform-origin:center}

/* ---- resting appearance ---- */
/* a real point source: white-hot core, tinted glow, diffraction spikes */
.c89-core{fill:#fffdf8;opacity:0.95}
.c89-halo{opacity:0.85}
.c89-spike{opacity:0.5}
.c89-spike--x{transform:rotate(45deg);opacity:0.28}
.c89-star__spikes{opacity:0.9}
.c89-ring{fill:none;stroke-width:0.45;opacity:0}
.c89-trail{stroke-width:1;stroke-linecap:round;opacity:0}
.c89-line{stroke:rgba(150,205,235,0.3);stroke-width:0.6;stroke-linecap:round;fill:none}
.c89-pulse{
  stroke:rgba(200,240,255,0.85);stroke-width:1.15;stroke-linecap:round;fill:none;
  stroke-dasharray:5 var(--len);stroke-dashoffset:5;opacity:0;
}
.c89-crab{
  fill:none;
  stroke:rgba(165,205,240,0.17);
  stroke-width:0.5;
  stroke-linecap:round;
  stroke-linejoin:round;
}
.c89-crab-fill{fill:rgba(90,150,220,0.02);stroke:none}
.c89-limb{
  fill:none;
  stroke:rgba(165,205,240,0.19);
  stroke-width:1.7;
  stroke-linecap:round;
  stroke-linejoin:round;
}

/* ---- idle: parked off-position, nothing drawn ---- */
.cancer-sky[data-state="idle"] .c89-star__fly{opacity:0;transform:translate(var(--dx), var(--dy)) scale(0.4)}
.cancer-sky[data-state="idle"] .c89-line{stroke-dashoffset:var(--len)}
.cancer-sky[data-state="idle"] .c89-crab-group{opacity:0}

/* =====================================================================
   1. stars ease in, trailing light
   ===================================================================== */
.cancer-sky[data-state="run"] .c89-star__fly{
  animation:c89-shoot 1080ms cubic-bezier(0.16,1,0.3,1) both;
  animation-delay:calc(var(--i) * 150ms);
}
@keyframes c89-shoot{
  0%{opacity:0;transform:translate(var(--dx), var(--dy)) scale(0.35)}
  18%{opacity:1}
  100%{opacity:1;transform:translate(0,0) scale(1)}
}

/* the streak stretches on the way in and collapses as it lands */
.cancer-sky[data-state="run"] .c89-trail{
  animation:c89-trail 1080ms cubic-bezier(0.16,1,0.3,1) both;
  animation-delay:calc(var(--i) * 150ms);
}
@keyframes c89-trail{
  0%{opacity:0;stroke-width:0.5}
  14%{opacity:0.9;stroke-width:1.5}
  72%{opacity:0.42;stroke-width:1}
  100%{opacity:0;stroke-width:0.3}
}

/* a ring breaks outward the moment a star settles */
.cancer-sky[data-state="run"] .c89-ring{
  animation:c89-ring 1250ms cubic-bezier(0.16,1,0.3,1) both;
  animation-delay:calc(var(--i) * 150ms + 860ms);
}
@keyframes c89-ring{
  0%{opacity:0;transform:scale(0.25)}
  22%{opacity:0.5}
  100%{opacity:0;transform:scale(3.4)}
}

/* and the glow blooms up to its resting level */
.cancer-sky[data-state="run"] .c89-halo{
  animation:c89-flare 1200ms cubic-bezier(0.16,1,0.3,1) both;
  animation-delay:calc(var(--i) * 150ms + 780ms);
}
@keyframes c89-flare{
  0%{opacity:0;transform:scale(0.3)}
  38%{opacity:0.95;transform:scale(1.3)}
  100%{opacity:0.85;transform:scale(1)}
}

/* =====================================================================
   2. the figure joins up, once the last star has landed
   ===================================================================== */
.cancer-sky[data-state="run"] .c89-line{
  stroke-dasharray:var(--len);
  animation:c89-draw 720ms cubic-bezier(0.33,1,0.68,1) both;
  animation-delay:calc(2080ms + var(--j) * 170ms);
}
@keyframes c89-draw{
  from{stroke-dashoffset:var(--len);opacity:0.15}
  to{stroke-dashoffset:0;opacity:1}
}

/* light runs the circuit, then again every few seconds */
.cancer-sky[data-state="run"] .c89-pulse{
  animation:c89-pulse-run 7s cubic-bezier(0.45,0,0.55,1) infinite;
  animation-delay:calc(2800ms + var(--j) * 170ms);
}
@keyframes c89-pulse-run{
  0%{stroke-dashoffset:5;opacity:0}
  4%{opacity:0.75}
  20%{stroke-dashoffset:calc(-1 * var(--len));opacity:0}
  100%{stroke-dashoffset:calc(-1 * var(--len));opacity:0}
}

/* =====================================================================
   3. the crab draws in behind the figure
   ===================================================================== */
.cancer-sky[data-state="run"] .c89-crab-group{
  animation:c89-crab-in 1800ms cubic-bezier(0.33,1,0.68,1) both;
  animation-delay:3700ms;
}
.cancer-sky[data-state="run"] .c89-crab,
.cancer-sky[data-state="run"] .c89-limb{
  stroke-dasharray:var(--clen);
  animation:c89-crab-draw 2200ms cubic-bezier(0.33,1,0.68,1) both;
  animation-delay:calc(3700ms + var(--k) * 85ms);
}
@keyframes c89-crab-in{from{opacity:0}to{opacity:1}}
@keyframes c89-crab-draw{from{stroke-dashoffset:var(--clen)}to{stroke-dashoffset:0}}

/* =====================================================================
   4. it keeps breathing once it has settled
   ===================================================================== */
.cancer-sky[data-state="run"] .c89-drift,
.cancer-sky[data-state="done"] .c89-drift{
  transform-box:fill-box;transform-origin:center;
  animation:c89-drift 24s cubic-bezier(0.45,0,0.55,1) infinite alternate;
}
@keyframes c89-drift{
  from{transform:translate3d(0,4px,0) scale(0.994)}
  to{transform:translate3d(0,-4px,0) scale(1.006)}
}
/* stars scintillate: the spikes breathe a little more than the core */
.cancer-sky[data-state="run"] .c89-star__spikes{
  animation:c89-scintillate 6.2s cubic-bezier(0.45,0,0.55,1) infinite;
  animation-delay:calc(4.8s + var(--i) * 530ms);
}
@keyframes c89-scintillate{
  0%,100%{opacity:0.9;transform:scale(1) rotate(0deg)}
  50%{opacity:0.45;transform:scale(0.86) rotate(3deg)}
}
.cancer-sky[data-state="run"] .c89-core{
  animation:c89-twinkle 5.4s cubic-bezier(0.45,0,0.55,1) infinite;
  animation-delay:calc(5.4s + var(--i) * 480ms);
}
@keyframes c89-twinkle{0%,100%{opacity:0.95}50%{opacity:0.68}}

/* the spikes flare open as the star arrives */
.cancer-sky[data-state="run"] .c89-star__spikes{
  animation:c89-spike-in 1400ms cubic-bezier(0.16,1,0.3,1) both,
            c89-scintillate 6.2s cubic-bezier(0.45,0,0.55,1) infinite;
  animation-delay:calc(var(--i) * 150ms + 720ms), calc(4.8s + var(--i) * 530ms);
}
@keyframes c89-spike-in{
  0%{opacity:0;transform:scale(0.1) rotate(-25deg)}
  45%{opacity:1;transform:scale(1.25) rotate(4deg)}
  100%{opacity:0.9;transform:scale(1) rotate(0deg)}
}

/* ---- finished state: reduced motion, and anything that skips the run ---- */
.cancer-sky[data-state="done"] .c89-star__fly{opacity:1;transform:translate(0,0) scale(1)}
.cancer-sky[data-state="done"] .c89-trail,
.cancer-sky[data-state="done"] .c89-ring,
.cancer-sky[data-state="done"] .c89-pulse{opacity:0}
.cancer-sky[data-state="done"] .c89-halo{opacity:0.85}
.cancer-sky[data-state="done"] .c89-line{stroke-dashoffset:0}
.cancer-sky[data-state="done"] .c89-crab-group{opacity:1}
.cancer-sky[data-state="done"] .c89-crab,
.cancer-sky[data-state="done"] .c89-limb{stroke-dashoffset:0}

@media(prefers-reduced-motion:reduce){
  .cancer-sky[data-state="run"] *{animation:none !important}
  .cancer-sky[data-state="run"] .c89-star__fly{opacity:1;transform:translate(0,0) scale(1)}
  .cancer-sky[data-state="run"] .c89-trail,
  .cancer-sky[data-state="run"] .c89-ring,
  .cancer-sky[data-state="run"] .c89-pulse{opacity:0}
  .cancer-sky[data-state="run"] .c89-halo{opacity:0.85}
  .cancer-sky[data-state="run"] .c89-line{stroke-dashoffset:0}
  .cancer-sky[data-state="run"] .c89-crab-group{opacity:1}
  .cancer-sky[data-state="run"] .c89-crab,
  .cancer-sky[data-state="run"] .c89-limb{stroke-dashoffset:0}
}

/* ---- placement: the timeline is a 700px column on the left, so on wide
   screens the constellation sits out in the open space to its right ---- */
@media(min-width:1100px){
  .cancer-sky svg{
    left:auto;
    right:3%;
    transform:translateY(-50%);
    height:min(88%, 660px);
  }
}
@media(max-width:1099px){
  .cancer-sky{opacity:0.26}
}
@media(max-width:900px){
  .cancer-sky{opacity:0.2}
  .cancer-sky svg{height:min(86%, 430px)}
}
