/* The account area: sign-in and the signed-in page.
 *
 * Loads after `tokens.css` and `base.css` and composes them. Nothing here
 * redefines a shell class — `.btn-primary`, `.btn-quiet`, `.eyebrow`, `.stack`
 * and the focus ring are used as they are found, and every new class is
 * prefixed `auth-`/`acct-` or namespaced under one, so a later change to the
 * shell lands here for free.
 *
 * Two things the token file does not carry, both reported rather than fixed:
 *
 * 1. **No danger colour.** The system has one accent and it means state, and
 *    green is the wrong thing to say when a field is wrong. So errors are said
 *    in full-weight ink, a doubled border and a glyph — three signals, none of
 *    them colour, which is what WCAG 1.4.1 asks for anyway. If a red is ever
 *    added to `tokens.css`, the three rules that would use it are marked below.
 * 2. **No width between `--measure` (62ch) and `--page-narrow` (780px).** A
 *    sign-in card is neither. `--auth-col` below is that missing step, declared
 *    once so there is one number rather than four.
 */

/* ================================================================== *
 * 1. The sign-in page
 * ================================================================== */

.auth {
  /* Less air above than a marketing section: the card is the whole page and a
   * visitor who arrived to type should not have to scroll to find the field. */
  padding-block: clamp(var(--s-2xl), 8vw, var(--s-4xl))
    clamp(var(--s-3xl), 10vw, var(--s-5xl));
}

.auth__col {
  /* The missing token. 27rem is the width at which the two labels, the reveal
   * button and "Sign in with Apple" all sit on one line at the largest step of
   * the type scale without a hyphen. */
  --auth-col: 27rem;
  width: 100%;
  max-width: var(--auth-col);
  margin-inline: auto;
  display: grid;
  gap: var(--s-xl);
}

/* Centred column, left-aligned contents. Centring the type as well is what
 * makes every sign-in page look like the same sign-in page. */
.auth__head {
  --gap: var(--s-s);
}

.auth__head .h1 {
  /* One step down from the marketing headline. This is a room, not a pitch. */
  font-size: var(--step-3);
}

.auth__head p {
  color: var(--ink-body);
  max-width: 34ch;
}

/* ---- The card ---- */

.auth__card {
  display: grid;
  gap: var(--s-l);
  padding: clamp(var(--s-l), 5vw, var(--s-xl));
  background-color: var(--paper-raised);
  border: 1px solid var(--paper-edge);
  border-radius: var(--radius-l);
  box-shadow: var(--lift-1);
}

/* The footnote under the card. A hairline on the leading edge instead of a
 * tinted box: this is an aside in a column of text, not a callout. */
.auth__aside {
  border-inline-start: 1px solid var(--paper-edge);
  padding-inline-start: var(--s-m);
  font-size: var(--step--1);
  line-height: 1.55;
  color: var(--ink-quiet);
  max-width: 40ch;
}

.auth__aside > * + * {
  margin-top: var(--s-xs);
}

.auth__links {
  --gap: var(--s-xs);
  font-size: var(--step--1);
  justify-items: start;
}

.auth__links a {
  color: var(--ink);
  text-decoration: underline;
  text-decoration-color: var(--ink-faint);
  transition: text-decoration-color var(--t-fast) var(--ease);
}

.auth__links a:hover {
  text-decoration-color: var(--ink);
}

/* ================================================================== *
 * 2. Fields
 *
 * Visible labels, always. A placeholder used as a label disappears the moment
 * someone types, takes the field's accessible name with it, and leaves anyone
 * who was interrupted mid-form with two unlabelled boxes.
 * ================================================================== */

.field {
  display: grid;
  gap: var(--s-2xs);
}

.field__row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s-s);
}

.field__label {
  font-size: var(--step--1);
  font-weight: 600;
  letter-spacing: -0.005em;
  color: var(--ink);
}

.field__hint {
  font-size: var(--step--1);
  line-height: 1.45;
  color: var(--ink-quiet);
}

.field__link {
  font-size: var(--step--1);
  color: var(--ink-quiet);
  text-decoration: underline;
  text-decoration-color: var(--paper-edge);
  transition:
    color var(--t-fast) var(--ease),
    text-decoration-color var(--t-fast) var(--ease);
}

.field__link:hover {
  color: var(--ink);
  text-decoration-color: var(--ink-faint);
}

.field__shell {
  position: relative;
}

.field__input {
  width: 100%;
  min-height: 44px;
  padding: var(--s-s) var(--s-m);
  margin-top: var(--s-2xs);
  background-color: var(--paper-sunk);
  border: 1px solid var(--paper-edge);
  border-radius: var(--radius-m);
  color: var(--ink);
  /* --step-0 floors at 1rem. Anything below 16px makes iOS Safari zoom the
   * viewport on focus and then leave it zoomed. */
  font-size: var(--step-0);
  line-height: 1.4;
  transition:
    border-color var(--t-fast) var(--ease),
    box-shadow var(--t-fast) var(--ease);
}

.field__input::placeholder {
  color: var(--ink-faint);
}

.field__input:hover {
  border-color: var(--ink-faint);
}

/* The wrong state, said three ways so that none of them has to be colour. The
 * second pixel of border is an inset shadow rather than a wider border,
 * because growing the border by 1px moves the text inside it. */
.field__input[aria-invalid="true"] {
  border-color: var(--ink);
  box-shadow: inset 0 0 0 1px var(--ink); /* ← a danger token would go here */
}

.field__note {
  display: flex;
  align-items: flex-start;
  gap: var(--s-2xs);
  margin-top: var(--s-2xs);
  font-size: var(--step--1);
  line-height: 1.45;
  /* Full-weight ink, not a quiet grey: this is the one line in the card the
   * visitor has to read. */
  color: var(--ink); /* ← and here */
}

.field__note svg {
  flex: none;
  /* Optically centred on the first line of the message rather than the top of
   * the box, which is where a flex-start icon otherwise sits. */
  margin-top: 0.15em;
}

/* ---- The reveal ---- */

.field__reveal {
  position: absolute;
  inset-inline-end: var(--s-2xs);
  top: 50%;
  transform: translateY(-50%);
  min-height: 36px;
  padding-inline: var(--s-s);
  border-radius: var(--radius-s);
  font-size: var(--step--1);
  font-weight: 600;
  color: var(--ink-quiet);
  transition: color var(--t-fast) var(--ease);
}

.field__reveal:hover {
  color: var(--ink);
}

/* Clearance for the button, measured from "Password" being the longer of the
 * two labels it can carry. Applied only where scripting exists, so a page
 * without JavaScript gets the full width of the field back rather than an
 * indent for a button that is not there. */
@media (scripting: enabled) {
  .field__shell .field__input {
    padding-inline-end: 4.75rem;
  }
}

@media (scripting: none) {
  .field__reveal {
    display: none;
  }
}

/* ================================================================== *
 * 3. The form-level alert
 * ================================================================== */

.auth__alert {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: var(--s-xs);
  padding: var(--s-s) var(--s-m);
  background-color: var(--paper-sunk);
  border: 1px solid var(--ink-faint);
  border-radius: var(--radius-m);
  font-size: var(--step--1);
  line-height: 1.5;
  color: var(--ink); /* ← and here */
}

.auth__alert svg {
  margin-top: 0.15em;
}

/* ================================================================== *
 * 4. Actions
 * ================================================================== */

.auth__submit,
.auth__apple {
  width: 100%;
}

/* `aria-disabled`, never the `disabled` attribute. A button that disables
 * itself on click drops focus to the body, and the person who pressed Return
 * loses their place in the form at the exact moment they are being told to
 * wait. The submit handler guards on the same flag. */
.auth__submit[aria-disabled="true"],
.auth__apple[aria-disabled="true"] {
  cursor: default;
}

.auth__apple[aria-disabled="true"] {
  color: var(--ink-quiet);
}

.auth__apple[aria-disabled="true"]:hover {
  border-color: var(--paper-edge);
  background-color: transparent;
}

.auth__apple svg {
  flex: none;
  /* The mark's optical centre sits low in its box. */
  margin-top: -0.1em;
}

.auth__or {
  display: flex;
  align-items: center;
  gap: var(--s-s);
  /* --ink-faint is 2.9:1 and this is text, not a rule. */
  color: var(--ink-quiet);
  font-size: var(--step--1);
}

.auth__or::before,
.auth__or::after {
  content: "";
  flex: 1;
  height: 1px;
  background-color: var(--paper-edge);
}

/* ---- The waiting state ---- */

.spinner {
  width: 1em;
  height: 1em;
  border: 2px solid currentColor;
  border-top-color: transparent;
  border-radius: 50%;
  animation: spin 620ms linear infinite;
}

@keyframes spin {
  to {
    transform: rotate(1turn);
  }
}

/* ================================================================== *
 * 5. The account page
 * ================================================================== */

.acct {
  padding-block: clamp(var(--s-2xl), 7vw, var(--s-3xl))
    clamp(var(--s-3xl), 10vw, var(--s-5xl));
}

.acct__col {
  max-width: var(--page-narrow);
  margin-inline: auto;
}

.acct__head {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--s-l);
}

.acct__head .stack {
  /* Wraps the sign-out onto its own line only once the heading column is down
   * to about eighteen characters, which is around 480px. */
  flex: 1 1 18rem;
  --gap: var(--s-xs);
}

.acct__who {
  font-size: var(--step--1);
  color: var(--ink-quiet);
}

.acct__who strong {
  color: var(--ink-body);
  font-weight: 600;
}

/* One idea per block, hairline between. Not cards: a card implies the blocks
 * are interchangeable, and these are in the order someone reads them. */
.acct__block {
  margin-top: clamp(var(--s-2xl), 6vw, var(--s-3xl));
  padding-top: clamp(var(--s-l), 4vw, var(--s-2xl));
  border-top: 1px solid var(--paper-edge);
}

.acct__block > * + * {
  margin-top: var(--s-m);
}

.acct__block h2 {
  font-size: var(--step-2);
  line-height: 1.15;
  letter-spacing: -0.02em;
  font-weight: 600;
  color: var(--ink);
}

.acct__note {
  font-size: var(--step--1);
  line-height: 1.55;
  color: var(--ink-quiet);
  max-width: var(--measure);
}

/* A value the template fills. Set apart so an unfilled slot reads as a slot
 * and not as a typo. */
.tpl {
  font-family: var(--mono);
  font-size: 0.92em;
  color: var(--ink-quiet);
}

/* ---- The licence key ---- */

.acct-key {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-m);
  padding: clamp(var(--s-m), 4vw, var(--s-l));
  background-color: var(--paper-sunk);
  border-radius: var(--radius-l);
}

.acct-key code {
  font-family: var(--mono);
  font-size: var(--step-1);
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.02em;
  color: var(--ink);
  /* One click takes the whole key, which is also the fallback when the
   * clipboard API is unavailable and the button can only offer ⌘C. */
  user-select: all;
  /* 24 characters of monospace at --step-1 is 254px, which clears a 320px
   * viewport by 2px. This is the guard for the day the format gets longer. */
  overflow-wrap: anywhere;
}

.acct-key__copy [data-copy-label] {
  display: inline-block;
  /* "Copy" and "Copied" are different widths and the button sits at the end of
   * a flex row, so without this the whole row twitches on click. */
  min-width: 6.5ch;
  text-align: center;
}

.acct-key__copy[data-state="done"] {
  color: var(--accent);
  border-color: var(--accent-quiet);
}

/* ---- The facts ---- */

.facts {
  border-top: 1px solid var(--paper-edge);
}

.facts__row {
  display: grid;
  gap: var(--s-2xs) var(--s-l);
  padding-block: var(--s-s);
  border-bottom: 1px solid var(--paper-edge);
}

.facts dt {
  font-size: var(--step--1);
  color: var(--ink-quiet);
}

.facts dd {
  margin: 0;
  color: var(--ink);
  font-weight: 600;
}

.facts__detail {
  margin-top: var(--s-2xs);
  font-size: var(--step--1);
  line-height: 1.5;
  font-weight: 400;
  color: var(--ink-quiet);
  max-width: 52ch;
}

/* The label column arrives only when there is room for it to be a column
 * rather than a squeeze. Below this the rows stack, which is what a phone
 * wants anyway. */
@media (min-width: 560px) {
  .facts__row {
    grid-template-columns: minmax(9rem, 15rem) 1fr;
    align-items: baseline;
  }
}

/* ---- Downloads ---- */

.dl-list {
  border-top: 1px solid var(--paper-edge);
}

.dl-list li {
  display: grid;
  gap: var(--s-3xs) var(--s-l);
  padding-block: var(--s-s);
  border-bottom: 1px solid var(--paper-edge);
  font-size: var(--step--1);
  color: var(--ink-quiet);
}

.dl-list b {
  font-family: var(--mono);
  font-size: 0.94em;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  color: var(--ink);
}

.dl-list time {
  color: var(--ink-body);
}

@media (min-width: 560px) {
  .dl-list li {
    grid-template-columns: 6rem 11rem 1fr;
    align-items: baseline;
  }
}

/* ================================================================== *
 * 6. Reduced motion
 *
 * `base.css` already clamps every duration and forces `animation-iteration-
 * count: 1`, which stops the spinner dead on whichever frame it reached — a
 * ring with a gap in it, which reads as a broken glyph rather than as waiting.
 * So the spinner is removed entirely and the label carries the state alone.
 * ================================================================== */

@media (prefers-reduced-motion: reduce) {
  .spinner {
    display: none;
  }
}
