/* ===========================================================================
   components.css — la capa propia sobre Bootstrap.

   Aquí va lo que Bootstrap no cubre del tema Clinical Precision: cabecera de
   página, tarjetas con título separado, chips pill con tinte, modales, estados
   vacíos, feedback, y la tabla densa que se convierte en tarjetas en móvil.

   Regla: si una vista necesita un estilo que no está aquí, se añade aquí
   primero. Nada de CSS suelto en los .cshtml.
   =========================================================================== */

/* --------------------------------- iconos -------------------------------- */

.prme-icon,
.prme-menu__icon,
.prme-sidebar__logo,
.prme-menu__chevron {
  display: inline-block;
  width: 20px;
  height: 20px;
  fill: none;
  vertical-align: middle;
}

.prme-menu__chevron {
  width: 16px;
  height: 16px;
  margin-left: auto;
  transition: transform 150ms ease;
}

.prme-menu__group[open] > .prme-menu__link .prme-menu__chevron { transform: rotate(180deg); }

.prme-menu__group > summary { cursor: pointer; list-style: none; }
.prme-menu__group > summary::-webkit-details-marker { display: none; }

@media (prefers-reduced-motion: reduce) {
  .prme-menu__chevron { transition: none; }
}

/* ------------------------------- accesibilidad --------------------------- */

.prme-skip-link {
  position: absolute;
  top: -100px;
  left: var(--prme-space-2);
  z-index: 100;
  padding: var(--prme-space-2) var(--prme-space-4);
  background: var(--prme-primary);
  border-radius: var(--prme-radius-control);
  color: var(--prme-on-primary);
  text-decoration: none;
}

.prme-skip-link:focus { top: var(--prme-space-2); }

.prme-visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* ----------------------------- cabecera de página ------------------------ */

.prme-page-head {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  gap: var(--prme-space-3);
  margin-bottom: var(--prme-stack);
}

.prme-page-head__text { flex: 1 1 260px; min-width: 0; }

/* Este es el título real de la pantalla: tamaño XL y letter-spacing negativo,
   como en el prototipo. Es lo primero que debe leerse al entrar. */
.prme-page-head__title {
  margin: 0;
  font-size: var(--prme-headline-xl-size);
  font-weight: 700;
  letter-spacing: -.02em;
  line-height: var(--prme-headline-xl-line);
}

/* Es metadato del título, no contenido: al mismo cuerpo que el texto normal
   competía con la primera fila de la tabla. */
.prme-page-head__sub {
  margin: var(--prme-space-1) 0 0;
  color: var(--prme-on-surface-variant);
  font-size: var(--prme-data-size);
  line-height: var(--prme-data-line);
}

.prme-page-head__actions {
  display: flex;
  flex: 0 0 auto;
  flex-wrap: wrap;
  gap: var(--prme-space-2);
}

/* --------------------------------- tarjeta ------------------------------- */

/* Capas tonales + sombra ambiental, no bordes pesados (DESIGN.md § Elevation).
   El borde es apenas una insinuación; lo que separa la tarjeta del fondo es el
   contraste blanco-sobre-gris más la sombra. */
.prme-card {
  background: var(--prme-surface-lowest);
  border: 1px solid rgb(0 0 0 / 4%);
  border-radius: var(--prme-radius-card);
  box-shadow: var(--prme-shadow-1);
  transition: box-shadow 150ms ease;
}

/* Solo las tarjetas accionables reaccionan; una tarjeta de solo lectura que se
   ilumina al pasar por encima promete una interacción que no existe. */
a.prme-card:hover,
.prme-card--interactive:hover { box-shadow: var(--prme-shadow-2); }

@media (prefers-reduced-motion: reduce) {
  .prme-card { transition: none; }
}

.prme-card__head {
  display: flex;
  align-items: center;
  gap: var(--prme-space-2);
  padding: var(--prme-space-4);
  border-bottom: 1px solid var(--prme-outline-variant);
}

.prme-card__title {
  margin: 0;
  font-size: var(--prme-headline-md-size);
  font-weight: 600;
  line-height: var(--prme-headline-md-line);
}

.prme-card__body { padding: var(--prme-space-4); }

.prme-card__foot {
  display: flex;
  justify-content: flex-end;
  gap: var(--prme-space-2);
  padding: var(--prme-space-3) var(--prme-space-4);
  border-top: 1px solid var(--prme-outline-variant);
}

/* Rejilla de tarjetas del dashboard. */
.prme-card-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  gap: var(--prme-gutter);
}

/* --------------------------------- métrica ------------------------------- */

.prme-metric__label {
  color: var(--prme-on-surface-variant);
  font-size: var(--prme-label-md-size);
  font-weight: 600;
  letter-spacing: .05em;
  text-transform: uppercase;
}

.prme-metric__value {
  display: block;
  margin-top: var(--prme-space-1);
  font-size: var(--prme-headline-xl-size);
  font-weight: 700;
  letter-spacing: -.02em;
  line-height: var(--prme-headline-xl-line);
}

.prme-metric__hint { color: var(--prme-on-surface-variant); font-size: var(--prme-label-md-size); }

/* ---------------------------------- chip --------------------------------- */

/* Pill, para distinguirlo de un botón. Fondo tintado + texto oscuro. */
.prme-chip {
  display: inline-flex;
  align-items: center;
  gap: var(--prme-space-1);
  padding: 2px var(--prme-space-2);
  border-radius: var(--prme-radius-pill);
  background: var(--prme-surface-container);
  color: var(--prme-on-surface-variant);
  font-size: var(--prme-label-md-size);
  font-weight: 600;
  line-height: var(--prme-label-md-line);
  white-space: nowrap;
}

.prme-chip--success { background: var(--prme-success-container); color: var(--prme-success); }
.prme-chip--warning { background: var(--prme-warning-container); color: var(--prme-warning); }
.prme-chip--danger  { background: var(--prme-error-container);   color: var(--prme-on-error-container); }
.prme-chip--info    { background: var(--prme-info-container);    color: var(--prme-info); }

/* --------------------------------- tabla --------------------------------- */

/*
   position:relative no es decorativo: sin él, el envoltorio no es bloque
   contenedor de sus descendientes posicionados, así que el overflow no los
   recorta. Los .prme-visually-hidden de las tablas —el caption y la cabecera de
   la columna de acciones— se quedaban en su posición estática dentro de una tabla
   más ancha que la pantalla, escapaban del scroll interno y estiraban el
   documento: en tablet la página entera hacía scroll horizontal por culpa de un
   span de 1px que nadie ve.
*/
.prme-table-wrap {
  position: relative;
  overflow-x: auto;
  background: var(--prme-surface-lowest);
  border: 1px solid var(--prme-outline-variant);
  border-radius: var(--prme-radius-card);
}

.prme-table-wrap > .table { margin: 0; }

/* Un contenedor por bloque. Cuando la tabla ya va dentro de una tarjeta —que es
   el patrón de todas las pantallas de lista— el envoltorio solo aporta el scroll
   horizontal: su borde y su radio se apilan sobre los de la tarjeta y dibujan dos
   marcos concéntricos. Es el detalle que más delataba una pantalla sin rematar. */
.prme-card > .prme-table-wrap {
  border: 0;
  border-radius: inherit;
  background: transparent;
}

.prme-table__sort {
  display: inline-flex;
  align-items: center;
  gap: var(--prme-space-1);
  padding: 0;
  border: 0;
  background: none;
  color: inherit;
  font: inherit;
  cursor: pointer;
}

.prme-table__sort:focus-visible { outline: var(--prme-focus-ring); outline-offset: var(--prme-focus-offset); }

.prme-table__actions { display: flex; gap: var(--prme-space-1); justify-content: flex-end; }

/* Acciones de fila: fantasma, no rellenas.
   Un listado de 30 filas con dos botones grises por fila son 60 bloques con el
   mismo peso que el dato, y el ojo ya no sabe dónde mirar. Aquí la acción se
   apoya en el texto y solo coge fondo al pasar por encima o al recibir el foco.
   No se ocultan hasta el hover: eso rompe el táctil y el recorrido por teclado. */
.prme-table__actions .btn-secondary {
  --bs-btn-bg: transparent;
  --bs-btn-border-color: transparent;
  --bs-btn-color: var(--prme-primary);
  --bs-btn-hover-bg: color-mix(in srgb, var(--prme-primary) 8%, transparent);
  --bs-btn-hover-border-color: transparent;
  --bs-btn-hover-color: var(--prme-primary);
  --bs-btn-active-bg: color-mix(in srgb, var(--prme-primary) 14%, transparent);
  --bs-btn-active-border-color: transparent;
  --bs-btn-active-color: var(--prme-primary);
  font-weight: 500;
}

/* Columnas numéricas: a la derecha, para poder comparar magnitudes de un vistazo.
   Las cifras tabulares ya las pone la regla general de .table en layout.css. */
.prme-num { text-align: right; }

/* Móvil: cada fila pasa a ser una tarjeta. El <th> de cada columna se repite
   como etiqueta vía data-label, para no perder el encabezado. */
@media (max-width: 767.98px) {
  .prme-table--cards > thead { display: none; }

  .prme-table--cards,
  .prme-table--cards > tbody,
  .prme-table--cards > tbody > tr,
  .prme-table--cards > tbody > tr > td { display: block; width: 100%; }

  .prme-table--cards > tbody > tr {
    padding: var(--prme-space-2) 0;
    border-bottom: 1px solid var(--prme-outline-variant);
  }

  .prme-table--cards > tbody > tr > td {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--prme-space-4);
    padding: var(--prme-space-1) var(--prme-space-4);
    border: 0;
  }

  .prme-table--cards > tbody > tr > td::before {
    content: attr(data-label);
    flex: 0 0 auto;
    color: var(--prme-on-surface-variant);
    font-size: var(--prme-label-md-size);
    font-weight: 600;
    letter-spacing: .05em;
    text-transform: uppercase;
  }

  .prme-table--cards > tbody > tr > td:empty { display: none; }
}

/* ------------------------------ estado vacío ----------------------------- */

.prme-empty {
  padding: var(--prme-space-8) var(--prme-space-4);
  color: var(--prme-on-surface-variant);
  text-align: center;
}

.prme-empty__title {
  margin: 0 0 var(--prme-space-1);
  color: var(--prme-on-surface);
  font-size: var(--prme-headline-md-size);
  font-weight: 600;
}

/* -------------------------------- feedback ------------------------------- */

.prme-feedback {
  display: flex;
  gap: var(--prme-space-3);
  padding: var(--prme-space-3) var(--prme-space-4);
  margin-bottom: var(--prme-space-4);
  border-left: 3px solid var(--prme-outline);
  border-radius: var(--prme-radius-control);
  background: var(--prme-surface-container);
}

.prme-feedback--success { border-left-color: var(--prme-success); background: var(--prme-success-container); }
.prme-feedback--error   { border-left-color: var(--prme-error);   background: var(--prme-error-container); }
.prme-feedback--warning { border-left-color: var(--prme-warning); background: var(--prme-warning-container); }

/* --------------------------------- modal --------------------------------- */

.prme-dialog-host:empty { display: none; }

.prme-modal {
  position: fixed;
  inset: 0;
  z-index: 50;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--prme-space-4);
  background: rgb(25 28 30 / 45%);
  backdrop-filter: blur(8px);
}

.prme-modal__panel {
  width: 100%;
  max-width: 520px;
  max-height: 90vh;
  overflow: auto;
  background: var(--prme-surface-lowest);
  border-radius: var(--prme-radius-card);
  box-shadow: var(--prme-shadow-modal);
}

.prme-modal__head {
  position: relative;
  padding: var(--prme-space-4);
  padding-right: var(--prme-space-8);
  border-bottom: 1px solid var(--prme-outline-variant);
}

.prme-modal__title {
  margin: 0;
  font-size: var(--prme-headline-md-size);
  font-weight: 600;
  line-height: var(--prme-headline-md-line);
}

.prme-modal__sub { margin: var(--prme-space-1) 0 0; color: var(--prme-on-surface-variant); font-size: var(--prme-data-size); }

.prme-modal__close { position: absolute; top: var(--prme-space-3); right: var(--prme-space-3); }

.prme-modal__body { padding: var(--prme-space-4); }

.prme-modal__foot {
  display: flex;
  justify-content: flex-end;
  gap: var(--prme-space-2);
  padding: var(--prme-space-3) var(--prme-space-4);
  border-top: 1px solid var(--prme-outline-variant);
}

/* ------------------------------- indicadores ----------------------------- */

/* Sustituye al <style> que htmx inyecta y que rompería el CSP estricto. */
.htmx-indicator { opacity: 0; transition: opacity 200ms ease-in; }
.htmx-request .htmx-indicator { opacity: 1; }
.htmx-request.htmx-indicator { opacity: 1; }

@media (prefers-reduced-motion: reduce) {
  .htmx-indicator { transition: none; }
}

/* ------------------------------ formularios ------------------------------ */

.prme-form-field { margin-bottom: var(--prme-space-4); }

/* Fila de campos: caben los que quepan, todos del mismo ancho.

   Antes eran dos columnas fijas, y una fila de TRES campos dejaba el tercero solo
   en la siguiente fila y estirado a lo ancho de la tarjeta — que es exactamente lo
   que se veía en el filtro de Backup y migración. Con auto-fit fluye a 1, 2 o 3
   columnas según el sitio, sin que la vista tenga que saber cuántos campos lleva. */
.prme-form-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr));
  gap: var(--prme-space-4);
}

/* Un <form> por botón dentro de una celda de acciones no debe romper la fila. */
.prme-inline-form { display: inline; margin: 0; }

.prme-workingdays {
  display: flex;
  align-items: baseline;
  gap: var(--prme-space-2);
  padding: var(--prme-space-2) var(--prme-space-3);
  margin-bottom: var(--prme-space-4);
  border-radius: var(--prme-radius-control);
  background: var(--prme-surface-container);
}

.prme-workingdays__value { font-size: var(--prme-headline-md-size); font-weight: 700; }

.prme-balance-hint {
  padding: var(--prme-space-2) var(--prme-space-3);
  margin-bottom: var(--prme-space-4);
  border-left: 3px solid var(--prme-primary);
  border-radius: var(--prme-radius-control);
  background: var(--prme-surface-low);
  font-size: var(--prme-data-size);
}

.prme-muted { color: var(--prme-on-surface-variant); }

.prme-chip--neutral { background: var(--prme-surface-container); color: var(--prme-on-surface-variant); }

.prme-mb-6 { margin-bottom: var(--prme-space-6); }
.prme-mt-2 { margin-top: var(--prme-space-2); }

/* Cifra de tarjeta cuando es una fecha y no un número: no cabe a 32px. */
.prme-metric__value--sm {
  font-size: var(--prme-headline-md-size);
  line-height: var(--prme-headline-md-line);
}

/* Checkbox alineado con la línea base de los campos de al lado en una fila. */
.prme-form-field--check { display: flex; align-items: center; padding-top: var(--prme-space-6); }

/* Muestra de color de un símbolo DP en la tabla de gestión. El color lo pone la
   clase .pl-code-* generada desde los datos (ver PlanCodeCss). */
.prme-code-swatch {
  display: inline-block;
  min-width: 44px;
  padding: 2px var(--prme-space-2);
  border: 1px solid var(--prme-outline-variant);
  border-radius: var(--prme-radius-sm);
  font-weight: 700;
  text-align: center;
}

/* --------------------------------- filtro -------------------------------- */

/* El filtro es una barra de herramientas, no una tarjeta: manda el resultado, no
   el formulario que lo pide. Sin sombra y sobre gris se lee como parte del
   armazón de la pantalla y deja el blanco elevado para los datos. */
.prme-filter {
  margin-bottom: var(--prme-stack);
  background: var(--prme-surface-low);
  border-color: var(--prme-outline-variant);
  box-shadow: none;
}

/*
   Flex y no grid. Con `grid-template-columns: repeat(3, 1fr) auto` un filtro de
   cuatro campos —AppLog— empujaba las acciones a una segunda fila y metía 70px de
   blanco entre el título y el primer dato. Y la corrección evidente,
   `repeat(auto-fit, minmax(180px,1fr)) auto`, es CSS inválido: una repetición
   automática no admite tracks intrínsecos al lado, así que el navegador tira toda
   la declaración. Con flex los campos se reparten el ancho que haya y las
   acciones se quedan al final de la última fila sin caso especial.
*/
.prme-filter__body {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: var(--prme-space-3) var(--prme-space-4);
}

/* min-width:0 para que un campo largo pueda encogerse en vez de desbordar. */
.prme-filter__body > .prme-form-field {
  flex: 1 1 100%;
  min-width: 0;
}

@media (min-width: 768px) {
  .prme-filter__body > .prme-form-field { flex: 1 1 180px; }

  /* Variante para una caja de búsqueda libre: se lleva el doble de ancho que los
     selectores porque es donde se escribe, no donde se elige. */
  .prme-filter__body--search > .prme-form-field:first-child { flex-grow: 2; }
}

/* margin-left:auto empuja las acciones al extremo derecho de su fila, tanto si
   comparten fila con los campos como si han bajado a la siguiente. */
.prme-filter__actions {
  display: flex;
  flex: 0 0 auto;
  gap: var(--prme-space-2);
  margin-left: auto;
}

.prme-filter .prme-form-field { margin-bottom: 0; }

/* ------------------------------ lista de datos --------------------------- */

.prme-dl {
  display: grid;
  grid-template-columns: minmax(120px, auto) 1fr;
  gap: var(--prme-space-2) var(--prme-space-4);
  margin: 0;
}

.prme-dl dt {
  color: var(--prme-on-surface-variant);
  font-size: var(--prme-label-md-size);
  font-weight: 600;
  letter-spacing: .05em;
  text-transform: uppercase;
}

.prme-dl dd { margin: 0; }

/* ----------------------------- días laborables --------------------------- */

.prme-workdays {
  display: flex;
  flex-wrap: wrap;
  gap: var(--prme-space-2);
  margin: 0;
  padding: 0;
  list-style: none;
}

.prme-workdays__item {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 96px;
  padding: var(--prme-space-2) var(--prme-space-3);
  border: 1px solid var(--prme-outline-variant);
  border-radius: var(--prme-radius-control);
  background: var(--prme-surface-low);
  color: var(--prme-on-surface-variant);
}

.prme-workdays__item--on {
  border-color: var(--prme-primary);
  background: var(--prme-primary-fixed);
  color: var(--prme-on-primary-fixed);
}

.prme-workdays__day { font-size: var(--prme-label-md-size); font-weight: 600; letter-spacing: .05em; text-transform: uppercase; }

.prme-workdays__state { font-weight: 600; }

/* -------------------------------- pestañas ------------------------------- */

.prme-tabs {
  display: flex;
  gap: var(--prme-space-1);
  margin-bottom: var(--prme-space-6);
  overflow-x: auto;
  border-bottom: 1px solid var(--prme-outline-variant);
}

.prme-tabs__link {
  padding: var(--prme-space-2) var(--prme-space-4);
  border-bottom: 2px solid transparent;
  color: var(--prme-on-surface-variant);
  font-weight: 600;
  text-decoration: none;
  white-space: nowrap;
}

.prme-tabs__link:hover { color: var(--prme-on-surface); }

.prme-tabs__link--active {
  border-bottom-color: var(--prme-primary);
  color: var(--prme-primary);
}

.prme-tabs__link:focus-visible {
  outline: var(--prme-focus-ring);
  outline-offset: calc(var(--prme-focus-offset) * -1);
}

/* ------------------------------ feature flags ---------------------------- */

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

.prme-feature {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--prme-space-3);
  padding: var(--prme-space-3) var(--prme-space-4);
  border-bottom: 1px solid var(--prme-outline-variant);
}

.prme-feature:last-child { border-bottom: 0; }

.prme-feature__text { display: flex; flex: 1 1 260px; flex-direction: column; gap: 2px; min-width: 0; }

.prme-feature__name { font-weight: 600; }

.prme-feature__hint { color: var(--prme-on-surface-variant); font-size: var(--prme-data-size); }

.prme-feature__state { display: flex; flex: 0 0 auto; align-items: center; gap: var(--prme-space-2); }

/* ---------------------------- formulario en línea ------------------------ */

.prme-form-inline {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: var(--prme-space-3);
}

.prme-form-inline .prme-form-field { margin-bottom: 0; }

.prme-hint { margin: var(--prme-space-1) 0 0; font-size: var(--prme-label-md-size); }

/* Diálogos con tabla dentro (reparto de vacaciones) necesitan más ancho. */
.prme-modal__panel--wide { max-width: 680px; }

.prme-modal__section {
  margin: 0 0 var(--prme-space-3);
  font-size: var(--prme-body-lg-size);
  font-weight: 600;
}

.prme-input--narrow { max-width: 110px; }

/* Cifra negativa en una tabla de saldos: el rojo la señala, pero el signo menos
   ya la identifica sin depender del color. */
.prme-negative { color: var(--prme-error); }
.prme-positive { color: var(--prme-success); }

/* Acción alineada a la derecha en la cabecera de una tarjeta. */
.prme-card__action { margin-left: auto; }

/* Tarjeta que es un enlace: hereda color y quita el subrayado. */
.prme-card-link { color: inherit; text-decoration: none; display: block; }

/* ------------------------------- desglose -------------------------------- */

.prme-breakdown {
  display: flex;
  flex-wrap: wrap;
  gap: var(--prme-space-2);
  margin: 0;
  padding: 0;
  list-style: none;
}

.prme-breakdown__item {
  display: flex;
  align-items: center;
  gap: var(--prme-space-2);
  padding: var(--prme-space-2) var(--prme-space-3);
  border: 1px solid var(--prme-outline-variant);
  border-radius: var(--prme-radius-control);
  background: var(--prme-surface-low);
}

.prme-breakdown__label { font-weight: 600; }

/* ---------------------------- notificaciones ----------------------------- */

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

.prme-notif {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--prme-space-3);
  padding: var(--prme-space-3) var(--prme-space-4);
  border-bottom: 1px solid var(--prme-outline-variant);
  border-left: 3px solid transparent;
}

.prme-notif:last-child { border-bottom: 0; }

/* No leída: barra en color + negrita. El color no es el único indicador. */
.prme-notif--unread {
  border-left-color: var(--prme-primary);
  background: var(--prme-surface-low);
}

.prme-notif--unread .prme-notif__title { font-weight: 700; }

.prme-notif__text { display: flex; flex-direction: column; gap: 2px; min-width: 0; }

.prme-notif__title { font-weight: 600; }

.prme-notif__message { color: var(--prme-on-surface-variant); font-size: var(--prme-data-size); }

.prme-notif__date { color: var(--prme-outline); font-size: var(--prme-label-md-size); }

/* -------------------------------- applog --------------------------------- */

/* Los mensajes de log son largos: se acotan para que la tabla siga siendo legible,
   con el texto completo disponible al seleccionarlo. */
.prme-log__message {
  max-width: 60ch;
  font-family: ui-monospace, "Cascadia Mono", Menlo, monospace;
  font-size: 12px;
  white-space: pre-wrap;
  word-break: break-word;
}

/* El origen es un espacio de nombres: recortarlo por la derecha se come justo la
   parte que informa (AuthLogic) y deja el prefijo, que siempre es el mismo. En
   escritorio se recorta igualmente para no robar ancho al mensaje, pero la vista
   pone el valor completo en title. */
.prme-log__source {
  max-width: 26ch;
  overflow: hidden;
  color: var(--prme-on-surface-variant);
  font-size: var(--prme-label-md-size);
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* En móvil la fila es una tarjeta y el origen tiene toda la línea para él: ahí no
   hay motivo para recortar, y el title no se puede consultar sin ratón. */
@media (max-width: 767.98px) {
  .prme-log__source {
    max-width: none;
    overflow: visible;
    white-space: normal;
    word-break: break-word;
  }
}

.prme-input--email { max-width: 360px; }

/* ------------------------------ interruptor ------------------------------ */

/*
   Toggle del prototipo. Es un <input type="checkbox"> de verdad, solo repintado:
   conserva el foco por teclado, la barra espaciadora, el envío del formulario y
   lo que anuncia un lector de pantalla. Un <div> con JS no daría nada de eso.
*/
.prme-switch {
  display: inline-flex;
  align-items: center;
  gap: var(--prme-space-2);
  cursor: pointer;
}

.prme-switch__input {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
}

.prme-switch__track {
  position: relative;
  flex: 0 0 auto;
  width: 40px;
  height: 24px;
  border-radius: var(--prme-radius-pill);
  background: var(--prme-outline-variant);
  transition: background-color 150ms ease;
}

.prme-switch__track::after {
  content: "";
  position: absolute;
  top: 4px;
  left: 4px;
  width: 16px;
  height: 16px;
  border-radius: var(--prme-radius-pill);
  background: var(--prme-surface-lowest);
  box-shadow: 0 1px 2px rgb(0 0 0 / 25%);
  transition: transform 150ms ease;
}

.prme-switch__input:checked + .prme-switch__track { background: var(--prme-primary); }

.prme-switch__input:checked + .prme-switch__track::after { transform: translateX(16px); }

.prme-switch__input:focus-visible + .prme-switch__track {
  outline: var(--prme-focus-ring);
  outline-offset: var(--prme-focus-offset);
}

.prme-switch__input:disabled + .prme-switch__track { opacity: .5; cursor: not-allowed; }

.prme-switch__label { font-size: var(--prme-data-size); }

/* El estado también va en texto, no solo en la posición del interruptor. */
.prme-switch__state { color: var(--prme-on-surface-variant); font-size: var(--prme-label-md-size); font-weight: 600; }

@media (prefers-reduced-motion: reduce) {
  .prme-switch__track,
  .prme-switch__track::after { transition: none; }
}

/* --------------------------- sesión suplantada ---------------------------- */
/* Franja de aviso mientras se navega como otro empleado. Usa el color de aviso
   del tema, no uno propio: si la compañía cambia su paleta, esto la sigue. */

.prme-impersonation {
  display: flex;
  align-items: center;
  gap: var(--prme-space-3);
  flex-wrap: wrap;
  padding: var(--prme-space-2) var(--prme-gutter);
  background: var(--prme-warning-container);
  color: var(--prme-on-surface);
  border-bottom: 2px solid var(--prme-warning);
  font-size: var(--prme-label-md-size);
}

.prme-impersonation__text { flex: 1 1 auto; min-width: 0; }

.prme-impersonation__sep { color: var(--prme-on-surface-variant); margin: 0 var(--prme-space-1); }

.prme-impersonation__form { flex: 0 0 auto; }

/* ------------------------- solicitudes pendientes ------------------------- */
/* Listado compacto dentro del diálogo que abre la barra del planner. */

.prme-pending {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--prme-space-2);
}

.prme-pending__item {
  display: flex;
  align-items: center;
  gap: var(--prme-space-3);
  padding: var(--prme-space-3);
  border-radius: var(--prme-radius-md);
  background: var(--prme-surface-container);
  /* Barra lateral de aviso: son cosas que esperan una decisión. */
  border-left: 3px solid var(--prme-warning);
}

.prme-pending__text {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.prme-pending__name { font-weight: 600; font-size: var(--prme-data-size); }

.prme-pending__meta { color: var(--prme-on-surface-variant); font-size: var(--prme-label-md-size); }

.prme-pending__reason {
  color: var(--prme-on-surface-variant);
  font-size: var(--prme-label-md-size);
  font-style: italic;
}

@media (max-width: 575.98px) {
  .prme-pending__item { flex-wrap: wrap; }
}

/* ---------------------------- calendario de festivos ---------------------- */

.cal-summary {
  display: flex;
  align-items: center;
  gap: var(--prme-space-2);
  flex-wrap: wrap;
  margin-bottom: var(--prme-space-4);
}

/* El botón de añadir se va al extremo: el resumen es lectura, esto es acción. */
.cal-summary__add { margin-left: auto; }

.cal-date { font-variant-numeric: tabular-nums; }

/* El día de la semana importa: un festivo que cae en sábado no cambia nada. */
.cal-weekday {
  display: block;
  color: var(--prme-on-surface-variant);
  font-size: var(--prme-label-md-size);
}

/* ------------------------------ saldos ------------------------------------ */

.bal-num { text-align: right; font-variant-numeric: tabular-nums; }

/* Un período sin días asignados ni consumidos existe, pero no dice nada: se
   atenúa para que no compita con los que sí. No se oculta — esconder filas hace
   dudar de si el dato está o falta. */
.bal-row--empty { color: var(--prme-on-surface-variant); }

.bal-row--empty strong { font-weight: 400; }

@media (max-width: 767.98px) {
  .bal-num { text-align: left; }
}

/* Listas de selección múltiple dentro de un diálogo (reglas del símbolo DP).
   Se usan checkboxes y no un <select multiple> porque el select nativo obliga a
   Ctrl+clic, que en móvil no existe. */
.prme-fieldset {
  border: 0;
  margin: 0 0 var(--prme-space-4);
  padding: 0;
  min-inline-size: 0;
}

.prme-fieldset > legend {
  float: none;
  width: auto;
}

.prme-checklist {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr));
  gap: var(--prme-space-1) var(--prme-space-4);
  /* Con plantillas grandes esta lista crece sin fin: se limita y desplaza dentro
     del diálogo, no arrastrando toda la página. */
  max-block-size: 15rem;
  overflow-y: auto;
  padding: var(--prme-space-2);
  border: 1px solid var(--prme-outline-variant);
  border-radius: var(--prme-radius-control);
}

.prme-checklist__item {
  display: flex;
  align-items: center;
  gap: var(--prme-space-2);
  padding: var(--prme-space-1) 0;
  cursor: pointer;
}

.prme-checklist__item > span {
  overflow-wrap: anywhere;
}

/* Conjunto de valores de una regla: se envuelven en vez de estirar la columna. */
.prme-chip-list {
  display: flex;
  flex-wrap: wrap;
  gap: var(--prme-space-1);
  margin: 0;
  padding: 0;
  list-style: none;
}

/* Diálogo de ayuda: texto largo agrupado en secciones. Sin decorado — se lee una
   vez y se cierra. */
.prme-help__section { margin-bottom: var(--prme-space-6); }
.prme-help__section:last-child { margin-bottom: 0; }

.prme-help__title {
  font-size: .78rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .06em;
  color: var(--prme-on-surface-variant);
  margin-bottom: var(--prme-space-2);
}

.prme-help__flow,
.prme-help__steps,
.prme-help__list {
  margin: 0;
  padding: 0;
  list-style: none;
}

/* El ciclo de estados se envuelve en pantallas estrechas en vez de desbordar. */
.prme-help__flow {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--prme-space-2);
}

.prme-help__flow-arrow,
.prme-help__flow-or { color: var(--prme-on-surface-variant); }

.prme-help__steps {
  display: flex;
  flex-direction: column;
  gap: var(--prme-space-2);
  counter-reset: prme-help-step;
}

.prme-help__step {
  counter-increment: prme-help-step;
  padding: var(--prme-space-3);
  padding-inline-start: var(--prme-space-8);
  border-radius: var(--prme-radius-control);
  background: var(--prme-surface-low);
  position: relative;
}

/* El número lo pone CSS: es orden visual, no contenido que deba leerse aparte. */
.prme-help__step::before {
  content: counter(prme-help-step);
  position: absolute;
  inset-inline-start: var(--prme-space-3);
  inset-block-start: var(--prme-space-3);
  inline-size: 1.5rem;
  block-size: 1.5rem;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: var(--prme-primary);
  color: var(--prme-on-primary);
  font-size: .75rem;
  font-weight: 700;
}

.prme-help__step-title { font-weight: 600; margin-bottom: var(--prme-space-1); }

.prme-help__terms { margin: var(--prme-space-2) 0 0; }
.prme-help__terms > dt { font-weight: 600; }
.prme-help__terms > dd { margin: 0 0 var(--prme-space-2); }

.prme-help__list {
  display: flex;
  flex-direction: column;
  gap: var(--prme-space-2);
}

.prme-help__list > li {
  padding: var(--prme-space-3);
  border: 1px solid var(--prme-outline-variant);
  border-radius: var(--prme-radius-control);
}

/* Aviso dentro de una celda: una regla que apunta a registros que ya no existen.
   Se pinta en la fila y no solo en un resumen porque lo que hay que reparar es
   esa regla, y quien la mira necesita ver el identificador huérfano. */
.prme-warning {
  display: flex;
  align-items: flex-start;
  gap: var(--prme-space-2);
  margin: 0;
  color: var(--prme-warning);
  font-size: .8rem;
}

.prme-warning > .prme-icon { flex-shrink: 0; margin-top: .1em; }

/* El identificador crudo: monoespaciado y partible, porque es un Guid y no cabe. */
.prme-warning__detail {
  display: block;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: .72rem;
  color: var(--prme-on-surface-variant);
  overflow-wrap: anywhere;
}

/* ------------------------------ barra de carga --------------------------- */

/* Fija arriba del todo y por encima de cualquier diálogo: es la única señal de
   que el servidor está trabajando, y taparla la haría inútil. */
.prme-progress {
  position: fixed;
  inset-block-start: 0;
  inset-inline: 0;
  block-size: 3px;
  z-index: 2000;
  pointer-events: none;
  background: transparent;
}

.prme-progress__bar {
  block-size: 100%;
  inline-size: 0;
  background: var(--prme-primary);
  /* Ancho: sigue al reloj del módulo. Opacidad: solo para el desvanecido final. */
  transition: inline-size .22s ease-out, opacity .2s ease-out;
}

.prme-progress--done .prme-progress__bar { opacity: 0; }

@media (prefers-reduced-motion: reduce) {
  .prme-progress__bar { transition: none; }
}

/* La rejilla del planner mientras htmx la sustituye. Se atenúa en vez de vaciarse:
   el mes anterior sigue siendo la mejor referencia hasta que llegue el nuevo, y
   dejar el hueco en blanco haría saltar la página. */
.prme-swapping.htmx-request {
  opacity: .45;
  transition: opacity .15s ease-out;
  pointer-events: none;
}

/* Caja de filtro sobre una lista de casillas. La pinta el JS, así que no existe
   si no hay JS — y entonces la lista sigue completa, solo hay que desplazarse. */
.prme-checklist-tools {
  display: flex;
  align-items: center;
  gap: var(--prme-space-3);
  margin-bottom: var(--prme-space-2);
}

.prme-checklist-tools > input { max-inline-size: 18rem; }

.prme-checklist-tools__count { font-size: .8rem; white-space: nowrap; }

/* ------------------------------ campo + botón ---------------------------- */

/* Un campo y su botón como una sola pieza. Sueltos, y con el campo a tamaño normal
   junto a un botón pequeño, parecían dos controles sin relación. */
.prme-input-group {
  display: flex;
  align-items: stretch;
  min-inline-size: 0;
}

.prme-input-group > .form-control {
  inline-size: 6.5rem;
  border-start-end-radius: 0;
  border-end-end-radius: 0;
  text-align: center;
  font-variant-numeric: tabular-nums;
}

.prme-input-group > .btn {
  border-start-start-radius: 0;
  border-end-start-radius: 0;
  /* Los bordes se solapan en vez de sumarse: si no, la juntura sale de 2 px. */
  margin-inline-start: -1px;
  white-space: nowrap;
}

/* El foco tiene que verse por encima del vecino, o la mitad del cerco queda tapada. */
.prme-input-group > :focus-visible { position: relative; z-index: 1; }

/* En la cabecera de una tarjeta el sitio es el que es: el botón se queda en icono. */
.prme-input-group--sm > .form-control,
.prme-input-group--sm > .btn {
  padding-block: var(--prme-space-1);
  font-size: .85rem;
}

.prme-input-group--sm > .form-control { inline-size: 5rem; }

/* Días laborables como fila de iniciales. El día que no se trabaja se apaga, pero
   el estado también va en el title de cada uno: el color por sí solo no es
   información accesible. */
.prme-weekdays {
  display: flex;
  flex-wrap: wrap;
  gap: var(--prme-space-2);
  margin: 0;
  padding: 0;
  list-style: none;
}

.prme-weekdays__day {
  inline-size: 2rem;
  block-size: 2rem;
  display: grid;
  place-items: center;
  border-radius: 50%;
  border: 1px solid var(--prme-outline-variant);
  color: var(--prme-on-surface-variant);
  font-size: .8rem;
  font-weight: 600;
}

.prme-weekdays__day--on {
  background: var(--prme-primary);
  border-color: var(--prme-primary);
  color: var(--prme-on-primary);
}

/* Sin el subrayado punteado del navegador: aquí abbr se usa por el title, no como
   abreviatura que haya que señalar. */
.prme-weekdays__day abbr { text-decoration: none; cursor: help; }

/* ---------------------------- historial de cambios ------------------------ */

/* Agrupado por día. El día es la unidad con la que se piensa un planning, así que
   la cabecera de fecha manda sobre la hora concreta del cambio. */
.prme-audit__day { margin-bottom: var(--prme-space-6); }
.prme-audit__day:last-child { margin-bottom: 0; }

.prme-audit__date {
  font-size: .78rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .06em;
  color: var(--prme-on-surface-variant);
  margin-bottom: var(--prme-space-2);
  padding-bottom: var(--prme-space-1);
  border-bottom: 1px solid var(--prme-outline-variant);
}

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

/* Cada cambio en una línea que se envuelve: acción, códigos, contexto y quién. */
.prme-audit__entry {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--prme-space-2);
  padding-block: var(--prme-space-2);
}

.prme-audit__entry + .prme-audit__entry { border-top: 1px solid var(--prme-outline-variant); }

.prme-audit__codes {
  display: flex;
  align-items: center;
  gap: var(--prme-space-2);
}

.prme-audit__arrow { color: var(--prme-on-surface-variant); }

/* Quién y cuándo, al final de la línea: es el dato que se busca cuando ya se ha
   entendido qué cambió. */
.prme-audit__who {
  margin-inline-start: auto;
  font-size: .78rem;
  white-space: nowrap;
}

/* ------------------------------ validación ------------------------------- */

/*
    Dos momentos distintos, y los dos tienen que verse:

    · Antes de enviar — :user-invalid. Se pinta solo después de que la persona haya
      tocado el campo o intentado enviar, no desde que la página carga: un campo
      vacío recién abierto no es un error, es un campo vacío.

    · Después de enviar — .input-validation-error, que pone MVC al volver a pintar
      la vista. Sin esta regla el servidor rechazaba el formulario y no se veía
      dónde, que es exactamente lo que pasaba con las políticas.
*/
.form-control:user-invalid,
.form-select:user-invalid,
.form-control.prme-invalid,
.form-select.prme-invalid,
.form-control.input-validation-error,
.form-select.input-validation-error {
  border-color: var(--prme-error);
}

.form-control:user-invalid:focus,
.form-select:user-invalid:focus,
.form-control.prme-invalid:focus,
.form-select.prme-invalid:focus,
.form-control.input-validation-error:focus,
.form-select.input-validation-error:focus {
  border-color: var(--prme-error);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--prme-error) 25%, transparent);
}

/* El mensaje de cada campo. La clase la pone MVC, así que funciona en cualquier
   formulario aunque la vista no haya puesto una clase propia. */
.field-validation-error {
  display: block;
  margin-top: var(--prme-space-1);
  color: var(--prme-error);
  font-size: .8rem;
}

.field-validation-valid { display: none; }

/* Resumen arriba: en un formulario largo el campo que falla puede estar fuera de
   la pantalla, y sin esto se envía, no pasa nada visible, y parece que se perdió. */
.validation-summary-errors { margin: 0; }
.validation-summary-errors ul { margin: 0; padding-inline-start: 1.2rem; }
.validation-summary-valid { display: none; }

/* Marca de obligatorio en la etiqueta. Con title, no solo con el asterisco: un
   símbolo suelto no dice qué significa. */
.form-label .prme-required {
  color: var(--prme-error);
  margin-inline-start: .15rem;
  cursor: help;
}

/* ------------------------- tarjeta que es un enlace ----------------------- */

/*
    En el inicio conviven tarjetas que solo informan y tarjetas que llevan a algún
    sitio, y se veían iguales: "New Request" parecía un dato más, no algo que se
    pueda pulsar. Estas se distinguen por el cursor, la flecha, el color del texto
    de acción y el movimiento al pasar por encima.
*/
.prme-card-link {
  position: relative;
  cursor: pointer;
  transition: transform .12s ease-out, box-shadow .12s ease-out, border-color .12s ease-out;
}

/* Flecha en la esquina. Decorativa: el enlace ya se anuncia como tal. */
.prme-card-link::after {
  content: "";
  position: absolute;
  inset-block-start: var(--prme-space-4);
  inset-inline-end: var(--prme-space-4);
  inline-size: .5rem;
  block-size: .5rem;
  border-inline-end: 2px solid var(--prme-primary);
  border-block-start: 2px solid var(--prme-primary);
  transform: rotate(45deg);
  transition: transform .12s ease-out;
}

.prme-card-link:hover,
.prme-card-link:focus-visible {
  border-color: var(--prme-primary);
  box-shadow: var(--prme-shadow-2);
  transform: translateY(-2px);
}

.prme-card-link:hover::after,
.prme-card-link:focus-visible::after { transform: rotate(45deg) translate(2px, -2px); }

/* La línea de acción, en color de marca: es lo que se va a hacer al pulsar, no una
   cifra que leer. Deja sitio a la flecha para no chocar con ella. */
.prme-card-link .prme-metric__value {
  color: var(--prme-primary);
  padding-inline-end: var(--prme-space-6);
}

@media (prefers-reduced-motion: reduce) {
  .prme-card-link,
  .prme-card-link::after { transition: none; }
  .prme-card-link:hover,
  .prme-card-link:focus-visible { transform: none; }
}

/* Panel estrecho: confirmaciones y avisos, donde el texto es una línea. */
.prme-modal__panel--narrow { max-inline-size: 26rem; }

/* ------------------------- consejo de equilibrio -------------------------- */

/* Bloque de observaciones para quien aprueba. Deliberadamente sobrio: no compite con
   los botones de aprobar y rechazar, porque no manda sobre ellos. */
.adv {
  margin-block: var(--prme-space-6);
  padding: var(--prme-space-4);
  border: 1px solid var(--prme-outline-variant);
  border-radius: var(--prme-radius-control);
  background: var(--prme-surface-low);
}

.adv__title {
  display: flex;
  align-items: center;
  gap: var(--prme-space-2);
  font-size: .85rem;
  font-weight: 600;
  margin: 0;
}

.adv__disclaimer { font-size: .78rem; margin: var(--prme-space-1) 0 var(--prme-space-3); }

.adv__row {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--prme-space-2);
  padding-block: var(--prme-space-2);
}

.adv__row + .adv__row { border-top: 1px solid var(--prme-outline-variant); }

.adv__row > .prme-metric__label { flex: 0 0 10rem; }

.adv__value {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--prme-space-2);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

.adv__of { font-weight: 400; font-size: .8rem; }

/* ── Pie legal y aviso de cookies ────────────────────────────────────────────
   Los dos viven aquí y no en layout.css porque salen en los dos layouts: el de
   la aplicación y el de las pantallas de acceso. */

.prme-legal {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--prme-space-3);
  padding: var(--prme-space-3) var(--prme-gutter);
  border-top: 1px solid var(--prme-outline-variant);
  color: var(--prme-on-surface-variant);
  font-size: var(--prme-label-md-size);
}

.prme-legal__link,
.prme-legal__button {
  color: inherit;
  text-decoration: underline;
}

/* El botón de retirar el consentimiento se lee como un enlace: es una acción
   menor del pie, no una llamada a la acción. Va en <form> porque cambia estado. */
.prme-legal__form { display: contents; }

.prme-legal__button {
  padding: 0;
  border: 0;
  background: none;
  font: inherit;
  cursor: pointer;
}

.prme-legal__link:hover,
.prme-legal__button:hover { color: var(--prme-primary); }

.prme-cookie {
  position: fixed;
  inset-inline: 0;
  inset-block-end: 0;
  z-index: 50;
  background: var(--prme-surface-highest);
  border-top: 1px solid var(--prme-outline);
  box-shadow: var(--prme-shadow-2);
}

.prme-cookie__inner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--prme-space-4);
  max-width: 72rem;
  margin-inline: auto;
  padding: var(--prme-space-4) var(--prme-gutter);
}

.prme-cookie__text {
  flex: 1 1 20rem;
  margin: 0;
  color: var(--prme-on-surface);
  font-size: var(--prme-body-md-size);
  line-height: var(--prme-body-md-line);
}

.prme-cookie__link { margin-inline-start: var(--prme-space-1); }

.prme-cookie__actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--prme-space-2);
}
