/* ═══════════════════════════════════════════════════════════════════════════════
   ▓ COMPONENTE · INPUT — gemelo vanilla ▓
   v1.0 · 2026-08-14 · pedido por Ricardo. v1.1 · 2026-10-05: modo `data-crece` (área de texto que crece sola). v1.5 · 2026-10-06: aviso con enlace (`data-enlace`) y desplegable sin elegir en gris (`option[data-ejemplo]`). v1.4 · 2026-10-06: sólo lectura, «(opcional)» del rótulo (`.exds-input-opt`) y ranura de adorno a la derecha (`.exds-input-wrap--adorno`), cosechados del Cajón de acción (los tres ya vivían en el kit y en la ficha). Ficha: `design-system/COMPONENTE_INPUT.md`

   POR QUÉ EXISTE. El Input tenía ficha (569 líneas) y kit de React con reglas y
   pruebas — pero **las tres apps de Exante son páginas estáticas y no pueden consumir
   React**. Así que quien tocaba un formulario **volvía a escribir el input a mano cada
   vez**: es la deriva que un catálogo existe para evitar, sólo que un nivel más abajo.

   ⛔ LO MEDIDO EN `app.exante.mx` SE USÓ PARA DOS COSAS DISTINTAS, Y SÓLO UNA VALÍA.
   La primera versión de este archivo decía: «me equivoqué en el radio (dije 6px, son 10)
   y en el alto (dije 40, son 38.4)». **El radio sí: nadie había fijado 6 y el 10 entró al
   canon. El alto NO: el canon decía 40, con razones, y se le cambió por el número de la
   pantalla.** Corregido el 2026-08-25 — ver la nota junto a `height`.

   *Mirar la pantalla contesta «¿cuánto mide hoy?». No contesta «¿cuánto DEBE medir?».
   Cuando el canon ya tiene respuesta, lo medido no la corrige: la contradice, y hay que
   decidir cuál manda.* La lección de INC-468 —un estado se describe mirándolo, no
   leyendo su regla— sigue en pie **para describir lo que hay**; usarla para reescribir
   lo que debe haber es la trampa que este archivo ya denuncia más abajo.

   ⛔ QUÉ TRAE Y QUÉ NO — la frontera es de Ricardo (2026-08-14):
     · **Los EFECTOS sí**: cómo se avisa. Se canonizan porque son del componente.
     · **Las REGLAS no**: qué es un dato válido. Cambian con cada pantalla y con el
       negocio; meterlas aquí haría envejecer el catálogo cada mes.

   REQUISITOS DEL ANFITRIÓN: los tokens del canon y un reinicio de `box-sizing` que
   incluya `::before/::after`.
   ═══════════════════════════════════════════════════════════════════════════════ */

/* ── LA ETIQUETA ENCIMA · hueco cerrado 2026-09-14 ─────────────────────────────
   ⛔ Vivía SÓLO en la ficha (`COMPONENTE_INPUT.md` §Variantes: «una sola forma:
   encima de la caja, en frase, con "?" de ayuda opcional — como el modal de
   confirmación del cotizador»; §Estados: «Label: visible por defecto, Inter 500,
   12–13px, --fg2, arriba del campo»), NUNCA en este gemelo — quien montaba un
   formulario la volvía a escribir a mano cada vez (medido al construir
   `ListaRepetible`, decisión 30/24 de Ricardo, 2026-09-14).
   La MEDIDA sale de la referencia que la propia ficha cita — `.field label` del
   modal de confirmación del cotizador (`exante-git/app/css/cotizador.css:1246`):
   `font-size: 0.75rem` (12px) · `font-weight: var(--fw-medium, 500)` ·
   `color: var(--text-secondary)` (= `var(--fg2)`, homologado 2026-08-07) ·
   `margin-bottom: 6px` · `letter-spacing: 0.2px`. No se inventa nada: es la
   misma cifra, con los nombres de token de este catálogo. */
.exds-input-lab {
  display: block; margin: 0 0 6px;
  font: 500 var(--fs-caption, 12px) var(--font-sans, Inter, sans-serif);
  color: var(--fg2, #4B5563);
  letter-spacing: 0.2px;
}

.exds-input-wrap {
  --in-dur: var(--motion-fast, 120ms);
  --in-ease: var(--ease-default, cubic-bezier(0.32, 0.72, 0, 1));

  display: flex; align-items: center; gap: var(--space-2, 8px);
  width: 100%;
  padding: 0 12px;
  /* ⛔ 40, Y ESTA LÍNEA DECÍA 38.4 CON LA COARTADA «medido en producción, no supuesto»
     (corregido 2026-08-25). Las dos mitades de esa frase eran ciertas y la conclusión
     estaba mal — es **exactamente** el modo de fallo que este mismo archivo denuncia
     unas líneas más abajo a propósito del fondo teñido del error:
     *medir producción para describir el canon es copiar el defecto con autoridad de
     dato. La ficha manda; lo medido era la deuda.*
     El canon dice 40 en CUATRO sitios y ninguno de ellos es una opinión:
     `COMPONENTE_INPUT.md` §Anatomía · su §Defectos-9 («alto no canónico 40/44/~42/~56
     → 40 base», o sea que el 38.4 ya estaba señalado como deuda antes de nacer este
     gemelo) · `gate_alto_control.js`, que mide Input y Select contra la escala 40 ·
     y el kit de React (`Input.jsx`: control 38 + 2 de borde = 40).
     El 38.4 vivía en un solo sitio: la justificación de quien escribió este gemelo. */
  height: 40px;
  background: var(--color-surface);
  border: 1px solid var(--color-border-default);
  border-radius: var(--radius-md, 10px); /* medido: 10px, NO --radius-sm */
  transition: border-color var(--in-dur) var(--in-ease),
              box-shadow   var(--in-dur) var(--in-ease),
              background   var(--in-dur) var(--in-ease);
}
.exds-input-wrap:focus-within { border-color: var(--color-border-focus); }
/* ⛔ ENCADENADO CON `.exds-input-wrap` A PROPÓSITO — NO ES ESTILO, ES PESO (2026-09-05, H3
   de la auditoría de ojos frescos a los goldens). El control interno vive SIN borde propio
   (línea de abajo: `border:0`), así que en reposo no compite con nada. Pero al enfocar, el
   `outline: 1px solid` global de `colors_and_type.css` (`input[type="text"]:focus`, peso
   0-2-1) SÍ aplica sobre él — y como el control no tiene borde que tapar, el outline dibuja
   un segundo rectángulo PEGADO AL TEXTO, unos 12px por dentro del borde que el wrapper ya
   oscureció arriba: dos líneas de foco visibles en la misma caja. `.exds-input-ctrl:focus`
   sola pesa 0-2-0 y pierde contra el global; encadenada con el wrapper
   (`.exds-input-wrap .exds-input-ctrl:focus`) pesa 0-3-0 y gana. Mismo arreglo que
   `asistente.css` (`.exds-dk-srch .exds-dk-srch-in:focus`). Cubre también `Select`, que
   reusa esta misma clase (`.exds-input-wrap--select .exds-input-ctrl`, ver abajo). */
.exds-input-wrap .exds-input-ctrl:focus { outline: none; }
/* El foco se enciende solo en el envoltorio (:focus-within): el anillo global por teclado no pinta un 2o contorno (2026-09-29). */
/* En TODOS los estados (2026-09-29, INC-1872): el control interior nunca pinta contorno propio; el
   indicador vive en el envoltorio. Antes se exceptuaba `data-estado` para conservar el anillo global
   como único indicador, pero en el backoffice ese anillo (backoffice.css:645, inset 1px) pintaba un
   recuadro cuadrado dentro del borde redondeado: doble contorno, medido en vivo. */
.exds-input-wrap .exds-input-ctrl:focus-visible { outline: none; box-shadow: none; }
/* Foco con estado semántico (v0.7 de COMPONENTE_FOCO.md · Ricardo, 2026-10-03): la MISMA línea de 1px que el
   campo ya tiene pasa a la variante -deep del estado. SIN outline, SIN box-shadow, SIN más grosor.
   DECISION-FUENTE: Ricardo, 2026-10-03 — «cuando se utiliza una semántica, ya sea verde, roja o ámbar, para
   inputs… nunca se pone ni doble línea ni línea más gruesa ni anillo. Simplemente cambia de color la línea que
   ya se encuentra en el input.» Retira el delineado 1px de INC-1872 (2026-09-29), que contradecía el canon.
   Error: --color-error → --color-error-deep · válido: --color-emerald → --color-success-deep · aviso ámbar: su
   reposo YA es --color-warning-deep (el más profundo que existe), así que el foco no lo cambia (ver ficha).
   La celda del prefijo (divisor del «$») lleva el mismo color que el borde, también en foco. */
.exds-input-wrap[data-estado="valido"]:focus-within { border-color: var(--color-success-deep, #038157); }
.exds-input-wrap[data-estado="valido"]:focus-within .exds-input-prefijo { border-right-color: var(--color-success-deep, #038157); }
.exds-input-wrap[data-estado="error"]:focus-within  { border-color: var(--color-error-deep, #D61005); }
.exds-input-wrap[data-estado="error"]:focus-within .exds-input-prefijo { border-right-color: var(--color-error-deep, #D61005); }

.exds-input-ctrl {
  flex: 1 1 auto; min-width: 0;
  border: 0; outline: 0; background: none; height: 100%;
  font: var(--fw-regular) var(--fs-body, 15px) var(--font-sans);
  color: var(--fg1);
}
/* Homologado 2026-08-23: el kit la trae en su `<style>` y este gemelo no la tenía. */
/* ⛔ SU PROPIO TOKEN, NO EL DEL TEXTO DE AYUDA (Ricardo, 2026-09-05: «es muy oscuro, al punto
   que llega a aparecer que ya está llenado el campo»). Usaba `--fg3` —el de helper y captions—
   por herencia de una migración, no por decisión. Un marcador de posición no compite por ser
   legible: compite por NO parecerse a una respuesta. El porqué entero, con su condición, vive
   junto al token en `colors_and_type.css`. */
.exds-input-ctrl::placeholder { color: var(--fg-placeholder); opacity: 1; }

/* ── EL AVISO · DENTRO de la caja, a la derecha ────────────────────────────────
   ⛔ Nunca debajo. Debajo empuja el contenido y **cambia el alto de la fila**, así que
   la pantalla salta justo cuando el usuario se equivocó — el peor momento posible.
   `flex-shrink: 0` = el aviso NUNCA cede espacio; cede el VALOR.
   `pointer-events: none` = pulsar sobre él enfoca el campo, no se queda muerto. */
.exds-input-aviso {
  flex: 0 0 auto; pointer-events: none; display: none;
  font: var(--fw-medium) var(--fs-caption, 12px) var(--font-sans);
  color: var(--color-error-deep, #D61005);
  /* Entrada por opacidad, homologada 2026-08-23 con `exds-msg-in` del kit — el gemelo
     sólo alternaba `display` de golpe y no animaba la aparición. */
  animation: exds-msg-in var(--motion-base, 250ms) var(--ease-out, cubic-bezier(0,0,.2,1)) both;
}
@keyframes exds-msg-in {
  from { opacity: 0; transform: translateY(-4px); }
  to   { opacity: 1; transform: translateY(0); }
}

/* ── LA MARCA DE VALIDADO · aparece por opacidad, no de golpe ────────────────── */
.exds-input-ok {
  flex: 0 0 auto; display: flex; opacity: 0;
  color: var(--color-emerald);
  transition: opacity var(--in-dur) var(--in-ease);
}
.exds-input-ok svg { width: 18px; height: 18px; }

/* ── ESTADO · VALIDADO ────────────────────────────────────────────────────────── */
.exds-input-wrap[data-estado="valido"] { border-color: var(--color-emerald); }
.exds-input-wrap[data-estado="valido"] .exds-input-ok { opacity: 1; }
/* El divisor del prefijo («$») también va en verde: la caja entera cambia de color (Ricardo, 2026-10-03). */
.exds-input-wrap[data-estado="valido"] .exds-input-prefijo { border-right-color: var(--color-emerald); }

/* ── ESTADO · ERROR ───────────────────────────────────────────────────────────── */
/* ⛔ EL CAMPO **NUNCA** SE RELLENA DE COLOR SEMÁNTICO (Ricardo, 2026-08-19).
   Hasta hoy esta regla añadía `background: rgba(184,50,39,.09)` con la coartada
   «tinte del error, medido en producción». Las dos mitades de esa frase eran ciertas
   y la conclusión estaba mal: **lo medido era el cotizador, que es justo la superficie
   que la ficha ya tenía señalada por pintar mal sus errores** (`COMPONENTE_INPUT.md`
   § DO/NO: «Error en ámbar (cotizador hoy)»). `COMPONENTE_INPUT.md` § Estados dice, y
   decía: «borde --color-error (la caja entera) + aviso rojo DENTRO de la caja, a la
   derecha + shake». Ni una palabra de relleno.

   *Medir producción para describir el canon es copiar el defecto con autoridad de dato.*
   La ficha manda; lo medido era la deuda.

   ⚠ Y NO ERA UNA PIEZA SOLA — se contaron cuatro: esta regla, la tabla del README de
   este kit («borde rojo, fondo teñido»), y DOS en el cotizador vivo
   (`app/css/cotizador.css` › `.field input.invalid` y `.pf-err .cz-prefix`). Las dos
   del cotizador **siguen abiertas**: son producción y pasan por `cambio-componente`. */
.exds-input-wrap[data-estado="error"] {
  border-color: var(--color-error);
}
.exds-input-wrap[data-estado="error"] .exds-input-aviso { display: block; }

/* ── LA SACUDIDA · UNA vez, ±5px ──────────────────────────────────────────────
   Es la ÚNICA del sistema. Nueve recetas del cotizador se movían cuatro distancias
   distintas, así que la fuerza del regaño dependía de EN QUÉ CAMPO te equivocabas. */
.exds-input-wrap.is-shake { animation: exds-input-shake var(--motion-shake, 380ms) var(--ease-shake, cubic-bezier(0.36,0.07,0.19,0.97)); }
@keyframes exds-input-shake {
  0%, 100% { transform: translateX(0); }
  15% { transform: translateX(-5px); }  30% { transform: translateX(5px); }
  45% { transform: translateX(-4px); }  60% { transform: translateX(4px); }
  75% { transform: translateX(-2px); }  90% { transform: translateX(2px); }
}

/* ── PREFIJO · la celda del `$` o del `+52` ───────────────────────────────────── */
.exds-input-prefijo {
  flex: 0 0 auto; align-self: stretch; display: flex; align-items: center;
  padding: 0 10px; margin: 0 0 0 -12px;
  background: var(--color-bg-subtle);
  border-right: 1px solid var(--color-border-default);
  border-radius: var(--radius-md, 10px) 0 0 var(--radius-md, 10px);
  font: var(--fw-medium) var(--fs-body-sm, 13px) var(--font-sans);
  color: var(--fg2);
}
/* ⛔ En error, la caja ENTERA se pone roja — celda del prefijo incluida. Un borde rojo
   que se parte a la mitad se lee como un defecto de dibujo, no como un aviso. */
.exds-input-wrap[data-estado="error"] .exds-input-prefijo { border-right-color: var(--color-error); }

/* ⛔ La guarda NO es opcional: una sacudida es exactamente lo que alguien con
   sensibilidad al movimiento pidió no ver. El color y el aviso siguen ahí. */
@media (prefers-reduced-motion: reduce) {
  /* Homologado 2026-08-23 con el kit, que apaga LA MISMA propiedad en LOS DOS
     selectores juntos, con `!important`. La sacudida y la entrada del aviso quedan
     cubiertas por esta línea; `.is-shake` no necesita su propia regla aparte. */
  .exds-input-wrap, .exds-input-aviso { animation: none !important; }
  .exds-input-wrap, .exds-input-ok { transition-duration: .01ms; }
}

/* ── SELECT · la variante de LISTA CERRADA ────────────────────────────────────
   v1.1 · 2026-08-25. Añadida porque el gemelo no la tenía y el canon SÍ: la ficha
   (`COMPONENTE_INPUT.md` §Variantes) dice «Select — chevron a la derecha (SVG
   neutro), appearance:none, padding-right 36-40px», el kit la monta desde hace
   semanas (`Input.jsx`, kind="select") y `COMPONENTE_TOOLBAR.md` §97 fijó el
   2026-08-01 que **el select es de Input**, también el de los filtros.

   ⛔ NO ES UNA DECISIÓN NUEVA. Es la traducción a vanilla de lo ya decidido. Lo
   que faltaba era el gemelo, y el precio de que faltara está medido: **16 dialectos
   de select vivos en las tres apps** (censo del 2026-08-25), con 7 altos distintos,
   9 rellenos derechos distintos y **4 maneras distintas de dibujar el chevron** —
   más 5 que no dibujan ninguno. Quien tocaba un desplegable no tenía de dónde
   copiar, así que se lo inventaba. Es la deriva de siempre, un nivel más abajo.

   ⛔ CUÁNDO **NO** ES ESTA PIEZA: si puede existir una respuesta válida que no esté
   en la lista, es un `Combobox` (`componentes/combobox/`). Un select con salida a
   texto libre no existe. */

/* ── ÁREA DE TEXTO QUE CRECE SOLA · `data-crece` (v0.13 · 2026-10-05) ─────────────────────────
   `DECISION-FUENTE: Ricardo, 2026-10-05 — «C»` (hoja `plans/decisiones/_decision_otro_lineas_2026-10-05.html`)
   y `«crecimiento debe tener efecto movimiento acorde.»`. Arranca como el Input de siempre (una
   línea, 40 px con el borde), suma un renglón cada vez que el texto no cabe (64 → 85 px) y se
   detiene en el tope (`data-crece` = 3 por omisión); del renglón siguiente en adelante el texto
   se desplaza DENTRO del campo (`data-desborda`). Sin tirador de redimensionar.
   El alto va en el TEXTAREA (no en el envoltorio): `22 + 21 x renglones` = alto del control
   (20 de relleno + 1,5 x --fs-body por renglón) + 2 del borde. `--crece-n` y `data-lineas` los
   pone `ExdsInput.crecer` (input.js) tras medir el texto en un espejo oculto.
   Movimiento: papel 2 «Apertura / cierre» de COMPONENTE_MOVIMIENTO.md (alto, --motion-base,
   --ease-default) — sin valores nuevos. Con reduced-motion el campo salta directo al alto nuevo
   (el cambio de tamaño ES la información: no hace falta una señal estática de sustitución). */
.exds-input-wrap--crece { position: relative; height: auto; padding: 0; }
.exds-input-ctrl[data-crece] {
  height: calc(var(--crece-n, 1) * 1.5 * var(--fs-body, 14px) + 20px); min-height: 0; resize: none;
  padding: 10px 12px; line-height: 1.5; overflow-y: hidden;
  transition: height var(--motion-base, 250ms) var(--ease-default, cubic-bezier(0.32, 0.72, 0, 1)),
              padding var(--motion-base, 250ms) var(--ease-default, cubic-bezier(0.32, 0.72, 0, 1));
}
.exds-input-ctrl[data-crece][data-lineas="1"] { height: 38px; padding: 8px 12px; }
.exds-input-ctrl[data-crece][data-desborda] { overflow-y: auto; }
.exds-input-ctrl[data-crece]::-webkit-scrollbar { width: 9px; }
/* LINT-ALLOW: rol-color scrollbar-thumb de data-crece · ningún token de rol cubre el pulgar de una barra de desplazamiento; mismo patrón que cajon-lateral.css:582 */
.exds-input-ctrl[data-crece]::-webkit-scrollbar-thumb {
  background: var(--color-border-default, #D1D5DB);
  border-radius: var(--radius-pill, 999px);
  border: 3px solid var(--color-surface, #FFFFFF);
}
/* El espejo con el que se mide el texto: misma tipografía y mismo relleno, invisible y sin
   tocar el diseño. Vive dentro del envoltorio (position: relative) y se crea la primera vez. */
.exds-input-ctrl[data-crece-espejo] {
  position: absolute; left: 0; top: 0; width: 100%; height: auto; min-height: 0;
  visibility: hidden; pointer-events: none; overflow: hidden; resize: none;
  padding: 10px 12px; box-sizing: border-box; line-height: 1.5; transition: none;
}
@media (prefers-reduced-motion: reduce) {
  .exds-input-ctrl[data-crece] { transition: none; }
}

/* El chevron se ancla al propio envoltorio. ⛔ Y va a 11px, no a 12, A PROPÓSITO:
   el kit lo pone a 12 contando desde el borde EXTERIOR (su ancla es un div sin
   borde); aquí el ancla es la caja del propio campo, cuyo interior empieza 1px más
   adentro. 11 + 1 de borde = la MISMA raya. */
.exds-input-wrap--select { position: relative; padding-right: 0; }

.exds-input-wrap--select .exds-input-ctrl {
  appearance: none; -webkit-appearance: none;
  padding-right: 36px;
  cursor: pointer;
}

.exds-input-chevron {
  position: absolute; right: 11px; top: 50%; transform: translateY(-50%);
  display: inline-flex; pointer-events: none;
  color: var(--fg3);
}
.exds-input-chevron svg { width: 16px; height: 16px; flex-shrink: 0; }

/* ⛔ El aviso ESQUIVA el chevron, no lo pisa. El chevron flota encima de la fila
   (es absoluto), así que sin este relleno el texto del error se le mete debajo y
   quedan dos dibujos superpuestos justo en el momento en que hay que leer uno. */
.exds-input-wrap--select .exds-input-aviso { padding-right: 34px; }

/* ── AYUDA PERSISTENTE (v0.8 · 2026-09-13, onboarding) ────────────────────────
   «Línea de ayuda persistente» de la ficha (§Anatomía de las ayudas, regla 5): está
   SIEMPRE, no sólo en error — explica algo que no cabe en el placeholder. Es un
   elemento HERMANO de `.exds-input-wrap`, debajo, NO el aviso de error de dentro.
   Estado OCR: el valor lo prellenó el reconocimiento de un documento, no el usuario.
   ⛔ SIN TINTE DE FONDO (regla «sin rellenos de color») Y SIN TINTE DE TEXTO (corregido
   2026-09-13, revisor-qa: la regla 5 de §Anatomía de las ayudas dice GRIS siempre —
   el estado OCR se distingue por el ÍCONO `sparkles`, no por el color del texto). */
/* DECISION-FUENTE: Ricardo, 2026-09-22/23 — paquete cajones laterales, H-6: la ayuda del Input
   pasa a line-height 1.45, como toda la ayuda del cuerpo (12 · 1.45). Antes sin interlínea
   propia (heredaba "normal" del navegador). */
.exds-input-help {
  display: flex; align-items: center; gap: 6px;
  margin: 6px 0 0;
  font: 400 var(--fs-caption, 12px) var(--font-sans, Inter, sans-serif);
  line-height: 1.45;
  color: var(--fg2, #4B5563);
}
.exds-input-help svg { width: 13px; height: 13px; flex-shrink: 0; }
.exds-input-help--ocr { color: var(--fg2, #4B5563); }

/* ── MODO EN FILA · el campo dentro de una celda de lista (v1.2 · 2026-10-03) ──────
   DECISION-FUENTE: Ricardo, 2026-10-03 — «ningun elemento de la lista puede provocar mas
   alto del estanndard ni doble fila, corregir de la manera mas limpia posible».
   La REGLA vive en `COMPONENTE_TABLA.md` (NINGUNA CELDA HACE CRECER LA FILA); esto es la
   salida limpia de ESTA pieza: ni ayuda debajo (empuja la fila) ni aviso dentro de la caja
   (una celda mide menos que los 284 px que ese aviso necesita). El borde cambia de estado
   como siempre (rojo si bloquea) y el TEXTO sale en un globo del Tooltip del catálogo,
   anclado al campo mientras tiene foco o el puntero encima.
   Marcado: `data-en-fila` en `.exds-input-wrap`, `data-tip` con el texto (lo pone input.js)
   y todo el campo dentro de `.exds-input-tip.exds-tip-wrap` — escrito YA en el marcado: si
   lo crea tooltip.js a la primera apertura, mover el campo del DOM le quita el foco.
   El aviso sigue en el DOM, fuera de la vista, para el lector de pantalla. */
.exds-input-tip.exds-tip-wrap { display: flex; width: 100%; }
.exds-input-wrap[data-en-fila] { position: relative; }
.exds-input-sr,
.exds-input-wrap[data-en-fila] .exds-input-aviso {
  position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; border: 0;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap;
}

/* ── AVISO QUE NO BLOQUEA · borde ÁMBAR, sólo en modo en fila (v1.3 · 2026-10-03) ─────────
   DECISION-FUENTE: Ricardo, 2026-10-03 — «Opción B»: en modo en fila, un aviso que NO bloquea
   pinta el BORDE del campo en ámbar (el error que bloquea sigue en rojo); el texto sigue en el
   globo. Ámbar = «te toca revisar» (regla de colores 7-bis: gris ok · ámbar acción de quien mira
   · rojo error · verde éxito).
   ⛔ EL TOKEN ES --color-warning-deep (#B05B00), NO --color-warning (#FF8400): el naranja base
   no llega a 3:1 contra el blanco como borde de control (WCAG 1.4.11); el deep sí (se mide en la
   prueba de vida). Y --color-warning-stroke (1.89:1) tampoco sirve: es de pastilla.
   ⛔ LA CAJA ENTERA, celda del prefijo incluida (regla de construcción de COMPONENTE_INPUT.md:
   el color del borde de un campo compuesto sale de UNA decisión). Los selectores llevan
   [data-en-fila] + [data-estado]: pesan 0-3-0 / 0-4-0 y le ganan al foco (0-2-0) y a la
   regla de la celda del prefijo por especificidad, no por orden de archivo.
   Sin relleno de color y SIN sacudida (la sacudida es del error). Foco: el mismo borde, sin
   cambio (ya es el -deep). */
.exds-input-wrap[data-en-fila][data-estado="aviso"] { border-color: var(--color-warning-deep, #B05B00); }
.exds-input-wrap[data-en-fila][data-estado="aviso"] .exds-input-prefijo { border-right-color: var(--color-warning-deep, #B05B00); }

/* ── SÓLO LECTURA · lo que llena otro campo (v1.4 · 2026-10-06) ───────────────────────────────
   La ficha lo dice (`COMPONENTE_INPUT.md` § Estados, «Solo lectura: bg --surface-2, texto --fg2»;
   --surface-2 es el alias de --color-bg-subtle) y el kit lo pinta (`Input.jsx`: fondo
   --color-bg-subtle, texto --fg2, borde de reposo SIN tocar) — pero este gemelo no lo traía, así
   que el Cajón de acción lo bajó a una clase propia (.exds-cjacc-auto, con el borde en el
   escalón claro: una desviación del kit que nadie había decidido). Se implementa aquí, con los
   valores del kit, y se retira la copia. Se enciende con el atributo `readonly` del propio
   campo — no hay clase que acordarse de poner: lo que el navegador ya sabe es de sólo lectura,
   se ve de sólo lectura. El borde NO cambia (como en el kit): es el de reposo. */
.exds-input-wrap:has(> .exds-input-ctrl[readonly]) {
  background: var(--color-bg-subtle, #F2F4F6);
}
.exds-input-wrap > .exds-input-ctrl[readonly] {
  color: var(--fg2, #4B5563);
}

/* ── «(OPCIONAL)» EN EL RÓTULO (v1.4 · 2026-10-06) ───────────────────────────────────────────
   Equivale a la prop `optional` del kit (`Input.jsx`: peso 400 · --fg3, dentro de un rótulo que
   ya es 12 · 500). Tamaño e interletrado se HEREDAN del rótulo, como en el kit. Requerido
   implícito: sólo lo opcional se marca. Un GRUPO entero opcional usa `.exds-caj-nota` del marco
   (`patrones/cajon-lateral/`), no esta clase.
   DECISION-FUENTE: Ricardo, 2026-10-05 — «si a las 2, pásalo al catálogo». */
.exds-input-opt {
  font-weight: 400;
  color: var(--fg3, #5C6B7A);
}

/* ── RANURA DE ADORNO A LA DERECHA · `.exds-input-wrap--adorno` (v1.4 · 2026-10-06) ───────────
   Equivale a la prop `adornment` del kit (`Input.jsx`: un nodo a la derecha DENTRO de la caja,
   absoluto a 6 px del borde y centrado en vertical, con 40 px de relleno derecho en el control
   para que no pise el valor). Su uso típico es un IconButton ghost —la X que quita un campo
   extra—: `.exds-input-adorno` lo coloca y el botón es el del catálogo, sin clase propia.
   El aviso lo esquiva con 34, como con el chevron del select. El relleno derecho de la caja
   baja a 0 (el control lo trae), igual que en el select. */
.exds-input-wrap--adorno { position: relative; padding-right: 0; }
.exds-input-wrap--adorno .exds-input-ctrl { padding-right: 40px; }
.exds-input-wrap--adorno .exds-input-aviso { padding-right: 34px; }
.exds-input-adorno {
  position: absolute; right: 6px; top: 50%; transform: translateY(-50%);
  display: inline-flex; align-items: center;
}

/* ── AVISO CON ENLACE · `data-enlace` en `.exds-input-aviso` (v1.5 · 2026-10-06) ──────────────
   Un aviso dentro del campo DEBE llevar un enlace que resuelva el problema siempre que sea
   coherente (p. ej. abrir la ficha que ya existe). Con enlace el aviso completo puede llegar a 24
   caracteres («Ya existe · Abrir ficha»; sin enlace sigue el tope de 22). El aviso canónico es
   `pointer-events: none` (pulsar sobre él enfoca el campo); con enlace tiene que dejarse pulsar,
   o «Abrir ficha» sería un dibujo. Sigue DENTRO de la caja, a la derecha, sin ícono. Lo marca
   `ExdsInput.error(texto, { enlace })`.
   DECISION-FUENTE: Ricardo, 2026-10-06 — «3 si (de hecho, no "puede", "debe de" siempre que sea coherente)». */
.exds-input-aviso[data-enlace] { pointer-events: auto; white-space: nowrap; }
.exds-input-aviso[data-enlace] a {
  color: inherit;
  font-weight: 500;
  text-decoration: underline;
  text-underline-offset: 2px;
}

/* ── DESPLEGABLE SIN ELEGIR · gris de marcador (v1.5 · 2026-10-06) ───────────────────────────
   Un `<select>` no tiene `::placeholder`: sin esto, «Elige una opción» se lee como una respuesta
   ya dada. SÓLO en campos de FORMULARIO: la opción vacía que hace de texto de ejemplo se marca con
   `data-ejemplo` (y `hidden`/`disabled` si se quiere que no sea elegible), y el control se pinta
   en el gris del marcador mientras ESA opción esté elegida. Un filtro cuya opción vacía es
   «Todos» NO lleva `data-ejemplo`: «Todos» es una opción real, y se queda en tinta.
   Texto canónico de la opción de ejemplo: «Elige una opción».
   DECISION-FUENTE: Ricardo, 2026-10-06 — «como en la tabla» (punto N9). */
.exds-input-wrap--select .exds-input-ctrl:has(> option[data-ejemplo]:checked) {
  color: var(--fg-placeholder, #848B99);
}
