/* ══════════════════════════════════════════════════════════
   NOVARTH GROUP - auth-aspx.css
   Bridge layer: puts the auth.css design system (login.html /
   register.html) onto the markup Web Forms actually emits -
   validator spans, UpdatePanel wrappers, asp:CheckBox - plus the
   verification card both auth pages share.
   Loaded AFTER css/auth.css; it only adds and overrides.
══════════════════════════════════════════════════════════ */

/* ══════════════════════════════════════════════════════════
   FIELD AS A FLEX COLUMN
   A server validator is an inline <span> the framework flips between
   display:none and display:inline. Vertical margins do nothing on an
   inline box, so the spacing has to come from the column gap instead -
   a hidden validator then costs neither height nor gap, and a visible
   one adds exactly one row.
══════════════════════════════════════════════════════════ */
.auth-form .field{
  display:flex; flex-direction:column;
  gap:.42rem;
  position:relative;
  margin-bottom:13px;
}
/* the meter would still claim a gap at max-height:0, so take it out of
   flow entirely until auth-aspx.js switches it on */
.auth-form .strength:not(.on){ display:none; }
.auth-form .strength.on{ margin-top:0; }
.auth-form .caps{ margin-top:0; }

/* An UpdatePanel renders a plain <div> around its content and has no
   CssClass to hand. Left alone it would collapse everything it wraps into
   a single flex item, so the column gap would vanish between the controls
   inside it. display:contents hands those children straight back to the
   form's own column. */
.auth-form div:not([class]){ display:contents; }

/* ══════════════════════════════════════════════════════════
   VALIDATORS
   ForeColor defaults to Red and is written as an inline style, so the
   colour has to be forced. Everything else is the .f-msg treatment.
══════════════════════════════════════════════════════════ */
.f-err{
  font-size:.76rem; font-weight:500; line-height:1.5;
  color:var(--danger) !important;
}
/* A validator's ForeColor error text has no element to hang a [data-lucide]
   marker on - it's a ::before, and Lucide only replaces real DOM nodes. This
   is the one icon on the auth pages that can't go through the JS swap, so
   it's the Lucide "triangle-alert" glyph's own path data, inlined instead of
   redrawn, to keep it the same icon as everywhere else. */
.f-err::before{
  content:''; display:inline-block;
  width:13px; height:13px; margin-right:.32rem; vertical-align:-2px;
  background:currentColor;
  -webkit-mask:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m21.73 18-8-14a2 2 0 0 0-3.46 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3Z'/%3E%3Cpath d='M12 9v4'/%3E%3Cpath d='M12 17h.01'/%3E%3C/svg%3E") center/contain no-repeat;
          mask:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m21.73 18-8-14a2 2 0 0 0-3.46 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3Z'/%3E%3Cpath d='M12 9v4'/%3E%3Cpath d='M12 17h.01'/%3E%3C/svg%3E") center/contain no-repeat;
}

/* ══════════════════════════════════════════════════════════
   PRE-FILLED FIELDS
   The floating label rides on :placeholder-shown. That breaks in two
   places: while Chrome is *previewing* an autofill the field looks full
   but its value is still the empty string, and a password manager can
   write a value without the page ever seeing an event. Either way the
   label stays centred and sits on top of the text.

   Two belts - the vendor pseudo-class for the preview state, and a class
   auth-aspx.js sets whenever the value is genuinely non-empty.
══════════════════════════════════════════════════════════ */
.f-box input.is-filled + label{
  transform:translate(-4px,calc(-50% - (var(--fld-h) / 2) - var(--lab-lift))) scale(.86);
  color:var(--gold);
}
/* Kept as separate rules on purpose: one unknown pseudo-class would
   invalidate the entire selector list it appears in. */
.f-box input:-webkit-autofill + label{
  transform:translate(-4px,calc(-50% - (var(--fld-h) / 2) - var(--lab-lift))) scale(.86);
  color:var(--gold);
}
.f-box input:autofill + label{
  transform:translate(-4px,calc(-50% - (var(--fld-h) / 2) - var(--lab-lift))) scale(.86);
  color:var(--gold);
}

/* asp:Label used for the resolved sponsor name - a span that is empty
   until the lookup posts back */
.sponsor-name{
  font-size:.78rem; font-weight:600; color:var(--ok);
}
.sponsor-name:empty{ display:none; }

/* ══════════════════════════════════════════════════════════
   VERIFICATION CARD  (login.aspx + Registration.aspx)
   Its own palette, scoped to the component so the gold accent the
   rest of the form runs on is left untouched.
══════════════════════════════════════════════════════════ */
.captcha-field{
  --cap-primary:#17345F;
  --cap-accent:#2D7FF9;
  --cap-warn:#E6A23C;
  --cap-border:#E8EDF5;
  --cap-surface:#FFFFFF;
  --cap-text:#1F2D3D;
  --cap-holder:#A0AEC0;
  --cap-font:var(--f-b);
}

/* On the registration form the fields are paired two-up; the card is a block
   of its own and takes the full row rather than sitting in one column. */
.field-grid > .captcha-field{ grid-column:1 / -1; }

.captcha-card{
  display:flex; flex-direction:column; gap:.5rem;
  padding:.65rem .75rem .7rem;
  border:1px solid var(--cap-border); border-radius:12px;
  /* translucent rather than flat white, so the card reads as glass over
     the panel instead of a second sheet of paper */
  background:linear-gradient(180deg,rgba(255,255,255,.94),rgba(246,250,255,.88));
  -webkit-backdrop-filter:blur(14px) saturate(140%);
          backdrop-filter:blur(14px) saturate(140%);
  box-shadow:
    0 1px 2px rgba(23,52,95,.05),
    0 12px 30px -20px rgba(23,52,95,.42);
  transition:box-shadow .3s var(--e-std), border-color .3s var(--e-std);
}
.captcha-card:hover{
  border-color:#DCE5F2;
  box-shadow:
    0 1px 2px rgba(23,52,95,.06),
    0 18px 38px -20px rgba(23,52,95,.5);
}

/* ── head ──────────────────────────────────────────────── */
.captcha-head{
  display:flex; align-items:center; justify-content:space-between; gap:.75rem;
}
.captcha-label{
  font-family:var(--cap-font); font-size:.74rem; font-weight:600;
  color:var(--cap-text);
}
.captcha-badge{
  display:inline-flex; align-items:center; gap:.26rem;
  padding:.16rem .45rem; border-radius:999px;
  border:1px solid rgba(45,127,249,.22);
  background:rgba(45,127,249,.08);
  font-family:var(--cap-font); font-size:.58rem; font-weight:600;
  letter-spacing:.015em; color:var(--cap-accent); white-space:nowrap;
}
.captcha-badge svg,
.captcha-badge i[data-lucide]{
  width:10px; height:10px; flex:0 0 auto;
  fill:none; stroke:currentColor; stroke-width:1.6;
  stroke-linecap:round; stroke-linejoin:round;
}

/* ── image + refresh ───────────────────────────────────── */
/* Plate, refresh and input share one row. The plate takes twice the free
   space so the code stays as large as the row allows, and the input keeps a
   150px basis - enough for six spaced-out characters plus its icon. */
.captcha-stage{ display:flex; align-items:center; flex-wrap:wrap; gap:.5rem; }

/* No inner padding: a bordered plate inside a bordered card inside a bordered
   panel is what made this read as bulky. The hairline alone gives it an edge.
   max-width stops it running away on the wide registration panel. */
.captcha-frame{
  flex:2 1 130px; min-width:0; max-width:230px;
  overflow:hidden;
  border:1px solid var(--cap-border); border-radius:9px;
  background:var(--cap-surface);
  box-shadow:inset 0 1px 3px rgba(23,52,95,.06);
}
/* The bitmap is drawn at 2x and scaled down here, which is what keeps the
   glyph edges clean on high-DPI screens. */
.captcha-img{
  display:block; width:100%; height:auto; border-radius:8px;
  transition:opacity .3s var(--e-std), transform .42s var(--e-emph), filter .3s var(--e-std);
}

.captcha-refresh{
  position:relative; flex:0 0 auto;
  display:grid; place-items:center;
  width:40px; height:40px; border-radius:50%;
  border:1px solid var(--cap-border);
  background:rgba(45,127,249,.06);
  color:var(--cap-accent); text-decoration:none;
  transition:transform .25s var(--e-emph), box-shadow .25s var(--e-std),
             background .25s var(--e-std), border-color .25s var(--e-std);
}
.captcha-refresh svg,
.captcha-refresh i[data-lucide]{
  width:17px; height:17px;
  fill:none; stroke:currentColor; stroke-width:1.75;
  stroke-linecap:round; stroke-linejoin:round;
  transition:transform .55s var(--e-emph);
}
.captcha-refresh:hover{
  background:rgba(45,127,249,.13);
  border-color:rgba(45,127,249,.34);
  transform:translateY(-2px);
  box-shadow:0 10px 20px -10px rgba(45,127,249,.75);
}
.captcha-refresh:hover svg{ transform:rotate(180deg); }
.captcha-refresh:active{ transform:translateY(0) scale(.95); }

/* tooltip - a styled one rather than the native title, which would show
   a second box on top of it */
.captcha-refresh::after{
  content:attr(data-tip);
  position:absolute; bottom:calc(100% + 9px); left:50%;
  transform:translate(-50%,5px);
  padding:.3rem .52rem; border-radius:7px;
  background:var(--cap-primary); color:#fff;
  font-family:var(--cap-font); font-size:.62rem; font-weight:500;
  white-space:nowrap; pointer-events:none; opacity:0;
  box-shadow:0 6px 16px -8px rgba(23,52,95,.9);
  transition:opacity .2s var(--e-std), transform .26s var(--e-emph);
}
.captcha-refresh:hover::after,
.captcha-refresh:focus-visible::after{ opacity:1; transform:translate(-50%,0); }

/* ── input ─────────────────────────────────────────────── */
.captcha-input{
  flex:1 1 150px; min-width:0;
  display:flex; align-items:center;
  height:46px; border-radius:10px;
  border:1px solid var(--cap-border);
  background:var(--cap-surface);
  transition:border-color .22s var(--e-std), box-shadow .22s var(--e-std),
             transform .22s var(--e-std);
}
.captcha-input:hover{ border-color:#D5DEEC; transform:translateY(-1px); }
.captcha-input:focus-within{
  border-color:var(--cap-accent);
  box-shadow:0 0 0 4px rgba(45,127,249,.14);
  transform:translateY(-1px);
}
.captcha-input-ic{
  flex:0 0 auto; display:grid; place-items:center;
  width:42px; height:100%; color:var(--cap-holder);
  transition:color .22s var(--e-std);
}
.captcha-input-ic svg,
.captcha-input-ic i[data-lucide]{
  width:18px; height:18px;
  fill:none; stroke:currentColor; stroke-width:1.6;
  stroke-linecap:round; stroke-linejoin:round;
}
.captcha-input:focus-within .captcha-input-ic{ color:var(--cap-accent); }

.captcha-input input{
  flex:1 1 auto; min-width:0;
  height:100%; padding:0 1rem 0 0;
  border:none; outline:none; background:none;
  font-family:var(--cap-font);
  font-size:14px;                 /* 16px keeps iOS from zooming on focus */
  font-weight:500; color:var(--cap-text);
  letter-spacing:.13em; text-transform:uppercase;
}
.captcha-input input::placeholder{
  color:var(--cap-holder); font-weight:500;
  letter-spacing:.01em; text-transform:none;
}
.captcha-input input:-webkit-autofill{
  -webkit-text-fill-color:var(--cap-text);
  -webkit-box-shadow:0 0 0 100px var(--cap-surface) inset;
}

/* label kept for screen readers - the field carries a placeholder instead */
.captcha-sr{
  position:absolute; width:1px; height:1px;
  margin:-1px; padding:0; border:0; overflow:hidden;
  clip:rect(0 0 0 0); clip-path:inset(50%); white-space:nowrap;
}

/* ── helper link ───────────────────────────────────────── */
.captcha-help{
  align-self:flex-start;
  font-family:var(--cap-font); font-size:.68rem; font-weight:500;
   text-decoration:none;
}
.captcha-help b{
  position:relative; color:var(--cap-accent); font-weight:600;
}
.captcha-help b::after{
  content:''; position:absolute; left:0; right:0; bottom:-2px; height:1px;
  background:currentColor;
  transform:scaleX(0); transform-origin:right;
  transition:transform .3s var(--e-emph);
}
.captcha-help:hover b::after{ transform:scaleX(1); transform-origin:left; }

/* ── swap animation ────────────────────────────────────── */
/* The class lands on .captcha-field, which sits outside the UpdatePanel and
   therefore survives the DOM being replaced mid-refresh. */
.captcha-field.is-swapping .captcha-img{
  opacity:0; transform:scale(.97) translateY(-3px); filter:blur(3px);
}
.captcha-field.is-swapping .captcha-refresh,
.captcha-field.is-swapping .captcha-help{ pointer-events:none; }
.captcha-field.is-swapping .captcha-refresh svg,
.captcha-field.is-swapping .captcha-refresh i[data-lucide]{
  animation:cap-spin .75s linear infinite; transition:none;
}
@keyframes cap-spin{ to{ transform:rotate(360deg); } }

/* ── states ────────────────────────────────────────────── */
.captcha-field.is-err .captcha-input{
  border-color:var(--danger); background:var(--danger-s);
  animation:shake .5s cubic-bezier(.36,.07,.19,.97);
}
.captcha-field.is-err .captcha-input-ic{ color:var(--danger); }
.captcha-field.is-ok:not(:focus-within) .captcha-input{ border-color:#BFE6D5; }

@media (max-width:400px){
  .captcha-card{ padding:.55rem .6rem .6rem; }
  .captcha-stage{ gap:.45rem; }
}

/* ══════════════════════════════════════════════════════════
   SUCCESS OVERLAY  (Registration.aspx)
   auth.css already styles .auth-done, .done-in and the pulsing
   .done-ring with its drawn checkmark. This adds the member-ID plate,
   the redirect progress bar, and the stagger that brings the copy in
   behind the tick rather than all at once.
══════════════════════════════════════════════════════════ */
.done-card{
  display:inline-block;
  margin:1.3rem auto 1.05rem;
  padding:.65rem 1.5rem .75rem;
  border:1px solid var(--line); border-radius:14px;
  background:var(--surf);
  box-shadow:0 12px 32px -20px rgba(15,36,69,.65);
}
.done-card span{
  display:block; margin-bottom:.15rem;
  font-family:var(--f-h); font-size:.58rem; font-weight:700;
  letter-spacing:.19em; text-transform:uppercase; color:var(--body-l);
}
.done-card b{
  display:block;
  font-family:var(--f-h); font-size:1.32rem; font-weight:800;
  letter-spacing:.07em; color:var(--ink);
}

.done-bar{
  display:block; width:190px; height:3px; margin:1.05rem auto 0;
  border-radius:2px; background:var(--line); overflow:hidden;
}
/* width and duration are driven from authSuccess(), so the bar empties in
   step with the redirect rather than guessing at it */
.done-bar i{
  display:block; width:0; height:100%; border-radius:2px;
  background:linear-gradient(90deg,var(--gold),var(--gold-l));
  transition:width 2.6s linear;
}

/* ── stagger ───────────────────────────────────────────── */
/* The ring keeps auth.css's own entrance; everything after it waits its
   turn so the tick reads first. */
.auth-done h3,
.auth-done .done-sub,
.auth-done .done-card,
.auth-done .done-next,
.auth-done .done-bar{ opacity:0; transform:translateY(10px); }

.auth-done.show h3{ animation:done-rise .5s .16s var(--e-emph) forwards; }
.auth-done.show .done-sub{ animation:done-rise .5s .26s var(--e-emph) forwards; }
.auth-done.show .done-card{ animation:done-rise .58s .36s var(--e-spring) forwards; }
.auth-done.show .done-next{ animation:done-rise .5s .5s var(--e-emph) forwards; }
.auth-done.show .done-bar{ animation:done-rise .5s .58s var(--e-emph) forwards; }

@keyframes done-rise{ to{ opacity:1; transform:none; } }

@media (max-width:480px){
  .done-card{ padding:.6rem 1.15rem .7rem; }
  .done-card b{ font-size:1.15rem; }
  .done-bar{ width:150px; }
}

/* ══════════════════════════════════════════════════════════
   CHECKBOX
   asp:CheckBox may wrap its <input> in a <span> depending on the
   properties set on it, which would otherwise be painted as a second
   tick box by auth.css. Neutralise any wrapper, keep only .ck, and
   drive the checked state with :has() so it works either way.
══════════════════════════════════════════════════════════ */
.check > span:not(.ck){ display:contents; }
.check > span:not(.ck)::after{ content:none; }
.check:has(input:checked) > .ck{ background:var(--gold); border-color:var(--gold); }
.check:has(input:checked) > .ck::after{ transform:rotate(42deg) scale(1); }
.check:has(input:focus-visible) > .ck{ outline:2px solid var(--gold); outline-offset:2px; }

/* ══════════════════════════════════════════════════════════
   SUBMIT (asp:LinkButton renders an <a>)
══════════════════════════════════════════════════════════ */
a.auth-submit{ text-decoration:none; }
a.auth-submit:hover{ color:#fff; }

/* right-aligned single option row (no "remember me" on the server form) */
.form-options-end{ justify-content:flex-end; }

/* ══════════════════════════════════════════════════════════
   WIDE PANEL - registration carries far more fields than the
   static register.html, so it pairs them two-up.
══════════════════════════════════════════════════════════ */
.auth-wrap-wide{ max-width:648px; }
.auth-form .field-grid{ gap:1.25rem .9rem; }

@media (max-width:1023px){
  .auth-wrap-wide{ max-width:560px; }
}

/* ══════════════════════════════════════════════════════════
   DESKTOP DENSITY
   The split layout gives the form a fixed-height column, so the whole
   panel has to land inside the viewport - a sign-in button you have to
   scroll to find is a broken sign-in page. Two tiers: a general trim on
   desktop, then a tighter one once the viewport is laptop-height.

   Only applies from 1024px up. Below that the panel is a bottom sheet
   and scrolling it is the expected gesture, not a failure.
══════════════════════════════════════════════════════════ */
@media (min-width:1024px){
  .auth-panel{ padding-block:1.35rem; }
  .auth-form-wrap{ padding-block:clamp(.5rem,2vh,1.5rem); }
  .auth-form{ gap:1.1rem; }
  .form-intro{ margin-bottom:1.25rem; }
  .auth-switch{ margin-top:1.15rem; }
  .form-options{ margin-top:-.55rem; }
  .form-options .text-link{ padding:.25rem 0; }
}

@media (min-width:1024px) and (max-height:860px){
  /* one token drives the field height, and the floating label's notch is
     measured from it - so the label follows without being re-tuned */
  :root{ --fld-h:48px; }

  .auth-panel{ padding-block:1rem; }
  .auth-form-wrap{ padding-block:.4rem; }
  .auth-form{ gap:.95rem; }

  .form-kicker{ font-size:.66rem; margin-bottom:.4rem; }
  .auth-form-wrap h2{ font-size:1.5rem; margin-bottom:.35rem; }
  .form-intro{ font-size:.82rem; margin-bottom:1rem; }

  .auth-submit{ height:50px; }
  .auth-submit.is-done{ width:50px; }
  .auth-switch{ margin-top:.95rem; }

  /* the verification card is the tallest single block in the column */
  .captcha-card{ padding:.55rem .7rem .62rem; gap:.42rem; }
  .captcha-input{ height:42px; }
  .captcha-input-ic{ width:38px; }
  .captcha-refresh{ width:38px; height:38px; }
  .captcha-refresh svg{ width:16px; height:16px; }
}

@media (min-width:1024px) and (max-height:720px){
  :root{ --fld-h:46px; }
  .auth-form{ gap:.8rem; }
  .auth-form-wrap h2{ font-size:1.35rem; }
  .form-intro{ margin-bottom:1rem; }
  .auth-submit{ height:48px; }
  .auth-submit.is-done{ width:48px; }
  .captcha-card{ gap:.38rem; }
}
@media (max-width:600px){
  .auth-form .field-grid{ grid-template-columns:1fr; gap:1.25rem; }
  /* too narrow for three things abreast - the input drops to its own line */
  .captcha-frame{ max-width:none; }
  .captcha-input{ flex:1 0 100%; }
}
