/* =============================================================================
 * flourish.css — the shared micro-celebration vocabulary.
 * Paired with assets/js/components/flourish.js (window.KeeprFlourish).
 *
 * The effect belongs to the ELEMENT that was acted on: it gives a little
 * press-and-bounce (a transform on the element itself) and a clean success
 * ring blooms out from its own rounded edge. Completions add sparkles leaving
 * the element; milestones add a confetti burst. Nothing floats separately from
 * the thing that was clicked.
 *
 * Keepr is light-only, so there is no dark theme here; every colour comes from
 * the base.css tokens. All motion is gated behind prefers-reduced-motion at the
 * bottom of this file AND in the JS (which builds only a still outline under
 * reduced motion), so a reduced-motion user gets a motionless highlight.
 *
 * The ring/sparkle overlay is aria-hidden + pointer-events:none: decorative
 * only, never traps a click, never takes focus. The real confirmation the user
 * (and a screen reader) relies on is still the toast / flash banner underneath.
 * ========================================================================== */

/* The single fixed layer the ring + sparkles render into. One per page, created
   lazily by the JS. Sits above page content but below the send-completion
   popover (10600); pointer-events:none means its z-index only decides what it
   is drawn OVER, never what it blocks. */
.kfl-layer {
    position: fixed;
    inset: 0;
    z-index: 10550;
    pointer-events: none;
    overflow: hidden;
}

/* -------------------------------------------------------------------------
 * The bounce — a brief press-and-pop on the TARGET element itself. This is the
 * clearest "it reacted": the button/checkbox/toggle you clicked springs a
 * little. A transform that resets when the class is removed.
 * ---------------------------------------------------------------------- */
.kfl-bump { animation: kflBump 0.44s cubic-bezier(0.2, 0.7, 0.3, 1.3) both; }
.kfl-bump.kfl-bump-strong { animation-name: kflBumpStrong; }

/* -------------------------------------------------------------------------
 * The ring — an overlay box positioned exactly over the element (same size and
 * border-radius), whose edge lights up and blooms outward via an expanding
 * box-shadow. Fixed-pixel spread, so the pulse looks the same on a wide button
 * and a small checkbox. No fill, so it never tints the control.
 * ---------------------------------------------------------------------- */
.kfl-ring {
    position: absolute;
    box-sizing: border-box;
    pointer-events: none;
    will-change: box-shadow, opacity;
    animation: kflRing 0.64s cubic-bezier(0.2, 0.7, 0.3, 1) both;
}
.kfl-ring.kfl-ring-strong { animation-name: kflRingStrong; }

/* Sparkles — little four-point stars that leave from the element's own edge
   and fly outward. The JS sets the origin (left/top) and the travel
   (--dx / --dy), spin (--r) and per-particle delay via inline custom
   properties (CSP allows inline styles). */
.kfl-spark {
    position: absolute;
    width: 13px;
    height: 13px;
    transform: translate(-50%, -50%);
    color: var(--kfl-spark-color, var(--color-success, #5fb87a));
    will-change: transform, opacity;
    animation: kflSpark 0.6s cubic-bezier(0.15, 0.7, 0.35, 1) var(--kfl-delay, 0s) both;
}
.kfl-spark svg { display: block; width: 100%; height: 100%; }

/* The confetti canvas — full viewport, drawn by the JS for ~1.3s then removed. */
.kfl-canvas {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    pointer-events: none;
}

/* Glow — a soft bloom painted on the TARGET element itself (a toggle, a
   checkbox), the truest "it is the element". Only a box-shadow, so the element
   keeps its own layout. */
.kfl-glow {
    animation: kflGlow 0.9s cubic-bezier(0.2, 0.7, 0.3, 1) both;
    border-radius: inherit;
}

@keyframes kflBump {
    0%   { transform: scale(1); }
    35%  { transform: scale(1.045); }
    100% { transform: scale(1); }
}
@keyframes kflBumpStrong {
    0%   { transform: scale(1); }
    30%  { transform: scale(1.07); }
    62%  { transform: scale(0.99); }
    100% { transform: scale(1); }
}
@keyframes kflRing {
    0%   { box-shadow: 0 0 0 2px rgba(95, 184, 122, 0.6); opacity: 1; }
    100% { box-shadow: 0 0 0 11px rgba(95, 184, 122, 0); opacity: 0; }
}
@keyframes kflRingStrong {
    0%   { box-shadow: 0 0 0 3px rgba(95, 184, 122, 0.62); opacity: 1; }
    100% { box-shadow: 0 0 0 18px rgba(95, 184, 122, 0); opacity: 0; }
}
@keyframes kflSpark {
    0%   { transform: translate(-50%, -50%) translate(0, 0) scale(0.2) rotate(0deg); opacity: 0; }
    25%  { opacity: 1; }
    100% { transform: translate(-50%, -50%) translate(var(--dx, 0), var(--dy, 0)) scale(1) rotate(var(--r, 90deg)); opacity: 0; }
}
@keyframes kflGlow {
    0%   { box-shadow: 0 0 0 0 rgba(95, 184, 122, 0.55); }
    70%  { box-shadow: 0 0 0 7px rgba(95, 184, 122, 0); }
    100% { box-shadow: 0 0 0 0 rgba(95, 184, 122, 0); }
}

/* -------------------------------------------------------------------------
 * Reduced motion: a still, motionless success outline on the element and
 * nothing else — the JS builds only a static ring (marked .kfl-static) and
 * refuses the bounce, bloom, sparkles and confetti. The @media block reinforces
 * it for the OS setting.
 * ---------------------------------------------------------------------- */
.kfl-ring.kfl-static { animation: none !important; box-shadow: 0 0 0 2px rgba(95, 184, 122, 0.85) !important; opacity: 1 !important; }

@media (prefers-reduced-motion: reduce) {
    .kfl-bump, .kfl-bump.kfl-bump-strong { animation: none !important; transform: none !important; }
    .kfl-ring { animation: none !important; box-shadow: 0 0 0 2px rgba(95, 184, 122, 0.85) !important; opacity: 1 !important; }
    .kfl-spark, .kfl-glow { animation: none !important; }
    .kfl-spark { display: none !important; }
}
