/* ===========================================================================
   alier-devexpress.css — Overrides de DevExpress Blazor 25.2.9
   ---------------------------------------------------------------------------
   Estiliza los componentes DevExpress SIN sustituirlos y SIN fijar color.
   Igual que alier-tokens.css: aquí no entra ningún color literal.

   ORDEN DE CARGA (importante, hay 4 hojas de Bootstrap compitiendo):
     1. bootstrap.min.css            (base)
     2. <tema>.min.css               (blazing-berry | bootswatch/*)
     3. bootstrap-external.bs5.css   (puente DevExpress <-> Bootstrap)
     4. alier-tokens.css
     5. alier-devexpress.css   <-- este archivo
     6. *.razor.css                  (scoped, siempre al final)
   =========================================================================== */

/* ===========================================================================
   1. GRID — el problema nº1: altura fija de 812px
   ---------------------------------------------------------------------------
   Medido en producción: el grid mide 812px tanto a 900px de alto como a
   1080px. A 1366x768 se desborda 88px fuera del viewport y la página NO
   hace scroll, así que el paginador queda inalcanzable.

   Solución: el grid nunca declara altura. La hereda del contenedor flex,
   que a su vez ocupa lo que queda del viewport. La clave es `min-height: 0`
   en TODOS los ancestros flex: sin él, un hijo flex se niega a encogerse por
   debajo de su contenido y el desbordamiento vuelve.
   =========================================================================== */

.al-grid-host {
  flex: 1 1 auto;
  min-height: 0;          /* <- sin esto no funciona nada de lo de arriba */
  display: flex;
  flex-direction: column;
}

.al-grid-host .dxbl-grid {
  height: 100% !important;  /* gana al inline-style que pone el componente */
  min-height: 0;
  display: flex;
  flex-direction: column;
  border: 1px solid var(--al-border-hairline);
  border-radius: var(--al-radius-surface);
  overflow: hidden;         /* recorta las esquinas del header y el pager */
  background: var(--al-surface);
}

/* La zona scrollable crece; cabecera y paginador se quedan fijos. */
.al-grid-host .dxbl-grid-table-container {
  flex: 1 1 auto;
  min-height: 0;
  overflow: auto;
}
.al-grid-host .dxbl-grid-pager          { flex: 0 0 auto; }

/* --- Cabecera de columna --------------------------------------------------
   Sticky, discreta, con el peso justo para leerse como cabecera y no como
   una fila más. */
.al-grid-host .dxbl-grid-header-row > th {
  position: sticky;
  top: 0;
  z-index: 2;
  background: var(--al-surface-sunken);
  color: var(--al-text-muted);
  font-size: var(--al-text-xs);
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  padding: var(--al-space-2) var(--al-row-pad-x);
  border-bottom: 1px solid var(--al-border);
  white-space: nowrap;
}

/* ---------------------------------------------------------------------------
   ALINEACIÓN — problema medido: TODAS las celdas tienen text-align:center.
   Con números centrados es imposible comparar magnitudes de un vistazo
   porque las unidades, decenas y centenas no se apilan.

   Regla: texto a la izquierda, números a la derecha con cifras tabulares,
   estado y acciones al centro. Nunca "todo centrado".
   --------------------------------------------------------------------------- */
.al-grid-host tbody > tr > td {
  padding: var(--al-row-pad-y) var(--al-row-pad-x);
  font-size: var(--al-row-font);
  line-height: var(--al-leading-tight);
  height: var(--al-row-h);
  color: var(--al-text);
  border-bottom: 1px solid var(--al-border-hairline);
  text-align: left;                 /* <- corrige el center heredado */
  vertical-align: middle;
}

.al-grid-host td.al-num,
.al-grid-host th.al-num {
  text-align: right;
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
}
.al-grid-host td.al-center,
.al-grid-host th.al-center { text-align: center; }

/* Identificadores y trackings: monoespaciada para detectar un dígito
   cambiado sin leer el número entero. */
.al-grid-host td.al-code {
  font-family: var(--bs-font-monospace, ui-monospace, "SFMono-Regular", Menlo, monospace);
  font-size: var(--al-text-sm);
  letter-spacing: -0.01em;
}

/* --- Filas de relleno de DevExpress ---------------------------------------
   Cuando hay menos filas que alto de pantalla, DevExpress rellena el hueco
   con <tr class="dxbl-grid-empty-row"> y un <td colspan> vacío. NO son datos:
   no se pueden seleccionar, no abren nada y no representan ningún envío.

   Todo lo que viene debajo habla de filas de datos, así que las excluye con
   :not(.dxbl-grid-empty-row). Sin eso, el relleno heredaba el cursor de mano
   y el resaltado al pasar por encima, y parecía media pantalla clicable.
   --------------------------------------------------------------------------- */

/* Celda vacía: un guion em en color sutil. Hoy se rellenan con un espacio
   en blanco, así que no se distingue "sin dato" de "dato perdido".
   Solo en filas de datos: en el relleno pintaba un guion suelto en el aire. */
.al-grid-host tbody > tr:not(.dxbl-grid-empty-row) > td:empty::after,
.al-grid-host td .al-empty::after {
  content: "—";
  color: var(--al-text-subtle);
}

/* --- Estados de fila ------------------------------------------------------
   La fila seleccionada hoy se pinta con el acento a plena saturación en todo
   el ancho, lo que hunde el contraste del texto. Aquí es un tinte + una
   barra de 3px en el borde de inicio, que se ve igual en claro y en oscuro. */
.al-grid-host tbody > tr:not(.dxbl-grid-empty-row):hover > td { background: var(--al-row-hover); }

.al-grid-host tbody > tr.dxbl-selected > td,
.al-grid-host tbody > tr[aria-selected="true"] > td {
  background: var(--al-row-selected);
  color: var(--al-text);            /* mantiene el color de cuerpo, no invierte */
}
.al-grid-host tbody > tr.dxbl-selected > td:first-child {
  box-shadow: inset 3px 0 0 0 var(--al-accent);
}

/* Fila clicable: hoy el doble clic sobre una fila no hace nada y la única
   vía para abrir un envío es la barra de iconos. Solo las de datos. */
.al-grid-host tbody > tr:not(.dxbl-grid-empty-row) { cursor: pointer; }
.al-grid-host tbody > tr:focus-visible > td:first-child {
  box-shadow: inset 3px 0 0 0 var(--al-accent);
  outline: none;
}

/* ===========================================================================
   2. CHIPS DE ESTADO
   ---------------------------------------------------------------------------
   El grid de Outbound no muestra estado en ninguna columna, pero la barra
   ofrece "Enviar" y "Cancelar": el operador decide a ciegas. El estado se
   codifica en forma Y color, nunca solo en color (daltonismo + impresión).
   =========================================================================== */
.al-chip {
  display: inline-flex;
  align-items: center;
  gap: var(--al-space-2);
  padding: 0.125rem var(--al-space-2);
  border-radius: var(--al-radius-pill);
  font-size: var(--al-text-xs);
  font-weight: 600;
  line-height: 1.6;
  white-space: nowrap;
  border: 1px solid transparent;
}
.al-chip::before {
  content: "";
  inline-size: 0.5rem;
  block-size: 0.5rem;
  border-radius: 50%;
  background: currentColor;
  flex: 0 0 auto;
}
.al-chip--draft     { color: var(--al-text-muted); background: var(--al-surface-sunken); border-color: var(--al-border); }
.al-chip--pending   { color: var(--al-warn);   background: var(--al-warn-bg); border-color: color-mix(in srgb, var(--al-warn) 45%, transparent); }
.al-chip--transit   { color: var(--al-info);   background: var(--al-info-bg); border-color: color-mix(in srgb, var(--al-info) 40%, transparent); }
.al-chip--delivered { color: var(--al-ok);     background: var(--al-ok-bg); border-color: color-mix(in srgb, var(--al-ok) 40%, transparent); }
/* --- Badge dentro de una celda de tabla ------------------------------------
   Vale para los chips de ESTADO (Outbound, Situación de DeCAs). Basta con
   que el chip sea hijo directo de la celda. Un chip con .al-chip--tag
   (marcas puntuales) se queda en pastilla: no es una columna de estado
   y estirarlo desalinea la raya de las filas vacías. Palé no es un chip:
   es un boolean + DxCheckBox (DEC-020).

   El badge de estado ocupa la celda ENTERA, de borde a borde: sin padding,
   sin margen y sin radio. La columna se lee entonces como una banda
   continua de color, que es la forma más rápida de localizar lo que
   necesita atención al recorrer la tabla en vertical.

   El !important es deliberado: el padding de las celdas lo fija
   bootstrap-external.bs5.min.css con un selector de especificidad altísima
   (siete :not() encadenados). Sin !important no hay forma razonable de
   ganarle sin copiar ese selector entero.
   --------------------------------------------------------------------------- */
.al-grid-host td:has(> .al-chip:not(.al-chip--tag)) {
  padding: 0 !important;
  vertical-align: middle;
}

.al-grid-host td > .al-chip:not(.al-chip--tag) {
  display: flex;
  align-items: center;
  justify-content: flex-start;
  inline-size: 100%;
  block-size: 100%;
  box-sizing: border-box;
  padding-inline: var(--al-row-pad-x);
  margin: 0;
  border-radius: 0;
  border-width: 0;
}

/* Sin :has() el badge se estira dentro del padding de la celda: se ve
   correcto, solo que sin llegar al borde. */
@supports not selector(td:has(> span)) {
  .al-grid-host td > .al-chip:not(.al-chip--tag) { block-size: auto; }
}

/* Cancelado lleva borde además de color: se distingue de los demás estados
   sin depender solo del tono (daltonismo, impresión en blanco y negro).
   Antes iba tachado, pero el tachado sobre un texto de 12px lo hacía difícil
   de leer, que es peor problema que el que resolvía. */
.al-chip--cancelled {
    color: var(--al-danger);
    background: var(--al-danger-bg);
    border-color: var(--al-danger);
}

/* Palé: DxCheckBox del bool, no chip. No se estira como banda de estado. */
.al-pale-check {
  display: inline-flex;
  align-items: center;
  min-block-size: 1.25rem;
}
.al-grid-host td:has(.al-pale-check) {
  text-align: center;
  vertical-align: middle;
}

/* ===========================================================================
   3. TOOLBAR
   ---------------------------------------------------------------------------
   Medido: 12 botones de 46px con 4px de separación, todos iconos grises
   idénticos y sin etiqueta. "Editar" y "Eliminar" están a 48px de distancia,
   y "Enviar"/"Cancelar" —irreversibles— quedan intercaladas entre acciones
   inocuas. Un desliz de 24px cambia editar por eliminar.

   Reestructuración en tres zonas separadas por espacio real:
     [ vista: columnas · densidad · exportar ]  [ PRIMARIA ]  [ contextual ]
   =========================================================================== */
.al-toolbar {
  display: flex;
  align-items: center;
  gap: var(--al-space-2);
  padding: var(--al-space-2) 0;
  flex-wrap: wrap;
}

/* Barra maestra de VISTA: columnas, exportar, fila de filtros, agrupación.
   Va siempre encima de cualquier barra de filtros de datos. Alineada al
   final, que es donde el operador ya busca el column chooser. */
.al-toolbar--view {
  justify-content: flex-end;
  flex-wrap: nowrap;
  padding-block-end: var(--al-space-1);
  border-block-end: 1px solid var(--al-border-hairline);
}
.al-toolbar--view .al-viewbar { margin-inline-start: 0; }

/* Segunda fila de barra: la de los filtros de datos. Va pegada a la primera
   —no dobla el aire entre ambas— y arranca por la izquierda.

   Dos filas escritas valen mas que una que se parte sola: a 1366 la barra
   de Outbound envolvia y los controles de vista acababan abajo a la
   izquierda, que es justo donde nadie los busca. */
.al-toolbar--filters {
  padding-block-start: 0;
}

/* Align the editors themselves when some fields have a caption above them. */
.al-toolbar--editors { align-items: flex-end; }

/* Un grupo que ocupa la fila entera: deja que la barra de vista se empuje
   sola hasta la derecha con su margen automatico. */
.al-toolbar__wide { flex: 1 1 auto; }

/* El buscador cede sitio antes que la barra de vista, pero no desaparece. */
.al-toolbar > .al-searchwrap { flex: 0 1 24rem; min-inline-size: 12rem; }
.al-toolbar__group {
  display: flex;
  align-items: center;
  gap: var(--al-space-2);          /* 8px entre botones, era 4px */
}
/* Separador real entre grupos: 24px + línea. Es lo que evita el error. */
.al-toolbar__group + .al-toolbar__group {
  margin-inline-start: var(--al-space-5);
  padding-inline-start: var(--al-space-5);
  border-inline-start: 1px solid var(--al-border-hairline);
}
.al-toolbar__spacer { flex: 1 1 auto; }

.al-toolbar .dxbl-btn {
  min-block-size: 2.25rem;         /* 36px, objetivo cómodo */
  border-radius: var(--al-radius-control);
  color: var(--al-text-muted);
}
.al-toolbar .dxbl-btn:hover:not(.al-btn--primary):not(.al-btn--solid-danger) {
  background: var(--al-row-hover);
  color: var(--al-text);
}
.al-toolbar .dxbl-btn:focus-visible { box-shadow: var(--al-focus-ring); outline: none; }

/* La acción primaria lleva texto siempre. Es la única con relleno sólido. */
.al-toolbar .al-btn-primary,
.al-toolbar .al-btn--primary.dxbl-btn {
  background: var(--al-accent-fill);
  color: var(--al-on-accent);
  font-weight: 600;
  padding-inline: var(--al-space-4);
}

/* Destructiva: nunca se mezcla con el resto. Color de peligro solo al
   interactuar, para que no grite en reposo. */
.al-toolbar .al-btn-danger { color: var(--al-danger); }
.al-toolbar .al-btn-danger:hover { background: var(--al-danger-bg); color: var(--al-danger); }

/* --- Barra contextual -----------------------------------------------------
   Las acciones sobre registro (Editar, Duplicar, Enviar, Etiqueta, Tracking,
   Consultar DeCA, Eliminar) NO están visibles cuando no hay nada
   seleccionado. Aparecen aquí, ya con el contexto delante. */
.al-actionbar {
  display: flex;
  align-items: center;
  gap: var(--al-space-3);
  min-block-size: var(--al-actionbar-h);
  padding-inline: var(--al-space-4);
  background: var(--al-accent-quiet);
  border: 1px solid var(--al-accent);
  border-radius: var(--al-radius-control);
  font-size: var(--al-text-base);
  flex-wrap: wrap;
}
.al-actionbar__count { font-weight: 600; min-inline-size: 0; }
/* La destructiva se empuja al extremo opuesto de las seguras. */
.al-actionbar__danger { margin-inline-start: auto; }

/* ===========================================================================
   4. FORMULARIOS
   ---------------------------------------------------------------------------
   Medido en "Editar DeCA independiente": 27 campos, 11 anchos distintos y
   9 ejes de alineación diferentes. No hay rejilla.

   Rejilla de 12 columnas. El campo no elige su ancho: lo hereda del tipo de
   dato que contiene (ver --al-field-* en alier-tokens.css).
   =========================================================================== */
.al-form { display: flex; flex-direction: column; gap: var(--al-space-6); }

.al-fieldset { border: 0; margin: 0; padding: 0; }
.al-fieldset > legend {
  font-size: var(--al-text-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--al-text-muted);
  padding: 0 0 var(--al-space-3);
  border-bottom: 1px solid var(--al-border-hairline);
  inline-size: 100%;
  margin-block-end: var(--al-space-4);
}

.al-grid12 {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  gap: var(--al-space-4) var(--al-space-4);
  align-items: start;
}
.al-col-1 { grid-column: span 1; }
.al-col-2 { grid-column: span 2; }
.al-col-3 { grid-column: span 3; }
.al-col-4 { grid-column: span 4; }
.al-col-5 { grid-column: span 5; }
.al-col-6 { grid-column: span 6; }
.al-col-7 { grid-column: span 7; }
.al-col-8 { grid-column: span 8; }
.al-col-9 { grid-column: span 9; }
.al-col-10 { grid-column: span 10; }
.al-col-11 { grid-column: span 11; }
.al-col-12 { grid-column: span 12; }

/* Por debajo de 640px cada campo ocupa el ancho completo: una columna de
   3/12 dentro de un modal estrecho no cabe ni para un código postal.
   Lo mismo para barras de página: apilar, no partir a medias (layout-sin-desbordes). */
@media (max-width: 640px) {
  .al-grid12 > [class*="al-col-"] { grid-column: 1 / -1; }

  .al-toolbar > .al-searchwrap {
    flex: 1 1 100%;
    min-inline-size: 0;
  }
  .al-toolbar--view {
    flex-wrap: wrap;
    justify-content: flex-start;
  }

  .al-actionbar {
    padding-inline: var(--al-space-3);
    padding-block: var(--al-space-2);
  }
  .al-actionbar__danger {
    margin-inline-start: 0;
    flex: 1 1 100%;
  }
}

/* Etiqueta encima del campo: un solo eje de alineación vertical.
   El formulario actual mezcla etiquetas a la izquierda con etiquetas inline
   y por eso ningún campo se alinea con el de al lado. */
.al-field { display: flex; flex-direction: column; gap: var(--al-space-1); min-inline-size: 0; }
.al-field > label {
  font-size: var(--al-text-sm);
  font-weight: 500;
  color: var(--al-text-muted);
}
/* OJO con el selector: una casilla NO es un campo de texto.
   `.al-field input` a secas alcanzaba también al input de un checkbox —el
   nativo y el que pinta DevExpress dentro de DxCheckBox— y le aplicaba
   inline-size:100%, borde y relleno de campo de texto: la casilla salía
   estirada como una caja ancha en lugar de un cuadrado.

   Segundo OJO: el textarea de un DxMemo TAMPOCO es un campo nativo. El
   cromo (borde, fondo, radio) vive en el envoltorio `.dxbl-memo-edit`.
   Pintarlo otra vez en el <textarea> produce el doble recuadro y, con el
   alto fijo de una línea, el resize se superpone a lo de debajo.
   `.dxbl-memo` no existe: la clase real es `.dxbl-memo-edit`. */
.al-field .dxbl-text-edit,
.al-field .dxbl-spin-edit,
.al-field .dxbl-combo-box,
.al-field .dxbl-date-edit,
.al-field input:not([type="checkbox"]):not([type="radio"]),
.al-field select,
.al-field textarea:not([class*="dxbl-"]) {
  inline-size: 100%;
  min-inline-size: 0;
  border-radius: var(--al-radius-control);
  border: 1px solid var(--al-border);
  background: var(--al-surface);
  color: var(--al-text);
  font-size: var(--al-text-base);
  box-shadow: none;
  min-block-size: 2.25rem;
}
/* Dx ya trae un input de 36px dentro. Si el wrapper suma el padding de
   campo nativo (8+8) sale un cajón de 55px. El relleno vertical lo come
   el input interno; el horizontal sí es nuestro.

   DxMemo se queda fuera: no es un editor de una línea. Su envoltorio
   también lleva `.dxbl-text-edit`; si hereda `block-size: 2.25rem` el
   textarea desborda y no empuja el layout. */
.al-field :is(.dxbl-text-edit:not(.dxbl-memo-edit), .dxbl-spin-edit, .dxbl-combo-box, .dxbl-date-edit) {
  padding-block: 0;
  padding-inline: var(--al-space-3);
  block-size: 2.25rem;
}
.al-field input:not([type="checkbox"]):not([type="radio"]):not(.dxbl-text-edit-input),
.al-field select {
  padding: var(--al-space-2) var(--al-space-3);
}
.al-field textarea:not([class*="dxbl-"]),
.al-field .dxbl-memo-edit {
  padding: var(--al-space-2) var(--al-space-3);
  block-size: auto;
  max-block-size: none;
  min-block-size: 4.5rem;
}
/* El cromo interno de DX (borde, fondo, padding) se apaga: el look es el
   del prototipo, no el de fábrica. El input de dentro hereda. El
   textarea del memo se apaga igual, pero conserva min-height: si pasa a
   0, el resize nativo no tiene suelo y el campo se aplasta. */
.al-field :is(.dxbl-text-edit:not(.dxbl-memo-edit), .dxbl-spin-edit, .dxbl-combo-box, .dxbl-date-edit) input,
.al-field .dxbl-memo-edit > textarea {
  border: 0;
  background: transparent;
  box-shadow: none;
  padding: 0;
  font: inherit;
  color: inherit;
  inline-size: 100%;
}
.al-field :is(.dxbl-text-edit:not(.dxbl-memo-edit), .dxbl-spin-edit, .dxbl-combo-box, .dxbl-date-edit) input {
  min-block-size: 0;
}
.al-field :is(.dxbl-text-edit, .dxbl-spin-edit, .dxbl-combo-box, .dxbl-date-edit):focus-within {
  box-shadow: var(--al-focus-ring);
  outline: none;
  border-color: var(--al-accent);
}
/* Casillas y radios dentro de un campo: cuadrados, del tamaño del texto y
   sin estirarse. El acento sale del tema, como todo lo demás. */
.al-field :is(input[type="checkbox"], input[type="radio"]) {
  inline-size: 1rem;
  block-size: 1rem;
  flex: 0 0 auto;
  accent-color: var(--al-accent);
}

/* Un campo que solo contiene una casilla no tiene etiqueta encima, así que
   arrancaría más arriba que el campo de al lado y la fila quedaría torcida.
   Este relleno equivale a la altura de una etiqueta más su separación: la
   casilla queda a la altura de los inputs vecinos. */
.al-field--check {
  padding-block-start: calc(var(--al-text-sm) * var(--al-leading-normal) + var(--al-space-1));
}

/* El anillo de foco de un editor Dx ya lo pinta el envoltorio
   (:focus-within). Si también se lo damos al input/textarea de dentro,
   se ven dos recuadros. */
.al-field :is(input, select, textarea):not([class*="dxbl-"]):focus-visible {
  box-shadow: var(--al-focus-ring);
  outline: none;
  border-color: var(--al-accent);
}
/* Selector interno: el 100% de .al-field parte el flex y deja «Elegir»
   debajo o lo aplasta. El editor Dx y el botón van en una fila, misma altura. */
.al-field .al-pickfield > :is(.dxbl-text-edit, input) {
  inline-size: auto;
  flex: 1 1 auto;
  min-inline-size: 0;
}
.al-pickfield .al-btn.dxbl-btn {
  flex: 0 0 auto;
  min-block-size: 2.25rem;
  block-size: 2.25rem;
  padding-inline: var(--al-space-3);
  align-self: center;
}
/* Campo obligatorio: marca textual, no solo un asterisco rojo. */
.al-field--required > label::after {
  content: attr(data-required-label);
  font-weight: 400;
  font-size: var(--al-text-xs);
  color: var(--al-text-subtle);
}
.al-field__hint  { font-size: var(--al-text-xs); color: var(--al-text-subtle); }
.al-field__error { font-size: var(--al-text-xs); color: var(--al-danger); font-weight: 500; }

/* Unidad dentro del campo (Kg, €, cm): hoy "Total peso" no indica unidad
   en ninguna parte. */
.al-field__unit {
  position: relative;
  display: flex;
  align-items: center;
}
.al-field__unit > span {
  position: absolute;
  inset-inline-end: var(--al-space-3);
  font-size: var(--al-text-sm);
  color: var(--al-text-subtle);
  pointer-events: none;
}
.al-field__unit > input,
.al-field__unit > :is(.dxbl-text-edit, .dxbl-spin-edit) {
  padding-inline-end: 2.5rem;
  text-align: right;
  font-variant-numeric: tabular-nums;
}

/* Barra de acciones del formulario: pegada abajo, siempre visible.
   Hoy hay que recorrer 900px de scroll para llegar a los botones. */
.al-form-actions {
  position: sticky;
  bottom: 0;
  display: flex;
  align-items: center;
  gap: var(--al-space-3);
  padding: var(--al-space-3) var(--al-space-5);
  margin-inline: calc(var(--al-space-5) * -1);
  background: var(--al-surface);
  border-top: 1px solid var(--al-border);
  box-shadow: var(--al-shadow-2);
  z-index: 3;
}
.al-form-actions__secondary { margin-inline-start: auto; }

/* ===========================================================================
   5. TARJETAS DE TRANSPORTISTA
   ---------------------------------------------------------------------------
   La fuente de estilos del marketplace es alier-components.css. No duplicar
   aquí geometría de tarjeta: dos hojas compitiendo es lo que dejó logos
   a 3.5rem en un sitio y a 6.5rem en el otro.
   =========================================================================== */

/* ===========================================================================
   6. ESTADO VACÍO
   ---------------------------------------------------------------------------
   Embalajes, Artículos y Contactos están vacíos y solo dicen
   "No data to display" (además, en inglés). Un estado vacío debe decir qué
   es esto y ofrecer la salida.
   =========================================================================== */
.al-empty-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--al-space-3);
  padding: var(--al-space-7) var(--al-space-5);
  text-align: center;
  color: var(--al-text-muted);
}
.al-empty-state h3 { font-size: var(--al-text-md); font-weight: 600; color: var(--al-text); margin: 0; }
.al-empty-state p  { font-size: var(--al-text-base); margin: 0; max-inline-size: 42ch; }

/* ===========================================================================
   7. ACCESIBILIDAD
   =========================================================================== */
.al-visually-hidden {
  position: absolute;
  inline-size: 1px; block-size: 1px;
  padding: 0; margin: -1px;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap;
}
.al-skip-link {
  position: absolute;
  inset-block-start: -100%;
  inset-inline-start: var(--al-space-3);
  z-index: 100;
  padding: var(--al-space-2) var(--al-space-4);
  background: var(--al-accent-fill);
  color: var(--al-on-accent);
  border-radius: var(--al-radius-control);
}
.al-skip-link:focus { inset-block-start: var(--al-space-3); }

/* Foco visible en todo lo interactivo: hoy DevExpress lo pinta muy tenue. */
.al-grid-host :focus-visible,
.al-toolbar :focus-visible,
.al-form :focus-visible { box-shadow: var(--al-focus-ring); outline: none; }

/* ===========================================================================
   6. CROMOS DX QUE NO PUEDEN VERSE
   ---------------------------------------------------------------------------
   Los controles son primitivas DevExpress. El look es el del prototipo.
   Si un DxTextBox enseña borde doble, botón clear o altura distinta, esta
   sección está mal. El embudo, las flechas de orden y el paginador no se
   tocan (DEC-010).
   =========================================================================== */

/* --- Botones: DxButton + clases .al-btn / .al-iconbtn --------------------
   RenderStyle se deja en Secondary/Contained y el color lo pone nuestra
   clase. all:revert-layer no existe aquí; se pisan las vars de DX. */
.al-btn.dxbl-btn,
.al-iconbtn.dxbl-btn,
.al-chipfilter__btn.dxbl-btn,
.al-choice.dxbl-btn,
.al-picker__row.dxbl-btn,
.al-lines__pick.dxbl-btn {
  --dxbl-btn-bg: transparent;
  --dxbl-btn-hover-bg: transparent;
  --dxbl-btn-pressed-bg: transparent;
  --dxbl-btn-border-color: transparent;
  --dxbl-btn-color: inherit;
  background: var(--al-btn-bg, transparent);
  color: inherit;
  border-color: inherit;
  box-shadow: none;
  min-block-size: unset;
  min-inline-size: unset;
  padding-block: 0;
  font: inherit;
  line-height: inherit;
  gap: inherit;
}
.al-btn.dxbl-btn { min-block-size: 2.25rem; padding-inline: var(--al-space-4); }
.al-btn--sm.dxbl-btn { min-block-size: 1.875rem; padding-inline: var(--al-space-3); font-size: var(--al-text-sm); }
.al-btn--xs.dxbl-btn { min-block-size: 1.625rem; padding-inline: var(--al-space-2); font-size: var(--al-text-xs); }
.al-btn--primary.dxbl-btn,
:where(.tms-ui) .dxbl-btn.al-btn--primary,
:where(.tms-ui) .dxbl-btn.dxbl-btn-secondary.al-btn--primary,
:where(.tms-ui) .dxbl-btn.dxbl-btn-contained.al-btn--primary {
  --dxbl-btn-bg: var(--al-accent-fill);
  --dxbl-btn-hover-bg: var(--al-accent-fill-hover);
  --dxbl-btn-color: var(--al-on-accent);
  --dxbl-btn-hover-color: var(--al-on-accent);
  background: var(--al-accent-fill) !important;
  background-color: var(--al-accent-fill) !important;
  color: var(--al-on-accent) !important;
  border-color: transparent !important;
}
.al-btn--primary.dxbl-btn:hover,
.al-btn--primary.dxbl-btn:focus-visible,
:where(.tms-ui) .dxbl-btn.al-btn--primary:hover,
:where(.tms-ui) .dxbl-btn.al-btn--primary:focus-visible,
:where(.tms-ui) .dxbl-btn.dxbl-btn-secondary.al-btn--primary:hover,
:where(.tms-ui) .dxbl-btn.dxbl-btn-contained.al-btn--primary:hover {
  background: var(--al-accent-fill-hover) !important;
  background-color: var(--al-accent-fill-hover) !important;
  color: var(--al-on-accent) !important;
}
.al-btn--primary.dxbl-btn .dxbl-btn-content {
  color: var(--al-on-accent) !important;
}
.al-btn--ghost.dxbl-btn,
:where(.tms-ui) .dxbl-btn.al-btn--ghost,
:where(.tms-ui) .dxbl-btn.dxbl-btn-secondary.al-btn--ghost {
  background: var(--al-surface) !important;
  background-color: var(--al-surface) !important;
  color: var(--al-text-muted) !important;
  border-color: var(--al-border) !important;
}
.al-btn--ghost.dxbl-btn:hover,
.al-btn--ghost.dxbl-btn:focus-visible,
:where(.tms-ui) .dxbl-btn.al-btn--ghost:hover,
:where(.tms-ui) .dxbl-btn.al-btn--ghost:focus-visible {
  background: var(--al-row-hover) !important;
  color: var(--al-text) !important;
  border-color: var(--al-border) !important;
}
.al-btn--ghost.dxbl-btn .dxbl-btn-content {
  color: inherit !important;
}
.al-btn--danger.dxbl-btn {
  background: transparent;
  color: var(--al-danger);
  border-color: transparent;
}
.al-btn--danger.dxbl-btn:hover,
.al-btn--danger.dxbl-btn:focus-visible {
  background: var(--al-danger-bg);
  color: var(--al-danger);
}
.al-btn--solid-danger.dxbl-btn {
  background: var(--al-danger-fill) !important;
  color: var(--al-on-danger) !important;
  border-color: transparent;
}
.al-btn--solid-danger.dxbl-btn:hover,
.al-btn--solid-danger.dxbl-btn:focus-visible {
  background: var(--al-danger-fill-hover) !important;
  color: var(--al-on-danger) !important;
}
.al-iconbtn.dxbl-btn {
  inline-size: 2.25rem;
  block-size: 2.25rem;
  padding: 0;
  background: transparent;
  color: var(--al-text-muted);
  border-color: transparent;
}
/* X del modal: DxButton no es el ítem flex (el host sí). El auto hay que
   ponerlo en el último hijo de la cabecera, no en el <button> interno. */
.al-modal__head {
  display: flex;
  align-items: flex-start;
  inline-size: 100%;
}
.al-modal__headtext {
  flex: 1 1 auto;
  min-inline-size: 0;
}
.al-modal__head > :last-child {
  margin-inline-start: auto;
  flex: 0 0 auto;
  align-self: flex-start;
}
.al-modal__head .al-modal__close,
.al-modal__head .al-iconbtn.dxbl-btn,
.al-modal__head .al-modal__close.dxbl-btn {
  inline-size: 2.25rem;
  max-inline-size: 2.25rem;
  block-size: 2.25rem;
}
.al-modal__dirty {
  margin-inline-start: auto;
}
.al-modal__dirty + :last-child {
  margin-inline-start: var(--al-space-2);
}
.al-drawer__head .al-iconbtn.dxbl-btn {
  margin-inline-start: auto;
  flex: 0 0 auto;
}
.al-iconbtn--sm.dxbl-btn {
  inline-size: 1.75rem;
  block-size: 1.75rem;
}
.al-iconbtn.dxbl-btn .dxbl-btn-content { display: grid; place-items: center; }
.al-choice.dxbl-btn {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--al-space-1);
  min-block-size: unset;
  padding: var(--al-space-3) var(--al-space-4);
  text-align: start;
  background: var(--al-surface);
  border: 1px solid var(--al-border);
  color: inherit;
}
.al-picker__row.dxbl-btn {
  /* DxButton pinta `inline-flex` con 4 clases; sin esto la fila
     queda en una sola línea (código · nombre · dirección). */
  display: grid !important;
  grid-template-columns: 7.5rem minmax(0, 1fr);
  grid-template-areas:
      "code name"
      "code meta";
  gap: 0 var(--al-space-3);
  align-items: center;
  justify-content: stretch;
  inline-size: 100%;
  min-block-size: 2.75rem;
  padding: var(--al-space-2) var(--al-space-3);
  background: transparent;
  border: 1px solid transparent;
  color: var(--al-text);
  text-align: start;
}
.al-picker__row.dxbl-btn .dxbl-btn-content {
  display: grid;
  grid-template-columns: 7.5rem minmax(0, 1fr);
  grid-template-areas:
      "code name"
      "code meta";
  gap: 0 var(--al-space-3);
  align-items: center;
  inline-size: 100%;
  justify-content: start;
  text-align: start;
}
/* El <span class="al-mono"> no es hijo directo: DxButton envuelve el
   contenido. El selector scoped `> .al-mono` no atraviesa ese cromo. */
.al-picker__row .al-mono {
  grid-area: code;
}
.al-lines__pick.dxbl-btn {
  min-block-size: unset;
  padding: 0;
  background: transparent;
  border: 0;
  color: inherit;
  font: inherit;
}
.al-card__link.dxbl-btn,
.al-ws__makedefault.dxbl-btn {
  min-block-size: unset;
  padding: 0;
  background: transparent;
  border: 0;
  color: var(--al-accent);
  font: inherit;
}
.al-btn.is-active.dxbl-btn {
  border-color: var(--al-accent);
  color: var(--al-accent);
}
.al-chipfilter__btn.dxbl-btn {
  min-block-size: 2.25rem;
  padding-inline: var(--al-space-3);
  border-radius: var(--al-radius-pill);
  background: var(--al-surface);
  color: var(--al-text-muted);
  border-color: var(--al-border-hairline);
}
.al-chipfilter__btn.is-active.dxbl-btn {
  background: var(--al-accent-quiet);
  border-color: var(--al-accent);
  color: var(--al-accent);
}

/* Buscador de barra: el icono Lucide se queda; el input es DxTextBox.
   OJO: .al-searchwrap tiene flex: 0 1 24rem. En una fila eso es el ANCHO.
   Dentro de .al-picker (columna) el mismo flex-basis se vuelve ALTURA:
   24rem = 384px y el campo queda flotando en el centro. El picker lo
   anula: una sola línea de 2.25rem. */
.al-picker .al-searchwrap,
.al-picker__search {
  flex: 0 0 auto;
  flex-basis: auto;
  min-block-size: 2.25rem;
  max-block-size: 2.25rem;
  min-inline-size: 0;
  max-inline-size: 28rem;
  inline-size: 100%;
  align-self: start;
}
.al-searchwrap .dxbl-text-edit {
  inline-size: 100%;
  min-block-size: 2.25rem;
  block-size: 2.25rem;
  max-block-size: 2.25rem;
  flex: 1 1 auto;
  padding-inline: 2.25rem var(--al-space-3);
  padding-block: 0;
  border: 1px solid var(--al-border);
  border-radius: var(--al-radius-control);
  background: var(--al-surface);
  color: var(--al-text);
  font-size: var(--al-text-base);
  box-shadow: none;
  position: relative;
  z-index: 0;
}
.al-searchwrap .dxbl-text-edit input {
  border: 0;
  background: transparent;
  box-shadow: none;
  padding: 0;
  font: inherit;
  color: inherit;
}
.al-searchwrap .dxbl-text-edit:focus-within {
  box-shadow: var(--al-focus-ring);
  border-color: var(--al-accent);
}

/* Filtros de lista (DeCAs): mismos campos, ahora Dx. */
.al-filters .dxbl-text-edit,
.al-filters .dxbl-combo-box,
.al-filters .dxbl-date-edit {
  min-block-size: 2.25rem;
  block-size: 2.25rem;
  border: 1px solid var(--al-border);
  border-radius: var(--al-radius-control);
  background: var(--al-surface);
  color: var(--al-text);
  box-shadow: none;
  padding-block: 0;
  padding-inline: var(--al-space-3);
}
.al-filters :is(.dxbl-text-edit, .dxbl-combo-box, .dxbl-date-edit) input {
  border: 0; background: transparent; box-shadow: none; padding: 0; font: inherit;
}

/* Líneas de bulto: spin/texto compactos, sin flechas de DX. */
.al-lines .dxbl-spin-edit,
.al-lines .dxbl-text-edit {
  min-block-size: 1.75rem;
  padding: 0.125rem var(--al-space-2);
  border: 1px solid var(--al-border);
  border-radius: var(--al-radius-control);
  background: var(--al-surface);
  box-shadow: none;
}
.al-lines :is(.dxbl-spin-edit, .dxbl-text-edit) input {
  border: 0; background: transparent; box-shadow: none; padding: 0; font: inherit;
  text-align: inherit;
}

/* Editor de bultos/artículos: DxGrid sin cromo de lista (pager, 100% alto). */
:where(.tms-ui) .dxbl-grid.al-lines-grid {
  height: auto !important;
  min-height: 0;
  border: 0;
  background: transparent;
  overflow: visible;
  display: block;
}
:where(.tms-ui) .dxbl-grid.al-lines-grid .dxbl-grid-table-container {
  overflow: visible;
}
:where(.tms-ui) .dxbl-grid.al-lines-grid .dxbl-grid-header-row > th {
  padding: var(--al-space-2);
  text-align: start;
  font-weight: 600;
  font-size: var(--al-text-xs);
  text-transform: uppercase;
  letter-spacing: .04em;
  color: var(--al-text-muted);
  border-block-end: 1px solid var(--al-border);
  background: transparent;
  white-space: nowrap;
}
:where(.tms-ui) .dxbl-grid.al-lines-grid tbody > tr > td {
  padding: var(--al-space-1) var(--al-space-2);
  border-block-end: 1px solid var(--al-border-hairline);
  vertical-align: middle;
  background: transparent;
}
:where(.tms-ui) .dxbl-grid.al-lines-grid--inner .dxbl-grid-header-row > th {
  border-block-end-color: var(--al-border-hairline);
}
:where(.tms-ui) .dxbl-grid.al-lines-grid--inner tbody > tr > td {
  border-block-end: none;
}
:where(.tms-ui) .dxbl-grid.al-lines-grid .dxbl-grid-detail-cell {
  padding: 0;
  background: transparent;
}

.al-field.is-invalid :is(.dxbl-text-edit, .dxbl-spin-edit, .dxbl-combo-box, .dxbl-date-edit) {
  border-color: var(--al-danger);
  background: color-mix(in srgb, var(--bs-danger) 6%, var(--bs-body-bg));
}
.al-field input:not([class*="dxbl-"])[readonly],
.al-field textarea:not([class*="dxbl-"])[readonly],
.al-field .dxbl-text-edit.dxbl-disabled,
.al-field .dxbl-text-edit:has(input[readonly]),
.al-field .dxbl-text-edit:has(textarea[readonly]) {
  background: var(--al-surface-sunken);
  color: var(--al-text-muted);
}

/* --- Modal: DxPopup envuelve .al-modal, no se ve el cromo de DX ----------
   En 25.2 el popup sombreado se pinta como dxbl-modal: dialog + content +
   body. Si no se apagan, el equipo ve DOS tarjetas: la de fábrica (fondo,
   radio, sombra, 8px de padding) y la nuestra .al-modal dentro. */
:where(.tms-ui) .dxbl-popup.al-dx-popup,
.al-dx-popup.dxbl-popup,
dxbl-modal-dialog.al-dx-popup,
.al-dx-popup {
  background: transparent !important;
  border: none !important;
  box-shadow: none !important;
  padding: 0 !important;
  overflow: visible;
  border-radius: 0 !important;
}
.al-dx-popup .dxbl-popup-content,
.al-dx-popup .dxbl-popup-body,
.al-dx-popup .dxbl-modal-content,
.al-dx-popup .dxbl-modal-body,
dxbl-modal-dialog.al-dx-popup .dxbl-modal-content,
dxbl-modal-dialog.al-dx-popup .dxbl-modal-body {
  padding: 0 !important;
  background: transparent !important;
  border: none !important;
  box-shadow: none !important;
  overflow: visible;
  border-radius: 0 !important;
}
dxbl-modal-root:has(.al-dx-popup),
dxbl-modal:has(.al-dx-popup) {
  background: transparent !important;
  box-shadow: none !important;
}
/* Shader del popup: el mismo scrim que .al-modal__scrim. Una sola capa. */
body > .dxbl-shader,
:where(.tms-ui) .dxbl-popup-root .dxbl-shader,
dxbl-modal-root:has(.al-dx-popup) .dxbl-shader {
  background: color-mix(in srgb, var(--bs-body-color) 45%, transparent);
  backdrop-filter: blur(2px);
}

/* ===========================================================================
   8. UN SOLO CROMO — receta para el equipo
   ---------------------------------------------------------------------------
   Dx pinta borde en el wrapper Y otra vez en `.dxbl-text-edit-input`.
   Bootswatch subraya `.btn` al hover. El botón del combo/fecha es más alto
   que el campo y parece una caja pegada. Esta sección lo aplasta: el
   único borde es el del envoltorio `.al-*`. Embudo, flechas y paginador
   del grid no se tocan (DEC-010).
   =========================================================================== */

/* El input de dentro no dibuja caja: si no, se ve el doble borde.
   DxMemo se queda fuera: overflow:hidden + min-height:0 aplasta el
   textarea y recorta el asa de resize. Su receta está debajo. */
:where(.tms-ui) .dxbl-text-edit:not(.dxbl-memo-edit) .dxbl-text-edit-input,
:where(.tms-ui) .dxbl-spin-edit .dxbl-text-edit-input,
:where(.tms-ui) .dxbl-combo-box .dxbl-text-edit-input,
:where(.tms-ui) .dxbl-date-edit .dxbl-text-edit-input {
  border: 0 !important;
  outline: none !important;
  box-shadow: none !important;
  background: transparent !important;
  min-height: 0 !important;
  min-block-size: 0 !important;
  padding: 0 !important;
  line-height: 1.25;
  border-radius: 0 !important;
  overflow: hidden;
}

/* Recuadro completo: overflow:hidden + max-height recortaba tres lados y
   dejaba la línea de abajo con las esquinas redondas. El radio va en el
   envoltorio, no en el input.

   DxMemo también lleva `.dxbl-text-edit`. Si entra aquí hereda 36px de
   alto, flex centrado y overflow visible: el textarea crece arriba y
   abajo a la vez y se superpone a etiqueta y pie. */
:where(.tms-ui) .dxbl-text-edit:not(.dxbl-memo-edit),
:where(.tms-ui) .dxbl-spin-edit,
:where(.tms-ui) .dxbl-combo-box,
:where(.tms-ui) .dxbl-date-edit {
  display: flex;
  align-items: center;
  overflow: visible;
  box-sizing: border-box;
  min-block-size: 2.25rem;
  padding-block: 0;
  border-width: 1px !important;
  border-style: solid !important;
  border-color: var(--al-border) !important;
  border-radius: var(--al-radius-control) !important;
  background: var(--al-surface);
  background-clip: padding-box;
}

/* DxMemo: un solo recuadro, alto auto, resize en flujo.
   El envoltorio es el cromo. El textarea es contenido: su altura
   (incluido el resize nativo) empuja lo de debajo. */
:where(.tms-ui) .dxbl-text-edit.dxbl-memo-edit {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  justify-content: flex-start;
  overflow: visible;
  box-sizing: border-box;
  min-block-size: 4.5rem;
  block-size: auto;
  padding-block: var(--al-space-2);
  padding-inline: var(--al-space-3);
  border-width: 1px !important;
  border-style: solid !important;
  border-color: var(--al-border) !important;
  border-radius: var(--al-radius-control) !important;
  background: var(--al-surface);
  background-clip: padding-box;
}
:where(.tms-ui) .dxbl-text-edit.dxbl-memo-edit > textarea {
  display: block;
  align-self: stretch;
  inline-size: 100%;
  max-inline-size: 100%;
  block-size: auto;
  min-block-size: 4.5rem;
  min-height: 4.5rem;
  border: 0 !important;
  outline: none !important;
  box-shadow: none !important;
  background: transparent !important;
  padding: 0 !important;
  margin: 0;
  line-height: inherit;
  font: inherit;
  color: inherit;
  border-radius: 0 !important;
  overflow: auto;
}

/* Flecha del combo / calendario: dentro del campo, sin caja propia. */
:where(.tms-ui) .dxbl-text-edit .dxbl-btn-group,
:where(.tms-ui) .dxbl-combo-box .dxbl-btn-group,
:where(.tms-ui) .dxbl-date-edit .dxbl-btn-group,
:where(.tms-ui) .dxbl-spin-edit .dxbl-btn-group {
  align-self: stretch;
  display: flex;
  border: 0;
  background: transparent;
  box-shadow: none;
  min-block-size: 0;
}
:where(.tms-ui) .dxbl-text-edit .dxbl-edit-btn,
:where(.tms-ui) .dxbl-combo-box .dxbl-edit-btn,
:where(.tms-ui) .dxbl-date-edit .dxbl-edit-btn,
:where(.tms-ui) .dxbl-spin-edit .dxbl-edit-btn,
:where(.tms-ui) .dxbl-text-edit .dxbl-btn-group .dxbl-btn,
:where(.tms-ui) .dxbl-combo-box .dxbl-btn-group .dxbl-btn,
:where(.tms-ui) .dxbl-date-edit .dxbl-btn-group .dxbl-btn {
  border: 0 !important;
  background: transparent !important;
  box-shadow: none !important;
  min-block-size: 0 !important;
  min-inline-size: 1.75rem;
  block-size: 100%;
  padding: 0;
  color: var(--al-text-muted);
}

/* Bootswatch / Bootstrap subrayan `.btn`. Los nuestros no. */
.al-btn.dxbl-btn,
.al-iconbtn.dxbl-btn,
.al-chipfilter__btn.dxbl-btn,
.al-choice.dxbl-btn,
.al-lines__pick.dxbl-btn,
.al-card__link.dxbl-btn,
.al-ws__makedefault.dxbl-btn,
:where(.tms-ui) .dxbl-edit-btn {
  text-decoration: none !important;
}
.al-btn.dxbl-btn:hover,
.al-btn.dxbl-btn:focus,
.al-btn.dxbl-btn:active,
.al-iconbtn.dxbl-btn:hover,
.al-chipfilter__btn.dxbl-btn:hover,
.al-choice.dxbl-btn:hover,
.al-card__link.dxbl-btn:hover,
:where(.tms-ui) .dxbl-edit-btn:hover {
  text-decoration: none !important;
}

/* El contenido interno del DxButton no añade un segundo borde. */
.al-btn.dxbl-btn .dxbl-btn-content,
.al-iconbtn.dxbl-btn .dxbl-btn-content,
.al-chipfilter__btn.dxbl-btn .dxbl-btn-content {
  border: 0;
  box-shadow: none;
  background: transparent;
  text-decoration: none;
  color: inherit;
}

/* ===========================================================================
   9. CROMO DX CON PIEL ALIER (duplicado experimental)
   ---------------------------------------------------------------------------
   Receta de AlModal: el host Dx se aplasta; el cromo visible es .al-*.
   No se toca embudo, flechas de orden ni paginador.
   =========================================================================== */
.al-theme__trigger.dxbl-btn,
.al-decaquota__trigger.dxbl-btn,
.al-user__trigger.dxbl-btn,
.al-theme__option.dxbl-btn,
.al-density__btn.dxbl-btn,
.al-decaquota__cta.dxbl-btn,
.al-user__item.dxbl-btn,
.al-chromeswitch__btn.dxbl-btn {
  --dxbl-btn-bg: transparent;
  --dxbl-btn-hover-bg: transparent;
  --dxbl-btn-pressed-bg: transparent;
  --dxbl-btn-border-color: transparent;
  --dxbl-btn-color: inherit;
  background: var(--al-btn-bg, transparent);
  color: inherit;
  border-color: inherit;
  box-shadow: none;
  min-block-size: unset;
  min-inline-size: unset;
  padding-block: 0;
  font: inherit;
  line-height: inherit;
  gap: inherit;
  text-decoration: none !important;
}
/* El neutralizador de arriba anula min-block-size; el chip la necesita para
   medir igual que el canónico (32px de alto, 32 de ancho en reposo).
   El `gap: inherit` del neutralizador dejaba el icono pegado al texto: en el
   canónico el hueco lo pone el propio disparador, y ese CSS no llega al
   <button> de DevExpress. Reposo sin hueco (solo icono) y 240 ms al abrir,
   como manda `DEC-017`. */
.al-theme__trigger.dxbl-btn,
.al-decaquota__trigger.dxbl-btn {
  min-block-size: 2rem;
  min-inline-size: 2rem;
  gap: 0;
  padding-inline: var(--al-space-2);
  background: var(--al-surface);
  border-color: var(--al-border);
  /* Sin esto el texto del chip hereda los 16px de la cabecera: el canónico lo
     fija en el disparador y ese CSS tampoco llega al <button> de Dx. */
  font-size: var(--al-text-sm);
  transition:
    gap var(--al-duration-expand) var(--al-ease-expand),
    padding-inline var(--al-duration-expand) var(--al-ease-expand);
}
/* El neutralizador hereda color y gap del host; estos dos los fija el
   canónico en el propio trigger, así que hay que repetirlos aquí. */
.al-theme__trigger.dxbl-btn { color: var(--al-text-muted); }

/* El host .al-user lleva la línea separadora; el botón no lleva borde.
   Sin esto, `border-color: inherit` le copia la línea a los cuatro lados.
   El gap heredado sería 0 y el avatar quedaría pegado al nombre. */
.al-user__trigger.dxbl-btn {
  min-block-size: 2rem;
  padding-inline: 0 var(--al-space-2);
  border: 0;
  gap: var(--al-space-2);
  color: var(--al-text-muted);
}
.al-user:hover .al-user__trigger.dxbl-btn,
.al-user.is-open .al-user__trigger.dxbl-btn { color: var(--al-text); }
.al-theme.is-open .al-theme__trigger.dxbl-btn,
.al-decaquota--chip.is-open .al-decaquota__trigger.dxbl-btn {
  gap: var(--al-space-2);
  padding-inline: var(--al-space-3);
  border-color: var(--al-accent);
}
/* Las filas de los paneles las pinta DevExpress: el <button> no lleva el
   atributo de scope, así que su geometría no puede vivir en el .razor.css.
   Se repiten aquí los mismos valores que el canónico, token a token. */
.al-theme__option.dxbl-btn {
  inline-size: 100%;
  min-block-size: 2rem;
  justify-content: flex-start;
  gap: var(--al-space-2);
  padding-block: 1px;
  padding-inline: var(--al-space-2);
  border-radius: var(--al-radius-control);
  background: transparent;
  border-color: transparent;
  font-size: var(--al-text-base);
  line-height: 1.5;
}
.al-theme__option.is-active.dxbl-btn {
  background: var(--al-accent-quiet);
  color: var(--al-accent);
  font-weight: 600;
}
.al-density__btn.dxbl-btn {
  inline-size: 1.75rem;
  block-size: 1.75rem;
  padding: 0;
  background: transparent;
  border-color: transparent;
}
.al-density__btn.is-active.dxbl-btn {
  background: var(--al-surface);
  color: var(--al-accent);
  box-shadow: var(--al-shadow-1);
}
.al-decaquota__cta.dxbl-btn {
  inline-size: 100%;
  min-block-size: 2rem;
  justify-content: flex-start;
  gap: var(--al-space-2);
  margin-block-start: var(--al-space-2);
  padding-inline: var(--al-space-2);
  border-radius: var(--al-radius-control);
  background: transparent;
  border-color: transparent;
  color: var(--al-accent);
  font-size: var(--al-text-sm);
  font-weight: 600;
}
.al-user__item.dxbl-btn {
  justify-content: flex-start;
  align-items: flex-start;
  gap: var(--al-space-2);
  padding: var(--al-space-2);
  border-radius: var(--al-radius-control);
  background: transparent;
  border-color: transparent;
  inline-size: 100%;
}

/* El neutralizador deja el hover y el foco en transparente y sin sombra: las
   filas de panel se quedarían sin respuesta. Se restituyen con los tokens. */
.al-theme__option.dxbl-btn:hover,
.al-user__item.dxbl-btn:hover,
.al-decaquota__cta.dxbl-btn:hover {
  background: var(--al-row-hover);
}
.al-theme__option.is-active.dxbl-btn:hover {
  background: var(--al-accent-quiet);
}
.al-theme__option.dxbl-btn:focus-visible,
.al-user__item.dxbl-btn:focus-visible,
.al-decaquota__cta.dxbl-btn:focus-visible {
  box-shadow: var(--al-focus-ring);
  outline: none;
}
.al-chromeswitch__btn.dxbl-btn {
  min-block-size: 1.5rem;
  padding-inline: var(--al-space-1);
  background: transparent;
  border-color: transparent;
}
.al-chromeswitch__btn.is-active.dxbl-btn { color: var(--al-accent); }

.al-theme__trigger.dxbl-btn .dxbl-btn-content,
.al-decaquota__trigger.dxbl-btn .dxbl-btn-content,
.al-user__trigger.dxbl-btn .dxbl-btn-content {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: inherit;
  inline-size: 100%;
  border: 0;
  box-shadow: none;
  background: transparent;
}
.al-theme__option.dxbl-btn .dxbl-btn-content,
.al-user__item.dxbl-btn .dxbl-btn-content {
  display: flex;
  align-items: flex-start;
  justify-content: flex-start;
  gap: inherit;
  inline-size: 100%;
  border: 0;
  box-shadow: none;
  background: transparent;
}
.al-density__btn.dxbl-btn .dxbl-btn-content {
  display: grid;
  place-items: center;
  border: 0;
  box-shadow: none;
  background: transparent;
}

/* El portal de DxDropDown nace en z-index 0 y queda detrás del shell (100dvh).
   AlModal ya usa ZIndex=200. El cromo experimental tiene que ir por encima. */
dxbl-popup-root:has(.al-dx-dd) {
  z-index: 400;
}

/* Host de DxDropDown: transparente, como .al-dx-popup. El menú es .al-*. */
.al-dx-dd,
.al-dx-dd.dxbl-drop-down,
.al-dx-dd.dxbl-popup,
.al-dx-dd.dxbl-dropdown {
  background: transparent !important;
  border: none !important;
  box-shadow: none !important;
  padding: 0 !important;
  overflow: visible;
  border-radius: 0 !important;
}
/* .dxbl-dropdown-body añade otros 8px sobre los del panel: el contenido
   quedaba a 16px del borde, el doble que en el canónico. */
.al-dx-dd .dxbl-drop-down-content,
.al-dx-dd .dxbl-dropdown-content,
.al-dx-dd .dxbl-dropdown-body,
.al-dx-dd .dxbl-popup-content,
.al-dx-dd .dxbl-popup-body {
  padding: 0 !important;
  background: transparent !important;
  border: none !important;
  box-shadow: none !important;
  overflow: visible;
  border-radius: 0 !important;
}

/* --- Drawer de ficha (AlDrawer, DEC-035) --------------------------------
   Distinto del sidebar de DxAppShell (.al-dx-drawer). El panel es el de
   un maestro corto: lista visible a la izquierda, ficha a la derecha.
   El cromo visible es .al-drawer; aquí se apaga el de fábrica. */
.al-page:has(.al-form-drawer) {
  padding: 0;
  overflow: hidden;
  gap: 0;
}
.al-form-drawer.dxbl-drawer,
:where(.tms-ui) .dxbl-drawer.al-form-drawer {
  flex: 1 1 auto;
  min-block-size: 0;
  min-inline-size: 0;
  block-size: 100%;
}
.al-form-drawer .dxbl-drawer-panel,
.al-form-drawer .dxbl-drawer-panel-container,
.al-form-drawer .dxbl-drawer-body {
  background: var(--al-surface);
  color: var(--al-text);
  border-inline-start: 1px solid var(--al-border);
  box-shadow: -12px 0 32px color-mix(in srgb, var(--bs-body-color) 18%, transparent);
  padding: 0;
  overflow: hidden;
  max-inline-size: 100%;
}
.al-form-drawer .dxbl-drawer-body {
  display: flex;
  flex-direction: column;
  min-block-size: 0;
  block-size: 100%;
}
.al-drawer-target {
  display: flex;
  flex-direction: column;
  gap: var(--al-space-3);
  min-block-size: 100%;
  min-inline-size: 0;
  padding: var(--al-space-4) var(--al-space-5);
  box-sizing: border-box;
}
@media (max-width: 640px) {
  .al-drawer-target { padding: var(--al-space-3); }
}

/* Contact catalog selectors and DeCA sections use the existing theme tokens. */
.tms-contact-selector { margin-block-end: 1.25rem; }
.tms-deca-form .tms-deca-section { margin-block-end: 1.5rem; }
.tms-deca-form .dxbl-fl-group { border-color: var(--bs-border-color); }
.pac-container { z-index: 2100; }