/* ============================================================
   PANEL DE ACCESO — SISTEMA VISUAL
   ============================================================
   Mundo comprometido: materiales oscuros por capas sobre un fondo
   de color fijo. La cromática translúcida (barra, navegación,
   hojas, el control de la puerta) deja pasar el contenido por
   debajo, como en el Centro de control de Apple.

   REGLA DE RENDIMIENTO, no negociable:
   backdrop-filter es de lo más caro que existe en CSS. Por eso solo
   vive en superficies PEQUEÑAS Y FIJAS. Nunca en listas que hacen
   scroll: ahí el navegador tendría que recalcular el desenfoque en
   cada cuadro y el celular se arrodilla.
   Y todo el movimiento es solo transform y opacity, que corren en
   la GPU sin recalcular la página.
   ============================================================ */

/* ── Fichas del sistema ───────────────────────────────────── */
:root {
  /* Fondo por capas. Nada es negro puro: el negro absoluto aplasta
     la profundidad y hace que los materiales no se lean. */
  --base: hsl(232 52% 8%);
  --base-alta: hsl(232 40% 13%);

  /* Materiales translúcidos.
     Para que el vidrio SE VEA hacen falta cuatro cosas a la vez:
       1. color de verdad detrás (lo pone .fondo)
       2. una superficie que deje pasar ese color  ← esto de aquí
       3. desenfoque suficiente
       4. un canto claro donde pegue la luz
     Antes iban al 72% de opacidad: casi sólidos. Un material que no
     deja pasar nada es un panel pintado, no vidrio. */
  --material-grueso: hsl(230 40% 22% / 0.44);
  --material-ligero: hsl(230 45% 46% / 0.24);
  --material-borde: hsl(230 60% 92% / 0.16);
  /* Borde superior más claro = la luz pegando en el canto del material */
  --material-canto: hsl(230 80% 98% / 0.34);

  /* Texto. El secundario va TEÑIDO del mismo tono del fondo,
     nunca gris neutro: el gris sobre un fondo con color se ve sucio. */
  --tinta: hsl(228 30% 97%);
  --tinta-media: hsl(228 18% 72%);
  --tinta-suave: hsl(228 14% 56%);

  /* Paleta de sistema de Apple, que es el listón elegido */
  --azul: hsl(211 100% 52%);
  --azul-vivo: hsl(211 100% 62%);
  --verde: hsl(135 65% 51%);
  --rojo: hsl(3 100% 61%);
  --ambar: hsl(37 100% 52%);

  /* Curvas de salida fuertes. Las de CSS son flojas: arrancan
     despacio justo cuando el ojo está mirando. */
  --salida: cubic-bezier(0.23, 1, 0.32, 1);
  --entrada-salida: cubic-bezier(0.77, 0, 0.175, 1);

  --radio: 18px;
  --radio-chico: 12px;

  /* Espaciado en rem para que respete el tamaño de letra del sistema */
  --hueco: 1rem;
}

/* ── Base ─────────────────────────────────────────────────── */
*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  min-height: 100dvh;
  background: var(--base);
  color: var(--tinta);
  font: 100%/1.5 system-ui, -apple-system, "Segoe UI", sans-serif;
  -webkit-font-smoothing: antialiased;
  overflow-wrap: break-word;
}

/* Fondo de color, fijo y sin animación. Le da a los materiales algo
   que desenfocar; si el fondo fuera plano, el vidrio no se vería.
   Estático = no cuesta un solo cuadro de animación. */
.fondo {
  position: fixed;
  inset: 0;
  z-index: -1;
  overflow: hidden;   /* la capa interna es más grande y no debe asomar */
}

/* La capa que lleva el color va en un hijo, no en .fondo, para poder
   moverla sin tocar nada más. */
.fondo::before {
  content: "";
  position: absolute;
  /* Más grande que la pantalla: al desplazarse nunca deja ver un borde */
  inset: -25%;
  background: var(--campo);
  /* La luz del ambiente según la hora (ver más abajo) */
  filter: var(--luz, none);
  transition: filter 3s ease;
}

/* ── La luz cambia con la hora ────────────────────────────────
   El atributo lo pone ajustarHora() en app.js.

   OJO CON LO QUE ESTO ES Y NO ES: no se percibe en una sesión.
   "Tarde" es la línea base —el fondo tal cual se diseñó— así que de
   día no aplica ningún filtro y no hay nada que ver. Solo se nota
   comparando entre días u horas lejanas.

   Su valor no es visual, es ergonómico: una portería no cierra, y a
   las 2 de la mañana este panel da menos luz en la cara. Sirve
   aunque nadie lo note conscientemente. Si algún día estorba, se
   borra este bloque y ajustarHora() y no pasa nada más.

   Se hace con filter y no cambiando los degradados por dos razones:
   los degradados no se pueden transicionar (saltarían de golpe a
   las 7pm), y filter corre en la GPU.

   Solo se mueven temperatura y brillo. Nunca se acerca al verde, al
   rojo ni al ámbar, reservados para los estados. */
[data-hora="madrugada"] { --luz: brightness(0.60) saturate(0.82) hue-rotate(14deg); }
[data-hora="manana"]    { --luz: brightness(1.06) saturate(1.06) hue-rotate(-12deg); }
[data-hora="tarde"]     { --luz: none; }
[data-hora="noche"]     { --luz: brightness(0.76) saturate(0.94) hue-rotate(9deg); }

/* Aquí vivió un fondo que se movía lentamente. Se quitó: a 90
   segundos por vuelta nadie lo percibía, y una animación que no se
   nota es complejidad sin beneficio. Costaba 0 FPS medidos, pero
   ese nunca fue el argumento a favor.
   El campo se queda quieto. */

/* ── EL CAMPO DE COLOR: "Aurora" ──────────────────────────────
   Cuatro tintes —azul, violeta, cian y magenta— a alta saturación,
   a toda la altura del viewport.

   Elegida por Julio después de ver Índigo, que era la versión
   disciplinada de esta misma idea. Su decisión manda sobre la mía:
   una regla de diseño no le gana a la persona dueña del producto.

   Nota para quien retome esto: la guía de impeccable marcaría esto
   como estrategia "drenched" (la superficie ES el color), que es la
   de menos permiso en una interfaz de trabajo. La compensación está
   en el resto del sistema: el contenido vive sobre materiales que
   suben el contraste, y los estados usan colores reservados que
   ningún tinte del fondo toca.

   ESA REGLA SÍ ES INTOCABLE: el verde, el rojo y el ámbar
   significan concedido, denegado y precaución. Son lo único que el
   administrador necesita leer de un vistazo, y ningún fondo puede
   competir con ellos. */
:root {
  --campo:
    radial-gradient(120% 78% at 8% -8%, hsl(214 96% 44% / 0.72), transparent 58%),
    radial-gradient(105% 68% at 96% 6%, hsl(276 92% 50% / 0.60), transparent 56%),
    radial-gradient(115% 72% at 88% 96%, hsl(188 96% 42% / 0.46), transparent 58%),
    radial-gradient(100% 62% at 4% 88%, hsl(322 90% 46% / 0.36), transparent 58%),
    linear-gradient(170deg, hsl(232 62% 16%), hsl(244 54% 10%) 52%, hsl(228 58% 7%));
}

/* ── Superficies del navegador ────────────────────────────────
   Lo que NO dibujamos también comunica. Selección, cursor, barras
   de scroll y anillos de foco vienen con estilos de fábrica que no
   pertenecen a ningún diseño. Teñirlos es de lo más barato que
   distingue una interfaz construida de una ensamblada. */
::selection { background: hsl(211 100% 52% / 0.34); color: var(--tinta); }

:root { scrollbar-color: hsl(228 20% 40% / 0.5) transparent; scrollbar-width: thin; }
::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb {
  background: hsl(228 20% 40% / 0.5);
  border: 3px solid transparent;
  border-radius: 99px;
  background-clip: content-box;
}
::-webkit-scrollbar-thumb:hover { background: hsl(228 20% 52% / 0.7); background-clip: content-box; }

:focus-visible {
  outline: 2px solid var(--azul-vivo);
  outline-offset: 3px;
  border-radius: 6px;
}

input, select, textarea { caret-color: var(--azul-vivo); }

/* Cifras alineadas en columna: sin esto, las horas y los folios
   bailan de un renglón a otro porque el 1 es más angosto. */
.resumen__cifra, .fila__hora, .clave__valor, .fila__folio { font-variant-numeric: tabular-nums; }

/* ── Tipografía ───────────────────────────────────────────────
   El interletrado depende del tamaño: el texto grande se ve
   despegado y hay que apretarlo; el chico necesita aire. Un solo
   valor de letter-spacing para todo está mal en algún lado. */
h1, h2, h3 { margin: 0; font-weight: 650; line-height: 1.15; letter-spacing: -0.021em; text-wrap: balance; }

.titulo-seccion {
  font-size: 1.0625rem;
  letter-spacing: -0.01em;
  margin-bottom: 0.75rem;
}

.parrafo {
  color: var(--tinta-media);
  max-width: 62ch;
  margin: 0 0 1.25rem;
  font-size: 0.9375rem;
}

/* Nota al pie de un campo: explica una consecuencia, no un adorno.
   Va más chica y más apagada para que no compita con la etiqueta. */
.parrafo--nota { font-size: 0.8125rem; color: var(--tinta-suave); margin-bottom: 0.875rem; }
.parrafo--centro { text-align: center; margin-inline: auto; }

.titulo-seccion--separado { margin-top: 1.75rem; }


/* ── Botones ──────────────────────────────────────────────── */
.boton {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  min-height: 44px;              /* alcanzable con el pulgar */
  padding: 0 1.1rem;
  border: 1px solid transparent;
  border-radius: 999px;
  background: none;
  color: var(--tinta);
  font: inherit;
  font-size: 0.9375rem;
  font-weight: 550;
  letter-spacing: -0.005em;
  cursor: pointer;
  /* Propiedades exactas, nunca "all": con all el navegador vigila
     cambios que nunca ocurren. */
  transition: transform 140ms var(--salida), background-color 140ms ease, opacity 140ms ease;
  -webkit-tap-highlight-color: transparent;
}

/* La respuesta al presionar va en pointer-down, no al soltar.
   Esperar al click se siente muerto. */
.boton:active { transform: scale(0.97); transition-duration: 90ms; }

.boton:disabled { opacity: 0.4; cursor: not-allowed; transform: none; }

.boton--primario { background: var(--azul); color: #fff; }
.boton--sutil { background: var(--material-ligero); border-color: var(--material-borde); }
.boton--ancho { width: 100%; }
.boton--icono { padding: 0; width: 44px; }

/* Un botón de reporte con su explicación debajo. Va alineado a la
   izquierda y con dos renglones, porque "Cobranza" a secas no dice lo
   que trae adentro, y quien duda entre dos reportes acaba bajando los
   dos para ver cuál era. */
.reporte {
  text-align: left;
  height: auto;
  padding-block: 0.75rem;
  align-items: flex-start;
}
.reporte .boton__texto { display: grid; gap: 0.125rem; }
.reporte__detalle {
  font-size: 0.8125rem;
  font-weight: 400;
  color: var(--tinta-media);
  line-height: 1.35;
  white-space: normal;
}

@media (hover: hover) and (pointer: fine) {
  .boton--primario:hover { background: var(--azul-vivo); }
  .boton--sutil:hover { background: hsl(228 20% 30% / 0.5); }
}

.boton[data-cargando="true"] .boton__texto { opacity: 0.55; }

.icono { width: 20px; height: 20px; display: block; flex: none; }

/* ── Campos ───────────────────────────────────────────────── */
.campo { display: block; margin-bottom: 0.875rem; }
.campo--enlinea { margin: 0; }

.campo__etiqueta {
  display: block;
  margin-bottom: 0.375rem;
  font-size: 0.8125rem;
  font-weight: 550;
  color: var(--tinta-media);
  letter-spacing: 0.002em;
}

/* "· opcional" junto a la etiqueta.
   Va más tenue y sin cursiva real: la idea es que se lea como una
   aclaración, no como otra etiqueta compitiendo por atención. Sin
   color propio —solo menos peso y menos opacidad— para no gastar
   ninguno de los tintes reservados. */
.campo__opcional {
  font-style: normal;
  font-weight: 450;
  opacity: 0.62;
}

.campo__control {
  width: 100%;
  min-height: 46px;
  padding: 0 0.875rem;
  border: 1px solid var(--material-borde);
  border-radius: var(--radio-chico);
  background: hsl(228 24% 14% / 0.6);
  color: var(--tinta);
  font: inherit;
  font-size: 1rem;               /* 16px evita que iOS haga zoom al enfocar */
  transition: border-color 140ms ease, background-color 140ms ease;
}

.campo__control::placeholder { color: var(--tinta-suave); }
.campo__control:focus { border-color: var(--azul); background: hsl(228 24% 16% / 0.8); }

select.campo__control { appearance: none; padding-right: 2rem; cursor: pointer; }

/* ── Avisos ───────────────────────────────────────────────── */
.aviso {
  margin: 0 0 0.875rem;
  padding: 0.75rem 0.875rem;
  border-radius: var(--radio-chico);
  font-size: 0.875rem;
}
.aviso--error { background: hsl(3 100% 61% / 0.14); color: hsl(3 100% 80%); }

/* Aviso de seguridad en la portada. Usa los colores reservados de
   estado: ámbar cuando el sistema está desarmado, rojo cuando algo
   ya pasó. No compite con el fondo porque esos dos tonos están
   apartados justo para esto. */
.alerta {
  display: flex;
  align-items: flex-start;
  gap: 0.75rem;
  margin: 0 0 1rem;
  padding: 0.875rem 1rem;
  border-radius: var(--radio);
  border: 1px solid transparent;
  font-size: 0.875rem;
  animation: subir 320ms var(--salida) both;
}
.alerta .icono { width: 20px; height: 20px; flex: none; margin-top: 1px; }
.alerta__cuerpo { min-width: 0; }
.alerta__titulo { display: block; font-weight: 620; letter-spacing: -0.008em; }
.alerta__detalle { display: block; margin-top: 0.125rem; opacity: 0.86; }

.alerta--desarmado {
  background: hsl(37 100% 52% / 0.14);
  border-color: hsl(37 100% 52% / 0.30);
  color: hsl(37 100% 80%);
}
.alerta--activa {
  background: hsl(3 100% 61% / 0.16);
  border-color: hsl(3 100% 61% / 0.34);
  color: hsl(3 100% 84%);
}

/* Ámbar: no es un error, es algo que hay que atender. La distinción
   importa —un error dice "no se hizo"; esto dice "se hizo a medias". */
.aviso--ojo { background: hsl(37 100% 52% / 0.14); color: hsl(37 100% 78%); }
.aviso:not([class*="--"]) { background: var(--material-ligero); color: var(--tinta-media); }

/* ── Buscadores y filtros ─────────────────────────────────────
   Una lista de 200 vecinos sin buscador obliga a hacer scroll con
   el pulgar hasta encontrar a alguien. El buscador es la diferencia
   entre una lista y una herramienta. */
.filtros {
  display: flex;
  align-items: flex-end;
  gap: 0.625rem;
  margin-bottom: 0.875rem;
  flex-wrap: wrap;
}
.filtros .buscador { flex: 1 1 14rem; min-width: 0; }
.filtros .campo--enlinea { flex: 0 0 auto; }

.buscador { position: relative; }

.buscador__lupa {
  position: absolute;
  left: 0.75rem;
  top: 50%;
  transform: translateY(-50%);
  color: var(--tinta-suave);
  pointer-events: none;   /* la lupa es señalética, no un botón */
}
.buscador__lupa .icono { width: 18px; height: 18px; }

.buscador__control { padding-left: 2.5rem; }

/* La cruz que Safari y Chrome ponen en los <input type=search> viene
   con su propio estilo de fábrica y no pertenece a este sistema. */
.buscador__control::-webkit-search-cancel-button { filter: invert(0.6); cursor: pointer; }

/* ── Paginación ───────────────────────────────────────────── */
.paginacion {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  margin-top: 1rem;
}
.paginacion__estado {
  font-size: 0.8125rem;
  color: var(--tinta-media);
  font-variant-numeric: tabular-nums;
  text-align: center;
}

/* ── Aviso accionable en el inicio ────────────────────────────
   Ámbar de precaución: un residente sin PIN existe pero no puede
   entrar a su casa. Es el fallo silencioso más caro del sistema, y
   por eso vive en la primera pantalla y se puede tocar. */
.atencion {
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: center;
  gap: 0.75rem;
  width: 100%;
  margin: 0 0 1.25rem;
  padding: 0.875rem;
  border: 1px solid hsl(37 100% 52% / 0.32);
  border-radius: var(--radio);
  background: hsl(37 100% 52% / 0.12);
  color: var(--tinta);
  font: inherit;
  text-align: left;
  cursor: pointer;
  transition: transform 140ms var(--salida), background-color 140ms ease;
  -webkit-tap-highlight-color: transparent;
}
.atencion:active { transform: scale(0.99); transition-duration: 90ms; }

@media (hover: hover) and (pointer: fine) {
  .atencion:hover { background: hsl(37 100% 52% / 0.2); }
}

.atencion__icono { color: var(--ambar); display: grid; place-items: center; }

/* El mismo bloque, pero para decir "salió bien".
   Verde solo aquí, y con el mismo significado que en el resto del
   panel: concedido / correcto. No es decoración — si se usara verde
   por bonito en otro lado, dejaría de leerse de un vistazo cuando de
   verdad importa. */
.atencion--bien {
  border-color: hsl(135 65% 51% / 0.32);
  background: hsl(135 65% 45% / 0.12);
}
.atencion--bien .atencion__icono { color: var(--verde); }

@media (hover: hover) and (pointer: fine) {
  .atencion--bien:hover { background: hsl(135 65% 45% / 0.2); }
}

/* Cuando es un resultado y no un botón, no debe fingir que se puede
   pulsar: ni cursor de mano ni respuesta al presionar. */
.atencion--estatico { cursor: default; }
.atencion--estatico:active { transform: none; }
.atencion__cuerpo { display: grid; gap: 0.125rem; min-width: 0; }
.atencion__titulo { font-size: 0.9375rem; font-weight: 580; letter-spacing: -0.008em; }
.atencion__detalle { font-size: 0.8125rem; color: var(--tinta-media); }

/* ── Ficha de datos (hojas de detalle) ────────────────────────
   Clave a la izquierda, valor a la derecha. Las claves van a un
   ancho fijo para que los valores queden alineados en columna: si
   cada renglón empieza en un sitio distinto, el ojo no puede
   recorrerlos de un vistazo. */
.ficha { margin: 0 0 1.25rem; display: grid; gap: 0.0625rem; }

.ficha__linea {
  display: grid;
  grid-template-columns: 8.5rem 1fr;
  gap: 0.75rem;
  padding: 0.5rem 0;
  border-bottom: 1px solid var(--material-borde);
  font-size: 0.875rem;
}
.ficha__linea:last-child { border-bottom: 0; }

/* Una aclaración debajo de un valor: de dónde sale ese número.
   Va más tenue y en bloque, para que se lea como nota al pie del dato
   y no compita con él. */
.ficha__pie {
  display: block;
  font-size: 0.75rem;
  color: var(--tinta-suave);
  margin-top: 0.0625rem;
}

.ficha__clave { margin: 0; color: var(--tinta-media); }
.ficha__valor { margin: 0; color: var(--tinta); overflow-wrap: anywhere; }

@media (max-width: 26rem) {
  /* En pantallas angostas, dos columnas dejarían los valores largos
     partidos en cuatro renglones. Mejor apilar. */
  .ficha__linea { grid-template-columns: 1fr; gap: 0.0625rem; }
}

/* ── Perfil (cabecera de la ficha de residente) ───────────── */
.perfil {
  display: flex;
  align-items: center;
  gap: 0.875rem;
  margin-bottom: 1.25rem;
}

.perfil__retrato {
  width: 64px; height: 64px;
  flex: none;
  border-radius: 50%;
  object-fit: cover;
  background: hsl(var(--tono, 230) 62% 42%);
  box-shadow: inset 0 1px 0 hsl(0 0% 100% / 0.22);
  display: grid; place-items: center;
  color: #fff;
  font-size: 1.25rem;
  font-weight: 640;
}

.perfil__cuerpo { display: grid; gap: 0.1875rem; justify-items: start; min-width: 0; }
.perfil__nombre { margin: 0; font-size: 1.0625rem; font-weight: 600; letter-spacing: -0.014em; }
.perfil__detalle { margin: 0; font-size: 0.8125rem; color: var(--tinta-media); }

/* ── Foto del momento del acceso ──────────────────────────────
   Es la prueba de quién entró. Se muestra grande, no como miniatura:
   una cara de 40px no sirve para reconocer a nadie. */
.captura { margin: 0 0 1.25rem; }

.captura__imagen {
  width: 100%;
  height: auto;
  max-height: none;
  object-fit: contain;
  border-radius: var(--radio);
  background: hsl(228 24% 15% / 0.6);
  display: block;
}

.captura__pie {
  margin-top: 0.5rem;
  font-size: 0.75rem;
  color: var(--tinta-suave);
  text-align: center;
}

/* Rojo reservado: acceso denegado. Es lo único, junto con el verde,
   que el administrador necesita leer de un vistazo. */
.marca--negado { background: hsl(3 100% 61% / 0.18); color: hsl(3 100% 80%); }

/* Dos campos que van juntos y significan una sola cosa (nombre y
   apellido, desde y hasta). En celular se apilan. */
.pareja { display: grid; gap: 0.75rem; }
@media (min-width: 26rem) {
  .pareja { grid-template-columns: 1fr 1fr; }
}

/* Acciones del pase generado: en fila y centradas, porque son
   hermanas y ninguna manda sobre las otras. */
.pase__acciones {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.5rem;
}
.pase__acciones .boton { text-decoration: none; }


/* ══ INICIAR SESIÓN ════════════════════════════════════════ */
.acceso {
  min-height: 100dvh;
  display: grid;
  place-items: center;
  padding: 1.5rem;
}

.acceso__hoja {
  width: min(100%, 25rem);
  padding: 2rem 1.75rem 1.75rem;
  border: 1px solid var(--material-borde);
  border-top-color: var(--material-canto);
  border-radius: 26px;
  background: var(--material-grueso);
  /* Material real, no un panel gris pintado */
  backdrop-filter: blur(30px) saturate(180%);
  -webkit-backdrop-filter: blur(30px) saturate(180%);
  box-shadow: 0 24px 60px hsl(228 40% 2% / 0.55);
  animation: materializar 420ms var(--salida) both;
}

/* El material llega desenfocándose y creciendo, como algo que se
   forma. No arranca en escala 0: nada en el mundo real aparece de
   la nada. */
@keyframes materializar {
  from { opacity: 0; transform: scale(0.96) translateY(8px); filter: blur(6px); }
  to   { opacity: 1; transform: none; filter: blur(0); }
}

.acceso__marca {
  display: grid;
  place-items: center;
  width: 46px; height: 46px;
  margin-bottom: 1.125rem;
  border-radius: 14px;
  background: var(--azul);
  color: #fff;
}
.acceso__marca .icono { width: 24px; height: 24px; }

.acceso__titulo { font-size: 1.75rem; letter-spacing: -0.028em; }
.acceso__sub { margin: 0.25rem 0 1.75rem; color: var(--tinta-media); font-size: 0.9375rem; }

/* ══ PANEL ═════════════════════════════════════════════════ */
.panel { min-height: 100dvh; }

/* ── Barra superior (material fijo, el contenido pasa debajo) ── */
.barra {
  position: sticky;
  top: 0;
  z-index: 20;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.625rem 1rem;
  padding-top: max(0.625rem, env(safe-area-inset-top));
  background: var(--material-grueso);
  backdrop-filter: blur(24px) saturate(180%);
  -webkit-backdrop-filter: blur(24px) saturate(180%);
  /* Degradado de borde en vez de una línea dura de 1px */
  border-bottom: 1px solid var(--material-borde);
}

.barra__identidad { display: flex; align-items: center; gap: 0.625rem; min-width: 0; }

.barra__marca {
  display: grid; place-items: center;
  width: 34px; height: 34px; flex: none;
  border-radius: 10px;
  background: var(--azul);
  color: #fff;
}
.barra__marca .icono { width: 18px; height: 18px; }

/* El nombre del condominio es contenido del cliente: puede ser
   "TECNOCYS" o "Residencial Villa del Sol Poniente". Sin recorte, el
   largo empuja la identidad fuera de la barra en celular — que es el
   equipo donde más se usa esto.

   min-width:0 tiene que estar en CADA nivel del flex, no solo en el
   contenedor de arriba: un hijo flex trae min-width:auto de fábrica y
   se niega a encogerse por debajo de su contenido, así que el
   text-overflow nunca llega a aplicarse. */
.barra__donde { min-width: 0; }

.barra__lugar {
  margin: 0;
  font-size: 0.9375rem;
  font-weight: 600;
  letter-spacing: -0.01em;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.barra__modo { margin: 0; font-size: 0.75rem; color: var(--tinta-suave); }

/* La identidad reemplazó al botón "Salir". Cerrar sesión, cambiar
   contraseña y ver quién eres son cosas de la misma familia: viven
   juntas detrás de tu propia cara, no sueltas en la barra. */
.identidad {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  min-height: 44px;
  padding: 0.25rem 0.75rem 0.25rem 0.25rem;
  border: 1px solid var(--material-borde);
  border-radius: 999px;
  background: var(--material-ligero);
  color: var(--tinta);
  font: inherit;
  font-size: 0.875rem;
  cursor: pointer;
  transition: transform 140ms var(--salida), background-color 140ms ease;
  -webkit-tap-highlight-color: transparent;
}
.identidad:active { transform: scale(0.97); transition-duration: 90ms; }

@media (hover: hover) and (pointer: fine) {
  .identidad:hover { background: hsl(230 40% 40% / 0.4); }
}

.identidad__retrato {
  display: grid;
  place-items: center;
  width: 34px; height: 34px;
  flex: none;
  border-radius: 50%;
  background: var(--azul);
  box-shadow: inset 0 1px 0 hsl(0 0% 100% / 0.24);
  color: #fff;
  font-size: 0.8125rem;
  font-weight: 640;
}

/* En celular el correo estorba: se queda solo el retrato */
.identidad__correo { display: none; }
@media (min-width: 34rem) {
  .identidad__correo { display: block; max-width: 16rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
}

/* ── Navegación ───────────────────────────────────────────── */
.navegacion {
  position: fixed;
  bottom: 0; left: 0; right: 0;
  z-index: 20;
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 1fr;
  padding: 0.375rem 0.5rem;
  padding-bottom: max(0.375rem, env(safe-area-inset-bottom));
  background: var(--material-grueso);
  backdrop-filter: blur(24px) saturate(180%);
  -webkit-backdrop-filter: blur(24px) saturate(180%);
  border-top: 1px solid var(--material-borde);
}

.navegacion__opcion {
  display: grid;
  justify-items: center;
  align-content: center;
  gap: 0.1875rem;
  /* 44px es el mínimo que un pulgar acierta con confianza */
  min-height: 44px;
  padding: 0.5rem 0.25rem;
  border: 0;
  border-radius: var(--radio-chico);
  background: none;
  color: var(--tinta-suave);
  font: inherit;
  font-size: 0.6875rem;
  font-weight: 550;
  cursor: pointer;
  transition: color 140ms ease, transform 140ms var(--salida);
  -webkit-tap-highlight-color: transparent;
}
.navegacion__opcion:active { transform: scale(0.94); }
.navegacion__opcion[aria-current="page"] { color: var(--azul-vivo); }

.lienzo {
  padding: 1.25rem 1rem 6.5rem;   /* espacio para la barra inferior */
  max-width: 60rem;
  margin: 0 auto;
}

/* La consola de Tecnocys no tiene barra de navegación abajo, así que
   ese hueco de 6.5rem sobraría y dejaría la página con un pie vacío. */
.lienzo--simple { padding-bottom: 2rem; }

/* ── Estado del sistema ───────────────────────────────────── */
.estado {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin: 0 0 1.25rem;
  font-size: 0.875rem;
  color: var(--tinta-media);
}

.estado__punto {
  width: 8px; height: 8px; flex: none;
  border-radius: 50%;
  background: var(--tinta-suave);
}
.estado__punto[data-estado="bien"] { background: var(--verde); }
.estado__punto[data-estado="mal"] { background: var(--rojo); }
.estado__punto[data-estado="aviso"] { background: var(--ambar); }
.estado__punto[data-estado="cargando"] { animation: latir 1.4s ease-in-out infinite; }

@keyframes latir { 50% { opacity: 0.3; } }

/* ── El control de la puerta ──────────────────────────────────
   El objeto principal de la pantalla. Grande, alcanzable con el
   pulgar, y sin ambigüedad sobre qué hace. */
.puerta {
  position: relative;
  display: grid;
  justify-items: start;
  align-content: space-between;
  gap: 0.25rem;
  width: 100%;
  min-height: 13.5rem;
  padding: 1.375rem 1.375rem 1.25rem;
  border: 1px solid hsl(212 100% 88% / 0.30);
  border-top-color: hsl(212 100% 96% / 0.5);
  border-radius: 28px;
  /* RELLENO, no contorno. En la app Casa un control es un objeto de
     color que ocupa espacio, no una caja vacía con un icono chico. */
  background:
    radial-gradient(120% 90% at 20% 0%, hsl(206 100% 62% / 0.95), transparent 62%),
    linear-gradient(158deg, hsl(214 100% 54%), hsl(232 92% 44%));
  color: #fff;
  font: inherit;
  text-align: left;
  cursor: pointer;
  overflow: hidden;
  box-shadow:
    0 18px 44px hsl(220 90% 12% / 0.55),
    inset 0 1px 0 hsl(0 0% 100% / 0.22);
  transition: transform 160ms var(--salida), filter 220ms ease;
  -webkit-tap-highlight-color: transparent;
}
/* Ya no es un <button>, así que el cursor y el :active de antes no
   aplican: lo que se toca es el deslizador de abajo. El control sigue
   siendo el objeto de color; solo cambió cómo se dispara. */
.puerta { cursor: default; }

/* ── Deslizar para abrir ──────────────────────────────────────
   Un <input type="range"> disfrazado. Ver el comentario largo del
   index.html para el porqué de no usar un div arrastrable. */
.deslizador {
  position: relative;
  width: 100%;
  margin-top: 1rem;
  /* 56px: por encima de los 44 mínimos de DESIGN.md, porque este se
     arrastra y no solo se toca. */
  height: 3.5rem;
}

.deslizador__pista {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  border-radius: 999px;
  background: hsl(220 60% 12% / 0.28);
  border: 1px solid hsl(0 0% 100% / 0.16);
  /* El canto claro arriba, igual que el resto de los materiales. */
  border-top-color: hsl(0 0% 100% / 0.3);
  pointer-events: none;
}

.deslizador__leyenda {
  font-size: 0.875rem;
  font-weight: 550;
  letter-spacing: 0.02em;
  color: hsl(0 0% 100% / 0.66);
  /* Se apaga conforme avanzas: la instrucción sobra en cuanto
     empezaste a hacerla. La opacidad la escribe el JS. */
  opacity: var(--avance-inverso, 1);
  transition: opacity 120ms linear;
}

/* El control real, invisible salvo por su tirador. */
.deslizador__control {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  margin: 0;
  appearance: none;
  -webkit-appearance: none;
  background: transparent;
  cursor: grab;
}
.deslizador__control:active { cursor: grabbing; }

/* El tirador. Dos reglas porque cada motor tiene la suya y NO se
   pueden juntar en un selector con coma: si un navegador no entiende
   una parte, tira la regla entera. */
.deslizador__control::-webkit-slider-thumb {
  appearance: none;
  -webkit-appearance: none;
  width: 3rem; height: 3rem;
  border-radius: 50%;
  background: #fff;
  border: none;
  box-shadow: 0 4px 14px hsl(220 90% 10% / 0.45);
  cursor: grab;
}
.deslizador__control::-moz-range-thumb {
  width: 3rem; height: 3rem;
  border-radius: 50%;
  background: #fff;
  border: none;
  box-shadow: 0 4px 14px hsl(220 90% 10% / 0.45);
  cursor: grab;
}

/* El anillo de foco del teclado va en el tirador, no en la caja: es
   lo que se mueve, y por lo tanto donde el ojo lo busca. */
.deslizador__control:focus-visible::-webkit-slider-thumb {
  outline: 3px solid hsl(0 0% 100% / 0.9);
  outline-offset: 3px;
}
.deslizador__control:focus-visible::-moz-range-thumb {
  outline: 3px solid hsl(0 0% 100% / 0.9);
  outline-offset: 3px;
}
.deslizador__control:focus { outline: none; }

/* Mientras se abre o ya terminó, el deslizador estorba: se apaga y
   deja de recibir toques. */
.puerta[data-fase="abriendo"] .deslizador,
.puerta[data-fase="abierta"] .deslizador,
.puerta[data-fase="fallo"] .deslizador {
  opacity: 0.35;
  pointer-events: none;
}

/* Volver al inicio se anima; arrastrar NO. Si el tirador tuviera
   transición mientras lo mueves, iría siempre por detrás del dedo. */
.deslizador__control[data-volviendo] {
  transition: none;
}

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

.puerta__icono {
  display: grid;
  place-items: center;
  width: 3.25rem; height: 3.25rem;
  border-radius: 17px;
  background: hsl(0 0% 100% / 0.20);
  box-shadow: inset 0 1px 0 hsl(0 0% 100% / 0.28);
}
.puerta__icono .icono { width: 30px; height: 30px; }

.puerta__accion {
  font-size: 1.75rem;
  font-weight: 660;
  letter-spacing: -0.028em;
  line-height: 1.1;
}
.puerta__lugar { font-size: 0.9375rem; color: hsl(0 0% 100% / 0.72); }

/* El aro es la confirmación: crece desde el centro del control
   hacia afuera cuando la puerta responde. */
.puerta__aro {
  position: absolute;
  inset: 0;
  border-radius: inherit;
  opacity: 0;
  background: radial-gradient(circle at 50% 42%, currentColor, transparent 62%);
  pointer-events: none;
}

/* El estado INUNDA el control de color, como un accesorio de la app
   Casa que se enciende. No es un borde de aviso: es el objeto entero
   cambiando. Imposible de malinterpretar de un vistazo. */
.puerta[data-fase="abriendo"] { filter: brightness(1.12) saturate(1.1); }

.puerta[data-fase="abierta"] {
  background:
    radial-gradient(120% 90% at 20% 0%, hsl(142 90% 58% / 0.95), transparent 62%),
    linear-gradient(158deg, hsl(140 82% 42%), hsl(162 86% 30%));
  border-color: hsl(142 100% 88% / 0.4);
}
.puerta[data-fase="abierta"] .puerta__aro { animation: pulso 900ms var(--salida) both; }

.puerta[data-fase="fallo"] {
  background:
    radial-gradient(120% 90% at 20% 0%, hsl(6 100% 66% / 0.95), transparent 62%),
    linear-gradient(158deg, hsl(3 88% 52%), hsl(348 84% 38%));
  border-color: hsl(6 100% 88% / 0.4);
}

@keyframes pulso {
  from { opacity: 0.5; transform: scale(0.85); }
  to   { opacity: 0; transform: scale(1.15); }
}

.puerta__pie { display: grid; gap: 0.125rem; }

/* 📌 Aquí estaban #ver-puerta, .captura__foto y una SEGUNDA definición
   de .captura y .captura__pie, para la foto a demanda. Todo se borró el
   13 de agosto de 2026.

   ⚠️ OJO CON LO QUE ESTO ARREGLA DE PASO: esas reglas repetían dos
      selectores que ya existen arriba (busca "Foto del momento del
      acceso"). Al ir después, ganaban por orden de cascada y le
      imponían su marco y su relleno a la foto de la BITÁCORA, que no
      tenía nada que ver. Al quitarlas, la foto del evento por fin usa
      las reglas escritas para ella. */

/* La cuenta va junto al título, no en un mosaico aparte.
   "Número grande + etiqueta chica" es el relleno por defecto de todo
   dashboard: ocupa espacio y no responde ninguna pregunta que el
   propio título no responda ya. */
.cuenta {
  margin: 0;
  font-size: 0.875rem;
  color: var(--tinta-media);
  font-variant-numeric: tabular-nums;
}

.encabezado--lista { align-items: baseline; margin-top: 1.75rem; }

/* Lo que va del lado derecho de un encabezado: la cuenta y el botón
   de actualizar viajan juntos, no como dos objetos sueltos. */
.encabezado__lado { display: flex; align-items: center; gap: 0.625rem; }


/* ── Listas ───────────────────────────────────────────────────
   Sin backdrop-filter aquí a propósito: estas listas hacen scroll
   y crecen, y el desenfoque las volvería lentas. */
/* El recibo, dentro de la hoja. Fondo claro porque es papel: se ve
   como se va a imprimir, no como el resto del panel. */
.recibo {
  width: 100%;
  min-height: 26rem;
  border: 1px solid var(--material-borde);
  border-radius: var(--radio);
  background: #fff;
}

/* El saldo de una casa, arriba de su estado de cuenta.
   Es lo único que el administrador viene a ver: va grande, con
   tabular-nums para que las cifras no bailen, y con el interletrado
   apretado que pide el texto de este tamaño. */
.monto-grande { text-align: center; padding: 0.5rem 0 1.5rem; }
.monto-grande__cifra {
  margin: 0;
  font-size: 2.25rem;
  font-weight: 660;
  letter-spacing: -0.03em;
  font-variant-numeric: tabular-nums;
}
.monto-grande__pie {
  margin: 0.125rem 0 0;
  font-size: 0.8125rem;
  color: var(--tinta-media);
}

.lista { display: grid; gap: 0.5rem; }

/* El nombre de un condominio lo pone el cliente y puede ser largo.
   Aquí se recorta en vez de partir la fila en varios renglones: una
   lista donde cada fila mide distinto se lee peor y se toca peor.

   Va acotado a esta lista y no a .fila en general, para no cambiar de
   rebote cómo se ven las de residentes y bitácora. */
.lista--condominios .fila__nombre,
.lista--condominios .fila__detalle {
  display: block;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.fila {
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: center;
  gap: 0.75rem;
  padding: 0.75rem 0.875rem;
  border: 1px solid var(--material-borde);
  border-radius: var(--radio);
  background: hsl(230 42% 18% / 0.46);
  /* Entra desde una posición ya visible, escalonada */
  animation: subir 320ms var(--salida) both;
  animation-delay: calc(var(--i, 0) * 36ms);
}

@keyframes subir {
  from { opacity: 0; transform: translateY(7px); }
  to   { opacity: 1; transform: none; }
}

.fila__retrato {
  width: 40px; height: 40px;
  border-radius: 50%;
  object-fit: cover;
  /* El tono sale del propio nombre, así cada persona conserva su
     color entre sesiones y la lista deja de ser una columna gris. */
  background: hsl(var(--tono, 230) 62% 42%);
  box-shadow: inset 0 1px 0 hsl(0 0% 100% / 0.22);
  display: grid; place-items: center;
  color: #fff;
  font-size: 0.8125rem;
  font-weight: 640;
  letter-spacing: 0.01em;
  flex: none;
}

.fila__cuerpo { min-width: 0; }
.fila__nombre { margin: 0; font-size: 0.9375rem; font-weight: 560; letter-spacing: -0.008em; }
.fila__detalle { margin: 0.0625rem 0 0; font-size: 0.8125rem; color: var(--tinta-media); }
.fila__hora { font-size: 0.8125rem; color: var(--tinta-media); text-align: right; white-space: nowrap; }

.marca {
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
  padding: 0.125rem 0.5rem;
  border-radius: 99px;
  font-size: 0.75rem;
  font-weight: 560;
  white-space: nowrap;
}
.marca--si { background: hsl(135 65% 45% / 0.18); color: hsl(135 70% 76%); }
.marca--no { background: hsl(37 100% 52% / 0.18); color: hsl(37 100% 74%); }
.marca--baja { background: hsl(3 100% 61% / 0.16); color: hsl(3 100% 80%); }
.marca--admin { background: hsl(211 100% 52% / 0.20); color: hsl(211 100% 82%); }

/* Filas que se pueden tocar. Son <button> y no <article>: si abre
   algo al pulsarla, tiene que ser alcanzable con el teclado y
   anunciarse como control. */
button.fila {
  width: 100%;
  text-align: left;
  font: inherit;
  color: inherit;
  cursor: pointer;
  transition: transform 140ms var(--salida), background-color 140ms ease;
  -webkit-tap-highlight-color: transparent;
}
button.fila:active { transform: scale(0.99); transition-duration: 90ms; }

@media (hover: hover) and (pointer: fine) {
  button.fila:hover { background: hsl(230 42% 24% / 0.55); }
}

/* La flecha dice "esto abre algo", sin necesidad de explicarlo */
.fila__chevron {
  width: 7px; height: 7px;
  flex: none;
  border-right: 1.5px solid var(--tinta-suave);
  border-bottom: 1.5px solid var(--tinta-suave);
  transform: rotate(-45deg);
}

.fila__lado { display: flex; align-items: center; gap: 0.625rem; }

/* Acciones dentro de una hoja: en columna, con la destructiva
   separada del resto para no tocarla por accidente. */
.acciones { display: grid; gap: 0.5rem; margin-top: 0.5rem; }
.acciones--peligro { margin-top: 1.5rem; padding-top: 1.25rem; border-top: 1px solid var(--material-borde); }

.boton--peligro { background: hsl(3 100% 61% / 0.16); color: hsl(3 100% 82%); }
@media (hover: hover) and (pointer: fine) {
  .boton--peligro:hover { background: hsl(3 100% 61% / 0.26); }
}

.dato { margin: 0 0 1rem; font-size: 0.875rem; color: var(--tinta-media); }
.dato strong { color: var(--tinta); font-weight: 600; }

/* ── Estados vacíos y de carga ────────────────────────────── */
.vacio {
  padding: 2.5rem 1.5rem;
  text-align: center;
  color: var(--tinta-media);
  border: 1px dashed var(--material-borde);
  border-radius: var(--radio);
  font-size: 0.9375rem;
}

.esqueleto {
  height: 62px;
  border-radius: var(--radio);
  background: hsl(228 24% 15% / 0.6);
  animation: latir 1.4s ease-in-out infinite;
}

/* ── Encabezado de sección ────────────────────────────────── */
.encabezado {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 1rem;
  margin-bottom: 0.875rem;
  flex-wrap: wrap;
}
.encabezado .titulo-seccion { margin: 0; }

.formulario {
  padding: 1.125rem;
  border: 1px solid var(--material-borde);
  border-radius: var(--radio);
  background: hsl(230 42% 18% / 0.46);
  margin-bottom: 1.25rem;
}

/* ── El pase generado ─────────────────────────────────────── */
.pase {
  display: grid;
  justify-items: center;
  gap: 0.875rem;
  padding: 1.5rem;
  border: 1px solid var(--material-borde);
  border-top-color: var(--material-canto);
  border-radius: var(--radio);
  background: var(--material-ligero);
  backdrop-filter: blur(20px) saturate(170%);
  -webkit-backdrop-filter: blur(20px) saturate(170%);
  animation: materializar 380ms var(--salida) both;
}

.pase__qr {
  width: 200px; height: 200px;
  border-radius: var(--radio-chico);
  background: #fff;
  padding: 10px;
  image-rendering: pixelated;   /* el QR es un mapa de bits: sin suavizar */
}

.pase__nombre { font-size: 1.0625rem; font-weight: 600; letter-spacing: -0.014em; text-align: center; }

.clave { text-align: center; }
.clave__etiqueta { display: block; font-size: 0.8125rem; color: var(--tinta-media); }
.clave__valor {
  font-size: 1.875rem;
  font-weight: 640;
  letter-spacing: 0.08em;
  line-height: 1.2;
}

/* ── Hoja emergente ───────────────────────────────────────── */
.velo {
  position: fixed;
  inset: 0;
  z-index: 40;
  background: hsl(228 40% 2% / 0.55);
  animation: aparecer 240ms ease both;
}
@keyframes aparecer { from { opacity: 0; } to { opacity: 1; } }

.hoja {
  position: fixed;
  z-index: 50;
  left: 0; right: 0; bottom: 0;
  max-height: 88dvh;
  overflow-y: auto;
  overscroll-behavior: contain;
  padding-bottom: max(1.25rem, env(safe-area-inset-bottom));
  border: 1px solid var(--material-borde);
  border-top-color: var(--material-canto);
  border-radius: 26px 26px 0 0;
  background: var(--material-grueso);
  backdrop-filter: blur(34px) saturate(180%);
  -webkit-backdrop-filter: blur(34px) saturate(180%);
  box-shadow: 0 -12px 48px hsl(228 40% 2% / 0.5);
  /* Entra por abajo y sale por abajo: si algo desaparece por un
     lado, esperamos que vuelva a salir por ahí. */
  animation: subir-hoja 340ms var(--salida) both;
}

@keyframes subir-hoja {
  from { transform: translateY(100%); }
  to   { transform: none; }
}

.hoja__barra {
  position: sticky;
  top: 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 1rem 1.125rem 0.75rem;
  background: inherit;
}
.hoja__titulo { font-size: 1.125rem; letter-spacing: -0.018em; }
.hoja__cuerpo { padding: 0 1.125rem; }

/* ── Notificaciones ───────────────────────────────────────── */
.avisos {
  position: fixed;
  z-index: 60;
  left: 50%;
  bottom: calc(env(safe-area-inset-bottom) + 5.5rem);
  transform: translateX(-50%);
  display: grid;
  gap: 0.5rem;
  width: min(92vw, 26rem);
  pointer-events: none;
}

.nota {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.75rem 1rem;
  border: 1px solid var(--material-borde);
  border-radius: 999px;
  background: var(--material-grueso);
  backdrop-filter: blur(24px) saturate(180%);
  -webkit-backdrop-filter: blur(24px) saturate(180%);
  box-shadow: 0 10px 28px hsl(228 40% 2% / 0.45);
  font-size: 0.875rem;
  /* Transición, no keyframes: se pueden interrumpir y reapuntar
     si llegan varias notas seguidas. */
  animation: nota-entra 300ms var(--salida) both;
}

@keyframes nota-entra {
  from { opacity: 0; transform: translateY(12px) scale(0.96); }
  to   { opacity: 1; transform: none; }
}

.nota[data-tipo="bien"] { color: hsl(135 70% 84%); }
.nota[data-tipo="mal"] { color: hsl(3 100% 84%); }
.nota .icono { width: 18px; height: 18px; flex: none; }

/* ══ ESCRITORIO ════════════════════════════════════════════ */
@media (min-width: 56rem) {
  .panel {
    display: grid;
    grid-template-columns: 15rem 1fr;
    /* "auto 1fr" y no filas automáticas: con min-height 100dvh y dos
       filas automáticas, el sobrante de altura se reparte entre
       ambas e infla la barra hasta 246px para 40px de contenido.
       Así la barra mide lo que mide su contenido y el resto se lo
       queda el lienzo. */
    grid-template-rows: auto 1fr;
    grid-template-areas: "barra barra" "nav lienzo";
  }

  .barra { grid-area: barra; padding: 0.75rem 1.5rem; }

  .navegacion {
    grid-area: nav;
    position: sticky;
    top: 4rem;
    align-self: start;
    inset: auto;
    grid-auto-flow: row;
    gap: 0.125rem;
    padding: 1.25rem 0.875rem;
    border-top: 0;
    background: none;
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
  }

  .navegacion__opcion {
    grid-auto-flow: column;
    justify-items: start;
    justify-content: start;
    align-items: center;
    gap: 0.75rem;
    min-height: 44px;
    padding: 0.625rem 0.875rem;
    font-size: 0.9375rem;
  }
  .navegacion__opcion[aria-current="page"] { background: var(--material-ligero); color: var(--tinta); }

  .lienzo { grid-area: lienzo; padding: 1.75rem 1.5rem 3rem; margin: 0; max-width: 72rem; }

  /* En escritorio el control de puerta NO se estira a todo lo ancho.
     Estirado deja de leerse como control y se vuelve un banner: el
     texto ocupa 153px y el resto queda vacío.
     El contrato de dirección dice "la acción principal va arriba a
     la izquierda en escritorio", así que aquí se cumple: control a
     la izquierda, actividad a la derecha. */
  #vista-inicio {
    display: grid;
    grid-template-columns: minmax(17rem, 21rem) 1fr;
    column-gap: 1.5rem;
    align-items: start;
  }
  /* El aviso de residentes sin PIN cruza las dos columnas: es lo
     único de esta pantalla que pide una decisión, y partirlo en
     una columna lo escondería al lado del control de la puerta. */
  #vista-inicio > .estado { grid-column: 1 / -1; grid-row: 1; }
  #vista-inicio > #pendientes { grid-column: 1 / -1; grid-row: 2; }
  #vista-inicio > #pendientes:empty { display: none; }
  #vista-inicio > .puerta { grid-column: 1; grid-row: 3 / span 2; min-height: 15.5rem; }
  #vista-inicio > .encabezado--lista { grid-column: 2; grid-row: 3; margin-top: 0; }
  #vista-inicio > #recientes { grid-column: 2; grid-row: 4; }


  .avisos { bottom: 1.5rem; }
}

/* ══ PREFERENCIAS DEL USUARIO ══════════════════════════════
   No son un extra: son parte del trabajo. */

/* Movimiento reducido no significa "sin respuesta": significa una
   respuesta más suave. Se conserva la opacidad, que ayuda a
   entender; se quita el desplazamiento, que marea. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
  .acceso__hoja, .pase, .fila, .nota { animation: aparecer 200ms ease both !important; }
  .estado__punto[data-estado="cargando"] { animation: none; opacity: 0.6; }
}

/* Quien pide menos transparencia necesita superficies sólidas:
   el desenfoque se quita y el fondo se opaca. */
@media (prefers-reduced-transparency: reduce) {
  .acceso__hoja, .barra, .navegacion, .hoja, .nota, .puerta, .pase {
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
    background: var(--base-alta);
  }
}

@media (prefers-contrast: more) {
  :root {
    --tinta-media: hsl(228 20% 86%);
    --tinta-suave: hsl(228 16% 74%);
    --material-borde: hsl(228 30% 90% / 0.34);
  }
  .acceso__hoja, .barra, .navegacion, .hoja, .puerta, .fila, .resumen__dato {
    background: var(--base-alta);
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
  }
}

/* ══ VIDRIO ADAPTATIVO ═════════════════════════════════════
   El atributo lo pone ajustarVidrio() en app.js según la potencia
   real del equipo. La idea no es elegir entre bonito y rápido para
   todos, sino darle a cada quien lo que su máquina aguante. */

/* Equipo medio: se conserva el material, con la mitad de desenfoque.
   Sube la opacidad de fondo para compensar lo que se pierde. */
[data-rendimiento="medio"] {
  --material-grueso: hsl(230 40% 20% / 0.66);
  --material-ligero: hsl(230 45% 44% / 0.34);
}
[data-rendimiento="medio"] .barra,
[data-rendimiento="medio"] .navegacion,
[data-rendimiento="medio"] .hoja,
[data-rendimiento="medio"] .nota,
[data-rendimiento="medio"] .acceso__hoja,
[data-rendimiento="medio"] .pase {
  backdrop-filter: blur(12px) saturate(150%);
  -webkit-backdrop-filter: blur(12px) saturate(150%);
}

/* Mientras el dedo hace scroll, el desenfoque es lo más caro que
   existe: se recalcula en cada cuadro. Lo apagamos y lo devolvemos
   al soltar; el fondo opaco cubre el hueco sin que se note. */
[data-rendimiento="medio"][data-scroll] .barra,
[data-rendimiento="medio"][data-scroll] .navegacion {
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  background: var(--base-alta);
}

/* Equipo de gama baja: superficies sólidas. Se ve bien y se mueve
   sin tirones, que es lo que de verdad importa ahí. */
[data-rendimiento="bajo"] .barra,
[data-rendimiento="bajo"] .navegacion,
[data-rendimiento="bajo"] .hoja,
[data-rendimiento="bajo"] .nota,
[data-rendimiento="bajo"] .acceso__hoja,
[data-rendimiento="bajo"] .pase {
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  background: var(--base-alta);
}

/* ── Comunidad: amenidades, reservas y solicitudes ────────────
   Lo mínimo que no existía ya. Todo lo demás (fila, marca, ficha,
   campo, acciones) se reusa tal cual: una sección que inventa su
   propio vocabulario visual se ve prestada aunque nadie sepa decir
   por qué. */

/* "Por aprobar" no es ni concedido ni denegado: es que falta una
   decisión. Usa el ámbar reservado para precaución, que es
   exactamente lo que significa. */
.marca--espera { background: hsl(37 100% 52% / 0.18); color: hsl(37 100% 74%); }

/* Dos campos que van juntos porque se leen juntos: abre/cierra,
   mínimo/máximo. En celular se apilan. */
.campo-doble { display: grid; grid-template-columns: 1fr 1fr; gap: 0.75rem; }
@media (max-width: 26rem) { .campo-doble { grid-template-columns: 1fr; } }

/* Una casilla con su etiqueta al lado, no encima. */
.campo--fila {
  display: flex;
  align-items: center;
  gap: 0.625rem;
  /* 44px de objetivo táctil, el mínimo de DESIGN.md, sin excepción. */
  min-height: 2.75rem;
}
.campo--fila input[type="checkbox"] {
  inline-size: 1.15rem;
  block-size: 1.15rem;
  accent-color: var(--azul);
  flex: none;
}
.campo--fila .campo__etiqueta { margin: 0; }

/* Dos botones lado a lado: rechazar y aprobar. */
.acciones--par { grid-template-columns: 1fr 1fr; }

/* La conversación de una solicitud. Sin desenfoque: puede crecer y
   hacer scroll, y ahí el navegador lo recalcularía en cada cuadro
   (regla 2 de DESIGN.md). */
.conversacion {
  display: grid;
  gap: 0.625rem;
  margin: 0.875rem 0;
  max-block-size: 22rem;
  overflow-y: auto;
  padding-inline-end: 0.25rem;
}

.mensaje {
  padding: 0.625rem 0.75rem;
  border-radius: 0.875rem;
  background: var(--material-ligero);
  border: 1px solid var(--material-borde);
  /* Que no se peguen a los dos bordes: se lee de quién es por dónde
     está, antes que por el nombre. */
  max-inline-size: 88%;
}
/* Los míos (del administrador) van del otro lado y en azul: es la
   convención que todo el mundo ya trae aprendida de su app de
   mensajes, y aquí no hay ninguna razón para contradecirla. */
.mensaje--mio {
  margin-inline-start: auto;
  background: hsl(211 100% 52% / 0.16);
  border-color: hsl(211 100% 62% / 0.28);
}
.mensaje__quien {
  margin: 0 0 0.2rem;
  font-size: 0.75rem;
  font-weight: 550;
  color: var(--tinta-suave);
}
.mensaje__texto {
  margin: 0;
  font-size: 0.9375rem;
  line-height: 1.45;
  color: var(--tinta);
  /* Los saltos de línea que escribió la persona se respetan: un
     reporte de tres puntos escrito en tres renglones no se puede
     aplastar en un párrafo. */
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

[hidden] { display: none !important; }
