/* ═══════════════════════════════════════════════════════
   DESKMATE NAVBAR GREETER
   Hourly mascot animation on the AI header button: the robot
   pops UP out of the circular button, waves, shows a speech
   bubble, then retracts. Rendered on a body-attached overlay
   stage (position:fixed) so no navbar container can clip it —
   the navbar itself is never resized or restyled.

   Layers: navbar .app-header is z-index 1025, Bootstrap modal
   backdrop is 1040 → the greeter sits at 1030 (above the bar,
   below any modal). All motion is transform/opacity only
   (GPU-composited, no layout).
   ═══════════════════════════════════════════════════════ */

/* Slightly larger face for the idle icon (32px circle, was a 19px
   glyph). Scoped to the new face image only — the .ai-header-icon
   geometry, background and badge are untouched. */
.ai-header-icon img.deskmate-face {
    width: 22px;
    height: 22px;
}

/* While the pop-out robot is on stage the idle face fades out, so
   the button reads as the empty "bowl" the robot climbed out of.
   The fade back in is started while the robot is still sliding home,
   so the retract crossfades into the idle face with no empty-button
   frame in between. */
.ai-header-icon img.deskmate-face {
    transition: opacity 0.25s ease;
}

.ai-header-icon.dm-away img.deskmate-face {
    opacity: 0;
}

/* ─── Stage (the clip window above the button) ────────
   Sized/positioned from the button's live bounding rect in JS:
   top of viewport down to ~72% into the circle. overflow:hidden
   is the emergence mask — the robot slides up inside it. */
.deskmate-stage {
    position: fixed;
    top: 0;
    z-index: 1030;
    overflow: hidden;
    pointer-events: none;
}

.deskmate-pop {
    position: absolute;
    left: 50%;
    top: 2px;
    /* --dm-y is set inline to the stage height = fully hidden. The robot also
       grows slightly as it rises (squash-and-stretch), anchored at its feet. */
    transform: translate(-50%, var(--dm-y, 40px)) scale(0.92) translateZ(0);
    transform-origin: 50% 100%;
    /* Rise: ease-out with a small overshoot — kept under the 2px headroom
       (top:2px) so the head never touches the clip edge mid-bounce. */
    transition: transform 0.45s cubic-bezier(0.34, 1.3, 0.64, 1);
    will-change: transform;
    /* Depth shadow + a soft brand-green ambient glow. No hard rim: an
       outline was tried and read as a cartoon stroke, which the design
       does not want. */
    filter: drop-shadow(0 2px 6px rgba(3, 32, 52, 0.45))
            drop-shadow(0 0 8px rgba(129, 181, 4, 0.28));
}

/* LIGHT theme (the app sets body.dark-mode ONLY in dark mode): the green
   glow is invisible on a near-white bar, so spend the budget on a soft
   neutral shadow instead — enough to lift the white robot off the light
   navbar, still no drawn outline. */
body:not(.dark-mode) .deskmate-pop {
    filter: drop-shadow(0 1px 2px rgba(3, 32, 52, 0.28))
            drop-shadow(0 4px 10px rgba(3, 32, 52, 0.22));
}

.deskmate-pop.dm-up {
    /* --dm-up-y (set inline per run) parks the robot PARTIALLY out — head
       and hand visible, body still in the button — instead of fully risen. */
    transform: translate(-50%, var(--dm-up-y, 0px)) scale(1) translateZ(0);
}

/* ─── Retract (the "going home" beat) ─────────────────
   Not a bare slide-down: a tiny anticipation hop (breathe up), then a
   dive that DEcelerates into the button so the robot settles rather
   than drops, while its shadow/glow softly dissolve. Starts from the
   PARTIAL rest position (--dm-up-y), the same spot dm-up parks at.
   An animation (not a transition) so the multi-beat path reads as one
   motion. */
.deskmate-pop.dm-retract {
    animation: dmRetract 0.6s cubic-bezier(0.55, 0, 0.6, 1) 1 forwards;
    filter: drop-shadow(0 0 1px rgba(3, 32, 52, 0))
            drop-shadow(0 0 2px rgba(129, 181, 4, 0));
    transition: filter 0.45s ease;
}

@keyframes dmRetract {
    0%   { transform: translate(-50%, var(--dm-up-y, 0px)) scale(1) translateZ(0); }
    16%  { transform: translate(-50%, calc(var(--dm-up-y, 0px) - 1.5px)) scale(1.03) translateZ(0); }
    100% { transform: translate(-50%, var(--dm-y, 40px)) scale(0.9) translateZ(0); }
}

/* Landing ripple: as the robot settles back in, the button emits one
   soft green pulse — the visual "touch-down". One-shot, then removed. */
.ai-header-icon.dm-land {
    animation: dmLand 0.45s ease-out 1;
}

@keyframes dmLand {
    0% {
        box-shadow: 0 2px 8px rgba(129, 181, 4, 0.4),
                    inset 0 1px 0 rgba(255, 255, 255, 0.25),
                    0 0 0 0 rgba(129, 181, 4, 0.45);
    }
    100% {
        box-shadow: 0 2px 8px rgba(129, 181, 4, 0.4),
                    inset 0 1px 0 rgba(255, 255, 255, 0.25),
                    0 0 12px 7px rgba(129, 181, 4, 0);
    }
}

.deskmate-pop svg {
    display: block;
}

/* ─── Wave ────────────────────────────────────────────
   The arm group rotates around its shoulder. transform-box lets
   the origin be expressed against the arm's own bounds. */
.dm-arm {
    transform-box: fill-box;
    transform-origin: 16% 88%;
}

.deskmate-stage.dm-wave .dm-arm {
    /* ONE continuous pass with decaying amplitude — looping a short keyframe
       N times parks the arm at 0° between iterations, which reads as stutter.
       Three swings that settle naturally instead. */
    animation: dmWave 1.05s ease-in-out 1 both;
}

@keyframes dmWave {
    0%   { transform: rotate(0deg); }
    15%  { transform: rotate(18deg); }
    35%  { transform: rotate(-14deg); }
    55%  { transform: rotate(13deg); }
    75%  { transform: rotate(-9deg); }
    100% { transform: rotate(0deg); }
}

/* Slight head bounce while waving (subtle, transform-only), timed to the
   same 1.05s pass as the arm so they settle together. */
.dm-head {
    transform-box: fill-box;
    transform-origin: 50% 100%;
}

.deskmate-stage.dm-wave .dm-head {
    animation: dmHeadBob 1.05s ease-in-out 1 both;
}

@keyframes dmHeadBob {
    0%, 100% { transform: translateY(0); }
    22%      { transform: translateY(-1.6px); }
    48%      { transform: translateY(-0.3px); }
    70%      { transform: translateY(-1.1px); }
}

/* ─── Speech bubble ───────────────────────────────────
   Hangs just below the navbar with its pointer aimed up at the
   robot (matches the concept frames). Fade + scale in/out. */
.deskmate-bubble {
    position: fixed;
    z-index: 1030;
    max-width: 220px;
    background: #ffffff;
    color: #17323f;
    border-radius: 12px;
    padding: 10px 14px 11px;
    box-shadow: 0 10px 30px rgba(4, 42, 68, 0.22), 0 2px 8px rgba(4, 42, 68, 0.14);
    font-size: 13px;
    line-height: 1.4;
    opacity: 0;
    transform: scale(0.85) translateY(-4px) translateZ(0);
    transform-origin: top right;
    /* Base transition = the EXIT path (class removed): a plain quick ease-in.
       The springy overshoot lives only on .dm-show, so entering bounces but
       leaving just slips away — reversing a spring reads as rubbery. */
    transition: opacity 0.2s ease-in, transform 0.2s ease-in;
    pointer-events: none;
    will-change: transform, opacity;
}

.deskmate-bubble.dm-show {
    opacity: 1;
    transform: scale(1) translateY(0) translateZ(0);
    transition: opacity 0.28s ease-out, transform 0.32s cubic-bezier(0.34, 1.3, 0.64, 1);
}

.deskmate-bubble-arrow {
    position: absolute;
    top: -5px;
    width: 12px;
    height: 12px;
    background: #ffffff;
    border-radius: 2px;
    transform: rotate(45deg);
}

.deskmate-bubble-title {
    font-weight: 600;
}

.deskmate-bubble-title b {
    color: var(--ai-green, #81B504);
    font-weight: 700;
}

.deskmate-bubble-beta {
    display: inline-block;
    vertical-align: middle;
    position: relative;
    top: -1px;
    margin: 0 2px;
    background: linear-gradient(45deg, #a0c34e, #82b900);
    color: #fff;
    font-size: 9px;
    font-weight: 700;
    letter-spacing: 0.5px;
    line-height: 1;
    padding: 2px 6px;
    border-radius: 9px;
    text-transform: uppercase;
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);
}

.deskmate-bubble-sub {
    color: #5b7482;
    font-size: 12.5px;
    margin-top: 1px;
}

/* ─── Reduced motion ──────────────────────────────────
   JS already skips the robot entirely and only fades the bubble;
   this is defense in depth if the classes ever get applied. */
@media (prefers-reduced-motion: reduce) {
    .deskmate-pop,
    .deskmate-bubble {
        transition-duration: 0.01ms;
    }

    .deskmate-stage.dm-wave .dm-arm,
    .deskmate-stage.dm-wave .dm-head,
    .deskmate-pop.dm-retract,
    .ai-header-icon.dm-land {
        animation: none;
    }
}
