/* ============================================================== sign in
   Glass card on near-black, the hero photograph bleeding in from the top
   right, angular green shards, a green-gradient call to action.

   Two things are held to deliberately, because this is the front door to a
   safety system and not a marketing page:
     - contrast stays high. Supporting copy never goes below #9aa9a1 on
       near-black, and nothing that matters is carried by a hairline alone.
     - every control is at least 48px tall. It gets used in gloves.
   ---------------------------------------------------------------------- */

.auth {
  --au-green: #2fe36a;
  --au-green-hi: #6bffa0;
  --au-green-lo: #12924a;
  --au-ink: #ffffff;
  --au-dim: #9aa9a1;
  --au-card: rgba(16, 24, 20, 0.72);
  --au-line: rgba(255, 255, 255, 0.10);
  --au-field: rgba(255, 255, 255, 0.045);

  position: relative;
  min-height: 100dvh;
  padding: 0 16px 40px;
  /* the status bar and the gesture bar are ours to keep clear of */
  padding-top: var(--sa-top);
  padding-bottom: calc(40px + var(--sa-bottom));
  padding-left: calc(16px + var(--sa-left));
  padding-right: calc(16px + var(--sa-right));
  overflow: hidden;
  background: #050806;
}

/* ---------- the scene behind the card ---------- */
.auth-scene { position: absolute; inset: var(--sa-top) 0 0 0; pointer-events: none; z-index: 0; }

.auth-photo {
  /* Full bleed across the top. Masking the left edge away left a dead black
     band beside the photograph, which read as a missing image rather than as
     design. It now runs the full width and only fades downward into the page. */
  position: absolute; top: 0; left: 0; right: 0;
  height: clamp(300px, 46vh, 500px);
  background: url("assets/hero-rail.jpg") 72% 44% / cover no-repeat;
  -webkit-mask-image:
    linear-gradient(to bottom, #000 0 52%, rgba(0, 0, 0, .55) 80%, transparent 100%);
  mask-image:
    linear-gradient(to bottom, #000 0 52%, rgba(0, 0, 0, .55) 80%, transparent 100%);
  opacity: .95;
}
/* a green wash, so the orange hi-vis sits inside the brand rather than fighting it */
.auth-scene::after {
  content: ""; position: absolute; inset: 0;
  background:
    /* just enough weight on the left for the wordmark to read against the
       sunset — a gradient over the photograph, not a black panel beside it */
    linear-gradient(96deg, rgba(5, 8, 6, .74) 0%, rgba(5, 8, 6, .34) 38%, rgba(5, 8, 6, 0) 68%),
    radial-gradient(120% 70% at 78% 0%, rgba(20, 90, 50, .26), transparent 60%),
    linear-gradient(180deg, rgba(5, 8, 6, .06) 0%, rgba(5, 8, 6, .70) 48%, #050806 78%);
}

/* Edge light, not shapes. The earlier clip-path slivers left a hard diagonal
   edge that read as a stray grey-green rectangle against the dark background —
   a blur cannot rescue a shape with a cut edge, so there is no shape now: just
   soft green falling off the left and bottom-right corners. */
.auth-shard { position: absolute; pointer-events: none; }
.auth-shard-l {
  left: -140px; top: 2%; width: 300px; height: 80%;
  background: radial-gradient(60% 50% at 50% 50%, rgba(47, 227, 106, .16), transparent 70%);
}
.auth-shard-r {
  right: -150px; bottom: -14%; width: 330px; height: 52%;
  background: radial-gradient(60% 50% at 50% 50%, rgba(47, 227, 106, .18), transparent 70%);
}
.auth-glow {
  position: absolute; left: 50%; top: 46%; width: 420px; height: 420px;
  transform: translate(-50%, -50%);
  background: radial-gradient(circle, rgba(47, 227, 106, .13), transparent 62%);
}

/* ---------- brand ---------- */
.auth-brand {
  position: relative; z-index: 2;
  padding: 26px 4px 0; line-height: 1;
}
.auth-brand .wordmark {
  font-size: 32px;
  background: linear-gradient(100deg, var(--au-green) 0%, #d9ffe8 46%, #ffffff 100%);
  -webkit-background-clip: text; background-clip: text; color: transparent;
}
/* Matches the reference mock: the descriptor sits beside the wordmark in
   title case, same as the app's own header lockup, only lifted for the dark
   background. */
.auth-brand .ctx { color: #c9d4cd; }

.auth-brand .sleepers {
  width: 210px; height: 5px; margin-top: 10px;
  background: repeating-linear-gradient(90deg,
    var(--au-green) 0 26px, rgba(255, 255, 255, .14) 26px 31px);
  border-radius: 1px;
}
/* the strapline needs air under the sleeper bar; at 4px the caps were almost
   touching it */
.auth-brand .tag { margin-top: 11px; letter-spacing: 1.7px; }
.auth-brand .tag b { color: #e8efe9; }
.auth-brand .tag span { color: var(--au-green); }

/* ---------- the card ---------- */
.auth-card {
  position: relative; z-index: 2;
  margin: clamp(140px, 24vh, 230px) auto 0;
  max-width: 460px;
  padding: 26px 20px 24px;
  border-radius: 26px;
  background: var(--au-card);
  border: 1px solid var(--au-line);
  backdrop-filter: blur(22px) saturate(118%);
  -webkit-backdrop-filter: blur(22px) saturate(118%);
  box-shadow:
    0 30px 80px rgba(0, 0, 0, .62),
    inset 0 1px 0 rgba(255, 255, 255, .07);
}

.auth-title {
  margin: 0; font-size: 40px; line-height: 1.16; font-weight: 800;
  letter-spacing: -.5px; color: var(--au-ink);
}
.auth-sub { margin: 8px 0 0; color: var(--au-dim); font-size: 15px; line-height: 1.45; }
.auth-rule {
  width: 72px; height: 3px; margin: 14px 0 22px; border-radius: 2px;
  background: linear-gradient(90deg, var(--au-green), rgba(47, 227, 106, 0));
}

/* ---------- fields ---------- */
.auth-field {
  display: flex; align-items: center;
  margin-bottom: 14px; padding-right: 12px;
  min-height: 58px;
  border-radius: 15px;
  background: var(--au-field);
  border: 1px solid var(--au-line);
  transition: border-color .15s, box-shadow .15s, background .15s;
}
.auth-field:focus-within {
  border-color: rgba(47, 227, 106, .55);
  background: rgba(47, 227, 106, .05);
  box-shadow: 0 0 0 4px rgba(47, 227, 106, .11);
}
.auth-ico {
  display: grid; place-items: center;
  width: 54px; height: 34px; flex: 0 0 54px;
  color: var(--au-green);
  border-right: 1px solid var(--au-line);
}
.auth-ico svg { width: 21px; height: 21px; }
.auth-field input {
  flex: 1 1 auto; min-width: 0;
  margin: 0; padding: 16px 14px;
  background: none; border: 0; border-radius: 0;
  color: var(--au-ink); font-size: 16px; font-weight: 500;
}
.auth-field input::placeholder { color: #7f8c85; font-weight: 400; letter-spacing: 0; }
.auth-field input:focus { outline: none; box-shadow: none; }
#pin { letter-spacing: 3px; }

.auth-eye {
  flex: 0 0 auto; display: grid; place-items: center;
  width: 44px; height: 44px; padding: 0;
  background: none; border: 0; cursor: pointer; color: #8a978f;
}
.auth-eye svg { width: 22px; height: 22px; }
.auth-eye:hover { color: var(--au-ink); }
.auth-eye[aria-pressed="true"] { color: var(--au-green); }
.auth-eye[aria-pressed="true"] .auth-eye-slash { display: none; }

/* ---------- submit ---------- */
.auth-submit {
  width: 100%; min-height: 58px; margin-top: 6px;
  display: flex; align-items: center; justify-content: center; gap: 12px;
  border: 0; border-radius: 15px; cursor: pointer;
  font-size: 17px; font-weight: 800; letter-spacing: 1.6px;
  color: #04210f;
  /* Flat green. The glossy gradient and the green halo around it read as a
     web button rather than a control, and the halo bled across the card. */
  background: var(--au-green);
  box-shadow: none;
  transition: transform .12s, background .15s;
}
.auth-submit svg { width: 22px; height: 22px; }
.auth-submit:hover { background: var(--au-green-hi); }
.auth-submit:active { transform: translateY(1px); background: var(--au-green-lo); }
.auth-submit:focus-visible { outline: 3px solid rgba(255, 255, 255, .7); outline-offset: 3px; }

.auth-msg { margin: 14px 0 0; min-height: 20px; font-size: 14px; line-height: 1.45; color: #ff8f86; }

/* ---------- demo accounts ---------- */
.auth-divider { position: relative; margin: 26px 0 16px; text-align: center; }
.auth-divider::before {
  content: ""; position: absolute; left: 0; right: 0; top: 50%; height: 1px;
  background: var(--au-line);
}
.auth-chip {
  position: relative; display: inline-flex; align-items: center; gap: 8px;
  padding: 9px 16px; border-radius: 999px;
  background: rgba(10, 18, 13, .92);
  border: 1px solid rgba(47, 227, 106, .34);
  font-size: 13px; color: var(--au-dim);
}
.auth-chip svg { width: 17px; height: 17px; color: var(--au-green); }
.auth-chip b { color: var(--au-ink); font-weight: 700; }

.auth-users { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.auth-users button {
  display: flex; align-items: center;
  min-height: 62px; padding-right: 12px;
  text-align: left; cursor: pointer;
  border-radius: 14px;
  background: rgba(255, 255, 255, .035);
  border: 1px solid var(--au-line);
  color: var(--au-ink);
  transition: border-color .15s, background .15s, box-shadow .15s;
}
.auth-users button:hover { border-color: rgba(47, 227, 106, .45); background: rgba(47, 227, 106, .07); }
.auth-users button.on {
  border-color: var(--au-green);
  background: rgba(47, 227, 106, .12);
  box-shadow: 0 0 0 3px rgba(47, 227, 106, .14), 0 8px 24px rgba(47, 227, 106, .18);
}
.auth-users .au-badge {
  display: grid; place-items: center;
  width: 46px; height: 32px; flex: 0 0 46px;
  color: var(--au-green);
  border-right: 1px solid var(--au-line);
}
.auth-users .au-badge svg { width: 19px; height: 19px; }
.auth-users .au-who { flex: 1 1 auto; padding: 10px 0 10px 12px; min-width: 0; }
.auth-users .au-name {
  display: block; font-size: 14px; font-weight: 700; line-height: 1.25;
  overflow-wrap: anywhere;
}
.auth-users .au-role {
  display: block; margin-top: 2px; font-size: 11.5px; font-weight: 600;
  letter-spacing: .6px; color: var(--au-dim);
}

.auth-note {
  display: flex; gap: 12px; align-items: flex-start;
  margin-top: 16px; padding: 14px;
  border-radius: 14px;
  background: rgba(255, 255, 255, .03);
  border: 1px solid var(--au-line);
}
.auth-note-ico { flex: 0 0 auto; color: var(--au-green); line-height: 0; margin-top: 1px; }
.auth-note-ico svg { width: 20px; height: 20px; }
.auth-note p { margin: 0; font-size: 12.5px; line-height: 1.55; color: var(--au-dim); }

/* the app's white header bar is replaced by the brand inside this screen */
body.auth-mode header.app { display: none; }

@media (max-width: 400px) {
  /* the lockup runs to the right edge on a phone; pull the wordmark and the
     descriptor in so the brand has air on both sides */
  .auth-brand .wordmark { font-size: 28px; }
  .auth-brand .sleepers { width: 184px; }
  .auth-title { font-size: 34px; }
  .auth-card { padding: 22px 16px 20px; border-radius: 22px; }
  .auth-users { gap: 8px; }
  /* Reclaim width from the badge rather than shrinking the name: a real staff
     name is longer than the demo ones, and type that keeps shrinking to fit is
     a losing game. This leaves ~96px for a name needing ~90px at 12px. */
  .auth-users .au-badge { width: 34px; flex-basis: 34px; }
  .auth-users .au-who { padding-left: 8px; }
  .auth-users .au-name { font-size: 12px; letter-spacing: -0.1px; }
}
/* only collapse to one column where two genuinely cannot fit */
@media (max-width: 318px) {
  .auth-users { grid-template-columns: 1fr; }
}

@media (prefers-reduced-motion: reduce) {
  .auth-submit, .auth-users button, .auth-field { transition: none; }
}

/* ============================================================== entrance
   The sign-in screen assembles rather than appearing. The idea is the line
   being energised: a current runs along the top, the sleeper run lays itself
   left to right under the wordmark, and the card settles in after it.

   Everything is opacity and transform (and one clip-path), so it stays on the
   compositor and costs nothing on a mid-range phone. Nothing here delays
   interaction — the fields are live from the first frame, so an AP who knows
   their PIN can type straight through the animation.
   ---------------------------------------------------------------------- */

@keyframes au-rise {
  from { opacity: 0; transform: translateY(16px); }
  to   { opacity: 1; transform: none; }
}
@keyframes au-fade { from { opacity: 0; } to { opacity: 1; } }

@keyframes au-photo {
  from { opacity: 0; transform: scale(1.07); }
  to   { opacity: .95; transform: none; }
}

/* the sleeper run lays itself out, left to right */
@keyframes au-sleepers {
  from { clip-path: inset(0 100% 0 0); }
  to   { clip-path: inset(0 0 0 0); }
}

@keyframes au-rule { from { width: 0; } to { width: 72px; } }

/* current travelling down the line, once */
@keyframes au-spark {
  0%   { transform: translateX(-130%); opacity: 0; }
  10%  { opacity: 1; }
  82%  { opacity: 1; }
  100% { transform: translateX(130%); opacity: 0; }
}

.auth-spark {
  position: absolute; top: 0; left: 0; z-index: 3;
  width: 46%; height: 2px;
  background: linear-gradient(90deg,
    rgba(47, 227, 106, 0), rgba(47, 227, 106, .25) 35%,
    #9affc2 62%, rgba(47, 227, 106, .25) 80%, rgba(47, 227, 106, 0));
  box-shadow: 0 0 14px rgba(47, 227, 106, .75);
  opacity: 0;
  animation: au-spark 1.25s cubic-bezier(.4, 0, .25, 1) .18s both;
}

.auth-photo   { animation: au-photo 1s cubic-bezier(.2, .7, .2, 1) both; }
.auth-brand .wordmark { animation: au-rise .5s cubic-bezier(.22, 1, .36, 1) .1s both; }
.auth-brand .ctx      { animation: au-fade .45s ease-out .34s both; }
.auth-brand .sleepers { animation: au-sleepers .66s cubic-bezier(.3, .9, .3, 1) .22s both; }
.auth-brand .tag      { animation: au-fade .45s ease-out .46s both; }

/* each of these carries its own --d, set in the markup */
.auth-card,
.auth-title,
.auth-sub,
.auth-field,
.auth-submit,
.pin-rules,
.auth-note,
#demoBox {
  animation: au-rise .58s cubic-bezier(.22, 1, .36, 1) both;
  animation-delay: var(--d, 0s);
}
.auth-rule {
  animation: au-rule .55s cubic-bezier(.22, 1, .36, 1) both;
  animation-delay: var(--d, 0s);
}

/* Motion is decoration here, never information. Switched off, every element
   simply starts in its final state. */
@media (prefers-reduced-motion: reduce) {
  .auth-spark { display: none; }
  .auth-photo, .auth-brand .wordmark, .auth-brand .ctx, .auth-brand .sleepers,
  .auth-brand .tag, .auth-card, .auth-title, .auth-sub, .auth-field,
  .auth-submit, #demoBox, .auth-rule {
    animation: none;
  }
}

/* ================================================= choosing your own PIN
   The screen between the one-time PIN an admin read out and the app itself.
   It is the same surface as signing in because it is the same moment — but
   it has to teach, not just collect: the rules tick off as they are typed,
   so nobody finds out what was wrong by pressing the button.
   ---------------------------------------------------------------------- */

.pin-rules {
  list-style: none;
  margin: 2px 0 18px;
  padding: 14px 15px;
  border-radius: 15px;
  background: rgba(255, 255, 255, .035);
  border: 1px solid var(--au-line);
  display: grid; gap: 9px;
}
.pin-rules li {
  display: flex; align-items: center; gap: 12px;
  font-size: 13.5px; line-height: 1.4; color: #93a899;
  transition: color .15s;
}

/* an empty ring until it is satisfied, then a filled tick */
.pr-mark {
  /* A real tick, as a mask. The old one was two borders of a rotated box
     nudged into place with measured pixels, which is why it sat off-centre,
     and it was drawn in #06240f, which is why it looked black on the green. A
     mask centres itself and takes its colour from the fill behind it. */
  --pr-tick: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M5 12.6l4.7 4.7L19 7' fill='none' stroke='%23000' stroke-width='3.4' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  position: relative; flex: 0 0 auto;
  width: 22px; height: 22px; border-radius: 50%;
  border: 1.5px solid rgba(255, 255, 255, .22);
  background: rgba(255, 255, 255, .03);
  transition: background .16s, border-color .16s, box-shadow .16s;
}
.pr-mark::after {
  content: ""; position: absolute; inset: 0;
  background: #ffffff;
  -webkit-mask: var(--pr-tick) center / 60% 60% no-repeat;
  mask: var(--pr-tick) center / 60% 60% no-repeat;
  transform: scale(.4);
  opacity: 0;
  transition: opacity .15s, transform .18s cubic-bezier(.3, 1.5, .5, 1);
}

.pin-rules li.ok { color: #cfeedb; }
.pin-rules li.ok .pr-mark {
  background: linear-gradient(180deg, #23cf66 0%, #0b8a42 100%);
  border-color: #2fe36a;
  box-shadow: 0 0 0 3px rgba(47, 227, 106, .12);
}
.pin-rules li.ok .pr-mark::after { opacity: 1; transform: scale(1); }

/* only once they have typed enough for the rule to mean something */
.pin-rules li.bad { color: #e8a84a; }
.pin-rules li.bad .pr-mark { border-color: rgba(201, 135, 42, .7); }

/* the submit stays out of reach until every rule is met */
.auth-submit:disabled {
  cursor: not-allowed;
  filter: grayscale(.75) brightness(.62);
  box-shadow: none;
}

.auth-note {
  margin: 14px 0 0;
  font-size: 12px; line-height: 1.55; color: #74867b; text-align: center;
}

@media (prefers-reduced-motion: reduce) {
  .pr-mark, .pr-mark::after { transition: none; }
}
