/* Reward Studio v2 — static production CSS.
   Per-cosmetic dynamic values (frame ring colors/type) are injected via
   wp_head by nxp_cosmetics_emit_dynamic_css() in inc/reward-studio/renderers.php. */

/* ---------- Avatar frame wrapper ---------- */
.nxp-cosmetic-frame {
    position: relative;
    display: inline-block;
    line-height: 0;
    padding: var(--nxp-frame-pad, 2px);
    transform-origin: center;
}
.nxp-cosmetic-frame::before {
    content: "";
    position: absolute;
    inset: 0;
    z-index: 0;
    clip-path: inherit;
    -webkit-mask-image: inherit;
    mask-image: inherit;
    border-radius: inherit;
}
.nxp-cosmetic-frame > img,
.nxp-cosmetic-frame > .nxp-cosmetic-avatar-fallback {
    position: relative;
    z-index: 1;
    display: block;
    object-fit: cover;
    clip-path: inherit;
    -webkit-mask-image: inherit;
    mask-image: inherit;
    border-radius: inherit;
    transform: scale(var(--nxp-inner-scale, 1));
}
.nxp-cosmetic-avatar-fallback {
    background: #374151;
    color: #e5e7eb;
    text-align: center;
    font-weight: 700;
}

/* ---------- Avatar shapes — circle and square only, by design ---------- */
.nxp-shape--circle { border-radius: 50%; }
.nxp-shape--square  { border-radius: 20%; }

/* No frame equipped: a plain neutral-grey ring, never a bare unframed avatar. */
.nxp-frame--none::before { background: var(--nxp-border-rw); }

/* The Reward Studio frame ring is the single source of truth for the ring
   around an avatar — suppress the older rank-tier border/glow
   (.kts-rank-wrap, from xp-system.php) wherever it wraps one, so a user's
   equipped frame (or the grey default) is never doubled up with a
   mismatched rank-colored square-ish border underneath it. */
.kts-rank-wrap:has(.nxp-cosmetic-frame)::after { display: none; }

/* ---------- Frame ring animations (shared keyframes; per-frame colors are inline/dynamic) ---------- */
@keyframes nxp-frame-spin    { from { transform: rotate(0deg); } to { transform: rotate(360deg); } }
@keyframes nxp-frame-pulse   { 0%,100% { opacity: 1; } 50% { opacity: .55; } }
@keyframes nxp-frame-shimmer { 0% { background-position: 200% 0; } 100% { background-position: -200% 0; } }
@keyframes nxp-frame-flicker { 0%,19%,21%,23%,54%,56%,100% { opacity: 1; } 20%,22%,55% { opacity: .4; } }
@keyframes nxp-glow-pulse    { 0%,100% { filter: brightness(1); } 50% { filter: brightness(1.5); } }
@keyframes nxp-glow-wave     { 0% { box-shadow: 0 0 6px currentColor; } 50% { box-shadow: 0 0 16px currentColor; } 100% { box-shadow: 0 0 6px currentColor; } }
@keyframes nxp-glow-flicker  { 0%,19%,21%,23%,54%,56%,100% { opacity: 1; } 20%,22%,55% { opacity: .5; } }
@keyframes nxp-glow-huespin  { from { filter: hue-rotate(0deg); } to { filter: hue-rotate(360deg); } }

/* Because conic-gradient background needs a real rotating element for spin,
   the ::before itself is what rotates (not the whole frame) so the inner
   avatar image stays upright. */
.nxp-cosmetic-frame::before { will-change: transform, opacity, background-position; }

/* ---------- Frame engine v3: layered effects ----------
   ring (::before) · halo (wrapper box-shadow / .nxp-frame-halo child) ·
   motion (wrapper transform — moving the avatar IS the effect) ·
   morph (wrapper border-radius; ring + img inherit) ·
   overlay (.nxp-frame-overlay child above the avatar). */

@keyframes nxp-fr-spin-ccw   { to { transform: rotate(-360deg); } }
@keyframes nxp-fr-pulse-ring { 0% { transform: scale(.85); opacity: .9; } 100% { transform: scale(1.45); opacity: 0; } }
@keyframes nxp-fr-neon {
    from { box-shadow: 0 0 10px currentColor, 0 0 20px currentColor; }
    to   { box-shadow: 0 0 2px currentColor, 0 0 6px currentColor; }
}
@keyframes nxp-fr-fire {
    from { box-shadow: 0 0 6px currentColor, 0 -6px 12px currentColor, inset 0 -4px 8px currentColor; }
    to   { box-shadow: 0 0 10px currentColor, 0 -12px 20px currentColor, inset 0 -6px 12px currentColor; }
}
@keyframes nxp-fr-aura {
    0%, 100% { box-shadow: 0 0 8px currentColor, inset 0 0 6px currentColor; }
    50%      { box-shadow: 0 0 18px currentColor, inset 0 0 12px currentColor; }
}
@keyframes nxp-fr-float     { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-6px); } }
@keyframes nxp-fr-heartbeat { 0%, 100% { transform: scale(1); } 15% { transform: scale(1.12); } 30% { transform: scale(1); } 45% { transform: scale(1.12); } }
@keyframes nxp-fr-coin      { from { transform: rotateY(0deg); } to { transform: rotateY(360deg); } }
@keyframes nxp-fr-bounce {
    0%, 100% { transform: translateY(0); animation-timing-function: cubic-bezier(.8,0,1,1); }
    50%      { transform: translateY(5px); animation-timing-function: cubic-bezier(0,0,.2,1); }
}
@keyframes nxp-fr-morph-blob {
    0%, 100% { border-radius: 40% 60% 70% 30% / 40% 50% 60% 50%; }
    34%      { border-radius: 70% 30% 50% 50% / 30% 30% 70% 70%; }
    67%      { border-radius: 100% 60% 60% 100% / 100% 100% 60% 60%; }
}
@keyframes nxp-fr-morph-wild {
    0%, 100% { border-radius: 50%; }
    25%      { border-radius: 31% 69% 26% 74%; }
    50%      { border-radius: 74% 26% 69% 31%; }
    75%      { border-radius: 35% 65% 42% 58%; }
}
@keyframes nxp-fr-matrix  { 0% { background-position: 0 -100%; } 100% { background-position: 0 100%; } }
@keyframes nxp-fr-radar   { to { transform: rotate(360deg); } }
@keyframes nxp-fr-svgdash {
    0%   { stroke-dasharray: 10 280; stroke-dashoffset: 0; }
    50%  { stroke-dasharray: 140 150; stroke-dashoffset: -90; }
    100% { stroke-dasharray: 10 280; stroke-dashoffset: -290; }
}

/* Halo child — only rendered for the pulse-ring effect. */
.nxp-frame-halo {
    content: "";
    position: absolute;
    inset: 0;
    z-index: 0;
    border-radius: inherit;
    clip-path: inherit;
    border: 2px solid currentColor;
    pointer-events: none;
}

/* Overlay child — plays ON TOP of the avatar, clipped to the frame shape. */
.nxp-frame-overlay {
    position: absolute;
    inset: 0;
    z-index: 2;
    border-radius: inherit;
    clip-path: inherit;
    -webkit-mask-image: inherit;
    mask-image: inherit;
    overflow: hidden;
    pointer-events: none;
}
/* svg-dash draws OUTSIDE the avatar edge, so it isn't clipped/masked. */
.nxp-ovfx--svg-dash { overflow: visible; clip-path: none; -webkit-mask-image: none; mask-image: none; border-radius: 0; inset: calc(-1 * var(--nxp-frame-pad, 2px)); }
.nxp-ovfx--svg-dash svg { width: 100%; height: 100%; display: block; transform: rotate(-90deg); }
.nxp-ovfx--svg-dash circle {
    fill: none;
    stroke-width: 4;
    stroke-linecap: round;
    animation: nxp-fr-svgdash var(--nxp-ov-speed, 3s) ease-in-out infinite;
}

/* Motion — transform animation of the whole frame (avatar included, by design). */
.nxp-motion--float     { animation: nxp-fr-float var(--nxp-motion-speed, 3s) ease-in-out infinite; }
.nxp-motion--heartbeat { animation: nxp-fr-heartbeat var(--nxp-motion-speed, 1.5s) ease-in-out infinite; }
.nxp-motion--coin-spin { animation: nxp-fr-coin var(--nxp-motion-speed, 3s) linear infinite; transform-style: preserve-3d; }
.nxp-motion--bounce    { animation: nxp-fr-bounce var(--nxp-motion-speed, 2s) infinite; }

/* Shape morph — overrides the static shape radius (declared after .nxp-shape--*). */
.nxp-morph--blob { border-radius: 45%; animation: nxp-fr-morph-blob var(--nxp-morph-speed, 6s) ease-in-out infinite alternate; }
.nxp-morph--wild { border-radius: 50%; animation: nxp-fr-morph-wild var(--nxp-morph-speed, 4s) linear infinite; }

/* ---------- Level-hex overlay (positioned relative to the avatar wrap) ---------- */
.nxp-cosmetic-avatar-wrap { position: relative; display: inline-block; line-height: 0; }
.nxp-cosmetic-level-hex {
    position: absolute;
    bottom: -3px;
    right: -3px;
    z-index: 2;
    min-width: 25px;
    height: 18px;
    padding: 0 3px;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 10px;
    font-weight: 700;
    color: #fff;
    background: #4b5563;
    clip-path: polygon(50% 0%,100% 25%,100% 75%,50% 100%,0% 75%,0% 25%);
}

/* ---------- Titles ---------- */
.nxp-user-title { display: inline-block; font-size: .85em; }
/* Animated titles are wrapped so the filter/opacity animation never sits on
   the background-clip:text element itself (Chrome breaks the clip there). */
.nxp-title-animwrap { display: inline-block; line-height: inherit; }
@keyframes nxp-title-pulse   { 0%,100% { opacity: 1; } 50% { opacity: .6; } }
@keyframes nxp-title-shimmer { 0% { filter: brightness(1); } 50% { filter: brightness(1.4); } 100% { filter: brightness(1); } }
@keyframes nxp-title-rainbow { 0% { filter: hue-rotate(0deg); } 100% { filter: hue-rotate(360deg); } }
.nxp-title-anim--pulse    { animation: nxp-title-pulse 2s ease-in-out infinite; }
.nxp-title-anim--shimmer  { animation: nxp-title-shimmer 2.4s ease-in-out infinite; }
.nxp-title-anim--rainbow  { animation: nxp-title-rainbow 3s linear infinite; }

/* ---------- Badges ---------- */
.nxp-badges-row { display: inline-flex; gap: 4px; align-items: center; vertical-align: middle; }
.nxp-badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: 6px;
    background: color-mix(in srgb, var(--nxp-badge-bg, #1f2937) calc(var(--nxp-badge-bg-opacity, 1) * 100%), transparent);
}
.nxp-badge--small  { width: 16px; height: 16px; font-size: 9px; }
.nxp-badge--medium { width: 20px; height: 20px; font-size: 11px; }
.nxp-badge--large  { width: 26px; height: 26px; font-size: 14px; }
.nxp-badge img { width: 70%; height: 70%; object-fit: contain; }

/* Text (with or without an icon) needs a pill shape instead of a fixed square. */
.nxp-badge--has-text {
    width: auto;
    height: auto;
    border-radius: 999px;
    padding: 2px 8px 2px 6px;
    gap: 4px;
}
.nxp-badge--has-text.nxp-badge--small  { padding: 1px 6px 1px 5px; }
.nxp-badge--has-text.nxp-badge--large  { padding: 3px 10px 3px 7px; }
.nxp-badge-text { font-weight: 700; white-space: nowrap; line-height: 1; }

/* Full-image badges (display_mode 'image', the default when an image is set):
   the upload IS the whole badge — no square box, no crop, no padding. Width
   follows the image's natural aspect ratio; only row height is fixed so
   comment rows stay tidy: Username [====badge====] */
.nxp-badge--image {
    width: auto;
    height: 20px;
    border-radius: 0;
    background: transparent !important;
    padding: 0;
}
.nxp-badge--image.nxp-badge--small  { height: 16px; }
.nxp-badge--image.nxp-badge--medium { height: 20px; }
.nxp-badge--image.nxp-badge--large  { height: 28px; }
.nxp-badge--image img { width: auto; height: 100%; max-width: 140px; object-fit: contain; }
.nxp-badge--image.nxp-badge--has-text { border-radius: 0; padding: 0; gap: 5px; }
@keyframes nxp-badge-pulse  { 0%,100% { transform: scale(1); } 50% { transform: scale(1.12); } }
@keyframes nxp-badge-bounce { 0%,100% { transform: translateY(0); } 50% { transform: translateY(-2px); } }
.nxp-badge-anim--pulse  { animation: nxp-badge-pulse 1.6s ease-in-out infinite; }
.nxp-badge-anim--bounce { animation: nxp-badge-bounce 1.2s ease-in-out infinite; }

/* ═══════════════════════════════════════════════════════════════
   SHARED READER HERO — nxp_render_profile_hero() (inc/profile-hero.php)
   Used by the reader profile, dashboard, and collection pages. Single
   source of truth — do not re-duplicate these rules in a page template.
═══════════════════════════════════════════════════════════════ */
:root { --nxp-rp-color: #9CA3AF; --nxp-rp-glow: transparent; }

.nxp-rp-hero {
    border: 1px solid var(--nxp-border);
    border-radius: 20px;
    overflow: hidden;
    margin-bottom: 16px;
    position: relative;
}
.nxp-rp-hero__banner {
    position: absolute; top: 0; left: 0; width: 100%; height: 110px;
    z-index: 0; pointer-events: none;
}
.nxp-rp-hero__body { padding: 50px 24px 24px; position: relative; z-index: 1; }
.nxp-rp-hero__top {
    display: flex; align-items: center;
    text-align: left; gap: 10px;
    margin-bottom: 14px;
}
.nxp-rp-avatar-wrap { position: relative; flex-shrink: 0; line-height: 0; }
.nxp-rp-hero__info { min-width: 0; max-width: 100%; line-height:1.2;}
.nxp-rp-name {
    font-size: 1.4rem; font-weight: 800; color: var(--nxp-text);
    margin: 0 0 2px; line-height: 1.2;
    display: flex; align-items: center; justify-content: flex-start; gap: 8px; min-width: 0;
}
.nxp-rp-name-text { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.nxp-rp-rank-row {
    display: flex; align-items: center; justify-content: flex-start; gap: 8px; flex-wrap: wrap; margin-top: 4px;
}

/* ── Hero actions — settings/public-profile icons + like button, grouped
   into one row floating in the hero's top-right corner ────────────────── */
.nxp-rp-hero__actions {
    position: absolute; top: 10px; right: 14px; z-index: 2;
    display: flex; align-items: center; gap: 6px;
}
.nxp-ud-hero-action {
    display: inline-flex; align-items: center; justify-content: center;
    width: 32px; height: 32px; border-radius: 8px;
    background: var(--nxp-surface); color: var(--nxp-text-2);
    font-size: 0.8rem; text-decoration: none;
    border: 1px solid var(--nxp-border-rw);
    transition: background 0.15s, color 0.15s;
}
.nxp-ud-hero-action:hover { background: var(--nxp-bg-2); color: var(--nxp-text); }
.nxp-rp-like-btn {
    display: inline-flex; align-items: center; gap: 6px;
    padding: 5px 12px; border-radius: 99px;
    font-size: 0.76rem; font-weight: 700;
    color: var(--nxp-text-2); background: var(--nxp-surface);
    border: 1px solid var(--nxp-border-rw); cursor: pointer;
    transition: color 0.15s, border-color 0.15s, background 0.15s;
}
.nxp-rp-like-btn:hover { border-color: #f06767; color: #f06767; }
.nxp-rp-like-btn i { font-size: 0.82rem; }
.nxp-rp-like-btn.is-liked {
    color: #f06767; border-color: color-mix(in srgb, #f06767 40%, transparent);
    background: color-mix(in srgb, #f06767 8%, var(--nxp-bg-3));
}
.nxp-rp-like-btn--readonly { cursor: default; color: var(--nxp-text-2); }
.nxp-rp-like-btn--readonly:hover { border-color: var(--nxp-border); color: var(--nxp-text-2); }
.nxp-rp-like-count { font-variant-numeric: tabular-nums; }

.nxp-rp-bio {
    font-size: 0.88rem; color: var(--nxp-text-2); line-height: 1.55; margin: 0 0 16px;
    /* max-width: 520px; */
}

/* XP bar */
.nxp-rp-xp { border: 1px solid var(--nxp-border); border-radius: 12px; padding: 14px 16px; }
.nxp-rp-xp__top { display: flex; justify-content: space-between; align-items: baseline; margin-bottom: 8px; }
.nxp-rp-xp__label { font-size: 0.78rem; font-weight: 700; color: var(--nxp-rp-color); }
.nxp-rp-xp__nums  { font-size: 0.72rem; color: var(--nxp-text-3); }
.nxp-rp-xp__bar   { height: 8px; background: var(--nxp-bg-2); border-radius: 99px; overflow: hidden; margin-bottom: 6px; }
.nxp-rp-xp__fill  {
    height: 100%; border-radius: 99px;
    background: linear-gradient(90deg, color-mix(in srgb, var(--nxp-rp-color) 70%, #fff), var(--nxp-rp-color));
    transition: width 1.2s cubic-bezier(0.34, 1.56, 0.64, 1);
}
.nxp-rp-xp__meta  { display: flex; justify-content: space-between; font-size: 0.7rem; color: var(--nxp-text-3); }

.nxp-rp-joined { font-size: 0.72rem; color: var(--nxp-text-4); text-align: right; margin-top: 8px; }

/* Editable-avatar overlay — the avatar looks completely normal at rest;
   hovering (or the label itself) fades in a "change avatar" camera overlay
   over the whole image, click opens the file picker. */
.nxp-rp-avatar-cam-overlay {
    position: absolute; inset: 0; z-index: 3; border-radius: 50%;
    display: flex; align-items: center; justify-content: center;
    background: rgba(0,0,0,0.5); color: #fff;
    font-size: 1.1rem; cursor: pointer;
    opacity: 0; transition: opacity 0.15s;
}
.nxp-rp-avatar-wrap:hover .nxp-rp-avatar-cam-overlay,
.nxp-rp-avatar-cam-overlay:focus-visible { opacity: 1; }

@media (max-width: 600px) {
    .nxp-rp-hero__banner { height: 84px; }
    .nxp-rp-hero__body { padding: 45px 14px 16px; }
    .nxp-rp-hero__actions { top: 10px; right: 10px; gap: 6px; }
    .nxp-rp-name { font-size: 1.15rem; gap: 6px; }
    .nxp-rp-bio { font-size: 0.8rem; }
    .nxp-rp-joined { font-size: 0.66rem; }
}

/* NOTE: no prefers-reduced-motion override here, deliberately. Windows'
   "Animation effects" accessibility toggle (off by default on some setups)
   makes browsers report reduced motion, and an override here silently
   blanked EVERY cosmetic animation for those visitors — frames, titles,
   badges — which are the core product of this site's gamification. */
