/* Custom cursor (assets/js/cursor.js) -- round 24 total redesign,
   replacing the field-reticle entirely per direct feedback ("i dislike
   mouse and cursor style... change this to something unique... you may
   use a multicolored approach"). New shape: a small precise dot tracking
   the exact pointer position, plus 4 palette-coloured particles in
   continuous orbit around it -- the cursor's resting state is already
   colourful and in motion, not a targeting-reticle that only reacts on
   interaction. Only ever active on fine-pointer, motion-OK devices; the
   JS never runs otherwise, so this CSS has no effect elsewhere. */
html.has-custom-cursor, html.has-custom-cursor * { cursor: none !important; }

.v2-cursor-dot, .v2-cursor-cluster {
  position: fixed; top: 0; left: 0; z-index: 9999; pointer-events: none;
  opacity: 0; transition: opacity 0.2s ease;
}
.v2-cursor-dot.is-active, .v2-cursor-cluster.is-active { opacity: 1; }

.v2-cursor-dot {
  width: 5px; height: 5px; margin: -2.5px 0 0 -2.5px; border-radius: 50%;
  background: var(--v2-ink, #1a1a1a); opacity: 1;
}

/* Each particle is positioned independently every frame by JS (orbit
   maths), so the cluster container itself carries no transform of its
   own -- only the fade-in/out opacity above. */
.v2-cursor-particle {
  position: fixed; top: 0; left: 0; width: 7px; height: 7px; margin: -3.5px 0 0 -3.5px;
  border-radius: 50%; opacity: 0.85;
  transition: width 0.2s ease, height 0.2s ease, margin 0.2s ease, opacity 0.2s ease;
}

/* Hover: particles grow slightly and sit fully opaque -- "this is
   interactive" without needing a colour change, since colour is already
   the cursor's baseline identity. */
.v2-cursor-cluster.is-hovering .v2-cursor-particle { width: 9px; height: 9px; margin: -4.5px 0 0 -4.5px; opacity: 1; }

/* Press: particles shrink (the orbit itself collapses inward via JS
   radius target; this just shrinks the dots to match the tighter space). */
.v2-cursor-cluster.is-pressed .v2-cursor-particle { width: 5px; height: 5px; margin: -2.5px 0 0 -2.5px; }

/* Drag: JS flattens the orbit into an ellipse and rotates it to the drag
   angle directly via transform, so no extra CSS state is needed here
   beyond a slightly longer/thinner particle to read as "streaking". */
.v2-cursor-cluster.is-dragging .v2-cursor-particle { width: 8px; height: 5px; margin: -2.5px 0 0 -4px; opacity: 0.95; }

/* Zoom: particles pulse brighter (fully opaque, slightly larger) while
   the JS radius target does the actual in/out motion -- direction reads
   from the motion itself, no glyph needed. */
.v2-cursor-cluster.is-zooming .v2-cursor-particle { opacity: 1; width: 8px; height: 8px; margin: -4px 0 0 -4px; }

/* Text-entry: collapses to a thin vertical bar (an "I-beam companion")
   instead of the orbit -- a big cluster over a text field would obscure
   what's being read/typed. Particles fade out, the bar fades in. */
.v2-cursor-cluster.is-texting .v2-cursor-particle { opacity: 0; }
.v2-cursor-bar {
  position: fixed; top: 0; left: 0; width: 2px; height: 20px; margin: -10px 0 0 8px; border-radius: 1px;
  background: var(--v2-ink, #1a1a1a); opacity: 0; transition: opacity 0.2s ease;
}
.v2-cursor-cluster.is-texting .v2-cursor-bar { opacity: 1; }

/* Click ripple: a short-lived, independent element spawned at the click
   point -- an expanding, fading ring, the "something just happened here"
   cue a plain shrink-on-press doesn't give on its own. Unchanged concept
   from the previous cursor, since it was never the part called out as
   disliked. */
.v2-cursor-ripple {
  position: fixed; top: 0; left: 0; z-index: 9998; pointer-events: none;
  width: 8px; height: 8px; margin: -4px 0 0 -4px; border-radius: 50%;
  border: 1.5px solid var(--v2-violet, #b57cff);
  opacity: 0.8; transform: scale(1);
  animation: v2-cursor-ripple 0.5s cubic-bezier(0.22,1,0.36,1) forwards;
}
@keyframes v2-cursor-ripple {
  to { transform: scale(5.5); opacity: 0; }
}

@media (prefers-reduced-motion: reduce) {
  .v2-cursor-ripple { animation: none; display: none; }
  .v2-cursor-particle { transition: opacity 0.15s ease; }
}
