/* ── CoinLobster mascot (views/partials/cl-mascot.ejs) ──────────────────────
   One file for every character appearance: the 3D cut-out, its grounded
   shadow, the idle float, the pop / peek entrances, the pointer lean and the
   pose crossfade. Cut-outs are transparent, so the ground shadow is drawn
   here and never baked into the art.

   Layout:  .clm  >  .clm__halo
                  >  .clm__stage (idle float)  >  .clm__tilt (lean, hover)
                                               >  .clm__layer (stacked poses)
                  >  .clm__shadow (counter-breathes against the float)

   Motion is CSS-first and reduced-motion drops every animation while keeping
   the shadow drawn, so a still mascot still looks like it is standing on
   something. */

.clm {
    position: relative;
    display: inline-block;
    flex: none;
    line-height: 0;
    isolation: isolate;
    --clm-ratio: 1.6;
    --clm-lift: 0px;
    --clm-tilt: 0deg;
    --clm-float-dur: 7s;
    --clm-shadow-color: rgba(0, 0, 0, 0.72);
    --clm-ease: var(--ai-ease, cubic-bezier(.4, 0, .2, 1));
}

.clm__stage {
    position: relative;
    display: block;
    width: 100%;
    aspect-ratio: var(--clm-ratio);
}

.clm__tilt {
    position: absolute;
    inset: 0;
    display: block;
    transform-style: preserve-3d;
    transform:
        translateY(var(--clm-lift))
        rotateX(calc(var(--ly, 0) * -5deg))
        rotateY(calc(var(--lx, 0) * 7deg))
        rotate(var(--clm-tilt));
    transition: transform .45s var(--clm-ease);
    will-change: transform;
}

/* every pose sits in the same box; only opacity separates them */
.clm__layer {
    position: absolute;
    inset: 0;
    display: block;
    opacity: 0;
    transition: opacity 260ms var(--clm-ease);
}
.clm__layer.is-on { opacity: 1; }
.clm__layer img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: contain;
    object-position: center bottom;
    user-select: none;
    -webkit-user-drag: none;
    filter: drop-shadow(0 14px 26px rgba(0, 0, 0, .38));
}

/* grounded soft ellipse: the character reads as standing, not floating in a void */
.clm__shadow {
    position: absolute;
    left: 50%;
    bottom: -4%;
    width: 66%;
    height: 15%;
    min-height: 10px;
    transform: translateX(-50%) scale(1);
    border-radius: 50%;
    pointer-events: none;
    z-index: -1;
    /* two ellipses: a tight contact core where the feet touch, and a wide soft
       falloff around it. Near-black rather than the house navy, or it vanishes
       into the background it is meant to sit on. */
    background:
        radial-gradient(38% 62% at 50% 42%, var(--clm-shadow-color), rgba(0, 0, 0, 0) 76%),
        radial-gradient(closest-side, rgba(0, 0, 0, .42), rgba(0, 0, 0, .16) 52%, rgba(0, 0, 0, 0) 84%);
    filter: blur(2px);
    transition: transform .45s var(--clm-ease), opacity .45s var(--clm-ease);
}

/* the shadow is opt-out (shadow: false drops the element entirely) */
.clm--shadow .clm__shadow { display: block; }
/* stacked poses are swapped by opacity, so hint only that layer */
.clm--multi .clm__layer { will-change: opacity; }

/* soft glow behind a hero mascot (kept from the old .cl-mascot__halo) */
.clm__halo,
.cl-mascot__halo {
    position: absolute;
    left: 50%;
    top: 50%;
    width: 150%;
    height: 150%;
    transform: translate(-50%, -50%);
    z-index: -2;
    pointer-events: none;
    background: radial-gradient(circle, rgba(51, 194, 200, .20), rgba(238, 90, 44, .09) 40%, transparent 70%);
}

/* ── idle float: slow, small, and the shadow breathes the other way ───────── */
.clm--float .clm__stage { animation: clm-float var(--clm-float-dur) var(--clm-ease) infinite; }
.clm--float .clm__shadow { animation: clm-ground var(--clm-float-dur) var(--clm-ease) infinite; }
@keyframes clm-float {
    0%, 100% { transform: translateY(0); }
    50%      { transform: translateY(-2.6%); }
}
@keyframes clm-ground {
    0%, 100% { transform: translateX(-50%) scale(1);    opacity: 1; }
    50%      { transform: translateX(-50%) scale(.88);  opacity: .72; }
}

/* ── entrances: play once, never loop ─────────────────────────────────────── */
.clm--pop        { animation: clm-pop 620ms var(--clm-ease) both; }
.clm--peek-right { animation: clm-peek-right 700ms var(--clm-ease) both; }
.clm--peek-left  { animation: clm-peek-left 700ms var(--clm-ease) both; }
@keyframes clm-pop {
    0%   { opacity: 0; transform: scale(.85) translateY(8px); }
    62%  { opacity: 1; transform: scale(1.04) translateY(0); }
    100% { opacity: 1; transform: scale(1) translateY(0); }
}
@keyframes clm-peek-right {
    0%   { opacity: 0; transform: translateX(26%) rotate(6deg); }
    100% { opacity: 1; transform: translateX(0) rotate(0); }
}
@keyframes clm-peek-left {
    0%   { opacity: 0; transform: translateX(-26%) rotate(-6deg); }
    100% { opacity: 1; transform: translateX(0) rotate(0); }
}

/* ── hover: a small lift and tilt, shadow tightens under it ───────────────── */
@media (hover: hover) {
    .clm:hover { --clm-lift: -7px; --clm-tilt: -2.5deg; }
    .clm:hover .clm__shadow { transform: translateX(-50%) scale(.9); opacity: .8; }
}

/* ── reduced motion: nothing moves, the shadow is still drawn ─────────────── */
@media (prefers-reduced-motion: reduce) {
    .clm--float .clm__stage,
    .clm--float .clm__shadow,
    .clm--pop, .clm--peek-right, .clm--peek-left { animation: none !important; }
    .clm__tilt, .clm__shadow { transition: none !important; }
    .clm__layer { transition: none !important; }
    .clm:hover { --clm-lift: 0px; --clm-tilt: 0deg; }
}

/* ── corner emblem ────────────────────────────────────────────────────────
   .hero-mascot is the small top-right sticker on ~19 pages. Its ring lives in
   cl-deep.css; here the partial fits inside it: a square box from the inline
   width, the cut-out inset off the ring, no ground shadow (it is not standing
   on anything up there). */
.clm.hero-mascot { display: inline-block; overflow: hidden; }
.clm.hero-mascot .clm__stage { aspect-ratio: 1; }
.clm.hero-mascot .clm__layer { inset: 13%; }
.clm.hero-mascot .clm__layer img { filter: drop-shadow(0 6px 12px rgba(0, 0, 0, .4)); }
.clm.hero-mascot .clm__shadow { display: none; }

/* ── legacy aliases ────────────────────────────────────────────────────────
   .cl-mascot / .cl-mascot--lean / .cl-mascot__halo were the 2D mascot's class
   names and are still emitted so page CSS written against them keeps working.
   The pointer-lean handler in partials/cl-deep-js.ejs sets --lx / --ly on the
   root, which .clm__tilt reads. */
.cl-mascot { position: relative; display: inline-block; flex: none; line-height: 0; }
.clm--lean .clm__tilt,
.cl-mascot--lean .clm__tilt { will-change: transform; }

/* Pages not yet swept still write the 2D markup by hand:
     <span class="cl-mascot cl-mascot--float hero-mascot"><img src="..."></span>
   Those rules used to live in cl-deep.css. They are kept here verbatim and held
   off the 3D component with :not(.clm), which carries both class names. */
.cl-mascot:not(.clm) { filter: drop-shadow(0 18px 30px rgba(0, 0, 0, 0.55)); will-change: transform; }
.cl-mascot:not(.clm) img { display: block; width: 100%; height: auto; user-select: none; -webkit-user-drag: none; }
.cl-mascot--float:not(.clm) { animation: cl-float 6s var(--ai-ease, ease-in-out) infinite; }
@keyframes cl-float { 0%,100% { transform: translateY(0) rotate(-2deg); } 50% { transform: translateY(-12px) rotate(1deg); } }
@media (prefers-reduced-motion: reduce) {
    .cl-mascot--float:not(.clm) { animation: none !important; }
}
