/* ============================================================================
   CULTURE CAVE - THE ROPE, FOR REAL
   Upgrades the descent rail from a striped gradient to a drawn rope.

   The old rope was two repeating-linear-gradients crossing each other. That
   reads as barber's pole, not as rope, because a real kernmantle sheath does
   three things a gradient cannot:
     - it is woven, so at every crossing one pick passes OVER and the next
       passes UNDER, and you can see it;
     - it is round, so the weave COMPRESSES towards the edges as the surface
       turns away from you, and the picks get narrower and darker;
     - it hangs, so it moves.
   All three need per-pixel shading and a physics step, so the rope is painted
   into a canvas by cave-rope.js. Everything else about the rail - the hit
   target, the gear markers, the scrubbing, the touch rules - is untouched.

   Additive: this only hides the old gradient. If the canvas cannot be created
   the class is never added and the gradient rope stays exactly as it was.
   ========================================================================== */

/* The canvas sits in the rope column BEHIND everything hanging off it.
   z-index:1 is above z-index:auto, so the canvas alone was painting over the
   axe, the radio and the karabiner - kit clipped to a rope has to sit in front
   of it or it looks like a photograph of a rope with stickers behind it. */
.rope-cv{position:absolute;left:0;top:0;width:100%;height:100%;
  z-index:1;pointer-events:none;display:block}
.rope.cv .rope-g{z-index:3}
.rope.cv .rope-anchor{z-index:6}

/* With the canvas up, .rope-l keeps its job as the hit target and loses its
   paint. It stays exactly where it was so every pointer handler still lines up. */
.rope.cv .rope-l{background:none;box-shadow:none;border-radius:0;
  /* a touch wider than the gradient rope was: five picks across 11px is 2.2px
     each, which is under what a screen can show cleanly */
  width:13px;margin-left:-6.5px}
@media(max-width:860px){.rope.cv .rope-l{width:9px;margin-left:-4.5px}}
.rope.cv .rope-l::after{display:none}

/* the descender rides the sway: cave-descent.js owns .rope-d's transform for
   depth, so the horizontal offset goes on a wrapper and the two compose */
/* A transformed element makes its own stacking context, so .rope-d's z-index:4
   became relative to THIS wrapper and the helmet dropped behind the canvas the
   moment the wrapper was introduced. The wrapper has to carry the z-index. */
.rope-sw{position:absolute;left:0;top:0;width:100%;height:100%;
  pointer-events:none;will-change:transform;z-index:5}
.rope.cv .rope-d{filter:drop-shadow(0 5px 9px rgba(0,0,0,.85))}

/* The rope is still, so the gear no longer needs carrying sideways with it.
   --gx is kept at 0 and the rules stay, so restoring any drift later is a
   one-line change in the script rather than a CSS reshuffle. */
.rope.cv .rope-g{transform:translateY(-50%) translateX(var(--gx,0px))}
.rope.cv .rope-g:hover,.rope.cv .rope-g:focus-visible{
  transform:translateY(-50%) translateX(var(--gx,0px)) scale(1.16)}

/* the one bit of life left: the strand warms slightly while you scrub the rail,
   which is a hover response rather than motion */
.rope-cv{transition:filter 180ms ease}
.rope.scrub .rope-cv{filter:brightness(1.08) saturate(1.05)}

@media (prefers-reduced-motion:reduce){
  .rope-cv{transition:none}
}
