/*
 * builder-login stylesheet (D-041) — the split-screen shell shared by the four
 * standalone auth documents: login, password request, password reset, and the
 * 2FA challenge. Loaded from those four views via a plain <link> (they have no
 * layout stack), AFTER app.css / lms-auth.css / lms-account.css so it can
 * refine their primitives, and BEFORE lms-responsive.css so the mobile
 * override layer still wins last.
 *
 * app.css's own .auth / .auth__box primitives are deliberately left alone:
 * resources/views/certificate/verify.blade.php still renders on them, and that
 * view belongs to another unit. This file introduces a parallel `lgn-` shell
 * instead of mutating the shared one.
 *
 * Everything colour-bearing resolves through app.css tokens. The brand panel is
 * the one exception and is intentional: it is a navy surface in BOTH themes, so
 * the ink on it is a fixed #fff family rather than a token that would flip to
 * dark text on a dark panel.
 */

/* ══ shell ══════════════════════════════════════════════════════════════════
   Two panels on one grid. Column order follows the document direction, so the
   brand panel lands on the inline start in RTL (right) and LTR (left) without
   a mirrored rule. Below 1000px the grid collapses to rows and the brand panel
   becomes a compact header strip — same DOM, no duplicated mark. */
.lgn__shell {
  flex: 1;
  display: grid;
  grid-template-columns: minmax(0, 1.02fr) minmax(0, 1fr);
  min-height: 100vh;
}

/* ══ brand panel ════════════════════════════════════════════════════════════ */
.lgn__brand {
  position: relative;
  overflow: hidden;
  display: flex;
  align-items: flex-end;
  padding: clamp(32px, 5vw, 64px);
  background: linear-gradient(158deg, var(--navy) 0%, var(--deep) 100%);
  color: #fff;
  isolation: isolate;
}

/* The thin orange accent, hairline-wide, running the full seam between the two
   panels. Logical inset so it stays on the seam in both directions. */
.lgn__brand::after {
  content: '';
  position: absolute;
  inset-block: 0;
  inset-inline-end: 0;
  width: 3px;
  background: var(--orange);
}

/* The circuit mark as a watermark: oversized, low opacity, bled off the block
   start and inline end so it reads as texture rather than as a second logo. */
.lgn__brand .lgn__mark {
  position: absolute;
  inset-block-start: -12%;
  inset-inline-end: -18%;
  width: 88%;
  color: #fff;
  opacity: .07;
  pointer-events: none;
  animation: lgnDrift 20s ease-in-out infinite;
}

.lgn__brand .lgn__mark svg { width: 100%; height: auto; }

/* Opacity only — a translating watermark this large repaints a full-viewport
   layer on every frame, which is measurable on low-end phones. */
@keyframes lgnDrift {
  0%, 100% { opacity: .05; }
  50% { opacity: .1; }
}

.lgn__brand-in { position: relative; z-index: 1; width: 100%; min-width: 0; }

/* Wraps rather than overflows: "ANUPET" is a single unbreakable token in a
   display face, so at the narrow end of the panel the ACADEMY sub-lockup has
   to drop to its own line instead of pushing the lockup out of the column —
   which, in an RTL document, pushes it off-screen entirely rather than into a
   scrollbar. */
/* `direction: ltr` on the FLEX CONTAINER, not just on the text: the two
   halves are separate flex items, so what reversed them is the main axis
   (rtl + `row` runs right-to-left and paints the first child rightmost),
   which no `unicode-bidi` reset can reach. A Latin wordmark reads
   left-to-right whatever the document does — under Arabic this box was
   printing the academy's own name as «ACADEMY ANUPET» on its own front
   door: the sign-in, forgot/reset, 2FA and certificate-verification pages
   alike.

   The container's own PLACEMENT must not move with it: with `direction:
   ltr` the items pack at the left, which would strand the lockup on the far
   side of an RTL panel. `justify-content: flex-end` puts the group back
   against the panel's inline-end, and it holds when `flex-wrap` drops
   ACADEMY to its own line at the narrow end. */
.lgn__word { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 10px; line-height: 1; direction: ltr; }
[dir="rtl"] .lgn__word { justify-content: flex-end; }
.lgn__word-a {
  font-family: var(--ff-x);
  font-size: clamp(1.9rem, 3.4vw, 2.6rem);
  letter-spacing: .04em;
}
.lgn__word-b {
  font-family: var(--ff-b);
  font-size: clamp(.72rem, 1.2vw, .9rem);
  font-weight: 600;
  letter-spacing: .34em;
  opacity: .72;
}

.lgn__rule {
  display: block;
  width: 58px;
  height: 3px;
  border-radius: 999px;
  background: var(--orange);
  margin-block: 22px 18px;
}

.lgn__motto {
  font-family: var(--ff-a);
  font-size: clamp(1.05rem, 1.6vw, 1.35rem);
  font-weight: 600;
  line-height: 1.55;
  color: rgba(255, 255, 255, .88);
  max-width: 26ch;
  overflow-wrap: anywhere;
}

/* ══ form panel ═════════════════════════════════════════════════════════════
   Centred, but with `start`-aligned overflow: a tall form (six OTP boxes plus
   an expanded recovery-code disclosure, or a stack of validation errors) must
   push the panel taller and scroll normally instead of being clipped at both
   ends the way `place-items:center` clips overflowing grid children. */
.lgn__panel {
  display: grid;
  justify-items: center;
  align-content: center;
  /* `safe` degrades to start-alignment the moment the form is taller than the
     panel — plain `center` would overflow equally in both directions and put
     the heading above the top of a short desktop window, out of reach of the
     scrollbar. Declared after the plain value so a browser that does not
     understand the keyword keeps the centred fallback. */
  align-content: safe center;
  background: var(--bg);
  padding: clamp(28px, 5vw, 56px) clamp(20px, 4vw, 48px);
}

.lgn__form { width: min(400px, 100%); min-width: 0; }

.lgn__title {
  font-size: clamp(1.55rem, 2.6vw, 2rem);
  letter-spacing: -.02em;
  color: var(--text-strong);
}

.lgn__sub {
  color: var(--text-muted);
  font-size: .95rem;
  line-height: 1.65;
  margin-block: 8px 28px;
  /* A trainee code or an email echoed into the subtitle can be longer than the
     column; break it rather than widening the panel. */
  overflow-wrap: anywhere;
}

/* ══ fields ═════════════════════════════════════════════════════════════════
   48px box, --r-md corners, token border, and a visible focus ring on top of
   the brand inset so focus is legible against both themes' field fill. */
.lgn .f { gap: 16px; }

.lgn .f label {
  font-size: 13px;
  font-weight: 600;
  color: var(--text-muted);
  margin-block-end: 7px;
}

.lgn .f input[type="text"],
.lgn .f input[type="email"],
.lgn .f input[type="password"] {
  min-height: 48px;
  padding: 12px 16px;
  border-radius: var(--r-md);
  background: var(--surface-1);
  box-shadow: inset 0 0 0 1px var(--border);
  transition: box-shadow .22s var(--ease);
}

.lgn .f input[type="text"]:hover,
.lgn .f input[type="email"]:hover,
.lgn .f input[type="password"]:hover {
  box-shadow: inset 0 0 0 1px var(--border-strong);
}

.lgn .f input:focus,
.lgn .otp input:focus {
  box-shadow: inset 0 0 0 2px var(--brand), var(--focus-ring);
}

/* Chrome paints its own autofill fill colour over `background`, which reverts
   the field to a white box on the dark theme. `-webkit-text-fill-color` plus a
   very long inset shadow is the only lever available to a plain stylesheet. */
.lgn .f input:-webkit-autofill {
  -webkit-text-fill-color: var(--ink);
  box-shadow: inset 0 0 0 1px var(--border), inset 0 0 0 100px var(--surface-1);
}

/* ══ remember-me ════════════════════════════════════════════════════════════
   The raw `accent-color` checkbox was called out in the visual QA sweep (P6)
   as the one control on this screen still opted out of the design system. The
   tick is a background data URI rather than a pseudo-element: pseudo-element
   support on `input` is inconsistent, a background image is not. */
.lgn__remember {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: .92rem;
  color: var(--text-muted);
  cursor: pointer;
  user-select: none;
  margin-block-start: 2px;
}

.lgn__remember input[type="checkbox"] {
  appearance: none;
  -webkit-appearance: none;
  flex: none;
  width: 20px;
  height: 20px;
  border-radius: 6px;
  background: var(--surface-1);
  box-shadow: inset 0 0 0 1px var(--border-strong);
  cursor: pointer;
  transition: background .18s var(--ease), box-shadow .18s var(--ease);
}

.lgn__remember input[type="checkbox"]:checked {
  background: var(--brand) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23ffffff' stroke-width='3.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m5 13 4 4 10-10'/%3E%3C/svg%3E") center / 13px 13px no-repeat;
  box-shadow: inset 0 0 0 1px var(--brand);
}

.lgn__remember input[type="checkbox"]:focus-visible { outline: none; box-shadow: var(--focus-ring); }

/* ══ primary action ═════════════════════════════════════════════════════════ */
.lgn__submit {
  min-height: 50px;
  margin-block-start: 6px;
  box-shadow: 0 10px 24px -12px var(--navy);
}

.lgn__submit:hover {
  box-shadow: 0 14px 30px -10px color-mix(in srgb, var(--brand) 65%, transparent);
}

.lgn__submit:active { transform: translateY(1px); }
.lgn__submit:focus-visible { outline: none; box-shadow: var(--focus-ring); }

/* ══ secondary links ════════════════════════════════════════════════════════
   A bordered footer rail rather than app.css's stack of three centred blocks —
   the three destinations (forgot password, back to the site, verify a
   certificate) are peers, so they read as one row that wraps on narrow
   screens instead of a vertical list that looked like a ranking. */
.lgn__links {
  display: flex;
  flex-wrap: wrap;
  gap: 10px 20px;
  margin-block-start: 28px;
  padding-block-start: 20px;
  border-block-start: 1px solid var(--border);
  font-size: .89rem;
}

.lgn__link {
  color: var(--text-muted);
  border-radius: var(--r-sm);
  transition: color .2s var(--ease);
}

.lgn__link:hover { color: var(--brand); }
.lgn__link:focus-visible { outline: none; box-shadow: var(--focus-ring); }

/* The companion toggle rides in that same rail as one more peer, and it is a
   <button> rather than an <a> because it changes state on the page the reader
   is already on — navigating nowhere is precisely what an anchor is wrong for.
   The cost of that choice is the UA's own button chrome, which would otherwise
   land a grey filled box with an outset border and an arrow cursor in a row of
   plain text links; the four declarations below are exactly that chrome and
   nothing more. Everything else is already handled elsewhere and is not
   repeated here: app.css gives every button `font:inherit` and `color:inherit`
   (so the rail's .89rem and the .lgn__link colour reach it), and app.css's
   universal reset zeroes its padding and margin. Colour, hover and focus ring
   come from .lgn__link itself, which this button also wears — that is the
   whole point of the pairing. */
.lgn__link--toggle {
  -webkit-appearance: none;appearance: none;
  background: none;
  border: 0;
  cursor: pointer;
}

/* ══ 2FA specifics ══════════════════════════════════════════════════════════
   The OTP row inherits its mechanics (LTR direction, shake, auto-advance
   hooks) from lms-auth.css. Only the box geometry is refined here so the code
   entry matches the new 48px field, and it is sized fluidly so six boxes plus
   their gaps always fit the panel — including at 375px, where a scrolling
   code row would be worse than a smaller one. */
.lgn .otp { gap: clamp(6px, 2vw, 10px); }

.lgn .otp input {
  width: clamp(34px, 11.5vw, 52px);
  height: 56px;
  border-radius: var(--r-md);
  background: var(--surface-1);
  box-shadow: inset 0 0 0 1px var(--border);
}

/* The recovery-code escape hatch: a real disclosure control, not a bare
   `<summary>` with an inline colour. */
.lgn__recovery { margin-block-start: 22px; }

.lgn__recovery summary {
  cursor: pointer;
  font-size: .89rem;
  color: var(--text-muted);
  list-style: none;
}

.lgn__recovery summary::-webkit-details-marker { display: none; }
.lgn__recovery summary:hover { color: var(--brand); }
.lgn__recovery summary:focus-visible { outline: none; box-shadow: var(--focus-ring); border-radius: var(--r-sm); }
.lgn__recovery .f { margin-block-start: 14px; }

/* ══ entry motion ═══════════════════════════════════════════════════════════
   Each block of the form rises and fades in, staggered, so the eye lands on
   the heading first and the button last. Capped at six steps: past that the
   last element would appear late enough to feel like a loading delay. */
@keyframes lgnRise {
  from { opacity: 0; transform: translateY(14px); }
  to { opacity: 1; transform: none; }
}

.lgn__form > * { animation: lgnRise .5s var(--ease) both; }
.lgn__form > *:nth-child(1) { animation-delay: .04s; }
.lgn__form > *:nth-child(2) { animation-delay: .1s; }
.lgn__form > *:nth-child(3) { animation-delay: .16s; }
.lgn__form > *:nth-child(4) { animation-delay: .22s; }
.lgn__form > *:nth-child(5) { animation-delay: .28s; }
.lgn__form > *:nth-child(n+6) { animation-delay: .32s; }

/* ══ compact layout (< 1000px) ══════════════════════════════════════════════
   The brand panel stops being a panel: it becomes a header strip with the mark
   at real size beside the wordmark, and the motto is dropped rather than
   squeezed — it is atmosphere, and atmosphere is the first thing to go when
   the visitor is holding a phone in a queue. */
@media (max-width: 999px) {
  /* `auto 1fr`, not two implicit auto rows: the shell is at least 100dvh tall,
     and auto rows share that free space between them — which inflated the
     header strip to a quarter of a phone screen before the form even started. */
  .lgn__shell {
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: auto 1fr;
    min-height: 100dvh;
  }

  .lgn__brand {
    align-items: center;
    gap: 14px;
    padding: 18px clamp(20px, 5vw, 40px);
  }

  .lgn__brand::after { inset-block: auto 0; inset-inline: 0; width: auto; height: 3px; }

  .lgn__brand .lgn__mark {
    position: static;
    width: 34px;
    flex: none;
    opacity: .95;
    animation: none;
  }

  .lgn__brand-in { max-width: none; }
  .lgn__rule, .lgn__motto { display: none; }
  .lgn__word-a { font-size: 1.35rem; }
  .lgn__word-b { font-size: .68rem; }
  .lgn__panel { align-content: start; padding-block: clamp(28px, 8vw, 48px); }
}

/* Six code boxes plus five gaps must clear the panel's own padding on the
   narrowest phone in the QA matrix (375px) without the row scrolling. */
@media (max-width: 420px) {
  .lgn .otp input { height: 50px; font-size: 1.2rem; }
}

/* ══ reduced motion ═════════════════════════════════════════════════════════ */
@media (prefers-reduced-motion: reduce) {
  .lgn__brand .lgn__mark { animation: none; opacity: .07; }
  .lgn__form > * { animation: none; opacity: 1; transform: none; }
  .lgn__submit:active { transform: none; }
}
