/* ===========================================================================
   alier-forms.css — estados de validación y ayudas de formulario
   Sin colores literales: todo derivado del tema activo.
   =========================================================================== */

/* --- Resumen de errores ---------------------------------------------------
   Aparece arriba del formulario solo DESPUÉS de un intento de guardar
   fallido. Enseñar los errores antes de que el usuario haya terminado de
   escribir es hostil y entrena a ignorarlos. */
.al-formerrors {
    display: flex;
    flex-direction: column;
    gap: var(--al-space-2);
    padding: var(--al-space-3) var(--al-space-4);
    margin-block-end: var(--al-space-5);
    background: var(--al-danger-bg);
    border: 1px solid var(--al-danger);
    border-radius: var(--al-radius-control);
    font-size: var(--al-text-base);
}
.al-formerrors b { color: var(--al-danger); }
.al-formerrors ul { margin: 0; padding-inline-start: var(--al-space-5); display: flex; flex-direction: column; gap: 2px; }
.al-formerrors li { color: var(--al-text); }

/* --- Campo inválido -------------------------------------------------------
   El estado se marca con borde Y con texto, nunca solo con color: un operador
   daltónico tiene que poder verlo, y el mensaje explica cómo arreglarlo. */
.al-field.is-invalid input:not([class*="dxbl-"]):not([type="checkbox"]):not([type="radio"]),
.al-field.is-invalid select,
.al-field.is-invalid textarea:not([class*="dxbl-"]),
.al-field.is-invalid .invalid {
    border-color: var(--al-danger);
    background: color-mix(in srgb, var(--bs-danger) 6%, var(--bs-body-bg));
}
.al-field.is-invalid > label { color: var(--al-danger); }

/* Blazor pone estas clases por su cuenta en los componentes Input*. */
.al-field .invalid { border-color: var(--al-danger); }
.al-field .modified.valid { border-color: color-mix(in srgb, var(--bs-success) 55%, transparent); }

/* --- Contador de caracteres ------------------------------------------------
   Va alineado a la derecha, debajo del textarea al que pertenece. */
.al-field--counter {
    margin-block-start: calc(var(--al-space-3) * -1);
    align-items: flex-end;
}

/* --- Campos de solo lectura -------------------------------------------------
   Se distinguen a simple vista: si parece editable y no lo es, el usuario
   pierde tiempo intentando escribir. */
.al-field input:not([class*="dxbl-"])[readonly],
.al-field textarea:not([class*="dxbl-"])[readonly] {
    background: var(--al-surface-sunken);
    color: var(--al-text-muted);
    cursor: default;
}

/* --- Ayuda y error ---------------------------------------------------------- */
.al-field__hint {
    font-size: var(--al-text-xs);
    color: var(--al-text-subtle);
    line-height: 1.35;
}
.al-field__error {
    font-size: var(--al-text-xs);
    color: var(--al-danger);
    font-weight: 500;
    line-height: 1.35;
}

/* La marca de obligatorio va en palabras, no solo con un asterisco rojo:
   un asterisco no lo entiende todo el mundo y no lo lee un lector de pantalla
   como "obligatorio". */
.al-field--required > label::after {
    content: attr(data-required-label);
    font-weight: 400;
    font-size: var(--al-text-xs);
    color: var(--al-text-subtle);
    letter-spacing: 0;
}
.al-field.is-invalid.al-field--required > label::after { color: var(--al-danger); }

/* ---------------------------------------------------------------------------
   Etiqueta de un campo condicional que aparece bajo una casilla.
   El original pinta estos inputs SIN etiqueta: para un lector de pantalla el
   campo no tiene nombre y solo se sabe qué es por el texto de la casilla de
   al lado, que no está asociada a él.
   --------------------------------------------------------------------------- */
.al-field__sublabel {
    display: block;
    margin-block: var(--al-space-2) var(--al-space-1);
    font-size: var(--al-text-sm);
    font-weight: 500;
    color: var(--al-text-muted);
}

/* ---------------------------------------------------------------------------
   Hueco de un campo que NO existe en esta superficie.
   Decir por qué falta un campo cuesta una línea y evita la pregunta "¿se me
   ha roto la pantalla?". El original simplemente no lo pinta.
   --------------------------------------------------------------------------- */
.al-field__standin {
    display: block;
    padding: var(--al-space-3);
    border: 1px dashed var(--al-border);
    border-radius: var(--al-radius-control);
    font-size: var(--al-text-sm);
    color: var(--al-text-muted);
    max-inline-size: 72ch;
}

/* ---------------------------------------------------------------------------
   Identidad del registro DENTRO de su formulario.

   En el original, el documento, su situación y su versión se leen dentro de
   la edición. El prototipo los dejaba solo en la barra de la lista, detrás
   del modal: al editar se perdía de vista qué se estaba tocando, y aquí cada
   guardado crea una versión nueva.

   Es contexto de lectura, no un campo: por eso no lleva borde de input ni
   compite con la rejilla de campos.
   --------------------------------------------------------------------------- */
.al-idhead {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-start;
    gap: var(--al-space-5);
    padding: var(--al-space-3) var(--al-space-4);
    background: var(--al-surface);
    border: 1px solid var(--al-border);
    border-radius: var(--al-radius-surface);
}

.al-idhead__main,
.al-idhead__item {
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-inline-size: 0;
}

.al-idhead__main { flex: 1 1 14rem; }

.al-idhead__eyebrow {
    font-size: var(--al-text-xs);
    color: var(--al-text-subtle);
}

.al-idhead b {
    font-size: var(--al-text-base);
    font-weight: 600;
    color: var(--al-text);
}

/* ===========================================================================
   Superficie sensible de los editores: el input ocupa el control entero

   Síntoma medido el 2026-09-20 en /decas (Tipo, Situación, Desde, Hasta y
   el selector de Filas por página): el primer clic no abría el desplegable,
   solo dibujaba el anillo de foco. Al segundo clic —con el ratón movido unos
   píxeles— sí abría.

   No era un problema de eventos ni de una capa que se tragara el
   pointerdown. Era geometría. DevExpress abre la lista cuando el puntero cae
   sobre el <input> (`drop-down-trigger-mode="Input"` con el input readonly);
   sobre el envoltorio <dxbl-combo-box> solo enfoca. Y el input era mucho más
   pequeño que el control que se ve:

     - El relleno vertical del input lo apaga `padding: 0 !important` (§8 de
       alier-devexpress.css, para que el campo no crezca a 55px). Sin él, el
       input se queda en su altura de línea —21px— y el envoltorio es flex
       con `align-items: center`: 7,5px muertos arriba y 7,5px abajo.
     - El relleno horizontal está en el ENVOLTORIO, así que los 12px de cada
       lado tampoco son superficie del input.

   Medición en /decas, filtro Tipo: control de 320x36 = 11.520px². Sensible
   solo el input (266x21) más el botón del chevron (30x36) = 6.666px², el 58%.
   El 42% restante —una franja de 7,5px arriba y abajo, y 12px a cada lado—
   enfocaba y nada más. Sondeo de 171 puntos sobre el control: 66,7% vivos en
   Desde/Hasta, 70,2% en Tipo/Situación, 76,6% en Filas por página, donde el
   input llegaba a medir 15px de alto. Después: 100% en los cinco.

   Como el fallo es de área y no de comportamiento, se arregla con área, no
   interceptando clics ni tocando parámetros de DevExpress.
   Detalle: knowledge/wiki/frontend/area-clicable-de-los-desplegables.md
   =========================================================================== */

/* 1 — El input llena el alto del control.
   Va sin acotar a `.al-field` a propósito: el recorte lo provoca una regla
   global nuestra, así que la reparación también tiene que serlo. Alcanza al
   paginador del grid y a la fila de filtros, donde el input medía 15px de
   alto dentro de un control de 36. No sustituye nada que pinte DevExpress:
   devuelve el área que nuestro propio override le había quitado. */
:where(.tms-ui) .dxbl-text-edit > input.dxbl-text-edit-input {
    align-self: stretch;
}

/* 2 — El relleno horizontal es del input, no del envoltorio.
   Movido al input, el texto arranca exactamente donde arrancaba (13px del
   borde), el clic en la franja lateral ya cae dentro del input, y el botón
   del chevron queda pegado al extremo derecho en lugar de a 13px de él.

   El `:has(> input...)` no es adorno: acota la regla a los editores de una
   sola línea. El envoltorio del DxMemo también lleva la clase
   `dxbl-text-edit` —su clase propia es `dxbl-memo-edit`, no `dxbl-memo`—,
   así que un `:not(.dxbl-memo)` no lo habría dejado fuera y le habría
   movido el texto.

   Esa exclusión NO basta. `.dxbl-text-edit` a secas (alto 36px, flex
   centrado) también casa con el memo y es lo que rompe Observaciones:
   doble recuadro y resize que se superpone. Receta en §8 de
   alier-devexpress.css.

   Nota para quien venga detrás: `dxbl-combo-box` y `dxbl-date-edit` son
   NOMBRES DE ETIQUETA, no clases. Los selectores `.dxbl-combo-box` que hay
   repartidos por la hoja no casan con nada; el que sostiene el cromo de
   todos estos editores es `.dxbl-text-edit`. */
.al-field .dxbl-text-edit:has(> input.dxbl-text-edit-input),
.al-filters .dxbl-text-edit:has(> input.dxbl-text-edit-input) {
    padding-inline: 0;
}

/* El `!important` es deliberado y mínimo: gana al `padding: 0 !important` de
   §8 de alier-devexpress.css, que existe para matar el relleno VERTICAL de
   fábrica y de paso se lleva por delante el horizontal. Solo se reponen los
   lados; el eje vertical sigue a cero, que es lo que sostiene los 36px. */
.al-field .dxbl-text-edit > input.dxbl-text-edit-input,
.al-filters .dxbl-text-edit > input.dxbl-text-edit-input {
    padding-inline: var(--al-space-3) !important;
}

/* El buscador de barra lleva el icono Lucide encima del hueco izquierdo: ahí
   el relleno grande se conserva, pero pasa al input por el mismo motivo. */
.al-searchwrap .dxbl-text-edit:has(> input.dxbl-text-edit-input) {
    padding-inline: 0;
}
.al-searchwrap .dxbl-text-edit > input.dxbl-text-edit-input {
    padding-inline: 2.25rem var(--al-space-3) !important;
}

/* Un formulario de página (no de diálogo) no se estira a 24 pulgadas. */
.al-form.al-form--page {
    max-inline-size: 60rem;
    padding-block-end: var(--al-space-6);
}

/* Maestro en drawer: el panel es estrecho. Cada campo a ancho completo,
   si no una columna de 3/12 no cabe (misma regla que < 640 px). */
.al-form--drawer .al-grid12 > [class*="al-col-"] {
    grid-column: 1 / -1;
}

/* ---------------------------------------------------------------------------
   Tarjetas de envío del DeCA (Shipment 1…N). Cada una es un trayecto; la
   numeración no es un orden de ejecución. Sin colores literales.
   --------------------------------------------------------------------------- */
.al-shipments {
    display: flex;
    flex-direction: column;
    gap: var(--al-space-4);
    margin-block-end: var(--al-space-5);
}

.al-shipments__share {
    margin-block: 0 var(--al-space-3);
    max-inline-size: 72ch;
}

.al-shipment {
    border: 1px solid var(--al-border);
    border-radius: var(--al-radius-surface);
    background: var(--al-surface);
    overflow: hidden;
}

.al-shipment__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--al-space-3);
    padding: var(--al-space-3) var(--al-space-4);
    background: var(--al-surface-sunken);
    border-block-end: 1px solid var(--al-border);
}

.al-shipment__title {
    margin: 0;
    font-size: var(--al-text-base);
    font-weight: 600;
    color: var(--al-text);
}

.al-shipment__body {
    padding: var(--al-space-4);
}

.al-shipment__foot {
    padding: 0 var(--al-space-4) var(--al-space-4);
}
