/* =====================================================================
   LOLO - the Aux7 axolotl
   Everything the partials/mascot.ejs figure needs: colour, the five
   poses, and the idle motion. Kept out of tokens.css deliberately -
   tokens.css is PRD section 5.1's "lift the board's token block verbatim"
   and stays that. This is additive.

   Motion rules, all of them from PRD section 5.4's prohibitions:
     - Lolo never appears beside a countdown, and nothing here pulses,
       bounces urgently or counts down.
     - The celebration pose is gated by the CALLER to gamification mode
       "full". This file will animate a .mascot-cheer wherever one is
       rendered; deciding whether to render one is the template's job.
     - Every animation is inside a prefers-reduced-motion guard, so the
       reduce case is a still drawing rather than a fast one.
   ===================================================================== */

:root {
  /* Pale cream body against the iris gills: the leucistic axolotl
     colourway, remapped onto the brand ramp so Lolo sits inside the
     palette rather than beside it. */
  --mascot-body:   #f7efe4;
  --mascot-belly:  #fffaf3;
  --mascot-line:   var(--ink-800);
  --mascot-gill:   var(--iris-400);
  --mascot-frond:  var(--iris-300);
  --mascot-blush:  #e9b9c9;
  --mascot-eye:    var(--ink-900);
  --mascot-ring:   var(--iris-400);
}

.mascot {
  display: inline-block;
  width: var(--mascot-size, 96px);
  height: var(--mascot-size, 96px);
  flex-shrink: 0;
  line-height: 0;
}

.mascot svg {
  overflow: visible;
  display: block;
}

/* ---------- Ink ---------- */

.mascot .m-body,
.mascot .m-tail,
.mascot .m-arm path {
  fill: var(--mascot-body);
  stroke: var(--mascot-line);
  stroke-width: 1.6;
  stroke-linejoin: round;
}

.mascot .m-belly {
  fill: var(--mascot-belly);
  stroke: none;
  opacity: 0.85;
}

.mascot .m-gill path {
  fill: none;
  stroke: var(--mascot-gill);
  stroke-width: 3.4;
  stroke-linecap: round;
}

.mascot .m-frond {
  fill: var(--mascot-frond);
  stroke: var(--mascot-gill);
  stroke-width: 1.2;
}

.mascot .m-blush {
  fill: var(--mascot-blush);
  stroke: none;
  opacity: 0.6;
}

.mascot .m-eye { fill: var(--mascot-eye); stroke: none; }
.mascot .m-glint { fill: #fff; stroke: none; }

.mascot .m-eyes-closed path,
.mascot .m-mouth {
  fill: none;
  stroke: var(--mascot-eye);
  stroke-width: 1.9;
  stroke-linecap: round;
}

.mascot .m-mouth-o {
  fill: var(--mascot-eye);
  stroke: none;
  display: none;
}

.mascot .m-bubble {
  fill: var(--mascot-gill);
  opacity: 0.75;
}

/* Below about 32px the tail, arms and blush turn to mush and the figure
   stops reading as anything. The compact variant drops them and keeps the
   head, gills and face, which survives down to 20px. Measured in the
   preview harness, not assumed. */
.mascot-compact .m-tail,
.mascot-compact .m-arm,
.mascot-compact .m-blush,
.mascot-compact .m-belly,
.mascot-compact .m-glint { display: none; }
.mascot-compact .m-body { stroke-width: 2.4; }
.mascot-compact .m-gill path { stroke-width: 4.2; }

/* ---------- Tones ----------
   line    : one colour, inherits currentColor. For the offline banner and
             anywhere Lolo is 24px and sitting inside a line of text.
   inverse : on an ink-900 surface, where the ink outline vanishes. */

.mascot-tone-line .m-body,
.mascot-tone-line .m-tail,
.mascot-tone-line .m-arm path { fill: none; stroke: currentColor; stroke-width: 2; }
.mascot-tone-line .m-belly { display: none; }
.mascot-tone-line .m-gill path { stroke: currentColor; stroke-width: 2.6; opacity: 0.75; }
.mascot-tone-line .m-frond { fill: none; stroke: currentColor; stroke-width: 1.8; opacity: 0.75; }
.mascot-tone-line .m-blush { display: none; }
.mascot-tone-line .m-eye { fill: currentColor; }
.mascot-tone-line .m-glint { display: none; }
.mascot-tone-line .m-eyes-closed path,
.mascot-tone-line .m-mouth { stroke: currentColor; }

.mascot-tone-inverse {
  --mascot-line: rgba(255, 255, 255, 0.55);
  --mascot-eye: var(--ink-900);
  --mascot-gill: var(--iris-300);
  --mascot-frond: var(--iris-200);
  --mascot-ring: var(--iris-300);
}

/* ---------- Poses ----------
   Both eye groups ship in the DOM; exactly one is visible at a time. */

.mascot .m-eyes-closed { display: none; }
.mascot-rest .m-eyes-open { display: none; }
.mascot-rest .m-eyes-closed { display: block; }

/* Bubbles and rings are drawn in every pose and hidden in all but one, so
   the same figure serves every call site without a second template. */
.mascot .m-bubbles { display: none; }
.mascot .m-rings { display: none; }
.mascot-think .m-bubbles { display: block; }
.mascot-cheer .m-rings { display: block; }

/* Waving: the left arm swings out from the body. transform-box/origin are
   both needed for a transform on an SVG group to rotate about a point in
   user units rather than the viewport. */
.mascot .m-arm-l { transform-box: view-box; transform-origin: 23px 46px; }
.mascot .m-arm-r { transform-box: view-box; transform-origin: 41px 46px; }

.mascot-wave .m-arm-l { transform: rotate(-38deg); }
.mascot-cheer .m-arm-l { transform: rotate(-52deg); }
.mascot-cheer .m-arm-r { transform: rotate(52deg); }

/* Thinking: eyes drift up and to the side, bubbles appear. Used as the
   loading state while a T1 impact estimate is in flight (PRD section
   6.5's "under 6s, or T0") - a spinner says nothing, an axolotl blowing
   bubbles says "still working" without claiming a duration. */
.mascot-think .m-eyes-open { transform: translate(1.6px, -1.3px); }
.mascot-think .m-mouth { display: none; }
.mascot-think .m-mouth-o { display: block; }

.mascot-rest .m-body-group { transform: translateY(2px); }

/* Rings, drawn only for cheer. Each starts invisible and is driven by the
   animation; the still fallback below keeps one faint ring so a
   reduced-motion viewer sees the same composition, not a bare figure. */
.mascot .m-ring {
  fill: none;
  stroke: var(--mascot-ring);
  stroke-width: 2.4;
  opacity: 0;
}
.mascot-cheer .m-ring-2 { opacity: 0.3; transform: scale(1.25); }

/* ---------- Motion ----------
   Held behind BOTH .mascot-animate (the caller's choice) and the reduce
   query, so a still Lolo is always one class away. */

@media (prefers-reduced-motion: no-preference) {
  /* The float is the baseline idle. Slow enough that it reads as
     buoyancy rather than a bounce: 5.2s, which is well past the point
     where peripheral vision stops treating it as an alert. */
  .mascot-animate .m-body-group {
    animation: lolo-float 5200ms var(--ease-standard) infinite;
  }

  .mascot-animate.mascot-rest .m-body-group {
    animation: lolo-breathe 6400ms var(--ease-standard) infinite;
  }

  /* Gills drift as two groups, left and right, out of phase with each
     other and with the float. That is what stops the whole figure reading
     as one rigid sticker sliding up and down, at a cost of two animations
     per mascot rather than six. */
  .mascot-animate .m-gills { transform-box: view-box; }
  .mascot-animate .m-gills-l {
    transform-origin: 18px 27px;
    animation: lolo-gill 3400ms var(--ease-standard) infinite;
  }
  .mascot-animate .m-gills-r {
    transform-origin: 46px 27px;
    animation: lolo-gill-r 4100ms var(--ease-standard) infinite;
    animation-delay: -1500ms;
  }

  /* The blink. 7s apart, and the eyes are shut for 140ms of it. */
  .mascot-animate:not(.mascot-rest) .m-eyes-open {
    animation: lolo-blink 7000ms step-end infinite;
  }

  /* The header and footer marks are 28 to 32px. Float and gill drift are
     invisible at that size and were costing an animation each on every
     page in the product, so compact keeps only the blink. */
  .mascot-animate.mascot-compact .m-body-group,
  .mascot-animate.mascot-compact .m-gills { animation: none; }

  .mascot-animate.mascot-wave .m-arm-l {
    animation: lolo-wave 2400ms var(--ease-standard) infinite;
  }

  .mascot-animate.mascot-think .m-bubble-1 { animation: lolo-bubble 2600ms linear infinite; }
  .mascot-animate.mascot-think .m-bubble-2 { animation: lolo-bubble 2600ms linear infinite; animation-delay: -900ms; }
  .mascot-animate.mascot-think .m-bubble-3 { animation: lolo-bubble 2600ms linear infinite; animation-delay: -1800ms; }

  /* Cheer runs three times and stops. An infinite celebration is a
     nag. */
  .mascot-animate.mascot-cheer .m-ring-1 { animation: lolo-ripple 1600ms var(--ease-out) 3; }
  .mascot-animate.mascot-cheer .m-ring-2 { animation: lolo-ripple 1600ms var(--ease-out) 3; animation-delay: 300ms; }
  .mascot-animate.mascot-cheer .m-ring-3 { animation: lolo-ripple 1600ms var(--ease-out) 3; animation-delay: 600ms; }
  .mascot-animate.mascot-cheer .m-body-group {
    animation: lolo-hop 640ms var(--ease-out) 2;
  }
}

@keyframes lolo-float {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(-2.4px); }
}

@keyframes lolo-breathe {
  0%, 100% { transform: translateY(2px) scale(1); }
  50%      { transform: translateY(2.8px) scale(1.012); }
}

@keyframes lolo-gill {
  0%, 100% { transform: rotate(0deg); }
  50%      { transform: rotate(3.4deg); }
}

@keyframes lolo-gill-r {
  0%, 100% { transform: rotate(0deg); }
  50%      { transform: rotate(-3deg); }
}

@keyframes lolo-blink {
  0%, 96%  { opacity: 1; }
  97%, 99% { opacity: 0; }
  100%     { opacity: 1; }
}

@keyframes lolo-wave {
  0%, 55%, 100% { transform: rotate(-38deg); }
  67%           { transform: rotate(-62deg); }
  78%           { transform: rotate(-28deg); }
  89%           { transform: rotate(-58deg); }
}

@keyframes lolo-bubble {
  0%   { opacity: 0; transform: translate(0, 4px) scale(0.6); }
  25%  { opacity: 0.9; }
  100% { opacity: 0; transform: translate(4px, -14px) scale(1.1); }
}

@keyframes lolo-ripple {
  0%   { opacity: 0.55; transform: scale(0.35); }
  100% { opacity: 0; transform: scale(1.5); }
}

@keyframes lolo-hop {
  0%, 100% { transform: translateY(0); }
  35%      { transform: translateY(-5px); }
  60%      { transform: translateY(0.5px); }
}

.mascot .m-rings {
  transform-box: view-box;
  transform-origin: 32px 46px;
}
.mascot .m-ring {
  transform-box: view-box;
  transform-origin: 32px 46px;
}

/* =====================================================================
   RIPPLE RINGS, standalone
   The same celebration language away from the mascot: a ring that opens
   out of an element and fades. Used on the accepted screen and when a
   Ripple total changes. Confetti was the alternative and it is the wrong
   register for a product sold to hospices and crisis lines.
   ===================================================================== */

.ripple-burst {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

.ripple-burst > .ripple-ring {
  position: absolute;
  inset: 0;
  border-radius: var(--radius-pill);
  border: 2px solid var(--iris-400);
  opacity: 0;
  pointer-events: none;
}

@media (prefers-reduced-motion: no-preference) {
  .ripple-burst.is-bursting > .ripple-ring {
    animation: ripple-out 1400ms var(--ease-out) forwards;
  }
  .ripple-burst.is-bursting > .ripple-ring:nth-child(2) { animation-delay: 220ms; }
  .ripple-burst.is-bursting > .ripple-ring:nth-child(3) { animation-delay: 440ms; }
}

@keyframes ripple-out {
  0%   { opacity: 0.5; transform: scale(0.85); }
  100% { opacity: 0; transform: scale(1.9); }
}

/* =====================================================================
   MASCOT LAYOUT HELPERS
   ===================================================================== */

/* An empty state: Lolo above a line of honest copy. */
.mascot-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: var(--space-3);
  padding: var(--space-8) var(--space-5);
  color: var(--fg-muted);
}
.mascot-empty p { margin: 0; max-width: 42ch; line-height: var(--lh-relaxed); }
.mascot-empty .mascot-empty-title {
  font-weight: var(--weight-semibold);
  color: var(--fg);
  font-size: var(--text-md);
}

/* Lolo peering over the top edge of something. The wrapper clips the
   bottom of the figure so only the head and gills clear the line. */
.mascot-peek {
  overflow: hidden;
  height: calc(var(--mascot-size, 96px) * 0.62);
  display: block;
}
.mascot-peek .mascot { vertical-align: top; }

/* Inline, sitting in a line of text at text height. */
.mascot-inline {
  vertical-align: -0.35em;
  margin-right: var(--space-2);
}
