/* ══════════════════════════════════════════════════════════════════
   COP · LA PANTALLA DE CARGA INTERACTIVA  ·  08/09/2026
   ──────────────────────────────────────────────────────────────────
   Franco: *«en algunos lugares tal vez haya que crear pantallas de
   carga que conecten entre ellas con un diseño interactivo, que cumple
   la misma función de por ejemplo los juegos como FIFA o Clash Royale
   que eviten esos tiempos muertos con un diseño top y que enganche o dé
   información»*.

   ⚠⚠ QUÉ HACE UNA PANTALLA DE CARGA DE JUEGO, Y POR QUÉ NO ES UNA
   RUEDITA. Una ruedita dice «esperá». Las de FIFA y Clash Royale hacen
   otras tres cosas, y son las que sacan el tiempo muerto:
     1. CUENTAN UNA HISTORIA. No es una barra opaca: son pasos con
        nombre —buscando, sorteando, armando— y el jugador ve avanzar
        algo que entiende. Un mismo tiempo de espera se siente la mitad
        cuando sabés en qué paso estás.
     2. REVELAN AL RIVAL. El momento en que aparecen los dos escudos y
        choca el VS es el gancho: la espera termina en un evento, no en
        una redirección.
     3. ENSEÑAN. El renglón de abajo rota consejos reales del modo. Es
        el único lugar de la app donde el jugador está mirando la
        pantalla sin nada que hacer.

   ⚠⚠ ES UNA CAPA, NO UNA PÁGINA. `buscando.html` es una pantalla
   entera, y por eso el 1v1 tiene que NAVEGAR para buscar rival: se
   pierde el contexto, y si el jugador vuelve atrás cae en la búsqueda
   otra vez. Esto se abre encima de la pantalla donde está parado, así
   que el mismo componente sirve para el duelo por equipos, para el 1v1
   y para cualquier espera que venga —y ninguna necesita una URL.

   ⚠ TODO SE MUEVE CON `transform` Y `opacity`. Nada de `width` ni de
   `top` animados: eso rehace el layout en cada cuadro y en un teléfono
   de gama media se ve el tirón. Y con `prefers-reduced-motion: reduce`
   TODO se apaga dejando las piezas en su lugar final —visibles—, que es
   la parte que se olvida.

   CÓMO SE USA (ver `cop-cargando.js`):
     COPCargando.abrir({ titulo, pasos:[…], tips:[…], yo:{…} })
     COPCargando.paso(1)
     COPCargando.rival({ nombre, escudo })
     COPCargando.listo({ texto, boton, alSeguir })
   ══════════════════════════════════════════════════════════════════ */

/* ── LA CAPA ───────────────────────────────────────────────────────
   ⚠ `position:fixed` con `inset:0` y NO `width:100vw`: `100vw` incluye
   la barra de scroll y saca la capa 15 px de la pantalla en escritorio.
   Es la trampa que ya costó dos veces en este proyecto. */
.cop-carg{
  position:fixed; inset:0; z-index:9000;
  display:flex; flex-direction:column; align-items:center; justify-content:center;
  gap:var(--gap-2xl, 1.8rem);
  padding:var(--cop-aire, 1.8rem) 1rem;
  box-sizing:border-box;
  background:var(--bg, #0b0e14);
  text-align:center;
  overflow:hidden;
}
.cop-carg[hidden]{display:none}

/* el halo del acento de la competencia detrás de todo.
   ⚠ EL COLOR NO ESTÁ ESCRITO: sale de `--cop-acento-rgb`, así que en
   División League y Carrera esta misma capa se abre violeta sin una
   regla nueva. */
.cop-carg::before{
  content:""; position:absolute; inset:0; z-index:0; pointer-events:none;
  background:
    radial-gradient(circle at 50% 38%, rgba(var(--cop-acento-rgb, 12,149,235),.20) 0, transparent 62%),
    radial-gradient(circle at 50% 100%, rgba(var(--cop-acento-rgb, 12,149,235),.08) 0, transparent 55%);
}
.cop-carg > *{position:relative; z-index:1; max-width:100%}

/* ── LA VARIANTE CON ARTE (13/09/2026) ─────────────────────────────
   Franco pidió una pantalla de carga «estilo gaming online mobile, como
   las de Clash Royale o Brawl Stars» y pasó el arte: el túnel de salida
   al campo con el logo de CP arriba. La variante se enciende sola cuando
   el que abre la capa pasa `arte`.

   ⚠⚠ EL CONTENIDO BAJA, NO SE CENTRA. El arte trae el logo y «CLASH OF
   PICKS» en el tercio de ARRIBA: con el contenido centrado, el anillo con
   el logo de la app le quedaba encima al logo del arte —el mismo dibujo
   dos veces, uno tapando al otro—. Abajo el arte es piso de túnel oscuro,
   que es exactamente donde un texto blanco se lee.

   ⚠ EL VELO NO ES DECORACIÓN: sobre la foto pelada el subtítulo gris
   (`--text-dim`) desaparece contra los reflejos del piso mojado. Es la
   misma razón por la que el apellido de las camisetas lleva contorno.

   ⚠ `--cop-carg-arte` LA ESCRIBE EL JS con la URL que le pasaron: la hoja
   no conoce ningún archivo. Así la próxima pantalla que quiera otra
   imagen no toca una línea de CSS. */
.cop-carg--arte{
  justify-content:flex-end;
  padding-bottom:max(var(--cop-aire, 1.8rem), env(safe-area-inset-bottom, 0px));
  gap:var(--gap-lg, 1rem);
  background:var(--bg, #0b0e14) var(--cop-carg-arte, none) center top / cover no-repeat;
}
/* el velo: transparente arriba —donde vive el arte— y macizo abajo,
   donde vive el texto. Va DESPUÉS del halo del acento y antes del
   contenido (`.cop-carg > *` ya está en z-index 1). */
.cop-carg--arte::after{
  content:""; position:absolute; inset:0; z-index:0; pointer-events:none;
  background:linear-gradient(to bottom,
    rgba(8,9,13,0) 0%, rgba(8,9,13,.15) 38%,
    rgba(8,9,13,.72) 62%, rgba(8,9,13,.93) 82%, rgba(8,9,13,.97) 100%);
}
/* con arte, el halo de color se apaga: dos degradados encima de una foto
   la enturbian y el acento ya lo pone el propio arte. */
.cop-carg--arte::before{opacity:.35}

/* la capa entra con un fundido corto: sin él, aparece de golpe encima
   de la pantalla y se lee como un salto de página. */
@keyframes cop-carg-entra{from{opacity:0}to{opacity:1}}
.cop-carg{animation:cop-carg-entra .18s ease-out both}

/* ── LA ESCENA DEL CHOQUE ──────────────────────────────────────────
   Dos escudos y un VS en el medio. Mientras no se sabe quién es el
   rival, el lado derecho es una silueta que respira: dice «acá va
   alguien» sin inventar quién.
   ⚠ ES UNA GRILLA DE TRES COLUMNAS Y NO UN `flex` con `gap`: las dos
   columnas de los lados tienen que medir LO MISMO para que el VS quede
   en el centro exacto, y con `flex` el nombre más largo lo corre. */
.cop-carg-vs{
  display:grid; grid-template-columns:1fr auto 1fr;
  align-items:center; gap:var(--gap-md, .7rem);
  width:100%; max-width:420px;
}
.cop-carg-lado{
  display:flex; flex-direction:column; align-items:center; gap:.5rem; min-width:0;
}
.cop-carg-esc{
  width:82px; height:82px; display:grid; place-items:center; flex:0 0 auto;
  filter:drop-shadow(0 8px 22px rgba(0,0,0,.6));
}
.cop-carg-esc img{width:100%;height:100%;object-fit:contain;display:block}
/* la silueta del rival desconocido */
.cop-carg-esc.cop-carg-esc--nadie{
  border-radius:50%;
  background:rgba(255,255,255,.05);
  box-shadow:inset 0 0 0 2px rgba(var(--cop-acento-rgb, 12,149,235),.35);
  font-family:Anton, Inter, sans-serif; font-size:2rem;
  color:rgba(255,255,255,.45);
}
.cop-carg-nom{
  font-family:Anton, Inter, sans-serif; font-weight:400;
  font-size:var(--fs-base, 1rem); letter-spacing:.5px; text-transform:uppercase;
  color:var(--text, #f4f6fb); line-height:var(--lh-tight, 1.1);
  /* dos renglones y corta: un nombre largo no puede correr el VS */
  overflow:hidden; display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical;
}
.cop-carg-nom--tenue{color:var(--text-faint, #5a6275)}
.cop-carg-vs-txt{
  font-family:Anton, Inter, sans-serif; font-size:1.6rem; letter-spacing:1px;
  color:rgb(var(--cop-acento-rgb, 12,149,235));
  text-shadow:0 0 18px rgba(var(--cop-acento-rgb, 12,149,235),.55);
}

/* ⚠ LOS DOS LADOS ENTRAN DESDE AFUERA, no aparecen: el gesto es el que
   hace que se lea como un enfrentamiento. Y entran UNA VEZ. */
@keyframes cop-carg-izq{from{opacity:0;transform:translateX(-26px)}to{opacity:1;transform:none}}
@keyframes cop-carg-der{from{opacity:0;transform:translateX(26px)}to{opacity:1;transform:none}}
.cop-carg-lado--yo{animation:cop-carg-izq .42s cubic-bezier(.2,.8,.3,1) both}
.cop-carg-lado--rival{animation:cop-carg-der .42s cubic-bezier(.2,.8,.3,1) both}

/* mientras no hay rival, la silueta respira */
@keyframes cop-carg-respira{0%,100%{transform:scale(1);opacity:.75}50%{transform:scale(1.06);opacity:1}}
.cop-carg-esc--nadie{animation:cop-carg-respira 1.8s ease-in-out infinite}

/* ⚠⚠ EL MOMENTO DEL HALLAZGO: cuando llega el rival, la capa se marca
   con `.cop-carg--hallado` y el escudo nuevo entra con un golpe y el VS
   pega un salto. Es UN solo cuadro de atención y dura 500 ms: más que
   eso deja de ser un gancho y pasa a ser una demora que agregué yo. */
@keyframes cop-carg-golpe{
  0%{opacity:0;transform:translateX(34px) scale(1.25)}
  60%{opacity:1;transform:translateX(0) scale(.96)}
  100%{transform:none}
}
@keyframes cop-carg-choque{
  0%{transform:scale(1)}
  35%{transform:scale(1.42)}
  70%{transform:scale(.94)}
  100%{transform:scale(1)}
}
.cop-carg--hallado .cop-carg-lado--rival{animation:cop-carg-golpe .5s cubic-bezier(.2,.9,.3,1) both}
.cop-carg--hallado .cop-carg-vs-txt{animation:cop-carg-choque .5s cubic-bezier(.3,1.4,.4,1) both}

/* ── EL ANILLO CON EL LOGO ─────────────────────────────────────────
   ⚠ SE ESCONDE CUANDO YA ESTÁ TODO LISTO: un anillo girando arriba de
   «¡Duelo listo!» es la contradicción más fácil de dejar puesta. */
.cop-carg-anillo{width:92px;height:92px;position:relative}
.cop-carg-anillo svg{width:100%;height:100%;animation:cop-carg-gira 1.1s linear infinite}
.cop-carg-anillo .cop-carg-ring-bg{stroke:var(--card-border,#1e2330)}
.cop-carg-anillo .cop-carg-ring-fg{stroke:rgb(var(--cop-acento-rgb, 12,149,235));stroke-linecap:round}
@keyframes cop-carg-gira{to{transform:rotate(360deg)}}
.cop-carg-anillo-logo{position:absolute;inset:0;display:grid;place-items:center}
.cop-carg-anillo-logo img{width:40px;height:40px;object-fit:contain;animation:cop-carg-late 1.6s ease-in-out infinite}
@keyframes cop-carg-late{0%,100%{transform:scale(1);opacity:.9}50%{transform:scale(1.09);opacity:1}}
.cop-carg--hallado .cop-carg-anillo{display:none}

/* ── TÍTULO Y BAJADA ──────────────────────────────────────────────── */
.cop-carg-tit{
  font-family:Anton, Inter, sans-serif; font-weight:400;
  font-size:clamp(1.4rem, 7vw, 2rem); letter-spacing:.5px;
  color:#fff; line-height:var(--lh-tight, 1.1);
}
.cop-carg-sub{
  margin-top:.5rem;
  color:var(--text-dim, #9aa3b5); font-size:var(--fs-base, 1rem);
  line-height:var(--lh-loose, 1.5); max-width:320px; margin-left:auto; margin-right:auto;
}
/* los tres puntitos que titilan detrás del título */
.cop-carg-pts span{animation:cop-carg-titila 1.4s infinite both}
.cop-carg-pts span:nth-child(2){animation-delay:.2s}
.cop-carg-pts span:nth-child(3){animation-delay:.4s}
@keyframes cop-carg-titila{0%,80%,100%{opacity:.2}40%{opacity:1}}
.cop-carg--hallado .cop-carg-pts{display:none}

/* ── LOS PASOS ─────────────────────────────────────────────────────
   ⚠⚠ ESTO ES LO QUE SACA EL TIEMPO MUERTO, más que cualquier animación:
   el jugador ve que algo avanza y sabe qué falta. Tres estados: hecho
   (tilde), corriendo (punto encendido + texto en blanco) y pendiente
   (apagado). Lo pendiente SE APAGA, NO SE ESCONDE —regla 9 del
   sistema—: hay que poder ver cuánto queda. */
.cop-carg-pasos{
  display:flex; flex-direction:column; gap:var(--gap-sm, .5rem);
  width:100%; max-width:320px; text-align:left;
}
.cop-carg-paso{
  display:flex; align-items:center; gap:var(--gap-md, .7rem);
  font-size:var(--fs-sm, .8rem); font-weight:700;
  color:var(--text-faint, #5a6275);
  opacity:.55; transition:opacity .25s, color .25s;
}
.cop-carg-paso-pt{
  flex:0 0 auto; width:18px; height:18px; border-radius:50%;
  display:grid; place-items:center;
  box-shadow:inset 0 0 0 1.5px currentColor;
}
.cop-carg-paso-pt svg{width:11px;height:11px;display:none}
.cop-carg-paso[data-estado="corriendo"]{opacity:1;color:rgb(var(--cop-acento-rgb, 12,149,235))}
.cop-carg-paso[data-estado="corriendo"] .cop-carg-paso-pt::after{
  content:""; width:8px; height:8px; border-radius:50%; background:currentColor;
  animation:cop-carg-pulso 1.2s ease-in-out infinite;
}
@keyframes cop-carg-pulso{0%,100%{transform:scale(.75);opacity:.6}50%{transform:scale(1);opacity:1}}
.cop-carg-paso[data-estado="hecho"]{opacity:1;color:var(--ok, #22c55e)}
.cop-carg-paso[data-estado="hecho"] .cop-carg-paso-pt svg{display:block}
.cop-carg-paso[data-estado="hecho"] .cop-carg-paso-txt{color:var(--text, #f4f6fb)}

/* ── EL TIP ROTATIVO ──────────────────────────────────────────────
   ⚠ SIN CAJA (regla 1): es una línea sobre el fondo de la página con
   una línea arriba, no un cartel con borde y color propio.
   ⚠ EL ALTO ESTÁ FIJADO EN DOS RENGLONES a propósito: los tips no miden
   lo mismo, y sin alto fijo cada cambio de tip corre todo lo de arriba.
   Un layout que salta cada cuatro segundos es peor que no tener tips. */
.cop-carg-tip{
  width:100%; max-width:360px;
  padding-top:var(--gap-lg, 1rem);
  border-top:1px solid var(--card-border, #1e2330);
  font-size:var(--fs-sm, .8rem); color:var(--text-dim, #9aa3b5);
  line-height:var(--lh-base, 1.3);
  min-height:calc(2 * 1.3em + var(--gap-lg, 1rem));
}
.cop-carg-tip b{
  display:block; margin-bottom:.2rem;
  font-size:var(--fs-xs, .72rem); letter-spacing:1.5px; text-transform:uppercase;
  color:rgb(var(--cop-acento-rgb, 12,149,235));
}
.cop-carg-tip-txt{display:block; animation:cop-carg-tip-e .45s ease-out both}
@keyframes cop-carg-tip-e{from{opacity:0;transform:translateY(6px)}to{opacity:1;transform:none}}

/* ── LOS BOTONES ──────────────────────────────────────────────────
   Son `.cop-b` del sistema. Acá sólo se decide el ancho de la columna.
   ⚠ EL DE CANCELAR SE VA CUANDO YA HAY DUELO: cancelar algo que ya
   pasó no significa nada. */
.cop-carg-acciones{display:flex;flex-direction:column;gap:var(--gap-md, .7rem);width:100%;max-width:320px}
.cop-carg--hallado .cop-carg-cancelar{display:none}
/* ⚠⚠ VA CON DOS CLASES (`.cop-carg .cop-carg-seguir`) Y NO CON UNA, y
   esto no es cosmética: `cop-boton.css` declara `.cop-b{display:
   inline-flex}` y se carga DESPUÉS de esta hoja —lo pide el orden de
   carga del sistema—. Un `.cop-carg-seguir{display:none}` a secas empata
   en especificidad con `.cop-b` (0-1-0) y pierde por orden de
   declaración, así que el botón «Continuar» se dibujaba VACÍO arriba de
   «Cancelar» durante toda la búsqueda. Se vio en la captura, no en los
   números.
   Es la décima aparición en este proyecto de la misma familia de
   defecto: un componente que declara `display` le gana a quien intenta
   esconderlo con la misma especificidad. */
.cop-carg .cop-carg-seguir{display:none}
.cop-carg.cop-carg--hallado .cop-carg-seguir{display:inline-flex}

/* ⚠ EN PANTALLA BAJA (un teléfono chico con el teclado, o apoyado) se
   sacan los pasos antes que la escena del choque: la escena es el
   gancho y los pasos son el detalle. */
@media (max-height:600px){
  .cop-carg{gap:var(--gap-lg, 1rem)}
  .cop-carg-pasos{display:none}
  .cop-carg-esc{width:64px;height:64px}
  .cop-carg-anillo{width:70px;height:70px}
}

/* ⚠⚠ Y TODO ESTO SE APAGA CON `prefers-reduced-motion`, dejando cada
   pieza VISIBLE y en su lugar final. Apagar animaciones sin restaurar
   `opacity:1; transform:none` deja media pantalla invisible, que es
   exactamente lo contrario de una ayuda de accesibilidad. */
@media (prefers-reduced-motion: reduce){
  .cop-carg,
  .cop-carg-lado--yo, .cop-carg-lado--rival,
  .cop-carg--hallado .cop-carg-lado--rival,
  .cop-carg--hallado .cop-carg-vs-txt,
  .cop-carg-esc--nadie, .cop-carg-anillo svg,
  .cop-carg-anillo-logo img, .cop-carg-tip-txt,
  .cop-carg-pts span,
  .cop-carg-paso[data-estado="corriendo"] .cop-carg-paso-pt::after{
    animation:none !important;
    opacity:1; transform:none;
  }
}
