/* ═══════════════════════════════════════
   ▓ COMPONENTE · Celda de cruce — gemelo vanilla ▓
   v1.0 · 2026-08-23. Ficha: design-system/COMPONENTE_CELDA_CRUCE.md
   Kit: catalogo-cd/components/CeldaCruce.jsx

   UN CONTROL QUE NO PUEDE ENSANCHAR SU COLUMNA. El indicador y su control comparten
   UNA celda: el indicador se aleja mientras el control llega, y en ningún instante se
   ven las dos cosas a cero. El control se toca a 24px y la columna sigue midiendo lo
   que mide el indicador.

   ⛔ NO CONFUNDIR CON .exds-turno (COMPONENTE_REJILLA.md, "Dos que se turnan"), que es
   la misma rejilla de una celda para dos ocupantes. La frontera es UNA pregunta y se
   contesta mirando, no opinando:

       ¿existe algún instante, aunque dure 200ms, en que las DOS se vean?
         NO  → .exds-turno   (relevo: una se va, la otra entra, nunca coinciden)
         SÍ  → esta pieza    (cruce: se cruzan a propósito, con un solo reloj)

   *La ficha de .exds-turno dice que solaparse ahí "es un defecto, no una técnica" — y
   tiene razón para su caso. Aquí el solape ES la técnica: sin él hay un hueco negro
   entre las dos señales, y un hueco parpadea.*

   DE DÓNDE SALE, con el número que lo justifica: se cosechó del cajón de
   notificaciones el 2026-08-23. Medido en navegador el 24-ago: con el control como
   VECINO del indicador el título arrancaba en 54px; SUPERPUESTO, en 36. Son 18px en
   cada una de las 143 filas, para siempre, a cambio de un control que casi nunca se
   toca.

   REQUISITOS DEL ANFITRIÓN:
     1. Los tokens del canon (colors_and_type.css).
     2. box-sizing: border-box.
     3. Si el control es un <span role="button"> (porque su fila ya es un <button> y
        un botón dentro de otro no es HTML válido), hace falta celda-cruce.js para
        que el teclado lo active.
   ═══════════════════════════════════════ */

/* ── LA CELDA ────────────────────────────────────────────────────────────────
   SE CENTRA POR CONSTRUCCIÓN, NO POR UN DESPLAZAMIENTO A MANO. Es una rejilla de
   1×1 con todo en la misma área: el indicador manda la medida y el control se
   monta encima. Si el indicador crece algún día, el control lo sigue solo — nadie
   tiene que acordarse de recalcular un margen.

   --cruce-baja existe porque un indicador pequeño no se alinea con el BORDE de la
   caja del texto que acompaña, sino con la línea óptica de su primera línea. Cuánto
   baja depende de la tipografía del anfitrión, así que lo pone el anfitrión: la
   pieza no puede saberlo y fingir que sí la volvería falsa en la siguiente pantalla.

   ⛔ 2026-08-29 · `--cruce-ind` PASA de `--dot-sm` (6px) a `--dot` (8px), y no es un
   ajuste cosmético: es COMPONENTE_DOT.md §2 aplicado. La fila de notificaciones (su
   único consumidor hoy) ES una fila de lista — el criterio de la ficha es "8px sobre
   lienzo, 6 dentro de otra pieza", y una celda de una lista no es "otra pieza". El
   6px que traía este default nació de copiar la implementación que la ficha vino a
   corregir (ver "DE DÓNDE SALE" arriba): el defecto se heredó al cosechar. */
.exds-cruce {
  --cruce-ind: var(--dot, 8px);
  --cruce-toque: 24px;
  --cruce-baja: 0px;
  --icon-swap-dur: var(--motion-base, 250ms);
  --icon-swap-ease: ease-in-out;
  --icon-swap-blur: 2px;
  --icon-swap-start-scale: .25;
  display: grid;
  place-items: center;
  position: relative;
  width: var(--cruce-ind, 6px);
  height: var(--cruce-ind, 6px);
  margin-top: var(--cruce-baja, 0px);
}
.exds-cruce > * { grid-area: 1 / 1; }

/* ── EL INDICADOR ────────────────────────────────────────────────────────────
   Es una envoltura, no un dibujo: dentro va la pieza que de verdad indica (un Dot,
   un Badge, un glifo). Esta hoja NO la pinta — sólo la mueve. */
.exds-cruce-ind {
  display: flex;
  transition: opacity var(--icon-swap-dur) var(--icon-swap-ease),
              transform var(--icon-swap-dur) var(--icon-swap-ease),
              filter var(--icon-swap-dur) var(--icon-swap-ease);
}

/* ── EL CONTROL ──────────────────────────────────────────────────────────────
   Mide 24 para el dedo y devuelve su caja de margen al tamaño del indicador con un
   margen negativo calculado — por eso NO ensancha la columna.

   ⛔ SIN DISCO DE HOVER: sobre un indicador de 6px el círculo gris pesa más que el
   glifo que anuncia. Y SIN REBOTE: la curva con sobrepaso se retiró del sistema en
   agosto de 2026. */
.exds-cruce-ctrl {
  width: var(--cruce-toque, 24px);
  height: var(--cruce-toque, 24px);
  margin: calc((var(--cruce-ind, 6px) - var(--cruce-toque, 24px)) / 2);
  display: grid;
  place-items: center;
  padding: 0;
  border: 0;
  background: transparent;
  border-radius: var(--radius-pill, 999px);
  cursor: pointer;
  opacity: 0;
  transform: scale(var(--icon-swap-start-scale));
  filter: blur(var(--icon-swap-blur));
  pointer-events: none;
  transition: opacity var(--icon-swap-dur) var(--icon-swap-ease),
              transform var(--icon-swap-dur) var(--icon-swap-ease),
              filter var(--icon-swap-dur) var(--icon-swap-ease);
}
/* Las dos caras del control —apagada y encendida— también se superponen, con la
   misma rejilla de una celda. */
.exds-cruce-ctrl > span { grid-area: 1 / 1; display: flex; }
.exds-cruce-ic-out,
.exds-cruce-ic-in {
  transition: opacity var(--icon-swap-dur) var(--icon-swap-ease),
              transform var(--icon-swap-dur) var(--icon-swap-ease),
              filter var(--icon-swap-dur) var(--icon-swap-ease),
              color var(--motion-fast, 120ms) var(--ease-out, cubic-bezier(0.32, 0.72, 0, 1));
}
.exds-cruce-ic-out { color: var(--fg3, #5C6B7A); }
.exds-cruce-ic-in {
  color: var(--color-warning, #FF8400);
  opacity: 0;
  transform: scale(var(--icon-swap-start-scale));
  filter: blur(var(--icon-swap-blur));
}

/* ═════════════════════════════════════════════════════════════════════════════
   EL INDICADOR SE APAGA POR HABERSE ATENDIDO, Y NO VUELVE

   Dos atributos, y viven en el ANFITRIÓN porque es la fila la que sabe:
     data-cruce-visto="true"    ya se atendió  → el indicador se apaga
     data-cruce-marcado="true"  el control está puesto → se queda visible y encendido,
                                y el indicador se apaga también

   ⛔ MARCAR ES ATENDER. Para decidir que algo te importa tuviste que leerlo, así que
   marcar apaga el indicador — y eso DISUELVE el conflicto que parecía haber entre las
   dos señales: no puede existir a la vez una fila marcada y sin ver, así que las dos
   nunca se disputan la celda.

   ⛔ Y DESMARCAR NO DEVUELVE EL INDICADOR. Una señal que se puede resucitar deja de
   significar "no lo has visto": significaría "no lo has visto, o lo has visto y
   cambiaste de opinión", que no es una señal, es una duda.
   DECISION-FUENTE: Ricardo, 2026-08-24 (cajón de notificaciones), generalizado aquí.

   Se garantiza en LOS DOS sitios —hoja y conducta— a propósito: un montaje que pinte
   "marcado" sin "visto" desde el servidor seguiría siendo correcto en pantalla.
   ═════════════════════════════════════════════════════════════════════════════ */
[data-cruce-visto="true"] .exds-cruce-ind,
[data-cruce-marcado="true"] .exds-cruce-ind {
  opacity: 0;
  transform: scale(.5);
}

/* ── EJE 1 · PRESENCIA — ¿se ve? La manda el ANFITRIÓN ───────────────────────
   El indicador y el control son LAS MITADES DE UN CRUCE CON UN SOLO RELOJ: en una
   fila sin atender, el indicador se aleja mientras el control llega, y no hay un
   instante en que no se vea ninguno de los dos. En una fila ya atendida no hay cruce
   que hacer —el indicador no está— y el control simplemente aparece.
   Es el icon-swap homologado del catálogo, el mismo de cifra→palomita.

   ⛔ El control MARCADO no depende del hover: es permanente, y por eso su selector no
   lleva ":hover" en ninguna parte.

   data-forzar="hover" reproduce el hover sin puntero. Existe para las hojas
   fieles y las capturas: un estado que sólo se puede ver con el ratón encima no se
   puede enseñar en un documento ni medir en un gate. */
.exds-cruce-host:hover .exds-cruce-ctrl,
.exds-cruce-ctrl:focus-visible,
[data-cruce-marcado="true"] .exds-cruce-ctrl,
[data-forzar="hover"] .exds-cruce-ctrl {
  opacity: 1;
  transform: scale(1);
  filter: blur(0);
  pointer-events: auto;
}
.exds-cruce-host:hover .exds-cruce-ind,
[data-forzar="hover"] .exds-cruce-ind {
  opacity: 0;
  transform: scale(var(--icon-swap-start-scale));
  filter: blur(var(--icon-swap-blur));
}
[data-cruce-marcado="true"] .exds-cruce-ic-out {
  opacity: 0;
  transform: scale(var(--icon-swap-start-scale));
  filter: blur(var(--icon-swap-blur));
}
[data-cruce-marcado="true"] .exds-cruce-ic-in {
  opacity: 1;
  transform: scale(1);
  filter: blur(0);
}

/* ── EJE 2 · RESPUESTA — ¿me estás tocando? La manda el PUNTERO ──────────────
   Los dos ejes son independientes y NUNCA se pisan: la PRESENCIA la decide el
   anfitrión (hover de la fila, foco, marca puesta) y la RESPUESTA la decide el
   puntero sobre el control.
   ⛔ EL PULSADO NO BAJA DEL REPOSO: 1.18 al pasar por encima, 1.02 al pulsar. El dedo
   siente el clic sin que el glifo parezca alejarse. */
.exds-cruce-ctrl:hover,
.exds-cruce-ctrl:focus-visible,
.exds-cruce-host:hover .exds-cruce-ctrl:hover,
[data-cruce-marcado="true"] .exds-cruce-ctrl:hover,
[data-cruce-marcado="true"] .exds-cruce-ctrl:focus-visible,
[data-forzar="hover"] .exds-cruce-ctrl:hover {
  opacity: 1;
  transform: scale(1.18);
  filter: blur(0);
  pointer-events: auto;
}
.exds-cruce-ctrl:active,
.exds-cruce-host:hover .exds-cruce-ctrl:active,
[data-cruce-marcado="true"] .exds-cruce-ctrl:active,
[data-forzar="hover"] .exds-cruce-ctrl:active {
  opacity: 1;
  transform: scale(1.02);
  filter: blur(0);
}
/* APAGADO → el contorno sube de gris a tinta. */
.exds-cruce-ctrl:hover .exds-cruce-ic-out,
.exds-cruce-ctrl:active .exds-cruce-ic-out,
.exds-cruce-ctrl:focus-visible .exds-cruce-ic-out { color: var(--fg1, #0F1419); }
/* ENCENDIDO → NO se oscurece. Vuelve el TRAZO del contorno, en el mismo color, encima
   del relleno: cae justo sobre el borde de la silueta y engorda el glifo medio píxel
   óptico. El control se pone en NEGRITA, no se apaga. Ninguna variante honda entra
   por hover. */
[data-cruce-marcado="true"] .exds-cruce-ctrl:hover .exds-cruce-ic-out,
[data-cruce-marcado="true"] .exds-cruce-ctrl:active .exds-cruce-ic-out,
[data-cruce-marcado="true"] .exds-cruce-ctrl:focus-visible .exds-cruce-ic-out {
  opacity: 1;
  transform: scale(1);
  filter: blur(0);
  color: var(--color-warning, #FF8400);
}
/* El foco de teclado HEREDA la misma respuesta que el ratón, y además el anillo. */
.exds-cruce-ctrl:focus-visible {
  outline: 2px solid var(--color-border-focus, #6E7378);
  outline-offset: 1px;
}

/* ── MOVIMIENTO REDUCIDO ────────────────────────────────────────────────────
   Se apaga el RECORRIDO, no la SEÑAL: el control sigue apareciendo y el indicador
   sigue apagándose, sólo que sin cruce (INC-405). Apagar el movimiento no puede
   dejar a nadie sin la información. */
@media (prefers-reduced-motion: reduce) {
  .exds-cruce-ind,
  .exds-cruce-ctrl,
  .exds-cruce-ic-out,
  .exds-cruce-ic-in { transition: none; }
}
