/* Estilos propios de la app, sobre el design system de Pensura.
 *
 * Regla de este archivo: acá va lo que es de ESTA app y no del sistema. Tablas, formularios,
 * botones, chips, vacíos, paginador, buscador y encabezado de página los pone
 * pensura-componentes.css; si algo de eso aparece redefinido acá, está mal.
 *
 * Todo color, medida y tipografía sale de un token (`var(--…)`). No hay literales de color:
 * los que había eran de la etapa Pico, con una paleta violeta que no es la de la marca.
 *
 * El shell —barra, navegación, selector de empresa, cuenta y composer— ya NO está acá: es
 * `.shell` del design system. Lo que queda son las piezas de pantalla de esta app y la
 * pantalla de ingreso, que tiene una composición propia.
 */

body {
	background: var(--color-fondo-alt);
	color: var(--color-texto-primario);
	font-family: var(--font-marca);
	font-size: var(--texto-md);
	line-height: var(--interlinea-cuerpo);
}

/* =====================================================================
   MARCA
   El logotipo fuera del shell (la pantalla de ingreso). Dentro del shell lo
   resuelve `.shell__logo`, que es del design system.
   ===================================================================== */

.marca-logo--claro {
	display: var(--web-en-claro);
}

.marca-logo--oscuro {
	display: var(--web-en-oscuro);
}

/* =====================================================================
   PIEZAS DE PANTALLA
   ===================================================================== */

/* Separación entre tarjetas del contenido. `.pieza` y `.metricas` son del sistema: acá solo se les
   da el ritmo vertical de esta app, que los componentes no fijan a propósito. Va sobre
   `.shell__contenido`, que es el <main> del shell: colgada de `.contenido` —el <main> de antes del
   rediseño— la regla no matcheaba nada y las tarjetas quedaban pegadas una a la otra. */
.shell__contenido .pieza,
.shell__contenido .metricas {
	margin-bottom: var(--esp-3);
}

/* Un segundo listado suelto en la misma pantalla, con su título afuera de la tabla (ej. invitaciones
   debajo de miembros). Sin tarjeta que lo separe, el aire de arriba es lo que dice que empieza otra
   cosa y no que el título le pertenece al paginador del listado anterior. */
.seccion-listado {
	margin-block-start: var(--esp-8);
}

.seccion-listado > .nota {
	margin-block-end: var(--esp-3);
}

.contenido .pieza > h2 {
	margin: 0 0 var(--esp-4);
	font-size: var(--texto-lg);
	font-weight: var(--peso-semibold);
}

.contenido .pieza > h3 {
	font-size: var(--texto-md);
	font-weight: var(--peso-semibold);
}

/* Encabezado de sección dentro de una pieza: el h2 y su acción en la misma línea. */
.encabezado-seccion {
	display: flex;
	align-items: center;
	justify-content: space-between;
	flex-wrap: wrap;
	gap: var(--esp-4);
	margin-bottom: var(--esp-4);
}

.encabezado-seccion > h2,
.encabezado-seccion > p {
	margin: 0;
}

/* Ícono de editar al lado del título de una pantalla de detalle. */
.editar-titulo {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	color: var(--color-texto-suave);
	text-decoration: none;
	transition: color var(--transicion);
}

.editar-titulo:hover {
	color: var(--color-texto-primario);
}

.editar-titulo svg {
	width: var(--esp-4);
	height: var(--esp-4);
}

.titulo-enlace {
	color: inherit;
	text-decoration: none;
}

.titulo-enlace:hover {
	text-decoration: underline;
}

/* El saldo al lado del título de una cuenta corriente: es un dato, no una acción. */
.saldo-actual {
	margin: 0;
	font-family: var(--font-marca);
	font-variant-numeric: tabular-nums lining-nums;
	font-size: var(--texto-xl);
	font-weight: var(--peso-medium);
}

/* Badge de estado genérico (corrida, lista de precios, credencial, membresía).
   TODO: es el ítem 9 de la onda 3 de PEDIDOS.md. Cuando el sistema entregue `.badge` —que
   tiene que distinguirse a la vista de `.chip-estado`, que es del dominio de la factura—,
   esto se borra. Hasta entonces se compone con los tokens de estado, sin literales. */
.badge {
	display: inline-flex;
	align-items: center;
	gap: var(--esp-2);
	padding: var(--esp-1) var(--esp-3);
	border-radius: var(--radio-full);
	font-size: var(--texto-xs);
	font-weight: var(--peso-medium);
	white-space: nowrap;
}

.badge-punto {
	width: var(--esp-2);
	height: var(--esp-2);
	border-radius: var(--radio-full);
	background: currentColor;
}

.badge-ok {
	background: var(--estado-pagada-fondo);
	color: var(--estado-pagada-texto);
}

.badge-pendiente {
	background: var(--estado-porvencer-fondo);
	color: var(--estado-porvencer-texto);
}

.badge-error {
	background: var(--estado-vencida-fondo);
	color: var(--estado-vencida-texto);
}

.badge-neutro {
	background: var(--estado-borrador-fondo);
	color: var(--estado-borrador-texto);
}

/* Moneda y monto en la misma celda numérica (cuentas corrientes del cliente).
   La directiva `formatearDinero` no imprime la moneda a propósito: la pone el contexto. Cuando
   ese contexto es la propia fila —cada cuenta corriente tiene su moneda— el código va al lado
   del número, con el tratamiento de rótulo que el sistema ya usa en `.kicker` (mono, versalita,
   texto suave) para que rotule sin competir con el importe.
   Si el patrón se repite en otras superficies, se pide al design system. */
.monto-con-moneda {
	display: inline-flex;
	align-items: baseline;
	gap: var(--esp-2);
}

.monto-con-moneda__moneda {
	font-family: var(--font-dato);
	font-size: var(--texto-xs);
	letter-spacing: var(--tracking-kicker);
	color: var(--color-texto-suave);
}

/* Acciones de fila como ícono (ver, editar, PDF, anular).
   El sistema no tiene botón de solo ícono: la ficha de la tabla muestra la columna de acciones
   con botones de texto («Ver»). Acá la app usa íconos porque hay hasta tres acciones por fila y
   los textos no entran, así que el `.boton--sm` se compone con un ícono adentro y el ancho se
   iguala al alto para que la columna quede pareja. Es composición de esta app, no un componente
   nuevo: si el patrón se repite en otras superficies, se pide al design system.
   Calificado con `.boton--sm` (no `.boton` a secas): un par de filas usan un botón de texto
   común («Revocar», en perfil.ftlh y credenciales-api-fragments.ftlh) en la misma columna, y con
   el selector genérico ese texto quedaba recortado dentro del cuadrado angosto pensado para
   íconos. Eso mismo le pasaba al botón de «Responder» de una invitación, y por eso la decisión de
   una invitación pasó a ser dos íconos.
   `.form-linea` entra en la misma regla porque la misma pieza aparece fuera de la tabla
   (la tarjeta de la pantalla de inicio) y los dos íconos tienen que medir lo mismo en los dos
   lugares. */
.tabla__acciones .boton--sm,
.form-linea .boton--sm {
	width: var(--control-sm);
	padding-inline: 0;
}

/* Con el dedo `.boton--sm` pasa a 44px de alto (lo hace el sistema): el cuadrado de íconos lo
   sigue, si no el botón queda de 32 de ancho por 44 de alto. */
@media (pointer: coarse) {
	.tabla__acciones .boton--sm,
	.form-linea .boton--sm {
		width: var(--control-tactil);
	}
}

.tabla__acciones .boton--sm svg,
.form-linea .boton--sm svg {
	width: var(--esp-4);
	height: var(--esp-4);
}

/* Concepto de un movimiento de cuenta corriente dibujado como ícono (extracto y detalle).
   No es un componente nuevo: es el ícono de dominio que la ficha de la tabla del sistema ya
   prevé para una celda, con el tamaño puesto acá porque el SVG viene sin dimensiones. El color
   es el del texto suave: el concepto acompaña al renglón, no compite con el importe.
   Si el patrón se repite en otras superficies, se pide al design system. */
.concepto {
	display: inline-flex;
	align-items: center;
	color: var(--color-texto-suave);
}

.concepto svg {
	width: var(--esp-6);
	height: var(--esp-6);
}

/* El ícono con su texto al lado: en el detalle es la palabra del concepto; en el extracto, la
   descripción del renglón, que comparte celda con el ícono. */
.movimiento-concepto {
	display: inline-flex;
	align-items: center;
	gap: var(--esp-2);
}

/* Pie de tabla: la fila que cierra una columna de importes con su total.
   `.tabla` estila `thead th` y `tbody td` y no toca el `tfoot`, así que sin esto la fila sale
   sin alto ni padding —apretada contra la última y corrida de sus propias columnas—. Acá no se
   inventa nada: toma la medida de la celda de los mismos tokens que el cuerpo y suma lo único
   propio del pie, el filete que lo separa y el peso que lo distingue de una fila más.
   La alineación numérica no se toca: `.tabla .tabla__num` (0,2,0) le gana a este selector
   (0,1,2), que es lo que se busca.

   No lleva variantes por densidad a propósito: hoy `.tabla--compacta` y `.tabla--comoda` no
   tienen efecto —sus reglas empatan en especificidad con las bases `.tabla thead th` /
   `.tabla tbody td`, que vienen después en el archivo y ganan—, así que toda celda mide
   `--tabla-fila`/`--tabla-pad` y el pie tiene que medir eso mismo para calzar. Escribir acá las
   densidades desalinearía el pie del cuerpo, que es justo lo que se vino a arreglar.
   TODO: es el ítem 16 de la onda 3 de PEDIDOS.md (`.tabla tfoot`), que también reporta lo de las
   densidades. Cuando el sistema entregue las dos cosas, esto se borra. */
.tabla tfoot th,
.tabla tfoot td {
	height: var(--tabla-fila);
	padding-inline: var(--tabla-pad);
	border-top: var(--borde-medio) solid var(--color-borde-sutil);
	color: var(--color-texto-primario);
	font-weight: var(--peso-medium);
	text-align: start;
	white-space: nowrap;
}

/* Variante destructiva de la acción de fila.
   TODO: es el ítem 10 de la onda 3 (`.boton--peligro`). */
.accion-icono-peligro:hover {
	border-color: var(--color-error);
	color: var(--color-error);
}

/* Respuesta de "credencial creada" (credenciales-api-fragments.ftlh). `.aviso` es flex y su
   único hijo, sin `min-width: 0`, no puede achicarse por debajo del ancho mínimo del contenido
   —acá, el comando de curl sin cortes—, así que en vez de scrollear el aviso entero empuja el
   ancho de la pantalla. */
.credencial-token {
	min-width: 0;
}

/* El sistema no tiene un bloque de código: es un caso único hoy (un ejemplo de curl dentro del
   aviso de éxito), así que se compone acá. Sin esto el <pre> no tiene fondo propio ni corta
   línea, y el comando se sale del aviso en vez de scrollear adentro.
   TODO: el patrón ya se repite (ver `.bloque-json`), así que está pedido al design system como
   «19. Bloque de código» en design-system/PEDIDOS.md. Cuando llegue, las dos se reemplazan. */
.credencial-comando {
	margin: var(--esp-2) 0 0;
	padding: var(--esp-3);
	overflow-x: auto;
	border-radius: var(--radio-md);
	background: var(--color-fondo);
	font-family: var(--font-dato);
	font-size: var(--texto-sm);
}

/* Snapshots JSON del detalle de una operación auditada. Mismo hueco que `.credencial-comando` —el
   sistema no tiene bloque de código— pero con dos diferencias que hacen que no sea la misma clase:
   son varias líneas (necesitan alto máximo y scroll vertical, o una excepción con veinte frames
   empuja el resto de la pantalla fuera de la vista) y el JSON ya viene indentado, así que la línea
   no se corta: se scrollea.
   TODO: reemplazar cuando el design system entregue «19. Bloque de código» (PEDIDOS.md). */
.bloque-json {
	max-height: 24rem;
	margin: var(--esp-2) 0 0;
	padding: var(--esp-3);
	overflow: auto;
	border-radius: var(--radio-md);
	background: var(--color-fondo);
	font-family: var(--font-dato);
	font-size: var(--texto-sm);
}

/* Código del error en las pantallas 404/405/5xx. */
.codigo-error {
	margin: 0 0 var(--esp-1);
	font-family: var(--font-dato);
	font-size: var(--texto-4xl);
	font-weight: var(--peso-light);
	line-height: 1;
	color: var(--color-texto-suave);
}

/* Separador con texto al medio ("o con tu email"). */
.separador {
	display: flex;
	align-items: center;
	gap: var(--esp-3);
	margin: var(--esp-4) 0;
	color: var(--color-texto-suave);
	font-size: var(--texto-sm);
}

.separador::before,
.separador::after {
	content: "";
	flex: 1;
	border-top: var(--borde-fino) solid var(--color-borde-sutil);
}

/* ---- Inicio de empresa: grilla de gráficos ---- */
.inicio-seccion-titulo {
	margin: var(--esp-8) 0 var(--esp-4);
	font-size: var(--texto-lg);
	font-weight: var(--peso-semibold);
}

.graficos-grid {
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr));
	gap: var(--esp-3);
}

.contenido .pieza.grafico-card {
	display: flex;
	flex-direction: column;
	gap: var(--esp-3);
	margin: 0;
}

.grafico-placeholder {
	display: flex;
	align-items: center;
	justify-content: center;
	min-height: 6.5rem;
	padding: var(--esp-3);
	border: var(--borde-fino) dashed var(--color-borde-sutil);
	border-radius: var(--radio-md);
	background: var(--color-fondo-alt);
	color: var(--color-acento);
}

.grafico-placeholder svg {
	width: 100%;
	height: auto;
	max-height: 5rem;
}

.grafico-nota {
	margin: 0;
	font-family: var(--font-dato);
	font-size: var(--texto-xs);
	letter-spacing: var(--tracking-kicker);
	text-transform: uppercase;
	color: var(--color-texto-suave);
}

/* ---- Editor de tramos de precio ---- */
.tramos-editor-ayuda,
.agregar-tramo-ayuda {
	font-size: var(--texto-sm);
	font-weight: var(--peso-regular);
	color: var(--color-texto-suave);
}

.metrica-encabezado {
	display: flex;
	align-items: center;
	justify-content: space-between;
	flex-wrap: wrap;
	gap: var(--esp-4);
}

.metrica-encabezado p,
.metrica-encabezado form {
	margin: 0;
}

.agregar-tramo {
	margin-top: var(--esp-6);
	padding-top: var(--esp-4);
	border-top: var(--borde-fino) solid var(--color-borde-sutil);
}

.agregar-tramo-titulo {
	margin: 0 0 var(--esp-3);
	font-family: var(--font-dato);
	font-size: var(--texto-xs);
	letter-spacing: var(--tracking-kicker);
	text-transform: uppercase;
	color: var(--color-texto-suave);
}

/* =====================================================================
   SELECT REMOTO · búsqueda en el server (Tom Select)
   TODO: es el ítem 15 de la onda 3 de design-system/PEDIDOS.md. Hasta que el sistema entregue
   un select remoto propio, esto reescribe la piel default de Tom Select (vendoreado en
   `static/js/lib/tom-select.js`) con los tokens de `.control`/`.campo`, para que no se vea como
   una librería aparte. El panel compone como `.selector__panel`/`.selector__opcion`: mismo
   z-index 30, mismo borde, misma sombra, misma fila — es el mismo problema con otra fuente.
   ===================================================================== */

/* El wrapper solo aporta posicionamiento para el panel; el look de `.control` (fondo, borde,
   min-height, padding) se lo damos a `.ts-control`, que es el que realmente se ve — copiar la
   clase al wrapper y dejar que la cascada de `.control` caiga ahí sería pelear con un <div>
   que no tiene los mismos pseudo-estados (:focus-visible, :disabled) que un control nativo. */
.ts-wrapper.control {
	position: relative;
	width: 100%;
	min-height: 0;
	padding: 0;
	background: none;
	border: 0;
	cursor: text;
}

/* Un select remoto usado como filtro en la fila de filtros (ej. usuario y empresa en la pantalla de
   sesiones). El `width: 100%` de arriba es para el select remoto de formulario, que ocupa su `.campo`;
   en la fila le ganaría a `.control--auto` y pondría cada filtro en un renglón. Acá crece como el
   `.buscador` de la misma fila y con el mismo piso, así el nombre elegido se lee entero. */
.buscador-fila .ts-wrapper.buscador-fila__filtro {
	flex: 1 1 calc(var(--esp-24) * 2.5);
	width: auto;
}

/* La X de un select remoto de filtro (la arma `select-remoto.js` adentro del wrapper): se dibuja sobre el
   borde derecho del control, y el control reserva ese lugar para que un nombre largo no quede
   abajo. Es un botón de ícono chico y sin borde, como la lupa del buscador del otro lado.

   Un filtro vive en una fila con otros y tiene que medir siempre lo mismo: lo elegido va en un
   solo renglón, cortado con «…» (el nombre entero queda en el `title` de la chip). Sin esto, un
   usuario con nombre y email largos partía la chip en tres renglones y mandaba el input abajo.

   Por lo mismo, el padding vertical es más chico que el de `.ts-control`: con `--esp-3` quedaban
   22px para el contenido y la chip mide ~25px, así que elegir algo estiraba el control de 48 a
   51px. El alto lo sigue fijando el `min-height` (`--control-lg`), igual con o sin chip. */
.ts-wrapper.select-remoto--quitable .ts-control {
	flex-wrap: nowrap;
	padding-block: var(--esp-2);
	padding-inline-end: calc(var(--esp-4) + var(--esp-8));
}

.ts-wrapper.select-remoto--quitable .ts-control .item {
	min-width: 0;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

.ts-wrapper.select-remoto--quitable .ts-control input {
	min-width: var(--esp-2);
}

/* Tom Select deja el placeholder en el input aunque ya haya algo elegido (su CSS lo esconde con el
   input entero, y acá el input queda a la vista para poder tipear otra búsqueda): sin esto, al lado
   de «Acme SA» se seguía leyendo «Todas las empresas». */
.ts-wrapper.select-remoto--quitable.has-items .ts-control input::placeholder {
	color: transparent;
}

.select-remoto__quitar {
	position: absolute;
	inset-block: 0;
	inset-inline-end: var(--esp-2);
	display: flex;
	align-items: center;
	justify-content: center;
	width: var(--esp-8);
	height: var(--esp-8);
	margin-block: auto;
	padding: 0;
	color: var(--color-texto-suave);
	background: none;
	border: 0;
	border-radius: var(--radio-sm);
	cursor: pointer;
}

.select-remoto__quitar[hidden] {
	display: none;
}

.select-remoto__quitar:hover {
	color: var(--color-texto-primario);
	background: var(--color-superficie-hover);
}

.select-remoto__quitar svg {
	width: calc(var(--esp-4) + var(--esp-1));
	height: calc(var(--esp-4) + var(--esp-1));
}

/* Una fila de filtros sin buscador (sesiones, la bandeja de obligaciones) va pegada a la tabla:
   `.buscador-fila` no trae separación propia —cuando lleva un `.buscador`, la pone el pie de éste— y
   acá son controles sueltos. Centrados en alto: un select y un campo de fecha no miden lo mismo, y arriba
   de todo quedaban desparejos por abajo. */
.filtros-listado {
	align-items: center;
	margin-bottom: var(--esp-4);
}

/* El filtro de fechas de un listado: el select y, si se eligió el rango, sus dos campos. Se reparte como la
   fila de afuera, así que en una pantalla angosta el rango baja entero debajo del select. */
.filtro-fechas {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: var(--esp-3);
}

/* Un rango de fechas en la fila de filtros: «Desde» y «Hasta» con su rótulo al costado. Si no entran en una
   línea, cada una baja a la suya, rótulo y campo juntos. */
.filtro-rango {
	display: flex;
	flex-wrap: wrap;
	gap: var(--esp-3);
}

.filtro-rango__campo {
	display: flex;
	align-items: center;
	gap: var(--esp-2);
	color: var(--color-texto-primario);
	font-size: var(--texto-md);
	font-weight: var(--peso-medium);
}

/* El resumen de lo que factura en bloque la bandeja de obligaciones, arriba de la tabla: a la izquierda
   cuántas son y cuánto suman, a la derecha el botón. Va con la misma caja que la tabla para leerse como
   parte del listado y no como un aviso.
   TODO: es el ítem 22 de la onda 3 de PEDIDOS.md (barra de acción sobre un listado). */
.resumen-facturar {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: space-between;
	gap: var(--esp-3);
	margin-bottom: var(--esp-4);
	padding: var(--esp-3) var(--esp-4);
	background: var(--color-superficie);
	border: var(--borde-fino) solid var(--color-borde-sutil);
	border-radius: var(--radio-md);
}

.resumen-facturar__texto {
	display: flex;
	flex-direction: column;
	gap: var(--esp-1);
}

/* El desglose por mes, cuando no hay un mes elegido: una `.tabla` suelta, sin `.tabla-caja`, porque la caja del
   resumen ya es su marco. No se estira al ancho: es un desglose chico al lado del botón. */
.resumen-facturar__meses {
	width: auto;
}

/* El aviso que abre el botón sin mes elegido. Es un `popover` de HTML: el navegador lo pone arriba de
   todo y lo cierra al hacer clic afuera, sin JS. */
.resumen-facturar__aviso {
	max-width: 28rem;
	padding: var(--esp-4);
	background: var(--color-superficie);
	color: var(--color-texto-primario);
	border: var(--borde-fino) solid var(--color-borde-sutil);
	border-radius: var(--radio-md);
}

/* Tom Select le agrega esta clase al <select> original al inicializarlo: no lo saca del DOM (el
   valor que viaja en el POST sigue siendo el de este <select>, Tom Select solo lo sincroniza), lo
   oculta visualmente pero lo deja accesible para lectores de pantalla — el CSS lo tiene que
   proveer quien lo vendorea, y es el mismo patrón que ya usa `.solo-lectores` del sistema. Sin
   esto el select nativo queda visible al lado del select remoto armado.
   El mismo <select> también lleva la clase `control` (se la puso @selectRemoto, para que Tom Select
   copie el look al wrapper), y `.control` fija `min-height: 48px` — un `height` más chico no le
   gana a un `min-height` más grande, así que hay que anularlo acá o el select "oculto" sigue
   midiendo 48px de alto. */
.ts-hidden-accessible {
	position: absolute;
	width: var(--borde-fino);
	height: var(--borde-fino);
	min-width: 0;
	min-height: 0;
	overflow: hidden;
	clip-path: inset(50%);
	white-space: nowrap;
	border: 0;
	padding: 0;
}

.ts-wrapper .ts-control {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: var(--esp-1);
	width: 100%;
	min-height: var(--control-lg);
	padding: var(--esp-3) var(--esp-4);
	background: var(--color-superficie);
	border: var(--borde-fino) solid var(--color-borde-control);
	border-radius: var(--radio-md);
	box-sizing: border-box;
	transition: border-color var(--transicion), background-color var(--transicion);
}

/* `line-height` acá, no heredado de `--interlinea-cuerpo` (pensado para párrafos, no para un
   control): un <select> nativo centra su texto ignorando el line-height del autor, pero este es
   un <input> real dentro de un flex `align-items: center`, que sí lo respeta — con 1.55 el
   glyph queda corrido hacia arriba dentro de su propia caja de línea, aunque la caja en sí esté
   centrada. Mismo criterio que `.boton` (otro control flex de una sola línea centrado por
   align-items): `--interlinea-titulo`, no `--interlinea-cuerpo`. */
.ts-wrapper .ts-control input {
	flex: 1;
	min-width: 4rem;
	padding: 0;
	border: 0;
	background: transparent;
	font: inherit;
	font-size: var(--texto-lg);
	line-height: var(--interlinea-titulo);
	color: inherit;
}

/* El elegido, para no confundirse con lo que se está tipeando al lado. Tom Select no le pone
   ningún estilo por su cuenta (ni su propia hoja default lo hace en modo single sin el plugin de
   "remove button"): sin esto el nombre elegido queda como texto suelto pegado al input vacío de
   al lado, los dos indistinguibles de un campo de texto libre — que es justo lo que parece un
   multiselect. El input sigue ahí a propósito: tipear reemplaza la elección, no la suma. */
.ts-wrapper .ts-control .item {
	padding: var(--esp-1) var(--esp-2);
	border-radius: var(--radio-sm);
	background: var(--color-superficie-hover);
	font-size: var(--texto-md);
	line-height: var(--interlinea-titulo);
}

.ts-wrapper .ts-control input::placeholder {
	color: var(--color-texto-suave);
}

.ts-wrapper .ts-control input:focus-visible {
	outline: none;
}

.ts-wrapper:hover .ts-control {
	border-color: var(--color-texto-primario);
}

/* Foco: la librería marca `.focus` en el wrapper cuando el input interno tiene foco. Un
   `:focus-visible` normal dibujaría el anillo alrededor del input chico, no de la caja entera —
   por eso el anillo se pone acá a mano, con el mismo tratamiento que `.control:focus-visible`. */
.ts-wrapper.focus .ts-control {
	border-color: var(--color-foco);
	outline: 2px solid var(--color-foco);
	outline-offset: 2px; /* mismo tratamiento que el anillo global, pensura-tokens.css §9 */
}

.ts-wrapper.disabled .ts-control {
	background: var(--color-superficie-hover);
	border-color: var(--color-borde-sutil);
	color: var(--color-texto-suave);
	cursor: not-allowed;
}

.campo--error .ts-wrapper.control .ts-control {
	border-color: var(--color-error);
	border-width: var(--borde-medio);
}

.ts-wrapper .ts-dropdown {
	position: absolute;
	z-index: 30; /* tope del sistema: mismo nivel que `.selector__panel` y `.menu-cuenta__panel` */
	inset-inline: 0;
	top: calc(100% + var(--esp-1));
	max-height: min(60vh, calc(var(--esp-24) * 3));
	overflow-y: auto;
	overscroll-behavior: contain; /* como .selector__panel: no encadenar el scroll a la página de atrás */
	padding: var(--esp-1);
	background: var(--color-superficie);
	border: var(--borde-fino) solid var(--color-borde-sutil);
	border-radius: var(--radio-md);
	box-shadow: var(--sombra-lg);
}

/* `line-height`, no `display: flex` + `align-items: center`: cuando la búsqueda matchea, Tom
   Select resalta el término envolviéndolo en un <span> en el medio del texto (texto + <span> +
   texto). En un contenedor flex, ESE ES EL PROBLEMA — cada tramo de texto alrededor del <span> se
   vuelve su propia "anonymous flex item", y el espacio que queda justo en el borde de esa caja
   (el final de "...de " antes del <span>) lo colapsa el propio layout de flexbox: "FUNDACION
   SANTA MARIA DE PEHUAJO" con el resaltado en "PEH" quedaba "...MARIA DEPEHUAJO", sin el espacio,
   solo cuando había match — con la lista sin filtrar (un único nodo de texto, sin <span> en el
   medio) no se notaba. Con line-height en vez de flex el texto fluye normal (el <span> del medio
   no parte nada en cajas separadas) y deja cada fila con la altura exacta de `--fila-default`
   sin necesitar centrar nada: min-height (44px) menos el padding vertical (2 × --esp-1) es lo
   que le queda al contenido, así que no sobra espacio para repartir. */
.ts-dropdown .option {
	min-height: var(--fila-default);
	padding: var(--esp-1) var(--esp-2);
	line-height: calc(var(--fila-default) - 2 * var(--esp-1));
	border-radius: var(--radio-sm);
	font-size: var(--texto-md);
	cursor: pointer;
}

.ts-dropdown .option.active {
	background: var(--color-superficie-hover);
}

/* Tom Select arma el `<span class="highlight">` alrededor del término tipeado, pero no le pone
   ningún estilo por su cuenta (no viene en su hoja default en modo single): sin esto el span
   existe en el DOM pero se ve idéntico al resto de la opción, y la búsqueda no resalta nada.
   Semibold + --color-link (no --color-acento, que mide ~2:1 contra superficie — se usa como
   fondo/borde/ícono, nunca como texto de lectura): --color-link es el token que el sistema ya
   documenta con contraste real para texto que tiene que destacarse y seguir siendo legible
   (6.53 s/fondo en claro, 8.74 s/superficie en oscuro), y semánticamente encaja: es lo que el
   usuario tipeó, resaltado dentro de una opción interactiva. */
.ts-dropdown .option .highlight {
	font-weight: var(--peso-semibold);
	color: var(--color-link);
}

.ts-dropdown .no-results {
	padding: var(--esp-3) var(--esp-2);
	color: var(--color-texto-suave);
	font-size: var(--texto-sm);
}

/* Fila final que agrega select-remoto.js cuando el server avisa `hayMas`: una opción de Tom
   Select con `disabled: true` (no un <div> propio) — por eso alcanza con `[aria-disabled]`, que
   es lo que la librería le pone en vez de `data-selectable`, y hereda el resto de `.option`
   (padding, tamaño, line-height) sin tener que repetirlo. */
.ts-dropdown .option[aria-disabled] {
	border-top: var(--borde-fino) solid var(--color-borde-sutil);
	color: var(--color-texto-suave);
	cursor: default;
}

/* "Buscando…" mientras espera la respuesta: reusa el giro de `.boton[aria-busy]` (mismo
   @keyframes, del sistema) en vez de copiar el spinner propio de Tom Select. Sin esto es un
   <div class="spinner"></div> vacío, sin tamaño ni animación — invisible. */
.ts-dropdown .spinner {
	width: var(--esp-4);
	height: var(--esp-4);
	margin: var(--esp-3) var(--esp-2);
	border: var(--borde-medio) solid var(--color-texto-suave);
	border-top-color: transparent;
	border-radius: var(--radio-full);
	animation: giro 700ms linear infinite;
}

@media (prefers-reduced-motion: reduce) {
	.ts-dropdown .spinner {
		animation-duration: 2400ms;
	}
}

/* Fila con el ícono "ver ficha" (select-remoto.js: render.option/render.item), en cada resultado
   del dropdown y en el chip ya elegido. Reemplaza el `<div>texto</div>` default de Tom Select por
   nombre + ícono, así que necesita flex acá — pero `.option`/`.item` (arriba) siguen aplicando: Tom
   Select le agrega esa clase al mismo elemento que devuelve el render, no lo envuelve, y por eso
   alcanza con esta clase extra en vez de reescribir el resto de la piel. `align-items: center`
   reemplaza al centrado por `line-height` de `.option` (no hace falta el truco de esa regla: acá
   el resaltado de búsqueda queda anidado dentro del <span> del nombre, no como hijo directo de un
   contenedor flex, así que no reaparece el bug de espacios que ese truco evita). */
.ts-dropdown .option.select-remoto__fila,
.ts-wrapper .ts-control .item.select-remoto__fila {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: var(--esp-2);
}

.ts-dropdown .option.select-remoto__fila > span,
.ts-wrapper .ts-control .item.select-remoto__fila > span {
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

.select-remoto__ficha {
	flex-shrink: 0;
	display: inline-flex;
	color: var(--color-texto-suave);
	border-radius: var(--radio-sm);
}

.select-remoto__ficha svg {
	width: var(--esp-4);
	height: var(--esp-4);
}

.select-remoto__ficha:hover {
	color: var(--color-link);
}

.select-remoto__ficha:focus-visible {
	outline: 2px solid var(--color-foco);
	outline-offset: 2px;
}

/* =====================================================================
   BUSCADOR GLOBAL · la lupita de la barra
   Clientes y usuarios en un mismo Tom Select (`buscador-global.js`). Es un desplegable más de la
   barra: el <summary> es un `.shell__accion` como el engranaje, y el panel compone como
   `.menu-cuenta__panel` —mismo z-index, borde y sombra—, anclado al borde derecho porque la lupita
   vive del lado de la cuenta. Adentro, el control y el dropdown son los del select remoto de arriba.
   TODO: es el ítem 20 de design-system/PEDIDOS.md; cuando el sistema lo entregue, esto se borra.
   ===================================================================== */

.buscador-global {
	position: relative;
}

.buscador-global > summary {
	list-style: none;
}

.buscador-global > summary::-webkit-details-marker {
	display: none;
}

.buscador-global[open] > summary {
	background: var(--color-superficie-hover);
	color: var(--color-texto-primario);
}

/* El mismo velo que cierra `.selector` y `.menu-cuenta` con un click afuera (ver el comentario de
   `.menu-cuenta[open] > summary::before` en el sistema): por debajo del panel, así los clicks de
   adentro llegan a donde tienen que llegar. */
.buscador-global[open] > summary::before {
	content: "";
	position: fixed;
	z-index: 10;
	inset: 0;
	cursor: default;
}

.buscador-global__panel {
	position: absolute;
	z-index: 30;
	top: calc(100% + var(--esp-1));
	inset-inline-end: 0;
	width: min(calc(var(--esp-24) * 4), calc(100vw - 2 * var(--esp-4)));
	padding: var(--esp-2);
	background: var(--color-superficie);
	border: var(--borde-fino) solid var(--color-borde-sutil);
	border-radius: var(--radio-md);
	box-shadow: var(--sombra-lg);
}

/* En angosto la lupita ya no está contra el borde derecho (la barra se reduce y quedan el
   engranaje y el avatar a su lado), así que anclado a ella el panel se salía por la izquierda. Ahí
   se ancla a la barra entera —`.shell__barra` es sticky, que posiciona—, con el margen de la página
   a los dos lados. Mismo breakpoint que la barra del sistema. */
@media (max-width: 48em) {
	.buscador-global {
		position: static;
	}

	.buscador-global__panel {
		inset-inline: var(--esp-4);
		width: auto;
	}
}

/* El rótulo de cada grupo: chico y apagado, que se lea como título de la lista y no como opción. */
.ts-dropdown .optgroup-header {
	padding: var(--esp-2) var(--esp-2) var(--esp-1);
	color: var(--color-texto-suave);
	font-size: var(--texto-xs);
	font-weight: var(--peso-semibold);
	text-transform: uppercase;
}

.ts-dropdown .optgroup + .optgroup {
	margin-top: var(--esp-1);
	border-top: var(--borde-fino) solid var(--color-borde-sutil);
}

/* =====================================================================
   AUTENTICACIÓN · panel de marca + formulario
   ===================================================================== */

.auth {
	min-height: 100vh;
	padding: 0;
	background: var(--color-fondo);
}

.auth-split {
	display: grid;
	grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
	min-height: 100vh;
}

/* El panel de marca va con el azul de la marca en los dos temas: es la única superficie de
   la app donde el color de marca se usa como fondo pleno. */
/* El panel se pinta con dos alias locales y no con colores sueltos, igual que la franja de
   marca del sitio (`--web-franja-*` en web/sitio/estilos.css): así el par fondo/texto cambia
   junto y no hay forma de mover uno y olvidarse del otro.
   En claro es el azul de la acción, que es el azul de marca. En oscuro NO sigue siendo azul:
   un azul saturado a pantalla completa sobre un tema oscuro pelea con todo, así que pasa a la
   superficie alternativa del tema. Queda oscuro en los dos casos, que es lo que el logotipo
   negativo necesita. */
.auth-marca {
	--auth-marca-fondo: var(--color-accion);
	--auth-marca-texto: var(--color-accion-texto);

	display: flex;
	flex-direction: column;
	justify-content: space-between;
	gap: var(--esp-8);
	padding: var(--esp-12);
	background: var(--auth-marca-fondo);
	color: var(--auth-marca-texto);
}

[data-theme="oscuro"] .auth-marca {
	--auth-marca-fondo: var(--color-fondo-alt);
	--auth-marca-texto: var(--color-texto-primario);
}

@media (prefers-color-scheme: dark) {
	:root:not([data-theme="claro"]) .auth-marca {
		--auth-marca-fondo: var(--color-fondo-alt);
		--auth-marca-texto: var(--color-texto-primario);
	}
}

.auth-marca-logo {
	display: inline-flex;
	align-items: center;
}

.auth-marca-logo .marca-logo {
	height: var(--esp-8);
	width: auto;
}

.auth-marca-titulo {
	margin: 0 0 var(--esp-3);
	font-size: var(--texto-3xl);
	font-weight: var(--peso-medium);
	line-height: var(--interlinea-titulo);
}

/* Secundario sobre el panel: el mismo texto con menos presencia, no un color aparte. Es lo
   que hace la franja del sitio con `--web-franja-p-opacidad`, y evita tener que verificar el
   contraste de un segundo color contra dos fondos distintos. */
.auth-marca-sub,
.auth-marca-pie {
	margin: 0;
	color: var(--auth-marca-texto);
	opacity: 0.85;
	font-size: var(--texto-md);
}

.auth-marca-pie {
	font-family: var(--font-dato);
	font-size: var(--texto-xs);
	letter-spacing: var(--tracking-kicker);
	text-transform: uppercase;
}

.auth-form {
	display: flex;
	align-items: center;
	justify-content: center;
	padding: var(--esp-12);
}

.auth-form-caja {
	width: 100%;
	max-width: 22rem;
}

.auth-form .encabezado {
	padding-block-end: var(--esp-6);
}

/* Los dos botones de la pantalla de auth son `.boton` del sistema; acá solo ocupan el ancho
   de la caja, que es de esta pantalla y no del componente. */
.auth-passkey,
.auth-secundario {
	width: 100%;
}

.auth-passkey svg {
	width: var(--esp-4);
	height: var(--esp-4);
}

.auth-acciones {
	display: flex;
	flex-direction: column;
	gap: var(--esp-3);
}

.auth-acciones form {
	margin: 0;
}

/* Las acciones apiladas miden todas el ancho de la caja, sean un link o un botón dentro de un form:
   el link es hijo directo del flex y se estira solo, pero el botón de un form no. */
.auth-acciones .boton {
	width: 100%;
}

.auth-legal {
	margin-top: var(--esp-6);
	font-size: var(--texto-xs);
	color: var(--color-texto-suave);
}

/* El aviso del sistema trae `margin-top` pero no `margin-bottom`, y lo que le sigue tampoco pone
   separación arriba: la `.pieza` sólo la pone abajo y el botón de ingresar no la pone. Sin esto el
   aviso queda pegado a lo de abajo y se leen como una sola pieza, en todas las pantallas. El último
   hijo queda afuera: ahí la separación la pone el padding de quien lo contiene.
   TODO: es el ítem 13 de la onda 3 de PEDIDOS.md. Cuando el sistema defina la separación del aviso
   respecto de lo que le sigue, esto se borra. */
.aviso:not(:last-child) {
	margin-bottom: var(--esp-4);
}

.auth [data-passkey-resultado]:empty,
.auth [data-registro-error]:empty {
	display: none;
}

@media (max-width: 640px) {
	.auth-split {
		grid-template-columns: 1fr;
	}

	.auth-marca {
		flex-direction: row;
		align-items: center;
		gap: var(--esp-3);
		padding: var(--esp-4) var(--esp-6);
	}

	.auth-marca-mensaje,
	.auth-marca-pie {
		display: none;
	}

	.auth-form {
		padding: var(--esp-8) var(--esp-6);
	}
}

/* =====================================================================
   AUTORIZACIÓN DE DISPOSITIVOS · QR + código de un solo uso
   TODO: pedido 14 de design-system/PEDIDOS.md (`.codigo-un-uso` y el marco del QR). Cuando
   el sistema los entregue, este bloque se borra y las pantallas usan el componente.
   ===================================================================== */

.qr-desafio {
	max-width: 16rem;
	margin: var(--esp-4) auto;
}

.qr-desafio svg {
	width: 100%;
	height: auto;
	/* El QR se lee por contraste: fondo claro fijo, para que el tema oscuro no lo invierta. */
	background: #fff;
	padding: var(--esp-2);
	border-radius: var(--radio-md);
}

/* El código se tipea a mano en el otro dispositivo: grande, monoespaciado y con tracking
   generoso para no confundir dígitos al leerlo de una pantalla a otra. */
.codigo-verificacion {
	font-family: var(--font-dato);
	font-size: clamp(var(--texto-3xl), 12vw, var(--texto-4xl));
	letter-spacing: 0.25em;
	text-align: center;
	margin: var(--esp-6) 0;
	font-variant-numeric: tabular-nums;
}

/* Celda con links propios adentro de una fila que es link entero (`.tabla__fila--link`). El
   componente estira el `<a>` de la fila sobre toda la fila con ::after, así que cualquier otro link
   queda debajo y no se puede tocar; el sistema levanta `.tabla__acciones` de la misma forma, pero
   sólo esa. Pasa en los cobros del recaudado, donde la columna «Imputado a» lleva un link por
   comprobante y la del cliente, uno a su ficha.
   TODO: es el ítem 1 de PEDIDOS.md (`.tabla`), que ya cubre la fila-link. Cuando el sistema
   generalice el escape para cualquier celda con links, esto se borra. */
.tabla .tabla__celda-links {
	position: relative;
	z-index: 1;
}

/* Filtro de selección múltiple: un grupo de checkboxes que convive en la fila de filtros con los
   campos `.campo`. Es el primer checkbox de la app y el sistema todavía no tiene ninguno, así que
   acá van sólo la disposición y el rótulo; la caja la sigue dibujando el navegador.
   El `fieldset` queda en flujo normal a propósito: el navegador renderiza el `legend` fuera de su
   caja, y con `display: grid` o `flex` encima eso se comporta distinto según el motor. Quien
   acomoda las opciones es `__opciones`, que además le da al grupo el mismo alto que un `.control`
   para que apoye en la misma línea de base que los campos de fecha de al lado.
   TODO: es el ítem 17 de la onda 3 de PEDIDOS.md (`.opciones`). Cuando el sistema entregue el grupo
   de checkboxes —con su caja propia, sus estados y su foco—, esto se borra. */
.filtro-agrupar {
	border: 0;
	padding: 0;
	margin: 0;
}

.filtro-agrupar__opciones {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: var(--esp-2) var(--esp-4);
	min-height: var(--control-lg);
	margin-block-start: var(--esp-2);
}

.filtro-agrupar__opcion {
	display: flex;
	align-items: center;
	gap: var(--esp-2);
	color: var(--color-texto-primario);
	font-size: var(--texto-lg);
	cursor: pointer;
}

.filtro-agrupar__opcion input {
	/* Lo único que le pone marca a la caja del navegador. Es el mismo color que el botón primario:
	   tildado es una acción afirmativa, igual que él. */
	accent-color: var(--color-accion);
	width: var(--esp-4);
	height: var(--esp-4);
	cursor: pointer;
}

/* Checklist de permisos de un perfil de empresa (plataforma). Es el mismo grupo de checkboxes que
   `.filtro-agrupar` pero en la escala que rompe: el catálogo son ~66 permisos, y en una sola columna
   de casillas sueltas —sin separador, con el rótulo debajo de su caja porque `.campo` es un grid—
   hay que ir con el mouse para saber qué casilla es cuál.

   La forma es una matriz: una fila por recurso, con su nombre a la izquierda y sus acciones al lado.
   Lo que resuelve la lectura son tres cosas, en este orden: el rótulo pegado a su caja (la casilla y
   su palabra son un solo `inline-flex` que además es el objetivo táctil), la divisoria entre filas,
   y el fondo del tildado, que deja ver de un vistazo qué otorga el perfil sin recorrer casilla por
   casilla.
   TODO: es el ítem 17 de la onda 3 de PEDIDOS.md (`.opciones`), ampliado con el caso matriz. Cuando
   el sistema entregue el grupo de checkboxes con su caja, sus estados y su agrupación, esto se
   borra. */
.permisos {
	/* Igual que `.filtro-agrupar`: el `fieldset` queda en flujo normal porque el `legend` se
	   renderiza fuera de su caja y con grid/flex encima eso cambia según el motor. */
	border: 0;
	padding: 0;
	margin: 0;
}

.permisos legend {
	padding: 0;
	font-size: var(--texto-md);
	font-weight: var(--peso-medium);
	color: var(--color-texto-primario);
}

.permisos__grupos {
	list-style: none;
	margin: var(--esp-2) 0 0;
	padding: 0;
	background: var(--color-superficie);
	border: var(--borde-fino) solid var(--color-borde-sutil);
	border-radius: var(--radio-md);
}

.permisos__grupo {
	display: grid;
	grid-template-columns: minmax(10rem, 15rem) 1fr;
	align-items: baseline;
	gap: var(--esp-1) var(--esp-4);
	padding: var(--esp-2) var(--esp-4);
}

/* La divisoria va entre filas y no en cada una: un borde por fila dibuja también el de arriba de
   todo y el de abajo de todo, encima del borde de la caja. */
.permisos__grupo + .permisos__grupo {
	border-block-start: var(--borde-fino) solid var(--color-borde-sutil);
}

.permisos__recurso {
	font-weight: var(--peso-medium);
	color: var(--color-texto-primario);
}

.permisos__acciones {
	display: flex;
	flex-wrap: wrap;
	gap: var(--esp-1) var(--esp-2);
}

.permisos__accion {
	display: inline-flex;
	align-items: center;
	gap: var(--esp-2);
	padding: var(--esp-1) var(--esp-2);
	border-radius: var(--radio-sm);
	color: var(--color-texto-primario);
	font-size: var(--texto-md);
	cursor: pointer;
}

.permisos__accion:hover {
	background: var(--color-superficie-hover);
}

/* El tildado se lee también sin mirar la caja: el fondo marca la acción otorgada, que es lo que se
   busca cuando se revisa un perfil ya guardado. No es el único canal —la caja sigue tildada—, así
   que un tema o un modo de alto contraste que aplane el fondo no pierde información. */
.permisos__accion:has(input:checked) {
	background: var(--color-superficie-hover);
	font-weight: var(--peso-medium);
}

.permisos__accion input {
	/* Misma caja que el filtro de agrupar: el navegador la dibuja y el accent le pone la marca. */
	accent-color: var(--color-accion);
	width: var(--esp-4);
	height: var(--esp-4);
	cursor: pointer;
}

/* Otra celda del título de una fila que es link entero (`.tabla__fila--link`). El sistema asume que
   ese título entra en una sola celda y sólo subraya `.tabla__link`; cuando el título se reparte en
   varias columnas —el recaudado agrupado por medio de cobro Y sociedad—, las demás quedan sin
   subrayar y se leen como dato inerte, o sea como si la fila fuera clickeable a medias.

   Es sólo el subrayado del hover: ni posición ni z-index. El área de clic ya la estira el ::after de
   `.tabla__link` sobre la fila entera, y levantar estas celdas encima se lo robaría.
   TODO: es el ítem 18 de la onda 3 de PEDIDOS.md. Cuando el sistema cubra el título repartido en
   varias columnas, esto se borra. */
.tabla__fila--link:hover .tabla__link-secundario {
	text-decoration: underline;
	text-decoration-color: var(--color-link);
	text-underline-offset: var(--esp-1);
}

/* Varios campos que son una sola cosa —la ubicación de una orden de trabajo: el select y, si es nueva,
   nombre, dirección, ciudad y coordenadas— van en un `fieldset` rotulado, para que se lean juntos y
   no como datos sueltos del formulario. Una caja fina con el `legend` sobre el borde, que es el dibujo
   del `fieldset` del navegador llevado a los tokens.
   El `fieldset` queda en flujo normal, como `.filtro-agrupar` y `.permisos`: el navegador renderiza el
   `legend` fuera de su caja y con grid o flex encima eso cambia según el motor. El espaciado de los
   campos lo pone un `.form` de adentro.
   TODO: es el ítem 21 de PEDIDOS.md (`.grupo-campos`). Cuando el sistema lo entregue, esto se borra. */
.grupo-campos {
	margin: 0;
	padding: var(--esp-4) var(--esp-6) var(--esp-6);
	border: var(--borde-fino) solid var(--color-borde-sutil);
	border-radius: var(--radio-md);
}

.grupo-campos legend {
	padding: 0 var(--esp-2);
	font-size: var(--texto-md);
	font-weight: var(--peso-medium);
	color: var(--color-texto-primario);
}

/* Aviso de pendientes en el menú de cuenta: el número sobre el avatar y el número en el ítem
   de adentro. Es lo que trae a alguien al perfil cuando le llegó una invitación — sin esto, la
   invitación sólo se ve si se la va a buscar.
   TODO: es el ítem 24 de PEDIDOS.md. El sistema ya entrega la misma idea para un destino de la
   navegación (`.shell__tab-badge`); esto es su par para el menú, y se borra cuando llegue.
   El número y no un punto por lo mismo que en el tab: un punto diría «algo pasó», no cuánto. */
.menu-cuenta__aviso {
	position: absolute;
	top: calc(var(--esp-1) * -1);
	inset-inline-end: calc(var(--esp-1) * -1);
	/* El avatar es el control que abre el menú: el aviso no le puede robar el click. */
	pointer-events: none;
}

.menu-cuenta__aviso,
.menu-cuenta__item-aviso {
	display: grid;
	place-items: center;
	min-width: var(--esp-4);
	height: var(--esp-4);
	padding: 0 var(--esp-1);
	border-radius: var(--radio-full);
	/* `pendiente` y no error: una invitación esperando no es algo que se rompió. */
	background: var(--estado-porvencer-texto);
	color: var(--color-texto-invertido);
	font-size: var(--texto-2xs);
	font-weight: var(--peso-medium);
	line-height: 1;
}

/* El lugar donde el fragmento deja el aviso no es una caja: el avatar es un grid centrado y el ítem un
   flex con gap, y una caja de más correría las iniciales o sumaría un hueco. Los avisos de adentro se
   ubican como si el lugar no estuviera. */
.menu-cuenta__lugar-aviso {
	display: contents;
}

/* En el ítem el número va al final de la fila: el ítem ya es un flex con gap. */
.menu-cuenta__item-aviso {
	margin-inline-start: auto;
}

/* =====================================================================
   RESPONSIVE
   El shell resuelve lo suyo (la navegación baja a la barra de tabs): eso vive en el design
   system. Acá queda solo lo que es de las pantallas de esta app.
   ===================================================================== */

@media (max-width: 48em) {
	/* Columna secundaria que se cae en angosto para achicar la fila. Se pone en el `th` y en
	   cada `td` de la columna.
	   TODO: el sistema resuelve esto con `.tabla--tarjetas`, que reagrupa la fila como tarjeta.
	   Cuando las tablas de la app pasen a esa variante, esta utilidad se borra. */
	.tabla .ocultar-mobile {
		display: none;
	}

	/* La matriz de permisos se apila: en angosto la columna del recurso deja al grupo de acciones sin
	   ancho para acomodarse, y cada acción termina en su propio renglón. El nombre del recurso pasa a
	   ser el encabezado de su bloque; la divisoria entre filas sigue siendo lo que los separa. */
	.permisos__grupo {
		grid-template-columns: 1fr;
		gap: var(--esp-2);
	}
}

/* El conforme del cliente al cerrar una orden de trabajo: el lienzo donde se firma y la firma ya cargada.
   El sistema no tiene un campo de firma, así que se compone acá. El blanco del lienzo no es un color de la
   interfaz sino el papel: lo pinta firma.js adentro del PNG, y por eso acá no hay fondo.
   TODO: es el ítem 23 de PEDIDOS.md («Campo de firma»). */

/* El conforme agrupa varios campos (los de la forma elegida los trae htmx): el gap es el mismo del `.form`,
   que es el que los separaría si no estuvieran envueltos. Una sola columna, a diferencia de `.form__grupo`. */
.conforme {
	display: grid;
	gap: var(--esp-6);
}

/* El botón va debajo del lienzo y no ocupa todo el ancho del campo. */
.conforme__borrar {
	justify-self: start;
}

/* El lienzo y el input del archivo, uno sobre otro: firma.js tapa el input con el lienzo en vez de esconderlo,
   para que el navegador pueda enfocarlo y avisar que falta la firma ahí mismo. Sin JS el input se ve normal. */
.conforme__papel {
	position: relative;
}

.conforme__archivo {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	opacity: 0;
	pointer-events: none;
}

.conforme__lienzo {
	display: block;
	width: 100%;
	/* Dos líneas de firma holgadas: entra una firma con rúbrica sin achicarla. */
	height: calc(var(--esp-24) * 2);
	border: var(--borde-fino) solid var(--color-borde-control);
	border-radius: var(--radio-md);
	/* Sin esto, en un celular el dedo scrollea la página en vez de firmar. */
	touch-action: none;
}

/* El logo de una empresa (en la edición de plataforma, y en el selector en lugar de la sigla) y el de una sociedad
   (en su ficha, el que va en sus comprobantes). Es una imagen
   que sube cada empresa, así que se encaja sin deformarla: no se sabe de antemano qué proporción tiene.
   TODO: es el ítem 26 de PEDIDOS.md (`.selector__logo`). */
.logo-empresa,
.logo-sociedad {
	display: block;
	max-width: 100%;
	max-height: var(--esp-16);
	margin-block-end: var(--esp-4);
	object-fit: contain;
}

/* «Modificar» del logo: el formulario se abre debajo de la imagen. */
.logo-modificar > summary {
	list-style: none;
}

.logo-modificar[open] > summary {
	margin-block-end: var(--esp-4);
}

.selector__logo {
	flex: 0 0 auto;
	width: var(--esp-6);
	height: var(--esp-6);
	border-radius: var(--radio-sm);
	object-fit: contain;
}

.conforme__firma {
	display: block;
	max-width: 100%;
	border: var(--borde-fino) solid var(--color-borde-sutil);
	border-radius: var(--radio-md);
}
