/* ============================================================
   IDENTITY — la página de perfil  ·  v2

   REGLA CENTRAL: no existe una tarjeta obligatoria.
   El contenido vive sobre el fondo. La "superficie" (la caja) es
   una opción más, con cinco estilos y opacidad/blur/borde/glow
   controlables. Un perfil válido puede no tener ni una caja.

   Consume tokens --p-* (los pone themes.css) y --u-* (los pone
   el usuario desde el editor).
   ============================================================ */

.pf{
  position:relative;
  min-height:100vh;min-height:100dvh;
  background:var(--p-bg);
  color:var(--p-text);
  font-family:var(--u-font, var(--p-fb));
  letter-spacing:var(--p-track);
  overflow-x:hidden;
  isolation:isolate;
}

/* ============================================================
   CAPAS DE FONDO
   media > opacidad > overlay > blur > ruido > viñeta > partículas
   ============================================================ */

.pf-bg{
  position:absolute; inset:0;
  z-index:-5;
  background:radial-gradient(120% 90% at 50% 0%, var(--p-bg2), var(--p-bg) 70%);
  background-size:cover;
  background-position:center;
}
.pf-bg--media{ background:var(--p-bg); }
.pf-bg video,
.pf-bg img.pf-bgimg{
  position:absolute; inset:0;
  width:100%; height:100%;
  object-fit:cover;
  opacity:var(--u-bg-op, 1);
}

.pf-veil{
  position:absolute; inset:0;
  z-index:-4;
  pointer-events:none;
  background:rgba(0,0,0,var(--p-dim-amt,.45));
  backdrop-filter:blur(var(--p-blur,0px));
  -webkit-backdrop-filter:blur(var(--p-blur,0px));
}

.pf-noise{
  position:absolute; inset:0;
  z-index:-3;
  pointer-events:none;
  opacity:var(--p-noise,0);
  mix-blend-mode:overlay;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.8' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='.6'/%3E%3C/svg%3E");
}

/* viñeta: oscurece los bordes y empuja la mirada al centro */
.pf-vig{
  position:absolute; inset:0;
  z-index:-2;
  pointer-events:none;
  opacity:var(--u-vig, 0);
  background:radial-gradient(ellipse at center,
    transparent 38%, rgba(0,0,0,.55) 78%, rgba(0,0,0,.85) 100%);
}

.pf-particles{
  position:absolute; inset:0;
  z-index:-1;
  pointer-events:none;
}

/* con fondo fijo las capas acompañan al scroll */
.pf[data-bgfixed="on"] .pf-bg,
.pf[data-bgfixed="on"] .pf-veil,
.pf[data-bgfixed="on"] .pf-noise,
.pf[data-bgfixed="on"] .pf-vig,
.pf[data-bgfixed="on"] .pf-particles{ position:fixed; }

/* ============================================================
   PUERTA DE ENTRADA (desbloquea el audio del navegador)
   ============================================================ */
.pf-gate{
  position:fixed; inset:0;
  z-index:800;
  display:grid; place-items:center;
  background:rgba(4,5,7,.86);
  backdrop-filter:blur(14px);
  -webkit-backdrop-filter:blur(14px);
  cursor:pointer;
  animation:gateIn .5s var(--ease-out) both;
}
.pf-gate.is-out{ animation:gateOut .55s var(--ease-out) forwards; }
@keyframes gateIn{ from{opacity:0} }
@keyframes gateOut{ to{ opacity:0; visibility:hidden; } }
.pf-gate span{
  font-family:var(--u-fontd, var(--u-font, var(--p-fd)));
  font-size:clamp(22px,4.5vw,42px);
  font-weight:700;
  letter-spacing:-.04em;
  color:#fff;
  text-transform:var(--p-uppercase,none);
  animation:gatePulse 2.4s var(--ease) infinite;
}
.pf-gate small{
  display:block; margin-top:12px; text-align:center;
  font-family:var(--p-fm); font-size:10.5px; letter-spacing:.18em;
  color:rgba(255,255,255,.45); text-transform:uppercase;
}
@keyframes gatePulse{ 50%{ opacity:.45; transform:scale(.985); } }

/* ============================================================
   HÉROE — la primera pantalla es el perfil, a pantalla completa
   ============================================================ */
.pf-hero{
  position:relative;
  min-height:100vh;min-height:100dvh;
  display:grid;
  align-items:center;
  padding:clamp(72px,10vh,120px) clamp(16px,5vw,48px) clamp(56px,8vh,96px);
}
/* El bloque SIEMPRE va centrado en la pantalla. La alineacion es
   del contenido, no de la posicion: pegarlo al borde por elegir
   "izquierda" era un error, no una funcion. Quien de verdad lo
   quiera a un lado usa `stackPos`. */
.pf-hero{ justify-items:center; }
.pf[data-pos="left"]  .pf-hero{ justify-items:start; }
.pf[data-pos="right"] .pf-hero{ justify-items:end; }

.pf[data-align="center"] .pf-stack{ text-align:center; align-items:center; }
.pf[data-align="left"]   .pf-stack{ text-align:left;   align-items:flex-start; }
.pf[data-align="right"]  .pf-stack{ text-align:right;  align-items:flex-end; }

/* Alineacion horizontal DENTRO de una pieza que es una fila: redes,
   badges y campos. El stack es una columna, asi que solo declara
   align-items y nunca justify-content. Esas filas usaban
   justify-content:inherit, que tomaba del stack un valor que nadie
   fija: resolvia a la izquierda aunque el perfil estuviera centrado.

   Una variable en lugar de tres reglas por elemento, para que
   ninguna pelea de especificidad la pueda pisar. */
.pf{
  --u-just:flex-start;
  /* de que color es el halo. Vive en la raiz del perfil para que se
     herede hacia dentro y una pieza pueda redefinirlo solo para lo
     suyo, igual que hace con el color. */
  --halo:var(--p-primary);
}
.pf[data-align="center"]{ --u-just:center; }
.pf[data-align="right"]{ --u-just:flex-end; }

/* ============================================================
   LA PILA DE BLOQUES
   `.pf-card` conserva el nombre para que los temas puedan seguir
   vistiéndola (win98, minecraft, cyberpunk…), pero por defecto
   es completamente transparente.
   ============================================================ */
.pf-stack{
  position:relative;
  display:flex;
  flex-direction:column;
  gap:var(--u-gap, 16px);
  width:100%;
  max-width:var(--u-width, 460px);
  border-radius:var(--u-radius, 0px);
  transform-style:preserve-3d;
  animation:cardIn .8s var(--ease-out) both;
}
@keyframes cardIn{ from{ opacity:0; transform:translateY(18px); } }

/* --- estilos de superficie ------------------------------- */
.pf[data-surface="none"] .pf-stack{
  background:transparent; border:0; box-shadow:none;
  backdrop-filter:none; -webkit-backdrop-filter:none;
  padding:0;
}
.pf[data-surface="solid"] .pf-stack{
  background:color-mix(in srgb, var(--p-bg2) calc(var(--u-op,92) * 1%), transparent);
  border:1px solid color-mix(in srgb, var(--p-line) calc(var(--u-bd,70) * 1%), transparent);
  box-shadow:var(--p-shadow);
}
.pf[data-surface="glass"] .pf-stack{
  background:color-mix(in srgb, #ffffff calc(var(--u-op,9) * 1%), transparent);
  border:1px solid color-mix(in srgb, #ffffff calc(var(--u-bd,18) * 1%), transparent);
  backdrop-filter:blur(var(--u-sblur,22px)) saturate(150%);
  -webkit-backdrop-filter:blur(var(--u-sblur,22px)) saturate(150%);
  box-shadow:0 30px 80px -50px rgba(0,0,0,.9);
}
.pf[data-surface="outline"] .pf-stack{
  background:transparent;
  border:1px solid color-mix(in srgb, var(--p-primary) calc(var(--u-bd,45) * 1%), transparent);
}
.pf[data-surface="glow"] .pf-stack{
  background:color-mix(in srgb, var(--p-bg2) calc(var(--u-op,55) * 1%), transparent);
  border:1px solid color-mix(in srgb, var(--p-primary) calc(var(--u-bd,40) * 1%), transparent);
  box-shadow:0 0 calc(var(--u-glow,40) * 1.4px) calc(var(--u-glow,40) * -0.5px) var(--p-primary),
             inset 0 0 60px -40px var(--p-primary);
}
/* relleno sólo cuando SÍ hay caja */
.pf:not([data-surface="none"]) .pf-stack{ padding:var(--u-pad, clamp(22px,4vw,34px)); }

/* inclinación 3D opcional */
.pf[data-tilt="on"] .pf-stack{
  transform:perspective(900px) rotateX(var(--rx,0deg)) rotateY(var(--ry,0deg));
  transition:transform .12s linear;
}
.pf[data-tilt="on"] .pf-stack.is-resting{ transition:transform .7s var(--ease-out); }

.pf-card__sheen{
  position:absolute; inset:0;
  border-radius:inherit;
  pointer-events:none;
  opacity:0;
  background:radial-gradient(320px circle at var(--mx,50%) var(--my,50%),
              rgba(255,255,255,.13), transparent 62%);
  transition:opacity .35s var(--ease);
}
.pf[data-tilt="on"] .pf-stack:hover .pf-card__sheen{ opacity:1; }
.pf[data-surface="none"] .pf-card__sheen{ display:none; }

/* ============================================================
   BLOQUES
   ============================================================ */

/* --- avatar --- */
.pf-avatar{
  position:relative;
  width:var(--u-av, 112px);
  aspect-ratio:1;
  display:grid; place-items:center;
  overflow:hidden;
  background:var(--p-surface-2);
  font-family:var(--u-fontd, var(--u-font, var(--p-fd)));
  font-weight:700;
  font-size:calc(var(--u-av, 112px) * .34);
  color:var(--p-primary);
  flex:none;
}
.pf-avatar img{ width:100%; height:100%; object-fit:cover; }

.pf[data-avshape="circle"]  .pf-avatar{ border-radius:50%; }
.pf[data-avshape="rounded"] .pf-avatar{ border-radius:24%; }
.pf[data-avshape="square"]  .pf-avatar{ border-radius:0; }
/* sin máscara: la imagen flota, sin fondo ni recorte */
.pf[data-avshape="bare"] .pf-avatar{
  border-radius:0; background:transparent; overflow:visible;
}
.pf[data-avshape="bare"] .pf-avatar img{ object-fit:contain; }

.pf[data-avborder="on"] .pf-avatar{ border:2px solid var(--p-primary); }
.pf[data-avglow="on"]   .pf-avatar{ box-shadow:var(--p-glow); }

.pf-avatar[data-fx="pulse"]{ animation:avPulse 2.6s var(--ease) infinite; }
@keyframes avPulse{ 50%{ transform:scale(1.04); } }
.pf-avatar[data-fx="ring"]::after{
  content:""; position:absolute; inset:-9px;
  border-radius:inherit;
  border:2px dashed var(--p-accent);
  animation:avSpin 9s linear infinite;
}
@keyframes avSpin{ to{ transform:rotate(360deg); } }
.pf-avatar[data-fx="float"]{ animation:avFloat 4.5s var(--ease) infinite; }
@keyframes avFloat{ 50%{ transform:translateY(-8px); } }
.pf-avatar[data-fx="glitch"]{ animation:avGlitch 4.5s steps(1) infinite; }
@keyframes avGlitch{
  0%,86%,100%{ transform:translate(0,0); filter:none; }
  88%{ transform:translate(-3px,2px); filter:hue-rotate(80deg) saturate(2); }
  90%{ transform:translate(3px,-2px); filter:hue-rotate(-60deg); }
  92%{ transform:translate(-2px,-1px); }
}

/* --- identidad --- */
.pf-idblock{ display:flex; flex-direction:column; gap:4px; align-items:inherit; width:100%; }

/* Nombre, @usuario, oficio y fecha son piezas independientes: se
   pueden mover y vestir por separado. Pero cuando van SEGUIDAS se
   leen como una unidad, y entre ellas el ritmo es de 4px, no el
   hueco del stack. Sin esto, partir el bloque de identidad
   separaria el @usuario del nombre en todos los perfiles ya
   guardados. En modo libre manda la rejilla, no esta regla. */
.pf:not([data-layout="free"]) .pf-stack > .pf-idblock + .pf-idblock{
  margin-top:calc(4px - var(--u-gap, 16px));
}

.pf-name{
  font-family:var(--u-fontd, var(--u-font, var(--p-fd)));
  /* peso y caja son del usuario si los pone, del tema si no.
     Sin esto una direccion editorial no puede tener un nombre fino
     ni una gaming un nombre en mayusculas: el peso estaba fijo. */
  font-weight:var(--u-nameW, 700);
  font-size:var(--u-name, clamp(28px,5.6vw,44px));
  line-height:1.08;
  letter-spacing:var(--p-track);
  text-transform:var(--u-nameCase, var(--p-uppercase, none));
  display:inline-flex; align-items:center; gap:9px;
  margin:0;
}
.pf-verified{ width:19px; height:19px; flex:none; color:var(--p-primary); }

.pf-handle{ font-family:var(--p-fm); font-size:12.5px; color:var(--p-dim); }
.pf-title{ font-size:14.5px; color:var(--p-dim); }
.pf-title b{ color:var(--p-text); font-weight:600; }
.pf-joined{ font-family:var(--p-fm); font-size:11px; color:var(--p-dim); opacity:.8; }

.pf-fields{ display:flex; flex-wrap:wrap; gap:6px; justify-content:var(--u-just, flex-start); }
.pf-field{
  display:inline-flex; align-items:center; gap:5px;
  padding:4px 9px;
  border:1px solid var(--p-line);
  border-radius:var(--p-chip-r);
  background:var(--p-surface);
  font-size:11.5px;
  color:var(--p-dim);
}
.pf-field b{
  font-weight:600; color:var(--p-text); opacity:.75;
  font-size:10.5px; text-transform:uppercase; letter-spacing:.06em;
}

/* --- estado --- */
.pf-status{
  display:inline-flex; align-items:center; gap:9px;
  padding:7px 14px 7px 11px;
  border:1px solid var(--p-line);
  border-radius:var(--p-chip-r);
  background:var(--p-surface-2);
  font-size:12.5px;
}
.pf-status__dot{
  width:9px; height:9px; border-radius:50%;
  background:var(--st,#43B581); flex:none;
  animation:stPing 2.2s var(--ease) infinite;
}
@keyframes stPing{
  0%  { box-shadow:0 0 0 0 color-mix(in srgb,var(--st,#43B581) 70%, transparent); }
  70% { box-shadow:0 0 0 9px transparent; }
  100%{ box-shadow:0 0 0 0 transparent; }
}
.pf-status__act{ color:var(--p-dim); }
.pf-status__act b{ color:var(--p-text); font-weight:600; }

/* --- widget de Discord --- */
.pf-dc{
  display:flex; align-items:center; gap:11px;
  padding:9px 14px 9px 10px;
  border:1px solid var(--p-line);
  border-radius:var(--p-chip-r);
  background:var(--p-surface-2);
  text-align:left;
  max-width:100%;
}
.pf-dc__av{
  position:relative;
  width:38px; height:38px; flex:none;
  border-radius:50%;
  display:grid; place-items:center;
  background:var(--p-surface);
  border:1px solid var(--p-line);
  font-size:16px;
}
.pf-dc__av img{ width:100%; height:100%; object-fit:cover; border-radius:50%; }
.pf-dc__dot{
  position:absolute; right:-2px; bottom:-2px;
  width:12px; height:12px; border-radius:50%;
  background:var(--st,#747F8D);
  border:2.5px solid var(--p-bg);
}
.pf-dc__u{
  display:flex; align-items:center; gap:6px;
  font-size:13.5px; font-weight:600; color:var(--p-text);
}
.pf-dc__bd{ font-size:11px; opacity:.85; }
.pf-dc__s{ display:block; font-size:11px; color:var(--p-dim); margin-top:1px; }

/* --- actividad en vivo --- */
.pf-live{ display:grid; gap:7px; width:100%; }
.pf-live__row{
  display:flex; align-items:center; gap:10px;
  padding:9px 12px;
  border-radius:var(--p-chip-r);
  background:var(--p-surface);
  border:1px solid var(--p-line);
  font-size:12.5px;
  text-align:left;
}
.pf-live__ico{ font-size:14px; flex:none; width:18px; text-align:center; }
.pf-live__txt{ flex:1; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.pf-live__meta{ font-family:var(--p-fm); font-size:10px; color:var(--p-dim); flex:none; }

/* --- bio --- */
.pf-bio{
  font-size:var(--u-bio, 14.5px);
  line-height:1.62;
  color:var(--p-dim);
  margin:0;
  max-width:46ch;
}

/* --- badges --- */
.pf-badges{ display:flex; flex-wrap:wrap; gap:7px; justify-content:var(--u-just, flex-start); }
.pf-badge{
  position:relative;
  display:inline-flex; align-items:center; gap:6px;
  padding:5px 11px 5px 8px;
  border-radius:var(--p-chip-r);
  border:1px solid var(--p-line);
  background:var(--p-surface-2);
  font-family:var(--p-fm);
  font-size:10px; font-weight:600;
  cursor:default;
  transition:transform var(--transition-fast), border-color var(--transition-fast);
}
.pf-badge:hover{ transform:translateY(-2px); border-color:var(--p-primary); }
.pf-badge i{ font-style:normal; font-size:12px; }
.pf-badges[data-style="icons"] .pf-badge{ padding:4px 6px; gap:0; border-color:transparent; background:transparent; }
.pf-badges[data-style="icons"] .pf-badge b{ display:none; }
.pf-badge[data-rare="legendary"]{
  border-color:var(--p-primary);
  box-shadow:0 0 18px -6px var(--p-primary);
}

/* --- nivel --- */
.pf-level{
  width:100%;
  padding:15px 16px;
  border:1px solid var(--p-line);
  border-radius:var(--p-chip-r);
  background:var(--p-surface);
  text-align:left;
}
.pf-level__top{
  display:flex; align-items:baseline; justify-content:space-between;
  font-family:var(--p-fm); font-size:10.5px; letter-spacing:.14em;
  text-transform:uppercase; color:var(--p-dim);
}
.pf-level__n{
  font-family:var(--u-fontd, var(--u-font, var(--p-fd)));
  font-size:26px; font-weight:700; line-height:1;
  color:var(--p-primary); letter-spacing:-.04em;
}
.pf-xp{
  margin-top:10px; height:8px; border-radius:100px;
  background:var(--p-surface-2); overflow:hidden;
  border:1px solid var(--p-line);
}
.pf-xp i{
  display:block; height:100%;
  background:linear-gradient(90deg,var(--p-primary),var(--p-accent));
  animation:fill 1.3s var(--ease-out) both;
}
.pf-level__foot{
  margin-top:7px;
  font-family:var(--p-fm); font-size:10px; color:var(--p-dim);
  display:flex; justify-content:space-between;
}

/* ============================================================
   REDES — cuatro estilos
   ============================================================ */
.pf-socials{ display:flex; flex-wrap:wrap; gap:9px; justify-content:var(--u-just, flex-start); align-items:center; }

.pf-social{
  display:grid; place-items:center;
  color:var(--p-icon, var(--p-text));
  /* el halo se hereda desde .pf para que una pieza pueda cambiarlo.
     Fijarlo AQUI, en el icono, lo hacia irrompible: la pieza definia
     su --halo y este lo volvia a poner en el acento del tema. */
  transition:transform var(--transition-normal), color var(--transition-fast),
             border-color var(--transition-fast), box-shadow var(--transition-normal),
             filter var(--transition-normal);
}
/* con el monocromo apagado manda el color de la marca... salvo que
   la pieza haya pedido su propio halo, que entonces gana ella */
.pf-socials[data-mono="off"]:not([data-halo]) .pf-social{ --halo:var(--brand, var(--p-primary)); }
.pf-social svg{ width:var(--u-ico, 20px); height:var(--u-ico, 20px); }
.pf-social__emoji{ font-size:var(--u-ico, 20px); line-height:1; }

/* icons: sin caja, sólo el glifo (el estilo de las referencias) */
.pf-socials[data-style="icons"] .pf-social{
  padding:4px; background:transparent; border:0;
}
.pf-socials[data-style="icons"] .pf-social:hover{ transform:translateY(-3px) scale(1.12); }

/* boxed: cuadrito por red */
.pf-socials[data-style="boxed"] .pf-social{
  width:42px; height:42px;
  border-radius:var(--p-chip-r);
  border:1px solid var(--p-line);
  background:var(--p-surface-2);
}
.pf-socials[data-style="boxed"] .pf-social:hover{
  transform:translateY(-4px) scale(1.05);
  border-color:var(--p-primary);
}

/* glow: halo permanente, más fuerte al pasar */
.pf-socials[data-style="glow"] .pf-social{
  width:42px; height:42px;
  border-radius:50%;
  border:1px solid color-mix(in srgb, var(--p-primary) 40%, transparent);
  background:var(--p-surface-2);
  box-shadow:0 0 18px -8px var(--p-primary);
}
.pf-socials[data-style="glow"] .pf-social:hover{
  transform:translateY(-4px);
  box-shadow:0 0 30px -6px var(--p-primary);
}

/* text: el nombre de la red, sin icono */
.pf-socials[data-style="text"]{ gap:14px; }
.pf-socials[data-style="text"] .pf-social{
  padding:2px 0;
  font-size:13.5px; font-weight:500;
  border:0; background:transparent;
}
.pf-socials[data-style="text"] .pf-social svg,
.pf-socials[data-style="text"] .pf-social .pf-social__emoji{ display:none; }
.pf-socials[data-style="text"] .pf-social::after{ content:attr(data-label); }
.pf-socials[data-style="text"] .pf-social:hover{ color:var(--p-primary); }

/* color de marca cuando el monocromo está apagado */
.pf-socials[data-mono="off"] .pf-social{ color:var(--brand, var(--p-text)); }
.pf-socials[data-mono="off"] .pf-social:hover{ border-color:var(--brand, var(--p-primary)); }
.pf-socials[data-mono="off"]:is([data-style="boxed"], [data-style="glow"]) .pf-social:hover{
  box-shadow:0 0 26px -8px var(--halo);
}

/* ============================================================
   HALO QUE SIGUE LA SILUETA
   box-shadow dibuja la sombra del BORDE de la caja. Donde hay caja
   —boxed (42px, radio 12) y glow (42px, círculo)— eso es justo lo
   que se quiere: el halo rodea la caja.

   En "icons" NO hay caja: fondo transparente, borde 0, radio 0. Ahí
   el box-shadow pintaba un rectángulo de 28x28 flotando detrás de un
   icono redondo, y se notaba que era la sombra de una caja invisible.

   drop-shadow sigue el canal alfa, o sea el dibujo de verdad. Dos
   capas: una corta y densa que define el contorno, otra larga y
   suave que da el resplandor.
   ============================================================ */
/* .pf delante a proposito: sin el, esta regla empata en
   especificidad con `.pf.glow-social .pf-social` (0,3,0) y pierde
   por orden de aparicion, que es justo lo que pasaba. */
.pf :is(.pf-socials[data-style="icons"], .pf-socials[data-style="text"]) .pf-social{
  box-shadow:none;
}

.pf.glow-social .pf-socials[data-style="icons"] .pf-social,
.pf-socials[data-style="icons"][data-mono="off"] .pf-social:hover{
  filter:drop-shadow(0 0 4px color-mix(in srgb, var(--halo) 85%, transparent))
         drop-shadow(0 0 11px color-mix(in srgb, var(--halo) 45%, transparent));
}
.pf.glow-social .pf-socials[data-style="icons"] .pf-social:hover{
  filter:drop-shadow(0 0 6px color-mix(in srgb, var(--halo) 95%, transparent))
         drop-shadow(0 0 18px color-mix(in srgb, var(--halo) 60%, transparent));
}

/* en "text" no hay icono que iluminar: el halo va en las letras */
.pf.glow-social .pf-socials[data-style="text"] .pf-social{
  text-shadow:0 0 14px color-mix(in srgb, var(--halo) 60%, transparent);
}

/* ============================================================
   ENLACES
   ============================================================ */
.pf-links{ display:grid; gap:9px; width:100%; }
.pf-link{
  position:relative;
  display:flex; align-items:center; gap:12px;
  padding:13px 15px;
  border:1px solid var(--p-line);
  border-radius:var(--p-chip-r);
  background:var(--p-surface);
  overflow:hidden;
  text-align:left;
  transition:transform var(--transition-normal), border-color var(--transition-fast),
             background var(--transition-fast);
}
.pf-link:hover{ transform:translateX(4px); border-color:var(--p-primary); background:var(--p-surface-2); }
.pf-link::before{
  content:""; position:absolute; left:0; top:0; bottom:0; width:3px;
  background:var(--p-primary);
  transform:scaleY(0); transform-origin:bottom;
  transition:transform .28s var(--ease-out);
}
.pf-link:hover::before{ transform:scaleY(1); }
.pf-link__ico{ font-size:17px; flex:none; width:22px; text-align:center; }
.pf-link__t{ font-weight:600; font-size:14px; }
.pf-link__d{ font-size:11.5px; color:var(--p-dim); margin-top:1px; }
.pf-link__arrow{ margin-left:auto; color:var(--p-dim); font-size:14px; transition:transform var(--transition-normal); }
.pf-link:hover .pf-link__arrow{ transform:translateX(3px); color:var(--p-primary); }

.pf-link--minimal{
  background:transparent; border-color:transparent;
  padding-inline:0; justify-content:center;
}
.pf-link--minimal:hover{ background:transparent; transform:none; color:var(--p-primary); }
.pf-link--minimal::before{ display:none; }

.pf-link--card{ flex-direction:column; align-items:stretch; gap:4px; padding:16px; }
.pf-link--card .pf-link__arrow{ position:absolute; right:16px; bottom:14px; margin-left:0; }
.pf-link--card .pf-link__ico{ text-align:left; width:auto; margin-bottom:2px; }

.pf-link--featured{
  flex-direction:column; align-items:stretch;
  padding:0; overflow:hidden; min-height:132px;
}
.pf-link--featured .pf-link__cover{
  height:96px;
  background-size:cover; background-position:center;
  background-color:var(--p-surface-2);
  display:grid; place-items:center; font-size:34px;
}
.pf-link--featured .pf-link__body{ display:flex; align-items:center; gap:12px; padding:13px 15px; }
.pf-link--featured .pf-link__arrow{ margin-left:auto; }
.pf-link--featured::before{ display:none; }

/* ============================================================
   MÚSICA — cuatro estilos
   ============================================================ */
.pf-music{
  display:flex; align-items:center; gap:13px;
  width:100%;
  padding:11px 14px;
  border:1px solid var(--p-line);
  border-radius:var(--p-chip-r);
  background:var(--p-surface);
  text-align:left;
}
.pf-music__cover{
  width:42px; height:42px; border-radius:8px; flex:none;
  background:var(--p-surface-2);
  display:grid; place-items:center; font-size:19px;
  overflow:hidden;
}
.pf-music__cover img{ width:100%; height:100%; object-fit:cover; }
/* el titulo y el artista comparten una caja que en un reproductor
   estrecho se queda sin sitio. Sus reglas ya pedian puntos
   suspensivos, pero son elementos en linea y ahi text-overflow no
   se aplica: el texto se derramaba sobre los controles
   (scrollWidth 127 dentro de 16px). El recorte va en la caja. */
.pf-music__meta{ flex:1; overflow:hidden; white-space:nowrap; text-overflow:ellipsis; }
.pf-music__t{ font-size:13px; font-weight:600; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.pf-music__a{ font-size:11px; color:var(--p-dim); overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.pf-music__viz{ display:flex; align-items:flex-end; gap:2.5px; height:22px; flex:none; }
.pf-music__viz i{
  width:3px; border-radius:2px; background:var(--p-primary);
  animation:viz 1s var(--ease) infinite alternate;
}
.pf-music__viz i:nth-child(2){ animation-delay:.14s }
.pf-music__viz i:nth-child(3){ animation-delay:.28s }
.pf-music__viz i:nth-child(4){ animation-delay:.42s }
.pf-music__viz i:nth-child(5){ animation-delay:.56s }
@keyframes viz{ from{ height:3px; opacity:.5 } to{ height:20px; opacity:1 } }
.pf-music.is-paused .pf-music__viz i{ animation-play-state:paused; height:4px; }
.pf-music__btn{
  width:34px; height:34px; flex:none;
  border-radius:50%; border:1px solid var(--p-line);
  background:var(--p-surface-2); color:var(--p-text);
  display:grid; place-items:center; cursor:pointer;
  transition:transform var(--transition-fast), border-color var(--transition-fast);
}
.pf-music__btn:hover{ transform:scale(1.09); border-color:var(--p-primary); }

.pf-music__bar{
  flex:1; height:3px; border-radius:100px;
  background:var(--p-surface-2); overflow:hidden;
  min-width:60px;
}
.pf-music__bar i{ display:block; height:100%; width:var(--u-prog,7%); background:var(--p-primary); }
.pf-music__time{ font-family:var(--p-fm); font-size:10px; color:var(--p-dim); flex:none; }

/* minimal: una sola línea */
.pf-music[data-style="minimal"]{
  border:0; background:transparent; padding:0;
  gap:8px; width:auto; font-size:13px;
}
.pf-music[data-style="minimal"] .pf-music__cover,
.pf-music[data-style="minimal"] .pf-music__viz,
.pf-music[data-style="minimal"] .pf-music__bar,
.pf-music[data-style="minimal"] .pf-music__time{ display:none; }
.pf-music[data-style="minimal"] .pf-music__btn{
  width:auto; height:auto; border:0; background:transparent; font-size:13px;
}

/* transparent: sólo los controles */
.pf-music[data-style="transparent"]{
  border:0; background:transparent; padding:0;
  width:auto; gap:14px;
}
.pf-music[data-style="transparent"] .pf-music__cover,
.pf-music[data-style="transparent"] .pf-music__meta,
.pf-music[data-style="transparent"] .pf-music__bar,
.pf-music[data-style="transparent"] .pf-music__time{ display:none; }

/* compact: sin barra ni tiempos */
.pf-music[data-style="compact"] .pf-music__bar,
.pf-music[data-style="compact"] .pf-music__time{ display:none; }

/* card: portada grande, barra y tiempos */
.pf-music[data-style="card"] .pf-music__viz{ display:none; }
.pf-music[data-style="card"] .pf-music__cover{ width:48px; height:48px; }

/* ============================================================
   ESTADÍSTICAS
   ============================================================ */
.pf-stats{
  display:grid; grid-template-columns:repeat(3,1fr);
  gap:1px; width:100%;
  border:1px solid var(--p-line);
  border-radius:var(--p-chip-r);
  overflow:hidden;
  background:var(--p-line);
}
.pf-stat{ background:var(--p-surface); padding:13px 8px; text-align:center; }
.pf-stat__n{
  font-family:var(--p-fm); font-size:16px; font-weight:700;
  color:var(--p-primary); font-variant-numeric:tabular-nums;
}
.pf-stat__l{
  font-family:var(--p-fm); font-size:9px;
  letter-spacing:.12em; text-transform:uppercase;
  color:var(--p-dim); margin-top:3px;
}

/* línea discreta de visitas, como en las referencias */
.pf-views{
  display:inline-flex; align-items:center; gap:7px;
  font-family:var(--p-fm); font-size:11.5px;
  color:var(--p-dim);
}
.pf-views svg{ width:13px; height:13px; opacity:.8; flex:none; }
.pf-views__sep{ opacity:.4; }

/* ============================================================
   SECCIONES BAJO EL HÉROE  (el scroll revela profundidad)
   ============================================================ */
.pf-scroll{
  position:absolute;
  left:50%; bottom:26px;
  transform:translateX(-50%);
  display:flex; flex-direction:column; align-items:center; gap:6px;
  font-family:var(--p-fm); font-size:10px;
  letter-spacing:.16em; text-transform:uppercase;
  color:var(--p-dim);
  animation:scrollHint 2.6s var(--ease) infinite;
}
@keyframes scrollHint{ 50%{ transform:translate(-50%,6px); opacity:.55; } }

.pf-sec{
  position:relative;
  padding:clamp(56px,10vh,110px) clamp(16px,5vw,48px);
  border-top:1px solid var(--p-line);
}
.pf-sec__in{
  width:100%;
  max-width:var(--u-width, 460px);
  margin-inline:auto;
}
.pf-sec__h{
  font-family:var(--p-fm); font-size:10px;
  letter-spacing:.2em; text-transform:uppercase;
  color:var(--p-dim);
  margin-bottom:18px;
}
.pf-sec__about{ font-size:15px; line-height:1.75; color:var(--p-dim); white-space:pre-wrap; margin:0; }

.pf-gallery{ display:grid; grid-template-columns:repeat(3,1fr); gap:7px; }
.pf-gallery figure{
  margin:0; aspect-ratio:1;
  border-radius:calc(var(--p-chip-r) * .7);
  overflow:hidden;
  background:var(--p-surface-2);
  display:grid; place-items:center;
  font-size:26px;
  border:1px solid var(--p-line);
  transition:transform var(--transition-normal);
}
.pf-gallery figure:hover{ transform:scale(1.06); z-index:2; }
.pf-gallery img{ width:100%; height:100%; object-fit:cover; }

.pf-proj{ display:grid; gap:8px; }
.pf-proj a{
  display:flex; gap:11px; align-items:flex-start;
  padding:11px 12px;
  border-radius:var(--p-chip-r);
  background:var(--p-surface-2);
  border:1px solid transparent;
  transition:border-color var(--transition-fast), transform var(--transition-normal);
}
.pf-proj a:hover{ border-color:var(--p-primary); transform:translateY(-2px); }
.pf-proj__t{ font-weight:600; font-size:13.5px; }
.pf-proj__d{ font-size:11.5px; color:var(--p-dim); }
.pf-proj__tag{
  margin-left:auto; flex:none;
  font-family:var(--p-fm); font-size:9.5px;
  padding:3px 7px; border-radius:100px;
  background:var(--p-surface); color:var(--p-dim);
}

/* --- califica mi perfil --- */
.pf-rate__score{
  display:flex; align-items:baseline; gap:9px;
  font-family:var(--u-fontd, var(--u-font, var(--p-fd))); font-weight:700;
  font-size:34px; letter-spacing:-.04em;
  color:var(--p-primary); line-height:1;
}
.pf-rate__score small{
  font-family:var(--p-fm); font-size:10px; font-weight:600;
  color:var(--p-dim); letter-spacing:.1em;
}
.pf-rate__rows{ margin-top:14px; display:grid; gap:9px; }
.pf-rate__row{ display:grid; grid-template-columns:86px 1fr 34px; align-items:center; gap:10px; }
.pf-rate__lab{
  font-family:var(--p-fm); font-size:9.5px;
  letter-spacing:.1em; text-transform:uppercase; color:var(--p-dim);
}
.pf-rate__bar{ height:5px; border-radius:100px; background:var(--p-surface-2); overflow:hidden; }
.pf-rate__bar i{
  display:block; height:100%; border-radius:100px;
  background:linear-gradient(90deg,var(--p-primary),var(--p-accent));
  animation:fill 1.1s var(--ease-out) both;
}
.pf-rate__v{ font-family:var(--p-fm); font-size:11px; text-align:right; }
.pf-vote{ display:flex; gap:5px; margin-top:16px; flex-wrap:wrap; }
.pf-vote button{
  flex:1; min-width:34px; padding:8px 0;
  border:1px solid var(--p-line);
  border-radius:calc(var(--p-chip-r) * .6);
  background:var(--p-surface-2);
  font-family:var(--p-fm); font-size:11px; font-weight:600;
  cursor:pointer;
  transition:transform var(--transition-fast), background var(--transition-fast), color var(--transition-fast);
}
.pf-vote button:hover{ background:var(--p-primary); color:var(--p-bg); transform:translateY(-2px); }
.pf-vote button.is-mine{ background:var(--p-primary); color:var(--p-bg); }

/* ============================================================
   PIE + ACCIONES FLOTANTES
   ============================================================ */
/* El pie va FIJO abajo, no al final del documento.
   Antes habia que desplazar hasta el fondo para verlo, y en un
   perfil de una sola pantalla eso significa que no lo ve nadie:
   la unica puerta de vuelta a IDENTITY estaba escondida.

   Se queda pegado a la ventana, discreto, y se aparta de los
   botones flotantes de la derecha. */
.pf-foot{
  position:fixed;
  left:0; right:0; bottom:0;
  z-index:55;                      /* por debajo de .pf-actions (60) */
  /* 120px a cada lado: los dos botones flotantes miden ~108px con
     su margen, y 76 se quedaban cortos. Medido, no estimado. */
  padding:10px 120px 12px;
  display:flex; align-items:center; justify-content:center;
  gap:12px; flex-wrap:wrap;
  font-family:var(--p-fm); font-size:10px;
  color:var(--p-dim);
  pointer-events:none;             /* no tapa lo que haya debajo... */
  /* SIN FONDO. Ni degradado ni barra.
     Aqui habia un degradado para que el texto se leyera sobre una
     foto o un video. En un movil el pie se sube 64px para esquivar
     los botones flotantes (mas abajo), y el degradado subia con el:
     el resultado era una franja difuminada flotando a media altura,
     sin tocar ningun borde. Se leia como un fallo de dibujado,
     porque lo parecia.

     La legibilidad la sostiene la sombra, que es lo que de verdad
     hacia el trabajo: sigue el contorno de cada letra en vez de
     pintar un rectangulo sobre la imagen que el usuario eligio. */
  text-shadow:
    0 1px 2px color-mix(in srgb, var(--p-bg) 92%, transparent),
    0 0 6px color-mix(in srgb, var(--p-bg) 78%, transparent),
    0 0 14px color-mix(in srgb, var(--p-bg) 60%, transparent);
}
.pf-foot > *{ pointer-events:auto; }   /* ...pero el enlace si se pulsa */
.pf-foot a{
  text-decoration:underline; text-underline-offset:3px;
  color:var(--p-text);
}
.pf-foot a:hover{ color:var(--p-primary); }

/* El contenido no puede quedar debajo del pie: se le deja sitio al
   final, lo que mida el pie mas un respiro. */
.pf{ padding-bottom:44px; }

@media (max-width:640px){
  /* Por debajo de esto, 120px a cada lado no dejan sitio al texto.
     El pie se sube por encima de los botones en vez de esquivarlos
     de lado. */
  .pf-foot{ padding:10px 16px 12px; bottom:64px; }
  .pf{ padding-bottom:96px; }
}

.pf-actions{ position:fixed; right:16px; bottom:16px; z-index:60; display:flex; gap:8px; }
.pf-fab{
  width:42px; height:42px; border-radius:50%;
  display:grid; place-items:center;
  border:1px solid var(--p-line);
  background:var(--p-surface-2);
  color:var(--p-text);
  cursor:pointer;
  backdrop-filter:blur(12px);
  -webkit-backdrop-filter:blur(12px);
  transition:transform var(--transition-fast), border-color var(--transition-fast);
}
.pf-fab svg{ width:17px; height:17px; }
.pf-fab:hover{ transform:scale(1.1); border-color:var(--p-primary); }

/* botón de sonido arriba a la izquierda, como en las referencias */
.pf-sound{
  position:fixed; left:16px; top:16px;
  z-index:70;
  width:40px; height:40px;
  display:grid; place-items:center;
  border-radius:var(--radius-md);
  border:1px solid var(--p-line);
  background:var(--p-surface-2);
  color:var(--p-text);
  cursor:pointer;
  backdrop-filter:blur(12px);
  -webkit-backdrop-filter:blur(12px);
  transition:transform var(--transition-fast);
}
.pf-sound:hover{ transform:scale(1.07); }
.pf-sound svg{ width:19px; height:19px; }

/* ============================================================
   BRILLO SELECTIVO, GRADIENTE Y NOMBRE ANIMADO
   ============================================================ */
.pf.is-gradient .pf-bg{
  background:radial-gradient(120% 90% at 50% 0%,
    color-mix(in srgb, var(--p-primary) 26%, var(--p-bg2)), var(--p-bg) 72%);
}
/* Estos tres leen --halo, no --p-primary. Por defecto --halo ES el
   acento del tema, asi que no cambia nada de como se ven; lo que
   gana es que una pieza con halo propio los tine tambien. */
.pf.glow-name .pf-name{
  text-shadow:0 0 24px color-mix(in srgb, var(--halo) 65%, transparent);
}
.pf.glow-social .pf-social{ box-shadow:0 0 22px -8px var(--halo); }
.pf.glow-badge .pf-badge{
  box-shadow:0 0 18px -6px var(--halo);
  border-color:color-mix(in srgb, var(--halo) 45%, var(--p-line));
}

/* ---- halo propio de una pieza ---------------------------------
   drop-shadow sigue la SILUETA de lo que hay dentro: las letras por
   su trazo, los iconos por su forma, el avatar por su recorte. Un
   box-shadow dibujaria un rectangulo alrededor de la caja, que es
   justo lo que no se quiere.
   ---------------------------------------------------------------- */
.pf [data-halo]{
  filter:drop-shadow(0 0 5px color-mix(in srgb, var(--halo) 72%, transparent))
         drop-shadow(0 0 15px color-mix(in srgb, var(--halo) 38%, transparent));
}
.pf.is-animname .pf-name{
  background:linear-gradient(100deg,
    var(--p-text) 20%, var(--p-primary) 42%, var(--p-accent) 58%, var(--p-text) 80%);
  background-size:250% 100%;
  -webkit-background-clip:text; background-clip:text;
  color:transparent;
  animation:nameSweep 5.5s linear infinite;
}
@keyframes nameSweep{ to{ background-position:-250% 0; } }
.pf[data-theme="gta"].is-animname .pf-name{ animation:none; }

@keyframes fill{ from{ width:0; } }

/* ============================================================
   CURSOR PERSONALIZADO
   ============================================================ */
.pf[data-cursor]:not([data-cursor="default"]){ cursor:none; }
.pf[data-cursor]:not([data-cursor="default"]) *{ cursor:none !important; }
.cur{ position:fixed; top:0; left:0; z-index:9990; pointer-events:none; will-change:transform; }
.cur--dot{
  width:9px; height:9px; margin:-4.5px 0 0 -4.5px;
  border-radius:50%; background:var(--p-primary,#fff);
  box-shadow:0 0 14px var(--p-primary,#fff);
}
.cur--ring{
  width:32px; height:32px; margin:-16px 0 0 -16px;
  border-radius:50%; border:1.5px solid var(--p-primary,#fff);
  transition:width .2s var(--ease), height .2s var(--ease), margin .2s var(--ease);
}
.cur--ring.is-hot{ width:48px; height:48px; margin:-24px 0 0 -24px; background:rgba(255,255,255,.08); }
.cur--glow{
  width:220px; height:220px; margin:-110px 0 0 -110px;
  border-radius:50%;
  background:radial-gradient(circle, color-mix(in srgb,var(--p-primary,#fff) 26%, transparent), transparent 68%);
  filter:blur(6px);
}
.cur--blade{
  width:22px; height:22px; margin:-2px 0 0 -2px;
  background:var(--p-primary,#fff);
  clip-path:polygon(0 0, 100% 62%, 44% 66%, 30% 100%);
}
.cur-trail{
  position:fixed; top:0; left:0;
  width:6px; height:6px; margin:-3px 0 0 -3px;
  border-radius:50%; background:var(--p-accent,#fff);
  pointer-events:none; z-index:9989; opacity:.55;
}

/* ============================================================
   RESPONSIVE — el móvil recorta coste visual, nunca legibilidad
   ============================================================ */
@media (max-width:640px){
  .pf-stack{ max-width:100%; }
  .pf-hero{ padding-top:84px; }
  .pf-card__sheen{ display:none; }
  .pf-veil{ backdrop-filter:blur(calc(var(--p-blur,0px) * .5)); }
  .pf-rate__row{ grid-template-columns:74px 1fr 30px; }
  .pf-avatar{ width:min(var(--u-av,112px), 40vw); }
  /* las alineaciones laterales dejan líneas huérfanas en móvil */
  .pf[data-align="left"] .pf-hero,
  .pf[data-align="right"] .pf-hero{ justify-items:center; }
  .pf[data-align="left"] .pf-stack,
  .pf[data-align="right"] .pf-stack{ text-align:center; align-items:center; }
  .pf[data-align="left"],
  .pf[data-align="right"]{ --u-just:center; }
}

@media (prefers-reduced-motion:reduce){
  .pf-scroll,
  .pf-avatar[data-fx],
  .pf.is-animname .pf-name{ animation:none; }
}

/* ============================================================
   LIBERTAD DE COMPOSICIÓN  ·  v3
   Ancho, cabecera en fila, estilo por bloque, animaciones.
   ============================================================ */

/* ---- ancho: el problema de la caja enorme y vacía ------------
   Con ancho fijo la caja se estira aunque el contenido sea corto.
   "auto" la hace abrazar el contenido, que es casi siempre lo
   que la gente quiere cuando pone pocos bloques. */
.pf[data-width="auto"] .pf-stack{
  width:fit-content;
  min-width:min(280px, 100%);
  max-width:min(var(--u-width, 460px), 100%);
}
.pf[data-width="fixed"] .pf-stack{ width:100%; max-width:var(--u-width, 460px); }
.pf[data-width="full"]  .pf-stack{ width:100%; max-width:min(1100px, 100%); }

/* ---- cabecera en fila: avatar junto al nombre ---------------- */
@media (max-width:520px){
}

/* ---- tipografía fina ----------------------------------------- */
.pf-name{ letter-spacing:var(--u-lsp, var(--p-track)); }
.pf-bio{ line-height:var(--u-lh, 1.62); }

/* ---- estilo por bloque ---------------------------------------
   Las cajas internas (estado, enlaces, música, stats, nivel,
   Discord, actividad) pueden vestirse aparte de la superficie. */
.pf[data-blockstyle="transparent"] :is(
  .pf-status, .pf-link, .pf-music, .pf-stats, .pf-level,
  .pf-dc, .pf-live__row, .pf-field, .pf-badge):not([data-bs]){
  background:transparent;
  border-color:transparent;
  box-shadow:none;
}
.pf[data-blockstyle="transparent"] .pf-stats:not([data-bs]){ gap:0; }
.pf[data-blockstyle="transparent"] .pf-stat:not([data-bs]){ background:transparent; }

.pf[data-blockstyle="glass"] :is(
  .pf-status, .pf-link, .pf-music, .pf-level,
  .pf-dc, .pf-live__row, .pf-field, .pf-badge):not([data-bs]){
  background:rgba(255,255,255,.07);
  border-color:rgba(255,255,255,.16);
  backdrop-filter:blur(14px) saturate(140%);
  -webkit-backdrop-filter:blur(14px) saturate(140%);
}
.pf[data-blockstyle="glass"] .pf-stat:not([data-bs]){ background:rgba(255,255,255,.06); }

.pf[data-blockstyle="solid"] :is(
  .pf-status, .pf-link, .pf-music, .pf-level,
  .pf-dc, .pf-live__row, .pf-field, .pf-badge):not([data-bs]){
  background:var(--p-bg2);
  border-color:var(--p-line);
}
.pf[data-blockstyle="solid"] .pf-stat:not([data-bs]){ background:var(--p-bg2); }

.pf[data-blockstyle="outline"] :is(
  .pf-status, .pf-link, .pf-music, .pf-stats, .pf-level,
  .pf-dc, .pf-live__row, .pf-field, .pf-badge):not([data-bs]){
  background:transparent;
  border-color:color-mix(in srgb, var(--p-primary) 40%, transparent);
}
.pf[data-blockstyle="outline"] .pf-stat:not([data-bs]){ background:transparent; }

/* curvatura propia de los bloques internos */
.pf :is(.pf-status, .pf-link, .pf-music, .pf-level, .pf-dc,
        .pf-live__row, .pf-field, .pf-badge, .pf-stats){
  border-radius:var(--u-brad, var(--p-chip-r));
}

/* ---- animación al pasar el puntero --------------------------- */
.pf[data-hover="none"] :is(.pf-link, .pf-social, .pf-badge, .pf-proj a):hover{
  transform:none; box-shadow:none;
}
.pf[data-hover="scale"] :is(.pf-link, .pf-social, .pf-proj a):hover{
  transform:scale(1.035);
}
.pf[data-hover="glow"] :is(.pf-link, .pf-social, .pf-proj a):hover{
  transform:none;
  box-shadow:0 0 26px -6px var(--p-primary);
  border-color:var(--p-primary);
}

/* ============================================================
   EFECTOS DE PUNTERO
   Los tres escriben variables CSS desde un solo reloj y dejan que
   el compositor haga el trabajo: nada de layout por fotograma.
   ============================================================ */

/* magnetismo: la pieza se inclina hacia el cursor. Se suma a lo que
   ya tuviera, por eso va en su propia variable y no pisa transform. */
.pf-social, .pf-badge, .pf-link__ico, .pf-music__btn{
  translate:var(--mgx, 0) var(--mgy, 0);
  transition:translate .18s var(--ease-out);
}

/* brillo que sigue al raton: una sola capa, sin tocar el fondo */
.pf-glow{
  position:absolute; inset:0; z-index:1;
  pointer-events:none;
  opacity:0;
  transition:opacity .35s var(--ease-out);
  background:radial-gradient(
    38vmax 38vmax at var(--gx, 50%) var(--gy, 50%),
    color-mix(in srgb, var(--p-primary) 16%, transparent) 0%,
    transparent 62%);
}

/* parallax: el fondo se mueve mas que el contenido. Si los dos se
   movieran igual no habria profundidad, solo deriva. */
.pf-bg, .pf[data-layout] .pf-stack{
  translate:var(--pxx, 0) var(--pxy, 0);
}

@media (prefers-reduced-motion:reduce){
  .pf-social, .pf-badge, .pf-link__ico, .pf-music__btn,
  .pf-bg, .pf[data-layout] .pf-stack{ translate:none; }
  .pf-glow{ display:none; }
}

/* ---- tipografía por pieza ------------------------------------
   Un bloque puede llevar su propia cara. Si no la define, hereda,
   asi que esto no cambia nada en un perfil que no lo use. */
/* tipografía por pieza: si el bloque no la define, hereda */
.pf-stack > *{ font-family:var(--b-font, inherit); }

/* Color por pieza. La pieza redefine --p-text/--p-dim/--p-icon, pero
   eso solo alcanza a lo que LEE la variable. Lo que unicamente hereda
   —el nombre, por ejemplo— se quedaria con el color ya computado en
   .pf. Volviendo a declararlo aqui, el valor se recalcula dentro de
   la pieza. Sin color propio es un no-op: la variable es la misma. */
.pf-stack > *{ color:var(--p-text); }

/* ---- animación de entrada ------------------------------------ */
.pf[data-enter="none"] .pf-stack{ animation:none; }
.pf[data-enter="fade"] .pf-stack{ animation:enterFade .7s var(--ease-out) both; }
.pf[data-enter="zoom"] .pf-stack{ animation:enterZoom .7s var(--ease-out) both; }
.pf[data-enter="blur"] .pf-stack{ animation:enterBlur .8s var(--ease-out) both; }
@keyframes enterFade{ from{ opacity:0 } }
@keyframes enterZoom{ from{ opacity:0; transform:scale(.94) } }
@keyframes enterBlur{ from{ opacity:0; filter:blur(14px) } }

/* escalonado: cada bloque entra un poco después que el anterior */
.pf[data-enter="stagger"] .pf-stack{ animation:none; }
.pf[data-enter="stagger"] .pf-stack > *:not(.pf-card__sheen){
  animation:enterRise .6s var(--ease-out) both;
  animation-delay:calc(var(--i, 0) * 70ms);
}
@keyframes enterRise{ from{ opacity:0; transform:translateY(14px) } }

/* ---- animación propia de una pieza ---------------------------
   Gana sobre la del perfil entero. El retardo escalonado va DESPUES
   de la forma corta: `animation:` reinicia el delay a cero. */
.pf-stack > [data-anim="fade"]{ animation:enterFade .7s var(--ease-out) both; }
.pf-stack > [data-anim="zoom"]{ animation:enterZoom .7s var(--ease-out) both; }
.pf-stack > [data-anim="blur"]{ animation:enterBlur .8s var(--ease-out) both; }
.pf-stack > [data-anim="rise"]{ animation:enterRise .6s var(--ease-out) both; }
.pf-stack > [data-anim="none"]{ animation:none; }
.pf-stack > [data-anim]:not([data-anim="none"]){
  animation-delay:calc(var(--i, 0) * 70ms);
}

@media (prefers-reduced-motion:reduce){
  .pf-stack,
  .pf-stack > [data-anim],
  .pf[data-enter="stagger"] .pf-stack > *{ animation:none !important; }
}

/* ============================================================
   MODO LIBRE  ·  rejilla de 12 columnas
   Cada bloque elige columna, ancho y alineación. Es libertad real
   sin posicionamiento absoluto: en móvil todo vuelve a apilarse
   solo, que es donde estos editores suelen romperse.
   ============================================================ */
.pf[data-layout="free"] .pf-stack{
  display:grid;
  grid-template-columns:repeat(12, 1fr);
  grid-auto-flow:row dense;
  align-items:center;
  column-gap:var(--u-gap, 16px);
  row-gap:var(--u-gap, 16px);
}
.pf[data-layout="free"] .pf-avatar{ justify-self:inherit; }

/* la rejilla necesita aire para que se note */
.pf[data-layout="free"][data-width="auto"] .pf-stack{ width:100%; }

@media (max-width:640px){
  /* en móvil la rejilla se rinde: una columna y el orden del editor */
  .pf[data-layout="free"] .pf-stack{
    display:flex; flex-direction:column;
  }
  .pf[data-layout="free"] .pf-stack > *{
    grid-column:auto !important;
    justify-self:auto !important;
    text-align:inherit !important;
  }
}

/* ============================================================
   DESBORDES  ·  regla estructural
   Una sola causa detras de todos los casos: un hijo de rejilla o de
   caja flexible arranca con min-width:auto, que significa "nunca mas
   estrecho que mi contenido". Con un nombre largo, una URL larga o
   la descripcion de un proyecto, ese minimo empuja el bloque fuera
   del contenedor. Y como el perfil no tiene scroll horizontal, el
   texto que se sale no queda a un scroll de distancia: desaparece.

   Antes esto se arreglaba bloque a bloque, cada vez que alguien
   tropezaba con el sintoma: habia once min-width:0 sueltos por este
   archivo. Aqui se declara una vez para todo el perfil.

   :where() no suma especificidad, asi que cualquier min-width
   explicito de este archivo sigue mandando sobre esta regla.
   ============================================================ */
:where(.pf, .pf *){ min-width:0; }

/* el reverso de lo anterior: si la caja se estrecha, la palabra se
   parte en vez de salirse. Se hereda a todo el perfil. */
.pf{ overflow-wrap:break-word; }

/* una rejilla sin columnas declaradas crea una pista implicita que
   se dimensiona por su contenido: el elemento mas largo manda y
   arrastra a los demas. minmax(0,1fr) la ata al ancho disponible.
   (.pf-links lo esquivaba con width:100%; .pf-proj no, y por eso a
   375px media 1416px de ancho con la descripcion fuera de pantalla.) */
:where(.pf) :where(.pf-links, .pf-proj){ grid-template-columns:minmax(0,1fr); }

/* los iconos y el avatar no entran en el trato: tienen tamaño propio
   y encogerlos no arregla nada, solo los deforma. (.pf-link__ico y
   .pf-proj__tag ya lo declaran por su cuenta; aqui se completa el
   resto para que la lista se lea entera en un sitio.) */
:where(.pf) :where(svg, img, .pf-avatar, .pf-social, .pf-proj__tag,
                   .pf-link__ico, .pf-link__arrow, .pf-status__dot){ flex:none; }

.pf-stack > *{ max-width:100%; }
.pf-idblock{ max-width:100%; }
.pf-name,
.pf-handle,
.pf-title,
.pf-joined,
.pf-status__act{ max-width:100%; }
.pf-avatar{ max-width:100%; }
.pf-views,
.pf-status{ max-width:100%; }

/* ============================================================
   ANCHO PROPIO  ·  container queries
   La vista previa mide ~340px pero el navegador sigue siendo
   ancho, así que las media queries del viewport nunca se
   activaban y la previsualización mostraba el diseño de
   escritorio dentro de una caja de móvil.

   Las previsualizaciones declaran un contenedor y las mismas
   reglas se repiten con @container. En el perfil real siguen
   mandando las @media, porque ahí .pf no puede ser contenedor:
   `container-type` rompería el fondo fijo (position:fixed pasa a
   anclarse al contenedor, no a la ventana).
   ============================================================ */
.prev__stage,
.demo__scroll,
.tplmodal__view,
.tpl__scale{
  container-type:inline-size;
  container-name:pfbox;
}

@container pfbox (max-width: 640px){
  .pf-stack{ max-width:100%; }
  .pf-hero{ padding-top:56px; padding-inline:16px; }
  .pf-card__sheen{ display:none; }
  .pf-rate__row{ grid-template-columns:74px 1fr 30px; }
  .pf-avatar{ width:min(var(--u-av,112px), 38cqw); }

  /* las alineaciones laterales dejan líneas huérfanas al estrechar */
  .pf[data-align="left"] .pf-stack,
  .pf[data-align="right"] .pf-stack{ text-align:center; align-items:center; }
  .pf-hero{ justify-items:center; }

  /* el modo libre se rinde: una columna, en el orden del editor */
  .pf[data-layout="free"] .pf-stack{ display:flex; flex-direction:column; }
  .pf[data-layout="free"] .pf-stack > *{
    grid-column:auto !important;
    justify-self:auto !important;
    text-align:inherit !important;
  }

  .pf-gallery{ grid-template-columns:repeat(2,1fr); }
  .pf-sec{ padding-inline:16px; }
}

@container pfbox (max-width: 420px){
  /* a este ancho un nombre gigante deja de caber: se reduce */
  .pf-name{ font-size:min(var(--u-name, clamp(28px,5.6vw,44px)), 11cqw); }
  .pf-stats{ grid-template-columns:1fr; }
}

/* ---- el nombre debe poder partirse ---------------------------
   Era inline-flex: el texto quedaba como elemento flexible con
   min-width:auto y no bajaba de su ancho maximo, asi que se salia
   de la caja en vez de pasar a la linea siguiente.
   -------------------------------------------------------------- */
.pf-name{
  display:block;
  overflow-wrap:break-word;
  word-break:break-word;
}
.pf-verified{
  display:inline-block;
  vertical-align:-0.14em;
  margin-left:.3em;
}

/* ============================================================
   CAJA PROPIA POR BLOQUE
   Cada bloque puede llevar su vidrio, su borde y su relleno, en
   vez de que una sola caja envuelva todo el perfil.
   ============================================================ */

.pf [data-bs]{
  border-radius:var(--b-rad, var(--p-chip-r));
  padding:var(--b-pad, 14px);
  transition:background var(--transition-normal), border-color var(--transition-normal),
             box-shadow var(--transition-normal);
}
/* el ancho es cosa de cada bloque, lleve caja propia o no */
.pf .pf-stack > [style*="--b-w"]{ width:var(--b-w); max-width:100%; }

.pf [data-bs="none"]{
  background:transparent;
  border:1px solid transparent;
  box-shadow:none;
  backdrop-filter:none; -webkit-backdrop-filter:none;
  padding:var(--b-pad, 0px);
}

.pf [data-bs="glass"]{
  background:color-mix(in srgb, #ffffff calc(var(--b-op, 10) * 1%), transparent);
  border:1px solid color-mix(in srgb, #ffffff calc(var(--b-bd, 18) * 1%), transparent);
  backdrop-filter:blur(var(--b-blur, 18px)) saturate(150%);
  -webkit-backdrop-filter:blur(var(--b-blur, 18px)) saturate(150%);
  box-shadow:0 24px 60px -44px rgba(0,0,0,.9);
}

.pf [data-bs="solid"]{
  background:color-mix(in srgb, var(--p-bg2) calc(var(--b-op, 92) * 1%), transparent);
  border:1px solid color-mix(in srgb, var(--p-line) calc(var(--b-bd, 70) * 1%), transparent);
  backdrop-filter:none; -webkit-backdrop-filter:none;
}

.pf [data-bs="outline"]{
  background:transparent;
  border:1px solid color-mix(in srgb, var(--p-primary) calc(var(--b-bd, 45) * 1%), transparent);
  backdrop-filter:none; -webkit-backdrop-filter:none;
}

.pf [data-bs="glow"]{
  background:color-mix(in srgb, var(--p-bg2) calc(var(--b-op, 55) * 1%), transparent);
  border:1px solid color-mix(in srgb, var(--p-primary) calc(var(--b-bd, 40) * 1%), transparent);
  box-shadow:0 0 calc(var(--b-glow, 40) * 1.2px) calc(var(--b-glow, 40) * -0.45px) var(--p-primary),
             inset 0 0 50px -38px var(--p-primary);
}

/* los contenedores que ya alineaban su contenido lo siguen haciendo */
.pf [data-bs].pf-socials,
.pf [data-bs].pf-badges,
.pf [data-bs].pf-fields{ justify-content:var(--u-just, flex-start); }
.pf [data-bs].pf-idblock{ align-items:inherit; }

/* ---- reproductor: enlace externo y hueco del iframe ---------- */
.pf-music__out{
  flex:none;
  width:26px; height:26px;
  display:grid; place-items:center;
  border-radius:50%;
  border:1px solid var(--p-line);
  color:var(--p-dim);
  font-size:12px;
  transition:color var(--transition-fast), border-color var(--transition-fast);
}
.pf-music__out:hover{ color:var(--p-primary); border-color:var(--p-primary); }

/* el reproductor de YouTube vive aquí: solo queremos su audio */
.pf-music__host{
  position:absolute;
  width:1px; height:1px;
  overflow:hidden;
  opacity:0;
  pointer-events:none;
}
.pf-music{ position:relative; }

/* ============================================================
   REPRODUCTOR  ·  v2
   Barra arrastrable, tiempos reales y anterior / pausa / siguiente.
   ============================================================ */

.pf-music{ gap:11px; }

.pf-music__meta{ flex:1 1 auto; }

/* --- barra: zona táctil generosa, riel fino --- */
.pf-music__bar{
  position:relative;
  flex:1 1 90px; min-width:60px;
  height:16px;
  display:flex; align-items:center;
  background:none;
  overflow:visible;
  cursor:pointer;
  touch-action:none;
}
.pf-music__bar::before{
  content:"";
  position:absolute; left:0; right:0;
  height:3px; border-radius:100px;
  background:color-mix(in srgb, var(--p-text) 16%, transparent);
}
.pf-music__bar i{
  position:relative; z-index:1;
  display:block; height:3px;
  width:0%;
  border-radius:100px;
  background:var(--p-primary);
}
.pf-music__bar i::after{
  content:"";
  position:absolute; right:-5px; top:50%;
  width:10px; height:10px; margin-top:-5px;
  border-radius:50%;
  background:var(--p-primary);
  box-shadow:0 0 0 3px color-mix(in srgb, var(--p-primary) 22%, transparent);
  opacity:0;
  transition:opacity var(--transition-fast);
}
.pf-music__bar:hover i::after,
.pf-music__bar:focus-visible i::after{ opacity:1; }

.pf-music__time{
  font-family:var(--p-fm);
  font-size:10.5px;
  color:var(--p-dim);
  flex:none;
  font-variant-numeric:tabular-nums;
  min-width:30px;
}

/* --- controles --- */
.pf-music__ctl{
  display:flex; align-items:center; gap:2px;
  flex:none;
}
.pf-music__nav{
  width:26px; height:26px;
  display:grid; place-items:center;
  border:0; border-radius:50%;
  background:transparent;
  color:var(--p-dim);
  cursor:pointer;
  transition:color var(--transition-fast), transform var(--transition-fast);
}
.pf-music__nav svg{ width:14px; height:14px; }
.pf-music__nav:hover{ color:var(--p-text); transform:scale(1.12); }

.pf-music__btn{
  width:30px; height:30px;
  border:0;
  background:transparent;
  color:var(--p-text);
  border-radius:50%;
}
.pf-music__btn svg{ width:17px; height:17px; }
.pf-music__btn:hover{ transform:scale(1.12); border-color:transparent; }

/* el icono cambia según el estado, sin tocar el DOM */
.pf-music .pf-ic-pause{ display:none; }
.pf-music:not(.is-paused) .pf-ic-play{ display:none; }
.pf-music:not(.is-paused) .pf-ic-pause{ display:block; }

/* --- qué muestra cada estilo --- */
.pf-music[data-style="compact"] .pf-music__bar,
.pf-music[data-style="compact"] .pf-music__time{ display:none; }

.pf-music[data-style="card"] .pf-music__viz{ display:none; }
.pf-music[data-style="card"] .pf-music__cover{ width:46px; height:46px; }

.pf-music[data-style="minimal"] .pf-music__ctl{ gap:0; }
.pf-music[data-style="minimal"] .pf-music__nav{ display:none; }
.pf-music[data-style="minimal"] .pf-music__btn{ width:auto; height:auto; }

.pf-music[data-style="transparent"] .pf-music__nav{ display:grid; }
.pf-music[data-style="transparent"] .pf-music__ctl{ gap:6px; }

@media (max-width:420px){
  .pf-music__viz{ display:none; }
  .pf-music[data-style="card"] .pf-music__meta{ flex-basis:100%; }
}


/* ============================================================
   EL PERFIL EN UN MOVIL DE VERDAD
   ============================================================ */

/* ---- lo fijo, fuera de la muesca y de la barra de inicio ---- */
.pf-foot{
  padding-bottom:calc(12px + env(safe-area-inset-bottom, 0px));
  padding-left:max(120px, env(safe-area-inset-left, 0px));
  padding-right:max(120px, env(safe-area-inset-right, 0px));
}
.pf-actions{
  right:calc(16px + env(safe-area-inset-right, 0px));
  bottom:calc(16px + env(safe-area-inset-bottom, 0px));
}
.pf-sound{
  left:calc(16px + env(safe-area-inset-left, 0px));
  top:calc(16px + env(safe-area-inset-top, 0px));
}

/* ---- objetivos tactiles de 44 px ----------------------------
   Medido a 375 px de ancho: los iconos de redes eran 38x38 y los
   botones flotantes 42x42. El minimo comodo con un dedo son 44.

   Se amplia el AREA DE TOQUE, no el icono: un pseudoelemento
   invisible que sobresale lo justo. Agrandar el icono habria
   cambiado el diseno que ya esta elegido, y el problema no era que
   se vieran pequenos sino que se fallaba al tocarlos.
   ------------------------------------------------------------ */
.pf-social, .pf-fab, .pf-sound{ position:relative; }
.pf-social::after, .pf-fab::after, .pf-sound::after{
  content:'';
  position:absolute;
  top:50%; left:50%;
  width:max(100%, 44px); height:max(100%, 44px);
  transform:translate(-50%,-50%);
}

/* El enlace del pie tenia 16 px de alto: imposible de acertar. */
.pf-foot a{
  display:inline-flex; align-items:center;
  min-height:44px; padding-inline:4px;
}

/* ---- sin hover no hay estados de hover ----------------------
   En una pantalla tactil `:hover` se queda PEGADO despues de tocar:
   el elemento se queda agrandado hasta que tocas otra cosa. Se
   limitan los efectos a los punteros que de verdad pueden pasar por
   encima. */
@media (hover: none) {
  .pf-social:hover, .pf-fab:hover{ transform:none; }
}

/* ---- respetar a quien pidio menos movimiento --------------- */
@media (prefers-reduced-motion: reduce) {
  .pf-bg video{ animation:none; }
  .pf *, .pf *::before, .pf *::after{
    animation-duration:.01ms !important;
    animation-iteration-count:1 !important;
    transition-duration:.01ms !important;
  }
}


/* Los botones de 1 a 10, con el dedo.
   Diez a 44 px necesitan 485 y solo hay 308, pero la fila ya lleva
   `flex-wrap`, asi que caen a dos lineas en vez de encogerse. Dos
   filas comodas valen mas que una fila imposible de acertar. */
@media (pointer: coarse) {
  .pf-vote button{ min-width:44px; min-height:44px; flex:0 0 auto; }
}


/* ============================================================
   EL AVATAR, CUADRADO EN TODAS PARTES
   ============================================================
   Sintoma: circulo correcto en Android, ovalo estirado en iPhone.
   Medido en el perfil real:

     ancho  34.7px   <- correcto, es --b-w:15% del usuario
     alto   34.7px   en Chrome
     alto   ~85px    en Safari (la proporcion de la imagen)

   `.pf-avatar` cuadra con `aspect-ratio:1`. Safari no lo aplica
   cuando el ancho viene en PORCENTAJE y el elemento es hijo de un
   contenedor flex en columna: el alto se lo acaba dictando la
   imagen de dentro. Como el avatar de esta persona es vertical,
   salia un ovalo.

   La solucion no depende de `aspect-ratio`: un pseudoelemento con
   `padding-top:100%`. Ese porcentaje se resuelve SIEMPRE contra el
   ancho del bloque contenedor, en todos los navegadores y desde
   hace quince años. El pseudoelemento fija la altura de la celda y
   la imagen se estira a esa celda.

   Se conserva `aspect-ratio` arriba: donde funciona, hace lo mismo
   y no estorba.
   ============================================================ */
.pf-avatar{
  display:grid;
  place-items:center;
}
.pf-avatar::before{
  content:'';
  grid-area:1 / 1;
  width:100%;
  padding-top:100%;        /* el % se mide contra el ANCHO: cuadrado */
  pointer-events:none;
}
.pf-avatar > *{
  grid-area:1 / 1;         /* misma celda que el espaciador */
  width:100%;
  height:100%;
  object-fit:cover;
}


/* ============================================================
   PASTILLA DE MUSICA  ·  como la pegatina de una historia
   ============================================================
   Compacta y superpuesta, no un bloque. La caratula redonda, el
   titulo, y las barras moviendose al lado. Al tocarla se despliega
   el reproductor de Spotify debajo.
   ============================================================ */
.pf-insta{ width:100%; display:flex; flex-direction:column; align-items:center; gap:10px; }

.pf-insta__pill{
  display:inline-flex; align-items:center; gap:10px;
  max-width:min(320px, 100%);
  padding:7px 14px 7px 7px;
  border:1px solid var(--p-line);
  border-radius:100px;                    /* pastilla, no tarjeta */
  background:color-mix(in srgb, var(--p-surface-2) 82%, transparent);
  -webkit-backdrop-filter:blur(14px); backdrop-filter:blur(14px);
  color:var(--p-text);
  font-family:var(--u-font, var(--p-fb));
  cursor:pointer; text-align:left;
  transition:transform var(--transition-fast), border-color var(--transition-fast);
}
.pf-insta__pill:hover{ border-color:var(--p-primary); }
@media (hover:hover){ .pf-insta__pill:hover{ transform:translateY(-1px); } }

.pf-insta__cover{
  width:34px; height:34px; flex:none;
  border-radius:50%;                      /* redonda, como Instagram */
  overflow:hidden;
  display:grid; place-items:center;
  background:var(--p-surface-3, var(--p-surface-2));
  font-size:15px; color:var(--p-primary);
}
.pf-insta__cover img{ width:100%; height:100%; object-fit:cover; display:block; }

.pf-insta__meta{ display:flex; flex-direction:column; min-width:0; line-height:1.25; }
.pf-insta__t{
  font-size:12.5px; font-weight:600;
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
}
.pf-insta__a{
  font-size:11px; color:var(--p-dim);
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
}

/* las barras: quietas en reposo, bailando cuando suena */
.pf-insta__viz{ display:flex; align-items:flex-end; gap:2.5px; height:18px; flex:none; margin-left:2px; }
.pf-insta__viz i{
  width:3px; height:4px; border-radius:2px;
  background:var(--p-primary);
}
.pf-insta.is-open .pf-insta__viz i{
  animation:viz 1s var(--ease, ease) infinite alternate;
}
.pf-insta.is-open .pf-insta__viz i:nth-child(2){ animation-delay:.14s }
.pf-insta.is-open .pf-insta__viz i:nth-child(3){ animation-delay:.28s }
.pf-insta.is-open .pf-insta__viz i:nth-child(4){ animation-delay:.42s }
.pf-insta.is-open .pf-insta__viz i:nth-child(5){ animation-delay:.56s }

/* el reproductor de Spotify, solo cuando se pide */
.pf-insta__player{
  width:100%; max-width:min(420px, 100%);
  border-radius:var(--p-chip-r, 12px);
  overflow:hidden; line-height:0;
}
.pf-insta__player iframe{ display:block; width:100%; height:152px; border:0; }
.pf-insta[data-tipo="playlist"] .pf-insta__player iframe,
.pf-insta[data-tipo="album"] .pf-insta__player iframe{ height:352px; }

/* quien pidio menos movimiento no ve las barras bailar */
@media (prefers-reduced-motion: reduce){
  .pf-insta.is-open .pf-insta__viz i{ animation:none; height:12px; }
}

/* ============================================================
   AVATAR AVANZADO
   ============================================================
   Todo lo de aquí es ADITIVO: cuelga de atributos y variables
   que un perfil guardado antes de esto no tiene, así que no
   cambia ni un píxel de lo que ya existe. Un perfil sin
   `data-avmask` no entra en ninguna de estas reglas.

   Las máscaras van con `clip-path`, no con `mask-image`: un
   clip-path es geometría escrita aquí mismo, sin URL, así que
   no descarga nada ni depende de la política de contenido.
   ============================================================ */

/* --- qué parte de la foto se ve ---------------------------- */
.pf-avatar img{ object-position:var(--u-avpos, 50% 50%); }

/* --- cómo encaja la imagen --------------------------------
   Independiente de la forma. Un PNG con transparencia quiere
   verse entero aunque su caja sea un círculo. */
.pf[data-avfit="contain"] .pf-avatar img{ object-fit:contain; }
.pf[data-avfit="cover"]   .pf-avatar img{ object-fit:cover; }

/* --- sin fondo detrás -------------------------------------
   Lo que hace que un PNG recortado flote en vez de salir
   pegado sobre un cuadrado gris. */
.pf[data-avfondo="off"] .pf-avatar{ background:transparent; }

/* --- máscaras ---------------------------------------------
   El recorte va en una capa de dentro y NO en `.pf-avatar`.
   Si se pusiera en el contenedor se llevaría por delante el
   aro de `data-fx="ring"`, que se dibuja fuera de la caja
   (inset:-9px), y el borde y el halo, que también son suyos.
   La capa solo existe cuando hay máscara. */
.pf-avatar__m{
  position:absolute; inset:0;
  display:grid; place-items:center;
  background:inherit;
  overflow:hidden;
}
.pf-avatar__m img{ width:100%; height:100%; }
.pf[data-avmask]:not([data-avmask="none"]) .pf-avatar{ background:transparent; }

.pf[data-avmask="hex"] .pf-avatar__m{
  clip-path:polygon(50% 0%, 93.3% 25%, 93.3% 75%, 50% 100%, 6.7% 75%, 6.7% 25%);
}
.pf[data-avmask="shield"] .pf-avatar__m{
  clip-path:polygon(50% 100%, 4% 72%, 4% 8%, 50% 0%, 96% 8%, 96% 72%);
}
.pf[data-avmask="star"] .pf-avatar__m{
  clip-path:polygon(50% 0%, 61.8% 34.5%, 98% 34.5%, 68.8% 56%, 80.9% 91%,
                    50% 69.5%, 19.1% 91%, 31.2% 56%, 2% 34.5%, 38.2% 34.5%);
}
.pf[data-avmask="diamond"] .pf-avatar__m{
  clip-path:polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%);
}
/* Una superelipse de verdad, no un radio grande: la diferencia
   se nota justo en las esquinas, que es lo único que se mira. */
.pf[data-avmask="squircle"] .pf-avatar__m{
  clip-path:path("M0,50 C0,10 10,0 50,0 C90,0 100,10 100,50 \
                  C100,90 90,100 50,100 C10,100 0,90 0,50 Z");
  clip-path:xywh(0 0 100% 100% round 30%);
}

/* --- decoración encima ------------------------------------
   El marco animado que va POR ENCIMA del avatar, estilo
   Discord. Sobresale a propósito: una decoración que cabe
   dentro de la caja no se lee como un marco, se lee como parte
   de la foto.

   `pointer-events:none` porque el avatar se arrastra y se
   selecciona en el editor, y un marco que se come el clic
   convierte una pieza en intocable. */
.pf-avatar__decor{
  position:absolute;
  inset:-12.5%;
  background-image:var(--u-avdecor);
  background-size:contain;
  background-position:center;
  background-repeat:no-repeat;
  pointer-events:none;
}

/* ============================================================
   NOMBRE VISIBLE
   ============================================================
   Aditivo, como el avatar avanzado: cuelga de variables y
   atributos que un perfil de antes no tiene. Con todo a cero
   —que es lo que sale si nadie eligió nada— estas reglas no
   pintan nada distinto de lo que ya se pintaba.
   ============================================================ */

/* --- degradado propio del nombre --------------------------
   El de `is-animname` usa los colores del tema y se mueve.
   Este es tuyo, con tus dos colores, y se está quieto: son dos
   cosas distintas y se pueden combinar. */
.pf[data-namegrad="on"] .pf-name{
  background-image:var(--u-namegrad);
  -webkit-background-clip:text;
  background-clip:text;
  color:transparent;
}

/* --- halo y sombra ----------------------------------------
   OJO con el orden: esto va DESPUÉS de `.pf.glow-name` a
   propósito. Tienen la misma especificidad, así que gana el
   último, y `--u-nameglow` ya trae 24px cuando el interruptor
   de siempre está encendido. Un perfil viejo ve exactamente el
   mismo halo que veía.

   Con degradado hay que cambiar de herramienta: bajo unas
   letras transparentes, un `text-shadow` se ve POR DEBAJO del
   relleno y queda como un manchón. `drop-shadow` sigue la
   silueta, que es lo que uno espera de una sombra. */
.pf:not([data-namegrad="on"]) .pf-name{
  text-shadow:
    0 0 var(--u-nameglow, 0px) color-mix(in srgb, var(--halo) 65%, transparent),
    0 2px var(--u-nameshadow, 0px) var(--u-nameshadowc, rgba(0,0,0,.45));
}
.pf[data-namegrad="on"] .pf-name{
  filter:
    drop-shadow(0 0 var(--u-nameglow, 0px) var(--halo))
    drop-shadow(0 2px var(--u-nameshadow, 0px) var(--u-nameshadowc, rgba(0,0,0,.45)));
}

/* --- animaciones ------------------------------------------ */
.pf[data-nameanim="sweep"] .pf-name{
  background-image:linear-gradient(100deg,
    var(--p-text) 20%, var(--p-primary) 42%, var(--p-accent) 58%, var(--p-text) 80%);
  background-size:250% 100%;
  -webkit-background-clip:text;
  background-clip:text;
  color:transparent;
  animation:nameSweep 5.5s linear infinite;
}
/* Con degradado propio, `sweep` mueve EL TUYO en vez de
   sustituirlo por el del tema: elegir dos colores y que la
   animación los ignore sería quitarte lo que acabas de elegir. */
.pf[data-namegrad="on"][data-nameanim="sweep"] .pf-name{
  background-image:var(--u-namegrad);
  background-size:250% 100%;
}
.pf[data-nameanim="pulse"] .pf-name{
  animation:nameLatido 2.8s var(--ease) infinite;
}
@keyframes nameLatido{ 50%{ transform:scale(1.03); } }
.pf[data-nameanim="float"] .pf-name{
  animation:nameFlota 5s var(--ease) infinite;
}
@keyframes nameFlota{ 50%{ transform:translateY(-5px); } }

/* Quien pide menos movimiento lo pide para todo, no solo para
   lo que ya existía cuando se escribió la regla de arriba. */
@media (prefers-reduced-motion: reduce){
  .pf[data-nameanim] .pf-name{ animation:none; }
}

/* ============================================================
   @USUARIO
   ============================================================ */

/* El botón de copiar no se ve como un botón: se ve como el
   @usuario, porque ES el @usuario. Lo único que cambia es el
   cursor, que es donde se descubre que se puede tocar. */
.pf-handle button{
  font:inherit; color:inherit; letter-spacing:inherit;
  background:none; border:0; padding:0; margin:0;
  cursor:copy;
}
.pf-handle button:hover{ color:var(--p-text); }
.pf-handle button:focus-visible{
  outline:2px solid var(--p-primary); outline-offset:3px; border-radius:3px;
}

/* El acuse de recibo. Va en un ::after y no en el texto para que
   copiar no cambie el ancho de la pieza: si el @usuario se
   encogiera y se estirara, el perfil entero daría un salto. */
.pf-handle[data-copiado="si"]{ position:relative; }
.pf-handle[data-copiado="si"]::after{
  content:"copiado";
  position:absolute; left:100%; top:50%;
  transform:translateY(-50%);
  margin-left:8px;
  font-size:10px; letter-spacing:.04em;
  color:var(--p-primary);
  white-space:nowrap;
  pointer-events:none;
}

/* Dentro del editor no se copia: se selecciona. Es la misma
   razón por la que ahí los enlaces del perfil tampoco navegan —
   un clic en la vista previa sirve para elegir la pieza que vas
   a editar, no para ejecutar lo que la pieza hace. */
.prev__stage .pf-handle button{ pointer-events:none; }

/* ============================================================
   BIOGRAFÍA
   ============================================================ */

/* Los saltos de línea que alguien escribió, respetados. Hasta
   ahora se guardaban y no se pintaban: el navegador colapsa el
   salto a un espacio y una bio de tres párrafos salía como un
   ladrillo. `pre-line` respeta los saltos y sigue colapsando los
   espacios de más, que es lo que se quiere — no `pre`, que
   conservaría también la sangría accidental de un copiar y
   pegar. */
.pf[data-biosaltos="on"] .pf-bio{ white-space:pre-line; }

/* El ancho de lectura. Los 46 caracteres de siempre siguen
   siendo el punto de partida: es la medida en la que una línea
   se lee sin perder el renglón. */
.pf-bio{ max-width:var(--u-biow, 46ch); }

/* Alineación propia, independiente de la del perfil. El margen
   acompaña al texto: con `max-width`, un párrafo alineado a la
   derecha que sigue pegado a la izquierda se lee como un fallo
   de maquetación. */
.pf[data-bioalign="left"]   .pf-bio{ text-align:left;   margin-inline:0 auto; }
.pf[data-bioalign="center"] .pf-bio{ text-align:center; margin-inline:auto; }
.pf[data-bioalign="right"]  .pf-bio{ text-align:right;  margin-inline:auto 0; }

/* Un enlace dentro de la bio se ve como un enlace, sin gritar. */
.pf-bio a{
  color:var(--p-text);
  text-decoration:underline;
  text-underline-offset:2px;
  text-decoration-color:color-mix(in srgb, var(--p-primary) 60%, transparent);
}
.pf-bio a:hover{ color:var(--p-primary); }
/* En el editor no navega: ahí el clic selecciona la pieza. */
.prev__stage .pf-bio a{ pointer-events:none; }

/* La etiqueta del contador de visitas. Va con el mismo tono que
   el número: es parte de la misma frase, no un añadido. */
.pf-views__l{ opacity:.75; }

/* ============================================================
   ANIMACIONES DE ENTRADA · lo que faltaba y lo nuevo
   ============================================================ */

/* `rise` es el valor por DEFECTO de `enterFx` desde siempre y no
   tenía regla a nivel de perfil: la animación existía —la usan el
   escalonado y las piezas sueltas— pero nadie la enganchaba al
   `.pf-stack`. O sea que el efecto de entrada por defecto no
   hacía nada en ningún perfil.

   Va aquí abajo y no arriba con las suyas a propósito: quien lea
   este bloque tiene que ver que es un arreglo, no una animación
   más. */
.pf[data-enter="rise"] .pf-stack{ animation:enterRise .6s var(--ease-out) both; }

/* --- glitch ------------------------------------------------
   Un salto de canal, no un temblor: los desplazamientos van con
   `steps(1)` en el original del avatar y aquí con paradas secas
   por la misma razón. Una interpolación suave lo convierte en un
   balanceo, que es otra cosa. */
@keyframes enterGlitch{
  0%   { opacity:0; transform:translate(-7px, 3px); filter:hue-rotate(75deg) saturate(2.2); }
  18%  { opacity:1; transform:translate(6px, -2px); filter:hue-rotate(-55deg) saturate(1.6); }
  34%  { transform:translate(-4px, 1px); filter:none; }
  52%  { transform:translate(3px, 0); }
  70%  { transform:translate(-1px, 0); }
  100% { transform:none; }
}
.pf[data-enter="glitch"] .pf-stack{ animation:enterGlitch .62s steps(1, end) both; }
.pf-stack > [data-anim="glitch"]{ animation:enterGlitch .62s steps(1, end) both; }

/* --- revelado 3D -------------------------------------------
   La perspectiva va en la propia transformación y no en el
   padre: puesta en `.pf-stack` afectaría a todo lo que hay
   dentro durante toda la vida de la página, no solo al segundo
   que dura la entrada. */
@keyframes enter3d{
  from{ opacity:0; transform:perspective(900px) rotateX(-26deg) translateY(20px); }
  to  { opacity:1; transform:perspective(900px) rotateX(0) translateY(0); }
}
.pf[data-enter="reveal3d"] .pf-stack{
  transform-origin:50% 0;
  animation:enter3d .85s var(--ease-out) both;
}
.pf-stack > [data-anim="reveal3d"]{
  transform-origin:50% 0;
  animation:enter3d .85s var(--ease-out) both;
}

/* Las nuevas se apagan con las de siempre: la regla de arriba
   nombra `.pf-stack` y `[data-anim]`, que ya las cubre, pero el
   `data-enter` del perfil no estaba contemplado. */
@media (prefers-reduced-motion:reduce){
  .pf[data-enter] .pf-stack{ animation:none !important; }
}
