/* Portal's own sign-in page (pages/signin.js, pages/signin-gate.js): the gate beside the words and the ways in.

   Wide (760px and up): the gate on the left, the column on the right, the pair centred on the page. The gate is the
   doors' own height: its top on the title's cap line, its bottom on the last way's bottom, and it keeps that size
   whatever the step holds, so the title never moves and the column is only as tall as what it holds (the terms and
   Cancel hang under the gate). The page's top is set from the gate's height, not the column's, for the same reason.
   Narrow: one column, the gate a small emblem over the title, everything on the column's one left edge.

   Every control is the one pill: the address, the code, the ways in, a status's one action. The filled pill is the
   press that continues; the quiet lines (a new code, another way, Start again, Cancel) are links in the text. What
   the page has to say is the line under the title, or under the field it is about; never a box. */
.signin {
  --title-size: 44px;
  --title-lh: 48px;
  --cap: calc(var(--title-lh) / 2 - var(--title-size) * .3);  /* the cap line under the line box's top: Funnel Display's ascent 1, descent .25, caps .675 */
  --control-h: 48px;
  --gap: 10px;  /* between pills */
  --or-h: 24px;
  --words-gap: 28px;  /* the title (and its line) to the first control */
  --col-w: 400px;
  --pair-gap: 72px;
  /* the doors: the address and Continue with email, or, Google, GitHub */
  --ways-h: calc(4 * var(--control-h) + 4 * var(--gap) + var(--or-h));
  --gate-h0: calc(var(--title-lh) - var(--cap) + var(--words-gap) + var(--ways-h));
  --gate: var(--gate-h, var(--gate-h0));
  display: grid; grid-template-columns: calc(var(--gate-h0) * .8) var(--col-w); column-gap: var(--pair-gap); justify-content: center; align-items: start;
  /* a little over the middle of what is under the top bar, counting the gate and the foot under it */
  padding-top: max(0px, calc((100vh - var(--topbar-h) - var(--gate-h0) - 72px) * .44 - 32px));
  min-width: 0;
}
@supports (height: 100svh) {
  .signin { padding-top: max(0px, calc((100svh - var(--topbar-h) - var(--gate-h0) - 72px) * .44 - 32px)); }
}
/* a gate taller than the doors' own (a line under the title) is wider too: it grows to the left, so the column, and
   everything in it, stays where it was */
.signin-gate-side { display: flex; justify-content: flex-end; padding-top: var(--cap); min-width: 0; }
.signin-gate {
  display: block; flex: none; width: calc(var(--gate) * .8); height: var(--gate);
  color: var(--ink); font-family: var(--font-mono); user-select: none;
}
.signin-main { min-width: 0; }

/* the words: the title (the step, one line, one tone) and the one line under it */
.signin-title {
  margin: 0; font-family: "Funnel Display", var(--font-sans); font-size: var(--title-size); line-height: var(--title-lh);
  font-weight: 600; letter-spacing: -.02em; color: var(--ink); text-wrap: balance;
}
.signin-title:focus { outline: none; }  /* given the keyboard when a step takes away what had it; never tabbed to */
.signin-lead {
  margin: 10px 0 0; max-width: 400px; color: var(--ink-2); font-size: 15.5px; line-height: 24px; letter-spacing: -.003em;
  text-wrap: balance;
}
.signin-lead:empty { margin: 0; }  /* kept in the tree, so what it says next is announced */
.signin-lead[data-tone="bad"] { color: var(--bad); }
/* an address is one piece: it moves to the next line whole, and breaks inside only when it is longer than a line */
.signin-lead:has(.signin-address) { text-wrap: pretty; }
.signin-address { display: inline-block; max-width: 100%; color: var(--ink); font-weight: 550; }
.signin-address > span { white-space: nowrap; }
.signin-address > .signin-address-long { white-space: normal; overflow-wrap: anywhere; }
.signin-address > .signin-address-tail { color: var(--ink-2); font-weight: 400; }
.signin-lead[data-tone="bad"] .signin-address, .signin-lead[data-tone="bad"] .signin-address-tail { color: inherit; }

/* the controls */
.signin-ways { display: grid; gap: var(--gap); margin-top: var(--words-gap); }
/* Turnstile's place: it takes room only while a person is asked (data-open). Otherwise it is out of the flow (no row,
   no gap in the form's grid) but still rendered, so the check runs, and nothing under the press moves. */
.signin-captcha { margin-top: 12px; }
.signin-email .signin-captcha { margin: 4px 0; }  /* under the press that asked */
.signin-captcha:not([data-open]) { position: absolute; width: 1px; height: 1px; margin: 0; overflow: hidden; clip-path: inset(50%); }
.signin-foot:empty { display: none; }
.signin-way {
  display: flex; align-items: center; justify-content: center; gap: 10px; width: 100%; height: var(--control-h); padding: 0 20px;
  border: 1px solid var(--rule-2); border-radius: var(--radius-cap); background: var(--raised); color: var(--ink);
  font: inherit; font-size: 15px; font-weight: 550; letter-spacing: -.003em; line-height: 1; text-decoration: none;
  cursor: pointer; appearance: none; -webkit-tap-highlight-color: transparent;
  transition: border-color .15s ease-out, background-color .15s ease-out, color .15s ease-out;
}
.signin-way-mark { flex: none; width: 18px; height: 18px; }
.signin-way-words { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* the press that continues: Continue with email, a status's one action */
.signin-way-submit, .signin-way-primary { background: var(--ink); border-color: var(--ink); color: var(--paper); }
.signin-way[disabled] { cursor: default; background: var(--raised); border-color: var(--rule); color: var(--ink-3); }
.signin-way[aria-busy="true"] { cursor: progress; }
/* A press under way, in place (no page in between): the pill keeps its look and says what it is doing, a soft light
   runs along its foot, and the rest of the step goes quiet and waits. */
.signin-way.signin-way-going { position: relative; cursor: progress; }
.signin-way.signin-way-going[disabled] { background: var(--raised); border-color: var(--edge); color: var(--ink); }
.signin-way-submit.signin-way-going[disabled], .signin-way-primary.signin-way-going[disabled] { background: var(--ink); border-color: var(--ink); color: var(--paper); }
.signin-way-going::after {
  content: ""; position: absolute; left: 22%; right: 22%; bottom: 9px; height: 1.5px; border-radius: var(--radius-cap);
  background: linear-gradient(90deg, transparent, currentColor, transparent) no-repeat; background-size: 40% 100%;
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 25%, #000 75%, transparent);
  mask-image: linear-gradient(90deg, transparent, #000 25%, #000 75%, transparent);  /* the light fades at the ends, never cut */
  opacity: .55; animation: signin-going 1.3s linear infinite;
}
@keyframes signin-going { from { background-position: -70% 0; } to { background-position: 170% 0; } }
.signin-way[aria-disabled="true"] { cursor: progress; }
/* the rest of the step, quiet while the press is under way (inert in signin.js: neither pointer nor keyboard) */
.signin-ways[data-pressing] > :not(:has(.signin-way-going)):not(.signin-way-going) { opacity: .4; transition: opacity .2s ease-out; }
.signin-cancel .btn-link[aria-disabled="true"] { color: var(--ink-3); cursor: progress; text-decoration: none; }
.signin-way:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }
.signin-way:active { transition-duration: 40ms; }
@media (hover: hover) {
  .signin-way:not([disabled]):hover { border-color: var(--edge); text-decoration: none; }
  .signin-way-submit:not([disabled]):hover, .signin-way-primary:not([disabled]):hover {
    background: color-mix(in srgb, var(--ink) 84%, var(--paper)); border-color: transparent;
  }
}

/* the address first, then Continue with email, the page's one filled pill */
.signin-email { display: grid; gap: var(--gap); }
.signin .signin-email-field {  /* over the console's input[type=email] rule, which draws a ruled field */
  display: block; width: 100%; height: var(--control-h); margin: 0; padding: 0 20px;
  border: 1px solid var(--edge); border-radius: var(--radius-cap); background: var(--paper); color: var(--ink);
  font: inherit; font-size: 16px; letter-spacing: -.003em; line-height: normal; outline: none; appearance: none; box-shadow: none;
  transition: border-color .15s ease-out, box-shadow .15s ease-out;
}
.signin .signin-email-field::placeholder { color: var(--ink-3); opacity: 1; }
/* (0,3,0) and up, over the console's own field rules: no inset line under a focused or refused field, no grey border
   on hover over the refusing one */
.signin .signin-email-field:focus { border-color: var(--ink); box-shadow: none; }
.signin .signin-email-field[aria-invalid="true"], .signin .signin-email-field[aria-invalid="true"]:hover { border-color: var(--bad); }
@media (hover: hover) { .signin .signin-email-field:hover:not(:focus):not([aria-invalid="true"]) { border-color: var(--ink-3); } }
/* the browser's own fill keeps the page's paper (Chrome paints it pale yellow or blue otherwise) */
.signin .signin-email-field:-webkit-autofill, .signin .signin-email-field:-webkit-autofill:hover {
  -webkit-box-shadow: 0 0 0 40px var(--paper) inset; -webkit-text-fill-color: var(--ink); caret-color: var(--ink);
  transition: background-color 600000s 0s, color 600000s 0s;
}
/* a slip, said under the field it is about, on the column's edge */
.signin-problem { margin: -2px 0 0; color: var(--bad); font-size: 13.5px; line-height: 20px; text-wrap: pretty; }

/* "or", on a hairline */
.signin-or { display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; gap: 14px; height: var(--or-h); color: var(--ink-3); font-size: 12.5px; line-height: 1; }
.signin-or::before, .signin-or::after { content: ""; height: 1px; background: var(--rule); }

/* The code from the email: the address field's pill holding six places, three and three as the email prints the
   code, spread across the field with a short rule between the groups. One real input, invisible, over it takes the
   typing. Each place is a digit over a low line: still to come, the line in the field's edge colour; next, in ink and
   pulsing; filled, the digit risen into place and its line gone quiet. */
.signin-code-field {
  position: relative; height: var(--control-h); border: 1px solid var(--edge); border-radius: var(--radius-cap);
  background: var(--paper); color: var(--ink); cursor: text; -webkit-tap-highlight-color: transparent;
  transition: border-color .15s ease-out, box-shadow .15s ease-out, background-color .26s ease-out, color .26s ease-out;
}
.signin-code-field .signin-code-input {
  position: absolute; inset: 0; z-index: 1; width: 100%; height: 100%; margin: 0; padding: 0; border: 0; border-radius: var(--radius-cap);
  background: transparent; color: transparent; caret-color: transparent; font-size: 16px; opacity: 0; outline: none; appearance: none;
}
.signin-code-shown {
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)) 28px repeat(3, minmax(0, 1fr)); align-items: stretch;
  height: 100%; max-width: 336px; margin: 0 auto; padding: 0 22px;
  font-family: var(--font-mono); font-size: 22px; font-weight: 500; line-height: 1; font-variant-numeric: tabular-nums;
}
.signin-place { position: relative; display: grid; place-items: center; min-width: 0; }
.signin-digit { display: block; padding-bottom: 3px; }
/* the low line under each place */
.signin-place::after {
  content: ""; position: absolute; left: 50%; bottom: 10px; width: 14px; height: 2px; border-radius: var(--radius-cap);
  background: var(--edge); transform: translateX(-50%);
  transition: width .2s cubic-bezier(.2, .8, .2, 1), background-color .2s ease-out, opacity .2s ease-out;
}
.signin-place[data-filled]::after { width: 10px; background: var(--rule-2); }
/* the next place: its line in ink, longer, pulsing while the field has the keyboard */
.signin-code-field:focus-within .signin-place[data-active]::after {
  width: 20px; background: var(--ink); animation: signin-caret 1.1s ease-in-out infinite;
}
@keyframes signin-caret { 50% { opacity: .35; } }
/* the rule between the groups, darker once the first three are in */
.signin-code-space { position: relative; }
.signin-code-space::before {
  content: ""; position: absolute; left: 50%; top: 50%; width: 8px; height: 2px; border-radius: var(--radius-cap);
  background: var(--rule-2); transform: translate(-50%, -50%); transition: background-color .2s ease-out, width .2s ease-out;
}
.signin-code-field:is([data-count="3"], [data-count="4"], [data-count="5"], [data-count="6"]) .signin-code-space::before { width: 10px; background: var(--ink-3); }
/* a digit typed rises into its place; several at once arrive one after another */
.signin-place[data-new] .signin-digit { animation: signin-digit-in .24s cubic-bezier(.2, .8, .2, 1) both; animation-delay: var(--d, 0ms); }
@keyframes signin-digit-in { from { opacity: 0; transform: translateY(8px) scale(.86); } to { opacity: 1; transform: none; } }
.signin-code-field:focus-within { border-color: var(--ink); }
@media (hover: hover) { .signin-code-field:not(:focus-within):not([data-state]):hover { border-color: var(--ink-3); } }
/* under check: ink runs along the six lines, the digits a shade quieter */
.signin-code-field[data-state="checking"] .signin-digit { color: var(--ink-2); transition: color .2s ease-out; }
.signin-code-field:is([data-state="checking"], [data-state="sending"]) .signin-place::after {
  width: 10px; background: var(--rule-2); animation: signin-run 1.05s ease-in-out infinite; animation-delay: calc(var(--i) * 70ms);
}
@keyframes signin-run { 0%, 60%, 100% { width: 10px; background: var(--rule-2); } 25% { width: 20px; background: var(--ink); } }
/* a wrong code: one shake, the refusing colour on the field and its lines until the next digit, the digits dropping
   out from the last; said under the field, the address kept above */
.signin-code-field[data-state="wrong"] { border-color: var(--bad); animation: signin-shake .4s cubic-bezier(.36, .07, .19, .97) both; }
.signin-code-field[data-state="wrong"] .signin-place::after, .signin-code-field[data-state="wrong"] .signin-code-space::before,
.signin-code-field[data-state="wrong"]:focus-within .signin-place[data-active]::after { background: var(--bad); }
.signin-place[data-leaving] .signin-digit { animation: signin-digit-out .26s ease-in both; animation-delay: calc((5 - var(--i)) * 30ms); }
@keyframes signin-digit-out { to { opacity: 0; transform: translateY(-7px) scale(.9); } }
@keyframes signin-shake { 15%, 85% { transform: translateX(-1px); } 30%, 70% { transform: translateX(3px); } 45%, 55% { transform: translateX(-4px); } 50% { transform: translateX(4px); } }
/* the right code: the field fills in ink, the digits in paper, as the page leaves */
.signin-code-field[data-state="right"] { background: var(--ink); border-color: var(--ink); color: var(--paper); box-shadow: none; }
/* the digits turn to paper only once the ink is past halfway, so the code never stands in its own colour */
.signin-code-field[data-state="right"] .signin-digit {
  color: var(--paper); transition: color .1s linear .13s;
  animation: signin-settle .32s cubic-bezier(.2, .8, .2, 1) both; animation-delay: calc(.13s + var(--i) * 30ms);
}
.signin-code-field[data-state="right"] .signin-place::after, .signin-code-field[data-state="right"] .signin-code-space::before { opacity: 0; }
@keyframes signin-settle { 40% { transform: translateY(-3px); } 100% { transform: none; } }
.signin-ways:has(.signin-code-field[data-state="right"]) :is(.signin-code .signin-way, .signin-again) {
  opacity: .3; pointer-events: none; transition: opacity .2s ease-out;
}

/* Entrances, so a step changes without a cut: its parts fade in one after another, a changed title or line fades in.
   Opacity only: nothing measured on the page (the gate's fit) ever sees a part out of its place. */
/* backwards, not both: the entrance holds each part out of sight through its delay, then lets opacity go, so a dim
   or a fade that follows (a press, the right code) transitions instead of cutting */
.signin-ways[data-enter] > *, .signin-terms[data-enter], .signin-foot[data-enter] {
  animation: signin-step-in .32s ease-out backwards; animation-delay: calc(var(--k, 0) * 45ms);
}
.signin-title[data-enter], .signin-lead[data-enter], .signin-way-words[data-enter] { animation: signin-step-in .26s ease-out backwards; }
@keyframes signin-step-in { from { opacity: 0; } }

/* the quiet line under the controls: a new code on the left, another way on the right, so the count moves nothing */
.signin-again { display: flex; flex-wrap: wrap; justify-content: space-between; gap: 20px; margin: 2px 0 0; font-size: 13.5px; line-height: 20px; }
.signin-again .btn-link, .signin-again a, .signin-cancel .btn-link {
  font: inherit; font-weight: 500; color: var(--ink-2); text-decoration: underline; text-decoration-color: var(--ink-4);
  text-underline-offset: 3px; text-decoration-thickness: 1px;
}
.signin-again .btn-link[disabled] { color: var(--ink-3); cursor: default; text-decoration: none; }
/* sized for its longest words ("Send a new code in 60 s"), so the line decides once whether it wraps, not as the
   count shortens */
.signin-again .signin-resend { font-variant-numeric: tabular-nums; min-width: 12.2em; text-align: left; }
@media (hover: hover) {
  .signin-again .btn-link:not([disabled]):hover, .signin-again a:hover, .signin-cancel .btn-link:hover { color: var(--ink); text-decoration-color: var(--ink); }
}

/* on a touch screen the quiet links keep their size of type and take a 40px target past it */
@media (pointer: coarse) {
  .signin-again .btn-link, .signin-again a, .signin-cancel .btn-link, .signin-terms a { position: relative; }
  .signin-again .btn-link::after, .signin-again a::after, .signin-cancel .btn-link::after, .signin-terms a::after {
    content: ""; position: absolute; inset: -10px -4px;
  }
}

@media (pointer: coarse) {
  .signin-terms:not([hidden]) ~ .signin-foot { margin-top: 20px; }  /* a tap under the terms is not Cancel */
}
@media (hover: none) {
  .signin-way:not([disabled]):active { border-color: var(--edge); }
  .signin-way-submit:not([disabled]):active, .signin-way-primary:not([disabled]):active {
    background: color-mix(in srgb, var(--ink) 84%, var(--paper)); border-color: transparent;
  }
}

/* a step under way: a hairline where the controls go, ink travelling along it */
.signin-working { position: relative; height: 2px; margin-top: calc((var(--control-h) - 2px) / 2); overflow: hidden; border-radius: var(--radius-cap); background: var(--rule); }
.signin-working::after {
  content: ""; position: absolute; inset: 0 auto 0 0; width: 28%; border-radius: var(--radius-cap); background: var(--ink);
  animation: signin-travel 1.1s ease-in-out infinite alternate;
}
@keyframes signin-travel { from { transform: translateX(0); } to { transform: translateX(257%); } }

/* the foot: the terms where the next press continues the sign-in, and Cancel */
.signin-terms { margin: 20px 0 0; max-width: 400px; color: var(--ink-3); font-size: 12.5px; line-height: 18px; text-wrap: balance; }
.signin-terms a { color: var(--ink-2); text-decoration-color: var(--ink-4); text-underline-offset: 2px; }
.signin-foot { margin-top: 20px; }
.signin-terms:not([hidden]) ~ .signin-foot { margin-top: 12px; }
.signin-cancel { margin: 0; font-size: 13.5px; line-height: 20px; }

/* A tablet's width: the same pair, a size smaller. */
@media (max-width: 1023px) {
  .signin { --title-size: 40px; --title-lh: 44px; --col-w: 360px; --pair-gap: 56px; }
}
/* Narrow: one column on its one left edge, the gate a small emblem over the title. */
@media (max-width: 759px) {
  .signin {
    --title-size: 32px; --title-lh: 38px; --words-gap: 24px;
    grid-template-columns: minmax(0, 400px); padding-top: clamp(0px, 2.5vh, 24px);
  }
  .signin-gate-side { justify-content: flex-start; padding: 0; margin-bottom: 24px; }
  .signin-gate { width: 80px; height: 100px; }
  .signin-lead { font-size: 15px; line-height: 23px; }
}
@media (max-width: 359px) {
  .signin { --title-size: 30px; --title-lh: 36px; }
}
/* A phone on its side: the first screen is the controls'. The emblem steps aside. */
@media (max-width: 759px) and (max-height: 480px) {
  .signin-gate-side { display: none; }
}
html[data-reduced-motion="true"] .signin-working::after { width: 100%; opacity: .25; }
html[data-reduced-motion="true"] .signin-way-going::after { background-position: 50% 0; opacity: .3; }
@media (prefers-reduced-motion: reduce) {
  .signin-ways[data-enter] > *, .signin-title[data-enter], .signin-lead[data-enter], .signin-terms[data-enter], .signin-foot[data-enter],
  .signin-way-words[data-enter] { animation: none; }
  .signin-way-going::after { animation: none; background-position: 50% 0; opacity: .3; }  /* a still mark, centred */
  .signin-way, .signin .signin-email-field, .signin-code-field { transition: none; }
  .signin-code-field[data-state="wrong"], .signin-code-field[data-state="checking"] .signin-place::after,
  .signin-code-field:focus-within .signin-place[data-active]::after, .signin-place[data-new] .signin-digit,
  .signin-place[data-leaving] .signin-digit, .signin-code-field[data-state="right"] .signin-digit { animation: none; }
  .signin-place::after, .signin-code-space::before { transition: none; }
  .signin-ways:has(.signin-code-field[data-state="right"]) :is(.signin-code .signin-way, .signin-again) { transition: none; }
  .signin-working::after { animation: none; width: 100%; opacity: .25; }
}
/* Forced colours (Windows contrast themes) paint backgrounds as the canvas: the places, the caret, the working line and
   the "or" rules are drawn in system colours instead, and the code field, whose own input is invisible, shows focus. */
@media (forced-colors: active) {
  .signin-place::after, .signin-code-space::before, .signin-working, .signin-or::before, .signin-or::after { forced-color-adjust: none; background: GrayText; }
  .signin-code-field:focus-within .signin-place[data-active]::after, .signin-working::after { forced-color-adjust: none; background: Highlight; }
  .signin-code-field:focus-within { outline: 2px solid Highlight; outline-offset: 2px; }
  .signin-way-going::after { forced-color-adjust: none; background: none; background-color: CanvasText; opacity: .6; }
}
