/* ============================================================
   LA BANCA ROTA · Portal de miembros

   Se apoya en css/lbr.css: las variables de marca, los botones,
   .form-card y .field vienen de ahí. Aquí solo va lo que el
   portal necesita y la web pública no.
   ============================================================ */

/* ---------- El atributo `hidden` tiene que ganar SIEMPRE ----------
   El navegador oculta lo marcado con `hidden` mediante una regla suya,
   `[hidden] { display: none }`. Pero los estilos de una hoja de autor pesan
   más que los del navegador, así que basta con darle `display: grid` a un
   elemento para que su `hidden` deje de funcionar, sin ningún aviso.

   Ya mordió tres veces aquí: el contador de la campana seguía pintado después
   de leer las novedades, y en la pantalla de entrar aparecía el separador
   "o con tu correo" sin ningún botón encima.

   Es de los pocos sitios donde `!important` es la respuesta correcta: oculto
   es oculto, y ninguna regla de maquetación debería poder discutirlo. */
[hidden] { display: none !important; }

/* ---------- Barra del modo demo ----------
   Deliberadamente fea y chillona: tiene que ser imposible confundir esto con
   el portal de verdad. Solo aparece con ?demo en la URL. */

.demo-barra {
  position: relative; z-index: 1000;
  background: #FFB020; color: #1a1000;
  font-size: 13.5px; font-weight: 700; text-align: center;
  padding: 9px 18px; letter-spacing: .02em;
}
.demo-barra a { text-decoration: underline; color: #1a1000; }
.demo-barra a:hover { opacity: .7; }

/* ---------- Remiendos al sistema base ----------
   Dos cosas que lbr.css no cubría porque la web pública no las usaba:
   el campo de fecha y el texto de ayuda bajo un campo. */

.field input[type=date] {
  width: 100%; padding: 12px 15px; border-radius: 12px;
  background: rgba(0, 0, 0, .28); border: 1px solid var(--line-soft);
  color: var(--tx); font-family: var(--sans); font-size: 16px;
  outline: none; transition: border-color .3s;
}
.field input[type=date]:focus { border-color: var(--lime); }
/* Safari e iOS pintan el icono del calendario en negro sobre fondo oscuro. */
.field input[type=date]::-webkit-calendar-picker-indicator { filter: invert(1); opacity: .55; cursor: pointer; }

.hint { margin-top: 9px; font-size: 13.5px; color: var(--tx-mute); line-height: 1.5; }

/* ---------- Barra del miembro ---------- */

.portal-bar {
  position: sticky; top: 0; z-index: 900;
  background: rgba(5, 20, 10, .92);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  border-bottom: 1px solid var(--line-soft);
}

.portal-bar-inner {
  max-width: var(--maxw); margin: 0 auto; padding: 14px 28px;
  display: flex; align-items: center; gap: 26px; flex-wrap: wrap;
}

.portal-bar .portal-logo { display: flex; align-items: center; gap: 11px; flex-shrink: 0; }
.portal-bar .portal-logo img { height: 30px; width: auto; }
.portal-bar .portal-logo span {
  font-family: 'Supersonic', sans-serif; font-size: 19px;
  text-transform: uppercase; letter-spacing: .01em;
}

.portal-menu { display: flex; gap: 22px; align-items: center; flex-wrap: wrap; }

.portal-menu a {
  font-size: 15px; font-weight: 700; color: var(--tx-soft);
  padding: 6px 0; border-bottom: 2px solid transparent;
  transition: color .25s, border-color .25s;
}
.portal-menu a:hover { color: var(--tx); }
.portal-menu a[aria-current="page"] { color: var(--lime); border-bottom-color: var(--lime); }

.portal-usuario { margin-left: auto; display: flex; align-items: center; gap: 14px; }

/* ---------- Campana de novedades ---------- */

.campana-caja { position: relative; }

.campana {
  position: relative;
  display: grid; place-items: center;
  width: 38px; height: 38px;
  background: none; border: 1px solid var(--line-soft); border-radius: 50%;
  color: var(--tx-soft); cursor: pointer;
  transition: border-color .25s, color .25s, background .25s;
}
.campana:hover { border-color: var(--line); color: var(--lime); background: rgba(210,251,84,.06); }
.campana:focus-visible { outline: 2px solid var(--lime); outline-offset: 2px; }
.campana svg { width: 19px; height: 19px; fill: none; stroke: currentColor; stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; }
.campana.con-novedades { color: var(--lime); border-color: var(--line); }

/* El contador. Es lo único del portal que puede llevar rojo: aquí el objetivo
   es justamente que salte a la vista. */
.campana-cuenta {
  position: absolute; top: -3px; right: -3px;
  min-width: 18px; height: 18px; padding: 0 5px;
  display: grid; place-items: center;
  border-radius: 999px;
  background: #E5484D; color: #fff;
  font-size: 11px; font-weight: 700; line-height: 1;
  border: 2px solid var(--bg);
}

.campana-panel {
  position: absolute; top: calc(100% + 12px); right: 0; z-index: 950;
  width: min(360px, calc(100vw - 36px));
  background: #08200F;
  border: 1px solid var(--line-soft); border-radius: 16px;
  box-shadow: 0 24px 60px rgba(0, 0, 0, .55);
  overflow: hidden;
  animation: campanaEntra .22s var(--ease);
}
@keyframes campanaEntra {
  from { opacity: 0; transform: translateY(-6px); }
  to   { opacity: 1; transform: none; }
}

.campana-titulo {
  padding: 13px 18px;
  font-size: 11.5px; font-weight: 700; letter-spacing: .18em; text-transform: uppercase;
  color: var(--tx-mute);
  border-bottom: 1px solid var(--line-soft);
  background: rgba(0, 0, 0, .22);
}

.campana-lista { max-height: 60vh; overflow-y: auto; }

.campana-item {
  display: flex; align-items: flex-start; gap: 12px;
  width: 100%; text-align: left;
  padding: 13px 18px;
  background: none; border: 0; border-bottom: 1px solid var(--line-soft);
  color: var(--tx); cursor: pointer;
  font-family: var(--sans);
  transition: background .2s;
}
.campana-item:last-child { border-bottom: 0; }
.campana-item:hover { background: rgba(210, 251, 84, .06); }
.campana-item:focus-visible { outline: 2px solid var(--lime); outline-offset: -2px; }

.campana-icono {
  flex-shrink: 0; width: 28px; height: 28px;
  display: grid; place-items: center; border-radius: 9px;
  background: rgba(210, 251, 84, .10); border: 1px solid var(--line);
  color: var(--lime); font-size: 13px;
}

.campana-txt { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.campana-txt b { font-size: 14.5px; font-weight: 700; line-height: 1.35; }
.campana-txt i { font-style: normal; font-size: 12.5px; color: var(--tx-mute); }

.campana-vacio {
  margin: 0; padding: 24px 18px; text-align: center;
  color: var(--tx-mute); font-size: 14px;
}

@media (max-width: 680px) {
  /* Anclado a la derecha de la pantalla, no del botón: en móvil el botón está
     casi en el borde y el panel se saldría. */
  .campana-panel { position: fixed; top: 62px; right: 12px; left: 12px; width: auto; }
}
.portal-usuario-nombre { font-weight: 700; font-size: 15px; }
.portal-usuario-enlace { font-size: 14px; color: var(--turquesa); }
.portal-usuario-enlace:hover { text-decoration: underline; }

.portal-usuario-salir {
  background: none; border: 1px solid var(--line-soft); color: var(--tx-soft);
  font-family: var(--sans); font-size: 14px; font-weight: 700;
  padding: 7px 15px; border-radius: 999px; cursor: pointer;
  transition: border-color .25s, color .25s;
}
.portal-usuario-salir:hover { border-color: var(--line); color: var(--lime); }

/* ---------- Encabezado de sección ---------- */

.portal-head { padding: 54px 0 8px; }
.portal-head h1 { font-size: clamp(38px, 6.5vw, 66px); margin: 18px 0 14px; }
.portal-head p { color: var(--tx-soft); max-width: 62ch; }

.portal-seccion { padding: 34px 0 60px; }
.portal-seccion + .portal-seccion { padding-top: 8px; }

.portal-seccion-head {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 18px; flex-wrap: wrap; margin-bottom: 22px;
}
.portal-seccion-head h2 { font-size: clamp(26px, 4vw, 38px); }
.portal-seccion-head .portal-contador { color: var(--tx-mute); font-size: 15px; font-weight: 700; }

/* ---------- Tarjetas de material ---------- */

.portal-lista { display: grid; gap: 18px; }
.portal-lista.dos { grid-template-columns: repeat(2, 1fr); }
.portal-lista.tres { grid-template-columns: repeat(3, 1fr); }

.portal-item {
  position: relative; overflow: hidden;
  display: flex; flex-direction: column; gap: 12px;
  background: var(--surface); border: 1px solid var(--line-soft);
  border-radius: var(--radius); padding: 26px 24px;
  transition: border-color .3s, background .3s, transform .3s var(--ease);
}
.portal-item:hover { border-color: var(--line); background: var(--surface-2); }

/* ---------- Imagen de fondo de la tarjeta ----------
   Primero lo intenté con la foto tenue por debajo de todo el texto. Se leía
   perfecto y no se veía la foto: entre bajarla de opacidad y taparla con un
   velo, quedaba en un 1% de presencia justo donde uno mira.

   Este enfoque separa las dos cosas en el espacio en vez de apilarlas: la foto
   ocupa la DERECHA de la tarjeta y se desvanece con una máscara antes de
   llegar al texto. Así la foto se ve de verdad y el título nunca compite con
   ella, porque literalmente no hay foto debajo.

     ::before  la foto, recortada con una máscara horizontal;
     ::after   un velo que deja limpia la izquierda y suaviza la derecha. */

/* La foto va en un <div class="portal-foto"> con su background-image en línea,
   no en un ::before que lea una variable CSS. Ese fue el primer intento y no
   pintaba nada: una ruta relativa dentro de una variable CSS se resuelve
   contra bases distintas según el navegador, y en algunos acababa pidiendo
   /css/assets/… — un 404 silencioso. */
.portal-foto {
  position: absolute; inset: 0; z-index: 0;
  background-size: cover;
  background-position: center right;
  background-repeat: no-repeat;
  opacity: .82;
  /* De transparente a opaca entre el 38% y el 92% del ancho: el texto vive a
     la izquierda de ese arranque. */
  -webkit-mask-image: linear-gradient(90deg,
    transparent 38%, rgba(0, 0, 0, .45) 62%, #000 92%);
  mask-image: linear-gradient(90deg,
    transparent 38%, rgba(0, 0, 0, .45) 62%, #000 92%);
  transition: opacity .4s var(--ease), transform .6s var(--ease);
  pointer-events: none;
}

.portal-item.con-imagen::after {
  content: ''; position: absolute; inset: 0; z-index: 0;
  background: linear-gradient(
    90deg,
    rgba(5, 20, 10, .97) 0%,
    rgba(5, 20, 10, .92) 45%,
    rgba(5, 20, 10, .40) 72%,
    rgba(5, 20, 10, .14) 100%
  );
}

/* El contenido va por encima de la foto y del velo; la foto se queda abajo. */
.portal-item.con-imagen > *:not(.portal-foto) { position: relative; z-index: 1; }

.portal-item.con-imagen:hover .portal-foto { opacity: 1; transform: scale(1.04); }

/* Bloqueada: la tarjeta ya va al 72% de opacidad, así que la foto se apaga
   para que no quede una mancha sucia junto al candado. */
.portal-item.bloqueado .portal-foto { opacity: .38; }
.portal-item.bloqueado:hover .portal-foto { opacity: .48; transform: none; }

/* En móvil la tarjeta es estrecha y el texto ocupa todo el ancho: ahí no hay
   una derecha libre donde poner la foto, así que vuelve a ir por debajo, tenue
   y con velo plano. */
@media (max-width: 680px) {
  .portal-foto {
    opacity: .30;
    -webkit-mask-image: none;
    mask-image: none;
  }
  .portal-item.con-imagen::after { background: rgba(5, 20, 10, .78); }
  .portal-item.con-imagen:hover .portal-foto { opacity: .30; transform: none; }
  .portal-item.bloqueado .portal-foto { opacity: .16; }
}

@media (prefers-reduced-motion: reduce) {
  .portal-item.con-imagen:hover .portal-foto { transform: none; }
}

.portal-item-top { display: flex; align-items: flex-start; gap: 14px; }

.portal-num {
  flex-shrink: 0; width: 40px; height: 40px; border-radius: 12px;
  display: grid; place-items: center;
  background: rgba(210, 251, 84, .10); border: 1px solid var(--line);
  color: var(--lime); font-weight: 700; font-size: 16px;
}

.portal-item h3 { font-size: 21px; line-height: 1.15; margin-bottom: 4px; }
.portal-item p { color: var(--tx-soft); font-size: 15.5px; margin: 0; }

.portal-item-pie {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  margin-top: auto; padding-top: 6px;
}

/* Bloqueado: se ve, pero no se abre. Ocultarlo dejaría el portal gratuito
   vacío y sin ninguna razón visible para pagar. */
.portal-item.bloqueado { opacity: .72; }
.portal-item.bloqueado .portal-num {
  background: rgba(245, 250, 254, .05); border-color: var(--line-soft); color: var(--tx-mute);
}
.portal-item.bloqueado:hover { border-color: var(--line-soft); background: var(--surface); }

.portal-etiqueta {
  display: inline-flex; align-items: center; gap: 7px;
  font-size: 12.5px; font-weight: 700; letter-spacing: .1em; text-transform: uppercase;
  padding: 5px 12px; border-radius: 999px;
  border: 1px solid var(--line-soft); color: var(--tx-mute);
}
.portal-etiqueta.lima { border-color: var(--line); color: var(--lime); background: rgba(210,251,84,.07); }
.portal-etiqueta.turquesa { border-color: rgba(47,178,175,.34); color: var(--turquesa); background: rgba(47,178,175,.07); }

.portal-abrir {
  display: inline-flex; align-items: center; gap: 9px;
  background: var(--lime); color: var(--verde-oscuro);
  font-family: var(--sans); font-size: 15px; font-weight: 700;
  border: 0; border-radius: 999px; padding: 10px 20px; cursor: pointer;
  transition: transform .25s var(--ease), box-shadow .25s;
}
.portal-abrir:hover { transform: translateY(-2px); box-shadow: 0 10px 26px rgba(210,251,84,.24); }
.portal-abrir[disabled] { opacity: .5; cursor: not-allowed; transform: none; box-shadow: none; }

.portal-abrir.secundario {
  background: transparent; color: var(--tx);
  border: 1px solid var(--line-soft);
}
.portal-abrir.secundario:hover { border-color: var(--line); color: var(--lime); box-shadow: none; }

/* ---------- Lista de boletines ----------
   Salen dos por semana y todos se llaman igual, así que la fecha es lo único
   que distingue un número de otro: va delante, en grande, y la lista se agrupa
   por mes. En tarjetas grandes esto serían cien rectángulos idénticos. */

/* ---------- Boletines: archivo e información adicional, en paralelo ----------
   El archivo se lleva el doble de ancho porque es lo que crece: dos números por
   semana. La columna de al lado son documentos sueltos, unos pocos. */

.boletines-cols {
  display: grid;
  grid-template-columns: minmax(0, 2fr) minmax(0, 1fr);
  gap: 0 30px;
  align-items: start;
}

/* Las cabeceras van las dos en la MISMA fila de la rejilla, y las listas en la
   fila de abajo. Así se alinean siempre, sin que importe si un título se parte
   en dos líneas: la fila mide lo que mida la más alta y las dos listas
   arrancan a la vez. Antes dependía de cuadrar tamaños de letra a ojo, y eso
   se rompe en cuanto cambia el texto o el ancho de la ventana.

   `display: contents` deja que los hijos de <section> y <aside> sean piezas
   directas de la rejilla, sin perder el agrupado semántico. */
.boletines-cols > section,
.boletines-cols > aside { display: contents; }

.boletines-cols > section > .portal-seccion-head { grid-column: 1; grid-row: 1; }
.boletines-cols > section > .boletin-lista       { grid-column: 1; grid-row: 2; }
.boletines-cols > aside   > .portal-seccion-head { grid-column: 2; grid-row: 1; }
.boletines-cols > aside   > .boletin-lista       { grid-column: 2; grid-row: 2; }

/* Sin documentos sueltos no hay segunda columna que llenar. */
.boletines-cols.sin-adicional { grid-template-columns: 1fr; }

.boletines-cols .portal-seccion-head {
  align-items: flex-end;
  margin-bottom: 20px;
}
.boletines-cols .portal-seccion-head h2 { font-size: clamp(24px, 2.4vw, 30px); }

/* En pantalla estrecha se apilan. Aquí `display: contents` estorbaría: sin él,
   cada columna vuelve a ser un bloque y el orden natural del HTML manda, con
   el archivo arriba por ser lo principal. */
@media (max-width: 900px) {
  .boletines-cols { display: block; }
  .boletines-cols > section,
  .boletines-cols > aside { display: block; }
  /* lbr.css le da a TODO <section> un relleno enorme para las franjas de la
     web pública (`clamp(80px, 11vw, 148px)`). En escritorio no molesta porque
     `display: contents` elimina la caja, pero aquí vuelve a existir. */
  .boletines-cols > section { padding: 0; margin: 0; }
  .boletines-cols > aside { padding: 0; margin: 44px 0 0; }
}

/* Cada mes es un <details> plegable. Solo el más reciente viene abierto: al
   año son cien filas, y una lista de cien renglones no es un archivo. */
.mes-grupo { border-bottom: 1px solid var(--line-soft); }
.mes-grupo:last-child { border-bottom: 0; }

.boletin-mes {
  display: flex; align-items: center; gap: 12px;
  font-family: var(--sans);
  font-size: 11.5px; font-weight: 700; letter-spacing: .18em; text-transform: uppercase;
  color: var(--tx-mute);
  margin: 0;
  padding: 11px 18px;
  background: rgba(0, 0, 0, .22);
  cursor: pointer;
  user-select: none;
  transition: background .2s, color .2s;
}
.boletin-mes:hover { background: rgba(0, 0, 0, .34); color: var(--tx-soft); }
.boletin-mes:focus-visible { outline: 2px solid var(--lime); outline-offset: -2px; }

/* Fuera el triángulo por defecto: se sustituye por uno propio a la derecha. */
.boletin-mes::-webkit-details-marker { display: none; }
.boletin-mes { list-style: none; }
.boletin-mes::marker { content: ''; }

.boletin-mes-conteo {
  letter-spacing: .06em; text-transform: none;
  color: var(--tx-mute); font-weight: 400; font-size: 12.5px;
}

.boletin-mes-flecha {
  margin-left: auto;
  width: 8px; height: 8px;
  border-right: 2px solid currentColor; border-bottom: 2px solid currentColor;
  transform: rotate(45deg) translate(-2px, -2px);
  transition: transform .25s var(--ease);
}
.mes-grupo[open] > .boletin-mes { color: var(--lime); background: rgba(210, 251, 84, .07); }
.mes-grupo[open] > .boletin-mes .boletin-mes-flecha {
  transform: rotate(-135deg) translate(-2px, -2px);
}

/* Dentro de un mes abierto, la última fila no necesita raya: ya la pone el
   propio grupo. */
.mes-grupo > .boletin:last-child { border-bottom: 0; }

@media (max-width: 680px) {
  .boletin-mes { padding: 10px 14px; gap: 8px; }
  .boletin-mes-conteo { font-size: 11.5px; }
}

/* La lista es un solo bloque con filas separadas por una línea, no una pila de
   cajas sueltas: con muchos números, cada caja con su borde y su sombra crea un
   ruido visual que impide recorrer la lista con la vista. */
.boletin-lista {
  border: 1px solid var(--line-soft);
  border-radius: 14px;
  overflow: hidden;
  background: var(--surface);
}

/* Una fila = una línea. La fila entera es clicable. */
.boletin {
  display: flex; align-items: center; gap: 16px;
  width: 100%; text-align: left;
  padding: 13px 18px;
  border: 0; border-bottom: 1px solid var(--line-soft);
  background: none; color: var(--tx);
  font-family: var(--sans); font-size: 15.5px;
  cursor: pointer;
  transition: background .2s, padding-left .2s var(--ease);
}
.boletin:last-child { border-bottom: 0; }
.boletin:hover { background: rgba(210, 251, 84, .06); padding-left: 24px; }
.boletin:focus-visible { outline: 2px solid var(--lime); outline-offset: -2px; }

/* Fecha: ancho fijo para que todas las filas queden alineadas en columna. */
.boletin-dia {
  flex: 0 0 68px;
  font-weight: 700; color: var(--lime);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.boletin-nombre { font-weight: 700; white-space: nowrap; }

/* Titular del número, si lo tiene. Se corta antes que empujar la fila. */
.boletin-nota {
  flex: 1; min-width: 0;
  color: var(--tx-mute); font-size: 14.5px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

.boletin-marca {
  margin-left: auto;
  font-size: 11.5px; font-weight: 700; letter-spacing: .12em; text-transform: uppercase;
  color: var(--lime);
  padding: 3px 10px; border-radius: 999px;
  border: 1px solid var(--line); background: rgba(210, 251, 84, .07);
  white-space: nowrap;
}

.boletin-flecha {
  margin-left: auto; padding-left: 8px;
  color: var(--tx-mute); font-size: 15px;
  transition: color .2s, transform .2s var(--ease);
}
/* Cuando hay distintivo, él se lleva el `margin-left:auto` y la flecha ya no. */
.boletin-marca ~ .boletin-flecha { margin-left: 0; }
.boletin:hover .boletin-flecha { color: var(--lime); transform: translateX(3px); }

.boletin.bloqueado, .boletin.roto { opacity: .6; }
.boletin.roto { cursor: default; }
.boletin.roto:hover { background: none; padding-left: 18px; }
.boletin.bloqueado .boletin-dia { color: var(--tx-mute); }

@media (max-width: 680px) {
  .boletin { gap: 12px; padding: 12px 14px; font-size: 15px; }
  .boletin:hover { padding-left: 14px; }
  .boletin-dia { flex: 0 0 58px; }
  /* En pantalla estrecha no caben nombre y titular: manda el titular, que es
     lo que distingue un número de otro cuando existe. */
  .boletin-nota { display: none; }
  .boletin-marca { font-size: 10.5px; padding: 3px 8px; }
}

/* ---------- Progreso ---------- */

.portal-progreso { display: flex; align-items: center; gap: 14px; margin-top: 8px; }

.portal-barra {
  flex: 1; height: 8px; border-radius: 999px; overflow: hidden;
  background: rgba(245, 250, 254, .08);
}
.portal-barra span {
  display: block; height: 100%; border-radius: 999px;
  background: linear-gradient(90deg, var(--turquesa), var(--lime));
  transition: width .6s var(--ease);
}
.portal-progreso-txt { font-size: 14px; font-weight: 700; color: var(--tx-soft); white-space: nowrap; }

.portal-completado {
  display: inline-flex; align-items: center; gap: 7px;
  color: var(--lime); font-size: 14px; font-weight: 700;
}

/* ---------- Avisos y estados ---------- */

.portal-aviso {
  display: flex; gap: 16px; align-items: flex-start;
  border-radius: var(--radius); padding: 22px 24px; margin-bottom: 26px;
  background: rgba(47, 178, 175, .08); border: 1px solid rgba(47, 178, 175, .28);
}
.portal-aviso.lima { background: rgba(210,251,84,.07); border-color: var(--line); }
.portal-aviso.alerta { background: rgba(255, 138, 138, .07); border-color: rgba(255,138,138,.3); }
.portal-aviso h3 { font-size: 19px; margin-bottom: 6px; }
.portal-aviso p { font-size: 15px; color: var(--tx-soft); margin: 0; }
.portal-aviso .btn { flex-shrink: 0; margin-left: auto; }

.portal-vacio {
  text-align: center; padding: 56px 26px;
  border: 1px dashed var(--line-soft); border-radius: var(--radius-l);
  color: var(--tx-mute);
}
.portal-vacio h3 { font-size: 22px; color: var(--tx-soft); margin-bottom: 8px; }

.portal-cargando { text-align: center; padding: 60px 20px; color: var(--tx-mute); }

.portal-error {
  display: none; border-radius: 12px; padding: 15px 18px; margin: 16px 0;
  background: rgba(255, 138, 138, .09); border: 1px solid rgba(255, 138, 138, .32);
  color: #ffb3b3; font-size: 15px; font-weight: 700;
}
.portal-error.visible { display: block; }

/* ---------- Portada del portal ---------- */

.portal-tarjetas { display: grid; grid-template-columns: repeat(3, 1fr); gap: 18px; margin-bottom: 12px; }

.portal-atajo {
  display: block; padding: 30px 26px; border-radius: var(--radius-l);
  background: var(--surface); border: 1px solid var(--line-soft);
  transition: transform .4s var(--ease), border-color .3s, background .3s;
}
.portal-atajo:hover { transform: translateY(-4px); border-color: var(--line); background: var(--surface-2); }
.portal-atajo h3 { font-size: 25px; margin: 14px 0 8px; }
.portal-atajo p { color: var(--tx-soft); font-size: 15.5px; margin: 0; }
.portal-atajo .portal-atajo-num {
  font-family: 'Bebas Neue', Impact, sans-serif; font-size: 44px; color: var(--lime); line-height: 1;
}

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

.portal-perfil { display: grid; grid-template-columns: 1fr 1fr; gap: 22px; align-items: start; }
.portal-perfil .ancho { grid-column: 1 / -1; }

.portal-dato { display: flex; justify-content: space-between; gap: 16px; padding: 13px 0; border-bottom: 1px solid var(--line-soft); }
.portal-dato:last-child { border-bottom: 0; }
.portal-dato dt { color: var(--tx-mute); font-size: 14.5px; }
.portal-dato dd { font-weight: 700; font-size: 15px; text-align: right; }

.portal-sesion { display: flex; justify-content: space-between; gap: 14px; padding: 14px 0; border-bottom: 1px solid var(--line-soft); font-size: 14.5px; }
.portal-sesion:last-child { border-bottom: 0; }
.portal-sesion .dispositivo { color: var(--tx-soft); word-break: break-word; max-width: 60%; }
.portal-sesion .actual { color: var(--lime); font-weight: 700; }

/* ---------- Responsive ---------- */

@media (max-width: 900px) {
  .portal-lista.tres, .portal-tarjetas { grid-template-columns: repeat(2, 1fr); }
  .portal-perfil { grid-template-columns: 1fr; }
}

@media (max-width: 680px) {
  .portal-bar-inner { padding: 12px 18px; gap: 14px; }
  .portal-menu { order: 3; width: 100%; gap: 16px; overflow-x: auto; padding-bottom: 2px; }
  .portal-menu::-webkit-scrollbar { display: none; }
  .portal-usuario { margin-left: auto; }
  .portal-usuario-nombre { display: none; }
  .portal-lista.dos, .portal-lista.tres, .portal-tarjetas { grid-template-columns: 1fr; }
  .portal-head { padding: 34px 0 6px; }
  .portal-aviso { flex-direction: column; }
  .portal-aviso .btn { margin-left: 0; width: 100%; justify-content: center; }
  .portal-item-pie { width: 100%; }
  .portal-abrir { flex: 1; justify-content: center; }
}
