/* Login: the shader stage, the glass card and the submit button morph.
   Owner: L1 (`js/app/views/login.js`). Root: `#v-auth` and the `.auth-stage` tile inside it, plus the
   `.rb*` morph parts of `#login-btn`. Nothing here styles the console: the moment the router swaps
   `auth-stage` for `c-head` the tile leaves this file's reach and `css/app/console.css` takes over.
   Tokens only (`css/tokens.css`); `main.css` already ships `.auth-form`, `.auth-err` and `.orb`, so
   this file only tightens what spec `_spec/console.md` 1.2 and 1.3 pin down. */

/* ---------- the stage ----------
   One container-wide tile. The shader sits at z0, the glass object at z1, the two mono captions at
   z2 and the card at z3. min-height is CSS only: orb.js reads `#stage` size once at init. */
/* `main.css` gives every `<section>` a `--sec` block padding and `base.css` zeroes it for the
   onboard and console views but not for this one, so the stage starts 144 px down the page and the
   tile no longer fits the viewport. Zero it here, and zero the `.app-main` padding the same way
   base.css already does for the other two views, so the `100dvh` height below is the real one.
   Requested for base.css (see requests) so this pair can come out again. */
#v-auth{padding:0}
/* flow-root so the tile's own 24 px bottom margin cannot collapse out of the main and add a
   scrollbar to a page that otherwise fits the viewport exactly */
body[data-view="auth"] .app-main{padding-top:0;padding-bottom:0;display:flow-root}
#v-auth .container{min-width:0}
.auth-stage{
  position:relative;
  isolation:isolate;
  overflow:hidden;
  border-radius:var(--r-tile);
  background:var(--bg-2);
  min-height:min(calc(100dvh - var(--nav-h) - 48px),820px);
  margin:24px 0;
}
.auth-stage .shader{position:absolute;inset:0;z-index:0}
.auth-stage .orb{position:absolute;inset:0;z-index:1;pointer-events:none}

/* ---------- captions ----------
   `.tile-k` in main.css is a space-between flex row with a bottom margin; both are wrong for an
   absolutely placed caption, so `.auth-cap` resets them.
   Both captions sit straight on a live shader whose colours move, so no fixed text colour can hold a
   contrast ratio on its own. Visual rule 7 answers that the same way `.tile-copy` does: a white
   scrim under the copy. Here it is a pill rather than a band, so the tile stays open. */
.auth-stage .auth-clock,.auth-stage .auth-cap{
  background:rgba(255,255,255,.72);
  -webkit-backdrop-filter:blur(10px) saturate(1.2);
  backdrop-filter:blur(10px) saturate(1.2);
  border-radius:var(--r-pill);
}
.auth-stage .auth-clock{
  position:absolute;z-index:2;
  left:clamp(20px,3vw,40px);top:clamp(20px,3vw,40px);
  font-size:13px;line-height:1;color:var(--text-2);letter-spacing:.06em;
  padding:7px 12px;
}
.auth-stage .auth-cap{
  position:absolute;z-index:2;
  right:clamp(20px,3vw,40px);bottom:clamp(20px,3vw,40px);
  display:inline-flex;align-items:center;gap:8px;margin:0;
  color:var(--text-2);padding:5px 6px 5px 12px;
}

/* ---------- the glass card ----------
   One of the two allowed shadows (glass over imagery), same recipe as `.chat` in main.css. */
.auth-stage .auth-glass{
  position:absolute;z-index:3;
  left:clamp(20px,5vw,72px);top:50%;
  transform:translateY(-50%);
  width:min(440px,calc(100% - 40px));
  padding:clamp(20px,2.4vw,32px);
  border-radius:20px;
  background:var(--glass);
  -webkit-backdrop-filter:blur(var(--glass-blur)) saturate(var(--glass-sat));
  backdrop-filter:blur(var(--glass-blur)) saturate(var(--glass-sat));
  border:1px solid var(--glass-line);
  box-shadow:var(--glass-lift);
}

/* ---------- the form ---------- */
.auth-stage .auth-form h1{
  font-size:clamp(26px,2.4vw,32px);font-weight:500;
  letter-spacing:-.025em;line-height:1.1;margin:0 0 18px;
}
.auth-stage .auth-form h1:focus{outline:none}
.auth-stage .auth-form label{display:grid;gap:6px;font-size:13px;color:var(--text-2);margin:0 0 14px}
.auth-stage .auth-form input{
  width:100%;font:inherit;font-size:16px;font-weight:500;
  height:48px;padding:0 14px;
  color:var(--ink);background:#fff;
  border:1px solid var(--line-control);border-radius:var(--app-r-input,12px);
  transition:border-color .15s var(--ease),box-shadow .15s var(--ease);
}
.auth-stage .auth-form input::placeholder{color:var(--text-3)}
/* the one allowed ring: ink border plus a 3 px halo, never the blue one from main.css */
.auth-stage .auth-form input:focus{border-color:var(--ink)}
.auth-stage .auth-form input:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
.auth-stage .auth-form input[aria-invalid="true"]{border-color:var(--err)}
.auth-stage .auth-form input[aria-invalid="true"]:focus{box-shadow:0 0 0 3px rgba(180,35,24,.14)}
.auth-hint{font-size:13px;line-height:1.5;color:var(--text-2);margin-top:12px}
.auth-hint b{font-weight:500;color:var(--text-2)}
.auth-alt{font-size:14px;color:var(--text-2);margin-top:16px}
.auth-alt a{text-decoration:underline;text-underline-offset:2px}
@media (prefers-reduced-motion:reduce){.auth-stage .auth-form input{transition:none}}

/* ---------- the submit button morph (spec 1.3) ----------
   `.rect.rect-blue.lg` gives the resting shape (46 high, radius 9, #0071E3). The script tweens width,
   radius and padding down to a 46 px disc, fades `.rb-label` out and the ring in, then draws the arc
   and the check. Every value the script animates has a resting value here so the instant fallback and
   the restore after a cancel land on the same pixels. */
.rb{position:relative;width:100%;overflow:hidden}
.rb-label{display:inline-block;opacity:1;transition:opacity .2s var(--ease)}
.rb-ring{
  position:absolute;left:50%;top:50%;
  width:24px;height:24px;margin:-12px 0 0 -12px;
  opacity:0;pointer-events:none;
  fill:none;stroke:#fff;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;
}
.rb-track{stroke-opacity:.3}
.rb-arc{transform:rotate(-90deg);transform-origin:12px 12px}
.rb-check{opacity:0}
.rb[disabled],.rb[aria-busy="true"]{cursor:default}
/* disabled is a busy state here, not a refusal: keep the blue, keep it readable */
.rb[disabled]{opacity:1}
.rb[disabled]:hover{filter:none}
@media (prefers-reduced-motion:reduce){.rb-label{transition:none}}

/* ---------- mobile (spec 1.2): the card stops floating and the glass object steps out ---------- */
@media (max-width:820px){
  .auth-stage{
    min-height:auto;margin:16px 0;padding:16px;
    display:flex;align-items:flex-end;
  }
  .auth-stage .orb{display:none}
  .auth-stage .auth-glass{
    position:static;transform:none;
    width:100%;margin-top:200px;
  }
  /* the caption would sit under the card down here, so it joins the clock at the top */
  .auth-stage .auth-cap{top:clamp(16px,4vw,20px);bottom:auto;right:clamp(16px,4vw,20px)}
  .auth-stage .auth-clock{left:clamp(16px,4vw,20px);top:clamp(16px,4vw,20px)}
}
