/* ═══════════════════════════════════════════════════════════════════════════════
   ▓ COMPONENTE · Botón de copiar — GEMELO VANILLA ▓
   v0.1 · 2026-08-19. Ficha: `design-system/COMPONENTE_BOTONCOPIAR.md` (v1.0, 2026-08-12).
   Kit React hermano: `design-system/catalogo-cd/components/BotonCopiar.jsx`.

   ⛔ POR QUÉ EXISTE. El `BotonCopiar` **sólo vivía en React** y **las tres apps de
   producción son HTML y CSS a secas**: ninguna podía montarlo. Es el mismo hallazgo que
   parió el gemelo del `Menu` (2026-08-17) y el del plegado de la `Toolbar` (2026-08-18).
   *Un componente que tu producto no puede usar no está canonizado: está documentado.*
   `DECISION-FUENTE: Ricardo 2026-08-19 — «poner boton de copiar al lado de tel y correo`
   `en lista contactos».`

   ⛔ MONTA UN `IconButton` GHOST, NO UN `<button>` CRUDO. Lo dice la § Composición de la
   ficha, y no es burocracia: un compuesto que re-implementa por dentro una pieza que ya
   existe reparte ese Frankenstein a cada pantalla que lo use, y ninguna puede verlo desde
   fuera. Por eso esta hoja **exige** `componentes/iconbutton/iconbutton.css` cargada
   antes, y **no vuelve a declarar ni el fondo, ni el hover, ni el foco, ni el radio**:
   todo eso es del `IconButton`. Lo único que hay aquí es lo que el copiar añade — el par
   de glifos, su cruce y la región que anuncia el hecho.

   ⛔ LA CONFIRMACIÓN ES UN CAMBIO DE GLIFO, NUNCA UN TOAST (regla 1 de la ficha). Copiar
   es una acción diminuta y frecuentísima: en una tabla de contactos se copian cinco
   teléfonos seguidos. Un toast por copia convierte una micro-acción en un evento, y cinco
   copias en cinco eventos que tapan la pantalla. El ícono pasa a palomita **1.4 s** y
   vuelve. *La respuesta a una acción pequeña tiene que ser del mismo tamaño que la acción.*

   REQUISITOS DEL ANFITRIÓN — los tres, o se ve mal en silencio:
     1. Los tokens del canon (`design-system/colors_and_type.css`).
     2. `componentes/iconbutton/iconbutton.css` — la pieza que este compuesto monta.
     3. Un reinicio con `box-sizing: border-box`.

   ── LO QUE `lint_tokens.js` MARCA EN ESTA HOJA, DECLARADO ─────────────────────
   ✅ **NADA. Esta hoja ya no declara un solo color.**
   `DECISION-FUENTE: Ricardo, 2026-08-24 — «el ícono de copiado no debe ir en verde, debe`
   `de ir en el mismo color neutro que el botón copiar».`
   Aquí había un párrafo entero justificando el verde de la palomita, con su token, sus dos
   excepciones de ESTADO SEMÁNTICO y cuatro números de contraste medidos. **Se retira
   completo**: el glifo hereda el neutro del `IconButton` y no hay nada que declarar ni que
   excepcionar. *Una excepción que desaparece al replantear la pregunta no era un permiso
   que hiciera falta: era el precio de una decisión que se podía no tomar.*

   ⛔ Y LA HISTORIA SE CONSERVA EN DOS LÍNEAS, porque el archivo llegó aquí tropezando dos
   veces con lo mismo: la cabecera dijo «va en `-deep`, igual que el kit» cuando la hoja ya
   usaba la BASE y el atrasado era el kit; se corrigió por la mañana del 24-ago, y por la
   tarde el verde se fue del todo. *Dos correcciones sobre qué verde tocaba, y la respuesta
   era que ninguno.*

   LINT-ALLOW: .01ms · anular la transición para quien pidió no ver movimiento
   No existe —ni debe existir— un token para «prácticamente cero»: es el modismo
   de `prefers-reduced-motion`, copiado del kit tal cual. Un token para esto sería
   vocabulario para una NO-decisión.
   ═══════════════════════════════════════════════════════════════════════════════ */

/* ═══════════════════════════════════════════════════════════════════════════════
   ▓ 1 · EL ENVOLTORIO ▓
   1:1 con el `<span>` externo del `.jsx`: `inline-flex` + centrado vertical. Existe para
   que el botón y su región viva viajen juntos como una sola cosa que quien monta pega al
   lado del valor.

   ⛔ `flex: none` — POR QUÉ ESTÁ. El botón vive dentro de `.exds-pl-cell`, que es un
   contenedor flex con `overflow:hidden`. Sin `flex:none`, el correo largo encoge el botón
   hasta hacerlo ilegible en vez de recortarse él —que es lo que la celda ya declara con su
   elipsis—. *Un elemento que puede encogerse dentro de un flex se encoge; el que no puede,
   obliga a su vecino a recortarse, que es justo lo que aquí se quiere.*
   ⛔ CORREGIDO 2026-08-24: aquí decía «NO está en el kit y aquí SÍ, y es la única desviación
   de esta hoja». **Ya no hay desviación ninguna**: el kit se homologó a esta hoja entera el
   24-ago, y el motivo de arriba es demasiado bueno para dejarlo sólo en un lado.
   ═══════════════════════════════════════════════════════════════════════════════ */
.exds-copiar {
  display: inline-flex;
  align-items: center;
  flex: none;
}

/* ═══════════════════════════════════════════════════════════════════════════════
   ▓ 2 · EL PAR DE GLIFOS — los DOS viven siempre ▓
   `copy` en reposo · `check` copiado. Se apilan en el marcado y se alternan; **el DOM no
   se reescribe**. Es la misma decisión que tomó el asistente el 2026-08-06: si el ícono
   viejo deja de existir antes de que el nuevo entre, cruzarlos es imposible — no queda
   "sin animar", queda escrito de forma que no se puede animar.

   ⛔ EL CRUCE VA CON `opacity` Y `transform`, NUNCA CON `display`. Es la lección (a) del
   gemelo del `Menu`: alternar `display` no se puede transicionar, y además reflota la
   caja. Aquí las dos capas ocupan la MISMA celda de una rejilla de 1×1, así que el botón
   no cambia de tamaño al cruzar.
   ⚠ MEDIDO EL 2026-08-24, y hay que rebajar la frase: aquí decía «que es lo que haría saltar
   la fila entera», y **no salta**. Con los dos glifos del mismo lienzo (16) la caja del botón
   sale **24×24 en reposo y 24×24 copiado** en las DOS versiones, apiladas o no. La rejilla es
   lo que hace POSIBLE el cruce; el salto de fila que prometía evitar no existía. *Un motivo
   inflado sobrevive al motivo bueno: el día que alguien mida, se cae el que sí valía.*

   ⛔ Y LA REJILLA VA EN UN `<span>` DE DENTRO, NO EN EL BOTÓN. El `IconButton` declara
   `display:inline-flex` y esta hoja **no le pisa ni una declaración**: pisarla la
   convertiría en un gemelo con criterio propio, que es medio Frankenstein. Lo que apila
   los glifos es una capa interna que el copiar sí posee.
   ═══════════════════════════════════════════════════════════════════════════════ */
.exds-copiar-par {
  display: grid;
  grid-template-areas: "glifo";
  place-items: center;
}
.exds-copiar-ic {
  grid-area: glifo;
  width: var(--exds-copiar-size, 16px);
  height: var(--exds-copiar-size, 16px);
  display: block;
  transition: opacity var(--motion-fast, 120ms) var(--ease-out),
              transform var(--motion-fast, 120ms) var(--ease-out);
}
/* ═══════════════════════════════════════════════════════════════════════════════
   ⛔ LA PALOMITA NO LLEVA COLOR PROPIO. Va en el MISMO neutro que el botón.

   `DECISION-FUENTE: Ricardo, 2026-08-24 — «el ícono de copiado no debe ir en verde, debe de`
   `ir en el mismo color neutro que el botón copiar».`

   Por eso en las reglas de abajo **no hay una sola declaración de `color`**: el glifo hereda
   `currentColor` del `IconButton` —`--fg3` en reposo, `--fg1` en hover—, exactamente igual que
   el glifo de copiar. Añadir un color aquí sería lo contrario de lo decidido.

   ⛔ Y ESTO RETIRA TRES COSAS, no sólo el tono, que es lo que lo hace una simplificación de
   verdad y no un cambio de valor:
     1. La regla extra que existía **sólo** para que el verde le ganara al hover del botón. Sin
        color propio no hay nada que pueda perder contra el hover: el problema desapareció con su
        solución. *Media pieza de esta hoja estaba sosteniendo una excepción.*
     2. Las dos **excepciones de ESTADO SEMÁNTICO** (Ricardo 2026-07-16) que el linter necesitaba
        para no cantar un texto verde. Ya no hay verde: no hay nada que excepcionar. *Una
        excepción que se puede borrar era una pregunta mal hecha, no un permiso.*
     3. Toda la **aritmética de contraste** — dos rondas de números (5,67/4,96 con el hex viejo;
        4,07/3,69 con la base) para un glifo que ahora usa el neutro del canon, ya AA por su
        propio token. *El cálculo era correcto las dos veces y la pregunta no lo era ninguna.*

   LO QUE **NO** CAMBIA, y es lo único que la confirmación necesitaba: el glifo **sí cambia** —
   de `copy` a `check`, con su cruce— y la región viva sigue anunciando «Copiado» con palabras.
   La regla 3 de la ficha («ningún estado se distingue sólo por color») nunca dependió del verde:
   aquí el cambio es de FORMA, que es más fuerte que un tono y no excluye a nadie.
   ═══════════════════════════════════════════════════════════════════════════════ */
.exds-copiar-ic[data-glifo="check"] { opacity: 0; transform: scale(.6); }
.exds-copiar[data-copiado="si"] .exds-copiar-ic[data-glifo="copy"]  { opacity: 0; transform: scale(.6); }
.exds-copiar[data-copiado="si"] .exds-copiar-ic[data-glifo="check"] { opacity: 1; transform: none; }

/* ═══════════════════════════════════════════════════════════════════════════════
   ▓ 3 · LA REGIÓN QUE ANUNCIA EL HECHO ▓
   El cambio de dibujo **no existe** para un lector de pantalla (regla 3 de la ficha), así
   que el hecho se dice aparte. Valores copiados del `.jsx` tal cual.

   ⛔ NO ES `display:none` NI `visibility:hidden`: las dos la sacan del árbol de
   accesibilidad y entonces no anuncia nada. Se esconde recortándola, que es la única
   manera de que siga existiendo para quien no la ve.
   ═══════════════════════════════════════════════════════════════════════════════ */
.exds-copiar-vivo {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
}

/* ⛔ SIN MOVIMIENTO, EL CRUCE SIGUE OCURRIENDO — sólo deja de moverse. Nunca se apaga el
   cambio de glifo: es la única confirmación que da la pieza. */
@media (prefers-reduced-motion: reduce) {
  .exds-copiar-ic { transition-duration: .01ms; }
  .exds-copiar-ic[data-glifo="check"] { transform: none; }
  .exds-copiar[data-copiado="si"] .exds-copiar-ic[data-glifo="copy"] { transform: none; }
}
