/* Penwork · hoja de la aplicación.
 *
 * Cuarta y última capa de la cascada:
 *
 *   design/tokens.css → design/base.css → design/componentes.css → esta hoja
 *
 * Aquí vive **solo lo que no es reutilizable**: lo que existe porque Penwork
 * firma documentos, custodia una bóveda y habla con un agente de escritorio. Si
 * una pieza de esta hoja le serviría al agente, a la Fase 4a o a una landing
 * futura, su sitio es `design/componentes.css`, no este fichero.
 *
 * Ni un literal de color: `design/tokens.css` es la única fuente de hex del
 * producto y `design/check.sh` lo comprueba en la CI.
 */

/* --- Iconos -------------------------------------------------------------- */
/* SVG en el marcado (ver `plantillas/macros/iconos.html`), con `currentColor`
   para que tomen el color de su contexto. */
.icono {
  width: 1.15em;
  height: 1.15em;
  flex: 0 0 auto;
  vertical-align: -0.2em;
}

/* --- Indicadores de htmx ------------------------------------------------- */
/* Estas reglas las inyectaba htmx como `<style>` en línea y la CSP estricta
   (`style-src 'self'`) las bloqueaba. Con
   `<meta name="htmx-config" content='{"includeIndicatorStyles": false}'>`
   htmx deja de inyectarlas y viven aquí, servidas desde el propio origen. */
.htmx-indicator { opacity: 0; transition: opacity 200ms ease-in; }
.htmx-request .htmx-indicator { opacity: 1; }
.htmx-request.htmx-indicator { opacity: 1; }

/* --- Banners de versión y de agente (F1a / F2a) -------------------------- */
/* Discretos y descartables a propósito: nunca bloquean y nunca recargan solos.
 * Una recarga forzada borraría la clave maestra de la bóveda de esta pestaña,
 * que es la razón de ser de toda la arquitectura de navegación.
 *
 * Viven FUERA de `#panel`, el único contenedor que htmx sustituye al navegar.
 * Si estuvieran dentro, cada cambio de pantalla los borraría.
 *
 * `display: flex` obliga a que `[hidden] { display: none !important }` siga en
 * `design/base.css`: sin esa regla, el banner se vería siempre. Ya pasó. */
.aviso-version {
  display: flex;
  align-items: center;
  gap: var(--esp-2);
  flex-wrap: wrap;
  margin: 0 0 var(--esp-3);
  padding: var(--esp-2) var(--esp-3);
  border: var(--borde-ancho-fino) solid var(--borde);
  border-left: 6px solid var(--azul);
  background: var(--tinte-azul);
  font-size: var(--texto-menudo);
}
.aviso-version p { flex: 1 1 16rem; }
.aviso-version .icono { color: var(--azul); }
.aviso-version .cerrar {
  background: none;
  border: 0;
  font-family: var(--tipo-titulo);
  font-weight: 900;
  font-size: var(--texto-h3);
  line-height: 1;
  padding: 0 var(--esp-0);
  color: inherit;
  cursor: pointer;
}

/* --- Estado de la bóveda ------------------------------------------------- */
/* El interruptor del lateral. Cerrada es el estado por defecto y se lee como un
   aviso; abierta, como un hecho. El candado son dos iconos en el marcado y el
   CSS enseña el que toca según `data-bloqueada`: antes era un emoji que
   repintaba el JavaScript. */
.estado-boveda {
  display: inline-flex;
  gap: var(--esp-1);
  align-items: center;
  width: 100%;
  margin-top: var(--esp-3);
  padding: var(--esp-1) var(--esp-2);
  border: var(--borde-ancho-fino) solid var(--sobre-negro-2);
  background: transparent;
  color: var(--sobre-negro);
  font-family: var(--tipo-titulo);
  font-weight: 700;
  font-size: var(--texto-menudo);
  text-align: left;
  cursor: pointer;
}
.estado-boveda:hover { background: var(--negro-2); }
.estado-boveda[data-bloqueada="0"] {
  background: var(--mantequilla);
  border-color: var(--mantequilla);
  color: var(--negro);
}
.candado { display: inline-flex; }
.candado svg { width: 1em; height: 1em; }
.candado .abierto { display: none; }
[data-bloqueada="0"] .candado .cerrado { display: none; }
[data-bloqueada="0"] .candado .abierto { display: inline-flex; }

/* Formulario de salida del pie del lateral. */
.salir { margin-top: var(--esp-2); }
.salir .enlace { color: var(--txt-2); }

/* --- Asistente de firma ------------------------------------------------- */

.previsualizacion { margin-top: var(--esp-1); }
.pagina-muestra {
  position: relative;
  width: min(18rem, 100%);
  aspect-ratio: 210 / 297;
  background: var(--papel);
  border: var(--borde-ancho-fino) solid var(--borde);
}
/* `firmar.js` le escribe left/width/bottom/height en porcentaje desde el CSSOM
   —lo único que la CSP permite para geometría dinámica—, así que tiene que
   seguir siendo absoluta dentro de un contenedor posicionado. */
.sello-muestra {
  position: absolute;
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding: 2px 4px;
  border: var(--borde-ancho-fino) solid var(--azul);
  background: var(--tinte-azul);
  font-family: var(--tipo-titulo);
  font-size: 0.6rem;
  line-height: 1.15;
  overflow: hidden;
}

progress {
  width: 100%;
  height: 1.1rem;
  accent-color: var(--azul);
}

/* Firmante encontrado al verificar. */
.firmante {
  font-family: var(--tipo-titulo);
  font-weight: 700;
  font-size: var(--texto-h3);
}

/* Resultado de un lote: una fila por documento con su descarga. */
.lista-lote {
  list-style: none;
  margin: var(--esp-2) 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--esp-1);
}
.lista-lote > li {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--esp-2);
  padding: var(--esp-1) 0;
  border-bottom: var(--borde-ancho-fino) solid var(--borde);
}

/* --- Kit de recuperación ------------------------------------------------ */
/* La clave se lee en voz alta y se copia a mano: monoespaciada, grande y con
   las cifras separadas. */
.clave-recuperacion {
  font-family: var(--tipo-mono);
  font-size: var(--texto-guia);
  letter-spacing: 0.06em;
  padding: var(--esp-3);
  border: var(--borde-ancho) solid var(--borde);
  background: var(--papel);
  text-align: center;
  word-break: break-all;
}

/* Medidor de fuerza de la passphrase: el texto que acompaña a las barras de
   `design/componentes.css`. `certificados.js` le escribe `data-puntuacion`.
   El color no es lo único que informa: el texto dice lo mismo. */
.medidor-txt[data-puntuacion="0"],
.medidor-txt[data-puntuacion="1"] { color: var(--rojo); }
.medidor-txt[data-puntuacion="2"] { color: var(--txt-2); }
.medidor-txt[data-puntuacion="3"],
.medidor-txt[data-puntuacion="4"] { color: var(--azul); }

/* --- Autenticación sin contraseñas (F1b) ------------------------------- */

/* Código de cuatro dígitos que se enseña en el dispositivo que abrió el enlace.
   Es el dato que la persona tiene que copiar a mano en otra pantalla. */
.codigo-cruzado {
  font-family: var(--tipo-mono);
  font-size: clamp(2rem, 8vw, 3rem);
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.35em;
  text-indent: 0.35em;          /* compensa el espaciado del último dígito */
  text-align: center;
  color: var(--azul);
  border: var(--borde-ancho) solid var(--borde);
  background: var(--papel);
  padding: var(--esp-3) var(--esp-1);
  margin: var(--esp-3) 0;
}
/* Y su campo de entrada al otro lado, con la misma pinta para que se reconozcan
   como la misma cosa. */
.codigo-corto {
  font-family: var(--tipo-mono);
  font-size: var(--texto-h3);
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.3em;
  text-align: center;
  max-width: 8rem;
}

/* La clave de recuperación del kit: ocho grupos de cuatro, 39 caracteres con los
   guiones. No vale `.codigo-corto`, que está pensada para los cuatro dígitos del
   reto y se queda en 8rem: aquí el campo tiene que caber entero para que se
   pueda comparar de un vistazo con el papel. */
.codigo-clave {
  font-family: var(--tipo-mono);
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

/* Lista de passkeys de la sección Seguridad. */
.lista-passkeys { list-style: none; padding: 0; margin: var(--esp-1) 0 var(--esp-3); }
.lista-passkeys:empty { display: none; }
.lista-passkeys .passkey {
  padding: var(--esp-2) 0;
  border-bottom: 1px solid var(--borde-fino);
}
.lista-passkeys .passkey:last-child { border-bottom: 0; }
.lista-passkeys .passkey.revocada { color: var(--txt-2); }
.lista-passkeys .passkey.revocada strong { text-decoration: line-through; }
.lista-passkeys .acciones { margin-top: var(--esp-0); }

/* Los subtítulos de Seguridad separan bloques distintos —passkeys, correo,
   código—, así que necesitan aire por arriba; sin él la sección se lee como un
   párrafo continuo. */
#panel-seguridad h3 { margin-top: var(--esp-5); margin-bottom: var(--esp-1); }
#panel-seguridad h3:first-of-type { margin-top: var(--esp-3); }

#totp-qr { margin: var(--esp-3) 0; }
#totp-qr svg { max-width: 12rem; height: auto; }

/* --- Estado del sistema ------------------------------------------------- */

.estado-global { font-size: var(--texto-guia); font-family: var(--tipo-titulo); font-weight: 700; }
.version-desplegada { font-family: var(--tipo-mono); font-size: var(--texto-menudo); }

/* --- Descarga del agente ----------------------------------------------- */

.descargas { display: grid; gap: var(--esp-3); }
.comando {
  font-family: var(--tipo-mono);
  font-size: var(--texto-menudo);
  background: var(--negro);
  color: var(--sobre-negro);
  padding: var(--esp-2);
  overflow-x: auto;
  white-space: pre;
}

/* --- Ajustes de la zona de trabajo ------------------------------------- */

/* `#panel` es el hueco que htmx sustituye al navegar, y nada más: no reparte
   espacio. Lo hizo durante el desarrollo de la Fase 1c —era una rejilla con
   `gap`, heredada del layout anterior, donde `#panel` contenía directamente el
   h1 y las secciones— y el resultado fue que la mitad de las pantallas tenían el
   doble de aire bajo la barra superior que la otra mitad: las que cuelgan
   `.topbar` y `.contenido` directamente de `#panel` recibían el `gap` y las que
   llevan un envoltorio intermedio, no. Quien reparte el espacio de una pantalla
   es `.contenido`, que es del sistema de diseño y es igual en las catorce. */

/* --- Páginas públicas de una sola tarjeta ------------------------------- */
/* Entrar, alta, canje del enlace y error no van dentro de una `.seccion` a
   sangre: son una tarjeta suelta en medio de la página y necesitan su propio
   aire vertical, o quedan pegadas a la cabecera sticky. */
main > .tarjeta { margin-block: var(--esp-6); }
main > .tarjeta + .ayuda,
main > .ayuda { max-width: 34rem; margin-inline: auto; padding: 0 var(--esp-3) var(--esp-6); }

/* --- Bóveda de credenciales (F8) ---------------------------------------- */

/* La pantalla tiene tres columnas —raíl de colecciones, lista y ficha— y esa
   geometría es de la aplicación, no del sistema de diseño: el agente no la
   consume. Por eso vive aquí y no en `design/componentes.css`, que se sincroniza
   a dos sitios más.

   El orden de los cortes no es casual. Primero se pliega la ficha, que es lo
   que se lee de un vistazo y no se toca; el raíl aguanta más, porque sin él no
   se puede cambiar de colección. */
.rejilla.con-rail-y-ficha {
  display: grid;
  /* Sin selección son DOS columnas: reservar la de la ficha dejaba un tercio de
     la pantalla en blanco y la lista arrinconada a la izquierda. La tercera
     aparece cuando hay algo que enseñar en ella. */
  grid-template-columns: 14rem minmax(0, 1fr);
  gap: var(--esp-4);
  align-items: start;
}
@media (min-width: 1101px) {
  .rejilla.con-rail-y-ficha.hay-ficha {
    grid-template-columns: 14rem minmax(0, 1fr) var(--ficha);
  }
}
@media (max-width: 1100px) {
  .rejilla.con-rail-y-ficha { grid-template-columns: 12rem minmax(0, 1fr); }
  .rejilla.con-rail-y-ficha > .ficha { grid-column: 1 / -1; }
}
@media (max-width: 720px) {
  .rejilla.con-rail-y-ficha { grid-template-columns: minmax(0, 1fr); }
}

/* El buscador va justo debajo de las pestañas: `.filtros` trae el aire de una
   barra de filtros de tabla y aquí dejaba un hueco de noventa píxeles entre lo
   que se pulsa y lo que se escribe. */
.buscador-credenciales { margin-block-start: var(--esp-3); }

/* El título del raíl y el de cada grupo arrancan a la misma altura: si no, las
   dos columnas de la pantalla salen escalonadas y parece un fallo de montaje. */
.rail-credenciales .rail-tit,
.grupo-credenciales > h2 { margin-block-start: 0; }
.rail-credenciales ul { list-style: none; margin: 0; padding: 0; }
.rail-credenciales li + li { margin-top: var(--esp-1); }
/* Solo los botones de la LISTA de colecciones van sin fondo ni borde. Sin el
   `ul` de delante, esta regla alcanzaba también al botón del pie —«Nueva
   colección»— y lo dejaba transparente y en gris: parecía un campo de texto. */
.rail-credenciales ul button {
  display: flex;
  justify-content: space-between;
  gap: var(--esp-2);
  width: 100%;
  text-align: left;
  background: none;
  border: var(--borde-ancho-fino) solid transparent;
  padding: var(--esp-2);
  font: inherit;
  color: inherit;
  cursor: pointer;
}
.rail-credenciales ul button[aria-pressed="true"] {
  border-color: var(--borde);
  background: var(--papel);
  box-shadow: var(--sombra-baja);
}
.rail-credenciales .cuenta { color: var(--txt-2); font-variant-numeric: tabular-nums; }
.rail-credenciales .aviso-rotar { color: var(--rojo); }
.vacio-rail { padding: var(--esp-2); }

.lista-credenciales { list-style: none; margin: 0; padding: 0; }
.lista-credenciales li + li { margin-top: var(--esp-1); }
.lista-credenciales button {
  display: block;
  width: 100%;
  text-align: left;
  background: var(--papel);
  border: var(--borde-ancho-fino) solid var(--borde-fino);
  padding: var(--esp-2) var(--esp-3);
  font: inherit;
  color: inherit;
  cursor: pointer;
  /* El área de pulsación llega a 24 px de alto incluso en móvil (WCAG 2.5.8). */
  min-height: 2.75rem;
}
.lista-credenciales button[aria-pressed="true"] {
  border-color: var(--borde);
  box-shadow: var(--sombra-baja);
}
.lista-credenciales .secundario-linea { display: block; }
.grupo-credenciales + .grupo-credenciales { margin-top: var(--esp-5); }
.grupo-credenciales > .seccion-cab {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--esp-2);
  margin-block-end: var(--esp-2);
}

/* La cuenta atrás del portapapeles y del revelado. Va con cifras tabulares para
   que el botón no cambie de ancho cada segundo, que es un baile molesto justo
   cuando la persona está mirando ahí. */
.cuenta-atras {
  margin-left: var(--esp-1);
  font-variant-numeric: tabular-nums;
}

/* El campo de contraseña del editor y su botón de ver, en la misma línea. */
.campo-con-boton { display: flex; gap: var(--esp-2); align-items: stretch; }
.campo-con-boton input { flex: 1; min-width: 0; }

.generador { margin-block: var(--esp-3); }
.generador .casilla { margin-right: var(--esp-2); }

/* El buscador es el verbo principal de esta pantalla: con el ancho de un campo
   de formulario cualquiera queda arrinconado y no se lee como lo que es. */
.buscador-credenciales { display: block; }
.buscador-credenciales .campo { width: 100%; max-width: 32rem; }
.buscador-credenciales .campo input { width: 100%; }

/* Un botón que ocupa su columna y se lee como botón. Sin esto, «Nueva
   colección» en el pie del raíl se confundía con un campo de texto: mismo
   ancho, mismo borde fino y el texto en gris. */
.boton.bloque { display: block; width: 100%; text-align: center; }

/* El pie de la ficha: el aviso honesto va con el mismo relleno que las
   acciones y separado de ellas por una línea, no pegado al borde de la caja. */
.pie-ficha { border-top: var(--borde-ancho-fino) solid var(--borde-fino); }
.pie-ficha .ayuda { margin: 0; }

/* Dentro de una tarjeta, un encabezado que sigue a un párrafo necesita aire o
   parece que titula el párrafo anterior. Se veía en la pantalla de importación,
   con «Columnas» pegado al resumen del formato. */
.tarjeta > h3,
.tarjeta > h2 + p + h3,
.tarjeta > div + h3 { margin-block-start: var(--esp-5); }
