/**
 * File: auth.css
 * Purpose: Styling for login.php and register.php (glassmorphism design)
 * Features: Two-column layout, SVG icon inputs, password toggle
 */
/* ============================================================
   AUTH PAGES — login.php + register.php
   Design language: glassmorphism, soft blue → cyan gradients,
   interactive inputs with leading SVG icons and password toggle.

   Color tokens (light → dark) come from :root in styles.css and
   css/dark-theme.css. Auth-specific tokens live below so that
   only this file needs to know about them.
   ============================================================ */

body {
  min-height: 100vh;
  position: relative;
  isolation: isolate;
  background: linear-gradient(138deg, #eef5ff 0%, #d8e6ff 36%, #e8f3ff 70%, #d5e1f5 100%);
}

body::before,
body::after {
  content: "";
  position: fixed;
  inset: 0;
  pointer-events: none;
}

body::before {
  z-index: -2;
  background:
    radial-gradient(920px 560px at 108% -8%, rgba(37, 99, 235, 0.32) 0%, rgba(37, 99, 235, 0) 64%),
    radial-gradient(760px 520px at -12% 106%, rgba(14, 116, 144, 0.3) 0%, rgba(14, 116, 144, 0) 60%),
    conic-gradient(from 210deg at 76% 30%, rgba(59, 130, 246, 0.18), rgba(14, 165, 233, 0.08), rgba(99, 102, 241, 0.14), rgba(59, 130, 246, 0.18));
  filter: saturate(1.06) contrast(1.02);
}

body::after {
  z-index: -1;
  opacity: 0.56;
  background-image:
    linear-gradient(120deg, rgba(255, 255, 255, 0.34) 0%, rgba(255, 255, 255, 0) 46%),
    repeating-linear-gradient(125deg, rgba(148, 163, 184, 0.1) 0px, rgba(148, 163, 184, 0.1) 2px, transparent 2px, transparent 36px),
    repeating-linear-gradient(0deg, rgba(148, 163, 184, 0.06) 0px, rgba(148, 163, 184, 0.06) 1px, transparent 1px, transparent 44px),
    repeating-linear-gradient(90deg, rgba(148, 163, 184, 0.06) 0px, rgba(148, 163, 184, 0.06) 1px, transparent 1px, transparent 44px);
  mask-image: radial-gradient(circle at center, rgba(0, 0, 0, 0.75), transparent 88%);
}

/* ============================================================
   Layout shell
   ============================================================ */

.auth-main {
  width: min(1160px, 94vw);
  margin: var(--page-start-gap) auto 3.4rem;
}

.auth-shell {
  display: grid;
  grid-template-columns: minmax(300px, 1.05fr) minmax(360px, 1fr);
  gap: 1.2rem;
  align-items: stretch;
  animation: auth-shell-rise 620ms cubic-bezier(0.22, 0.95, 0.38, 1) both;
}

@keyframes auth-shell-rise {
  from {
    opacity: 0;
    transform: translateY(14px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

@media (prefers-reduced-motion: reduce) {
  .auth-shell {
    animation: none;
  }
}

/* ============================================================
   Auth visual aside (left)
   ============================================================ */

.auth-visual,
.auth-card {
  border-radius: 28px;
  border: 1px solid rgba(255, 255, 255, 0.56);
  backdrop-filter: blur(12px);
  box-shadow: 0 24px 48px rgba(15, 23, 42, 0.15);
}

/* ============================================================
   NEW `.auth-visual` BACKGROUND — synced with site's blue/cyan/
   indigo language. Three effective layers, all CSS-pure:

     L0 (base, animated) white-shine — painted over the saturated
        base for the classic glass highlight.
     L1 (base, animated) rich diagonal gradient — 7 stops,
        anchored in site tokens:
          #0a1430  very deep navy-950
          #14275e  navy-800
          #1d4ed8  --accent-deep
          #2563eb  --accent           (peak blue)
          #0ea5e9  sky-500            (a hit of cyan at 70%)
          #1e40af  blue-800
          #1e1b4b  indigo-950         (deep violet end-cap)
        Same TWO layers as before — the existing
        `auth-visual-colorflow` keyframe still drives them,
        just at a slower 16s cycle.

     L2 (decor, full panel, animated) the new `::before`
        canvas, inset:0, painted OVER the base. Three sub-layers,
        each with its own blend-mode:
          • top-right CONIC halo (indigo→cyan→fade)
          • diagonal AURORA band  (teal→sky→violet wash)
          • fine DOT MESH         (pearly speckle, repeats)
          Animates with the new `auth-visual-decor-drift`
          keyframe (22s) so the panel "breathes".

     L3 (decor, bottom-left, animated) `::after` is now a
        multi-color CHROMATIC ORB — bigger (320×320) and denser
        (4 stacked radial gradients: indigo core, sky mid, cyan
        sparkle, violet halo). Floats with `auth-visual-float`
        alternate-reverse (11s).

   The content layer (`.auth-visual > *`) keeps its z-index:1
   so kicker / hero title / hero text / points list stay
   readable above all four background layers. Sparkles
   (.auth-visual-sparkle s1/s2/s3) keep their z-index:0 and
   source-order paint so they still read as floating glints
   on top of ::before / ::after.
   ============================================================ */

.auth-visual {
  position: relative;
  overflow: hidden;
  padding: 2rem 1.8rem;
  color: #f8fbff;
  display: grid;
  align-content: start;
  gap: 1rem;

  /* Two animated layers — same count as before. The new 7-stop
     base anchors blue→cyan→violet with site tokens so the
     panel matches the language used in body::before /
     election-hero / footer-decor. */
  background:
    linear-gradient(118deg, rgba(255, 255, 255, 0.22) 0%, rgba(255, 255, 255, 0) 32%, rgba(255, 255, 255, 0.10) 100%),
    linear-gradient(135deg,
      #0a1430 0%,
      #14275e 18%,
      #1d4ed8 38%,
      #2563eb 52%,
      #0ea5e9 70%,
      #1e40af 86%,
      #1e1b4b 100%);
  background-size: 200% 200%, 240% 240%;
  background-position: 0% 15%, 0% 50%;
  background-blend-mode: soft-light, normal;
  animation: auth-visual-colorflow 16s cubic-bezier(0.45, 0.05, 0.55, 0.95) infinite;
  will-change: background-position;
}

/* NEW — ::before is no longer a single teal orb at top-right.
   Instead it covers the full panel with three blended decors
   (corner conic, diagonal aurora, fine dot mesh) that bleed
   chromatic richness across the panel without competing with
   the white text on top. Painted ABOVE the `.auth-visual`
   background stack but BELOW the content (which sits at
   z-index:1 via the existing `.auth-visual > *` rule).

   The conic starts at 220deg @ 88% 14% so its indigo-cyan arc
   blooms across the top-right quadrant; the aurora band is
   diagonal (112deg) so it sweeps teal→sky→violet across the
   middle; the dot mesh is a tiny repeating radial-gradient
   tile (22×22) that gives a fine-grained "glassy grain"
   texture, very low alpha so it reads as speckle, not noise. */
.auth-visual::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  pointer-events: none;
  z-index: 0;
  background:
    /* top-right CONIC halo — brightens the corner with indigo→cyan
       sweep. screen-blends with the layer below so the deep-blue
       base still anchors the rest of the panel. */
    conic-gradient(from 220deg at 88% 14%,
      rgba(99, 102, 241, 0.40) 0deg,
      rgba(56, 189, 248, 0.26) 70deg,
      rgba(14, 165, 233, 0.00) 130deg,
      rgba(14, 165, 233, 0.00) 360deg),
    /* diagonal AURORA band — teal at upper-left, lifts to sky,
       then dips into violet at lower-right. overlay-blends so it
       adds chromatic punch without washing out the base. */
    linear-gradient(112deg,
      rgba(94, 234, 212, 0.00) 0%,
      rgba(94, 234, 212, 0.32) 24%,
      rgba(56, 189, 248, 0.20) 48%,
      rgba(139, 92, 246, 0.34) 78%,
      rgba(139, 92, 246, 0.00) 100%),
    /* fine DOT MESH — 0.6px white dots on a 22×22 tile,
       soft-light so they read as pearly speckle even on the
       brightest spots. */
    radial-gradient(circle at center,
      rgba(255, 255, 255, 0.10) 0.6px,
      rgba(255, 255, 255, 0) 1.6px);
  background-size: 100% 100%, 220% 160%, 22px 22px;
  background-position: 50% 50%, 0% 30%, 0 0;
  background-repeat: no-repeat, no-repeat, repeat;
  background-blend-mode: screen, overlay, soft-light;
  animation: auth-visual-decor-drift 22s cubic-bezier(0.45, 0.05, 0.55, 0.95) infinite;
  /* The decor-drift keyframe mutates `background-position` across all
     three stacked layers (conic + aurora + dot mesh). Without this
     hint the compositor repaints the multi-layer composite every
     frame; pinning it to its own layer lets the GPU cache the
     pre-composited bitmap. Pair with respect for prefers-reduced-
     motion — the dedicated media query below zeroes this off too. */
  will-change: background-position;
}

/* ENRICHED — ::after is now the asymmetric chromatic anchor at
   the lower-left. Bigger (320×320 instead of 240), with FOUR
   stacked radial gradients so the panel sees indigo+sky+cyan
   +violet instead of just two colors. Floats with the existing
   `auth-visual-float` keyframe, in `alternate-reverse` so the
   panel's two pseudo elements drift in opposite phase. */
.auth-visual::after {
  content: "";
  position: absolute;
  bottom: -120px;
  inset-inline-start: -110px;
  width: 320px;
  height: 320px;
  border-radius: 50%;
  pointer-events: none;
  z-index: 0;
  background:
    /* indigo core */
    radial-gradient(circle at 60% 40%, rgba(165, 180, 252, 0.55) 0%, rgba(165, 180, 252, 0) 60%),
    /* sky-blue mid */
    radial-gradient(circle at 30% 70%, rgba(56, 189, 248, 0.42) 0%, rgba(56, 189, 248, 0) 65%),
    /* cyan sparkle top */
    radial-gradient(circle at 75% 75%, rgba(34, 211, 238, 0.30) 0%, rgba(34, 211, 238, 0) 70%),
    /* violet halo trailing */
    radial-gradient(circle at 40% 30%, rgba(139, 92, 246, 0.32) 0%, rgba(139, 92, 246, 0) 75%);
  filter: blur(2px);
  opacity: 0.72;
  animation: auth-visual-float 11s ease-in-out infinite alternate-reverse;
}

/* Drift the ::before decor canvas so the conic / aurora / dot
   mesh gently breathe in sync with the panel's colorflow
   animation. Same easing curve keeps the visual rhythm pinned
   to the existing 16s base animation; the 22s offset is
   intentionally different so the conic and aurora don't
   lock-step. */
@keyframes auth-visual-decor-drift {
  0%   { background-position: 50% 50%, 0% 30%, 0 0; }
  50%  { background-position: 56% 44%, 8% 22%, -3px -3px; }
  100% { background-position: 50% 50%, 0% 30%, 0 0; }
}

@keyframes auth-visual-float {
  from { transform: translate3d(0, 0, 0) scale(1); }
  to   { transform: translate3d(20px, -16px, 0) scale(1.06); }
}

@keyframes auth-visual-colorflow {
  0%   { background-position: 0% 15%, 0% 50%; }
  30%  { background-position: 88% 82%, 42% 44%; }
  65%  { background-position: 22% 22%, 74% 62%; }
  100% { background-position: 100% 86%, 100% 50%; }
}

@media (prefers-reduced-motion: reduce) {
  .auth-visual,
  .auth-visual::before,
  .auth-visual::after {
    animation: none;
  }
}

/* Visual content sits above the decorative blobs */
.auth-visual > * {
  position: relative;
  z-index: 1;
}

.auth-kicker {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  width: fit-content;
  padding: 0.4rem 0.85rem;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.18);
  border: 1px solid rgba(255, 255, 255, 0.32);
  font-size: 0.84rem;
  font-weight: 600;
  letter-spacing: 0.01em;
  backdrop-filter: blur(8px);
  transition:
    background   220ms ease,
    border-color 220ms ease,
    transform    220ms cubic-bezier(0.34, 1.56, 0.64, 1),
    box-shadow   220ms ease;
}

/* Touch surfaces without real hover (mass-tap mobile) skip this so the
   kicker doesn't stay in phantom-hover state after a tap. */
@media (hover: hover) {
  .auth-kicker:hover {
    background: rgba(255, 255, 255, 0.3);
    border-color: rgba(255, 255, 255, 0.48);
    transform: translateY(-1px);
    box-shadow: 0 8px 18px rgba(15, 23, 42, 0.22);
  }
}

/* 4-point sparkle SVG via mask-image. The `border-radius: 50%`
   stays as a graceful fallback — if the engine drops `mask-image`,
   the paint falls back to the colored disc we had before. The same
   path shape is reused for `.auth-visual-sparkle` below so the panel
   reads as one visual language. */
.auth-kicker::before {
  content: "";
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: #5eead4;
  box-shadow:
    0 0 10px rgba(94, 234, 212, 0.55),
    0 0 0 3px rgba(94, 234, 212, 0.3);
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 0C11.8 6.8 6.8 11.8 0 12C6.8 12.2 11.8 17.2 12 24C12.2 17.2 17.2 12.2 24 12C17.2 11.8 12.2 6.8 12 0Z'/%3E%3C/svg%3E") center/contain no-repeat;
          mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 0C11.8 6.8 6.8 11.8 0 12C6.8 12.2 11.8 17.2 12 24C12.2 17.2 17.2 12.2 24 12C17.2 11.8 12.2 6.8 12 0Z'/%3E%3C/svg%3E") center/contain no-repeat;
  animation: auth-pulse 2s ease-in-out infinite;
}

@keyframes auth-pulse {
  0%, 100% { transform: scale(1);   opacity: 1;   }
  50%      { transform: scale(1.2); opacity: 0.7; }
}

@media (prefers-reduced-motion: reduce) {
  .auth-kicker::before { animation: none; }
}

.auth-hero-title {
  margin: 0;
  font-size: clamp(1.55rem, 2.4vw, 2.15rem);
  font-weight: 800;
  line-height: 1.4;
  max-width: 24ch;
  text-shadow: 0 2px 18px rgba(15, 23, 42, 0.35);
}

/* Light-mode gradient text on the hero title. Wrapped in @supports so
   older WebViews that ignore `background-clip: text` keep the solid
   white color and the existing text-shadow — no degradation.
   The light side mirrors the dark-mode rule in css/dark-theme.css,
   which already does `background: linear-gradient(...)`. */
@supports (background-clip: text) or (-webkit-background-clip: text) {
  .auth-hero-title {
    background: linear-gradient(135deg, #f8fbff 0%, #bae6fd 55%, #a5f3fc 100%);
    -webkit-background-clip: text;
            background-clip: text;
    -webkit-text-fill-color: transparent;
            color: transparent;
  }
}

.auth-hero-text {
  margin: 0;
  color: rgba(248, 250, 252, 0.9);
  line-height: 1.95;
  max-width: 32ch;
  font-size: 1rem;
}

.auth-points {
  list-style: none;
  display: grid;
  gap: 0.62rem;
  margin: 0.6rem 0 0;
  padding: 0;
}

.auth-points li {
  display: grid;
  grid-template-columns: 28px 1fr;
  align-items: center;
  gap: 0.7rem;
  color: rgba(248, 250, 252, 0.97);
  padding: 0.5rem 0.7rem;
  border-radius: 12px;
  background: rgba(255, 255, 255, 0.09);
  border: 1px solid rgba(255, 255, 255, 0.14);
  transition: background 220ms ease, transform 220ms ease, border-color 220ms ease;
}

.auth-points li:hover {
  background: rgba(255, 255, 255, 0.18);
  border-color: rgba(255, 255, 255, 0.34);
  transform: translateX(-3px); /* RTL: nudge visually */
  box-shadow: 0 10px 22px rgba(15, 23, 42, 0.22);
}

/* SVG checkmark drawn via mask-image over a teal→sky gradient. The
   `border-radius: 50%` is preserved as a fallback — if the engine
   drops the mask, the element degrades to a solid gradient disc that
   matches the previous visual treatment exactly. The stroke-only
   checkmark path uses `stroke='black'` to map the alpha channel —
   `currentColor` would be cleaner but isn't reliably resolved on
   pseudo-elements; `black` works and URL-encoding-free. */
.auth-points li::before {
  content: "";
  width: 32px;
  height: 32px;
  border-radius: 50%;
  display: block;
  flex-shrink: 0;
  background: linear-gradient(135deg, #5eead4, #38bdf8);
  box-shadow:
    0 6px 14px rgba(56, 189, 248, 0.42),
    inset 0 0 0 4px rgba(255, 255, 255, 0.18);
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'/%3E%3C/svg%3E") center/68% no-repeat;
          mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'/%3E%3C/svg%3E") center/68% no-repeat;
  transition:
    transform 280ms cubic-bezier(0.34, 1.56, 0.64, 1),
    filter    280ms ease;
}

/* Hover-only micro-rotate-and-scale on the marker; composes with the
   parent `<li>` translateX (no transform conflict — different elements).
   Tablet / phone taps skip this. */
@media (hover: hover) {
  .auth-points li:hover::before {
    transform: scale(1.1) rotate(-4deg);
    filter: drop-shadow(0 6px 10px rgba(56, 189, 248, 0.55));
  }
}

/* Decorative sparkles — SVG 4-point gem stars drawn via mask-image
   over a soft white→sky gradient with a cyan drop-shadow for that
   wet "glass glint" feel. The `border-radius: 50%` is graceful
   fallback for engines without `mask-image`. Same path shape as
   `.auth-kicker::before` so the panel speaks one shape language. */
.auth-visual-sparkle {
  position: absolute;
  width: 14px;
  height: 14px;
  border-radius: 50%;
  pointer-events: none;
  z-index: 0;
  background: linear-gradient(135deg, rgba(255, 255, 255, 0.96), rgba(186, 230, 253, 0.94));
  filter: drop-shadow(0 0 6px rgba(186, 230, 253, 0.6));
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 0C11.8 6.8 6.8 11.8 0 12C6.8 12.2 11.8 17.2 12 24C12.2 17.2 17.2 12.2 24 12C17.2 11.8 12.2 6.8 12 0Z'/%3E%3C/svg%3E") center/contain no-repeat;
          mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 0C11.8 6.8 6.8 11.8 0 12C6.8 12.2 11.8 17.2 12 24C12.2 17.2 17.2 12.2 24 12C17.2 11.8 12.2 6.8 12 0Z'/%3E%3C/svg%3E") center/contain no-repeat;
  animation: auth-twinkle 3.5s ease-in-out infinite;
}
.auth-visual-sparkle.s1 { top: 18%; inset-inline-end: 32%; animation-delay: 0s; }
.auth-visual-sparkle.s2 { top: 62%; inset-inline-end: 14%; animation-delay: 1.2s; width: 11px; height: 11px; }
.auth-visual-sparkle.s3 { top: 78%; inset-inline-end: 56%; animation-delay: 2.4s; width: 9px;  height: 9px; }

@keyframes auth-twinkle {
  0%, 100% { opacity: 0.2; transform: scale(0.7); }
  50%      { opacity: 0.9; transform: scale(1.1); }
}

@media (prefers-reduced-motion: reduce) {
  .auth-visual-sparkle { animation: none; opacity: 0.4; }
}

/* ============================================================
   Auth card (form)
   ============================================================ */

.auth-card {
  background: rgba(255, 255, 255, 0.86);
  padding: 2rem 1.8rem;
  display: grid;
  align-content: start;
  gap: 1rem;
}

.auth-card-head {
  display: grid;
  gap: 0.4rem;
}

.auth-card-head h1 {
  margin: 0;
  font-size: clamp(1.65rem, 2.1vw, 2rem);
  font-weight: 800;
  line-height: 1.3;
  letter-spacing: -0.01em;
  color: #0f172a;
}

/* Gradient + text-clip only when the engine supports background-clip:
   text. Without this, the heading remains readable in solid color on
   browsers that ignore -webkit-background-clip (very old Safari and
   some embedded WebViews). */
@supports (background-clip: text) or (-webkit-background-clip: text) {
  .auth-card-head h1 {
    background: linear-gradient(135deg, #0f172a 30%, #1d4ed8 100%);
    -webkit-background-clip: text;
            background-clip: text;
    -webkit-text-fill-color: transparent;
            color: transparent;
  }
}

.auth-subtitle {
  margin: 0.15rem 0 0;
  color: #475569;
  line-height: 1.85;
  font-size: 0.94rem;
}

/* ============================================================
   Field layout + labels
   ============================================================ */

.auth-form {
  display: grid;
  gap: 0.8rem;
  margin-top: 0.4rem;
}

.auth-grid-two {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0.85rem 0.95rem;
}

.auth-grid-two .full {
  grid-column: 1 / -1;
}

.auth-field {
  display: grid;
  gap: 0.32rem;
  min-width: 0; /* allow icon + input to overflow gracefully in RTL */
}

.auth-field label {
  font-size: 0.92rem;
  color: #334155;
  font-weight: 600;
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
}

.auth-field label::after {
  content: "";
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: linear-gradient(135deg, #3b82f6, #06b6d4);
  opacity: 0;
  transition: opacity 200ms ease;
}

.auth-field:focus-within label::after { opacity: 1; }

.auth-field-hint {
  margin: 0;
  font-size: 0.78rem;
  line-height: 1.5;
  color: #64748b;
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  min-height: 18px;
}

.auth-field-hint.is-error { color: #be123c; }
.auth-field-hint.is-ok    { color: #047857; }

/* ============================================================
   Input wrapper — icon + input + (optional) password toggle
   ============================================================ */

.auth-input-wrap {
  position: relative;
  display: flex;
  align-items: center;
}

/* The leading icon is a <span class="auth-input-icon"> that wraps an
   inline SVG. We style the SPAN (positioning, color) and let the inner
   SVG inherit color via stroke="currentColor". */
.auth-input-wrap > .auth-input-icon {
  position: absolute;
  inset-inline-start: 0.95rem;
  top: 50%;
  transform: translateY(-50%);
  width: 18px;
  height: 18px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: #64748b;
  pointer-events: none;
  transition: color 200ms ease, transform 200ms ease;
}

.auth-input-wrap > .auth-input-icon svg {
  width: 100%;
  height: 100%;
  display: block;
}

.auth-input-wrap:focus-within > .auth-input-icon {
  color: #2563eb;
}

.auth-input-wrap input,
.auth-input-wrap select {
  width: 100%;
  padding: 0.88rem 0.95rem;
  padding-inline-start: 2.65rem; /* room for the leading icon */
  border-radius: 14px;
  border: 1px solid rgba(148, 163, 184, 0.4);
  background: rgba(255, 255, 255, 0.94);
  color: #0f172a;
  font-family: inherit;
  font-size: 0.96rem;
  line-height: 1.4;
  transition:
    border-color 180ms ease,
    box-shadow 220ms ease,
    background 180ms ease,
    transform 180ms ease;
}

/* When the input has the toggle button (password), reserve a bit
   of inline-end padding so the eye icon doesn't overlap the text. */
.auth-input-wrap.has-toggle input { padding-inline-end: 3.4rem; }

.auth-input-wrap input::placeholder {
  color: #94a3b8;
}

.auth-input-wrap input:hover:not(:focus),
.auth-input-wrap select:hover:not(:focus) {
  border-color: rgba(37, 99, 235, 0.35);
  background-color: rgba(255, 255, 255, 1);
}

.auth-input-wrap input:focus,
.auth-input-wrap select:focus {
  outline: none;
  border-color: rgba(37, 99, 235, 0.6);
  background-color: #fff;
  box-shadow:
    0 0 0 4px rgba(59, 130, 246, 0.15),
    0 8px 18px rgba(37, 99, 235, 0.08);
}

/* (No dead selectors — icon sits before the input in the DOM, so the
   +/~ adjacent-sibling combinators cannot reach it. :focus-within on
   .auth-input-wrap above already drives the focus highlight.) */

/* Invalid state — applies when JS sets aria-invalid="true" */
.auth-input-wrap input[aria-invalid="true"],
.auth-input-wrap select[aria-invalid="true"] {
  border-color: rgba(225, 29, 72, 0.55);
  background-color: rgba(254, 242, 242, 0.94);
}

.auth-input-wrap input[aria-invalid="true"]:focus,
.auth-input-wrap select[aria-invalid="true"]:focus {
  box-shadow:
    0 0 0 4px rgba(225, 29, 72, 0.18),
    0 8px 18px rgba(225, 29, 72, 0.1);
}

.auth-input-wrap input[aria-invalid="true"] ~ .auth-input-icon {
  color: #e11d48;
}

/* Select chevron — sits on the END side (opposite the leading icon) so
   it never overlaps the leading icon visually. We pre-compute the LTR
   and RTL pixel offsets rather than rely on `background-position-x: end`,
   which has spotty cross-browser support. The SVG data: URI only carries
   a `viewBox` (no width/height attrs), so without an explicit
   `background-size`, browsers fall back to `auto` and stretch the
   chevron to fill the entire background area — making it enormous.
   Pinning it to 14×14 keeps it proportional to the 18px leading icons
   without competing visually. */
.auth-input-wrap select {
  cursor: pointer;
  appearance: none;
  -webkit-appearance: none;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23475569' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'><polyline points='6 9 12 15 18 9'/></svg>");
  background-repeat: no-repeat;
  background-position-x: calc(100% - 0.95rem);
  background-position-y: center;
  background-size: 14px;
  padding-inline-end: 2.4rem;
  padding-inline-start: 2.65rem;
}

[dir="rtl"] .auth-input-wrap select {
  background-position-x: 0.95rem;
}

/* ============================================================
   POLISHED `.auth-input-wrap.has-icon` (icon-only variant).

   The leading-icon, no-toggle wrapper used for first_name,
   last_name, phone, national_code, academic_grade, academic_field.
   This block layers 5 micro-interactions on top of the base
   treatment above:

     1.  Subtle hover lift (-1px translateY, multi-layer shadow).
     2.  Gradient focus ring rendered via `::after` + mask-composite.
     3.  Icon nudge toward input text on focus (RTL-aware: -2px X).
     4.  `.is-filled` state — JS toggled when input has a value;
         clean teal tint + green icon, signals "value captured".
     5.  `.has-error` state — JS adds once when aria-invalid flips
         true; triggers a brief translateX shake.
   Also adds caret-color, ::selection tint, and a webkit-autofill
   override that kills Chrome's yellow tint without losing the
   gradient focus ring.
   ============================================================ */

.auth-input-wrap.has-icon {
  position: relative;
  display: flex;
  align-items: center;
  background: rgba(255, 255, 255, 0.94);
  border: 1px solid rgba(148, 163, 184, 0.4);
  border-radius: 14px;
  z-index: 0;
  box-shadow: 0 0 0 0 rgba(37, 99, 235, 0);
  transition:
    border-color  220ms cubic-bezier(0.4, 0, 0.2, 1),
    background    220ms ease,
    box-shadow    280ms cubic-bezier(0.4, 0, 0.2, 1),
    transform     320ms cubic-bezier(0.34, 1.56, 0.64, 1);
}

/* The actual input/select inside .has-icon drops its own border +
   background-color so the wrap's border + ::after gradient ring are
   the visible "container". We use `background-color: transparent`
   rather than the `background:` shorthand because the latter would
   also reset `background-image` to none — losing the select chevron
   defined earlier in this file (academic grade & field selects). */
.auth-input-wrap.has-icon input,
.auth-input-wrap.has-icon select {
  background-color: transparent;
  border: none;
  border-radius: 14px;
  box-shadow: none;
  padding: 0.88rem 0.95rem;
  padding-inline-start: 2.65rem;
  caret-color: #2563eb;
}

.auth-input-wrap.has-icon > .auth-input-icon {
  z-index: 2; /* above the ::after gradient ring */
  transition:
    color     220ms ease,
    transform 360ms cubic-bezier(0.34, 1.56, 0.64, 1);
}

/* Gradient focus ring — sits 2px outside the wrap's border and uses
   mask-composite to render only the outline. */
.auth-input-wrap.has-icon::after {
  content: "";
  position: absolute;
  inset: -2px;
  z-index: 1;
  pointer-events: none;
  border-radius: 16px;
  padding: 2px;
  background: linear-gradient(135deg, #2563eb 0%, #06b6d4 55%, #8b5cf6 100%);
  -webkit-mask:
    linear-gradient(#fff 0 0) content-box,
    linear-gradient(#fff 0 0);
  -webkit-mask-composite: xor;
          mask-composite: exclude;
  opacity: 0;
  transform: scale(0.985);
  transition:
    opacity   240ms ease,
    transform 360ms cubic-bezier(0.34, 1.56, 0.64, 1);
}

/* Hover — lifts the wrap with a soft layered shadow. */
.auth-input-wrap.has-icon:hover {
  border-color: rgba(37, 99, 235, 0.35);
  background: #fff;
  transform: translateY(-1px);
  box-shadow:
    0 4px 12px rgba(37, 99, 235, 0.08),
    0 1px 2px  rgba(15, 23, 42, 0.04);
}

/* Focus — turns the border transparent so the ::after gradient ring
   is the only outline, the inner glow lifts, and the icon nudges
   toward the input text. The project ships RTL-only, so the icon
   lives on the visual right; nudging toward the text means moving
   it LEFT visually. transform translateX uses physical coords,
   hence the negative -2px X offset. */
.auth-input-wrap.has-icon:focus-within {
  border-color: transparent;
  background: #fff;
  box-shadow:
    0 0 0 4px rgba(59, 130, 246, 0.16),
    0 10px 24px rgba(37, 99, 235, 0.12),
    0 2px 6px  rgba(15, 23, 42, 0.06);
}

/* Combined hover + focus lift — but only on devices that can hover.
   This avoids the mobile-tap "1px lift" surprise (where :focus-within
   fires on tap without a real :hover) AND keeps desktop consistent
   (mouse hovers AND hovering-then-tabbing both lift). */
@media (hover: hover) {
  .auth-input-wrap.has-icon:hover,
  .auth-input-wrap.has-icon:focus-within {
    transform: translateY(-1px);
  }
}

.auth-input-wrap.has-icon:focus-within::after {
  opacity: 1;
  transform: scale(1);
}

[dir="rtl"] .auth-input-wrap.has-icon:focus-within > .auth-input-icon {
  color: #2563eb;
  transform: translate(-2px, -50%) scale(1.1);
}

/* Inverse rule for LTR pages — kept defensively so the polish
   behaves the same way if an LTR locale is ever introduced. The
   lower specificity means the [dir="rtl"] rule above still wins
   on the current RTL-only build. */
.auth-input-wrap.has-icon:focus-within > .auth-input-icon {
  color: #2563eb;
  transform: translate(2px, -50%) scale(1.1);
}

/* Filled state — JS adds `.is-filled` whenever the wrapped input/select
   carries a non-empty value. Subtle teal tint, green icon. */
.auth-input-wrap.has-icon.is-filled {
  border-color: rgba(16, 185, 129, 0.36);
  background: linear-gradient(180deg, rgba(236, 253, 245, 0.7), rgba(255, 255, 255, 0.96));
  box-shadow: 0 2px 8px rgba(16, 185, 129, 0.06);
}

.auth-input-wrap.has-icon.is-filled > .auth-input-icon {
  color: #059669;
}

.auth-input-wrap.has-icon.is-filled:focus-within > .auth-input-icon {
  color: #2563eb; /* focus wins over filled for icon emphasis */
}

/* When the user focuses an already-filled field, swap the gradient
   ring to a tinted stroke that keeps the "value captured" message
   alive instead of dropping it. Only the `background` needs an
   override here — `opacity: 1` and `transform: scale(1)` cascade
   from the lower-specificity :focus-within::after rule. */
.auth-input-wrap.has-icon.is-filled:focus-within::after {
  background: linear-gradient(135deg, #10b981 0%, #06b6d4 60%, #2563eb 100%);
}

/* Invalid state — JS adds `.has-error` ONCE per aria-invalid flip
   to trigger the shake. The persisted aria-invalid style still
   keeps the rose border + tinted background. */
.auth-input-wrap.has-icon.has-error {
  animation: auth-shake 360ms cubic-bezier(0.36, 0.07, 0.19, 0.97);
}

@keyframes auth-shake {
  10%, 90% { transform: translateX(-1px); }
  20%, 80% { transform: translateX(2px);  }
  30%, 50%, 70% { transform: translateX(-3px); }
  40%, 60%      { transform: translateX(3px);  }
}

/* Caret / selection polish for both input + select. */
.auth-input-wrap.has-icon input,
.auth-input-wrap.has-icon select {
  caret-color: #2563eb;
}

.auth-input-wrap.has-icon input::selection,
.auth-input-wrap.has-icon select::selection {
  background: rgba(37, 99, 235, 0.22);
}

/* Kill Chrome's autofill yellow tint while keeping the gradient
   focus ring. The inset box-shadow fills 1000px so the autofill
   yellow never leaks through. */
.auth-input-wrap.has-icon input:-webkit-autofill,
.auth-input-wrap.has-icon input:-webkit-autofill:hover,
.auth-input-wrap.has-icon input:-webkit-autofill:focus {
  -webkit-text-fill-color: #0f172a;
  -webkit-box-shadow: 0 0 0 1000px rgba(255, 255, 255, 0.96) inset;
          box-shadow: 0 0 0 1000px rgba(255, 255, 255, 0.96) inset;
  caret-color: #2563eb;
  border-radius: 14px;
}

@media (prefers-reduced-motion: reduce) {
  .auth-input-wrap.has-icon,
  .auth-input-wrap.has-icon::after,
  .auth-input-wrap.has-icon > .auth-input-icon {
    transition: none !important;
  }
  .auth-input-wrap.has-icon.has-error {
    animation: none;
  }
}

/* ============================================================
   Password toggle (show / hide)
   ============================================================ */

.auth-pw-toggle {
  position: absolute;
  inset-inline-end: 0.4rem;
  top: 50%;
  transform: translateY(-50%);
  width: 44px;
  height: 44px;
  min-width: 44px;
  min-height: 44px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 12px;
  background: transparent;
  border: none;
  color: #64748b;
  cursor: pointer;
  transition: background 180ms ease, color 180ms ease, transform 180ms ease;
}

.auth-pw-toggle:hover {
  background: rgba(37, 99, 235, 0.1);
  color: #2563eb;
}

.auth-pw-toggle:focus-visible {
  outline: 2px solid rgba(37, 99, 235, 0.55);
  outline-offset: 2px;
}

.auth-pw-toggle:active { transform: translateY(-50%) scale(0.92); }

.auth-pw-toggle svg { width: 18px; height: 18px; }
.auth-pw-toggle .pw-eye-off { display: none; }
.auth-pw-toggle.is-revealed .pw-eye    { display: none; }
.auth-pw-toggle.is-revealed .pw-eye-off { display: block; }

/* ============================================================
   Password strength meter (register only)
   ============================================================ */

.auth-pw-meter {
  display: grid;
  gap: 0.45rem;
  margin-top: 0.15rem;
}

.auth-pw-meter-bars {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 4px;
  height: 6px;
}

.auth-pw-meter-bar {
  background: rgba(148, 163, 184, 0.28);
  border-radius: 999px;
  transition: background 200ms ease;
}

.auth-pw-meter[data-level="1"] .auth-pw-meter-bar:nth-child(-n+1) { background: linear-gradient(90deg, #ef4444, #f97316); }
.auth-pw-meter[data-level="2"] .auth-pw-meter-bar:nth-child(-n+2) { background: linear-gradient(90deg, #f59e0b, #facc15); }
.auth-pw-meter[data-level="3"] .auth-pw-meter-bar:nth-child(-n+3) { background: linear-gradient(90deg, #10b981, #84cc16); }
.auth-pw-meter[data-level="4"] .auth-pw-meter-bar                  { background: linear-gradient(90deg, #10b981, #06b6d4); }

.auth-pw-meter-label {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  font-size: 0.78rem;
  color: #64748b;
}

.auth-pw-meter-label .pw-meter-text {
  font-weight: 600;
  letter-spacing: 0.01em;
}

.auth-pw-meter[data-level="0"] .pw-meter-text { color: #64748b; }
.auth-pw-meter[data-level="1"] .pw-meter-text { color: #b91c1c; }
.auth-pw-meter[data-level="2"] .pw-meter-text { color: #b45309; }
.auth-pw-meter[data-level="3"] .pw-meter-text { color: #047857; }
.auth-pw-meter[data-level="4"] .pw-meter-text { color: #0f766e; }

.auth-pw-rules {
  list-style: none;
  margin: 0.4rem 0 0;
  padding: 0;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0.32rem 0.7rem;
}

.auth-pw-rules li {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  font-size: 0.78rem;
  color: #475569;
  padding: 0.22rem 0.5rem;
  border-radius: 8px;
  background: rgba(241, 245, 249, 0.7);
  border: 1px solid rgba(148, 163, 184, 0.18);
  transition: background 200ms ease, color 200ms ease, border-color 200ms ease;
}

.auth-pw-rules li svg {
  width: 14px;
  height: 14px;
  stroke-width: 3;
  flex-shrink: 0;
}

.auth-pw-rules li .pw-rule-circle {
  width: 14px;
  height: 14px;
  border-radius: 50%;
  border: 2px solid rgba(148, 163, 184, 0.55);
  flex-shrink: 0;
  transition: border-color 200ms ease, background 200ms ease;
}

.auth-pw-rules li.is-valid {
  background: rgba(220, 252, 231, 0.9);
  border-color: rgba(22, 163, 74, 0.32);
  color: #166534;
}
.auth-pw-rules li.is-valid .pw-rule-circle {
  background: #16a34a;
  border-color: #16a34a;
}
.auth-pw-rules li.is-valid .pw-rule-icon { display: block; }
/* The .is-valid selector already has higher specificity (0,0,3,1) than
   the base rule (0,0,2,1), so this rule wins without an attribute
   selector or source-order tricks. */
.auth-pw-rules li.is-valid .pw-rule-circle-empty { display: none; }

.auth-pw-rules li .pw-rule-icon { display: none; color: #16a34a; }
/* The :not() wrapper keeps this selector's specificity lower than any
   .is-valid override, so the explicit `display: block` on .pw-rule-icon
   inside valid rules reliably wins without relying on source order. */

@media (max-width: 520px) {
  .auth-pw-rules { grid-template-columns: 1fr; }
}

/* ============================================================
   Submit button (uses .cta from styles.css — enhanced here)
   ============================================================ */

.auth-submit {
  margin-top: 0.4rem;
  width: 100%;
  min-height: 50px;
  font-size: 1rem;
  font-weight: 700;
  letter-spacing: 0.01em;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.55rem;
  position: relative;
  overflow: hidden;
}

.auth-submit svg { width: 18px; height: 18px; }

.auth-submit::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(120deg, rgba(255, 255, 255, 0) 30%, rgba(255, 255, 255, 0.32) 50%, rgba(255, 255, 255, 0) 70%);
  transform: translateX(-120%);
  transition: transform 700ms ease;
}

.auth-submit:hover:not(:disabled)::after { transform: translateX(120%); }

.auth-submit:focus-visible {
  outline: 2px solid rgba(37, 99, 235, 0.55);
  outline-offset: 3px;
}

.auth-submit:disabled {
  opacity: 0.65;
  cursor: not-allowed;
  transform: none;
}

.auth-submit.is-loading {
  cursor: progress;
  pointer-events: none;
}

.auth-submit .auth-submit-spinner {
  display: none;
  width: 18px;
  height: 18px;
  border: 2.5px solid rgba(255, 255, 255, 0.32);
  border-top-color: #fff;
  border-radius: 50%;
  animation: auth-spin 700ms linear infinite;
}

.auth-submit.is-loading .auth-submit-spinner { display: inline-block; }

@keyframes auth-spin {
  to { transform: rotate(360deg); }
}

@media (prefers-reduced-motion: reduce) {
  .auth-submit-spinner { animation-duration: 1.6s; }
}

/* ============================================================
   Alerts (success / error)
   ============================================================ */

.auth-alert {
  display: grid;
  grid-template-columns: 24px 1fr;
  align-items: start;
  gap: 0.7rem;
  border-radius: 14px;
  padding: 0.85rem 1rem;
  margin-bottom: 0.4rem;
  font-size: 0.92rem;
  line-height: 1.85;
  font-weight: 500;
  animation: auth-alert-in 320ms cubic-bezier(0.22, 0.95, 0.38, 1) both;
}

@keyframes auth-alert-in {
  from { opacity: 0; transform: translateY(-6px); }
  to   { opacity: 1; transform: translateY(0); }
}

@media (prefers-reduced-motion: reduce) {
  .auth-alert { animation: none; }
}

.auth-alert-icon {
  width: 22px;
  height: 22px;
  border-radius: 50%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  margin-top: 2px;
}

.auth-alert svg { width: 14px; height: 14px; stroke-width: 2.5; }

.auth-error {
  background: linear-gradient(135deg, rgba(255, 241, 242, 0.92), rgba(254, 226, 226, 0.86));
  border: 1px solid rgba(244, 63, 94, 0.32);
  color: #9f1239;
}
.auth-error .auth-alert-icon {
  background: linear-gradient(135deg, #f43f5e, #e11d48);
  color: #fff;
  box-shadow: 0 4px 12px rgba(244, 63, 94, 0.32);
}

.auth-success {
  background: linear-gradient(135deg, rgba(236, 253, 245, 0.92), rgba(209, 250, 229, 0.86));
  border: 1px solid rgba(16, 185, 129, 0.32);
  color: #065f46;
}
.auth-success .auth-alert-icon {
  background: linear-gradient(135deg, #10b981, #059669);
  color: #fff;
  box-shadow: 0 4px 12px rgba(16, 185, 129, 0.3);
}

/* ============================================================
   Footer area: switch between login ↔ register
   ============================================================ */

.auth-switch {
  margin: 0.6rem 0 0;
  text-align: center;
  color: #475569;
  font-size: 0.95rem;
  padding: 0.85rem;
  background: rgba(241, 245, 249, 0.55);
  border-radius: 12px;
  border: 1px solid rgba(148, 163, 184, 0.18);
}

.auth-switch a {
  color: var(--accent);
  font-weight: 700;
  display: inline-flex;
  align-items: center;
  gap: 0.32rem;
  padding: 0.2rem 0.45rem;
  border-radius: 8px;
  transition: background 180ms ease, color 180ms ease, transform 180ms ease;
}

.auth-switch a svg {
  width: 14px;
  height: 14px;
  transition: transform 200ms ease;
}

.auth-switch a:hover {
  background: rgba(37, 99, 235, 0.12);
  color: var(--accent-deep);
  transform: translateY(-1px);
}

.auth-switch a:hover svg { transform: translateX(-3px); } /* arrow nudges toward target in RTL */

/* ============================================================
   Responsive — collapse two-column shell under 980px
   ============================================================ */

@media (max-width: 980px) {
  .auth-shell {
    grid-template-columns: 1fr;
  }

  .auth-visual {
    min-height: 220px;
    padding: 1.5rem 1.2rem;
  }

  .auth-card {
    padding: 1.4rem 1.1rem;
  }
}

@media (max-width: 640px) {
  .auth-main {
    width: min(94vw, 520px);
  }

  .auth-grid-two {
    grid-template-columns: 1fr;
  }

  .auth-card-head h1 { font-size: 1.6rem; }
  .auth-hero-title  { font-size: 1.4rem; }
}
