/*
 * Cursori live degli altri operatori. Vivono nel layer mondo (#canvas-world), in
 * coordinate mondo: pan e zoom del canvas li trasformano insieme al board. Per
 * restare di dimensione fissa a schermo a ogni zoom, ogni cursore si
 * contro-scala con `--vp-zoom-inv` (l'inverso dello zoom, scritto sul canvas dal
 * Viewport), con l'origine sulla punta della freccia.
 *
 * Il colore del peer arriva runtime in `--cursor-color` (dal roster); qui non è
 * mai hardcoded. I cursori sono decorativi: non intercettano i pointer, così non
 * rubano click al board sotto.
 */

.cursors {
  position: absolute;
  top: 0;
  left: 0;
  width: 0;
  height: 0;
  /* Decorativo: non ruba i pointer al board sotto. */
  pointer-events: none;
  /* Stessa trasformazione del mondo (#canvas-world): così i figli, posizionati in
     coordinate mondo, seguono pan e zoom identici ai frame — ma questo layer è
     fuori da #canvas-world, fratello dopo di esso, con z-index alto: nessuna
     schermata può coprirlo. È il modo di tenere i cursori "sopra tutto" senza
     dipendere dallo stacking dei frame. */
  transform-origin: 0 0;
  transform: translate3d(var(--vp-x, 0px), var(--vp-y, 0px), 0) scale(var(--vp-zoom, 1));
  will-change: transform;
  z-index: 100;
}

.cursor {
  position: absolute;
  top: 0;
  left: 0;
  /* `translate` (px mondo, dal renderer) posiziona; `scale` contro-scala lo zoom.
     Sono proprietà distinte così non si calpestano. Origine in alto-sinistra: la
     punta della freccia indica il punto mondo esatto a ogni zoom. */
  transform-origin: 0 0;
  scale: var(--vp-zoom-inv, 1);
  will-change: translate, scale;
  /* Micro-smoothing sulla posizione: il tick arriva a ~20/s, la transizione breve
     ammorbidisce lo scatto tra un frame e l'altro senza latenza percepibile. */
  transition: translate 60ms linear;
}

.cursor__arrow {
  display: block;
  filter: drop-shadow(0 1px 1px rgb(0 0 0 / 35%));
}

/*
 * Il proprio cursore mostra solo la bolla della chat: la freccia si nasconde,
 * perché il puntatore vero è quello di sistema. La bolla resta ancorata dov'è la
 * freccia (a top:30px dal punto), quindi appare appena sotto il cursore di sistema.
 */
.cursor--self {
  z-index: 1;
}

.cursor--self .cursor__arrow {
  display: none;
}

/* Sul proprio cursore la freccia è nascosta: la bolla può stare più vicina alla
   punta del puntatore di sistema, senza rischio di coprirlo. */
.cursor--self .cursor__chat {
  top: 14px;
  left: 12px;
}

/*
 * La bolla della chat sul cursore, identica per il proprio e per quello dei peer.
 * Sotto la freccia, sul colore del cursore. Cresce col contenuto (larghezza auto,
 * righe che si impilano). Angolo alto-sinistra **appuntito**, gli altri tre
 * stondati — come Figma, la punta "esce" dalla freccia. Compare solo se c'è testo.
 */
.cursor__chat {
  position: absolute;
  /* Distanza dalla punta. Sui **peer** la freccia è disegnata, quindi la bolla sta
     più in basso per non coprirla; sul **proprio** cursore la freccia è nascosta
     (c'è quello di sistema), quindi la si tiene più vicina — la regola self la
     rialza. */
  top: 24px;
  left: 8px;
  display: block;
  max-width: 280px;
  width: max-content;
  padding: 6px 11px;
  /* Appuntito in alto a sinistra, tondo altrove. */
  border-radius: 2px var(--radius-lg) var(--radius-lg) var(--radius-lg);
  background: var(--cursor-color, var(--border-strong));
  color: #fff;
  font-size: var(--text-sm);
  line-height: 1.4;
  text-shadow: 0 1px 1px rgb(0 0 0 / 30%);
  box-shadow: var(--shadow-frame);
  /* I ghost escono dalla bolla verso l'alto: non devono essere tagliati. */
  overflow: visible;
}

.cursor__chat[hidden] {
  display: none;
}

/*
 * La riga corrente: **una sola**, quindi la bolla ha altezza costante e il testo
 * che stai scrivendo non si sposta mai. Cresce solo in larghezza col contenuto,
 * e manda a capo da sé quando supera il massimo.
 */
.cursor__chat-line {
  display: block;
  min-height: 1.4em;
  /* Larghezza minima: quella che occupa il placeholder ("Scrivi qualcosa…", 17
     caratteri). Così la bolla non si restringe sotto quella misura mentre si
     scrive, e non balla a ogni carattere cancellato. */
  min-width: 17ch;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

/*
 * Le righe completate: volano **sopra** la bolla, senza occuparne lo spazio
 * (posizione assoluta), salgono e svaniscono in circa un secondo. È l'effetto
 * "scorre verso l'alto" mentre il campo dove scrivi resta fermo.
 */
.cursor__chat-ghosts {
  position: absolute;
  bottom: calc(100% - 2px);
  left: 0;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  width: max-content;
  max-width: 280px;
  pointer-events: none;
}

.cursor__chat-ghost {
  display: block;
  padding: 2px 11px;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  animation: cursor-chat-rise 1s var(--ease) forwards;
}

@keyframes cursor-chat-rise {
  from {
    translate: 0 0;
    opacity: 0.85;
  }
  to {
    translate: 0 -18px;
    opacity: 0;
  }
}

/* Il testo della riga corrente. */
.cursor__chat-text {
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

/* L'invito a scrivere: tenue. */
.cursor__chat-text--placeholder {
  opacity: 0.65;
}

/*
 * Fade-in della bolla: quando compare (apertura) e quando torna allo stato vuoto
 * dopo un invio. Lo scatta il renderer aggiungendo la classe alla transizione.
 */
.cursor__chat--fade-in {
  animation: cursor-chat-in 200ms var(--ease);
}

@keyframes cursor-chat-in {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}

/*
 * Uscita del **proprio** cursore dopo il silenzio (o Esc): la bolla sfuma invece
 * di sparire di colpo. La durata combacia con FADE_MS in cursor-chat.ts, che
 * chiude la chat a fine transizione.
 */
.cursor--fading .cursor__chat {
  opacity: 0;
  transition: opacity 260ms var(--ease);
}

/*
 * Uscita della bolla di un **peer**: chi legge riceve solo un messaggio vuoto,
 * quindi la dissolvenza la si applica qui, in ricezione, prima di nasconderla —
 * così vede lo stesso fade di chi scrive. A fine animazione il nodo si nasconde.
 */
.cursor__chat--leaving {
  animation: cursor-chat-leave 260ms var(--ease) forwards;
  pointer-events: none;
}

@keyframes cursor-chat-leave {
  from {
    opacity: 1;
  }
  to {
    opacity: 0;
  }
}

/* L'etichetta col nome: pastiglia colorata accanto alla freccia, testo su tinta piena. */
.cursor__label {
  position: absolute;
  top: 16px;
  left: 12px;
  max-width: 160px;
  padding: 2px 7px;
  border-radius: var(--radius-sm);
  background: var(--cursor-color, var(--border-strong));
  color: #fff;
  font-size: var(--text-xs);
  font-weight: 600;
  line-height: 1.4;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  text-shadow: 0 1px 1px rgb(0 0 0 / 30%);
}
