/* Agenda Notaría — hoja de estilos del cliente web (Electron + PWA). */

/* ---------- Identidad ----------
   El morado de marca es el mismo que el del logo (`logo_morado.svg` pinta con
   este hexadecimal exacto) y el mismo que usa el resto de programas de
   Signatus. De él salen por derivación el degradado de la cabecera y el tono
   suave de las pastillas: no se inventa ningún morado nuevo por el camino.

   OJO: este morado es de MARCA — cabecera, botones y acentos. Nunca sustituye
   al color de un empleado, que sigue saliendo de `colores.js` y significa
   identidad de persona (principio 5). Si algún día el morado acaba pintando
   la franja de una cita, el sistema de color está roto. */
:root {
  --marca: #481c5f;
  --marca-oscura: #2b0f43;   /* arranque del degradado de la cabecera */
  --marca-clara: #6f2c93;    /* final del degradado y estados hover */
  --marca-suave: #f0e5f5;    /* pastillas, iconos y fondos de acento */
  --marca-tenue: #f7f2fa;    /* ilustraciones y fondos apenas teñidos */

  --fondo: #f6f3f9;
  --superficie: #ffffff;
  --borde: #e4dcec;
  --borde-suave: #f0ebf5;
  /* Borde de los campos y desplegables: el morado de la marca muy rebajado.
     Translúcido a propósito, para que valga igual sobre el relleno claro del
     campo que sobre el blanco de una tarjeta. */
  --borde-campo: rgba(72, 28, 95, 0.22);

  /* Rejilla de la vista día. Cada subdivisión más tenue que la anterior: la
     hora se lee de un vistazo y la media y los cuartos se notan sin buscarlos,
     pero sin competir con la línea de la hora ni con las citas. Separada de
     `--borde-suave` a propósito: esa variable la usan también los bordes de
     columna y otros divisores, y subirle el contraste solo aquí no debía
     oscurecer el resto de la pantalla. */
  --rejilla-hora: #c7cbd1;
  --rejilla-media: #dde0e4;
  --rejilla-cuarto: #eceef1;
  --texto: #241a33;
  --texto-tenue: #6b6280;
  /* `--acento` es lo que ya usaban botones y estados activos en toda la hoja.
     Apuntarlo al morado de marca reviste la aplicación entera sin tener que
     reescribir cada regla que lo usaba. */
  --acento: var(--marca);

  /* Estado excepcional: los dos únicos casos con fondo de color (principio 5). */
  --aplazada-fondo: #fef3c7;
  --aplazada-borde: #b45309;
  --cancelada-fondo: #fee2e2;
  --cancelada-borde: #b91c1c;

  /* «Urgente» no es un estado sino una marca que se cruza con ellos, pero para
     el color se comporta igual: se lleva el fondo del bloque, que es el canal
     de «esto no es lo normal». Mismo rojo que cancelada pero más saturado, y
     con la etiqueta en negativo: se pidió que fuera lo que más salta a la
     vista de toda la agenda. Las dos nunca coinciden en un bloque —una cita
     cancelada pierde la marca, ver `esUrgente()`—, así que no compiten. */
  --urgente-fondo: #fecaca;
  --urgente-borde: #dc2626;

  --radio: 12px;
  --radio-tarjeta: 18px;
  --sombra: 0 1px 2px rgba(72, 28, 95, 0.05), 0 2px 8px rgba(72, 28, 95, 0.06);
  --sombra-tarjeta: 0 2px 6px rgba(72, 28, 95, 0.05), 0 8px 24px rgba(72, 28, 95, 0.07);

  /* Serif solo para los títulos. Georgia va primero porque está en Windows,
     macOS, Android e iOS: no hay que pedir nada a ningún servidor, así que la
     aplicación sigue funcionando sin conexión y no se filtra a nadie de fuera
     qué notaría abre la agenda. Playfair queda detrás por si alguien la tiene
     instalada. */
  --serif: "Playfair Display", Georgia, "Times New Roman", serif;
}

* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--fondo);
  color: var(--texto);
  font: 14px/1.45 "Segoe UI", system-ui, -apple-system, sans-serif;
}

/* Los títulos de sección van en serif: es lo que le da carácter a la pantalla
   sin tocar la letra del contenido, que sigue siendo sans y se lee mejor en
   tablas y formularios. */
.usuarios__titulo,
.perfil__seccion,
.estadisticas__subtitulo,
.dia-movil__seccion-titulo,
.bandeja__titulo,
.hoja-mas__titulo,
.dia__titulo,
.recepcion__nombre,
.dia-movil__concepto,
.saldo__restantes,
.estadisticas__numero,
.vacio-ilustrado__titulo {
  font-family: var(--serif);
  letter-spacing: 0.01em;
}

.cargando {
  padding: 2rem;
  color: var(--texto-tenue);
}

/* ---------- Controles ---------- */

.boton {
  padding: 0.4rem 0.8rem;
  border: 1px solid var(--borde);
  border-radius: var(--radio);
  background: var(--superficie);
  color: var(--texto);
  font: inherit;
  cursor: pointer;
}

.boton:hover { background: var(--marca-tenue); border-color: var(--marca-suave); }
.boton:disabled { opacity: 0.6; cursor: default; }

.boton--icono {
  width: 2rem;
  padding: 0.4rem 0;
  font-size: 1.1rem;
  line-height: 1;
}

.boton--principal {
  background: var(--marca);
  border-color: var(--marca);
  color: #fff;
  width: 100%;
  padding: 0.6rem;
  font-weight: 600;
}

.boton--principal:hover {
  background: var(--marca-clara);
  border-color: var(--marca-clara);
}

/* Regla general: cualquier clase que fije `display` gana al `display: none`
   que el navegador aplica por el atributo `hidden`, y el elemento se sigue
   viendo aunque el código lo haya ocultado. Se corta aquí, una vez, en vez de
   ir acordándose clase por clase. */
[hidden] { display: none !important; }

.campo { display: block; margin-bottom: 0.9rem; }

.campo__etiqueta {
  display: block;
  margin-bottom: 0.25rem;
  color: var(--texto-tenue);
  font-size: 0.85rem;
}

/* Campos y desplegables, en el morado claro de la marca. El gris que el
   navegador pinta por su cuenta en un `<select>` era lo único de los
   formularios que se salía de la paleta, y encima cambiaba de tono según el
   navegador. Al enfocar pasan a blanco: es lo que distingue de un vistazo
   dónde se está escribiendo del resto de la fila. */
.campo__control {
  width: 100%;
  padding: 0.5rem 0.6rem;
  border: 1px solid var(--borde-campo);
  border-radius: var(--radio);
  background: var(--marca-suave);
  color: var(--texto);
  font: inherit;
}

.campo__control:focus {
  outline: 2px solid var(--acento);
  outline-offset: -1px;
  background: var(--superficie);
}

.campo__control:disabled,
.campo__control[readonly] {
  background: var(--borde-suave);
  color: var(--texto-tenue);
}

/* Lo que no tiene vuelta atrás se ve distinto antes de pulsarlo. En rojo pero
   sin relleno: tiene que reconocerse como peligroso, no competir con la acción
   principal de la pantalla. */
/* El apartado de la bandeja que pide que alguien haga algo. En ámbar y no en
   rojo: no es un error, es trabajo pendiente. */
.bandeja__titulo--aviso { color: #8a5a00; }

.boton--peligro {
  border-color: var(--cancelada-borde);
  color: var(--cancelada-borde);
}

.boton--peligro:hover {
  background: var(--cancelada-borde);
  color: #fff;
}

/* ---------- Casillas y opciones ----------
   Las que dibuja el navegador son grises y desentonan con el resto: van en la
   familia de la marca, morado claro con el borde morado, y al marcarlas se
   rellenan del morado fuerte con la señal en blanco. El relleno tiene que ser
   fuerte, no claro, porque es lo único que hay detrás de la marca de verificado.

   Va aquí arriba a propósito, antes que las reglas de cada formulario: así
   cualquier ajuste concreto —un margen, un tamaño— sigue pudiendo mandar sobre
   esto sin pelearse por especificidad. */

input[type="checkbox"],
input[type="radio"] {
  appearance: none;
  -webkit-appearance: none;
  display: inline-grid;
  place-content: center;
  flex: 0 0 auto;
  width: 1.05rem;
  height: 1.05rem;
  margin: 0;
  border: 1.5px solid var(--marca-clara);
  background: var(--marca-suave);
  cursor: pointer;
  transition: background-color 0.15s ease, border-color 0.15s ease;
}

input[type="checkbox"] { border-radius: 0.32rem; }
input[type="radio"] { border-radius: 50%; }

input[type="checkbox"]:checked,
input[type="radio"]:checked {
  background: var(--marca);
  border-color: var(--marca);
}

/* La marca de verificado: un rectángulo con dos lados y girado, que es la
   forma más fiable de dibujar un palote en CSS. */
input[type="checkbox"]:checked::before {
  content: "";
  width: 0.3rem;
  height: 0.58rem;
  margin-top: -0.12rem;
  border: solid #fff;
  border-width: 0 2px 2px 0;
  transform: rotate(45deg);
}

input[type="radio"]:checked::before {
  content: "";
  width: 0.42rem;
  height: 0.42rem;
  border-radius: 50%;
  background: #fff;
}

input[type="checkbox"]:focus-visible,
input[type="radio"]:focus-visible {
  outline: 2px solid var(--marca-clara);
  outline-offset: 2px;
}

input[type="checkbox"]:disabled,
input[type="radio"]:disabled {
  border-color: var(--borde);
  background: var(--borde-suave);
  cursor: default;
}

input[type="checkbox"]:disabled:checked,
input[type="radio"]:disabled:checked {
  background: var(--texto-tenue);
  border-color: var(--texto-tenue);
}

/* ---------- Acceso ---------- */

.acceso {
  display: grid;
  place-items: center;
  min-height: 100vh;
  padding: 1rem;
}

.acceso__caja {
  width: min(360px, 100%);
  padding: 1.8rem;
  background: var(--superficie);
  border: 1px solid var(--borde);
  border-radius: 10px;
  box-shadow: var(--sombra);
}

.acceso__titulo {
  margin: 0 0 1.2rem;
  font-size: 1.25rem;
}

.acceso__aviso {
  margin: 0 0 0.8rem;
  min-height: 1.2em;
  color: var(--cancelada-borde);
  font-size: 0.85rem;
}

/* ---------- Armazón ---------- */

.agenda {
  display: flex;
  flex-direction: column;
  height: 100vh;
}

/* La cabecera es la única superficie de color fuerte de la aplicación. En
   escritorio es una barra recta; en móvil, el @media de más abajo enciende la
   onda del borde inferior. El degradado sale de los dos tonos derivados del
   morado de marca, sin inventar ninguno. */
.cabecera {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.55rem 1.1rem;
  background: linear-gradient(105deg, var(--marca-oscura) 0%, var(--marca) 55%, var(--marca-clara) 100%);
  color: #fff;
}

.cabecera__marca {
  margin: 0;
  font-size: 1.15rem;
  font-weight: 400;
  /* Sin esto «Agenda Notaría» se parte en dos renglones en cuanto la barra va
     justa de sitio, y la cabecera crece de alto sin motivo. */
  white-space: nowrap;
  flex: 0 0 auto;
}

/* La marca lleva a la agenda. Va como botón para que funcione con teclado y
   lector de pantalla, pero se despoja de todo lo que la haría parecer uno:
   sigue leyéndose como el nombre de la aplicación. */
.cabecera__marca-boton {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0;
  border: 0;
  background: none;
  color: inherit;
  font: inherit;
  text-align: left;
  cursor: pointer;
}

.cabecera__logo {
  width: 3rem;
  height: 3rem;
  flex: 0 0 auto;
  /* El SVG viene con más alto que ancho: así se ve entero y centrado en vez
     de deformarse para llenar el cuadrado. */
  object-fit: contain;
}

.cabecera__marca-texto { font-family: var(--serif); letter-spacing: 0.01em; }

/* Nunca subrayada, ni al pasar el ratón ni de pestaña activa: sigue siendo el
   nombre de la aplicación, y un subrayado la convierte en un enlace más. Que
   lleva a la agenda se nota al pulsarla, no hace falta anunciarlo. */
.cabecera__marca-boton,
.cabecera__marca-boton:hover,
.cabecera__marca-boton .cabecera__marca-texto,
.cabecera__marca-boton:hover .cabecera__marca-texto { text-decoration: none; }

.cabecera__marca-boton:focus-visible {
  outline: 2px solid #fff;
  outline-offset: 3px;
  border-radius: 4px;
}

/* La onda vive siempre en el DOM y el CSS decide si se ve: así girar el móvil
   no obliga a reconstruir la cabecera. En escritorio, fuera. */
.cabecera__onda { display: none; }

.cabecera__sesion {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  flex: 0 0 auto;
}

.cabecera__nombre { white-space: nowrap; }

/* La campana se envuelve en un `<span>`, y un `<span>` a secas es texto: crea
   una caja de línea con su hueco de base, y eso empujaba la campana un par de
   píxeles hacia arriba respecto al avatar de al lado. En cuanto deja de ser
   texto y pasa a ser una caja, las dos quedan centradas. */
.cabecera__campanita {
  display: inline-flex;
  align-items: center;
  flex: 0 0 auto;
}

.cabecera__usuario { font-weight: 600; }

/* Dentro de la cabecera todo va en blanco sobre el morado. Se apunta a los
   elementos concretos y no a `.cabecera *` para no repintar de blanco los
   menús que cuelgan de ella y se dibujan sobre fondo claro. */
.cabecera .cabecera__usuario,
.cabecera .cabecera__nombre { color: #fff; }

.cabecera .cabecera__rol {
  background: rgba(255, 255, 255, 0.16);
  color: #fff;
}

.cabecera__avatar {
  background-color: #fff;
  border-color: rgba(255, 255, 255, 0.6);
  color: var(--marca);
}

.cabecera__salir {
  background: rgba(255, 255, 255, 0.12);
  border: 1px solid rgba(255, 255, 255, 0.35);
  color: #fff;
}

.cabecera__salir:hover { background: rgba(255, 255, 255, 0.22); }

/* El desplegable nativo pinta sus opciones con el color del sistema: si el
   texto se queda blanco, la lista abierta sale en blanco sobre blanco. */
.cabecera__idioma option { color: var(--texto); background: var(--superficie); }

.cabecera__rol,
.columna__rol {
  padding: 0.1rem 0.4rem;
  background: var(--borde-suave);
  border-radius: 999px;
  color: var(--texto-tenue);
  font-size: 0.72rem;
  text-transform: capitalize;
}

.contenido { flex: 1; min-height: 0; display: flex; }

/* ---------- Vista día ---------- */

/* La agenda va en su tarjeta, como el resto de pantallas: era lo único que
   iba a sangre contra el fondo y por eso desentonaba. Nada más que eso —marco
   suave, esquinas y sombra—; por dentro sigue siendo la misma rejilla.
   El `overflow: hidden` es lo que hace que la rejilla respete las esquinas al
   desplazarse; no afecta al botón flotante, que va en posición fija. */
.dia {
  display: flex;
  flex-direction: column;
  flex: 1;
  min-width: 0;
  margin: 1rem;
  overflow: hidden;
  background: var(--superficie);
  border: 1px solid var(--borde);
  border-radius: var(--radio-tarjeta);
  box-shadow: var(--sombra-tarjeta);
}

/* Envuelve a propósito: con ocho controles, en una pantalla de portátil no
   caben en una fila y el botón de «Nueva cita» se salía por la derecha. En
   dos filas —fecha y vista arriba, acciones debajo— es además como está en
   las referencias de escritorio. */
.dia__barra {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.5rem 0.9rem;
  padding: 0.6rem 1rem;
  background: var(--superficie);
  border-bottom: 1px solid var(--borde);
}

/* Nunca se encoge ni se reparte: es el ancla de la barra. */
.dia__navegacion { display: flex; align-items: center; gap: 0.35rem; flex: 0 0 auto; }

/* Estando ya en hoy no hay a dónde volver, así que se apaga — pero sigue
   ocupando su sitio entre las dos flechas. Ver el porqué en `vista-agenda.js`.
   Se atenúa sin más: un botón apagado que además cambiara de forma volvería a
   mover lo de al lado, que es justo lo que se quería evitar. */
.dia__volver-hoy:disabled {
  opacity: 0.3;
  cursor: default;
}

/* Los desplegables de las barras —la fecha, el año, de quién es el saldo— van
   igual que los campos de los formularios: son lo mismo, solo que sueltos en
   una barra en vez de dentro de una ficha. */
.dia__selector {
  padding: 0.35rem 0.5rem;
  border: 1px solid var(--borde-campo);
  border-radius: var(--radio);
  background: var(--marca-suave);
  color: var(--texto);
  font: inherit;
}

.dia__selector:focus { background: var(--superficie); }

.dia__titulo {
  margin: 0;
  font-size: 1rem;
  font-weight: 600;
  /* Una línea siempre. Sin esto, en una barra apretada el navegador parte
     «lunes, 10 de agosto de 2026» en tres renglones y estira la barra entera
     a más del triple de alto. */
  flex: 0 1 auto;
  min-width: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Solo la primera letra. Con `text-transform: capitalize` salía «Lunes, 10 De
   Agosto De 2026»: en castellano y en gallego los meses y las preposiciones
   van en minúscula. */
.dia__titulo::first-letter { text-transform: uppercase; }

/* La fecha completa cuando el título ya dice «Hoy», «Mañana» o «Ayer»: el
   apodo se lee de un vistazo, pero el dato exacto no se pierde. */
.dia__subtitulo {
  color: var(--texto-tenue);
  font-size: 0.8rem;
}

.dia__subtitulo:empty { display: none; }

/* Volver a hoy. Discreto y sin texto, y solo aparece cuando hoy no está
   a la vista: si ya lo estás mirando, no hay nada a lo que volver. */
.dia__volver-hoy {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: var(--texto-tenue);
}

.dia__volver-hoy:hover { color: var(--acento); }
.dia__volver-hoy svg { width: 15px; height: 15px; }

.dia__filtro {
  display: flex;
  align-items: center;
  gap: 0.35rem;
  font-size: 0.82rem;
  white-space: nowrap;
  cursor: pointer;
}

.dia__filtro input { margin: 0; }

.dia__sincronia {
  margin-left: auto;
  font-size: 0.78rem;
}

.dia__sincronia--ok { color: var(--texto-tenue); }
.dia__sincronia--error { color: var(--cancelada-borde); font-weight: 600; }

.dia__aviso {
  padding: 0.5rem 1rem;
  background: var(--aplazada-fondo);
  border-bottom: 1px solid var(--aplazada-borde);
  color: #7c2d12;
  font-size: 0.82rem;
}

.dia__cuerpo {
  display: flex;
  flex: 1;
  min-height: 0;
}

/* ---------- Rejilla horaria ---------- */

.rejilla {
  display: flex;
  flex: 1;
  min-width: 0;
  overflow: auto;
  background: var(--superficie);
}

/* El recuadro que se dibuja al arrastrar de una hora a otra para crear una
   cita. Enseña el rango ya redondeado al cuarto, así que lo que ves mientras
   arrastras es exactamente lo que va a salir en el formulario. */
.seleccion-horas {
  position: absolute;
  left: 2px;
  right: 2px;
  z-index: 4;
  display: flex;
  align-items: flex-start;
  justify-content: center;
  padding-top: 2px;
  border: 1px dashed var(--marca);
  border-radius: 6px;
  background: var(--marca-suave);
  opacity: 0.85;
  color: var(--marca);
  font-size: 0.7rem;
  font-variant-numeric: tabular-nums;
  font-weight: 600;
  /* Que no se coma el `mouseup`: los eventos tienen que llegar al lienzo. */
  pointer-events: none;
}

.rejilla__horas {
  position: sticky;
  left: 0;
  z-index: 3;
  flex: 0 0 56px;
  /* Deja hueco a la cabecera pegajosa de las columnas. */
  padding-top: 44px;
  background: var(--superficie);
  border-right: 1px solid var(--borde);
}

.rejilla__hora {
  padding-right: 0.5rem;
  border-top: 1px solid var(--borde-suave);
  color: var(--texto-tenue);
  font-size: 0.72rem;
  text-align: right;
}

.rejilla__columnas {
  display: flex;
  flex: 1;
  min-width: 0;
}

/* `flex-shrink: 0` y el min-width en línea que pone vista-agenda.js según los
   carriles que necesite: antes de comprimir el texto, se saca scroll. */
.columna {
  flex: 1 0 190px;
  min-width: 190px;
  border-right: 1px solid var(--borde-suave);
}

.columna__cabecera {
  position: sticky;
  top: 0;
  z-index: 2;
  display: flex;
  align-items: center;
  gap: 0.4rem;
  height: 44px;
  padding: 0 0.5rem;
  background: var(--superficie);
  /* El subrayado de color identifica al empleado, igual que la franja. */
  border-bottom: 3px solid;
}

.columna__punto {
  flex: 0 0 auto;
  width: 9px;
  height: 9px;
  border-radius: 50%;
}

.columna__nombre {
  flex: 1;
  overflow: hidden;
  font-weight: 600;
  font-size: 0.85rem;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* El `background-size` real lo pone vista-agenda.js con su escala; aquí solo
   queda un valor de respaldo por si el JS no llegara a ejecutarse. */
/* Tres rejillas superpuestas, de más marcada a más tenue: la hora en punto, la
   media y los cuartos. Sirven para calcular a ojo dónde cae una cita de 10:15
   sin tener que medir contra la hora entera.

   El orden importa: en CSS la primera capa se pinta encima, así que la línea de
   la hora va delante y no la tapa ninguna de las finas. El alto de cada capa
   sale de dividir el de la hora, que es `PX_POR_HORA` en vista-agenda.js — si
   una de las dos cambia sin la otra, la rejilla deja de cuadrar con las citas. */
.columna__lienzo {
  position: relative;
  background-image:
    linear-gradient(to bottom, var(--rejilla-hora) 1px, transparent 1px),
    linear-gradient(to bottom, var(--rejilla-media) 1px, transparent 1px),
    linear-gradient(to bottom, var(--rejilla-cuarto) 1px, transparent 1px);
  background-size: 100% 80px, 100% 40px, 100% 20px;
}

/* ---------- Cita ---------- */

.cita,
.bandeja__tarjeta {
  position: relative;
  display: flex;
  overflow: hidden;
  background: var(--superficie);
  border: 2px solid var(--borde);
  border-radius: var(--radio);
  box-shadow: var(--sombra);
}

.cita {
  position: absolute;
  margin: 1px 2px;
}

/* Rol por forma de borde, nunca por color: el color ya significa persona. */
.cita--encargado { border-style: solid; }
.cita--firmante { border-style: dashed; }
.cita--apoyo { border-style: dotted; }

.cita__franja {
  flex: 0 0 5px;
  background: var(--color-empleado, var(--borde));
}

.cita__contenido {
  min-width: 0;
  padding: 0.2rem 0.4rem;
  font-size: 0.76rem;
  /* Ajustado: con el interlineado normal, tres líneas no entraban en el bloque
     de una cita de tres cuartos de hora por menos de un píxel. */
  line-height: 1.35;
}

.cita__contenido p {
  margin: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Dos líneas por cita: arriba cuándo y qué, abajo quién y con qué teléfono.
   Cada línea es una sola fila que se recorta con puntos suspensivos por el
   final; partirla en dos renglones descuadraría la rejilla horaria, donde el
   alto de cada bloque es su duración y no puede crecer. */
.cita__linea {
  display: flex;
  align-items: baseline;
  gap: 0.3rem;
}

.cita__linea > * { flex: 0 0 auto; }

/* El concepto y el nombre del cliente son lo que puede ser largo, así que son
   los que ceden: se llevan el sitio que sobre y se recortan si no llegan. */
.cita__concepto,
.cita__cliente {
  flex: 0 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* La hora es lo único que va en negrita y a plena tinta. Es lo que se busca al
   recorrer una columna con la vista; lo demás se lee cuando ya has parado en
   la cita, así que va más apagado y no compite. */
.cita__hora {
  font-weight: 700;
  color: var(--texto);
  font-variant-numeric: tabular-nums;
}

.cita__concepto { color: var(--texto-tenue); }

/* Una cita puede llevar varios trámites («Compraventa + Hipoteca»). En un
   bloque alto caben los nombres enteros; en uno de quince minutos, no. Se
   dibujan los dos textos y aquí se decide cuál se ve, igual que con el resto
   de las líneas de la tarjeta: quien pinta el bloque solo sabe su tamaño. */
.cita__gestiones--corto { display: none; }
.cita--compacta .cita__gestiones--largo { display: none; }
.cita--compacta .cita__gestiones--corto { display: inline; }

.cita__cliente { color: var(--texto-tenue); }
.cita__tel { color: var(--texto-tenue); font-variant-numeric: tabular-nums; }

/* El estado excepcional se dice también con letras, no solo con el fondo de
   color: en una pantalla al sol, o para quien no distinga bien los colores,
   el fondo solo no basta. */
.cita__estado {
  color: var(--cancelada-borde);
  font-size: 0.68rem;
  text-transform: uppercase;
  letter-spacing: 0.02em;
}

.cita__ampliacion { color: var(--texto-tenue); }
.cita__expediente { color: var(--texto-tenue); font-variant-numeric: tabular-nums; }

.cita__rol {
  color: var(--texto-tenue);
  font-size: 0.68rem;
  text-transform: uppercase;
  letter-spacing: 0.02em;
}

.cita__privado { color: var(--cancelada-borde); font-weight: 700; }

/* Cuántas líneas se ven, según lo que dure la cita.
   Una de quince minutos y una de una hora no miden lo mismo, así que no tiene
   sentido que enseñen lo mismo: en la larga sobra sitio y se aprovecha. Las
   líneas de más existen siempre en el HTML; lo que cambia es cuáles se ven. */
.cita__linea--extra1,
.cita__linea--extra2 {
  display: none;
}

/* Corta —quince minutos—: solo la de arriba, que dice cuándo y qué. Recortar
   dos líneas a la mitad no informa; dejar una entera, sí. */
.cita--compacta .cita__linea--secundaria {
  display: none;
}

/* Tres cuartos de hora: entra un dato más. */
.cita--tres-lineas .cita__linea--extra1 {
  display: flex;
}

/* Una hora o más: entran los dos. */
.cita--cuatro-lineas .cita__linea--extra1,
.cita--cuatro-lineas .cita__linea--extra2 {
  display: flex;
}

.cita__extra {
  flex: 0 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  color: var(--texto-tenue);
}

/* Media columna, porque hay dos citas a la misma hora: cae el teléfono y se
   queda el nombre del cliente. Lo que identifica una cita al recorrer la
   agenda es con quién es, no el número; el número se mira cuando ya has
   parado en ella, y para eso está la ficha.
   Quitarlo entero y no recortarlo tiene además su motivo: un teléfono cortado
   por la mitad sigue pareciendo un teléfono, y alguien podría marcarlo. */
.cita--estrecha .cita__tel {
  display: none;
}

/* ---------- Bandeja de pendientes ---------- */

.bandeja {
  flex: 0 0 250px;
  overflow-y: auto;
  padding: 0.8rem;
  background: var(--fondo);
  border-left: 1px solid var(--borde);
}

.bandeja__titulo {
  margin: 0 0 0.6rem;
  font-size: 0.8rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--texto-tenue);
}

.bandeja__tarjeta {
  margin-bottom: 0.5rem;
  /* Sin hueco asignado todavía: borde discontinuo, como la firma que espera. */
  border-style: dashed;
}

.bandeja__vacia { margin: 0; color: var(--texto-tenue); font-size: 0.8rem; }

.cita,
.bandeja__tarjeta { cursor: pointer; }

.cita:hover,
.bandeja__tarjeta:hover { filter: brightness(0.97); }

.columna__lienzo { cursor: copy; }

/* ---------- Navegación ---------- */

/* Las pestañas son lo único que puede encogerse en la barra: la marca y los
   controles de sesión tienen que caber enteros, y con `min-width: 0` el
   navegador puede estrecharlas antes que desbordar la cabecera. */
.cabecera__nav {
  display: flex;
  gap: 0.15rem;
  margin-right: auto;
  min-width: 0;
  flex: 1 1 auto;
  overflow: hidden;
}

.cabecera__nav .pestana {
  padding: 0.35rem 0.55rem;
  white-space: nowrap;
}

.pestana {
  padding: 0.35rem 0.75rem;
  border: 0;
  border-bottom: 2px solid transparent;
  background: none;
  color: var(--texto-tenue);
  font: inherit;
  cursor: pointer;
}

/* Las pestañas viven sobre el morado de la cabecera, así que van en blanco
   translúcido y la activa se marca en blanco pleno con su subrayado. */
.cabecera__nav .pestana { color: rgba(255, 255, 255, 0.78); }
.cabecera__nav .pestana:hover { color: #fff; }

.cabecera__nav .pestana--activa {
  border-bottom-color: #fff;
  color: #fff;
  font-weight: 600;
}

.pestana:hover { color: var(--texto); }

.pestana--activa {
  border-bottom-color: var(--acento);
  color: var(--texto);
  font-weight: 600;
}

/* ---------- Usuarios ---------- */

/* Estadísticas, Ajustes y Mi perfil comparten aquí el mismo margen y ancho
   que el resto de pantallas de administración: sin esta regla se quedaban
   sin la clase base y el contenido salía pegado al borde, ocupando todo el
   ancho de la ventana. */
.usuarios,
.estadisticas,
.ajustes,
.perfil { flex: 1; min-width: 0; overflow: auto; padding: 1rem; }

.usuarios__barra {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  margin-bottom: 0.9rem;
}

.usuarios__barra--separada {
  margin-top: 1.6rem;
  padding-top: 1.2rem;
  border-top: 1px solid var(--borde);
}

/* El título se queda con el sitio que sobra para que el botón de acción vaya
   pegado a la derecha, como en las referencias. */
.usuarios__titulo { margin: 0; margin-right: auto; font-size: 1.15rem; }
.usuarios__cargando { color: var(--texto-tenue); }

/* El interruptor general de avisos al cliente.
   Va enmarcado y en rojo mientras está apagado, no porque haya nada roto sino
   porque es la llave que decide si esta aplicación le escribe a gente de fuera.
   Eso no puede parecer una preferencia más de una lista. */
.ajustes__llave {
  margin: 0 0 1.2rem;
  padding: 0.9rem 1rem;
  border: 1px solid #e8c4c4;
  border-left: 4px solid #b3261e;
  border-radius: var(--radio);
  background: #fdf6f6;
}

.ajustes__llave--abierta {
  border-color: #bfe3cf;
  border-left-color: #1d9e75;
  background: #f5fbf8;
}

.ajustes__llave .formulario__pista { margin: 0.4rem 0 0; }

/* ---------- Pie de autoría ----------
   El mismo que lleva Signatus, para que las dos aplicaciones de la casa se
   firmen igual: el texto primero y el logo después, no al revés.

   Va fuera del área que hace scroll, así que se queda abajo del todo sin
   tapar nada y sin moverse con el contenido. */
.pie {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;
  gap: 0.35rem;
  padding: 0.7rem 1rem;
  /* Sobre el fondo, sin tarjeta ni línea de separación: es una firma, no una
     sección de la aplicación, y metida en una barra blanca pesaba como si lo
     fuera. */
  color: var(--texto-tenue);
  font-size: 0.78rem;
}

.pie__logo {
  height: 1.05rem;
  width: auto;
  /* Se alinea con la línea de texto, no con la caja: si no, el trazo del logo
     queda flotando medio renglón por encima de las letras. */
  vertical-align: middle;
  flex: 0 0 auto;
}

.pie a {
  color: var(--marca);
  text-decoration: none;
  font-weight: 600;
}

.pie a:hover { text-decoration: underline; }

.pie__sep { opacity: 0.5; }

/* Botón, no enlace: no lleva a ninguna dirección, abre una ventana. Se viste
   de enlace porque es lo que la persona espera ver en un pie. */
.pie__enlace {
  padding: 0;
  border: 0;
  background: none;
  color: var(--texto-tenue);
  font: inherit;
  text-decoration: underline;
  cursor: pointer;
}

.pie__enlace:hover { color: var(--marca); }

.licencias p { margin: 0 0 0.8rem; line-height: 1.5; }
.licencias p:last-child { margin-bottom: 0; }
/* La barra de desplazamiento, en la paleta de la aplicación.
 *
 * **Solo en escritorio.** Declarar un alto para `::-webkit-scrollbar` hace
 * que Chrome dibuje también la barra horizontal aunque no haya nada que
 * desplazar de lado, y en el móvil eso salía como una franja gris suelta
 * entre dos tarjetas, como si algo estuviera mal pintado. Ahí abajo tampoco
 * hace falta: las tablas se convierten en tarjetas y no se van de ancho.
 */
@media (min-width: 721px) {

  /* Con muchos usuarios la tabla se va de ancho y aparece la barra gris del
   * navegador, que es lo único de la pantalla que no es de esta casa. Se pinta
   * en lila y más fina.
   *
   * Se declara de las dos formas porque no hay una sola que valga en todas
   * partes: `scrollbar-color` es la estándar (Firefox y los Chrome nuevos) y
   * `::-webkit-scrollbar` es la que entienden Chrome, Edge y el WebView de
   * Android, que es justo donde corre la APK. */
  .usuarios,
  .estadisticas,
  .ajustes,
  .perfil,
  .tabla-ancha {
    scrollbar-width: thin;
    scrollbar-color: var(--marca-clara) transparent;
  }

  .usuarios::-webkit-scrollbar,
  .estadisticas::-webkit-scrollbar,
  .ajustes::-webkit-scrollbar,
  .perfil::-webkit-scrollbar,
  .tabla-ancha::-webkit-scrollbar { width: 10px; height: 10px; }

  .usuarios::-webkit-scrollbar-track,
  .estadisticas::-webkit-scrollbar-track,
  .ajustes::-webkit-scrollbar-track,
  .perfil::-webkit-scrollbar-track,
  .tabla-ancha::-webkit-scrollbar-track { background: transparent; }

  .usuarios::-webkit-scrollbar-thumb,
  .estadisticas::-webkit-scrollbar-thumb,
  .ajustes::-webkit-scrollbar-thumb,
  .perfil::-webkit-scrollbar-thumb,
  .tabla-ancha::-webkit-scrollbar-thumb {
    border-radius: 999px;
    background: var(--marca-clara);
    /* El borde transparente deja aire alrededor sin necesidad de otro elemento:
       el fondo se recorta a la caja de relleno y el borde deja ver lo de atrás. */
    border: 3px solid transparent;
    background-clip: padding-box;
  }

  .usuarios::-webkit-scrollbar-thumb:hover,
  .estadisticas::-webkit-scrollbar-thumb:hover,
  .ajustes::-webkit-scrollbar-thumb:hover,
  .perfil::-webkit-scrollbar-thumb:hover,
  .tabla-ancha::-webkit-scrollbar-thumb:hover { background: var(--marca); background-clip: padding-box; }
}

/* Clientes es un buscador, así que el campo manda: ancho, centrado y grande.
   No hay botón de alta a propósito — un cliente nace al darle cita, no antes. */
.clientes__buscador-fila { margin: 0.2rem 0 1rem; }

.clientes__buscador {
  width: 100%;
  max-width: 34rem;
  padding: 0.65rem 0.9rem;
  font-size: 1rem;
}

.clientes__lista {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
  margin: 0;
  padding: 0;
  list-style: none;
  max-width: 46rem;
}

/* Cada resultado es un botón entero, no una fila con un enlace dentro: se
   pulsa en cualquier parte, que es lo que se espera cuando lo que hay debajo
   es una ficha. */
.clientes__ficha {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 0.1rem 0.8rem;
  width: 100%;
  padding: 0.6rem 0.85rem;
  border: 1px solid var(--borde);
  border-radius: var(--radio);
  background: var(--superficie);
  color: inherit;
  font: inherit;
  text-align: left;
  cursor: pointer;
}

.clientes__ficha:hover { background: #f8f9fb; }

.clientes__nombre { font-weight: 600; }

.clientes__datos {
  grid-column: 1;
  color: var(--texto-tenue);
  font-size: 0.82rem;
  font-variant-numeric: tabular-nums;
}

/* A la derecha y en las dos filas: es el dato que se compara de un vistazo
   entre varios resultados. */
.clientes__citas {
  grid-column: 2;
  grid-row: 1 / span 2;
  align-self: center;
  color: var(--texto-tenue);
  font-size: 0.78rem;
  white-space: nowrap;
}

.clientes__pie {
  margin: 0.8rem 0 0;
  color: var(--texto-tenue);
  font-size: 0.8rem;
}

/* El icono de la cabecera de sección: el trazo suelto, sin pastilla detrás.
   El cuadrado de fondo pesaba más que el propio icono y competía con el
   título, que es lo que se tiene que leer primero. */
.seccion__icono {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.8rem;
  height: 1.8rem;
  flex: 0 0 auto;
  color: var(--marca);
}

.seccion__glifo { width: 1.5rem; height: 1.5rem; display: block; }

.tabla {
  width: 100%;
  background: var(--superficie);
  border: 1px solid var(--borde);
  border-radius: var(--radio-tarjeta);
  box-shadow: var(--sombra-tarjeta);
  /* Separate y no collapse: con collapse el navegador ignora el redondeo de
     las esquinas y la tabla vuelve a salir cuadrada. */
  border-collapse: separate;
  border-spacing: 0;
  overflow: hidden;
  font-size: 0.85rem;
}

.tabla th,
.tabla td {
  padding: 0.5rem 0.7rem;
  border-bottom: 1px solid var(--borde-suave);
  text-align: left;
}

.tabla th {
  color: var(--texto-tenue);
  font-size: 0.75rem;
  text-transform: uppercase;
  letter-spacing: 0.03em;
}

.tabla tbody tr { cursor: pointer; }
.tabla tbody tr:hover { background: #f8f9fb; }
.tabla__fila--inactiva { opacity: 0.55; }

.etiqueta {
  display: inline-block;
  padding: 0.05rem 0.4rem;
  background: var(--borde-suave);
  border-radius: 999px;
  font-size: 0.72rem;
}

/* ---------- Selector Día/Semana/Mes ---------- */

.dia__modos {
  display: flex;
  gap: 0.15rem;
  padding: 0.15rem;
  background: var(--fondo);
  border: 1px solid var(--borde);
  border-radius: var(--radio);
}

.dia__modo {
  padding: 0.3rem 0.6rem;
  border: 0;
  border-radius: 4px;
  background: none;
  color: var(--texto-tenue);
  font: inherit;
  font-size: 0.82rem;
  cursor: pointer;
}

.dia__modo:hover { color: var(--texto); }

.dia__modo--activo {
  background: var(--superficie);
  color: var(--texto);
  font-weight: 600;
  box-shadow: var(--sombra);
}

/* ---------- Vista semana ---------- */

.semana {
  display: flex;
  flex: 1;
  min-width: 0;
  overflow: auto;
  background: var(--superficie);
}

.semana__dia {
  flex: 1 0 160px;
  min-width: 140px;
  padding: 0.5rem;
  border-right: 1px solid var(--borde-suave);
}

.semana__dia--hoy { background: #fafbfc; }

.semana__cabecera {
  display: flex;
  align-items: baseline;
  gap: 0.35rem;
  width: 100%;
  margin-bottom: 0.5rem;
  padding: 0.3rem 0.2rem;
  border: 0;
  border-bottom: 2px solid var(--borde-suave);
  background: none;
  font: inherit;
  text-align: left;
  cursor: pointer;
}

.semana__dia--hoy .semana__cabecera { border-bottom-color: var(--acento); }

.semana__nombre {
  color: var(--texto-tenue);
  font-size: 0.75rem;
  text-transform: uppercase;
}

.semana__numero { font-weight: 700; }

.semana__lista { display: flex; flex-direction: column; }

.semana__evento {
  position: relative;
  display: flex;
  overflow: hidden;
  margin-bottom: 0.35rem;
  background: var(--superficie);
  border: 2px solid var(--borde);
  border-radius: var(--radio);
  cursor: pointer;
}

.semana__evento:hover { filter: brightness(0.97); }

/* En escritorio la semana son siete columnas estrechas: ahí solo caben la hora
   y el trámite, y en renglones separados. Las otras dos líneas se dibujan
   igual —el JS no sabe de anchos— y aparecen en el móvil, donde la semana es
   una lista y hay sitio. */
.semana__linea { display: block; margin: 0; }

.semana__quien,
.semana__cliente { display: none; }

.semana__vacio { margin: 0; color: var(--texto-tenue); font-size: 0.78rem; }

/* ---------- Vista mes ---------- */

.mes {
  flex: 1;
  min-width: 0;
  overflow: auto;
  padding: 0.6rem;
  background: var(--superficie);
}

/* `minmax(0, 1fr)` y no `1fr` a secas: `1fr` es en realidad `minmax(auto, 1fr)`,
   así que una celda con un texto largo que no parte —el nombre de un festivo—
   ensancha su columna y deja las otras seis estrechas. Las siete tienen que
   medir lo mismo pase lo que pase dentro. */
.mes__cabecera-dias {
  display: grid;
  grid-template-columns: repeat(7, minmax(0, 1fr));
  margin-bottom: 0.3rem;
}

.mes__nombre-dia {
  padding: 0.3rem;
  color: var(--texto-tenue);
  font-size: 0.75rem;
  text-align: center;
  text-transform: uppercase;
}

.mes__rejilla {
  display: grid;
  grid-template-columns: repeat(7, minmax(0, 1fr));
  gap: 1px;
  background: var(--borde-suave);
  border: 1px solid var(--borde-suave);
}

.mes__celda {
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
  min-height: 90px;
  padding: 0.3rem;
  border: 0;
  background: var(--superficie);
  font: inherit;
  text-align: left;
  cursor: pointer;
}

.mes__celda:hover { background: #fafbfc; }
.mes__celda--fuera { background: var(--fondo); color: var(--texto-tenue); }

.mes__celda--hoy .mes__numero {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.4em;
  height: 1.4em;
  background: var(--acento);
  border-radius: 50%;
  color: #fff;
}

.mes__numero { font-size: 0.8rem; font-weight: 600; }
.mes__chips { display: flex; flex-direction: column; gap: 0.15rem; }

.mes__chip {
  overflow: hidden;
  padding: 0.05rem 0.3rem;
  border-left: 3px solid var(--color-empleado, var(--borde));
  border-radius: 3px;
  background: var(--borde-suave);
  color: var(--texto);
  font-size: 0.68rem;
  text-overflow: ellipsis;
  white-space: nowrap;
  cursor: pointer;
}

.mes__mas { color: var(--texto-tenue); font-size: 0.66rem; }

/* ---------- Mis firmas ---------- */

.firmas { flex: 1; min-width: 0; overflow: auto; padding: 1rem; }

.firmas__grupo { margin-bottom: 1.4rem; }

.firmas__titulo-grupo {
  margin: 0 0 0.5rem;
  font-size: 0.8rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--texto-tenue);
}

.firmas__fecha {
  margin: 0.8rem 0 0.4rem;
  font-size: 0.82rem;
  font-weight: 600;
  text-transform: capitalize;
}

.firmas__vacio { margin: 0; color: var(--texto-tenue); }

.firmas__tarjeta {
  position: relative;
  display: flex;
  overflow: hidden;
  margin-bottom: 0.5rem;
  background: var(--superficie);
  border: 2px solid var(--borde);
  border-radius: var(--radio);
  box-shadow: var(--sombra);
  cursor: pointer;
}

.firmas__tarjeta:hover { filter: brightness(0.97); }

/* ---------- Vista recepción ----------
   Pensada para leerse de pie y a distancia desde el mostrador, así que todo va
   un punto más grande que en el resto de la aplicación. Sin ningún elemento
   pulsable: es una pantalla para mirar, no para usar. */

.recepcion { flex: 1; min-width: 0; overflow: auto; padding: 1rem; }

.recepcion__rejilla {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: 0.9rem;
}

.recepcion__persona {
  padding: 1rem 1.1rem;
  background: var(--superficie);
  border: 1px solid var(--borde);
  /* La franja de la izquierda sigue siendo el color de la persona, no el
     morado de marca: identidad de empleado (principio 5). */
  border-left: 6px solid var(--color-empleado, var(--borde));
  border-radius: var(--radio-tarjeta);
  box-shadow: var(--sombra-tarjeta);
}

.recepcion__cabecera {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin-bottom: 0.6rem;
  padding-bottom: 0.5rem;
  border-bottom: 1px solid var(--borde-suave);
}

.recepcion__nombre { font-size: 1.15rem; font-weight: 700; }

.recepcion__libre {
  margin: 0;
  padding: 0.6rem 0;
  color: var(--texto-tenue);
  font-size: 1.1rem;
}

.recepcion__etiqueta,
.recepcion__etiquetaBloque {
  margin: 0 0 0.25rem;
  color: var(--texto-tenue);
  font-size: 0.72rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.06em;
}

.recepcion__proximas { margin-top: 0.7rem; }

.recepcion__cita {
  position: relative;
  display: flex;
  overflow: hidden;
  margin-bottom: 0.4rem;
  background: var(--superficie);
  border: 2px solid var(--borde);
  border-radius: var(--radio);
}

/* La cita de ahora mismo es la que se lee desde lejos; las siguientes van en
   tamaño normal, que son contexto y no lo que se pregunta al entrar. */
.recepcion__ahora .recepcion__cita .cita__hora { font-size: 1rem; }
.recepcion__ahora .recepcion__cita .cita__concepto { font-size: 1.15rem; }
.recepcion__ahora .recepcion__cita { border-width: 3px; }

.recepcion__cita .cita__contenido { padding: 0.4rem 0.6rem; font-size: 0.85rem; }

/* ---------- Buscador único ---------- */

.buscador { position: relative; }

.buscador__campo {
  width: min(260px, 30vw);
  padding: 0.35rem 0.5rem;
  font-size: 0.85rem;
}

.buscador__resultados {
  position: absolute;
  top: calc(100% + 4px);
  left: 0;
  z-index: 20;
  width: min(420px, 80vw);
  max-height: 60vh;
  overflow-y: auto;
  background: var(--superficie);
  border: 1px solid var(--borde);
  border-radius: var(--radio);
  box-shadow: 0 10px 30px rgba(16, 24, 40, 0.18);
}

.buscador__estado {
  margin: 0;
  padding: 0.7rem 0.8rem;
  color: var(--texto-tenue);
  font-size: 0.82rem;
}

.buscador__resultado {
  display: block;
  width: 100%;
  padding: 0.5rem 0.8rem;
  border: 0;
  border-bottom: 1px solid var(--borde-suave);
  background: none;
  font: inherit;
  text-align: left;
  cursor: pointer;
}

.buscador__resultado:hover { background: #f8f9fb; }
.buscador__resultado:last-child { border-bottom: 0; }

.buscador__fecha {
  display: block;
  color: var(--texto-tenue);
  font-size: 0.74rem;
  font-variant-numeric: tabular-nums;
}

.buscador__concepto { display: block; font-weight: 600; font-size: 0.85rem; }
.buscador__cliente { display: block; color: var(--texto-tenue); font-size: 0.78rem; }

/* ---------- Festivos ----------
   Color propio, distinto del ámbar de «aplazada» y del rojo de «cancelada»:
   un festivo no es un estado excepcional de una cita, es una propiedad del día.
   Por eso tiñe el fondo de la celda o la columna, nunca el bloque de una cita. */

.festivo-etiqueta {
  display: inline-block;
  overflow: hidden;
  padding: 0.05rem 0.4rem;
  background: var(--marca-suave);
  border-radius: 999px;
  color: var(--marca);
  font-size: 0.7rem;
  font-weight: 600;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* El cumpleaños se distingue del festivo por color: los dos son «hoy pasa algo
   con este día», pero no son la misma clase de cosa y conviene no confundirlos
   de un vistazo. */
.festivo-etiqueta--cumple {
  background: #fdf0d5;
  color: #8a5a00;
}

.festivo-etiqueta--bloque {
  display: block;
  margin: 0.15rem 0;
  border-radius: 3px;
  font-weight: 500;
  text-align: left;
}

.mes__celda--festivo { background: var(--marca-tenue); }
.mes__celda--festivo:hover { background: var(--marca-suave); }
.semana__dia--festivo { background: var(--marca-tenue); }

/* ---------- Ausencias ---------- */

.ausencias__acciones { display: flex; align-items: center; gap: 0.5rem; }

.ausencias__aviso {
  margin-bottom: 1rem;
  padding: 0.6rem 0.8rem;
  background: var(--aplazada-fondo);
  border: 1px solid var(--aplazada-borde);
  border-radius: var(--radio);
  color: #7c2d12;
  font-size: 0.85rem;
}

.saldos {
  display: flex;
  flex-wrap: wrap;
  gap: 0.7rem;
  margin-bottom: 1.4rem;
}

.saldo {
  flex: 0 1 190px;
  padding: 0.85rem 1rem;
  background: var(--superficie);
  border: 1px solid var(--borde);
  border-radius: var(--radio-tarjeta);
  box-shadow: var(--sombra-tarjeta);
}

.saldo__tipo {
  margin: 0;
  color: var(--texto-tenue);
  font-size: 0.78rem;
  text-transform: uppercase;
  letter-spacing: 0.03em;
}

/* El número grande en morado de marca y en serif: es el dato que se va a
   buscar en esta pantalla, y así se ve desde lejos. */
.saldo__restantes {
  margin: 0.1rem 0;
  color: var(--marca);
  font-size: 2.1rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  line-height: 1.1;
}

.saldo__detalle { margin: 0 0 0.4rem; color: var(--texto-tenue); font-size: 0.76rem; }

.ausencia--pendiente { background: var(--borde-suave); }
.ausencia--aprobada { background: #dcfce7; color: #14532d; }
.ausencia--rechazada { background: var(--cancelada-fondo); color: #7f1d1d; }

.ausencias__solape { color: var(--aplazada-borde); font-size: 0.8rem; }

/* El desvío del formulario de cita: «¿No es una cita? Marcar que no estás».
   Discreto y arriba del todo, donde se lee antes de empezar a rellenar. */
.formulario__desvio {
  margin: 0 0 0.9rem;
  padding-bottom: 0.7rem;
  border-bottom: 1px solid var(--borde-suave);
}

/* Un botón que se lee como un enlace: la acción no es la principal del
   formulario, pero sigue siendo una acción y tiene que ser pulsable con el
   teclado. */
.enlace {
  border: none;
  background: none;
  padding: 0;
  font: inherit;
  color: var(--marca);
  text-decoration: underline;
  cursor: pointer;
}

.enlace:hover { color: var(--marca-clara); }

/* La casilla que decide si la ausencia es de días o de un rato. Va destacada
   sobre fondo suave porque cambia el resto del formulario: no es una opción
   más, es la bifurcación. */
.ausencias__modo {
  background: var(--marca-tenue);
  border: 1px solid var(--borde-suave);
  border-radius: var(--radio);
  padding: 0.6rem 0.8rem;
  margin: 0.2rem 0 0.9rem;
}

.ausencias__modo .campo { margin: 0; }

/* Saldos del equipo, en rejilla como Recepción.

   En lista —una persona debajo de otra— comparar el saldo de dos personas
   obligaba a subir y bajar, que es justo lo que se viene a hacer a esta
   pantalla. En rejilla caben tres o cuatro de un vistazo. */
.ausencias__equipo {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
  gap: 0.9rem;
  /* `stretch` y no `start`: quien tiene cinco tipos de ausencia hacía su
     tarjeta más alta que la de al lado y dejaba un escalón. Todas ocupan lo
     mismo y la fila queda recta. */
  align-items: stretch;
  margin-bottom: 1.2rem;
}

.ausencias__persona {
  padding: 0.9rem 1rem;
  background: var(--superficie);
  border: 1px solid var(--borde);
  /* La franja del color de esa persona, igual que en Recepción y en su columna
     de la agenda: es lo que dice de quién es el bloque (principio 5). */
  border-left: 6px solid var(--color-empleado, var(--borde));
  border-radius: var(--radio-tarjeta);
  box-shadow: var(--sombra-tarjeta);
}

.ausencias__persona-nombre {
  margin: 0 0 0.6rem;
  font-size: 0.95rem;
  font-weight: 600;
  color: var(--texto);
}

/* Dentro de la tarjeta de una persona las cajas de saldo van más estrechas y
   sin sombra: ya están dentro de una tarjeta, y repetir el relieve convierte
   el bloque en un montón de cajas dentro de cajas. */
.ausencias__persona .saldos {
  margin-bottom: 0;
  gap: 0.5rem;
}

.ausencias__persona .saldo {
  flex: 1 1 118px;
  padding: 0.55rem 0.7rem;
  box-shadow: none;
  background: var(--marca-tenue);
}

.ausencias__persona .saldo__restantes { font-size: 1.5rem; }
.ausencias__persona .saldo__tipo { font-size: 0.7rem; }

/* El «Ver más» de las listas plegadas: discreto, porque no es la acción
   principal de la pantalla — es una salida por si hace falta. */
.ausencias__vermas {
  margin-top: 0.2rem;
  font-size: 0.85rem;
}

/* Bloqueo de columna de quien no está disponible. Va por debajo de las citas
   (z-index 0 frente al 1 de .cita) a propósito: si alguien tiene una cita el
   día que libra hay que verla para poder moverla, no taparla. */
.columna__ausente {
  position: absolute;
  inset: 0;
  z-index: 0;
  display: flex;
  align-items: flex-start;
  justify-content: center;
  padding-top: 0.6rem;
  background: repeating-linear-gradient(
    45deg,
    rgba(107, 114, 128, 0.09) 0 8px,
    rgba(107, 114, 128, 0.02) 8px 16px
  );
  color: var(--texto-tenue);
  font-size: 0.75rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
}

.columna--ausente .columna__nombre { color: var(--texto-tenue); }

/* ---------------------------------------------------------------------
   Columna encogida

   Una tira de 44 px con las iniciales y un punto por cita. El ancho es fijo
   y pequeño a propósito: si creciera con el contenido dejaría de cumplir su
   función, que es devolverle sitio a las columnas que sí tienen trabajo.
   --------------------------------------------------------------------- */
.columna--encogida {
  min-width: 44px;
  max-width: 44px;
  flex: 0 0 44px;
  cursor: pointer;
}

/* Sin fondo propio: una columna encogida es la misma columna, solo que
   estrecha. Teñirla la convertía en «otra cosa» y rompía la lectura de la
   rejilla, que es una superficie continua con sus líneas de hora. */

.columna--encogida .columna__cabecera {
  justify-content: center;
  padding-left: 0;
  padding-right: 0;
}

.columna__iniciales {
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  color: var(--texto-tenue);
}

/* El punto de cada cita, a la altura de su hora. Centrado y pequeño: no dice
   qué hay, solo que hay algo — para eso está desplegarla. */
.columna__marca {
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  width: 8px;
  height: 8px;
  border-radius: 50%;
  z-index: 1;
}

/* Ausencia de unas horas: médico, una gestión, llegar tarde.

   Rayado como la columna de quien no viene en todo el día —el ojo tiene que
   leer «aquí no hay nadie» sin detenerse— pero **en otro tono**: el día
   entero va en gris y un rato suelto, en ámbar. Son dos cosas distintas y
   conviene no confundirlas de lejos: una es «hoy no cuentes con esta
   persona», la otra «a esta hora no, pero el resto del día sí».

   Nada del lenguaje de una cita: ni franja de color de persona, ni fondo
   blanco, ni borde continuo. No es una cita, es su ausencia. */
.ausencia-corta {
  position: absolute;
  left: 0;
  right: 2px;
  z-index: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  border-radius: 6px;
  background: repeating-linear-gradient(
    45deg,
    rgba(180, 83, 9, 0.16) 0 8px,
    rgba(180, 83, 9, 0.05) 8px 16px
  );
  border: 1px dashed rgba(180, 83, 9, 0.45);
}

/* La ficha del hueco: de quién, cuándo y por qué, en ese orden — que es el
   orden en que se pregunta al mirar la agenda. */
.ficha-ausencia {
  padding: 0.9rem 1rem;
  background: var(--aplazada-fondo);
  border-left: 4px solid var(--aplazada-borde);
  border-radius: 0 var(--radio) var(--radio) 0;
  margin-bottom: 1rem;
}

.ficha-ausencia__quien {
  margin: 0;
  font-size: 1.05rem;
  font-weight: 600;
  color: var(--texto);
}

.ficha-ausencia__cuando {
  margin: 0.2rem 0 0;
  color: var(--texto);
}

.ficha-ausencia__motivo {
  margin: 0.5rem 0 0;
  color: var(--aplazada-borde);
  font-weight: 600;
}

/* En la columna encogida es solo una banda: no cabe texto, y lo que hace falta
   saber a ese ancho es que a esa hora hay un hueco. No se pulsa — para eso se
   despliega la columna. */
.ausencia-corta--encogida {
  cursor: pointer;
  border-radius: 3px;
}

.ausencia-corta--encogida .ausencia-corta__texto { display: none; }

/* Se pulsa para ver de quién es y por qué. */
.ausencia-corta { cursor: pointer; }
.ausencia-corta:hover { border-color: var(--aplazada-borde); }

.ausencia-corta__texto {
  padding: 0 0.35rem;
  /* El mismo ámbar que ya marca una cita aplazada: es el color que en esta
     aplicación significa «atención, esto no va como lo normal». */
  color: var(--aplazada-borde);
  font-size: 0.68rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.cita { z-index: 1; }

/* ---------- Diálogo ---------- */

.dialogo {
  width: min(var(--ancho-dialogo, 560px), calc(100vw - 2rem));
  max-height: calc(100vh - 3rem);
  padding: 0;
  border: 1px solid var(--borde);
  border-radius: 10px;
  box-shadow: 0 10px 30px rgba(16, 24, 40, 0.18);
}

.dialogo::backdrop { background: rgba(17, 24, 39, 0.45); }

.dialogo__cabecera {
  position: sticky;
  top: 0;
  z-index: 1;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.8rem 1rem;
  background: var(--superficie);
  border-bottom: 1px solid var(--borde);
}

.dialogo__titulo { margin: 0; font-size: 1rem; }
.dialogo__cuerpo { padding: 1rem; }
.dialogo__cargando { margin: 0; color: var(--texto-tenue); }
.dialogo__error { margin: 0; color: var(--cancelada-borde); }

/* ---------- Formulario ---------- */

.formulario__rejilla {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0 0.8rem;
}

.campo--ancho { grid-column: 1 / -1; }

.campo--casilla {
  display: flex;
  align-items: flex-start;
  gap: 0.5rem;
  margin-bottom: 0.6rem;
  font-size: 0.85rem;
  line-height: 1.35;
}

/* La casilla se alinea con la **primera línea** del texto, no con el centro
   del bloque. Centrada, en cuanto una descripción ocupaba dos o tres
   renglones —los permisos, en un móvil, casi todos— cada casilla quedaba a
   una altura distinta y la lista se leía a saltos. */
.campo--casilla input {
  margin: 0.15rem 0 0;
  flex: 0 0 auto;
}

textarea.campo__control { resize: vertical; font: inherit; }

.formulario__grupo {
  margin: 0.4rem 0 1rem;
  padding: 0.7rem 0.8rem;
  border: 1px solid var(--borde);
  border-radius: var(--radio);
}

.formulario__grupo legend { padding: 0 0.3rem; font-size: 0.8rem; font-weight: 600; }

.formulario__pista {
  margin: 0 0 0.6rem;
  color: var(--texto-tenue);
  font-size: 0.78rem;
}

.participante {
  display: grid;
  grid-template-columns: 1fr 1fr auto;
  gap: 0.2rem 0.4rem;
  margin-bottom: 0.5rem;
}

.contacto {
  display: grid;
  grid-template-columns: 1.4fr 1fr auto;
  gap: 0.4rem;
  margin-bottom: 0.4rem;
}

/* Los trámites de más de una cita. El primero no vive aquí: es el desplegable
   de arriba, el principal, del que salen la duración y la firma. Estas son las
   añadidas, y por eso van sangradas y con su aspa para quitarlas. */
.gestiones { margin-top: 0.4rem; }

.gestion {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 0.4rem;
  margin-bottom: 0.4rem;
}

.gestiones__anadir { margin-top: 0.2rem; }

/* Los idiomas de atención ocupan la fila entera bajo los desplegables. */
.participante > [data-idiomas] { grid-column: 1 / -1; }

.participante__idiomas {
  color: var(--texto-tenue);
  font-size: 0.74rem;
}

.casillas-idioma {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
  gap: 0 0.6rem;
}

/* Va sobre el morado de la cabecera, así que el recuadro es blanco
   translúcido y la letra blanca. Esta es la ÚNICA definición del selector:
   antes había otra más arriba y esta, al venir después, la pisaba y lo
   dejaba en blanco sobre blanco. */
.cabecera__idioma {
  padding: 0.3rem 0.5rem;
  border: 1px solid rgba(255, 255, 255, 0.4);
  border-radius: var(--radio);
  background: rgba(255, 255, 255, 0.14);
  color: #fff;
  font: inherit;
  font-size: 0.8rem;
}

.cabecera__idioma:hover { background: rgba(255, 255, 255, 0.24); }

/* Atribución que exigen las condiciones de uso de la fuente de festivos. */
.catalogo__fuente {
  margin: 0.5rem 0 0;
  color: var(--texto-tenue);
  font-size: 0.76rem;
}

.formulario__errores {
  margin-bottom: 0.8rem;
  padding: 0.6rem 0.8rem;
  background: var(--cancelada-fondo);
  border: 1px solid var(--cancelada-borde);
  border-radius: var(--radio);
  color: #7f1d1d;
  font-size: 0.82rem;
}

.formulario__errores p { margin: 0 0 0.3rem; }
.formulario__errores ul { margin: 0; padding-left: 1.1rem; }

.formulario__pie {
  display: flex;
  justify-content: flex-end;
  gap: 0.5rem;
  padding-top: 0.6rem;
  border-top: 1px solid var(--borde-suave);
}

.boton--auto { width: auto; }

/* ---------- Ficha ---------- */

.ficha {
  display: grid;
  grid-template-columns: minmax(110px, auto) 1fr;
  gap: 0.35rem 0.9rem;
  margin: 0 0 1rem;
  font-size: 0.86rem;
}

.ficha dt { color: var(--texto-tenue); }
.ficha dd { margin: 0; }
.ficha__lista { margin: 0; padding-left: 1.1rem; }
.ficha__tenue { color: var(--texto-tenue); font-size: 0.78rem; }

.ficha__estado {
  padding: 0.1rem 0.5rem;
  border-radius: 999px;
  background: var(--borde-suave);
  text-transform: capitalize;
}

.ficha__estado--aplazada { background: var(--aplazada-fondo); color: #7c2d12; }
.ficha__estado--cancelada { background: var(--cancelada-fondo); color: #7f1d1d; }
/* En negativo, al lado del estado: se leen juntos —«confirmada» y «URGENTE»—
   y tienen que distinguirse en un golpe de vista como dos cosas distintas. */
.ficha__estado--urgente { background: var(--urgente-borde); color: #fff; }

.ficha__historial h3 {
  margin: 0 0 0.5rem;
  font-size: 0.8rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--texto-tenue);
}

.historial {
  margin: 0 0 1rem;
  padding: 0;
  list-style: none;
  font-size: 0.8rem;
}

.historial__linea {
  padding: 0.4rem 0;
  border-top: 1px solid var(--borde-suave);
}

.historial__campo { font-weight: 600; }

.historial__valores {
  display: block;
  overflow-wrap: anywhere;
}

/* ---------- Campanita de avisos ---------- */

.campanita { position: relative; display: inline-flex; }

.campanita__boton {
  position: relative;
  border: 1px solid transparent;
  background: none;
  cursor: pointer;
  font-size: 1.05rem;
  line-height: 1;
  padding: 0.35rem 0.4rem;
  border-radius: var(--radio);
}

.campanita__boton:hover { border-color: rgba(255, 255, 255, 0.35); }

/* En la cabecera la campana va en blanco, del mismo grosor de trazo que el
   resto de iconos de la aplicación. */
.campanita__icono {
  display: block;
  width: 1.35rem;
  height: 1.35rem;
  color: #fff;
}

/* El contador es el punto de aviso de las referencias: ámbar, pequeño y
   pegado a la campana. Ámbar y no rojo porque no es un error, es que hay
   algo por leer. */
.campanita__cuenta {
  position: absolute;
  top: 1px;
  right: 0;
  min-width: 15px;
  padding: 0 3px;
  border-radius: 9px;
  background: #f5a524;
  color: #3d2600;
  font-size: 0.62rem;
  font-weight: 700;
  line-height: 15px;
  text-align: center;
}

/* El color se declara aquí a propósito. El panel cuelga de la cabecera, y la
   cabecera pinta su texto de blanco; todo lo que no traiga color propio lo
   hereda, así que el titular del aviso salía blanco sobre blanco y no se veía
   —solo se leían la cita y la hora, que sí llevan color—. */
.campanita__panel {
  position: absolute;
  top: calc(100% + 6px);
  right: 0;
  z-index: 30;
  width: 320px;
  color: var(--texto);
  max-height: 60vh;
  overflow-y: auto;
  background: var(--superficie);
  border: 1px solid var(--borde);
  border-radius: var(--radio);
  box-shadow: var(--sombra);
}

.campanita__cabecera {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  padding: 0.5rem 0.7rem;
  border-bottom: 1px solid var(--borde-suave);
  font-weight: 600;
  font-size: 0.85rem;
}

.campanita__lista { list-style: none; margin: 0; padding: 0; }

.campanita__aviso {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 0.5rem;
  padding: 0.55rem 0.7rem;
  border-bottom: 1px solid var(--borde-suave);
  font-size: 0.83rem;
}

/* Lo no leído se distingue por peso y por una marca al margen, no solo por
   color: quien no lo perciba tiene que poder verlo igual. */
.campanita__aviso--nuevo {
  border-left: 3px solid var(--acento);
  font-weight: 600;
}

.campanita__texto { margin: 0; }
.campanita__cita { margin: 0.15rem 0 0; color: var(--texto-tenue); }

.campanita__cuando {
  margin: 0.15rem 0 0;
  color: var(--texto-tenue);
  font-size: 0.75rem;
  font-weight: 400;
}

.campanita__leer {
  border: 1px solid var(--borde);
  background: var(--superficie);
  border-radius: var(--radio);
  cursor: pointer;
  padding: 0.1rem 0.35rem;
  color: var(--texto-tenue);
}

.campanita__vacio {
  padding: 0.9rem 0.7rem;
  color: var(--texto-tenue);
  font-size: 0.85rem;
}

/* ---------- Perfil ---------- */

.perfil__formulario {
  display: flex;
  flex-direction: column;
  gap: 1rem;
  /* 460px bastaba solo para los ajustes de correo; con los datos propios, la
     información de solo lectura y la foto necesita el mismo ancho que el
     resto de formularios de administración. */
  max-width: 640px;
}

/* «Mis datos» y «Avisos por correo» son cosas distintas y se ven como tal:
   dos tarjetas separadas, no una sola columna larga con líneas divisorias. */
.perfil__tarjeta {
  background: var(--superficie);
  border: 1px solid var(--borde);
  border-radius: var(--radio-tarjeta);
  box-shadow: var(--sombra-tarjeta);
  padding: 1.1rem 1.2rem;
}

.perfil__foto-fila {
  display: flex;
  align-items: center;
  gap: 1rem;
  margin-bottom: 0.4rem;
}

.perfil__avatar {
  width: 4.5rem;
  height: 4.5rem;
  flex: 0 0 auto;
  border-radius: 50%;
  background: var(--borde-suave) center/cover no-repeat;
  border: 1px solid var(--borde);
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--texto-tenue);
  font-size: 1.3rem;
  font-weight: 700;
}

.perfil__foto-acciones { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem; }

/* El campo de fichero real va escondido detrás de un botón normal: el que da
   el navegador por defecto no se puede vestir con el resto de la interfaz. */
.perfil__foto-boton { position: relative; cursor: pointer; }
.perfil__foto-boton input[type="file"] { position: absolute; inset: 0; opacity: 0; cursor: pointer; }

.perfil__foto-acciones .formulario__pista,
.perfil__foto-acciones .dialogo__error { flex-basis: 100%; margin: 0.2rem 0 0; }

.perfil__info {
  margin: 0 0 0.6rem;
}

.perfil__info dd { margin-bottom: 0.5rem; }

.perfil__seccion { margin: 0 0 0.3rem; font-size: 1rem; }

.perfil__nota {
  margin: 0 0 0.6rem;
  color: var(--texto-tenue);
  font-size: 0.85rem;
}

.perfil__ajustes {
  border: 0;
  margin: 0.4rem 0 0;
  padding: 0;
}

/* Sin activar, los ajustes se ven pero no se tocan: dejan claro qué se podrá
   configurar sin dar a entender que ya está funcionando. */
.perfil__ajustes[disabled] { opacity: 0.5; }

.campo--interruptor {
  flex-direction: row;
  align-items: center;
  gap: 0.5rem;
}

.perfil__aviso {
  margin: 0.5rem 0;
  min-height: 1.2em;
  font-size: 0.85rem;
}

/* ---------- Canales de aviso al cliente ---------- */

/* Correo y extensión, en su propia fila bajo el nombre y el teléfono: son
   datos del cliente que no siempre se tienen a mano al dar la cita, así que no
   deben competir por sitio con los dos que sí. */
.contacto__extra {
  grid-column: 1 / -1;
  display: grid;
  grid-template-columns: 2fr 1fr;
  gap: 0.4rem;
}

.contacto__canales {
  grid-column: 1 / -1;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.6rem;
  margin: -0.2rem 0 0.4rem;
  font-size: 0.8rem;
}

.contacto__canalesEtiqueta { color: var(--texto-tenue); }

.contacto__canal {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
  cursor: pointer;
}

.ficha__avisos { margin-top: 0.8rem; }

.avisos { list-style: none; margin: 0; padding: 0; font-size: 0.85rem; }

.avisos__linea {
  padding: 0.4rem 0.6rem;
  border-left: 3px solid var(--borde);
  margin-bottom: 0.3rem;
  background: #f8f9fb;
}

.avisos__linea--enviado { border-left-color: #15803d; }

/* Lo que no ha salido se marca como lo que es. El texto ya lo dice («NO
   enviado»), el color solo acompaña: no puede ser la única señal. */
.avisos__linea--fallido,
.avisos__linea--no_configurado {
  border-left-color: var(--cancelada-borde);
  background: var(--cancelada-fondo);
}

/* ---------- Ajustes del despacho ---------- */

.ajustes__caja {
  background: var(--superficie);
  border: 1px solid var(--borde);
  border-radius: var(--radio-tarjeta);
  box-shadow: var(--sombra-tarjeta);
  padding: 1.1rem 1.2rem;
  max-width: 640px;
}

.ajustes__dias {
  border: 0;
  padding: 0;
  margin: 0 0 1rem;
  display: flex;
  flex-wrap: wrap;
  gap: 0.7rem;
}

.ajustes__dia {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  font-size: 0.87rem;
  cursor: pointer;
}

.ajustes__rejilla {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: 0 0.8rem;
}

.ajustes__estadoCanal {
  margin-left: 0.4rem;
  padding: 0.05rem 0.4rem;
  border-radius: 9px;
  font-size: 0.7rem;
  text-transform: none;
}

.ajustes__estadoCanal--listo { background: #dcfce7; color: #15803d; }
.ajustes__estadoCanal--pendiente { background: var(--cancelada-fondo); color: var(--cancelada-borde); }

/* El porqué de que un canal no esté listo va pegado a su casilla, con sangría,
   para que se lea como una nota de ese canal y no del bloque entero. */
.ajustes__motivo {
  margin: -0.5rem 0 0.8rem 1.6rem;
  color: var(--cancelada-borde);
}

.ajustes__proveedor {
  border: 1px solid var(--borde-suave);
  border-radius: var(--radio);
  padding: 0.7rem 0.9rem 0.2rem;
  margin: 0 0 1rem;
}

.ajustes__proveedor legend {
  padding: 0 0.35rem;
  font-weight: 600;
  font-size: 0.9rem;
}

/* ---------- Sala de una cita (ficha) ---------- */

.ficha__salas { margin-top: 1.1rem; }

.ficha__salas h3 {
  margin: 0 0 0.4rem;
  font-size: 0.9rem;
}

.salas__opciones {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-bottom: 0.5rem;
}

.salas__opcion {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  border: 1px solid var(--borde);
  border-radius: var(--radio);
  padding: 0.3rem 0.6rem;
  cursor: pointer;
  font-size: 0.87rem;
}

.salas__opcion:hover { background: #f8f9fb; }

/* ---------- Menú de descarga ---------- */

.descarga { position: relative; display: inline-flex; }

.descarga__menu {
  position: absolute;
  top: calc(100% + 4px);
  right: 0;
  z-index: 30;
  min-width: 130px;
  background: var(--superficie);
  border: 1px solid var(--borde);
  border-radius: var(--radio);
  box-shadow: var(--sombra);
  overflow: hidden;
}

.descarga__opcion {
  display: block;
  width: 100%;
  padding: 0.45rem 0.8rem;
  border: 0;
  background: none;
  font: inherit;
  text-align: left;
  cursor: pointer;
}

.descarga__opcion:hover { background: #f8f9fb; }

/* ---------- Ajustes por pestañas ---------- */

.ajustes__pestanas {
  display: flex;
  flex-wrap: wrap;
  gap: 0.25rem;
  margin-bottom: 0.9rem;
  border-bottom: 1px solid var(--borde);
}

.ajustes__pestana {
  border: 1px solid transparent;
  border-bottom: 0;
  background: none;
  font: inherit;
  cursor: pointer;
  padding: 0.45rem 0.9rem;
  border-radius: var(--radio) var(--radio) 0 0;
  color: var(--texto-tenue);
  margin-bottom: -1px;
}

.ajustes__pestana:hover { color: var(--texto); }

.ajustes__pestana--activa {
  background: var(--superficie);
  border-color: var(--borde);
  color: var(--texto);
  font-weight: 600;
}

/* Dentro de un panel la primera sección ya no necesita separador: la pestaña
   es la que dice dónde empieza el bloque. */
.ajustes__panel > .perfil__seccion:first-child { margin-top: 0; }

.ajustes__pie {
  display: flex;
  align-items: center;
  gap: 1rem;
  margin-top: 1.2rem;
  padding-top: 0.9rem;
  border-top: 1px solid var(--borde-suave);
}

.ajustes__pie .perfil__aviso { margin: 0; flex: 1 1 auto; }

/* ---------- Asignar hueco y borrado de usuario ---------- */

.cita__asignar { margin-top: 0.35rem; }

.usuarios__color {
  display: flex;
  align-items: center;
  gap: 0.6rem;
}

.usuarios__color-muestra {
  width: 2.6rem;
  height: 2rem;
  padding: 0.15rem;
  flex: 0 0 auto;
}

.usuarios__color-muestra:disabled { opacity: 0.5; cursor: not-allowed; }

.usuarios__borrar {
  margin-top: 1.2rem;
  padding-top: 0.9rem;
  border-top: 1px solid var(--borde-suave);
}

/* Borrar es lo único que destruye datos: se distingue del resto de botones,
   pero sin gritar — no es la acción que se busca en esta pantalla. */
.usuarios__borrar-boton {
  border-color: var(--cancelada-borde);
  color: var(--cancelada-borde);
}

.usuarios__borrar-boton:hover { background: var(--cancelada-fondo); }

.usuarios__borrar [data-borrar-resultado] { margin-top: 0.7rem; }

/* ---------- Gráficos de estadísticas ---------- */

/* Con presencia, pero sin salirse: es el «de un vistazo» junto a la tabla,
   no una segunda tabla en forma de dibujo. Ancho tope para que en una
   pantalla ancha no se estire — eso era lo que hacía que una barra con un
   valor mucho más alto que el resto ocupara todo el largo del bloque. */
.grafico {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 1rem;
  flex: 0 1 320px;
  max-width: 320px;
}

/* El texto de dentro va en las mismas unidades que el viewBox del SVG
   (0 0 180 180): al crecer la caja crece todo el dibujo por igual, sin
   tocar aquí el tamaño de letra. */
.grafico__lienzo { width: 140px; height: 140px; flex: 0 0 auto; }
.grafico__cifra { font-size: 20px; font-weight: 700; fill: var(--texto); }
.grafico__pie { font-size: 8.5px; fill: var(--texto-tenue); }

.grafico__leyenda {
  flex: 1 1 9rem;
  margin: 0;
  padding: 0;
  list-style: none;
  font-size: 0.86rem;
}

.grafico__leyenda li {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.2rem 0;
}

.grafico__leyenda-nombre {
  flex: 1 1 auto;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.grafico__leyenda-valor {
  color: var(--texto-tenue);
  font-variant-numeric: tabular-nums;
  font-size: 0.8rem;
}

.grafico__muestra {
  width: 0.6rem;
  height: 0.6rem;
  border-radius: 2px;
  flex: 0 0 auto;
}

/* Barras: una rejilla de tres columnas de ancho fijo, no `1fr`. Con `1fr` la
   pista se estiraba a lo que quedase de la pantalla y una sola barra
   dominante acababa cruzando todo el bloque; con un ancho fijo, el más largo
   posible mide siempre lo mismo, esté la pantalla como esté. */
.grafico--barras {
  display: block;
  flex: 0 1 320px;
  max-width: 320px;
}

.grafico__fila {
  display: grid;
  grid-template-columns: minmax(5rem, 8rem) 9rem 1.8rem;
  align-items: center;
  gap: 0.5rem;
  padding: 0.25rem 0;
  font-size: 0.82rem;
}

.grafico__nombre {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* `--parte` es cuánto ocupa esta fila respecto de la mayor; los trozos de
   dentro se reparten ese ancho entre sí. */
.grafico__pista {
  display: flex;
  width: var(--parte);
  height: 0.75rem;
  overflow: hidden;
  border-radius: 3px;
}

.grafico__trozo { height: 100%; }

.grafico__valor {
  color: var(--texto-tenue);
  text-align: right;
  font-variant-numeric: tabular-nums;
  font-size: 0.8rem;
}

.grafico__leyenda-roles {
  display: flex;
  flex-wrap: wrap;
  gap: 0.7rem;
  margin: 0.5rem 0 0;
  color: var(--texto-tenue);
  font-size: 0.75rem;
}

.grafico__clave { display: flex; align-items: center; gap: 0.35rem; }

/* ---------- Anticipo del saldo al pedir una ausencia ---------- */

.saldo-previo {
  margin: 0.6rem 0;
  padding: 0.55rem 0.7rem;
  background: var(--borde-suave);
  border-radius: var(--radio);
  font-size: 0.84rem;
}

/* Pedir más días de los que quedan no se impide —puede haber un motivo, y
   quien aprueba decide—, pero se ve. */
.saldo-previo--pasado {
  background: var(--aplazada-fondo);
  color: var(--aplazada-borde);
}

/* ---------- Menú de columnas de la vista día ---------- */

.columnas__menu {
  width: 15rem;
  max-height: 60vh;
  padding: 0.6rem;
  overflow-y: auto;
}

.columnas__titulo {
  margin: 0.5rem 0 0.3rem;
  color: var(--texto-tenue);
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.03em;
}

.columnas__titulo:first-child { margin-top: 0; }

.columnas__opcion {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  margin: 0;
  padding: 0.2rem 0;
}

/* Cada persona del menú: su casilla a la izquierda y el botón de encoger a la
   derecha. Dos acciones distintas sobre la misma fila. */
.columnas__fila {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

.columnas__fila .columnas__opcion { flex: 1; min-width: 0; }

.columnas__encoger {
  flex: 0 0 auto;
  display: grid;
  place-items: center;
  width: 24px;
  height: 24px;
  padding: 0;
  border: 1px solid transparent;
  border-radius: 6px;
  background: none;
  color: var(--texto-tenue);
  cursor: pointer;
}

.columnas__encoger:hover { background: var(--marca-suave); color: var(--marca); }

/* Puesto: el botón se queda encendido, para saber quién está encogido sin
   tener que mirar la agenda que queda detrás del menú. */
.columnas__encoger--puesto {
  background: var(--marca-suave);
  border-color: var(--borde-campo);
  color: var(--marca);
}

/* La misma franja de color que identifica a esa persona en su columna: aquí
   sirve para reconocerla sin leer, igual que allí (principio 5). */
.columnas__punto {
  width: 0.6rem;
  height: 0.6rem;
  border-radius: 50%;
  flex: 0 0 auto;
}

/* ---------- Reglas de resumen por correo ---------- */

.perfil__regla {
  margin: 0.8rem 0;
  padding: 0.8rem;
  border: 1px solid var(--borde);
  border-radius: var(--radio);
}

.perfil__regla-barra {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.6rem;
  margin-bottom: 0.5rem;
}

.perfil__regla-barra .campo { margin: 0; }

.perfil__destino {
  display: flex;
  gap: 0.4rem;
  margin-bottom: 0.4rem;
}

.perfil__destino .campo__control { flex: 1 1 auto; }

/* ---------- Horario semanal ---------- */

.horario { display: grid; gap: 0.35rem; }

.horario__dia {
  display: grid;
  grid-template-columns: minmax(8rem, 1fr) auto auto auto minmax(10rem, auto);
  align-items: center;
  gap: 0.5rem;
}

.horario__casilla { margin: 0; }
.horario__hora { width: auto; }
.horario__separador { color: var(--texto-tenue); }
.horario__cadencia { width: auto; }

/* La tarde en su propia fila, a lo ancho y sangrada bajo el nombre del día:
   así se lee como «este día, además, por la tarde» y no como otro día más.
   El botón de añadirla ocupa ese mismo sitio mientras no la haya. */
.horario__anadir,
.horario__tarde { grid-column: 1 / -1; }

.horario__anadir {
  justify-self: start;
  margin-left: 1.6rem;
}

.horario__tarde {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin-left: 1.6rem;
}

.horario__etiqueta-tarde {
  color: var(--texto-tenue);
  font-size: 0.82rem;
  min-width: 4.5rem;
}

/* Un día con tarde queda separado del siguiente: sin esto, tres filas seguidas
   con jornada partida se leen como un bloque continuo y cuesta ver dónde
   acaba un día y empieza otro. */
.horario__dia:has(.horario__tarde:not([hidden])) {
  padding-bottom: 0.4rem;
  border-bottom: 1px solid var(--borde-suave, rgba(0, 0, 0, 0.07));
}

@media (max-width: 760px) {
  /* En pantalla estrecha el nombre del día se lleva la fila entera y las horas
     caen debajo: con cinco columnas no cabe ninguna. La cadencia va al final,
     también a lo ancho, porque su texto es el más largo de la fila. */
  .horario__dia { grid-template-columns: 1fr auto auto; }
  .horario__casilla,
  .horario__cadencia { grid-column: 1 / -1; }
  .horario__cadencia { width: 100%; }

  /* Sin sangrar: a este ancho el margen se come el campo de la hora. */
  .horario__anadir,
  .horario__tarde { margin-left: 0; }
  .horario__tarde { flex-wrap: wrap; }
}

/* ---------- Aviso de conexión ---------- */

.conexion {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.6rem;
  padding: 0.4rem 0.8rem;
  background: var(--aplazada-fondo);
  border-bottom: 1px solid var(--aplazada-borde);
  font-size: 0.85rem;
}

/* Sin línea pesa más que «hay cambios sin enviar»: se distingue de un vistazo
   sin depender solo del color, porque el texto ya lo dice. */
.conexion--sin-red {
  background: var(--cancelada-fondo);
  border-bottom-color: var(--cancelada-borde);
  font-weight: 600;
}

/* ---------- Cadena del expediente (ficha) ---------- */

.ficha__expediente { margin-top: 1.1rem; }

.ficha__expediente h3 {
  margin: 0 0 0.4rem;
  font-size: 0.9rem;
}

.cadena {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
}

.cadena__cita {
  border: 1px solid var(--borde);
  border-radius: var(--radio);
  overflow: hidden;
}

.cadena__enlace {
  display: grid;
  grid-template-columns: 1fr 1fr auto;
  gap: 0.5rem;
  align-items: baseline;
  width: 100%;
  padding: 0.4rem 0.6rem;
  border: 0;
  background: none;
  font: inherit;
  color: inherit;
  text-align: left;
  cursor: pointer;
}

.cadena__enlace:hover { background: #f8f9fb; }
.cadena__cuando { color: var(--texto-tenue); font-size: 0.82rem; }
.cadena__concepto { font-weight: 600; }

.cadena__estado {
  color: var(--texto-tenue);
  font-size: 0.75rem;
  text-transform: lowercase;
}

/* ---------- Estadísticas ---------- */

/* Fila propia debajo del título, no dentro de él: así el título puede quedarse
   fijo arriba en móvil sin arrastrar consigo los seis controles del filtro. */
.estadisticas__filtro {
  display: flex;
  align-items: flex-end;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-bottom: 0.9rem;
}

.estadisticas > .usuarios__barra { margin-bottom: 0.6rem; }

/* En la barra de filtros la etiqueta va encima y muy pegada: son campos de
   apoyo, no un formulario que haya que rellenar entero. */
.campo--linea { margin: 0; }
.campo--linea .campo__etiqueta { font-size: 0.72rem; }

.estadisticas__cifras {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  margin-bottom: 0.9rem;
}

.estadisticas__cifra {
  flex: 1 1 130px;
  background: var(--superficie);
  border: 1px solid var(--borde);
  border-radius: var(--radio-tarjeta);
  box-shadow: var(--sombra-tarjeta);
  padding: 0.85rem 1rem;
}

.estadisticas__numero {
  display: block;
  color: var(--marca);
  font-size: 1.9rem;
  font-weight: 700;
  line-height: 1.1;
}

.estadisticas__etiqueta {
  display: block;
  color: var(--texto-tenue);
  font-size: 0.8rem;
}

/* Cada bloque («Por tipo de gestión», «Por empleado», «Por entidad») es su
   propia tarjeta, separada de las demás — sin esto se leían como una sola
   columna larga donde no quedaba claro dónde terminaba un desglose y
   empezaba el siguiente. */
.estadisticas__bloque {
  background: var(--superficie);
  border: 1px solid var(--borde);
  border-radius: var(--radio-tarjeta);
  box-shadow: var(--sombra-tarjeta);
  padding: 0.9rem 1.1rem;
  margin-bottom: 0.9rem;
}

.estadisticas__subtitulo {
  margin: 0 0 0.6rem;
  font-size: 0.95rem;
}

/* Ya está dentro de la tarjeta del bloque: un borde y un fondo propios
   serían un marco dentro de otro marco. */
.estadisticas__bloque .tabla {
  border: 0;
  background: transparent;
}

/* Estas tablas no llevan a ninguna parte: no deben parecer pulsables. */
.estadisticas .tabla tbody tr { cursor: default; }

/* Más compactas que el resto de tablas de la aplicación: aquí acompañan a un
   gráfico y lo que importa es ver muchas filas de un vistazo, no cada fila
   por separado. */
.estadisticas .tabla th,
.estadisticas .tabla td {
  padding: 0.3rem 0.6rem;
}

.tabla__num { text-align: right; white-space: nowrap; }

/* Gráfico y tabla lado a lado: el gráfico es el «de un vistazo», compacto a
   propósito, y la tabla de al lado sigue siendo la fuente exacta. Apilarlos
   —gráfico grande arriba, tabla entera abajo— duplicaba el mismo dato dos
   veces y se comía media pantalla por bloque. */
.estadisticas__cuerpo {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  gap: 1.2rem;
  /* Sin este tope, en una pantalla ancha la tabla (que sí crece, más abajo)
     se estira hasta ocupar todo el hueco sobrante y acaba gigantesca y medio
     en blanco — el gráfico se queda pequeño al lado sin que crezca con ella. */
  max-width: 900px;
}

/* Crece un poco para acomodar nombres largos, pero con un tope: sin él es
   ella la que se come todo el ancho sobrante de `.estadisticas__cuerpo`. */
.estadisticas__cuerpo .tabla { flex: 1 1 320px; max-width: 480px; min-width: 0; }

/* ---------- Aviso de solapamiento ---------- */

.formulario__solape {
  border: 1px solid var(--aplazada-borde);
  background: var(--aplazada-fondo);
  border-radius: var(--radio);
  padding: 0.6rem 0.75rem;
  margin-bottom: 0.75rem;
  font-size: 0.87rem;
}

.solape__titulo { margin: 0 0 0.3rem; font-weight: 600; }
.solape__lista { margin: 0; padding-left: 1.1rem; }
.solape__pregunta { margin: 0.4rem 0 0; }

.boton--menudo { font-size: 0.75rem; padding: 0.15rem 0.4rem; }

/* La cabecera abre el perfil desde el propio nombre: es un botón, pero no
   debe parecer uno más entre los de la barra. */
.cabecera__usuario {
  border: 1px solid transparent;
  background: none;
  color: inherit;
  font: inherit;
  cursor: pointer;
  padding: 0.2rem 0.35rem;
  border-radius: var(--radio);
}

.cabecera__usuario:hover { border-color: var(--borde); }

/* ---------- Estado excepcional de una cita (principio 5) ----------
   Va al final de la hoja y con la clase repetida (0,2,0 de especificidad) a
   propósito: tiene que ganar a TODAS las superficies donde aparece una cita
   —vista día, semana, mes, bandeja y «mis firmas»—, y varias de ellas se
   definen más abajo fijando su propio fondo. Con una sola clase, la última
   regla escrita ganaba y aplazada/cancelada se quedaban sin distintivo fuera
   de la vista día.

   Fondo de color solo aquí: una cita confirmada nunca lleva ninguno. */

.cita--aplazada.cita--aplazada {
  background: var(--aplazada-fondo);
  border-color: var(--aplazada-borde);
}

.cita--cancelada.cita--cancelada {
  background: var(--cancelada-fondo);
  border-color: var(--cancelada-borde);
}

/* En el chip del mes el texto va suelto, sin .cita__concepto que tachar. */
.cita--cancelada .cita__concepto,
.mes__chip.cita--cancelada {
  text-decoration: line-through;
}

/* Urgente, con tres clases repetidas para ganar también a aplazada y cancelada,
   que ya iban con dos: una cita urgente **y** aplazada tiene que verse urgente,
   porque es lo que decide qué se atiende antes. Cancelada nunca llega hasta
   aquí — `esUrgente()` en colores.js le retira la marca. */
.cita--urgente.cita--urgente.cita--urgente {
  background: var(--urgente-fondo);
  border-color: var(--urgente-borde);
  /* El recuadro interior es lo que la separa de un simple fondo rosa: dibuja
     el bloque entero aunque el borde exterior lo pise otra regla. */
  box-shadow: inset 0 0 0 1.5px var(--urgente-borde);
}

/* La etiqueta dentro del bloque. Lo que la hace destacar más que «cancelada»
   no es el fondo —los dos son rojizos— sino que esta se lee en negativo. */
.cita__urgente {
  background: var(--urgente-borde);
  color: #fff;
  font-size: 0.62rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  padding: 0 4px;
  border-radius: 4px;
  margin-right: 4px;
}

/* ---------- Hoja de papel ----------
   En pantalla no se ve nunca: la construye impresion.js y solo aparece al
   imprimir. Ver el porqué en la cabecera de ese fichero — resumiendo, la
   rejilla por horas se lee bien en un monitor y fatal en papel, porque el
   hueco entre las 9:00 y las 12:30 es hueco de verdad y ocupa media hoja. */

.dia__hoja { display: none; }

/* ---------- Vista previa de impresión ----------
   La hoja de papel, a tamaño real, dentro de un marco con scroll. No se
   reescala: una vista previa que encoge el papel no sirve para lo que se usa,
   que es comprobar si el texto cabe. Si el A4 no entra en la ventana, se
   arrastra — igual que se movería la hoja sobre la mesa. */
.previa {
  overflow: auto;
  max-height: 62vh;
  padding: 1rem;
  background: #eceef3;
  border: 1px solid var(--borde);
  border-radius: var(--radio);
}

.previa__papel {
  margin: 0 auto;
  padding: 10mm;
  background: #fff;
  box-shadow: 0 2px 10px rgba(15, 23, 42, 0.18);
}

.previa__papel--vertical { padding: 12mm; }

/* ---------- Estilo de la hoja de papel ----------
   Fuera de @media print a propósito: el aspecto de la hoja es el mismo en
   pantalla y en papel, y lo único que cambia con el medio es si se ve o no.
   Así además se puede revisar en el navegador sin abrir el diálogo de
   impresión, que es donde se comprobó que cabía.

   Las tres vistas (día, semana, mes) siguen la maqueta de referencia que dio
   el despacho: día apaisada con columnas por empleado, semana vertical como
   lista de siete bloques, mes como calendario con las citas escritas. Cada
   una lleva su propia orientación de página (`page:`, más abajo en
   @media print) y su propia estructura, pero comparten cabecera, leyenda y
   pie — y las tres marcan el color de identidad del empleado (principio 5),
   aunque la maqueta original solo lo mostrara en la vista día. */

/* Que el navegador imprima de verdad los fondos. Aun así nada depende solo
   del color: la persona lleva su nombre escrito y el estado, su borde y su
   propio texto. */
.hoja,
.hoja * {
  -webkit-print-color-adjust: exact;
  print-color-adjust: exact;
}

.hoja {
  font-size: 8.5pt;
  line-height: 1.3;
  color: #111;
}

.hoja__cabecera {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 4mm;
  border-bottom: 2px solid #000;
  padding-bottom: 3mm;
  margin-bottom: 3mm;
}

.hoja__titulo { margin: 0; font-size: 13pt; }
.hoja__subtitulo { margin: 1mm 0 0; font-size: 9pt; color: #444; }
.hoja__sello { font-size: 7.5pt; color: #888; white-space: nowrap; }

.hoja__vacio { font-size: 10pt; }

.hoja__nota { margin-top: 3mm; font-size: 7pt; color: #888; }

.hoja__pie {
  margin-top: 4mm;
  padding-top: 2mm;
  border-top: 1px solid #999;
  font-size: 7pt;
  color: #555;
}

/* ---------- Leyenda de color por empleado ----------
   Común a las tres hojas: sin esto, la franja de color de una cita no dice
   nada por sí sola en papel. La etiqueta de un estado excepcional, si la
   hoja tiene alguno, va aparte y empujada a la derecha — es un aviso sobre
   la hoja entera, no un empleado más de la lista. */

.hoja__leyenda {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 1.5mm 4mm;
  margin: 0 0 3mm;
  font-size: 7.5pt;
  color: #333;
}

.hoja__leyenda-item { display: flex; align-items: center; gap: 1mm; }

.hoja__leyenda-punto {
  width: 2.5mm;
  height: 2.5mm;
  border-radius: 1px;
  border: 0.3mm solid rgba(0, 0, 0, 0.35);
}

.hoja__leyenda-estado {
  margin-left: auto;
  padding: 0.4mm 2mm;
  border-radius: 2px;
  background: var(--aplazada-fondo);
  color: #7a5b00;
  font-size: 7pt;
  text-transform: uppercase;
  letter-spacing: 0.02em;
}

/* ---------- Vista día: rejilla de columnas, una fila por hora ---------- */

.hoja__grid-dia {
  display: grid;
  border: 1px solid #333;
  border-radius: 1mm;
  overflow: hidden;
  font-size: 7.5pt;
}

.hoja__grid-dia > div {
  border-right: 1px solid #ddd;
  border-bottom: 1px solid #ddd;
  padding: 0.8mm 1.5mm;
  min-height: 5mm;
}

.hoja__cab-emp {
  font-weight: 700;
  background: #f8f9fb;
  border-top: 1mm solid #000;
}

.hoja__hora {
  color: #888;
  font-size: 7pt;
  font-variant-numeric: tabular-nums;
}

/* La cita es una cajita propia dentro de su celda, con su franja de color a
   la izquierda — la misma que en pantalla identifica a quien la lleva
   (principio 5). Un estado excepcional tiñe el fondo y además lo dice con
   texto, sin tocar esa franja: la identidad del empleado no se pisa nunca. */
.hoja__cita {
  border-left: 0.8mm solid;
  background: #f8f9fb;
  border-radius: 1px;
  padding: 0.5mm 1.2mm;
  margin-bottom: 0.6mm;
}

.hoja__cita b { display: block; font-size: 7.3pt; }
.hoja__cita span { display: block; font-size: 6.5pt; color: #666; }

.hoja__cita--aplazada { background: var(--aplazada-fondo); }
.hoja__cita--cancelada { background: var(--cancelada-fondo); text-decoration: line-through; }

/* En papel, además del fondo va escrito «URGENTE»: muchas impresoras del
   despacho son en blanco y negro y ahí el color no llega. */
.hoja__cita--urgente,
.hoja__chip--urgente,
.hoja__evento-mes--urgente {
  background: var(--urgente-fondo);
  box-shadow: inset 0 0 0 1px var(--urgente-borde);
}

.hoja__cita-estado--urgente { color: var(--urgente-borde); font-weight: 700; }

.hoja__cita-estado {
  display: inline-block;
  margin: 0.3mm 0;
  padding: 0 1mm;
  border: 0.3mm solid #000;
  font-size: 6pt;
  text-transform: uppercase;
  text-decoration: none;
}

/* Sigue en marcha, no empieza en esta hora: solo la franja de color continúa,
   sin repetir el texto de una hora a la siguiente. */
.hoja__celda-continua { border-left-width: 0.8mm; border-left-style: solid; }

.hoja__pendientes { margin-top: 4mm; }

.hoja__fecha {
  margin: 3mm 0 1mm;
  font-size: 9.5pt;
  font-weight: 700;
}

.hoja__lista-pendientes {
  margin: 0;
  padding: 0;
  list-style: none;
  font-size: 8pt;
}

.hoja__lista-pendientes li {
  padding: 0.8mm 0;
  border-bottom: 0.25mm solid #ddd;
}

/* ---------- Vista semana: un bloque por día, citas como etiquetas ---------- */

.hoja__semana-dia {
  border: 1px solid #ddd;
  border-radius: 1mm;
  padding: 1.5mm 2.5mm;
  margin-bottom: 1.5mm;
  break-inside: avoid;
}

.hoja__dia-vacio { font-size: 7.5pt; color: #999; }

.hoja__chip {
  display: inline-block;
  border-left: 0.8mm solid;
  background: #f8f9fb;
  border-radius: 1px;
  font-size: 7pt;
  padding: 0.5mm 1.5mm;
  margin: 0.5mm 1.5mm 0.5mm 0;
}

.hoja__chip--aplazada { background: var(--aplazada-fondo); }
.hoja__chip--cancelada { background: var(--cancelada-fondo); text-decoration: line-through; }

/* ---------- Vista mes: calendario con las citas escritas ---------- */

.hoja__cal-mes {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 0.8mm;
  font-size: 7pt;
}

.hoja__mes-cab {
  text-align: center;
  color: #888;
  font-weight: 700;
  padding: 0.8mm;
  font-size: 7.5pt;
  text-transform: uppercase;
}

.hoja__mes-celda {
  border: 0.25mm solid #ddd;
  border-radius: 1px;
  min-height: 18mm;
  padding: 0.8mm;
}

.hoja__dia-numero { font-size: 8.5pt; font-weight: 700; }
.hoja__dia-fuera { color: #aaa; }
.hoja__dia-fuera .hoja__dia-numero { font-weight: 400; }

/* El día de hoy no lleva color de fondo —tendría que sobrevivir en blanco y
   negro—, así que se marca con un borde grueso, igual que un estado
   excepcional se marca con el suyo. */
.hoja__dia-hoy { border: 0.6mm solid #000; }

.hoja__evento-mes {
  display: block;
  border-left: 0.6mm solid;
  background: #f8f9fb;
  padding: 0.2mm 0.8mm;
  margin-top: 0.5mm;
  font-size: 6.3pt;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.hoja__evento-mes--aplazada { background: var(--aplazada-fondo); }
.hoja__evento-mes--cancelada { background: var(--cancelada-fondo); text-decoration: line-through; }

.hoja__mas { display: block; font-size: 6pt; color: #999; margin-top: 0.3mm; }


/* ---------- Impresión ----------
   En papel sobra todo lo que sirve para navegar y sobra también la propia
   rejilla: se imprime la hoja compacta, una línea por cita. El color se
   conserva pero nunca es lo único que distingue algo, porque la mayoría de las
   impresoras de un despacho son en blanco y negro. */

@media print {
  /* Cada vista lleva la orientación que le pide su forma: el día necesita
     ancho —una columna por empleado—, y semana y mes son listas altas y
     estrechas que no ganan nada apaisadas. `size` sin nombre es la hoja por
     defecto si el navegador no soporta páginas con nombre (`page:`, más
     abajo); en ese caso todo sale apaisado, que sigue siendo mejor que nada. */
  @page { size: A4 landscape; margin: 10mm; }
  @page hoja-dia { size: A4 landscape; margin: 10mm; }
  @page hoja-vertical { size: A4 portrait; margin: 12mm; }

  .hoja--dia { page: hoja-dia; }
  .hoja--semana,
  .hoja--mes { page: hoja-vertical; }

  body { background: #fff; }

  /* Todo lo de pantalla fuera, incluida la rejilla y la bandeja. */
  .cabecera,
  .conexion__hueco,
  .dia__barra,
  .dia__aviso,
  .dia__cuerpo,
  .dialogo,
  .usuarios__barra {
    display: none !important;
  }

  /* Sin alturas fijas ni scroll: en papel no hay dónde desplazarse. */
  .agenda,
  .contenido,
  .dia,
  .usuarios,
  .firmas,
  .estadisticas {
    display: block;
    height: auto;
    max-height: none;
    overflow: visible;
  }

  /* La tarjeta de la agenda es cosa de la pantalla: en papel, ni marco ni
     sombra ni márgenes, que se comen milímetros de hoja. */
  .dia {
    margin: 0;
    background: none;
    border: 0;
    border-radius: 0;
    box-shadow: none;
  }

  .dia__hoja { display: block; }

  a[href]::after { content: ""; }
}


/* ---------- Barra de la agenda: agrupaciones que solo cuentan en móvil ----
   `display: contents` hace que este contenedor no exista para el diseño: sus
   cuatro controles siguen siendo hijos directos de `.dia__barra`, sueltos y
   en el mismo sitio de siempre. En móvil el @media lo convierte en un menú
   desplegable de verdad, sin duplicar ni un botón ni un manejador. */

/* Tamaño por defecto de cualquier icono de línea. Un SVG con `viewBox` y sin
   medidas se estira hasta llenar a su padre: sin esta red, olvidarse de darle
   una clase propia en un sitio nuevo lo convierte en un dibujo gigante. */
.icono { width: 1.25rem; height: 1.25rem; display: block; }

.dia__acciones { display: contents; }

/* Los dos botones de icono existen solo en el teléfono. */
.dia__icono { display: none; }

/* Cita por teléfono. Solo se marca esta: presencial es lo normal y lo que se
   supone, así que señalar las dos llenaría la agenda de iconos mudos. */
.cita__telefono {
  color: var(--acento);
  font-size: 0.9em;
}

/* El año del buscador, encima de los resultados. */
.buscador__anio {
  padding: 0.45rem 0.6rem;
  border-bottom: 1px solid var(--borde-suave);
  background: var(--fondo);
  font-size: 0.78rem;
}

.buscador__anio label { display: flex; align-items: center; gap: 0.5rem; }
.buscador__anio span { color: var(--texto-tenue); }

.buscador__anio select {
  padding: 0.15rem 0.3rem;
  border: 1px solid var(--borde);
  border-radius: var(--radio);
  background: var(--superficie);
  font: inherit;
}

/* Horario de atención a citas web, en el perfil. Una fila por día, igual que
   el horario laboral de la ficha de usuario pero sin la cadencia de semanas:
   esto no es un turno que alterne, es a qué horas se cogen citas de fuera. */
.atencion-web { margin-top: 0.6rem; }

/* ---------- Avatar de la cabecera ---------- */

.cabecera__avatar {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.9rem;
  height: 1.9rem;
  flex: 0 0 auto;
  border-radius: 50%;
  border: 1px solid var(--borde);
  background: var(--borde-suave) center/cover no-repeat;
  color: var(--texto-tenue);
  font-size: 0.72rem;
  font-weight: 700;
}

.cabecera__usuario {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
}

/* ---------- Navegación de móvil ----------
   Escondida en escritorio y encendida por el @media de más abajo. Vive
   siempre en el DOM para que girar el teléfono no obligue a reconstruir la
   cabecera: lo único que cambia es cuál de las dos barras se ve. */

.barra-inferior,
.hoja-mas { display: none; }

/* Barra flotante, despegada del borde y con una curva que sube sobre la
   pestaña abierta, como en las referencias: no es una barra pegada abajo sino
   una pastilla sobre el fondo.
   Ni fondo ni sombra aquí: los pone la silueta en SVG que dibuja
   `barra-inferior.js`, porque la joroba se mueve de pestaña en pestaña y eso
   no se dibuja con `border-radius`. */
.barra-inferior {
  position: relative;
  flex: 0 0 auto;
  /* Pegada abajo. Antes dejaba medio centímetro por debajo que, sumado al
     hueco del gesto, subía la pastilla y dejaba una banda muerta entre ella y
     la barra del sistema. */
  margin: 0 0.6rem 0.35rem;
  /* El hueco del sistema, entero. Se probó a reservar solo la mitad para que la
     barra no quedara tan alta, y el resultado fue peor: la pastilla se metía
     encima de los botones de Android. Lo que se recorta para bajarla es el
     margen de aquí arriba, nunca este hueco. */
  padding-bottom: env(safe-area-inset-bottom, 0);
}

/* Debajo de la pastilla, el fondo de la aplicación y nada más.
 *
 * Aquí hubo un intento de teñir de lila la franja del gesto de Android para
 * que su rayita contrastara. Salió peor: se veía como una banda de otro color
 * pegada bajo la barra. Lo que va debajo tiene que ser el mismo fondo que el
 * resto de la pantalla, para que no haya ninguna costura. */
.barra-inferior::after {
  content: "";
  position: absolute;
  left: -0.6rem;
  right: -0.6rem;
  bottom: -0.35rem;
  height: calc(env(safe-area-inset-bottom, 0px) + 0.35rem);
  background: var(--fondo);
  pointer-events: none;
  z-index: -1;
}

/* Sobresale por arriba a propósito: la mancha se dibuja fuera de la caja de la
   barra para que no ocupe alto ni empuje el contenido, igual que la sombra de
   una tarjeta no cuenta como tamaño. Cuánto sobresale lo pone el JS en `top`,
   sacado del propio dibujo: aquí no hay ningún número que se pueda descuadrar
   con el suyo. */
.barra-inferior__fondo {
  position: absolute;
  left: 0;
  right: 0;
  /* Alto explícito desde el JS, **no** `bottom: 0`. Con `top` y `bottom` a la
     vez el SVG se estiraría hasta el borde de la caja, y como la barra reserva
     abajo el hueco del gesto de Android, el dibujo se deformaría justo en la
     APK. Con el alto puesto a mano mide lo que dice su `viewBox` y la franja
     del gesto queda libre por debajo. */
  pointer-events: none;
  /* `drop-shadow` y no `box-shadow`: la sombra tiene que seguir la curva, y
     `box-shadow` dibujaría la de un rectángulo por debajo de ella. */
  filter: drop-shadow(0 2px 6px rgba(72, 28, 95, 0.06))
          drop-shadow(0 8px 22px rgba(72, 28, 95, 0.1));
}

.barra-inferior__pastilla { fill: var(--superficie); }
.barra-inferior__halo { fill: var(--marca-suave); }
.barra-inferior__disco { fill: var(--marca); }

.barra-inferior__boton {
  /* Por encima de la silueta, que va en el fondo de la misma caja. */
  position: relative;
  z-index: 1;
  flex: 1 1 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.1rem;
  padding: 0.3rem 0.2rem 0.35rem;
  border: 0;
  background: none;
  color: var(--texto-tenue);
  font: inherit;
  font-size: 0.64rem;
  line-height: 1.2;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}

.barra-inferior__icono {
  width: 1.3rem;
  height: 1.3rem;
  /* Es lo que decide el alto de toda la barra. Este valor la deja en unos
     58 px, que es lo que necesita el disco para caber sin comerse la etiqueta. */
  padding: 0.42rem 0;
  box-sizing: content-box;
  /* El icono de la pestaña abierta sube hasta el centro del disco morado.
     Cuánto sube lo calcula `barra-inferior.js` a partir del dibujo y lo deja
     en `--alza-icono`: si el disco cambia de tamaño, el icono le sigue. La
     transición dura lo mismo que el viaje del hueco para que suban juntos. */
  transform: translateY(0);
  transition: transform 0.28s cubic-bezier(0.65, 0, 0.35, 1), color 0.2s ease;
}

.barra-inferior__boton--activo { color: var(--marca); font-weight: 600; }

.barra-inferior__boton--activo .barra-inferior__icono {
  transform: translateY(calc(var(--alza-icono, 0px) * -1));
  /* Sobre el morado del disco, el trazo va en blanco. */
  color: #fff;
}

.barra-inferior__boton:active .barra-inferior__icono { opacity: 0.5; }

/* Quien haya pedido menos movimiento en su teléfono no tiene por qué ver
   viajar el hueco: el icono cambia de sitio sin animación. El deslizamiento
   del dibujo lo desactiva el propio JS mirando lo mismo. */
@media (prefers-reduced-motion: reduce) {
  .barra-inferior__icono { transition: color 0.2s ease; }
}

/* La hoja de «Más»: el resto de pantallas, que en un teléfono no caben como
   pestañas. Sube desde abajo porque es de donde se ha pulsado. */
.hoja-mas {
  position: fixed;
  inset: 0;
  z-index: 40;
}

.hoja-mas__fondo {
  position: absolute;
  inset: 0;
  background: rgba(15, 23, 42, 0.45);
}

.hoja-mas__panel {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  max-height: 85vh;
  overflow-y: auto;
  padding: 0.6rem 0.9rem calc(1rem + env(safe-area-inset-bottom, 0));
  background: var(--superficie);
  border-radius: 1.25rem 1.25rem 0 0;
  box-shadow: 0 -8px 30px rgba(15, 23, 42, 0.18);
  animation: hoja-sube 0.18s ease-out;
}

/* La rayita de arriba: dice «esto sube desde abajo y se puede cerrar», que es
   lo que todo el mundo ya sabe leer en un teléfono. */
.hoja-mas__asa {
  display: block;
  width: 2.5rem;
  height: 0.25rem;
  margin: 0 auto 0.7rem;
  border-radius: 999px;
  background: var(--borde);
}

@keyframes hoja-sube {
  from { transform: translateY(12%); opacity: 0.6; }
  to { transform: translateY(0); opacity: 1; }
}

.hoja-mas__titulo {
  margin: 0 0 0.5rem;
  color: var(--texto-tenue);
  font-size: 0.72rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.05em;
}

.hoja-mas__lista { display: flex; flex-direction: column; }

.hoja-mas__opcion {
  display: flex;
  align-items: center;
  gap: 0.85rem;
  padding: 0.8rem 0.3rem;
  border: 0;
  border-bottom: 1px solid var(--borde-suave);
  background: none;
  color: inherit;
  font: inherit;
  font-size: 0.95rem;
  text-align: left;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}

.hoja-mas__opcion:last-child { border-bottom: 0; }
.hoja-mas__opcion:active { background: var(--borde-suave); }

/* Cada pantalla con su icono, en una pastilla suave: una lista de texto suelto
   se lee mucho peor de un vistazo que una con marcas a la izquierda. */
/* El trazo suelto, sin recuadro detrás. El cuadrado azulado pesaba más que el
   propio icono y convertía una lista de pantallas en una rejilla de pastillas
   de colores que no significaban nada. */
.hoja-mas__icono {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.9rem;
  height: 1.9rem;
  flex: 0 0 auto;
  color: var(--marca);
}

/* Clase propia, sin el relleno ancho de la barra inferior: ese relleno está
   ahí para dibujar la pastilla de la pestaña activa y aquí sacaba el icono
   fuera de su cuadro. */
.hoja-mas__glifo { width: 1.2rem; height: 1.2rem; display: block; }

/* Va fuera del formulario, así que le toca su propio ancho y su separación. */
/* Las tarjetas que viven fuera del formulario.
   Dentro de él las limita el propio formulario; aquí fuera hay que decirlo, o
   se estiran a lo ancho de la pantalla y desentonan con todas las demás.
   Se listan juntas para que la próxima que salga del formulario tenga dónde
   engancharse en vez de repetir el número. */
.perfil__sesion,
.perfil__tarjeta--fuera {
  max-width: 640px;
  margin-top: 1rem;
}

.perfil__salir { width: 100%; }

/* «Guardar» cierra la pantalla, debajo de la tarjeta de sesión. Pegado a
   ella, sin el hueco de una tarjeta más: es el final de la pantalla, no otra
   sección. */
.perfil__guardar {
  margin-top: 0.7rem;
  max-width: 640px;
}

/* Vacío no deja hueco, pero sigue en el árbol: es una zona `role="status"` y
   quitarlo del todo con `display: none` puede hacer que el lector de pantalla
   no cante el mensaje cuando aparezca. Hay que quitarle también el alto
   mínimo, que es el que reservaba el renglón aunque no hubiera nada escrito. */
.perfil__aviso:empty { margin: 0; min-height: 0; }

/* ---------- Vista día en móvil: lista cronológica ----------
   No hay columnas por empleado: el eje es el tiempo y cada cita una tarjeta.
   El color sigue diciendo de quién es (principio 5) y el estado excepcional
   se marca con fondo Y con su nombre escrito, igual que en escritorio. */

.dia-movil {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  padding: 0.75rem;
}

/* Hueco al final para que ni el botón flotante ni el disco de la pestaña
   activa —que sobresale por encima de la barra— se sienten sobre la última
   cita: son opacos, y sin esto tapan justo la que se quiere leer. */
.dia__cuerpo > .dia-movil:last-child,
.dia-movil__seccion:last-child { padding-bottom: 6.5rem; }

.dia-movil__cita {
  display: flex;
  align-items: stretch;
  gap: 0.6rem;
  overflow: hidden;
  background: var(--superficie);
  border: 1px solid var(--borde);
  border-radius: var(--radio);
  cursor: pointer;
}

.dia-movil__hora {
  display: flex;
  flex-direction: column;
  justify-content: center;
  flex: 0 0 3.1rem;
  padding: 0.55rem 0 0.55rem 0.15rem;
  font-variant-numeric: tabular-nums;
  text-align: center;
}

/* Las dos horas pesan igual. La de fin iba más pequeña y en gris, y en una
   agenda eso es engañoso: saber cuándo acaba una cita importa tanto como
   saber cuándo empieza — es lo que dice si da tiempo a meter otra detrás. */
.dia-movil__inicio,
.dia-movil__fin { font-size: 0.92rem; font-weight: 700; }

.dia-movil__sin-hora { color: var(--texto-tenue); font-size: 0.72rem; }

.dia-movil__cuerpo {
  min-width: 0;
  flex: 1 1 auto;
  padding: 0.55rem 0.7rem 0.55rem 0;
}

.dia-movil__cuerpo p { margin: 0; }

.dia-movil__concepto { font-size: 0.92rem; font-weight: 600; }

.dia-movil__quien {
  display: flex;
  flex-wrap: wrap;
  gap: 0.15rem 0.6rem;
  margin-top: 0.2rem !important;
  color: var(--texto-tenue);
  font-size: 0.78rem;
}

.dia-movil__persona { display: inline-flex; align-items: center; gap: 0.3rem; }

.dia-movil__punto {
  width: 0.5rem;
  height: 0.5rem;
  flex: 0 0 auto;
  border-radius: 50%;
}

.dia-movil__extra {
  margin-top: 0.2rem !important;
  color: var(--texto-tenue);
  font-size: 0.76rem;
}

/* El estado, escrito: el fondo de color solo no vale si alguien no distingue
   bien los colores o mira la pantalla al sol. */
.dia-movil__estado {
  display: inline-block;
  margin-top: 0.35rem;
  padding: 0.05rem 0.45rem;
  border: 1px solid currentColor;
  border-radius: 999px;
  font-size: 0.68rem;
  text-transform: uppercase;
  letter-spacing: 0.02em;
}

.dia-movil__accion { display: block; margin-top: 0.5rem; }

.dia-movil__seccion {
  padding: 0.75rem;
  border-top: 1px solid var(--borde);
}

.dia-movil__seccion-titulo {
  margin: 0 0 0.5rem;
  color: var(--texto-tenue);
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.dia-movil__seccion .dia-movil__cita { margin-bottom: 0.5rem; }

.dia-movil__vacio { margin: 0; color: var(--texto-tenue); font-size: 0.85rem; }

/* ---------- Vista mes en móvil: puntos, no chips ---------- */

.mes__puntos {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.16rem;
  margin-top: 0.15rem;
}

.mes__punto {
  width: 0.4rem;
  height: 0.4rem;
  border-radius: 50%;
}

/* El festivo se distingue por forma, no por color: un punto morado más sería
   un compañero más, y aquí el color ya está diciendo de quién es la cita
   (principio 5). Un rombo no se confunde con ninguno. */
.mes__punto--festivo {
  border-radius: 1px;
  background: var(--marca);
  transform: rotate(45deg) scale(0.86);
}

/* El cumpleaños, rombo también —no es una cita, así que no puede ser un
   círculo— pero en el ámbar de su etiqueta: los dos son «este día tiene algo»
   y aun así se distinguen sin tener que leer nada. */
.mes__punto--cumple {
  border-radius: 1px;
  background: #d69100;
  transform: rotate(45deg) scale(0.86);
}

/* Dentro de la etiqueta del día, el rombo va delante del nombre y a su tamaño,
   no al de los puntos de la rejilla del móvil. */
.festivo-etiqueta--cumple .mes__punto--cumple {
  display: inline-block;
  width: 0.42rem;
  height: 0.42rem;
  margin-right: 0.3rem;
  vertical-align: baseline;
}

/* Las que no caben en la semana vertical, dichas y no escondidas. */
.semana__mas {
  align-self: flex-start;
  margin-top: 0.15rem;
  padding: 0.1rem 0.45rem;
  border: 1px solid var(--borde);
  border-radius: 999px;
  background: none;
  color: var(--texto-tenue);
  font: inherit;
  font-size: 0.7rem;
  cursor: pointer;
}


/* ---------- Pantallas estrechas (PWA en móvil) ---------- */

@media (max-width: 720px) {
  /* El umbral es el mismo que el de `responsive.js`. Si se cambia uno hay que
     cambiar el otro, o aparecen estados imposibles: barra inferior puesta con
     la rejilla de columnas de escritorio detrás. */

  .dia__cuerpo { flex-direction: column; overflow-y: auto; }

  .bandeja {
    flex: 0 0 auto;
    max-height: 40vh;
    border-left: 0;
    border-top: 1px solid var(--borde);
  }

  /* ---- La barra deja de ser una barra de escritorio ----
     En un teléfono no caben nueve controles en fila: apilados ocupaban 223 px
     —el 41 % de la pantalla— antes de enseñar una sola cita. Aquí quedan dos
     filas cortas: fecha con sus flechas arriba, y el selector de vista debajo.
     Todo lo demás se va al menú de los tres puntos o al botón flotante. */

  .dia__barra {
    position: relative;
    flex-wrap: wrap;
    gap: 0.4rem;
    padding: 0.35rem 0.5rem;
  }

  .dia__navegacion { order: 1; gap: 0.1rem; }

  /* El título es lo que más importa y se lleva el sitio que sobra. Se toca
     para cambiar de fecha, y por eso lleva subrayado punteado: sin ninguna
     pista, nadie adivina que se puede pulsar. */
  .dia__titulo {
    order: 2;
    /* Base 0, no `auto`: así el título se queda con lo que sobra en vez de
       partir del ancho de su texto y empujar los iconos a una fila nueva.
       Una fecha larga se recorta con puntos suspensivos, que es lo normal. */
    flex: 1 1 0;
    min-width: 0;
    font-size: 0.95rem;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    text-decoration: underline dotted var(--borde);
    text-underline-offset: 3px;
    cursor: pointer;
  }

  .dia__icono {
    order: 3;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2.1rem;
    height: 2.1rem;
    flex: 0 0 auto;
    padding: 0;
    border: 0;
    border-radius: 50%;
    background: none;
    color: var(--texto-tenue);
    cursor: pointer;
  }

  .dia__icono svg { width: 1.15rem; height: 1.15rem; }
  .dia__icono[aria-expanded="true"] { background: var(--borde-suave); color: var(--texto); }

  /* El buscador aparece bajo la barra al pulsar la lupa, a lo ancho. Un campo
     de búsqueda permanente se comía media fila para algo que se usa a ratos. */
  .buscador { order: 4; display: none; flex: 1 0 100%; }
  .buscador--abierto { display: block; }
  .buscador__campo { width: 100%; }
  .buscador__resultados { width: 100%; }

  /* Selector de vista a lo ancho: es lo que más se toca de toda la barra. */
  .dia__modos { order: 5; flex: 1 0 100%; }
  .dia__modo { flex: 1; padding: 0.4rem 0.3rem; }

  /* Fuera de la barra. La fecha exacta se lee en el título; el calendario del
     sistema se abre tocándolo, así que el `input` sobra a la vista. Y el
     «actualizado a las…» solo interesa cuando algo va mal. */
  .dia__selector,
  .dia__subtitulo,
  .dia__sincronia--ok { display: none; }

  .dia__sincronia { order: 6; flex: 1 0 100%; margin-left: 0; }
  .festivo-etiqueta { order: 6; }

  /* ---- Menú de los tres puntos ---- */

  .dia__acciones {
    display: none;
    position: absolute;
    top: calc(100% - 0.2rem);
    right: 0.5rem;
    z-index: 30;
    flex-direction: column;
    align-items: stretch;
    gap: 0.6rem;
    min-width: 13rem;
    padding: 0.8rem;
    background: var(--superficie);
    border: 1px solid var(--borde);
    border-radius: var(--radio);
    box-shadow: 0 10px 30px rgba(15, 23, 42, 0.18);
  }

  .dia__acciones--abierto { display: flex; }

  /* Dentro del menú los submenús se abren en línea, no flotando: un panel
     flotante dentro de otro se sale de la pantalla en un teléfono. */
  .dia__acciones .descarga { position: static; display: block; }

  .dia__acciones .descarga__menu {
    position: static;
    width: 100%;
    margin-top: 0.4rem;
    box-shadow: none;
  }

  .dia__acciones .descarga__boton,
  .dia__acciones .boton { width: 100%; }

  /* Imprimir y Exportar, fuera del móvil.
   *
   * No es que estorben: es que no llevan a ninguna parte. Imprimir abre el
   * diálogo del sistema y en un teléfono acaba en «guardar como PDF» sobre una
   * hoja pensada para A4; exportar deja un fichero en la carpeta de descargas
   * que ahí no se va a abrir con nada. Las dos cosas se hacen desde el
   * escritorio, donde además está la impresora. */
  .dia__acciones [data-imprimir],
  .dia__acciones .descarga--exportar,
  .estadisticas__filtro .descarga { display: none; }

  /* ---- Botón flotante de nueva cita ----
     La acción principal, redonda y al alcance del pulgar, justo encima de la
     barra de pestañas. Es lo que se espera de una aplicación de móvil. */
  .dia__nueva {
    position: fixed;
    right: 1rem;
    /* Despegado de la barra de navegación, que va flotando con su propio
       margen: los dos se leen como cosas distintas y el botón no se pisa con
       las pestañas. La cuenta es 3.7rem de barra más 0.5rem de margen, y de
       ahí un dedo de separación. No hace falta contar además el disco de la
       pestaña abierta: en la agenda la pestaña abierta es la primera, que
       está en el otro extremo. */
    bottom: calc(5.6rem + env(safe-area-inset-bottom, 0px));
    z-index: 25;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 3.5rem;
    height: 3.5rem;
    padding: 0;
    border: 0;
    border-radius: 50%;
    background: var(--marca);
    box-shadow: 0 8px 20px rgba(72, 28, 95, 0.4);
  }

  .dia__nueva-texto { display: none; }

  .dia__nueva::before {
    content: "+";
    font-size: 1.9rem;
    font-weight: 400;
    line-height: 1;
  }

  /* ---- Cualquier tabla pasa a ser una lista de tarjetas ----
     Una tabla de seis columnas en un teléfono obliga a arrastrar de lado para
     leer una sola fila, que es justo lo que no se hace en un móvil. Cada fila
     se convierte en una tarjeta y cada celda en una línea «etiqueta: valor»,
     con la etiqueta sacada del `data-etiqueta` que pone el JS.

     Va sobre `.tabla` y no sobre cada pantalla a propósito: vale para
     Usuarios, para Vacaciones y para la próxima tabla que aparezca, sin
     tener que acordarse de nada. */

  .tabla,
  .tabla tbody,
  .tabla tr,
  .tabla td {
    display: block;
    width: auto;
  }

  /* La cabecera desaparece: su texto viaja ya en cada celda. */
  .tabla thead { display: none; }

  .tabla {
    border: 0;
    background: none;
  }

  .tabla tr {
    margin-bottom: 0.6rem;
    padding: 0.7rem 0.85rem;
    background: var(--superficie);
    border: 1px solid var(--borde);
    border-radius: var(--radio);
  }

  /* Etiqueta a la izquierda, valor a la derecha, en dos columnas de verdad.
     Con un flex y `space-between` una celda de cinco permisos los repartía a
     lo ancho y quedaban islas de texto sueltas; con todo apretado a la
     derecha, quedaban en escalera. Con rejilla, el valor ocupa su columna y
     el texto fluye dentro de ella como en cualquier párrafo. */
  .tabla td {
    display: grid;
    grid-template-columns: minmax(5.5rem, auto) 1fr;
    gap: 0.2rem 0.8rem;
    align-items: baseline;
    padding: 0.2rem 0;
    border: 0;
    text-align: left;
  }

  .tabla td::before {
    content: attr(data-etiqueta);
    color: var(--texto-tenue);
    font-size: 0.72rem;
    text-transform: uppercase;
    letter-spacing: 0.03em;
  }

  /* Una lista de etiquetas no cabe en la columna estrecha del valor, así que
     se lleva la fila entera y fluye debajo de su rótulo, seguidas y sin
     huecos. Es lo que hace que cinco permisos se lean como una frase y no
     como cinco islas repartidas por la tarjeta. */
  .tabla td .etiquetas {
    grid-column: 1 / -1;
    display: flex;
    flex-wrap: wrap;
    gap: 0.3rem;
  }

  /* Una celda sin etiqueta —el catálogo no las trae en todas— no debe dejar
     la columna vacía a su izquierda: ocupa la fila entera. */
  .tabla td:not([data-etiqueta]):not([data-principal]) { grid-template-columns: 1fr; }

  /* La primera celda es el título de la tarjeta: a lo ancho, sin etiqueta
     delante y algo mayor, porque es el nombre por el que se busca la fila. */
  .tabla td[data-principal] {
    display: block;
    margin-bottom: 0.3rem;
    padding-bottom: 0.35rem;
    border-bottom: 1px solid var(--borde-suave);
    font-size: 0.95rem;
    text-align: left;
  }

  .tabla td[data-principal]::before { content: none; }

  /* Una celda sin etiqueta (una tabla que aún no la ponga) no debe dejar un
     hueco raro a la izquierda. */
  .tabla td:not([data-etiqueta]):not([data-principal])::before { content: none; }

  .tabla__num { text-align: right; }

  /* El bloque es la tarjeta blanca y dentro van sus filas lilas. Lo único que
     sobraba era **el dibujo de fondo del bloque**: las filas lilas dejan aire
     entre ellas, y por ese aire asomaba el gráfico de adorno como una franja
     gris suelta, que es lo que se veía como uniones raras entre tarjetas.
     Sigue en las tarjetas de cifra, que son macizas y ahí sí luce.

     El selector lleva `.estadisticas` delante a propósito: `ilustraciones.css`
     se carga después que esta hoja, así que con la misma especificidad ganaba
     su `background-image` y el dibujo seguía pintándose. */
  .estadisticas .estadisticas__bloque { background-image: none; }

  /* Sin sombra: era el «sombreado raro» de las esquinas. El fondo blanco y el
     borde se quedan, que son lo que separa la tarjeta del fondo. */
  .estadisticas__bloque,
  .estadisticas__cifra,
  .perfil__tarjeta,
  .saldo,
  .recepcion__persona,
  .tabla tr { box-shadow: none; }

  /* Los bloques de estadísticas ya son tarjetas, así que sus filas **no son
     otras tarjetas**: sin marco y con un tinte suave, para que se lean como
     renglones de la tarjeta y no como tarjetas dentro de otra. */
  .estadisticas__bloque .tabla tr {
    margin-bottom: 0.3rem;
    padding: 0.5rem 0.6rem;
    background: var(--marca-tenue);
    border: 0;
  }

  /* Gráfico y tabla, uno debajo del otro y a lo ancho: en 375 px no caben
     los dos al lado sin que uno de los dos quede ilegible. */
  .estadisticas__cuerpo { flex-direction: column; }
  .estadisticas__cuerpo .grafico,
  .estadisticas__cuerpo .grafico--barras,
  .estadisticas__cuerpo .tabla {
    flex: 1 1 auto;
    max-width: 100%;
    width: 100%;
  }

  .grafico__fila { grid-template-columns: minmax(4rem, 1fr) 6rem 1.6rem; }

  /* Saldos de dos en dos y llenando el ancho: en una columna sola quedaban
     unas tarjetas estrechas con media pantalla vacía al lado. */
  .saldos {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 0.6rem;
    margin-bottom: 1rem;
  }

  .saldo { padding: 0.6rem 0.7rem; }

  /* ---- Pulido general de móvil ----
     Esquinas algo más redondas, títulos de pantalla que no gritan, y respuesta
     al dedo: sin el destello de pulsación, tocar una tarjeta parece que no ha
     hecho nada hasta que cambia la pantalla. */

  /* Sin relleno arriba, y el hueco lo pone la barra del título.
     El relleno superior de un contenedor con scroll no se va con el scroll:
     deja una franja suya por encima del título pegajoso, y por esa franja se
     veía pasar el contenido —tarjetas cortadas asomando sobre el título—.
     Metido dentro de la barra, que es opaca, no hay por dónde asomar. */
  .usuarios,
  .estadisticas,
  .ajustes,
  .perfil { padding: 0 0.75rem 0.75rem; }

  /* Lo que tenía que llegar de lado a lado era la **pantalla**, no las
     tarjetas. Se probó a quitarles el borde y el redondeo y quedaron pegadas a
     los cantos, sin la franja de color de la persona a la izquierda, que es
     justo lo que dice de quién es cada bloque (principio 5). Cada tarjeta es
     una tarjeta, con su margen y sus esquinas. */
  .recepcion { padding: 0 0.75rem 1rem; }
  .recepcion__rejilla { gap: 0.6rem; }

  /* De lado a lado. La pantalla lleva relleno lateral, así que una barra
     pegajosa que respetara ese relleno dejaba dos pasillos por los que se veía
     subir el contenido al deslizar. Los márgenes negativos la sacan hasta los
     cantos y el relleno propio devuelve el aire por dentro, así que tapa la
     franja entera. */
  .usuarios__barra {
    position: sticky;
    top: 0;
    z-index: 5;
    margin-left: -0.75rem;
    margin-right: -0.75rem;
    padding: 0.75rem 0.75rem 0.6rem;
    background: var(--fondo);
  }

  /* En una pantalla con secciones, el título de la pantalla deja de pegarse.
     Si no, se quedaba clavado arriba y el título de la sección se le montaba
     encima: como el de pantalla es más alto —lleva su botón— asomaba por
     debajo y se veían los dos a la vez. Pegajosos solo los de sección, que
     además se relevan solos: cada uno se suelta al acabar su `.seccion`, así
     que arriba solo hay un título en cada momento. */
  .usuarios--con-secciones > .usuarios__barra { position: static; }

  /* Pegajosa también, así que sin línea de separación: una raya encima de un
     título que flota sobre el contenido se lee como un corte, no como un
     separador. El aire de más ya dice que empieza otra sección. */
  .usuarios__barra--separada {
    margin-top: 1.2rem;
    border-top: 0;
  }

  .usuarios__titulo { font-size: 1.05rem; }

  /* ---- Panel de notificaciones ----
     En escritorio cuelga de la campana con 320 px de ancho. En un teléfono la
     campana está pegada al borde derecho, así que esos 320 px se salían por
     la izquierda y el panel aparecía cortado. Quitándole la posición a la
     campana, el panel pasa a colgar de la cabecera entera y se estira de
     margen a margen.
     El `100%` de la cabecera cae por debajo de la onda, así que se le restan
     esos 3.2rem de relleno para que quede justo bajo la campana. */
  .campanita { position: static; }

  .campanita__panel {
    top: calc(100% - 2.8rem);
    left: 0.7rem;
    right: 0.7rem;
    width: auto;
    max-height: 65vh;
  }

  .tabla tr,
  .saldo,
  .perfil__tarjeta,
  .estadisticas__bloque,
  .estadisticas__cifra { border-radius: 0.85rem; }

  .dia-movil__cita { border-radius: 0.85rem; }

  .dia-movil__cita,
  .tabla tbody tr,
  .hoja-mas__opcion,
  .barra-inferior__boton { -webkit-tap-highlight-color: transparent; }

  .dia-movil__cita:active { background: var(--borde-suave); }

  /* Los botones sueltos de una pantalla llenan el ancho: en un teléfono un
     botón de 90 px perdido en una fila es difícil de acertar con el pulgar. */
  .usuarios__barra .boton,
  .ausencias__acciones .boton { min-height: 2.5rem; }

  /* La acción principal del perfil, a lo ancho y al alcance del pulgar, igual
     que «Salir», que va justo encima. */
  .perfil__guardar { width: 100%; min-height: 2.5rem; }

  .columna { flex: 0 0 160px; }

  .formulario__rejilla { grid-template-columns: 1fr; }
  .participante { grid-template-columns: 1fr 1fr auto; }
  .ficha { grid-template-columns: 1fr; gap: 0 0; }
  .ficha dd { margin-bottom: 0.5rem; }

  /* Las pestañas de arriba dejan sitio a la barra de abajo, que se alcanza
     con el pulgar. Y lo que no cabe en una cabecera de teléfono se va con
     ellas: el nombre entero, la categoría, el idioma y «Salir» viven en la
     hoja de «Más». */
  .cabecera__nav,
  .cabecera__nombre,
  .cabecera__rol,
  .cabecera__idioma,
  .cabecera__salir { display: none; }

  /* ---- Cabecera de móvil: alta, con la onda abajo ----
     El relleno de abajo deja sitio a la curva para que no se coma el logo ni
     el avatar, y el margen negativo del contenido lo sube hasta meterse bajo
     la onda: así la primera tarjeta asoma por debajo de la curva en vez de
     dejar una franja de fondo entre las dos. */
  /* El relleno de arriba respeta la zona reservada del teléfono: la hora, la
     batería y la cámara. Sin esto, el logo y el avatar quedan debajo de los
     iconos del sistema y no hay forma de pulsarlos. El `max()` deja un mínimo
     razonable en los móviles que no declaran zona segura. */
  .cabecera {
    padding: max(env(safe-area-inset-top, 0px), 0.6rem) 0.9rem 3.2rem;
    gap: 0.5rem;
    border-radius: 0;
    /* Por encima del contenido: la onda tiene que verse sobre la agenda, que
       sube hasta meterse debajo. Sin esto, el primer bloque de la agenda la
       tapaba y la curva no se veía. */
    z-index: 10;
  }

  .cabecera__marca { font-size: 1.05rem; }
  .cabecera__logo { width: 3.2rem; height: 3.2rem; }

  .cabecera__onda {
    display: block;
    position: absolute;
    left: 0;
    right: 0;
    bottom: -1px;
    width: 100%;
    height: 3rem;
    /* `currentColor` toma el color del fondo de la página: la onda no pinta
       morado, recorta la cabecera dejando ver lo que hay debajo. */
    color: var(--fondo);
    pointer-events: none;
  }

  /* Sin margen negativo: la curva ya vive dentro del relleno inferior de la
     cabecera, así que el contenido arranca justo debajo de ella. Subirlo se
     comía la primera fila de controles, que quedaba tapada por el morado. */
  .contenido { margin-top: 0; }

  /* En el móvil la agenda ya es una lista de tarjetas sobre el fondo gris:
     meterla además dentro de otra tarjeta sería tarjeta dentro de tarjeta,
     justo lo que se acaba de quitar en estadísticas. Aquí va a sangre. */
  .dia {
    margin: 0;
    background: none;
    border: 0;
    border-radius: 0;
    box-shadow: none;
  }

  .barra-inferior { display: flex; }
  .hoja-mas:not([hidden]) { display: block; }

  /* Abajo manda la barra de pestañas: el pie no cabe y encima competiría con
     ella. Se va entero — firma y aviso legal juntos. Estuvo un tiempo el
     enlace del aviso suelto al final de la hoja de «Más» y quedaba flotando
     ahí sin nada que lo explicara: si no se ve la firma, tampoco su enlace. */
  .pie { display: none; }

  /* ---- Semana: lista vertical de días ---- */

  .semana { flex-direction: column; }

  .semana__dia {
    border-right: 0;
    border-bottom: 1px solid var(--borde-suave);
  }

  /* Hoy con su franja de acento a la izquierda: en una lista vertical el
     fondo gris clarito de escritorio no se distingue de un día cualquiera. */
  .semana__dia--hoy {
    background: #f4f8ff;
    border-left: 3px solid var(--acento);
  }

  .semana__lista { flex-direction: column; }

  /* La tarjeta de la semana enseña lo mismo que la del día: las dos horas
     igual de marcadas, el trámite, de quién es la cita y con quién es. */
  .semana__quien,
  .semana__cliente { display: block; margin: 0.15rem 0 0 !important; }

  /* Hora y trámite comparten renglón; si no cabe, lo que se recorta es el
     trámite —la hora nunca, que es por lo que se recorre la lista. */
  .semana__linea {
    display: flex;
    align-items: baseline;
    gap: 0.45rem;
    margin: 0;
    min-width: 0;
  }

  .semana__evento .cita__hora { flex: 0 0 auto; font-weight: 700; font-size: 0.88rem; }

  .semana__evento .cita__concepto {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-size: 0.9rem;
    font-weight: 600;
    color: var(--texto);
  }

  .semana__quien {
    display: flex;
    flex-wrap: wrap;
    gap: 0.15rem 0.6rem;
    color: var(--texto-tenue);
    font-size: 0.78rem;
  }

  .semana__persona { display: inline-flex; align-items: center; gap: 0.3rem; }

  .semana__punto {
    width: 0.5rem;
    height: 0.5rem;
    border-radius: 50%;
    flex: 0 0 auto;
  }

  .semana__cliente { color: var(--texto-tenue); font-size: 0.8rem; }

  /* ---- Mes: cuadrícula de puntos ---- */

  .mes__celda {
    min-height: 3rem;
    align-items: center;
    gap: 0;
    padding: 0.25rem 0.1rem;
  }

  .mes__numero { font-size: 0.8rem; }

  /* Un día de otro mes se atenúa pero no desaparece: sirve de referencia para
     no contar mal la primera y la última semana. */
  .mes__celda--fuera { opacity: 0.45; }
}

/* El texto de ejemplo de la plantilla de WhatsApp: se copia y se pega tal cual
   en Meta, así que se enseña en monoespaciada y sin que se reajusten los
   {{huecos}} al ancho de la caja. */
.ajustes__plantilla {
  margin: 0.4rem 0 0;
  padding: 0.6rem 0.75rem;
  background: var(--borde-suave);
  border-radius: var(--radio);
  font-family: ui-monospace, "Cascadia Code", Consolas, monospace;
  font-size: 0.8rem;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

/* ---------- Fichas de cliente repetidas ----------
   Panel de limpieza, dentro de la pantalla de clientes. Cada grupo es un
   bloque cerrado con su propio botón: se funden de uno en uno y se ve lo que
   se lleva cada uno antes de decidir. */

.duplicados { display: grid; gap: 1rem; }

.duplicados__grupo {
  border: 1px solid var(--borde-suave, rgba(0, 0, 0, 0.12));
  border-radius: var(--radio);
  padding: 0.9rem 1rem;
}

.duplicados__nombre { margin: 0; font-size: 1rem; }

.duplicados__resumen {
  margin: 0.15rem 0 0.6rem;
  color: var(--texto-tenue);
  font-size: 0.82rem;
}

.duplicados__fichas {
  list-style: none;
  margin: 0 0 0.7rem;
  padding: 0;
  display: grid;
  gap: 0.3rem;
}

.duplicados__ficha {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.75rem;
  flex-wrap: wrap;
}

.duplicados__datos { color: var(--texto-tenue); font-size: 0.82rem; }

/* Grupo ya fundido: se queda el aviso en su sitio en vez de desaparecer, para
   no descolocar la lista de lo que aún queda por revisar. */
.duplicados__hecho {
  margin: 0;
  color: var(--texto-tenue);
}

/* Informe del testigo de latidos, en Mi perfil. Monoespaciado y con los
   saltos de línea respetados: es una lista de horas y se lee en columna. */
.perfil__diagnostico {
  margin: 0.6rem 0;
  padding: 0.6rem 0.75rem;
  background: var(--fondo-suave, rgba(0, 0, 0, 0.04));
  border-radius: var(--radio);
  font-size: 0.8rem;
  white-space: pre-wrap;
  overflow-x: auto;
}

/* Versión en el pie y en Mi perfil. Discreta: es un dato de servicio, no
   algo que haya que leer todos los días — pero tiene que estar a la vista
   cuando se necesita, que es justo cuando algo falla. */
.pie__version { color: var(--texto-tenue); font-variant-numeric: tabular-nums; }

.perfil__versiones {
  margin: 0.2rem 0 0.6rem;
  color: var(--texto-tenue);
  font-size: 0.85rem;
  font-variant-numeric: tabular-nums;
}
