/* login.css — the PIN pad.
 *
 * The same black ground and greyscale as everything else; the person accent
 * only arrives at the moment the PIN is accepted, because until then the app
 * does not know whose accent it is. That is the whole gesture of this screen:
 * four grey dots fill, and on the last one the app turns their colour and
 * dissolves.
 *
 * Sized for a phone held in one hand: keys are 64px tall (the design system's
 * --tap floor is 44), the pad sits at the BOTTOM of the viewport where a thumb
 * reaches, and the brand and dots take the space above it. No text input, so
 * iOS never raises a keyboard over the thing you are typing into.
 */

/* While the pad is up the app is not behind it, it is out of the page. A
 * curtain one `display:block` away from the ledgers would be theatre — the real
 * gate is cli/api_auth.py, and this is just the shell keeping its hands down. */
:root[data-locked] .top,
:root[data-locked] .tabbar,
:root[data-locked] #view,
:root[data-locked] #pane,
:root[data-locked] #toast {
  display: none;
}

.login {
  position: fixed;
  inset: 0;
  z-index: 90;
  display: flex;
  align-items: stretch;           /* so .login-inner is full height without a % */
  justify-content: center;
  background: var(--bg);
  padding: max(24px, env(safe-area-inset-top)) 16px
           max(20px, env(safe-area-inset-bottom)) 16px;
  opacity: 1;
  transition: opacity 400ms var(--ease);
}

.login:focus { outline: none; }

/* Two `margin-top: auto` rules — one on the brand, one on the pad — split the
   free height between them: the wordmark and the dots sit in the upper half,
   the keypad is pinned to the bottom where a thumb is, and both stay put from a
   short phone to a tall one without a media query or a magic number. */
.login-inner {
  display: flex;
  flex-direction: column;
  align-items: center;
  width: 100%;
  max-width: 320px;
}

/* ------------------------------------------------------------ the head --- */

.login-brand {
  margin-top: auto;
  font: 700 var(--fs-9)/1.1 var(--font);
  letter-spacing: -.03em;
  color: var(--ink);
}

/* --ink-2, not --ink-3: this is the only instruction on the screen, so it
   takes the stronger secondary ink (7.7:1 or better in both modes). */
.login-lede {
  margin-top: 6px;
  font-size: var(--fs-3);
  color: var(--ink-2);
}

/* ------------------------------------------------------------ the dots --- */

.login-dots {
  display: flex;
  gap: 18px;
  margin: 28px 0 0;
  min-height: 16px;
  align-items: center;
}

.login-dot {
  width: 14px;
  height: 14px;
  border-radius: 50%;
  border: 1.5px solid var(--ink-3);
  background: transparent;
  transition: background-color 140ms var(--ease), border-color 140ms var(--ease),
              transform 140ms var(--ease);
}

.login-dot.is-on {
  background: var(--ink);
  border-color: var(--ink);
  transform: scale(1.06);
}

/* The one moment the accent appears: the PIN was right, so the app now knows
   whose it is. */
.login.is-ok .login-dot.is-on {
  background: var(--accent-mark);
  border-color: var(--accent-mark);
}

.login.is-busy .login-dots { opacity: .55; }

/* --------------------------------------------------------- the message --- */

.login-msg {
  margin: 14px 0 0;
  min-height: 20px;
  font-size: var(--fs-3);
  color: var(--red);
  text-align: center;
  text-wrap: balance;
}

.login.is-locked .login-msg { color: var(--ink-2); }

/* ------------------------------------------------------------- the pad --- */

.login-pad {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 12px;
  width: 100%;
  max-width: 288px;
  margin-top: auto;               /* the other half of the free height */
  padding-top: 34px;              /* ...and a floor under the message */
}

.login-key {
  display: grid;
  place-items: center;
  /* SQUARE, so `border-radius: 50%` is a circle and not the ellipse a
     wider-than-tall key would give. The pad's width sets the diameter; the
     min-height is the floor for the case where it cannot (--tap is 44). */
  aspect-ratio: 1;
  min-height: 64px;
  min-width: 44px;
  padding: 0;
  /* A control's boundary is --edge (3:1 or better on every ground); --line
     is decorative and measured about 1.3:1 in light. */
  border: 1px solid var(--edge);
  border-radius: 50%;
  background: var(--surface);
  color: var(--ink);
  font: 400 var(--fs-9)/1 var(--font);
  font-variant-numeric: tabular-nums;
  letter-spacing: -.01em;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  user-select: none;
  transition: background-color 120ms var(--ease), transform 120ms var(--ease);
}

.login-key:active { background: var(--surface-2); transform: scale(.95); }
.login-key:focus-visible { outline: 2px solid var(--accent-ink); outline-offset: 2px; }

.login-key[disabled] {
  opacity: .35;
  pointer-events: none;
}

.login-key-blank {
  border: 0;
  background: none;
  pointer-events: none;
}

.login-key-delete {
  border-color: transparent;
  background: none;
  color: var(--ink-2);
}

.login-key-delete:active { background: var(--surface); }

.login-delete-icon { width: 28px; height: 28px; stroke-width: 1.7; }

/* -------------------------------------------------------- the reactions -- */

/* Wrong PIN: a short lateral shake, no colour flash — the message says what
   happened and the dots have already cleared. */
@keyframes login-shake {
  10%, 90% { transform: translateX(-4px); }
  20%, 80% { transform: translateX(6px); }
  30%, 50%, 70% { transform: translateX(-8px); }
  40%, 60% { transform: translateX(8px); }
}

.login.is-wrong .login-inner {
  animation: login-shake 400ms var(--ease);
}

/* Accepted: the dots take the accent, then the whole screen dissolves into the
   app behind it. */
.login.is-gone {
  opacity: 0;
  pointer-events: none;
}

/* ---------------------------------------------------------------- a11y --- */

@media (prefers-reduced-motion: reduce) {
  /* The shake is the one animation here that carries no information the message
     does not already carry, so it goes entirely rather than being shortened. */
  .login.is-wrong .login-inner { animation: none; }
  .login,
  .login-dot,
  .login-key { transition: none; }
}

/* A short screen shrinks the pad by narrowing it — the keys are square, so the
   width IS the height, and one number keeps them circular. */
@media (max-height: 660px) {
  .login-brand { font-size: var(--fs-7); }
  .login-dots { margin-top: 18px; }
  .login-pad { padding-top: 20px; gap: 10px; max-width: 232px; }
  .login-key { min-height: 56px; font-size: var(--fs-8); }
  .login-delete-icon { width: 24px; height: 24px; }
}


/* ------------------------------------------------------------- the mark --- */

/* The Kaire double-K, above the wordmark. It carries the BRAND colour; the
 * per-person accent (amber for Alex, slate for Jordan) is identity, not brand,
 * and it is deliberately absent here — this screen does not yet know who is
 * holding the phone, which is the same reason there is no person picker on it.
 * The accent arrives at the moment the PIN is accepted, on the dots. */
/* The mark's first path is the TILE with the K knocked out of it, so the K is
   a hole and shows whatever is behind. Teal ink over a white ground therefore
   gives the same object as the home-screen icon — teal tile, white K — instead
   of the black K a hole over the black page would show. --on-brand is that
   white in both modes (--ink would turn the K near-black in light mode). The
   radius is the SVG's own: 23.68 of a 128.35 viewBox is 18.45%. */
.login-mark {
  display: block;
  width: 56px;
  height: 56px;
  color: var(--brand);
  background: var(--on-brand);
  border-radius: 18.45%;
  margin-bottom: 14px;
}

.login-brand { margin-top: 0; }

@media (max-height: 660px) {
  .login-mark { width: 44px; height: 44px; margin-bottom: 10px; }
}

/* Wide (§3.3): no thumb to reach for, so the pad is not pinned to the bottom
   edge of a desk screen, 200px under its dots. The brand, the dots and the
   keys sit together as one block, centred. The lock screen is the whole
   viewport, so this is a viewport rule, like the shell's own. */
@media (min-width: 1024px) {
  .login-inner { justify-content: center; }
  .login-pad { margin-top: 0; }
}

/* ------------------------------------------------ Face ID (round 12) ---
 * K-Fit's own address only (js/login.js offers it when GET /api/session says
 * `webauthn: true`). One large button; on a device that has used Face ID it
 * comes FIRST and the keys wait behind "Use PIN instead". */
.login-faceid {
  min-height: 52px;
  width: min(100%, 300px);
  margin-top: var(--s-4);
  padding: 0 var(--s-5);
  border: 0;
  border-radius: 999px;
  background: var(--brand);
  color: var(--on-brand);
  font: inherit;
  font-weight: 600;
}

.login-faceid[disabled] { opacity: 0.6; }

.login-use-pin {
  min-height: 44px;
  margin-top: var(--s-2);
  padding: 0 var(--s-4);
  border: 0;
  background: none;
  color: var(--ink-2);
  font: inherit;
  text-decoration: underline;
}

.login.is-faceid-first .login-dots,
.login.is-faceid-first .login-pad { display: none; }

/* The step-up ("Face ID opens this screen") sits over the app, which stays. */
.login-stepup .login-inner { justify-content: center; }

/* The VEIL (js/relock.js): the instant the app is hidden, everything but the
 * lock screen is blurred, because iOS takes the app-switcher snapshot then
 * and it must not show a dose list. Own address only. */
html[data-veiled] body > *:not(.login) {
  filter: blur(24px);
}

/* ------------------------------------- the own address's lock (3 Oct) ---
 * js/login.js mountOwnLock: no keypad at kfit.kaireapp.dev. Face ID first,
 * "I have a one-time code" under it, and for a person with no passkey yet,
 * the code field and then "Add Face ID". One centred block, phone or desk. */
.login.is-own .login-inner { justify-content: center; }

.login-code {
  display: grid;
  gap: var(--s-2);
  width: min(100%, 300px);
  margin-top: var(--s-4);
}

.login-code[hidden],
.login-add-faceid[hidden],
.login-faceid[hidden],
.login-use-code[hidden] { display: none; }

.login-code-input {
  min-height: 52px;
  padding: 0 var(--s-4);
  border: 1px solid var(--edge);
  border-radius: var(--r-field);
  background: var(--field-bg);
  color: var(--ink);
  /* --fs-7 (18px): at or above iOS's 16px floor, so focusing it never zooms. */
  font: 500 var(--fs-7)/1 var(--font);
  font-variant-numeric: tabular-nums;
  letter-spacing: .08em;
  text-align: center;
}

.login-code-input::placeholder { color: var(--ink-3); letter-spacing: 0; }
.login-code-input:focus-visible { outline: 2px solid var(--accent-ink); outline-offset: 2px; }
.login-code .login-code-go { width: 100%; margin-top: 0; }
.login.is-own.is-busy .login-inner { opacity: .7; }
