/* ============================================================================
   PWA DEL SOCIO — fundación de diseño
   Mobile-first, white-label. El acento sale de --acento (el color del gimnasio);
   los neutros son la escala Zinc fija. Claro por defecto, oscuro por sistema.
   Todo scopeado bajo .pwa.
   ============================================================================ */

:root {
  --sans: "IBM Plex Sans", system-ui, -apple-system, sans-serif;
  --mono: "IBM Plex Mono", ui-monospace, monospace;

  --acento: #4f46e5;                 /* índigo soft por defecto; lo pisa el gimnasio (color_primario) */
  --acento-fg: #ffffff;

  --lienzo: #f4f5f8;                 /* canvas gris-plata frío: las cards flotan encima */
  --superficie: #ffffff;
  --superficie-2: #f7f8fb;
  --superficie-3: #eef0f4;
  --borde: #ecedf1;
  --borde-fuerte: #e3e5ea;

  --fg: #111726;
  --fg-atenuado: #525a6b;
  --fg-sutil: #98a0b0;
  --fg-placeholder: #b9bec9;
  --texto-callout: #4a5161;

  --exito: #0a7a44;
  --aviso: #b45309;
  --peligro: #c92a2a;
  --info: #2f5bd0;

  --rad: 14px;
  --rad-chico: 12px;
  --rad-grande: 28px;
  /* Sombra suave y esparcida (la firma soft): profundidad por sombra, no por líneas. */
  --sombra: 0 1px 2px rgba(17, 23, 38, .04), 0 12px 28px -10px rgba(17, 23, 38, .16);

  color-scheme: light;
}

/* Derivadas del acento: viven en .pwa —el <body> que recibe --acento del gimnasio— para que
   se recalculen con ESE color. En :root quedaban congeladas al default y rompían el white-label. */
.pwa {
  --acento-press: color-mix(in srgb, var(--acento) 82%, #000);
  --acento-suave: color-mix(in srgb, var(--acento) 9%, var(--superficie));
  --acento-inerte: color-mix(in srgb, var(--acento) 48%, var(--superficie));
  /* El acento COMO TEXTO sobre superficie, ajustado por tema en el server (contraste AA). El
     relleno con texto encima sigue usando --acento; esto es para cuando el acento ES el texto. */
  --acento-texto: var(--acento-texto-claro);
  /* El acento como RELLENO/borde visible sin texto (puntos, barras, indicadores), 3:1 por tema. */
  --acento-relleno: var(--acento-relleno-claro);
}

/* Oscuro: lo activa data-tema en el <html>, que fija el script del <head> desde localStorage
   (auto/claro/oscuro). "Automático" se resuelve ahí a claro/oscuro según prefers-color-scheme,
   igual que el selector del backoffice. Claro sigue siendo el default (:root de arriba). */
:root[data-tema="oscuro"] {
  --lienzo: #0e1014;
  --superficie: #181b21;
  --superficie-2: #14161b;
  --superficie-3: #22262e;
  --borde: #252932;
  --borde-fuerte: #2e333d;

  --fg: #e7e9ee;
  --fg-atenuado: #a5adbd;
  --fg-sutil: #6b7382;
  --fg-placeholder: #5b6270;
  --texto-callout: #9aa2b2;

  --sombra: 0 1px 2px rgba(0, 0, 0, .3), 0 16px 34px -12px rgba(0, 0, 0, .6);

  color-scheme: dark;
}

:root[data-tema="oscuro"] .pwa {
  --acento-suave: color-mix(in srgb, var(--acento) 16%, var(--superficie));
  --acento-inerte: color-mix(in srgb, var(--acento) 40%, var(--superficie));
  --acento-texto: var(--acento-texto-oscuro);
  --acento-relleno: var(--acento-relleno-oscuro);
}

/* iOS: sin rubber-band. Las pantallas que entran en el viewport no rebotan; las que scrollean, no
   rebotan más allá de los extremos ni encadenan el scroll al documento. (pwa.css es sólo de la PWA.) */
html { overscroll-behavior: none; }
.pwa * { box-sizing: border-box; }
/* El atributo `hidden` debe ocultar SIEMPRE: un componente con display propio (p. ej.
   .pwa-push, position:fixed + display:flex) lo pisa y el elemento queda trancado
   aunque el JS haga `.hidden = true`. Regla global en vez de un parche por componente. */
.pwa [hidden] { display: none !important; }

/* Sistema de íconos (#101): un set de formas (32×32, roles .mn/.dt/.bg/.ck), dos modos de render.
   Tokens derivados del acento del gimnasio; viven en .pwa (donde el layout inyecta --acento) para
   que color-mix resuelva con ESE color. */
.pwa { --ico-deep: color-mix(in srgb, var(--acento) 78%, #0a0714); --ico-lite: color-mix(in srgb, var(--acento) 42%, #ffffff); --ico-ink: #15161d; }
/* En oscuro la superficie es oscura, así que el ícono bitono se arma al revés que en claro: los
   rellenos mezclan hacia el BLANCO (no al negro) y el contorno va CLARO (mismo acento, más claro)
   en vez de tinta casi negra. Sin esto, un acento oscuro (p.ej. azul marino) se fundía con el
   fondo y el ícono no se notaba. El deep queda saturado (90%) para no lavar los acentos vivos. */
:root[data-tema="oscuro"] .pwa {
  --ico-deep: color-mix(in srgb, var(--acento) 90%, #ffffff);
  --ico-lite: color-mix(in srgb, var(--acento) 50%, #ffffff);
  --ico-ink: color-mix(in srgb, var(--acento) 32%, #ffffff);
}
.ico { display: inline-block; vertical-align: middle; flex: none; }
.ico .bg { fill: var(--superficie); }
.ico .ck { fill: none; stroke-width: 3; stroke-linecap: round; stroke-linejoin: round; }
/* Mono = contorno de una tinta (currentColor; el estado la define). Se dibuja como línea, no como
   silueta rellena: así el detalle (.dt) no se funde con la forma (.mn) y no se pierden trazos. */
.ico--mono .mn, .ico--mono .dt { fill: none; stroke: currentColor; stroke-width: 2; stroke-linejoin: round; stroke-linecap: round; }
.ico--mono .bg { fill: none; }
.ico--mono .ck { stroke: currentColor; }
.ico--bitono .mn { fill: var(--ico-deep); }
.ico--bitono .dt { fill: var(--ico-lite); }
.ico--bitono .mn, .ico--bitono .dt { stroke: var(--ico-ink); stroke-width: 1.3; paint-order: stroke; }
.ico--bitono .ck { stroke: #ffffff; }
.pwa {
  margin: 0;
  font-family: var(--sans);
  background: var(--lienzo);
  color: var(--fg);
  -webkit-font-smoothing: antialiased;
}
.pwa .mono { font-family: var(--mono); }

/* Los <a> vienen subrayados por el default del navegador. En la PWA los links son tabs, filas de
   menú, tarjetas y CTAs: el subrayado es decisión de cada componente, no algo general. Reset acá
   para no repetir text-decoration:none en cada uno. El único subrayado intencional es .pwa-enlace. */
.pwa a { text-decoration: none; }

/* ============================ MARCA ============================ */

/* Marca en superficies grandes (login, bienvenida): centrada y con protagonismo (#4). */
.pwa-marca { display: flex; align-items: center; justify-content: center; gap: 12px; }
.pwa-marca__sigla {
  width: 56px; height: 56px; flex: 0 0 56px; border-radius: 50%;
  background: var(--acento); color: var(--acento-fg);
  display: flex; align-items: center; justify-content: center; font-weight: 700; font-size: 24px;
}
.pwa-marca__nombre { font-size: 16px; font-weight: 600; color: var(--fg); }
.pwa-marca__logo { max-width: 280px; max-height: 88px; object-fit: contain; }

/* Marca del gimnasio: el ícono subido llena el cuadradito de sigla (hereda su forma). */
.pwa .marca-img { width: 100%; height: 100%; object-fit: cover; border-radius: inherit; display: block; }

/* ============================ ACCESO (Ingresar / Código) ============================ */

/* Pantalla de una sola acción: contenido arriba, botón al alcance del pulgar abajo.
   Centrada en una columna de ancho de teléfono para que también se vea bien en desktop. */
.pwa-acceso {
  min-height: 100vh; min-height: 100dvh;
  display: flex; flex-direction: column;
}
.pwa-acceso__cuerpo {
  flex: 1; width: 100%; max-width: 460px; margin: 0 auto;
  display: flex; flex-direction: column;
  padding: 28px 24px max(26px, env(safe-area-inset-bottom));
}
.pwa-acceso h1 {
  margin: 0; font-size: 25px; font-weight: 700; line-height: 1.15;
  color: var(--fg); text-wrap: balance;
}
.pwa-acceso__sub { margin: 10px 0 0; font-size: 15px; line-height: 1.45; color: var(--fg-atenuado); }
.pwa-acceso__sub strong { font-family: var(--mono); font-weight: 500; color: var(--fg); }
.pwa-acceso__empuje { flex: 1; min-height: 16px; }

/* Campo */
.pwa-campo { margin-top: 24px; }
.pwa-campo__label {
  display: block; font-family: var(--mono); font-size: 11px; letter-spacing: .08em;
  text-transform: uppercase; color: var(--fg-atenuado); margin-bottom: 8px;
}
.pwa-campo input {
  width: 100%; height: 58px; padding: 0 16px;
  border: 1.5px solid var(--borde); border-radius: var(--rad);
  background: var(--superficie); color: var(--fg);
  font-family: var(--mono); font-size: 20px;
}
.pwa-campo input::placeholder { color: var(--fg-placeholder); }
.pwa-campo input:focus {
  outline: none; border-color: var(--acento);
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--acento) 18%, transparent);
}
/* Foco de teclado con la marca para links, botones y tabs (sobre el default del navegador). */
.pwa a:focus-visible, .pwa button:focus-visible, .pwa [role="button"]:focus-visible {
  outline: 2px solid var(--acento); outline-offset: 2px;
}

/* Botón */
.pwa-boton {
  display: flex; align-items: center; justify-content: center;
  /* padding lateral: el botón suele ir a todo el ancho (width:100% + border-box, así que no
     desborda), pero cuando el contenedor se encoge al contenido (p.ej. dentro de .pwa-vacio,
     que centra en columna) el texto quedaría pegado a los bordes sin este respiro. */
  width: 100%; height: 56px; padding: 0 24px; border: none; border-radius: var(--rad);
  background: var(--acento); color: var(--acento-fg);
  font-family: inherit; font-size: 16px; font-weight: 600; cursor: pointer;
}
.pwa-boton:not(.pwa-boton--secundario):not(.pwa-boton--peligro-suave):hover { background: var(--acento-press); }
.pwa-boton:disabled { background: var(--acento-inerte); cursor: not-allowed; }
/* `.pwa .pwa-enlace` (y no `.pwa-enlace` a secas) para ganarle en especificidad al reset `.pwa a`
   de arriba: este link SÍ va subrayado a propósito — es texto atenuado, el subrayado avisa que es
   clickable ("Pedir un código nuevo"). */
.pwa .pwa-enlace {
  display: block; margin-top: 16px; text-align: center; font-size: 14px;
  color: var(--fg-atenuado); text-decoration: underline; text-underline-offset: 3px;
}

/* Aviso (fuera del padrón, demasiados intentos, código inválido) */
.pwa-aviso {
  display: flex; gap: 10px; align-items: flex-start; margin-top: 16px;
  background: var(--superficie-3); border: 1px solid var(--borde);
  border-radius: var(--rad-chico); padding: 12px 13px;
}
.pwa-aviso__punto { width: 7px; height: 7px; flex: none; margin-top: 6px; border-radius: 50%; background: var(--acento-relleno); }
.pwa-aviso__texto { font-size: 13px; line-height: 1.4; color: var(--texto-callout); }

/* Código: seis casillas */
.pwa-codigo { display: flex; gap: 9px; margin-top: 26px; }
.pwa-codigo input {
  flex: 1; width: 100%; min-width: 0; height: 60px; padding: 0; text-align: center;
  border: 1.5px solid var(--borde); border-radius: var(--rad-chico); background: var(--superficie-2);
  color: var(--fg); font-family: var(--mono); font-size: 26px; font-weight: 600;
}
.pwa-codigo input:focus {
  outline: none; border-color: var(--acento); background: var(--superficie);
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--acento) 18%, transparent);
}

/* ============================================================================
   SHELL LOGUEADO — header + cuerpo + tab bar (Inicio / Premios / Cuenta)
   ============================================================================ */

.pwa-app {
  /* Altura DEFINIDA (no min-height): así el contenedor flex mide exactamente el viewport y el
     scroll vive en .pwa-cuerpo, dejando header y tabs anclados arriba/abajo. Con min-height el
     cuerpo crecía con el contenido, la app superaba el viewport y scrolleaba el body → los tabs
     se iban con él. `overflow: hidden` blinda que nunca scrollee la app entera. */
  height: 100vh; height: 100dvh;
  max-width: 480px; margin: 0 auto;
  display: flex; flex-direction: column; overflow: hidden;
  background: var(--lienzo);
}

/* Header de las pantallas con tab (marca + campana) */
.pwa-header {
  flex: none; display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: max(20px, calc(env(safe-area-inset-top) + 10px)) 22px 12px; border-bottom: 1px solid var(--borde);
  background: var(--superficie);
}
.pwa-header__marca { display: flex; align-items: center; gap: 10px; }
/* Marca del header del shell logueado: más grande para darle presencia (#4). El header crece
   solo lo necesario (align-items: center); la campana sigue centrada. */
.pwa-header__sigla {
  width: 58px; height: 58px; flex: none; border-radius: 50%;
  background: var(--acento); color: var(--acento-fg);
  display: flex; align-items: center; justify-content: center; font-weight: 700; font-size: 21px;
}
/* Con ícono cuadrado va en un cuadrado redondeado (no círculo) para no recortarlo. Mantiene el fondo
   de acento (heredado): un logo blanco sobre transparente sería invisible sobre el header claro; el
   acento es el color de marca y el logo está hecho para leerse encima. Un ícono opaco lo tapa igual. */
.pwa-header__sigla:has(.marca-img) { border-radius: 14px; padding: 6px; }
.pwa-header__nombre { font-size: 16px; font-weight: 600; color: var(--fg); }
.pwa-header__logo { max-height: 44px; max-width: 220px; object-fit: contain; display: block; }
.pwa-campana {
  position: relative; width: 44px; height: 44px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center; color: var(--fg-atenuado);
  background: none; border: 0; padding: 0; cursor: pointer;
}
.pwa-campana:active { background: var(--superficie-3); }
.pwa-campana__punto {
  position: absolute; top: 4px; right: 5px; min-width: 16px; height: 16px; padding: 0 4px;
  border-radius: 999px; background: var(--acento); color: var(--acento-fg); border: 2px solid var(--superficie);
  font-size: 10px; font-weight: 700; line-height: 12px; text-align: center;
}

/* Header de las pantallas empujadas (volver + título) */
.pwa-header--volver { justify-content: flex-start; gap: 6px; }
.pwa-volver {
  display: flex; align-items: center; gap: 4px; margin: -6px -6px -6px -8px; padding: 6px 8px;
  color: var(--fg); font-size: 16px; font-weight: 600;
}
.pwa-volver svg { width: 22px; height: 22px; }

/* Cuerpo scrolleable */
.pwa-cuerpo { flex: 1; min-height: 0; overflow-y: auto; overscroll-behavior: none; -webkit-overflow-scrolling: touch; padding: 22px; }

/* Tab bar */
.pwa-tabs {
  flex: none; display: flex; border-top: 1px solid var(--borde); background: var(--superficie);
  padding: 8px 12px max(12px, env(safe-area-inset-bottom));
}
.pwa-tab {
  flex: 1; display: flex; flex-direction: column; align-items: center; gap: 5px; padding-top: 3px;
  color: var(--fg-atenuado); font-size: 11px; font-weight: 500;
}
.pwa-tab svg { width: 22px; height: 22px; }
.pwa-tab.is-activa { color: var(--acento-texto); font-weight: 600; }
.pwa-tab__marca { width: 20px; height: 3px; border-radius: 99px; background: transparent; margin-bottom: 2px; }
.pwa-tab.is-activa .pwa-tab__marca { background: var(--acento-relleno); }

/* Insignia de estado (DESIGN.md § Badges/Pills: "para estados de socio/membresía/canje").
   Mismo componente que el backoffice (punto + pastilla + color-mix con la superficie),
   pero scopeado bajo .pwa —el backoffice lo scopea bajo .bo— así que vive acá con sus
   propios tokens en vez de heredar de backoffice.css, que este layout ni carga. */
.pwa .badge {
  display: inline-flex; align-items: center; gap: 5px; padding: 3px 9px; border-radius: 99px;
  font-size: 11.5px; font-weight: 600; border: 1px solid var(--borde); color: var(--fg-atenuado);
}
.pwa .badge::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: currentColor; }
.pwa .badge--ok      { color: var(--exito);   background: color-mix(in srgb, var(--exito) 13%, var(--superficie));   border-color: color-mix(in srgb, var(--exito) 26%, var(--superficie)); }
.pwa .badge--info    { color: var(--info);    background: color-mix(in srgb, var(--info) 12%, var(--superficie));    border-color: color-mix(in srgb, var(--info) 26%, var(--superficie)); }
.pwa .badge--aviso    { color: var(--aviso);   background: color-mix(in srgb, var(--aviso) 13%, var(--superficie));   border-color: color-mix(in srgb, var(--aviso) 26%, var(--superficie)); }
.pwa .badge--peligro  { color: var(--peligro); background: color-mix(in srgb, var(--peligro) 12%, var(--superficie)); border-color: color-mix(in srgb, var(--peligro) 26%, var(--superficie)); }

/* ============================ DETALLE DE PUNTOS (Lealtad) ============================ */

.pwa-saldo__valor {
  font-family: var(--mono); font-size: 56px; font-weight: 700; line-height: 1;
  letter-spacing: -.02em; color: var(--fg);
}
.pwa-saldo__label { margin-top: 6px; font-size: 15px; color: var(--fg-atenuado); }
.pwa-saldo__detalle { margin-top: 8px; font-family: var(--mono); font-size: 12px; color: var(--fg-atenuado); }

.pwa-bloques { display: flex; flex-direction: column; gap: 15px; }

/* Panel: agrupa filas de lista (datos del perfil, mensajes, asistencias) en una card
   blanca que flota sobre el canvas — misma firma soft que .pwa-tarjeta. */
.pwa-panel {
  background: var(--superficie); border: 1px solid var(--borde);
  border-radius: 16px; box-shadow: var(--sombra); padding: 2px 18px;
}
.pwa-panel > :last-child { border-bottom: 0; }

/* Tarjeta de impulso */
.pwa-impulso {
  display: flex; gap: 12px; align-items: center; padding: 14px 15px; border-radius: 16px;
  background: var(--acento-suave); border: 1px solid color-mix(in srgb, var(--acento) 26%, var(--superficie));
}
.pwa-impulso__mult {
  flex: none; width: 40px; height: 40px; border-radius: 12px; background: var(--acento); color: var(--acento-fg);
  display: flex; align-items: center; justify-content: center; font-family: var(--mono); font-size: 17px; font-weight: 700;
}
.pwa-impulso__texto { font-size: 13px; line-height: 1.4; color: var(--fg); }
.pwa-impulso__texto strong { color: var(--acento-texto); }

/* Tarjeta de desafío */
.pwa-desafio { background: var(--superficie); border: 1px solid var(--borde); border-radius: 16px; padding: 15px; box-shadow: var(--sombra); }
.pwa-desafio__fila { display: flex; justify-content: space-between; align-items: baseline; gap: 10px; }
.pwa-desafio__nombre { font-size: 14px; font-weight: 600; color: var(--fg); }
.pwa-desafio__conteo { font-family: var(--mono); font-size: 13px; color: var(--fg-atenuado); }
.pwa-progreso { margin-top: 10px; height: 8px; border-radius: 99px; background: var(--borde); overflow: hidden; }
.pwa-progreso > span { display: block; height: 100%; border-radius: 99px; background: var(--acento-relleno); }

/* Mis desafíos (épica #96, Slice D): la card enriquecida (recompensa, plazo, estado). */
.pwa-lista-desafios { display: flex; flex-direction: column; gap: 12px; }
.pwa-desafio__desc { margin-top: 6px; font-size: 13px; color: var(--fg-atenuado); line-height: 1.45; }
.pwa-desafio__pie { display: flex; justify-content: space-between; align-items: baseline; gap: 10px; margin-top: 12px; flex-wrap: wrap; }
.pwa-desafio__premio { font-size: 13px; font-weight: 600; color: var(--acento-texto); }
.pwa-desafio__meta { font-size: 12px; color: var(--fg-atenuado); }
.pwa-desafio__badge { font-size: 12px; font-weight: 600; padding: 3px 9px; border-radius: 999px; white-space: nowrap; }
.pwa-desafio__badge--ok { background: var(--acento-suave); color: var(--acento-texto); }
.pwa-desafio__badge--no { background: color-mix(in srgb, var(--fg) 8%, var(--superficie)); color: var(--fg-atenuado); }
.pwa-desafio--fallido { opacity: 0.72; }

/* Saldo héroe (Opción E, #98): en «Mis puntos» el saldo manda — centrado, más grande. Wrapper
   propio para NO tocar .pwa-saldo__valor/__label (compartidas con Inicio y Membresías). */
.pwa-saldo-heroe { text-align: center; padding: 6px 0 2px; }
.pwa-saldo-heroe .pwa-saldo__valor { font-size: 60px; }

/* Fila de 3 acciones (Opción E, #98): disco circular + label. Premios DESTACADA = relleno de
   acento (es para lo que se juntan los puntos); Ranking/Mis desafíos = superficie con borde. El
   ícono es mono → hereda el `color` del disco (acento-texto en superficie, acento-fg en relleno). */
.pwa-acciones { display: flex; justify-content: center; gap: 12px; }
.pwa-accion { flex: 1 1 0; max-width: 112px; display: flex; flex-direction: column; align-items: center; gap: 8px; text-decoration: none; }
.pwa-accion__disco {
  width: 60px; height: 60px; border-radius: 50%; display: flex; align-items: center; justify-content: center;
  background: var(--superficie); border: 1.5px solid var(--borde-fuerte); color: var(--acento-texto);
  box-shadow: var(--sombra); transition: transform .12s ease;
}
.pwa-accion__label { font-size: 12.5px; font-weight: 600; color: var(--fg); text-align: center; line-height: 1.2; }
.pwa-accion--destacada .pwa-accion__disco { background: var(--acento); border-color: var(--acento); color: var(--acento-fg); }
.pwa-accion:active .pwa-accion__disco { transform: scale(.94); }

.pwa-acciones__hint { margin: 12px 0 0; text-align: center; font-size: 13px; line-height: 1.4; color: var(--fg-atenuado); }
.pwa-acciones__hint strong { color: var(--acento-texto); font-weight: 700; }

/* Entrada al check-in (decisión de implementación: el diseño no la cableó en la nav) */
.pwa-checkin-cta {
  display: flex; align-items: center; gap: 12px;
  background: var(--acento); color: var(--acento-fg); border-radius: 16px; padding: 15px;
}
.pwa-checkin-cta__icono {
  flex: none; width: 40px; height: 40px; border-radius: 12px;
  background: color-mix(in srgb, var(--acento-fg) 22%, transparent);
  display: flex; align-items: center; justify-content: center;
}
.pwa-checkin-cta__titulo { display: block; font-size: 15px; font-weight: 600; }
.pwa-checkin-cta__sub { display: block; font-size: 12.5px; opacity: .9; margin-top: 2px; }

/* Acceso al check-in (#17): acción fija abajo, arriba de los tabs (fuera del scroll). El estado
   "ya registraste hoy" va como card atenuada (no-acción). */
.pwa-accion-fija {
  flex: none; padding: 12px 22px;
  background: var(--lienzo); box-shadow: 0 -6px 16px -10px rgba(17, 23, 38, .18);
}
.pwa-checkin-hecho {
  display: flex; align-items: center; gap: 10px;
  background: var(--acento-suave); color: var(--texto-callout);
  border: 1px solid color-mix(in srgb, var(--acento) 22%, var(--superficie));
  border-radius: 16px; padding: 15px; font-size: 14px; font-weight: 500;
}
.pwa-checkin-hecho__check {
  flex: none; width: 26px; height: 26px; border-radius: 50%;
  background: var(--acento); color: var(--acento-fg);
  display: flex; align-items: center; justify-content: center; font-size: 14px; font-weight: 700;
}
/* Lista de movimientos */
.pwa-rotulo {
  font-family: var(--mono); font-size: 11px; letter-spacing: .08em; text-transform: uppercase;
  color: var(--fg-atenuado); margin-bottom: 6px;
}
.pwa-movimiento {
  display: flex; justify-content: space-between; align-items: center; gap: 12px;
  padding: 11px 0; border-bottom: 1px solid var(--borde);
}
.pwa-movimiento:last-child { border-bottom: 0; }
.pwa-movimiento__desc { font-size: 14px; color: var(--fg); }
.pwa-movimiento__monto { font-family: var(--mono); font-size: 14px; font-weight: 600; }
.pwa-movimiento__monto.es-pos { color: var(--exito); }
.pwa-movimiento__monto.es-neg { color: var(--fg-atenuado); }

/* Estado vacío */
.pwa-vacio {
  flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center;
  text-align: center; gap: 16px; padding: 40px 12px;
}
.pwa-vacio__icono {
  width: 72px; height: 72px; border-radius: 18px; background: var(--superficie-3); border: 1px solid var(--borde);
  display: flex; align-items: center; justify-content: center; font-size: 26px; color: var(--fg-sutil);
}
.pwa-vacio__texto { margin: 0; font-size: 16px; line-height: 1.5; color: var(--texto-callout); text-wrap: balance; max-width: 300px; }

/* ============================ FLASH + PUSH ============================ */

.pwa-flash { flex: none; margin: 12px 22px -6px; padding: 11px 14px; border-radius: 12px; font-size: 13.5px; line-height: 1.4; }
.pwa-flash.es-ok { background: var(--acento-suave); color: var(--fg); border: 1px solid color-mix(in srgb, var(--acento) 26%, var(--superficie)); }
.pwa-flash.es-alerta { background: var(--superficie-3); color: var(--texto-callout); border: 1px solid var(--borde); }

/* Pantalla de resultado del check-in (#95, Acceso 4.3): check grande con entrada "pop + onda",
   confeti sólo en verde (es-ok) — no se festeja un plan vencido — y vuelta sola al inicio (la
   barra de progreso, con duración por nivel, la fija el Stimulus). Único mensaje: título + detalle
   de FEEDBACK_COBERTURA, sin el banner + bloque "Listo" duplicados de antes. */
/* El cuerpo es block por defecto (scroll de listas); acá lo volvemos flex-column para que el hero
   ocupe toda la pantalla (su flex:1 centra el check y ancla el pie abajo). Sólo en el resultado. */
.pwa-cuerpo:has(> .pwa-checkin-hero) { display: flex; flex-direction: column; }
.pwa-checkin-hero { position: relative; flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center; text-align: center; padding: 0 30px; gap: 0; }
.pwa-hero-mark { position: relative; width: 112px; height: 112px; margin-bottom: 22px; }
.pwa-hero-disco { position: absolute; inset: 0; border-radius: 50%; display: flex; align-items: center; justify-content: center; transform: scale(0); }
.pwa-hero-disco svg { width: 56px; height: 56px; }
.pwa-hero-disco svg path { fill: none; stroke: #fff; stroke-width: 9; stroke-linecap: round; stroke-linejoin: round; stroke-dasharray: 48; stroke-dashoffset: 48; }
.pwa-hero-onda { position: absolute; inset: 0; border-radius: 50%; border: 3px solid; opacity: 0; }
.es-ok .pwa-hero-disco { background: var(--exito); } .es-ok .pwa-hero-onda { border-color: var(--exito); }
.es-aviso .pwa-hero-disco { background: var(--aviso); } .es-aviso .pwa-hero-onda { border-color: var(--aviso); }
.es-rojo .pwa-hero-disco { background: var(--peligro); } .es-rojo .pwa-hero-onda { border-color: var(--peligro); }
.pwa-checkin-hero.go .pwa-hero-disco { animation: pwa-pop .52s cubic-bezier(.22,1,.36,1) forwards; }
.pwa-checkin-hero.go .pwa-hero-onda { animation: pwa-onda .72s ease-out .06s; }
.pwa-checkin-hero.go .pwa-hero-disco svg path { animation: pwa-trazo .34s ease .22s forwards; }
@keyframes pwa-pop { to { transform: scale(1); } }
@keyframes pwa-onda { 0% { transform: scale(.7); opacity: .55; } 100% { transform: scale(2.15); opacity: 0; } }
@keyframes pwa-trazo { to { stroke-dashoffset: 0; } }
.pwa-hero-titulo { font-size: 25px; font-weight: 600; color: var(--fg); margin: 0 0 7px; letter-spacing: -.01em; }
.pwa-hero-detalle { font-size: 14.5px; color: var(--fg-atenuado); margin: 0; max-width: 26ch; }
.pwa-hero-pie { position: absolute; left: 0; right: 0; bottom: 26px; padding: 0 30px; text-align: center; }
.pwa-hero-barra { display: block; height: 3px; border-radius: 2px; background: var(--borde-fuerte); overflow: hidden; margin: 0 6px 10px; }
.pwa-hero-barra i { display: block; height: 100%; background: currentColor; color: var(--fg-sutil); transform: scaleX(0); transform-origin: left; }
.pwa-checkin-hero.go .pwa-hero-barra i { animation: pwa-cuenta var(--pwa-vuelve, 4s) linear forwards; }
@keyframes pwa-cuenta { to { transform: scaleX(1); } }
.pwa-hero-volver { font-size: 13px; color: var(--fg-atenuado); text-decoration: underline; text-underline-offset: 3px; }
/* confeti (lo crea el JS sólo en verde) */
.pwa-confeti { position: absolute; top: 50%; left: 50%; width: 9px; height: 9px; border-radius: 2px; opacity: 0; }
.pwa-checkin-hero.go .pwa-confeti { animation: pwa-estallido .8s cubic-bezier(.2,.7,.3,1) forwards; }
@keyframes pwa-estallido {
  0% { transform: translate(-50%, -50%) scale(.2); opacity: 0; }
  12% { opacity: 1; }
  100% { transform: translate(calc(-50% + var(--x)), calc(-50% + var(--y))) rotate(var(--r)) scale(1); opacity: 0; }
}
@media (prefers-reduced-motion: reduce) {
  .pwa-hero-disco { transform: scale(1) !important; animation: none !important; }
  .pwa-hero-disco svg path { stroke-dashoffset: 0 !important; animation: none !important; }
  .pwa-hero-onda, .pwa-confeti { display: none !important; }
  .pwa-hero-barra i { transform: scaleX(1) !important; animation: none !important; }
}

.pwa-push { position: fixed; inset: 0; z-index: 50; display: flex; align-items: flex-end; background: rgba(10, 10, 12, .4); }
.pwa-push__caja {
  width: 100%; max-width: 480px; margin: 0 auto; background: var(--superficie);
  border-radius: 22px 22px 0 0; padding: 22px 22px max(22px, env(safe-area-inset-bottom));
}
.pwa-push__texto { margin: 0 0 16px; font-size: 16px; line-height: 1.5; color: var(--fg); text-align: center; }
.pwa-push__acciones { display: flex; flex-direction: column; gap: 8px; }
.pwa-push__no { border: none; background: none; color: var(--fg-atenuado); font-family: inherit; font-size: 15px; padding: 10px; cursor: pointer; }

/* ============================ CATÁLOGO ============================ */

.pwa-catalogo__saldo { font-size: 15px; color: var(--fg-atenuado); margin-bottom: 16px; }
.pwa-catalogo__saldo strong { font-family: var(--mono); font-weight: 700; color: var(--fg); }

.pwa-premios { display: flex; flex-direction: column; gap: 12px; }
.pwa-premio { background: var(--superficie); border: 1px solid var(--borde); border-radius: 16px; padding: 12px; box-shadow: var(--sombra); }
.pwa-premio__fila { display: flex; gap: 12px; align-items: center; }
.pwa-premio__foto {
  flex: none; width: 68px; height: 68px; border-radius: 12px; object-fit: cover;
  display: flex; align-items: center; justify-content: center;
}
/* Sin foto cargada: un ícono de premio sobre superficie lisa (antes decía "foto" en mono). */
.pwa-premio__foto--vacia { background: var(--superficie-3); color: var(--fg-sutil); }
.pwa-premio__nombre { font-size: 15px; font-weight: 600; color: var(--fg); line-height: 1.3; }
.pwa-premio__costo { margin-top: 4px; font-family: var(--mono); font-size: 14px; color: var(--texto-callout); }
.pwa-premio__pedir { width: 100%; height: 44px; margin-top: 12px; font-size: 15px; }
.pwa-premio__faltan { margin-top: 12px; }
.pwa-premio__barra { height: 6px; border-radius: 99px; background: var(--superficie-3); overflow: hidden; }
.pwa-premio__barra > span { display: block; height: 100%; border-radius: 99px; background: var(--acento-relleno); }
.pwa-premio__falta-texto { margin-top: 7px; font-size: 13px; font-weight: 500; color: var(--acento-texto); }

/* Tarjeta de comprobante activo (en el catálogo) */
.pwa-comprobantes { display: flex; flex-direction: column; gap: 10px; margin-bottom: 22px; }
.pwa-comprobante-card {
  display: flex; align-items: center; gap: 12px; padding: 14px;
  background: var(--acento-suave); border: 1px solid color-mix(in srgb, var(--acento) 26%, var(--superficie));
  border-radius: 16px;
}
.pwa-comprobante-card__cod {
  flex: none; font-family: var(--mono); font-size: 15px; font-weight: 700; letter-spacing: .04em;
  color: var(--acento-texto); background: var(--superficie); border-radius: 10px; padding: 8px 10px;
}
.pwa-comprobante-card__info { flex: 1; min-width: 0; }
.pwa-comprobante-card__nombre { font-size: 14px; font-weight: 600; color: var(--fg); }
.pwa-comprobante-card__sub { font-size: 12.5px; color: var(--fg-atenuado); margin-top: 1px; }
.pwa-comprobante-card__flecha { flex: none; color: var(--acento-texto); font-size: 18px; }

/* ============================ COMPROBANTE (pantalla) ============================ */

.pwa-comprobante { display: flex; flex-direction: column; align-items: center; text-align: center; padding-top: 8px; }
.pwa-estado-pill {
  display: inline-flex; align-items: center; gap: 8px; padding: 8px 14px; border-radius: 999px;
  font-size: 13px; font-weight: 600;
  background: var(--acento-suave); color: var(--acento-texto);
  border: 1px solid color-mix(in srgb, var(--acento) 26%, var(--superficie));
}
.pwa-estado-pill::before { content: ""; width: 8px; height: 8px; border-radius: 50%; background: currentColor; }
.pwa-estado-pill.es-neutro { background: var(--superficie-3); color: var(--fg-atenuado); border-color: var(--borde); }
.pwa-estado-pill.es-ok { background: color-mix(in srgb, var(--exito) 12%, var(--superficie)); color: var(--exito); border-color: color-mix(in srgb, var(--exito) 30%, var(--superficie)); }

.pwa-comprobante__premio { margin-top: 20px; }
.pwa-comprobante__nombre { font-size: 19px; font-weight: 700; color: var(--fg); }
.pwa-comprobante__costo { margin-top: 4px; font-family: var(--mono); font-size: 15px; color: var(--fg-atenuado); }
.pwa-comprobante__qr { margin-top: 24px; padding: 16px; background: #fff; border: 1px solid var(--borde); border-radius: 20px; }
.pwa-comprobante__qr svg { display: block; width: 232px; height: 232px; }
.pwa-comprobante__codigo {
  margin-top: 22px; font-family: var(--mono); font-size: 40px; font-weight: 700; letter-spacing: .06em; color: var(--fg);
}
.pwa-comprobante__vigencia { margin-top: 10px; font-size: 14px; color: var(--fg-atenuado); }
.pwa-comprobante__anular { margin-top: 28px; }
.pwa-comprobante__anular button {
  border: none; background: none; color: var(--fg-atenuado); font-family: inherit; font-size: 14px;
  text-decoration: underline; text-underline-offset: 3px; cursor: pointer;
}

/* ============================ CHECK-IN ============================ */

.pwa-detalle h2 { margin: 0; font-size: 23px; font-weight: 700; color: var(--fg); }
.pwa-detalle__sub { margin: 8px 0 0; font-size: 15px; line-height: 1.45; color: var(--fg-atenuado); }

.pwa-visor {
  position: relative; width: 100%; aspect-ratio: 1; margin-top: 16px; border-radius: 20px;
  overflow: hidden; background: #141416;
}
.pwa-visor video { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
/* Pulso de "código leído" (#53): flash verde breve al decodificar, antes de enviar. */
.pwa-visor.es-leido { animation: visor-leido .4s ease; }
.pwa-visor.es-leido::after {
  content: ""; position: absolute; inset: 0; z-index: 2;
  background: color-mix(in srgb, var(--exito) 45%, transparent); animation: visor-leido-fade .4s ease forwards;
}
@keyframes visor-leido { 0% { box-shadow: inset 0 0 0 0 var(--exito); } 40% { box-shadow: inset 0 0 0 5px var(--exito); } 100% { box-shadow: inset 0 0 0 0 transparent; } }
@keyframes visor-leido-fade { from { opacity: 1; } to { opacity: 0; } }
.pwa-visor__marco { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); width: 62%; height: 62%; }
.pwa-visor__esq { position: absolute; width: 30px; height: 30px; }
.pwa-visor__esq--si { top: 0; left: 0; border-top: 4px solid var(--acento); border-left: 4px solid var(--acento); border-top-left-radius: 8px; }
.pwa-visor__esq--sd { top: 0; right: 0; border-top: 4px solid var(--acento); border-right: 4px solid var(--acento); border-top-right-radius: 8px; }
.pwa-visor__esq--ii { bottom: 0; left: 0; border-bottom: 4px solid var(--acento); border-left: 4px solid var(--acento); border-bottom-left-radius: 8px; }
.pwa-visor__esq--id { bottom: 0; right: 0; border-bottom: 4px solid var(--acento); border-right: 4px solid var(--acento); border-bottom-right-radius: 8px; }
.pwa-visor__linea { position: absolute; top: 50%; left: 6px; right: 6px; height: 2px; background: var(--acento); box-shadow: 0 0 10px var(--acento); animation: pwa-barrer 2.4s ease-in-out infinite; }
.pwa-visor__pista { position: absolute; bottom: 14px; left: 0; right: 0; text-align: center; font-size: 13px; color: rgba(255, 255, 255, .7); }
@keyframes pwa-barrer { 0%, 100% { top: 20%; } 50% { top: 80%; } }
@media (prefers-reduced-motion: reduce) { .pwa-visor__linea { animation: none; top: 50%; } }

.pwa-separador { display: flex; align-items: center; gap: 12px; margin: 18px 0; }
.pwa-separador::before, .pwa-separador::after { content: ""; flex: 1; height: 1px; background: var(--borde); }
.pwa-separador span { font-size: 13px; color: var(--fg-atenuado); }

.pwa-codigo-fila { display: flex; gap: 10px; }
.pwa-codigo-fila input {
  flex: 1; min-width: 0; height: 56px; padding: 0 16px; border: 1.5px solid var(--borde); border-radius: var(--rad);
  background: var(--superficie); color: var(--fg); font-family: var(--mono); font-size: 18px;
}
.pwa-codigo-fila input:focus { outline: none; border-color: var(--acento); box-shadow: 0 0 0 4px color-mix(in srgb, var(--acento) 18%, transparent); }
.pwa-codigo-fila button { flex: none; width: auto; padding: 0 20px; height: 56px; }

/* ============================ BANDEJA + MENSAJE ============================ */

.pwa-msg { display: flex; gap: 12px; padding: 16px 0; border-bottom: 1px solid var(--borde); }
.pwa-msg__punto { flex: none; width: 9px; height: 9px; margin-top: 6px; border-radius: 50%; background: var(--acento-relleno); }
.pwa-msg__punto.es-leido { background: transparent; }
.pwa-msg__cuerpo { flex: 1; min-width: 0; }
.pwa-msg__titulo { font-size: 15px; font-weight: 600; color: var(--fg); }
.pwa-msg__titulo.es-leido { font-weight: 500; color: var(--fg-atenuado); }
.pwa-msg__extracto {
  margin-top: 3px; font-size: 14px; line-height: 1.4; color: var(--fg-atenuado);
  overflow: hidden; text-overflow: ellipsis; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
}

.pwa-mensaje__marca { display: flex; align-items: center; gap: 8px; color: var(--fg-atenuado); font-size: 13px; font-weight: 500; }
.pwa-mensaje__sigla {
  width: 22px; height: 22px; flex: none; border-radius: 6px; background: var(--acento); color: var(--acento-fg);
  display: flex; align-items: center; justify-content: center; font-size: 10px; font-weight: 700;
}
.pwa-mensaje__titulo { margin: 14px 0 0; font-size: 22px; font-weight: 700; line-height: 1.2; color: var(--fg); }
.pwa-mensaje__imagen { width: 100%; border-radius: 16px; margin-top: 16px; }
.pwa-mensaje__cuerpo { margin-top: 14px; font-size: 15px; line-height: 1.6; color: var(--fg); white-space: pre-line; }

/* ============================ ASISTENCIAS ============================ */

/* `display: block` + `text-decoration: none` porque el inicio compuesto (rediseño modular,
   plan 2 / task 2) la usa también como link_to de tarjeta completa (antes sólo era un <div>
   estático en reclamos/index) — sin esto, el <a> hereda el subrayado y color de link del user
   agent y el box model de inline puede quedar inconsistente. */
.pwa-tarjeta {
  display: block; background: var(--superficie); border: 1px solid var(--borde);
  border-radius: 16px; padding: 16px; text-decoration: none; box-shadow: var(--sombra);
}
.pwa-tarjeta__encabezado { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.pwa-tarjeta__titulo { font-size: 15px; font-weight: 600; color: var(--fg); }
.pwa-tarjeta__sub { margin-top: 3px; font-size: 14px; line-height: 1.4; color: var(--fg-atenuado); }
.pwa-tarjeta input[type="date"] {
  /* -webkit-appearance:none — sin esto, iOS le da al input de fecha un ancho intrínseco nativo
     que ignora width:100% y se desborda del card por la derecha. El campo ya tiene su propio
     borde/padding/radio, así que la apariencia nativa no aporta nada. */
  -webkit-appearance: none; appearance: none; min-width: 0;
  width: 100%; height: 52px; margin-top: 12px; padding: 0 14px; border: 1.5px solid var(--borde);
  border-radius: 12px; background: var(--superficie); color: var(--fg); font-family: var(--mono); font-size: 16px;
}
.pwa-tarjeta input[type="date"]:focus { outline: none; border-color: var(--acento); box-shadow: 0 0 0 4px color-mix(in srgb, var(--acento) 18%, transparent); }
.pwa-tarjeta .pwa-boton { height: 50px; margin-top: 10px; font-size: 15px; }

.pwa-asistencia { display: flex; justify-content: space-between; align-items: center; padding: 14px 0; border-bottom: 1px solid var(--borde); }
.pwa-asistencia:last-child { border-bottom: 0; }
.pwa-asistencia__fecha { font-family: var(--mono); font-size: 14px; color: var(--fg); }
.pwa-asistencia__sede { font-size: 13px; color: var(--fg-atenuado); }

/* ============================ PERFIL + NOTIFICACIONES ============================ */

.pwa-perfil { display: flex; flex-direction: column; align-items: center; gap: 10px; }
.pwa-perfil__avatar {
  width: 76px; height: 76px; border-radius: 50%; background: var(--acento); color: var(--acento-fg);
  display: flex; align-items: center; justify-content: center; font-size: 28px; font-weight: 700;
}
.pwa-perfil__nombre { font-size: 18px; font-weight: 700; color: var(--fg); }
.pwa-perfil__rol { margin-top: 2px; font-size: 13px; color: var(--fg-atenuado); }

.pwa-datos { margin-top: 22px; }
.pwa-dato { padding: 12px 0; border-bottom: 1px solid var(--borde); }
.pwa-dato__label { font-size: 12px; color: var(--fg-atenuado); }
.pwa-dato__valor { margin-top: 2px; font-size: 16px; color: var(--fg); }
.pwa-dato__valor.mono { font-family: var(--mono); }

.pwa-menu-fila {
  display: flex; align-items: center; justify-content: space-between; padding: 16px 0;
  border-bottom: 1px solid var(--borde); font-size: 16px; color: var(--fg);
}
.pwa-menu-fila__flecha { color: var(--fg-sutil); font-size: 18px; }
.pwa-salir { margin-top: 20px; }
.pwa-salir button {
  width: 100%; border: none; background: none; color: var(--fg-atenuado); font-family: inherit;
  font-size: 15px; padding: 12px; cursor: pointer; text-decoration: underline; text-underline-offset: 3px;
}

.pwa-toggle-fila { display: flex; align-items: center; justify-content: space-between; gap: 16px; padding: 16px 0; border-bottom: 1px solid var(--borde); }
.pwa-toggle-fila__texto { font-size: 15px; color: var(--fg); }
.pwa-toggle { position: relative; flex: none; }
.pwa-toggle input { position: absolute; opacity: 0; width: 0; height: 0; }
.pwa-toggle__pista {
  display: block; width: 46px; height: 28px; border-radius: 999px; background: var(--borde-fuerte); transition: background .15s;
}
.pwa-toggle__pista::after {
  content: ""; position: absolute; top: 3px; left: 3px; width: 22px; height: 22px; border-radius: 50%;
  background: #fff; box-shadow: 0 1px 3px rgba(0, 0, 0, .3); transition: left .15s;
}
.pwa-toggle input:checked + .pwa-toggle__pista { background: var(--acento-relleno); }
.pwa-toggle input:checked + .pwa-toggle__pista::after { left: 21px; }
.pwa-nota { margin: 16px 0 22px; font-size: 14px; line-height: 1.5; color: var(--fg-atenuado); }

/* Selector de tema (Automático / Claro / Oscuro): segmented control, mismo espíritu que el
   .bo-tema del backoffice pero con objetivos táctiles más grandes. */
.pwa-tema { display: flex; gap: 4px; padding: 4px; border-radius: 14px; background: var(--superficie-3); }
.pwa-tema__opcion {
  flex: 1; padding: 11px 8px; border: none; border-radius: 10px; background: transparent;
  color: var(--fg-atenuado); font-family: inherit; font-size: 14px; font-weight: 500; cursor: pointer;
}
.pwa-tema__opcion.is-actual {
  background: var(--superficie); color: var(--fg); font-weight: 600;
  box-shadow: 0 1px 3px rgba(20, 20, 30, .12);
}

/* ============================ RANKING ============================ */

/* Ranking (feature ranking, Slice A) — segmentado de período + tabla de posiciones. Sistema soft:
   cards blancas flotando sobre el canvas, puntos en mono, acento del gimnasio para lo destacado. */
.pwa-seg {
  display: flex; gap: 4px; padding: 4px; margin-bottom: 20px;
  background: var(--superficie); border: 1px solid var(--borde);
  border-radius: 14px; box-shadow: var(--sombra);
}
.pwa-seg__op {
  flex: 1; text-align: center; padding: 9px 8px; border-radius: 10px;
  font-size: 14px; font-weight: 500; color: var(--fg-atenuado); text-decoration: none;
  transition: background .15s, color .15s;
}
.pwa-seg__op.is-activa { background: var(--acento); color: var(--acento-fg); font-weight: 600; }

.pwa-rank { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 8px; }
.pwa-rank__fila {
  display: flex; align-items: center; gap: 14px; padding: 14px 16px;
  background: var(--superficie); border: 1px solid var(--borde);
  border-radius: 14px; box-shadow: var(--sombra);
}
.pwa-rank__fila.es-vos {
  border-color: color-mix(in srgb, var(--acento) 45%, var(--borde));
  background: color-mix(in srgb, var(--acento) 7%, var(--superficie));
}
.pwa-rank__pos {
  flex: none; width: 30px; height: 30px; display: flex; align-items: center; justify-content: center;
  font-family: var(--mono); font-size: 14px; font-weight: 600; color: var(--fg-atenuado);
  background: var(--lienzo); border-radius: 9px;
}
.pwa-rank__fila.es-podio .pwa-rank__pos { background: var(--acento); color: var(--acento-fg); }
.pwa-rank__nombre { flex: 1; min-width: 0; font-size: 15px; color: var(--fg); display: flex; align-items: center; gap: 8px; }
.pwa-rank__nombre-texto { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pwa-rank__vos {
  flex: none; font-size: 11px; font-weight: 600; letter-spacing: .04em; text-transform: uppercase;
  color: var(--acento-texto); background: color-mix(in srgb, var(--acento) 12%, var(--superficie));
  padding: 2px 7px; border-radius: 6px;
}
.pwa-rank__pts { flex: none; font-family: var(--mono); font-size: 15px; font-weight: 600; color: var(--fg); }

.pwa-rank-cta {
  margin-bottom: 16px; padding: 13px 15px; border-radius: 12px; font-size: 13px; line-height: 1.5;
  color: var(--texto-callout); background: color-mix(in srgb, var(--acento) 8%, var(--superficie));
  border: 1px solid color-mix(in srgb, var(--acento) 20%, var(--superficie));
}
.pwa-rank-cta a { color: var(--acento-texto); font-weight: 600; text-decoration: none; }

/* Podio de la card de ranking en el inicio (top 3, compacto). */
.pwa-podio { list-style: none; margin: 12px 0 0; padding: 0; display: flex; flex-direction: column; gap: 6px; }
.pwa-podio__item { display: flex; align-items: center; gap: 10px; font-size: 14px; }
.pwa-podio__pos { flex: none; width: 20px; font-family: var(--mono); font-weight: 600; color: var(--acento-texto); }
.pwa-podio__nombre { flex: 1; min-width: 0; color: var(--fg); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pwa-podio__pts { flex: none; font-family: var(--mono); font-weight: 600; color: var(--fg-atenuado); }

/* Salón de la fama (ranking Slice B) — una card por podio cerrado, reusa .pwa-podio. */
.pwa-salon-podio {
  background: var(--superficie); border: 1px solid var(--borde); border-radius: 14px;
  box-shadow: var(--sombra); padding: 14px 16px; margin-bottom: 10px;
}
.pwa-salon-podio__periodo {
  font-size: 12px; font-weight: 600; letter-spacing: .02em; color: var(--fg-atenuado); margin-bottom: 2px;
}
.pwa-salon-link { font-size: 14px; font-weight: 600; color: var(--acento-texto); text-decoration: none; }

/* ============================ BIENVENIDA (#23) ============================ */

/* Puerta de entrada pública: marca centrada + acciones (login / instalar). Usa el layout
   portal_acceso (minimal, sin tab bar). Columna de ancho de teléfono, centrada en desktop. */
.pwa-bienvenida {
  min-height: 100vh; min-height: 100dvh;
  display: flex; flex-direction: column;
}
.pwa-hero {
  background: var(--acento); color: var(--acento-fg);
  border-radius: 0 0 var(--rad-grande) var(--rad-grande);
  padding: max(56px, calc(env(safe-area-inset-top) + 40px)) 28px 40px;
  display: flex; flex-direction: column; align-items: center; text-align: center;
}
.pwa-hero__marca { display: flex; justify-content: center; }
.pwa-hero .pwa-marca__logo {
  max-height: 128px; filter: drop-shadow(0 8px 20px rgba(0, 0, 0, .25));
}
.pwa-hero .pwa-marca__sigla { width: 96px; height: 96px; flex-basis: 96px; font-size: 38px; }
.pwa-hero__saludo { margin: 36px 0 0; font-size: 15px; font-weight: 500; opacity: .85; }
.pwa-hero__nombre { margin: 3px 0 0; font-size: 30px; font-weight: 700; line-height: 1.15; }
.pwa-bienvenida__pie {
  flex: 1; width: 100%; max-width: 460px; margin: 0 auto;
  display: flex; flex-direction: column; justify-content: flex-end; gap: 20px;
  padding: 32px 24px max(26px, env(safe-area-inset-bottom));
}
.pwa-bienvenida__sub {
  text-align: center; font-size: 14px; line-height: 1.5;
  color: var(--fg-atenuado); max-width: 260px; margin: 0 auto;
}
.pwa-bienvenida__acciones { width: 100%; display: flex; flex-direction: column; gap: 12px; }

/* Instructivo de instalación (#23). El botón secundario y el modal <dialog> nativo. */
.pwa-boton--secundario {
  background: transparent; color: var(--acento-texto);
  border: 1.5px solid var(--borde);
}
/* El secundario NO hereda el hover del primario (fondo acento + texto acento = invisible): tiene
   el suyo, un wash sutil que mantiene el texto --acento legible en claro y oscuro. */
.pwa-boton--secundario:hover {
  background: var(--acento-suave);
  border-color: color-mix(in srgb, var(--acento) 40%, var(--borde-fuerte));
}
/* Destructivo suave (cancelar reserva, #9): ghost rojo — distinto del primario de acento. El texto
   usa --peligro en claro y un rojo levantado en oscuro (el token --peligro es fijo y sobre superficie
   oscura queda algo bajo). El borde/hover se derivan por color-mix, así andan en ambos temas. */
.pwa-boton--peligro-suave {
  background: transparent; color: var(--peligro);
  border: 1.5px solid color-mix(in srgb, var(--peligro) 45%, var(--borde));
}
.pwa-boton--peligro-suave:hover {
  background: color-mix(in srgb, var(--peligro) 10%, transparent);
  border-color: color-mix(in srgb, var(--peligro) 60%, var(--borde-fuerte));
}
:root[data-tema="oscuro"] .pwa .pwa-boton--peligro-suave { color: color-mix(in srgb, var(--peligro) 62%, #fff); }
.pwa-instalar { width: 100%; }
.pwa-instalar__modal {
  border: none; border-radius: var(--rad); padding: 0; max-width: 360px; width: calc(100% - 40px);
  background: var(--superficie); color: var(--fg);
}
.pwa-instalar__modal::backdrop { background: rgba(10, 10, 12, .4); }
.pwa-instalar__caja { padding: 22px; text-align: left; }
.pwa-instalar__titulo { font-size: 17px; font-weight: 700; margin-bottom: 14px; color: var(--fg); }
.pwa-instalar__pasos { margin: 0 0 18px; padding-left: 20px; display: flex; flex-direction: column; gap: 10px; }
.pwa-instalar__pasos li { font-size: 14px; line-height: 1.45; color: var(--fg); }
.pwa-instalar__glyph {
  display: inline-flex; align-items: center; justify-content: center; vertical-align: -4px;
  width: 24px; height: 24px; border-radius: 6px; background: var(--superficie-3); color: var(--fg);
}
.pwa-glyph { display: block; }

/* ============================ BANNER INSTALAR EN EL INICIO (#8) ============================ */

/* Empujón sutil arriba del inicio del socio; el JS lo oculta en standalone o si se descartó. */
.pwa-instalar-banner {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 12px 14px; margin-bottom: 16px;
  background: var(--superficie); border: 1px solid var(--borde); border-radius: var(--rad);
}
.pwa-instalar-banner__texto { font-size: 13.5px; line-height: 1.35; color: var(--fg-atenuado); }
.pwa-instalar-banner__acciones { display: flex; align-items: center; gap: 6px; flex: none; }
/* El botón "Instalá la app" del componente reusado va compacto dentro del banner. */
.pwa-instalar-banner .pwa-instalar { width: auto; }
.pwa-instalar-banner .pwa-boton--secundario { padding: 8px 12px; font-size: 13px; white-space: nowrap; }
.pwa-instalar-banner__cerrar {
  flex: none; width: 28px; height: 28px; border-radius: 50%; border: none; background: transparent;
  color: var(--fg-atenuado); font-size: 14px; line-height: 1; cursor: pointer;
}
.pwa-instalar-banner__cerrar:active { background: var(--superficie-3); }

/* ============================ RESERVAS: dos vistas + días (#10) ============================ */

/* Toggle segmentado (Reservá tu clase / Clases ya reservadas). */
.pwa-segmento {
  display: flex; gap: 4px; padding: 4px; margin-bottom: 16px;
  background: var(--superficie); border: 1px solid var(--borde); border-radius: var(--rad);
}
.pwa-segmento__op {
  flex: 1; text-align: center; padding: 9px 8px; border-radius: calc(var(--rad) - 4px);
  font-size: 13.5px; font-weight: 600; color: var(--fg-atenuado);
}
.pwa-segmento__op.is-activa { background: var(--acento); color: var(--acento-fg); }

/* Chips de día, scroll horizontal. */
.pwa-dias {
  display: flex; gap: 8px; overflow-x: auto; padding-bottom: 6px; margin-bottom: 16px;
  scrollbar-width: none;
}
.pwa-dias::-webkit-scrollbar { display: none; }
.pwa-dia {
  flex: none; padding: 8px 14px; border-radius: 999px; white-space: nowrap;
  background: var(--superficie); border: 1px solid var(--borde);
  font-size: 13px; font-weight: 600; color: var(--fg-atenuado);
}
.pwa-dia.is-activa { background: var(--acento); color: var(--acento-fg); border-color: var(--acento); }

/* Bandeja como sheet global (#42): overlay que sube desde abajo sobre la pantalla actual. */
.pwa-bandeja-sheet { position: fixed; inset: 0; z-index: 60; display: flex; flex-direction: column; justify-content: flex-end; }
.pwa-bandeja-sheet[hidden] { display: none; }
/* Scrim más oscuro (#50): .4 dejaba el panel claro mezclado con el fondo. */
.pwa-bandeja-sheet__fondo { position: absolute; inset: 0; background: rgba(10, 10, 12, .55); }
.pwa-bandeja-sheet__panel {
  position: relative; width: 100%; max-width: 480px; margin: 0 auto;
  max-height: 88dvh; display: flex; flex-direction: column; overflow: hidden;
  background: var(--lienzo); border-radius: 20px 20px 0 0; box-shadow: var(--sombra);
  border: 1px solid var(--borde); border-bottom: none; /* despega el panel del fondo (#50) */
}
/* Barra contextual, sticky arriba del scroll del panel (#50): la rinde cada vista dentro del frame. */
.pwa-bandeja-sheet__barra {
  position: sticky; top: 0; z-index: 1; background: var(--lienzo);
  flex: none; display: flex; align-items: center; justify-content: space-between;
  padding: 16px 18px; border-bottom: 1px solid var(--borde);
}
.pwa-bandeja-sheet__titulo { font-size: 16px; font-weight: 600; color: var(--fg); }
.pwa-bandeja-sheet__volver { display: inline-flex; align-items: center; gap: 4px; color: var(--fg-atenuado); font-size: 14px; font-weight: 600; }
.pwa-bandeja-sheet__volver svg { width: 20px; height: 20px; }
.pwa-bandeja-sheet__cerrar { background: none; border: 0; padding: 4px 8px; font-size: 20px; line-height: 1; color: var(--fg-atenuado); cursor: pointer; }
.pwa-bandeja-sheet turbo-frame { display: block; flex: 1; min-height: 0; overflow-y: auto; -webkit-overflow-scrolling: touch; padding: 0; }
/* El padding del contenido vive en el cuerpo (scopeado al sheet: en deep-link lo pone .pwa-cuerpo). */
.pwa-bandeja-sheet .pwa-bandeja-sheet__cuerpo { padding: 18px 18px calc(18px + env(safe-area-inset-bottom)); }
