/* ============================================================
   Custom cursor: a white stage microphone (desktop, fine pointer only)
   Owner: js/v3/components/cursor.js, js/v3/components/magnetic.js

   Layers (markup in index.html, unchanged)
   - .cursor__dot   : the microphone, 28px, artwork assets/images/cursor-mic.svg.
                      Position, tilt and scale are ONE transform written per
                      frame by cursor.js: never put a transition on transform here.
   - .cursor__ring  : the pink light pool on the mic head (same damped position);
                      size / brightness per state, ::after is the press pulse.
   - .cursor-trail  : canvas with a short additive pink light trail.

   Everything is hidden (opacity 0) until cursor.js adds body.has-cursor.
   State classes live on .cursor: is-hidden, is-press, is-pulse and one of
   is-hover / is-text / is-media / is-input.

   Notes
   - .cursor is display:contents on purpose. A position:fixed wrapper
     creates a stacking context, which would isolate the glow's
     mix-blend-mode from the page. Each layer is fixed on its own.
   - left/top are physical on purpose: clientX/clientY are measured
     from the left edge whatever the writing direction, so logical
     inset properties would mirror the cursor in RTL.
   - transform-origin is 0 0 on both layers: the JS transform ends with
     a translate(-hotspot) so rotate / scale pivot on the mic head.
   ============================================================ */
:root {
  --cursor-size: 28px;
  --cursor-glow-size: 54px;
  --cursor-glow-hover-size: 76px;
  --cursor-glow-media-size: 86px;
  --cursor-pink: var(--magenta-glow, #ff8fbb);
  --cursor-magenta: var(--magenta, #d64a7c);
}

.cursor { display: contents; }

.cursor__dot,
.cursor__ring,
.cursor-trail {
  position: fixed;
  top: 0;
  left: 0;
  pointer-events: none;
  opacity: 0;
}

/* --- trail canvas: additive light, under the glow --- */
.cursor-trail {
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: calc(var(--z-cursor) - 2);
  mix-blend-mode: screen;
  transition: opacity .8s var(--ease-soft);
}

/* --- the microphone --- */
.cursor__dot {
  z-index: var(--z-cursor);
  width: var(--cursor-size);
  height: var(--cursor-size);
  transform-origin: 0 0;
  background: url("../assets/images/cursor-mic.svg") center / contain no-repeat;
  /* a hint of shadow under the white so it still reads on white video frames */
  filter: drop-shadow(0 1px 1.5px rgba(0, 0, 0, .45));
  will-change: transform;
  transition: opacity var(--dur-fast) var(--ease-out);
}

/* --- the light pool on the head --- */
.cursor__ring {
  z-index: calc(var(--z-cursor) - 1);
  width: var(--cursor-glow-size);
  height: var(--cursor-glow-size);
  border-radius: 50%;
  transform-origin: 0 0;
  background: radial-gradient(
    circle,
    rgba(255, 143, 187, .62) 0%,
    rgba(239, 109, 156, .34) 30%,
    rgba(214, 74, 124, .12) 52%,
    rgba(214, 74, 124, 0) 70%
  );
  mix-blend-mode: screen;
  will-change: transform;
  transition:
    width var(--dur-fast) var(--ease-out),
    height var(--dur-fast) var(--ease-out),
    opacity var(--dur-fast) var(--ease-out);
}

/* press pulse: its own element, so its transform never collides with the JS one */
.cursor__ring::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(255, 143, 187, .7) 0%, rgba(255, 143, 187, .25) 40%, rgba(255, 143, 187, 0) 66%);
  opacity: 0;
  transform: scale(.5);
}
.cursor.is-pulse .cursor__ring::after { animation: cursor-pulse .6s var(--ease-out) both; }
@keyframes cursor-pulse {
  0%   { opacity: .95; transform: scale(.5); }
  100% { opacity: 0;   transform: scale(1.8); }
}

/* label under the mic (is-media): "צפייה" */
.cursor__label {
  position: absolute;
  top: 100%;
  left: 50%;
  display: block;
  font-family: var(--font-body);
  font-weight: 500;
  font-size: 0.7rem;
  line-height: 1;
  letter-spacing: 0.18em;
  text-indent: 0.18em; /* optical centring: compensates the trailing tracking */
  color: var(--ivory);
  text-shadow: var(--outline);
  white-space: nowrap;
  opacity: 0;
  transform: translate(-50%, -6px) scale(0.8);
  transition:
    opacity var(--dur-fast) var(--ease-out),
    transform var(--dur-fast) var(--ease-out);
}

/* --- shown only once the module has taken over the pointer --- */
body.has-cursor .cursor__dot { opacity: 1; }
body.has-cursor .cursor__ring { opacity: .72; }
body.has-cursor .cursor-trail { opacity: 1; }

/* --- states --- */
/* hover: links, buttons, magnetic elements, moments: mic scales 1.18 (JS), glow opens and brightens */
body.has-cursor .cursor.is-hover .cursor__ring,
body.has-cursor .cursor.is-media .cursor__ring {
  width: var(--cursor-glow-hover-size);
  height: var(--cursor-glow-hover-size);
  opacity: 1;
}

/* text: quiet glow, the mic stays */
body.has-cursor .cursor.is-text .cursor__ring { opacity: .55; }

/* text inputs: the mic steps back so the native caret UI stays usable */
body.has-cursor .cursor.is-input .cursor__dot { opacity: .35; }
body.has-cursor .cursor.is-input .cursor__ring { opacity: .2; }

/* media: hover look, larger pool, label */
body.has-cursor .cursor.is-media .cursor__ring {
  width: var(--cursor-glow-media-size);
  height: var(--cursor-glow-media-size);
}
.cursor.is-media .cursor__label { opacity: 1; transform: translate(-50%, 2px) scale(1); }

/* press: the mic dips 8% (JS); the pool tightens while the pulse rings out */
body.has-cursor .cursor.is-press .cursor__ring { opacity: 1; }

/* hidden: pointer left the window / over an iframe / before the first move */
body.has-cursor .cursor.is-hidden .cursor__dot,
body.has-cursor .cursor.is-hidden .cursor__ring { opacity: 0; }

/* --- native cursor ---
   base.css hides it on body / a / button under body.has-cursor (fine pointers
   only: has-cursor is never set on touch). Text fields keep the I-beam under
   the faded mic, and html.is-touch / coarse pointers keep every native cursor. */
body.has-cursor input,
body.has-cursor textarea,
body.has-cursor select,
body.has-cursor [contenteditable=""],
body.has-cursor [contenteditable="true"] { cursor: auto; }
html.is-touch body.has-cursor,
html.is-touch body.has-cursor a,
html.is-touch body.has-cursor button { cursor: auto; }
@media (pointer: coarse), (hover: none) {
  body.has-cursor,
  body.has-cursor a,
  body.has-cursor button { cursor: auto; }
}

/* --- magnetic elements ---
   GSAP drives transform inline every frame; .btn's CSS transition list
   includes transform, which would chase every write. Drop transform
   from the list for magnetised buttons only (magnetic.js adds
   .is-magnetic). The press feel is handled by GSAP instead of :active. */
.btn.is-magnetic {
  transition-property: color, border-color, background-color, box-shadow;
}
.caction.is-magnetic {
  transition-property: border-color, background-color;
}

/* --- reduced motion: the mic is still shown, but nothing swings or pulses --- */
@media (prefers-reduced-motion: reduce) {
  .cursor.is-pulse .cursor__ring::after { animation: none; }
  .cursor__ring,
  .cursor__label { transition: none; }
}

/* --- safety nets: never on touch / coarse pointers --- */
.cursor.is-off .cursor__dot,
.cursor.is-off .cursor__ring,
.cursor-trail.is-off { display: none; }
@media (pointer: coarse), (hover: none) {
  .cursor__dot,
  .cursor__ring,
  .cursor-trail { display: none; }
}
