/* =====================================================================================================
   THE STRESS LADDER (js/work.js renderLadder): Retsu's face for each stage (FINE, TENSE, STORMY, THUNDER) + BURNOUT on one
   rail across a pill plate under the score, each stage in its own pastel (mint, butter, peach, coral, lavender). The stage she is in is big, hops on the beat and acts its mood; a miss is a little show
   (fuse, deflate, slam, burst, shockwave, spray). The HUD has no stress meter.
   Moods: 0 FINE sways happily · 1 TENSE glances about and sweats · 2 STORMY huffs steam on the beat ·
          3 THUNDER trembles under a flickering bolt · 4 BURNOUT sways woozy, smoking.
   ===================================================================================================== */

/* ---------- the moods (they move the face inside its round badge) ---------- */
@keyframes st-sway { 0%, 100% { transform: rotate(-7deg); } 50% { transform: rotate(7deg); } }
@keyframes st-nerv { 0%, 38%, 100% { transform: none; } 44%, 58% { transform: translateX(-2px) rotate(-5deg); } 64%, 80% { transform: translateX(2px) rotate(4deg); } }
@keyframes st-huff { 0%, 100% { transform: scale(1); } 12% { transform: scale(1.1, .9); } 30% { transform: scale(.96, 1.05); } }
@keyframes st-tremble { 0% { transform: translate(1.5px, -1px) rotate(1.5deg); } 50% { transform: translate(-1.5px, 1px) rotate(-1.5deg); } 100% { transform: translate(1px, 1px); } }
@keyframes st-woozy { 0%, 100% { transform: rotate(-11deg) translateY(2px); } 50% { transform: rotate(9deg) translateY(-1px); } }
@keyframes st-spin { to { transform: rotate(360deg); } }

/* =====================================================================================================  the ladder  */
/* the status group: CLEARED + the score, the ladder under it, one centred column (left band in landscape, under the HUD upright) */
.ww-status { position: absolute; left: 182px; top: 78px; transform: translateX(-50%); display: flex; flex-direction: column; align-items: center; gap: 16px; }
html.portrait .ww-status { left: 50%; top: 104px; gap: 18px; }

/* the plate: a soft cream sticker with a glossy top lip, tinted faintly with the colour of the stage she is in, and tall
   enough to hold the big face and its ring. Faces sit on one rail; sizes are vars so the rail's fill can be worked out. */
.ww-ladder { --sm: 40px; --big: 76px; --gap: 17px; --pad: 18px; --ring: 4px; --hop: 12px; --idle: st-sway calc(var(--beat, .5s) * 2) ease-in-out infinite;
  --hue: #5fd09a; --step: calc(var(--sm) + var(--gap));
  position: relative; display: flex; align-items: center; gap: var(--gap); padding: calc(var(--ring) + 11px) var(--pad);
  border-radius: 999px; border: 3px solid var(--ink-a);
  background: radial-gradient(120px 90px at calc(var(--pad) + var(--cur) * var(--step) + var(--big) / 2) 50%, color-mix(in srgb, var(--hue) 30%, transparent), transparent 75%),
    linear-gradient(#fffdf9, #f8ede8);
  box-shadow: inset 0 3px 0 #fff, inset 0 -5px 0 rgba(58,36,51,.07), 0 5px 0 var(--ink-a), 0 12px 22px rgba(58,36,51,.18); }
.ww-ladder.s1 { --hop: 10px; --idle: st-nerv calc(var(--beat, .5s) * 2) ease-in-out infinite; }
.ww-ladder.s2 { --hop: 16px; --idle: st-huff var(--beat, .5s) ease-out infinite; }
.ww-ladder.s3 { --hop: 7px;  --idle: st-tremble .13s steps(2) infinite; }
.ww-ladder.s4 { --hop: 0px;  --idle: st-woozy calc(var(--beat, .5s) * 3) ease-in-out infinite; }
.ww-ladder.calm { --idle: none; }

/* the rail: a recessed groove from the first face to the last; the fill runs to the centre of the face she is in, coloured
   by where it reaches (mint -> butter -> peach -> coral -> lavender) */
.ww-rail { position: absolute; left: calc(var(--pad) + var(--sm) / 2); right: calc(var(--pad) + var(--sm) / 2); top: 50%; height: 14px; margin-top: -7px; z-index: 0;
  border-radius: 999px; background: #ece3ef; border: 2.5px solid var(--ink-a); box-shadow: inset 0 3px 0 rgba(58,36,51,.14); }
.ww-fill { position: absolute; left: 0; top: 0; bottom: 0; border-radius: 999px; --len: calc(4 * var(--step) + var(--big) / 2 - var(--sm) / 2);
  width: calc(var(--cur) * var(--step) + var(--big) / 2 - var(--sm) / 2);
  background: linear-gradient(90deg, #5fd09a, #ffc23d 30%, #ff9452 55%, #ff5c7c 80%, #a88be0) 0 0 / var(--len) 100% no-repeat;
  box-shadow: inset 0 2px 0 rgba(255,255,255,.55); }
.ww-fill b { display: none; }

/* the faces: badges tinted with their stage's colour behind her; the ones still ahead wait faded */
.ww-step { position: relative; display: block; flex: none; width: var(--sm); height: var(--sm); box-sizing: border-box; border-radius: 50%;
  background: color-mix(in srgb, var(--c) 22%, #fff); border: 3px solid var(--ink-a); box-shadow: 0 3px 0 rgba(58,36,51,.35); z-index: 1; transform-origin: 50% 85%;
  animation: ww-hpop .32s cubic-bezier(.3,1.7,.5,1) calc(var(--i) * 55ms) both; }
.ww-face { position: absolute; inset: 2px; display: block; transform-origin: 50% 80%; z-index: 1; }
.ww-face .ico-svg { display: block; width: 100%; height: 100%; }
.ww-step.next { background: #f3eef5; border-color: #9c8aa0; box-shadow: none; }
.ww-step.next .ww-face { filter: grayscale(.85) opacity(.5); }
.ww-step.burn.next { border-style: dashed; }

/* the stage she is in: big, a white keyline and a ring in its colour, a soft glow behind, hopping on the beat and acting its mood */
.ww-step.cur { width: var(--big); height: var(--big); z-index: 3; background: color-mix(in srgb, var(--c) 20%, #fff);
  box-shadow: 0 0 0 3px #fff, 0 0 0 calc(var(--ring) + 3px) var(--c), 0 0 0 calc(var(--ring) + 5.5px) var(--ink-a), 0 7px 0 calc(var(--ring) + 4px) rgba(58,36,51,.22);
  animation: ww-hpop .32s cubic-bezier(.3,1.7,.5,1) calc(var(--i) * 55ms) both, st-hop var(--beat, .5s) cubic-bezier(.3,0,.3,1) .45s infinite; }
.ww-step.cur .ww-face { inset: 3px; animation: var(--idle); }
.ww-glow { position: absolute; inset: -22px; border-radius: 50%; z-index: -1; pointer-events: none;
  background: radial-gradient(circle, color-mix(in srgb, var(--c) 55%, transparent) 30%, transparent 70%); animation: st-glow calc(var(--beat, .5s) * 2) ease-in-out infinite; }
@keyframes st-glow { 0%, 100% { opacity: .55; transform: scale(.92); } 50% { opacity: 1; transform: scale(1.06); } }
@keyframes st-hop { 0%, 100% { transform: translateY(0) scale(1, 1); } 10% { transform: translateY(0) scale(1.12, .86); }
  38% { transform: translateY(calc(var(--hop) * -1)) scale(.93, 1.09); } 66% { transform: translateY(0) scale(1.08, .92); } 82% { transform: scale(.98, 1.02); } }
.s3 .ww-step.cur { animation: ww-hpop .32s cubic-bezier(.3,1.7,.5,1) calc(var(--i) * 55ms) both, st-hop calc(var(--beat, .5s) / 2) cubic-bezier(.3,0,.3,1) .45s infinite,
  st-ring .3s steps(1) infinite; }
@keyframes st-ring { 0% { box-shadow: 0 0 0 3px #fff, 0 0 0 calc(var(--ring) + 3px) var(--c), 0 0 0 calc(var(--ring) + 5.5px) var(--ink-a), 0 7px 0 calc(var(--ring) + 4px) rgba(58,36,51,.22); }
  50% { box-shadow: 0 0 0 3px #fff, 0 0 0 calc(var(--ring) + 3px) #ffe36a, 0 0 0 calc(var(--ring) + 5.5px) var(--ink-a), 0 7px 0 calc(var(--ring) + 4px) rgba(58,36,51,.22); } }

/* ---------- a miss: the rail surges on (a spark at its tip), the old face deflates, the new one slams in ---------- */
.m-hit .ww-fill { animation: st-surge .34s cubic-bezier(.5,0,.6,1) .04s both; }
@keyframes st-surge { from { width: calc(var(--prev) * var(--step) + var(--big) / 2 - var(--sm) / 2); } }
.m-hit .ww-fill b { display: block; position: absolute; right: -11px; top: 50%; width: 24px; height: 24px; margin-top: -12px; border-radius: 50%; z-index: 5;
  background: radial-gradient(circle, #fff 0 22%, #fff3a0 32%, color-mix(in srgb, var(--hue) 80%, transparent) 55%, transparent 70%); animation: st-spark .5s ease-out .04s both; }
@keyframes st-spark { 0% { transform: scale(.5); opacity: 1; } 60% { transform: scale(1.6); opacity: 1; } 100% { transform: scale(2.4); opacity: 0; } }
.ww-step.was { animation: st-was .5s cubic-bezier(.3,1.5,.5,1) both; }
@keyframes st-was { 0% { transform: scale(1.85); } 45% { transform: scale(.72, .8); } 70% { transform: scale(1.08); } 100% { transform: none; } }
.ww-step.cur.hit { animation: st-slam .55s cubic-bezier(.2,1.5,.4,1) .3s both, st-hop var(--beat, .5s) cubic-bezier(.3,0,.3,1) 1.05s infinite; }
.s3 .ww-step.cur.hit { animation: st-slam .55s cubic-bezier(.2,1.5,.4,1) .3s both, st-hop calc(var(--beat, .5s) / 2) cubic-bezier(.3,0,.3,1) 1.05s infinite, st-ring .26s steps(1) .85s infinite; }
@keyframes st-slam { 0% { transform: scale(.15) rotate(-35deg); } 40% { transform: scale(1.55) rotate(9deg); } 54% { transform: scale(1.3) translateX(-7px) rotate(-7deg); }
  66% { transform: scale(1.24) translateX(7px) rotate(5deg); } 80% { transform: scale(1.1) translateX(-3px) rotate(-2deg); } 100% { transform: none; } }
.ww-step.cur.hit .ww-face { animation: st-flash .55s ease-out .3s both, var(--idle); }
@keyframes st-flash { 0%, 25% { filter: brightness(2.4) saturate(.2); } 100% { filter: none; } }
/* the comic burst behind the face, and a shockwave ring in the stage colour */
.ww-burst { position: absolute; left: 50%; top: 50%; width: 240px; height: 240px; margin: -120px 0 0 -120px; border-radius: 50%; z-index: -1; pointer-events: none;
  background: repeating-conic-gradient(from 4deg, var(--c) 0 8deg, rgba(255,255,255,0) 8deg 21deg);
  -webkit-mask: radial-gradient(circle closest-side, transparent 0 36%, #000 38% 62%, transparent 86%); mask: radial-gradient(circle closest-side, transparent 0 36%, #000 38% 62%, transparent 86%);
  animation: st-burst .7s cubic-bezier(.2,.8,.3,1) .3s both; }
@keyframes st-burst { 0% { transform: scale(.55) rotate(0); opacity: 1; } 55% { opacity: .95; } 100% { transform: scale(1.35) rotate(28deg); opacity: 0; } }
.ww-wave { position: absolute; inset: -8px; border-radius: 50%; border: 6px solid var(--c); pointer-events: none; z-index: 4; animation: st-wave .6s ease-out .3s both; }
@keyframes st-wave { 0% { transform: scale(.6); opacity: 1; } 100% { transform: scale(2.5); opacity: 0; border-width: 1px; } }
/* the spray: drops, steam, bolts or smoke flung out of the slam (sparkles for a win) */
.ww-pt { position: absolute; left: 50%; top: 50%; width: 22px; height: 22px; margin: -11px 0 0 -11px; z-index: 5; pointer-events: none;
  animation: st-pt .8s cubic-bezier(.15,.7,.3,1) calc(.33s + var(--k, 0s)) both; }
.ww-pt svg, .ww-deco svg { display: block; width: 100%; height: 100%; overflow: visible; }
@keyframes st-pt { 0% { transform: translate(0, 0) scale(.3) rotate(0); opacity: 1; } 65% { opacity: 1; }
  100% { transform: translate(var(--dx), calc(var(--dy) + 26px)) scale(1.05) rotate(var(--r)); opacity: 0; } }
.ww-pt.soft { width: 17px; height: 17px; margin: -8.5px 0 0 -8.5px; animation-duration: .65s; animation-delay: var(--k, 0s); }

/* ---------- a win: a little phew ---------- */
.ww-step.cur.win { animation: st-phew .5s cubic-bezier(.3,1.6,.5,1) both, st-hop var(--beat, .5s) cubic-bezier(.3,0,.3,1) .55s infinite; }
@keyframes st-phew { 0% { transform: scale(1.22, .8); } 35% { transform: scale(.9, 1.14) translateY(-12px); } 65% { transform: scale(1.05, .95); } 100% { transform: none; } }

/* ---------- what each face wears ---------- */
.ww-deco { position: absolute; display: block; pointer-events: none; z-index: 2; }
.ww-step .ww-deco.drop { width: 16px; height: 21px; right: -2px; top: 8px; animation: st-drip calc(var(--beat, .5s) * 2) ease-in infinite; }
@keyframes st-drip { 0% { transform: translateY(-4px) scale(.3); opacity: 0; } 18% { transform: none; opacity: 1; } 75% { transform: translateY(26px) scale(.9, 1.12); opacity: 1; } 100% { transform: translateY(36px) scale(.6); opacity: 0; } }
.ww-step .ww-deco.puff, .ww-step .ww-deco.smoke { width: 26px; height: 19px; top: -4px; --sx: -12px; animation: st-steam calc(var(--beat, .5s) * 2) ease-out infinite; }
.ww-step .ww-deco.puff.d0, .ww-step .ww-deco.smoke.d0 { left: -14px; }
.ww-step .ww-deco.puff.d1, .ww-step .ww-deco.smoke.d1 { right: -14px; --sx: 12px; animation-delay: var(--beat, .5s); }
@keyframes st-steam { 0% { transform: translate(0, 12px) scale(.2); opacity: 0; } 22% { opacity: 1; } 100% { transform: translate(var(--sx), -34px) scale(1.2); opacity: 0; } }
.ww-step .ww-deco.smoke { width: 30px; height: 22px; animation-duration: calc(var(--beat, .5s) * 3); }
.ww-step .ww-deco.smoke.d1 { animation-delay: calc(var(--beat, .5s) * 1.5); }
.ww-step .ww-deco.bolt { width: 24px; height: 32px; right: -14px; top: -18px; animation: st-zap var(--beat, .5s) steps(1) infinite; }
@keyframes st-zap { 0% { opacity: 1; transform: rotate(14deg); } 18% { opacity: 0; } 42% { opacity: 1; transform: rotate(-8deg) scale(1.2); } 58%, 100% { opacity: 0; } }

/* ---------- one loss from BURNOUT: the plate breathes in coral, the last stretch of rail is hazard tape, BURNOUT waits ---------- */
.ww-ladder.danger { animation: st-plate calc(var(--beat, .5s) * 2) ease-in-out infinite; }
@keyframes st-plate { 0%, 100% { box-shadow: inset 0 3px 0 #fff, inset 0 -5px 0 rgba(58,36,51,.07), 0 5px 0 var(--ink-a), 0 12px 22px rgba(58,36,51,.18), 0 0 0 0 rgba(255,92,124,0); }
  50% { box-shadow: inset 0 3px 0 #fff, inset 0 -5px 0 rgba(58,36,51,.07), 0 5px 0 var(--ink-a), 0 12px 22px rgba(58,36,51,.18), 0 0 0 7px rgba(255,92,124,.35); } }
.ww-ladder.danger .ww-rail::after { content: ''; position: absolute; top: 0; bottom: 0; right: 0; border-radius: 0 999px 999px 0;
  left: calc(3 * var(--step) + var(--big) / 2 - var(--sm) / 2);
  background: repeating-linear-gradient(-45deg, #ffe36a 0 5px, #fff4c4 5px 10px); background-size: 14.14px 14.14px; animation: st-haz .7s linear infinite; }
@keyframes st-haz { to { background-position: 14.14px 0; } }
.ww-step.lure { animation: ww-hpop .32s cubic-bezier(.3,1.7,.5,1) calc(var(--i) * 55ms) both, st-lure 1.2s ease-in-out .4s infinite; }
@keyframes st-lure { 0%, 100% { transform: rotate(-6deg); } 50% { transform: rotate(6deg) scale(1.08); } }
.ww-step.lure .ww-face { filter: grayscale(.2) opacity(.9); }
.ww-step.lure::before { content: ''; position: absolute; inset: -7px; border-radius: 50%; border: 3px dashed var(--c); animation: st-spin 3s linear infinite; }
.ww-step.lure .ww-deco.smoke.d0 { width: 22px; height: 16px; top: -16px; left: 10px; right: auto; --sx: 4px; }

/* ---------- BURNOUT (GAME OVER): the plate cools to lavender; the faces keep their colour, a touch softer ---------- */
.ww-ladder.burnt { background: radial-gradient(120px 90px at calc(100% - var(--pad) - var(--big) / 2) 50%, rgba(168,139,224,.35), transparent 75%), linear-gradient(#f8f4fb, #ece4f2); }
.ww-ladder.burnt .ww-step.past .ww-face { filter: saturate(.7); }
.ww-step.burn.cur .ww-deco.smoke { top: -22px; }
.ww-step.burn.cur .ww-deco.smoke.d0 { left: 6px; --sx: -10px; }
.ww-step.burn.cur .ww-deco.smoke.d1 { right: 4px; --sx: 10px; }

/* ---------- phone held upright: a row under the score ---------- */
html.portrait .ww-ladder { --sm: 50px; --big: 92px; --gap: 22px; --pad: 22px; --ring: 5px; }

/* ---------- reduce shake: no trembling, no slamming about (the meter still reads) ---------- */
.ww-ladder.calm .ww-step.cur, .ww-ladder.calm .ww-step.cur.hit, .ww-ladder.calm .ww-step.cur.win, .ww-ladder.calm .ww-step.lure, .ww-ladder.calm .ww-step.was {
  animation: ww-hpop .32s cubic-bezier(.3,1.7,.5,1) calc(var(--i) * 55ms) both; }

/* ---------- reduced motion: the faces still read, nothing loops or flies ---------- */
@media (prefers-reduced-motion: reduce) {
  .ww-step, .ww-step.cur, .ww-step.cur.hit, .ww-step.cur.win, .ww-step.was, .ww-step.lure, .s3 .ww-step.cur, .s3 .ww-step.cur.hit { animation: ww-hpop .2s ease-out both; }
  .ww-step .ww-face, .ww-deco, .ww-ladder.danger, .ww-rail::after, .ww-fill, .ww-glow, .ww-step.lure::before { animation: none !important; }
  .ww-pt, .ww-burst, .ww-wave, .ww-fill b { display: none !important; }
}
