/* cosmetics.css — La apariencia de los cosméticos.
 *
 * Toda la pinta (y todas las animaciones) de marcos, decoraciones, fondos y
 * títulos se escribe A MANO aquí. El catálogo (src/config/cosmetics.js) solo
 * guarda el nombre de la clase: nunca llega CSS desde la BD ni desde el panel
 * de admin, porque un estilo venido de datos sería una vía de inyección.
 *
 * Añadir un cosmético = una entrada en el catálogo + un bloque en este archivo.
 *
 * Convención de clases:
 *   .cos-frame-*   marco de avatar      .cos-deco-*   decoración de avatar
 *   .cos-bg-*      fondo de tarjeta     .cos-cframe-* marco de tarjeta
 */

/* El ángulo de los degradados cónicos no es animable salvo que se declare su
   tipo. Sin soporte, los marcos giratorios simplemente se quedan quietos. */
@property --cos-angle {
  syntax: '<angle>';
  initial-value: 0deg;
  inherits: false;
}

/* ---------------------------------------------------------------------------
   Envoltorio del avatar
   Apila retrato + marco + decoración en la misma celda. Se renderiza SIEMPRE
   (lleve o no cosméticos) para que exista un único camino de render; sin nada
   equipado es un envoltorio vacío que no cambia nada de lo que ya se veía.
   --------------------------------------------------------------------------- */
.avatar-wrap {
  display: inline-grid;
  place-items: center;
  flex-shrink: 0;
  line-height: 0;
  /* Cuánto sobresale el marco. Por defecto PEGADO al retrato (su borde interior
     justo en el filo del avatar); los marcos con `gap` lo separan. */
  --cos-ring: 3px;
  --cos-deco: 20px; /* tamaño de la decoración */
}
.avatar-wrap > * {
  grid-area: 1 / 1;
}

.avatar-wrap-sm {
  --cos-deco: 15px;
}
.avatar-wrap-lg {
  --cos-deco: 32px;
}

/* Marcos con separación (config `gap: true`): el anillo se aleja del retrato. */
.avatar-wrap.cos-gap {
  --cos-ring: 7px;
}
.avatar-wrap-sm.cos-gap {
  --cos-ring: 5px;
}
.avatar-wrap-lg.cos-gap {
  --cos-ring: 10px;
}

/* La sombra dura (offset, firma de la app) debe salir del BORDE EXTERIOR: del
   marco equipado si lo hay, no del retrato de dentro. Si saliera del avatar, la
   sombra cruzaría el hueco entre avatar y marco y se vería un artefacto raro
   (peor en modo claro). Se resuelve con un pseudo del tamaño del marco que solo
   aporta la sombra; no se pone en el propio marco porque su máscara (anillo de
   degradado) recortaría el box-shadow. */
.avatar-wrap:has(.cos-frame:not([hidden]))::before {
  content: '';
  grid-area: 1 / 1;
  place-self: center;
  width: calc(100% + var(--cos-ring) * 2);
  height: calc(100% + var(--cos-ring) * 2);
  border-radius: calc(var(--radius-sm) + var(--cos-ring));
  transform: rotate(-3deg);
  box-shadow: var(--shadow-ink-sm);
  pointer-events: none;
}
/* Con marco equipado, el retrato ya no proyecta su propia sombra ni (por
   defecto) muestra su borde. Se quita el ANCHO del borde, no solo el color: un
   borde transparente de 2px seguiría dejando un anillo de fondo visible entre el
   retrato y el marco (el "pixel blanco"). Con box-sizing: border-box la caja no
   cambia de tamaño, el retrato solo rellena hasta el marco. */
.avatar-wrap:has(.cos-frame:not([hidden])) .avatar {
  box-shadow: none;
  border-width: 0;
}
/* ...salvo los marcos que piden conservar el borde interior (config
   `innerBorder: true`), como Tinta. */
.avatar-wrap.cos-inner:has(.cos-frame:not([hidden])) .avatar {
  border-width: 2px;
  border-color: var(--text);
}
/* La sombra del marco acompaña el enderezado del avatar editable al hover. */
.avatar-upload:hover .avatar-wrap::before {
  transform: rotate(0deg) scale(1.03);
}

/* ---------------------------------------------------------------------------
   Marcos de avatar
   El marco rodea al retrato y acompaña su giro (-3deg, ver avatar.css).
   --------------------------------------------------------------------------- */
.cos-frame {
  width: calc(100% + var(--cos-ring) * 2);
  height: calc(100% + var(--cos-ring) * 2);
  /* Radio de un contorno concéntrico: el de dentro (avatar, --radius-sm) MÁS la
     separación. Con el mismo radio que el avatar el marco se vería más cuadrado
     que el retrato que envuelve. */
  border-radius: calc(var(--radius-sm) + var(--cos-ring));
  transform: rotate(-3deg);
  pointer-events: none;
  transition: transform 240ms var(--ease-spring);
}
/* Al pasar por encima del avatar editable, el marco sigue al retrato. */
.avatar-upload:hover .cos-frame {
  transform: rotate(0deg) scale(1.03);
}

/* Truco del anillo: el degradado se pinta en toda la caja y la máscara recorta
   el interior, dejando solo el borde. Sirve para cualquier degradado, cosa que
   `border-color` no permite. */
.cos-frame-cobre,
.cos-frame-jade,
.cos-frame-brasa,
.cos-frame-neon,
.cos-frame-aurora,
.cos-frame-vortice {
  padding: 3px;
  -webkit-mask:
    linear-gradient(#000 0 0) content-box,
    linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
  mask-composite: exclude;
}

/* Tinta (común): trazo a rayas, como un recorte de cuaderno. */
.cos-frame-tinta {
  border: 2px dashed var(--text);
  opacity: 0.75;
}

/* Bruma (común): un halo tenue de niebla, sin animación. Como tinta, va por
   `border` (no entra en el grupo de máscara) para no depender de un degradado. */
.cos-frame-bruma {
  border: 3px solid color-mix(in srgb, var(--text) 30%, transparent);
  box-shadow: 0 0 8px color-mix(in srgb, var(--text) 18%, transparent);
}

/* Cobre (poco común): metal cálido con brillo estático. */
.cos-frame-cobre {
  background: linear-gradient(135deg, #8a4a26, #d98a4f 40%, #f3c89a 55%, #8a4a26);
}

/* Jade (poco común): piedra pulida de vetas verdes, brillo estático como cobre. */
.cos-frame-jade {
  background: linear-gradient(135deg, #1f6b4a, #4fce8f 45%, #cfeede 55%, #1f6b4a);
}

/* Brasa (raro): ascua que respira. */
.cos-frame-brasa {
  background: linear-gradient(160deg, #ff8a3d, #ff3d3d 55%, #7a1e0c);
  animation: cos-pulse 2.4s var(--ease) infinite;
}

/* Neón (muy raro): un barrido de luz que da vueltas al retrato. */
.cos-frame-neon {
  background: conic-gradient(
    from var(--cos-angle),
    var(--brand) 0deg,
    var(--cyan) 90deg,
    #ff5fa8 180deg,
    var(--brand) 270deg,
    var(--brand) 360deg
  );
  animation: cos-spin 3.5s linear infinite;
}

/* Aurora (legendaria): el cónico gira y además late. */
.cos-frame-aurora {
  padding: 4px;
  background: conic-gradient(
    from var(--cos-angle),
    #4fce8f,
    #39c6d6,
    #8f7bf2,
    #ffcf66,
    #4fce8f
  );
  filter: saturate(1.2);
  animation: cos-spin 6s linear infinite, cos-glow 3s var(--ease) infinite;
}

/* Vórtice (muy raro, exclusivo del pase): remolino oscuro con filo violeta que
   gira lento. Reutiliza cos-spin. */
.cos-frame-vortice {
  padding: 4px;
  background: conic-gradient(
    from var(--cos-angle),
    #1b1030,
    #8f7bf2 25%,
    #1b1030 50%,
    #39c6d6 75%,
    #1b1030
  );
  filter: saturate(1.15);
  animation: cos-spin 5s linear infinite;
}

@keyframes cos-spin {
  to {
    --cos-angle: 360deg;
  }
}
@keyframes cos-pulse {
  0%,
  100% {
    filter: brightness(1);
  }
  50% {
    filter: brightness(1.45);
  }
}
@keyframes cos-glow {
  0%,
  100% {
    box-shadow: 0 0 0 rgba(143, 123, 242, 0);
  }
  50% {
    box-shadow: 0 0 14px rgba(143, 123, 242, 0.75);
  }
}

/* ---------------------------------------------------------------------------
   Decoraciones de avatar
   Un glifo posado en la esquina superior derecha del retrato.
   --------------------------------------------------------------------------- */
.cos-deco {
  place-self: start end;
  font-size: var(--cos-deco);
  line-height: 1;
  pointer-events: none;
  translate: 32% -30%;
  filter: drop-shadow(1px 1px 0 rgba(9, 13, 24, 0.55));
}

.cos-deco-hoja {
  rotate: -12deg;
  animation: cos-sway 3.6s var(--ease) infinite;
}
.cos-deco-gota {
  animation: cos-float 3.2s var(--ease) infinite;
}
.cos-deco-chispa {
  animation: cos-twinkle 1.8s var(--ease) infinite;
}
.cos-deco-llama {
  animation: cos-flicker 1.1s steps(3, end) infinite;
}
.cos-deco-rayo {
  rotate: 6deg;
  animation: cos-twinkle 1.3s steps(2, end) infinite;
}
.cos-deco-corona {
  rotate: 12deg;
  animation: cos-float 2.6s var(--ease) infinite;
}
/* Cometa (exclusivo del pase): flota con una estela suave. Reutiliza cos-float. */
.cos-deco-cometa {
  rotate: -18deg;
  filter: drop-shadow(1px 1px 0 rgba(9, 13, 24, 0.55)) drop-shadow(-3px 2px 4px rgba(79, 140, 255, 0.6));
  animation: cos-float 2.2s var(--ease) infinite;
}

@keyframes cos-sway {
  0%,
  100% {
    rotate: -12deg;
  }
  50% {
    rotate: 4deg;
  }
}
@keyframes cos-twinkle {
  0%,
  100% {
    opacity: 1;
    scale: 1;
  }
  50% {
    opacity: 0.55;
    scale: 1.18;
  }
}
@keyframes cos-flicker {
  0%,
  100% {
    scale: 1 1;
  }
  33% {
    scale: 1.08 0.94;
  }
  66% {
    scale: 0.94 1.08;
  }
}
@keyframes cos-float {
  0%,
  100% {
    translate: 32% -30%;
  }
  50% {
    translate: 32% -44%;
  }
}

/* ---------------------------------------------------------------------------
   Tarjeta de perfil: fondo y marco
   `isolation` abre un contexto de apilado propio para que el fondo (z-index:-1)
   quede por encima del color de la card pero por debajo de su contenido, sin
   tener que posicionar nada más.
   --------------------------------------------------------------------------- */
.cos-card {
  position: relative;
  isolation: isolate;
}
.cos-card::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  border-radius: inherit;
  pointer-events: none;
}
.cos-card::after {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  pointer-events: none;
}

/* El marco trae su propio contorno: quitamos el borde base de la .card. Se quita
   el ANCHO, no solo el color: el marco (::after) se alinea al padding-box, así
   que un borde de 2px lo metería hacia dentro y dejaría un pequeño espacio con
   el filo de la tarjeta (de donde sale la sombra). Con border-box el layout no
   se mueve. */
.cos-card-bare {
  border-width: 0;
}

/* Separación del marco de tarjeta (config `gap: true`): el marco se mete hacia
   dentro, dejando aire con el borde de la card. Sin gap va pegado al borde (el
   ::after por defecto está en inset: 0), justo donde nace la sombra. */
.cos-cframe-gap::after {
  inset: 6px;
  border-radius: var(--radius);
}

/* ---------------------------------------------------------------------------
   Tinta de la tarjeta (config `ink` del fondo)
   Un fondo OPACO ya no sigue al tema: un cielo nocturno es oscuro también en
   modo claro, y la tinta oscura del tema encima sería ilegible. Por eso el fondo
   declara su tono y la tarjeta redefine sus tokens de texto SOLO en su subárbol.
   Es la misma idea que ya usa la app: los componentes consumen tokens semánticos,
   así que basta redefinirlos aquí para que todo dentro se recoloree.

   Hay que reponer también `color`, porque el color heredado del body ya está
   resuelto: redefinir --text no lo recalcularía por sí solo.
   --------------------------------------------------------------------------- */
.cos-ink-dark {
  --text: #f2f3f7;
  --text-muted: #a6adc2;
  --text-faint: #6d7590;
  --border: rgba(246, 244, 237, 0.12);
  --border-strong: rgba(246, 244, 237, 0.38);
  color: var(--text);
}
.cos-ink-light {
  --text: #1a2233;
  --text-muted: #59617a;
  --text-faint: #969db4;
  --border: rgba(19, 26, 41, 0.14);
  --border-strong: rgba(19, 26, 41, 0.5);
  color: var(--text);
}

/* ---- Fondos (pintan ::before) ---- */
.cos-bg-cuadricula::before {
  background-image:
    linear-gradient(var(--border) 1px, transparent 1px),
    linear-gradient(90deg, var(--border) 1px, transparent 1px);
  background-size: 18px 18px;
  opacity: 0.9;
}

.cos-bg-papel::before {
  background-color: color-mix(in srgb, var(--paper) 12%, transparent);
  background-image: repeating-linear-gradient(
    -38deg,
    rgba(120, 90, 50, 0.09) 0 2px,
    transparent 2px 9px
  );
}

/* Crepúsculo: OPACO a propósito (ver `ink` en el catálogo). Se ve igual en tema
   claro y oscuro, y siempre lleva tinta clara encima. */
.cos-bg-crepusculo::before {
  background: linear-gradient(160deg, #93502c, #4c3059 52%, #1f1b3a);
}

.cos-bg-vetas::before {
  background:
    repeating-linear-gradient(
      115deg,
      color-mix(in srgb, var(--brand) 16%, transparent) 0 3px,
      transparent 3px 22px
    ),
    radial-gradient(120% 80% at 100% 0%, var(--brand-soft), transparent 60%);
}

/* Olas (poco común): oleaje suave que sigue al tema (translúcido, sin `ink`). */
.cos-bg-olas::before {
  background:
    repeating-linear-gradient(
      -20deg,
      color-mix(in srgb, var(--brand) 12%, transparent) 0 2px,
      transparent 2px 14px
    ),
    radial-gradient(120% 90% at 0% 100%, var(--brand-soft), transparent 60%);
}

/* Circuito (raro): rejilla con nodos en los cruces, como una placa. Translúcido:
   sigue al tema vía --border y --brand, sin necesidad de `ink`. */
.cos-bg-circuito::before {
  background-image:
    linear-gradient(var(--border) 1px, transparent 1px),
    linear-gradient(90deg, var(--border) 1px, transparent 1px),
    radial-gradient(circle, color-mix(in srgb, var(--brand) 45%, transparent) 2px, transparent 2.5px);
  background-size: 26px 26px;
  opacity: 0.85;
}

/* Nocturno: un cielo con estrellas que parpadean muy despacio. OPACO a propósito
   (ver `ink` en el catálogo): un cielo nocturno es oscuro también en tema claro. */
.cos-bg-nocturno::before {
  background-color: #0d1226;
  background-image:
    radial-gradient(1.5px 1.5px at 12% 24%, #fff, transparent),
    radial-gradient(1.5px 1.5px at 78% 16%, #cfe2ff, transparent),
    radial-gradient(1.5px 1.5px at 42% 72%, #fff, transparent),
    radial-gradient(1.5px 1.5px at 88% 64%, #ffe9a8, transparent),
    radial-gradient(1.5px 1.5px at 28% 48%, #fff, transparent),
    radial-gradient(130% 90% at 20% 0%, rgba(143, 123, 242, 0.35), transparent 65%);
  animation: cos-stars 4.5s var(--ease) infinite;
}
/* El titileo va por brillo, NO por opacidad: bajar la opacidad dejaría asomar la
   superficie de la tarjeta y en tema claro el fondo se lavaría, perdiendo el
   contraste que la tinta clara da por hecho. */
@keyframes cos-stars {
  0%,
  100% {
    filter: brightness(1);
  }
  50% {
    filter: brightness(1.3);
  }
}

/* ---- Marcos de tarjeta (pintan ::after) ----
   La separación (inset) la aporta `.cos-cframe-gap`; aquí solo el estilo. */
/* Línea (común): un filo fino y sólido, la versión sobria de costura. */
.cos-cframe-linea::after {
  border: 2px solid var(--border-strong);
}

.cos-cframe-costura::after {
  border: 2px dashed var(--border-strong);
}

/* Runas (raro): filo de degradado turquesa recortado con máscara, como dorado
   pero frío y sin animación. */
.cos-cframe-runas::after {
  border: 2px solid transparent;
  background: linear-gradient(135deg, #2a6f8f, #6fd0e6 50%, #2a6f8f) border-box;
  -webkit-mask:
    linear-gradient(#000 0 0) content-box,
    linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
  mask-composite: exclude;
}

.cos-cframe-dorado::after {
  border: 3px solid transparent;
  background: linear-gradient(135deg, #8a6a1f, #ffd97a 45%, #fff3cf 52%, #8a6a1f) border-box;
  -webkit-mask:
    linear-gradient(#000 0 0) content-box,
    linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
  mask-composite: exclude;
}

.cos-cframe-prisma::after {
  padding: 3px;
  background: conic-gradient(
    from var(--cos-angle),
    #ff5fa8,
    #ffcf66,
    #4fce8f,
    #39c6d6,
    #8f7bf2,
    #ff5fa8
  );
  -webkit-mask:
    linear-gradient(#000 0 0) content-box,
    linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
  mask-composite: exclude;
  animation: cos-spin 8s linear infinite;
}

/* ---------------------------------------------------------------------------
   Título y lema (bajo el nombre, en la tarjeta de perfil)
   --------------------------------------------------------------------------- */
.cos-title {
  display: inline-block;
  max-width: 100%;
  font-family: var(--font-display);
  font-style: italic;
  /* Algo más pequeño que el texto base: el sesgo recorta un pelín las esquinas,
     así que se le quita presión de tamaño. */
  font-size: 0.82rem;
  line-height: 1.25; /* aire vertical para la itálica display, que no se corte arriba/abajo */
  letter-spacing: 0.03em;
  text-transform: uppercase;
  /* Padding lateral generoso: el sesgo empuja el texto hacia las esquinas y sin
     holgura se sale del recuadro de color (más aún con una sola palabra). */
  padding: 3px 16px;
  /* Margen horizontal = holgura para las esquinas diagonales que sobresalen del
     recuadro, para que ningún borde de al lado las recorte. */
  margin-inline: 3px;
  color: var(--on-brand);
  background: var(--rarity-color, var(--brand));
  border: 2px solid var(--text);
  box-shadow: var(--shadow-ink-sm);
  transform: skew(var(--skew));
  white-space: nowrap; /* un título nunca parte en dos líneas */
}
.cos-title span {
  display: inline-block;
  transform: skew(calc(var(--skew) * -1));
  white-space: nowrap;
}

/* (El lema se retiró: la bio ya cumple esa función.) */

/* Móvil muy estrecho: en vez de partir o desbordar, el título encoge entero. */
@media (max-width: 375px) {
  .cos-title {
    font-size: var(--fs-xs);
    padding: 2px 12px;
    letter-spacing: 0.02em;
  }
}

/* ---------------------------------------------------------------------------
   Nada de esto merece marear a nadie: sin movimiento, los cosméticos siguen
   viéndose (color y forma), solo se quedan quietos.
   --------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  .cos-frame,
  .cos-deco,
  .cos-card::before,
  .cos-card::after {
    animation: none !important;
  }
}
