/* Quantella identity - the whole design system.
 *
 * Hand-written, no framework, no build step.
 *
 * The idea: Quantella issues credentials, so every page here is a document it
 * issues or amends, not a form floating in a box. That gives the layout its parts
 * and they are all load-bearing rather than decorative - a designation and an
 * issuer at the head, an aperture framing whoever is being identified, ruled fields
 * the way a form is ruled, and a validity strip at the foot stating how long the
 * session lasts and who to ask. Remove the card and the page becomes the document.
 *
 * Ground is a cool document stock rather than warm cream, ink is a green-black the
 * way real printing ink is rather than #000, and there is exactly one red on the
 * page: the seal, spent on the mark and on the focused field. Colours exist once as
 * tokens; no component hard-codes one.
 *
 * One webfont, served from this origin. The old rule here was no webfont at all, so
 * that the login page never waits - that reasoning was about a third-party request
 * and a blocking fetch. Same-origin, preloaded, `font-display: swap` and a system
 * stack underneath keeps the intent: first paint never waits for it.
 */

@font-face {
  font-family: "Archivo Variable";
  src: url("/static/fonts/archivo-latin-var.woff2") format("woff2");
  font-weight: 300 800;
  font-stretch: 62% 125%;
  font-style: normal;
  font-display: swap;
  /* Latin only. Danish sits inside Latin-1, so the extended subsets would be
     bytes on the one page where bytes are least welcome. */
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+2000-206F, U+20AC, U+2122, U+2212, U+FEFF, U+FFFD;
}

:root {
  color-scheme: light dark;

  --paper: #eff1ec;
  --paper-inset: #e5e8df;
  --rule: #c6c9bd;
  --rule-fine: #dcdfd4;
  /* The boundary of anything you can type in or press. A field here IS its
     underline, so that line is a control boundary rather than decoration and owes
     3:1 against the paper (WCAG 1.4.11); the decorative rules above do not and stay
     quiet. Measured, not guessed: 3.20:1 light, 3.59:1 dark. */
  --rule-strong: #83887a;
  --ink: #14170f;
  --ink-soft: #5b5f4f;
  --seal: #a8172e;
  --seal-wash: rgba(168, 23, 46, 0.08);

  --danger-line: #a8172e;
  --danger-text: #8a1526;
  --danger-wash: rgba(168, 23, 46, 0.07);

  --ok-line: #2f5d3a;
  --ok-text: #2b5535;
  --ok-wash: rgba(47, 93, 58, 0.08);

  --display: "Archivo Variable", ui-sans-serif, system-ui, -apple-system,
    "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas,
    "DejaVu Sans Mono", monospace;

  --doc-w: 32.5rem;
  --r: 2px;

  --step: 22px;
}

@media (prefers-color-scheme: dark) {
  :root {
    --paper: #13150e;
    --paper-inset: #1c1f16;
    --rule: #3a3e2f;
    --rule-fine: #262a1e;
    --rule-strong: #6a7060;
    --ink: #e9ece0;
    --ink-soft: #979b87;
    --seal: #e2566a;
    --seal-wash: rgba(226, 86, 106, 0.12);

    --danger-line: #e2566a;
    --danger-text: #f0a5b0;
    --danger-wash: rgba(226, 86, 106, 0.12);

    --ok-line: #6f9e78;
    --ok-text: #a8c9ae;
    --ok-wash: rgba(111, 158, 120, 0.12);
  }
}

*,
*::before,
*::after { box-sizing: border-box; }

/* `hidden` has to win. The attribute is honoured by a UA rule, which any author rule
   setting `display` on the same element beats - so `.rule { display: flex }` below
   would reveal the "eller" divider even in a browser that never enabled the passkey
   block it introduces. Progressive enhancement that leaks its off state is worse
   than none, because it advertises a route that is not there. */
[hidden] { display: none !important; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--display);
  font-size: 15.5px;
  line-height: 1.55;
  font-variant-numeric: tabular-nums;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

/* The document ------------------------------------------------------------- */

.doc {
  width: 100%;
  max-width: var(--doc-w);
  min-height: 100dvh;
  margin: 0 auto;
  padding: clamp(26px, 5vh, 54px) 26px clamp(20px, 4vh, 40px);
  display: flex;
  flex-direction: column;
}

/* Forms with two-column rows, and pages that are read rather than filled in,
   need a wider measure than a single column of fields. */
.doc--wide { --doc-w: 41rem; }

/* Centred in what is left between head and strip. A short form otherwise sits at
   the top of a tall window with the strip stranded far below it. */
.sheet {
  flex: 1;
  display: flex;
  flex-direction: column;
  /* `safe` so a page taller than the viewport falls back to the top rather than
     centring and putting its own first line out of reach above the scroll. Older
     engines drop the declaration entirely, which lands on the same safe default. */
  justify-content: safe center;
  padding: clamp(26px, 5vh, 46px) 0;
}

/* Blocks that should keep their own width rather than stretching to the column. */
.aperture { align-self: flex-start; }

/* Head: what this document is, and who issues it. Both halves are facts, which is
   the test a structural device has to pass to earn its place. */
.head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 16px;
  padding-bottom: 11px;
  border-bottom: 1.5px solid var(--ink);
}

.head__type {
  font-family: var(--mono);
  font-size: 10.5px;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: var(--ink-soft);
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  color: var(--ink);
  text-decoration: none;
}

.brand__mark {
  width: 17px;
  height: 17px;
  flex: none;
  /* The one red on the page. */
  color: var(--seal);
}

.brand__name {
  font-size: 13.5px;
  font-weight: 620;
  font-stretch: 108%;
  letter-spacing: 0.005em;
}

/* Foot: the validity strip. Session length is a real term of the credential and was
   previously invisible to the person it applies to. */
.strip {
  display: flex;
  align-items: baseline;
  gap: 10px 20px;
  flex-wrap: wrap;
  padding-top: 12px;
  border-top: 1px solid var(--rule);
  font-family: var(--mono);
  font-size: 10.5px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-soft);
}

.strip__links {
  display: flex;
  gap: 18px;
  margin-left: auto;
}

.strip a {
  color: var(--ink-soft);
  text-decoration: none;
  border-bottom: 1px solid transparent;
}

.strip a:hover { color: var(--ink); border-bottom-color: var(--rule); }

/* The aperture ------------------------------------------------------------- */

/* The signature. A hairline window framing whoever is being identified: the service
   you arrived from on the login page, you on the account page. The caption names
   the role rather than repeating the name, which the heading already carries. */
.aperture {
  display: inline-flex;
  flex-direction: column;
  gap: 9px;
  margin-bottom: 26px;
}

.aperture__frame {
  display: grid;
  place-items: center;
  width: 74px;
  height: 74px;
  border: 1px solid var(--rule-strong);
  border-radius: var(--r);
  background: var(--paper-inset);
}

.aperture__caption {
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: var(--ink-soft);
}

/* The mark inside the aperture: a ring with the tail of a Q. Every measurement
   derives from these three, so a new size is one rule and the tail cannot drift out
   of proportion with the ring. */
.crest {
  --crest-size: 44px;
  --crest-stroke: 1.5px;
  --crest-tail: 11px;

  position: relative;
  display: grid;
  place-items: center;
  width: var(--crest-size);
  height: var(--crest-size);
  border-radius: 50%;
  border: var(--crest-stroke) solid var(--ink);
  font-size: 17px;
  font-weight: 600;
  font-stretch: 104%;
  letter-spacing: -0.01em;
  color: var(--ink);
}

/* Pivot at the ring's centre, rotate to the lower right, then push out along that
   same 45 degree line: the bar meets the stroke and grows outward instead of
   straddling it. Translating after the rotation is what makes the offset radial, so
   it stays on the circumference at any size. */
.crest::after {
  content: "";
  position: absolute;
  left: 50%;
  top: 50%;
  margin-top: calc(var(--crest-stroke) / -2);
  width: var(--crest-tail);
  height: var(--crest-stroke);
  background: var(--ink);
  border-radius: var(--crest-stroke);
  transform-origin: left center;
  transform: rotate(45deg)
             translateX(calc(var(--crest-size) / 2 - var(--crest-stroke)));
}

.crest--sm {
  --crest-size: 34px;
  --crest-stroke: 1.5px;
  --crest-tail: 8px;
  font-size: 13px;
}

/* Type --------------------------------------------------------------------- */

/* Set in a slightly expanded cut. That width is what makes a heading read as the
   designation on a form rather than a heading in an app. */
.title {
  margin: 0 0 8px;
  font-size: clamp(27px, 4.4vw, 33px);
  line-height: 1.1;
  font-weight: 680;
  font-stretch: 112%;
  letter-spacing: -0.022em;
  text-wrap: balance;
}

.title--tight { margin-bottom: 4px; }

.subtitle {
  margin: 0 0 30px;
  max-width: 46ch;
  color: var(--ink-soft);
  font-size: 14.5px;
}

.subtitle strong { color: var(--ink); font-weight: 600; }
.subtitle--spaced { margin-top: 20px; }

/* Section rule. The label sits on the rule the way a section is named on a form. */
.eyebrow {
  margin: 34px 0 16px;
  padding-bottom: 8px;
  border-bottom: 1px solid var(--rule);
  font-family: var(--mono);
  font-size: 10.5px;
  font-weight: 500;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: var(--ink-soft);
}

.help { margin: 24px 0 0; font-size: 13.5px; }
.hint { margin: 8px 0 0; font-size: 12.5px; color: var(--ink-soft); }

a { color: var(--ink); text-decoration-thickness: 1px; text-underline-offset: 3px; }
a:hover { color: var(--seal); }

/* Pages that are read rather than filled in. */
.prose { font-size: 14.5px; line-height: 1.62; color: var(--ink-soft); }
.prose p { margin: 0 0 13px; }
.prose > :last-child { margin-bottom: 0; }
.prose strong { color: var(--ink); font-weight: 600; }
.prose ul { margin: 0 0 13px; padding-left: 17px; }
.prose li { margin-bottom: 7px; }
.prose li:last-child { margin-bottom: 0; }

/* Fields ------------------------------------------------------------------- */

/* A field is a ruled line, not a box. The label is set in mono caps the way a form
   names what belongs on the line. */
.field { display: block; margin-bottom: var(--step); }

.field__label {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 5px;
  font-family: var(--mono);
  font-size: 10.5px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-soft);
}

/* Show/hide, set on the label's own line so it sits above the rule rather than
   floating inside the field and covering what is being typed. */
.reveal {
  padding: 0;
  border: 0;
  background: none;
  font: inherit;
  letter-spacing: inherit;
  text-transform: inherit;
  color: var(--ink-soft);
  cursor: pointer;
  border-bottom: 1px solid var(--rule-strong);
}

.reveal:hover { color: var(--ink); border-bottom-color: var(--ink); }

/* Caps Lock. A hint rather than an alert: nothing has gone wrong yet, and colouring
   it like a failure would make the page look broken while someone is still typing. */
.hint--warn { color: var(--ink); }

.hint--warn::before {
  content: "";
  display: inline-block;
  width: 5px;
  height: 5px;
  margin-right: 7px;
  border-radius: 50%;
  background: var(--seal);
  vertical-align: 2px;
}

input[type="text"],
input[type="email"],
input[type="password"],
input[type="tel"],
input[type="search"],
input[type="date"],
input[type="number"],
input[type="url"],
select,
textarea {
  width: 100%;
  padding: 6px 2px 8px;
  border: 0;
  border-bottom: 1.5px solid var(--rule-strong);
  border-radius: 0;
  background: transparent;
  color: var(--ink);
  font-family: inherit;
  /* 16px is the floor at which iOS stops zooming the page on focus. */
  font-size: 16px;
  line-height: 1.4;
  appearance: none;
  transition: border-color 120ms ease;
}

input::placeholder { color: var(--ink-soft); opacity: 0.65; }

/* Focus is ink, not seal. The seal is the authority mark and the colour of a
   failure; letting it also mean "you are typing here" would make red mean two
   things on a page where one of them is an error. The rule thickens as well as
   darkens, so the signal is not carried by colour alone. */
input:focus,
select:focus,
textarea:focus {
  outline: none;
  border-bottom-color: var(--ink);
  box-shadow: 0 1.5px 0 0 var(--ink);
}

.field:focus-within .field__label { color: var(--ink); }

input[type="date"] { min-height: 41px; }
input[type="date"]::-webkit-calendar-picker-indicator { opacity: 0.5; cursor: pointer; }
input[type="search"]::-webkit-search-decoration,
input[type="search"]::-webkit-search-cancel-button { appearance: none; }

/* Two fields on one line: an address is written that way, so it is entered that way. */
.row { display: flex; gap: 14px; }
.field--grow { flex: 1 1 auto; }
.field--narrow { flex: 0 1 8rem; }

/* A choice on a form, set as a line of the document rather than as a widget. The
   native control is kept and only resized: a hand-built checkbox loses keyboard
   behaviour, the indeterminate state and every assistive technology's idea of what
   it is, in exchange for a square that matches the palette. */
.check {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  margin-top: 4px;
  font-size: 14px;
  color: var(--ink-soft);
  cursor: pointer;
}

.check input {
  flex: none;
  width: 15px;
  height: 15px;
  margin: 2px 0 0;
  accent-color: var(--seal);
  cursor: pointer;
}

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

/* Buttons ------------------------------------------------------------------ */

/* Sized to its words rather than to the column. Full-bleed it becomes the loudest
   thing on the page and competes with the aperture, which is the element meant to
   be remembered. It goes full width on narrow screens, where a thumb needs the
   target more than the composition needs the restraint. */
.btn {
  display: inline-block;
  min-width: 11.5rem;
  margin-top: 30px;
  padding: 12px 26px;
  border: 1.5px solid var(--ink);
  border-radius: var(--r);
  background: var(--ink);
  color: var(--paper);
  font-family: inherit;
  font-size: 15px;
  font-weight: 620;
  font-stretch: 104%;
  letter-spacing: 0.005em;
  text-align: center;
  text-decoration: none;
  cursor: pointer;
  transition: box-shadow 120ms ease, border-color 120ms ease, color 120ms ease;
}

/* The seal registering behind the action, rather than the button changing colour.
   Recolouring it red would make red mean a third thing. */
.btn:hover { box-shadow: 3px 3px 0 0 var(--seal); }

.btn--quiet {
  background: transparent;
  color: var(--ink);
  border-color: var(--rule-strong);
}

.btn--quiet:hover { border-color: var(--ink); box-shadow: 3px 3px 0 0 var(--seal); }

.btn--small {
  width: auto;
  /* Or it inherits the primary button's min-width and a two-word control ends up
     as wide as the thing it sits beside. */
  min-width: 0;
  margin-top: 0;
  padding: 8px 15px;
  font-size: 13px;
}

/* Focus ring. One rule for everything focusable by keyboard, drawn outside the
   element so it never shifts the layout. */
:focus-visible {
  outline: 2px solid var(--seal);
  outline-offset: 3px;
  border-radius: var(--r);
}

/* A stack of destinations. These are entries in a list of things you can do, not
   calls to action, so they are ruled rows like the table of facts above them rather
   than a column of boxes competing with it. */
.stack { display: flex; flex-direction: column; margin-top: 2px; }

.stack .btn,
.stack form { margin: 0; }

.stack .btn {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  min-width: 0;
  padding: 15px 2px;
  border: 0;
  border-bottom: 1px solid var(--rule-fine);
  border-radius: 0;
  background: transparent;
  color: var(--ink);
  font-size: 15px;
  font-weight: 570;
  font-stretch: 100%;
  text-align: left;
  box-shadow: none;
  transition: padding-left 140ms ease, color 140ms ease;
}

/* Drawn from the same two borders as the disclosure marker, so every arrow on the
   page is the same object at a different angle. */
.stack .btn::after {
  content: "";
  width: 6px;
  height: 6px;
  flex: none;
  margin-right: 3px;
  border-top: 1.25px solid var(--rule-strong);
  border-right: 1.25px solid var(--rule-strong);
  transform: rotate(45deg);
  transition: border-color 140ms ease;
}

.stack .btn:hover {
  padding-left: 8px;
  color: var(--seal);
  box-shadow: none;
}

.stack .btn:hover::after { border-color: var(--seal); }

/* Messages ----------------------------------------------------------------- */

.alert,
.notice {
  margin: 0 0 22px;
  padding: 11px 14px;
  border-left: 2px solid;
  border-radius: 0 var(--r) var(--r) 0;
  font-size: 14px;
}

.alert {
  border-left-color: var(--danger-line);
  background: var(--danger-wash);
  color: var(--danger-text);
}

.notice {
  border-left-color: var(--ok-line);
  background: var(--ok-wash);
  color: var(--ok-text);
}

.tag {
  display: inline-block;
  margin-left: 7px;
  padding: 2px 7px;
  border: 1px solid var(--rule);
  border-radius: var(--r);
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-soft);
  vertical-align: 1px;
}

/* Identification block ----------------------------------------------------- */

.identity {
  display: flex;
  align-items: center;
  gap: 16px;
  margin-bottom: 30px;
}

/* The same aperture as the login page, at the size a heading can sit beside. On
   this page the framed subject is you. */
.identity .aperture__frame {
  width: 54px;
  height: 54px;
  flex: none;
}

.identity__email {
  margin: 0;
  color: var(--ink-soft);
  font-size: 14px;
}

/* Recorded facts. A credential states its terms as key and value, so this is a
   ruled table rather than a paragraph. */
.kv { margin: 0; font-size: 14.5px; }

.kv--split {
  display: grid;
  grid-template-columns: minmax(8.5rem, 34%) 1fr;
  gap: 0;
}

.kv--split dt,
.kv--split dd {
  margin: 0;
  padding: 11px 0;
  border-top: 1px solid var(--rule-fine);
}

.kv--split dt {
  font-family: var(--mono);
  font-size: 10.5px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-soft);
  /* Nudged onto the same optical baseline as the value beside it. */
  padding-top: 14px;
}

.kv--split dd { color: var(--ink); }

/* Services ----------------------------------------------------------------- */

.apps { list-style: none; margin: 0; padding: 0; }

.app {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  padding: 16px 0;
  border-bottom: 1px solid var(--rule-fine);
}

.app:first-child { border-top: 1px solid var(--rule-fine); }
.app__head { display: flex; align-items: center; gap: 13px; min-width: 0; }

/* Without this the flex child refuses to shrink, the meta line wraps early and
   pushes the button into two lines. */
.app__text { min-width: 0; }
.app__name { font-weight: 620; font-size: 15px; }

.app__meta {
  margin-top: 1px;
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.04em;
  color: var(--ink-soft);
}

@media (max-width: 460px) {
  /* Stack rather than squeeze: at this width the button and the meta line cannot
     both keep their dignity on one row. */
  .app { flex-direction: column; align-items: stretch; gap: 12px; }
  .app form { align-self: flex-start; }
}

/* Ways in ------------------------------------------------------------------- */

/* Two routes past the same gate. Which one leads is set by a class the script adds
   after it has confirmed the browser can do WebAuthn, so the default - and the
   permanent state of an older browser - is the password form in front. */

.lead { margin-bottom: 26px; }

/* The hero action, and the only full-width button in the system. Everything else is
   sized to its words; this one is the thing the page is asking you to do. */
.btn--hero {
  display: block;
  width: 100%;
  margin-top: 0;
  padding: 16px 20px;
  font-size: 16px;
}

.lead__note {
  margin: 12px 0 0;
  max-width: 42ch;
  font-size: 13px;
  line-height: 1.5;
  color: var(--ink-soft);
}

.lead .alert { margin: 16px 0 0; }

/* The label sits on the rule the way a section is named on a form. */
.rule {
  display: flex;
  align-items: center;
  gap: 14px;
  margin: 30px 0 22px;
  font-family: var(--mono);
  font-size: 10.5px;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: var(--ink-soft);
}

.rule::before,
.rule::after {
  content: "";
  flex: 1;
  height: 1px;
  background: var(--rule);
}

.rule span { flex: none; }

/* Standalone because it governs both routes rather than belonging to the form it
   submits with. */
.check--standalone { margin-top: 22px; }

/* With passkeys available the password submit steps back to an outline. Same width
   as the hero rather than sized to its words: two buttons of different widths at
   different ends of the column read as a mistake, and fill against outline is
   already all the difference the hierarchy needs. */
.signin--keys #password-login .btn {
  display: block;
  width: 100%;
  margin-top: 24px;
  background: transparent;
  color: var(--ink);
  border-color: var(--rule-strong);
}

.signin--keys #password-login .btn:hover {
  border-color: var(--ink);
  box-shadow: 3px 3px 0 0 var(--seal);
}

/* Without passkeys the block above it is never drawn, so the checkbox would sit
   above the fields it appears to belong to. Move it below them.
 *
 * Visual order only; focus still follows the document, so this one optional
 * checkbox is tabbed before the e-mail field in the fallback path. Reordering the
 * markup instead would put it in the wrong place in the common path, which is the
 * one nearly everybody sees. */
.signin { display: flex; flex-direction: column; }
.signin:not(.signin--keys) .check--standalone { order: 1; margin-top: 22px; }

/* Activity log ------------------------------------------------------------- */

/* A register: one ruled line per entry, timestamps in mono so the columns line up
   and a run of attempts within a minute of each other is visible as a shape rather
   than as text to be read. */
.log { list-style: none; margin: 0; padding: 0; }

.log__row {
  display: grid;
  grid-template-columns: 8.5rem 1fr auto;
  gap: 4px 18px;
  align-items: baseline;
  padding: 12px 0;
  border-top: 1px solid var(--rule-fine);
}

.log__row:last-child { border-bottom: 1px solid var(--rule-fine); }

.log__when {
  display: flex;
  gap: 9px;
  font-family: var(--mono);
  font-size: 11.5px;
  letter-spacing: 0.02em;
  color: var(--ink-soft);
}

.log__time { color: var(--ink-soft); opacity: 0.75; }
.log__what { font-size: 14.5px; }

.log__where {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.02em;
  color: var(--ink-soft);
  text-align: right;
}

/* The rows someone is scanning for. A seal-coloured rule rather than red text: the
   entry is not an error, it is the one worth a second look.
 *
 * It hangs in the document's own margin rather than indenting the row. Indenting
 * would push the marked rows out of the timestamp column, and a register whose
 * columns do not line up cannot be scanned, which is the only thing it is for. */
.log__row--notable { position: relative; }

.log__row--notable::before {
  content: "";
  position: absolute;
  left: -13px;
  top: 12px;
  bottom: 12px;
  width: 2px;
  background: var(--seal);
}

@media (max-width: 560px) {
  /* Three columns cannot hold at this width without the device string wrapping to
     one word per line. Stack, and let the timestamp lead. */
  .log__row { grid-template-columns: 1fr; gap: 2px; }
  .log__where { text-align: left; }
}

/* Address picker ----------------------------------------------------------- */

.suggest {
  position: relative;
  margin-top: 2px;
  border: 1px solid var(--rule-strong);
  border-radius: var(--r);
  background: var(--paper);
  max-height: 15rem;
  overflow-y: auto;
  z-index: 5;
}

.suggest__item {
  padding: 10px 12px;
  border-bottom: 1px solid var(--rule-fine);
  font-size: 14.5px;
  cursor: pointer;
}

.suggest__item:last-child { border-bottom: none; }
.suggest__item:hover,
.suggest__item[aria-selected="true"] { background: var(--seal-wash); color: var(--seal); }

/* The resolved address. A result, not another field: shown the way it will be
   written down, with one control to reopen the search. */
.chosen {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  margin-bottom: var(--step);
  padding: 14px 0;
  border-top: 1px solid var(--rule);
  border-bottom: 1px solid var(--rule);
}

.chosen__lines { font-size: 15.5px; }
.chosen__meta {
  margin-top: 1px;
  font-family: var(--mono);
  font-size: 11.5px;
  letter-spacing: 0.04em;
  color: var(--ink-soft);
}

.manual { margin-bottom: var(--step); }

.manual > summary {
  padding: 4px 0;
  font-family: var(--mono);
  font-size: 10.5px;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--ink-soft);
  cursor: pointer;
  list-style: none;
}

.manual > summary::-webkit-details-marker { display: none; }

/* Drawn rather than typed, so it is the same weight as the rules around it instead
   of whatever glyph the platform has for a triangle. */
.manual > summary::before {
  content: "";
  display: inline-block;
  width: 6px;
  height: 6px;
  margin-right: 9px;
  border-right: 1.25px solid currentColor;
  border-bottom: 1.25px solid currentColor;
  transform: translateY(-1px) rotate(-45deg);
  transition: transform 140ms ease;
}

.manual[open] > summary::before { transform: translateY(-3px) rotate(45deg); }
.manual > summary:hover { color: var(--ink); }
.manual[open] > summary { margin-bottom: 14px; }

code {
  font-family: var(--mono);
  font-size: 13px;
  word-break: break-all;
}

/* Entrance. Exactly one moment: the rule under the head draws across, the way a
   line is ruled onto a form before anything is written on it.

   It animates a pseudo-element, never the content. An entrance that starts the page
   at opacity 0 has a failure mode where the page is simply blank, and this is a
   login screen: nothing here may depend on an animation completing in order to be
   readable. Everything else on the page is static. */
@keyframes rule-in {
  from { transform: scaleX(0); }
  to { transform: scaleX(1); }
}

.head {
  position: relative;
  border-bottom: 0;
}

.head::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 1.5px;
  background: var(--ink);
  transform-origin: left center;
  animation: rule-in 520ms cubic-bezier(0.22, 0.7, 0.25, 1) both;
}

@media (max-width: 540px) {
  .doc { padding-left: 20px; padding-right: 20px; }
  .row { flex-wrap: wrap; gap: 0 14px; }
  .field--narrow { flex: 1 1 6rem; }
  /* A thumb needs the target more than the composition needs the restraint. */
  .btn { display: block; width: 100%; }
  .btn--small { display: inline-block; width: auto; }
}

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after { animation: none !important; transition: none !important; }
}
