/* ═══════════════════════════════════════════════════════════════════════════
   THL — Capa de componentes reutilizables

   ÚNICO lugar donde se decide la forma de los controles del SaaS. Un módulo
   nunca redefine un botón, una ficha, una hoja de acciones ni un estado vacío:
   usa estas clases. Cambiar aquí cambia todo el sistema.

   Contiene dos partes:
   1. Los componentes `.ui-*`, para marcado nuevo.
   2. La adopción: las primitivas que ya usan todos los módulos (`.btn`,
      `.act-kebab`, `.act-menu`, `.bdg`, `.emp`) heredan esta misma forma, así
      que los módulos existentes se actualizan sin tocar su marcado.

   Los colores salen siempre de tokens.css. Aquí no se escribe ningún literal.
   ═══════════════════════════════════════════════════════════════════════════ */

:root {
  --ui-pill: var(--rdp);        /* radio de botones y fichas */
  --ui-soft: 12px;              /* radio de pastillas de icono */
  --ui-card: 20px;              /* radio de tarjetas y hojas */
  --ui-tap: 40px;               /* alto mínimo de un control */
  --ui-tap-lg: 44px;            /* alto mínimo táctil */
  --ui-tile: 42px;              /* pastilla de icono de una fila */
  --ui-gap: 10px;               /* separación entre controles hermanos */
  --ui-gap-lg: 16px;            /* separación entre grupos de controles */
  /* Escala de iconos. Antes convivían seis tamaños distintos calculados por
     herencia; ahora un icono elige uno de estos cuatro pasos y nada más. */
  --ui-icon-sm: 1rem;           /* dentro de texto, etiquetas y distintivos */
  --ui-icon: 1.15rem;           /* acciones de barra y de formulario */
  --ui-icon-lg: 1.35rem;        /* acciones táctiles y de cabecera */
  --ui-icon-xl: 1.75rem;        /* flotante y controles de llamada */
  --ui-icon-hero: 2.5rem;       /* el único icono de un estado vacío */
  /* Densidad de las listas. Una fila de datos no necesita respirar como una
     tarjeta: cuanto más corta, más filas caben sin recurrir al scroll. */
  --ui-row-pad: .85rem;         /* relleno vertical de una celda en celular */
  --ui-row-pad-lg: .7rem;       /* el mismo, en pantallas amplias */
  --ui-speed: .16s;
  /* Los únicos colores literales permitidos fuera de tokens.css viven aquí:
     un velo y una sombra no tienen equivalente en la paleta del tema. */
  --ui-scrim: rgba(3, 10, 8, .55);
  --ui-lift: 0 12px 28px -10px rgba(0, 0, 0, .55);
}
@media (prefers-reduced-motion: reduce) { :root { --ui-speed: 0s; } }

/* ─── Acción con icono: la unidad básica de toda barra de herramientas ─── */
.ui-tool {
  display: inline-flex; align-items: center; gap: 7px;
  min-height: var(--ui-tap); padding: 0 14px;
  border: 1px solid var(--bo); border-radius: var(--ui-pill);
  background: var(--bg3); color: var(--fg);
  font: inherit; font-size: .8rem; cursor: pointer; white-space: nowrap;
  transition: background var(--ui-speed), border-color var(--ui-speed), color var(--ui-speed);
}
.ui-tool i { font-size: var(--ui-icon); }
.ui-tool:hover:not(:disabled) { background: var(--bgh); border-color: var(--bo2); }
.ui-tool:focus-visible { outline: 2px solid var(--ac); outline-offset: 2px; }
.ui-tool.is-on { background: var(--acg); border-color: var(--ac); color: var(--ac); }
.ui-tool.is-off, .ui-tool:disabled { opacity: .35; pointer-events: none; }
.ui-tool.is-danger { color: var(--da); }
.ui-tool.is-danger:hover { background: color-mix(in srgb, var(--da) 12%, transparent); border-color: var(--da); }
.ui-tool.is-primary { background: var(--ac); border-color: var(--ac); color: var(--on-ac); font-weight: 650; }
.ui-tool.is-primary:hover:not(:disabled) { background: var(--ac2); border-color: var(--ac2); }
/* Solo icono: cuadrado perfecto, sin depender de la longitud de la etiqueta. */
.ui-tool.is-icon { width: var(--ui-tap); padding: 0; justify-content: center; }
.ui-tool.is-icon > span { display: none; }

/* ─── Botón circular de acciones de una fila ─── */
.ui-more {
  display: grid; place-items: center;
  width: var(--ui-tap); height: var(--ui-tap); padding: 0;
  border: 0; border-radius: 50%; background: transparent; color: var(--fg2);
  font-size: var(--ui-icon-lg); cursor: pointer;
  transition: background var(--ui-speed), color var(--ui-speed);
}
.ui-more:hover { background: var(--bg3); color: var(--fg); }
.ui-more:focus-visible { outline: 2px solid var(--ac); outline-offset: 1px; }

/* ─── Ficha de filtro ─── */
.ui-chip {
  display: inline-flex; align-items: center; gap: 6px; flex-shrink: 0;
  min-height: 36px; padding: 0 14px;
  border: 1px solid var(--bo); border-radius: var(--ui-pill);
  background: transparent; color: var(--fg2);
  font: inherit; font-size: .78rem; cursor: pointer; white-space: nowrap;
  transition: background var(--ui-speed), color var(--ui-speed), border-color var(--ui-speed);
}
.ui-chip i { font-size: 1rem; }
.ui-chip:hover { background: var(--bgh); color: var(--fg); }
.ui-chip.is-on { background: var(--acg); border-color: var(--ac); color: var(--ac); font-weight: 600; }
.ui-chip:focus-visible { outline: 2px solid var(--ac); outline-offset: 2px; }
.ui-chips { display: flex; gap: 8px; overflow-x: auto; padding-bottom: 2px; scrollbar-width: none; }
.ui-chips::-webkit-scrollbar { display: none; }

/* ─── Barra de búsqueda ─── */
.ui-search {
  display: flex; align-items: center; gap: 8px;
  padding: 4px 6px 4px 16px;
  border: 1px solid var(--bo); border-radius: var(--ui-pill); background: var(--bg3);
  transition: border-color var(--ui-speed), box-shadow var(--ui-speed);
}
.ui-search:focus-within { border-color: var(--ac); box-shadow: 0 0 0 3px var(--acg); }
.ui-search > i { color: var(--fg2); font-size: var(--ui-icon); flex-shrink: 0; }
.ui-search input {
  flex: 1; min-width: 0; min-height: var(--ui-tap);
  border: 0; background: transparent; color: var(--fg); font: inherit; font-size: .92rem;
}
.ui-search input:focus { outline: none; }
.ui-search input::-webkit-search-cancel-button { display: none; }
.ui-search .ui-tool { border: 0; background: transparent; padding: 0 10px; }

/* ─── Pastilla de icono por categoría ─── */
.ui-tile {
  display: grid; place-items: center;
  width: var(--ui-tile); height: var(--ui-tile); flex-shrink: 0;
  border-radius: var(--ui-soft); background: var(--bg3); color: var(--fg2); font-size: var(--ui-icon-lg);
}
.ui-tile[data-tone=info] { background: color-mix(in srgb, var(--bl) 16%, transparent); color: var(--bl); }
.ui-tile[data-tone=ok] { background: color-mix(in srgb, var(--ac) 16%, transparent); color: var(--ac); }
.ui-tile[data-tone=danger] { background: color-mix(in srgb, var(--da) 14%, transparent); color: var(--da); }
.ui-tile[data-tone=warn] { background: color-mix(in srgb, var(--wa) 16%, transparent); color: var(--wa); }

/* ─── Distintivo ─── */
.ui-flag {
  display: inline-flex; align-items: center; flex: 0 0 auto;
  padding: 3px 10px; border-radius: var(--ui-pill);
  background: var(--bg3); color: var(--fg2);
  font-size: .68rem; font-weight: 700; letter-spacing: .02em;
}
.ui-flag[data-tone=ok] { background: color-mix(in srgb, var(--ac) 15%, transparent); color: var(--ac); }
.ui-flag[data-tone=warn] { background: color-mix(in srgb, var(--wa) 18%, transparent); color: var(--wa); }
.ui-flag[data-tone=danger] { background: color-mix(in srgb, var(--da) 15%, transparent); color: var(--da); }
.ui-flag[data-tone=info] { background: color-mix(in srgb, var(--bl) 15%, transparent); color: var(--bl); }

/* ─── Botón de creación: etiqueta en escritorio, flotante en celular ─── */
.ui-fab {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  min-height: var(--ui-tap-lg); padding: 0 20px;
  border: 0; border-radius: var(--ui-pill);
  background: var(--ac); color: var(--on-ac);
  font: inherit; font-size: .86rem; font-weight: 650; cursor: pointer;
  box-shadow: 0 8px 22px -12px var(--ac);
}
.ui-fab i { font-size: var(--ui-icon-lg); }
.ui-fab:hover { background: var(--ac2); }
.ui-fab:focus-visible { outline: 2px solid var(--ac); outline-offset: 3px; }

/* ─── Hoja de acciones: sube desde abajo en celular, se centra en escritorio ─── */
.ui-sheet { position: fixed; inset: 0; z-index: 2500; display: grid; }
.ui-sheet[hidden] { display: none; }
.ui-sheet-veil { position: absolute; inset: 0; background: var(--ui-scrim); opacity: 0; transition: opacity .2s; }
.ui-sheet.is-open .ui-sheet-veil { opacity: 1; }
.ui-sheet-card {
  position: relative; justify-self: center; align-self: center;
  width: min(420px, calc(100vw - 32px)); max-height: min(70dvh, 560px); overflow: auto;
  padding: 20px; border: 1px solid var(--bo2); border-radius: calc(var(--ui-card) + 2px);
  background: var(--bg); box-shadow: var(--sh2);
  transform: scale(.97); opacity: 0; transition: transform .2s, opacity .2s;
}
.ui-sheet.is-open .ui-sheet-card { transform: none; opacity: 1; }
.ui-sheet-grip { display: none; }
.ui-sheet-card h3 { margin: 0 0 14px; font-size: 1rem; letter-spacing: -.02em; overflow-wrap: anywhere; }

/* ─── Opción de menú o de hoja ─── */
.ui-menu-item {
  display: flex; align-items: center; gap: 14px; width: 100%;
  min-height: 52px; padding: 0 12px;
  border: 0; border-radius: var(--rd); background: transparent; color: var(--fg);
  font: inherit; font-size: .9rem; text-align: left; cursor: pointer;
}
.ui-menu-item i { font-size: var(--ui-icon-lg); color: var(--fg2); }
.ui-menu-item:hover:not(:disabled) { background: var(--bgh); }
.ui-menu-item:focus-visible { outline: 2px solid var(--ac); outline-offset: -2px; }
.ui-menu-item:disabled { opacity: .4; cursor: not-allowed; }
.ui-menu-item.is-danger, .ui-menu-item.is-danger i { color: var(--da); }
.ui-menu-item.is-danger:hover { background: color-mix(in srgb, var(--da) 10%, transparent); }

/* ─── Estado vacío ─── */
.ui-empty { padding: 56px 20px; text-align: center; color: var(--fg2); }
.ui-empty i, .ui-empty .bi { font-size: var(--ui-icon-hero); color: var(--ac); }
.ui-empty h3 { margin: 12px 0 6px; color: var(--fg); font-size: 1.05rem; }
.ui-empty p { margin: 0; font-size: .85rem; line-height: 1.5; }

/* ═══════════════════════════════════════════════════════════════════════════
   ADOPCIÓN — las primitivas que ya usan todos los módulos toman esta forma.
   Por eso una lista de facturas o de clientes cambia sin editar su marcado.
   ═══════════════════════════════════════════════════════════════════════════ */

/* Botones: misma pastilla, mismo foco y sin desplazamiento al pasar el cursor. */
.btn { border-radius: var(--ui-pill); min-height: var(--ui-tap); transition: background var(--ui-speed), border-color var(--ui-speed), color var(--ui-speed); }
.btn:focus-visible { outline: 2px solid var(--ac); outline-offset: 2px; }
.btn i { font-size: var(--ui-icon); }
.btn-p:hover, .btn-s:hover, .btn-w:hover { transform: none; box-shadow: none; }
.btn-p { box-shadow: 0 8px 22px -14px var(--ac); }
.btn-p:hover:not(:disabled) { background: var(--ac2); }

/* Acciones de fila: círculo, como en la lista de archivos. */
.act-kebab { width: var(--ui-tap); height: var(--ui-tap); border-radius: 50%; font-size: var(--ui-icon-lg); transition: background var(--ui-speed), color var(--ui-speed); }
.act-kebab:focus-visible { outline: 2px solid var(--ac); outline-offset: 1px; }
.act-menu { border-radius: var(--ui-card); padding: 8px; }
.act-menu-item { min-height: var(--ui-tap-lg); border-radius: var(--rd); font-weight: 500; gap: 12px; }
.act-menu-item i { font-size: var(--ui-icon-lg); color: var(--fg2); }
.act-menu-item.is-danger i { color: var(--da); }

/* Distintivos de estado: misma forma que `.ui-flag`. */
.bdg { padding: 3px 10px; border-radius: var(--ui-pill); font-size: .68rem; font-weight: 700; }

/* Estado vacío: sin borde punteado, icono en acento. */
.emp { padding: 56px 20px; background: transparent; border: 0; }
.emp .bi { font-size: var(--ui-icon-hero); margin-bottom: 10px; color: var(--ac); }

/* Acciones de cabecera en celular: icono, no rótulo.
   `workspace.js` envuelve el texto en `.btn-label`, así que aquí basta con
   esconderlo y cuadrar el botón. El nombre sigue en `aria-label`, de modo que
   un lector de pantalla lee «Nueva factura» donde el ojo ve un «+». */
@media (max-width: 767px) {
  .list-shell > .ct .btn .btn-label,
  .list-shell > .bar .btn .btn-label { display: none; }
  /* Lo mismo para las acciones que un módulo genera al vuelo: ya nacen con
     icono y etiqueta, y la etiqueta se recoge igual. */
  .list-shell > .ct .ui-tool > span,
  .list-shell > .bar .ui-tool > span { display: none; }
  .list-shell > .ct .ui-tool,
  .list-shell > .bar .ui-tool {
    flex: 0 0 auto; width: var(--ui-tap-lg); min-width: var(--ui-tap-lg);
    padding: 0; justify-content: center; gap: 0;
  }
  .list-shell > .ct .btn,
  .list-shell > .bar .btn {
    /* `flex:0 0 auto` gana a la regla que estira las acciones de barra: un
       icono cuadrado no debe repartirse el ancho de la pantalla. */
    flex: 0 0 auto;
    width: var(--ui-tap-lg); min-width: var(--ui-tap-lg); padding: 0;
    justify-content: center; gap: 0;
  }
  /* Paginación en un solo renglón. Ocupaba dos, con dos rótulos largos, para
     una acción que se entiende con una flecha. */
  /* La paginación puede envolver: forzarla a un renglón encimaba el rango con
     las flechas. Lo que se retira es el número de página, que ya está dicho en
     «1-5 de 5». */
  .list-pager { padding-top: .5rem; margin-top: .5rem; gap: 6px 10px; }
  .list-pager-page { display: none; }
  .list-pager-nav { width: auto; gap: 6px; margin-left: auto; }
  .list-pager-nav .btn { width: var(--ui-tap); min-width: var(--ui-tap); padding: 0; justify-content: center; gap: 0; }
  .list-pager-nav .btn .btn-label { display: none; }
  .list-pager-size { gap: 4px; }
  .list-pager-size select { min-height: var(--ui-tap); }

  /* Título e iconos comparten renglón, en vez de abrir una banda de botones. */
  .list-shell > .ct { flex-wrap: nowrap; }
  .list-shell > .ct > .toolbar-actions,
  .list-shell > .ct > div:last-child { flex: 0 0 auto; margin-left: auto; }
  .list-shell > .ct .btn i,
  .list-shell > .bar .btn i { font-size: var(--ui-icon-lg); }
}

/* Campos con icono. El icono no es decoración: dice qué hace el campo antes
   de leer el marcador de posición, y en celular el marcador se recorta.
   Se dibujan con bordes y currentColor, sin imágenes, para que sigan al tema
   y a `color-scheme` sin una versión por tema. */
.ui-field { position: relative; display: inline-flex; align-items: center; min-width: 0; }
.ui-field > input, .ui-field > select { width: 100%; min-width: 0; }

/* Lupa: un círculo y un mango. */
.ui-field.has-search > input { padding-inline-start: 38px; }
.ui-field.has-search::before {
  content: ""; position: absolute; left: 15px; top: 50%;
  width: 11px; height: 11px; margin-top: -7px;
  border: 1.6px solid currentColor; border-radius: 50%;
  color: var(--fg2); opacity: .8; pointer-events: none;
}
.ui-field.has-search::after {
  content: ""; position: absolute; left: 24px; top: 50%;
  width: 6px; height: 1.6px; margin-top: 3px;
  background: currentColor; border-radius: 2px; transform: rotate(45deg);
  color: var(--fg2); opacity: .8; pointer-events: none;
}
.ui-field.has-search:focus-within::before, .ui-field.has-search:focus-within::after { color: var(--ac); opacity: 1; }

/* Chevrón: se sustituye la flecha del sistema por una propia. */
.ui-field.has-chevron > select { appearance: none; -webkit-appearance: none; padding-inline-end: 30px; }
.ui-field.has-chevron::after {
  content: ""; position: absolute; right: 13px; top: 50%;
  width: 7px; height: 7px; margin-top: -5px;
  border-right: 1.7px solid currentColor; border-bottom: 1.7px solid currentColor;
  transform: rotate(45deg); color: var(--fg2); pointer-events: none;
}
.ui-field.has-chevron:focus-within::after { color: var(--ac); }
/* Una etiqueta que envuelve su desplegable sigue siendo una etiqueta. */
label.ui-field { gap: 6px; }

/* Disparador de filtros: un embudo con la cuenta encima. Vive aquí y no en un
   módulo porque lo monta `workspace.js` para todas las listas a la vez. */
.filter-disclosure { position: relative; }
.filter-disclosure .filter-count {
  position: absolute; top: -3px; right: -3px;
  min-width: 17px; height: 17px; padding: 0 4px;
  display: grid; place-items: center;
  border-radius: var(--ui-pill); background: var(--ac); color: var(--on-ac);
  font-size: .62rem; font-weight: 700; line-height: 1;
}

/* Búsqueda de las listas: misma pastilla que la barra de Cloud. */
.h-s input, .h-s select, .h-s-sel { border-radius: var(--ui-pill); }
.h-s input { padding-inline: 16px; }
.h-s select, .h-s-sel { padding-inline: 14px; }
.sidebar-search input { border-radius: var(--ui-pill); padding-inline: 16px; }

/* Campos de formulario: mismo foco en todo el sistema. */
.fg input:focus-visible, .fg select:focus-visible, .fg textarea:focus-visible { outline: none; }

/* ─── Ficha de registro: la fila de una lista con datos heterogéneos ───
   Una factura, un compromiso o un movimiento bancario no son ocho columnas
   comparables: son un titular, un importe y un estado. La tabla obligaba a
   ocho columnas y en 390 px se veían tres, sin aviso de que había más.

   La ficha muestra siempre lo que se consulta —quién, cuánto, en qué estado—
   y guarda el resto en columnas que solo aparecen cuando hay ancho para
   ellas. Nunca hay scroll horizontal. */
.rec-wrap {
  /* Ocupa el espacio libre de .list-shell y scrollea por dentro: el resto
     de la tarjeta (cabecera, ayuda, filtros, totales, paginador) no se mueve. */
  flex: 1 1 auto; min-height: 0; overflow: auto; -webkit-overflow-scrolling: touch;
}
.rec-list { list-style: none; margin: 0; padding: 0; }
.rec-item {
  display: grid; align-items: center; gap: 2px var(--ui-gap);
  grid-template-columns: auto minmax(0, 1fr) auto auto;
  grid-template-areas: 'tile main money more' '. flags flags .';
  padding: .7rem .9rem; border-bottom: 1px solid var(--bo);
}
.rec-item:last-child { border-bottom: 0; }
.rec-item:hover { background: var(--bgh); }
.rec-item > .ui-tile { grid-area: tile; }
.rec-main {
  grid-area: main; display: grid; gap: 2px; min-width: 0;
  padding: 0; border: 0; background: none; color: inherit;
  font: inherit; text-align: left; cursor: pointer;
}
.rec-main:not([data-open]) { cursor: default; }
.rec-main:focus-visible { outline: 2px solid var(--ac); outline-offset: 3px; border-radius: var(--rd); }
.rec-title {
  color: var(--fg); font-size: .86rem; font-weight: 600; letter-spacing: -.01em;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.rec-sub {
  color: var(--fg2); font-size: .74rem; line-height: 1.35;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.rec-money {
  grid-area: money; display: grid; justify-items: end; gap: 1px;
  color: var(--fg); font-size: .88rem; font-weight: 650;
  font-variant-numeric: tabular-nums; white-space: nowrap;
}
.rec-money small { color: var(--fg2); font-size: .7rem; font-weight: 500; }
.rec-money[data-tone=danger] { color: var(--da); }
.rec-flags { grid-area: flags; display: flex; flex-wrap: wrap; gap: 6px; }
.rec-item > .ui-more { grid-area: more; }
/* Las columnas de apoyo no caben en un teléfono y no son lo que se consulta. */
.rec-col { display: none; }
.rec-head { display: none; }

@media (min-width: 900px) {
  .rec-item {
    grid-template-columns: auto minmax(0, 2fr) repeat(var(--rec-cols, 0), minmax(0, 1fr)) auto auto auto;
    grid-template-areas: none;
    gap: var(--ui-gap);
  }
  /* Las áreas con nombre desaparecen aquí, así que hay que soltarlas con la
     misma especificidad con la que se asignaron: si no, el icono y el menú
     no encuentran su área y la rejilla los manda a una segunda fila. */
  .rec-item > .ui-tile, .rec-item > .rec-main, .rec-item > .rec-money,
  .rec-item > .rec-flags, .rec-item > .ui-more { grid-area: auto; }
  .rec-flags { justify-content: flex-end; }
  .rec-col {
    display: block; min-width: 0; color: var(--fg2); font-size: .78rem;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }
  .rec-head {
    position: sticky; top: 0; z-index: 2; background: var(--bg);
    box-shadow: 0 1px 0 var(--bo2);
    display: grid; align-items: center; gap: var(--ui-gap);
    grid-template-columns: auto minmax(0, 2fr) repeat(var(--rec-cols, 0), minmax(0, 1fr)) auto auto auto;
    padding: .45rem .9rem; border-bottom: 1px solid var(--bo);
    color: var(--fg2); font-size: .68rem; font-weight: 700;
    letter-spacing: .06em; text-transform: uppercase;
  }
  .rec-head > span:nth-child(1) { visibility: hidden; }
  .rec-head .rec-head-money { text-align: right; }
}

@media (max-width: 767px) {
  /* El menú de acciones de una fila se comporta como hoja inferior. */
  .act-menu { border-radius: var(--ui-card) var(--ui-card) 0 0; }
  .ui-fab {
    position: fixed; top: auto;
    right: max(16px, var(--safe-r)); bottom: calc(20px + var(--safe-b));
    z-index: 900; width: 60px; height: 60px; padding: 0; border-radius: var(--ui-card);
    box-shadow: var(--ui-lift);
  }
  .ui-fab > span { display: none; }
  .ui-fab i { font-size: var(--ui-icon-xl); }
  .ui-sheet-card {
    align-self: end; justify-self: stretch; width: auto; max-height: 78dvh;
    padding: 8px 12px calc(18px + var(--safe-b));
    border-radius: var(--ui-card) var(--ui-card) 0 0; border-bottom: 0;
    transform: translateY(100%); transition: transform .24s ease, opacity .2s;
  }
  .ui-sheet.is-open .ui-sheet-card { transform: none; }
  .ui-sheet-grip { display: block; width: 40px; height: 4px; margin: 6px auto 12px; border-radius: 999px; background: var(--bo2); }
  .ui-sheet-card h3 { padding-inline: 12px; }
  .ui-menu-item { min-height: 56px; }
}
@media (prefers-reduced-motion: reduce) {
  .ui-sheet-card, .ui-sheet-veil { transition: none; }
}
