* { box-sizing: border-box; }
:root {
    --font-display: "Archivo", 'Helvetica Neue', Arial, sans-serif;
    --font-ui: "Inter", 'Helvetica Neue', Arial, sans-serif;
}
.mono {
    font-family: var(--font-ui);
}

/* ================= STEP 1: full-bleed background + scrim ================= */
.stage {
    position: relative;
    min-height: 100vh;
    overflow: hidden;
    /* dark-on-light AA hint, scoped to this section only (not global) */
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}
/* 5 cross-fading layers, one per icon, timed with moduleScaleN/descRevealN */
.stage-bg-layer {
    position: absolute;
    inset: 0;
    background-size: cover;
    background-position: center;
    opacity: 0;
    /* pivot on the artwork's own subject, not a layout split */
    transform-origin: 45% 48%;
}
/* fill-mode redeclared per rule since `animation` shorthand resets it */
.stage-bg-layer.bg0 {
    background-image: var(--bg-img-0);
    animation: bgPanZoom 26s ease-in-out infinite alternate, bgFade0 22.5s linear infinite 1.4s;
    animation-fill-mode: none, backwards;
}
.stage-bg-layer.bg1 {
    background-image: var(--bg-img-1);
    animation: bgPanZoom 26s ease-in-out infinite alternate, bgFade1 22.5s linear infinite 1.4s;
    animation-fill-mode: none, backwards;
}
.stage-bg-layer.bg2 {
    background-image: var(--bg-img-2);
    animation: bgPanZoom 26s ease-in-out infinite alternate, bgFade2 22.5s linear infinite 1.4s;
    animation-fill-mode: none, backwards;
}
.stage-bg-layer.bg3 {
    background-image: var(--bg-img-3);
    animation: bgPanZoom 26s ease-in-out infinite alternate, bgFade3 22.5s linear infinite 1.4s;
    animation-fill-mode: none, backwards;
}
.stage-bg-layer.bg4 {
    background-image: var(--bg-img-4);
    animation: bgPanZoom 26s ease-in-out infinite alternate, bgFade4 22.5s linear infinite 1.4s;
    animation-fill-mode: none, backwards;
}
/* Ken-Burns drift shared by all layers; 26s vs 22.5s fade loop deliberately
   don't divide evenly, so it reads as organic rather than synced */
@keyframes bgPanZoom {
    0%   { transform: scale(1.16) translate(-3.2%, -2.6%); }
    100% { transform: scale(1) translate(0%, 0%); }
}
@keyframes bgFade0 {
    0%   { opacity: 1; }
    16%  { opacity: 1; animation-timing-function: ease; }
    20%  { opacity: 0; animation-timing-function: linear; }
    96%  { opacity: 0; animation-timing-function: ease; }
    100% { opacity: 1; }
}
@keyframes bgFade1 {
    0%   { opacity: 0; }
    16%  { opacity: 0; animation-timing-function: ease; }
    20%  { opacity: 1; animation-timing-function: linear; }
    36%  { opacity: 1; animation-timing-function: ease; }
    40%  { opacity: 0; }
    100% { opacity: 0; }
}
@keyframes bgFade2 {
    0%   { opacity: 0; }
    36%  { opacity: 0; animation-timing-function: ease; }
    40%  { opacity: 1; animation-timing-function: linear; }
    56%  { opacity: 1; animation-timing-function: ease; }
    60%  { opacity: 0; }
    100% { opacity: 0; }
}
@keyframes bgFade3 {
    0%   { opacity: 0; }
    56%  { opacity: 0; animation-timing-function: ease; }
    60%  { opacity: 1; animation-timing-function: linear; }
    76%  { opacity: 1; animation-timing-function: ease; }
    80%  { opacity: 0; }
    100% { opacity: 0; }
}
@keyframes bgFade4 {
    0%   { opacity: 0; }
    76%  { opacity: 0; animation-timing-function: ease; }
    80%  { opacity: 1; animation-timing-function: linear; }
    96%  { opacity: 1; animation-timing-function: ease; }
    100% { opacity: 0; }
}
@media (prefers-reduced-motion: reduce) {
    .stage-bg-layer { animation: none; opacity: 0; transform: none; }
    .stage-bg-layer.bg0 { opacity: 1; }
}

.stage-scrim {
    position: absolute;
    inset: 0;
    background: linear-gradient(160deg, rgba(3,6,20,0.8) 0%, rgba(6,24,52,0.64) 45%, rgba(3,6,20,0.78) 100%);
}

/* one dot per icon; active dot matches whichever icon is dwelling */
.bg-carousel {
    position: absolute;
    left: 50%;
    bottom: 28px;
    transform: translateX(-50%);
    z-index: 3;
    display: flex;
    gap: 8px;
}
.bg-carousel-dot {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: rgba(255,255,255,0.3);
}
.bg-carousel-dot.d0 { animation: dotActive0 22.5s linear infinite 1.4s; animation-fill-mode: backwards; }
.bg-carousel-dot.d1 { animation: dotActive1 22.5s linear infinite 1.4s; }
.bg-carousel-dot.d2 { animation: dotActive2 22.5s linear infinite 1.4s; }
.bg-carousel-dot.d3 { animation: dotActive3 22.5s linear infinite 1.4s; }
.bg-carousel-dot.d4 { animation: dotActive4 22.5s linear infinite 1.4s; }
@keyframes dotActive0 {
    0%   { background: #fff; width: 22px; border-radius: 4px; }
    16%  { background: #fff; width: 22px; border-radius: 4px; animation-timing-function: ease; }
    20%  { background: rgba(255,255,255,0.3); width: 8px; border-radius: 50%; animation-timing-function: linear; }
    96%  { background: rgba(255,255,255,0.3); width: 8px; border-radius: 50%; animation-timing-function: ease; }
    100% { background: #fff; width: 22px; border-radius: 4px; }
}
@keyframes dotActive1 {
    0%   { background: rgba(255,255,255,0.3); width: 8px; border-radius: 50%; }
    16%  { background: rgba(255,255,255,0.3); width: 8px; border-radius: 50%; animation-timing-function: ease; }
    20%  { background: #fff; width: 22px; border-radius: 4px; animation-timing-function: linear; }
    36%  { background: #fff; width: 22px; border-radius: 4px; animation-timing-function: ease; }
    40%  { background: rgba(255,255,255,0.3); width: 8px; border-radius: 50%; }
    100% { background: rgba(255,255,255,0.3); width: 8px; border-radius: 50%; }
}
@keyframes dotActive2 {
    0%   { background: rgba(255,255,255,0.3); width: 8px; border-radius: 50%; }
    36%  { background: rgba(255,255,255,0.3); width: 8px; border-radius: 50%; animation-timing-function: ease; }
    40%  { background: #fff; width: 22px; border-radius: 4px; animation-timing-function: linear; }
    56%  { background: #fff; width: 22px; border-radius: 4px; animation-timing-function: ease; }
    60%  { background: rgba(255,255,255,0.3); width: 8px; border-radius: 50%; }
    100% { background: rgba(255,255,255,0.3); width: 8px; border-radius: 50%; }
}
@keyframes dotActive3 {
    0%   { background: rgba(255,255,255,0.3); width: 8px; border-radius: 50%; }
    56%  { background: rgba(255,255,255,0.3); width: 8px; border-radius: 50%; animation-timing-function: ease; }
    60%  { background: #fff; width: 22px; border-radius: 4px; animation-timing-function: linear; }
    76%  { background: #fff; width: 22px; border-radius: 4px; animation-timing-function: ease; }
    80%  { background: rgba(255,255,255,0.3); width: 8px; border-radius: 50%; }
    100% { background: rgba(255,255,255,0.3); width: 8px; border-radius: 50%; }
}
@keyframes dotActive4 {
    0%   { background: rgba(255,255,255,0.3); width: 8px; border-radius: 50%; }
    76%  { background: rgba(255,255,255,0.3); width: 8px; border-radius: 50%; animation-timing-function: ease; }
    80%  { background: #fff; width: 22px; border-radius: 4px; animation-timing-function: linear; }
    96%  { background: #fff; width: 22px; border-radius: 4px; animation-timing-function: ease; }
    100% { background: rgba(255,255,255,0.3); width: 8px; border-radius: 50%; }
}
@media (prefers-reduced-motion: reduce) {
    .bg-carousel-dot { animation: none; }
    .bg-carousel-dot.d0 { background: #fff; width: 22px; border-radius: 4px; }
}

/* ================= STEP 2: heading (logo + typography) ================= */
.hero {
    position: relative;
    z-index: 2;
    padding: 44px 0 0 48px;
}
.heading-logo-chip {
    display: inline-block;
    background: #ffffff;
    border-radius: 14px;
    padding: 5px 10px;
    margin-bottom: 22px;
    box-shadow: 0 8px 22px rgba(0,0,0,0.25);
}
.heading-logo {
    height: 66px;
    display: block;
}
.hero h1 {
    margin: 0;
    font-family: var(--font-display);
    font-weight: 700;
    font-size: clamp(2.25rem, 4.5vw, 3.5rem);
    line-height: 1.06;
    letter-spacing: -0.025em;
}
.hero-sub {
    font-family: var(--font-ui);
    font-weight: 500;
    font-size: 0.9375rem;
    line-height: 1.6;
    letter-spacing: 0.02em;
    color: rgba(234,242,255,0.62);
    max-width: 32em;
    margin: 16px 0 0;
}
/* only shown (reordered below the login card) in the ≤768px query */
.hero-sub-mobile { display: none; }
/* separate span so its text-clip mask never overlaps .impact's own —
   nesting both on h1 caused a fringe */
.metal {
    background: linear-gradient(135deg, #f5f8fd 0%, #cdd9ec 25%, #f5f8fd 50%, #cdd9ec 75%, #f5f8fd 100%);
    background-size: 200% auto;
    -webkit-background-clip: text;
    background-clip: text;
    color: transparent;
    -webkit-text-fill-color: transparent;
    -webkit-font-smoothing: antialiased;
}

/* animated gradient fill for the "Impact" word */
.impact {
    font-family: "Bricolage Grotesque", ui-sans-serif, sans-serif;
    font-weight: 800;
    background: linear-gradient(100deg, #5ec4ff, #6fc3ff, #1d78d1, #2c86dd, #5ec4ff);
    background-size: 300% auto;
    -webkit-background-clip: text;
    background-clip: text;
    color: transparent;
    -webkit-text-fill-color: transparent;
    -webkit-font-smoothing: antialiased;
    display: inline-block;
    padding-right: 0.1em;
    animation: impactFlow 12s ease-in-out infinite, impactGlow 3.5s ease-in-out infinite;
}
@keyframes impactFlow {
    0%, 100% { background-position: 0% 50%; }
    50%      { background-position: 100% 50%; }
}
@keyframes impactGlow {
    0%, 100% { filter: drop-shadow(0 0 6px rgba(94,196,255,0.18)) drop-shadow(0 0 14px rgba(29,120,209,0.1)); }
    50%      { filter: drop-shadow(0 0 12px rgba(94,196,255,0.32)) drop-shadow(0 0 22px rgba(29,120,209,0.18)); }
}
@media (prefers-reduced-motion: reduce) {
    .impact { animation: none; }
}

/* ================= STEP 3: module rail (icon squares + travelling cluster) ================= */
.module-rail {
    position: relative;
    z-index: 2;
    padding: 48px 0 24px 76px;
    display: flex;
    flex-direction: column;
    gap: 40px;
    width: max-content;
}
.module-item {
    position: relative;
    display: flex;
    align-items: center;
}
/* running-light ring: spinning gradient clipped to the icon's shape via
   overflow:hidden; .module-sq-wrap holds an unclipped copy for the glow
   (blur would otherwise get clipped too) */
.module-sq-wrap {
    position: relative;
    flex: 0 0 auto;
    width: 56px;
    height: 56px;
    opacity: 0;
    transform: scale(1);
    animation:
        moduleBlink 1.4s ease-out forwards,
        moduleScale0 22.5s linear infinite 1.4s;
    animation-fill-mode: forwards, backwards;
    animation-delay: 0.05s, 1.4s;
}
.module-sq-wrap::before {
    content: "";
    display: block;
    position: absolute;
    inset: -2px;
    pointer-events: none;
    opacity: 0;
    background: conic-gradient(from 0deg,
        rgba(94,196,255,0) 0deg,
        rgba(94,196,255,0) 70deg,
        rgba(94,196,255,0.05) 117deg,
        rgba(94,196,255,0.2) 153deg,
        rgba(94,196,255,0.75) 172deg,
        rgba(94,196,255,0.95) 176deg,
        rgba(94,196,255,0.45) 179deg,
        rgba(94,196,255,0) 180deg,
        rgba(94,196,255,0) 250deg,
        rgba(94,196,255,0.05) 297deg,
        rgba(94,196,255,0.2) 333deg,
        rgba(94,196,255,0.75) 352deg,
        rgba(94,196,255,0.95) 356deg,
        rgba(94,196,255,0.45) 359deg,
        rgba(94,196,255,0) 360deg);
    filter: blur(6px);
    animation: runningLightSpin 2.2s linear infinite, runningLight0 22.5s linear infinite 1.4s;
    animation-fill-mode: none, backwards;
}
.module-sq {
    position: relative;
    overflow: hidden;
    width: 100%;
    height: 100%;
    border-radius: 10px;
    display: flex;
    align-items: center;
    justify-content: center;
}
.module-sq::before {
    content: "";
    display: block;
    position: absolute;
    z-index: 0;
    width: 130px;
    height: 130px;
    pointer-events: none;
    opacity: 0;
    /* two comets 180deg apart: long low-alpha tail, short bright head */
    background: conic-gradient(from 0deg,
        rgba(94,196,255,0) 0deg,
        rgba(94,196,255,0) 70deg,
        rgba(94,196,255,0.1) 118deg,
        rgba(94,196,255,0.4) 154deg,
        rgba(94,196,255,0.9) 171deg,
        #eaf4ff 173deg,
        #eaf4ff 176deg,
        rgba(94,196,255,0.55) 179deg,
        rgba(94,196,255,0) 180deg,
        rgba(94,196,255,0) 250deg,
        rgba(94,196,255,0.1) 298deg,
        rgba(94,196,255,0.4) 334deg,
        rgba(94,196,255,0.9) 351deg,
        #eaf4ff 353deg,
        #eaf4ff 356deg,
        rgba(94,196,255,0.55) 359deg,
        rgba(94,196,255,0) 360deg);
    filter: blur(2px);
    animation: runningLightSpin 2.2s linear infinite, runningLight0 22.5s linear infinite 1.4s;
    animation-fill-mode: none, backwards;
}
.module-sq-inner {
    position: relative;
    z-index: 1;
    margin: 1px;
    width: 54px;
    height: 54px;
    border-radius: 9px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: #5e93f5;
}
@keyframes runningLightSpin {
    0%   { transform: rotate(0deg); }
    100% { transform: rotate(360deg); }
}
/* mirrors moduleScaleN's shape — ring on only during the dwell window */
@keyframes runningLight0 {
    0%   { opacity: 1; animation-timing-function: linear; }
    16%  { opacity: 1; animation-timing-function: cubic-bezier(.85,0,.15,1); }
    20%  { opacity: 0; animation-timing-function: linear; }
    96%  { opacity: 0; animation-timing-function: cubic-bezier(.85,0,.15,1); }
    100% { opacity: 1; }
}
@keyframes runningLight1 {
    16%  { opacity: 0; animation-timing-function: cubic-bezier(.85,0,.15,1); }
    20%  { opacity: 1; animation-timing-function: linear; }
    36%  { opacity: 1; animation-timing-function: cubic-bezier(.85,0,.15,1); }
    40%  { opacity: 0; }
}
@keyframes runningLight2 {
    36%  { opacity: 0; animation-timing-function: cubic-bezier(.85,0,.15,1); }
    40%  { opacity: 1; animation-timing-function: linear; }
    56%  { opacity: 1; animation-timing-function: cubic-bezier(.85,0,.15,1); }
    60%  { opacity: 0; }
}
@keyframes runningLight3 {
    56%  { opacity: 0; animation-timing-function: cubic-bezier(.85,0,.15,1); }
    60%  { opacity: 1; animation-timing-function: linear; }
    76%  { opacity: 1; animation-timing-function: cubic-bezier(.85,0,.15,1); }
    80%  { opacity: 0; }
}
@keyframes runningLight4 {
    76%  { opacity: 0; animation-timing-function: cubic-bezier(.85,0,.15,1); }
    80%  { opacity: 1; animation-timing-function: linear; }
    96%  { opacity: 1; animation-timing-function: cubic-bezier(.85,0,.15,1); }
    100% { opacity: 0; }
}
.module-sq svg {
    width: 40px;
    height: 40px;
    fill: none;
    stroke: #eaf4ff;
    stroke-width: 1.5;
    stroke-linecap: round;
    stroke-linejoin: round;
}
/* description auto-reveals while its icon is active, no hover, synced to
   the icon scale/cluster move timeline. Fixed width/height/margin here
   (never animated) keeps row height consistent across icons. */
.module-desc-clip {
    width: 420px;
    height: 62px;
    margin-left: 20px;
    overflow: hidden;
    display: flex;
    align-items: center;
}
/* the sliding block: title + description move together as one unit */
.module-desc-inner {
    width: 420px;
    opacity: 0;
    transform: translateX(-100%);
    display: flex;
    flex-direction: column;
    gap: 5px;
    animation: descReveal0 22.5s linear infinite 1.4s;
    /* holds descReveal0's 0% (hidden) through the 1.4s delay */
    animation-fill-mode: backwards;
}
/* description's glow is a separate ::after overlay faded via opacity;
   title animates color+text-shadow directly instead (avoids a fringe
   its bolder glyph showed through the overlay technique) */
.module-title {
    margin: 0;
    font-family: var(--font-display);
    font-weight: 700;
    font-size: 1rem;
    line-height: 1.3;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: #f5f8fd;
    text-shadow: 0 0 0 rgba(94,196,255,0);
    -webkit-font-smoothing: antialiased;
    animation: titleColorFade0 22.5s linear infinite 1.4s;
    animation-fill-mode: backwards;
}
.module-desc {
    position: relative;
    margin: 0;
    font-family: var(--font-ui);
    font-weight: 400;
    font-size: 1rem;
    line-height: 1.5;
    letter-spacing: 0;
    color: rgba(255,255,255,0.68);
    -webkit-font-smoothing: antialiased;
}
/* gradient+glow overlay, positioned over the real text; only
   background-position and opacity animate, both of which tween cleanly */
.module-desc::after {
    content: attr(data-text);
    position: absolute;
    inset: 0;
    pointer-events: none;
    opacity: 0;
    color: transparent;
    -webkit-text-fill-color: transparent;
    -webkit-font-smoothing: antialiased;
    background-size: 200% 100%;
    background-repeat: no-repeat;
    -webkit-background-clip: text;
    background-clip: text;
    animation: descTextSweep 6s linear infinite, textGlowFade0 22.5s linear infinite 1.4s;
    animation-fill-mode: none, backwards;
}
/* lighter blue so it doesn't dip dark/muted at the gradient's middle */
.module-desc::after {
    background-image: linear-gradient(120deg, rgba(140,220,255,1) 0%, rgba(56,165,235,1) 50%, rgba(140,220,255,1) 100%);
    text-shadow: 0 0 4px rgba(94,196,255,0.16), 0 0 9px rgba(29,120,209,0.08);
}
/* title's color+text-shadow flash — same rise/fade shape and colors as
   the description's overlay, just expressed as a direct color change */
@keyframes titleColorFade0 {
    0%, 3% { color: #f5f8fd; text-shadow: 0 0 0 rgba(94,196,255,0); animation-timing-function: linear; }
    4%     { color: rgba(140,220,255,1); text-shadow: 0 0 5px rgba(94,196,255,0.18), 0 0 10px rgba(29,120,209,0.09); animation-timing-function: cubic-bezier(.4,0,.2,1); }
    10%    { color: #f5f8fd; text-shadow: 0 0 0 rgba(94,196,255,0); }
    100%   { color: #f5f8fd; text-shadow: 0 0 0 rgba(94,196,255,0); }
}
@keyframes titleColorFade1 {
    0%, 19% { color: #f5f8fd; text-shadow: 0 0 0 rgba(94,196,255,0); animation-timing-function: linear; }
    20%     { color: rgba(140,220,255,1); text-shadow: 0 0 5px rgba(94,196,255,0.18), 0 0 10px rgba(29,120,209,0.09); animation-timing-function: cubic-bezier(.4,0,.2,1); }
    26%     { color: #f5f8fd; text-shadow: 0 0 0 rgba(94,196,255,0); }
    100%    { color: #f5f8fd; text-shadow: 0 0 0 rgba(94,196,255,0); }
}
@keyframes titleColorFade2 {
    0%, 39% { color: #f5f8fd; text-shadow: 0 0 0 rgba(94,196,255,0); animation-timing-function: linear; }
    40%     { color: rgba(140,220,255,1); text-shadow: 0 0 5px rgba(94,196,255,0.18), 0 0 10px rgba(29,120,209,0.09); animation-timing-function: cubic-bezier(.4,0,.2,1); }
    46%     { color: #f5f8fd; text-shadow: 0 0 0 rgba(94,196,255,0); }
    100%    { color: #f5f8fd; text-shadow: 0 0 0 rgba(94,196,255,0); }
}
@keyframes titleColorFade3 {
    0%, 59% { color: #f5f8fd; text-shadow: 0 0 0 rgba(94,196,255,0); animation-timing-function: linear; }
    60%     { color: rgba(140,220,255,1); text-shadow: 0 0 5px rgba(94,196,255,0.18), 0 0 10px rgba(29,120,209,0.09); animation-timing-function: cubic-bezier(.4,0,.2,1); }
    66%     { color: #f5f8fd; text-shadow: 0 0 0 rgba(94,196,255,0); }
    100%    { color: #f5f8fd; text-shadow: 0 0 0 rgba(94,196,255,0); }
}
@keyframes titleColorFade4 {
    0%, 79% { color: #f5f8fd; text-shadow: 0 0 0 rgba(94,196,255,0); animation-timing-function: linear; }
    80%     { color: rgba(140,220,255,1); text-shadow: 0 0 5px rgba(94,196,255,0.18), 0 0 10px rgba(29,120,209,0.09); animation-timing-function: cubic-bezier(.4,0,.2,1); }
    86%     { color: #f5f8fd; text-shadow: 0 0 0 rgba(94,196,255,0); }
    100%    { color: #f5f8fd; text-shadow: 0 0 0 rgba(94,196,255,0); }
}
/* Each description holds open continuously after reveal, all the way to
   the shared 96-100% wrap window, where all 5 retract staggered
   bottom-to-top (matching the cluster's upward travel). icon0 eases in
   over 0-4% (same shape as descReveal1's 16-20% rise) rather than
   snapping instantly at the loop wrap. */
@keyframes descReveal0 {
    0%     { transform: translateX(-100%); opacity: 0; animation-timing-function: cubic-bezier(.85,0,.15,1); }
    4%     { transform: translateX(30px);  opacity: 1; animation-timing-function: linear; }
    99.2%  { transform: translateX(30px);  opacity: 1; animation-timing-function: cubic-bezier(.4,0,.2,1); }
    100%   { transform: translateX(-100%); opacity: 0; }
}
@keyframes descReveal1 {
    16%    { transform: translateX(-100%); opacity: 0; animation-timing-function: cubic-bezier(.85,0,.15,1); }
    20%    { transform: translateX(30px);  opacity: 1; animation-timing-function: linear; }
    98.4%  { transform: translateX(30px);  opacity: 1; animation-timing-function: cubic-bezier(.4,0,.2,1); }
    99.2%  { transform: translateX(-100%); opacity: 0; }
}
@keyframes descReveal2 {
    36%    { transform: translateX(-100%); opacity: 0; animation-timing-function: cubic-bezier(.85,0,.15,1); }
    40%    { transform: translateX(30px);  opacity: 1; animation-timing-function: linear; }
    97.6%  { transform: translateX(30px);  opacity: 1; animation-timing-function: cubic-bezier(.4,0,.2,1); }
    98.4%  { transform: translateX(-100%); opacity: 0; }
}
@keyframes descReveal3 {
    56%    { transform: translateX(-100%); opacity: 0; animation-timing-function: cubic-bezier(.85,0,.15,1); }
    60%    { transform: translateX(30px);  opacity: 1; animation-timing-function: linear; }
    96.8%  { transform: translateX(30px);  opacity: 1; animation-timing-function: cubic-bezier(.4,0,.2,1); }
    97.6%  { transform: translateX(-100%); opacity: 0; }
}
@keyframes descReveal4 {
    76%    { transform: translateX(-100%); opacity: 0; animation-timing-function: cubic-bezier(.85,0,.15,1); }
    80%    { transform: translateX(30px);  opacity: 1; animation-timing-function: linear; }
    96%    { transform: translateX(30px);  opacity: 1; animation-timing-function: cubic-bezier(.4,0,.2,1); }
    96.8%  { transform: translateX(-100%); opacity: 0; }
}
/* continuous sweep, only visible while textGlowFadeN raises opacity */
@keyframes descTextSweep {
    0%   { background-position: 0% 0%; }
    100% { background-position: 100% 0%; }
}
/* quick opacity rise on reveal, gentle fade-out over the next 6% */
@keyframes textGlowFade0 {
    0%, 3% { opacity: 0; animation-timing-function: linear; }
    4%     { opacity: 1; animation-timing-function: cubic-bezier(.4,0,.2,1); }
    10%    { opacity: 0; }
    100%   { opacity: 0; }
}
@keyframes textGlowFade1 {
    0%, 19% { opacity: 0; animation-timing-function: linear; }
    20%     { opacity: 1; animation-timing-function: cubic-bezier(.4,0,.2,1); }
    26%     { opacity: 0; }
    100%    { opacity: 0; }
}
@keyframes textGlowFade2 {
    0%, 39% { opacity: 0; animation-timing-function: linear; }
    40%     { opacity: 1; animation-timing-function: cubic-bezier(.4,0,.2,1); }
    46%     { opacity: 0; }
    100%    { opacity: 0; }
}
@keyframes textGlowFade3 {
    0%, 59% { opacity: 0; animation-timing-function: linear; }
    60%     { opacity: 1; animation-timing-function: cubic-bezier(.4,0,.2,1); }
    66%     { opacity: 0; }
    100%    { opacity: 0; }
}
@keyframes textGlowFade4 {
    0%, 79% { opacity: 0; animation-timing-function: linear; }
    80%     { opacity: 1; animation-timing-function: cubic-bezier(.4,0,.2,1); }
    86%     { opacity: 0; }
    100%    { opacity: 0; }
}
@media (prefers-reduced-motion: reduce) {
    .module-desc-inner { animation: none; transform: translateX(0); opacity: 1; }
    .module-title { animation: none; color: #f5f8fd; text-shadow: none; }
    .module-desc::after { animation: none; opacity: 0; }
}
/* blink delay is non-sequential so it reads as scattered, not a sweep */
.module-item:nth-child(2) .module-sq-wrap { animation-name: moduleBlink, moduleScale1; animation-delay: 0.35s, 1.4s; }
.module-item:nth-child(3) .module-sq-wrap { animation-name: moduleBlink, moduleScale2; animation-delay: 0.12s, 1.4s; }
.module-item:nth-child(4) .module-sq-wrap { animation-name: moduleBlink, moduleScale3; animation-delay: 0.5s, 1.4s; }
.module-item:nth-child(5) .module-sq-wrap { animation-name: moduleBlink, moduleScale4; animation-delay: 0.2s, 1.4s; }
/* same phase-lock, applied to the running-light ring */
.module-item:nth-child(2) .module-sq::before,
.module-item:nth-child(2) .module-sq-wrap::before { animation-name: runningLightSpin, runningLight1; }
.module-item:nth-child(3) .module-sq::before,
.module-item:nth-child(3) .module-sq-wrap::before { animation-name: runningLightSpin, runningLight2; }
.module-item:nth-child(4) .module-sq::before,
.module-item:nth-child(4) .module-sq-wrap::before { animation-name: runningLightSpin, runningLight3; }
.module-item:nth-child(5) .module-sq::before,
.module-item:nth-child(5) .module-sq-wrap::before { animation-name: runningLightSpin, runningLight4; }
/* phase-locked to each icon's own dwell window via descRevealN */
.module-item:nth-child(2) .module-desc-inner { animation-name: descReveal1; }
.module-item:nth-child(3) .module-desc-inner { animation-name: descReveal2; }
.module-item:nth-child(4) .module-desc-inner { animation-name: descReveal3; }
.module-item:nth-child(5) .module-desc-inner { animation-name: descReveal4; }
/* same phase-lock for the title's color flash + description's glow */
.module-item:nth-child(2) .module-title { animation-name: titleColorFade1; }
.module-item:nth-child(3) .module-title { animation-name: titleColorFade2; }
.module-item:nth-child(4) .module-title { animation-name: titleColorFade3; }
.module-item:nth-child(5) .module-title { animation-name: titleColorFade4; }
.module-item:nth-child(2) .module-desc::after { animation-name: descTextSweep, textGlowFade1; }
.module-item:nth-child(3) .module-desc::after { animation-name: descTextSweep, textGlowFade2; }
.module-item:nth-child(4) .module-desc::after { animation-name: descTextSweep, textGlowFade3; }
.module-item:nth-child(5) .module-desc::after { animation-name: descTextSweep, textGlowFade4; }

@keyframes moduleBlink {
    0%   { opacity: 0; }
    10%  { opacity: 0.6; }
    20%  { opacity: 0.05; }
    35%  { opacity: 0.8; }
    45%  { opacity: 0.15; }
    60%  { opacity: 1; }
    100% { opacity: 1; }
}

/* each square is 1.6x only during its own dwell, synced to clusterMove
   below, using the same slow-fast-slow curve at transition edges */
@keyframes moduleScale0 {
    0%   { transform: scale(1.6); animation-timing-function: linear; }
    16%  { transform: scale(1.6); animation-timing-function: cubic-bezier(.85,0,.15,1); }
    20%  { transform: scale(1);   animation-timing-function: linear; }
    96%  { transform: scale(1);   animation-timing-function: cubic-bezier(.85,0,.15,1); }
    100% { transform: scale(1.6); }
}
@keyframes moduleScale1 {
    16%  { transform: scale(1);   animation-timing-function: cubic-bezier(.85,0,.15,1); }
    20%  { transform: scale(1.6); animation-timing-function: linear; }
    36%  { transform: scale(1.6); animation-timing-function: cubic-bezier(.85,0,.15,1); }
    40%  { transform: scale(1); }
}
@keyframes moduleScale2 {
    36%  { transform: scale(1);   animation-timing-function: cubic-bezier(.85,0,.15,1); }
    40%  { transform: scale(1.6); animation-timing-function: linear; }
    56%  { transform: scale(1.6); animation-timing-function: cubic-bezier(.85,0,.15,1); }
    60%  { transform: scale(1); }
}
@keyframes moduleScale3 {
    56%  { transform: scale(1);   animation-timing-function: cubic-bezier(.85,0,.15,1); }
    60%  { transform: scale(1.6); animation-timing-function: linear; }
    76%  { transform: scale(1.6); animation-timing-function: cubic-bezier(.85,0,.15,1); }
    80%  { transform: scale(1); }
}
@keyframes moduleScale4 {
    76%  { transform: scale(1);   animation-timing-function: cubic-bezier(.85,0,.15,1); }
    80%  { transform: scale(1.6); animation-timing-function: linear; }
    96%  { transform: scale(1.6); animation-timing-function: cubic-bezier(.85,0,.15,1); }
    100% { transform: scale(1); }
}

/* the 4-square travelling cluster */
.cluster {
    position: absolute;
    left: 76px;
    top: 51px;
    width: 56px;
    height: 56px;
    pointer-events: none;
    opacity: 0;
    animation:
        moduleBlink 1.4s ease-out forwards,
        clusterMove 22.5s linear infinite 1.4s,
        clusterArrivalBlink 22.5s linear infinite 1.4s;
}
.cluster-dot {
    position: absolute;
    width: 11px;
    height: 11px;
    border-radius: 3px;
    background: #e8f28f;
    top: 50%; left: 50%;
}
.dot-top    { transform: translate(-50%, -50%) translateY(-57px); }
.dot-bottom { transform: translate(-50%, -50%) translateY(57px); }
.dot-left   { transform: translate(-50%, -50%) translateX(-57px); }
.dot-right  { transform: translate(-50%, -50%) translateX(57px); }

/* each transition rotates one full turn while translating to the next
   square, on the same slow-fast-slow curve */
@keyframes clusterMove {
    0%   { transform: translateY(0px)   rotate(0deg); }
    16%  { transform: translateY(0px)   rotate(0deg);   animation-timing-function: cubic-bezier(.85,0,.15,1); }
    20%  { transform: translateY(102px) rotate(90deg); }
    36%  { transform: translateY(102px) rotate(90deg);  animation-timing-function: cubic-bezier(.85,0,.15,1); }
    40%  { transform: translateY(204px) rotate(180deg); }
    56%  { transform: translateY(204px) rotate(180deg); animation-timing-function: cubic-bezier(.85,0,.15,1); }
    60%  { transform: translateY(306px) rotate(270deg); }
    76%  { transform: translateY(306px) rotate(270deg); animation-timing-function: cubic-bezier(.85,0,.15,1); }
    80%  { transform: translateY(408px) rotate(360deg); }
    96%  { transform: translateY(408px) rotate(360deg); animation-timing-function: cubic-bezier(.85,0,.15,1); }
    100% { transform: translateY(0px)   rotate(450deg); }
}

/* quick flicker on landing, then settles until the next transition */
@keyframes clusterArrivalBlink {
    0%    { opacity: 0.35; }
    0.6%  { opacity: 1; }
    1.2%  { opacity: 0.25; }
    1.8%  { opacity: 1; }
    20%   { opacity: 1; }
    20.6% { opacity: 0.35; }
    21.2% { opacity: 1; }
    21.8% { opacity: 0.25; }
    22.4% { opacity: 1; }
    40%   { opacity: 1; }
    40.6% { opacity: 0.35; }
    41.2% { opacity: 1; }
    41.8% { opacity: 0.25; }
    42.4% { opacity: 1; }
    60%   { opacity: 1; }
    60.6% { opacity: 0.35; }
    61.2% { opacity: 1; }
    61.8% { opacity: 0.25; }
    62.4% { opacity: 1; }
    80%   { opacity: 1; }
    80.6% { opacity: 0.35; }
    81.2% { opacity: 1; }
    81.8% { opacity: 0.25; }
    82.4% { opacity: 1; }
    100% { opacity: 1; }
}

@media (prefers-reduced-motion: reduce) {
    .module-sq-wrap, .cluster { animation: none; opacity: 1; }
    .module-sq::before, .module-sq-wrap::before { animation: none; opacity: 0; }
}

/* ================= STEP 4: right-side login card (glassmorphism) ================= */
.login-card {
    position: absolute;
    z-index: 4;
    /* `right` (not `left`) so the ≤768px query's position:static reset
       stays independent of it. clamp keeps the card a consistent 40-96px
       from the right edge at every desktop width. */
    right: clamp(40px, 4vw, 96px);
    top: 50%;
    transform: translateY(-50%);
    width: min(420px, 34vw);
    padding: 40px 36px;
    border-radius: 28px;
    background: rgba(255,255,255,0.08);
    backdrop-filter: blur(24px);
    -webkit-backdrop-filter: blur(24px);
    border: 1px solid rgba(255,255,255,0.22);
    box-shadow: 0 30px 80px rgba(0,0,0,0.45), inset 0 1px 0 rgba(255,255,255,0.15);
    color: #fff;
}
.login-greeting {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    justify-content: center;
    gap: 0;
    margin: 0 0 24px;
    text-align: left;
}
.login-greeting .greeting-accent {
    width: 28px;
    height: 2px;
    border-radius: 1px;
    background: #5e93f5;
    margin-bottom: 8px;
}
.login-greeting .greeting-hello {
    font-family: var(--font-ui);
    font-size: 1.25rem;
    font-weight: 400;
    line-height: 1.4;
    color: rgba(255,255,255,0.55);
    margin-bottom: 2px;
}
.login-greeting .greeting-line2 {
    position: relative;
    display: flex;
    align-items: center;
    gap: 10px;
    font-family: var(--font-display);
    font-size: 1.75rem;
    font-weight: 700;
    line-height: 1.2;
    letter-spacing: -0.01em;
    color: #fff;
}
/* single-line note under a card heading (e.g. forgot-password's subtext) */
.login-card-note {
    font-family: var(--font-ui);
    font-size: 0.875rem;
    font-weight: 400;
    line-height: 1.5;
    color: rgba(255,255,255,0.7);
    margin: 0 0 24px;
}
.login-greeting img {
    display: none;
}
.login-greeting .brand-word.is-regulus {
    font-family: "Bricolage Grotesque", ui-sans-serif, sans-serif;
    font-weight: 800;
    color: #5e93f5;
    font-size: 1.1em;
}

/* min-width:0 overrides the default min-width:auto that was letting a
   long field's content push its .register-grid column wider than its
   1fr share */
.login-field { margin-bottom: 22px; min-width: 0; }
.login-field label {
    display: block;
    margin-bottom: 8px;
    font-family: var(--font-ui);
    font-size: 0.8125rem;
    font-weight: 500;
    line-height: 1.4;
    color: rgba(255,255,255,0.85);
}
.login-field .req { color: #ff8a8a; }
.login-input-wrap { position: relative; min-width: 0; }
/* opaque fill instead of a translucent tint — the glass card's blur
   otherwise let whatever sits behind it bleed through, costing the
   white input text its contrast */
.login-input {
    width: 100%;
    height: 54px;
    border-radius: 16px;
    background: #16223b;
    border: 1px solid rgba(255,255,255,0.22);
    color: #fff;
    padding: 0 48px 0 18px;
    font-family: var(--font-ui);
    font-size: 0.9375rem;
    font-weight: 400;
    line-height: 1.4;
}
.login-input::placeholder { color: rgba(255,255,255,0.45); }
.login-input:focus {
    outline: none;
    border-color: rgba(255,255,255,0.55);
    background: #1c2c4c;
}
.login-icon-btn {
    position: absolute;
    right: 16px;
    top: 50%;
    transform: translateY(-50%);
    cursor: pointer;
    color: rgba(255,255,255,0.6);
    display: flex;
}
.login-icon-btn svg {
    width: 20px;
    height: 20px;
    fill: none;
    stroke: currentColor;
    stroke-width: 1.7;
    stroke-linecap: round;
    stroke-linejoin: round;
}
/* autofill forces a white input background, making the light icon
   invisible — darken it only while :autofill actually matches */
.login-input:autofill ~ .login-icon-btn,
.login-input:-webkit-autofill ~ .login-icon-btn {
    color: rgba(0,0,0,0.55);
}

.login-row {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    margin: 4px 0 28px;
    font-family: var(--font-ui);
    font-size: 0.8125rem;
    font-weight: 400;
    line-height: 1.5;
}
.login-forgot { color: #5e93f5; font-weight: 500; text-decoration: none; }

.login-btn {
    /* block, not the default inline-block — margin:auto (used by the
       shared spin() JS to re-center the shrunk spinner) needs it */
    display: block;
    position: relative;
    overflow: hidden;
    width: 100%;
    height: 58px;
    border: none;
    border-radius: 999px;
    background: linear-gradient(115deg, #2f5bb0, #3d7fd6, #6fa8f5, #3d7fd6, #2f5bb0);
    background-size: 300% auto;
    animation: loginBtnFlow 9s ease-in-out infinite, loginBtnGlow 3.5s ease-in-out infinite;
    color: #fff;
    font-family: var(--font-ui);
    font-size: 0.9375rem;
    font-weight: 600;
    line-height: 1;
    letter-spacing: 0.01em;
    cursor: pointer;
    margin-bottom: 26px;
    transition: transform .2s ease;
}
.login-btn:hover { transform: translateY(-1px); }
@keyframes loginBtnFlow {
    0%, 100% { background-position: 0% 50%; }
    50%      { background-position: 100% 50%; }
}
@keyframes loginBtnGlow {
    0%, 100% { filter: drop-shadow(0 0 4px rgba(94,168,245,0.1)) drop-shadow(0 0 9px rgba(61,127,214,0.07)); }
    50%      { filter: drop-shadow(0 0 8px rgba(94,168,245,0.2)) drop-shadow(0 0 16px rgba(61,127,214,0.13)); }
}
/* subtle light swipe, hover-only */
.login-btn::after {
    content: "";
    position: absolute;
    top: 0;
    left: -60%;
    width: 35%;
    height: 100%;
    background: linear-gradient(115deg, transparent, rgba(255,255,255,0.12), transparent);
    transform: skewX(-20deg);
    transition: left 1s ease;
    pointer-events: none;
}
.login-btn:hover::after { left: 130%; }
@media (prefers-reduced-motion: reduce) {
    .login-btn::after { transition: none; }
    .login-btn { animation: none; }
}

.login-links {
    text-align: center;
    font-family: var(--font-ui);
    /* smaller + nowrap so "To share your Industrial Knowledge
       Experience? Click here" fits on one line at the card's normal
       (≥~420px) width instead of wrapping mid-sentence; at very narrow
       desktop widths it can still overflow rather than wrap — an
       acceptable tradeoff since that band is already a tight squeeze */
    font-size: 0.75rem;
    white-space: nowrap;
    font-weight: 400;
    line-height: 1.5;
    color: rgba(255,255,255,0.75);
    margin: 0 0 8px;
}
.login-links a { color: #5e93f5; font-weight: 500; text-decoration: none; }

.login-oem { margin-top: 28px; text-align: center; }
.login-oem .label {
    font-family: var(--font-ui);
    font-size: 0.6875rem;
    font-weight: 500;
    line-height: 1;
    color: rgba(255,255,255,0.55);
    text-transform: uppercase;
    letter-spacing: 0.1em;
    margin-bottom: 14px;
}
/* auto-scrolling OEM strip — a real overflow-x:auto element (driven via
   scrollLeft in the script section), not a CSS @keyframes marquee, so
   wheel/drag can move it too without fighting the auto-scroll */
.login-oem-carousel {
    display: flex;
    align-items: center;
    gap: 20px;
    overflow-x: auto;
    overflow-y: hidden;
    /* headroom for the hover scale below so it doesn't clip against
       overflow-y:hidden */
    padding: 10px 4px;
    cursor: grab;
    /* hide the native scrollbar while staying scrollable */
    scrollbar-width: none;
    -ms-overflow-style: none;
}
.login-oem-carousel::-webkit-scrollbar { display: none; }
.login-oem-carousel.is-dragging { cursor: grabbing; }
.login-oem-carousel img {
    height: 56px;
    width: auto;
    object-fit: contain;
    background: #fff;
    border-radius: 12px;
    padding: 5px 8px;
    flex: 0 0 auto;
    transition: transform 0.6s ease, opacity 0.6s ease;
    /* stop the browser's native "ghost image" drag from fighting our
       own click-and-drag scroll handling */
    -webkit-user-drag: none;
    user-select: none;
}
/* hover anywhere on the strip dims every logo; the one actually under
   the cursor is un-dimmed and scaled up by a more specific rule */
.login-oem-carousel:hover img { opacity: 0.55; }
.login-oem-carousel img:hover { opacity: 1; transform: scale(1.06); }

/* ================= STEP 5: real-page integration =================
   Server-side alerts/@error labels re-themed for the dark card, plus
   sizing for the real (shared) FontAwesome password-toggle icon. */
.login-card .alert {
    border-radius: 12px;
    padding: 12px 16px;
    font-family: var(--font-ui);
    font-size: 0.8125rem;
    line-height: 1.5;
    margin-bottom: 18px;
    border: 1px solid transparent;
}
.login-card .alert-danger {
    background: rgba(255,90,90,0.12);
    border-color: rgba(255,90,90,0.35);
    color: #ffb3b3;
}
.login-card .alert-success {
    background: rgba(94,196,255,0.12);
    border-color: rgba(94,196,255,0.35);
    color: #bfe4ff;
}
.login-field label.error {
    display: block;
    margin-top: 6px;
    font-size: 0.75rem;
    font-weight: 400;
}
.login-icon-btn i {
    font-size: 18px;
    line-height: 1;
}
/* toggled by jQuery Validate's highlight()/unhighlight() */
.login-field.has-error .login-input {
    border-color: rgba(255,90,90,0.6);
}

/* ================= STEP 6: register page =================
   Register's form is too tall for login/forgot's absolutely-positioned
   overlay card (which never contributes to .stage's own height, so it'd
   just get clipped by .stage's overflow:hidden). .stage-row instead makes
   .stage a real flex row — .stage-left (hero + module-rail) and
   .login-card--wide as ordinary in-flow siblings, side by side on desktop
   and stacked ≤768px — so .stage always grows to fit the taller side. */
/* nowrap: .stage-left keeps its full content-driven width; the card is
   the only side that flexes/shrinks (see .login-card--wide below) */
.stage.stage-row {
    display: flex;
    align-items: flex-start;
    flex-wrap: nowrap;
    gap: 40px;
    padding: 40px;
}
.stage-row .stage-left {
    /* untouched: module-rail's own natural min-width:auto minimum applies */
    flex: 1 1 420px;
}
/* the card is the only flexible side of the row. min-width:0 (no floor)
   lets it shrink fully rather than overflow past .stage's edge; margin-right
   keeps a gutter as it narrows. container-type:inline-size lets the form
   grid below react to the card's own width (not the viewport's). */
.login-card.login-card--wide {
    position: relative;
    right: auto;
    top: auto;
    transform: none;
    flex: 1 1 340px;
    min-width: 0;
    max-width: 100%;
    margin-right: 24px;
    align-self: center;
    container-type: inline-size;
}
/* .span-2 fields (security-question sub-grid, PO checkbox, reCAPTCHA row)
   take the full width regardless of column count */
/* minmax(0, 1fr) on the track itself — plain 1fr still lets a track's
   automatic min-content size (a long label) win over its fr-share,
   rendering "equal" columns unevenly */
.register-grid {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 4px 24px;
}
.register-grid .span-2 { grid-column: 1 / -1; }
/* gap tightens up before the columns themselves have to give way */
@container (max-width: 340px) {
    .register-grid { gap: 4px 14px; }
}
/* single column once the CARD (not the viewport) can't fit two */
@container (max-width: 480px) {
    .register-grid { grid-template-columns: 1fr; }
}
/* padding shrinks further as the card keeps narrowing past that point */
@container (max-width: 360px) {
    .login-card.login-card--wide { padding: 32px 24px; }
}
@container (max-width: 240px) {
    .login-card.login-card--wide { padding: 20px 14px; }
}
/* Authorized checkbox + reCAPTCHA sit side by side, checkbox v-centered */
.register-grid .login-recaptcha-row { justify-content: center; }
.register-grid .login-field--checkbox { display: flex; align-items: center; }
.login-card-note {
    margin-top: 4px;
    text-align: center;
}
.login-card-note a { color: #5e93f5; text-decoration: none; }
.login-card-subtext {
    font-family: var(--font-ui);
    font-size: 0.875rem;
    font-weight: 400;
    line-height: 1.5;
    color: rgba(255,255,255,0.65);
    margin: 6px 0 24px;
}

/* left-aligned icon, mirroring the password field's right-side toggle */
.login-input-icon-left {
    position: absolute;
    left: 16px;
    top: 50%;
    transform: translateY(-50%);
    color: rgba(255,255,255,0.45);
    display: flex;
    pointer-events: none;
}
.login-input-icon-left svg {
    width: 18px;
    height: 18px;
    fill: none;
    stroke: currentColor;
    stroke-width: 1.6;
    stroke-linecap: round;
    stroke-linejoin: round;
}
.login-input.has-icon { padding-left: 44px; }
/* register never needs the right-side password-toggle padding */
.register-grid .login-input { padding-right: 18px; }
/* drop the icon once the card is too narrow for its 44px reservation */
@container (max-width: 240px) {
    .login-input-icon-left { display: none; }
    .login-input.has-icon { padding-left: 14px; }
}

/* smooth open/close instead of jQuery's instant show()/hide() */
#security_question_box {
    overflow: hidden;
    max-height: 400px;
    opacity: 1;
    transition: max-height 0.35s ease, opacity 0.25s ease, margin 0.35s ease;
}
#security_question_box.is-hidden {
    max-height: 0;
    opacity: 0;
    margin: 0;
    pointer-events: none;
}

/* <select> — reset native chrome, add a custom chevron matching the
   site's thin-stroke icon style */
.login-select {
    appearance: none;
    -webkit-appearance: none;
    -moz-appearance: none;
    padding-right: 44px;
    cursor: pointer;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 24 24' fill='none' stroke='%23b9c6de' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 16px center;
    background-size: 14px;
}
.login-select option { background: #16223b; color: #fff; }

/* number input — hide the default spinner arrows for a cleaner look
   consistent with the rest of the inputs */
.login-input[type="number"]::-webkit-inner-spin-button,
.login-input[type="number"]::-webkit-outer-spin-button {
    -webkit-appearance: none;
    margin: 0;
}
.login-input[type="number"] { appearance: textfield; -moz-appearance: textfield; }

/* vertically centers against its sibling grid cell (OEM select + label) */
.login-field--toggle {
    display: flex;
    align-items: center;
}
/* iOS-style toggle switch (Security questions) */
.toggle-switch {
    position: relative;
    display: inline-grid;
    grid-template-columns: 44px auto;
    align-items: center;
    gap: 10px;
    cursor: pointer;
    margin: 0; /* resets Bootstrap's global label{margin-bottom:.5rem} */
}
.toggle-switch input {
    position: absolute;
    opacity: 0;
    width: 1px;
    height: 1px;
    margin: 0;
}
/* the pill: a real element with a ::after dot, toggled via the input's
   checked state using `~` (not the stricter `+`) */
.toggle-track {
    position: relative;
    display: inline-block;
    width: 44px;
    height: 24px;
    border-radius: 999px;
    background: rgba(255,255,255,0.2);
    border: 1px solid rgba(255,255,255,0.25);
    transition: background-color 0.2s ease, border-color 0.2s ease;
}
.toggle-track::after {
    content: "";
    position: absolute;
    top: 2px;
    left: 2px;
    width: 18px;
    height: 18px;
    border-radius: 50%;
    background: #fff;
    transition: transform 0.2s ease;
}
.toggle-switch input:checked ~ .toggle-track {
    background-color: #3d7fd6;
    border-color: #3d7fd6;
}
.toggle-switch input:checked ~ .toggle-track::after {
    transform: translateX(20px);
}
.toggle-label {
    display: flex;
    align-items: center;
    height: 24px;
    font-family: var(--font-ui);
    font-size: 0.8125rem;
    font-weight: 500;
    line-height: 1;
    color: rgba(255,255,255,0.85);
}

/* plain checkbox (PO authorization). Qualified as .login-field
   .login-checkbox (not bare .login-checkbox) since .login-field label's
   higher specificity would otherwise override display:flex here */
.login-field .login-checkbox {
    display: flex;
    align-items: center;
    gap: 10px;
    margin: 0;
    cursor: pointer;
    font-family: var(--font-ui);
    font-size: 0.8125rem;
    font-weight: 400;
    color: rgba(255,255,255,0.85);
}
.login-checkbox input {
    position: absolute;
    opacity: 0;
    width: 0;
    height: 0;
}
.login-checkbox-box {
    position: relative;
    flex: 0 0 auto;
    width: 18px;
    height: 18px;
    border-radius: 5px;
    border: 1.5px solid rgba(255,255,255,0.4);
    display: grid;
    place-content: center;
    transition: background 0.15s ease, border-color 0.15s ease;
}
.login-checkbox input:checked + .login-checkbox-box {
    background: #fff;
    border-color: #fff;
}
.login-checkbox input:checked + .login-checkbox-box::after {
    content: "";
    width: 9px;
    height: 9px;
    border-radius: 2px;
    background: #3d7fd6;
}

.login-recaptcha-row {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 8px;
}
/* Google's widget is a fixed ~304x78px iframe (ignores CSS width) that
   can overflow the narrowed card; wrap+scale to reclaim that space since
   transform:scale alone doesn't shrink the layout box it occupies */
.recaptcha-scale-wrap {
    width: 304px;
    height: 78px;
    overflow: hidden;
}
.recaptcha-scale-wrap .g-recaptcha { transform-origin: 0 0; }
@container (max-width: 320px) {
    .recaptcha-scale-wrap { width: 270px; height: 69px; }
    .recaptcha-scale-wrap .g-recaptcha { transform: scale(0.888); }
}
@container (max-width: 280px) {
    .recaptcha-scale-wrap { width: 230px; height: 59px; }
    .recaptcha-scale-wrap .g-recaptcha { transform: scale(0.756); }
}
@container (max-width: 240px) {
    .recaptcha-scale-wrap { width: 190px; height: 49px; }
    .recaptcha-scale-wrap .g-recaptcha { transform: scale(0.625); }
}

/* jQuery UI autocomplete (Company Name) — !important overrides its own
   default light theme, which clashes with the dark glass card */
.ui-autocomplete {
    background: #16223b !important;
    border: 1px solid rgba(255,255,255,0.22) !important;
    border-radius: 12px !important;
    padding: 6px !important;
    font-family: var(--font-ui) !important;
    box-shadow: 0 20px 50px rgba(0,0,0,0.5) !important;
}
.ui-autocomplete .ui-menu-item-wrapper {
    padding: 8px 12px !important;
    border-radius: 8px !important;
    margin: 0 !important;
    border: none !important;
    background: transparent !important;
    color: #fff !important;
    font-size: 0.875rem !important;
}
.ui-autocomplete .ui-menu-item-wrapper.ui-state-active {
    background: rgba(94,196,255,0.18) !important;
    color: #fff !important;
}

/* ================= MOBILE (<=768px) =================
   Laptop/tablet (769px+) is untouched. .stage becomes a centered flex
   column; .hero/.login-card/.hero-sub-mobile/.module-rail reorder via
   `order`. The icon rail's animations are left alone — only padding and
   the description's clip width change, plus nowrap+ellipsis so the row's
   fixed height (and the cluster's timing) never has to change. */
@media (max-width: 768px) {
    .stage {
        display: flex;
        flex-direction: column;
        align-items: center;
    }
    .hero {
        order: 1;
        width: 100%;
        padding: 40px 24px 0;
        text-align: center;
    }
    .hero .hero-sub { display: none; }
    .login-card {
        order: 2;
        position: static;
        /* position:static alone doesn't cancel the base rule's
           translateY(-50%), so the card would still render shifted up */
        transform: none;
        width: calc(100% - 40px);
        max-width: 480px;
        margin: 28px 0;
        padding: 40px 24px;
    }
    /* needs its own position+z-index (unlike other rules' plain static
       content) to paint above .stage-bg-layer/.stage-scrim */
    .hero-sub-mobile {
        display: block;
        order: 3;
        position: relative;
        z-index: 2;
        width: calc(100% - 48px);
        max-width: 340px;
        margin: 0 0 32px;
        text-align: center;
        font-family: var(--font-ui);
        font-weight: 500;
        font-size: 0.9375rem;
        line-height: 1.6;
        letter-spacing: 0.02em;
        color: rgba(234,242,255,0.85);
        text-shadow: 0 1px 6px rgba(0,0,0,0.6);
    }
    /* width:max-content (same strategy as desktop) sizes the rail to
       its own compact content instead of stretching full-bleed, so
       margin:auto actually centers the icon+text block as a unit —
       width:100% here was the "stuck to the left" bug: the rail
       spanned the full viewport but its content never filled that
       width, so it just sat left-anchored by its own padding instead
       of being centered. max-width guards the narrowest phones. */
    .module-rail {
        order: 4;
        width: max-content;
        max-width: calc(100% - 32px);
        margin: 0 auto;
        padding: 48px 20px 32px 24px;
    }
    /* icon shrunk 56->44px; row height is driven by .module-desc-clip's
       unchanged 62px, so clusterMove's timing is unaffected */
    .module-sq-wrap { width: 44px; height: 44px; }
    .module-sq-inner { width: 42px; height: 42px; border-radius: 7px; }
    .module-sq svg { width: 30px; height: 30px; }
    /* cluster/dots repositioned to match the smaller icon */
    .cluster { left: 24px; top: 57px; width: 44px; height: 44px; }
    .dot-top    { transform: translate(-50%, -50%) translateY(-45px); }
    .dot-bottom { transform: translate(-50%, -50%) translateY(45px); }
    .dot-left   { transform: translate(-50%, -50%) translateX(-45px); }
    .dot-right  { transform: translate(-50%, -50%) translateX(45px); }
    /* scales with viewport (100vw-108px = rail padding+icon+margin),
       capped at 280px; ellipsis is the safety net below that */
    .module-desc-clip { width: min(280px, calc(100vw - 108px)); }
    .module-desc-inner { width: 100%; }
    .module-title, .module-desc, .module-desc::after {
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
    }
    .module-title { font-size: 0.6875rem; }
    .module-desc { font-size: 0.75rem; }

}

/* ================= REGISTER (<=992px) =================
   Register's row-to-stacked switch needs a wider breakpoint than the
   shared 768px one: .module-desc-clip is a hard-coded 420px and doesn't
   shrink until 768px, so the side-by-side row has no room for a usable
   card below ~992px. Kept as its own query so login/forgot-password
   keep switching at exactly 768px, unaffected. */
@media (max-width: 992px) {
    .stage.stage-row {
        flex-direction: column;
        padding: 0;
        gap: 0;
        /* re-centers the stacked column, overriding the desktop rule's
           align-items:flex-start (same specificity, wins on source order) */
        align-items: center;
    }
    /* display:contents promotes .stage-left's children to direct flex
       items of .stage, so they pick up the order:1/2/3/4 rules below —
       matching login/forgot-password's stacking order */
    .stage-row .stage-left { display: contents; }
    /* scoped with .stage-row so login/forgot-password (no such class)
       keep their own unconditional styling untouched */
    .stage-row .hero {
        order: 1;
        width: 100%;
        padding: 40px 24px 0;
        text-align: center;
    }
    .stage-row .hero .hero-sub { display: none; }
    .stage-row .hero-sub-mobile {
        display: block;
        order: 3;
        position: relative;
        z-index: 2;
        width: calc(100% - 48px);
        max-width: 340px;
        margin: 0 0 32px;
        text-align: center;
        font-family: var(--font-ui);
        font-weight: 500;
        font-size: 0.9375rem;
        line-height: 1.6;
        letter-spacing: 0.02em;
        color: rgba(234,242,255,0.85);
        text-shadow: 0 1px 6px rgba(0,0,0,0.6);
    }
    .stage-row .module-rail {
        order: 4;
        width: max-content;
        max-width: calc(100% - 32px);
        margin: 0 auto;
        padding: 48px 20px 32px 24px;
    }
    .stage-row .module-sq-wrap { width: 44px; height: 44px; }
    .stage-row .module-sq-inner { width: 42px; height: 42px; border-radius: 7px; }
    .stage-row .module-sq svg { width: 30px; height: 30px; }
    .stage-row .cluster { left: 24px; top: 57px; width: 44px; height: 44px; }
    .stage-row .dot-top    { transform: translate(-50%, -50%) translateY(-45px); }
    .stage-row .dot-bottom { transform: translate(-50%, -50%) translateY(45px); }
    .stage-row .dot-left   { transform: translate(-50%, -50%) translateX(-45px); }
    .stage-row .dot-right  { transform: translate(-50%, -50%) translateX(45px); }
    .stage-row .module-desc-clip { width: min(280px, calc(100vw - 108px)); }
    .stage-row .module-desc-inner { width: 100%; }
    .stage-row .module-title,
    .stage-row .module-desc,
    .stage-row .module-desc::after {
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
    }
    .stage-row .module-title { font-size: 0.6875rem; }
    .stage-row .module-desc { font-size: 0.75rem; }
    .login-card.login-card--wide {
        order: 2;
        /* reset flex-basis to auto — in column mode a leftover 420px
           would be read as a height, not a width */
        flex: 0 0 auto;
        width: calc(100% - 40px);
        min-width: 0;
        max-width: 480px;
        margin: 28px auto;
    }
    .register-grid { grid-template-columns: 1fr; }
}
