/* efectos.css — lo que se mueve ENCIMA del tablero.

   piel.css pinta el tablero; esto es lo que pasa cuando algo golpea, muere o
   entra. Son tres cosas y las tres viven en `src/ui/efectos.js`, que es quien
   sabe DÓNDE ponerlas; aquí sólo está CÓMO se ven.

   1. Las HOJAS: flipbooks de 4×4 en `assets/piel/efectos/`, dieciséis
      fotogramas que se recorren con `steps()` en dos ejes —columnas cuatro
      veces, filas una— igual que un motor pasa un sprite sheet.
   2. Las MEZCLAS: los efectos de luz llegan sobre negro y van con
      `mix-blend-mode: screen`, donde el negro desaparece; los que ensucian
      llegan sobre blanco y van con `multiply`. Nada se keyea.
   3. Los FANTASMAS: una carta que viaja de una zona a otra no se mueve, se
      CLONA: el clon vuela por encima de todo y la de verdad espera invisible
      en su sitio. Así el vuelo no compone con `aterrizar`, `voltear` ni la
      inclinación de la mano —que ya viven en `transform`— y no lo recorta el
      `overflow` de la mano.

   La regla de siempre: nada cambia de tamaño en la rejilla. Todo es
   `transform`, `opacity` y capas absolutas por encima.

   Y una trampa que decide la estructura: `mix-blend-mode` mezcla con lo que
   hay debajo DENTRO del contexto de apilamiento del padre. Si los efectos
   colgaran de una capa con `z-index`, esa capa sería un contexto propio, la
   mezcla se haría contra su propio fondo transparente y cada chispa saldría
   con su cuadrado negro. Por eso cuelgan del campo directamente, cada uno con
   su `z-index`, y no de una capa. */

/* ----------------------------------------------------------------- hojas */

.fx {
  position: absolute; left: 0; top: 0; pointer-events: none; z-index: 6;
  will-change: transform, opacity;
}

/* `--x` y `--y` son el CENTRO del efecto en el campo; `--tam` su lado. */
.fx-hoja {
  width: var(--tam); height: var(--tam);
  background-image: var(--hoja);
  background-size: 400% 400%; background-repeat: no-repeat;
  mix-blend-mode: screen;
  transform: translate(calc(var(--x) - var(--tam) / 2), calc(var(--y) - var(--tam) / 2))
             rotate(var(--giro, 0deg));
  animation: fx-col calc(var(--dura) / 4) steps(4) 4, fx-fila var(--dura) steps(4) 1;
  animation-fill-mode: forwards;
}
/* Con la hoja a 400 % el 33,3 % es la segunda celda y el 100 % la cuarta; el
   133 % queda fuera y sólo se alcanza al terminar, cuando ya no se ve. */
@keyframes fx-col  { from { background-position-x: 0; } to { background-position-x: 133.3333%; } }
@keyframes fx-fila { from { background-position-y: 0; } to { background-position-y: 133.3333%; } }

/* ------------------------------------------------------------ partículas
   Una chispa es una hoja pequeña que además viaja. Las tres animaciones tocan
   propiedades distintas —dos el fondo, una el transform— así que conviven. */
.fx-particula {
  width: var(--tam); height: var(--tam);
  background-image: var(--hoja);
  background-size: 400% 400%; background-repeat: no-repeat;
  mix-blend-mode: screen;
  animation: fx-col calc(var(--dura) / 4) steps(4) 4,
             fx-fila var(--dura) steps(4) 1,
             fx-vuelo var(--dura) cubic-bezier(.1, .7, .3, 1) both;
}
@keyframes fx-vuelo {
  from { transform: translate(var(--x0), var(--y0)) rotate(var(--giro, 0deg)) scale(1); opacity: 1; }
  to   { transform: translate(var(--x1), var(--y1)) rotate(var(--giro, 0deg)) scale(.35); opacity: 0; }
}

/* ------------------------------------------------------------- suciedad
   Las grietas se abren en el hábitat y el polvo sube de una carta que muere. */
.fx-grietas {
  width: var(--tam); height: calc(var(--tam) * 585 / 1024);
  background: url('assets/piel/efectos/grietas.webp') center / 100% 100% no-repeat;
  mix-blend-mode: multiply;
  transform-origin: center;
  animation: fx-grietas 1s ease-out both;
}
@keyframes fx-grietas {
  0%   { opacity: 0; transform: translate(var(--x0), var(--y0)) scale(.55); }
  14%  { opacity: .95; transform: translate(var(--x0), var(--y0)) scale(1); }
  70%  { opacity: .95; }
  100% { opacity: 0; transform: translate(var(--x0), var(--y0)) scale(1.04); }
}

/* El polvo NO va en `multiply`: una nube clara sobre piedra oscura no
   oscurece nada y no se veía. Lleva alfa de verdad, que le pone la
   herramienta según lo lejos que está cada píxel del blanco, y se pinta
   encima sin mezcla. */
.fx-polvo {
  width: var(--tam); height: var(--tam);
  background: url('assets/piel/efectos/polvo.webp') center / contain no-repeat;
  animation: fx-polvo .75s ease-out both;
}
@keyframes fx-polvo {
  0%   { opacity: 0; transform: translate(var(--x0), var(--y0)) scale(.4); }
  20%  { opacity: .85; }
  100% { opacity: 0; transform: translate(var(--x0), calc(var(--y0) - 14px)) scale(1.35); }
}

/* --------------------------------------------------------------- el peso
   La sacudida es del CAMPO entero y no de la carta: la carta ya se sacude
   sola con `golpeada`; esto es la mesa temblando. `--fuerza` en píxeles. */
#campo.sacude { animation: fx-sacude .34s cubic-bezier(.36, .07, .19, .97) both; }
@keyframes fx-sacude {
  10%, 90% { transform: translate(calc(var(--fuerza) * -.3), 0); }
  20%, 80% { transform: translate(calc(var(--fuerza) * .6), calc(var(--fuerza) * .25)); }
  30%, 50%, 70% { transform: translate(calc(var(--fuerza) * -1), calc(var(--fuerza) * -.3)); }
  40%, 60% { transform: translate(var(--fuerza), calc(var(--fuerza) * .2)); }
}

/* El hit-stop: 80 ms con TODO parado. Es el recurso más viejo de los juegos
   de pelea y el que más peso da por lo que cuesta: la sacudida y el
   flipbook arrancan después, y el destello es lo único que corre durante la
   congelación, para que se lea como golpe y no como tirón. */
#partida.congelado * { animation-play-state: paused !important; }
#partida.congelado .fx-destello { animation-play-state: running !important; }

/* ----------------------------------------------------------- fantasmas */
.fx-fantasma {
  position: absolute !important; margin: 0; z-index: 40; pointer-events: none;
  transform-origin: top left;
  animation: fx-volar var(--vuelo, 300ms) cubic-bezier(.25, .8, .25, 1) var(--retardo, 0ms) both;
}
/* El dorso encima mientras vuela: una carta que sale del mazo va boca abajo. */
.fx-fantasma .carta-dorso { z-index: 5; }
@keyframes fx-volar {
  from { transform: translate(var(--fx), var(--fy)) scale(var(--fs)); opacity: .75; }
  to   { transform: none; opacity: 1; }
}
/* La de verdad, mientras su fantasma viaja. */
.en-vuelo { visibility: hidden !important; }
/* Y la que espera a que termine su ceremonia. */
.retenida { visibility: hidden !important; }

/* ---------------------------------------------------- la invocación
   Una legendaria no entra: se invoca. Se oscurece la partida, la carta crece
   al centro con los rayos girando detrás y el aura abriéndose, y al final se
   encoge hasta su ranura, donde la de verdad se voltea al llegar. */
.invocacion {
  position: absolute; inset: 0; z-index: 30; pointer-events: none;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 12px;
  overflow: hidden;
  background: radial-gradient(70% 60% at 50% 45%, rgba(40, 28, 12, .82), rgba(8, 6, 4, .94));
  animation: fx-velo var(--ceremonia) ease-out both;
}
@keyframes fx-velo {
  0% { opacity: 0; } 8% { opacity: 1; } 84% { opacity: 1; } 100% { opacity: 0; }
}
/* El lado va en una variable y el centrado se calcula DE ELLA. Estaba en
   `vmin` con un `max-width` aparte, y el tope recorta la caja pero no el
   margen: en cuanto la pantalla daba de sí, las dos capas se iban arriba y a
   la izquierda la mitad de lo recortado. */
.invocacion-rayos, .invocacion-aura {
  position: absolute; left: 50%; top: 45%;
  width: var(--lado); height: var(--lado);
  margin: calc(var(--lado) / -2) 0 0 calc(var(--lado) / -2);
  mix-blend-mode: screen; pointer-events: none;
}
/* Los rayos GIRAN, y un cuadrado que gira sólo cubre siempre su círculo
   inscrito: fuera de él, sus cuatro cantos barren la pantalla. La textura
   llega brillante hasta el borde —235 de 255 a cuatro quintos del radio, 41
   a un píxel del canto— así que en `screen` sobre el velo ese corte se veía,
   y lo que se veía era un cuadrado dando vueltas detrás de la carta.
   La máscara redonda lo recorta por dentro del círculo inscrito: gira consigo
   misma, así que ya no hay borde que se mueva. El lado sube lo justo para que
   el disco opaco llegue donde llegaba el cuadrado (.76 x 195 ~ 150). */
.invocacion-rayos {
  --lado: min(195vmin, 1170px);
  background: url('assets/piel/efectos/rayos.webp') center / cover no-repeat;
  -webkit-mask-image: radial-gradient(circle closest-side, #000 76%, transparent 99%);
  mask-image: radial-gradient(circle closest-side, #000 76%, transparent 99%);
  animation: fx-girar 9s linear infinite, fx-rayos var(--ceremonia) ease-out both;
}
@keyframes fx-girar { to { transform: rotate(360deg); } }
@keyframes fx-rayos { 0% { opacity: 0; } 15% { opacity: .9; } 78% { opacity: .9; } 100% { opacity: 0; } }
/* El aura no gira —es un flipbook de 4x4— así que no necesita máscara: sólo
   el centrado bueno. */
.invocacion-aura {
  --lado: min(110vmin, 640px);
  background: url('assets/piel/efectos/aura.webp') 0 0 / 400% 400% no-repeat;
  animation: fx-col 280ms steps(4) 4 120ms both, fx-fila 1120ms steps(4) 1 120ms both;
}
.invocacion-carta {
  position: relative; width: min(60vw, 236px);
  filter: drop-shadow(0 0 26px rgba(217, 164, 65, .55)) drop-shadow(0 12px 18px rgba(0, 0, 0, .7));
  animation: fx-invocar var(--ceremonia) cubic-bezier(.2, .8, .2, 1) both;
}
.invocacion-carta .carta--visor { width: 100%; }
@keyframes fx-invocar {
  0%   { opacity: 0; transform: scale(.25); }
  16%  { opacity: 1; transform: scale(1.07); }
  24%  { transform: scale(1); }
  76%  { opacity: 1; transform: translate(0, 0) scale(1); }
  100% { opacity: .1; transform: translate(var(--dx, 0px), var(--dy, 0px)) scale(var(--ds, .3)); }
}
.invocacion-rotulo {
  position: relative; text-align: center; color: var(--acento-claro);
  font-family: 'Cinzel', 'Terralis', serif; letter-spacing: .18em; font-size: 11px; text-transform: uppercase;
  text-shadow: 0 1px 3px #000, 0 0 12px rgba(217, 164, 65, .5);
  animation: fx-rotulo var(--ceremonia) ease-out both;
}
.invocacion-rotulo b { display: block; font-size: 15px; letter-spacing: .26em; color: var(--acento-vivo, #f4d99b); }
.invocacion-rotulo span { display: block; margin-top: 4px; font-style: italic; text-transform: none; letter-spacing: .04em; font-size: 12px; }
@keyframes fx-rotulo {
  0%, 18% { opacity: 0; transform: translateY(10px); }
  30%     { opacity: 1; transform: none; }
  72%     { opacity: 1; }
  84%     { opacity: 0; }
}

/* ------------------------------------------------------ el clima, puesto
   Dos capas fijas dentro del campo, `render.js` escribe `data-clima` con el
   id de la carta puesta, y cada clima dice qué va en cada capa. Las texturas
   son mosaicos cerrados por `tools/efectos.py`, en `screen` las de luz y en
   `multiply` la calima; el tinte de color va en la segunda capa sin mezcla.
   Nada de esto cambia el tamaño de nada: las dos capas son absolutas. */
.clima-capa {
  position: absolute; inset: 0; z-index: 5; pointer-events: none;
  display: none; will-change: background-position, opacity;
}
#campo[data-clima]:not([data-clima=""]) > .clima-capa { display: block; }

/* Monzón de verano: lluvia gruesa cayendo en diagonal y el cielo cerrado. */
#campo[data-clima="sabana"] > .clima-capa.a {
  background: url('assets/piel/efectos/lluvia.webp') 0 0 / 224px 224px repeat;
  mix-blend-mode: screen; opacity: .55;
  animation: clima-lluvia .7s linear infinite;
}
#campo[data-clima="sabana"] > .clima-capa.b { background: rgba(12, 18, 30, .28); }
@keyframes clima-lluvia { to { background-position: -60px 224px; } }

/* Estación de lluvias: llovizna fina, casi vertical, y el verde saturado. */
#campo[data-clima="bosque"] > .clima-capa.a {
  background: url('assets/piel/efectos/llovizna.webp') 0 0 / 256px auto repeat;
  mix-blend-mode: screen; opacity: .5;
  animation: clima-llovizna 1.1s linear infinite;
}
#campo[data-clima="bosque"] > .clima-capa.b { background: rgba(72, 128, 64, .22); mix-blend-mode: multiply; }
@keyframes clima-llovizna { to { background-position: -8px 171px; } }

/* Bruma de valle: dos capas de niebla a distinta velocidad, para que el
   bucle no se vea. */
#campo[data-clima="canal"] > .clima-capa.a {
  background: url('assets/piel/efectos/bruma.webp') 0 0 / 560px auto repeat;
  mix-blend-mode: screen; opacity: .42;
  animation: clima-bruma-a 46s linear infinite;
}
#campo[data-clima="canal"] > .clima-capa.b {
  background: url('assets/piel/efectos/bruma.webp') 0 40% / 420px auto repeat;
  mix-blend-mode: screen; opacity: .3;
  animation: clima-bruma-b 31s linear infinite;
}
@keyframes clima-bruma-a { to { background-position: 560px 0; } }
@keyframes clima-bruma-b { to { background-position: -420px 40%; } }

/* Crecida estacional: el agua sube por el tercio de abajo, con su horizonte
   negro fundiéndose en la piedra. */
#campo[data-clima="llanura"] > .clima-capa.a {
  top: auto; height: 44%;
  background: url('assets/piel/efectos/agua.webp') 0 100% / auto 100% repeat-x;
  mix-blend-mode: screen; opacity: .7;
  animation: clima-agua 28s linear infinite;
}
#campo[data-clima="llanura"] > .clima-capa.b { background: rgba(40, 60, 70, .16); }
@keyframes clima-agua { to { background-position: 660px 100%; } }

/* Sequía prolongada: la calima en los bordes, respirando, y el aire caliente. */
#campo[data-clima="aridez"] > .clima-capa.a {
  background: url('assets/piel/efectos/calima.webp') center / 100% 100% no-repeat;
  mix-blend-mode: multiply; opacity: .85;
  animation: clima-calima 5.5s ease-in-out infinite;
}
#campo[data-clima="aridez"] > .clima-capa.b { background: rgba(214, 150, 60, .12); }
@keyframes clima-calima { 0%, 100% { opacity: .78; } 50% { opacity: .95; } }

/* Quien pide menos movimiento se queda sin mesa que tiembla, sin chispas y
   sin vuelos; `efectos.js` ya no los crea, y esto es el cinturón por si
   alguno se cuela. El clima se queda puesto, quieto. */
@media (prefers-reduced-motion: reduce) {
  #campo.sacude { animation: none; }
  .fx-particula, .fx-fantasma { display: none; }
  .en-vuelo { visibility: visible !important; }
  .clima-capa { animation: none !important; }
}

/* ------------------------------------------------------ el rótulo del final
   VICTORIA o DERROTA sobre el tablero (src/ui/fin.js). Cuelga de #partida como
   la invocación, se quita solo y un toque lo salta. Con movimiento reducido no
   se crea: lo decide el JS. */
.fin-rotulo {
  position: absolute; inset: 0; z-index: 40; cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  background: radial-gradient(75% 55% at 50% 50%, rgba(24, 16, 8, .6), rgba(6, 4, 3, .9));
  animation: fin-velo var(--rotulo) ease-out both;
}
@keyframes fin-velo { 0% { opacity: 0; } 12% { opacity: 1; } 86% { opacity: 1; } 100% { opacity: 0; } }
.fin-rotulo-pieza {
  position: relative; width: min(88vw, 520px); aspect-ratio: 16 / 9;
  display: flex; align-items: flex-end; justify-content: center;
  animation: fin-cae var(--rotulo) cubic-bezier(.2, .9, .3, 1.2) both;
}
@keyframes fin-cae {
  0%       { opacity: 0; transform: translateY(-36px) scale(1.25); }
  14%      { opacity: 1; transform: translateY(3px) scale(.98); }
  22%, 100% { opacity: 1; transform: none; }
}
.fin-rotulo-sello {
  position: absolute; left: 50%; top: 0; width: 30%; aspect-ratio: 1; margin-left: -15%; z-index: 1;
  background: url('assets/piel/ico_trofeo.webp') center / contain no-repeat;
  filter: drop-shadow(0 0 16px rgba(232, 192, 121, .7));
}
.fin-rotulo.pierde .fin-rotulo-sello { filter: grayscale(1) brightness(.6); }
.fin-rotulo-tela {
  position: relative; width: 100%; height: 62%; padding-bottom: 6%;
  display: flex; align-items: center; justify-content: center;
  background: linear-gradient(#3a2d1f, #211810);
  border-top: 3px solid var(--borde-fuerte);
  clip-path: polygon(0 0, 100% 0, 96% 50%, 100% 100%, 50% 86%, 0 100%, 4% 50%);
}
.fin-rotulo-tela b {
  font-family: 'Terralis', 'Cinzel', Georgia, serif; font-weight: 700;
  font-size: clamp(32px, 10vw, 60px); letter-spacing: .08em; text-transform: uppercase;
  color: #e6ddd0; text-shadow: 0 2px 0 #000, 0 0 16px rgba(0, 0, 0, .8);
}
.fin-rotulo.gana .fin-rotulo-tela b {
  color: var(--acento-vivo, #f4d99b); text-shadow: 0 2px 0 #000, 0 0 22px rgba(217, 164, 65, .6);
}
/* Con el estandarte de verdad la tela empieza bajo la barra —un quinto del
   alto— y acaba en la V: la palabra se centra en lo que queda, más pequeña. */
.fin-rotulo.con-arte .fin-rotulo-tela {
  background: url('assets/piel/fin/estandarte.webp') center / 100% 100% no-repeat;
  border: 0; clip-path: none; padding: 5% 0 4%;
}
.fin-rotulo.con-arte .fin-rotulo-tela b { font-size: clamp(24px, 7.5vw, 44px); }
.fin-rotulo.con-arte .fin-rotulo-sello { background-image: url('assets/piel/fin/sello_victoria.webp'); }

/* ------------------------------------------------------ la presentación
   Quién contra quién antes de la partida (src/ui/presentacion.js). La
   pantalla se parte en diagonal: el rival arriba y tú abajo, y cada mitad
   entra desde su lado. Todo es transform, clip-path y opacity; el centrado
   del VS va con `translate`, que es otra propiedad y no pisa la animación. */
.presentacion {
  position: absolute; inset: 0; z-index: 45; overflow: hidden; cursor: pointer;
  background: #0b0806;
  animation: pres-velo var(--dura) ease-out both;
}
@keyframes pres-velo { 0% { opacity: 0; } 8% { opacity: 1; } 88% { opacity: 1; } 100% { opacity: 0; } }
.pres-mitad { position: absolute; inset: 0; }
.pres-mitad.rival {
  clip-path: polygon(0 0, 100% 0, 100% 56%, 0 42%);
  background: radial-gradient(90% 60% at 80% 20%, rgba(200,103,74,.42), transparent 70%),
    linear-gradient(#2a120c, #120806);
  animation: pres-entra-rival 650ms cubic-bezier(.2,.8,.2,1) backwards;
}
.pres-mitad.propio {
  clip-path: polygon(0 44%, 100% 58%, 100% 100%, 0 100%);
  background: radial-gradient(90% 60% at 20% 80%, rgba(232,192,121,.32), transparent 70%),
    linear-gradient(#17110a, #2a2014);
  animation: pres-entra-propio 650ms cubic-bezier(.2,.8,.2,1) 80ms backwards;
}
@keyframes pres-entra-rival { from { transform: translateX(45%); opacity: 0; } }
@keyframes pres-entra-propio { from { transform: translateX(-45%); opacity: 0; } }
/* El retrato ocupa su mitad y se funde hacia la costura. */
.pres-retrato { position: absolute; left: 0; right: 0; opacity: .7; }
.pres-mitad.rival .pres-retrato {
  top: 0; height: 56%;
  -webkit-mask-image: linear-gradient(to bottom, #000 45%, transparent 95%);
  mask-image: linear-gradient(to bottom, #000 45%, transparent 95%);
}
.pres-mitad.propio .pres-retrato {
  bottom: 0; height: 56%;
  -webkit-mask-image: linear-gradient(to top, #000 45%, transparent 95%);
  mask-image: linear-gradient(to top, #000 45%, transparent 95%);
}
.pres-retrato > img, .pres-retrato > svg { display: block; width: 100%; height: 100%; object-fit: cover; }
.pres-retrato > svg { opacity: .35; }
/* Tu retrato de la tienda tapa la portada del mazo; el del rival, sólo en un
   duelo, que es cuando existe `--retrato-rival`. Sin variable no hay imagen y
   se sigue viendo la portada. */
.pres-retrato::after {
  content: ''; position: absolute; inset: 0; pointer-events: none;
  /* Ampliado: los retratos traen una viñeta redonda y a sangre se veía su arco. */
  background: var(--retrato-propio, none) center 28% / 130% auto no-repeat;
}
.pres-mitad.rival .pres-retrato::after { background-image: var(--retrato-rival, none); }
/* El estandarte cuelga por dentro de cada mitad, con el emblema del clado. */
.pres-estandarte {
  position: absolute; width: min(22vw, 120px); aspect-ratio: 1 / 2.5;
  background: linear-gradient(#4a3a22, #2a2014);
  border-top: 3px solid var(--borde-fuerte);
  clip-path: polygon(0 0, 100% 0, 100% 100%, 50% 88%, 0 100%);
  filter: drop-shadow(0 8px 12px rgba(0,0,0,.6));
}
.pres-mitad.rival .pres-estandarte { right: 9%; top: 0; background: linear-gradient(#5a2419, #2a100b); }
.pres-mitad.propio .pres-estandarte { left: 9%; top: 58%; }
/* El emblema va en absoluto y no con padding: un padding en % se mide contra
   el ANCHO DEL CONTENEDOR —la mitad entera, 375 px— y no contra el
   estandarte, y lo mandaba al pie de la tela. */
.pres-estandarte .emblema {
  position: absolute; left: 50%; top: 30%; translate: -50% 0;
  width: 64%; height: auto; aspect-ratio: 1;
}
/* Con el arte, la caja lleva la proporción MEDIDA del estandarte recortado
   (787 / 1919, tools/presentacion.py). La barra es más ancha que la tela —la
   tela ocupa el 56 % central—, así que el emblema se estrecha para caber en
   ella y baja a un tercio del alto. */
.presentacion.con-arte .pres-estandarte {
  width: min(26vw, 140px); aspect-ratio: 787 / 1919;
  border: 0; clip-path: none; filter: drop-shadow(0 8px 12px rgba(0,0,0,.6));
  /* Con estandarte de la tienda, `--estandarte-propio` y, en un duelo,
     `--estandarte-rival` (src/ui/tienda.js). */
  background: var(--estandarte-propio, url('assets/piel/vs/estandarte_propio.webp')) center / 100% 100% no-repeat;
}
.presentacion.con-arte .pres-estandarte .emblema { width: 46%; top: 33%; }
.presentacion.con-arte .pres-mitad.rival .pres-estandarte {
  background-image: var(--estandarte-rival, url('assets/piel/vs/estandarte_rival.webp'));
}
.pres-nombre {
  position: absolute; display: flex; flex-direction: column; gap: 3px; max-width: 58%;
  text-shadow: 0 2px 3px #000, 0 0 14px rgba(0,0,0,.8);
}
.pres-mitad.rival .pres-nombre { left: 18px; top: calc(var(--seguro-arriba) + 22%); }
.pres-mitad.propio .pres-nombre { right: 18px; bottom: calc(var(--seguro-abajo) + 18%); align-items: flex-end; text-align: right; }
.pres-nombre b {
  font-family: 'Terralis', 'Cinzel', Georgia, serif; font-size: clamp(20px, 6.4vw, 30px); font-weight: 700;
  line-height: 1.05; color: var(--texto); max-width: 100%;
  /* Dos líneas: «El clan de Ceratosaurus» no cabe en una y cortarlo en
     «El clan de Cerato…» se lleva justo lo que lo nombra. */
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; line-clamp: 2;
  overflow: hidden; overflow-wrap: anywhere;
}
.pres-nombre span { font-size: 11px; letter-spacing: .14em; text-transform: uppercase; color: var(--texto-2); }
.pres-costura {
  position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(90deg, #8a6c38, #f4d99b 50%, #8a6c38);
  clip-path: polygon(0 42%, 100% 56%, 100% 58%, 0 44%);
  filter: drop-shadow(0 0 8px rgba(217,164,65,.7));
  animation: pres-costura 700ms ease-out 200ms backwards;
}
@keyframes pres-costura { from { opacity: 0; } }
.pres-centro {
  position: absolute; left: 0; right: 0; top: 50%; translate: 0 -50%;
  display: flex; flex-direction: column; align-items: center; gap: 4px;
  text-shadow: 0 2px 3px #000;
  animation: pres-centro 500ms cubic-bezier(.2,.9,.3,1.3) 350ms backwards;
}
@keyframes pres-centro { from { opacity: 0; transform: scale(1.6); } }
.pres-vs {
  display: grid; place-items: center; width: 68px; height: 68px;
  font-family: 'Terralis', 'Cinzel', Georgia, serif; font-size: 22px; color: var(--acento-vivo);
  background: url('assets/piel/fin/medallon_vs.webp') center / contain no-repeat;
}
.pres-centro b {
  font-family: 'Cinzel', 'Terralis', serif; font-size: 12px; letter-spacing: .28em; text-transform: uppercase;
  color: var(--acento-claro);
}
.pres-centro small { font-size: 11px; color: var(--texto-2); }
.fin-rotulo.con-arte.pierde .fin-rotulo-sello {
  background-image: url('assets/piel/fin/sello_derrota.webp'); filter: drop-shadow(0 4px 8px rgba(0, 0, 0, .8));
}
