/* The login shell's own styling: the gradient ground, the drifting
   backdrop fields and the card that sits on them.

   Loaded by sigma/templates/auth_base.html after css/output.css, so these
   rules beat a Tailwind utility on a tie, and after appearance.css, which
   wins on specificity regardless. */

body {
    font-family: 'Inter', sans-serif;
    /* Near-black at the top so the hero type carries the page,
       falling into the blue bloom the card sits on. */
    background: linear-gradient(180deg, #04050c 0%, #04050c 20%, #090721 38%, #251367 60%, #1e3fae 84%, #3069e8 100%);
    min-height: 100vh;
    overflow-x: hidden;
}

/* ===== Backdrop =====
   Blue and violet sweep past each other in opposite directions, so
   the mix behind the card keeps changing - two fields of the same
   hue read as one mass and look static however far they travel.
   Negative animation-delays start them mid-sweep, so the first
   painted frame is already a blend rather than one flat colour.
   Blurred colour fields drift slowly behind the card,
   and a pair of faint sine lines along the bottom. Everything is
   fixed and aria-hidden, so it never affects layout or reading
   order, and it all goes still under prefers-reduced-motion. */
.auth-scene {
    position: fixed; inset: 0;
    overflow: hidden;
    pointer-events: none;
}
.bloom {
    position: absolute;
    border-radius: 9999px;
    filter: blur(70px);
    will-change: transform;
}
.bloom-a {
    width: 1300px; height: 860px;
    left: 50%; bottom: -180px;
    margin-left: -650px;
    background: radial-gradient(closest-side, rgba(37, 99, 235, 0.95), rgba(37, 99, 235, 0) 76%);
    animation: bloom-sweep-a 12s ease-in-out infinite alternate;
    animation-delay: -5s;
}
.bloom-b {
    width: 900px; height: 640px;
    left: 50%; bottom: -60px;
    margin-left: -300px;
    background: radial-gradient(closest-side, rgba(124, 58, 237, 0.72), rgba(124, 58, 237, 0) 74%);
    animation: bloom-sweep-b 15s ease-in-out infinite alternate;
    animation-delay: -6s;
}
/* The fields sweep across the screen, left end to right end and
   back, with a small vertical bob - a traverse, not a pulse from
   the centre. No scale: growing in place is what read as
   "breathing". */
@keyframes bloom-sweep-a {
    from { transform: translate(-42vw, 0); filter: blur(70px) hue-rotate(0deg); }
    to   { transform: translate(42vw, -60px); filter: blur(70px) hue-rotate(34deg); }
}
@keyframes bloom-sweep-b {
    from { transform: translate(36vw, -35px); filter: blur(70px) hue-rotate(0deg); }
    to   { transform: translate(-36vw, 30px); filter: blur(70px) hue-rotate(-30deg); }
}
/* The module accents, whispering at the edges: teal (Portfolio) low
   left, sky (Projects) upper right. Kept well under the blue so the
   page reads blue with colour moving inside it, not tri-colour. */
.bloom-c {
    width: 700px; height: 480px;
    left: -180px; bottom: -80px;
    background: radial-gradient(closest-side, rgba(45, 212, 191, 0.5), rgba(45, 212, 191, 0) 70%);
    animation: bloom-sweep-c 14s ease-in-out infinite alternate;
}
.bloom-d {
    width: 620px; height: 440px;
    right: -160px; top: 8%;
    background: radial-gradient(closest-side, rgba(56, 189, 248, 0.4), rgba(56, 189, 248, 0) 70%);
    animation: bloom-sweep-c 18s ease-in-out infinite alternate-reverse;
}
@keyframes bloom-sweep-c {
    from { transform: translate(0, 0); opacity: 0.62; }
    to   { transform: translate(64vw, -45px); opacity: 1; }
}


/* Black scrim over the colour fields, painting the top of the page
   back down to the page black. Without it a field sweeping high
   ends at its own soft edge somewhere behind the hero; with it the
   colour always reads as fading up into the dark, whatever the
   fields are doing underneath. Last in the scene, so it paints
   above them. */
.auth-topfade {
    position: absolute;
    left: 0; right: 0; top: 0;
    height: 62%;
    background: linear-gradient(180deg,
        #04050c 0%,
        rgba(4, 5, 12, 0.92) 22%,
        rgba(4, 5, 12, 0.6) 48%,
        rgba(4, 5, 12, 0) 100%);
}

/* Light band along the bottom horizon, the reference's bright
   floor under the wave lines. */
.auth-horizon {
    position: absolute;
    left: -10%; bottom: -140px;
    width: 120%; height: 280px;
    background: radial-gradient(ellipse at 50% 100%, rgba(191, 219, 254, 0.55), rgba(191, 219, 254, 0) 70%);
    filter: blur(30px);
}

.auth-waves {
    position: absolute;
    left: -25%; bottom: 4vh;
    width: 150%; height: 120px;
    opacity: 0.5;
}
.auth-waves path {
    fill: none;
    stroke: rgba(255, 255, 255, 0.10);
    stroke-width: 1;
    animation: wave-drift 14s ease-in-out infinite alternate;
}
.auth-waves path + path {
    stroke: rgba(147, 197, 253, 0.12);
    animation-duration: 19s;
    animation-direction: alternate-reverse;
}
@keyframes wave-drift {
    from { transform: translateX(0); }
    to   { transform: translateX(11%); }
}

/* Shared page logo, top-left, outside the card. */
.powered-logo { height: 17px; width: auto; opacity: 0.9; }


/* Holds the inlined logo. Layout only: the text properties this
   rule used to carry went with the letterspaced "SIGMA" it replaced. */
.hero-kicker {
    display: flex;
    justify-content: center;
    margin-bottom: 14px;
}
.hero-title {
    font-size: clamp(2rem, 4.5vw, 3.25rem);
    font-weight: 700;
    letter-spacing: -0.02em;
    color: #f8fafc;
    text-align: center;
}
.hero-sub {
    margin-top: 10px;
    max-width: 34rem;
    text-align: center;
    font-size: 0.85rem;
    line-height: 1.6;
    color: rgba(199, 210, 254, 0.72);
}

/* Hero and card rise in once, in order. */
.hero-kicker { animation: rise 0.6s ease-out both; }
.hero-title { animation: rise 0.6s ease-out 0.08s both; }
.hero-sub { animation: rise 0.6s ease-out 0.16s both; }
.auth-card-wrap { animation: rise 0.6s ease-out 0.24s both; }
.auth-powered { animation: rise 0.6s ease-out 0.32s both; }
@keyframes rise {
    from { opacity: 0; transform: translateY(14px); }
    to   { opacity: 1; transform: translateY(0); }
}

@media (prefers-reduced-motion: reduce) {
    .bloom, .auth-waves path, .hero-kicker,
    .hero-title, .hero-sub, .auth-card-wrap, .auth-powered { animation: none; }
}

.htmx-loading { opacity: 0.5; pointer-events: none; }
.htmx-indicator { display: none; }
.htmx-request .htmx-indicator { display: inline; }

/* Alpine hides an [x-cloak] element until it starts, so a closed menu never
   flashes open on load. The portal shell declares the same rule in base.html. */
[x-cloak] { display: none !important; }
