/* ═══════════════════════════════════════
   ▓ COMPONENTE · Banner — gemelo vanilla ▓
   v1.0 · 2026-08-23. Ficha: `design-system/COMPONENTE_BANNER.md` (v1.7)
   Kit: `catalogo-cd/components/Banner.jsx`

   El aviso que SE QUEDA en la pantalla. Es la contracara del Toast: como no se esfuma, aquí
   el color SÍ significa — comunica la categoría (info, éxito, advertencia, error, neutral).

   REQUISITOS DEL ANFITRIÓN:
     1. Los tokens del canon (`colors_and_type.css`).
     2. `box-sizing: border-box`.

   ⛔ NINGÚN BANNER LLEVA ÍCONO. En ninguna variante, sin excepciones (Ricardo, 2026-08-19).
   El texto va en el color semántico, así que la señal la lleva la frase; el ícono repetía lo
   que la frase ya decía. La última excepción («subtle no tiene fondo, el ícono es su única
   señal») se cayó el día anterior, cuando el cuerpo pasó a pintarse en color.

   ⛔ QUÉ VARIANTE Y CUÁNDO — la elige el ALCANCE, nunca la gravedad ni el gusto:
       de UN elemento concreto  → anchored   (¿si borro el elemento el aviso pierde sentido?)
       de una SECCIÓN o grupo   → subtle     (¿acompaña a un grupo sin ser de ninguno?)
       de TODA la pantalla      → tint       (¿sigue teniendo sentido con la pantalla vacía?)
   Y UN SOLO `tint` por pantalla: si dos avisos lo piden, el segundo no es de pantalla.
   ═══════════════════════════════════════ */

/* ══ LA PALETA POR CATEGORÍA ═════════════════════════════════════════════════
   Cada tono declara sus cuatro papeles y el resto de la hoja los usa por su papel, no por su
   color. Así la variante decide QUÉ papel pinta cada cosa y el tono decide con qué color, sin
   que ninguna regla tenga que conocer a las dos. */
.exds-banner[data-tone="info"] {
  --exds-bn-tint: var(--color-info-tint, #E7F1FE);
  --exds-bn-deep: var(--color-info-deep, #0664E0);
  --exds-bn-base: var(--color-info, #1A73E8);
  --exds-bn-wash: var(--color-info-wash, rgba(6, 100, 224, 0.1));
  --exds-bn-borde: var(--color-info-stroke, #9BBFED);
}

.exds-banner[data-tone="success"] {
  --exds-bn-tint: var(--color-success-tint, #E7FEF6);
  --exds-bn-deep: var(--color-success-deep, #038157);
  --exds-bn-base: var(--color-success, #0B8F6B);
  --exds-bn-wash: var(--color-success-wash, rgba(3, 129, 87, 0.1));
  --exds-bn-borde: var(--color-success-stroke, #5CD9A9);
}

.exds-banner[data-tone="warning"] {
  --exds-bn-tint: var(--color-warning-tint, #FEF6EE);
  --exds-bn-deep: var(--color-warning-deep, #B05B00);
  --exds-bn-base: var(--color-warning, #FF8400);
  --exds-bn-wash: var(--color-warning-wash, rgba(176, 91, 0, 0.1));
  --exds-bn-borde: var(--color-warning-stroke, #E2B483);
}

.exds-banner[data-tone="error"] {
  --exds-bn-tint: var(--color-error-tint, #FEE8E7);
  --exds-bn-deep: var(--color-error-deep, #D61005);
  --exds-bn-base: var(--color-error, #DA342B);
  --exds-bn-wash: var(--color-error-wash, rgba(214, 16, 5, 0.1));
  --exds-bn-borde: var(--color-error-stroke, #ED9F9B);
}

/* El neutral no tiene familia de color: su «profundo» y su «base» son el mismo gris de
   texto secundario, y su tinte es el fondo sutil del canon. */
.exds-banner[data-tone="neutral"] {
  --exds-bn-tint: var(--color-bg-subtle, #F2F4F6);
  --exds-bn-deep: var(--fg2, #4B5563);
  --exds-bn-base: var(--fg2, #4B5563);
  --exds-bn-wash: var(--color-bg-subtle, #F2F4F6);
  --exds-bn-borde: var(--color-notice-stroke, rgba(110, 115, 120, 0.22));
}

/* ══ LA CAJA ═════════════════════════════════════════════════════════════════
   El tono por defecto del texto es el PROFUNDO, que es el que corresponde cuando hay un fondo
   de la propia familia detrás (tint y anchored). El `subtle` lo corrige más abajo. */
.exds-banner {
  display: flex;
  gap: 10px;
  align-items: flex-start;
  font-family: var(--font-sans, "Inter", -apple-system, "system-ui", sans-serif);
  font-size: var(--fs-body-sm, 13px);
  line-height: 1.5;
  color: var(--exds-bn-deep);
}

/* ══ TINT · el callout de toda la pantalla ═══════════════════════════════════
   ⛔ EL CONTORNO ES OBLIGATORIO Y SÓLO DE ESTA VARIANTE (Ricardo, 2026-08-19). Un tinte sobre
   una tarjeta blanca se derretía —el ámbar daba 1,22:1 contra el blanco— y no se podía
   arreglar oscureciendo el fondo, porque el mismo fondo tiene que aguantar el texto a 4,5:1.
   `anchored` no lo lleva porque emerge de una superficie que ya lo delimita, y `subtle` no
   tiene caja que contornear. */
.exds-banner[data-variant="tint"] {
  background: var(--exds-bn-tint);
  border-radius: var(--radius-md, 10px);
  padding: 12px 14px;
  border: 1px solid var(--exds-bn-borde);
}

/* ══ SUBTLE · la nota de una sección ═════════════════════════════════════════
   ⛔ Y AQUÍ EL TONO DEL TEXTO CAMBIA, porque lo decide EL FONDO y no la variante
   (COMPONENTE_SEMANTICOS §0-quater, Ricardo 2026-08-20): un elemento semántico se oscurece a
   su tono profundo SÓLO cuando lo que tiene detrás es de su propia familia. Aquí no hay
   fondo: debajo está el lienzo, que no es de nadie, así que conserva su BASE. */
.exds-banner[data-variant="subtle"] {
  background: transparent;
  padding: 0;
  color: var(--exds-bn-base);
}

/* ⛔ DOS EXCEPCIONES, NO UNA — y la segunda llevaba escrita como cumplida (corregido 2026-08-29).
   Sobre blanco: rojo 5,96 ✓ · azul 4,51 ✓ · **verde 4,07 ✗** · naranja 2,46 ✗. Esta línea decía
   que el verde «se lee», y no llega por 0,43. El mismo texto, palabra por palabra, vivía también
   en `badge.css` y afirmaba lo mismo — *un comentario equivocado que se copia se vuelve dos
   fuentes que se confirman entre sí.* Lo destapó Ricardo preguntando si los banners y los badges
   estaban afectados por la regla del color de texto.
   Ninguna se arregla oscureciendo más: el verde va a su `-deep` (4,90) y el naranja al suyo
   (4,84), que es el mínimo indispensable y el último peldaño que existe.
   `DECISION-FUENTE: Ricardo, 2026-08-29 — «acercarse lo más posible al color base, si acaso se
   oscurece lo mínimo indispensable para lectura» · «cuidar no oscurecer demasiado para no perder
   identidad del color».` Ver COMPONENTE_SEMANTICOS.md § piso y techo. */
.exds-banner[data-variant="subtle"][data-tone="warning"],
.exds-banner[data-variant="subtle"][data-tone="success"] {
  color: var(--exds-bn-deep);
}

/* ══ ANCHORED · el aviso que EMERGE de un contenedor ═════════════════════════
   ⛔ EL LADO QUE TOCA LA SUPERFICIE VA RECTO (Ricardo, 2026-08-18 · opción A). `data-edge`
   dice QUÉ BORDE DEL AVISO está pegado, y ése pierde el radio; los otros dos lo conservan.
   `top` (el caso canónico, el error del composer) = el aviso CUELGA de la superficie.

   ⚠ Revierte en parte la decisión del 4-ago, que dejó las cuatro esquinas redondeadas con un
   argumento correcto —lo que hace emerger es el wash y el traslape, no una esquina recta— y
   un defecto ARITMÉTICO: con radio 10 y traslape 6, la curva es MÁS LARGA que lo que se mete,
   así que ~4px de curva quedan al aire por costado y dibujan un diente. *La regla vieja
   razonaba sobre lo que la esquina SIGNIFICA; el defecto vivía en lo que la esquina MIDE.*

   El ancho es el MISMO que el de la superficie y el traslape (margen negativo, sólo VERTICAL)
   lo pone quien lo monta. */
.exds-banner[data-variant="anchored"] {
  background: var(--exds-bn-wash);
  padding: 12px 14px;
  border-radius: 0 0 var(--radius-md, 10px) var(--radius-md, 10px);
}

.exds-banner[data-variant="anchored"][data-edge="bottom"] {
  border-radius: var(--radius-md, 10px) var(--radius-md, 10px) 0 0;
}

/* ══ EL CONTENIDO ════════════════════════════════════════════════════════════
   Todo hereda el color de la caja: la jerarquía la hace el PESO, nunca un gris. Un `--fg3`
   dentro de un tinte rompe la familia — mete un cuarto color en una caja que ya declara el
   suyo. Y bajar el énfasis con opacidad tumba el contraste por debajo de AA. */
.exds-banner-cuerpo {
  flex: 1;
  min-width: 0;
  color: inherit;
}

.exds-banner-ttl {
  font-weight: 600;
  color: inherit;
}

/* La acción es un ENLACE SUBRAYADO, no un botón con caja: así está triageado en la
   §Composición de la ficha. El subrayado es un borde inferior en `currentColor`, que sigue al
   tono sin tener que declararlo cinco veces. */
.exds-banner-accion {
  display: inline-block;
  margin-left: 8px;
  margin-top: 0;
  background: transparent;
  border: 0;
  padding: 0 0 1px;
  cursor: pointer;
  font-family: var(--font-sans, "Inter", -apple-system, "system-ui", sans-serif);
  font-size: var(--fs-body-sm, 13px);
  font-weight: 500;
  color: inherit;
  border-bottom: 1px solid currentColor;
}

/* Si la acción es lo único que hay, no se sangra: el margen la separa del texto, y sin texto
   dejaría el enlace descolgado 8px de la nada. */
.exds-banner-cuerpo > .exds-banner-accion:first-child {
  margin-left: 0;
}

.exds-banner-x {
  flex-shrink: 0;
  background: transparent;
  border: 0;
  padding: 0;
  cursor: pointer;
  color: inherit;
  opacity: 0.7;
  display: flex;
  align-items: center;
  line-height: 1;
}

/* ══ LA SALIDA · la hace el COMPONENTE, y es el PAPEL 2 ══════════════════════
   (Ricardo, 2026-08-19.) Al pulsar la ×, el aviso encoge su alto y se apaga a la vez:
   --motion-base sobre alto, opacidad, márgenes, relleno y borde.

   ⛔ NO es el papel 4. El 4 es la ENTRADA de un elemento y lleva su rebote. *Un rebote es una
   llegada, y esto es una despedida.*

   ⛔ Y LO QUE DE VERDAD CAMBIÓ NO ES EL EFECTO: ES DE QUIÉN ES. Antes estaba delegado —«lo
   pone quien lo monta»— y así el aviso desaparecía de golpe en cualquier pantalla que no se
   acordara de animarlo. *Lo que puede salir mal en cada montaje pertenece a la pieza.*

   ⛔ El BORDE se colapsa ENTERO, no sólo arriba y abajo: desde que `tint` lleva contorno,
   dejar los lados a 1px durante la salida deja una RAYA VERTICAL de 1px encogiéndose. Y el
   `min-height` va también: sin él el aviso se quedaba en 1px —medido—, y ese píxel es el que
   hacía que el salto final se notara. */
.exds-banner[data-cerrable="true"] {
  overflow: hidden;
  transition: max-height var(--motion-base, 250ms) var(--ease-default, cubic-bezier(0.32, 0.72, 0, 1)), opacity var(--motion-base, 250ms) var(--ease-default, cubic-bezier(0.32, 0.72, 0, 1)), margin-top var(--motion-base, 250ms) var(--ease-default, cubic-bezier(0.32, 0.72, 0, 1)), margin-bottom var(--motion-base, 250ms) var(--ease-default, cubic-bezier(0.32, 0.72, 0, 1)), padding-top var(--motion-base, 250ms) var(--ease-default, cubic-bezier(0.32, 0.72, 0, 1)), padding-bottom var(--motion-base, 250ms) var(--ease-default, cubic-bezier(0.32, 0.72, 0, 1)), border-width var(--motion-base, 250ms) var(--ease-default, cubic-bezier(0.32, 0.72, 0, 1));
}

.exds-banner[data-saliendo="true"] {
  max-height: 0;
  opacity: 0;
  margin-top: 0;
  margin-bottom: 0;
  padding-top: 0;
  padding-bottom: 0;
  border-width: 0;
  min-height: 0;
}

/* ══ SIN MOVIMIENTO · y apagar el movimiento NO es dejar sin señal (INC-405) ══
   Se retira el encogido, no el aviso de que el aviso se fue: el nodo desaparece de una vez,
   que es la señal estática equivalente. Lo que NO puede pasar —y es lo que esta regla
   impide— es que se quede quieto y visible mientras el temporizador corre por detrás. */
@media (prefers-reduced-motion: reduce) {
  .exds-banner[data-cerrable="true"] {
    transition: none;
  }
}
