/* Shared visual language for every Account screen.

   Two things live here:

   1. .auth-brand — the QService lockup as it appears in the WHITE form panel. Used by the
      Login/Register switcher AND by the single-mode pages below, so it is defined once here
      rather than duplicated. (In the blue panel it sat on the curved edge and got sliced.)

   2. .auth-shell — the same curved blue panel + white form panel as the Login/Register
      switcher, minus the two-mode sliding machinery, for the single-mode pages:
      ForgetPassword, ResetPassword, SetupTwoFactor, VerifySmsCode, VerifyTwoFactor.

   Every layout rule is scoped .auth-shell.login-page / .auth-shell .login-* (two selectors)
   so it outranks each page's own inline <style> block — those are emitted AFTER this
   stylesheet and still carry the old flex-based .login-page rules. */

/* ============================ 1. Brand lockup ============================ */

.auth-brand {
    display: flex;
    align-items: center;
    gap: 10px;
    font-size: 20px;
    font-weight: 800;
    color: var(--qs-primary);
    margin-bottom: var(--qs-space-5);
}
.auth-brand__img {
    width: 36px;
    height: 36px;
    border-radius: var(--qs-radius-md);
    object-fit: contain;
}
/* 2026-08 audit remediation (L5-crit gap b): both literals tokenised. The dark rule
   is KEPT rather than collapsed — the design genuinely differs per theme here (brand
   blue on light, near-white on dark), so this is not a case where one tokenised
   light rule can serve both. */
html[data-theme="dark"] .auth-brand { color: var(--qs-text); }

/* ======================= 2. Single-mode page shell ======================= */

.auth-shell.login-page {
    position: relative;
    display: block;
    width: 100vw;
    height: 100vh;
    overflow: hidden;
}

.auth-shell .login-left,
.auth-shell .login-right {
    position: absolute;
    top: 0;
    height: 100%;
    flex: none;
    min-width: 0;   /* must stay 0 — a larger min-width overflows the absolute box and
                       forces a page scrollbar, which is what happened on the switcher */
}

.auth-shell .login-left  { width: 70%; }
.auth-shell .login-right {
    width: 30%;
    overflow-y: auto;
    /* NEVER a horizontal scrollbar on a 480px auth panel - it can only ever be a bug.
       Measured cause: .login-lang (the language switcher) is position:fixed but sits INSIDE
       this panel in the markup. A fixed element normally escapes an ancestor's scroll box,
       but only if no ancestor establishes a containing block (transform/filter/will-change
       do). Here one does, so the switcher - rendered ~1048px away at the opposite corner -
       was counted into this panel's scrollable width: scrollWidth 1384 against clientWidth
       480. That produced the horizontal bar, and its offset above the panel top produced the
       vertical one.
       Clipping here is the safe fix; moving the switcher out of the panel in five auth views
       would be the structural one. */
    box-shadow: none !important;   /* the panel now meets a curve, not a flush edge —
                                      the old shadow reads as a stray line */
}

/* SCROLLBARS ON THE AUTH PANEL
   -----------------------------
   The panel reported scrollHeight 1350 against clientHeight 900 while its actual content
   measures 687px (96px padding-top + 543px card + 48px padding-bottom) - so it drew a
   scrollbar over 450px of empty background. Scrolling to the bottom confirms it: the
   region is blank panel, no element in it.

   Rather than keep hunting the phantom, this is solved by construction. A scroll container
   is only CORRECT here when the content genuinely cannot fit; the content height is known
   and fixed, so the viewport height at which it stops fitting is known too.

     >= 720px tall : content fits with room to spare -> no scroll container at all,
                     so no phantom height can produce a bar.
     <  720px tall : the card really would be clipped -> allow vertical scrolling, which
                     is the case a scrollbar is actually for.

   The threshold sits just above the measured 687px content height. overflow-x is hidden in
   both cases: a horizontal bar on a 480px auth panel can only ever be a bug. */
.auth-shell .login-right {
    overflow-x: hidden;
    overflow-y: hidden;
}

@media (max-height: 719px) {
    .auth-shell .login-right {
        overflow-y: auto;
        /* Scrolling still works (needed on a short viewport) - just don't draw a bar over
           the curved auth panel, it reads as a stray paint stroke against the blue curve. */
        scrollbar-width: none;        /* Firefox */
        -ms-overflow-style: none;     /* old Edge/IE */
    }
    .auth-shell .login-right::-webkit-scrollbar {
        width: 0;
        height: 0;
        background: transparent;
    }
}

/* Sides + curve match the Login page exactly: LTR blue right, RTL blue left.
   Blue anchored left curves on its right edge and vice versa. */
.auth-shell .login-left  { right: 0; clip-path: url(#authCurveRight); }
.auth-shell .login-right { left: 0; }

[dir="rtl"] .auth-shell .login-left  { right: auto; left: 0; clip-path: url(#authCurveLeft); }
[dir="rtl"] .auth-shell .login-right { left: auto; right: 0; }

/* Blue panel no longer holds the logo — centre its message, pin the copyright. */
.auth-shell .login-left__inner  { justify-content: center; }
.auth-shell .login-left__footer {
    position: absolute;
    bottom: 32px;
    left: 0;
    right: 0;
    text-align: center;
}

/* The language pill and theme toggle already default to the inline-end side, which is
   exactly where the blue panel now sits in both directions — so they need no override
   here, unlike the switcher where the blue panel changes sides. */

@media (max-width: 768px) {
    .auth-shell .login-left  { display: none; }
    .auth-shell .login-right { width: 100%; left: 0; right: 0; }
    [dir="rtl"] .auth-shell .login-right { left: 0; right: 0; }
}

/* ==================== 3. Entrance choreography ====================

   Plays once on page load. Every rule targets the CONTENTS of the blue panel, never the
   .auth-color wrapper itself — that wrapper's transform belongs to the mode switcher, and
   two animations on one property would fight. Same reason the orbs get their drift and
   their entrance in ONE `animation` shorthand: a second `animation` declaration replaces
   the first outright rather than adding to it.

   Order of the beat: panel settles -> orbs bloom -> light sweeps across -> headline and
   sub-copy rise -> footer fades up. Transform/opacity only, so none of it causes layout. */

/* Blue panel settles in, then keeps a very slow living gradient.
   These selectors outrank the per-page `.login-left` rule, so the gradient drift has to be
   re-listed here or declaring `animation` would cancel it. */
.auth-color .login-left,
.auth-shell .login-left {
    background-size: 220% 220%;
    animation: qsPanelIn 1.05s cubic-bezier(.22,1,.36,1) both,
               qsAuthSheen 22s ease-in-out 1.05s infinite;
}

/* Decorative orbs bloom in, then hand off to a slow endless drift. */
.auth-color .login-left::before,
.auth-shell .login-left::before {
    animation: qsOrbIn 1.2s cubic-bezier(.22,1,.36,1) .15s both,
               qsDriftA 16s ease-in-out 1.35s infinite;
}
.auth-color .login-left::after,
.auth-shell .login-left::after {
    animation: qsOrbIn 1.2s cubic-bezier(.22,1,.36,1) .30s both,
               qsDriftB 20s ease-in-out 1.50s infinite;
}
.auth-color .login-left__circle,
.auth-shell .login-left__circle {
    animation: qsOrbIn 1.2s cubic-bezier(.22,1,.36,1) .45s both,
               qsDriftC 13s ease-in-out 1.65s infinite;
}

/* One-shot band of light travelling across the panel, behind the copy (z-index 0 vs the
   .login-left__inner z-index 1). Absolutely positioned so it never joins the flex flow. */
.login-left__sheen {
    position: absolute;
    top: -25%;
    bottom: -25%;
    left: 0;
    width: 38%;
    z-index: 0;
    pointer-events: none;
    background: linear-gradient(100deg,
        rgba(255,255,255,0) 0%,
        rgba(255,255,255,0.13) 50%,
        rgba(var(--qs-white-rgb), 0) 100%);
    transform: translateX(-180%) skewX(-14deg);
    /* Loops rather than firing once — the panel should stay alive, not freeze after load.
       The sweep itself occupies only the first quarter of the cycle; the rest is a deliberate
       pause with the band parked off-screen at opacity 0, so the restart is invisible. */
    animation: qsSheenLoop 9s cubic-bezier(.45,0,.2,1) .6s infinite;
}

/* ---- Orbit: commerce + service motifs circling the platform (markup in _AuthOrbit.cshtml).

   Two counter-rotating rings read as motion far more clearly than drifting blobs, and the
   opposed directions stop it looking like one rigid object being spun.

   The rings must carry their own centring INSIDE the keyframes: `transform` is a single
   property, so animating rotate() would otherwise wipe out the translate(-50%,-50%) that
   centres them, and each ring would fly off to the bottom-right. ---- */
.qs-orbit {
    position: absolute;
    top: 50%;
    left: 50%;
    width: 0;
    height: 0;
    z-index: 0;                 /* behind .login-left__inner, which is z-index 1 */
    pointer-events: none;
    color: rgba(var(--qs-white-rgb), .62);
    animation: qsAuthFade 1.4s ease .7s both;
}

.qs-orbit__ring {
    position: absolute;
    top: 50%;
    left: 50%;
    border-radius: var(--qs-radius-circle);
    border: 1px solid rgba(var(--qs-white-rgb), .10);
}
.qs-orbit__ring--dotted {
    width: 720px; height: 720px;
    border-style: dashed;
    border-color: rgba(var(--qs-white-rgb), .07);
    animation: qsOrbitCW 90s linear infinite;
}
.qs-orbit__ring--outer {
    width: 540px; height: 540px;
    animation: qsOrbitCW 42s linear infinite;
}
.qs-orbit__ring--inner {
    width: 360px; height: 360px;
    border-color: rgba(var(--qs-white-rgb), .08);
    animation: qsOrbitCCW 32s linear infinite;
}

.qs-orbit__node {
    position: absolute;
    width: 46px;
    height: 46px;
    border-radius: 15px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: rgba(var(--qs-white-rgb), .13);
    border: 1px solid rgba(var(--qs-white-rgb), .22);
    box-shadow: 0 6px 18px rgba(var(--qs-shadow-rgb), .18);
}
.qs-orbit__node svg { width: 22px; height: 22px; }

/* Four anchor points per ring, placed with offsets rather than trigonometry so each node's
   own `transform` stays free for the counter-rotation below. */
.qs-orbit__node--t { top: -23px;    left: calc(50% - 23px); }
.qs-orbit__node--b { bottom: -23px; left: calc(50% - 23px); }
.qs-orbit__node--l { left: -23px;   top: calc(50% - 23px); }
.qs-orbit__node--r { right: -23px;  top: calc(50% - 23px); }

/* Each node spins against its ring at the same period, so the icons ride the orbit while
   staying upright instead of tumbling. */
.qs-orbit__ring--outer .qs-orbit__node { animation: qsOrbitNodeCCW 42s linear infinite; }
.qs-orbit__ring--inner .qs-orbit__node { animation: qsOrbitNodeCW  32s linear infinite; }

@keyframes qsOrbitCW  {
    from { transform: translate(-50%, -50%) rotate(0deg); }
    to   { transform: translate(-50%, -50%) rotate(360deg); }
}
@keyframes qsOrbitCCW {
    from { transform: translate(-50%, -50%) rotate(0deg); }
    to   { transform: translate(-50%, -50%) rotate(-360deg); }
}
@keyframes qsOrbitNodeCW  { from { transform: rotate(0deg); } to { transform: rotate(360deg); } }
@keyframes qsOrbitNodeCCW { from { transform: rotate(0deg); } to { transform: rotate(-360deg); } }

/* Shorter viewports clip the outer rings against .login-left's overflow — scale the whole
   system down rather than letting it read as random arcs. */
@media (max-height: 760px), (max-width: 1280px) {
    .qs-orbit__ring--dotted { width: 600px; height: 600px; }
    .qs-orbit__ring--outer  { width: 450px; height: 450px; }
    .qs-orbit__ring--inner  { width: 300px; height: 300px; }
    .qs-orbit__node         { width: 40px; height: 40px; border-radius: 13px; }
    .qs-orbit__node svg     { width: 19px; height: 19px; }
    .qs-orbit__node--t { top: -20px;    left: calc(50% - 20px); }
    .qs-orbit__node--b { bottom: -20px; left: calc(50% - 20px); }
    .qs-orbit__node--l { left: -20px;   top: calc(50% - 20px); }
    .qs-orbit__node--r { right: -20px;  top: calc(50% - 20px); }
}

/* Copy rises after the panel has landed. */
.auth-color .login-left__content h1,
.auth-shell .login-left__content h1 { animation: qsAuthRise .75s cubic-bezier(.22,1,.36,1) .42s both; }
.auth-color .login-left__content p,
.auth-shell .login-left__content p  { animation: qsAuthRise .75s cubic-bezier(.22,1,.36,1) .56s both; }
.auth-color .login-left__footer,
.auth-shell .login-left__footer     { animation: qsAuthFade 1s ease .95s both; }

/* White side: brand mark, then the form heading. */
.auth-brand                     { animation: qsAuthRise .6s cubic-bezier(.22,1,.36,1) .20s both; }
.auth-form  .login-right__header,
.auth-shell .login-right__header { animation: qsAuthRise .6s cubic-bezier(.22,1,.36,1) .32s both; }

@keyframes qsPanelIn {
    from { opacity: 0; transform: scale(1.05); }
    to   { opacity: 1; transform: none; }
}
@keyframes qsOrbIn {
    from { opacity: 0; transform: scale(.55); }
    to   { opacity: 1; transform: scale(1); }
}
@keyframes qsSheenLoop {
    0%   { transform: translateX(-180%) skewX(-14deg); opacity: 0; }
    3%   { opacity: 1; }
    20%  { opacity: 1; }
    24%  { transform: translateX(360%) skewX(-14deg); opacity: 0; }
    100% { transform: translateX(360%) skewX(-14deg); opacity: 0; }
}
@keyframes qsAuthRise {
    from { opacity: 0; transform: translateY(18px); }
    to   { opacity: 1; transform: none; }
}
@keyframes qsAuthFade {
    from { opacity: 0; }
    to   { opacity: 1; }
}
@keyframes qsAuthSheen {
    0%   { background-position: 0% 50%; }
    50%  { background-position: 100% 50%; }
    100% { background-position: 0% 50%; }
}
/* Drift + a slow "breathing" scale in the SAME keyframes — two separate animations would
   both target `transform` and the later one would simply cancel the earlier. */
@keyframes qsDriftA {
    0%, 100% { transform: translate(0, 0) scale(1); }
    33%      { transform: translate(38px, 26px) scale(1.10); }
    66%      { transform: translate(14px, 46px) scale(1.04); }
}
@keyframes qsDriftB {
    0%, 100% { transform: translate(0, 0) scale(1); }
    40%      { transform: translate(-44px, -30px) scale(1.12); }
    70%      { transform: translate(-18px, -46px) scale(1.05); }
}
@keyframes qsDriftC {
    0%, 100% { transform: translate(0, 0) scale(1); }
    50%      { transform: translate(-30px, 38px) scale(1.16); }
}

@media (prefers-reduced-motion: reduce) {
    .auth-color .login-left,            .auth-shell .login-left,
    .auth-color .login-left::before,    .auth-shell .login-left::before,
    .auth-color .login-left::after,     .auth-shell .login-left::after,
    .auth-color .login-left__circle,    .auth-shell .login-left__circle,
    .auth-color .login-left__content h1, .auth-shell .login-left__content h1,
    .auth-color .login-left__content p,  .auth-shell .login-left__content p,
    .auth-color .login-left__footer,     .auth-shell .login-left__footer,
    .auth-form  .login-right__header,    .auth-shell .login-right__header,
    .auth-brand,
    .qs-orbit,
    .qs-orbit__ring,
    .qs-orbit__node {
        animation: none !important;
    }
    .login-left__sheen { display: none; }
    /* The rings still need their centring transform once the animation is off — without it
       they would sit at the bottom-right corner instead of around the copy. */
    .qs-orbit__ring { transform: translate(-50%, -50%); }
}

/* ============================================================================
   2026-08 audit remediation (L4) - shared auth-shell rules hoisted out of the four
   Account views' inline <style> blocks (Login / Register / ForgetPassword /
   ResetPassword), which together carried 1,257 lines of ~90%-similar CSS.

   Only rules that were BYTE-IDENTICAL in all four AND whose selector occurred
   exactly once per file were moved: if a selector appeared twice, removing one copy
   would silently change which rule wins. That test passed for 22 of 81 rules, so the
   honest saving is ~280 lines, not the ~1,000 the original plan estimated - the
   blocks are highly similar but genuinely not identical.
   ============================================================================ */
.page-content, .content-wrapper { padding: 0 !important; margin: 0 !important; height: 100vh !important; }
.login-left__inner {
    position: relative;
    z-index: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: space-between;
    width: 100%;
    padding: var(--qs-space-7) var(--qs-space-7);
    color: var(--qs-nav-fg);
}
.login-left__logo {
    display: flex;
    align-items: center;
    gap: var(--qs-space-3);
    font-size: 24px;
    font-weight: 800;
    color: var(--qs-nav-fg);
    align-self: flex-start;
}
.login-left__logo-img {
    border-radius: 9px;
    width: 40px; height: 40px;
    object-fit: contain;
    box-shadow: 0 2px 8px rgba(var(--qs-shadow-rgb), .30), 0 0 0 1px rgba(var(--qs-shadow-rgb), .05);
}
.login-left__content p {
    font-size: 16px;
    color: rgba(var(--qs-white-rgb), 0.7);
    margin-bottom: 28px;
}
.login-left__footer { font-size: 12px; color: rgba(var(--qs-white-rgb), 0.45); }
[dir="rtl"] .login-right { box-shadow: -8px 0 40px rgba(var(--qs-shadow-rgb), 0.08); }
[dir="ltr"] .login-right { box-shadow: 8px 0 40px rgba(var(--qs-shadow-rgb), 0.08); }
.login-right__inner { width: 100%; }
[dir="rtl"] .login-right__header { text-align: right; }
[dir="ltr"] .login-right__header { text-align: left; }
[dir="ltr"] .login-field label { text-align: left; }
.login-input-wrap {
    position: relative;
    display: flex;
    align-items: center;
}
.login-input::placeholder { color: var(--qs-border-strong); }
/* Language switcher */
.login-lang {
    position: fixed;
    top: 22px;
    right: 72px;
    display: flex;
    justify-content: flex-end;
    margin-bottom: 0;
    z-index: 1051;
}
[dir="rtl"] .login-lang { right: auto; left: 72px; justify-content: flex-start; }
.login-lang__btn {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    padding: 7px 14px;
    border: 1.5px solid var(--qs-border);
    border-radius: 20px;
    font-size: 13px;
    font-weight: 600;
    color: var(--qs-text-muted);
    text-decoration: none;
    transition: all 0.18s ease;
    background: var(--qs-bg);
}
.login-lang__btn:hover {
    border-color: var(--qs-primary);
    color: var(--qs-primary);
    background: var(--qs-info-subtle-bg);
    text-decoration: none;
}
.login-btn::after {
    content: "";
    position: absolute;
    top: -50%;
    left: -120%;
    width: 80%;
    height: 200%;
    background: linear-gradient(120deg, rgba(var(--qs-white-rgb), 0) 0%, rgba(var(--qs-white-rgb), 0.25) 50%, rgba(var(--qs-white-rgb), 0) 100%);
    transform: skewX(-20deg);
    transition: left 0.6s ease;
}
.login-btn:hover {
    transform: translateY(-2px);
    box-shadow: 0 10px 26px rgba(var(--qs-primary-rgb), 0.55);
    filter: brightness(1.02);
}
.login-btn:hover::after { left: 120%; }
.login-btn i { font-size: 13px; }

/* ============================================================================
   2026-08 audit remediation (L4, pass 2) - the four Account views still each
   carried their own copy of these rules, byte-identical wherever the selector
   appeared. Moved here; per-page <style> blocks keep only what genuinely
   differs in value (sizes/spacing) between the pages. */

/* Decorative circles on the blue panel — same in Login/Register/ForgetPassword/ResetPassword. */
.login-left::before {
    content: '';
    position: absolute;
    width: 500px; height: 500px;
    border-radius: var(--qs-radius-circle);
    background: rgba(var(--qs-white-rgb), 0.06);
    top: -150px; left: -150px;
}
.login-left::after {
    content: '';
    position: absolute;
    width: 350px; height: 350px;
    border-radius: var(--qs-radius-circle);
    background: rgba(var(--qs-white-rgb), 0.04);
    bottom: -100px; right: -80px;
}
.login-left__circle {
    position: absolute;
    width: 200px; height: 200px;
    border-radius: var(--qs-radius-circle);
    background: rgba(var(--qs-white-rgb), 0.05);
    bottom: 30%; left: 60%;
}

.login-eye:hover { color: var(--qs-primary-hover); }
.login-input::-ms-reveal,
.login-input::-ms-clear { display: none; }

/* Register form logo upload — same in Login (mobile switch) and Register. */
.reg-logo-upload { text-align: center; margin-bottom: 20px; }
.reg-logo-upload small { display: block; font-size: 11px; color: var(--qs-text-faint); margin-top: var(--qs-space-2); }
.reg-logo-upload .text-req { color: var(--qs-danger-solid); }
.reg-logo-label { cursor: pointer; display: inline-block; margin: 0; }
.reg-logo-circle {
    width: 100px; height: 100px;
    border-radius: var(--qs-radius-circle);
    border: 3px dashed var(--qs-border-strong);
    display: flex; align-items: center; justify-content: center;
    position: relative; overflow: hidden;
    transition: all 0.3s ease;
    background: var(--qs-bg);
    margin: 0 auto;
}
.reg-logo-circle:hover { border-color: var(--qs-primary-hover); transform: scale(1.05); }
.reg-logo-placeholder { display: flex; flex-direction: column; align-items: center; justify-content: center; color: var(--qs-text-faint); text-align: center; padding: var(--qs-space-2); }
.reg-logo-placeholder i { font-size: 28px; margin-bottom: var(--qs-space-1); color: var(--qs-primary); }
.reg-logo-placeholder span { font-size: 10px; font-weight: 500; }
.reg-logo-img { width: 100%; height: 100%; object-fit: cover; }
.reg-logo-overlay {
    position: absolute; top: 0; left: 0; right: 0; bottom: 0;
    background: rgba(var(--qs-shadow-rgb), 0.6);
    display: flex; align-items: center; justify-content: center;
    opacity: 0; transition: opacity 0.3s ease;
}
.reg-logo-circle:hover .reg-logo-overlay { opacity: 1; }
.reg-logo-overlay i { color: var(--qs-nav-fg); font-size: 24px; }

/* Two-column grid — same in Login (mobile switch) and Register. */
.reg-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 0 var(--qs-space-4); }
@media (max-width: 1100px) {
    .reg-grid { grid-template-columns: 1fr; }
}
@media (max-width: 768px) {
    .reg-grid { grid-template-columns: 1fr; }
}

/* Mobile collapse of the blue panel — same in ForgetPassword and ResetPassword. */
@media (max-width: 768px) {
    .login-left { display: none; }
    .login-right { width: 100%; min-width: unset; padding: var(--qs-space-6) var(--qs-space-5); box-shadow: none; }
}
