/* ===========================================================================
   Edmundo Ríos School — components.css
   Tarjetas, botones, formularios, badges, tablas, alertas.

   Criterio visual: mucho aire, borde fino (var(--bw), 1px) y nada de sombras
   difusas. La marca es de cancha — una escuela de fútbol, no un tablero de
   control — así que la jerarquía la dan el espacio y la tipografía, no el peso.
   Se lee igual en el celular a plena luz en la banqueta y en modo noche a las
   6 a. m. antes de la primera clase.
   =========================================================================== */

/* ── Tarjetas ─────────────────────────────────────────────────────────────── */
.card {
  background: var(--surface);
  border: var(--bw) solid var(--border);
  border-radius: var(--radius);
  padding: 1.125rem;
}
.card-pad-sm { padding: .75rem; }
.card-pad-lg { padding: 1.5rem; }

.card-head {
  display: flex; align-items: center; gap: .625rem;
  margin: -.25rem 0 .875rem;
}
.card-head h2, .card-head h3 { margin: 0; }
.card-body > :last-child { margin-bottom: 0; }

/* Tarjeta con acento del contexto: barra superior del color del rol */
.card-accent { border-top: 4px solid var(--accent); }
.card-hover { transition: border-color .15s, transform .15s; }
.card-hover:hover { border-color: var(--accent); transform: translateY(-2px); }

/* Tarjeta de bienvenida del dashboard */
.card-welcome {
  background: var(--accent-soft);
  border-color: var(--accent);
}

/* ── Botones ──────────────────────────────────────────────────────────────── */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: .5rem;
  padding: .6875rem 1.125rem;
  border: var(--bw) solid transparent;
  border-radius: var(--radius-sm);
  /* Caja de frase, no versalitas. El texto de un botón es una ORDEN que se
     lee («Entrar», «Crear cuenta»), no una etiqueta de sistema: en versales
     y con tracking se lee más despacio y grita.

     Las versalitas se quedan donde sí son micro-etiquetas y no frases: los
     badges de estado y las cabeceras de tabla. */
  font-weight: 600; font-size: .875rem; line-height: 1.2;
  letter-spacing: 0;
  text-decoration: none; white-space: nowrap;
  /* 44px: el mínimo táctil que se puede tocar sin fallar en un celular */
  min-height: 44px;
  transition: background-color .15s, border-color .15s, color .15s, transform .06s;
  user-select: none;
}
.btn:hover { text-decoration: none; }
.btn:active { transform: translateY(1px); }
.btn:disabled, .btn.is-disabled { opacity: .5; cursor: not-allowed; transform: none; }

.btn-primary {
  background: var(--accent); color: var(--accent-ink); border-color: var(--accent);
}
.btn-primary:hover:not(:disabled) { filter: brightness(1.08); }

.btn-outline {
  background: transparent; color: var(--accent); border-color: var(--accent);
}
.btn-outline:hover:not(:disabled) { background: var(--accent-soft); }

.btn-ghost { background: transparent; color: var(--text); border-color: var(--border); }
.btn-ghost:hover:not(:disabled) { border-color: var(--accent); color: var(--accent); }

.btn-danger { background: var(--danger); color: #fff; border-color: var(--danger); }
.btn-danger:hover:not(:disabled) { filter: brightness(1.08); }

.btn-plain { background: transparent; color: var(--muted); border-color: transparent; }
.btn-plain:hover:not(:disabled) { color: var(--text); background: var(--surface-2); }

.btn-sm  { padding: .4375rem .75rem; font-size: .8125rem; min-height: 36px; }
.btn-lg  { padding: .875rem 1.5rem; font-size: 1.0625rem; min-height: 52px; }
.btn-block { display: flex; width: 100%; }
.btn-icon { padding: .5rem; min-height: 44px; min-width: 44px; }

/* Botón cargando: el texto se atenúa y aparece un spinner */
.btn.is-loading { pointer-events: none; position: relative; color: transparent !important; }
.btn.is-loading::after {
  content: ''; position: absolute; width: 18px; height: 18px;
  border: 2px solid currentColor; border-top-color: transparent; border-radius: 50%;
  animation: spin .6s linear infinite;
  color: var(--accent-ink);
}
.btn-outline.is-loading::after, .btn-ghost.is-loading::after { color: var(--accent); }
@keyframes spin { to { transform: rotate(360deg); } }

/* ── Formularios ──────────────────────────────────────────────────────────── */
.field { margin-bottom: 1rem; }
.label {
  display: block; margin-bottom: .375rem;
  font-weight: 600; font-size: .875rem; color: var(--text);
}
.label .req { color: var(--danger); margin-left: .125rem; }
.label .opt { color: var(--muted); font-weight: 400; margin-left: .25rem; font-size: .8125rem; }

.input, .select, .textarea {
  width: 100%;
  padding: .6875rem .875rem;
  background: var(--surface);
  color: var(--text);
  border: var(--bw) solid var(--border);
  border-radius: var(--radius-sm);
  min-height: 46px;
  transition: border-color .15s, box-shadow .15s;
  appearance: none;
}
.input::placeholder, .textarea::placeholder { color: var(--muted); }
.input:focus, .select:focus, .textarea:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
}
.input:disabled, .select:disabled, .textarea:disabled {
  background: var(--surface-2); color: var(--muted); cursor: not-allowed;
}
.textarea { min-height: 110px; resize: vertical; line-height: 1.5; }

.select {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23888' stroke-width='2'%3E%3Cpath d='M4 6l4 4 4-4'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right .75rem center;
  background-size: 16px;
  padding-right: 2.25rem;
}

.field.has-error .input, .field.has-error .select, .field.has-error .textarea {
  border-color: var(--danger);
}
.field-error { display: block; margin-top: .3125rem; font-size: .8125rem; color: var(--danger); font-weight: 500; }
.field-hint  { display: block; margin-top: .3125rem; font-size: .8125rem; color: var(--muted); }

/* Input con prefijo (lada telefónica, etc.) */
.input-group { display: flex; }
.input-group > .select { width: auto; flex: 0 0 auto; border-radius: var(--radius-sm) 0 0 var(--radius-sm); border-right: 0; }
/* min-width:0 es obligatorio aquí: por defecto un elemento flex no encoge por
   debajo de su min-content, y el min-content de un <input> lo fija su atributo
   `size` (~180px). Sumado al select de la lada, que no encoge, el grupo se salía
   de la pantalla en celulares de 320px. */
.input-group > .input  { min-width: 0; flex: 1 1 auto; border-radius: 0 var(--radius-sm) var(--radius-sm) 0; }

/* Botón pegado al campo (ojo de la contraseña, "copiar", "probar"…).
   Vive AQUÍ y no en auth.css porque lo usan también /super/whatsapp,
   /super/correo y /super/almacenamiento, que no cargan el CSS del acceso: sin
   esta regla ese botón salía sin estilo en las tres pantallas. */
.input-addon {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 48px;                      /* tocable con el pulgar */
  padding: 0 .75rem;
  background: var(--surface);
  border: var(--bw) solid var(--border);
  border-left: 0;
  border-top-right-radius: var(--radius-sm);
  border-bottom-right-radius: var(--radius-sm);
  color: var(--muted);
  cursor: pointer;
  transition: color .15s;
}
.input-addon:hover { color: var(--text); }
.input-addon[aria-pressed="true"] { color: var(--accent); }

/* Variante ENMARCADA: el borde lo dibuja el grupo, no cada pieza, para que un
   icono guía y un botón quepan dentro del mismo recuadro y se lean como un solo
   control. Va como modificador y NO sobre `.input-group` a secas a propósito: el
   grupo normal lo usa la lada + celular del registro y del perfil, donde cada
   pieza SÍ pinta su borde — dárselo a todos dejaba ese campo con doble marco. */
.input-group.-framed {
  align-items: stretch;
  background: var(--surface);
  border: var(--bw) solid var(--border);
  border-radius: var(--radius-sm);
  transition: border-color .15s, box-shadow .15s;
}
.input-group.-framed > .input {
  background: transparent;
  border: 0;
  border-radius: 0;
}
/* El campo deja de dibujar su propio foco: lo dibuja el marco entero, para que
   el anillo rodee también al icono y al botón. */
.input-group.-framed > .input:focus,
.input-group.-framed > .input:focus-visible { outline: none; box-shadow: none; }
.input-group.-framed:focus-within {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 18%, transparent);
}
.input-group.-framed > .input-addon {
  background: transparent;
  border: 0;
  border-radius: var(--radius-sm);
}

/* ── Lada + número ────────────────────────────────────────────────────────
   Vive AQUÍ y no en cada módulo: lo usan el registro, el perfil y el contacto
   de emergencia del cuestionario de salud. Estaba copiado, idéntico, en dos
   archivos; el tercero habría sido el que se quedara atrás el día que alguien
   ajuste el ancho. */
.input-group .phone-code {
  flex: 0 0 7.5rem;
  border-top-right-radius: 0;
  border-bottom-right-radius: 0;
  border-right: 0;
}
.input-group .phone-code + .input {
  border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
  border-left: var(--bw) solid var(--border);
  border-right: var(--bw) solid var(--border);
}

/* Icono guía a la izquierda del campo. Decorativo: la etiqueta de arriba es la
   que nombra el campo, así que no se anuncia ni recibe foco. */
.input-lead {
  display: inline-flex; align-items: center;
  padding-inline: .75rem .125rem;
  color: var(--muted);
  pointer-events: none;
}
.input-group.-framed:focus-within .input-lead { color: var(--accent); }

/* Checkbox / radio */
.check { display: flex; align-items: flex-start; gap: .625rem; cursor: pointer; padding: .25rem 0; }
.check input { width: 20px; height: 20px; margin: .125rem 0 0; accent-color: var(--accent); flex: 0 0 auto; cursor: pointer; }
.check span { font-size: .9375rem; }

/* Opciones tipo tarjeta (el onboarding las usa en vez de <select>: se tocan
   mejor en celular y se leen de un vistazo) */
.choice-grid { display: grid; gap: .625rem; grid-template-columns: repeat(auto-fit, minmax(min(100%, 130px), 1fr)); }
.choice {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: .375rem; text-align: center;
  padding: .875rem .625rem; min-height: 76px;
  background: var(--surface);
  border: var(--bw) solid var(--border);
  border-radius: var(--radius-sm);
  font-weight: 600; font-size: .9375rem;
  cursor: pointer;
  transition: border-color .15s, background-color .15s, transform .06s;
}
.choice:hover { border-color: var(--accent); }
.choice:active { transform: scale(.98); }
.choice input { position: absolute; opacity: 0; pointer-events: none; }
.choice.is-selected, .choice:has(input:checked) {
  border-color: var(--accent);
  background: var(--accent-soft);
  color: var(--accent);
}
.choice-icon { font-size: 1.5rem; line-height: 1; }
.choice-sub { font-size: .75rem; font-weight: 400; color: var(--muted); }
.choice.is-selected .choice-sub { color: inherit; opacity: .8; }

/* ── Campo de dinero ───────────────────────────────────────────────────────
   El "$" pegado al campo, como una sola pieza. Lo usan el editor de planes y
   los formularios de finanzas.

   Vive AQUÍ y no en planes.css porque eso fue exactamente el fallo: finanzas
   usaba las clases sin cargar ese archivo, y el signo caía ARRIBA del campo
   —sin borde, sin fondo— como si faltara algo. Un estilo que solo existe en
   el CSS de otro módulo es un estilo que no existe. */
.money-in { display: flex; align-items: stretch; }
.money-in-sign {
  display: flex; align-items: center; justify-content: center;
  flex: 0 0 auto; min-width: 2.5rem;
  font-size: 1.1rem; font-weight: 600; color: var(--muted);
  background: color-mix(in srgb, var(--muted) 8%, transparent);
  border: var(--bw) solid var(--border); border-right: 0;
  border-radius: var(--radius-sm) 0 0 var(--radius-sm);
}
/* min-width:0 es obligatorio: un elemento flex no encoge por debajo de su
   min-content, y el de un <input> lo fija su atributo `size` (~180px). En un
   modal angosto, el campo se salía por la derecha. */
.money-in .input {
  min-width: 0;
  border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
  font-size: 1.1rem; font-weight: 600;
}

/* ── Ventana emergente ─────────────────────────────────────────────────────
   La usan el editor de planes y la bandeja de comprobantes. Vive aquí porque
   la segunda pantalla que necesitó una habría copiado la primera, y a la
   tercera ya serían tres formas distintas de oscurecer el fondo.

   `overflow-y: auto` en la capa y `margin: auto` en la tarjeta: cuando el
   contenido es más alto que la pantalla —un formulario en un celular con el
   teclado abierto— la tarjeta se pega arriba y la capa hace scroll. Con
   `align-items: center` el borde superior quedaría inalcanzable. */
.modal {
  position: fixed; inset: 0; z-index: 120;
  display: flex; padding: 1rem; overflow-y: auto;
  background: color-mix(in srgb, #23261f 55%, transparent);
  opacity: 0; transition: opacity .18s ease;
}
.modal.show { opacity: 1; }
.modal[hidden] { display: none; }

.modal-card {
  width: 100%; max-width: 26rem; margin: auto;
  background: var(--surface);
  border: var(--bw) solid var(--border);
  border-radius: var(--radius-lg);
  padding: 1.5rem;
  transform: translateY(8px); transition: transform .18s ease;
}
.modal.show .modal-card { transform: none; }
.modal-card-wide { max-width: 34rem; }

/* ── Barra de semana ───────────────────────────────────────────────────────
   "‹  3 – 9 ago 2026  ›". La usan el calendario del jugador y los partidos del
   día del negocio: las dos pantallas navegan de lunes a domingo y tienen que
   verse igual, así que vive aquí y no copiada en dos módulos.

   El encabezado con la fecha NO es adorno: sin él, "12" y "19" son dos
   números sueltos y nadie sabe si el segundo es de este mes o del que viene. */
.weekbar {
  display: flex; align-items: center; justify-content: space-between; gap: .5rem;
  margin: 1rem 0 .5rem;
}
.weekbar-t {
  margin: 0; flex: 1 1 auto; text-align: center;
  font-weight: 600; font-size: .9375rem;
}
.weekbar-nav {
  display: inline-flex; align-items: center; justify-content: center;
  flex: 0 0 auto;
  width: 40px; height: 40px;             /* se toca con el pulgar sin apuntar */
  border: var(--bw) solid var(--border); border-radius: var(--radius-sm);
  color: var(--text); text-decoration: none;
  font-size: 1.25rem; line-height: 1;
  transition: border-color .12s, color .12s;
}
.weekbar-nav:hover { border-color: var(--accent); color: var(--accent); text-decoration: none; }
/* El extremo del rango se deja VISIBLE y apagado, no se quita: si el botón
   desapareciera, los otros dos se recorrerían y el que ayer estaba a la
   izquierda hoy estaría en medio. */
.weekbar-nav.is-off { opacity: .25; cursor: default; }

/* ── Badges ───────────────────────────────────────────────────────────────── */
.badge {
  display: inline-flex; align-items: center; gap: .3125rem;
  padding: .1875rem .5rem;
  border: 1px solid var(--border);
  border-radius: 999px;
  font-size: .75rem; font-weight: 700;
  text-transform: uppercase; letter-spacing: .03em;
  white-space: nowrap;
}
.badge-accent  { background: var(--accent-soft);  color: var(--accent);  border-color: var(--accent); }
.badge-success { background: var(--accent-soft);  color: var(--success); border-color: var(--success); }
.badge-warning { color: var(--warning); border-color: var(--warning); }
.badge-danger  { color: var(--danger);  border-color: var(--danger); }
.badge-muted   { color: var(--muted); }
.badge-dot { width: 7px; height: 7px; border-radius: 50%; background: currentColor; }

/* ── Alertas ──────────────────────────────────────────────────────────────── */
.alert {
  display: flex; align-items: flex-start; gap: .625rem;
  padding: .875rem 1rem;
  border: var(--bw) solid var(--border);
  border-left-width: 5px;
  border-radius: var(--radius-sm);
  background: var(--surface);
  font-size: .9375rem;
}
.alert-success { border-left-color: var(--success); }
.alert-warning { border-left-color: var(--warning); }
.alert-danger  { border-left-color: var(--danger); }
.alert-info    { border-left-color: var(--info); }
.alert-icon { flex: 0 0 auto; font-size: 1.125rem; line-height: 1.4; }
.alert > div > :last-child { margin-bottom: 0; }

/* ── Tablas ───────────────────────────────────────────────────────────────── */
.table-wrap { overflow-x: auto; -webkit-overflow-scrolling: touch; border: var(--bw) solid var(--border); border-radius: var(--radius); }
.table { width: 100%; font-size: .9375rem; }
.table th, .table td { padding: .75rem .875rem; text-align: left; }
.table thead th {
  background: var(--surface-2);
  font-size: .75rem; font-weight: 700; text-transform: uppercase; letter-spacing: .04em;
  color: var(--muted);
  border-bottom: var(--bw) solid var(--border);
  white-space: nowrap;
}
.table tbody tr + tr td { border-top: 1px solid var(--border); }
.table tbody tr:hover td { background: var(--surface-2); }
.table td.num { text-align: right; font-variant-numeric: tabular-nums; }

/* ── Avatar ───────────────────────────────────────────────────────────────── */
.avatar {
  display: inline-flex; align-items: center; justify-content: center;
  width: 40px; height: 40px; flex: 0 0 auto;
  border-radius: 50%;
  border: var(--bw) solid var(--border);
  background: var(--accent-soft); color: var(--accent);
  font-weight: 700; font-size: .875rem;
  overflow: hidden;
}
/* Alineado ARRIBA, no al centro. Las fotos de perfil se guardan 9:16 —de la
   cintura para arriba— y centrarlas dentro de un círculo de 40 px enseñaba el
   pecho en vez de la cara. En una foto cuadrada de las de antes no cambia nada:
   sin sobrante vertical, no hay nada que alinear. */
.avatar img { width: 100%; height: 100%; object-fit: cover; object-position: top; }
.avatar-sm { width: 32px; height: 32px; font-size: .75rem; }
.avatar-lg { width: 64px; height: 64px; font-size: 1.25rem; }
.avatar-xl { width: 88px; height: 88px; font-size: 1.75rem; }

/* ── Foto vertical ─────────────────────────────────────────────────────────
   La foto de perfil COMPLETA, tal como se guarda: 9:16, de la cintura para
   arriba. La usan el perfil de cada quien y la ficha del jugador, así que
   vive aquí — la segunda pantalla que la necesitó habría copiado la primera.

   `contain` y no `cover`: las fotos de antes de que existiera el recortador
   son cuadradas, y recortarlas a 9:16 les cortaría media cara. Con `contain`
   se ven enteras, con dos bandas del color del fondo, y las nuevas —que ya son
   9:16— llenan el marco exacto sin banda ninguna. */
.photo-v {
  flex: 0 0 auto;
  width: 96px; aspect-ratio: 9 / 16;
  border-radius: var(--radius);
  border: var(--bw) solid var(--border);
  background: var(--surface-2);
  overflow: hidden;
}
.photo-v img { display: block; width: 100%; height: 100%; object-fit: contain; }
.photo-v-lg { width: 132px; }

@media (max-width: 30rem) {
  .photo-v    { width: 78px; }
  .photo-v-lg { width: 108px; }
}

/* ── Lista de datos (etiqueta arriba, valor abajo) ────────────────────────── */
/* Apilado en vez de dos columnas: en un celular angosto una tabla parte los
   valores largos a media palabra. */
.data-list { display: grid; gap: .875rem; margin: 0; }
@media (min-width: 420px) { .data-list { grid-template-columns: repeat(2, 1fr); } }
.data-list dt {
  font-size: .6875rem; text-transform: uppercase; letter-spacing: .12em;
  font-weight: 600; color: var(--muted); margin-bottom: .125rem;
}
.data-list dd { margin: 0; font-weight: 600; overflow-wrap: anywhere; }

/* Un renglón que ocupa el ancho COMPLETO de la lista.
   Existe para las listas que son una sucesión de renglones —los jugadores de un
   papá, los datos de contacto de la escuela— y no una rejilla de pares
   etiqueta/valor: sin él, el segundo renglón se sube a la derecha del primero y
   la lista se lee como una tabla de dos columnas que nadie pidió. */
.data-list-row { grid-column: 1 / -1; display: flex; align-items: center; gap: .625rem; min-width: 0; }
.data-list-row + .data-list-row { border-top: var(--bw) solid var(--border); padding-top: .875rem; }
/* El par etiqueta/valor en un renglón: la etiqueta a la izquierda, el dato a la
   derecha, que es como se lee una ficha. */
.data-list > div.data-list-row { justify-content: space-between; }
.data-list > div.data-list-row dt { margin-bottom: 0; }
ul.data-list, ol.data-list { list-style: none; padding: 0; }
/* ── Estado vacío ─────────────────────────────────────────────────────────── */
.empty { text-align: center; padding: 2.5rem 1rem; color: var(--muted); }
.empty-icon { font-size: 2.5rem; margin-bottom: .5rem; opacity: .6; }
.empty h3 { color: var(--text); }

/* ── Barra de progreso ────────────────────────────────────────────────────── */
.progress {
  height: 8px; background: var(--surface-2);
  border: 1px solid var(--border); border-radius: 999px; overflow: hidden;
}
.progress-bar { height: 100%; background: var(--accent); border-radius: 999px; transition: width .35s ease; }

/* ── Skeleton (carga) ─────────────────────────────────────────────────────── */
.skeleton {
  background: linear-gradient(90deg, var(--surface-2) 25%, var(--border) 50%, var(--surface-2) 75%);
  background-size: 200% 100%;
  animation: shimmer 1.3s infinite;
  border-radius: var(--radius-sm);
}
@keyframes shimmer { to { background-position: -200% 0; } }

/* ── Separador con texto ──────────────────────────────────────────────────── */
.divider { display: flex; align-items: center; gap: .75rem; color: var(--muted); font-size: .8125rem; }
.divider::before, .divider::after { content: ''; flex: 1; height: 1px; background: var(--border); }

/* ── Toast (avisos flotantes) ─────────────────────────────────────────────── */
.toast-host {
  /* Por encima de la hoja de la agenda (1000) y del diálogo (2000): si no,
     el aviso queda escondido detrás del modal, abajo. */
  position: fixed; z-index: 3000;
  left: 50%; transform: translateX(-50%);
  bottom: calc(env(safe-area-inset-bottom, 0px) + 5.5rem);
  display: flex; flex-direction: column; gap: .5rem;
  width: min(92vw, 420px);
  pointer-events: none;
}
@media (min-width: 900px) { .toast-host { bottom: 1.5rem; } }
.toast {
  pointer-events: auto;
  background: var(--surface);
  border: var(--bw) solid var(--border);
  border-left-width: 5px;
  border-radius: var(--radius-sm);
  padding: .75rem 1rem;
  font-size: .9375rem; font-weight: 500;
  box-shadow: 0 8px 24px rgb(0 0 0 / .16);
  animation: toast-in .2s ease-out;
}
.toast-success { border-left-color: var(--success); }
.toast-danger  { border-left-color: var(--danger); }
.toast-warning { border-left-color: var(--warning); }
.toast-info    { border-left-color: var(--info); }
@keyframes toast-in { from { opacity: 0; transform: translateY(8px); } }

/* ── Diálogo modal propio (reemplaza alert/confirm/prompt nativos) ────────── */
.er-dialog-ov {
  position: fixed; inset: 0; z-index: 2000;
  display: flex; align-items: center; justify-content: center; padding: 1rem;
  background: rgba(15, 23, 42, .5); backdrop-filter: blur(3px);
  animation: bm-dialog-fade .15s ease;
}
.er-dialog {
  width: 100%; max-width: 400px;
  background: var(--surface); border: var(--bw) solid var(--border);
  border-radius: var(--radius); padding: 1.5rem;
  box-shadow: 0 20px 60px rgba(0, 0, 0, .3);
  animation: bm-dialog-pop .18s ease-out;
}
.er-dialog-title { margin: 0 0 .5rem; font-size: 1.15rem; }
.er-dialog-msg { margin: 0 0 1.125rem; color: var(--muted); line-height: 1.55; }
.er-dialog-title + .er-dialog-msg { margin-top: -.125rem; }
/* Desglose del diálogo: "de tal a tal fecha", "luego paga tanto". Etiqueta
   arriba y valor abajo y no en dos columnas, porque los valores son fechas y
   cantidades de largo muy distinto y en columnas quedan bailando. */
.er-dialog-lines {
  margin: 0 0 1.125rem; padding: .75rem .875rem;
  border-radius: var(--radius-sm); background: var(--surface-2);
  display: flex; flex-direction: column; gap: .5rem;
}
.er-dialog-lines dt {
  font-size: .6875rem; letter-spacing: .05em; text-transform: uppercase;
  color: var(--muted); margin-bottom: .0625rem;
}
.er-dialog-lines dd { margin: 0; font-size: .9375rem; color: var(--text); }

/* Cuando el título ES la cifra —cuánto tiene que pagar—, manda en la pantalla:
   es lo que la dueña va a leer en voz alta por encima del mostrador. */
.er-dialog.is-amount .er-dialog-title {
  font-size: 2rem; font-weight: 700; color: var(--accent);
  font-variant-numeric: tabular-nums;
}

.er-dialog-input { margin-bottom: 1.25rem; }
.er-dialog-foot { display: flex; gap: .625rem; justify-content: flex-end; flex-wrap: wrap; }
.er-dialog-foot .btn { min-width: 96px; }
@keyframes bm-dialog-fade { from { opacity: 0; } }
@keyframes bm-dialog-pop { from { transform: translateY(10px) scale(.97); opacity: 0; } }
@media (max-width: 420px) {
  .er-dialog-foot { flex-direction: column-reverse; }
  .er-dialog-foot .btn { width: 100%; }
}
@media (prefers-reduced-motion: reduce) { .er-dialog-ov, .er-dialog { animation: none; } }

/* ── Sesión prestada: "estás viendo la plataforma como X" ─────────────────
   Barra fija abajo, presente en TODOS los layouts. El color es --warning y no
   --danger a propósito: no pasó nada malo, solo hay que no olvidarlo. */
body.is-impersonating { --imp-h: 52px; }

.imp-bar {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 1900;
  background: var(--warning); color: #fff;
  box-shadow: 0 -6px 20px rgba(0, 0, 0, .18);
  padding-bottom: env(safe-area-inset-bottom, 0px);
}
.imp-bar-in {
  display: flex; align-items: center; gap: .75rem;
  max-width: 1180px; margin: 0 auto; padding: .5rem 1rem;
  min-height: var(--imp-h, 52px);
}
.imp-bar-eye { display: inline-flex; line-height: 1; flex: none; }
.imp-bar-eye .ic { width: 18px; height: 18px; }
.imp-bar-txt { display: flex; flex-direction: column; min-width: 0; flex: 1 1 auto; }
.imp-bar-txt strong { font-size: .9rem; font-weight: 600; }
.imp-bar-sub { font-size: .75rem; opacity: .85; }
.imp-bar form { flex: none; margin: 0; }
.imp-bar-btn {
  background: #fff; color: var(--warning);
  border: var(--bw) solid #fff; font-weight: 600; white-space: nowrap;
}
.imp-bar-btn:hover { background: rgba(255, 255, 255, .88); color: var(--warning); }

@media (max-width: 899px) {
  .imp-bar-sub { display: none; }   /* a 360 px solo cabe lo importante */

  /* Donde hay navegación inferior, el aviso se sienta ARRIBA de ella: taparla
     dejaría al super admin sin poder moverse por la plataforma que vino a
     revisar. Donde no la hay (portada, errores), va pegado abajo. */
  body:has(.bottomnav) .imp-bar {
    bottom: calc(var(--bottomnav-h) + env(safe-area-inset-bottom, 0px));
    padding-bottom: 0;
  }
  body.is-impersonating:has(.bottomnav) .shell-main {
    padding-bottom: calc(var(--bottomnav-h) + var(--imp-h) + env(safe-area-inset-bottom, 0px) + 1rem);
  }
  body.is-impersonating:has(.bottomnav) .footer {
    margin-bottom: calc(var(--bottomnav-h) + var(--imp-h) + env(safe-area-inset-bottom, 0px));
  }
  body.is-impersonating:has(.bottomnav) .toast-host {
    bottom: calc(env(safe-area-inset-bottom, 0px) + var(--bottomnav-h) + var(--imp-h) + 1rem);
  }
}

@media (min-width: 900px) {
  body.is-impersonating .shell-main { padding-bottom: calc(var(--imp-h) + 1.5rem); }
  body.is-impersonating .footer     { margin-bottom: var(--imp-h); }
  body.is-impersonating .toast-host { bottom: calc(var(--imp-h) + 1rem); }
}

/* Layouts sin .shell (portada, acceso, errores): el aire se le da al body. */
body.is-impersonating:not(:has(.shell)) {
  padding-bottom: calc(var(--imp-h) + env(safe-area-inset-bottom, 0px));
}

/* ── Invitación a instalar la app ────────────────────────────────────────────
   Barra al pie, por encima de la navegación inferior. Se puede quitar y no
   vuelve: un aviso que reaparece en cada visita se cierra por reflejo y deja de
   leerse. */
.pw-inst {
  position: fixed; left: .75rem; right: .75rem; bottom: .75rem; z-index: 60;
  display: flex; align-items: center; gap: .875rem; flex-wrap: wrap;
  padding: .875rem 1rem;
  background: var(--surface); color: var(--text);
  border: 1px solid var(--border); border-radius: var(--radius);
  box-shadow: 0 12px 32px -8px rgba(0,0,0,.28);
  transform: translateY(130%); opacity: 0;
  transition: transform .22s ease, opacity .22s ease;
}
.pw-inst.is-in { transform: translateY(0); opacity: 1; }
.pw-inst-txt { display: flex; flex-direction: column; flex: 1 1 12rem; min-width: 0; }
.pw-inst-txt strong { font-size: .9375rem; }
.pw-inst-txt span { font-size: .8125rem; color: var(--muted); }
.pw-inst-acts { display: flex; gap: .5rem; flex: 0 0 auto; }

/* Con la navegación inferior puesta, la barra se sube para no taparla. */
body.has-bottomnav .pw-inst { bottom: calc(var(--bottomnav-h, 60px) + .75rem); }

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

/* ── Ver / ocultar contraseña ──────────────────────────────────────────────── */
/* Los DOS ojos vienen en el HTML y aquí se enseña el que toca, según el
   aria-pressed que mueve el JS. Así el JavaScript nunca escribe SVG.
   Ojo cerrado = "mostrar"; ojo abierto = "ocultar", que es lo que va a pasar
   si lo tocas — el icono anuncia la ACCIÓN, no el estado actual.

   Vive aquí y no en cada módulo porque el mismo botón sale en el acceso, en el
   registro, en la conexión del correo y en la del WhatsApp. Estaba copiada en
   dos de ellos y faltaba en los otros dos, que salieron del paso con un emoji:
   👁 no es un icono sino una FUENTE, y en el servidor no hay ninguna que lo
   dibuje — se veía un cuadrito. */
.input-addon[data-toggle-password] .ic { display: none; }
.input-addon[data-toggle-password][aria-pressed="false"] svg:first-child,
.input-addon[data-toggle-password][aria-pressed="true"]  svg:last-child { display: block; }
/* El aviso que se repite parpadea, para que se note que sí respondió al toque
   aunque no aparezca uno nuevo. */
@keyframes toast-again { 0% { transform: scale(1); } 45% { transform: scale(1.035); } 100% { transform: scale(1); } }
.toast.is-again { animation: toast-again .28s ease; }
@media (prefers-reduced-motion: reduce) { .toast.is-again { animation: none; } }
