/* ============================================================================
 * Staff chrome for sharelab, built on AnswerLab's tokens.
 *
 * LOAD ORDER IS LOAD-BEARING: bootstrap → answerlab-tokens.css → this file.
 * Bootstrap is kept for its reboot and `.container` only; every colour, face and
 * measurement below comes from the token file, and this file wins on the
 * cascade by loading last. Reordering the three <link> tags in base.html hands
 * typography and colour back to Bootstrap's defaults, which look fine and are
 * not AnswerLab's.
 *
 * NO CLASSES ON <tr> OR <td>, ANYWHERE. Three test files parse these tables by
 * regular expression — `re.findall(r"<tr>(.*?)</tr>")` in test_staff_audit.py
 * and test_staff_views.py, and `re.findall(r"<td>(.*?)</td>")` in
 * test_recipient_routes.py, which also extracts the Granted and First-opened
 * cells and compares them to bare date strings. Those tests exist because a real
 * bug once rendered `granted_at` in the "First opened" column and the suite
 * stayed green, so they are not incidental coupling to be refactored away.
 *
 * Every row and column treatment here therefore comes from a structural
 * selector: a class on the <table>, plus `nth-child` for per-column rules and
 * `:has()` for the live row. Tighter than usual, and it makes this redesign
 * provably behaviour-neutral.
 * ========================================================================== */

body {
  background: var(--bg-page);
  color: var(--fg-1);
  font-family: var(--font-sans);
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  -webkit-font-smoothing: antialiased;
}

/* ── Chrome ────────────────────────────────────────────────────────────────
 * The only persistent surface. It exists mainly to answer two questions a
 * researcher asks constantly on an internal tool — who am I signed in as, and
 * how do I get out — which had no answer at all before: the sign-out route has
 * existed since phase 1 and nothing linked to it.
 * ------------------------------------------------------------------------- */
.al-chrome {
  background: var(--bg-1);
  border-bottom: 1px solid var(--divider);
}

.al-chrome__inner {
  align-items: baseline;
  display: flex;
  gap: var(--space-4);
  justify-content: space-between;
  margin: 0 auto;
  max-width: 1140px;
  padding: var(--space-3) var(--space-4);
}

.al-wordmark {
  color: var(--fg-1);
  font-size: var(--fs-body);
  font-weight: var(--fw-bold);
  letter-spacing: var(--tracking-tight);
  text-decoration: none;
}

/* The orange is a single dot, not the word. Signal Orange is the brand's accent
 * but fails AA as body-size text (3.06:1 on white), so it appears here as a
 * graphic — where 3:1 is the bar and it passes — rather than as a label. */
.al-wordmark::after {
  background: var(--al-orange);
  border-radius: var(--radius-pill);
  content: "";
  display: inline-block;
  height: 5px;
  margin-left: 3px;
  vertical-align: 2px;
  width: 5px;
}

.al-identity {
  align-items: baseline;
  display: flex;
  gap: var(--space-3);
}

.al-identity__who {
  color: var(--fg-3);
  font-family: var(--font-mono);
  font-size: var(--fs-small);
}

/* ── Page ─────────────────────────────────────────────────────────────────── */
.al-page {
  margin: 0 auto;
  max-width: 1140px;
  padding: var(--space-6) var(--space-4) var(--space-7);
}

.al-back {
  color: var(--fg-2);
  display: inline-block;
  font-size: var(--fs-small);
  margin-bottom: var(--space-4);
  text-decoration: none;
}

.al-back:hover {
  color: var(--fg-1);
  text-decoration: underline;
}

.al-more {
  display: inline-block;
  font-size: var(--fs-small);
  margin-top: var(--space-4);
}

/* Sentence case, per the source's explicit brand rule — never Title Case. */
.al-page h1 {
  font-size: var(--fs-title);
  font-weight: var(--fw-medium);
  letter-spacing: var(--tracking-tight);
  line-height: var(--lh-heading);
  margin: 0 0 var(--space-2);
}

.al-page h2 {
  font-size: var(--fs-section);
  font-weight: var(--fw-medium);
  letter-spacing: var(--tracking-tight);
  line-height: var(--lh-heading);
  margin: var(--space-6) 0 var(--space-3);
}

.al-subtitle {
  color: var(--fg-2);
  margin: 0 0 var(--space-6);
}

/* The source's eyebrow: orange, 11px/500, letter-spaced, and NOT uppercased —
 * the brand rule is sentence case everywhere. */
.al-eyebrow {
  color: var(--fg-accent);
  font-size: var(--fs-small);
  font-weight: var(--fw-medium);
  letter-spacing: 0.04em;
  margin: 0 0 var(--space-1);
}

.al-note {
  color: var(--fg-2);
  font-size: var(--fs-small);
  margin: var(--space-2) 0 0;
}

/* `color` is not optional here. Bootstrap's reboot sets `code { color: #d63384 }`, a
 * magenta that has nothing to do with this palette, and it was rendering every report
 * slug and the `flask seed-dev` hint in pink — a colour no token in this file defines.
 * Setting only font-family left Bootstrap winning on the property nobody thought to
 * check. Any element that opts into the mono face takes its foreground with it. */
.al-mono {
  color: inherit;
  font-family: var(--font-mono);
  font-size: 0.92em;
}

/* Same reason, for the `<code>` in prose that carries no class of its own. */
.al-page code {
  color: inherit;
}

a {
  color: var(--fg-link);
  text-decoration-thickness: 1px;
  text-underline-offset: 2px;
}

/* ── Tables ───────────────────────────────────────────────────────────────── */
.al-table {
  background: var(--bg-1);
  border: 1px solid var(--divider);
  border-collapse: collapse;
  border-radius: var(--radius-md);
  font-size: 14px;
  overflow: hidden;
  width: 100%;
}

.al-table thead th {
  background: var(--bg-1);
  border-bottom: 1px solid var(--divider);
  color: var(--fg-3);
  font-size: var(--fs-small);
  font-weight: var(--fw-medium);
  letter-spacing: 0.04em;
  padding: var(--space-3) var(--space-3);
  text-align: left;
  white-space: nowrap;
}

.al-table tbody td {
  border-top: 1px solid var(--divider);
  padding: var(--space-3);
  vertical-align: baseline;
}

.al-table tbody tr:first-child td {
  border-top: none;
}

/* THE SIGNATURE: the live version's row.
 *
 * Charcoal on Illumination Yellow — at 10.8:1 the highest-contrast pairing in
 * the whole palette, and the brand's own designated "primary highlight". It is
 * the only filled, coloured element on any page in this application, and it
 * looks identical in both themes.
 *
 * It earns that because it encodes something true and consequential: exactly one
 * version is live at a time, and "what can a client open right now" is the
 * question this product exists to answer. Everything else on the page stays
 * quiet so that this reads from across a desk.
 *
 * NOTHING ELSE ON A STAFF PAGE MAY BE YELLOW. There was briefly a `.al-btn--primary` in
 * yellow on the upload button, and side by side the page had two loud yellow objects and
 * no single most-important fact — the signature stops being one the moment it is not the
 * only one. That variant is deleted rather than left unused, so reintroducing the clash
 * takes writing the colour out by hand. The upload button is `--dark`, which is the
 * strongest weight available that is not this.
 *
 * Selected with `:has()` because NOTHING here can carry a class: the row is parsed by
 * `re.findall(r"<tr>(.*?)</tr>")` in three files, and test_publish_routes asserts the
 * literal `<strong>(live)</strong>`, so the marker cannot take one either. The selector
 * therefore keys on structure — a <strong> in the Version cell — which is unambiguous
 * because Jinja autoescapes version notes, so no <strong> can arrive from data. Scoped to
 * the versions table rather than `.al-table` generally: it is the only table with a live
 * row, and a narrower selector cannot light up a row somewhere else by accident. */
.al-table--versions tbody tr:has(td:first-child strong) {
  background: var(--state-live-bg);
  color: var(--state-live-fg);
}

.al-table--versions tbody tr:has(td:first-child strong) td {
  border-top-color: rgba(37, 36, 41, 0.18);
}

/* Per-column treatment, by position, since cells cannot carry classes. Any
 * column holding a value a researcher might paste into an email — an address, a
 * slug, a date, a size, a count — is set in mono so it reads as data rather than
 * prose. The comment beside each rule names the column, because an nth-child
 * number is meaningless to the next reader and silently wrong if a column moves.
 * A moved column is caught: test_recipient_routes asserts the recipients row has
 * exactly six cells for this reason. */

/* Version history: Version | Status | Size | Uploaded by | Published | Note */
.al-table--versions tbody td:nth-child(1), /* v4 */
.al-table--versions tbody td:nth-child(3), /* 167 KiB */
.al-table--versions tbody td:nth-child(5) /* 2026-09-02 */ {
  font-family: var(--font-mono);
  white-space: nowrap;
}

/* Recipients: Email | Granted | Status | Views | First opened | actions */
.al-table--recipients tbody td:nth-child(1), /* maya@acme.example */
.al-table--recipients tbody td:nth-child(2), /* 2026-09-02 */
.al-table--recipients tbody td:nth-child(4), /* 3 */
.al-table--recipients tbody td:nth-child(5) /* 2026-09-02 */ {
  font-family: var(--font-mono);
  white-space: nowrap;
}

/* Dates and the session label line up as columns of values, so they take the mono face —
 * matching .al-table--recipients' treatment of the same kinds of cell. */
.al-table--tokens tbody td:nth-child(2), /* maya-macbook */
.al-table--tokens tbody td:nth-child(3), /* 2026-09-09 */
.al-table--tokens tbody td:nth-child(4) /* 2026-09-09 14:30 */ {
  font-family: var(--font-mono);
  font-size: var(--fs-small);
}

.al-table--tokens tbody td:last-child {
  text-align: right;
}

/* Audit: When | Event | Actor | Recipient | Version */
.al-table--audit tbody td:nth-child(1), /* 2026-09-03 18:03 */
.al-table--audit tbody td:nth-child(3), /* tbohmbach@answerlab.com */
.al-table--audit tbody td:nth-child(4), /* the contact */
.al-table--audit tbody td:nth-child(5) /* v4 */ {
  font-family: var(--font-mono);
  white-space: nowrap;
}

/* Audit event names are identifiers too — `sessions_ended`, `link_redeemed` —
 * and read as such. Not nowrap: this is the widest column. */
.al-table--audit tbody td:nth-child(2) {
  font-family: var(--font-mono);
}

/* Access requests: Request | Requested | actions */
.al-table--requests tbody td:nth-child(2) {
  font-family: var(--font-mono);
  white-space: nowrap;
}

/* Actions sit right, so the eye finds them in one place down the table. */
.al-table--recipients tbody td:last-child,
.al-table--requests tbody td:last-child {
  text-align: right;
  white-space: nowrap;
}

.al-table--recipients tbody td:last-child form,
.al-table--requests tbody td:last-child form {
  display: inline-block;
  margin-left: var(--space-1);
}

/* ── State chips ──────────────────────────────────────────────────────────── */
.al-chip {
  background: var(--state-quiet-bg);
  border-radius: var(--radius-sm);
  color: var(--state-quiet-fg);
  display: inline-block;
  font-size: var(--fs-small);
  font-weight: var(--fw-medium);
  letter-spacing: 0.02em;
  padding: 2px var(--space-2);
  white-space: nowrap;
}

.al-chip--withdrawn {
  background: var(--state-withdrawn-bg);
  color: var(--state-withdrawn-fg);
}

.al-chip--pending {
  background: var(--state-pending-bg);
  color: var(--state-pending-fg);
}

/* On the live row the chip sits on yellow, so it needs its own ground. */
.al-table--versions tbody tr:has(td:first-child strong) .al-chip {
  background: rgba(37, 36, 41, 0.12);
  color: var(--al-charcoal);
}

/* ── Buttons — the source's five variants, verbatim values ───────────────── */
/* `text-decoration: none` is here for the one anchor that wears button classes: the
 * Okta sign-in link, which must stay an anchor because the redirect is a GET carrying
 * the state and PKCE challenge seeded by that render. Without this it inherited the
 * base `a` rule and shipped to QA as an underlined button label on the first page every
 * staff member sees. Every other `.al-btn` is a real <button>, which is why nothing
 * local caught it. */
.al-btn {
  background: transparent;
  text-decoration: none;
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  cursor: pointer;
  font-family: var(--font-sans);
  font-size: 14px;
  font-weight: var(--fw-medium);
  padding: 10px 20px;
  transition:
    background-color 0.15s,
    color 0.15s,
    transform 0.05s;
}

.al-btn:active {
  transform: scale(0.985);
}

/* Uses tokens, NOT --al-charcoal directly. The source's `.btn-dark` is charcoal-on-white,
 * which is correct in light mode and invisible in dark, where charcoal IS the surface —
 * the "Add recipient" button vanished entirely until this was caught by looking at the
 * page. `--btn-solid-*` flip with the theme so the button stays a solid contrast block in
 * both, which is the property that made it the right choice for a secondary action. */
.al-btn--dark {
  background: var(--btn-solid-bg);
  color: var(--btn-solid-fg);
}

.al-btn--dark:hover {
  background: var(--btn-solid-bg-hover);
}

.al-btn--outline {
  border-color: var(--fg-1);
  color: var(--fg-1);
}

.al-btn--outline:hover {
  background: var(--fg-1);
  color: var(--bg-1);
}

/* Deliberately the weakest weight — used for the dismissive action beside a real one
 * ("Deny" next to "Issue link") and for Sign out. It keeps the base class's 1px
 * transparent border rather than dropping to bare text, so revealing that border on
 * hover shifts nothing; without some border on hover it read as a caption sitting
 * between two buttons, which is the one thing a control must never do. */
.al-btn--ghost {
  color: var(--fg-link);
  padding: 10px var(--space-3);
}

.al-btn--ghost:hover {
  border-color: var(--divider);
  text-decoration: underline;
}

/* DEPARTURE: the source has no destructive variant, because a report deck has
 * nothing to destroy. Revoking access and ending sessions are irreversible from
 * the recipient's side, so they should not look like "New link" sitting beside
 * them. Built from --al-red rather than a new hue, and outline rather than
 * filled: the brand is largely flat, and a filled red would outweigh the live
 * marker, which is meant to be the only filled thing on the page. */
.al-btn--danger {
  border-color: var(--al-red);
  color: var(--state-withdrawn-fg);
}

.al-btn--danger:hover {
  background: var(--al-red);
  color: var(--al-white);
}

.al-btn--sm {
  font-size: 12px;
  padding: 6px 12px;
}

/* ── Forms ────────────────────────────────────────────────────────────────── */
/* `flex-start`, so the fields hang from a shared top edge. Bottom-aligning them lines up
 * the inputs but leaves the LABELS at different heights the moment one field is taller
 * than another — visible the instant the report form put a textarea beside a text input.
 * The button is positioned separately; see the alignment note below it. */
.al-form {
  align-items: flex-start;
  background: var(--bg-1);
  border: 1px solid var(--divider);
  border-radius: var(--radius-md);
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  padding: var(--space-4);
}

/* THE BUTTON ALIGNS WITH THE CONTROLS, NOT WITH THE ROW.
 *
 * This was `align-self: flex-end`, which bottom-aligns to the tallest item in the row.
 * That is only correct when every field is the same height, and on a real form none of
 * them are: a native file input is taller than a text input because of its inner
 * button, and a textarea is taller still. So on the publish form the button sat ~10px
 * below the version-note input, and on the add-a-report form it sat at the bottom of
 * the textarea, far below the title input it appears to belong to. Reported from QA.
 *
 * Aligning to the top instead, offset by exactly the label block, puts the button's top
 * edge on the same line as every control's top edge no matter what else is in the row —
 * and `--control-h` makes the single-line controls and the button the same height, so
 * their bottoms agree too. A textarea then grows downward from a shared top edge, which
 * is the one thing that reads as deliberate rather than ragged. */
.al-form > .al-btn {
  align-self: flex-start;
  margin-top: var(--label-block);
  min-height: var(--control-h);
  padding-block: 0;
}

/* Overrides BOTH of the rule above's positioning choices, because neither survives the
 * axis flip: in a column, `align-self` resolves horizontally, so `flex-start` would pin
 * the button to the left edge at its text width, and `margin-top: --label-block` would
 * add a label's worth of space above a button that has no label beside it. In the
 * stacked form the button belongs across the full measure, one normal gap below its
 * field. */
.al-form--stacked > .al-btn {
  align-self: stretch;
  margin-top: 0;
}

.al-form--stacked {
  align-items: stretch;
  background: none;
  border: 0;
  flex-direction: column;
  padding: 0;
}

.al-field {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
}

.al-field label {
  color: var(--fg-2);
  font-size: var(--fs-small);
  font-weight: var(--fw-medium);
  /* Explicit, because --label-block is computed from it. */
  line-height: var(--lh-label);
}

.al-field input[type="text"],
.al-field input[type="email"],
.al-field input[type="number"],
.al-field input[type="file"],
.al-field textarea {
  background: var(--bg-1);
  border: 1px solid var(--al-grey-mid);
  border-radius: var(--radius-sm);
  color: var(--fg-1);
  font-family: var(--font-sans);
  font-size: 14px;
  /* One height for every single-line control on a row, so the row has a shared
   * baseline to align the button to. `box-sizing: border-box` comes from Bootstrap's
   * reboot, so the border is inside this. */
  min-height: var(--control-h);
  padding: 8px 10px;
}

/* `height`, not just `min-height`, for the single-line controls. A native file input
 * sizes itself from its inner button's metrics and ignored the padding set above,
 * measuring 44.3px against every other control's 40 — the last 4px of raggedness on the
 * publish row, and small enough to look like sloppiness rather than a bug. */
.al-field input[type="text"],
.al-field input[type="email"],
.al-field input[type="number"],
.al-field input[type="file"] {
  height: var(--control-h);
}

/* The file input needs its own box model because the inner button is a flex item here
 * rather than inline content — without this the filename sits on the box's top edge. */
.al-field input[type="file"] {
  align-items: center;
  display: flex;
  padding: 0 10px;
}

/* The one remaining browser-native control on any staff page, and it looked it: a grey
 * system button with a system face sitting inside a designed field. Styled as the
 * quietest weight in the set, since choosing a file is a step within the form and not
 * the form's action — that is "Upload and publish", to its right. */
.al-field input[type="file"]::file-selector-button {
  background: var(--state-quiet-bg);
  border: 1px solid var(--divider);
  border-radius: var(--radius-sm);
  color: var(--fg-1);
  cursor: pointer;
  font-family: var(--font-sans);
  font-size: 13px;
  font-weight: var(--fw-medium);
  margin-right: var(--space-3);
  padding: 5px 12px;
  transition: background-color 0.15s;
}

.al-field input[type="file"]::file-selector-button:hover {
  background: var(--divider);
}

.al-field textarea {
  /* Taller by design and free to grow downward — its TOP still sits on the row's
   * shared control line, which is the edge alignment is judged against. */
  min-height: 4.5rem;
  resize: vertical;
}

.al-select {
  appearance: none;
  min-height: var(--control-h);
  background: var(--bg-1);
  /* The chevron is drawn in CSS rather than an image: default-src 'self' would permit a
   * file from static/, but a two-line gradient needs no HTTP request at all. */
  background-image: linear-gradient(45deg, transparent 50%, currentcolor 50%),
    linear-gradient(135deg, currentcolor 50%, transparent 50%);
  background-position: calc(100% - 16px) center, calc(100% - 11px) center;
  background-repeat: no-repeat;
  background-size: 5px 5px, 5px 5px;
  border: 1px solid var(--al-grey-mid);
  border-radius: var(--radius-sm);
  color: var(--fg-1);
  font-family: var(--font-sans);
  font-size: 14px;
  padding: 8px 34px 8px 10px;
  width: 100%;
}

.al-errors {
  color: var(--state-withdrawn-fg);
  font-size: var(--fs-small);
  list-style: none;
  margin: var(--space-1) 0 0;
  padding: 0;
}

/* ── Panels ───────────────────────────────────────────────────────────────── */
.al-panel {
  background: var(--bg-2);
  border-radius: var(--radius-md);
  color: var(--fg-1);
  padding: var(--space-4);
}

/* The minted link is shown exactly once and cannot be retrieved again (§6.2), so
 * it gets a panel rather than a line of prose — a value you must copy now should
 * not look like a sentence you can skim. */
.al-panel--once {
  border-left: 3px solid var(--al-orange);
}

.minted > * {
  margin: 0;
}

.minted__lede + .minted__value {
  margin-top: var(--space-3);
}

/* The link and its button on one line, wrapping together on a narrow window rather than
 * the button dropping away from the value it copies. `baseline` so the button sits on the
 * link's text line instead of floating against a code block that may wrap to two. */
.minted__value {
  align-items: baseline;
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
}

.minted__value code {
  overflow-wrap: anywhere;
}

/* `hidden` MUST WIN over any display a button variant sets. `.al-btn` sets no `display`
 * today, so the UA stylesheet's `[hidden] { display: none }` applies and the copy button
 * starts hidden as intended — but a variant that later sets one would silently reveal a
 * button whose script has already decided it cannot work, on a value that cannot be shown
 * again. 0,2,0 beats `.al-btn`'s 0,1,0 without reaching for !important. */
.al-btn[hidden] {
  display: none;
}

#copy-minted-status:empty {
  display: none;
}

.al-panel--once code,
.al-panel code {
  font-family: var(--font-mono);
  font-size: 0.92em;
  overflow-wrap: anywhere;
}

/* Marks the local auth stub as what it is — the one panel on any page that must not be
 * mistaken for the real product in a screenshot.
 *
 * ORANGE, NOT YELLOW, and that is the rule at the signature block being obeyed rather
 * than bent. The first version of this panel had a yellow border and the pending
 * yellow wash, which broke "nothing else may be yellow" on the same afternoon it was
 * written — and the two never appear on one page, which is exactly the reasoning that
 * erodes a rule like this. Orange is already this file's signal colour, the eyebrow
 * above is orange, and a 3px border only needs 3:1. Nothing was lost by obeying it. */
.al-panel--dev {
  background: rgba(255, 94, 0, 0.07);
  border-left: 3px solid var(--al-orange);
  /* The panel is a plain block elsewhere; here it stacks a label, a note and a form,
   * which without a gap render as one run of text. */
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.al-panel--dev > * {
  margin: 0;
}

.al-empty {
  color: var(--fg-2);
  padding: var(--space-5) 0;
}

/* ── Lists ────────────────────────────────────────────────────────────────── */
.al-list {
  list-style: none;
  margin: 0;
  padding: 0;
}

.al-list > li {
  /* `center`, not `baseline`. A row pairs running text with a chip, and baseline
   * alignment lines up the chip's TEXT with the link's, which leaves the chip's padded
   * box hanging below the line. Both sides are single-line, so centring is what reads
   * level. */
  align-items: center;
  border-top: 1px solid var(--divider);
  display: flex;
  gap: var(--space-3);
  justify-content: space-between;
  padding: var(--space-3) 0;
}

/* `space-between` distributes the FREE SPACE between every child, which is right for
 * the dashboard's two (name, then org hard right) and wrong for a three-item row: on
 * the project page it stranded the slug alone in the middle of the page, equidistant
 * from a title on the left and a chip on the right, reading as three unrelated columns
 * rather than one report. Reported from QA.
 *
 * Here the title and slug sit together — they name the same thing — and only the status
 * is pushed away, by its own auto margin rather than by distributing space. */
.al-list--reports > li {
  justify-content: flex-start;
}

.al-list--reports > li > .al-chip {
  margin-left: auto;
}

.al-list > li:first-child {
  border-top: none;
}

.al-list__meta {
  color: var(--fg-3);
  font-size: var(--fs-small);
}

/* ── Quality floor ────────────────────────────────────────────────────────── */
:focus-visible {
  outline: 2px solid var(--al-orange);
  outline-offset: 2px;
}

@media (prefers-reduced-motion: reduce) {
  .al-summary::before {
    transition: none;
  }

  .al-btn {
    transition: none;
  }

  .al-btn:active {
    transform: none;
  }
}

@media (max-width: 46rem) {
  .al-chrome__inner,
  .al-page {
    padding-left: var(--space-3);
    padding-right: var(--space-3);
  }

  /* Wide tables scroll in their own container rather than the page. */
  .al-scroll {
    overflow-x: auto;
  }

  .al-form {
    align-items: stretch;
    flex-direction: column;
  }
}

/* ── Organizations ────────────────────────────────────────────────────────────
 * The org list is the only page where each row expands into forms, so its rows
 * stack rather than sitting on one baseline like the project and report lists.
 * ------------------------------------------------------------------------- */
.al-list--stacked > li {
  display: block;
}

.al-org__name {
  font-size: var(--fs-section);
  font-weight: var(--fw-medium);
  letter-spacing: var(--tracking-tight);
}

.al-list--stacked .al-list__meta {
  display: block;
  margin-top: var(--space-1);
}

/* <details>/<summary> is the existing disclosure for the policy and project
 * forms. Styled as a control rather than left as the browser's triangle-and-link,
 * because these two are the only admin-only actions in the product (§3.3) and
 * looked like footnotes. */
.al-summary {
  color: var(--fg-link);
  cursor: pointer;
  display: inline-block;
  font-size: var(--fs-small);
  font-weight: var(--fw-medium);
  margin-top: var(--space-3);
  padding: var(--space-1) 0;
}

/* `display: inline-block` on a <summary> suppresses the native disclosure triangle, so
 * these two read as plain orange labels with no sign that they open anything. A caret
 * that turns on open restores the affordance the display change removed. */
.al-summary::marker,
.al-summary::-webkit-details-marker {
  content: "";
  display: none;
}

.al-summary::before {
  content: "\203a";
  display: inline-block;
  margin-right: var(--space-2);
  transition: transform 120ms ease;
}

[open] > .al-summary::before {
  transform: rotate(90deg);
}

.al-summary:hover {
  text-decoration: underline;
}

details[open] .al-summary {
  margin-bottom: var(--space-2);
}

/* ── Sign-in ──────────────────────────────────────────────────────────────────
 * A narrow column, deliberately without a set-piece. It is tempting to make the page
 * a person sees first the most designed one; the report page is where the work is, and
 * a loud sign-in screen would compete with it for the one bold gesture the design
 * allows itself. */
.al-signin {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
  margin-top: var(--space-6);
  max-width: 22rem;
}

.al-signin__title {
  font-size: var(--fs-title);
  font-weight: var(--fw-bold);
  letter-spacing: var(--tracking-tight);
  line-height: var(--lh-heading);
  margin: 0;
}

.al-signin__lede {
  color: var(--fg-2);
  margin: 0;
}

/* A full-width action reads as the page's single next step, which on this page it is. */
.al-btn--block {
  justify-content: center;
  width: 100%;
}

/* The confirmation page's fact list. A <dl> rather than a table: three label/value pairs are
 * not tabular data, and the labels are what a researcher scans to answer "is this mine?".
 * Two columns on anything wider than a phone so the values line up and a wrong one is
 * obvious at a glance. */
.al-confirm {
  display: grid;
  gap: var(--space-2) var(--space-5);
  grid-template-columns: max-content 1fr;
  margin: var(--space-5) 0;
}

.al-confirm dt {
  color: var(--fg-2);
  font-size: var(--fs-small);
  font-weight: var(--fw-medium);
  letter-spacing: 0.04em;
  padding-top: 0.2em;
}

.al-confirm dd {
  margin: 0;
}

/* The device code, at a size someone can compare against a terminal without leaning in.
 * Letter-spaced because that is the whole job: telling two similar codes apart. */
.al-code-display {
  font-family: var(--font-mono);
  font-size: var(--fs-section);
  letter-spacing: 0.12em;
}
