/* static/css/particles.css */

/* ==========================================================================
   imgen.red reusable particle fields
   ========================================================================== */

.particle-host {
    position: relative;
    overflow: hidden;
    isolation: isolate;
}

.particle-host > :not(.imgen-particles) {
    position: relative;
    z-index: 2;
}

.imgen-particles {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    pointer-events: none;
    overflow: visible;
    z-index: 1;
}

.imgen-particles svg {
    display: block;
    width: 100%;
    height: 100%;
    overflow: visible;
}

.imgen-particles .p-line {
    fill: none;
    stroke-linecap: round;
    stroke-linejoin: round;
    stroke-dasharray: 720;
    stroke-dashoffset: 720;
    animation:
        particle-line-draw 2.2s cubic-bezier(0.16, 1, 0.3, 1) forwards,
        particle-line-breathe 4.2s ease-in-out 2.2s infinite;
}

.imgen-particles .p-line-soft {
    opacity: 0.34;
}

.imgen-particles .p-line-hot {
    opacity: 0.78;
}

.imgen-particles .p-dot,
.imgen-particles .p-spark,
.imgen-particles .p-square {
    transform-box: fill-box;
    transform-origin: center;
    opacity: 0;
    animation: particle-spark-float 3.2s ease-in-out infinite;
}

.imgen-particles .p-orb {
    transform-box: fill-box;
    transform-origin: center;
    animation: particle-orb-breathe 3.6s ease-in-out infinite;
}

.imgen-particles .p-blur {
    animation: particle-glow-breathe 4.8s ease-in-out infinite;
}

/* delays */
.imgen-particles .p-delay-1 { animation-delay: 0.15s; }
.imgen-particles .p-delay-2 { animation-delay: 0.35s; }
.imgen-particles .p-delay-3 { animation-delay: 0.55s; }
.imgen-particles .p-delay-4 { animation-delay: 0.75s; }
.imgen-particles .p-delay-5 { animation-delay: 0.95s; }
.imgen-particles .p-delay-6 { animation-delay: 1.15s; }
.imgen-particles .p-delay-7 { animation-delay: 1.35s; }
.imgen-particles .p-delay-8 { animation-delay: 1.55s; }

/* density modifiers */
.particle-host-soft .imgen-particles {
    opacity: 0.62;
}

.particle-host-muted .imgen-particles {
    opacity: 0.42;
}

.particle-host-loud .imgen-particles {
    opacity: 1;
}

/* placement helpers */
.imgen-particles.is-corner-left {
    inset: auto auto 0 0;
    width: min(420px, 70%);
    height: min(320px, 70%);
}

.imgen-particles.is-corner-right {
    inset: auto 0 0 auto;
    width: min(420px, 70%);
    height: min(320px, 70%);
}

.imgen-particles.is-top-right {
    inset: 0 0 auto auto;
    width: min(460px, 76%);
    height: min(280px, 60%);
}

.imgen-particles.is-full {
    inset: 0;
}

.imgen-particles.is-inline-trail {
    inset: auto 0 0 0;
    height: 140px;
}

.imgen-particles.is-halo {
    inset: 50% auto auto 50%;
    width: min(380px, 80%);
    height: min(380px, 80%);
    transform: translate(-50%, -50%);
}

/* ==========================================================================
   Keyframes
   ========================================================================== */

@keyframes particle-line-draw {
    to {
        stroke-dashoffset: 0;
    }
}

@keyframes particle-line-breathe {
    0%,
    100% {
        opacity: 0.38;
    }

    50% {
        opacity: 0.92;
    }
}

@keyframes particle-spark-float {
    0% {
        opacity: 0;
        transform: translateY(9px) scale(0.48) rotate(0deg);
    }

    18% {
        opacity: 1;
    }

    54% {
        opacity: 0.9;
        transform: translateY(-5px) scale(1) rotate(90deg);
    }

    100% {
        opacity: 0;
        transform: translateY(-18px) scale(0.48) rotate(180deg);
    }
}

@keyframes particle-orb-breathe {
    0%,
    100% {
        transform: scale(1);
        opacity: 0.45;
    }

    50% {
        transform: scale(1.12);
        opacity: 0.92;
    }
}

@keyframes particle-glow-breathe {
    0%,
    100% {
        opacity: 0.38;
        transform: scale(0.96);
    }

    50% {
        opacity: 0.82;
        transform: scale(1.06);
    }
}

@media (prefers-reduced-motion: reduce) {
    .imgen-particles *,
    .imgen-particles *::before,
    .imgen-particles *::after {
        animation: none !important;
        transition: none !important;
    }

    .imgen-particles .p-line {
        stroke-dashoffset: 0 !important;
    }

    .imgen-particles .p-dot,
    .imgen-particles .p-spark,
    .imgen-particles .p-square {
        opacity: 0.8 !important;
    }
}

/* ==========================================================================
   Button particle FX
   ========================================================================== */

.button.has-particles {
    position: relative;
    overflow: hidden;
    isolation: isolate;
}

.button.has-particles > :not(.button-particles) {
    position: relative;
    z-index: 3;
}

.button.has-particles::before {
    content: "";
    position: absolute;
    inset: -2px;
    background:
        radial-gradient(circle at 20% 50%, rgba(255, 0, 60, 0.42), transparent 28%),
        linear-gradient(
            90deg,
            transparent,
            rgba(255, 255, 255, 0.22),
            rgba(255, 45, 85, 0.42),
            transparent
        );
    transform: translateX(-120%);
    opacity: 0;
    z-index: 1;
    pointer-events: none;
}

.button.has-particles::after {
    content: "";
    position: absolute;
    inset: 1px;
    border-radius: inherit;
    background:
        linear-gradient(
            90deg,
            rgba(255, 0, 60, 0),
            rgba(255, 0, 60, 0.24),
            rgba(34, 211, 238, 0.12),
            rgba(255, 0, 60, 0)
        );
    opacity: 0.42;
    z-index: 0;
    pointer-events: none;
}

.button.has-particles:hover::before,
.button.has-particles:focus-visible::before {
    animation: button-energy-sweep 900ms cubic-bezier(0.16, 1, 0.3, 1);
}

.button-particles {
    position: absolute;
    inset: 0;
    z-index: 2;
    pointer-events: none;
    overflow: visible;
    border-radius: inherit;
}

.button-particle {
    position: absolute;
    width: 4px;
    height: 4px;
    border-radius: 1.5px;
    background: #ff2d55;
    box-shadow: 0 0 12px rgba(255, 0, 60, 0.95);
    opacity: 0;
    transform: translateY(6px) scale(0.4) rotate(0deg);
}

.button-particle-1 {
    left: 18%;
    top: 26%;
}

.button-particle-2 {
    left: 34%;
    top: 66%;
    width: 3px;
    height: 3px;
    background: #ff8aa0;
}

.button-particle-3 {
    left: 58%;
    top: 22%;
    width: 5px;
    height: 5px;
}

.button-particle-4 {
    left: 74%;
    top: 70%;
    width: 3px;
    height: 3px;
    background: #ff8aa0;
}

.button-particle-5 {
    left: 88%;
    top: 38%;
    width: 4px;
    height: 4px;
}

.button.has-particles:hover .button-particle,
.button.has-particles:focus-visible .button-particle {
    animation: button-particle-pop 1100ms ease-out both;
}

.button.has-particles:hover .button-particle-1,
.button.has-particles:focus-visible .button-particle-1 {
    animation-delay: 80ms;
}

.button.has-particles:hover .button-particle-2,
.button.has-particles:focus-visible .button-particle-2 {
    animation-delay: 150ms;
}

.button.has-particles:hover .button-particle-3,
.button.has-particles:focus-visible .button-particle-3 {
    animation-delay: 220ms;
}

.button.has-particles:hover .button-particle-4,
.button.has-particles:focus-visible .button-particle-4 {
    animation-delay: 300ms;
}

.button.has-particles:hover .button-particle-5,
.button.has-particles:focus-visible .button-particle-5 {
    animation-delay: 380ms;
}

/* Always-on subtle version */
.button.has-particles.button-particles-live .button-particle {
    animation: button-particle-idle 3s ease-in-out infinite;
}

.button.has-particles.button-particles-live .button-particle-1 {
    animation-delay: 0.1s;
}

.button.has-particles.button-particles-live .button-particle-2 {
    animation-delay: 0.5s;
}

.button.has-particles.button-particles-live .button-particle-3 {
    animation-delay: 0.9s;
}

.button.has-particles.button-particles-live .button-particle-4 {
    animation-delay: 1.3s;
}

.button.has-particles.button-particles-live .button-particle-5 {
    animation-delay: 1.7s;
}

@keyframes button-energy-sweep {
    0% {
        opacity: 0;
        transform: translateX(-120%);
    }

    18% {
        opacity: 1;
    }

    100% {
        opacity: 0;
        transform: translateX(120%);
    }
}

@keyframes button-particle-pop {
    0% {
        opacity: 0;
        transform: translateY(7px) scale(0.35) rotate(0deg);
    }

    18% {
        opacity: 1;
    }

    58% {
        opacity: 0.95;
        transform: translateY(-7px) scale(1) rotate(90deg);
    }

    100% {
        opacity: 0;
        transform: translateY(-16px) scale(0.45) rotate(180deg);
    }
}

@keyframes button-particle-idle {
    0%,
    100% {
        opacity: 0;
        transform: translateY(5px) scale(0.4) rotate(0deg);
    }

    18% {
        opacity: 0.7;
    }

    55% {
        opacity: 0.48;
        transform: translateY(-5px) scale(0.85) rotate(90deg);
    }
}

@media (prefers-reduced-motion: reduce) {
    .button.has-particles::before,
    .button.has-particles::after,
    .button.has-particles .button-particle {
        animation: none !important;
    }

    .button.has-particles::before {
        display: none;
    }

    .button.has-particles::after {
        opacity: 0.18;
    }

    .button.has-particles .button-particle {
        opacity: 0 !important;
    }
}

/* ==========================================================================
   Text / span particle FX
   ========================================================================== */

.fx-text-red,
.fx-text-hot {
    position: relative;
    display: inline-block;
    color: #ff2d55;
    text-shadow: 0 0 18px rgba(255, 0, 60, 0.38);
}

.fx-text-red::after,
.fx-text-hot::after {
    content: "";
    position: absolute;
    left: -6%;
    right: -6%;
    bottom: 0.04em;
    height: 0.18em;
    border-radius: 999px;
    background: linear-gradient(
        90deg,
        transparent,
        rgba(255, 45, 85, 0.95),
        rgba(255, 138, 160, 0.7),
        transparent
    );
    transform: scaleX(0.18);
    transform-origin: left center;
    opacity: 0.34;
    filter: blur(2px);
    animation: fx-text-energy 3.2s ease-in-out infinite;
    pointer-events: none;
}

.fx-text-hot::before {
    content: "";
    position: absolute;
    width: 0.26em;
    height: 0.26em;
    right: -0.38em;
    top: 0.1em;
    border-radius: 2px;
    background: #ff2d55;
    box-shadow: 0 0 14px rgba(255, 0, 60, 0.9);
    opacity: 0;
    animation: fx-text-spark 2.8s ease-in-out infinite;
    pointer-events: none;
}

.fx-muted-pulse {
    position: relative;
    display: inline-flex;
    align-items: center;
    gap: 0.5em;
}

.fx-muted-pulse::before {
    content: "";
    width: 0.48em;
    height: 0.48em;
    border-radius: 999px;
    background: #ff003c;
    box-shadow: 0 0 14px rgba(255, 0, 60, 0.85);
    animation: fx-dot-pulse 1.8s ease-in-out infinite;
}

/* Tiny badge/pill */
.fx-pill {
    position: relative;
    display: inline-flex;
    align-items: center;
    gap: 0.5em;
    min-height: 26px;
    padding: 0 10px;
    border: 1px solid rgba(255, 45, 85, 0.24);
    border-radius: 999px;
    background:
        radial-gradient(circle at 18% 50%, rgba(255, 0, 60, 0.18), transparent 42%),
        rgba(255, 255, 255, 0.045);
    color: #ffb3c1;
    font-size: 12px;
    font-weight: 800;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    overflow: hidden;
}

.fx-pill::after {
    content: "";
    position: absolute;
    inset: 0;
    transform: translateX(-110%);
    background: linear-gradient(
        90deg,
        transparent,
        rgba(255, 255, 255, 0.14),
        rgba(255, 45, 85, 0.2),
        transparent
    );
    animation: fx-pill-sheen 4.2s ease-in-out infinite;
    pointer-events: none;
}

/* ==========================================================================
   Input field FX
   ========================================================================== */

/*
Usage:
<label class="field-fx">
    <span>Username</span>
    <input ...>
</label>
*/

.field-fx {
    position: relative;
    display: grid;
    gap: 8px;
}

.field-fx > span,
.field-fx .form-label {
    transition:
        color 0.16s ease,
        text-shadow 0.16s ease;
}

.field-fx:focus-within > span,
.field-fx:focus-within .form-label {
    color: #ffb3c1;
    text-shadow: 0 0 14px rgba(255, 0, 60, 0.34);
}

.field-fx input,
.field-fx textarea,
.field-fx select {
    position: relative;
    z-index: 2;
}

.field-fx::before {
    content: "";
    position: absolute;
    left: 10px;
    right: 10px;
    bottom: 0;
    height: 46px;
    border-radius: var(--radius-sm, 14px);
    background:
        radial-gradient(circle at 16% 50%, rgba(255, 0, 60, 0.22), transparent 38%),
        linear-gradient(
            90deg,
            rgba(255, 0, 60, 0),
            rgba(255, 45, 85, 0.36),
            rgba(34, 211, 238, 0.12),
            rgba(255, 0, 60, 0)
        );
    opacity: 0;
    filter: blur(12px);
    transform: scaleX(0.84);
    transition:
        opacity 0.18s ease,
        transform 0.18s ease;
    pointer-events: none;
    z-index: 1;
}

.field-fx:focus-within::before {
    opacity: 1;
    transform: scaleX(1);
}

.field-fx::after {
    content: "";
    position: absolute;
    left: 18px;
    right: 18px;
    bottom: 0;
    height: 1px;
    background: linear-gradient(
        90deg,
        transparent,
        rgba(255, 45, 85, 0.98),
        rgba(255, 138, 160, 0.62),
        transparent
    );
    opacity: 0;
    transform: scaleX(0.2);
    transition:
        opacity 0.18s ease,
        transform 0.24s cubic-bezier(0.16, 1, 0.3, 1);
    pointer-events: none;
    z-index: 3;
}

.field-fx:focus-within::after {
    opacity: 1;
    transform: scaleX(1);
}

/* Optional always-premium variant */
.field-fx.field-fx-live::before {
    opacity: 0.28;
    animation: field-energy-idle 3.8s ease-in-out infinite;
}

.field-fx.field-fx-live::after {
    opacity: 0.4;
    animation: field-line-idle 4.2s ease-in-out infinite;
}

/* ==========================================================================
   Input particle dots
   ========================================================================== */

/*
Usage:
<label class="field-fx field-particles">
    <span>Username</span>
    <input ...>
    <i class="field-particle field-particle-1"></i>
    <i class="field-particle field-particle-2"></i>
    <i class="field-particle field-particle-3"></i>
</label>
*/

.field-particles {
    overflow: visible;
}

.field-particle {
    position: absolute;
    width: 4px;
    height: 4px;
    border-radius: 1.5px;
    background: #ff2d55;
    box-shadow: 0 0 12px rgba(255, 0, 60, 0.9);
    opacity: 0;
    pointer-events: none;
    z-index: 4;
}

.field-particle-1 {
    right: 18px;
    bottom: 34px;
}

.field-particle-2 {
    right: 52px;
    bottom: 12px;
    width: 3px;
    height: 3px;
    background: #ff8aa0;
}

.field-particle-3 {
    left: 22px;
    bottom: 12px;
    width: 3px;
    height: 3px;
}

.field-particles:focus-within .field-particle {
    animation: field-particle-pop 1.2s ease-out both;
}

.field-particles:focus-within .field-particle-1 {
    animation-delay: 90ms;
}

.field-particles:focus-within .field-particle-2 {
    animation-delay: 180ms;
}

.field-particles:focus-within .field-particle-3 {
    animation-delay: 270ms;
}

/* ==========================================================================
   Text/input FX keyframes
   ========================================================================== */

@keyframes fx-text-energy {
    0%,
    100% {
        transform: scaleX(0.18);
        opacity: 0.22;
    }

    45% {
        transform: scaleX(1);
        opacity: 0.62;
    }

    70% {
        transform: scaleX(0.46);
        opacity: 0.34;
    }
}

@keyframes fx-text-spark {
    0%,
    100% {
        opacity: 0;
        transform: translateY(4px) scale(0.4) rotate(0deg);
    }

    22% {
        opacity: 1;
    }

    58% {
        opacity: 0.8;
        transform: translateY(-5px) scale(1) rotate(90deg);
    }
}

@keyframes fx-dot-pulse {
    0%,
    100% {
        opacity: 0.42;
        transform: scale(0.85);
    }

    50% {
        opacity: 1;
        transform: scale(1.18);
    }
}

@keyframes fx-pill-sheen {
    0%,
    42% {
        transform: translateX(-110%);
    }

    68%,
    100% {
        transform: translateX(110%);
    }
}

@keyframes field-energy-idle {
    0%,
    100% {
        opacity: 0.18;
        transform: scaleX(0.92);
    }

    50% {
        opacity: 0.44;
        transform: scaleX(1);
    }
}

@keyframes field-line-idle {
    0%,
    100% {
        opacity: 0.18;
        transform: scaleX(0.24);
    }

    50% {
        opacity: 0.52;
        transform: scaleX(1);
    }
}

@keyframes field-particle-pop {
    0% {
        opacity: 0;
        transform: translateY(7px) scale(0.4) rotate(0deg);
    }

    18% {
        opacity: 1;
    }

    56% {
        opacity: 0.9;
        transform: translateY(-5px) scale(1) rotate(90deg);
    }

    100% {
        opacity: 0;
        transform: translateY(-15px) scale(0.4) rotate(180deg);
    }
}

@media (prefers-reduced-motion: reduce) {
    .fx-text-red::before,
    .fx-text-red::after,
    .fx-text-hot::before,
    .fx-text-hot::after,
    .fx-muted-pulse::before,
    .fx-pill::after,
    .field-fx::before,
    .field-fx::after,
    .field-particle {
        animation: none !important;
        transition: none !important;
    }
}